Use Voyager for source feed

This commit is contained in:
Jobobby04
2022-11-28 22:16:18 -05:00
parent bd73eff732
commit 658c84bef8
10 changed files with 469 additions and 343 deletions
@@ -34,7 +34,6 @@ import eu.kanade.presentation.components.SearchToolbar
import eu.kanade.presentation.util.plus
import eu.kanade.presentation.util.topSmallPaddingValues
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.browse.source.feed.SourceFeedPresenter
import exh.savedsearches.models.FeedSavedSearch
import exh.savedsearches.models.SavedSearch
@@ -93,41 +92,49 @@ sealed class SourceFeedUI {
@Composable
fun SourceFeedScreen(
presenter: SourceFeedPresenter,
onFabClick: () -> Unit,
name: String,
isLoading: Boolean,
items: List<SourceFeedUI>,
onFabClick: (() -> Unit)?,
onClickBrowse: () -> Unit,
onClickLatest: () -> Unit,
onClickSavedSearch: (SavedSearch) -> Unit,
onClickDelete: (FeedSavedSearch) -> Unit,
onClickManga: (Manga) -> Unit,
onClickSearch: (String) -> Unit,
searchQuery: String?,
onSearchQueryChange: (String?) -> Unit,
isIncognitoMode: Boolean,
isDownloadOnly: Boolean,
getMangaState: @Composable (Manga) -> State<Manga>,
) {
Scaffold(
topBar = { scrollBehavior ->
SourceFeedToolbar(
title = presenter.source.name,
state = presenter,
title = name,
searchQuery = searchQuery,
onSearchQueryChange = onSearchQueryChange,
scrollBehavior = scrollBehavior,
incognitoMode = presenter.isIncognitoMode,
downloadedOnlyMode = presenter.isDownloadOnly,
incognitoMode = isIncognitoMode,
downloadedOnlyMode = isDownloadOnly,
onClickSearch = onClickSearch,
)
},
floatingActionButton = {
BrowseSourceFloatingActionButton(
isVisible = presenter.filterItems.isNotEmpty(),
onFabClick = onFabClick,
isVisible = onFabClick != null,
onFabClick = onFabClick ?: {},
)
},
) { paddingValues ->
Crossfade(targetState = presenter.isLoading) { state ->
Crossfade(targetState = isLoading) { state ->
when (state) {
true -> LoadingScreen()
false -> {
SourceFeedList(
state = presenter,
items = items,
paddingValues = paddingValues,
getMangaState = { presenter.getManga(it) },
getMangaState = getMangaState,
onClickBrowse = onClickBrowse,
onClickLatest = onClickLatest,
onClickSavedSearch = onClickSavedSearch,
@@ -142,7 +149,7 @@ fun SourceFeedScreen(
@Composable
fun SourceFeedList(
state: SourceFeedState,
items: List<SourceFeedUI>,
paddingValues: PaddingValues,
getMangaState: @Composable ((Manga) -> State<Manga>),
onClickBrowse: () -> Unit,
@@ -155,7 +162,7 @@ fun SourceFeedList(
contentPadding = paddingValues + topSmallPaddingValues,
) {
items(
state.items.orEmpty(),
items.orEmpty(),
key = { it.id },
) { item ->
SourceFeedItem(
@@ -248,7 +255,8 @@ fun SourceFeedItem(
@Composable
fun SourceFeedToolbar(
title: String,
state: SourceFeedState,
searchQuery: String?,
onSearchQueryChange: (String?) -> Unit,
scrollBehavior: TopAppBarScrollBehavior,
incognitoMode: Boolean,
downloadedOnlyMode: Boolean,
@@ -256,10 +264,10 @@ fun SourceFeedToolbar(
) {
SearchToolbar(
titleContent = { AppBarTitle(title) },
searchQuery = state.searchQuery,
onChangeSearchQuery = { state.searchQuery = it },
searchQuery = searchQuery,
onChangeSearchQuery = onSearchQueryChange,
onSearch = onClickSearch,
onClickCloseSearch = { state.searchQuery = null },
onClickCloseSearch = { onSearchQueryChange(null) },
scrollBehavior = scrollBehavior,
incognitoMode = incognitoMode,
downloadedOnlyMode = downloadedOnlyMode,
@@ -1,31 +0,0 @@
package eu.kanade.presentation.browse
import androidx.compose.runtime.Stable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.ui.browse.source.browse.toItems
@Stable
interface SourceFeedState {
val isLoading: Boolean
var searchQuery: String?
val filters: FilterList
val filterItems: List<IFlexible<*>>
val items: List<SourceFeedUI>?
}
fun SourceFeedState(): SourceFeedState {
return SourceFeedStateImpl()
}
class SourceFeedStateImpl : SourceFeedState {
override var isLoading: Boolean by mutableStateOf(true)
override var searchQuery: String? by mutableStateOf(null)
override var filters: FilterList by mutableStateOf(FilterList())
override val filterItems: List<IFlexible<*>> by derivedStateOf { filters.toItems() }
override var items: List<SourceFeedUI>? by mutableStateOf(null)
}
@@ -0,0 +1,81 @@
package eu.kanade.presentation.browse.components
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import eu.kanade.tachiyomi.R
@Composable
fun SourceFeedAddDialog(
onDismissRequest: () -> Unit,
name: String,
addFeed: () -> Unit,
) {
AlertDialog(
onDismissRequest = onDismissRequest,
confirmButton = {
TextButton(onClick = addFeed) {
Text(text = stringResource(R.string.action_add))
}
},
dismissButton = {
TextButton(onClick = onDismissRequest) {
Text(text = stringResource(android.R.string.cancel))
}
},
title = {
Text(text = stringResource(R.string.feed))
},
text = {
Text(text = stringResource(R.string.feed_add, name))
},
)
}
@Composable
fun SourceFeedDeleteDialog(
onDismissRequest: () -> Unit,
deleteFeed: () -> Unit,
) {
AlertDialog(
onDismissRequest = onDismissRequest,
confirmButton = {
TextButton(onClick = deleteFeed) {
Text(text = stringResource(R.string.action_delete))
}
},
dismissButton = {
TextButton(onClick = onDismissRequest) {
Text(text = stringResource(android.R.string.cancel))
}
},
title = {
Text(text = stringResource(R.string.feed))
},
text = {
Text(text = stringResource(R.string.feed_delete))
},
)
}
@Composable
fun SourceFeedFailedToLoadSavedSearchDialog(
onDismissRequest: () -> Unit,
) {
AlertDialog(
onDismissRequest = onDismissRequest,
confirmButton = {
TextButton(onClick = onDismissRequest) {
Text(text = stringResource(android.R.string.ok))
}
},
title = {
Text(text = stringResource(R.string.save_search_failed_to_load))
},
text = {
Text(text = stringResource(R.string.save_search_failed_to_load_message))
},
)
}