diff --git a/app/src/main/java/org/kiwix/kiwixmobile/intro/IntroFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/intro/IntroFragment.kt index 66efa6c1c..7ad4c018f 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/intro/IntroFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/intro/IntroFragment.kt @@ -22,11 +22,13 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.compose.ui.platform.ComposeView -import androidx.navigation.fragment.findNavController +import androidx.navigation.NavOptions import org.kiwix.kiwixmobile.cachedComponent 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.main.CoreMainActivity +import org.kiwix.kiwixmobile.ui.KiwixDestination import javax.inject.Inject class IntroFragment : BaseFragment(), IntroContract.View, FragmentActivityExtensions { @@ -58,7 +60,10 @@ class IntroFragment : BaseFragment(), IntroContract.View, FragmentActivityExtens private fun navigateToLibrary() { presenter.setIntroShown() - findNavController().navigate(IntroFragmentDirections.actionIntrofragmentToLibraryFragment()) + val navOptions = NavOptions.Builder() + .setPopUpTo(KiwixDestination.Intro.route, inclusive = true) + .build() + (requireActivity() as CoreMainActivity).navigate(KiwixDestination.Library.route, navOptions) } override fun onDestroyView() { diff --git a/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt b/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt index 659f00078..a69606a54 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivity.kt @@ -28,18 +28,22 @@ import android.view.MenuItem import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode +import androidx.compose.material3.BottomAppBarDefaults import androidx.compose.material3.DrawerValue +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.rememberDrawerState import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.rememberCoroutineScope import androidx.core.content.pm.ShortcutInfoCompat import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.graphics.drawable.IconCompat import androidx.core.os.ConfigurationCompat -import androidx.core.os.bundleOf import androidx.lifecycle.lifecycleScope import androidx.navigation.NavController +import androidx.navigation.NavOptions import androidx.navigation.compose.rememberNavController +import com.google.android.material.bottomnavigation.BottomNavigationView import eu.mhutti1.utils.storage.StorageDevice import eu.mhutti1.utils.storage.StorageDeviceUtils import kotlinx.coroutines.delay @@ -59,9 +63,9 @@ import org.kiwix.kiwixmobile.core.main.ACTION_NEW_TAB import org.kiwix.kiwixmobile.core.main.CoreMainActivity import org.kiwix.kiwixmobile.core.main.DrawerMenuItem import org.kiwix.kiwixmobile.core.main.NEW_TAB_SHORTCUT_ID -import org.kiwix.kiwixmobile.core.main.ZIM_FILE_URI_KEY import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange import org.kiwix.kiwixmobile.core.utils.dialog.AlertDialogShower +import org.kiwix.kiwixmobile.core.utils.dialog.DialogHost import org.kiwix.kiwixmobile.kiwixActivityComponent import org.kiwix.kiwixmobile.ui.KiwixDestination import javax.inject.Inject @@ -106,6 +110,7 @@ class KiwixMainActivity : CoreMainActivity() { KiwixDestination.Reader.route ) + private val shouldShowBottomAppBar = mutableStateOf(true) // private lateinit var activityKiwixMainBinding: ActivityKiwixMainBinding private var isIntroScreenVisible: Boolean = false @@ -116,6 +121,7 @@ class KiwixMainActivity : CoreMainActivity() { } private val storageDeviceList = arrayListOf() + @OptIn(ExperimentalMaterial3Api::class) override fun onCreate(savedInstanceState: Bundle?) { cachedComponent.inject(this) super.onCreate(savedInstanceState) @@ -123,17 +129,27 @@ class KiwixMainActivity : CoreMainActivity() { navController = rememberNavController() leftDrawerState = rememberDrawerState(DrawerValue.Closed) uiCoroutineScope = rememberCoroutineScope() + bottomAppBarScrollBehaviour = BottomAppBarDefaults.exitAlwaysScrollBehavior() KiwixMainActivityScreen( navController = navController, leftDrawerContent = leftDrawerMenu, topLevelDestinationsRoute = topLevelDestinationsRoute, leftDrawerState = leftDrawerState, uiCoroutineScope = uiCoroutineScope, - enableLeftDrawer = enableLeftDrawer.value + enableLeftDrawer = enableLeftDrawer.value, + shouldShowBottomAppBar = shouldShowBottomAppBar.value, + bottomAppBarScrollBehaviour = bottomAppBarScrollBehaviour ) LaunchedEffect(navController) { navController.addOnDestinationChangedListener(finishActionModeOnDestinationChange) + if (sharedPreferenceUtil.showIntro() && !isIntroScreenNotVisible()) { + val navOptions = NavOptions.Builder() + .setPopUpTo(KiwixDestination.Reader.route, inclusive = true) + .build() + navigate(KiwixDestination.Intro.route, navOptions) + } } + DialogHost(alertDialogShower) } // activityKiwixMainBinding.drawerNavView.apply { // setupWithNavController(navController) @@ -191,34 +207,12 @@ class KiwixMainActivity : CoreMainActivity() { override fun onStart() { super.onStart() - if (sharedPreferenceUtil.showIntro() && !isIntroScreenNotVisible()) { - // navigate(KiwixReaderFragmentDirections.actionReaderFragmentToIntroFragment()) - } if (!sharedPreferenceUtil.prefIsTest) { sharedPreferenceUtil.setIsPlayStoreBuildType(BuildConfig.IS_PLAYSTORE) } setDefaultDeviceLanguage() } - /** - * This is for manually showing/hiding the BottomNavigationView with animation from compose - * screens until we migrate the BottomNavigationView to compose. Once we migrate we will remove it. - * - * TODO Remove this once we migrate to compose. - */ - override fun toggleBottomNavigation(isVisible: Boolean) { - // activityKiwixMainBinding.bottomNavView.animate() - // ?.translationY( - // if (isVisible) { - // ZERO.toFloat() - // } else { - // activityKiwixMainBinding.bottomNavView.height.toFloat() - // } - // ) - // ?.setDuration(KIWIX_BOTTOM_BAR_ANIMATION_DURATION) - // ?.start() - } - private fun setDefaultDeviceLanguage() { if (sharedPreferenceUtil.prefDeviceDefaultLanguage.isEmpty()) { ConfigurationCompat.getLocales( @@ -256,9 +250,7 @@ class KiwixMainActivity : CoreMainActivity() { private fun handleGetContentIntent(intent: Intent?) { if (intent?.action == ACTION_GET_CONTENT) { - // activityKiwixMainBinding.bottomNavView.menu.findItem(R.id.downloadsFragment)?.let { - // NavigationUI.onNavDestinationSelected(it, navController) - // } + navigate(KiwixDestination.Downloads.route) } } @@ -286,12 +278,7 @@ class KiwixMainActivity : CoreMainActivity() { } private fun openLocalLibraryWithZimFilePath(path: String) { - navigate( - R.id.libraryFragment, - bundleOf( - ZIM_FILE_URI_KEY to path, - ) - ) + navigate(KiwixDestination.Library.createRoute(zimFileUri = path)) } private fun handleNotificationIntent(intent: Intent) { @@ -307,6 +294,10 @@ class KiwixMainActivity : CoreMainActivity() { } } + private fun openZimFromFilePath(path: String) { + navigate(KiwixDestination.Reader.createRoute(zimFileUri = path)) + } + override fun onNavigationItemSelected(item: MenuItem): Boolean { when (item.itemId) { id.menu_host_books -> openZimHostFragment() @@ -359,6 +350,24 @@ class KiwixMainActivity : CoreMainActivity() { // activityKiwixMainBinding.root.addView(getDialogHostComposeView(alertDialogShower), 0) } + override fun openSearch(searchString: String, isOpenedFromTabView: Boolean, isVoice: Boolean) { + navigate( + KiwixDestination.Search.createRoute( + searchString = searchString, + isOpenedFromTabView = isOpenedFromTabView, + isVoice = isVoice + ) + ) + } + + override fun hideBottomAppBar() { + shouldShowBottomAppBar.value = false + } + + override fun showBottomAppBar() { + shouldShowBottomAppBar.value = true + } + // Outdated shortcut ids(new_tab, get_content) // Remove if the application has the outdated shortcuts. private fun removeOutdatedIdShortcuts() { 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 ccf099ad5..4c1c371d0 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivityScreen.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/main/KiwixMainActivityScreen.kt @@ -60,10 +60,11 @@ fun KiwixMainActivityScreen( topLevelDestinationsRoute: Set, leftDrawerState: DrawerState, uiCoroutineScope: CoroutineScope, - enableLeftDrawer: Boolean + enableLeftDrawer: Boolean, + shouldShowBottomAppBar: Boolean, + bottomAppBarScrollBehaviour: BottomAppBarScrollBehavior ) { val navBackStackEntry by navController.currentBackStackEntryAsState() - val scrollingBehavior = BottomAppBarDefaults.exitAlwaysScrollBehavior() KiwixTheme { ModalNavigationDrawer( drawerState = leftDrawerState, @@ -77,16 +78,17 @@ fun KiwixMainActivityScreen( Box { Scaffold( bottomBar = { - if (navBackStackEntry?.destination?.route in topLevelDestinationsRoute) { + if (navBackStackEntry?.destination?.route in topLevelDestinationsRoute && shouldShowBottomAppBar) { BottomNavigationBar( navController = navController, - scrollBehavior = scrollingBehavior, + bottomAppBarScrollBehaviour = bottomAppBarScrollBehaviour, navBackStackEntry = navBackStackEntry, leftDrawerState = leftDrawerState, uiCoroutineScope = uiCoroutineScope ) } - } + }, + modifier = Modifier.fillMaxSize() ) { paddingValues -> Box(modifier = Modifier.padding(paddingValues)) { KiwixNavGraph( @@ -104,7 +106,7 @@ fun KiwixMainActivityScreen( @Composable fun BottomNavigationBar( navController: NavHostController, - scrollBehavior: BottomAppBarScrollBehavior, + bottomAppBarScrollBehaviour: BottomAppBarScrollBehavior, navBackStackEntry: NavBackStackEntry?, leftDrawerState: DrawerState, uiCoroutineScope: CoroutineScope @@ -130,12 +132,14 @@ fun BottomNavigationBar( BottomAppBar( containerColor = Black, contentColor = White, - scrollBehavior = scrollBehavior + scrollBehavior = bottomAppBarScrollBehaviour ) { bottomNavItems.forEach { item -> 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) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/local/LocalLibraryFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/local/LocalLibraryFragment.kt index 3fb6351b6..5158941d6 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/local/LocalLibraryFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/local/LocalLibraryFragment.kt @@ -39,6 +39,7 @@ import androidx.appcompat.view.ActionMode import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Menu +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.mutableStateOf @@ -51,6 +52,7 @@ import androidx.fragment.app.FragmentActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import androidx.navigation.NavOptions import eu.mhutti1.utils.storage.Bytes import eu.mhutti1.utils.storage.StorageDevice import kotlinx.coroutines.CoroutineDispatcher @@ -78,7 +80,6 @@ import org.kiwix.kiwixmobile.core.navigateToSettings import org.kiwix.kiwixmobile.core.reader.ZimFileReader import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.ui.components.NavigationIcon -import org.kiwix.kiwixmobile.core.ui.components.rememberBottomNavigationVisibility import org.kiwix.kiwixmobile.core.ui.models.ActionMenuItem import org.kiwix.kiwixmobile.core.ui.models.IconItem import org.kiwix.kiwixmobile.core.utils.EXTERNAL_SELECT_POSITION @@ -173,6 +174,7 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal baseActivity.cachedComponent.inject(this) } + @OptIn(ExperimentalMaterial3Api::class) override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -183,10 +185,6 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal return ComposeView(requireContext()).apply { setContent { val lazyListState = rememberLazyListState() - val isBottomNavVisible = rememberBottomNavigationVisibility(lazyListState) - LaunchedEffect(isBottomNavVisible) { - (requireActivity() as KiwixMainActivity).toggleBottomNavigation(isBottomNavVisible) - } LaunchedEffect(Unit) { updateLibraryScreenState( bottomNavigationHeight = getBottomNavigationHeight(), @@ -202,6 +200,7 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal onMultiSelect = { offerAction(RequestSelect(it)) }, onRefresh = { onSwipeRefresh() }, onDownloadButtonClick = { downloadBookButtonClick() }, + bottomAppBarScrollBehaviour = (requireActivity() as CoreMainActivity).bottomAppBarScrollBehaviour ) { NavigationIcon( iconItem = IconItem.Vector(Icons.Filled.Menu), @@ -493,9 +492,12 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal zimFileReader.dispose() } } + val navOptions = NavOptions.Builder() + .setPopUpTo(KiwixDestination.Reader.route, false) + .build() activity?.navigate( - LocalLibraryFragmentDirections.actionNavigationLibraryToNavigationReader() - .apply { zimFileUri = file.toUri().toString() } + KiwixDestination.Reader.createRoute(zimFileUri = file.toUri().toString()), + navOptions ) } } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/local/LocalLibraryScreen.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/local/LocalLibraryScreen.kt index fac91b17e..5757f789b 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/local/LocalLibraryScreen.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/local/LocalLibraryScreen.kt @@ -30,6 +30,7 @@ import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.BottomAppBarScrollBehavior import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon @@ -49,7 +50,6 @@ import androidx.compose.ui.text.style.TextAlign import org.kiwix.kiwixmobile.R.string import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.main.reader.CONTENT_LOADING_PROGRESSBAR_TESTING_TAG -import org.kiwix.kiwixmobile.core.main.reader.rememberScrollBehavior import org.kiwix.kiwixmobile.core.ui.components.ContentLoadingProgressBar import org.kiwix.kiwixmobile.core.ui.components.KiwixAppBar import org.kiwix.kiwixmobile.core.ui.components.KiwixButton @@ -60,7 +60,6 @@ import org.kiwix.kiwixmobile.core.ui.theme.Black import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme import org.kiwix.kiwixmobile.core.ui.theme.White import org.kiwix.kiwixmobile.core.utils.ComposeDimens.EIGHT_DP -import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FAB_ICON_BOTTOM_MARGIN import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FOUR_DP import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.BooksOnDiskListItem import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.BooksOnDiskListItem.BookOnDisk @@ -85,10 +84,9 @@ fun LocalLibraryScreen( onClick: ((BookOnDisk) -> Unit)? = null, onLongClick: ((BookOnDisk) -> Unit)? = null, onMultiSelect: ((BookOnDisk) -> Unit)? = null, + bottomAppBarScrollBehaviour: BottomAppBarScrollBehavior, navigationIcon: @Composable () -> Unit ) { - val (bottomNavHeight, lazyListState) = - rememberScrollBehavior(state.bottomNavigationHeight, listState) val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() KiwixTheme { Scaffold( @@ -105,7 +103,7 @@ fun LocalLibraryScreen( modifier = Modifier .systemBarsPadding() .nestedScroll(scrollBehavior.nestedScrollConnection) - .padding(bottom = bottomNavHeight.value) + .nestedScroll(bottomAppBarScrollBehaviour.nestedScrollConnection) ) { contentPadding -> SwipeRefreshLayout( isRefreshing = state.swipeRefreshItem.first, @@ -130,7 +128,7 @@ fun LocalLibraryScreen( onClick, onLongClick, onMultiSelect, - lazyListState + listState ) } } @@ -178,7 +176,6 @@ private fun SelectFileButton(fabButtonClick: () -> Unit) { FloatingActionButton( onClick = fabButtonClick, modifier = Modifier - .padding(bottom = FAB_ICON_BOTTOM_MARGIN) .testTag(SELECT_FILE_BUTTON_TESTING_TAG), containerColor = Black, shape = MaterialTheme.shapes.extraLarge diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/OnlineLibraryFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/OnlineLibraryFragment.kt index 7aca6fbec..bbc45ba10 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/OnlineLibraryFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/OnlineLibraryFragment.kt @@ -34,6 +34,7 @@ import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Menu +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.mutableStateOf @@ -75,7 +76,6 @@ import org.kiwix.kiwixmobile.core.navigateToSettings import org.kiwix.kiwixmobile.core.page.SEARCH_ICON_TESTING_TAG import org.kiwix.kiwixmobile.core.ui.components.NavigationIcon import org.kiwix.kiwixmobile.core.ui.components.ONE -import org.kiwix.kiwixmobile.core.ui.components.rememberBottomNavigationVisibility import org.kiwix.kiwixmobile.core.ui.models.ActionMenuItem import org.kiwix.kiwixmobile.core.ui.models.IconItem import org.kiwix.kiwixmobile.core.utils.BookUtils @@ -244,14 +244,11 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions { } } + @OptIn(ExperimentalMaterial3Api::class) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) composeView?.setContent { val lazyListState = rememberLazyListState() - val isBottomNavVisible = rememberBottomNavigationVisibility(lazyListState) - LaunchedEffect(isBottomNavVisible) { - (requireActivity() as KiwixMainActivity).toggleBottomNavigation(isBottomNavVisible) - } LaunchedEffect(Unit) { onlineLibraryScreenState.value.update { copy( @@ -273,7 +270,8 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions { contentDescription = string.open_drawer, onClick = { navigationIconClick(onlineLibraryScreenState.value.value.isSearchActive) } ) - } + }, + bottomAppBarScrollBehaviour = (requireActivity() as CoreMainActivity).bottomAppBarScrollBehaviour ) DialogHost(alertDialogShower) } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/OnlineLibraryScreen.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/OnlineLibraryScreen.kt index 13201b5d1..050062959 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/OnlineLibraryScreen.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/online/OnlineLibraryScreen.kt @@ -35,6 +35,7 @@ import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.BottomAppBarScrollBehavior import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api @@ -61,7 +62,6 @@ import org.kiwix.kiwixmobile.core.R.string 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.rememberScrollBehavior import org.kiwix.kiwixmobile.core.ui.components.ContentLoadingProgressBar import org.kiwix.kiwixmobile.core.ui.components.KiwixAppBar import org.kiwix.kiwixmobile.core.ui.components.KiwixSearchView @@ -98,10 +98,9 @@ fun OnlineLibraryScreen( state: OnlineLibraryScreenState, actionMenuItems: List, listState: LazyListState, + bottomAppBarScrollBehaviour: BottomAppBarScrollBehavior, navigationIcon: @Composable () -> Unit, ) { - val (bottomNavHeight, lazyListState) = - rememberScrollBehavior(state.bottomNavigationHeight, listState) val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() KiwixTheme { @@ -118,7 +117,7 @@ fun OnlineLibraryScreen( }, modifier = Modifier .nestedScroll(scrollBehavior.nestedScrollConnection) - .padding(bottom = bottomNavHeight.value) + .nestedScroll(bottomAppBarScrollBehaviour.nestedScrollConnection) ) { paddingValues -> SwipeRefreshLayout( isRefreshing = state.isRefreshing && !state.scanningProgressItem.first, @@ -132,7 +131,7 @@ fun OnlineLibraryScreen( end = paddingValues.calculateEndPadding(LocalLayoutDirection.current), ) ) { - OnlineLibraryScreenContent(state, lazyListState) + OnlineLibraryScreenContent(state, listState) } } } 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 128742703..91d82ebf1 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 @@ -28,6 +28,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.net.toUri import androidx.drawerlayout.widget.DrawerLayout import androidx.lifecycle.lifecycleScope +import androidx.navigation.NavOptions import com.google.android.material.bottomnavigation.BottomNavigationView import kotlinx.coroutines.launch import org.kiwix.kiwixmobile.cachedComponent @@ -55,6 +56,7 @@ import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_FILE import org.kiwix.kiwixmobile.core.utils.TAG_KIWIX import org.kiwix.kiwixmobile.core.utils.files.FileUtils import org.kiwix.kiwixmobile.core.utils.files.Log +import org.kiwix.kiwixmobile.ui.KiwixDestination import java.io.File class KiwixReaderFragment : CoreReaderFragment() { @@ -70,9 +72,10 @@ class KiwixReaderFragment : CoreReaderFragment() { val activity = activity as CoreMainActivity readerScreenState.update { copy(onOpenLibraryButtonClicked = { - activity.navigate( - KiwixReaderFragmentDirections.actionNavigationReaderToNavigationLibrary() - ) + val navOptions = NavOptions.Builder() + .setPopUpTo(KiwixDestination.Reader.route, inclusive = true) + .build() + activity.navigate(KiwixDestination.Library.route, navOptions) }) } activity.supportActionBar?.setDisplayHomeAsUpEnabled(true) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/ui/KiwixNavGraph.kt b/app/src/main/java/org/kiwix/kiwixmobile/ui/KiwixNavGraph.kt index 3e3691bc3..15a1464fb 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/ui/KiwixNavGraph.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/ui/KiwixNavGraph.kt @@ -18,26 +18,52 @@ package org.kiwix.kiwixmobile.ui +import android.net.Uri import android.os.Bundle import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.viewinterop.AndroidView +import androidx.core.net.toUri import androidx.core.view.doOnAttach import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentContainerView import androidx.fragment.app.commit import androidx.navigation.NavHostController +import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import androidx.navigation.navArgument +import org.kiwix.kiwixmobile.core.main.BOOKMARK_FRAGMENT +import org.kiwix.kiwixmobile.core.main.DOWNLOAD_FRAGMENT +import org.kiwix.kiwixmobile.core.main.FIND_IN_PAGE_SEARCH_STRING +import org.kiwix.kiwixmobile.core.main.HELP_FRAGMENT +import org.kiwix.kiwixmobile.core.main.HISTORY_FRAGMENT +import org.kiwix.kiwixmobile.core.main.INTRO_FRAGMENT +import org.kiwix.kiwixmobile.core.main.LANGUAGE_FRAGMENT +import org.kiwix.kiwixmobile.core.main.LOCAL_FILE_TRANSFER_FRAGMENT +import org.kiwix.kiwixmobile.core.main.LOCAL_LIBRARY_FRAGMENT +import org.kiwix.kiwixmobile.core.main.NOTES_FRAGMENT +import org.kiwix.kiwixmobile.core.main.PAGE_URL_KEY +import org.kiwix.kiwixmobile.core.main.READER_FRAGMENT +import org.kiwix.kiwixmobile.core.main.SEARCH_FRAGMENT +import org.kiwix.kiwixmobile.core.main.SETTINGS_FRAGMENT +import org.kiwix.kiwixmobile.core.main.SHOULD_OPEN_IN_NEW_TAB +import org.kiwix.kiwixmobile.core.main.ZIM_FILE_URI_KEY +import org.kiwix.kiwixmobile.core.main.ZIM_HOST_FRAGMENT +import org.kiwix.kiwixmobile.core.main.reader.SEARCH_ITEM_TITLE_KEY import org.kiwix.kiwixmobile.core.page.bookmark.BookmarksFragment import org.kiwix.kiwixmobile.core.page.history.HistoryFragment import org.kiwix.kiwixmobile.core.page.notes.NotesFragment +import org.kiwix.kiwixmobile.core.search.NAV_ARG_SEARCH_STRING import org.kiwix.kiwixmobile.core.search.SearchFragment +import org.kiwix.kiwixmobile.core.utils.EXTRA_IS_WIDGET_VOICE +import org.kiwix.kiwixmobile.core.utils.TAG_FROM_TAB_SWITCHER import org.kiwix.kiwixmobile.help.KiwixHelpFragment import org.kiwix.kiwixmobile.intro.IntroFragment import org.kiwix.kiwixmobile.language.LanguageFragment @@ -58,24 +84,47 @@ fun KiwixNavGraph( startDestination = KiwixDestination.Reader.route, modifier = modifier ) { - composable(KiwixDestination.Reader.route) { + composable( + route = KiwixDestination.Reader.route, + arguments = listOf( + navArgument(ZIM_FILE_URI_KEY) { type = NavType.StringType; defaultValue = "" }, + navArgument(FIND_IN_PAGE_SEARCH_STRING) { type = NavType.StringType; defaultValue = "" }, + navArgument(PAGE_URL_KEY) { type = NavType.StringType; defaultValue = "" }, + navArgument(SHOULD_OPEN_IN_NEW_TAB) { type = NavType.BoolType; defaultValue = false }, + navArgument(SEARCH_ITEM_TITLE_KEY) { type = NavType.StringType; defaultValue = "" } + ) + ) { backStackEntry -> + val zimFileUri = backStackEntry.arguments?.getString(ZIM_FILE_URI_KEY).orEmpty() + val findInPageSearchString = + backStackEntry.arguments?.getString(FIND_IN_PAGE_SEARCH_STRING).orEmpty() + val pageUrl = backStackEntry.arguments?.getString(PAGE_URL_KEY).orEmpty() + val shouldOpenInNewTab = backStackEntry.arguments?.getBoolean(SHOULD_OPEN_IN_NEW_TAB) ?: false + val searchItemTitle = backStackEntry.arguments?.getString(SEARCH_ITEM_TITLE_KEY).orEmpty() + FragmentContainer { KiwixReaderFragment().apply { arguments = Bundle().apply { - putString("zimFileUri", "") - putString("findInPageSearchString", "") - putString("pageUrl", "") - putBoolean("shouldOpenInNewTab", false) - putString("searchItemTitle", "") + putString(ZIM_FILE_URI_KEY, zimFileUri) + putString(FIND_IN_PAGE_SEARCH_STRING, findInPageSearchString) + putString(PAGE_URL_KEY, pageUrl) + putBoolean(SHOULD_OPEN_IN_NEW_TAB, shouldOpenInNewTab) + putString(SEARCH_ITEM_TITLE_KEY, searchItemTitle) } } } } - composable(KiwixDestination.Library.route) { + composable( + route = KiwixDestination.Library.route, + arguments = listOf( + navArgument(ZIM_FILE_URI_KEY) { type = NavType.StringType; defaultValue = "" } + ) + ) { backStackEntry -> + val zimFileUri = backStackEntry.arguments?.getString(ZIM_FILE_URI_KEY).orEmpty() + FragmentContainer { LocalLibraryFragment().apply { arguments = Bundle().apply { - putString("zimFileUri", "") + putString(ZIM_FILE_URI_KEY, zimFileUri) } } } @@ -125,16 +174,51 @@ fun KiwixNavGraph( KiwixSettingsFragment() } } - composable(KiwixDestination.Search.route) { + composable( + route = KiwixDestination.Search.route, + arguments = listOf( + navArgument(NAV_ARG_SEARCH_STRING) { type = NavType.StringType; defaultValue = "" }, + navArgument(TAG_FROM_TAB_SWITCHER) { type = NavType.BoolType; defaultValue = false }, + navArgument(EXTRA_IS_WIDGET_VOICE) { type = NavType.BoolType; defaultValue = false } + ) + ) { backStackEntry -> + val searchString = backStackEntry.arguments?.getString(NAV_ARG_SEARCH_STRING).orEmpty() + val isOpenedFromTabSwitcher = + backStackEntry.arguments?.getBoolean(TAG_FROM_TAB_SWITCHER) ?: false + val isVoice = backStackEntry.arguments?.getBoolean(EXTRA_IS_WIDGET_VOICE) ?: false FragmentContainer { - SearchFragment() + SearchFragment().apply { + arguments = Bundle().apply { + putString(NAV_ARG_SEARCH_STRING, searchString) + putBoolean(TAG_FROM_TAB_SWITCHER, isOpenedFromTabSwitcher) + putBoolean(EXTRA_IS_WIDGET_VOICE, isVoice) + } + } } } - composable(KiwixDestination.LocalFileTransfer.route) { + composable( + route = KiwixDestination.LocalFileTransfer.route, + arguments = listOf( + navArgument("uris") { + type = NavType.StringType + nullable = true + defaultValue = null + } + ) + ) { backStackEntry -> + val urisParam = backStackEntry.arguments?.getString("uris") + val uris: List? = + urisParam?.takeIf { it != "null" }?.split(",")?.map { + Uri.decode(it).toUri() + } + FragmentContainer { LocalFileTransferFragment().apply { arguments = Bundle().apply { - putParcelableArray("uris", null) + putParcelableArray( + "uris", + uris?.toTypedArray() + ) } } } @@ -142,6 +226,7 @@ fun KiwixNavGraph( } } +@OptIn(ExperimentalMaterial3Api::class) @Composable fun FragmentContainer( fragmentProvider: () -> Fragment @@ -170,17 +255,72 @@ fun FragmentContainer( } sealed class KiwixDestination(val route: String) { - object Reader : KiwixDestination("readerFragment") - object Library : KiwixDestination("libraryFragment") - object Downloads : KiwixDestination("downloadsFragment") - object Bookmarks : KiwixDestination("bookmarksFragment") - object Notes : KiwixDestination("notesFragment") - object Intro : KiwixDestination("introFragment") - object History : KiwixDestination("historyFragment") - object Language : KiwixDestination("languageFragment") - object ZimHost : KiwixDestination("zimHostFragment") - object Help : KiwixDestination("helpFragment") - object Settings : KiwixDestination("kiwixSettingsFragment") - object Search : KiwixDestination("searchFragment") - object LocalFileTransfer : KiwixDestination("localFileTransferFragment") + object Reader : KiwixDestination( + READER_FRAGMENT + + "?$ZIM_FILE_URI_KEY={$ZIM_FILE_URI_KEY}" + + "&$FIND_IN_PAGE_SEARCH_STRING={$FIND_IN_PAGE_SEARCH_STRING}" + + "&$PAGE_URL_KEY={$PAGE_URL_KEY}" + + "&$SHOULD_OPEN_IN_NEW_TAB={$SHOULD_OPEN_IN_NEW_TAB}" + + "&$SEARCH_ITEM_TITLE_KEY={$SEARCH_ITEM_TITLE_KEY}" + ) { + fun createRoute( + zimFileUri: String = "", + findInPageSearchString: String = "", + pageUrl: String = "", + shouldOpenInNewTab: Boolean = false, + searchItemTitle: String = "" + ): String { + return READER_FRAGMENT + + "?$ZIM_FILE_URI_KEY=${Uri.encode(zimFileUri)}" + + "&$FIND_IN_PAGE_SEARCH_STRING=${Uri.encode(findInPageSearchString)}" + + "&$PAGE_URL_KEY=${Uri.encode(pageUrl)}" + + "&$SHOULD_OPEN_IN_NEW_TAB=$shouldOpenInNewTab" + + "&$SEARCH_ITEM_TITLE_KEY=${Uri.encode(searchItemTitle)}" + } + } + + object Library : + KiwixDestination("$LOCAL_LIBRARY_FRAGMENT?$ZIM_FILE_URI_KEY={$ZIM_FILE_URI_KEY}") { + fun createRoute(zimFileUri: String = "") = + "$LOCAL_LIBRARY_FRAGMENT?$ZIM_FILE_URI_KEY=${Uri.encode(zimFileUri)}" + } + + object Downloads : KiwixDestination(DOWNLOAD_FRAGMENT) + object Bookmarks : KiwixDestination(BOOKMARK_FRAGMENT) + object Notes : KiwixDestination(NOTES_FRAGMENT) + object Intro : KiwixDestination(INTRO_FRAGMENT) + object History : KiwixDestination(HISTORY_FRAGMENT) + object Language : KiwixDestination(LANGUAGE_FRAGMENT) + object ZimHost : KiwixDestination(ZIM_HOST_FRAGMENT) + object Help : KiwixDestination(HELP_FRAGMENT) + object Settings : KiwixDestination(SETTINGS_FRAGMENT) + object Search : KiwixDestination( + SEARCH_FRAGMENT + + "?$NAV_ARG_SEARCH_STRING={$NAV_ARG_SEARCH_STRING}" + + "&$TAG_FROM_TAB_SWITCHER={$TAG_FROM_TAB_SWITCHER}" + + "&$EXTRA_IS_WIDGET_VOICE={$EXTRA_IS_WIDGET_VOICE}" + ) { + fun createRoute( + searchString: String = "", + isOpenedFromTabView: Boolean = false, + isVoice: Boolean = false + ): String { + return SEARCH_FRAGMENT + + "?$NAV_ARG_SEARCH_STRING=$searchString" + + "&$TAG_FROM_TAB_SWITCHER=$isOpenedFromTabView" + + "&$EXTRA_IS_WIDGET_VOICE=$isVoice" + } + } + + object LocalFileTransfer : KiwixDestination("$LOCAL_FILE_TRANSFER_FRAGMENT?uris={uris}") { + fun createRoute(uris: String? = null): String { + return if (uris != null) + "$LOCAL_FILE_TRANSFER_FRAGMENT?uris=${Uri.encode(uris)}" + else + "$LOCAL_FILE_TRANSFER_FRAGMENT?uris=null" + } + } } + +fun List.toUriParam(): String = + joinToString(",") { Uri.encode(it.toString()) } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/NavigateToDownloads.kt b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/NavigateToDownloads.kt index 0a5338d97..c97d527f0 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/NavigateToDownloads.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/NavigateToDownloads.kt @@ -19,12 +19,17 @@ package org.kiwix.kiwixmobile.zimManager.fileselectView.effects import androidx.appcompat.app.AppCompatActivity +import androidx.navigation.NavOptions import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.navigate -import org.kiwix.kiwixmobile.nav.destination.library.local.LocalLibraryFragmentDirections +import org.kiwix.kiwixmobile.ui.KiwixDestination object NavigateToDownloads : SideEffect { override fun invokeWith(activity: AppCompatActivity) { - activity.navigate(LocalLibraryFragmentDirections.actionNavigationLibraryToNavigationDownloads()) + val navOptions = NavOptions.Builder() + .setPopUpTo(KiwixDestination.Library.route, inclusive = true) + .setRestoreState(true) + .build() + activity.navigate(KiwixDestination.Downloads.route, navOptions) } } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/OpenFileWithNavigation.kt b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/OpenFileWithNavigation.kt index 9497c1377..a0d153654 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/OpenFileWithNavigation.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/OpenFileWithNavigation.kt @@ -20,6 +20,7 @@ package org.kiwix.kiwixmobile.zimManager.fileselectView.effects import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope +import androidx.navigation.NavOptions import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -28,7 +29,7 @@ import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.extensions.toast import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.BooksOnDiskListItem import org.kiwix.kiwixmobile.main.KiwixMainActivity -import org.kiwix.kiwixmobile.nav.destination.library.local.LocalLibraryFragmentDirections.actionNavigationLibraryToNavigationReader +import org.kiwix.kiwixmobile.ui.KiwixDestination @Suppress("InjectDispatcher") data class OpenFileWithNavigation(private val bookOnDisk: BooksOnDiskListItem.BookOnDisk) : @@ -45,10 +46,12 @@ data class OpenFileWithNavigation(private val bookOnDisk: BooksOnDiskListItem.Bo activity.getString(R.string.error_file_not_found, zimReaderSource.toDatabase()) ) } else { + val navOptions = NavOptions.Builder() + .setPopUpTo(KiwixDestination.Library.route, inclusive = false) + .build() activity.navigate( - actionNavigationLibraryToNavigationReader().apply { - zimFileUri = zimReaderSource.toDatabase() - } + KiwixDestination.Reader.createRoute(zimFileUri = zimReaderSource.toDatabase()), + navOptions ) } } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/ShareFiles.kt b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/ShareFiles.kt index 9e998a21e..58542205f 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/ShareFiles.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zimManager/fileselectView/effects/ShareFiles.kt @@ -19,12 +19,11 @@ package org.kiwix.kiwixmobile.zimManager.fileselectView.effects import androidx.appcompat.app.AppCompatActivity -import androidx.core.os.bundleOf -import org.kiwix.kiwixmobile.R import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.navigate import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.BooksOnDiskListItem.BookOnDisk -import org.kiwix.kiwixmobile.localFileTransfer.URIS_KEY +import org.kiwix.kiwixmobile.ui.KiwixDestination +import org.kiwix.kiwixmobile.ui.toUriParam data class ShareFiles(private val selectedBooks: List) : SideEffect { @@ -34,8 +33,7 @@ data class ShareFiles(private val selectedBooks: List) : it.zimReaderSource.getUri(activity) } activity.navigate( - R.id.localFileTransferFragment, - bundleOf(URIS_KEY to selectedFileContentURIs.toTypedArray()) + KiwixDestination.LocalFileTransfer.createRoute(uris = selectedFileContentURIs.toUriParam()) ) } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/ActivityExtensions.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/ActivityExtensions.kt index 16cf61743..165d5dd02 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/ActivityExtensions.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/ActivityExtensions.kt @@ -26,7 +26,6 @@ import android.content.pm.PackageManager import android.content.res.Configuration import android.graphics.Color import android.os.Build -import android.os.Bundle import android.os.Environment import android.view.Menu import android.view.MenuItem @@ -41,7 +40,7 @@ import androidx.lifecycle.Observer import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProviders -import androidx.navigation.NavDirections +import androidx.navigation.NavOptions import org.kiwix.kiwixmobile.core.di.components.CoreActivityComponent import org.kiwix.kiwixmobile.core.main.CoreMainActivity import org.kiwix.kiwixmobile.core.utils.REQUEST_POST_NOTIFICATION_PERMISSION @@ -93,22 +92,14 @@ object ActivityExtensions { ViewModelProviders.of(this, viewModelFactory) .get(T::class.java) - fun Activity.navigate(action: NavDirections) { - coreMainActivity.navigate(action) - } - val Activity.cachedComponent: CoreActivityComponent get() = coreMainActivity.cachedComponent fun Activity.setupDrawerToggle(shouldEnableRightDrawer: Boolean = false) = coreMainActivity.setupDrawerToggle(shouldEnableRightDrawer) - fun Activity.navigate(route: String) { - coreMainActivity.navigate(route) - } - - fun Activity.navigate(fragmentId: Int, bundle: Bundle) { - coreMainActivity.navigate(fragmentId, bundle) + fun Activity.navigate(route: String, navOptions: NavOptions? = null) { + coreMainActivity.navigate(route, navOptions) } fun Activity.popNavigationBackstack() { diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt index 05e467ea8..0929120fb 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt @@ -27,7 +27,9 @@ import android.view.MenuItem import androidx.activity.OnBackPressedCallback import androidx.appcompat.app.ActionBarDrawerToggle import androidx.appcompat.app.AppCompatActivity +import androidx.compose.material3.BottomAppBarScrollBehavior import androidx.compose.material3.DrawerState +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.core.net.toUri @@ -73,6 +75,21 @@ const val KIWIX_INTERNAL_ERROR = 10 const val ACTION_NEW_TAB = "NEW_TAB" const val NEW_TAB_SHORTCUT_ID = "new_tab_shortcut" +// Fragments names for compose based navigation. +const val READER_FRAGMENT = "readerFragment" +const val LOCAL_LIBRARY_FRAGMENT = "localLibraryFragment" +const val DOWNLOAD_FRAGMENT = "downloadsFragment" +const val BOOKMARK_FRAGMENT = "bookmarkFragment" +const val NOTES_FRAGMENT = "notesFragment" +const val INTRO_FRAGMENT = "introFragment" +const val HISTORY_FRAGMENT = "historyFragment" +const val LANGUAGE_FRAGMENT = "languageFragment" +const val ZIM_HOST_FRAGMENT = "zimHostFragment" +const val HELP_FRAGMENT = "helpFragment" +const val SETTINGS_FRAGMENT = "settingsFragment" +const val SEARCH_FRAGMENT = "searchFragment" +const val LOCAL_FILE_TRANSFER_FRAGMENT = "localFileTransferFragment" + abstract class CoreMainActivity : BaseActivity(), WebViewProvider { abstract val searchFragmentRoute: String @@ -108,8 +125,17 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider { */ protected val leftDrawerMenu = mutableStateListOf() + /** + * Manages the enabling/disabling the left drawer + */ protected val enableLeftDrawer = mutableStateOf(true) + /** + * For managing the the showing/hiding the bottomAppBar when scrolling. + */ + @OptIn(ExperimentalMaterial3Api::class) + lateinit var bottomAppBarScrollBehaviour: BottomAppBarScrollBehavior + // abstract val drawerContainerLayout: DrawerLayout // abstract val drawerNavView: NavigationView // abstract val readerTableOfContentsDrawer: NavigationView @@ -319,6 +345,7 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider { } open fun disableDrawer(disableRightDrawer: Boolean = true) { + enableLeftDrawer.value = false // drawerToggle?.isDrawerIndicatorEnabled = false // drawerContainerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) // if (disableRightDrawer) { @@ -424,8 +451,8 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider { } } - fun navigate(route: String) { - navController.navigate(route) + fun navigate(route: String, navOptions: NavOptions? = null) { + navController.navigate(route, navOptions) } fun navigate(fragmentId: Int, bundle: Bundle) { @@ -446,29 +473,11 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider { navigate(historyFragmentRoute) } - fun openSearch( + abstract fun openSearch( searchString: String = "", isOpenedFromTabView: Boolean = false, isVoice: Boolean = false - ) { - // navigate( - // searchFragmentRoute, - // bundleOf( - // NAV_ARG_SEARCH_STRING to searchString, - // TAG_FROM_TAB_SWITCHER to isOpenedFromTabView, - // EXTRA_IS_WIDGET_VOICE to isVoice - // ) - // ) - } - - fun openZimFromFilePath(path: String) { - // navigate( - // readerFragmentRoute, - // bundleOf( - // ZIM_FILE_URI_KEY to path, - // ) - // ) - } + ) fun openPage( pageUrl: String, @@ -607,14 +616,6 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider { abstract val readerFragmentRoute: String abstract fun createApplicationShortcuts() abstract fun setDialogHostToActivity(alertDialogShower: AlertDialogShower) - - /** - * This is for showing and hiding the bottomNavigationView when user scroll the screen. - * We are making this abstract so that it can be easily used from the reader screen. - * Since we do not have the bottomNavigationView in custom apps. So doing this way both apps will - * provide there own implementation. - * - * TODO we will remove this once we will migrate mainActivity to the compose. - */ - abstract fun toggleBottomNavigation(isVisible: Boolean) + abstract fun hideBottomAppBar() + abstract fun showBottomAppBar() } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/OnSwipeTouchListener.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/OnSwipeTouchListener.kt deleted file mode 100644 index 436b3848d..000000000 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/OnSwipeTouchListener.kt +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Kiwix Android - * Copyright (c) 2019 Kiwix - * 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 . - * - */ -package org.kiwix.kiwixmobile.core.main - -import android.annotation.SuppressLint -import android.content.Context -import org.kiwix.kiwixmobile.core.utils.files.Log -import android.view.GestureDetector -import android.view.GestureDetector.SimpleOnGestureListener -import android.view.MotionEvent -import android.view.View -import android.view.View.OnTouchListener -import kotlin.math.abs - -open class OnSwipeTouchListener constructor(context: Context) : OnTouchListener { - private val gestureDetector: GestureDetector - - init { - gestureDetector = GestureDetector(context, GestureListener()) - } - - @SuppressLint("ClickableViewAccessibility") override fun onTouch( - view: View, - event: MotionEvent - ): Boolean = gestureDetector.onTouchEvent(event) - - private inner class GestureListener : SimpleOnGestureListener() { - private val tag = "GestureListener" - private val swipeThreshold = 100 - private val swipeVelocityThreshold = 100 - - override fun onDown(event: MotionEvent): Boolean = true - - override fun onSingleTapUp(event: MotionEvent): Boolean { - onTap(event) - return super.onSingleTapUp(event) - } - - // See:- https://stackoverflow.com/questions/73463685/gesturedetector-ongesturelistener-overridden-methods-are-not-working-in-android - @Suppress("NOTHING_TO_OVERRIDE", "ACCIDENTAL_OVERRIDE", "NestedBlockDepth", "ReturnCount") - override fun onFling( - e1: MotionEvent, - e2: MotionEvent, - velocityX: Float, - velocityY: Float - ): Boolean { - try { - val diffY = e2.y - e1.y - val diffX = e2.x - e1.x - if (abs(diffX) > abs(diffY)) { - if (abs(diffX) > swipeThreshold && abs(velocityX) > swipeVelocityThreshold) { - if (diffX > 0) { - onSwipeRight() - } else { - onSwipeLeft() - } - return true - } - } else if (abs(diffY) > swipeThreshold && abs(velocityY) > swipeVelocityThreshold) { - if (diffY > 0) { - onSwipeBottom() - } - return true - } - } catch (exception: Exception) { - Log.e(tag, "Exception in onFling", exception) - } - return false - } - } - - open fun onSwipeRight() {} - open fun onSwipeLeft() {} - open fun onSwipeBottom() {} - open fun onTap(e: MotionEvent?) {} -} 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 773cb98c9..7f54633b2 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 @@ -741,10 +741,10 @@ abstract class CoreReaderFragment : } private fun showTabSwitcher() { - (requireActivity() as CoreMainActivity).disableDrawer() - // Set a negative top margin to the web views to remove - // the unwanted blank space caused by the toolbar. - // setTopMarginToWebViews(-requireActivity().getToolbarHeight()) + (requireActivity() as CoreMainActivity).apply { + disableDrawer() + hideBottomAppBar() + } setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) readerScreenState.update { copy( @@ -787,6 +787,7 @@ abstract class CoreReaderFragment : */ protected open fun hideTabSwitcher(shouldCloseZimBook: Boolean = true) { setUpDrawerToggle() + (requireActivity() as CoreMainActivity).showBottomAppBar() setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) readerScreenState.update { copy( @@ -1569,7 +1570,10 @@ abstract class CoreReaderFragment : @Suppress("MagicNumber") protected open fun openFullScreen() { - (requireActivity() as CoreMainActivity).disableDrawer(false) + (requireActivity() as CoreMainActivity).apply { + disableDrawer(false) + hideBottomAppBar() + } readerScreenState.update { copy( shouldShowBottomAppBar = false, @@ -1588,6 +1592,7 @@ abstract class CoreReaderFragment : @Suppress("MagicNumber") open fun closeFullScreen() { setUpDrawerToggle() + (requireActivity() as CoreMainActivity).showBottomAppBar() setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) sharedPreferenceUtil?.putPrefFullScreen(false) updateBottomToolbarVisibility() diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/search/SearchFragment.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/search/SearchFragment.kt index b9f56c966..e802363b7 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/search/SearchFragment.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/search/SearchFragment.kt @@ -226,7 +226,7 @@ class SearchFragment : BaseFragment() { private fun goBack() { val readerFragmentRoute = (activity as CoreMainActivity).readerFragmentRoute - findNavController().popBackStack(readerFragmentRoute, false) + (requireActivity() as CoreMainActivity).navController.popBackStack(readerFragmentRoute, false) } private fun getSearchListItemForQuery(query: String): SearchListItem? = diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/ComposeDimens.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/ComposeDimens.kt index 569e0fafc..cc5f66f56 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/ComposeDimens.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/ComposeDimens.kt @@ -109,9 +109,6 @@ object ComposeDimens { // BookItem dimens val BOOK_ICON_SIZE = 48.dp - // LocalLibraryFragment dimens - val FAB_ICON_BOTTOM_MARGIN = 50.dp - // HelpFragment dimens val HELP_SCREEN_DIVIDER_HEIGHT = 0.7.dp val HELP_SCREEN_ITEM_TITLE_TEXT_SIZE = 20.sp diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt index e5521b273..319d4a34c 100644 --- a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt @@ -285,8 +285,16 @@ class CustomMainActivity : CoreMainActivity() { activityCustomMainBinding.root.addView(getDialogHostComposeView(alertDialogShower), 0) } - override fun toggleBottomNavigation(isVisible: Boolean) { - // Do nothing as we do not have the bottomNavigationView in custom apps. + override fun openSearch(searchString: String, isOpenedFromTabView: Boolean, isVoice: Boolean) { + // TODO implement when refactoring the custom app UI. + } + + override fun hideBottomAppBar() { + // Do nothing since custom apps does not have the bottomAppBar. + } + + override fun showBottomAppBar() { + // Do nothing since custom apps does not have the bottomAppBar. } // Outdated shortcut id(new_tab) 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 6d6dfda38..b4c8c5f03 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 @@ -36,6 +36,7 @@ import org.kiwix.kiwixmobile.core.base.BaseActivity import org.kiwix.kiwixmobile.core.extensions.browserIntent import org.kiwix.kiwixmobile.core.extensions.isFileExist import org.kiwix.kiwixmobile.core.extensions.update +import org.kiwix.kiwixmobile.core.main.CoreMainActivity import org.kiwix.kiwixmobile.core.main.reader.CoreReaderFragment import org.kiwix.kiwixmobile.core.main.reader.ReaderMenuState import org.kiwix.kiwixmobile.core.main.reader.RestoreOrigin @@ -272,7 +273,8 @@ class CustomReaderFragment : CoreReaderFragment() { }, onNoFilesFound = { if (sharedPreferenceUtil?.prefIsTest == false) { - findNavController().navigate(R.id.customDownloadFragment) + // TODO refactor this when migrating the custom app in compose + // (requireActivity() as CoreMainActivity).navigate(R.id.customDownloadFragment) } } )