mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-08-03 10:46:53 -04:00
Fixed: Pressing the back button no longer reopens the Search fragment when you’re on the Reader fragment and navigated there from Search (which was happening before).
* Fixed: Pressing the back button now correctly closes the left drawer when it’s open on the Local Library or Online fragments. * Introduced: A common mechanism to support back press handling across all fragments and the activity, and added support for "Periodic back navigation".
This commit is contained in:
parent
51bd9e7908
commit
8112632c80
@ -51,11 +51,9 @@ import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
||||
import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange
|
||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||
import org.kiwix.kiwixmobile.core.utils.TestingUtils.COMPOSE_TEST_RULE_ORDER
|
||||
import org.kiwix.kiwixmobile.core.utils.TestingUtils.RETRY_RULE_ORDER
|
||||
import org.kiwix.kiwixmobile.main.KiwixMainActivity
|
||||
import org.kiwix.kiwixmobile.main.topLevel
|
||||
import org.kiwix.kiwixmobile.nav.destination.library.library
|
||||
import org.kiwix.kiwixmobile.testutils.RetryRule
|
||||
import org.kiwix.kiwixmobile.testutils.TestUtils
|
||||
import org.kiwix.kiwixmobile.testutils.TestUtils.closeSystemDialogs
|
||||
import org.kiwix.kiwixmobile.testutils.TestUtils.isSystemUINotRespondingDialogVisible
|
||||
@ -65,9 +63,9 @@ import java.util.concurrent.TimeUnit
|
||||
|
||||
@LargeTest
|
||||
class DownloadTest : BaseActivityTest() {
|
||||
@Rule(order = RETRY_RULE_ORDER)
|
||||
@JvmField
|
||||
val retryRule = RetryRule()
|
||||
// @Rule(order = RETRY_RULE_ORDER)
|
||||
// @JvmField
|
||||
// val retryRule = RetryRule()
|
||||
|
||||
@get:Rule(order = COMPOSE_TEST_RULE_ORDER)
|
||||
val composeTestRule = createComposeRule()
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
package org.kiwix.kiwixmobile.main
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.compose.LocalActivity
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
@ -75,6 +77,7 @@ fun KiwixMainActivityScreen(
|
||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||
val currentRoute = navBackStackEntry?.destination?.route
|
||||
val shouldShowBottomBar = currentRoute in topLevelDestinationsRoute && shouldShowBottomAppBar
|
||||
OnUserBackPressed(leftDrawerState, uiCoroutineScope, currentRoute, navController)
|
||||
KiwixTheme {
|
||||
ModalNavigationDrawer(
|
||||
drawerState = leftDrawerState,
|
||||
@ -119,6 +122,33 @@ fun KiwixMainActivityScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun OnUserBackPressed(
|
||||
leftDrawerState: DrawerState,
|
||||
uiCoroutineScope: CoroutineScope,
|
||||
currentRoute: String?,
|
||||
navController: NavHostController
|
||||
) {
|
||||
val activity = LocalActivity.current
|
||||
BackHandler(enabled = true) {
|
||||
when {
|
||||
leftDrawerState.isOpen -> uiCoroutineScope.launch { leftDrawerState.close() }
|
||||
|
||||
currentRoute == KiwixDestination.Reader.route &&
|
||||
navController.previousBackStackEntry?.destination?.route != KiwixDestination.Search.route -> {
|
||||
activity?.finish()
|
||||
}
|
||||
|
||||
else -> {
|
||||
val popped = navController.popBackStack()
|
||||
if (!popped) {
|
||||
activity?.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun BottomNavigationBar(
|
||||
|
@ -66,6 +66,7 @@ import org.kiwix.kiwixmobile.cachedComponent
|
||||
import org.kiwix.kiwixmobile.core.R.string
|
||||
import org.kiwix.kiwixmobile.core.base.BaseActivity
|
||||
import org.kiwix.kiwixmobile.core.base.BaseFragment
|
||||
import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.ZERO
|
||||
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isManageExternalStoragePermissionGranted
|
||||
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.navigate
|
||||
@ -200,7 +201,9 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
||||
onMultiSelect = { offerAction(RequestSelect(it)) },
|
||||
onRefresh = { onSwipeRefresh() },
|
||||
onDownloadButtonClick = { downloadBookButtonClick() },
|
||||
bottomAppBarScrollBehaviour = (requireActivity() as CoreMainActivity).bottomAppBarScrollBehaviour
|
||||
bottomAppBarScrollBehaviour = (requireActivity() as CoreMainActivity).bottomAppBarScrollBehaviour,
|
||||
navHostController = (requireActivity() as CoreMainActivity).navController,
|
||||
onUserBackPressed = { onUserBackPressed() }
|
||||
) {
|
||||
NavigationIcon(
|
||||
iconItem = IconItem.Vector(Icons.Filled.Menu),
|
||||
@ -213,12 +216,16 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
||||
}
|
||||
}
|
||||
|
||||
private fun onUserBackPressed(): FragmentActivityExtensions.Super {
|
||||
val coreMainActivity = (activity as? CoreMainActivity)
|
||||
if (coreMainActivity?.navigationDrawerIsOpen() == true) {
|
||||
coreMainActivity.closeNavigationDrawer()
|
||||
return FragmentActivityExtensions.Super.ShouldNotCall
|
||||
}
|
||||
return FragmentActivityExtensions.Super.ShouldCall
|
||||
}
|
||||
|
||||
private fun navigationIconClick() {
|
||||
// Manually handle the navigation open/close.
|
||||
// Since currently we are using the view based navigation drawer in other screens.
|
||||
// Once we fully migrate to jetpack compose we will refactor this code to use the
|
||||
// compose navigation.
|
||||
// TODO Replace with compose based navigation when migration is done.
|
||||
val activity = activity as CoreMainActivity
|
||||
if (activity.navigationDrawerIsOpen()) {
|
||||
activity.closeNavigationDrawer()
|
||||
|
@ -47,9 +47,12 @@ import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.navigation.NavHostController
|
||||
import org.kiwix.kiwixmobile.R.string
|
||||
import org.kiwix.kiwixmobile.core.R
|
||||
import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions
|
||||
import org.kiwix.kiwixmobile.core.main.reader.CONTENT_LOADING_PROGRESSBAR_TESTING_TAG
|
||||
import org.kiwix.kiwixmobile.core.main.reader.OnBackPressed
|
||||
import org.kiwix.kiwixmobile.core.ui.components.ContentLoadingProgressBar
|
||||
import org.kiwix.kiwixmobile.core.ui.components.KiwixAppBar
|
||||
import org.kiwix.kiwixmobile.core.ui.components.KiwixButton
|
||||
@ -73,7 +76,7 @@ const val BOOK_LIST_TESTING_TAG = "bookListTestingTag"
|
||||
const val SELECT_FILE_BUTTON_TESTING_TAG = "selectFileButtonTestingTag"
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Suppress("ComposableLambdaParameterNaming")
|
||||
@Suppress("ComposableLambdaParameterNaming", "LongParameterList")
|
||||
@Composable
|
||||
fun LocalLibraryScreen(
|
||||
state: LocalLibraryScreenState,
|
||||
@ -85,6 +88,8 @@ fun LocalLibraryScreen(
|
||||
onLongClick: ((BookOnDisk) -> Unit)? = null,
|
||||
onMultiSelect: ((BookOnDisk) -> Unit)? = null,
|
||||
bottomAppBarScrollBehaviour: BottomAppBarScrollBehavior?,
|
||||
onUserBackPressed: () -> FragmentActivityExtensions.Super,
|
||||
navHostController: NavHostController,
|
||||
navigationIcon: @Composable () -> Unit
|
||||
) {
|
||||
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
|
||||
@ -117,6 +122,7 @@ fun LocalLibraryScreen(
|
||||
.fillMaxSize()
|
||||
.padding(contentPadding)
|
||||
) {
|
||||
OnBackPressed(onUserBackPressed, navHostController)
|
||||
if (state.scanningProgressItem.first) {
|
||||
ContentLoadingProgressBar(
|
||||
modifier = Modifier.testTag(CONTENT_LOADING_PROGRESSBAR_TESTING_TAG),
|
||||
|
@ -29,7 +29,6 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
@ -271,7 +270,9 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
|
||||
onClick = { navigationIconClick(onlineLibraryScreenState.value.value.isSearchActive) }
|
||||
)
|
||||
},
|
||||
bottomAppBarScrollBehaviour = (requireActivity() as CoreMainActivity).bottomAppBarScrollBehaviour
|
||||
bottomAppBarScrollBehaviour = (requireActivity() as CoreMainActivity).bottomAppBarScrollBehaviour,
|
||||
navHostController = (requireActivity() as CoreMainActivity).navController,
|
||||
onUserBackPressed = { onUserBackPressed() }
|
||||
)
|
||||
DialogHost(alertDialogShower)
|
||||
}
|
||||
@ -460,8 +461,13 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
|
||||
composeView = null
|
||||
}
|
||||
|
||||
override fun onBackPressed(activity: AppCompatActivity): FragmentActivityExtensions.Super {
|
||||
if (isKeyboardVisible() || onlineLibraryScreenState.value.value.isSearchActive) {
|
||||
@Suppress("ReturnCount")
|
||||
private fun onUserBackPressed(): FragmentActivityExtensions.Super {
|
||||
val coreMainActivity = (activity as? CoreMainActivity)
|
||||
if (coreMainActivity?.navigationDrawerIsOpen() == true) {
|
||||
coreMainActivity.closeNavigationDrawer()
|
||||
return FragmentActivityExtensions.Super.ShouldNotCall
|
||||
} else if (isKeyboardVisible() || onlineLibraryScreenState.value.value.isSearchActive) {
|
||||
closeKeyboard()
|
||||
closeSearch()
|
||||
return FragmentActivityExtensions.Super.ShouldNotCall
|
||||
|
@ -56,12 +56,15 @@ import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.semantics.testTag
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.navigation.NavHostController
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import org.kiwix.kiwixmobile.core.R.string
|
||||
import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.FIVE
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.ZERO
|
||||
import org.kiwix.kiwixmobile.core.extensions.hideKeyboardOnLazyColumnScroll
|
||||
import org.kiwix.kiwixmobile.core.main.reader.OnBackPressed
|
||||
import org.kiwix.kiwixmobile.core.ui.components.ContentLoadingProgressBar
|
||||
import org.kiwix.kiwixmobile.core.ui.components.KiwixAppBar
|
||||
import org.kiwix.kiwixmobile.core.ui.components.KiwixSearchView
|
||||
@ -99,6 +102,8 @@ fun OnlineLibraryScreen(
|
||||
actionMenuItems: List<ActionMenuItem>,
|
||||
listState: LazyListState,
|
||||
bottomAppBarScrollBehaviour: BottomAppBarScrollBehavior?,
|
||||
onUserBackPressed: () -> FragmentActivityExtensions.Super,
|
||||
navHostController: NavHostController,
|
||||
navigationIcon: @Composable () -> Unit,
|
||||
) {
|
||||
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
|
||||
@ -135,6 +140,7 @@ fun OnlineLibraryScreen(
|
||||
end = paddingValues.calculateEndPadding(LocalLayoutDirection.current),
|
||||
)
|
||||
) {
|
||||
OnBackPressed(onUserBackPressed, navHostController)
|
||||
OnlineLibraryScreenContent(state, listState)
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:enableOnBackInvokedCallback="false"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:hardwareAccelerated="true"
|
||||
android:hasFragileUserData="true"
|
||||
|
@ -24,7 +24,6 @@ import android.os.Process
|
||||
import android.view.ActionMode
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.material3.BottomAppBarScrollBehavior
|
||||
@ -38,7 +37,6 @@ import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.NavDirections
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.NavOptions
|
||||
import com.google.android.material.navigation.NavigationView
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@ -47,7 +45,6 @@ import org.kiwix.kiwixmobile.core.CoreApp
|
||||
import org.kiwix.kiwixmobile.core.R
|
||||
import org.kiwix.kiwixmobile.core.base.BaseActivity
|
||||
import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions
|
||||
import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions.Super.ShouldCall
|
||||
import org.kiwix.kiwixmobile.core.data.remote.ObjectBoxToLibkiwixMigrator
|
||||
import org.kiwix.kiwixmobile.core.data.remote.ObjectBoxToRoomMigrator
|
||||
import org.kiwix.kiwixmobile.core.di.components.CoreActivityComponent
|
||||
@ -144,6 +141,11 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider {
|
||||
*/
|
||||
val enableLeftDrawer = mutableStateOf(true)
|
||||
|
||||
/**
|
||||
* For managing the back press of fragments.
|
||||
*/
|
||||
val customBackHandler = mutableStateOf<(() -> FragmentActivityExtensions.Super)?>(null)
|
||||
|
||||
/**
|
||||
* For managing the the showing/hiding the bottomAppBar when scrolling.
|
||||
*/
|
||||
@ -197,7 +199,6 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
createApplicationShortcuts()
|
||||
}
|
||||
handleBackPressed()
|
||||
leftDrawerMenu.addAll(leftNavigationDrawerMenuItems)
|
||||
}
|
||||
|
||||
@ -231,11 +232,6 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
onBackPressedCallBack.remove()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
startMonitoringDownloads()
|
||||
downloadMonitor.stopListeningDownloads()
|
||||
@ -253,11 +249,6 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UnusedParameter")
|
||||
private fun NavigationView.setLockMode(lockMode: Int) {
|
||||
// drawerContainerLayout.setDrawerLockMode(lockMode, this)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
@ -339,41 +330,6 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider {
|
||||
externalLinkOpener.openExternalUrl(KIWIX_SUPPORT_URL.toUri().browserIntent(), false)
|
||||
}
|
||||
|
||||
private fun handleBackPressed() {
|
||||
onBackPressedDispatcher.addCallback(this, onBackPressedCallBack)
|
||||
}
|
||||
|
||||
private val onBackPressedCallBack =
|
||||
object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
if (navigationDrawerIsOpen()) {
|
||||
closeNavigationDrawer()
|
||||
return
|
||||
}
|
||||
if (activeFragments().filterIsInstance<FragmentActivityExtensions>().isEmpty()) {
|
||||
isEnabled = false
|
||||
return onBackPressedDispatcher.onBackPressed().also {
|
||||
isEnabled = true
|
||||
}
|
||||
}
|
||||
activeFragments().filterIsInstance<FragmentActivityExtensions>().forEach {
|
||||
if (it.onBackPressed(this@CoreMainActivity) == ShouldCall) {
|
||||
if (navController.currentDestination?.route?.equals(readerFragmentRoute) == true &&
|
||||
navController.previousBackStackEntry?.destination
|
||||
?.route?.equals(searchFragmentRoute) == false
|
||||
) {
|
||||
drawerToggle = null
|
||||
finish()
|
||||
} else {
|
||||
isEnabled = false
|
||||
onBackPressedDispatcher.onBackPressed()
|
||||
isEnabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
if (activeFragments().filterIsInstance<FragmentActivityExtensions>().isEmpty()) {
|
||||
return super.onCreateOptionsMenu(menu)
|
||||
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Kiwix Android
|
||||
* Copyright (c) 2020 Kiwix <android.kiwix.org>
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.kiwix.kiwixmobile.core.main
|
||||
|
||||
import android.graphics.Typeface
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView.Adapter
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import org.kiwix.kiwixmobile.core.R
|
||||
import org.kiwix.kiwixmobile.core.base.adapter.BaseViewHolder
|
||||
import org.kiwix.kiwixmobile.core.databinding.SectionListBinding
|
||||
|
||||
class TableDrawerAdapter constructor(
|
||||
private val listener: TableClickListener
|
||||
) : Adapter<ViewHolder>() {
|
||||
private var title: String = ""
|
||||
private val sections: MutableList<DocumentSection> = mutableListOf()
|
||||
|
||||
fun setSections(sections: List<DocumentSection>) {
|
||||
this.sections.clear()
|
||||
this.sections.addAll(sections)
|
||||
}
|
||||
|
||||
fun setTitle(title: String) {
|
||||
this.title = title
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (position == 0) {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
viewType: Int
|
||||
): ViewHolder {
|
||||
val binding = SectionListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return if (viewType == 0) {
|
||||
HeaderTableDrawerViewHolder(binding)
|
||||
} else {
|
||||
SectionTableDrawerViewHolder(binding)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int = sections.size + 1
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
when (holder) {
|
||||
is HeaderTableDrawerViewHolder -> {
|
||||
holder.bind(title)
|
||||
holder.itemView.setOnClickListener(listener::onHeaderClick)
|
||||
}
|
||||
|
||||
is SectionTableDrawerViewHolder -> {
|
||||
val titleAdjustedPosition = position - 1
|
||||
holder.bind(sections[titleAdjustedPosition])
|
||||
holder.itemView.setOnClickListener {
|
||||
listener.onSectionClick(it, titleAdjustedPosition)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
throw IllegalStateException("Unknown ViewHolder $holder found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface TableClickListener {
|
||||
fun onHeaderClick(view: View?)
|
||||
fun onSectionClick(view: View?, position: Int)
|
||||
}
|
||||
|
||||
class HeaderTableDrawerViewHolder(private val sectionListBinding: SectionListBinding) :
|
||||
BaseViewHolder<String>(sectionListBinding.root) {
|
||||
override fun bind(item: String) {
|
||||
val context = itemView.context
|
||||
sectionListBinding.titleText.typeface = Typeface.DEFAULT_BOLD
|
||||
sectionListBinding.titleText.text =
|
||||
when {
|
||||
item.isNotEmpty() -> item
|
||||
context is WebViewProvider ->
|
||||
context.getCurrentWebView()?.title
|
||||
?: context.getString(R.string.no_section_info)
|
||||
|
||||
else -> context.getString(R.string.no_section_info)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SectionTableDrawerViewHolder(private val sectionListBinding: SectionListBinding) :
|
||||
BaseViewHolder<TableDrawerAdapter.DocumentSection>(sectionListBinding.root) {
|
||||
override fun bind(
|
||||
item: TableDrawerAdapter.DocumentSection
|
||||
) {
|
||||
val context = itemView.context
|
||||
val padding =
|
||||
((item.level - 1) * context.resources.getDimension(R.dimen.title_text_padding)).toInt()
|
||||
sectionListBinding.titleText.setPadding(padding, 0, 0, 0)
|
||||
sectionListBinding.titleText.text = item.title
|
||||
}
|
||||
}
|
||||
|
||||
data class DocumentSection(var title: String, var id: String, var level: Int)
|
||||
}
|
@ -474,7 +474,9 @@ abstract class CoreReaderFragment :
|
||||
},
|
||||
mainActivityBottomAppBarScrollBehaviour = (requireActivity() as CoreMainActivity).bottomAppBarScrollBehaviour,
|
||||
documentSections = documentSections,
|
||||
showTableOfContentDrawer = shouldTableOfContentDrawer
|
||||
showTableOfContentDrawer = shouldTableOfContentDrawer,
|
||||
onUserBackPressed = { onUserBackPressed(requireActivity() as CoreMainActivity) },
|
||||
navHostController = (requireActivity() as CoreMainActivity).navController
|
||||
)
|
||||
DialogHost(alertDialogShower as AlertDialogShower)
|
||||
}
|
||||
@ -842,9 +844,16 @@ abstract class CoreReaderFragment :
|
||||
shouldTableOfContentDrawer.update { true }
|
||||
}
|
||||
|
||||
@Suppress("ReturnCount", "NestedBlockDepth")
|
||||
override fun onBackPressed(activity: AppCompatActivity): FragmentActivityExtensions.Super {
|
||||
@Suppress("ReturnCount", "NestedBlockDepth", "LongMethod", "CyclomaticComplexMethod")
|
||||
private fun onUserBackPressed(coreMainActivity: CoreMainActivity): FragmentActivityExtensions.Super {
|
||||
when {
|
||||
coreMainActivity.leftDrawerState.isOpen -> {
|
||||
coreMainActivity.uiCoroutineScope.launch {
|
||||
coreMainActivity.leftDrawerState.close()
|
||||
}
|
||||
return FragmentActivityExtensions.Super.ShouldNotCall
|
||||
}
|
||||
|
||||
readerScreenState.value.showTabSwitcher -> {
|
||||
selectTab(
|
||||
if (currentWebViewIndex < webViewList.size) {
|
||||
@ -893,7 +902,12 @@ abstract class CoreReaderFragment :
|
||||
isHomePageOfServiceWorkerZimFiles(url, webViewBackWordHistoryList)
|
||||
) {
|
||||
// If it is the last page that is showing to the user, then exit the application.
|
||||
return@onBackPressed FragmentActivityExtensions.Super.ShouldCall
|
||||
if (coreMainActivity.navController.previousBackStackEntry?.destination?.route !=
|
||||
coreMainActivity.searchFragmentRoute
|
||||
) {
|
||||
activity?.finish()
|
||||
}
|
||||
return FragmentActivityExtensions.Super.ShouldCall
|
||||
}
|
||||
}
|
||||
// Otherwise, go to the previous page.
|
||||
|
@ -22,6 +22,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
import android.widget.FrameLayout
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
@ -114,9 +115,11 @@ import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.compose.ui.zIndex
|
||||
import androidx.navigation.NavHostController
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.kiwix.kiwixmobile.core.R
|
||||
import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.HUNDERED
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.ZERO
|
||||
import org.kiwix.kiwixmobile.core.extensions.update
|
||||
@ -177,13 +180,15 @@ const val READER_BOTTOM_BAR_TABLE_CONTENT_BUTTON_TESTING_TAG =
|
||||
"readerBottomBarTableContentButtonTestingTag"
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Suppress("ComposableLambdaParameterNaming", "LongMethod")
|
||||
@Suppress("ComposableLambdaParameterNaming", "LongMethod", "LongParameterList")
|
||||
@Composable
|
||||
fun ReaderScreen(
|
||||
state: ReaderScreenState,
|
||||
actionMenuItems: List<ActionMenuItem>,
|
||||
showTableOfContentDrawer: MutableState<Boolean>,
|
||||
documentSections: MutableList<DocumentSection>?,
|
||||
onUserBackPressed: () -> FragmentActivityExtensions.Super,
|
||||
navHostController: NavHostController,
|
||||
mainActivityBottomAppBarScrollBehaviour: BottomAppBarScrollBehavior?,
|
||||
navigationIcon: @Composable () -> Unit
|
||||
) {
|
||||
@ -215,6 +220,7 @@ fun ReaderScreen(
|
||||
}
|
||||
.semantics { testTag = READER_SCREEN_TESTING_TAG }
|
||||
) { paddingValues ->
|
||||
OnBackPressed(onUserBackPressed, navHostController)
|
||||
ReaderContentLayout(
|
||||
state,
|
||||
Modifier.padding(paddingValues),
|
||||
@ -251,6 +257,19 @@ fun ReaderScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun OnBackPressed(
|
||||
onUserBackPressed: () -> FragmentActivityExtensions.Super,
|
||||
navHostController: NavHostController
|
||||
) {
|
||||
BackHandler(enabled = true) {
|
||||
val result = onUserBackPressed()
|
||||
if (result == FragmentActivityExtensions.Super.ShouldCall) {
|
||||
navHostController.popBackStack()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Suppress("ComposableLambdaParameterNaming")
|
||||
@Composable
|
||||
@ -731,7 +750,8 @@ private fun BottomAppBarButtonIcon(
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClick,
|
||||
enabled = shouldEnable
|
||||
).testTag(testingTag),
|
||||
)
|
||||
.testTag(testingTag),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
|
@ -22,7 +22,7 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.lifecycle.Lifecycle
|
||||
@ -39,6 +39,7 @@ import kotlinx.coroutines.withContext
|
||||
import org.kiwix.kiwixmobile.core.R
|
||||
import org.kiwix.kiwixmobile.core.base.BaseActivity
|
||||
import org.kiwix.kiwixmobile.core.base.BaseFragment
|
||||
import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions
|
||||
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent
|
||||
import org.kiwix.kiwixmobile.core.extensions.closeKeyboard
|
||||
import org.kiwix.kiwixmobile.core.extensions.coreMainActivity
|
||||
@ -123,6 +124,12 @@ class SearchFragment : BaseFragment() {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
composeView?.apply {
|
||||
setContent {
|
||||
DisposableEffect(Unit) {
|
||||
(activity as CoreMainActivity).customBackHandler.value = { handleBackPress() }
|
||||
onDispose {
|
||||
(activity as CoreMainActivity).customBackHandler.value = null
|
||||
}
|
||||
}
|
||||
SearchScreen(
|
||||
searchScreenState.value,
|
||||
actionMenuItems(),
|
||||
@ -134,7 +141,6 @@ class SearchFragment : BaseFragment() {
|
||||
searchViewModel.setAlertDialogShower(dialogShower as AlertDialogShower)
|
||||
observeViewModelData()
|
||||
handleSearchArgument()
|
||||
handleBackPress()
|
||||
}
|
||||
|
||||
private fun handleSearchArgument() {
|
||||
@ -203,15 +209,9 @@ class SearchFragment : BaseFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleBackPress() {
|
||||
activity?.onBackPressedDispatcher?.addCallback(
|
||||
viewLifecycleOwner,
|
||||
object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
goBack()
|
||||
}
|
||||
}
|
||||
)
|
||||
private fun handleBackPress(): FragmentActivityExtensions.Super {
|
||||
goBack()
|
||||
return FragmentActivityExtensions.Super.ShouldCall
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
@ -71,7 +71,9 @@ class CustomMainActivity : CoreMainActivity() {
|
||||
leftDrawerContent = leftDrawerMenu,
|
||||
topLevelDestinationsRoute = topLevelDestinationsRoute,
|
||||
leftDrawerState = leftDrawerState,
|
||||
enableLeftDrawer = enableLeftDrawer.value
|
||||
enableLeftDrawer = enableLeftDrawer.value,
|
||||
uiCoroutineScope = uiCoroutineScope,
|
||||
customBackHandler = customBackHandler
|
||||
)
|
||||
DialogHost(alertDialogShower)
|
||||
}
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
package org.kiwix.kiwixmobile.custom.main
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.compose.LocalActivity
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
@ -27,10 +29,14 @@ import androidx.compose.material3.DrawerState
|
||||
import androidx.compose.material3.ModalNavigationDrawer
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions
|
||||
import org.kiwix.kiwixmobile.core.main.DrawerMenuGroup
|
||||
import org.kiwix.kiwixmobile.core.main.LeftDrawerMenu
|
||||
import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme
|
||||
@ -42,9 +48,18 @@ fun CustomMainActivityScreen(
|
||||
topLevelDestinationsRoute: Set<String>,
|
||||
leftDrawerState: DrawerState,
|
||||
enableLeftDrawer: Boolean,
|
||||
customBackHandler: MutableState<(() -> FragmentActivityExtensions.Super)?>,
|
||||
uiCoroutineScope: CoroutineScope
|
||||
) {
|
||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||
val currentRoute = navBackStackEntry?.destination?.route
|
||||
OnUserBackPressed(
|
||||
leftDrawerState,
|
||||
uiCoroutineScope,
|
||||
currentRoute,
|
||||
navController,
|
||||
customBackHandler
|
||||
)
|
||||
KiwixTheme {
|
||||
ModalNavigationDrawer(
|
||||
drawerState = leftDrawerState,
|
||||
@ -76,3 +91,34 @@ fun CustomMainActivityScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun OnUserBackPressed(
|
||||
leftDrawerState: DrawerState,
|
||||
uiCoroutineScope: CoroutineScope,
|
||||
currentRoute: String?,
|
||||
navController: NavHostController,
|
||||
customBackHandler: MutableState<(() -> FragmentActivityExtensions.Super)?>,
|
||||
) {
|
||||
val activity = LocalActivity.current
|
||||
BackHandler(enabled = true) {
|
||||
when {
|
||||
leftDrawerState.isOpen -> uiCoroutineScope.launch { leftDrawerState.close() }
|
||||
customBackHandler.value?.invoke() == FragmentActivityExtensions.Super.ShouldNotCall -> {
|
||||
// do nothing since fragment handles the back press.
|
||||
}
|
||||
|
||||
currentRoute == CustomDestination.Reader.route &&
|
||||
navController.previousBackStackEntry?.destination?.route != CustomDestination.Search.route -> {
|
||||
activity?.finish()
|
||||
}
|
||||
|
||||
else -> {
|
||||
val popped = navController.popBackStack()
|
||||
if (!popped) {
|
||||
activity?.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user