Use Voyager for source feed
This commit is contained in:
@@ -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))
|
||||
},
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user