Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
26 changes: 26 additions & 0 deletions fix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import sys

filename = r'c:\Users\irem\OneDrive\Belgeler\Projects\VibeCode\Lemuroid\lemuroid-app\src\main\java\com\swordfish\lemuroid\app\mobile\feature\settings\general\SettingsScreen.kt'

with open(filename, 'r', encoding='utf-8') as f:
content = f.read()

old_str = ''' LocalSaveSyncSettings(
state = state,
onChangeFolder = { viewModel.changeLocalSaveSyncFolder() },
onSyncNow = { viewModel.syncLocalSaveSyncFolderManually() }
)'''

new_str = ''' val viewContext = androidx.compose.ui.platform.LocalContext.current
LocalSaveSyncSettings(
state = state,
onChangeFolder = { viewModel.changeLocalSaveSyncFolder(viewContext) },
onSyncNow = { viewModel.syncLocalSaveSyncFolderManually(viewContext) }
)'''

content = content.replace(old_str, new_str)

with open(filename, 'w', encoding='utf-8', newline='\n') as f:
f.write(content)

print("Done")
4 changes: 4 additions & 0 deletions lemuroid-app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@
android:name="com.swordfish.lemuroid.app.shared.settings.StorageFrameworkPickerLauncher"
android:theme="@style/LemuroidMaterialTheme.Invisible" />

<activity
android:name="com.swordfish.lemuroid.app.shared.settings.LocalSaveSyncPickerLauncher"
android:theme="@style/LemuroidMaterialTheme.Invisible" />

<!-- Leanback activities -->
<activity
android:name=".app.tv.main.MainTVActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import dagger.android.support.AndroidSupportInjectionModule
LemuroidApplicationModule::class,
LibraryIndexWork.Module::class,
SaveSyncWork.Module::class,
com.swordfish.lemuroid.app.shared.savesync.LocalSaveSyncWork.Module::class,
ChannelUpdateWork.Module::class,
CoreUpdateWork.Module::class,
CacheCleanerWork.Module::class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ abstract class LemuroidApplicationModule {
@ContributesAndroidInjector
abstract fun storageFrameworkPickerLauncher(): StorageFrameworkPickerLauncher

@PerActivity
@ContributesAndroidInjector
abstract fun localSaveSyncPickerLauncher(): com.swordfish.lemuroid.app.shared.settings.LocalSaveSyncPickerLauncher

@PerActivity
@ContributesAndroidInjector(modules = [GamePadBindingActivity.Module::class])
abstract fun gamepadBindingActivity(): GamePadBindingActivity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ fun SettingsScreen(
)
GeneralSettings()
InputSettings(navController = navController)
val viewContext = androidx.compose.ui.platform.LocalContext.current
LocalSaveSyncSettings(
state = state,
onChangeFolder = { viewModel.changeLocalSaveSyncFolder(viewContext) },
onSyncNow = { viewModel.syncLocalSaveSyncFolderManually(viewContext) }
)
MiscSettings(
indexingInProgress = indexingInProgress,
isSaveSyncSupported = state.isSaveSyncSupported,
Expand Down Expand Up @@ -222,3 +228,54 @@ private fun RomsSettings(
}
}
}

