Migrate Accompanist SwipeRefresh to Compose PullRefresh (#8106)
This commit is contained in:
parent
6ca32710be
commit
2c4ddca38e
9 changed files with 66 additions and 59 deletions
|
@ -179,7 +179,6 @@ dependencies {
|
||||||
implementation(compose.ui.tooling)
|
implementation(compose.ui.tooling)
|
||||||
implementation(compose.ui.util)
|
implementation(compose.ui.util)
|
||||||
implementation(compose.accompanist.webview)
|
implementation(compose.accompanist.webview)
|
||||||
implementation(compose.accompanist.swiperefresh)
|
|
||||||
implementation(compose.accompanist.flowlayout)
|
implementation(compose.accompanist.flowlayout)
|
||||||
implementation(compose.accompanist.permissions)
|
implementation(compose.accompanist.permissions)
|
||||||
implementation(compose.accompanist.themeadapter)
|
implementation(compose.accompanist.themeadapter)
|
||||||
|
@ -325,6 +324,7 @@ tasks {
|
||||||
"-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi",
|
"-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi",
|
||||||
"-opt-in=androidx.compose.material.ExperimentalMaterialApi",
|
"-opt-in=androidx.compose.material.ExperimentalMaterialApi",
|
||||||
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api",
|
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api",
|
||||||
|
"-opt-in=androidx.compose.material.ExperimentalMaterialApi",
|
||||||
"-opt-in=androidx.compose.ui.ExperimentalComposeUiApi",
|
"-opt-in=androidx.compose.ui.ExperimentalComposeUiApi",
|
||||||
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
|
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
|
||||||
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
|
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
|
||||||
|
|
|
@ -40,7 +40,7 @@ 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.SwipeRefresh
|
import eu.kanade.presentation.components.PullRefresh
|
||||||
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.padding
|
import eu.kanade.presentation.util.padding
|
||||||
|
@ -68,7 +68,7 @@ fun ExtensionScreen(
|
||||||
onClickUpdateAll: () -> Unit,
|
onClickUpdateAll: () -> Unit,
|
||||||
onRefresh: () -> Unit,
|
onRefresh: () -> Unit,
|
||||||
) {
|
) {
|
||||||
SwipeRefresh(
|
PullRefresh(
|
||||||
refreshing = state.isRefreshing,
|
refreshing = state.isRefreshing,
|
||||||
onRefresh = onRefresh,
|
onRefresh = onRefresh,
|
||||||
enabled = !state.isLoading,
|
enabled = !state.isLoading,
|
||||||
|
|
|
@ -309,7 +309,7 @@ private fun Modifier.selectedOutline(
|
||||||
}
|
}
|
||||||
|
|
||||||
return this then modifierElementOf(
|
return this then modifierElementOf(
|
||||||
params = isSelected.hashCode() + color.hashCode(),
|
key = isSelected.hashCode() + color.hashCode(),
|
||||||
create = { SelectedOutlineNode(isSelected, color) },
|
create = { SelectedOutlineNode(isSelected, color) },
|
||||||
update = {
|
update = {
|
||||||
it.selected = isSelected
|
it.selected = isSelected
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package eu.kanade.presentation.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||||
|
import androidx.compose.material.pullrefresh.pullRefresh
|
||||||
|
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clipToBounds
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Code reference: [Accompanist SwipeRefresh](https://github.com/google/accompanist/blob/677bc4ca0ee74677a8ba73793d04d85fe4ab55fb/swiperefresh/src/main/java/com/google/accompanist/swiperefresh/SwipeRefresh.kt#L265-L283)
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun PullRefresh(
|
||||||
|
refreshing: Boolean,
|
||||||
|
onRefresh: () -> Unit,
|
||||||
|
enabled: Boolean,
|
||||||
|
indicatorPadding: PaddingValues = PaddingValues(0.dp),
|
||||||
|
content: @Composable () -> Unit,
|
||||||
|
) {
|
||||||
|
val state = rememberPullRefreshState(
|
||||||
|
refreshing = refreshing,
|
||||||
|
onRefresh = onRefresh,
|
||||||
|
)
|
||||||
|
|
||||||
|
Box(Modifier.pullRefresh(state, enabled)) {
|
||||||
|
content()
|
||||||
|
|
||||||
|
Box(
|
||||||
|
Modifier
|
||||||
|
.padding(indicatorPadding)
|
||||||
|
.matchParentSize()
|
||||||
|
.clipToBounds(),
|
||||||
|
) {
|
||||||
|
PullRefreshIndicator(
|
||||||
|
refreshing = refreshing,
|
||||||
|
state = state,
|
||||||
|
modifier = Modifier.align(Alignment.TopCenter),
|
||||||
|
backgroundColor = MaterialTheme.colorScheme.primary,
|
||||||
|
contentColor = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
package eu.kanade.presentation.components
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.unit.Dp
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.google.accompanist.swiperefresh.SwipeRefreshState
|
|
||||||
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
|
|
||||||
import com.google.accompanist.swiperefresh.SwipeRefreshIndicator as AccompanistSwipeRefreshIndicator
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SwipeRefreshIndicator(
|
|
||||||
state: SwipeRefreshState,
|
|
||||||
refreshTriggerDistance: Dp,
|
|
||||||
refreshingOffset: Dp = 16.dp,
|
|
||||||
) {
|
|
||||||
AccompanistSwipeRefreshIndicator(
|
|
||||||
state = state,
|
|
||||||
refreshTriggerDistance = refreshTriggerDistance,
|
|
||||||
backgroundColor = MaterialTheme.colorScheme.primary,
|
|
||||||
contentColor = MaterialTheme.colorScheme.onPrimary,
|
|
||||||
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) },
|
|
||||||
) {
|
|
||||||
content()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,7 +18,7 @@ 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.SwipeRefresh
|
import eu.kanade.presentation.components.PullRefresh
|
||||||
import eu.kanade.presentation.components.rememberPagerState
|
import eu.kanade.presentation.components.rememberPagerState
|
||||||
import eu.kanade.tachiyomi.ui.library.LibraryItem
|
import eu.kanade.tachiyomi.ui.library.LibraryItem
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
@ -79,11 +79,11 @@ fun LibraryContent(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SwipeRefresh(
|
PullRefresh(
|
||||||
refreshing = isRefreshing,
|
refreshing = isRefreshing,
|
||||||
onRefresh = {
|
onRefresh = {
|
||||||
val started = onRefresh(categories[currentPage()])
|
val started = onRefresh(categories[currentPage()])
|
||||||
if (!started) return@SwipeRefresh
|
if (!started) return@PullRefresh
|
||||||
scope.launch {
|
scope.launch {
|
||||||
// Fake refresh status but hide it after a second as it's a long running task
|
// Fake refresh status but hide it after a second as it's a long running task
|
||||||
isRefreshing = true
|
isRefreshing = true
|
||||||
|
|
|
@ -51,8 +51,8 @@ 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.PullRefresh
|
||||||
import eu.kanade.presentation.components.Scaffold
|
import eu.kanade.presentation.components.Scaffold
|
||||||
import eu.kanade.presentation.components.SwipeRefresh
|
|
||||||
import eu.kanade.presentation.components.TwoPanelBox
|
import eu.kanade.presentation.components.TwoPanelBox
|
||||||
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
|
||||||
|
@ -287,7 +287,7 @@ private fun MangaScreenSmallImpl(
|
||||||
) { contentPadding ->
|
) { contentPadding ->
|
||||||
val topPadding = contentPadding.calculateTopPadding()
|
val topPadding = contentPadding.calculateTopPadding()
|
||||||
|
|
||||||
SwipeRefresh(
|
PullRefresh(
|
||||||
refreshing = state.isRefreshingData,
|
refreshing = state.isRefreshingData,
|
||||||
onRefresh = onRefresh,
|
onRefresh = onRefresh,
|
||||||
enabled = chapters.fastAll { !it.selected },
|
enabled = chapters.fastAll { !it.selected },
|
||||||
|
@ -421,7 +421,7 @@ fun MangaScreenLargeImpl(
|
||||||
|
|
||||||
val insetPadding = WindowInsets.systemBars.only(WindowInsetsSides.Horizontal).asPaddingValues()
|
val insetPadding = WindowInsets.systemBars.only(WindowInsetsSides.Horizontal).asPaddingValues()
|
||||||
var topBarHeight by remember { mutableStateOf(0) }
|
var topBarHeight by remember { mutableStateOf(0) }
|
||||||
SwipeRefresh(
|
PullRefresh(
|
||||||
refreshing = state.isRefreshingData,
|
refreshing = state.isRefreshingData,
|
||||||
onRefresh = onRefresh,
|
onRefresh = onRefresh,
|
||||||
enabled = chapters.fastAll { !it.selected },
|
enabled = chapters.fastAll { !it.selected },
|
||||||
|
|
|
@ -29,8 +29,8 @@ 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.MangaBottomActionMenu
|
import eu.kanade.presentation.components.MangaBottomActionMenu
|
||||||
|
import eu.kanade.presentation.components.PullRefresh
|
||||||
import eu.kanade.presentation.components.Scaffold
|
import eu.kanade.presentation.components.Scaffold
|
||||||
import eu.kanade.presentation.components.SwipeRefresh
|
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.download.model.Download
|
import eu.kanade.tachiyomi.data.download.model.Download
|
||||||
import eu.kanade.tachiyomi.ui.updates.UpdatesItem
|
import eu.kanade.tachiyomi.ui.updates.UpdatesItem
|
||||||
|
@ -96,11 +96,11 @@ fun UpdateScreen(
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
var isRefreshing by remember { mutableStateOf(false) }
|
var isRefreshing by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
SwipeRefresh(
|
PullRefresh(
|
||||||
refreshing = isRefreshing,
|
refreshing = isRefreshing,
|
||||||
onRefresh = {
|
onRefresh = {
|
||||||
val started = onUpdateLibrary()
|
val started = onUpdateLibrary()
|
||||||
if (!started) return@SwipeRefresh
|
if (!started) return@PullRefresh
|
||||||
scope.launch {
|
scope.launch {
|
||||||
// Fake refresh status but hide it after a second as it's a long running task
|
// Fake refresh status but hide it after a second as it's a long running task
|
||||||
isRefreshing = true
|
isRefreshing = true
|
||||||
|
|
|
@ -16,10 +16,11 @@ material3-core = { module = "androidx.compose.material3:material3" }
|
||||||
material-icons = { module = "androidx.compose.material:material-icons-extended" }
|
material-icons = { module = "androidx.compose.material:material-icons-extended" }
|
||||||
|
|
||||||
# Here until M3's swipeable became public https://issuetracker.google.com/issues/234640556
|
# Here until M3's swipeable became public https://issuetracker.google.com/issues/234640556
|
||||||
material-core = { module = "androidx.compose.material:material" }
|
# Using alpha version for PullRefresh fix
|
||||||
|
# TODO: use default version after next Compose BOM is released
|
||||||
|
material-core = { module = "androidx.compose.material:material", version = "1.4.0-alpha03" }
|
||||||
|
|
||||||
accompanist-webview = { module = "com.google.accompanist:accompanist-webview", version.ref = "accompanist" }
|
accompanist-webview = { module = "com.google.accompanist:accompanist-webview", version.ref = "accompanist" }
|
||||||
accompanist-swiperefresh = { module = "com.google.accompanist:accompanist-swiperefresh", version.ref = "accompanist" }
|
|
||||||
accompanist-flowlayout = { module = "com.google.accompanist:accompanist-flowlayout", version.ref = "accompanist" }
|
accompanist-flowlayout = { module = "com.google.accompanist:accompanist-flowlayout", version.ref = "accompanist" }
|
||||||
accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" }
|
accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" }
|
||||||
accompanist-themeadapter = { module = "com.google.accompanist:accompanist-themeadapter-material3", version.ref = "accompanist" }
|
accompanist-themeadapter = { module = "com.google.accompanist:accompanist-themeadapter-material3", version.ref = "accompanist" }
|
Reference in a new issue