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:
MohitMaliFtechiz 2025-03-18 18:50:53 +05:30
parent a72d021e95
commit 9be780b863
7 changed files with 361 additions and 64 deletions

View File

@ -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) {

View File

@ -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), {})
// }
// }

View File

@ -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"

View File

@ -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)
} }

View File

@ -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)

View File

@ -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(

View File

@ -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
} }