Refactor SwipeRefresh and fix some issues (#8169)

This commit is contained in:
stevenyomi 2022-10-09 23:20:43 +08:00 committed by GitHub
parent 737d0fb8f3
commit 404f53b16b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 46 deletions

View File

@ -37,14 +37,12 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.google.accompanist.flowlayout.FlowRow import com.google.accompanist.flowlayout.FlowRow
import com.google.accompanist.swiperefresh.SwipeRefresh
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import eu.kanade.presentation.browse.components.BaseBrowseItem import eu.kanade.presentation.browse.components.BaseBrowseItem
import eu.kanade.presentation.browse.components.ExtensionIcon import eu.kanade.presentation.browse.components.ExtensionIcon
import eu.kanade.presentation.components.EmptyScreen import eu.kanade.presentation.components.EmptyScreen
import eu.kanade.presentation.components.FastScrollLazyColumn import eu.kanade.presentation.components.FastScrollLazyColumn
import eu.kanade.presentation.components.LoadingScreen import eu.kanade.presentation.components.LoadingScreen
import eu.kanade.presentation.components.SwipeRefreshIndicator import eu.kanade.presentation.components.SwipeRefresh
import eu.kanade.presentation.manga.components.DotSeparatorNoSpaceText import eu.kanade.presentation.manga.components.DotSeparatorNoSpaceText
import eu.kanade.presentation.theme.header import eu.kanade.presentation.theme.header
import eu.kanade.presentation.util.horizontalPadding import eu.kanade.presentation.util.horizontalPadding
@ -73,9 +71,9 @@ fun ExtensionScreen(
onRefresh: () -> Unit, onRefresh: () -> Unit,
) { ) {
SwipeRefresh( SwipeRefresh(
state = rememberSwipeRefreshState(presenter.isRefreshing), refreshing = presenter.isRefreshing,
indicator = { s, trigger -> SwipeRefreshIndicator(s, trigger) },
onRefresh = onRefresh, onRefresh = onRefresh,
enabled = !presenter.isLoading,
) { ) {
when { when {
presenter.isLoading -> LoadingScreen() presenter.isLoading -> LoadingScreen()

View File

@ -1,10 +1,15 @@
package eu.kanade.presentation.components package eu.kanade.presentation.components
import android.os.Build
import androidx.compose.foundation.LocalOverscrollConfiguration
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.google.accompanist.swiperefresh.SwipeRefreshState import com.google.accompanist.swiperefresh.SwipeRefreshState
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import com.google.accompanist.swiperefresh.SwipeRefreshIndicator as AccompanistSwipeRefreshIndicator import com.google.accompanist.swiperefresh.SwipeRefreshIndicator as AccompanistSwipeRefreshIndicator
@Composable @Composable
@ -21,3 +26,30 @@ fun SwipeRefreshIndicator(
refreshingOffset = refreshingOffset, refreshingOffset = refreshingOffset,
) )
} }
@Composable
fun SwipeRefresh(
refreshing: Boolean,
onRefresh: () -> Unit,
enabled: Boolean,
indicatorPadding: PaddingValues = PaddingValues(0.dp),
content: @Composable () -> Unit,
) {
com.google.accompanist.swiperefresh.SwipeRefresh(
state = rememberSwipeRefreshState(refreshing),
onRefresh = onRefresh,
swipeEnabled = enabled,
indicatorPadding = indicatorPadding,
indicator = { s, trigger -> SwipeRefreshIndicator(s, trigger) },
) {
// TODO: remove this workaround when A12 stretch overscroll works well with refreshing
// see https://github.com/tachiyomiorg/tachiyomi/issues/8168
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
CompositionLocalProvider(LocalOverscrollConfiguration provides null) {
content()
}
} else {
content()
}
}
}

View File

@ -17,14 +17,12 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.LocalUriHandler
import com.google.accompanist.pager.rememberPagerState import com.google.accompanist.pager.rememberPagerState
import com.google.accompanist.swiperefresh.SwipeRefresh
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import eu.kanade.core.prefs.PreferenceMutableState import eu.kanade.core.prefs.PreferenceMutableState
import eu.kanade.domain.category.model.Category import eu.kanade.domain.category.model.Category
import eu.kanade.domain.library.model.LibraryDisplayMode import eu.kanade.domain.library.model.LibraryDisplayMode
import eu.kanade.domain.library.model.LibraryManga import eu.kanade.domain.library.model.LibraryManga
import eu.kanade.presentation.components.EmptyScreen import eu.kanade.presentation.components.EmptyScreen
import eu.kanade.presentation.components.SwipeRefreshIndicator import eu.kanade.presentation.components.SwipeRefresh
import eu.kanade.presentation.library.LibraryState import eu.kanade.presentation.library.LibraryState
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.library.LibraryItem import eu.kanade.tachiyomi.ui.library.LibraryItem
@ -89,7 +87,7 @@ fun LibraryContent(
} }
SwipeRefresh( SwipeRefresh(
state = rememberSwipeRefreshState(isRefreshing = isRefreshing), refreshing = isRefreshing,
onRefresh = { onRefresh = {
val started = onRefresh(categories[currentPage()]) val started = onRefresh(categories[currentPage()])
if (!started) return@SwipeRefresh if (!started) return@SwipeRefresh
@ -100,12 +98,7 @@ fun LibraryContent(
isRefreshing = false isRefreshing = false
} }
}, },
indicator = { s, trigger -> enabled = state.selectionMode.not(),
SwipeRefreshIndicator(
state = s,
refreshTriggerDistance = trigger,
)
},
) { ) {
if (state.searchQuery.isNullOrEmpty() && isLibraryEmpty) { if (state.searchQuery.isNullOrEmpty() && isLibraryEmpty) {
val handler = LocalUriHandler.current val handler = LocalUriHandler.current

View File

@ -48,15 +48,13 @@ import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.google.accompanist.swiperefresh.SwipeRefresh
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import eu.kanade.domain.chapter.model.Chapter import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.presentation.components.ChapterDownloadAction import eu.kanade.presentation.components.ChapterDownloadAction
import eu.kanade.presentation.components.ExtendedFloatingActionButton import eu.kanade.presentation.components.ExtendedFloatingActionButton
import eu.kanade.presentation.components.LazyColumn import eu.kanade.presentation.components.LazyColumn
import eu.kanade.presentation.components.MangaBottomActionMenu import eu.kanade.presentation.components.MangaBottomActionMenu
import eu.kanade.presentation.components.Scaffold import eu.kanade.presentation.components.Scaffold
import eu.kanade.presentation.components.SwipeRefreshIndicator import eu.kanade.presentation.components.SwipeRefresh
import eu.kanade.presentation.components.VerticalFastScroller import eu.kanade.presentation.components.VerticalFastScroller
import eu.kanade.presentation.manga.components.ChapterHeader import eu.kanade.presentation.manga.components.ChapterHeader
import eu.kanade.presentation.manga.components.ExpandableMangaDescription import eu.kanade.presentation.manga.components.ExpandableMangaDescription
@ -290,16 +288,10 @@ private fun MangaScreenSmallImpl(
val topPadding = contentPadding.calculateTopPadding() val topPadding = contentPadding.calculateTopPadding()
SwipeRefresh( SwipeRefresh(
state = rememberSwipeRefreshState(state.isRefreshingData), refreshing = state.isRefreshingData,
onRefresh = onRefresh, onRefresh = onRefresh,
swipeEnabled = !chapters.any { it.selected }, enabled = chapters.none { it.selected },
indicatorPadding = contentPadding, indicatorPadding = contentPadding,
indicator = { s, trigger ->
SwipeRefreshIndicator(
state = s,
refreshTriggerDistance = trigger,
)
},
) { ) {
VerticalFastScroller( VerticalFastScroller(
listState = chapterListState, listState = chapterListState,
@ -425,21 +417,14 @@ fun MangaScreenLargeImpl(
val insetPadding = WindowInsets.systemBars.only(WindowInsetsSides.Horizontal).asPaddingValues() val insetPadding = WindowInsets.systemBars.only(WindowInsetsSides.Horizontal).asPaddingValues()
val (topBarHeight, onTopBarHeightChanged) = remember { mutableStateOf(0) } val (topBarHeight, onTopBarHeightChanged) = remember { mutableStateOf(0) }
SwipeRefresh( SwipeRefresh(
state = rememberSwipeRefreshState(state.isRefreshingData), refreshing = state.isRefreshingData,
onRefresh = onRefresh, onRefresh = onRefresh,
swipeEnabled = !chapters.any { it.selected }, enabled = chapters.none { it.selected },
indicatorPadding = PaddingValues( indicatorPadding = PaddingValues(
start = insetPadding.calculateStartPadding(layoutDirection), start = insetPadding.calculateStartPadding(layoutDirection),
top = with(density) { topBarHeight.toDp() }, top = with(density) { topBarHeight.toDp() },
end = insetPadding.calculateEndPadding(layoutDirection), end = insetPadding.calculateEndPadding(layoutDirection),
), ),
clipIndicatorToPadding = true,
indicator = { s, trigger ->
SwipeRefreshIndicator(
state = s,
refreshTriggerDistance = trigger,
)
},
) { ) {
val chapterListState = rememberLazyListState() val chapterListState = rememberLazyListState()

View File

@ -24,8 +24,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import com.google.accompanist.swiperefresh.SwipeRefresh
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.ChapterDownloadAction import eu.kanade.presentation.components.ChapterDownloadAction
import eu.kanade.presentation.components.EmptyScreen import eu.kanade.presentation.components.EmptyScreen
@ -33,7 +31,7 @@ import eu.kanade.presentation.components.LazyColumn
import eu.kanade.presentation.components.LoadingScreen import eu.kanade.presentation.components.LoadingScreen
import eu.kanade.presentation.components.MangaBottomActionMenu import eu.kanade.presentation.components.MangaBottomActionMenu
import eu.kanade.presentation.components.Scaffold import eu.kanade.presentation.components.Scaffold
import eu.kanade.presentation.components.SwipeRefreshIndicator import eu.kanade.presentation.components.SwipeRefresh
import eu.kanade.presentation.components.VerticalFastScroller import eu.kanade.presentation.components.VerticalFastScroller
import eu.kanade.presentation.util.plus import eu.kanade.presentation.util.plus
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
@ -130,7 +128,7 @@ private fun UpdateScreenContent(
var isRefreshing by remember { mutableStateOf(false) } var isRefreshing by remember { mutableStateOf(false) }
SwipeRefresh( SwipeRefresh(
state = rememberSwipeRefreshState(isRefreshing = isRefreshing), refreshing = isRefreshing,
onRefresh = { onRefresh = {
val started = onUpdateLibrary() val started = onUpdateLibrary()
if (!started) return@SwipeRefresh if (!started) return@SwipeRefresh
@ -141,14 +139,8 @@ private fun UpdateScreenContent(
isRefreshing = false isRefreshing = false
} }
}, },
swipeEnabled = presenter.selectionMode.not(), enabled = presenter.selectionMode.not(),
indicatorPadding = contentPaddingWithNavBar, indicatorPadding = contentPaddingWithNavBar,
indicator = { s, trigger ->
SwipeRefreshIndicator(
state = s,
refreshTriggerDistance = trigger,
)
},
) { ) {
if (presenter.uiModels.isEmpty()) { if (presenter.uiModels.isEmpty()) {
EmptyScreen(textResource = R.string.information_no_recent) EmptyScreen(textResource = R.string.information_no_recent)