diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt index 3bc8e5c2b..00e9f05cd 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt @@ -58,6 +58,7 @@ import org.kiwix.kiwixmobile.core.main.ToolbarScrollingKiwixWebView import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.reader.ZimReaderSource.Companion.fromDatabaseValue +import org.kiwix.kiwixmobile.core.search.viewmodel.effects.SearchItemToOpen import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_FILE import org.kiwix.kiwixmobile.core.utils.TAG_KIWIX @@ -69,6 +70,7 @@ private const val HIDE_TAB_SWITCHER_DELAY: Long = 300 class KiwixReaderFragment : CoreReaderFragment() { private var isFullScreenVideo: Boolean = false + private var searchItemToOpen: SearchItemToOpen? = null override fun inject(baseActivity: BaseActivity) { baseActivity.cachedComponent.inject(this) @@ -111,7 +113,16 @@ class KiwixReaderFragment : CoreReaderFragment() { } else { val restoreOrigin = if (args.searchItemTitle.isNotEmpty()) FromSearchScreen else FromExternalLaunch - manageExternalLaunchAndRestoringViewState(restoreOrigin) + manageExternalLaunchAndRestoringViewState(restoreOrigin) { + // This lambda function is invoked after restoring the tabs. It checks if there is a + // search item to open. If `searchItemToOpen` is not null, it will call the superclass + // method to open the specified search item. After opening, it sets `searchItemToOpen` + // to null to prevent any unexpected behavior on subsequent calls. + searchItemToOpen?.let { + super.openSearchItem(it) + } + searchItemToOpen = null + } } } requireArguments().clear() @@ -151,6 +162,18 @@ class KiwixReaderFragment : CoreReaderFragment() { openZimFile(zimReaderSource) } + /** + * Stores the specified search item to be opened later. + * + * This method saves the provided `SearchItemToOpen` object, which will be used to + * open the searched item after the tabs have been restored. + * + * @param item The search item to be opened after restoring the tabs. + */ + override fun openSearchItem(item: SearchItemToOpen) { + searchItemToOpen = item + } + override fun loadDrawerViews() { drawerLayout = requireActivity().findViewById(R.id.navigation_container) tableDrawerRightContainer = requireActivity().findViewById(R.id.reader_drawer_nav_view) @@ -243,7 +266,7 @@ class KiwixReaderFragment : CoreReaderFragment() { } } - override fun restoreViewStateOnInvalidJSON() { + override fun restoreViewStateOnInvalidWebViewHistory() { Log.d(TAG_KIWIX, "Kiwix normal start, no zimFile loaded last time -> display home page") exitBook() } @@ -256,15 +279,16 @@ class KiwixReaderFragment : CoreReaderFragment() { * as the ZIM file is already set in the reader. The method handles setting up the ZIM file and bookmarks, * and restores the tabs and positions from the provided data. * - * @param webViewHistoryItemList JSON string representing the list of articles to be restored. - * @param currentTab Index of the tab to be restored as the currently active one. + * @param webViewHistoryItemList WebViewHistoryItem list representing the list of articles to be restored. + * @param currentTab Index of the tab to be restored as the currently active one. * @param restoreOrigin Indicates whether the restoration is triggered from an external launch or the search screen. + * @param onComplete Callback to be invoked upon completion of the restoration process. */ - - override fun restoreViewStateOnValidJSON( + override fun restoreViewStateOnValidWebViewHistory( webViewHistoryItemList: List, currentTab: Int, - restoreOrigin: RestoreOrigin + restoreOrigin: RestoreOrigin, + onComplete: () -> Unit ) { when (restoreOrigin) { FromExternalLaunch -> { @@ -274,7 +298,7 @@ class KiwixReaderFragment : CoreReaderFragment() { val zimReaderSource = fromDatabaseValue(settings.getString(TAG_CURRENT_FILE, null)) if (zimReaderSource?.canOpenInLibkiwix() == true) { if (zimReaderContainer?.zimReaderSource == null) { - openZimFile(zimReaderSource) + openZimFile(zimReaderSource, isFromManageExternalLaunch = true) Log.d( TAG_KIWIX, "Kiwix normal start, Opened last used zimFile: -> ${zimReaderSource.toDatabase()}" @@ -282,7 +306,7 @@ class KiwixReaderFragment : CoreReaderFragment() { } else { zimReaderContainer?.zimFileReader?.let(::setUpBookmarks) } - restoreTabs(webViewHistoryItemList, currentTab) + restoreTabs(webViewHistoryItemList, currentTab, onComplete) } else { getCurrentWebView()?.snack(string.zim_not_opened) exitBook() // hide the options for zim file to avoid unexpected UI behavior @@ -291,7 +315,7 @@ class KiwixReaderFragment : CoreReaderFragment() { } FromSearchScreen -> { - restoreTabs(webViewHistoryItemList, currentTab) + restoreTabs(webViewHistoryItemList, currentTab, onComplete) } } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt index 149258556..45713cb45 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt @@ -24,7 +24,6 @@ import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem -import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.zim_manager.Language import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt index 3a06d4f78..8938cf27b 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt @@ -28,8 +28,8 @@ import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks import org.kiwix.kiwixmobile.core.dao.NewBookDao import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao import org.kiwix.kiwixmobile.core.dao.NotesRoomDao -import org.kiwix.kiwixmobile.core.dao.WebViewHistoryRoomDao import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao +import org.kiwix.kiwixmobile.core.dao.WebViewHistoryRoomDao import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity import org.kiwix.kiwixmobile.core.di.qualifiers.IO import org.kiwix.kiwixmobile.core.di.qualifiers.MainThread @@ -37,7 +37,6 @@ import org.kiwix.kiwixmobile.core.extensions.HeaderizableList import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem -import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer import org.kiwix.kiwixmobile.core.zim_manager.Language @@ -148,7 +147,9 @@ class Repository @Inject internal constructor( Completable.fromAction { notesRoomDao.deleteNotes(noteList) } .subscribeOn(ioThread) - override suspend fun insertWebViewPageHistoryItems(webViewHistoryEntityList: List) { + override suspend fun insertWebViewPageHistoryItems( + webViewHistoryEntityList: List + ) { webViewHistoryRoomDao.insertWebViewPageHistoryItems(webViewHistoryEntityList) } @@ -159,7 +160,7 @@ class Repository @Inject internal constructor( .observeOn(mainThread) override suspend fun clearWebViewPagesHistory() { - webViewHistoryRoomDao.clearPageHistoryWithPrimaryKey() + webViewHistoryRoomDao.clearWebViewPagesHistory() } override fun deleteNote(noteTitle: String): Completable = diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt index 69c3f3477..839ec6eb6 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt @@ -100,8 +100,8 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.json.JSONException import org.kiwix.kiwixmobile.core.BuildConfig +import org.kiwix.kiwixmobile.core.CoreApp import org.kiwix.kiwixmobile.core.DarkModeConfig import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.StorageObserver @@ -286,6 +286,7 @@ abstract class CoreReaderFragment : private var isFirstTimeMainPageLoaded = true private var isFromManageExternalLaunch = false + private var shouldSaveTabsOnPause = true @JvmField @Inject @@ -421,6 +422,9 @@ abstract class CoreReaderFragment : savedInstanceState: Bundle? ) { super.onViewCreated(view, savedInstanceState) + // Set this to true to enable saving the tab history + // when the fragment goes into the paused state. + shouldSaveTabsOnPause = true setupMenu() donationDialogHandler?.setDonationDialogCallBack(this) val activity = requireActivity() as AppCompatActivity? @@ -1306,6 +1310,15 @@ abstract class CoreReaderFragment : } } + /** + * Initializes a new instance of `KiwixWebView` with the specified URL. + * + * @param url The URL to load in the web view. This is ignored if `shouldLoadUrl` is false. + * @param shouldLoadUrl A flag indicating whether to load the specified URL in the web view. + * When restoring tabs, this should be set to false to avoid loading + * an extra page, as the previous web view history will be restored directly. + * @return The initialized `KiwixWebView` instance, or null if initialization fails. + */ private fun initalizeWebView(url: String, shouldLoadUrl: Boolean = true): KiwixWebView? { if (isAdded) { val attrs = requireActivity().getAttributes(R.xml.webview) @@ -1354,6 +1367,17 @@ abstract class CoreReaderFragment : newTab(url, false) } + /** + * Creates a new instance of `KiwixWebView` and adds it to the list of web views. + * + * @param url The URL to load in the newly created web view. + * @param selectTab A flag indicating whether to select the newly created tab immediately. + * Defaults to true, which means the new tab will be selected. + * @param shouldLoadUrl A flag indicating whether to load the specified URL in the web view. + * If set to false, the web view will be created without loading the URL, + * which is useful when restoring tabs. + * @return The newly created `KiwixWebView` instance, or null if the initialization fails. + */ private fun newTab( url: String, selectTab: Boolean = true, @@ -1529,6 +1553,17 @@ abstract class CoreReaderFragment : } } + override fun onSearchMenuClickedMenuClicked() { + // Set this to false to prevent saving the tab history in onPause + // when opening the search fragment. + shouldSaveTabsOnPause = false + saveTabStates { + // Pass this function to saveTabStates so that after saving + // the tab state in the database, it will open the search fragment. + openSearch("", isOpenedFromTabView = isInTabSwitcher, false) + } + } + @Suppress("NestedBlockDepth") override fun onReadAloudMenuClicked() { if (requireActivity().hasNotificationPermission(sharedPreferenceUtil)) { @@ -2103,7 +2138,21 @@ abstract class CoreReaderFragment : openSearch("", isOpenedFromTabView = false, isVoice) } - private fun openSearchItem(item: SearchItemToOpen) { + /** + * Opens a search item based on its properties. + * + * If the item should open in a new tab, a new tab is created. + * + * The method attempts to load the page URL directly. If the page URL is not available, + * it attempts to convert the page title to a URL using the ZIM reader container. The + * resulting URL is then loaded in the current web view. + * + * Note: This method is overridden in the `KiwixReaderFragment` class to store the + * `SearchItemToOpen` object for later use. If modifications are made to this method, + * please check the overridden version to understand how it interacts with the fragment's + * navigation logic. + */ + open fun openSearchItem(item: SearchItemToOpen) { if (item.shouldOpenInNewTab) { createNewTab() } @@ -2360,13 +2409,42 @@ abstract class CoreReaderFragment : updateNightMode() } - private fun saveTabStates() { + /** + * Saves the current state of tabs and web view history to persistent storage. + * + * This method is designed to be called when the fragment is about to pause, + * ensuring that the current tab states are preserved. It performs the following steps: + * + * 1. Clears any previous web view page history stored in the database. + * 2. Retrieves the current activity's shared preferences to store the tab states. + * 3. Iterates over the currently opened web views, creating a list of + * `WebViewHistoryEntity` objects based on their URLs. + * 4. Saves the collected web view history entities to the database. + * 5. Updates the shared preferences with the current ZIM file and tab index. + * 6. Logs the current ZIM file being saved for debugging purposes. + * 7. Calls the provided `onComplete` callback function once all operations are finished. + * + * Note: This method runs on the main thread and performs database operations + * in a background thread to avoid blocking the UI. + * + * @param onComplete A lambda function to be executed after the tab states have + * been successfully saved. This is optional and defaults to + * an empty function. + * + * Example usage: + * ``` + * saveTabStates { + * openSearch("", isOpenedFromTabView = isInTabSwitcher, false) + * } + */ + private fun saveTabStates(onComplete: () -> Unit = {}) { CoroutineScope(Dispatchers.Main).launch { // clear the previous history saved in database withContext(Dispatchers.IO) { repositoryActions?.clearWebViewPageHistory() } - val settings = requireActivity().getSharedPreferences( + val coreApp = sharedPreferenceUtil?.context as CoreApp + val settings = coreApp.getMainActivity().getSharedPreferences( SharedPreferenceUtil.PREF_KIWIX_MOBILE, 0 ) @@ -2382,10 +2460,43 @@ abstract class CoreReaderFragment : editor.putString(TAG_CURRENT_FILE, zimReaderContainer?.zimReaderSource?.toDatabase()) editor.putInt(TAG_CURRENT_TAB, currentWebViewIndex) editor.apply() + Log.d( + TAG_KIWIX, + "Save current zim file to preferences: " + + "${zimReaderContainer?.zimReaderSource?.toDatabase()}" + ) + onComplete.invoke() } } - private fun getWebViewHistoryEntity( + /** + * Retrieves a `WebViewHistoryEntity` from the given `KiwixWebView` instance. + * + * This method captures the current state of the specified web view, including its + * scroll position and back-forward list, and creates a `WebViewHistoryEntity` + * if the necessary conditions are met. The steps involved are as follows: + * + * 1. Initializes a `Bundle` to store the state of the web view. + * 2. Calls `saveState` on the provided `webView`, which populates the bundle + * with the current state of the web view's back-forward list. + * 3. Retrieves the ID of the currently loaded ZIM file from the `zimReaderContainer`. + * 4. Checks if the ZIM ID is not null and if the web back-forward list contains any entries: + * - If both conditions are satisfied, it creates and returns a `WebViewHistoryEntity` + * containing a `WebViewHistoryItem` with the following data: + * - `zimId`: The ID of the current ZIM file. + * - `webViewIndex`: The index of the web view in the list of opened views. + * - `webViewPosition`: The current vertical scroll position of the web view. + * - `webViewBackForwardList`: The bundle containing the saved state of the + * web view's back-forward list. + * 5. If the ZIM ID is null or the web back-forward list is empty, the method returns null. + * + * @param webView The `KiwixWebView` instance from which to retrieve the history entity. + * @param webViewIndex The index of the web view in the list of opened web views, + * used to identify the position of this web view in the history. + * @return A `WebViewHistoryEntity` containing the state information of the web view, + * or null if the necessary conditions for creating the entity are not met. + */ + private suspend fun getWebViewHistoryEntity( webView: KiwixWebView, webViewIndex: Int ): WebViewHistoryEntity? { @@ -2406,14 +2517,14 @@ abstract class CoreReaderFragment : return null } + /** + * @see shouldSaveTabsOnPause + */ override fun onPause() { super.onPause() - saveTabStates() - Log.d( - TAG_KIWIX, - "onPause Save current zim file to preferences: " + - "${zimReaderContainer?.zimReaderSource?.toDatabase()}" - ) + if (shouldSaveTabsOnPause) { + saveTabStates() + } } override fun webViewUrlLoading() { @@ -2597,7 +2708,8 @@ abstract class CoreReaderFragment : @SuppressLint("CheckResult") protected fun manageExternalLaunchAndRestoringViewState( - restoreOrigin: RestoreOrigin = FromExternalLaunch + restoreOrigin: RestoreOrigin = FromExternalLaunch, + onComplete: () -> Unit = {} ) { val settings = requireActivity().getSharedPreferences( SharedPreferenceUtil.PREF_KIWIX_MOBILE, @@ -2606,29 +2718,49 @@ abstract class CoreReaderFragment : val currentTab = safelyGetCurrentTab(settings) repositoryActions?.loadWebViewPagesHistory() ?.subscribe({ webViewHistoryItemList -> - Log.e( - "VALID_DATA", - "manageExternalLaunchAndRestoringViewState: ${webViewHistoryItemList.size}" - ) if (webViewHistoryItemList.isEmpty()) { - restoreViewStateOnInvalidJSON() + restoreViewStateOnInvalidWebViewHistory() return@subscribe } - restoreViewStateOnValidJSON(webViewHistoryItemList, currentTab, restoreOrigin) + restoreViewStateOnValidWebViewHistory( + webViewHistoryItemList, + currentTab, + restoreOrigin, + onComplete + ) }, { - Log.e("INVALID_DATA", "manageExternalLaunchAndRestoringViewState: $it") - restoreViewStateOnInvalidJSON() + restoreViewStateOnInvalidWebViewHistory() }) } private fun safelyGetCurrentTab(settings: SharedPreferences): Int = max(settings.getInt(TAG_CURRENT_TAB, 0), 0) - /* This method restores tabs state in new launches, do not modify it - unless it is explicitly mentioned in the issue you're fixing */ + /** + * Restores the tabs based on the provided webViewHistoryItemList. + * + * This method performs the following actions: + * - Resets the current web view index to zero. + * - Removes the first tab from the webViewList and updates the tabs adapter. + * - Iterates over the provided webViewHistoryItemList, creating new tabs and restoring + * their states based on the historical data. + * - Selects the specified tab to make it the currently active one. + * - Invokes the onComplete callback once the restoration is finished. + * + * If any error occurs during the restoration process, it logs a warning and displays + * a toast message to inform the user that the tabs could not be restored. + * + * @param webViewHistoryItemList List of WebViewHistoryItem representing the historical data for restoring tabs. + * @param currentTab Index of the tab to be set as the currently active tab after restoration. + * @param onComplete Callback to be invoked upon successful restoration of the tabs. + * + * @Warning: This method restores tabs state in new launches, do not modify it + * unless it is explicitly mentioned in the issue you're fixing. + */ protected fun restoreTabs( webViewHistoryItemList: List, - currentTab: Int + currentTab: Int, + onComplete: () -> Unit ) { try { currentWebViewIndex = 0 @@ -2643,8 +2775,9 @@ abstract class CoreReaderFragment : } } selectTab(currentTab) - } catch (e: JSONException) { - Log.w(TAG_KIWIX, "Kiwix shared preferences corrupted", e) + onComplete.invoke() + } catch (ignore: Exception) { + Log.w(TAG_KIWIX, "Kiwix shared preferences corrupted", ignore) activity.toast(R.string.could_not_restore_tabs, Toast.LENGTH_LONG) } // After restoring the tabs, observe any search actions that the user might have triggered. @@ -2671,6 +2804,18 @@ abstract class CoreReaderFragment : ) } + /** + * Restores the state of a given KiwixWebView based on the provided WebViewHistoryItem. + * + * This method retrieves the back-forward list from the WebViewHistoryItem and + * uses it to restore the web view's state. It also sets the vertical scroll position + * of the web view to the position stored in the WebViewHistoryItem. + * + * If the provided WebViewHistoryItem is null, the method does nothing. + * + * @param webView The KiwixWebView instance whose state is to be restored. + * @param webViewHistoryItem The WebViewHistoryItem containing the saved state and scroll position. + */ private fun restoreTabState(webView: KiwixWebView, webViewHistoryItem: WebViewHistoryItem?) { webViewHistoryItem?.webViewBackForwardListBundle?.let { bundle -> webView.restoreState(bundle) @@ -2744,28 +2889,29 @@ abstract class CoreReaderFragment : } /** - * Restores the view state after successfully reading valid JSON from shared preferences. + * Restores the view state after successfully reading valid webViewHistory from room database. * Developers modifying this method in subclasses, such as CustomReaderFragment and * KiwixReaderFragment, should review and consider the implementations in those subclasses - * (e.g., CustomReaderFragment.restoreViewStateOnValidJSON, - * KiwixReaderFragment.restoreViewStateOnValidJSON) to ensure consistent behavior - * when handling valid JSON scenarios. + * (e.g., CustomReaderFragment.restoreViewStateOnValidWebViewHistory, + * KiwixReaderFragment.restoreViewStateOnValidWebViewHistory) to ensure consistent behavior + * when handling valid webViewHistory scenarios. */ - protected abstract fun restoreViewStateOnValidJSON( + protected abstract fun restoreViewStateOnValidWebViewHistory( webViewHistoryItemList: List, currentTab: Int, - restoreOrigin: RestoreOrigin + restoreOrigin: RestoreOrigin, + onComplete: () -> Unit ) /** - * Restores the view state when the attempt to read JSON from shared preferences fails - * due to invalid or corrupted data. Developers modifying this method in subclasses, such as + * Restores the view state when the attempt to read webViewHistory from room database fails + * due to the absence of any history records. Developers modifying this method in subclasses, such as * CustomReaderFragment and KiwixReaderFragment, should review and consider the implementations - * in those subclasses (e.g., CustomReaderFragment.restoreViewStateOnInvalidJSON, - * KiwixReaderFragment.restoreViewStateOnInvalidJSON) to ensure consistent behavior + * in those subclasses (e.g., CustomReaderFragment.restoreViewStateOnInvalidWebViewHistory, + * KiwixReaderFragment.restoreViewStateOnInvalidWebViewHistory) to ensure consistent behavior * when handling invalid JSON scenarios. */ - abstract fun restoreViewStateOnInvalidJSON() + abstract fun restoreViewStateOnInvalidWebViewHistory() } enum class RestoreOrigin { diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainMenu.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainMenu.kt index 6123f1cfb..277b8a2fe 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainMenu.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainMenu.kt @@ -61,6 +61,7 @@ class MainMenu( fun onRandomArticleMenuClicked() fun onReadAloudMenuClicked() fun onFullscreenMenuClicked() + fun onSearchMenuClickedMenuClicked() } init { @@ -154,7 +155,7 @@ class MainMenu( } private fun navigateToSearch(): Boolean { - (activity as CoreMainActivity).openSearch(isOpenedFromTabView = isInTabSwitcher) + menuClickListener.onSearchMenuClickedMenuClicked() return true } diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt index 9fc4e6de4..9e3602498 100644 --- a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt @@ -150,25 +150,26 @@ class CustomReaderFragment : CoreReaderFragment() { } /** - * Restores the view state when the attempt to read JSON from shared preferences fails - * due to invalid or corrupted data. In this case, it opens the homepage of the zim file, - * as custom apps always have the zim file available. + * Restores the view state when the attempt to read web view history from the room database fails + * due to the absence of any history records. In this case, it navigates to the homepage of the + * ZIM file, as custom apps are expected to have the ZIM file readily available. */ - override fun restoreViewStateOnInvalidJSON() { + override fun restoreViewStateOnInvalidWebViewHistory() { openHomeScreen() } /** - * Restores the view state when the JSON data is valid. This method restores the tabs - * and loads the last opened article in the specified tab. + * Restores the view state when the webViewHistory data is valid. + * This method restores the tabs with webView pages history. */ - override fun restoreViewStateOnValidJSON( + override fun restoreViewStateOnValidWebViewHistory( webViewHistoryItemList: List, currentTab: Int, // Unused in custom apps as there is only one ZIM file that is already set. - restoreOrigin: RestoreOrigin + restoreOrigin: RestoreOrigin, + onComplete: () -> Unit ) { - restoreTabs(webViewHistoryItemList, currentTab) + restoreTabs(webViewHistoryItemList, currentTab, onComplete) } /** @@ -183,6 +184,27 @@ class CustomReaderFragment : CoreReaderFragment() { ) } + /** + * Opens a ZIM file or an OBB file based on the validation of available files. + * + * This method uses the `customFileValidator` to check for the presence of required files. + * Depending on the validation results, it performs the following actions: + * + * - If a valid ZIM file is found: + * - It opens the ZIM file and creates a `ZimReaderSource` for it. + * - Saves the book information in the database to be displayed in the `ZimHostFragment`. + * - Manages the external launch and restores the view state if specified. + * + * - If both ZIM and OBB files are found: + * - The ZIM file is deleted, and the OBB file is opened instead. + * - Manages the external launch and restores the view state if specified. + * + * If no valid files are found and the app is not in test mode, the user is navigated to + * the `customDownloadFragment` to facilitate downloading the required files. + * + * @param shouldManageExternalLaunch Indicates whether to manage external launch and + * restore the view state after opening the file. Default is false. + */ private fun openObbOrZim(shouldManageExternalLaunch: Boolean = false) { customFileValidator.validate( onFilesFound = {