From 67a05315a738788b9e8d0d8ab922ca363865be89 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Wed, 13 Aug 2025 14:22:02 +0530 Subject: [PATCH] Fixed: When opening the search from widget or from outside the application then search is broken with large ZIM files. * Fixed: When launching the app fresh (cold start), the search screen could appear before the ZIM file was ready (because ZIM file loading in the reader happens on the IO thread), resulting in no search results. Now, incoming actions are delayed until the ZIM file finishes loading so that search works correctly. * Fixed: Multiple fragment instances were created when repeatedly opening different fragments via bottomAppBar buttons, causing the back button to bring them to the foreground one by one instead of expected behavior. --- .../main/KiwixMainActivityScreen.kt | 16 ++++++++++--- .../core/main/reader/CoreReaderFragment.kt | 24 +++++++++++++++---- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivityScreen.kt b/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivityScreen.kt index 0c14f77da..9d7bceb0e 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivityScreen.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivityScreen.kt @@ -43,6 +43,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTag import androidx.navigation.NavBackStackEntry +import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState import kotlinx.coroutines.CoroutineScope @@ -189,11 +190,20 @@ fun BottomNavigationBar( NavigationBarItem( selected = currentDestinationRoute == item.route, onClick = { - // Do not load again fragment that is already loaded. - if (item.route == currentDestinationRoute) return@NavigationBarItem uiCoroutineScope.launch { leftDrawerState.close() - navController.navigate(item.route) + navController.navigate(item.route) { + // Avoid multiple copies of the same destination + launchSingleTop = true + + // Pop up to the start destination of the graph to avoid building up a large stack + popUpTo(navController.graph.findStartDestination().id) { + saveState = true + } + + // Restore state when reselecting a previously selected tab + restoreState = true + } } }, icon = { diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/reader/CoreReaderFragment.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/reader/CoreReaderFragment.kt index 85ee32973..584cd2bba 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/reader/CoreReaderFragment.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/reader/CoreReaderFragment.kt @@ -338,6 +338,13 @@ abstract class CoreReaderFragment : return readerLifeCycleScope } + /** + * Handles actions that require the ZIM file to be fully loaded in the reader + * before opening the search screen. The search screen depends on the ZIM file, + * as its results come from the ZimFileReader. + */ + private var pendingIntent: Intent? = null + private var storagePermissionForNotesLauncher: ActivityResultLauncher? = registerForActivityResult( ActivityResultContracts.RequestPermission() @@ -1073,6 +1080,7 @@ abstract class CoreReaderFragment : super.onDestroyView() findInPageTitle = null searchItemToOpen = null + pendingIntent = null try { coreReaderLifeCycleScope?.cancel() readerLifeCycleScope?.cancel() @@ -1907,12 +1915,15 @@ abstract class CoreReaderFragment : requireActivity().consumeObservable(TAG_FILE_SEARCHED) } - private fun handleIntentActions(intent: Intent) { - Log.d(TAG_KIWIX, "action" + requireActivity().intent?.action) - startIntentBasedOnAction(intent) + private fun handlePendingIntent() { + pendingIntent?.let { + startIntentBasedOnAction(it) + } + pendingIntent = null } private fun startIntentBasedOnAction(intent: Intent?) { + Log.d(TAG_KIWIX, "action" + requireActivity().intent?.action) when (intent?.action) { Intent.ACTION_PROCESS_TEXT -> { goToSearchWithText(intent) @@ -1981,7 +1992,7 @@ abstract class CoreReaderFragment : intent: Intent, activity: AppCompatActivity ): FragmentActivityExtensions.Super { - handleIntentActions(intent) + pendingIntent = intent return FragmentActivityExtensions.Super.ShouldCall } @@ -2483,6 +2494,8 @@ abstract class CoreReaderFragment : } if (webViewHistoryList.isEmpty()) { restoreViewStateOnInvalidWebViewHistory() + // handle the pending intent if any present. + handlePendingIntent() return } restoreViewStateOnValidWebViewHistory( @@ -2499,6 +2512,7 @@ abstract class CoreReaderFragment : searchItemToOpen = null findInPageTitle?.let(::findInPage) findInPageTitle = null + handlePendingIntent() } } catch (e: Exception) { Log.e( @@ -2506,6 +2520,8 @@ abstract class CoreReaderFragment : "Could not restore tabs. Original exception = ${e.printStackTrace()}" ) restoreViewStateOnInvalidWebViewHistory() + // handle the pending intent if any present. + handlePendingIntent() } }