Update to snapshot Compose and remove workaround (#1050)
* Update to snapshot Compose * Fix dep * Revert "More workaround" This reverts commit9013778f58. * Revert "Workaround for lazy layout lagging (#1042)" This reverts commitb83e0fd0* Revert "Workaround for comment list lagging at the bottom" This reverts commit45be957df5. * Fix minOffset for blur radius calculation Also use `onSizeChanged` instead of `onGloballyPositioned` as measurement happens before placement.
This commit is contained in:
1 parent
5762b0bfc3
commit
21b9fe3cb2
16 files changed
+130
-128
No files matched your search
@@ -277,6 +277,11 @@ dependencies {
|
||||
implementation(libs.compose.ui.tooling.preview)
|
||||
}
|
||||
|
||||
// TODO: Remove once Annotation 1.8.0 is out
|
||||
configurations.all {
|
||||
resolutionStrategy.force("androidx.annotation:annotation:1.8.0-rc01")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21)
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ import androidx.compose.ui.input.pointer.positionChange
|
||||
import androidx.compose.ui.input.pointer.util.VelocityTracker
|
||||
import androidx.compose.ui.input.pointer.util.addPointerInputChange
|
||||
import androidx.compose.ui.layout.layout
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.unit.Constraints
|
||||
@@ -364,8 +364,8 @@ fun ModalSideDrawer(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Modifier.onGloballyPositioned {
|
||||
val width = it.size.width
|
||||
Modifier.onSizeChanged {
|
||||
val width = it.width
|
||||
if (width != 0) {
|
||||
maxValue = width.toFloat()
|
||||
drawerState.anchoredDraggableState.updateAnchors(
|
||||
|
||||
@@ -77,6 +77,7 @@ import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.runtime.currentCompositeKeyHash
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@@ -93,6 +94,7 @@ import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalViewConfiguration
|
||||
@@ -370,13 +372,15 @@ class MainActivity : EhActivity() {
|
||||
},
|
||||
) {
|
||||
LocalTouchSlopProvider(Settings.touchSlopFactor.toFloat()) {
|
||||
// TODO: Correctly calculate it after https://android-review.googlesource.com/3017366
|
||||
val minOffset = -with(density) { DrawerDefaults.MaximumDrawerWidth.toPx() }
|
||||
var minOffset by remember {
|
||||
mutableFloatStateOf(-with(density) { DrawerDefaults.MaximumDrawerWidth.toPx() })
|
||||
}
|
||||
ModalNavigationDrawer(
|
||||
drawerContent = {
|
||||
ModalDrawerSheet(
|
||||
drawerState = navDrawerState,
|
||||
modifier = Modifier.widthIn(max = (configuration.screenWidthDp - 56).dp),
|
||||
modifier = Modifier.widthIn(max = (configuration.screenWidthDp - 56).dp)
|
||||
.onSizeChanged { minOffset = -it.width.toFloat() },
|
||||
windowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Start),
|
||||
) {
|
||||
val scrollState = rememberScrollState()
|
||||
@@ -425,7 +429,7 @@ class MainActivity : EhActivity() {
|
||||
ModalDrawerSheet(
|
||||
modifier = Modifier.widthIn(max = (configuration.screenWidthDp - 112).dp),
|
||||
drawerShape = ShapeDefaults.Large.copy(topEnd = CornerSize(0), bottomEnd = CornerSize(0)),
|
||||
windowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Vertical + WindowInsetsSides.End),
|
||||
windowInsets = WindowInsets.systemBars.only(WindowInsetsSides.Top + WindowInsetsSides.End),
|
||||
) {
|
||||
CompositionLocalProvider(LocalViewConfiguration provides viewConfiguration) {
|
||||
sheet(sideSheetState)
|
||||
|
||||
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
@@ -25,19 +26,24 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ShapeDefaults
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.pulltorefresh.PullToRefreshState
|
||||
import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults
|
||||
import androidx.compose.material3.pulltorefresh.pullToRefresh
|
||||
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.paging.LoadState
|
||||
@@ -54,7 +60,10 @@ import com.hippo.ehviewer.ui.screen.collectDetailSizeAsState
|
||||
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalGrid
|
||||
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalStaggeredGrid
|
||||
import com.hippo.ehviewer.util.displayString
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Stable
|
||||
operator fun PaddingValues.plus(r: PaddingValues) = object : PaddingValues {
|
||||
@@ -65,6 +74,7 @@ operator fun PaddingValues.plus(r: PaddingValues) = object : PaddingValues {
|
||||
override fun calculateTopPadding() = l.calculateTopPadding() + r.calculateTopPadding()
|
||||
}
|
||||
|
||||
context(CoroutineScope)
|
||||
@Composable
|
||||
fun GalleryList(
|
||||
modifier: Modifier = Modifier,
|
||||
@@ -76,20 +86,41 @@ fun GalleryList(
|
||||
detailItemContent: @Composable (LazyGridItemScope.(BaseGalleryInfo) -> Unit),
|
||||
thumbListState: LazyStaggeredGridState = rememberLazyStaggeredGridState(),
|
||||
thumbItemContent: @Composable (LazyStaggeredGridItemScope.(BaseGalleryInfo) -> Unit),
|
||||
refreshState: PullToRefreshState,
|
||||
searchBarOffsetY: () -> Int,
|
||||
scrollToTopOnRefresh: Boolean = true,
|
||||
onRefresh: () -> Unit,
|
||||
onLoading: () -> Unit,
|
||||
) {
|
||||
val marginH = dimensionResource(id = R.dimen.gallery_list_margin_h)
|
||||
val marginV = dimensionResource(id = R.dimen.gallery_list_margin_v)
|
||||
val combinedModifier = contentModifier.nestedScroll(refreshState.nestedScrollConnection)
|
||||
Box(modifier = modifier.fillMaxSize()) {
|
||||
|
||||
var isRefreshing by remember { mutableStateOf(false) }
|
||||
val refreshState = rememberPullToRefreshState()
|
||||
Box(
|
||||
modifier = modifier.fillMaxSize().pullToRefresh(
|
||||
isRefreshing = isRefreshing,
|
||||
state = refreshState,
|
||||
enabled = { data.loadState.refresh is LoadState.NotLoading },
|
||||
) {
|
||||
isRefreshing = true
|
||||
launch {
|
||||
if (data.loadState.prepend.endOfPaginationReached) {
|
||||
onRefresh()
|
||||
} else {
|
||||
data.retry()
|
||||
}
|
||||
snapshotFlow { data.loadState }.drop(1).first { state ->
|
||||
state.prepend !is LoadState.Loading && state.refresh !is LoadState.Loading
|
||||
}
|
||||
isRefreshing = false
|
||||
}
|
||||
},
|
||||
) {
|
||||
if (listMode == 0) {
|
||||
val columnWidth by collectDetailSizeAsState()
|
||||
FastScrollLazyVerticalGrid(
|
||||
columns = GridCells.Adaptive(columnWidth),
|
||||
modifier = combinedModifier,
|
||||
modifier = contentModifier,
|
||||
state = detailListState,
|
||||
contentPadding = contentPadding + PaddingValues(marginH, marginV),
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.gallery_list_interval)),
|
||||
@@ -118,7 +149,7 @@ fun GalleryList(
|
||||
val thumbColumns by Settings.thumbColumns.collectAsState()
|
||||
FastScrollLazyVerticalStaggeredGrid(
|
||||
columns = StaggeredGridCells.Fixed(thumbColumns),
|
||||
modifier = combinedModifier,
|
||||
modifier = contentModifier,
|
||||
state = thumbListState,
|
||||
verticalItemSpacing = gridInterval,
|
||||
horizontalArrangement = Arrangement.spacedBy(gridInterval),
|
||||
@@ -144,23 +175,8 @@ fun GalleryList(
|
||||
}
|
||||
}
|
||||
|
||||
if (refreshState.isRefreshing) {
|
||||
LaunchedEffect(Unit) {
|
||||
if (data.loadState.prepend.endOfPaginationReached) {
|
||||
onRefresh()
|
||||
} else {
|
||||
data.retry()
|
||||
}
|
||||
snapshotFlow { data.loadState }.drop(1).collect { state ->
|
||||
if (state.prepend !is LoadState.Loading && state.refresh !is LoadState.Loading) {
|
||||
refreshState.endRefresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when (val state = data.loadState.refresh) {
|
||||
is LoadState.Loading -> if (!refreshState.isRefreshing && scrollToTopOnRefresh) {
|
||||
is LoadState.Loading -> if (!isRefreshing && scrollToTopOnRefresh) {
|
||||
LaunchedEffect(Unit) {
|
||||
onLoading()
|
||||
}
|
||||
@@ -195,6 +211,13 @@ fun GalleryList(
|
||||
ErrorTip(modifier = Modifier.widthIn(max = 228.dp), text = stringResource(id = R.string.gallery_list_empty_hit))
|
||||
}
|
||||
}
|
||||
|
||||
PullToRefreshDefaults.Indicator(
|
||||
state = refreshState,
|
||||
isRefreshing = isRefreshing,
|
||||
modifier = Modifier.align(Alignment.TopCenter).padding(top = contentPadding.calculateTopPadding())
|
||||
.offset { IntOffset(0, searchBarOffsetY()) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ package com.hippo.ehviewer.ui.main
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
@@ -74,16 +74,12 @@ fun SearchFilter(
|
||||
fun isCategoryChecked(bit: Int) = category and bit != 0
|
||||
val categories = remember(category) { categoryTable.sortedBy { !isCategoryChecked(it.first) } }
|
||||
LazyRow(
|
||||
// Workaround for https://issuetracker.google.com/332939169
|
||||
// contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp),
|
||||
modifier = Modifier.padding(top = 8.dp),
|
||||
contentPadding = PaddingValues(start = 8.dp, top = 8.dp, end = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
// Workaround for the first item's animation
|
||||
// https://github.com/Calvin-LL/Reorderable/issues/4#issuecomment-1853131769
|
||||
item {
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
}
|
||||
item {}
|
||||
items(categories, { it.first }) {
|
||||
FilterChip(
|
||||
selected = isCategoryChecked(it.first),
|
||||
@@ -92,9 +88,6 @@ fun SearchFilter(
|
||||
modifier = Modifier.thenIf(animateItems) { animateItem() },
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
}
|
||||
}
|
||||
var languageFilter by Settings.languageFilter.asMutableState()
|
||||
val languages = remember {
|
||||
|
||||
@@ -5,9 +5,12 @@ import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
import androidx.compose.foundation.layout.statusBarsIgnoringVisibility
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.safeDrawing
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.material3.BottomSheetDefaults
|
||||
@@ -102,8 +105,9 @@ fun ReaderScreen(info: BaseGalleryInfo, page: Int = -1, navigator: DestinationsN
|
||||
val state = rememberModalBottomSheetState()
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = { dispose() },
|
||||
modifier = Modifier.windowInsetsPadding(WindowInsets.safeDrawing.only(WindowInsetsSides.Top)),
|
||||
sheetState = state,
|
||||
windowInsets = WindowInsets.statusBarsIgnoringVisibility,
|
||||
contentWindowInsets = { WindowInsets(0) },
|
||||
) {
|
||||
ReaderPageSheetMeta(
|
||||
retry = { pageLoader.retryPage(page.index) },
|
||||
@@ -170,10 +174,11 @@ fun ReaderScreen(info: BaseGalleryInfo, page: Int = -1, navigator: DestinationsN
|
||||
)
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = { dispose() },
|
||||
modifier = Modifier.windowInsetsPadding(WindowInsets.safeDrawing.only(WindowInsetsSides.Top)),
|
||||
// Yeah, I know color state should not be read here, but we have to do it...
|
||||
scrimColor = scrim,
|
||||
dragHandle = null,
|
||||
windowInsets = WindowInsets.statusBarsIgnoringVisibility,
|
||||
contentWindowInsets = { WindowInsets(0) },
|
||||
) {
|
||||
SettingsPager(modifier = Modifier.fillMaxSize()) { page ->
|
||||
isColorFilter = page == 2
|
||||
|
||||
@@ -12,9 +12,13 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
@@ -299,8 +303,7 @@ fun DownloadsScreen(navigator: DestinationsNavigator) = composing(navigator) {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
state = labelsListState,
|
||||
// Workaround for https://issuetracker.google.com/332939169
|
||||
// contentPadding = WindowInsets.systemBars.only(WindowInsetsSides.Bottom).asPaddingValues(),
|
||||
contentPadding = WindowInsets.systemBars.only(WindowInsetsSides.Bottom).asPaddingValues(),
|
||||
) {
|
||||
item {
|
||||
ListItem(
|
||||
|
||||
@@ -27,7 +27,6 @@ import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
@@ -47,7 +46,6 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.paging.LoadState
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingSource
|
||||
@@ -212,10 +210,6 @@ fun FavouritesScreen(navigator: DestinationsNavigator) = composing(navigator) {
|
||||
}
|
||||
}
|
||||
|
||||
val refreshState = rememberPullToRefreshState {
|
||||
data.loadState.refresh is LoadState.NotLoading
|
||||
}
|
||||
|
||||
var fabExpanded by remember { mutableStateOf(false) }
|
||||
var fabHidden by remember { mutableStateOf(false) }
|
||||
val checkedInfoMap = remember { mutableStateMapOf<Long, BaseGalleryInfo>() }
|
||||
@@ -231,7 +225,6 @@ fun FavouritesScreen(navigator: DestinationsNavigator) = composing(navigator) {
|
||||
fabHidden = true
|
||||
},
|
||||
onSearchHidden = { fabHidden = false },
|
||||
refreshState = refreshState,
|
||||
tagNamespace = !isLocalFav,
|
||||
searchBarOffsetY = { searchBarOffsetY },
|
||||
trailingIcon = {
|
||||
@@ -320,7 +313,7 @@ fun FavouritesScreen(navigator: DestinationsNavigator) = composing(navigator) {
|
||||
)
|
||||
}
|
||||
},
|
||||
refreshState = refreshState,
|
||||
searchBarOffsetY = { searchBarOffsetY },
|
||||
scrollToTopOnRefresh = urlBuilder.favCat != FavListUrlBuilder.FAV_CAT_LOCAL,
|
||||
onRefresh = { refresh() },
|
||||
onLoading = { searchBarOffsetY = 0 },
|
||||
|
||||
@@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
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
|
||||
@@ -41,8 +40,7 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.pulltorefresh.PullToRefreshContainer
|
||||
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
|
||||
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -90,6 +88,7 @@ import com.hippo.ehviewer.ui.composing
|
||||
import com.hippo.ehviewer.ui.jumpToReaderByPage
|
||||
import com.hippo.ehviewer.ui.legacy.CoilImageGetter
|
||||
import com.hippo.ehviewer.ui.main.GalleryCommentCard
|
||||
import com.hippo.ehviewer.ui.main.plus
|
||||
import com.hippo.ehviewer.ui.openBrowser
|
||||
import com.hippo.ehviewer.ui.tools.animateFloatMergePredictiveBackAsState
|
||||
import com.hippo.ehviewer.ui.tools.normalizeSpan
|
||||
@@ -106,7 +105,6 @@ import com.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import kotlin.math.roundToInt
|
||||
@@ -279,20 +277,28 @@ fun GalleryCommentsScreen(gid: Long, navigator: DestinationsNavigator) = composi
|
||||
) { paddingValues ->
|
||||
val keylineMargin = dimensionResource(id = R.dimen.keyline_margin)
|
||||
var editTextMeasured by remember { mutableStateOf(MinimumContentPaddingEditText) }
|
||||
val refreshState = rememberPullToRefreshState()
|
||||
if (refreshState.isRefreshing) {
|
||||
LaunchedEffect(Unit) {
|
||||
runSuspendCatching {
|
||||
withIOContext { refreshComment(true) }
|
||||
var isRefreshing by remember { mutableStateOf(false) }
|
||||
PullToRefreshBox(
|
||||
isRefreshing = isRefreshing,
|
||||
onRefresh = {
|
||||
isRefreshing = true
|
||||
launchIO {
|
||||
runSuspendCatching {
|
||||
refreshComment(true)
|
||||
}
|
||||
isRefreshing = false
|
||||
}
|
||||
refreshState.endRefresh()
|
||||
}
|
||||
}
|
||||
Box(modifier = Modifier.fillMaxSize().imePadding().nestedScroll(refreshState.nestedScrollConnection)) {
|
||||
},
|
||||
modifier = Modifier.fillMaxSize().imePadding(),
|
||||
) {
|
||||
val additionalPadding = if (commenting) {
|
||||
editTextMeasured
|
||||
} else {
|
||||
0.dp
|
||||
if (!comments.hasMore) {
|
||||
MinimumContentPaddingEditText
|
||||
} else {
|
||||
0.dp
|
||||
}
|
||||
}
|
||||
val voteUpSucceed = stringResource(R.string.vote_up_successfully)
|
||||
val cancelVoteUpSucceed = stringResource(R.string.cancel_vote_up_successfully)
|
||||
@@ -302,14 +308,8 @@ fun GalleryCommentsScreen(gid: Long, navigator: DestinationsNavigator) = composi
|
||||
LazyColumn(
|
||||
modifier = Modifier.padding(horizontal = keylineMargin),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
contentPadding = PaddingValues(
|
||||
// top = paddingValues.calculateTopPadding(),
|
||||
bottom = paddingValues.calculateBottomPadding() + additionalPadding,
|
||||
),
|
||||
contentPadding = paddingValues + PaddingValues(bottom = additionalPadding),
|
||||
) {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(paddingValues.calculateTopPadding()))
|
||||
}
|
||||
items(
|
||||
items = comments.comments,
|
||||
key = { it.id },
|
||||
@@ -406,18 +406,8 @@ fun GalleryCommentsScreen(gid: Long, navigator: DestinationsNavigator) = composi
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Workaround for comment list lagging when reaching the bottom
|
||||
// https://github.com/FooIbar/EhViewer/issues/994
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(MinimumContentPaddingEditText))
|
||||
}
|
||||
}
|
||||
}
|
||||
PullToRefreshContainer(
|
||||
state = refreshState,
|
||||
modifier = Modifier.align(Alignment.TopCenter).padding(top = paddingValues.calculateTopPadding()),
|
||||
)
|
||||
Surface(
|
||||
modifier = Modifier.align(Alignment.BottomCenter).layout { measurable, constraints ->
|
||||
val origin = measurable.measure(constraints)
|
||||
|
||||
@@ -803,7 +803,7 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: DestinationsNa
|
||||
if (showBottomSheet && galleryDetail != null) {
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = { showBottomSheet = false },
|
||||
windowInsets = WindowInsets(0, 0, 0, 0),
|
||||
contentWindowInsets = { WindowInsets(0, 0, 0, 0) },
|
||||
) {
|
||||
GalleryInfoBottomSheet(galleryDetail, navigator)
|
||||
}
|
||||
|
||||
@@ -11,12 +11,16 @@ import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.calculateEndPadding
|
||||
import androidx.compose.foundation.layout.calculateStartPadding
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
@@ -34,6 +38,7 @@ import androidx.compose.material.icons.filled.Shuffle
|
||||
import androidx.compose.material.icons.outlined.Bookmarks
|
||||
import androidx.compose.material3.ElevatedCard
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.ListItem
|
||||
@@ -43,7 +48,6 @@ import androidx.compose.material3.SwipeToDismissBoxState
|
||||
import androidx.compose.material3.SwipeToDismissBoxValue
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.Stable
|
||||
@@ -76,7 +80,6 @@ import androidx.compose.ui.util.fastAny
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import androidx.compose.ui.util.lerp
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.paging.LoadState
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingSource
|
||||
@@ -373,11 +376,12 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) = c
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
state = quickSearchListState,
|
||||
// Workaround for https://issuetracker.google.com/332939169
|
||||
// contentPadding = WindowInsets.systemBars.only(WindowInsetsSides.Bottom).asPaddingValues(),
|
||||
contentPadding = WindowInsets.systemBars.only(WindowInsetsSides.Bottom).asPaddingValues(),
|
||||
) {
|
||||
// Fix the first item's reorder animation
|
||||
item {}
|
||||
stickyHeader {
|
||||
HorizontalDivider()
|
||||
}
|
||||
itemsIndexed(quickSearchList, key = { _, item -> item.id!! }) { index, item ->
|
||||
ReorderableItem(reorderableLazyListState, key = item.id!!) { isDragging ->
|
||||
// Not using rememberSwipeToDismissBoxState to prevent LazyColumn from reusing it
|
||||
@@ -468,10 +472,6 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) = c
|
||||
}
|
||||
}
|
||||
|
||||
val refreshState = rememberPullToRefreshState {
|
||||
data.loadState.refresh is LoadState.NotLoading
|
||||
}
|
||||
|
||||
var fabExpanded by remember { mutableStateOf(false) }
|
||||
var fabHidden by remember { mutableStateOf(false) }
|
||||
|
||||
@@ -537,7 +537,6 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) = c
|
||||
onApplySearch = ::onApplySearch,
|
||||
onSearchExpanded = { fabHidden = true },
|
||||
onSearchHidden = { fabHidden = false },
|
||||
refreshState = refreshState,
|
||||
suggestionProvider = {
|
||||
GalleryDetailUrlParser.parse(it, false)?.run {
|
||||
GalleryDetailUrlSuggestion(gid, token)
|
||||
@@ -677,7 +676,7 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) = c
|
||||
info = info,
|
||||
)
|
||||
},
|
||||
refreshState = refreshState,
|
||||
searchBarOffsetY = { searchBarOffsetY },
|
||||
onRefresh = {
|
||||
urlBuilder.setRange(0)
|
||||
data.refresh()
|
||||
|
||||
@@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.displayCutoutPadding
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
@@ -16,8 +17,6 @@ import androidx.compose.foundation.layout.ime
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.layout.union
|
||||
@@ -44,8 +43,6 @@ import androidx.compose.material3.SearchBarDefaults
|
||||
import androidx.compose.material3.SearchBarHorizontalPadding
|
||||
import androidx.compose.material3.SearchBarInputField
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.pulltorefresh.PullToRefreshContainer
|
||||
import androidx.compose.material3.pulltorefresh.PullToRefreshState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -110,7 +107,6 @@ fun SearchBarScreen(
|
||||
onApplySearch: (String) -> Unit,
|
||||
onSearchExpanded: () -> Unit,
|
||||
onSearchHidden: () -> Unit,
|
||||
refreshState: PullToRefreshState? = null,
|
||||
suggestionProvider: SuggestionProvider? = null,
|
||||
tagNamespace: Boolean = false,
|
||||
searchBarOffsetY: () -> Int,
|
||||
@@ -222,12 +218,6 @@ fun SearchBarScreen(
|
||||
}
|
||||
}
|
||||
|
||||
val scrollAwayModifier = if (!expanded) {
|
||||
Modifier.offset { IntOffset(0, searchBarOffsetY()) }
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
|
||||
BoxWithConstraints(modifier = Modifier.fillMaxSize()) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
@@ -240,13 +230,6 @@ fun SearchBarScreen(
|
||||
floatingActionButton = floatingActionButton,
|
||||
content = content,
|
||||
)
|
||||
if (refreshState != null) {
|
||||
PullToRefreshContainer(
|
||||
state = refreshState,
|
||||
modifier = Modifier.align(Alignment.TopCenter).safeDrawingPadding()
|
||||
.padding(top = 48.dp) then scrollAwayModifier,
|
||||
)
|
||||
}
|
||||
// https://issuetracker.google.com/337191298
|
||||
// Workaround for can't exit SearchBar due to refocus in non-touch mode
|
||||
Box(Modifier.size(1.dp).focusable())
|
||||
@@ -260,7 +243,7 @@ fun SearchBarScreen(
|
||||
}
|
||||
val activeState = rememberCompositionActiveState()
|
||||
SearchBar(
|
||||
modifier = Modifier.align(Alignment.TopCenter) then scrollAwayModifier
|
||||
modifier = Modifier.align(Alignment.TopCenter).thenIf(!expanded) { offset { IntOffset(0, searchBarOffsetY()) } }
|
||||
.windowInsetsPadding(WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal)),
|
||||
inputField = {
|
||||
SearchBarInputField(
|
||||
@@ -312,11 +295,9 @@ fun SearchBarScreen(
|
||||
activeState.Anchor()
|
||||
filter?.invoke()
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
.windowInsetsPadding(WindowInsets.navigationBars.union(WindowInsets.ime).only(WindowInsetsSides.Bottom)),
|
||||
// Workaround for https://issuetracker.google.com/332939169
|
||||
// contentPadding = WindowInsets.navigationBars.union(WindowInsets.ime)
|
||||
// .only(WindowInsetsSides.Bottom).asPaddingValues(),
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentPadding = WindowInsets.navigationBars.union(WindowInsets.ime)
|
||||
.only(WindowInsetsSides.Bottom).asPaddingValues(),
|
||||
) {
|
||||
// Workaround for prepending before the first item
|
||||
item {}
|
||||
|
||||
@@ -215,9 +215,8 @@ fun FilterScreen(navigator: DestinationsNavigator) {
|
||||
) { paddingValues ->
|
||||
Deferred({ allFilterMap.await() }) { filters ->
|
||||
LazyColumn(
|
||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection).padding(paddingValues),
|
||||
// Workaround for https://issuetracker.google.com/332939169
|
||||
// contentPadding = paddingValues,
|
||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
contentPadding = paddingValues,
|
||||
) {
|
||||
var showTip = true
|
||||
filters.forEach { (filterMode, filters) ->
|
||||
|
||||
@@ -44,8 +44,11 @@ import androidx.annotation.StringRes
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.statusBarsIgnoringVisibility
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.safeDrawing
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.material3.BottomSheetDefaults
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -315,10 +318,11 @@ class ReaderActivity : EhActivity() {
|
||||
)
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = { dispose() },
|
||||
modifier = Modifier.windowInsetsPadding(WindowInsets.safeDrawing.only(WindowInsetsSides.Top)),
|
||||
dragHandle = null,
|
||||
// Yeah, I know color state should not be read here, but we have to do it...
|
||||
scrimColor = scrim,
|
||||
windowInsets = WindowInsets.statusBarsIgnoringVisibility,
|
||||
contentWindowInsets = { WindowInsets(0) },
|
||||
) {
|
||||
SettingsPager(modifier = Modifier.fillMaxSize()) { page ->
|
||||
isColorFilter = page == 2
|
||||
@@ -648,7 +652,8 @@ class ReaderActivity : EhActivity() {
|
||||
dialogState.dialog {
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = { it.cancel() },
|
||||
windowInsets = WindowInsets.statusBarsIgnoringVisibility,
|
||||
modifier = Modifier.windowInsetsPadding(WindowInsets.safeDrawing.only(WindowInsetsSides.Top)),
|
||||
contentWindowInsets = { WindowInsets(0) },
|
||||
) {
|
||||
ReaderPageSheet(page) { it.cancel() }
|
||||
}
|
||||
|
||||
@@ -67,9 +67,9 @@ coil-gif = { module = "io.coil-kt.coil3:coil-gif" }
|
||||
coil-network = { module = "io.coil-kt.coil3:coil-network-ktor" }
|
||||
|
||||
compose-bom = { module = "dev.chrisbanes.compose:compose-bom", version.ref = "compose-bom" }
|
||||
compose-foundation = { module = "androidx.compose.foundation:foundation" }
|
||||
compose-foundation = { module = "androidx.compose.foundation:foundation", version = "1.7.0-SNAPSHOT" }
|
||||
compose-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" }
|
||||
compose-material3 = { module = "androidx.compose.material3:material3" }
|
||||
compose-material3 = { module = "androidx.compose.material3:material3", version = "1.3.0-SNAPSHOT" }
|
||||
compose-material3-windowsizeclass = { module = "androidx.compose.material3:material3-window-size-class" }
|
||||
compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
|
||||
compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
|
||||
|
||||
@@ -12,6 +12,8 @@ dependencyResolutionManagement {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven("https://jitpack.io")
|
||||
// TODO: Remove on Compose 1.7.0-beta01
|
||||
maven("https://androidx.dev/snapshots/builds/11800816/artifacts/repository")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user