Merge pull request #4419 from kiwix/Fixes#4418

Fixed: The Tabs history is not restoring in custom apps.
This commit is contained in:
Kelson 2025-09-06 13:42:49 +02:00 committed by GitHub
commit 7b4afafa2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 54 additions and 33 deletions

View File

@ -81,7 +81,6 @@ class KiwixReaderFragment : CoreReaderFragment() {
activity.navigate(KiwixDestination.Library.route, navOptions) activity.navigate(KiwixDestination.Library.route, navOptions)
}) })
} }
activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
activity.enableLeftDrawer() activity.enableLeftDrawer()
openPageInBookFromNavigationArguments() openPageInBookFromNavigationArguments()
} }
@ -110,6 +109,8 @@ class KiwixReaderFragment : CoreReaderFragment() {
if (zimFileUri.isNotEmpty()) { if (zimFileUri.isNotEmpty()) {
tryOpeningZimFile(zimFileUri) tryOpeningZimFile(zimFileUri)
} else { } else {
isWebViewHistoryRestoring = true
isFromManageExternalLaunch = true
val restoreOrigin = val restoreOrigin =
if (searchItemTitle.isNotEmpty()) FromSearchScreen else FromExternalLaunch if (searchItemTitle.isNotEmpty()) FromSearchScreen else FromExternalLaunch
manageExternalLaunchAndRestoringViewState(restoreOrigin) manageExternalLaunchAndRestoringViewState(restoreOrigin)
@ -224,7 +225,7 @@ class KiwixReaderFragment : CoreReaderFragment() {
} }
} }
override fun restoreViewStateOnInvalidWebViewHistory() { override suspend fun restoreViewStateOnInvalidWebViewHistory() {
Log.d(TAG_KIWIX, "Kiwix normal start, no zimFile loaded last time -> display home page") Log.d(TAG_KIWIX, "Kiwix normal start, no zimFile loaded last time -> display home page")
exitBook() exitBook()
} }
@ -242,7 +243,7 @@ class KiwixReaderFragment : CoreReaderFragment() {
* @param restoreOrigin Indicates whether the restoration is triggered from an external launch or the search screen. * @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. * @param onComplete Callback to be invoked upon completion of the restoration process.
*/ */
override fun restoreViewStateOnValidWebViewHistory( override suspend fun restoreViewStateOnValidWebViewHistory(
webViewHistoryItemList: List<WebViewHistoryItem>, webViewHistoryItemList: List<WebViewHistoryItem>,
currentTab: Int, currentTab: Int,
restoreOrigin: RestoreOrigin, restoreOrigin: RestoreOrigin,
@ -250,29 +251,27 @@ class KiwixReaderFragment : CoreReaderFragment() {
) { ) {
when (restoreOrigin) { when (restoreOrigin) {
FromExternalLaunch -> { FromExternalLaunch -> {
coreReaderLifeCycleScope?.launch { if (!isAdded) return
if (!isAdded) return@launch val settings =
val settings = activity?.getSharedPreferences(SharedPreferenceUtil.PREF_KIWIX_MOBILE, 0)
activity?.getSharedPreferences(SharedPreferenceUtil.PREF_KIWIX_MOBILE, 0) val zimReaderSource = fromDatabaseValue(settings?.getString(TAG_CURRENT_FILE, null))
val zimReaderSource = fromDatabaseValue(settings?.getString(TAG_CURRENT_FILE, null)) if (zimReaderSource?.canOpenInLibkiwix() == true) {
if (zimReaderSource?.canOpenInLibkiwix() == true) { if (zimReaderContainer?.zimReaderSource == null) {
if (zimReaderContainer?.zimReaderSource == null) { openZimFile(zimReaderSource, isFromManageExternalLaunch = true)
openZimFile(zimReaderSource, isFromManageExternalLaunch = true) Log.d(
Log.d( TAG_KIWIX,
TAG_KIWIX, "Kiwix normal start, Opened last used zimFile: -> ${zimReaderSource.toDatabase()}"
"Kiwix normal start, Opened last used zimFile: -> ${zimReaderSource.toDatabase()}"
)
} else {
zimReaderContainer?.zimFileReader?.let(::setUpBookmarks)
}
restoreTabs(webViewHistoryItemList, currentTab, onComplete)
} else {
readerScreenState.value.snackBarHostState.snack(
requireActivity().getString(string.zim_not_opened),
lifecycleScope = lifecycleScope
) )
exitBook() // hide the options for zim file to avoid unexpected UI behavior } else {
zimReaderContainer?.zimFileReader?.let(::setUpBookmarks)
} }
restoreTabs(webViewHistoryItemList, currentTab, onComplete)
} else {
readerScreenState.value.snackBarHostState.snack(
requireActivity().getString(string.zim_not_opened),
lifecycleScope = lifecycleScope
)
exitBook() // hide the options for zim file to avoid unexpected UI behavior
} }
} }

View File

@ -172,6 +172,7 @@ import java.io.IOException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import javax.inject.Inject import javax.inject.Inject
import kotlin.concurrent.Volatile
import kotlin.math.max import kotlin.math.max
const val SEARCH_ITEM_TITLE_KEY = "searchItemTitle" const val SEARCH_ITEM_TITLE_KEY = "searchItemTitle"
@ -224,7 +225,8 @@ abstract class CoreReaderFragment :
protected var currentWebViewIndex by mutableStateOf(0) protected var currentWebViewIndex by mutableStateOf(0)
private var currentTtsWebViewIndex = 0 private var currentTtsWebViewIndex = 0
private var isFirstTimeMainPageLoaded = true private var isFirstTimeMainPageLoaded = true
private var isFromManageExternalLaunch = false
@Volatile var isFromManageExternalLaunch = false
private val savingTabsMutex = Mutex() private val savingTabsMutex = Mutex()
private var searchItemToOpen: SearchItemToOpen? = null private var searchItemToOpen: SearchItemToOpen? = null
private var findInPageTitle: String? = null private var findInPageTitle: String? = null
@ -340,6 +342,8 @@ abstract class CoreReaderFragment :
*/ */
private var pendingIntent: Intent? = null private var pendingIntent: Intent? = null
@Volatile var isWebViewHistoryRestoring = false
private var storagePermissionForNotesLauncher: ActivityResultLauncher<String>? = private var storagePermissionForNotesLauncher: ActivityResultLauncher<String>? =
registerForActivityResult( registerForActivityResult(
ActivityResultContracts.RequestPermission() ActivityResultContracts.RequestPermission()
@ -2304,6 +2308,9 @@ abstract class CoreReaderFragment :
} }
updateBottomToolbarVisibility() updateBottomToolbarVisibility()
updateNightMode() updateNightMode()
if (!isWebViewHistoryRestoring) {
saveTabStates()
}
} }
} }
@ -2333,7 +2340,6 @@ abstract class CoreReaderFragment :
showProgressBarWithProgress(progress) showProgressBarWithProgress(progress)
if (progress == 100) { if (progress == 100) {
hideProgressBar() hideProgressBar()
saveTabStates()
Log.d(TAG_KIWIX, "Loaded URL: " + getCurrentWebView()?.url) Log.d(TAG_KIWIX, "Loaded URL: " + getCurrentWebView()?.url)
} }
(webView.context as AppCompatActivity).invalidateOptionsMenu() (webView.context as AppCompatActivity).invalidateOptionsMenu()
@ -2434,6 +2440,7 @@ abstract class CoreReaderFragment :
restoreViewStateOnInvalidWebViewHistory() restoreViewStateOnInvalidWebViewHistory()
// handle the pending intent if any present. // handle the pending intent if any present.
handlePendingIntent() handlePendingIntent()
isWebViewHistoryRestoring = false
return return
} }
restoreViewStateOnValidWebViewHistory( restoreViewStateOnValidWebViewHistory(
@ -2446,11 +2453,14 @@ abstract class CoreReaderFragment :
// to open the specified item, then sets `searchItemToOpen` to null to prevent // to open the specified item, then sets `searchItemToOpen` to null to prevent
// any unexpected behavior on future calls. Similarly, if `findInPageTitle` is set, // any unexpected behavior on future calls. Similarly, if `findInPageTitle` is set,
// it invokes `findInPage` and resets `findInPageTitle` to null. // it invokes `findInPage` and resets `findInPageTitle` to null.
isWebViewHistoryRestoring = false
searchItemToOpen?.let(::openSearchItem) searchItemToOpen?.let(::openSearchItem)
searchItemToOpen = null searchItemToOpen = null
findInPageTitle?.let(::findInPage) findInPageTitle?.let(::findInPage)
findInPageTitle = null findInPageTitle = null
handlePendingIntent() handlePendingIntent()
// When the restoration completes than save the tabs history.
saveTabStates()
} }
}.onFailure { }.onFailure {
Log.e( Log.e(
@ -2460,6 +2470,7 @@ abstract class CoreReaderFragment :
restoreViewStateOnInvalidWebViewHistory() restoreViewStateOnInvalidWebViewHistory()
// handle the pending intent if any present. // handle the pending intent if any present.
handlePendingIntent() handlePendingIntent()
isWebViewHistoryRestoring = false
} }
} }
@ -2487,7 +2498,7 @@ abstract class CoreReaderFragment :
* @Warning: This method restores tabs state in new launches, do not modify it * @Warning: This method restores tabs state in new launches, do not modify it
* unless it is explicitly mentioned in the issue you're fixing. * unless it is explicitly mentioned in the issue you're fixing.
*/ */
protected fun restoreTabs( protected suspend fun restoreTabs(
webViewHistoryItemList: List<WebViewHistoryItem>, webViewHistoryItemList: List<WebViewHistoryItem>,
currentTab: Int, currentTab: Int,
onComplete: () -> Unit onComplete: () -> Unit
@ -2612,7 +2623,7 @@ abstract class CoreReaderFragment :
* KiwixReaderFragment.restoreViewStateOnValidWebViewHistory) to ensure consistent behavior * KiwixReaderFragment.restoreViewStateOnValidWebViewHistory) to ensure consistent behavior
* when handling valid webViewHistory scenarios. * when handling valid webViewHistory scenarios.
*/ */
protected abstract fun restoreViewStateOnValidWebViewHistory( protected abstract suspend fun restoreViewStateOnValidWebViewHistory(
webViewHistoryItemList: List<WebViewHistoryItem>, webViewHistoryItemList: List<WebViewHistoryItem>,
currentTab: Int, currentTab: Int,
restoreOrigin: RestoreOrigin, restoreOrigin: RestoreOrigin,
@ -2627,7 +2638,7 @@ abstract class CoreReaderFragment :
* KiwixReaderFragment.restoreViewStateOnInvalidWebViewHistory) to ensure consistent behavior * KiwixReaderFragment.restoreViewStateOnInvalidWebViewHistory) to ensure consistent behavior
* when handling invalid JSON scenarios. * when handling invalid JSON scenarios.
*/ */
abstract fun restoreViewStateOnInvalidWebViewHistory() abstract suspend fun restoreViewStateOnInvalidWebViewHistory()
} }
enum class RestoreOrigin { enum class RestoreOrigin {

View File

@ -185,8 +185,14 @@ class CustomReaderFragment : CoreReaderFragment() {
// See https://github.com/kiwix/kiwix-android/issues/3541 // See https://github.com/kiwix/kiwix-android/issues/3541
zimReaderContainer?.zimFileReader?.let(::setUpBookmarks) zimReaderContainer?.zimFileReader?.let(::setUpBookmarks)
} else { } else {
isWebViewHistoryRestoring = true
isFromManageExternalLaunch = true
coreReaderLifeCycleScope?.launch { coreReaderLifeCycleScope?.launch {
openObbOrZim(true) if (zimReaderContainer?.zimFileReader == null || zimReaderContainer?.zimReaderSource?.exists() == false) {
openObbOrZim(true)
} else {
manageExternalLaunchAndRestoringViewState()
}
} }
} }
customMainActivity?.consumeObservable<String>(PAGE_URL_KEY) customMainActivity?.consumeObservable<String>(PAGE_URL_KEY)
@ -197,7 +203,7 @@ class CustomReaderFragment : CoreReaderFragment() {
* due to the absence of any history records. In this case, it navigates to the homepage of the * 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. * ZIM file, as custom apps are expected to have the ZIM file readily available.
*/ */
override fun restoreViewStateOnInvalidWebViewHistory() { override suspend fun restoreViewStateOnInvalidWebViewHistory() {
openHomeScreen() openHomeScreen()
} }
@ -205,7 +211,7 @@ class CustomReaderFragment : CoreReaderFragment() {
* Restores the view state when the webViewHistory data is valid. * Restores the view state when the webViewHistory data is valid.
* This method restores the tabs with webView pages history. * This method restores the tabs with webView pages history.
*/ */
override fun restoreViewStateOnValidWebViewHistory( override suspend fun restoreViewStateOnValidWebViewHistory(
webViewHistoryItemList: List<WebViewHistoryItem>, webViewHistoryItemList: List<WebViewHistoryItem>,
currentTab: Int, currentTab: Int,
// Unused in custom apps as there is only one ZIM file that is already set. // Unused in custom apps as there is only one ZIM file that is already set.
@ -430,8 +436,13 @@ class CustomReaderFragment : CoreReaderFragment() {
super.onResume() super.onResume()
if (appSettingsLaunched) { if (appSettingsLaunched) {
appSettingsLaunched = false appSettingsLaunched = false
isWebViewHistoryRestoring = true
coreReaderLifeCycleScope?.launch { coreReaderLifeCycleScope?.launch {
openObbOrZim(true) if (zimReaderContainer?.zimFileReader == null) {
openObbOrZim(true)
} else {
manageExternalLaunchAndRestoringViewState()
}
} }
} }
} }