Revert back LazyList.isScroll... & fix menuAnchor deprecation caused by Bump compose version (#9682b8d9)

This commit is contained in:
Cuong M. Tran 2024-05-20 13:16:40 +07:00
parent ac86a9a2d9
commit 6cf789e747
No known key found for this signature in database
GPG key ID: 733AA7624B9315C2
3 changed files with 113 additions and 62 deletions

View file

@ -34,14 +34,11 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
@ -76,6 +73,7 @@ import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.screens.LoadingScreen
import tachiyomi.presentation.core.theme.header
import tachiyomi.presentation.core.util.clearFocusOnSoftKeyboardHide
import tachiyomi.presentation.core.util.isScrollingUp
import tachiyomi.presentation.core.util.plus
import tachiyomi.presentation.core.util.runOnEnterKeyPressed
import tachiyomi.presentation.core.util.secondaryItemAlpha
@ -172,9 +170,9 @@ fun AnimatedFloatingSearchBox(
placeholderText: String? = null,
) {
AnimatedVisibility(
visible = listState.isScrollingUp().value,
visible = listState.isScrollingUp(),
enter = expandVertically(),
exit = shrinkVertically()
exit = shrinkVertically(),
) {
SourcesSearch(
searchQuery = searchQuery,
@ -184,24 +182,6 @@ fun AnimatedFloatingSearchBox(
}
}
@Composable
fun LazyListState.isScrollingUp(): State<Boolean> {
return produceState(initialValue = true) {
var lastIndex = 0
var lastScroll = Int.MAX_VALUE
snapshotFlow {
firstVisibleItemIndex to firstVisibleItemScrollOffset
}.collect { (currentIndex, currentScroll) ->
if (currentIndex != lastIndex || currentScroll != lastScroll) {
value = currentIndex < lastIndex ||
(currentIndex == lastIndex && currentScroll < lastScroll)
lastIndex = currentIndex
lastScroll = currentScroll
}
}
}
}
@Composable
fun SourcesSearch(
searchQuery: String?,
@ -250,39 +230,47 @@ fun SourcesSearch(
keyboardActions = KeyboardActions(onSearch = { searchAndClearFocus() }),
singleLine = true,
cursorBrush = SolidColor(MaterialTheme.colorScheme.onBackground),
decorationBox = { innerTextField -> TextFieldDefaults.DecorationBox(
value = searchQuery ?: "",
innerTextField = innerTextField,
enabled = true,
singleLine = true,
visualTransformation = VisualTransformation.None,
interactionSource = remember { MutableInteractionSource() },
placeholder = { Text(
modifier = Modifier.secondaryItemAlpha(),
text = (placeholderText ?: stringResource(MR.strings.action_search_hint)),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.bodyMedium,
) },
leadingIcon = { SearchBoxLeadingIcon(
isFocused || !searchQuery.isNullOrBlank(),
modifier = Modifier,
onClickCloseSearch,
) },
trailingIcon = { SearchBoxTrailingIcon(
searchQuery.isNullOrEmpty(),
modifier = Modifier,
onClickClearSearch,
) },
shape = RoundedCornerShape(24.dp),
colors = TextFieldDefaults.colors(
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
errorIndicatorColor = Color.Transparent,
cursorColor = MaterialTheme.colorScheme.onBackground,
),
contentPadding = PaddingValues(12.dp),
) }
decorationBox = { innerTextField ->
TextFieldDefaults.DecorationBox(
value = searchQuery ?: "",
innerTextField = innerTextField,
enabled = true,
singleLine = true,
visualTransformation = VisualTransformation.None,
interactionSource = remember { MutableInteractionSource() },
placeholder = {
Text(
modifier = Modifier.secondaryItemAlpha(),
text = (placeholderText ?: stringResource(MR.strings.action_search_hint)),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.bodyMedium,
)
},
leadingIcon = {
SearchBoxLeadingIcon(
isFocused || !searchQuery.isNullOrBlank(),
modifier = Modifier,
onClickCloseSearch,
)
},
trailingIcon = {
SearchBoxTrailingIcon(
searchQuery.isNullOrEmpty(),
modifier = Modifier,
onClickClearSearch,
)
},
shape = RoundedCornerShape(24.dp),
colors = TextFieldDefaults.colors(
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
errorIndicatorColor = Color.Transparent,
cursorColor = MaterialTheme.colorScheme.onBackground,
),
contentPadding = PaddingValues(12.dp),
)
}
)
}
@ -292,7 +280,7 @@ fun SearchBoxLeadingIcon(
@Suppress("UNUSED_PARAMETER") modifier: Modifier = Modifier,
onClickCloseSearch: () -> Unit = {},
) {
if (isSearching)
if (isSearching) {
IconButton(
onClick = onClickCloseSearch,
) {
@ -301,11 +289,12 @@ fun SearchBoxLeadingIcon(
contentDescription = "Close",
)
}
else
} else {
Icon(
imageVector = Icons.Filled.Search,
contentDescription = "Search",
)
}
}
@Composable
@ -314,7 +303,7 @@ fun SearchBoxTrailingIcon(
@Suppress("UNUSED_PARAMETER") modifier: Modifier = Modifier,
onClickClearSearch: () -> Unit = {},
) {
if (!isEmpty)
if (!isEmpty) {
IconButton(
onClick = onClickClearSearch,
) {
@ -323,6 +312,7 @@ fun SearchBoxTrailingIcon(
contentDescription = "Clear",
)
}
}
}
// KMK <--
@ -475,9 +465,10 @@ fun SourceOptionsDialog(
// SY <--
// KMK -->
if (onClickSettings != null && source.installedExtension !== null &&
source.id !in listOf(LocalSource.ID, EH_SOURCE_ID, EXH_SOURCE_ID)) {
source.id !in listOf(LocalSource.ID, EH_SOURCE_ID, EXH_SOURCE_ID)
) {
Text(
text = stringResource(MR.strings.label_extension_info),
text = stringResource(MR.strings.label_extension_info),
modifier = Modifier
.clickable(onClick = onClickSettings)
.fillMaxWidth()

View file

@ -26,6 +26,7 @@ import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MenuAnchorType
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Slider
@ -215,7 +216,7 @@ fun SelectItem(
) {
OutlinedTextField(
modifier = Modifier
.menuAnchor()
.menuAnchor(MenuAnchorType.PrimaryEditable)
.fillMaxWidth()
.padding(
horizontal = SettingsItemsPaddings.Horizontal,

View file

@ -3,7 +3,10 @@ package tachiyomi.presentation.core.util
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
@Composable
fun LazyListState.shouldExpandFAB(): Boolean {
@ -16,3 +19,59 @@ fun LazyListState.shouldExpandFAB(): Boolean {
}
.value
}
@Composable
fun LazyListState.isScrolledToStart(): Boolean {
return remember {
derivedStateOf {
val firstItem = layoutInfo.visibleItemsInfo.firstOrNull()
firstItem == null || firstItem.offset == layoutInfo.viewportStartOffset
}
}.value
}
@Composable
fun LazyListState.isScrolledToEnd(): Boolean {
return remember {
derivedStateOf {
val lastItem = layoutInfo.visibleItemsInfo.lastOrNull()
lastItem == null || lastItem.size + lastItem.offset <= layoutInfo.viewportEndOffset
}
}.value
}
@Composable
fun LazyListState.isScrollingUp(): Boolean {
var previousIndex by remember { mutableIntStateOf(firstVisibleItemIndex) }
var previousScrollOffset by remember { mutableIntStateOf(firstVisibleItemScrollOffset) }
return remember {
derivedStateOf {
if (previousIndex != firstVisibleItemIndex) {
previousIndex > firstVisibleItemIndex
} else {
previousScrollOffset >= firstVisibleItemScrollOffset
}.also {
previousIndex = firstVisibleItemIndex
previousScrollOffset = firstVisibleItemScrollOffset
}
}
}.value
}
@Composable
fun LazyListState.isScrollingDown(): Boolean {
var previousIndex by remember { mutableIntStateOf(firstVisibleItemIndex) }
var previousScrollOffset by remember { mutableIntStateOf(firstVisibleItemScrollOffset) }
return remember {
derivedStateOf {
if (previousIndex != firstVisibleItemIndex) {
previousIndex < firstVisibleItemIndex
} else {
previousScrollOffset <= firstVisibleItemScrollOffset
}.also {
previousIndex = firstVisibleItemIndex
previousScrollOffset = firstVisibleItemScrollOffset
}
}
}.value
}