mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-17 11:25:34 -04:00
Migrated the LocalLibraryFragment
to jetpack.
* Created `LocalLibraryScreen` for compose UI. * Refactored the `LocalLibraryFragment` functionality with compose. * Minor refinement in `KiwixAppBar` for title and hamburger icon.
This commit is contained in:
parent
a72d021e95
commit
9be780b863
@ -41,7 +41,12 @@ import androidx.activity.result.ActivityResultLauncher
|
|||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.appcompat.widget.Toolbar
|
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.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
@ -84,6 +89,9 @@ import org.kiwix.kiwixmobile.core.navigateToAppSettings
|
|||||||
import org.kiwix.kiwixmobile.core.navigateToSettings
|
import org.kiwix.kiwixmobile.core.navigateToSettings
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
||||||
|
import org.kiwix.kiwixmobile.core.ui.components.NavigationIcon
|
||||||
|
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
|
import org.kiwix.kiwixmobile.core.utils.EXTERNAL_SELECT_POSITION
|
||||||
import org.kiwix.kiwixmobile.core.utils.INTERNAL_SELECT_POSITION
|
import org.kiwix.kiwixmobile.core.utils.INTERNAL_SELECT_POSITION
|
||||||
import org.kiwix.kiwixmobile.core.utils.LanguageUtils
|
import org.kiwix.kiwixmobile.core.utils.LanguageUtils
|
||||||
@ -116,7 +124,9 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
private const val WAS_IN_ACTION_MODE = "WAS_IN_ACTION_MODE"
|
private const val WAS_IN_ACTION_MODE = "WAS_IN_ACTION_MODE"
|
||||||
private const val MATERIAL_BOTTOM_VIEW_ENTER_ANIMATION_DURATION = 225L
|
private const val MATERIAL_BOTTOM_VIEW_ENTER_ANIMATION_DURATION = 225L
|
||||||
|
const val LOCAL_FILE_TRANSFER_MENU_BUTTON_TESTING_TAG = "localFileTransferMenuButtonTestingTag"
|
||||||
|
|
||||||
|
@Suppress("LargeClass")
|
||||||
class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCallback {
|
class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCallback {
|
||||||
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
|
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
|
||||||
|
|
||||||
@ -136,8 +146,20 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
|||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
private var fragmentDestinationLibraryBinding: FragmentDestinationLibraryBinding? = null
|
private var fragmentDestinationLibraryBinding: FragmentDestinationLibraryBinding? = null
|
||||||
private var permissionDeniedLayoutShowing = false
|
private var permissionDeniedLayoutShowing = false
|
||||||
private var fileSelectListState: FileSelectListState? = null
|
|
||||||
private var zimFileUri: Uri? = null
|
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))
|
||||||
|
|
||||||
private val zimManageViewModel by lazy {
|
private val zimManageViewModel by lazy {
|
||||||
requireActivity().viewModel<ZimManageViewModel>(viewModelFactory)
|
requireActivity().viewModel<ZimManageViewModel>(viewModelFactory)
|
||||||
@ -154,13 +176,11 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
|||||||
if (readStorageHasBeenPermanentlyDenied(isGranted)) {
|
if (readStorageHasBeenPermanentlyDenied(isGranted)) {
|
||||||
fragmentDestinationLibraryBinding?.apply {
|
fragmentDestinationLibraryBinding?.apply {
|
||||||
permissionDeniedLayoutShowing = true
|
permissionDeniedLayoutShowing = true
|
||||||
fileManagementNoFiles.visibility = VISIBLE
|
noFilesViewItem.value = Triple(
|
||||||
goToDownloadsButtonNoFiles.visibility = VISIBLE
|
requireActivity().resources.getString(string.grant_read_storage_permission),
|
||||||
fileManagementNoFiles.text =
|
requireActivity().resources.getString(string.go_to_settings_label),
|
||||||
requireActivity().resources.getString(string.grant_read_storage_permission)
|
true
|
||||||
goToDownloadsButtonNoFiles.text =
|
)
|
||||||
requireActivity().resources.getString(string.go_to_settings_label)
|
|
||||||
zimfilelist.visibility = GONE
|
|
||||||
}
|
}
|
||||||
} else if (isGranted) {
|
} else if (isGranted) {
|
||||||
permissionDeniedLayoutShowing = false
|
permissionDeniedLayoutShowing = false
|
||||||
@ -202,25 +222,88 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
|||||||
): View? {
|
): View? {
|
||||||
LanguageUtils(requireActivity())
|
LanguageUtils(requireActivity())
|
||||||
.changeFont(requireActivity(), sharedPreferenceUtil)
|
.changeFont(requireActivity(), sharedPreferenceUtil)
|
||||||
fragmentDestinationLibraryBinding =
|
// fragmentDestinationLibraryBinding =
|
||||||
FragmentDestinationLibraryBinding.inflate(
|
// FragmentDestinationLibraryBinding.inflate(
|
||||||
inflater,
|
// inflater,
|
||||||
container,
|
// container,
|
||||||
false
|
// false
|
||||||
)
|
// )
|
||||||
val toolbar = fragmentDestinationLibraryBinding?.root?.findViewById<Toolbar>(R.id.toolbar)
|
// val toolbar = fragmentDestinationLibraryBinding?.root?.findViewById<Toolbar>(R.id.toolbar)
|
||||||
val activity = activity as CoreMainActivity
|
// val activity = activity as CoreMainActivity
|
||||||
activity.setSupportActionBar(toolbar)
|
// activity.setSupportActionBar(toolbar)
|
||||||
activity.supportActionBar?.apply {
|
// activity.supportActionBar?.apply {
|
||||||
setDisplayHomeAsUpEnabled(true)
|
// setDisplayHomeAsUpEnabled(true)
|
||||||
setTitle(string.library)
|
// setTitle(string.library)
|
||||||
}
|
// }
|
||||||
if (toolbar != null) {
|
// if (toolbar != null) {
|
||||||
activity.setupDrawerToggle(toolbar)
|
// activity.setupDrawerToggle(toolbar)
|
||||||
}
|
// }
|
||||||
setupMenu()
|
// setupMenu()
|
||||||
|
|
||||||
return fragmentDestinationLibraryBinding?.root
|
val composeView = ComposeView(requireContext()).apply {
|
||||||
|
setContent {
|
||||||
|
snackBarHostState = remember { SnackbarHostState() }
|
||||||
|
LocalLibraryScreen(
|
||||||
|
state = fileSelectListState.value,
|
||||||
|
snackBarHostState = snackBarHostState,
|
||||||
|
fabButtonClick = { filePickerButtonClick() },
|
||||||
|
actionMenuItems = actionMenuItems(),
|
||||||
|
onClick = { onBookItemClick(it) },
|
||||||
|
onLongClick = { onBookItemLongClick(it) },
|
||||||
|
onMultiSelect = { offerAction(RequestSelect(it)) },
|
||||||
|
onRefresh = {},
|
||||||
|
swipeRefreshItem = true to true,
|
||||||
|
noFilesViewItem = noFilesViewItem.value,
|
||||||
|
onDownloadButtonClick = { downloadBookButtonClick() }
|
||||||
|
) {
|
||||||
|
NavigationIcon(
|
||||||
|
iconItem = IconItem.Vector(Icons.Filled.Menu),
|
||||||
|
contentDescription = string.open_drawer,
|
||||||
|
onClick = {
|
||||||
|
// 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()
|
||||||
|
} else {
|
||||||
|
activity.openNavigationDrawer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return composeView
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun actionMenuItems() = listOf(
|
||||||
|
ActionMenuItem(
|
||||||
|
IconItem.Drawable(R.drawable.ic_baseline_mobile_screen_share_24px),
|
||||||
|
string.get_content_from_nearby_device,
|
||||||
|
{ navigateToLocalFileTransferFragment() },
|
||||||
|
isEnabled = true,
|
||||||
|
testingTag = LOCAL_FILE_TRANSFER_MENU_BUTTON_TESTING_TAG
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun onBookItemClick(bookOnDisk: BookOnDisk) {
|
||||||
|
if (!requireActivity().isManageExternalStoragePermissionGranted(sharedPreferenceUtil)) {
|
||||||
|
showManageExternalStoragePermissionDialog()
|
||||||
|
} else {
|
||||||
|
offerAction(RequestNavigateTo(bookOnDisk))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onBookItemLongClick(bookOnDisk: BookOnDisk) {
|
||||||
|
if (!requireActivity().isManageExternalStoragePermissionGranted(sharedPreferenceUtil)) {
|
||||||
|
showManageExternalStoragePermissionDialog()
|
||||||
|
} else {
|
||||||
|
offerAction(RequestMultiSelection(bookOnDisk))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupMenu() {
|
private fun setupMenu() {
|
||||||
@ -294,7 +377,6 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
|||||||
offerAction(FileSelectActions.UserClickedDownloadBooksButton)
|
offerAction(FileSelectActions.UserClickedDownloadBooksButton)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setUpFilePickerButton()
|
|
||||||
|
|
||||||
fragmentDestinationLibraryBinding?.zimfilelist?.addOnScrollListener(
|
fragmentDestinationLibraryBinding?.zimfilelist?.addOnScrollListener(
|
||||||
SimpleRecyclerViewScrollListener { _, newState ->
|
SimpleRecyclerViewScrollListener { _, newState ->
|
||||||
@ -314,6 +396,15 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
|||||||
showCopyMoveDialogForOpenedZimFileFromStorage()
|
showCopyMoveDialogForOpenedZimFileFromStorage()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun downloadBookButtonClick() {
|
||||||
|
if (permissionDeniedLayoutShowing) {
|
||||||
|
permissionDeniedLayoutShowing = false
|
||||||
|
requireActivity().navigateToAppSettings()
|
||||||
|
} else {
|
||||||
|
offerAction(FileSelectActions.UserClickedDownloadBooksButton)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun showCopyMoveDialogForOpenedZimFileFromStorage() {
|
private fun showCopyMoveDialogForOpenedZimFileFromStorage() {
|
||||||
val args = LocalLibraryFragmentArgs.fromBundle(requireArguments())
|
val args = LocalLibraryFragmentArgs.fromBundle(requireArguments())
|
||||||
if (args.zimFileUri.isNotEmpty()) {
|
if (args.zimFileUri.isNotEmpty()) {
|
||||||
@ -374,15 +465,13 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpFilePickerButton() {
|
private fun filePickerButtonClick() {
|
||||||
fragmentDestinationLibraryBinding?.selectFile?.setOnClickListener {
|
|
||||||
if (!requireActivity().isManageExternalStoragePermissionGranted(sharedPreferenceUtil)) {
|
if (!requireActivity().isManageExternalStoragePermissionGranted(sharedPreferenceUtil)) {
|
||||||
showManageExternalStoragePermissionDialog()
|
showManageExternalStoragePermissionDialog()
|
||||||
} else if (requestExternalStorageWritePermission()) {
|
} else if (requestExternalStorageWritePermission()) {
|
||||||
showFileChooser()
|
showFileChooser()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun showFileChooser() {
|
private fun showFileChooser() {
|
||||||
val intent =
|
val intent =
|
||||||
@ -546,7 +635,7 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
|||||||
val effectResult = it.invokeWith(requireActivity() as AppCompatActivity)
|
val effectResult = it.invokeWith(requireActivity() as AppCompatActivity)
|
||||||
if (effectResult is ActionMode) {
|
if (effectResult is ActionMode) {
|
||||||
actionMode = effectResult
|
actionMode = effectResult
|
||||||
fileSelectListState?.selectedBooks?.size?.let(::setActionModeTitle)
|
fileSelectListState.value.selectedBooks.size.let(::setActionModeTitle)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Throwable::printStackTrace
|
Throwable::printStackTrace
|
||||||
@ -571,30 +660,19 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun render(state: FileSelectListState) {
|
private fun render(state: FileSelectListState) {
|
||||||
fileSelectListState = state
|
fileSelectListState.value = state
|
||||||
val items: List<BooksOnDiskListItem> = state.bookOnDiskListItems
|
if (state.bookOnDiskListItems.none(BooksOnDiskListItem::isSelected)) {
|
||||||
bookDelegate.selectionMode = state.selectionMode
|
|
||||||
booksOnDiskAdapter.items = items
|
|
||||||
if (items.none(BooksOnDiskListItem::isSelected)) {
|
|
||||||
actionMode?.finish()
|
actionMode?.finish()
|
||||||
actionMode = null
|
actionMode = null
|
||||||
}
|
}
|
||||||
setActionModeTitle(state.selectedBooks.size)
|
setActionModeTitle(state.selectedBooks.size)
|
||||||
fragmentDestinationLibraryBinding?.apply {
|
noFilesViewItem.value = Triple(
|
||||||
if (items.isEmpty()) {
|
requireActivity().resources.getString(string.no_files_here),
|
||||||
fileManagementNoFiles.text = requireActivity().resources.getString(string.no_files_here)
|
requireActivity().resources.getString(string.download_books),
|
||||||
goToDownloadsButtonNoFiles.text =
|
// If here are no items available then show the "No files here" text, and "Download books"
|
||||||
requireActivity().resources.getString(string.download_books)
|
// button so that user can go to "Online library" screen by clicking this button.
|
||||||
|
state.bookOnDiskListItems.isEmpty()
|
||||||
fileManagementNoFiles.visibility = View.VISIBLE
|
)
|
||||||
goToDownloadsButtonNoFiles.visibility = View.VISIBLE
|
|
||||||
zimfilelist.visibility = View.GONE
|
|
||||||
} else {
|
|
||||||
fileManagementNoFiles.visibility = View.GONE
|
|
||||||
goToDownloadsButtonNoFiles.visibility = View.GONE
|
|
||||||
zimfilelist.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setActionModeTitle(selectedBookCount: Int) {
|
private fun setActionModeTitle(selectedBookCount: Int) {
|
||||||
|
@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
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.itemsIndexed
|
||||||
|
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.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import org.kiwix.kiwixmobile.R.string
|
||||||
|
import org.kiwix.kiwixmobile.core.R
|
||||||
|
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.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.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
|
||||||
|
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||||
|
import org.kiwix.kiwixmobile.ui.BookItem
|
||||||
|
import org.kiwix.kiwixmobile.ui.ZimFilesLanguageHeader
|
||||||
|
import org.kiwix.kiwixmobile.zimManager.fileselectView.FileSelectListState
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Suppress("ComposableLambdaParameterNaming", "LongParameterList", "UnusedParameter")
|
||||||
|
@Composable
|
||||||
|
fun LocalLibraryScreen(
|
||||||
|
state: FileSelectListState,
|
||||||
|
snackBarHostState: SnackbarHostState,
|
||||||
|
swipeRefreshItem: Pair<Boolean, Boolean>,
|
||||||
|
onRefresh: () -> Unit,
|
||||||
|
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 swipeRefreshState = rememberPullToRefreshState()
|
||||||
|
KiwixTheme {
|
||||||
|
Scaffold(
|
||||||
|
snackbarHost = { KiwixSnackbarHost(snackbarHostState = snackBarHostState) },
|
||||||
|
topBar = { KiwixAppBar(R.string.library, navigationIcon, actionMenuItems) },
|
||||||
|
modifier = Modifier.systemBarsPadding()
|
||||||
|
) { contentPadding ->
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(contentPadding)
|
||||||
|
// .pullToRefresh(
|
||||||
|
// isRefreshing = swipeRefreshItem.first,
|
||||||
|
// state = swipeRefreshState,
|
||||||
|
// enabled = swipeRefreshItem.second,
|
||||||
|
// onRefresh = { onRefresh }
|
||||||
|
// )
|
||||||
|
// .pullToRefreshIndicator(
|
||||||
|
// state = swipeRefreshState,
|
||||||
|
// isRefreshing = swipeRefreshItem.first
|
||||||
|
// )
|
||||||
|
) {
|
||||||
|
if (noFilesViewItem.third) {
|
||||||
|
NoFilesView(noFilesViewItem, onDownloadButtonClick)
|
||||||
|
} else {
|
||||||
|
BookItemList(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectFileButton(
|
||||||
|
fabButtonClick,
|
||||||
|
Modifier
|
||||||
|
.align(Alignment.BottomEnd)
|
||||||
|
.padding(end = SIXTEEN_DP, bottom = FAB_ICON_BOTTOM_MARGIN)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun BookItemList(
|
||||||
|
state: FileSelectListState,
|
||||||
|
onClick: ((BookOnDisk) -> Unit)? = null,
|
||||||
|
onLongClick: ((BookOnDisk) -> Unit)? = null,
|
||||||
|
onMultiSelect: ((BookOnDisk) -> Unit)? = null,
|
||||||
|
) {
|
||||||
|
LazyColumn(modifier = Modifier.fillMaxSize()) {
|
||||||
|
itemsIndexed(state.bookOnDiskListItems) { index, bookItem ->
|
||||||
|
when (bookItem) {
|
||||||
|
is BooksOnDiskListItem.LanguageItem -> {
|
||||||
|
ZimFilesLanguageHeader(bookItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
is BookOnDisk -> {
|
||||||
|
BookItem(
|
||||||
|
index = index,
|
||||||
|
bookOnDisk = bookItem,
|
||||||
|
selectionMode = state.selectionMode,
|
||||||
|
onClick = onClick,
|
||||||
|
onLongClick = onLongClick,
|
||||||
|
onMultiSelect = onMultiSelect
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun SelectFileButton(fabButtonClick: () -> Unit, modifier: Modifier) {
|
||||||
|
FloatingActionButton(
|
||||||
|
onClick = fabButtonClick,
|
||||||
|
modifier = modifier,
|
||||||
|
containerColor = Black,
|
||||||
|
shape = MaterialTheme.shapes.extraLarge
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.ic_add_blue_24dp),
|
||||||
|
contentDescription = stringResource(id = string.select_zim_file),
|
||||||
|
tint = White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun NoFilesView(
|
||||||
|
noFilesViewItem: Triple<String, String, Boolean>,
|
||||||
|
onDownloadButtonClick: () -> Unit
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = noFilesViewItem.first,
|
||||||
|
style = MaterialTheme.typography.titleLarge.copy(fontWeight = FontWeight.Medium)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(EIGHT_DP))
|
||||||
|
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), {})
|
||||||
|
// }
|
||||||
|
// }
|
@ -66,8 +66,7 @@
|
|||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/libraryFragment"
|
android:id="@+id/libraryFragment"
|
||||||
android:name="org.kiwix.kiwixmobile.nav.destination.library.LocalLibraryFragment"
|
android:name="org.kiwix.kiwixmobile.nav.destination.library.LocalLibraryFragment"
|
||||||
android:label="Library"
|
android:label="Library">
|
||||||
tools:layout="@layout/fragment_destination_library">
|
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_navigation_library_to_navigation_reader"
|
android:id="@+id/action_navigation_library_to_navigation_reader"
|
||||||
app:destination="@id/readerFragment"
|
app:destination="@id/readerFragment"
|
||||||
|
@ -326,13 +326,17 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider {
|
|||||||
handleDrawerOnNavigation()
|
handleDrawerOnNavigation()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigationDrawerIsOpen(): Boolean =
|
fun navigationDrawerIsOpen(): Boolean =
|
||||||
drawerContainerLayout.isDrawerOpen(drawerNavView)
|
drawerContainerLayout.isDrawerOpen(drawerNavView)
|
||||||
|
|
||||||
fun closeNavigationDrawer() {
|
fun closeNavigationDrawer() {
|
||||||
drawerContainerLayout.closeDrawer(drawerNavView)
|
drawerContainerLayout.closeDrawer(drawerNavView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun openNavigationDrawer() {
|
||||||
|
drawerContainerLayout.openDrawer(drawerNavView)
|
||||||
|
}
|
||||||
|
|
||||||
fun openSupportKiwixExternalLink() {
|
fun openSupportKiwixExternalLink() {
|
||||||
externalLinkOpener.openExternalUrl(KIWIX_SUPPORT_URL.toUri().browserIntent(), false)
|
externalLinkOpener.openExternalUrl(KIWIX_SUPPORT_URL.toUri().browserIntent(), false)
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,6 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight.Companion.SemiBold
|
|
||||||
import org.kiwix.kiwixmobile.core.ui.models.ActionMenuItem
|
import org.kiwix.kiwixmobile.core.ui.models.ActionMenuItem
|
||||||
import org.kiwix.kiwixmobile.core.ui.models.toPainter
|
import org.kiwix.kiwixmobile.core.ui.models.toPainter
|
||||||
import org.kiwix.kiwixmobile.core.ui.theme.Black
|
import org.kiwix.kiwixmobile.core.ui.theme.Black
|
||||||
@ -45,6 +44,7 @@ import org.kiwix.kiwixmobile.core.ui.theme.MineShaftGray350
|
|||||||
import org.kiwix.kiwixmobile.core.ui.theme.White
|
import org.kiwix.kiwixmobile.core.ui.theme.White
|
||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.KIWIX_APP_BAR_HEIGHT
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.KIWIX_APP_BAR_HEIGHT
|
||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIXTEEN_DP
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIXTEEN_DP
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TWO_DP
|
||||||
|
|
||||||
const val TOOLBAR_TITLE_TESTING_TAG = "toolbarTitle"
|
const val TOOLBAR_TITLE_TESTING_TAG = "toolbarTitle"
|
||||||
|
|
||||||
@ -64,6 +64,7 @@ fun KiwixAppBar(
|
|||||||
.background(color = Black),
|
.background(color = Black),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
|
Spacer(Modifier.padding(start = TWO_DP))
|
||||||
navigationIcon()
|
navigationIcon()
|
||||||
searchBar?.let {
|
searchBar?.let {
|
||||||
// Display the search bar when provided
|
// Display the search bar when provided
|
||||||
@ -90,7 +91,7 @@ private fun AppBarTitle(
|
|||||||
Text(
|
Text(
|
||||||
text = stringResource(titleId),
|
text = stringResource(titleId),
|
||||||
color = appBarTitleColor,
|
color = appBarTitleColor,
|
||||||
style = MaterialTheme.typography.titleLarge.copy(fontWeight = SemiBold),
|
style = MaterialTheme.typography.titleMedium,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = SIXTEEN_DP)
|
.padding(horizontal = SIXTEEN_DP)
|
||||||
.testTag(TOOLBAR_TITLE_TESTING_TAG)
|
.testTag(TOOLBAR_TITLE_TESTING_TAG)
|
||||||
|
@ -46,7 +46,10 @@ val KiwixTypography = Typography(
|
|||||||
headlineMedium = TextStyle(fontSize = MEDIUM_HEADLINE_TEXT_SIZE),
|
headlineMedium = TextStyle(fontSize = MEDIUM_HEADLINE_TEXT_SIZE),
|
||||||
headlineSmall = TextStyle(fontSize = SMALL_HEADLINE_TEXT_SIZE),
|
headlineSmall = TextStyle(fontSize = SMALL_HEADLINE_TEXT_SIZE),
|
||||||
titleLarge = TextStyle(fontSize = LARGE_TITLE_TEXT_SIZE),
|
titleLarge = TextStyle(fontSize = LARGE_TITLE_TEXT_SIZE),
|
||||||
titleMedium = TextStyle(fontSize = MEDIUM_TITLE_TEXT_SIZE),
|
titleMedium = TextStyle(
|
||||||
|
fontSize = MEDIUM_TITLE_TEXT_SIZE,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
),
|
||||||
titleSmall = TextStyle(fontSize = SMALL_TITLE_TEXT_SIZE),
|
titleSmall = TextStyle(fontSize = SMALL_TITLE_TEXT_SIZE),
|
||||||
bodyLarge = TextStyle(fontSize = LARGE_BODY_TEXT_SIZE),
|
bodyLarge = TextStyle(fontSize = LARGE_BODY_TEXT_SIZE),
|
||||||
bodyMedium = TextStyle(
|
bodyMedium = TextStyle(
|
||||||
|
@ -72,7 +72,7 @@ object ComposeDimens {
|
|||||||
val MEDIUM_HEADLINE_TEXT_SIZE = 28.sp
|
val MEDIUM_HEADLINE_TEXT_SIZE = 28.sp
|
||||||
val SMALL_HEADLINE_TEXT_SIZE = 24.sp
|
val SMALL_HEADLINE_TEXT_SIZE = 24.sp
|
||||||
val LARGE_TITLE_TEXT_SIZE = 22.sp
|
val LARGE_TITLE_TEXT_SIZE = 22.sp
|
||||||
val MEDIUM_TITLE_TEXT_SIZE = 18.sp
|
val MEDIUM_TITLE_TEXT_SIZE = 20.sp
|
||||||
val SMALL_TITLE_TEXT_SIZE = 16.sp
|
val SMALL_TITLE_TEXT_SIZE = 16.sp
|
||||||
val LARGE_BODY_TEXT_SIZE = 16.sp
|
val LARGE_BODY_TEXT_SIZE = 16.sp
|
||||||
val MEDIUM_BODY_TEXT_SIZE = 14.sp
|
val MEDIUM_BODY_TEXT_SIZE = 14.sp
|
||||||
@ -93,6 +93,9 @@ object ComposeDimens {
|
|||||||
val MAXIMUM_HEIGHT_OF_QR_CODE = 128.dp
|
val MAXIMUM_HEIGHT_OF_QR_CODE = 128.dp
|
||||||
val MINIMUM_HEIGHT_OF_BOOKS_LIST = 256.dp
|
val MINIMUM_HEIGHT_OF_BOOKS_LIST = 256.dp
|
||||||
|
|
||||||
// BookItem dimes
|
// BookItem dimens
|
||||||
val BOOK_ICON_SIZE = 40.dp
|
val BOOK_ICON_SIZE = 40.dp
|
||||||
|
|
||||||
|
// LocalLibraryFragment dimens
|
||||||
|
val FAB_ICON_BOTTOM_MARGIN = 66.dp
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user