mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-08-03 10:46:53 -04:00
feat: language fragment to jetpack compose
- added orders to the test rule to avoid retries error in tests. - renamed content lambda to "navigationIcon". - removed redundant "Experimental api" from kiwixSearchView. - added appropriate text size for kiwixSearchView.
This commit is contained in:
parent
90830da5ca
commit
56e0c1c7b1
@ -27,6 +27,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
@ -47,6 +48,7 @@ import org.kiwix.kiwixmobile.language.viewmodel.LanguageViewModel
|
||||
import org.kiwix.kiwixmobile.language.viewmodel.State
|
||||
import org.kiwix.kiwixmobile.language.viewmodel.State.Content
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@SuppressLint("ComposableLambdaParameterNaming")
|
||||
@Composable
|
||||
fun LanguageScreen(
|
||||
@ -68,13 +70,13 @@ fun LanguageScreen(
|
||||
navigationIcon = navigationIcon,
|
||||
actionMenuItems = actionMenuItemList,
|
||||
searchBar = if (isSearchActive) {
|
||||
{ modifier ->
|
||||
{
|
||||
KiwixSearchView(
|
||||
modifier = modifier,
|
||||
value = searchText,
|
||||
testTag = SEARCH_FIELD_TESTING_TAG,
|
||||
onValueChange = onAppBarValueChange,
|
||||
onClearClick = onClearClick
|
||||
onClearClick = onClearClick,
|
||||
modifier = Modifier
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
@ -42,21 +42,11 @@ fun ContentLoadingProgressBar(
|
||||
) {
|
||||
when (progressBarStyle) {
|
||||
ProgressBarStyle.CIRCLE -> {
|
||||
if (progress == ZERO) {
|
||||
// Indeterminate mode - will spin continuously
|
||||
CircularProgressIndicator(
|
||||
modifier = modifier,
|
||||
color = progressBarColor
|
||||
)
|
||||
} else {
|
||||
// Determinate mode - shows specific progress
|
||||
CircularProgressIndicator(
|
||||
modifier = modifier,
|
||||
progress = { progress.toFloat() / HUNDERED },
|
||||
color = progressBarColor,
|
||||
trackColor = progressBarTrackColor
|
||||
)
|
||||
}
|
||||
CircularProgressIndicator(
|
||||
modifier = modifier,
|
||||
color = progressBarColor,
|
||||
trackColor = progressBarTrackColor
|
||||
)
|
||||
}
|
||||
|
||||
ProgressBarStyle.HORIZONTAL -> {
|
||||
|
@ -19,64 +19,86 @@
|
||||
package org.kiwix.kiwixmobile.core.ui.components
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight.Companion.SemiBold
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.ZERO
|
||||
import org.kiwix.kiwixmobile.core.ui.models.ActionMenuItem
|
||||
import org.kiwix.kiwixmobile.core.ui.models.IconItem
|
||||
import org.kiwix.kiwixmobile.core.ui.models.toPainter
|
||||
import org.kiwix.kiwixmobile.core.ui.theme.Black
|
||||
import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme
|
||||
import org.kiwix.kiwixmobile.core.ui.theme.MineShaftGray350
|
||||
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.SIXTEEN_DP
|
||||
|
||||
const val TOOLBAR_TITLE_TESTING_TAG = "toolbarTitle"
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun KiwixAppBar(
|
||||
@StringRes titleId: Int,
|
||||
navigationIcon: @Composable () -> Unit,
|
||||
actionMenuItems: List<ActionMenuItem> = emptyList(),
|
||||
topAppBarScrollBehavior: TopAppBarScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(),
|
||||
// Optional search bar, used in fragments that require it
|
||||
searchBar: (@Composable (Modifier) -> Unit)? = null
|
||||
searchBar: (@Composable () -> Unit)? = null
|
||||
) {
|
||||
KiwixTheme {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(KIWIX_APP_BAR_HEIGHT)
|
||||
.background(color = Black),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
navigationIcon()
|
||||
searchBar?.let { searchBarComposable ->
|
||||
searchBarComposable(
|
||||
Modifier.weight(1f)
|
||||
)
|
||||
} ?: run {
|
||||
// Otherwise, show the title
|
||||
AppBarTitle(titleId)
|
||||
Spacer(Modifier.weight(1f))
|
||||
}
|
||||
ActionMenu(actionMenuItems)
|
||||
TopAppBar(
|
||||
title = { AppBarTitleSection(titleId, searchBar) },
|
||||
navigationIcon = navigationIcon,
|
||||
actions = { ActionMenu(actionMenuItems) },
|
||||
scrollBehavior = topAppBarScrollBehavior,
|
||||
colors = TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = Black,
|
||||
scrolledContainerColor = Black
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("ComposableLambdaParameterNaming")
|
||||
@Composable
|
||||
private fun AppBarTitleSection(
|
||||
@StringRes titleId: Int,
|
||||
searchBar: (@Composable () -> Unit)? = null
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(start = SIXTEEN_DP),
|
||||
contentAlignment = Alignment.CenterStart
|
||||
) {
|
||||
searchBar?.let {
|
||||
it()
|
||||
} ?: run {
|
||||
AppBarTitle(titleId)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -93,10 +115,11 @@ private fun AppBarTitle(
|
||||
Text(
|
||||
text = stringResource(titleId),
|
||||
color = appBarTitleColor,
|
||||
style = MaterialTheme.typography.titleLarge.copy(fontWeight = SemiBold),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = SIXTEEN_DP)
|
||||
.testTag(TOOLBAR_TITLE_TESTING_TAG)
|
||||
.testTag(TOOLBAR_TITLE_TESTING_TAG),
|
||||
)
|
||||
}
|
||||
|
||||
@ -107,14 +130,10 @@ private fun ActionMenu(actionMenuItems: List<ActionMenuItem>) {
|
||||
IconButton(
|
||||
enabled = menuItem.isEnabled,
|
||||
onClick = menuItem.onClick,
|
||||
modifier = Modifier
|
||||
.testTag(menuItem.testingTag)
|
||||
modifier = Modifier.testTag(menuItem.testingTag)
|
||||
) {
|
||||
Icon(
|
||||
painter = when (val icon = menuItem.icon) {
|
||||
is IconItem.Vector -> rememberVectorPainter(icon.imageVector)
|
||||
is IconItem.Drawable -> painterResource(icon.drawableRes)
|
||||
},
|
||||
painter = menuItem.icon.toPainter(),
|
||||
contentDescription = stringResource(menuItem.contentDescription),
|
||||
tint = if (menuItem.isEnabled) menuItem.iconTint else Color.Gray
|
||||
)
|
||||
@ -122,3 +141,23 @@ private fun ActionMenu(actionMenuItems: List<ActionMenuItem>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberBottomNavigationVisibility(lazyListState: LazyListState?): Boolean {
|
||||
var isToolbarVisible by remember { mutableStateOf(true) }
|
||||
var lastScrollIndex by remember { mutableIntStateOf(ZERO) }
|
||||
val updatedLazyListState = rememberUpdatedState(lazyListState)
|
||||
|
||||
LaunchedEffect(updatedLazyListState) {
|
||||
updatedLazyListState.value?.let { state ->
|
||||
snapshotFlow { state.firstVisibleItemIndex }
|
||||
.collect { newScrollIndex ->
|
||||
if (newScrollIndex != lastScrollIndex) {
|
||||
isToolbarVisible = newScrollIndex < lastScrollIndex
|
||||
lastScrollIndex = newScrollIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return isToolbarVisible
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user