This commit is contained in:
FooIbar committed 2023-11-23 20:48:21 +08:00
1 parent 35cff4647a
commit 16fddcb377
1 file changed
+97 -95
@@ -39,6 +39,7 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ShapeDefaults
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
@@ -126,7 +127,6 @@ import moe.tarsin.coroutines.runSuspendCatching
fun FavouritesScreen(navigator: NavController) {
// Meta State
var urlBuilder by rememberSaveable { mutableStateOf(FavListUrlBuilder(favCat = Settings.recentFavCat)) }
var refreshKey by rememberSaveable { mutableStateOf(false) }
var searchBarOffsetY by remember { mutableStateOf(0) }
// Derived State
@@ -149,69 +149,7 @@ fun FavouritesScreen(navigator: NavController) {
val coroutineScope = rememberCoroutineScope()
val localFavCountFlow = rememberInVM { EhDB.localFavCount }
val searchBarHint = stringResource(R.string.search_bar_hint, favCatName)
fun refresh(newUrlBuilder: FavListUrlBuilder) {
if (urlBuilder == newUrlBuilder) {
refreshKey = !refreshKey
} else {
urlBuilder = newUrlBuilder
}
}
fun switchFav(newCat: Int, keyword: String? = null) {
refresh(
urlBuilder.copy(
keyword = keyword,
favCat = newCat,
jumpTo = null,
).apply { setIndex(null, true) },
)
Settings.recentFavCat = urlBuilder.favCat
}
with(activity) {
ProvideSideSheetContent { sheetState ->
val localFavCount by localFavCountFlow.collectAsState(0)
TopAppBar(
title = { Text(text = stringResource(id = R.string.collections)) },
windowInsets = WindowInsets(0, 0, 0, 0),
)
val scope = currentRecomposeScope
LaunchedEffect(Unit) {
Settings.favChangesFlow.collect {
scope.invalidate()
}
}
val localFav = stringResource(id = R.string.local_favorites) to localFavCount
val faves = if (EhCookieStore.hasSignedIn()) {
arrayOf(
localFav,
stringResource(id = R.string.cloud_favorites) to Settings.favCloudCount,
*Settings.favCat.zip(Settings.favCount.toTypedArray()).toTypedArray(),
)
} else {
arrayOf(localFav)
}
Column(
modifier = Modifier.verticalScroll(rememberScrollState())
.windowInsetsPadding(WindowInsets.systemBars.only(WindowInsetsSides.Bottom)),
) {
faves.forEachIndexed { index, (name, count) ->
ListItem(
headlineContent = { Text(text = name) },
trailingContent = { Text(text = count.toString(), style = MaterialTheme.typography.bodyLarge) },
modifier = Modifier.clickable {
switchFav(index - 2)
coroutineScope.launch { sheetState.close() }
},
)
}
}
}
}
val searchFieldState = rememberTextFieldState()
val data = rememberInVM(urlBuilder, refreshKey) {
val data = rememberInVM(urlBuilder.favCat == FavListUrlBuilder.FAV_CAT_LOCAL) {
if (urlBuilder.favCat == FavListUrlBuilder.FAV_CAT_LOCAL) {
Pager(PagingConfig(20, jumpThreshold = 40)) {
if (keyword.isBlank()) {
@@ -255,13 +193,63 @@ fun FavouritesScreen(navigator: NavController) {
}.flow.cachedIn(viewModelScope)
}.collectAsLazyPagingItems()
fun refresh(newUrlBuilder: FavListUrlBuilder = urlBuilder.copy(jumpTo = null, prev = null, next = null)) {
urlBuilder = newUrlBuilder
data.refresh()
}
with(activity) {
ProvideSideSheetContent { sheetState ->
val localFavCount by localFavCountFlow.collectAsState(0)
TopAppBar(
title = { Text(text = stringResource(id = R.string.collections)) },
windowInsets = WindowInsets(0, 0, 0, 0),
)
val scope = currentRecomposeScope
LaunchedEffect(Unit) {
Settings.favChangesFlow.collect {
scope.invalidate()
}
}
val localFav = stringResource(id = R.string.local_favorites) to localFavCount
val faves = if (EhCookieStore.hasSignedIn()) {
arrayOf(
localFav,
stringResource(id = R.string.cloud_favorites) to Settings.favCloudCount,
*Settings.favCat.zip(Settings.favCount.toTypedArray()).toTypedArray(),
)
} else {
arrayOf(localFav)
}
Column(
modifier = Modifier.verticalScroll(rememberScrollState())
.windowInsetsPadding(WindowInsets.systemBars.only(WindowInsetsSides.Bottom)),
) {
faves.forEachIndexed { index, (name, count) ->
ListItem(
headlineContent = { Text(text = name) },
trailingContent = { Text(text = count.toString(), style = MaterialTheme.typography.bodyLarge) },
modifier = Modifier.clickable {
val newCat = index - 2
refresh(FavListUrlBuilder(newCat))
Settings.recentFavCat = newCat
coroutineScope.launch { sheetState.close() }
},
)
}
}
}
}
val searchFieldState = rememberTextFieldState()
val refreshState = rememberPullToRefreshState {
data.loadState.refresh is LoadState.NotLoading
}
if (refreshState.isRefreshing) {
LaunchedEffect(Unit) {
data.refresh()
refresh()
}
}
@@ -288,7 +276,7 @@ fun FavouritesScreen(navigator: NavController) {
title = title,
searchFieldState = searchFieldState,
searchFieldHint = searchBarHint,
onApplySearch = { switchFav(urlBuilder.favCat, it) },
onApplySearch = { refresh(FavListUrlBuilder(urlBuilder.favCat, it)) },
onSearchExpanded = { hidden = true },
onSearchHidden = { hidden = false },
refreshState = refreshState,
@@ -312,33 +300,6 @@ fun FavouritesScreen(navigator: NavController) {
Settings.listModeBackField.valueFlow()
}.collectAsState(Settings.listMode)
Box(modifier = Modifier.fillMaxSize()) {
when (val state = data.loadState.refresh) {
is LoadState.Loading -> if (data.itemCount == 0) {
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
}
is LoadState.Error -> {
Column(
modifier = Modifier.align(Alignment.Center).widthIn(max = 228.dp)
.clip(ShapeDefaults.Small).clickable { data.retry() },
horizontalAlignment = Alignment.CenterHorizontally,
) {
Icon(
imageVector = EhIcons.Big.Default.SadAndroid,
contentDescription = null,
modifier = Modifier.padding(16.dp).size(120.dp),
tint = MaterialTheme.colorScheme.tertiary,
)
Text(
text = ExceptionUtils.getReadableString(state.error),
style = MaterialTheme.typography.bodyLarge,
textAlign = TextAlign.Center,
)
}
}
is LoadState.NotLoading -> SideEffect {
refreshState.endRefresh()
}
}
if (listMode == 0) {
val height = (3 * Settings.listThumbSize * 3).pxToDp.dp
val showPages = Settings.showGalleryPages
@@ -428,6 +389,47 @@ fun FavouritesScreen(navigator: NavController) {
}
}
}
when (val state = data.loadState.refresh) {
is LoadState.Loading -> if (!refreshState.isRefreshing) {
Surface {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
CircularProgressIndicator()
}
}
}
is LoadState.Error -> {
Surface {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Column(
modifier = Modifier.widthIn(max = 228.dp)
.clip(ShapeDefaults.Small).clickable { data.retry() },
horizontalAlignment = Alignment.CenterHorizontally,
) {
Icon(
imageVector = EhIcons.Big.Default.SadAndroid,
contentDescription = null,
modifier = Modifier.padding(16.dp).size(120.dp),
tint = MaterialTheme.colorScheme.tertiary,
)
Text(
text = ExceptionUtils.getReadableString(state.error),
style = MaterialTheme.typography.bodyLarge,
textAlign = TextAlign.Center,
)
}
}
}
}
is LoadState.NotLoading -> SideEffect {
refreshState.endRefresh()
}
}
}
}
@@ -468,10 +470,10 @@ fun FavouritesScreen(navigator: NavController) {
}
}
onClick(Icons.Default.Refresh) {
switchFav(urlBuilder.favCat)
refresh()
}
onClick(Icons.AutoMirrored.Default.LastPage) {
refresh(urlBuilder.copy().apply { setIndex("1-0", false) })
refresh(urlBuilder.copy(jumpTo = null, prev = "1-0", next = null))
}
} else {
onClick(Icons.Default.DoneAll) {