mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-08-03 10:46:53 -04:00
Created LocalLibraryScreenState
to encapsulate all UI-related states, reducing state management's complexity.
This commit is contained in:
parent
5b507d8f3d
commit
80fbf74d9a
@ -40,9 +40,7 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Menu
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toUri
|
||||
@ -87,9 +85,6 @@ import org.kiwix.kiwixmobile.core.utils.EXTERNAL_SELECT_POSITION
|
||||
import org.kiwix.kiwixmobile.core.utils.INTERNAL_SELECT_POSITION
|
||||
import org.kiwix.kiwixmobile.core.utils.LanguageUtils
|
||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||
import org.kiwix.kiwixmobile.core.utils.SimpleRecyclerViewScrollListener
|
||||
import org.kiwix.kiwixmobile.core.utils.SimpleRecyclerViewScrollListener.Companion.SCROLL_DOWN
|
||||
import org.kiwix.kiwixmobile.core.utils.SimpleRecyclerViewScrollListener.Companion.SCROLL_UP
|
||||
import org.kiwix.kiwixmobile.core.utils.TAG_KIWIX
|
||||
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower
|
||||
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog
|
||||
@ -97,7 +92,6 @@ import org.kiwix.kiwixmobile.core.utils.files.FileUtils
|
||||
import org.kiwix.kiwixmobile.core.utils.files.FileUtils.isSplittedZimFile
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||
import org.kiwix.kiwixmobile.databinding.FragmentDestinationLibraryBinding
|
||||
import org.kiwix.kiwixmobile.main.KiwixMainActivity
|
||||
import org.kiwix.kiwixmobile.nav.destination.library.CopyMoveFileHandler
|
||||
import org.kiwix.kiwixmobile.zimManager.MAX_PROGRESS
|
||||
@ -134,34 +128,19 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
||||
|
||||
private var actionMode: ActionMode? = null
|
||||
private val disposable = CompositeDisposable()
|
||||
private var fragmentDestinationLibraryBinding: FragmentDestinationLibraryBinding? = null
|
||||
private var permissionDeniedLayoutShowing = false
|
||||
private var zimFileUri: Uri? = null
|
||||
private lateinit var snackBarHostState: SnackbarHostState
|
||||
private var fileSelectListState = mutableStateOf(FileSelectListState(emptyList()))
|
||||
|
||||
/**
|
||||
* This is a Triple which is responsible for showing and hiding the "No file here",
|
||||
* and "Download books" button.
|
||||
*
|
||||
* A [Triple] containing:
|
||||
* - [String]: The title text displayed when no files are available.
|
||||
* - [String]: The label for the download button.
|
||||
* - [Boolean]: The boolean value for showing or hiding this view.
|
||||
*/
|
||||
private var noFilesViewItem = mutableStateOf(Triple("", "", false))
|
||||
|
||||
/**
|
||||
* This is a Pair which is responsible for showing and hiding the "Pull to refresh"
|
||||
* animation.
|
||||
*
|
||||
* A [Pair] containing:
|
||||
* - [Boolean]: The first boolean triggers/hide the "pull to refresh" animation.
|
||||
* - [Boolean]: The second boolean enable/disable the "pull to refresh".
|
||||
*/
|
||||
private var swipeRefreshItem = mutableStateOf(Pair(false, true))
|
||||
|
||||
private var scanningProgressItem = mutableStateOf(Pair(false, ZERO))
|
||||
val libraryScreenState = mutableStateOf(
|
||||
LocalLibraryScreenState(
|
||||
fileSelectListState = FileSelectListState(emptyList()),
|
||||
snackBarHostState = SnackbarHostState(),
|
||||
swipeRefreshItem = Pair(false, true),
|
||||
scanningProgressItem = Pair(false, ZERO),
|
||||
noFilesViewItem = Triple("", "", false),
|
||||
actionMenuItems = listOf(),
|
||||
bottomNavigationHeight = ZERO
|
||||
)
|
||||
)
|
||||
|
||||
private val zimManageViewModel by lazy {
|
||||
requireActivity().viewModel<ZimManageViewModel>(viewModelFactory)
|
||||
@ -174,10 +153,12 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
||||
val isGranted = permissionResult.values.all { it }
|
||||
val isPermanentlyDenied = readStorageHasBeenPermanentlyDenied(isGranted)
|
||||
permissionDeniedLayoutShowing = isPermanentlyDenied
|
||||
noFilesViewItem.value = Triple(
|
||||
requireActivity().resources.getString(string.grant_read_storage_permission),
|
||||
requireActivity().resources.getString(string.go_to_settings_label),
|
||||
isPermanentlyDenied
|
||||
updateLibraryScreenState(
|
||||
noFilesViewItem = Triple(
|
||||
requireActivity().resources.getString(string.grant_read_storage_permission),
|
||||
requireActivity().resources.getString(string.go_to_settings_label),
|
||||
isPermanentlyDenied
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@ -195,20 +176,18 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
||||
|
||||
val composeView = ComposeView(requireContext()).apply {
|
||||
setContent {
|
||||
snackBarHostState = remember { SnackbarHostState() }
|
||||
updateLibraryScreenState(
|
||||
bottomNavigationHeight = getBottomNavigationHeight(),
|
||||
actionMenuItems = actionMenuItems()
|
||||
)
|
||||
LocalLibraryScreen(
|
||||
state = fileSelectListState.value,
|
||||
snackBarHostState = snackBarHostState,
|
||||
state = libraryScreenState.value,
|
||||
fabButtonClick = { filePickerButtonClick() },
|
||||
actionMenuItems = actionMenuItems(),
|
||||
onClick = { onBookItemClick(it) },
|
||||
onLongClick = { onBookItemLongClick(it) },
|
||||
onMultiSelect = { offerAction(RequestSelect(it)) },
|
||||
onRefresh = { onSwipeRefresh() },
|
||||
swipeRefreshItem = swipeRefreshItem.value,
|
||||
noFilesViewItem = noFilesViewItem.value,
|
||||
onDownloadButtonClick = { downloadBookButtonClick() },
|
||||
scanningProgressItem = scanningProgressItem.value
|
||||
) {
|
||||
NavigationIcon(
|
||||
iconItem = IconItem.Vector(Icons.Filled.Menu),
|
||||
@ -260,6 +239,28 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateLibraryScreenState(
|
||||
fileSelectListState: FileSelectListState? = null,
|
||||
snackBarHostState: SnackbarHostState? = null,
|
||||
swipeRefreshItem: Pair<Boolean, Boolean>? = null,
|
||||
scanningProgressItem: Pair<Boolean, Int>? = null,
|
||||
noFilesViewItem: Triple<String, String, Boolean>? = null,
|
||||
actionMenuItems: List<ActionMenuItem>? = null,
|
||||
bottomNavigationHeight: Int? = null
|
||||
) {
|
||||
libraryScreenState.value = libraryScreenState.value.copy(
|
||||
fileSelectListState = fileSelectListState ?: libraryScreenState.value.fileSelectListState,
|
||||
snackBarHostState = snackBarHostState ?: libraryScreenState.value.snackBarHostState,
|
||||
swipeRefreshItem = swipeRefreshItem ?: libraryScreenState.value.swipeRefreshItem,
|
||||
scanningProgressItem = scanningProgressItem
|
||||
?: libraryScreenState.value.scanningProgressItem,
|
||||
noFilesViewItem = noFilesViewItem ?: libraryScreenState.value.noFilesViewItem,
|
||||
actionMenuItems = actionMenuItems ?: libraryScreenState.value.actionMenuItems,
|
||||
bottomNavigationHeight = bottomNavigationHeight
|
||||
?: libraryScreenState.value.bottomNavigationHeight
|
||||
)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
copyMoveFileHandler?.apply {
|
||||
@ -270,38 +271,20 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
||||
.also {
|
||||
coreMainActivity.navHostContainer
|
||||
.setBottomMarginToFragmentContainerView(0)
|
||||
|
||||
getBottomNavigationView()?.let { bottomNavigationView ->
|
||||
setBottomMarginToSwipeRefreshLayout(bottomNavigationView.measuredHeight)
|
||||
}
|
||||
}
|
||||
disposable.add(sideEffects())
|
||||
disposable.add(fileSelectActions())
|
||||
zimManageViewModel.deviceListScanningProgress.observe(viewLifecycleOwner) {
|
||||
// hide this progress bar when scanning is complete.
|
||||
scanningProgressItem.value = Pair(it != MAX_PROGRESS, it)
|
||||
// enable if the previous scanning is completes.
|
||||
swipeRefreshItem.value = Pair(false, it == MAX_PROGRESS)
|
||||
updateLibraryScreenState(
|
||||
// hide this progress bar when scanning is complete.
|
||||
scanningProgressItem = Pair(it != MAX_PROGRESS, it),
|
||||
// enable if the previous scanning is completes.
|
||||
swipeRefreshItem = Pair(false, it == MAX_PROGRESS)
|
||||
)
|
||||
}
|
||||
if (savedInstanceState != null && savedInstanceState.getBoolean(WAS_IN_ACTION_MODE)) {
|
||||
zimManageViewModel.fileSelectActions.offer(FileSelectActions.RestartActionMode)
|
||||
}
|
||||
|
||||
fragmentDestinationLibraryBinding?.zimfilelist?.addOnScrollListener(
|
||||
SimpleRecyclerViewScrollListener { _, newState ->
|
||||
when (newState) {
|
||||
SCROLL_DOWN -> {
|
||||
setBottomMarginToSwipeRefreshLayout(0)
|
||||
}
|
||||
|
||||
SCROLL_UP -> {
|
||||
getBottomNavigationView()?.let {
|
||||
setBottomMarginToSwipeRefreshLayout(it.measuredHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
showCopyMoveDialogForOpenedZimFileFromStorage()
|
||||
}
|
||||
|
||||
@ -325,22 +308,24 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
||||
private fun onSwipeRefresh() {
|
||||
if (permissionDeniedLayoutShowing) {
|
||||
// When permission denied layout is showing hide the "Swipe refresh".
|
||||
swipeRefreshItem.value = false to true
|
||||
updateLibraryScreenState(swipeRefreshItem = false to true)
|
||||
} else {
|
||||
if (!requireActivity().isManageExternalStoragePermissionGranted(sharedPreferenceUtil)) {
|
||||
showManageExternalStoragePermissionDialog()
|
||||
// Set loading to false since the dialog is currently being displayed.
|
||||
// If the user clicks on "No" in the permission dialog,
|
||||
// the loading icon remains visible infinitely.
|
||||
swipeRefreshItem.value = false to true
|
||||
updateLibraryScreenState(swipeRefreshItem = false to true)
|
||||
} else {
|
||||
// hide the swipe refreshing because now we are showing the ContentLoadingProgressBar
|
||||
// to show the progress of how many files are scanned.
|
||||
// disable the swipe refresh layout until the ongoing scanning will not complete
|
||||
// to avoid multiple scanning.
|
||||
swipeRefreshItem.value = false to false
|
||||
// Show the progress Bar.
|
||||
scanningProgressItem.value = true to ZERO
|
||||
updateLibraryScreenState(
|
||||
swipeRefreshItem = false to false,
|
||||
// Show the progress Bar.
|
||||
scanningProgressItem = true to ZERO
|
||||
)
|
||||
requestFileSystemCheck()
|
||||
}
|
||||
}
|
||||
@ -360,13 +345,7 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
||||
private fun getBottomNavigationView() =
|
||||
requireActivity().findViewById<BottomNavigationView>(R.id.bottom_nav_view)
|
||||
|
||||
private fun setBottomMarginToSwipeRefreshLayout(marginBottom: Int) {
|
||||
fragmentDestinationLibraryBinding?.zimSwiperefresh?.apply {
|
||||
val params = layoutParams as CoordinatorLayout.LayoutParams?
|
||||
params?.bottomMargin = marginBottom
|
||||
requestLayout()
|
||||
}
|
||||
}
|
||||
private fun getBottomNavigationHeight() = getBottomNavigationView().measuredHeight
|
||||
|
||||
private fun filePickerButtonClick() {
|
||||
if (!requireActivity().isManageExternalStoragePermissionGranted(sharedPreferenceUtil)) {
|
||||
@ -510,10 +489,12 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
||||
) {
|
||||
checkPermissions()
|
||||
} else if (!permissionDeniedLayoutShowing) {
|
||||
noFilesViewItem.value = Triple(
|
||||
requireActivity().resources.getString(string.no_files_here),
|
||||
requireActivity().resources.getString(string.download_books),
|
||||
false
|
||||
updateLibraryScreenState(
|
||||
noFilesViewItem = Triple(
|
||||
requireActivity().resources.getString(string.no_files_here),
|
||||
requireActivity().resources.getString(string.download_books),
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -540,7 +521,11 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
||||
val effectResult = it.invokeWith(requireActivity() as AppCompatActivity)
|
||||
if (effectResult is ActionMode) {
|
||||
actionMode = effectResult
|
||||
fileSelectListState.value.selectedBooks.size.let(::setActionModeTitle)
|
||||
libraryScreenState
|
||||
.value
|
||||
.fileSelectListState
|
||||
.selectedBooks
|
||||
.size.let(::setActionModeTitle)
|
||||
}
|
||||
},
|
||||
Throwable::printStackTrace
|
||||
@ -568,20 +553,21 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
||||
// Force recomposition by first setting an empty list before assigning the updated list.
|
||||
// This is necessary because modifying an object's property doesn't trigger recomposition,
|
||||
// as Compose still considers the list unchanged.
|
||||
fileSelectListState.value = FileSelectListState(emptyList())
|
||||
fileSelectListState.value = state
|
||||
updateLibraryScreenState(
|
||||
fileSelectListState = state,
|
||||
noFilesViewItem = Triple(
|
||||
requireActivity().resources.getString(string.no_files_here),
|
||||
requireActivity().resources.getString(string.download_books),
|
||||
// If here are no items available then show the "No files here" text, and "Download books"
|
||||
// button so that user can go to "Online library" screen by clicking this button.
|
||||
state.bookOnDiskListItems.isEmpty()
|
||||
)
|
||||
)
|
||||
if (state.bookOnDiskListItems.none(BooksOnDiskListItem::isSelected)) {
|
||||
actionMode?.finish()
|
||||
actionMode = null
|
||||
}
|
||||
setActionModeTitle(state.selectedBooks.size)
|
||||
noFilesViewItem.value = Triple(
|
||||
requireActivity().resources.getString(string.no_files_here),
|
||||
requireActivity().resources.getString(string.download_books),
|
||||
// If here are no items available then show the "No files here" text, and "Download books"
|
||||
// button so that user can go to "Online library" screen by clicking this button.
|
||||
state.bookOnDiskListItems.isEmpty()
|
||||
)
|
||||
}
|
||||
|
||||
private fun setActionModeTitle(selectedBookCount: Int) {
|
||||
@ -679,7 +665,7 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
||||
}
|
||||
|
||||
private fun showStorageSelectionSnackBar(message: String) {
|
||||
snackBarHostState.snack(
|
||||
libraryScreenState.value.snackBarHostState.snack(
|
||||
message = message,
|
||||
actionLabel = getString(string.download_change_storage),
|
||||
lifecycleScope = lifecycleScope,
|
||||
|
@ -26,35 +26,42 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.kiwix.kiwixmobile.R.string
|
||||
import org.kiwix.kiwixmobile.core.R
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.ZERO
|
||||
import org.kiwix.kiwixmobile.core.ui.components.ContentLoadingProgressBar
|
||||
import org.kiwix.kiwixmobile.core.ui.components.KiwixAppBar
|
||||
import org.kiwix.kiwixmobile.core.ui.components.KiwixButton
|
||||
import org.kiwix.kiwixmobile.core.ui.components.KiwixSnackbarHost
|
||||
import org.kiwix.kiwixmobile.core.ui.components.ProgressBarStyle
|
||||
import org.kiwix.kiwixmobile.core.ui.components.SwipeRefreshLayout
|
||||
import org.kiwix.kiwixmobile.core.ui.models.ActionMenuItem
|
||||
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.SIXTEEN_DP
|
||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TEN_DP
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||
import org.kiwix.kiwixmobile.ui.BookItem
|
||||
@ -62,54 +69,65 @@ import org.kiwix.kiwixmobile.ui.ZimFilesLanguageHeader
|
||||
import org.kiwix.kiwixmobile.zimManager.fileselectView.FileSelectListState
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Suppress("ComposableLambdaParameterNaming", "LongParameterList")
|
||||
@Suppress("ComposableLambdaParameterNaming")
|
||||
@Composable
|
||||
fun LocalLibraryScreen(
|
||||
state: FileSelectListState,
|
||||
snackBarHostState: SnackbarHostState,
|
||||
swipeRefreshItem: Pair<Boolean, Boolean>,
|
||||
state: LocalLibraryScreenState,
|
||||
onRefresh: () -> Unit,
|
||||
scanningProgressItem: Pair<Boolean, Int>,
|
||||
noFilesViewItem: Triple<String, String, Boolean>,
|
||||
onDownloadButtonClick: () -> Unit,
|
||||
fabButtonClick: () -> Unit,
|
||||
actionMenuItems: List<ActionMenuItem>,
|
||||
onClick: ((BookOnDisk) -> Unit)? = null,
|
||||
onLongClick: ((BookOnDisk) -> Unit)? = null,
|
||||
onMultiSelect: ((BookOnDisk) -> Unit)? = null,
|
||||
navigationIcon: @Composable () -> Unit
|
||||
) {
|
||||
val lazyListState = rememberLazyListState()
|
||||
val bottomNavHeightInDp = with(LocalDensity.current) { state.bottomNavigationHeight.toDp() }
|
||||
val bottomNavHeight = remember { mutableStateOf(bottomNavHeightInDp) }
|
||||
LaunchedEffect(lazyListState) {
|
||||
snapshotFlow { lazyListState.firstVisibleItemScrollOffset }
|
||||
.collect { scrollOffset ->
|
||||
bottomNavHeight.value = if (scrollOffset > 0) ZERO.dp else bottomNavHeightInDp
|
||||
}
|
||||
}
|
||||
KiwixTheme {
|
||||
Scaffold(
|
||||
snackbarHost = { KiwixSnackbarHost(snackbarHostState = snackBarHostState) },
|
||||
topBar = { KiwixAppBar(R.string.library, navigationIcon, actionMenuItems) },
|
||||
snackbarHost = { KiwixSnackbarHost(snackbarHostState = state.snackBarHostState) },
|
||||
topBar = { KiwixAppBar(R.string.library, navigationIcon, state.actionMenuItems) },
|
||||
modifier = Modifier.systemBarsPadding()
|
||||
) { contentPadding ->
|
||||
SwipeRefreshLayout(
|
||||
isRefreshing = swipeRefreshItem.first,
|
||||
isEnabled = swipeRefreshItem.second,
|
||||
isRefreshing = state.swipeRefreshItem.first,
|
||||
isEnabled = state.swipeRefreshItem.second,
|
||||
onRefresh = onRefresh,
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(contentPadding)
|
||||
.padding(bottom = bottomNavHeight.value)
|
||||
) {
|
||||
if (scanningProgressItem.first) {
|
||||
if (state.scanningProgressItem.first) {
|
||||
ContentLoadingProgressBar(
|
||||
progressBarStyle = ProgressBarStyle.HORIZONTAL,
|
||||
progress = scanningProgressItem.second
|
||||
progress = state.scanningProgressItem.second
|
||||
)
|
||||
}
|
||||
if (noFilesViewItem.third) {
|
||||
NoFilesView(noFilesViewItem, onDownloadButtonClick)
|
||||
if (state.noFilesViewItem.third) {
|
||||
NoFilesView(state.noFilesViewItem, onDownloadButtonClick)
|
||||
} else {
|
||||
BookItemList(state, onClick, onLongClick, onMultiSelect)
|
||||
BookItemList(
|
||||
state.fileSelectListState,
|
||||
onClick,
|
||||
onLongClick,
|
||||
onMultiSelect,
|
||||
lazyListState
|
||||
)
|
||||
}
|
||||
|
||||
SelectFileButton(
|
||||
fabButtonClick,
|
||||
Modifier
|
||||
.align(Alignment.BottomEnd)
|
||||
.padding(end = SIXTEEN_DP, bottom = FAB_ICON_BOTTOM_MARGIN)
|
||||
.padding(end = SIXTEEN_DP, bottom = TEN_DP)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -122,8 +140,9 @@ private fun BookItemList(
|
||||
onClick: ((BookOnDisk) -> Unit)? = null,
|
||||
onLongClick: ((BookOnDisk) -> Unit)? = null,
|
||||
onMultiSelect: ((BookOnDisk) -> Unit)? = null,
|
||||
lazyListState: LazyListState,
|
||||
) {
|
||||
LazyColumn(modifier = Modifier.fillMaxSize()) {
|
||||
LazyColumn(modifier = Modifier.fillMaxSize(), state = lazyListState) {
|
||||
itemsIndexed(state.bookOnDiskListItems) { index, bookItem ->
|
||||
when (bookItem) {
|
||||
is BooksOnDiskListItem.LanguageItem -> {
|
||||
@ -179,32 +198,3 @@ fun NoFilesView(
|
||||
KiwixButton(noFilesViewItem.second, onDownloadButtonClick)
|
||||
}
|
||||
}
|
||||
|
||||
// @Preview
|
||||
// @Preview(name = "NightMode", uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
// @Composable
|
||||
// fun PreviewLocalLibrary() {
|
||||
// LocalLibraryScreen(
|
||||
// state = FileSelectListState(listOf(), SelectionMode.NORMAL),
|
||||
// snackBarHostState = SnackbarHostState(),
|
||||
// actionMenuItems = listOf(
|
||||
// ActionMenuItem(
|
||||
// IconItem.Drawable(org.kiwix.kiwixmobile.R.drawable.ic_baseline_mobile_screen_share_24px),
|
||||
// R.string.get_content_from_nearby_device,
|
||||
// { },
|
||||
// isEnabled = true,
|
||||
// testingTag = DELETE_MENU_BUTTON_TESTING_TAG
|
||||
// )
|
||||
// ),
|
||||
// onRefresh = {},
|
||||
// fabButtonClick = {},
|
||||
// swipeRefreshItem = false to true,
|
||||
// noFilesViewItem = Triple(
|
||||
// stringResource(R.string.no_files_here),
|
||||
// stringResource(R.string.download_books),
|
||||
// {}
|
||||
// )
|
||||
// ) {
|
||||
// NavigationIcon(IconItem.Vector(Icons.Filled.Menu), {})
|
||||
// }
|
||||
// }
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Kiwix Android
|
||||
* Copyright (c) 2025 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.nav.destination.library.local
|
||||
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import org.kiwix.kiwixmobile.core.ui.models.ActionMenuItem
|
||||
import org.kiwix.kiwixmobile.zimManager.fileselectView.FileSelectListState
|
||||
|
||||
/**
|
||||
* Represents the UI state for the Local Library Screen.
|
||||
*
|
||||
* This data class encapsulates all UI-related states in a single object,
|
||||
* reducing complexity in the Fragment.
|
||||
*/
|
||||
data class LocalLibraryScreenState(
|
||||
/**
|
||||
* Manages the file selection list state.
|
||||
*/
|
||||
val fileSelectListState: FileSelectListState,
|
||||
/**
|
||||
* Handles snack bar messages and displays.
|
||||
*/
|
||||
val snackBarHostState: SnackbarHostState,
|
||||
/**
|
||||
* Controls the visibility and behavior of the "Pull to refresh" animation.
|
||||
*
|
||||
* A [Pair] containing:
|
||||
* - [Boolean]: The first boolean triggers/hides the "pull to refresh" animation.
|
||||
* - [Boolean]: The second boolean enables/disables the "pull to refresh" gesture.
|
||||
*/
|
||||
val swipeRefreshItem: Pair<Boolean, Boolean>,
|
||||
/**
|
||||
* Represents the scanning progress state.
|
||||
*
|
||||
* A [Pair] containing:
|
||||
* - [Boolean]: Whether scanning is in progress.
|
||||
* - [Int]: The progress percentage of the scan.
|
||||
*/
|
||||
val scanningProgressItem: Pair<Boolean, Int>,
|
||||
/**
|
||||
* Controls the visibility of the "No files here" message and the "Download books" button.
|
||||
*
|
||||
* A [Triple] containing:
|
||||
* - [String]: The title text displayed when no files are available.
|
||||
* - [String]: The label for the download button.
|
||||
* - [Boolean]: Whether to show or hide this view.
|
||||
*/
|
||||
val noFilesViewItem: Triple<String, String, Boolean>,
|
||||
/**
|
||||
* Represents a list of action menu items available in the screen's top app bar.
|
||||
*/
|
||||
val actionMenuItems: List<ActionMenuItem>,
|
||||
/**
|
||||
* Stores the height of the bottom navigation bar in pixels.
|
||||
*/
|
||||
val bottomNavigationHeight: Int
|
||||
)
|
Loading…
x
Reference in New Issue
Block a user