From cfc03cba000b7a28dcdb3cf018c62025f09a2d03 Mon Sep 17 00:00:00 2001 From: KhooLy <73142442+KhooLy@users.noreply.github.com> Date: Tue, 28 Jul 2026 02:23:47 +0300 Subject: [PATCH] fix: sync Android navigation state with in-app destination changes MainActivity kept its own currentDestination alongside FluxaAppHost's internal appState.uiState.destination, with only a one-way sync (external -> internal). Any purely-internal navigation (bottom nav taps, "switch profiles" from Settings) moved appState's destination without MainActivity's copy ever finding out. If a later external navigation call (e.g. profile selection completing) happened to name a destination MainActivity's stale copy already equaled, it was treated as a no-op and silently dropped -- reproducible by going Settings -> Switch profiles -> tapping a profile, which then did nothing. Add a callback that mirrors appState's destination back out to MainActivity whenever it changes internally, and guard the existing external->internal effect so it only re-applies on a genuine change (avoiding a reset loop that would otherwise wipe editingProfile/ selectedDetail/etc. on every round trip). Also account for showProfilePickerSettings in the screen transition key, which was missing and left the profile picker settings screen keyed identically to whatever destination was active underneath it. --- app/src/main/java/com/fluxa/app/ui/MainActivity.kt | 1 + .../main/java/com/fluxa/app/ui/routes/AppRoutesHost.kt | 4 +++- .../commonMain/kotlin/com/fluxa/app/shared/FluxaApp.kt | 1 + .../kotlin/com/fluxa/app/shared/FluxaAppHost.kt | 10 +++++++++- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/fluxa/app/ui/MainActivity.kt b/app/src/main/java/com/fluxa/app/ui/MainActivity.kt index 5c6546f..a69f774 100644 --- a/app/src/main/java/com/fluxa/app/ui/MainActivity.kt +++ b/app/src/main/java/com/fluxa/app/ui/MainActivity.kt @@ -531,6 +531,7 @@ class MainActivity : FragmentActivity() { settingsPopRequestId = settingsPopRequestId, onSettingsCanPopChanged = { canPopSettings = it }, onNavigateToDestination = { destination -> navigateToDestination(destination, false) }, + onDestinationChanged = { destination -> currentDestination = destination }, onPlayerRequestChanged = { playerRequest = it }, profileManager = profileManager, homeViewModel = homeViewModel, diff --git a/app/src/main/java/com/fluxa/app/ui/routes/AppRoutesHost.kt b/app/src/main/java/com/fluxa/app/ui/routes/AppRoutesHost.kt index 3fd2883..50691d6 100644 --- a/app/src/main/java/com/fluxa/app/ui/routes/AppRoutesHost.kt +++ b/app/src/main/java/com/fluxa/app/ui/routes/AppRoutesHost.kt @@ -61,7 +61,8 @@ internal fun AppRoutesHost( onUpdateInfoChanged: (UpdateManager.UpdateInfo?) -> Unit, navigateBackSafely: () -> Unit, settingsPopRequestId: Int, - onSettingsCanPopChanged: (Boolean) -> Unit + onSettingsCanPopChanged: (Boolean) -> Unit, + onDestinationChanged: (FluxaDestination) -> Unit = {} ) { if (playerRequest != null) { PlayerRoute( @@ -226,6 +227,7 @@ internal fun AppRoutesHost( onSettingsBackRequested = navigateBackSafely, settingsPopRequestId = settingsPopRequestId, onSettingsCanPopChanged = onSettingsCanPopChanged, + onDestinationChanged = onDestinationChanged, onManageAddonsRequested = { onNavigateToDestination(FluxaDestination.AddonStore) }, onManagePluginsRequested = { onNavigateToDestination(FluxaDestination.Plugins) }, onConnectStremioRequested = { diff --git a/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaApp.kt b/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaApp.kt index 0cbe733..5ec5962 100644 --- a/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaApp.kt +++ b/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaApp.kt @@ -247,6 +247,7 @@ fun FluxaApp( val screenKey = when { playerState?.content != null -> "player:${playerState.content?.id.orEmpty()}" state.editingProfile != null -> "profileEdit" + state.showProfilePickerSettings -> "profilePickerSettings" state.showSourceSelection -> "sources" state.selectedDetail != null -> "detail:${state.selectedDetail.id}" libraryState?.folderDetail?.folder != null -> "folder:${libraryState.folderDetail.folder.id}" diff --git a/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaAppHost.kt b/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaAppHost.kt index f048d9c..7313af4 100644 --- a/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaAppHost.kt +++ b/shared/src/commonMain/kotlin/com/fluxa/app/shared/FluxaAppHost.kt @@ -101,6 +101,7 @@ fun FluxaAppHost( onSettingsBackRequested: () -> Unit = {}, settingsPopRequestId: Int = 0, onSettingsCanPopChanged: (Boolean) -> Unit = {}, + onDestinationChanged: (FluxaDestination) -> Unit = {}, modifier: Modifier = Modifier ) { FluxaAppHost( @@ -150,6 +151,7 @@ fun FluxaAppHost( onSettingsBackRequested = onSettingsBackRequested, settingsPopRequestId = settingsPopRequestId, onSettingsCanPopChanged = onSettingsCanPopChanged, + onDestinationChanged = onDestinationChanged, modifier = modifier ) } @@ -202,6 +204,7 @@ fun FluxaAppHost( onSettingsBackRequested: () -> Unit = {}, settingsPopRequestId: Int = 0, onSettingsCanPopChanged: (Boolean) -> Unit = {}, + onDestinationChanged: (FluxaDestination) -> Unit = {}, modifier: Modifier = Modifier ) { val scope = rememberCoroutineScope() @@ -255,6 +258,9 @@ fun FluxaAppHost( catalogHome = catalogHome ) ) + LaunchedEffect(appState.uiState.destination) { + onDestinationChanged(appState.uiState.destination) + } var profileAvatarUrl by remember(appState.uiState.editingProfile) { val target = appState.uiState.editingProfile val initial = (target as? ProfileEditTarget.Existing)?.let { existing -> @@ -288,7 +294,9 @@ fun FluxaAppHost( appState.updateLanguage(language) } LaunchedEffect(destination) { - destination?.let(appState::selectDestination) + if (destination != null && destination != appState.uiState.destination) { + appState.selectDestination(destination) + } } LaunchedEffect(detailRequest) { detailRequest?.let(appState::selectDetail)