Replace StateViewModel with explicit backing fields (#3763)
Assisted-by: Claude:claude-opus-5
This commit is contained in:
+15
-9
@@ -30,6 +30,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastMap
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
@@ -39,9 +40,10 @@ import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.update
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import tachiyomi.core.common.util.lang.launchIO
|
||||
import tachiyomi.core.common.util.lang.launchUI
|
||||
import tachiyomi.core.common.util.lang.toLong
|
||||
@@ -220,7 +222,11 @@ class ClearDatabaseScreen : Screen() {
|
||||
}
|
||||
}
|
||||
|
||||
class ClearDatabaseViewModel : StateViewModel<ClearDatabaseViewModel.State>(State.Loading) {
|
||||
class ClearDatabaseViewModel : ViewModel() {
|
||||
|
||||
val state: StateFlow<ClearDatabaseViewModel.State>
|
||||
field = MutableStateFlow<ClearDatabaseViewModel.State>(State.Loading)
|
||||
|
||||
private val getSourcesWithNonLibraryManga: GetSourcesWithNonLibraryManga = Injekt.get()
|
||||
private val database: Database = Injekt.get()
|
||||
|
||||
@@ -228,7 +234,7 @@ class ClearDatabaseViewModel : StateViewModel<ClearDatabaseViewModel.State>(Stat
|
||||
viewModelScope.launchIO {
|
||||
getSourcesWithNonLibraryManga.subscribe()
|
||||
.collectLatest { list ->
|
||||
mutableState.update { old ->
|
||||
state.update { old ->
|
||||
val items = list.sortedBy { it.name }
|
||||
when (old) {
|
||||
State.Loading -> State.Ready(items)
|
||||
@@ -245,7 +251,7 @@ class ClearDatabaseViewModel : StateViewModel<ClearDatabaseViewModel.State>(Stat
|
||||
database.historyQueries.removeResettedHistory()
|
||||
}
|
||||
|
||||
fun toggleSelection(source: Source) = mutableState.update { state ->
|
||||
fun toggleSelection(source: Source) = state.update { state ->
|
||||
if (state !is State.Ready) return@update state
|
||||
val mutableList = state.selection.toMutableList()
|
||||
if (mutableList.contains(source.id)) {
|
||||
@@ -256,17 +262,17 @@ class ClearDatabaseViewModel : StateViewModel<ClearDatabaseViewModel.State>(Stat
|
||||
state.copy(selection = mutableList)
|
||||
}
|
||||
|
||||
fun clearSelection() = mutableState.update { state ->
|
||||
fun clearSelection() = state.update { state ->
|
||||
if (state !is State.Ready) return@update state
|
||||
state.copy(selection = emptyList())
|
||||
}
|
||||
|
||||
fun selectAll() = mutableState.update { state ->
|
||||
fun selectAll() = state.update { state ->
|
||||
if (state !is State.Ready) return@update state
|
||||
state.copy(selection = state.items.fastMap { it.id })
|
||||
}
|
||||
|
||||
fun invertSelection() = mutableState.update { state ->
|
||||
fun invertSelection() = state.update { state ->
|
||||
if (state !is State.Ready) return@update state
|
||||
state.copy(
|
||||
selection = state.items
|
||||
@@ -275,12 +281,12 @@ class ClearDatabaseViewModel : StateViewModel<ClearDatabaseViewModel.State>(Stat
|
||||
)
|
||||
}
|
||||
|
||||
fun showConfirmation() = mutableState.update { state ->
|
||||
fun showConfirmation() = state.update { state ->
|
||||
if (state !is State.Ready) return@update state
|
||||
state.copy(showConfirmation = true)
|
||||
}
|
||||
|
||||
fun hideConfirmation() = mutableState.update { state ->
|
||||
fun hideConfirmation() = state.update { state ->
|
||||
if (state !is State.Ready) return@update state
|
||||
state.copy(showConfirmation = false)
|
||||
}
|
||||
|
||||
+8
-3
@@ -11,6 +11,7 @@ import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
@@ -22,8 +23,9 @@ import eu.kanade.tachiyomi.data.backup.create.BackupCreator
|
||||
import eu.kanade.tachiyomi.data.backup.create.BackupOptions
|
||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||
import tachiyomi.presentation.core.components.LazyColumnWithAction
|
||||
@@ -119,10 +121,13 @@ class CreateBackupScreen : Screen() {
|
||||
}
|
||||
}
|
||||
|
||||
class CreateBackupViewModel : StateViewModel<CreateBackupViewModel.State>(State()) {
|
||||
class CreateBackupViewModel : ViewModel() {
|
||||
|
||||
val state: StateFlow<CreateBackupViewModel.State>
|
||||
field = MutableStateFlow<CreateBackupViewModel.State>(State())
|
||||
|
||||
fun toggle(setter: (BackupOptions, Boolean) -> BackupOptions, enabled: Boolean) {
|
||||
mutableState.update {
|
||||
state.update {
|
||||
it.copy(
|
||||
options = setter(it.options, enabled),
|
||||
)
|
||||
|
||||
+9
-4
@@ -20,6 +20,7 @@ import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
@@ -33,8 +34,9 @@ import eu.kanade.tachiyomi.data.backup.BackupFileValidator
|
||||
import eu.kanade.tachiyomi.data.backup.restore.BackupRestoreJob
|
||||
import eu.kanade.tachiyomi.data.backup.restore.RestoreOptions
|
||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||
import tachiyomi.presentation.core.components.LazyColumnWithAction
|
||||
@@ -176,7 +178,10 @@ class RestoreBackupScreen(
|
||||
class RestoreBackupViewModel(
|
||||
private val context: Context,
|
||||
private val uri: String,
|
||||
) : StateViewModel<RestoreBackupViewModel.State>(State()) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<RestoreBackupViewModel.State>
|
||||
field = MutableStateFlow<RestoreBackupViewModel.State>(State())
|
||||
|
||||
companion object {
|
||||
val URI_KEY = CreationExtras.Key<String>()
|
||||
@@ -196,7 +201,7 @@ class RestoreBackupViewModel(
|
||||
}
|
||||
|
||||
fun toggle(setter: (RestoreOptions, Boolean) -> RestoreOptions, enabled: Boolean) {
|
||||
mutableState.update {
|
||||
state.update {
|
||||
it.copy(
|
||||
options = setter(it.options, enabled),
|
||||
)
|
||||
@@ -234,7 +239,7 @@ class RestoreBackupViewModel(
|
||||
}
|
||||
|
||||
private fun setError(error: Any?, canRestore: Boolean) {
|
||||
mutableState.update {
|
||||
state.update {
|
||||
it.copy(
|
||||
error = error,
|
||||
canRestore = canRestore,
|
||||
|
||||
+1
-2
@@ -8,7 +8,6 @@ import eu.kanade.domain.source.service.SourcePreferences
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SearchItemResult
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SearchViewModel
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.domain.manga.interactor.GetManga
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
@@ -46,7 +45,7 @@ class MigrateSearchViewModel(
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
val manga = getManga.await(mangaId)!!
|
||||
mutableState.update {
|
||||
updateState {
|
||||
it.copy(
|
||||
from = manga,
|
||||
searchQuery = manga.title,
|
||||
|
||||
+15
-10
@@ -6,6 +6,7 @@ import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
@@ -23,7 +24,9 @@ import eu.kanade.domain.track.interactor.AddTracks
|
||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.util.removeCovers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
@@ -31,7 +34,6 @@ import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import tachiyomi.core.common.preference.CheckboxState
|
||||
import tachiyomi.core.common.preference.mapAsCheckboxState
|
||||
import tachiyomi.core.common.util.lang.launchIO
|
||||
@@ -68,7 +70,10 @@ class BrowseSourceViewModel(
|
||||
private val updateManga: UpdateManga = Injekt.get(),
|
||||
private val addTracks: AddTracks = Injekt.get(),
|
||||
getIncognitoState: GetIncognitoState = Injekt.get(),
|
||||
) : StateViewModel<BrowseSourceViewModel.State>(State(Listing.valueOf(listingQuery))) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<BrowseSourceViewModel.State>
|
||||
field = MutableStateFlow<BrowseSourceViewModel.State>(State(Listing.valueOf(listingQuery)))
|
||||
|
||||
companion object {
|
||||
val SOURCE_ID_KEY = CreationExtras.Key<Long>()
|
||||
@@ -89,7 +94,7 @@ class BrowseSourceViewModel(
|
||||
val source = sourceManager.getOrStub(sourceId)
|
||||
|
||||
init {
|
||||
mutableState.update {
|
||||
state.update {
|
||||
var query: String? = null
|
||||
var listing = it.listing
|
||||
|
||||
@@ -142,15 +147,15 @@ class BrowseSourceViewModel(
|
||||
}
|
||||
|
||||
fun resetFilters() {
|
||||
mutableState.update { it.copy(filters = source.getFilterList()) }
|
||||
state.update { it.copy(filters = source.getFilterList()) }
|
||||
}
|
||||
|
||||
fun setListing(listing: Listing) {
|
||||
mutableState.update { it.copy(listing = listing, toolbarQuery = null) }
|
||||
state.update { it.copy(listing = listing, toolbarQuery = null) }
|
||||
}
|
||||
|
||||
fun setFilters(filters: FilterList) {
|
||||
mutableState.update {
|
||||
state.update {
|
||||
it.copy(
|
||||
filters = filters,
|
||||
)
|
||||
@@ -161,7 +166,7 @@ class BrowseSourceViewModel(
|
||||
val input = state.value.listing as? Listing.Search
|
||||
?: Listing.Search(query = null, filters = source.getFilterList())
|
||||
|
||||
mutableState.update {
|
||||
state.update {
|
||||
it.copy(
|
||||
listing = input.copy(
|
||||
query = query ?: input.query,
|
||||
@@ -201,7 +206,7 @@ class BrowseSourceViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
mutableState.update {
|
||||
state.update {
|
||||
val listing = if (genreExists) {
|
||||
Listing.Search(query = null, filters = defaultFilters)
|
||||
} else {
|
||||
@@ -310,11 +315,11 @@ class BrowseSourceViewModel(
|
||||
}
|
||||
|
||||
fun setDialog(dialog: Dialog?) {
|
||||
mutableState.update { it.copy(dialog = dialog) }
|
||||
state.update { it.copy(dialog = dialog) }
|
||||
}
|
||||
|
||||
fun setToolbarQuery(query: String?) {
|
||||
mutableState.update { it.copy(toolbarQuery = query) }
|
||||
state.update { it.copy(toolbarQuery = query) }
|
||||
}
|
||||
|
||||
sealed class Listing(open val query: String?, open val filters: FilterList) {
|
||||
|
||||
+20
-9
@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.browse.source.globalsearch
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.produceState
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
@@ -11,13 +12,14 @@ import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import mihon.domain.manga.model.toDomainManga
|
||||
import tachiyomi.core.common.preference.toggle
|
||||
import tachiyomi.core.common.util.lang.launchIO
|
||||
@@ -37,7 +39,16 @@ abstract class SearchViewModel(
|
||||
private val networkToLocalManga: NetworkToLocalManga = Injekt.get(),
|
||||
private val getManga: GetManga = Injekt.get(),
|
||||
private val preferences: SourcePreferences = Injekt.get(),
|
||||
) : StateViewModel<SearchViewModel.State>(initialState) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<State>
|
||||
field = MutableStateFlow<State>(initialState)
|
||||
|
||||
// Subclasses can't touch the backing field (Kotlin forbids a visibility modifier on one),
|
||||
// so state writes from them go through here.
|
||||
protected fun updateState(function: (State) -> State) {
|
||||
state.update(function)
|
||||
}
|
||||
|
||||
private val coroutineDispatcher = Executors.newFixedThreadPool(5).asCoroutineDispatcher()
|
||||
private var searchJob: Job? = null
|
||||
@@ -61,8 +72,8 @@ abstract class SearchViewModel(
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
preferences.globalSearchFilterState.changes().collectLatest { state ->
|
||||
mutableState.update { it.copy(onlyShowHasResults = state) }
|
||||
preferences.globalSearchFilterState.changes().collectLatest { onlyShowHasResults ->
|
||||
state.update { it.copy(onlyShowHasResults = onlyShowHasResults) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,11 +115,11 @@ abstract class SearchViewModel(
|
||||
}
|
||||
|
||||
fun updateSearchQuery(query: String?) {
|
||||
mutableState.update { it.copy(searchQuery = query) }
|
||||
state.update { it.copy(searchQuery = query) }
|
||||
}
|
||||
|
||||
fun setSourceFilter(filter: SourceFilter) {
|
||||
mutableState.update { it.copy(sourceFilter = filter) }
|
||||
state.update { it.copy(sourceFilter = filter) }
|
||||
search()
|
||||
}
|
||||
|
||||
@@ -178,7 +189,7 @@ abstract class SearchViewModel(
|
||||
}
|
||||
|
||||
private fun updateItems(items: Map<Source, SearchItemResult>) {
|
||||
mutableState.update {
|
||||
state.update {
|
||||
it.copy(
|
||||
items = items
|
||||
.toSortedMap(sortComparator(items)),
|
||||
@@ -193,12 +204,12 @@ abstract class SearchViewModel(
|
||||
fun setMigrateDialog(currentId: Long, target: Manga) {
|
||||
viewModelScope.launchIO {
|
||||
val current = getManga.await(currentId) ?: return@launchIO
|
||||
mutableState.update { it.copy(dialog = Dialog.Migrate(target, current)) }
|
||||
state.update { it.copy(dialog = Dialog.Migrate(target, current)) }
|
||||
}
|
||||
}
|
||||
|
||||
fun clearDialog() {
|
||||
mutableState.update { it.copy(dialog = null) }
|
||||
state.update { it.copy(dialog = null) }
|
||||
}
|
||||
|
||||
@Immutable
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package eu.kanade.tachiyomi.ui.deeplink
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
@@ -9,8 +10,9 @@ import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.online.ResolvableSource
|
||||
import eu.kanade.tachiyomi.source.online.UriType
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import mihon.domain.manga.model.toDomainManga
|
||||
import mihon.domain.source.interactor.UpdateMangaFromRemote
|
||||
import tachiyomi.core.common.util.lang.launchIO
|
||||
@@ -28,7 +30,10 @@ class DeepLinkViewModel(
|
||||
private val networkToLocalManga: NetworkToLocalManga = Injekt.get(),
|
||||
private val getChapterByUrlAndMangaId: GetChapterByUrlAndMangaId = Injekt.get(),
|
||||
private val updateMangaFromRemote: UpdateMangaFromRemote = Injekt.get(),
|
||||
) : StateViewModel<DeepLinkViewModel.State>(State.Loading) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<DeepLinkViewModel.State>
|
||||
field = MutableStateFlow<DeepLinkViewModel.State>(State.Loading)
|
||||
|
||||
companion object {
|
||||
val QUERY_KEY = CreationExtras.Key<String>()
|
||||
@@ -58,7 +63,7 @@ class DeepLinkViewModel(
|
||||
null
|
||||
}
|
||||
|
||||
mutableState.update {
|
||||
state.update {
|
||||
if (manga == null) {
|
||||
State.NoResults
|
||||
} else {
|
||||
|
||||
@@ -8,6 +8,7 @@ import androidx.compose.material3.SnackbarResult
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.util.fastAny
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
@@ -41,6 +42,8 @@ import eu.kanade.tachiyomi.util.chapter.getNextUnread
|
||||
import eu.kanade.tachiyomi.util.removeCovers
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
@@ -50,7 +53,6 @@ import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import logcat.LogPriority
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import mihon.domain.chapter.interactor.FilterChaptersForDownload
|
||||
import mihon.domain.source.interactor.UpdateMangaFromRemote
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
@@ -116,7 +118,10 @@ class MangaViewModel(
|
||||
private val filterChaptersForDownload: FilterChaptersForDownload = Injekt.get(),
|
||||
private val updateMangaFromRemote: UpdateMangaFromRemote = Injekt.get(),
|
||||
val snackbarHostState: SnackbarHostState = SnackbarHostState(),
|
||||
) : StateViewModel<MangaViewModel.State>(State.Loading) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<State>
|
||||
field = MutableStateFlow<State>(State.Loading)
|
||||
|
||||
companion object {
|
||||
val MANGA_ID_KEY = CreationExtras.Key<Long>()
|
||||
@@ -168,7 +173,7 @@ class MangaViewModel(
|
||||
* Helper function to update the UI state only if it's currently in success state
|
||||
*/
|
||||
private inline fun updateSuccessState(func: (State.Success) -> State.Success) {
|
||||
mutableState.update {
|
||||
state.update {
|
||||
when (it) {
|
||||
State.Loading -> it
|
||||
is State.Success -> func(it)
|
||||
@@ -228,7 +233,7 @@ class MangaViewModel(
|
||||
val needRefreshChapter = chapters.isEmpty()
|
||||
|
||||
// Show what we have earlier
|
||||
mutableState.update {
|
||||
state.update {
|
||||
State.Success(
|
||||
manga = manga,
|
||||
source = Injekt.get<SourceManager>().getOrStub(manga.source),
|
||||
|
||||
@@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
@@ -13,8 +14,9 @@ import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.presentation.manga.MangaNotesScreen
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import tachiyomi.core.common.util.lang.launchNonCancellable
|
||||
import tachiyomi.domain.manga.interactor.UpdateMangaNotes
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
@@ -46,7 +48,10 @@ class MangaNotesScreen(
|
||||
class Model(
|
||||
private val manga: Manga,
|
||||
private val updateMangaNotes: UpdateMangaNotes = Injekt.get(),
|
||||
) : StateViewModel<State>(State(manga, manga.notes)) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<State>
|
||||
field = MutableStateFlow<State>(State(manga, manga.notes))
|
||||
|
||||
companion object {
|
||||
val MANGA_KEY = CreationExtras.Key<Manga>()
|
||||
@@ -63,7 +68,7 @@ class MangaNotesScreen(
|
||||
fun updateNotes(content: String) {
|
||||
if (content == state.value.notes) return
|
||||
|
||||
mutableState.update {
|
||||
state.update {
|
||||
it.copy(notes = content)
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@ import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.openInBrowser
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
@@ -68,7 +70,6 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
import logcat.LogPriority
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.core.common.util.lang.launchNonCancellable
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
@@ -205,7 +206,10 @@ data class TrackInfoDialogHomeScreen(
|
||||
private val mangaId: Long,
|
||||
private val sourceId: Long,
|
||||
private val getTracks: GetTracks = Injekt.get(),
|
||||
) : StateViewModel<Model.State>(State()) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<Model.State>
|
||||
field = MutableStateFlow<Model.State>(State())
|
||||
|
||||
companion object {
|
||||
val MANGA_ID_KEY = CreationExtras.Key<Long>()
|
||||
@@ -231,7 +235,7 @@ data class TrackInfoDialogHomeScreen(
|
||||
.catch { logcat(LogPriority.ERROR, it) }
|
||||
.distinctUntilChanged()
|
||||
.map { it.mapToTrackItem() }
|
||||
.collectLatest { trackItems -> mutableState.update { it.copy(trackItems = trackItems) } }
|
||||
.collectLatest { trackItems -> state.update { it.copy(trackItems = trackItems) } }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,7 +328,10 @@ private data class TrackStatusSelectorScreen(
|
||||
class Model(
|
||||
private val track: Track,
|
||||
private val tracker: Tracker,
|
||||
) : StateViewModel<Model.State>(State(track.status)) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<Model.State>
|
||||
field = MutableStateFlow<Model.State>(State(track.status))
|
||||
|
||||
companion object {
|
||||
val TRACK_KEY = CreationExtras.Key<Track>()
|
||||
@@ -345,7 +352,7 @@ private data class TrackStatusSelectorScreen(
|
||||
}
|
||||
|
||||
fun setSelection(selection: Long) {
|
||||
mutableState.update { it.copy(selection = selection) }
|
||||
state.update { it.copy(selection = selection) }
|
||||
}
|
||||
|
||||
fun setStatus() {
|
||||
@@ -393,7 +400,10 @@ private data class TrackChapterSelectorScreen(
|
||||
class Model(
|
||||
private val track: Track,
|
||||
private val tracker: Tracker,
|
||||
) : StateViewModel<Model.State>(State(track.lastChapterRead.toInt())) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<Model.State>
|
||||
field = MutableStateFlow<Model.State>(State(track.lastChapterRead.toInt()))
|
||||
|
||||
companion object {
|
||||
val TRACK_KEY = CreationExtras.Key<Track>()
|
||||
@@ -419,7 +429,7 @@ private data class TrackChapterSelectorScreen(
|
||||
}
|
||||
|
||||
fun setSelection(selection: Int) {
|
||||
mutableState.update { it.copy(selection = selection) }
|
||||
state.update { it.copy(selection = selection) }
|
||||
}
|
||||
|
||||
fun setChapter() {
|
||||
@@ -467,7 +477,10 @@ private data class TrackScoreSelectorScreen(
|
||||
class Model(
|
||||
private val track: Track,
|
||||
private val tracker: Tracker,
|
||||
) : StateViewModel<Model.State>(State(tracker.displayScore(track))) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<Model.State>
|
||||
field = MutableStateFlow<Model.State>(State(tracker.displayScore(track)))
|
||||
|
||||
companion object {
|
||||
val TRACK_KEY = CreationExtras.Key<Track>()
|
||||
@@ -488,7 +501,7 @@ private data class TrackScoreSelectorScreen(
|
||||
}
|
||||
|
||||
fun setSelection(selection: String) {
|
||||
mutableState.update { it.copy(selection = selection) }
|
||||
state.update { it.copy(selection = selection) }
|
||||
}
|
||||
|
||||
fun setScore() {
|
||||
@@ -788,7 +801,10 @@ data class TrackerSearchScreen(
|
||||
private val currentUrl: String?,
|
||||
initialQuery: String,
|
||||
private val tracker: Tracker,
|
||||
) : StateViewModel<Model.State>(State()) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<Model.State>
|
||||
field = MutableStateFlow<Model.State>(State())
|
||||
|
||||
companion object {
|
||||
val MANGA_ID_KEY = CreationExtras.Key<Long>()
|
||||
@@ -820,7 +836,7 @@ data class TrackerSearchScreen(
|
||||
fun trackingSearch(query: String) {
|
||||
viewModelScope.launch {
|
||||
// To show loading state
|
||||
mutableState.update { it.copy(queryResult = null, selected = null) }
|
||||
state.update { it.copy(queryResult = null, selected = null) }
|
||||
|
||||
val result = withIOContext {
|
||||
try {
|
||||
@@ -830,7 +846,7 @@ data class TrackerSearchScreen(
|
||||
Result.failure(e)
|
||||
}
|
||||
}
|
||||
mutableState.update { oldState ->
|
||||
state.update { oldState ->
|
||||
oldState.copy(
|
||||
queryResult = result,
|
||||
selected = result.getOrNull()?.find { it.tracking_url == currentUrl },
|
||||
@@ -844,7 +860,7 @@ data class TrackerSearchScreen(
|
||||
}
|
||||
|
||||
fun updateSelection(selected: TrackSearch) {
|
||||
mutableState.update { it.copy(selected = selected) }
|
||||
state.update { it.copy(selected = selected) }
|
||||
}
|
||||
|
||||
@Immutable
|
||||
|
||||
@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.more
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
@@ -17,10 +18,11 @@ import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||
import eu.kanade.tachiyomi.util.storage.saveTo
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import logcat.LogPriority
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import uy.kohesive.injekt.Injekt
|
||||
@@ -32,7 +34,10 @@ class NewUpdateScreenModel(
|
||||
private val downloadLink: String,
|
||||
private val context: Context = Injekt.get(),
|
||||
private val network: NetworkHelper = Injekt.get(),
|
||||
) : StateViewModel<NewUpdateScreenModel.State>(State(changelogInfo = changelogInfo)) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<NewUpdateScreenModel.State>
|
||||
field = MutableStateFlow<NewUpdateScreenModel.State>(State(changelogInfo = changelogInfo))
|
||||
|
||||
private val apkFile: File
|
||||
get() = File(context.externalCacheDir, "update.apk")
|
||||
@@ -43,16 +48,16 @@ class NewUpdateScreenModel(
|
||||
if (downloadJob?.isActive == true) return
|
||||
|
||||
downloadJob = viewModelScope.launch {
|
||||
mutableState.update { it.copy(downloadProgress = 0, stage = Stage.Downloading) }
|
||||
state.update { it.copy(downloadProgress = 0, stage = Stage.Downloading) }
|
||||
try {
|
||||
withIOContext { downloadApk() }
|
||||
mutableState.update { it.copy(downloadProgress = 100, stage = Stage.Downloaded) }
|
||||
state.update { it.copy(downloadProgress = 100, stage = Stage.Downloaded) }
|
||||
} catch (e: CancellationException) {
|
||||
throw e
|
||||
} catch (e: Exception) {
|
||||
logcat(LogPriority.ERROR, e)
|
||||
apkFile.delete()
|
||||
mutableState.update { it.copy(stage = Stage.Failed) }
|
||||
state.update { it.copy(stage = Stage.Failed) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,7 +76,7 @@ class NewUpdateScreenModel(
|
||||
if (progress > savedProgress && currentTime - 200 > lastTick) {
|
||||
savedProgress = progress
|
||||
lastTick = currentTime
|
||||
mutableState.update { it.copy(downloadProgress = progress) }
|
||||
state.update { it.copy(downloadProgress = progress) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.stats
|
||||
|
||||
import androidx.compose.ui.util.fastDistinctBy
|
||||
import androidx.compose.ui.util.fastFilter
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import eu.kanade.core.util.fastCountNot
|
||||
import eu.kanade.presentation.more.stats.StatsScreenState
|
||||
@@ -9,8 +10,9 @@ import eu.kanade.presentation.more.stats.data.StatsData
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import tachiyomi.core.common.util.lang.launchIO
|
||||
import tachiyomi.domain.history.interactor.GetTotalReadDuration
|
||||
import tachiyomi.domain.library.model.LibraryManga
|
||||
@@ -32,7 +34,10 @@ class StatsViewModel(
|
||||
private val getTracks: GetTracks = Injekt.get(),
|
||||
private val preferences: LibraryPreferences = Injekt.get(),
|
||||
private val trackerManager: TrackerManager = Injekt.get(),
|
||||
) : StateViewModel<StatsScreenState>(StatsScreenState.Loading) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<StatsScreenState>
|
||||
field = MutableStateFlow<StatsScreenState>(StatsScreenState.Loading)
|
||||
|
||||
private val loggedInTrackers by lazy { trackerManager.loggedInTrackers() }
|
||||
|
||||
@@ -73,7 +78,7 @@ class StatsViewModel(
|
||||
trackerCount = loggedInTrackers.size,
|
||||
)
|
||||
|
||||
mutableState.update {
|
||||
state.update {
|
||||
StatsScreenState.Success(
|
||||
overview = overviewStatData,
|
||||
titles = titlesStatData,
|
||||
|
||||
@@ -2,17 +2,16 @@ package eu.kanade.tachiyomi.ui.webview
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import eu.kanade.presentation.more.stats.StatsScreenState
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.util.system.openInBrowser
|
||||
import eu.kanade.tachiyomi.util.system.toShareIntent
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import logcat.LogPriority
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
@@ -23,7 +22,7 @@ class WebViewViewModel(
|
||||
val sourceId: Long?,
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val network: NetworkHelper = Injekt.get(),
|
||||
) : StateViewModel<StatsScreenState>(StatsScreenState.Loading) {
|
||||
) : ViewModel() {
|
||||
|
||||
companion object {
|
||||
val SOURCE_ID_KEY = CreationExtras.Key<Long?>()
|
||||
|
||||
@@ -36,6 +36,7 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEachIndexed
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
@@ -48,8 +49,9 @@ import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.ui.browse.migration.search.MigrateSearchScreen
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import mihon.feature.migration.list.MigrationListScreen
|
||||
import sh.calvin.reorderable.ReorderableCollectionItemScope
|
||||
import sh.calvin.reorderable.ReorderableItem
|
||||
@@ -309,7 +311,10 @@ class MigrationConfigScreen(private val mangaIds: Collection<Long>) : Screen() {
|
||||
class Model(
|
||||
val sourcePreferences: SourcePreferences = Injekt.get(),
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
) : StateViewModel<Model.State>(State()) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<Model.State>
|
||||
field = MutableStateFlow<Model.State>(State())
|
||||
|
||||
private val sourcesComparator = { includedSources: List<Long> ->
|
||||
compareBy<MigrationSource>(
|
||||
@@ -322,12 +327,12 @@ class MigrationConfigScreen(private val mangaIds: Collection<Long>) : Screen() {
|
||||
init {
|
||||
viewModelScope.launchIO {
|
||||
initSources()
|
||||
mutableState.update { it.copy(isLoading = false) }
|
||||
state.update { it.copy(isLoading = false) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSources(action: (List<MigrationSource>) -> List<MigrationSource>) {
|
||||
mutableState.update { state ->
|
||||
state.update { state ->
|
||||
val updatedSources = action(state.sources)
|
||||
val includedSources = updatedSources.mapNotNull { if (!it.isSelected) null else it.id }
|
||||
state.copy(sources = updatedSources.sortedWith(sourcesComparator(includedSources)))
|
||||
@@ -364,7 +369,7 @@ class MigrationConfigScreen(private val mangaIds: Collection<Long>) : Screen() {
|
||||
}
|
||||
.toList()
|
||||
|
||||
mutableState.update { state ->
|
||||
state.update { state ->
|
||||
state.copy(sources = sources.sortedWith(sourcesComparator(includedSources)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,14 +18,16 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import cafe.adriel.voyager.core.screen.Screen
|
||||
import eu.kanade.domain.manga.model.hasCustomCover
|
||||
import eu.kanade.domain.source.service.SourcePreferences
|
||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import mihon.domain.migration.models.MigrationFlag
|
||||
import mihon.domain.migration.usecases.MigrateMangaUseCase
|
||||
import mihon.feature.common.utils.getLabel
|
||||
@@ -128,7 +130,10 @@ class MigrateDialogViewModel(
|
||||
private val coverCache: CoverCache = Injekt.get(),
|
||||
private val downloadManager: DownloadManager = Injekt.get(),
|
||||
private val migrateManga: MigrateMangaUseCase = Injekt.get(),
|
||||
) : StateViewModel<MigrateDialogViewModel.State>(State()) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<MigrateDialogViewModel.State>
|
||||
field = MutableStateFlow<MigrateDialogViewModel.State>(State())
|
||||
|
||||
fun init(current: Manga, target: Manga) {
|
||||
val applicableFlags = buildList {
|
||||
@@ -144,7 +149,7 @@ class MigrateDialogViewModel(
|
||||
}
|
||||
}
|
||||
val selectedFlags = sourcePreference.migrationFlags.get()
|
||||
mutableState.update {
|
||||
state.update {
|
||||
State(
|
||||
current = current,
|
||||
target = target,
|
||||
@@ -155,7 +160,7 @@ class MigrateDialogViewModel(
|
||||
}
|
||||
|
||||
fun toggleSelection(flag: MigrationFlag) {
|
||||
mutableState.update {
|
||||
state.update {
|
||||
val selectedFlags = it.selectedFlags.toMutableSet()
|
||||
.apply { if (contains(flag)) remove(flag) else add(flag) }
|
||||
.toSet()
|
||||
@@ -164,13 +169,13 @@ class MigrateDialogViewModel(
|
||||
}
|
||||
|
||||
suspend fun migrateManga(replace: Boolean) {
|
||||
val state = state.value
|
||||
val current = state.current ?: return
|
||||
val target = state.target ?: return
|
||||
sourcePreference.migrationFlags.set(state.selectedFlags)
|
||||
mutableState.update { it.copy(isMigrating = true) }
|
||||
val currentState = state.value
|
||||
val current = currentState.current ?: return
|
||||
val target = currentState.target ?: return
|
||||
sourcePreference.migrationFlags.set(currentState.selectedFlags)
|
||||
state.update { it.copy(isMigrating = true) }
|
||||
migrateManga(current, target, replace)
|
||||
mutableState.update { it.copy(isMigrating = false, isMigrated = true) }
|
||||
state.update { it.copy(isMigrating = false, isMigrated = true) }
|
||||
}
|
||||
|
||||
data class State(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mihon.feature.migration.list
|
||||
|
||||
import androidx.annotation.FloatRange
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
@@ -16,13 +17,14 @@ import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.currentCoroutineContext
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
import logcat.LogPriority
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import mihon.domain.migration.usecases.MigrateMangaUseCase
|
||||
import mihon.domain.source.interactor.UpdateMangaFromRemote
|
||||
import mihon.feature.migration.list.models.MigratingManga
|
||||
@@ -49,7 +51,10 @@ class MigrationListViewModel(
|
||||
private val getChaptersByMangaId: GetChaptersByMangaId = Injekt.get(),
|
||||
private val migrateManga: MigrateMangaUseCase = Injekt.get(),
|
||||
private val updateMangaFromRemote: UpdateMangaFromRemote = Injekt.get(),
|
||||
) : StateViewModel<MigrationListViewModel.State>(State()) {
|
||||
) : ViewModel() {
|
||||
|
||||
val state: StateFlow<MigrationListViewModel.State>
|
||||
field = MutableStateFlow<MigrationListViewModel.State>(State())
|
||||
|
||||
companion object {
|
||||
val MANGA_IDS_KEY = CreationExtras.Key<Collection<Long>>()
|
||||
@@ -97,7 +102,7 @@ class MigrationListViewModel(
|
||||
}
|
||||
.awaitAll()
|
||||
.filterNotNull()
|
||||
mutableState.update { it.copy(items = manga) }
|
||||
state.update { it.copy(items = manga) }
|
||||
runMigrations(manga)
|
||||
}
|
||||
}
|
||||
@@ -215,7 +220,7 @@ class MigrationListViewModel(
|
||||
}
|
||||
|
||||
private suspend fun updateMigrationProgress() {
|
||||
mutableState.update { state ->
|
||||
state.update { state ->
|
||||
state.copy(
|
||||
finishedCount = items.count { it.searchResult.value != SearchResult.Searching },
|
||||
migrationComplete = migrationComplete(),
|
||||
@@ -265,7 +270,7 @@ class MigrationListViewModel(
|
||||
|
||||
private fun migrateMangas(replace: Boolean) {
|
||||
migrateJob = viewModelScope.launchIO {
|
||||
mutableState.update { it.copy(dialog = Dialog.Progress(0f)) }
|
||||
state.update { it.copy(dialog = Dialog.Progress(0f)) }
|
||||
val items = items
|
||||
try {
|
||||
items.forEachIndexed { index, manga ->
|
||||
@@ -285,14 +290,14 @@ class MigrationListViewModel(
|
||||
if (e is CancellationException) throw e
|
||||
logcat(LogPriority.WARN, throwable = e)
|
||||
}
|
||||
mutableState.update {
|
||||
state.update {
|
||||
it.copy(dialog = Dialog.Progress((index.toFloat() / items.size).coerceAtMost(1f)))
|
||||
}
|
||||
}
|
||||
|
||||
navigateBack()
|
||||
} finally {
|
||||
mutableState.update { it.copy(dialog = null) }
|
||||
state.update { it.copy(dialog = null) }
|
||||
migrateJob = null
|
||||
}
|
||||
}
|
||||
@@ -327,7 +332,7 @@ class MigrationListViewModel(
|
||||
}
|
||||
|
||||
private fun removeManga(item: MigratingManga) {
|
||||
mutableState.update { it.copy(items = items.toMutableList().apply { remove(item) }) }
|
||||
state.update { it.copy(items = items.toMutableList().apply { remove(item) }) }
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
@@ -337,7 +342,7 @@ class MigrationListViewModel(
|
||||
}
|
||||
|
||||
fun showMigrateDialog(copy: Boolean) {
|
||||
mutableState.update { state ->
|
||||
state.update { state ->
|
||||
state.copy(
|
||||
dialog = Dialog.Migrate(
|
||||
copy = copy,
|
||||
@@ -349,13 +354,13 @@ class MigrationListViewModel(
|
||||
}
|
||||
|
||||
fun showExitDialog() {
|
||||
mutableState.update {
|
||||
state.update {
|
||||
it.copy(dialog = Dialog.Exit)
|
||||
}
|
||||
}
|
||||
|
||||
fun dismissDialog() {
|
||||
mutableState.update { it.copy(dialog = null) }
|
||||
state.update { it.copy(dialog = null) }
|
||||
}
|
||||
|
||||
data class ChapterInfo(
|
||||
|
||||
Reference in New Issue
Block a user