refactor(feeds): collapse RefresheableBox overloads to a single PullToRefreshBox
The InvalidatableContent overload now delegates to the onRefresh overload, so there is only one PullToRefreshBox/state-management path to maintain. https://claude.ai/code/session_01MgnMaw8U83rXPSnoGF4KBY
This commit is contained in:
@@ -40,30 +40,14 @@ import com.vitorpamplona.amethyst.ui.layouts.LocalDisappearingScaffoldPadding
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RefresheableBox(
|
fun RefresheableBox(
|
||||||
invalidateableContent: InvalidatableContent,
|
invalidateableContent: InvalidatableContent,
|
||||||
enablePullRefresh: Boolean = true,
|
enablePullRefresh: Boolean = true,
|
||||||
content: @Composable BoxScope.() -> Unit,
|
content: @Composable BoxScope.() -> Unit,
|
||||||
) {
|
) {
|
||||||
var isRefreshing by remember { mutableStateOf(false) }
|
|
||||||
val scope = rememberCoroutineScope()
|
|
||||||
val onRefresh: () -> Unit = {
|
|
||||||
isRefreshing = true
|
|
||||||
scope.launch {
|
|
||||||
invalidateableContent.invalidateData()
|
|
||||||
delay(500)
|
|
||||||
isRefreshing = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enablePullRefresh) {
|
if (enablePullRefresh) {
|
||||||
PullToRefreshBoxWithScaffoldPadding(
|
RefresheableBox(onRefresh = invalidateableContent::invalidateData, content = content)
|
||||||
isRefreshing = isRefreshing,
|
|
||||||
onRefresh = onRefresh,
|
|
||||||
content = content,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Box(Modifier.fillMaxSize(), content = content)
|
Box(Modifier.fillMaxSize(), content = content)
|
||||||
}
|
}
|
||||||
@@ -77,44 +61,25 @@ fun RefresheableBox(
|
|||||||
) {
|
) {
|
||||||
var isRefreshing by remember { mutableStateOf(false) }
|
var isRefreshing by remember { mutableStateOf(false) }
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val onRefreshWrapped: () -> Unit = {
|
|
||||||
isRefreshing = true
|
|
||||||
scope.launch {
|
|
||||||
onRefresh()
|
|
||||||
delay(500)
|
|
||||||
isRefreshing = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PullToRefreshBoxWithScaffoldPadding(
|
|
||||||
isRefreshing = isRefreshing,
|
|
||||||
onRefresh = onRefreshWrapped,
|
|
||||||
content = content,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [PullToRefreshBox] anchors its indicator at the top of the box. Inside a
|
|
||||||
* [DisappearingScaffold] the content fills the full screen height (feed items
|
|
||||||
* scroll behind the top bar), so the default indicator would appear behind the
|
|
||||||
* top bar. Offset the indicator down by the scaffold's top padding so it
|
|
||||||
* surfaces just below the bar.
|
|
||||||
*/
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
private fun PullToRefreshBoxWithScaffoldPadding(
|
|
||||||
isRefreshing: Boolean,
|
|
||||||
onRefresh: () -> Unit,
|
|
||||||
content: @Composable BoxScope.() -> Unit,
|
|
||||||
) {
|
|
||||||
val state = rememberPullToRefreshState()
|
val state = rememberPullToRefreshState()
|
||||||
val topPadding = LocalDisappearingScaffoldPadding.current.calculateTopPadding()
|
val topPadding = LocalDisappearingScaffoldPadding.current.calculateTopPadding()
|
||||||
|
|
||||||
PullToRefreshBox(
|
PullToRefreshBox(
|
||||||
isRefreshing = isRefreshing,
|
isRefreshing = isRefreshing,
|
||||||
onRefresh = onRefresh,
|
onRefresh = {
|
||||||
|
isRefreshing = true
|
||||||
|
scope.launch {
|
||||||
|
onRefresh()
|
||||||
|
delay(500)
|
||||||
|
isRefreshing = false
|
||||||
|
}
|
||||||
|
},
|
||||||
state = state,
|
state = state,
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
// Anchor the indicator below the scaffold's top bar. Inside a DisappearingScaffold
|
||||||
|
// the content fills the full screen height (feed items scroll behind the bar),
|
||||||
|
// so the default top-aligned indicator would sit behind the top bar. Outside a
|
||||||
|
// scaffold the local default is 0.dp and behaviour is unchanged.
|
||||||
indicator = {
|
indicator = {
|
||||||
PullToRefreshDefaults.Indicator(
|
PullToRefreshDefaults.Indicator(
|
||||||
modifier =
|
modifier =
|
||||||
|
|||||||
Reference in New Issue
Block a user