mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-08 14:52:13 -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.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
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
|
||||||
import org.kiwix.kiwixmobile.language.viewmodel.State.Content
|
import org.kiwix.kiwixmobile.language.viewmodel.State.Content
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@SuppressLint("ComposableLambdaParameterNaming")
|
@SuppressLint("ComposableLambdaParameterNaming")
|
||||||
@Composable
|
@Composable
|
||||||
fun LanguageScreen(
|
fun LanguageScreen(
|
||||||
@ -68,13 +70,13 @@ fun LanguageScreen(
|
|||||||
navigationIcon = navigationIcon,
|
navigationIcon = navigationIcon,
|
||||||
actionMenuItems = actionMenuItemList,
|
actionMenuItems = actionMenuItemList,
|
||||||
searchBar = if (isSearchActive) {
|
searchBar = if (isSearchActive) {
|
||||||
{ modifier ->
|
{
|
||||||
KiwixSearchView(
|
KiwixSearchView(
|
||||||
modifier = modifier,
|
|
||||||
value = searchText,
|
value = searchText,
|
||||||
testTag = SEARCH_FIELD_TESTING_TAG,
|
testTag = SEARCH_FIELD_TESTING_TAG,
|
||||||
onValueChange = onAppBarValueChange,
|
onValueChange = onAppBarValueChange,
|
||||||
onClearClick = onClearClick
|
onClearClick = onClearClick,
|
||||||
|
modifier = Modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -42,21 +42,11 @@ fun ContentLoadingProgressBar(
|
|||||||
) {
|
) {
|
||||||
when (progressBarStyle) {
|
when (progressBarStyle) {
|
||||||
ProgressBarStyle.CIRCLE -> {
|
ProgressBarStyle.CIRCLE -> {
|
||||||
if (progress == ZERO) {
|
CircularProgressIndicator(
|
||||||
// Indeterminate mode - will spin continuously
|
modifier = modifier,
|
||||||
CircularProgressIndicator(
|
color = progressBarColor,
|
||||||
modifier = modifier,
|
trackColor = progressBarTrackColor
|
||||||
color = progressBarColor
|
)
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// Determinate mode - shows specific progress
|
|
||||||
CircularProgressIndicator(
|
|
||||||
modifier = modifier,
|
|
||||||
progress = { progress.toFloat() / HUNDERED },
|
|
||||||
color = progressBarColor,
|
|
||||||
trackColor = progressBarTrackColor
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgressBarStyle.HORIZONTAL -> {
|
ProgressBarStyle.HORIZONTAL -> {
|
||||||
|
@ -19,64 +19,86 @@
|
|||||||
package org.kiwix.kiwixmobile.core.ui.components
|
package org.kiwix.kiwixmobile.core.ui.components
|
||||||
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
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.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
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.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.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.res.stringResource
|
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.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.Black
|
||||||
import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme
|
import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme
|
||||||
import org.kiwix.kiwixmobile.core.ui.theme.MineShaftGray350
|
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.SIXTEEN_DP
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIXTEEN_DP
|
||||||
|
|
||||||
const val TOOLBAR_TITLE_TESTING_TAG = "toolbarTitle"
|
const val TOOLBAR_TITLE_TESTING_TAG = "toolbarTitle"
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun KiwixAppBar(
|
fun KiwixAppBar(
|
||||||
@StringRes titleId: Int,
|
@StringRes titleId: Int,
|
||||||
navigationIcon: @Composable () -> Unit,
|
navigationIcon: @Composable () -> Unit,
|
||||||
actionMenuItems: List<ActionMenuItem> = emptyList(),
|
actionMenuItems: List<ActionMenuItem> = emptyList(),
|
||||||
|
topAppBarScrollBehavior: TopAppBarScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(),
|
||||||
// Optional search bar, used in fragments that require it
|
// Optional search bar, used in fragments that require it
|
||||||
searchBar: (@Composable (Modifier) -> Unit)? = null
|
searchBar: (@Composable () -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
KiwixTheme {
|
KiwixTheme {
|
||||||
Row(
|
TopAppBar(
|
||||||
modifier = Modifier
|
title = { AppBarTitleSection(titleId, searchBar) },
|
||||||
.fillMaxWidth()
|
navigationIcon = navigationIcon,
|
||||||
.height(KIWIX_APP_BAR_HEIGHT)
|
actions = { ActionMenu(actionMenuItems) },
|
||||||
.background(color = Black),
|
scrollBehavior = topAppBarScrollBehavior,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
colors = TopAppBarDefaults.topAppBarColors(
|
||||||
) {
|
containerColor = Black,
|
||||||
navigationIcon()
|
scrolledContainerColor = Black
|
||||||
searchBar?.let { searchBarComposable ->
|
)
|
||||||
searchBarComposable(
|
)
|
||||||
Modifier.weight(1f)
|
}
|
||||||
)
|
}
|
||||||
} ?: run {
|
|
||||||
// Otherwise, show the title
|
@Suppress("ComposableLambdaParameterNaming")
|
||||||
AppBarTitle(titleId)
|
@Composable
|
||||||
Spacer(Modifier.weight(1f))
|
private fun AppBarTitleSection(
|
||||||
}
|
@StringRes titleId: Int,
|
||||||
ActionMenu(actionMenuItems)
|
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(
|
||||||
text = stringResource(titleId),
|
text = stringResource(titleId),
|
||||||
color = appBarTitleColor,
|
color = appBarTitleColor,
|
||||||
style = MaterialTheme.typography.titleLarge.copy(fontWeight = SemiBold),
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
maxLines = 1,
|
||||||
modifier = Modifier
|
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(
|
IconButton(
|
||||||
enabled = menuItem.isEnabled,
|
enabled = menuItem.isEnabled,
|
||||||
onClick = menuItem.onClick,
|
onClick = menuItem.onClick,
|
||||||
modifier = Modifier
|
modifier = Modifier.testTag(menuItem.testingTag)
|
||||||
.testTag(menuItem.testingTag)
|
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
painter = when (val icon = menuItem.icon) {
|
painter = menuItem.icon.toPainter(),
|
||||||
is IconItem.Vector -> rememberVectorPainter(icon.imageVector)
|
|
||||||
is IconItem.Drawable -> painterResource(icon.drawableRes)
|
|
||||||
},
|
|
||||||
contentDescription = stringResource(menuItem.contentDescription),
|
contentDescription = stringResource(menuItem.contentDescription),
|
||||||
tint = if (menuItem.isEnabled) menuItem.iconTint else Color.Gray
|
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