Code tweaks
This commit is contained in:
@@ -1,102 +0,0 @@
|
||||
package it.vfsfitvnm.vimusic.utils
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import it.vfsfitvnm.vimusic.savers.ListSaver
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
|
||||
|
||||
@Composable
|
||||
fun <T> produceSaveableListState(
|
||||
flowProvider: () -> Flow<List<T>>,
|
||||
stateSaver: ListSaver<T, List<Any?>>,
|
||||
): State<List<T>> {
|
||||
val state = rememberSaveable(stateSaver = stateSaver) {
|
||||
mutableStateOf(emptyList())
|
||||
}
|
||||
|
||||
var hasToRecollect by rememberSaveable {
|
||||
mutableStateOf(true)
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
flowProvider()
|
||||
.flowOn(Dispatchers.IO)
|
||||
.drop(if (hasToRecollect) 0 else 1)
|
||||
.collect {
|
||||
hasToRecollect = false
|
||||
state.value = it
|
||||
}
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun <T> produceSaveableListState(
|
||||
flowProvider: () -> Flow<List<T>>,
|
||||
stateSaver: ListSaver<T, List<Any?>>,
|
||||
key1: Any?,
|
||||
): State<List<T>> {
|
||||
val state = rememberSaveable(stateSaver = stateSaver) {
|
||||
mutableStateOf(emptyList())
|
||||
}
|
||||
|
||||
var hasToRecollect by rememberSaveable(key1) {
|
||||
// println("hasToRecollect: $sortBy, $sortOrder")
|
||||
mutableStateOf(true)
|
||||
}
|
||||
|
||||
LaunchedEffect(key1) {
|
||||
// println("[${System.currentTimeMillis()}] LaunchedEffect, $hasToRecollect, $sortBy, $sortOrder")
|
||||
flowProvider()
|
||||
.flowOn(Dispatchers.IO)
|
||||
.drop(if (hasToRecollect) 0 else 1)
|
||||
.collect {
|
||||
hasToRecollect = false
|
||||
// println("[${System.currentTimeMillis()}] collecting... ")
|
||||
state.value = it
|
||||
}
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun <T> produceSaveableListState(
|
||||
flowProvider: () -> Flow<List<T>>,
|
||||
stateSaver: ListSaver<T, List<Any?>>,
|
||||
key1: Any?,
|
||||
key2: Any?,
|
||||
): State<List<T>> {
|
||||
val state = rememberSaveable(stateSaver = stateSaver) {
|
||||
mutableStateOf(emptyList())
|
||||
}
|
||||
|
||||
// var hasToRecollect by rememberSaveable(key1, key2) {
|
||||
//// println("hasToRecollect: $sortBy, $sortOrder")
|
||||
// mutableStateOf(true)
|
||||
// }
|
||||
|
||||
LaunchedEffect(key1, key2) {
|
||||
// println("[${System.currentTimeMillis()}] LaunchedEffect, $hasToRecollect, $sortBy, $sortOrder")
|
||||
flowProvider()
|
||||
.flowOn(Dispatchers.IO)
|
||||
// .drop(if (hasToRecollect) 0 else 1)
|
||||
.collect {
|
||||
// hasToRecollect = false
|
||||
// println("[${System.currentTimeMillis()}] collecting... ")
|
||||
state.value = it
|
||||
}
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
@file:OptIn(ExperimentalTypeInference::class)
|
||||
|
||||
package it.vfsfitvnm.vimusic.utils
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -14,27 +16,23 @@ import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.experimental.ExperimentalTypeInference
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
|
||||
@OptIn(ExperimentalTypeInference::class)
|
||||
@Composable
|
||||
fun <T> produceSaveableState(
|
||||
initialValue: T,
|
||||
stateSaver: Saver<T, out Any>,
|
||||
@BuilderInference producer: suspend ProduceStateScope<T>.() -> Unit
|
||||
): State<T> {
|
||||
val result = rememberSaveable(stateSaver = stateSaver) { mutableStateOf(initialValue) }
|
||||
|
||||
var hasToFetch by rememberSaveable { mutableStateOf(true) }
|
||||
val result = rememberSaveable(stateSaver = stateSaver) {
|
||||
mutableStateOf(initialValue)
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
if (hasToFetch) {
|
||||
ProduceSaveableStateScope(result, coroutineContext).producer()
|
||||
hasToFetch = false
|
||||
}
|
||||
ProduceSaveableStateScope(result, coroutineContext).producer()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTypeInference::class)
|
||||
@Composable
|
||||
fun <T> produceSaveableState(
|
||||
initialValue: T,
|
||||
@@ -42,20 +40,42 @@ fun <T> produceSaveableState(
|
||||
key1: Any?,
|
||||
@BuilderInference producer: suspend ProduceStateScope<T>.() -> Unit
|
||||
): State<T> {
|
||||
val result = rememberSaveable(stateSaver = stateSaver) { mutableStateOf(initialValue) }
|
||||
|
||||
var hasToFetch by rememberSaveable(key1) { mutableStateOf(true) }
|
||||
val state = rememberSaveable(stateSaver = stateSaver) {
|
||||
mutableStateOf(initialValue)
|
||||
}
|
||||
|
||||
LaunchedEffect(key1) {
|
||||
if (hasToFetch) {
|
||||
ProduceSaveableStateScope(result, coroutineContext).producer()
|
||||
hasToFetch = false
|
||||
}
|
||||
ProduceSaveableStateScope(state, coroutineContext).producer()
|
||||
}
|
||||
return result
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun <T> produceSaveableOneShotState(
|
||||
initialValue: T,
|
||||
stateSaver: Saver<T, out Any>,
|
||||
key1: Any?,
|
||||
@BuilderInference producer: suspend ProduceStateScope<T>.() -> Unit
|
||||
): State<T> {
|
||||
val state = rememberSaveable(stateSaver = stateSaver) {
|
||||
mutableStateOf(initialValue)
|
||||
}
|
||||
|
||||
var produced by rememberSaveable(key1) {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
LaunchedEffect(key1) {
|
||||
if (!produced) {
|
||||
ProduceSaveableStateScope(state, coroutineContext).producer()
|
||||
produced = true
|
||||
}
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTypeInference::class)
|
||||
@Composable
|
||||
fun <T> produceSaveableState(
|
||||
initialValue: T,
|
||||
@@ -64,42 +84,42 @@ fun <T> produceSaveableState(
|
||||
key2: Any?,
|
||||
@BuilderInference producer: suspend ProduceStateScope<T>.() -> Unit
|
||||
): State<T> {
|
||||
val result = rememberSaveable(stateSaver = stateSaver) { mutableStateOf(initialValue) }
|
||||
val result = rememberSaveable(stateSaver = stateSaver) {
|
||||
mutableStateOf(initialValue)
|
||||
}
|
||||
|
||||
var hasToFetch by rememberSaveable(key1, key2) { mutableStateOf(true) }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
if (hasToFetch) {
|
||||
ProduceSaveableStateScope(result, coroutineContext).producer()
|
||||
hasToFetch = false
|
||||
}
|
||||
LaunchedEffect(key1, key2) {
|
||||
ProduceSaveableStateScope(result, coroutineContext).producer()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTypeInference::class)
|
||||
@Composable
|
||||
fun <T> produceSaveableRelaunchableState(
|
||||
fun <T> produceSaveableRelaunchableOneShotState(
|
||||
initialValue: T,
|
||||
stateSaver: Saver<T, out Any>,
|
||||
key1: Any?,
|
||||
key2: Any?,
|
||||
@BuilderInference producer: suspend ProduceStateScope<T>.() -> Unit
|
||||
): Pair<State<T>, () -> Unit> {
|
||||
val result = rememberSaveable(stateSaver = stateSaver) { mutableStateOf(initialValue) }
|
||||
val result = rememberSaveable(stateSaver = stateSaver) {
|
||||
mutableStateOf(initialValue)
|
||||
}
|
||||
|
||||
var hasToFetch by rememberSaveable(key1, key2) { mutableStateOf(true) }
|
||||
var produced by rememberSaveable(key1, key2) {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
||||
val relaunchableEffect = relaunchableEffect(key1, key2) {
|
||||
if (hasToFetch) {
|
||||
if (!produced) {
|
||||
ProduceSaveableStateScope(result, coroutineContext).producer()
|
||||
hasToFetch = false
|
||||
produced = true
|
||||
}
|
||||
}
|
||||
|
||||
return result to {
|
||||
hasToFetch = true
|
||||
produced = false
|
||||
relaunchableEffect()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package it.vfsfitvnm.vimusic.utils
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.grid.LazyGridState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.saveable.listSaver
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
|
||||
@Composable
|
||||
fun rememberLazyListStates(count: Int): List<LazyListState> {
|
||||
return rememberSaveable(
|
||||
saver = listSaver(
|
||||
save = { states: List<LazyListState> ->
|
||||
List(states.size * 2) {
|
||||
when (it % 2) {
|
||||
0 -> states[it / 2].firstVisibleItemIndex
|
||||
1 -> states[it / 2].firstVisibleItemScrollOffset
|
||||
else -> error("unreachable")
|
||||
}
|
||||
}
|
||||
},
|
||||
restore = { states ->
|
||||
List(states.size / 2) {
|
||||
LazyListState(
|
||||
firstVisibleItemIndex = states[it * 2],
|
||||
firstVisibleItemScrollOffset = states[it * 2 + 1]
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
) {
|
||||
List(count) { LazyListState(0, 0) }
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberLazyGridStates(count: Int): List<LazyGridState> {
|
||||
return rememberSaveable(
|
||||
saver = listSaver(
|
||||
save = { states: List<LazyGridState> ->
|
||||
List(states.size * 2) {
|
||||
when (it % 2) {
|
||||
0 -> states[it / 2].firstVisibleItemIndex
|
||||
1 -> states[it / 2].firstVisibleItemScrollOffset
|
||||
else -> error("unreachable")
|
||||
}
|
||||
}
|
||||
},
|
||||
restore = { states ->
|
||||
List(states.size / 2) {
|
||||
LazyGridState(
|
||||
firstVisibleItemIndex = states[it * 2],
|
||||
firstVisibleItemScrollOffset = states[it * 2 + 1]
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
) {
|
||||
List(count) { LazyGridState(0, 0) }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user