diff --git a/app/src/main/java/eu/kanade/domain/chapter/interactor/SetReadStatus.kt b/app/src/main/java/eu/kanade/domain/chapter/interactor/SetReadStatus.kt index 49a718b51..673b686f5 100644 --- a/app/src/main/java/eu/kanade/domain/chapter/interactor/SetReadStatus.kt +++ b/app/src/main/java/eu/kanade/domain/chapter/interactor/SetReadStatus.kt @@ -72,9 +72,9 @@ class SetReadStatus( suspend fun await(manga: Manga, read: Boolean) = await(manga.id, read) - sealed class Result { - data object Success : Result() - data object NoChapters : Result() - data class InternalError(val error: Throwable) : Result() + sealed interface Result { + data object Success : Result + data object NoChapters : Result + data class InternalError(val error: Throwable) : Result } } diff --git a/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt index 31e103a59..42f794af6 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt @@ -53,7 +53,7 @@ import eu.kanade.presentation.more.settings.widget.TrailingWidgetBuffer import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.source.ConfigurableSource -import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsState +import eu.kanade.tachiyomi.ui.browse.extension.details.ExtensionDetailsScreenModel import eu.kanade.tachiyomi.util.system.LocaleHelper import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.components.material.DIVIDER_ALPHA @@ -65,7 +65,7 @@ import tachiyomi.presentation.core.screens.EmptyScreen @Composable fun ExtensionDetailsScreen( navigateUp: () -> Unit, - state: ExtensionDetailsState, + state: ExtensionDetailsScreenModel.State, onClickSourcePreferences: (sourceId: Long) -> Unit, onClickWhatsNew: () -> Unit, onClickReadme: () -> Unit, diff --git a/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt index 9e4e7857c..433add984 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt @@ -43,7 +43,7 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.ui.browse.extension.ExtensionUiModel -import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsState +import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsScreenModel import eu.kanade.tachiyomi.util.system.LocaleHelper import tachiyomi.presentation.core.components.FastScrollLazyColumn import tachiyomi.presentation.core.components.material.PullRefresh @@ -57,7 +57,7 @@ import tachiyomi.presentation.core.util.secondaryItemAlpha @Composable fun ExtensionScreen( - state: ExtensionsState, + state: ExtensionsScreenModel.State, contentPadding: PaddingValues, searchQuery: String?, onLongClickItem: (Extension) -> Unit, @@ -108,7 +108,7 @@ fun ExtensionScreen( @Composable private fun ExtensionContent( - state: ExtensionsState, + state: ExtensionsScreenModel.State, contentPadding: PaddingValues, onLongClickItem: (Extension) -> Unit, onClickItemCancel: (Extension) -> Unit, diff --git a/app/src/main/java/eu/kanade/presentation/browse/MigrateMangaScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/MigrateMangaScreen.kt index f3d72cb79..a896fb525 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/MigrateMangaScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/MigrateMangaScreen.kt @@ -8,7 +8,7 @@ import androidx.compose.ui.Modifier import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.manga.components.BaseMangaListItem import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.ui.browse.migration.manga.MigrateMangaState +import eu.kanade.tachiyomi.ui.browse.migration.manga.MigrateMangaScreenModel import tachiyomi.domain.manga.model.Manga import tachiyomi.presentation.core.components.FastScrollLazyColumn import tachiyomi.presentation.core.components.material.Scaffold @@ -18,7 +18,7 @@ import tachiyomi.presentation.core.screens.EmptyScreen fun MigrateMangaScreen( navigateUp: () -> Unit, title: String?, - state: MigrateMangaState, + state: MigrateMangaScreenModel.State, onClickItem: (Manga) -> Unit, onClickCover: (Manga) -> Unit, ) { @@ -51,7 +51,7 @@ fun MigrateMangaScreen( @Composable private fun MigrateMangaContent( contentPadding: PaddingValues, - state: MigrateMangaState, + state: MigrateMangaScreenModel.State, onClickItem: (Manga) -> Unit, onClickCover: (Manga) -> Unit, ) { diff --git a/app/src/main/java/eu/kanade/presentation/browse/MigrateSourceScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/MigrateSourceScreen.kt index bae685e2a..aaf23646a 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/MigrateSourceScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/MigrateSourceScreen.kt @@ -26,7 +26,7 @@ import eu.kanade.domain.source.interactor.SetMigrateSorting import eu.kanade.presentation.browse.components.BaseSourceItem import eu.kanade.presentation.browse.components.SourceIcon import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.ui.browse.migration.sources.MigrateSourceState +import eu.kanade.tachiyomi.ui.browse.migration.sources.MigrateSourceScreenModel import eu.kanade.tachiyomi.util.system.copyToClipboard import tachiyomi.domain.source.model.Source import tachiyomi.presentation.core.components.Badge @@ -43,7 +43,7 @@ import tachiyomi.presentation.core.util.secondaryItemAlpha @Composable fun MigrateSourceScreen( - state: MigrateSourceState, + state: MigrateSourceScreenModel.State, contentPadding: PaddingValues, onClickItem: (Source) -> Unit, onToggleSortingDirection: () -> Unit, diff --git a/app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt index 994642493..d72f8692e 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/SourcesFilterScreen.kt @@ -12,7 +12,7 @@ import eu.kanade.presentation.browse.components.BaseSourceItem import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.ui.browse.source.SourcesFilterState +import eu.kanade.tachiyomi.ui.browse.source.SourcesFilterScreenModel import eu.kanade.tachiyomi.util.system.LocaleHelper import tachiyomi.domain.source.model.Source import tachiyomi.presentation.core.components.FastScrollLazyColumn @@ -22,7 +22,7 @@ import tachiyomi.presentation.core.screens.EmptyScreen @Composable fun SourcesFilterScreen( navigateUp: () -> Unit, - state: SourcesFilterState.Success, + state: SourcesFilterScreenModel.State.Success, onClickLanguage: (String) -> Unit, onClickSource: (Source) -> Unit, ) { @@ -54,7 +54,7 @@ fun SourcesFilterScreen( @Composable private fun SourcesFilterContent( contentPadding: PaddingValues, - state: SourcesFilterState.Success, + state: SourcesFilterScreenModel.State.Success, onClickLanguage: (String) -> Unit, onClickSource: (Source) -> Unit, ) { diff --git a/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt index ff79134ce..12175e4bd 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt @@ -192,7 +192,7 @@ fun SourceOptionsDialog( ) } -sealed class SourceUiModel { - data class Item(val source: Source) : SourceUiModel() - data class Header(val language: String) : SourceUiModel() +sealed interface SourceUiModel { + data class Item(val source: Source) : SourceUiModel + data class Header(val language: String) : SourceUiModel } diff --git a/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt b/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt index e74a57aa9..3cd5be4f0 100644 --- a/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt @@ -20,7 +20,6 @@ import eu.kanade.presentation.components.SearchToolbar import eu.kanade.presentation.history.components.HistoryItem import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.history.HistoryScreenModel -import eu.kanade.tachiyomi.ui.history.HistoryState import tachiyomi.domain.history.model.HistoryWithRelations import tachiyomi.presentation.core.components.FastScrollLazyColumn import tachiyomi.presentation.core.components.material.Scaffold @@ -33,7 +32,7 @@ import java.util.Date @Composable fun HistoryScreen( - state: HistoryState, + state: HistoryScreenModel.State, snackbarHostState: SnackbarHostState, onSearchQueryChange: (String?) -> Unit, onClickCover: (mangaId: Long) -> Unit, @@ -139,7 +138,7 @@ private fun HistoryScreenContent( } } -sealed class HistoryUiModel { - data class Header(val date: Date) : HistoryUiModel() - data class Item(val item: HistoryWithRelations) : HistoryUiModel() +sealed interface HistoryUiModel { + data class Header(val date: Date) : HistoryUiModel + data class Item(val item: HistoryWithRelations) : HistoryUiModel } diff --git a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt index 7b2696561..03030cb4e 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt @@ -62,7 +62,7 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.source.getNameForMangaInfo import eu.kanade.tachiyomi.ui.manga.ChapterItem -import eu.kanade.tachiyomi.ui.manga.MangaScreenState +import eu.kanade.tachiyomi.ui.manga.MangaScreenModel import eu.kanade.tachiyomi.util.lang.toRelativeString import eu.kanade.tachiyomi.util.system.copyToClipboard import tachiyomi.domain.chapter.model.Chapter @@ -82,7 +82,7 @@ import java.util.Date @Composable fun MangaScreen( - state: MangaScreenState.Success, + state: MangaScreenModel.State.Success, snackbarHostState: SnackbarHostState, dateRelativeTime: Int, dateFormat: DateFormat, @@ -210,7 +210,7 @@ fun MangaScreen( @Composable private fun MangaScreenSmallImpl( - state: MangaScreenState.Success, + state: MangaScreenModel.State.Success, snackbarHostState: SnackbarHostState, dateRelativeTime: Int, dateFormat: DateFormat, @@ -436,7 +436,7 @@ private fun MangaScreenSmallImpl( @Composable fun MangaScreenLargeImpl( - state: MangaScreenState.Success, + state: MangaScreenModel.State.Success, snackbarHostState: SnackbarHostState, dateRelativeTime: Int, dateFormat: DateFormat, diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearDatabaseScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearDatabaseScreen.kt index 3772e4677..013a7fa1b 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearDatabaseScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearDatabaseScreen.kt @@ -19,6 +19,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope @@ -269,12 +270,15 @@ private class ClearDatabaseScreenModel : StateScreenModel, val selection: List = emptyList(), val showConfirmation: Boolean = false, - ) : State() + ) : State } } diff --git a/app/src/main/java/eu/kanade/presentation/more/stats/StatsScreenState.kt b/app/src/main/java/eu/kanade/presentation/more/stats/StatsScreenState.kt index aaa535194..c490a5381 100644 --- a/app/src/main/java/eu/kanade/presentation/more/stats/StatsScreenState.kt +++ b/app/src/main/java/eu/kanade/presentation/more/stats/StatsScreenState.kt @@ -3,9 +3,9 @@ package eu.kanade.presentation.more.stats import androidx.compose.runtime.Immutable import eu.kanade.presentation.more.stats.data.StatsData -sealed class StatsScreenState { +sealed interface StatsScreenState { @Immutable - data object Loading : StatsScreenState() + data object Loading : StatsScreenState @Immutable data class Success( @@ -13,5 +13,5 @@ sealed class StatsScreenState { val titles: StatsData.Titles, val chapters: StatsData.Chapters, val trackers: StatsData.Trackers, - ) : StatsScreenState() + ) : StatsScreenState } diff --git a/app/src/main/java/eu/kanade/presentation/more/stats/data/StatsData.kt b/app/src/main/java/eu/kanade/presentation/more/stats/data/StatsData.kt index 98143f887..8ea31cd9c 100644 --- a/app/src/main/java/eu/kanade/presentation/more/stats/data/StatsData.kt +++ b/app/src/main/java/eu/kanade/presentation/more/stats/data/StatsData.kt @@ -1,28 +1,28 @@ package eu.kanade.presentation.more.stats.data -sealed class StatsData { +sealed interface StatsData { data class Overview( val libraryMangaCount: Int, val completedMangaCount: Int, val totalReadDuration: Long, - ) : StatsData() + ) : StatsData data class Titles( val globalUpdateItemCount: Int, val startedMangaCount: Int, val localMangaCount: Int, - ) : StatsData() + ) : StatsData data class Chapters( val totalChapterCount: Int, val readChapterCount: Int, val downloadCount: Int, - ) : StatsData() + ) : StatsData data class Trackers( val trackedTitleCount: Int, val meanScore: Double, val trackerCount: Int, - ) : StatsData() + ) : StatsData } diff --git a/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt b/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt index 010e84995..a896e8d58 100644 --- a/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt @@ -28,7 +28,7 @@ import eu.kanade.presentation.manga.components.MangaBottomActionMenu import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.ui.updates.UpdatesItem -import eu.kanade.tachiyomi.ui.updates.UpdatesState +import eu.kanade.tachiyomi.ui.updates.UpdatesScreenModel import kotlinx.coroutines.delay import kotlinx.coroutines.launch import tachiyomi.presentation.core.components.FastScrollLazyColumn @@ -40,7 +40,7 @@ import kotlin.time.Duration.Companion.seconds @Composable fun UpdateScreen( - state: UpdatesState, + state: UpdatesScreenModel.State, snackbarHostState: SnackbarHostState, lastUpdated: Long, relativeTime: Int, @@ -209,7 +209,7 @@ private fun UpdatesBottomBar( ) } -sealed class UpdatesUiModel { - data class Header(val date: String) : UpdatesUiModel() - data class Item(val item: UpdatesItem) : UpdatesUiModel() +sealed interface UpdatesUiModel { + data class Header(val date: String) : UpdatesUiModel + data class Item(val item: UpdatesItem) : UpdatesUiModel } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/saver/ImageSaver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/saver/ImageSaver.kt index b0ce4e3f8..9656c0fd9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/saver/ImageSaver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/saver/ImageSaver.kt @@ -152,8 +152,8 @@ sealed class Image( } } -sealed class Location { - data class Pictures private constructor(val relativePath: String) : Location() { +sealed interface Location { + data class Pictures private constructor(val relativePath: String) : Location { companion object { fun create(relativePath: String = ""): Pictures { return Pictures(relativePath) @@ -161,7 +161,7 @@ sealed class Location { } } - data object Cache : Location() + data object Cache : Location fun directory(context: Context): File { return when (this) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/model/LoadResult.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/model/LoadResult.kt index 7f2ef4efd..98da1710e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/model/LoadResult.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/model/LoadResult.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.extension.model -sealed class LoadResult { - data class Success(val extension: Extension.Installed) : LoadResult() - data class Untrusted(val extension: Extension.Untrusted) : LoadResult() - data object Error : LoadResult() +sealed interface LoadResult { + data class Success(val extension: Extension.Installed) : LoadResult + data class Untrusted(val extension: Extension.Untrusted) : LoadResult + data object Error : LoadResult } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionFilterScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionFilterScreenModel.kt index 973d85eb6..bb8116428 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionFilterScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionFilterScreenModel.kt @@ -54,20 +54,20 @@ class ExtensionFilterScreenModel( } } -sealed class ExtensionFilterEvent { - data object FailedFetchingLanguages : ExtensionFilterEvent() +sealed interface ExtensionFilterEvent { + data object FailedFetchingLanguages : ExtensionFilterEvent } -sealed class ExtensionFilterState { +sealed interface ExtensionFilterState { @Immutable - data object Loading : ExtensionFilterState() + data object Loading : ExtensionFilterState @Immutable data class Success( val languages: List, val enabledLanguages: Set = emptySet(), - ) : ExtensionFilterState() { + ) : ExtensionFilterState { val isEmpty: Boolean get() = languages.isEmpty() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsScreenModel.kt index 6f8c0579f..ca3a01745 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsScreenModel.kt @@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.extension import android.app.Application import androidx.annotation.StringRes +import androidx.compose.runtime.Immutable import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.coroutineScope import eu.kanade.domain.extension.interactor.GetExtensionsByType @@ -35,7 +36,7 @@ class ExtensionsScreenModel( preferences: SourcePreferences = Injekt.get(), private val extensionManager: ExtensionManager = Injekt.get(), private val getExtensions: GetExtensionsByType = Injekt.get(), -) : StateScreenModel(ExtensionsState()) { +) : StateScreenModel(State()) { private var _currentDownloads = MutableStateFlow>(hashMapOf()) @@ -190,16 +191,17 @@ class ExtensionsScreenModel( fun trustSignature(signatureHash: String) { extensionManager.trustSignature(signatureHash) } -} -data class ExtensionsState( - val isLoading: Boolean = true, - val isRefreshing: Boolean = false, - val items: ItemGroups = mutableMapOf(), - val updates: Int = 0, - val searchQuery: String? = null, -) { - val isEmpty = items.isEmpty() + @Immutable + data class State( + val isLoading: Boolean = true, + val isRefreshing: Boolean = false, + val items: ItemGroups = mutableMapOf(), + val updates: Int = 0, + val searchQuery: String? = null, + ) { + val isEmpty = items.isEmpty() + } } typealias ItemGroups = MutableMap> diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsScreenModel.kt index fbb7513b5..60247d244 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsScreenModel.kt @@ -38,7 +38,7 @@ class ExtensionDetailsScreenModel( private val extensionManager: ExtensionManager = Injekt.get(), private val getExtensionSources: GetExtensionSources = Injekt.get(), private val toggleSource: ToggleSource = Injekt.get(), -) : StateScreenModel(ExtensionDetailsState()) { +) : StateScreenModel(State()) { private val _events: Channel = Channel() val events: Flow = _events.receiveAsFlow() @@ -160,21 +160,21 @@ class ExtensionDetailsScreenModel( url + "/src/" + pkgName.replace(".", "/") + path } } + + @Immutable + data class State( + val extension: Extension.Installed? = null, + private val _sources: List? = null, + ) { + + val sources: List + get() = _sources.orEmpty() + + val isLoading: Boolean + get() = extension == null || _sources == null + } } -sealed class ExtensionDetailsEvent { - data object Uninstalled : ExtensionDetailsEvent() -} - -@Immutable -data class ExtensionDetailsState( - val extension: Extension.Installed? = null, - private val _sources: List? = null, -) { - - val sources: List - get() = _sources.orEmpty() - - val isLoading: Boolean - get() = extension == null || _sources == null +sealed interface ExtensionDetailsEvent { + data object Uninstalled : ExtensionDetailsEvent } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrationMangaScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrateMangaScreen.kt similarity index 93% rename from app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrationMangaScreen.kt rename to app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrateMangaScreen.kt index 938845096..8f4de4d95 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrationMangaScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrateMangaScreen.kt @@ -17,7 +17,7 @@ import eu.kanade.tachiyomi.util.system.toast import kotlinx.coroutines.flow.collectLatest import tachiyomi.presentation.core.screens.LoadingScreen -data class MigrationMangaScreen( +data class MigrateMangaScreen( private val sourceId: Long, ) : Screen() { @@ -25,7 +25,7 @@ data class MigrationMangaScreen( override fun Content() { val context = LocalContext.current val navigator = LocalNavigator.currentOrThrow - val screenModel = rememberScreenModel { MigrationMangaScreenModel(sourceId) } + val screenModel = rememberScreenModel { MigrateMangaScreenModel(sourceId) } val state by screenModel.state.collectAsState() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrationMangaScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrateMangaScreenModel.kt similarity index 77% rename from app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrationMangaScreenModel.kt rename to app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrateMangaScreenModel.kt index 62c81613a..7485a22df 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrationMangaScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrateMangaScreenModel.kt @@ -20,11 +20,11 @@ import tachiyomi.domain.source.service.SourceManager import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get -class MigrationMangaScreenModel( +class MigrateMangaScreenModel( private val sourceId: Long, private val sourceManager: SourceManager = Injekt.get(), private val getFavorites: GetFavorites = Injekt.get(), -) : StateScreenModel(MigrateMangaState()) { +) : StateScreenModel(State()) { private val _events: Channel = Channel() val events: Flow = _events.receiveAsFlow() @@ -51,24 +51,24 @@ class MigrationMangaScreenModel( } } } + + @Immutable + data class State( + val source: Source? = null, + private val titleList: List? = null, + ) { + + val titles: List + get() = titleList.orEmpty() + + val isLoading: Boolean + get() = source == null || titleList == null + + val isEmpty: Boolean + get() = titles.isEmpty() + } } -sealed class MigrationMangaEvent { - data object FailedFetchingFavorites : MigrationMangaEvent() -} - -@Immutable -data class MigrateMangaState( - val source: Source? = null, - private val titleList: List? = null, -) { - - val titles: List - get() = titleList.orEmpty() - - val isLoading: Boolean - get() = source == null || titleList == null - - val isEmpty: Boolean - get() = titles.isEmpty() +sealed interface MigrationMangaEvent { + data object FailedFetchingFavorites : MigrationMangaEvent } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreenDialogScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreenDialogScreenModel.kt index 0bd9bda89..887d35feb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreenDialogScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreenDialogScreenModel.kt @@ -37,7 +37,7 @@ class MigrateSearchScreenDialogScreenModel( val dialog: Dialog? = null, ) - sealed class Dialog { - data class Migrate(val manga: Manga) : Dialog() + sealed interface Dialog { + data class Migrate(val manga: Manga) : Dialog } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrateSourceScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrateSourceScreenModel.kt index b1e251a67..f6b4b0441 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrateSourceScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrateSourceScreenModel.kt @@ -1,5 +1,6 @@ package eu.kanade.tachiyomi.ui.browse.migration.sources +import androidx.compose.runtime.Immutable import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.coroutineScope import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount @@ -23,7 +24,7 @@ class MigrateSourceScreenModel( preferences: SourcePreferences = Injekt.get(), private val getSourcesWithFavoriteCount: GetSourcesWithFavoriteCount = Injekt.get(), private val setMigrateSorting: SetMigrateSorting = Injekt.get(), -) : StateScreenModel(MigrateSourceState()) { +) : StateScreenModel(State()) { private val _channel = Channel(Int.MAX_VALUE) val channel = _channel.receiveAsFlow() @@ -76,16 +77,17 @@ class MigrateSourceScreenModel( } } - sealed class Event { - data object FailedFetchingSourcesWithCount : Event() + @Immutable + data class State( + val isLoading: Boolean = true, + val items: List> = emptyList(), + val sortingMode: SetMigrateSorting.Mode = SetMigrateSorting.Mode.ALPHABETICAL, + val sortingDirection: SetMigrateSorting.Direction = SetMigrateSorting.Direction.ASCENDING, + ) { + val isEmpty = items.isEmpty() + } + + sealed interface Event { + data object FailedFetchingSourcesWithCount : Event } } - -data class MigrateSourceState( - val isLoading: Boolean = true, - val items: List> = emptyList(), - val sortingMode: SetMigrateSorting.Mode = SetMigrateSorting.Mode.ALPHABETICAL, - val sortingDirection: SetMigrateSorting.Direction = SetMigrateSorting.Direction.ASCENDING, -) { - val isEmpty = items.isEmpty() -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrateSourceTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrateSourceTab.kt index 6b3c7a916..14dcd9756 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrateSourceTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrateSourceTab.kt @@ -15,7 +15,7 @@ import eu.kanade.presentation.browse.MigrateSourceScreen import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.TabContent import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.ui.browse.migration.manga.MigrationMangaScreen +import eu.kanade.tachiyomi.ui.browse.migration.manga.MigrateMangaScreen @Composable fun Screen.migrateSourceTab(): TabContent { @@ -40,7 +40,7 @@ fun Screen.migrateSourceTab(): TabContent { state = state, contentPadding = contentPadding, onClickItem = { source -> - navigator.push(MigrationMangaScreen(source.id)) + navigator.push(MigrateMangaScreen(source.id)) }, onToggleSortingDirection = screenModel::toggleSortingDirection, onToggleSortingMode = screenModel::toggleSortingMode, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreen.kt index 69a278d3b..f3480242d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreen.kt @@ -22,12 +22,12 @@ class SourcesFilterScreen : Screen() { val screenModel = rememberScreenModel { SourcesFilterScreenModel() } val state by screenModel.state.collectAsState() - if (state is SourcesFilterState.Loading) { + if (state is SourcesFilterScreenModel.State.Loading) { LoadingScreen() return } - if (state is SourcesFilterState.Error) { + if (state is SourcesFilterScreenModel.State.Error) { val context = LocalContext.current LaunchedEffect(Unit) { context.toast(R.string.internal_error) @@ -36,7 +36,7 @@ class SourcesFilterScreen : Screen() { return } - val successState = state as SourcesFilterState.Success + val successState = state as SourcesFilterScreenModel.State.Success SourcesFilterScreen( navigateUp = navigator::pop, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreenModel.kt index 0ff8035cb..618bf8bd5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreenModel.kt @@ -1,5 +1,6 @@ package eu.kanade.tachiyomi.ui.browse.source +import androidx.compose.runtime.Immutable import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.coroutineScope import eu.kanade.domain.source.interactor.GetLanguagesWithSources @@ -21,7 +22,7 @@ class SourcesFilterScreenModel( private val getLanguagesWithSources: GetLanguagesWithSources = Injekt.get(), private val toggleSource: ToggleSource = Injekt.get(), private val toggleLanguage: ToggleLanguage = Injekt.get(), -) : StateScreenModel(SourcesFilterState.Loading) { +) : StateScreenModel(State.Loading) { init { coroutineScope.launch { @@ -32,14 +33,14 @@ class SourcesFilterScreenModel( ) { a, b, c -> Triple(a, b, c) } .catch { throwable -> mutableState.update { - SourcesFilterState.Error( + State.Error( throwable = throwable, ) } } .collectLatest { (languagesWithSources, enabledLanguages, disabledSources) -> mutableState.update { - SourcesFilterState.Success( + State.Success( items = languagesWithSources, enabledLanguages = enabledLanguages, disabledSources = disabledSources, @@ -56,23 +57,26 @@ class SourcesFilterScreenModel( fun toggleLanguage(language: String) { toggleLanguage.await(language) } -} -sealed class SourcesFilterState { + sealed interface State { - data object Loading : SourcesFilterState() + @Immutable + data object Loading : State - data class Error( - val throwable: Throwable, - ) : SourcesFilterState() + @Immutable + data class Error( + val throwable: Throwable, + ) : State - data class Success( - val items: SortedMap>, - val enabledLanguages: Set, - val disabledSources: Set, - ) : SourcesFilterState() { + @Immutable + data class Success( + val items: SortedMap>, + val enabledLanguages: Set, + val disabledSources: Set, + ) : State { - val isEmpty: Boolean - get() = items.isEmpty() + val isEmpty: Boolean + get() = items.isEmpty() + } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesScreenModel.kt index 431ad50bd..d191fdf15 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesScreenModel.kt @@ -93,8 +93,8 @@ class SourcesScreenModel( mutableState.update { it.copy(dialog = null) } } - sealed class Event { - data object FailedFetchingSources : Event() + sealed interface Event { + data object FailedFetchingSources : Event } data class Dialog(val source: Source) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt index b69725dfd..91e98f80b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt @@ -365,15 +365,15 @@ class BrowseSourceScreenModel( } } - sealed class Dialog { - data object Filter : Dialog() - data class RemoveManga(val manga: Manga) : Dialog() - data class AddDuplicateManga(val manga: Manga, val duplicate: Manga) : Dialog() + sealed interface Dialog { + data object Filter : Dialog + data class RemoveManga(val manga: Manga) : Dialog + data class AddDuplicateManga(val manga: Manga, val duplicate: Manga) : Dialog data class ChangeMangaCategory( val manga: Manga, val initialSelection: List>, - ) : Dialog() - data class Migrate(val newManga: Manga) : Dialog() + ) : Dialog + data class Migrate(val newManga: Manga) : Dialog } @Immutable diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/SearchScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/SearchScreenModel.kt index 0ec404551..55c2e151b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/SearchScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/SearchScreenModel.kt @@ -190,16 +190,16 @@ enum class SourceFilter { PinnedOnly, } -sealed class SearchItemResult { - data object Loading : SearchItemResult() +sealed interface SearchItemResult { + data object Loading : SearchItemResult data class Error( val throwable: Throwable, - ) : SearchItemResult() + ) : SearchItemResult data class Success( val result: List, - ) : SearchItemResult() { + ) : SearchItemResult { val isEmpty: Boolean get() = result.isEmpty() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreenModel.kt index 01435fa23..45fbdcb4a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreenModel.kt @@ -107,27 +107,27 @@ class CategoryScreenModel( } } -sealed class CategoryDialog { - data object Create : CategoryDialog() - data class Rename(val category: Category) : CategoryDialog() - data class Delete(val category: Category) : CategoryDialog() +sealed interface CategoryDialog { + data object Create : CategoryDialog + data class Rename(val category: Category) : CategoryDialog + data class Delete(val category: Category) : CategoryDialog } -sealed class CategoryEvent { - sealed class LocalizedMessage(@StringRes val stringRes: Int) : CategoryEvent() +sealed interface CategoryEvent { + sealed class LocalizedMessage(@StringRes val stringRes: Int) : CategoryEvent data object InternalError : LocalizedMessage(R.string.internal_error) } -sealed class CategoryScreenState { +sealed interface CategoryScreenState { @Immutable - data object Loading : CategoryScreenState() + data object Loading : CategoryScreenState @Immutable data class Success( val categories: List, val dialog: CategoryDialog? = null, - ) : CategoryScreenState() { + ) : CategoryScreenState { val isEmpty: Boolean get() = categories.isEmpty() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryScreenModel.kt index 2d7160008..582f6a36c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryScreenModel.kt @@ -34,7 +34,7 @@ class HistoryScreenModel( private val getHistory: GetHistory = Injekt.get(), private val getNextChapters: GetNextChapters = Injekt.get(), private val removeHistory: RemoveHistory = Injekt.get(), -) : StateScreenModel(HistoryState()) { +) : StateScreenModel(State()) { private val _events: Channel = Channel(Channel.UNLIMITED) val events: Flow = _events.receiveAsFlow() @@ -113,21 +113,21 @@ class HistoryScreenModel( mutableState.update { it.copy(dialog = dialog) } } - sealed class Dialog { - data object DeleteAll : Dialog() - data class Delete(val history: HistoryWithRelations) : Dialog() + @Immutable + data class State( + val searchQuery: String? = null, + val list: List? = null, + val dialog: Dialog? = null, + ) + + sealed interface Dialog { + data object DeleteAll : Dialog + data class Delete(val history: HistoryWithRelations) : Dialog } - sealed class Event { - data class OpenChapter(val chapter: Chapter?) : Event() - data object InternalError : Event() - data object HistoryCleared : Event() + sealed interface Event { + data class OpenChapter(val chapter: Chapter?) : Event + data object InternalError : Event + data object HistoryCleared : Event } } - -@Immutable -data class HistoryState( - val searchQuery: String? = null, - val list: List? = null, - val dialog: HistoryScreenModel.Dialog? = null, -) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt index 439849263..2eb992478 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt @@ -291,11 +291,11 @@ object HomeScreen : Screen() { showBottomNavEvent.send(show) } - sealed class Tab { - data class Library(val mangaIdToOpen: Long? = null) : Tab() - data object Updates : Tab() - data object History : Tab() - data class Browse(val toExtensions: Boolean = false) : Tab() - data class More(val toDownloads: Boolean) : Tab() + sealed interface Tab { + data class Library(val mangaIdToOpen: Long? = null) : Tab + data object Updates : Tab + data object History : Tab + data class Browse(val toExtensions: Boolean = false) : Tab + data class More(val toDownloads: Boolean) : Tab } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt index 6b59322af..2441707fe 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt @@ -657,10 +657,10 @@ class LibraryScreenModel( mutableState.update { it.copy(dialog = null) } } - sealed class Dialog { - data object SettingsSheet : Dialog() - data class ChangeCategory(val manga: List, val initialSelection: List>) : Dialog() - data class DeleteManga(val manga: List) : Dialog() + sealed interface Dialog { + data object SettingsSheet : Dialog + data class ChangeCategory(val manga: List, val initialSelection: List>) : Dialog + data class DeleteManga(val manga: List) : Dialog } @Immutable diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt index 7792de3e8..2f21f7ef1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt @@ -75,12 +75,12 @@ class MangaScreen( val state by screenModel.state.collectAsState() - if (state is MangaScreenState.Loading) { + if (state is MangaScreenModel.State.Loading) { LoadingScreen() return } - val successState = state as MangaScreenState.Success + val successState = state as MangaScreenModel.State.Success val isHttpSource = remember { successState.source is HttpSource } LaunchedEffect(successState.manga, screenModel.source) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt index c1662c697..06b4a7088 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt @@ -98,10 +98,10 @@ class MangaScreenModel( private val getTracks: GetTracks = Injekt.get(), private val setMangaCategories: SetMangaCategories = Injekt.get(), val snackbarHostState: SnackbarHostState = SnackbarHostState(), -) : StateScreenModel(MangaScreenState.Loading) { +) : StateScreenModel(State.Loading) { - private val successState: MangaScreenState.Success? - get() = state.value as? MangaScreenState.Success + private val successState: State.Success? + get() = state.value as? State.Success private val loggedServices by lazy { trackManager.services.filter { it.isLogged } } @@ -133,11 +133,11 @@ class MangaScreenModel( /** * Helper function to update the UI state only if it's currently in success state */ - private inline fun updateSuccessState(func: (MangaScreenState.Success) -> MangaScreenState.Success) { + private inline fun updateSuccessState(func: (State.Success) -> State.Success) { mutableState.update { when (it) { - MangaScreenState.Loading -> it - is MangaScreenState.Success -> func(it) + State.Loading -> it + is State.Success -> func(it) } } } @@ -175,7 +175,7 @@ class MangaScreenModel( // Show what we have earlier mutableState.update { - MangaScreenState.Success( + State.Success( manga = manga, source = Injekt.get().getOrStub(manga.source), isFromSource = isFromSource, @@ -334,8 +334,7 @@ class MangaScreenModel( } fun promptChangeCategories() { - val state = successState ?: return - val manga = state.manga + val manga = successState?.manga ?: return coroutineScope.launch { val categories = getCategories() val selection = getMangaCategoryIds(manga) @@ -662,9 +661,9 @@ class MangaScreenModel( } fun markPreviousChapterRead(pointer: Chapter) { - val successState = successState ?: return + val manga = successState?.manga ?: return val chapters = filteredChapters.orEmpty().map { it.chapter } - val prevChapters = if (successState.manga.sortDescending()) chapters.asReversed() else chapters + val prevChapters = if (manga.sortDescending()) chapters.asReversed() else chapters val pointerPos = prevChapters.indexOf(pointer) if (pointerPos != -1) markChaptersRead(prevChapters.take(pointerPos), true) } @@ -940,13 +939,13 @@ class MangaScreenModel( // Track sheet - end - sealed class Dialog { - data class ChangeCategory(val manga: Manga, val initialSelection: List>) : Dialog() - data class DeleteChapters(val chapters: List) : Dialog() - data class DuplicateManga(val manga: Manga, val duplicate: Manga) : Dialog() - data object SettingsSheet : Dialog() - data object TrackSheet : Dialog() - data object FullCover : Dialog() + sealed interface Dialog { + data class ChangeCategory(val manga: Manga, val initialSelection: List>) : Dialog + data class DeleteChapters(val chapters: List) : Dialog + data class DuplicateManga(val manga: Manga, val duplicate: Manga) : Dialog + data object SettingsSheet : Dialog + data object TrackSheet : Dialog + data object FullCover : Dialog } fun dismissDialog() { @@ -968,48 +967,48 @@ class MangaScreenModel( fun showCoverDialog() { updateSuccessState { it.copy(dialog = Dialog.FullCover) } } -} -sealed class MangaScreenState { - @Immutable - object Loading : MangaScreenState() + sealed interface State { + @Immutable + object Loading : State - @Immutable - data class Success( - val manga: Manga, - val source: Source, - val isFromSource: Boolean, - val chapters: List, - val trackItems: List = emptyList(), - val isRefreshingData: Boolean = false, - val dialog: MangaScreenModel.Dialog? = null, - val hasPromptedToAddBefore: Boolean = false, - ) : MangaScreenState() { + @Immutable + data class Success( + val manga: Manga, + val source: Source, + val isFromSource: Boolean, + val chapters: List, + val trackItems: List = emptyList(), + val isRefreshingData: Boolean = false, + val dialog: Dialog? = null, + val hasPromptedToAddBefore: Boolean = false, + ) : State { - val processedChapters by lazy { - chapters.applyFilters(manga).toList() - } + val processedChapters by lazy { + chapters.applyFilters(manga).toList() + } - val trackingAvailable: Boolean - get() = trackItems.isNotEmpty() + val trackingAvailable: Boolean + get() = trackItems.isNotEmpty() - val trackingCount: Int - get() = trackItems.count { it.track != null } + val trackingCount: Int + get() = trackItems.count { it.track != null } - /** - * Applies the view filters to the list of chapters obtained from the database. - * @return an observable of the list of chapters filtered and sorted. - */ - private fun List.applyFilters(manga: Manga): Sequence { - val isLocalManga = manga.isLocal() - val unreadFilter = manga.unreadFilter - val downloadedFilter = manga.downloadedFilter - val bookmarkedFilter = manga.bookmarkedFilter - return asSequence() - .filter { (chapter) -> applyFilter(unreadFilter) { !chapter.read } } - .filter { (chapter) -> applyFilter(bookmarkedFilter) { chapter.bookmark } } - .filter { applyFilter(downloadedFilter) { it.isDownloaded || isLocalManga } } - .sortedWith { (chapter1), (chapter2) -> getChapterSort(manga).invoke(chapter1, chapter2) } + /** + * Applies the view filters to the list of chapters obtained from the database. + * @return an observable of the list of chapters filtered and sorted. + */ + private fun List.applyFilters(manga: Manga): Sequence { + val isLocalManga = manga.isLocal() + val unreadFilter = manga.unreadFilter + val downloadedFilter = manga.downloadedFilter + val bookmarkedFilter = manga.bookmarkedFilter + return asSequence() + .filter { (chapter) -> applyFilter(unreadFilter) { !chapter.read } } + .filter { (chapter) -> applyFilter(bookmarkedFilter) { chapter.bookmark } } + .filter { applyFilter(downloadedFilter) { it.isDownloaded || isLocalManga } } + .sortedWith { (chapter1), (chapter2) -> getChapterSort(manga).invoke(chapter1, chapter2) } + } } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreTab.kt index d587334ce..ed09839b0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreTab.kt @@ -108,8 +108,8 @@ private class MoreScreenModel( } } -sealed class DownloadQueueState { - data object Stopped : DownloadQueueState() - data class Paused(val pending: Int) : DownloadQueueState() - data class Downloading(val pending: Int) : DownloadQueueState() +sealed interface DownloadQueueState { + data object Stopped : DownloadQueueState + data class Paused(val pending: Int) : DownloadQueueState + data class Downloading(val pending: Int) : DownloadQueueState } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt index 1d9f4bf0f..7da721c58 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt @@ -798,9 +798,9 @@ class ReaderViewModel( Error, } - sealed class SaveImageResult { - class Success(val uri: Uri) : SaveImageResult() - class Error(val error: Throwable) : SaveImageResult() + sealed interface SaveImageResult { + class Success(val uri: Uri) : SaveImageResult + class Error(val error: Throwable) : SaveImageResult } /** @@ -860,18 +860,18 @@ class ReaderViewModel( get() = viewerChapters?.currChapter?.pages?.size ?: -1 } - sealed class Dialog { - data object Loading : Dialog() - data object Settings : Dialog() - data class PageActions(val page: ReaderPage) : Dialog() + sealed interface Dialog { + data object Loading : Dialog + data object Settings : Dialog + data class PageActions(val page: ReaderPage) : Dialog } - sealed class Event { - data object ReloadViewerChapters : Event() - data class SetOrientation(val orientation: Int) : Event() - data class SetCoverResult(val result: SetAsCoverResult) : Event() + sealed interface Event { + data object ReloadViewerChapters : Event + data class SetOrientation(val orientation: Int) : Event + data class SetCoverResult(val result: SetAsCoverResult) : Event - data class SavedImage(val result: SaveImageResult) : Event() - data class ShareImage(val uri: Uri, val page: ReaderPage) : Event() + data class SavedImage(val result: SaveImageResult) : Event + data class ShareImage(val uri: Uri, val page: ReaderPage) : Event } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/model/ReaderChapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/model/ReaderChapter.kt index b02793015..af32c11b3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/model/ReaderChapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/model/ReaderChapter.kt @@ -39,10 +39,10 @@ data class ReaderChapter(val chapter: Chapter) { } } - sealed class State { - data object Wait : State() - data object Loading : State() - data class Error(val error: Throwable) : State() - data class Loaded(val pages: List) : State() + sealed interface State { + data object Wait : State + data object Loading : State + data class Error(val error: Throwable) : State + data class Loaded(val pages: List) : State } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesScreenModel.kt index 66f8250d4..5986aba47 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesScreenModel.kt @@ -60,7 +60,7 @@ class UpdatesScreenModel( private val libraryPreferences: LibraryPreferences = Injekt.get(), val snackbarHostState: SnackbarHostState = SnackbarHostState(), uiPreferences: UiPreferences = Injekt.get(), -) : StateScreenModel(UpdatesState()) { +) : StateScreenModel(State()) { private val _events: Channel = Channel(Int.MAX_VALUE) val events: Flow = _events.receiveAsFlow() @@ -366,46 +366,46 @@ class UpdatesScreenModel( libraryPreferences.newUpdatesCount().set(0) } - sealed class Dialog { - data class DeleteConfirmation(val toDelete: List) : Dialog() - } + @Immutable + data class State( + val isLoading: Boolean = true, + val items: List = emptyList(), + val dialog: UpdatesScreenModel.Dialog? = null, + ) { + val selected = items.filter { it.selected } + val selectionMode = selected.isNotEmpty() - sealed class Event { - data object InternalError : Event() - data class LibraryUpdateTriggered(val started: Boolean) : Event() - } -} + fun getUiModel(context: Context, relativeTime: Int): List { + val dateFormat by mutableStateOf(UiPreferences.dateFormat(Injekt.get().dateFormat().get())) -@Immutable -data class UpdatesState( - val isLoading: Boolean = true, - val items: List = emptyList(), - val dialog: UpdatesScreenModel.Dialog? = null, -) { - val selected = items.filter { it.selected } - val selectionMode = selected.isNotEmpty() - - fun getUiModel(context: Context, relativeTime: Int): List { - val dateFormat by mutableStateOf(UiPreferences.dateFormat(Injekt.get().dateFormat().get())) - - return items - .map { UpdatesUiModel.Item(it) } - .insertSeparators { before, after -> - val beforeDate = before?.item?.update?.dateFetch?.toDateKey() ?: Date(0) - val afterDate = after?.item?.update?.dateFetch?.toDateKey() ?: Date(0) - when { - beforeDate.time != afterDate.time && afterDate.time != 0L -> { - val text = afterDate.toRelativeString( - context = context, - range = relativeTime, - dateFormat = dateFormat, - ) - UpdatesUiModel.Header(text) + return items + .map { UpdatesUiModel.Item(it) } + .insertSeparators { before, after -> + val beforeDate = before?.item?.update?.dateFetch?.toDateKey() ?: Date(0) + val afterDate = after?.item?.update?.dateFetch?.toDateKey() ?: Date(0) + when { + beforeDate.time != afterDate.time && afterDate.time != 0L -> { + val text = afterDate.toRelativeString( + context = context, + range = relativeTime, + dateFormat = dateFormat, + ) + UpdatesUiModel.Header(text) + } + // Return null to avoid adding a separator between two items. + else -> null } - // Return null to avoid adding a separator between two items. - else -> null } - } + } + } + + sealed interface Dialog { + data class DeleteConfirmation(val toDelete: List) : Dialog + } + + sealed interface Event { + data object InternalError : Event + data class LibraryUpdateTriggered(val started: Boolean) : Event } } diff --git a/domain/src/main/java/tachiyomi/domain/category/interactor/CreateCategoryWithName.kt b/domain/src/main/java/tachiyomi/domain/category/interactor/CreateCategoryWithName.kt index b497d2ff1..f8b4ba802 100644 --- a/domain/src/main/java/tachiyomi/domain/category/interactor/CreateCategoryWithName.kt +++ b/domain/src/main/java/tachiyomi/domain/category/interactor/CreateCategoryWithName.kt @@ -37,8 +37,8 @@ class CreateCategoryWithName( } } - sealed class Result { - data object Success : Result() - data class InternalError(val error: Throwable) : Result() + sealed interface Result { + data object Success : Result + data class InternalError(val error: Throwable) : Result } } diff --git a/domain/src/main/java/tachiyomi/domain/category/interactor/DeleteCategory.kt b/domain/src/main/java/tachiyomi/domain/category/interactor/DeleteCategory.kt index 287732768..8fee4d982 100644 --- a/domain/src/main/java/tachiyomi/domain/category/interactor/DeleteCategory.kt +++ b/domain/src/main/java/tachiyomi/domain/category/interactor/DeleteCategory.kt @@ -35,8 +35,8 @@ class DeleteCategory( } } - sealed class Result { - data object Success : Result() - data class InternalError(val error: Throwable) : Result() + sealed interface Result { + data object Success : Result + data class InternalError(val error: Throwable) : Result } } diff --git a/domain/src/main/java/tachiyomi/domain/category/interactor/RenameCategory.kt b/domain/src/main/java/tachiyomi/domain/category/interactor/RenameCategory.kt index eb06ec78a..1cbf5e276 100644 --- a/domain/src/main/java/tachiyomi/domain/category/interactor/RenameCategory.kt +++ b/domain/src/main/java/tachiyomi/domain/category/interactor/RenameCategory.kt @@ -28,8 +28,8 @@ class RenameCategory( suspend fun await(category: Category, name: String) = await(category.id, name) - sealed class Result { - data object Success : Result() - data class InternalError(val error: Throwable) : Result() + sealed interface Result { + data object Success : Result + data class InternalError(val error: Throwable) : Result } } diff --git a/domain/src/main/java/tachiyomi/domain/category/interactor/ReorderCategory.kt b/domain/src/main/java/tachiyomi/domain/category/interactor/ReorderCategory.kt index fb65b3f4a..af61400ab 100644 --- a/domain/src/main/java/tachiyomi/domain/category/interactor/ReorderCategory.kt +++ b/domain/src/main/java/tachiyomi/domain/category/interactor/ReorderCategory.kt @@ -57,10 +57,10 @@ class ReorderCategory( } } - sealed class Result { - data object Success : Result() - data object Unchanged : Result() - data class InternalError(val error: Throwable) : Result() + sealed interface Result { + data object Success : Result + data object Unchanged : Result + data class InternalError(val error: Throwable) : Result } private enum class MoveTo { diff --git a/domain/src/main/java/tachiyomi/domain/category/interactor/UpdateCategory.kt b/domain/src/main/java/tachiyomi/domain/category/interactor/UpdateCategory.kt index d6c91e1ef..65d6d31ce 100644 --- a/domain/src/main/java/tachiyomi/domain/category/interactor/UpdateCategory.kt +++ b/domain/src/main/java/tachiyomi/domain/category/interactor/UpdateCategory.kt @@ -17,8 +17,8 @@ class UpdateCategory( } } - sealed class Result { - data object Success : Result() - data class Error(val error: Exception) : Result() + sealed interface Result { + data object Success : Result + data class Error(val error: Exception) : Result } } diff --git a/domain/src/main/java/tachiyomi/domain/library/model/LibraryDisplayMode.kt b/domain/src/main/java/tachiyomi/domain/library/model/LibraryDisplayMode.kt index 7bda1b2f2..bc2fde0fb 100644 --- a/domain/src/main/java/tachiyomi/domain/library/model/LibraryDisplayMode.kt +++ b/domain/src/main/java/tachiyomi/domain/library/model/LibraryDisplayMode.kt @@ -1,11 +1,11 @@ package tachiyomi.domain.library.model -sealed class LibraryDisplayMode { +sealed interface LibraryDisplayMode { - data object CompactGrid : LibraryDisplayMode() - data object ComfortableGrid : LibraryDisplayMode() - data object List : LibraryDisplayMode() - data object CoverOnlyGrid : LibraryDisplayMode() + data object CompactGrid : LibraryDisplayMode + data object ComfortableGrid : LibraryDisplayMode + data object List : LibraryDisplayMode + data object CoverOnlyGrid : LibraryDisplayMode object Serializer { fun deserialize(serialized: String): LibraryDisplayMode { diff --git a/domain/src/main/java/tachiyomi/domain/release/interactor/GetApplicationRelease.kt b/domain/src/main/java/tachiyomi/domain/release/interactor/GetApplicationRelease.kt index 89950d30d..735782fd2 100644 --- a/domain/src/main/java/tachiyomi/domain/release/interactor/GetApplicationRelease.kt +++ b/domain/src/main/java/tachiyomi/domain/release/interactor/GetApplicationRelease.kt @@ -71,9 +71,9 @@ class GetApplicationRelease( val forceCheck: Boolean = false, ) - sealed class Result { - data class NewUpdate(val release: Release) : Result() - data object NoNewUpdate : Result() - data object ThirdPartyInstallation : Result() + sealed interface Result { + data class NewUpdate(val release: Release) : Result + data object NoNewUpdate : Result + data object ThirdPartyInstallation : Result } } diff --git a/source-local/src/commonMain/kotlin/tachiyomi/source/local/io/Format.kt b/source-local/src/commonMain/kotlin/tachiyomi/source/local/io/Format.kt index a73534f21..53406b5de 100644 --- a/source-local/src/commonMain/kotlin/tachiyomi/source/local/io/Format.kt +++ b/source-local/src/commonMain/kotlin/tachiyomi/source/local/io/Format.kt @@ -2,11 +2,11 @@ package tachiyomi.source.local.io import java.io.File -sealed class Format { - data class Directory(val file: File) : Format() - data class Zip(val file: File) : Format() - data class Rar(val file: File) : Format() - data class Epub(val file: File) : Format() +sealed interface Format { + data class Directory(val file: File) : Format + data class Zip(val file: File) : Format + data class Rar(val file: File) : Format + data class Epub(val file: File) : Format class UnknownFormatException : Exception()