@Composable
private fun LocalSaveSyncSettings(
state: SettingsViewModel.State,
onChangeFolder: () -> Unit,
onSyncNow: () -> Unit,
) {
val context = androidx.compose.ui.platform.LocalContext.current

val currentDirectory = state.localSaveDirectory ?: ""
val emptyDirectory = androidx.compose.ui.res.stringResource(com.swordfish.lemuroid.R.string.none)

val currentDirectoryName =
androidx.compose.runtime.remember(state.localSaveDirectory) {
runCatching {
if (currentDirectory.isNotEmpty()) {
androidx.documentfile.provider.DocumentFile.fromTreeUri(context, android.net.Uri.parse(currentDirectory))?.name
} else null
}.getOrNull() ?: emptyDirectory
}

com.swordfish.lemuroid.app.utils.android.settings.LemuroidCardSettingsGroup(title = { androidx.compose.material3.Text(text = androidx.compose.ui.res.stringResource(id = com.swordfish.lemuroid.R.string.settings_title_local_save_sync)) }) {
com.swordfish.lemuroid.app.utils.android.settings.LemuroidSettingsMenuLink(
title = { androidx.compose.material3.Text(text = androidx.compose.ui.res.stringResource(id = com.swordfish.lemuroid.R.string.directory)) },
subtitle = { androidx.compose.material3.Text(text = currentDirectoryName) },
onClick = { onChangeFolder() }
)
val extensionValues = androidx.compose.ui.res.stringArrayResource(id = com.swordfish.lemuroid.R.array.pref_key_local_save_sync_export_extension_values).toList()
val extensionDisplayNames = androidx.compose.ui.res.stringArrayResource(id = com.swordfish.lemuroid.R.array.pref_key_local_save_sync_export_extension_display_names).toList()

val extensionState = com.swordfish.lemuroid.app.utils.android.settings.indexPreferenceState(
id = com.swordfish.lemuroid.R.string.pref_key_local_save_sync_export_extension,
default = "default",
values = extensionValues
)

com.swordfish.lemuroid.app.utils.android.settings.LemuroidSettingsList(
state = extensionState,
title = { androidx.compose.material3.Text(text = androidx.compose.ui.res.stringResource(id = com.swordfish.lemuroid.R.string.settings_title_local_save_sync_export_extension)) },
items = extensionDisplayNames,
enabled = currentDirectory.isNotEmpty()
)

com.swordfish.lemuroid.app.utils.android.settings.LemuroidSettingsMenuLink(
title = { androidx.compose.material3.Text(text = androidx.compose.ui.res.stringResource(id = com.swordfish.lemuroid.R.string.local_save_sync_sync_now)) },
subtitle = { androidx.compose.material3.Text(text = androidx.compose.ui.res.stringResource(id = com.swordfish.lemuroid.R.string.local_save_sync_sync_now_description)) },
onClick = { onSyncNow() },
enabled = currentDirectory.isNotEmpty()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,32 @@ class SettingsViewModel(
data class State(
val currentDirectory: String = "",
val isSaveSyncSupported: Boolean = false,
val localSaveDirectory: String = "",
)

val indexingInProgress = PendingOperationsMonitor(context).anyLibraryOperationInProgress()

val directoryScanInProgress = PendingOperationsMonitor(context).isDirectoryScanInProgress()

val uiState =
sharedPreferences.getString(context.getString(com.swordfish.lemuroid.lib.R.string.pref_key_extenral_folder))
.asFlow()
kotlinx.coroutines.flow.combine(
sharedPreferences.getString(context.getString(com.swordfish.lemuroid.lib.R.string.pref_key_extenral_folder)).asFlow(),
sharedPreferences.getString(context.getString(com.swordfish.lemuroid.lib.R.string.pref_key_local_save_sync_folder)).asFlow()
) { romsDir, localSavesDir ->
State(romsDir, saveSyncManager.isSupported(), localSavesDir)
}
.flowOn(Dispatchers.IO)
.stateIn(viewModelScope, SharingStarted.Lazily, "")
.map { State(it, saveSyncManager.isSupported()) }
.stateIn(viewModelScope, SharingStarted.Lazily, State())

fun changeLocalStorageFolder() {
settingsInteractor.changeLocalStorageFolder()
}

fun changeLocalSaveSyncFolder(context: Context) {
com.swordfish.lemuroid.app.shared.settings.LocalSaveSyncPickerLauncher.pickFolder(context)
}

fun syncLocalSaveSyncFolderManually(context: Context) {
com.swordfish.lemuroid.app.shared.savesync.LocalSaveSyncWork.enqueueManualWork(context)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ class GameLauncher(
GlobalScope.launch {
val system = GameSystem.findById(game.systemId)
val coreConfig = coresSelection.getCoreConfigForSystem(system)

// Perform an immediate bidirectional local sync right before the Core launches.
// This ensures any newly placed manually copied .sav files are injected into Lemuroid!
com.swordfish.lemuroid.app.shared.savesync.LocalSaveSyncWork.performSync(activity.applicationContext)

gameLaunchTaskHandler.handleGameStart(activity.applicationContext)
BaseGameActivity.launchGame(activity, coreConfig, game, loadSave, leanback)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,16 @@ class GameLaunchTaskHandler(
private fun cancelBackgroundWork(context: Context) {
SaveSyncWork.cancelAutoWork(context)
SaveSyncWork.cancelManualWork(context)
// Also cancel local syncs
androidx.work.WorkManager.getInstance(context).cancelUniqueWork(com.swordfish.lemuroid.app.shared.savesync.LocalSaveSyncWork.UNIQUE_PERIODIC_WORK_ID)
androidx.work.WorkManager.getInstance(context).cancelUniqueWork(com.swordfish.lemuroid.app.shared.savesync.LocalSaveSyncWork.UNIQUE_WORK_ID)
CacheCleanerWork.cancelCleanCacheLRU(context)
}

private fun rescheduleBackgroundWork(context: Context) {
// Let's slightly delay the sync. Maybe the user wants to play another game.
SaveSyncWork.enqueueAutoWork(context, 5)
com.swordfish.lemuroid.app.shared.savesync.LocalSaveSyncWork.enqueueAutoWork(context)
CacheCleanerWork.enqueueCleanCacheLRU(context)
}

Expand All @@ -76,6 +80,10 @@ class GameLaunchTaskHandler(
val game = data?.extras?.getSerializable(BaseGameActivity.PLAY_GAME_RESULT_GAME) as Game

updateGamePlayedTimestamp(game)

// Push internal saves instantaneously backwards to the user's external SAF directory
com.swordfish.lemuroid.app.shared.savesync.LocalSaveSyncWork.performSync(activity.applicationContext)

if (enableRatingFlow) {
displayReviewRequest(activity, duration)
}
Expand Down
Loading