From 41855c34deab39f0b1290ef054a9e13ece18d62b Mon Sep 17 00:00:00 2001 From: Andreas Date: Fri, 15 Jul 2022 23:35:19 +0200 Subject: [PATCH] Add Stable interface for Category state (#7539) (cherry picked from commit a21aa8125e63b9e0d4377aa9c97d6614ee4acf7f) --- .../presentation/category/CategoryScreen.kt | 30 +++++++++---------- .../presentation/category/CategoryState.kt | 28 +++++++++++++++++ .../presentation/category/SortTagScreen.kt | 28 ++++++++--------- .../presentation/category/SortTagState.kt | 27 +++++++++++++++++ .../category/SourceCategoryScreen.kt | 25 ++++++++-------- .../category/SourceCategoryState.kt | 27 +++++++++++++++++ .../presentation/category/SourceRepoScreen.kt | 24 +++++++-------- .../presentation/category/SourceRepoState.kt | 27 +++++++++++++++++ .../category/components/CategoryContent.kt | 18 +++++++---- .../category/components/CategoryListItem.kt | 13 ++++---- .../components/genre/SortTagContent.kt | 14 +++++---- .../components/genre/SortTagListItem.kt | 5 +++- .../components/repo/SourceRepoContent.kt | 10 +++++-- .../components/repo/SourceRepoListItem.kt | 5 +++- .../sources/SourceCategoryContent.kt | 17 ++++++----- .../sources/SourceCategoryListItem.kt | 5 +++- .../ui/category/CategoryPresenter.kt | 25 +++++++++++----- .../ui/category/genre/SortTagPresenter.kt | 28 ++++++++++------- .../ui/category/repos/RepoPresenter.kt | 25 +++++++++++----- .../sources/SourceCategoryPresenter.kt | 25 +++++++++++----- 20 files changed, 288 insertions(+), 118 deletions(-) create mode 100644 app/src/main/java/eu/kanade/presentation/category/CategoryState.kt create mode 100644 app/src/main/java/eu/kanade/presentation/category/SortTagState.kt create mode 100644 app/src/main/java/eu/kanade/presentation/category/SourceCategoryState.kt create mode 100644 app/src/main/java/eu/kanade/presentation/category/SourceRepoState.kt diff --git a/app/src/main/java/eu/kanade/presentation/category/CategoryScreen.kt b/app/src/main/java/eu/kanade/presentation/category/CategoryScreen.kt index 402bcb243..ad4a079c3 100644 --- a/app/src/main/java/eu/kanade/presentation/category/CategoryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/category/CategoryScreen.kt @@ -7,7 +7,6 @@ import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarScrollState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll @@ -20,6 +19,7 @@ import eu.kanade.presentation.category.components.CategoryFloatingActionButton import eu.kanade.presentation.category.components.CategoryRenameDialog import eu.kanade.presentation.category.components.CategoryTopAppBar import eu.kanade.presentation.components.EmptyScreen +import eu.kanade.presentation.components.LoadingScreen import eu.kanade.presentation.components.Scaffold import eu.kanade.presentation.util.horizontalPadding import eu.kanade.presentation.util.plus @@ -52,25 +52,25 @@ fun CategoryScreen( floatingActionButton = { CategoryFloatingActionButton( lazyListState = lazyListState, - onCreate = { presenter.dialog = CategoryPresenter.Dialog.Create }, + onCreate = { presenter.dialog = Dialog.Create }, ) }, ) { paddingValues -> val context = LocalContext.current - val categories by presenter.categories.collectAsState(initial = emptyList()) - if (categories.isEmpty()) { - EmptyScreen(textResource = R.string.information_empty_category) - } else { - CategoryContent( - categories = categories, - lazyListState = lazyListState, - paddingValues = paddingValues + topPaddingValues + PaddingValues(horizontal = horizontalPadding), - onMoveUp = { presenter.moveUp(it) }, - onMoveDown = { presenter.moveDown(it) }, - onRename = { presenter.dialog = Dialog.Rename(it) }, - onDelete = { presenter.dialog = Dialog.Delete(it) }, - ) + when { + presenter.isLoading -> LoadingScreen() + presenter.isEmpty -> EmptyScreen(textResource = R.string.information_empty_category) + else -> { + CategoryContent( + state = presenter, + lazyListState = lazyListState, + paddingValues = paddingValues + topPaddingValues + PaddingValues(horizontal = horizontalPadding), + onMoveUp = { presenter.moveUp(it) }, + onMoveDown = { presenter.moveDown(it) }, + ) + } } + val onDismissRequest = { presenter.dialog = null } when (val dialog = presenter.dialog) { Dialog.Create -> { diff --git a/app/src/main/java/eu/kanade/presentation/category/CategoryState.kt b/app/src/main/java/eu/kanade/presentation/category/CategoryState.kt new file mode 100644 index 000000000..5873f6bde --- /dev/null +++ b/app/src/main/java/eu/kanade/presentation/category/CategoryState.kt @@ -0,0 +1,28 @@ +package eu.kanade.presentation.category + +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.kanade.domain.category.model.Category +import eu.kanade.tachiyomi.ui.category.CategoryPresenter + +@Stable +interface CategoryState { + val isLoading: Boolean + var dialog: CategoryPresenter.Dialog? + val categories: List + val isEmpty: Boolean +} + +fun CategoryState(): CategoryState { + return CategoryStateImpl() +} + +class CategoryStateImpl : CategoryState { + override var isLoading: Boolean by mutableStateOf(true) + override var dialog: CategoryPresenter.Dialog? by mutableStateOf(null) + override var categories: List by mutableStateOf(emptyList()) + override val isEmpty: Boolean by derivedStateOf { categories.isEmpty() } +} diff --git a/app/src/main/java/eu/kanade/presentation/category/SortTagScreen.kt b/app/src/main/java/eu/kanade/presentation/category/SortTagScreen.kt index ad02cd264..cb9e25b13 100644 --- a/app/src/main/java/eu/kanade/presentation/category/SortTagScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/category/SortTagScreen.kt @@ -7,8 +7,6 @@ import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarScrollState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext @@ -19,6 +17,7 @@ import eu.kanade.presentation.category.components.CategoryFloatingActionButton import eu.kanade.presentation.category.components.CategoryTopAppBar import eu.kanade.presentation.category.components.genre.SortTagContent import eu.kanade.presentation.components.EmptyScreen +import eu.kanade.presentation.components.LoadingScreen import eu.kanade.presentation.components.Scaffold import eu.kanade.presentation.util.horizontalPadding import eu.kanade.presentation.util.plus @@ -56,19 +55,20 @@ fun SortTagScreen( }, ) { paddingValues -> val context = LocalContext.current - val tags by presenter.tags.collectAsState(initial = emptyList()) - if (tags.isEmpty()) { - EmptyScreen(textResource = R.string.information_empty_tags) - } else { - SortTagContent( - categories = tags, - lazyListState = lazyListState, - paddingValues = paddingValues + topPaddingValues + PaddingValues(horizontal = horizontalPadding), - onMoveUp = { tag, index -> presenter.moveUp(tag, index) }, - onMoveDown = { tag, index -> presenter.moveDown(tag, index) }, - onDelete = { presenter.dialog = Dialog.Delete(it) }, - ) + when { + presenter.isLoading -> LoadingScreen() + presenter.isEmpty -> EmptyScreen(textResource = R.string.information_empty_category) + else -> { + SortTagContent( + state = presenter, + lazyListState = lazyListState, + paddingValues = paddingValues + topPaddingValues + PaddingValues(horizontal = horizontalPadding), + onMoveUp = { tag, index -> presenter.moveUp(tag, index) }, + onMoveDown = { tag, index -> presenter.moveDown(tag, index) }, + ) + } } + val onDismissRequest = { presenter.dialog = null } when (val dialog = presenter.dialog) { Dialog.Create -> { diff --git a/app/src/main/java/eu/kanade/presentation/category/SortTagState.kt b/app/src/main/java/eu/kanade/presentation/category/SortTagState.kt new file mode 100644 index 000000000..0a4813f31 --- /dev/null +++ b/app/src/main/java/eu/kanade/presentation/category/SortTagState.kt @@ -0,0 +1,27 @@ +package eu.kanade.presentation.category + +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.kanade.tachiyomi.ui.category.genre.SortTagPresenter + +@Stable +interface SortTagState { + val isLoading: Boolean + var dialog: SortTagPresenter.Dialog? + val tags: List + val isEmpty: Boolean +} + +fun SortTagState(): SortTagState { + return SortTagStateImpl() +} + +class SortTagStateImpl : SortTagState { + override var isLoading: Boolean by mutableStateOf(true) + override var dialog: SortTagPresenter.Dialog? by mutableStateOf(null) + override var tags: List by mutableStateOf(emptyList()) + override val isEmpty: Boolean by derivedStateOf { tags.isEmpty() } +} diff --git a/app/src/main/java/eu/kanade/presentation/category/SourceCategoryScreen.kt b/app/src/main/java/eu/kanade/presentation/category/SourceCategoryScreen.kt index b8f514d63..eb3263144 100644 --- a/app/src/main/java/eu/kanade/presentation/category/SourceCategoryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/category/SourceCategoryScreen.kt @@ -7,8 +7,6 @@ import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarScrollState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext @@ -20,6 +18,7 @@ import eu.kanade.presentation.category.components.CategoryRenameDialog import eu.kanade.presentation.category.components.CategoryTopAppBar import eu.kanade.presentation.category.components.sources.SourceCategoryContent import eu.kanade.presentation.components.EmptyScreen +import eu.kanade.presentation.components.LoadingScreen import eu.kanade.presentation.components.Scaffold import eu.kanade.presentation.util.horizontalPadding import eu.kanade.presentation.util.plus @@ -57,18 +56,18 @@ fun SourceCategoryScreen( }, ) { paddingValues -> val context = LocalContext.current - val categories by presenter.categories.collectAsState(initial = emptyList()) - if (categories.isEmpty()) { - EmptyScreen(textResource = R.string.information_empty_category) - } else { - SourceCategoryContent( - categories = categories, - lazyListState = lazyListState, - paddingValues = paddingValues + topPaddingValues + PaddingValues(horizontal = horizontalPadding), - onRename = { presenter.dialog = Dialog.Rename(it) }, - onDelete = { presenter.dialog = Dialog.Delete(it) }, - ) + when { + presenter.isLoading -> LoadingScreen() + presenter.isEmpty -> EmptyScreen(textResource = R.string.information_empty_category) + else -> { + SourceCategoryContent( + state = presenter, + lazyListState = lazyListState, + paddingValues = paddingValues + topPaddingValues + PaddingValues(horizontal = horizontalPadding), + ) + } } + val onDismissRequest = { presenter.dialog = null } when (val dialog = presenter.dialog) { Dialog.Create -> { diff --git a/app/src/main/java/eu/kanade/presentation/category/SourceCategoryState.kt b/app/src/main/java/eu/kanade/presentation/category/SourceCategoryState.kt new file mode 100644 index 000000000..88f7480fa --- /dev/null +++ b/app/src/main/java/eu/kanade/presentation/category/SourceCategoryState.kt @@ -0,0 +1,27 @@ +package eu.kanade.presentation.category + +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.kanade.tachiyomi.ui.category.sources.SourceCategoryPresenter + +@Stable +interface SourceCategoryState { + val isLoading: Boolean + var dialog: SourceCategoryPresenter.Dialog? + val categories: List + val isEmpty: Boolean +} + +fun SourceCategoryState(): SourceCategoryState { + return SourceCategoryStateImpl() +} + +class SourceCategoryStateImpl : SourceCategoryState { + override var isLoading: Boolean by mutableStateOf(true) + override var dialog: SourceCategoryPresenter.Dialog? by mutableStateOf(null) + override var categories: List by mutableStateOf(emptyList()) + override val isEmpty: Boolean by derivedStateOf { categories.isEmpty() } +} diff --git a/app/src/main/java/eu/kanade/presentation/category/SourceRepoScreen.kt b/app/src/main/java/eu/kanade/presentation/category/SourceRepoScreen.kt index f9742c7c7..b54c8c649 100644 --- a/app/src/main/java/eu/kanade/presentation/category/SourceRepoScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/category/SourceRepoScreen.kt @@ -7,8 +7,6 @@ import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarScrollState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext @@ -19,6 +17,7 @@ import eu.kanade.presentation.category.components.CategoryFloatingActionButton import eu.kanade.presentation.category.components.CategoryTopAppBar import eu.kanade.presentation.category.components.repo.SourceRepoContent import eu.kanade.presentation.components.EmptyScreen +import eu.kanade.presentation.components.LoadingScreen import eu.kanade.presentation.components.Scaffold import eu.kanade.presentation.util.horizontalPadding import eu.kanade.presentation.util.plus @@ -56,17 +55,18 @@ fun SourceRepoScreen( }, ) { paddingValues -> val context = LocalContext.current - val repos by presenter.repos.collectAsState(initial = emptyList()) - if (repos.isEmpty()) { - EmptyScreen(textResource = R.string.information_empty_repos) - } else { - SourceRepoContent( - repos = repos, - lazyListState = lazyListState, - paddingValues = paddingValues + topPaddingValues + PaddingValues(horizontal = horizontalPadding), - onDelete = { presenter.dialog = Dialog.Delete(it) }, - ) + when { + presenter.isLoading -> LoadingScreen() + presenter.isEmpty -> EmptyScreen(textResource = R.string.information_empty_category) + else -> { + SourceRepoContent( + state = presenter, + lazyListState = lazyListState, + paddingValues = paddingValues + topPaddingValues + PaddingValues(horizontal = horizontalPadding), + ) + } } + val onDismissRequest = { presenter.dialog = null } when (val dialog = presenter.dialog) { Dialog.Create -> { diff --git a/app/src/main/java/eu/kanade/presentation/category/SourceRepoState.kt b/app/src/main/java/eu/kanade/presentation/category/SourceRepoState.kt new file mode 100644 index 000000000..927dac786 --- /dev/null +++ b/app/src/main/java/eu/kanade/presentation/category/SourceRepoState.kt @@ -0,0 +1,27 @@ +package eu.kanade.presentation.category + +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.kanade.tachiyomi.ui.category.repos.RepoPresenter + +@Stable +interface SourceRepoState { + val isLoading: Boolean + var dialog: RepoPresenter.Dialog? + val repos: List + val isEmpty: Boolean +} + +fun SourceRepoState(): SourceRepoState { + return SourceRepoStateImpl() +} + +class SourceRepoStateImpl : SourceRepoState { + override var isLoading: Boolean by mutableStateOf(true) + override var dialog: RepoPresenter.Dialog? by mutableStateOf(null) + override var repos: List by mutableStateOf(emptyList()) + override val isEmpty: Boolean by derivedStateOf { repos.isEmpty() } +} diff --git a/app/src/main/java/eu/kanade/presentation/category/components/CategoryContent.kt b/app/src/main/java/eu/kanade/presentation/category/components/CategoryContent.kt index 191609e42..0b0f24852 100644 --- a/app/src/main/java/eu/kanade/presentation/category/components/CategoryContent.kt +++ b/app/src/main/java/eu/kanade/presentation/category/components/CategoryContent.kt @@ -5,34 +5,40 @@ import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import eu.kanade.domain.category.model.Category +import eu.kanade.presentation.category.CategoryState import eu.kanade.presentation.components.LazyColumn +import eu.kanade.tachiyomi.ui.category.CategoryPresenter.Dialog @Composable fun CategoryContent( - categories: List, + state: CategoryState, lazyListState: LazyListState, paddingValues: PaddingValues, onMoveUp: (Category) -> Unit, onMoveDown: (Category) -> Unit, - onRename: (Category) -> Unit, - onDelete: (Category) -> Unit, ) { + val categories = state.categories LazyColumn( state = lazyListState, contentPadding = paddingValues, verticalArrangement = Arrangement.spacedBy(8.dp), ) { - itemsIndexed(categories) { index, category -> + itemsIndexed( + items = categories, + key = { _, category -> category.id }, + ) { index, category -> CategoryListItem( + modifier = Modifier.animateItemPlacement(), category = category, canMoveUp = index != 0, canMoveDown = index != categories.lastIndex, onMoveUp = onMoveUp, onMoveDown = onMoveDown, - onRename = onRename, - onDelete = onDelete, + onRename = { state.dialog = Dialog.Rename(category) }, + onDelete = { state.dialog = Dialog.Delete(category) }, ) } } diff --git a/app/src/main/java/eu/kanade/presentation/category/components/CategoryListItem.kt b/app/src/main/java/eu/kanade/presentation/category/components/CategoryListItem.kt index ff0ed8807..21b192b72 100644 --- a/app/src/main/java/eu/kanade/presentation/category/components/CategoryListItem.kt +++ b/app/src/main/java/eu/kanade/presentation/category/components/CategoryListItem.kt @@ -21,15 +21,18 @@ import eu.kanade.presentation.util.horizontalPadding @Composable fun CategoryListItem( + modifier: Modifier = Modifier, category: Category, canMoveUp: Boolean, canMoveDown: Boolean, onMoveUp: (Category) -> Unit, onMoveDown: (Category) -> Unit, - onRename: (Category) -> Unit, - onDelete: (Category) -> Unit, + onRename: () -> Unit, + onDelete: () -> Unit, ) { - ElevatedCard { + ElevatedCard( + modifier = modifier, + ) { Row( modifier = Modifier .padding(start = horizontalPadding, top = horizontalPadding, end = horizontalPadding), @@ -52,10 +55,10 @@ fun CategoryListItem( Icon(imageVector = Icons.Outlined.ArrowDropDown, contentDescription = "") } Spacer(modifier = Modifier.weight(1f)) - IconButton(onClick = { onRename(category) }) { + IconButton(onClick = onRename) { Icon(imageVector = Icons.Outlined.Edit, contentDescription = "") } - IconButton(onClick = { onDelete(category) }) { + IconButton(onClick = onDelete) { Icon(imageVector = Icons.Outlined.Delete, contentDescription = "") } } diff --git a/app/src/main/java/eu/kanade/presentation/category/components/genre/SortTagContent.kt b/app/src/main/java/eu/kanade/presentation/category/components/genre/SortTagContent.kt index 4de92f0bf..f088f21eb 100644 --- a/app/src/main/java/eu/kanade/presentation/category/components/genre/SortTagContent.kt +++ b/app/src/main/java/eu/kanade/presentation/category/components/genre/SortTagContent.kt @@ -5,32 +5,36 @@ import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import eu.kanade.presentation.category.SortTagState import eu.kanade.presentation.components.LazyColumn +import eu.kanade.tachiyomi.ui.category.genre.SortTagPresenter @Composable fun SortTagContent( - categories: List, + state: SortTagState, lazyListState: LazyListState, paddingValues: PaddingValues, onMoveUp: (String, Int) -> Unit, onMoveDown: (String, Int) -> Unit, - onDelete: (String) -> Unit, ) { + val tags = state.tags LazyColumn( state = lazyListState, contentPadding = paddingValues, verticalArrangement = Arrangement.spacedBy(8.dp), ) { - itemsIndexed(categories) { index, tag -> + itemsIndexed(tags) { index, tag -> SortTagListItem( + modifier = Modifier.animateItemPlacement(), tag = tag, index = index, canMoveUp = index != 0, - canMoveDown = index != categories.lastIndex, + canMoveDown = index != tags.lastIndex, onMoveUp = onMoveUp, onMoveDown = onMoveDown, - onDelete = onDelete, + onDelete = { state.dialog = SortTagPresenter.Dialog.Delete(it) }, ) } } diff --git a/app/src/main/java/eu/kanade/presentation/category/components/genre/SortTagListItem.kt b/app/src/main/java/eu/kanade/presentation/category/components/genre/SortTagListItem.kt index 18cef464a..dad5b3e34 100644 --- a/app/src/main/java/eu/kanade/presentation/category/components/genre/SortTagListItem.kt +++ b/app/src/main/java/eu/kanade/presentation/category/components/genre/SortTagListItem.kt @@ -19,6 +19,7 @@ import eu.kanade.presentation.util.horizontalPadding @Composable fun SortTagListItem( + modifier: Modifier, tag: String, index: Int, canMoveUp: Boolean, @@ -27,7 +28,9 @@ fun SortTagListItem( onMoveDown: (String, Int) -> Unit, onDelete: (String) -> Unit, ) { - ElevatedCard { + ElevatedCard( + modifier = modifier, + ) { Row( modifier = Modifier .padding(start = horizontalPadding, top = horizontalPadding, end = horizontalPadding), diff --git a/app/src/main/java/eu/kanade/presentation/category/components/repo/SourceRepoContent.kt b/app/src/main/java/eu/kanade/presentation/category/components/repo/SourceRepoContent.kt index 9c576f3fa..cf189c8f6 100644 --- a/app/src/main/java/eu/kanade/presentation/category/components/repo/SourceRepoContent.kt +++ b/app/src/main/java/eu/kanade/presentation/category/components/repo/SourceRepoContent.kt @@ -5,16 +5,19 @@ import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import eu.kanade.presentation.category.SourceRepoState import eu.kanade.presentation.components.LazyColumn +import eu.kanade.tachiyomi.ui.category.repos.RepoPresenter @Composable fun SourceRepoContent( - repos: List, + state: SourceRepoState, lazyListState: LazyListState, paddingValues: PaddingValues, - onDelete: (String) -> Unit, ) { + val repos = state.repos LazyColumn( state = lazyListState, contentPadding = paddingValues, @@ -22,8 +25,9 @@ fun SourceRepoContent( ) { items(repos) { repo -> SourceRepoListItem( + modifier = Modifier.animateItemPlacement(), repo = repo, - onDelete = onDelete, + onDelete = { state.dialog = RepoPresenter.Dialog.Delete(it) }, ) } } diff --git a/app/src/main/java/eu/kanade/presentation/category/components/repo/SourceRepoListItem.kt b/app/src/main/java/eu/kanade/presentation/category/components/repo/SourceRepoListItem.kt index c5b223324..8d20fd6d3 100644 --- a/app/src/main/java/eu/kanade/presentation/category/components/repo/SourceRepoListItem.kt +++ b/app/src/main/java/eu/kanade/presentation/category/components/repo/SourceRepoListItem.kt @@ -17,10 +17,13 @@ import eu.kanade.presentation.util.horizontalPadding @Composable fun SourceRepoListItem( + modifier: Modifier, repo: String, onDelete: (String) -> Unit, ) { - ElevatedCard { + ElevatedCard( + modifier = modifier, + ) { Row( modifier = Modifier .padding(start = horizontalPadding, top = horizontalPadding, end = horizontalPadding), diff --git a/app/src/main/java/eu/kanade/presentation/category/components/sources/SourceCategoryContent.kt b/app/src/main/java/eu/kanade/presentation/category/components/sources/SourceCategoryContent.kt index a5c146e28..66c7760e4 100644 --- a/app/src/main/java/eu/kanade/presentation/category/components/sources/SourceCategoryContent.kt +++ b/app/src/main/java/eu/kanade/presentation/category/components/sources/SourceCategoryContent.kt @@ -3,29 +3,32 @@ package eu.kanade.presentation.category.components.sources import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import eu.kanade.presentation.category.SourceCategoryState import eu.kanade.presentation.components.LazyColumn +import eu.kanade.tachiyomi.ui.category.sources.SourceCategoryPresenter @Composable fun SourceCategoryContent( - categories: List, + state: SourceCategoryState, lazyListState: LazyListState, paddingValues: PaddingValues, - onRename: (String) -> Unit, - onDelete: (String) -> Unit, ) { + val categories = state.categories LazyColumn( state = lazyListState, contentPadding = paddingValues, verticalArrangement = Arrangement.spacedBy(8.dp), ) { - itemsIndexed(categories) { index, category -> + items(categories) { category -> SourceCategoryListItem( + modifier = Modifier.animateItemPlacement(), category = category, - onRename = onRename, - onDelete = onDelete, + onRename = { state.dialog = SourceCategoryPresenter.Dialog.Rename(category) }, + onDelete = { state.dialog = SourceCategoryPresenter.Dialog.Delete(category) }, ) } } diff --git a/app/src/main/java/eu/kanade/presentation/category/components/sources/SourceCategoryListItem.kt b/app/src/main/java/eu/kanade/presentation/category/components/sources/SourceCategoryListItem.kt index adad511f2..2d1a70e50 100644 --- a/app/src/main/java/eu/kanade/presentation/category/components/sources/SourceCategoryListItem.kt +++ b/app/src/main/java/eu/kanade/presentation/category/components/sources/SourceCategoryListItem.kt @@ -18,11 +18,14 @@ import eu.kanade.presentation.util.horizontalPadding @Composable fun SourceCategoryListItem( + modifier: Modifier, category: String, onRename: (String) -> Unit, onDelete: (String) -> Unit, ) { - ElevatedCard { + ElevatedCard( + modifier = modifier, + ) { Row( modifier = Modifier .padding(start = horizontalPadding, top = horizontalPadding, end = horizontalPadding), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryPresenter.kt index 66926bb07..b24c81ec9 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryPresenter.kt @@ -1,36 +1,45 @@ package eu.kanade.tachiyomi.ui.category -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue +import android.os.Bundle import eu.kanade.domain.category.interactor.CreateCategoryWithName import eu.kanade.domain.category.interactor.DeleteCategory import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.domain.category.interactor.RenameCategory import eu.kanade.domain.category.interactor.ReorderCategory import eu.kanade.domain.category.model.Category +import eu.kanade.presentation.category.CategoryState +import eu.kanade.presentation.category.CategoryStateImpl import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.util.lang.launchIO import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.consumeAsFlow import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get class CategoryPresenter( + private val state: CategoryStateImpl = CategoryState() as CategoryStateImpl, private val getCategories: GetCategories = Injekt.get(), private val createCategoryWithName: CreateCategoryWithName = Injekt.get(), private val renameCategory: RenameCategory = Injekt.get(), private val reorderCategory: ReorderCategory = Injekt.get(), private val deleteCategory: DeleteCategory = Injekt.get(), -) : BasePresenter() { - - var dialog: Dialog? by mutableStateOf(null) - - val categories = getCategories.subscribe() +) : BasePresenter(), CategoryState by state { private val _events: Channel = Channel(Int.MAX_VALUE) val events = _events.consumeAsFlow() + override fun onCreate(savedState: Bundle?) { + super.onCreate(savedState) + presenterScope.launchIO { + getCategories.subscribe() + .collectLatest { + state.isLoading = false + state.categories = it + } + } + } + fun createCategory(name: String) { presenterScope.launchIO { when (createCategoryWithName.await(name)) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/genre/SortTagPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/genre/SortTagPresenter.kt index c91928f7f..fa1bed38e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/genre/SortTagPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/genre/SortTagPresenter.kt @@ -1,15 +1,16 @@ package eu.kanade.tachiyomi.ui.category.genre -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue +import android.os.Bundle import eu.kanade.domain.manga.interactor.CreateSortTag import eu.kanade.domain.manga.interactor.DeleteSortTag import eu.kanade.domain.manga.interactor.GetSortTag import eu.kanade.domain.manga.interactor.ReorderSortTag +import eu.kanade.presentation.category.SortTagState +import eu.kanade.presentation.category.SortTagStateImpl import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.util.lang.launchIO import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.consumeAsFlow import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -18,22 +19,27 @@ import uy.kohesive.injekt.api.get * Presenter of [SortTagController]. Used to manage the categories of the library. */ class SortTagPresenter( + private val state: SortTagStateImpl = SortTagState() as SortTagStateImpl, private val getSortTag: GetSortTag = Injekt.get(), private val createSortTag: CreateSortTag = Injekt.get(), private val deleteSortTag: DeleteSortTag = Injekt.get(), private val reorderSortTag: ReorderSortTag = Injekt.get(), -) : BasePresenter() { - - var dialog: Dialog? by mutableStateOf(null) - - /** - * List containing categories. - */ - val tags = getSortTag.subscribe() +) : BasePresenter(), SortTagState by state { private val _events: Channel = Channel(Int.MAX_VALUE) val events = _events.consumeAsFlow() + override fun onCreate(savedState: Bundle?) { + super.onCreate(savedState) + presenterScope.launchIO { + getSortTag.subscribe() + .collectLatest { + state.isLoading = false + state.tags = it + } + } + } + fun createTag(name: String) { presenterScope.launchIO { when (createSortTag.await(name)) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/repos/RepoPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/repos/RepoPresenter.kt index e03a23d13..958d563d3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/repos/RepoPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/repos/RepoPresenter.kt @@ -1,14 +1,15 @@ package eu.kanade.tachiyomi.ui.category.repos -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue +import android.os.Bundle import eu.kanade.domain.source.interactor.CreateSourceRepo import eu.kanade.domain.source.interactor.DeleteSourceRepos import eu.kanade.domain.source.interactor.GetSourceRepos +import eu.kanade.presentation.category.SourceRepoState +import eu.kanade.presentation.category.SourceRepoStateImpl import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.util.lang.launchIO import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.consumeAsFlow import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -17,18 +18,26 @@ import uy.kohesive.injekt.api.get * Presenter of [RepoController]. Used to manage the repos for the extensions. */ class RepoPresenter( + private val state: SourceRepoStateImpl = SourceRepoState() as SourceRepoStateImpl, private val getSourceRepos: GetSourceRepos = Injekt.get(), private val createSourceRepo: CreateSourceRepo = Injekt.get(), private val deleteSourceRepos: DeleteSourceRepos = Injekt.get(), -) : BasePresenter() { - - var dialog: Dialog? by mutableStateOf(null) - - val repos = getSourceRepos.subscribe() +) : BasePresenter(), SourceRepoState by state { private val _events: Channel = Channel(Int.MAX_VALUE) val events = _events.consumeAsFlow() + override fun onCreate(savedState: Bundle?) { + super.onCreate(savedState) + presenterScope.launchIO { + getSourceRepos.subscribe() + .collectLatest { + state.isLoading = false + state.repos = it + } + } + } + /** * Creates and adds a new repo to the database. * diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/sources/SourceCategoryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/sources/SourceCategoryPresenter.kt index 3872400b0..dcc47456b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/sources/SourceCategoryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/sources/SourceCategoryPresenter.kt @@ -1,15 +1,16 @@ package eu.kanade.tachiyomi.ui.category.sources -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue +import android.os.Bundle import eu.kanade.domain.source.interactor.CreateSourceCategory import eu.kanade.domain.source.interactor.DeleteSourceCategory import eu.kanade.domain.source.interactor.GetSourceCategories import eu.kanade.domain.source.interactor.RenameSourceCategory +import eu.kanade.presentation.category.SourceCategoryState +import eu.kanade.presentation.category.SourceCategoryStateImpl import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.util.lang.launchIO import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.consumeAsFlow import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -18,19 +19,27 @@ import uy.kohesive.injekt.api.get * Presenter of [SourceCategoryController]. Used to manage the categories of the library. */ class SourceCategoryPresenter( + private val state: SourceCategoryStateImpl = SourceCategoryState() as SourceCategoryStateImpl, private val getSourceCategories: GetSourceCategories = Injekt.get(), private val createSourceCategory: CreateSourceCategory = Injekt.get(), private val renameSourceCategory: RenameSourceCategory = Injekt.get(), private val deleteSourceCategory: DeleteSourceCategory = Injekt.get(), -) : BasePresenter() { - - var dialog: Dialog? by mutableStateOf(null) - - val categories = getSourceCategories.subscribe() +) : BasePresenter(), SourceCategoryState by state { private val _events: Channel = Channel(Int.MAX_VALUE) val events = _events.consumeAsFlow() + override fun onCreate(savedState: Bundle?) { + super.onCreate(savedState) + presenterScope.launchIO { + getSourceCategories.subscribe() + .collectLatest { + state.isLoading = false + state.categories = it + } + } + } + /** * Creates and adds a new category to the database. *