Update Voyager
This commit is contained in:
@@ -4,7 +4,7 @@ import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import cafe.adriel.voyager.core.model.StateScreenModel
|
||||
import cafe.adriel.voyager.core.model.coroutineScope
|
||||
import cafe.adriel.voyager.core.model.screenModelScope
|
||||
import coil.imageLoader
|
||||
import coil.request.ImageRequest
|
||||
import coil.size.Size
|
||||
@@ -40,14 +40,14 @@ class MangaCoverScreenModel(
|
||||
) : StateScreenModel<Manga?>(null) {
|
||||
|
||||
init {
|
||||
coroutineScope.launchIO {
|
||||
screenModelScope.launchIO {
|
||||
getManga.subscribe(mangaId)
|
||||
.collect { newManga -> mutableState.update { newManga } }
|
||||
}
|
||||
}
|
||||
|
||||
fun saveCover(context: Context) {
|
||||
coroutineScope.launch {
|
||||
screenModelScope.launch {
|
||||
try {
|
||||
saveCoverInternal(context, temp = false)
|
||||
snackbarHostState.showSnackbar(
|
||||
@@ -65,7 +65,7 @@ class MangaCoverScreenModel(
|
||||
}
|
||||
|
||||
fun shareCover(context: Context) {
|
||||
coroutineScope.launch {
|
||||
screenModelScope.launch {
|
||||
try {
|
||||
val uri = saveCoverInternal(context, temp = true) ?: return@launch
|
||||
withUIContext {
|
||||
@@ -117,7 +117,7 @@ class MangaCoverScreenModel(
|
||||
*/
|
||||
fun editCover(context: Context, data: Uri) {
|
||||
val manga = state.value ?: return
|
||||
coroutineScope.launchIO {
|
||||
screenModelScope.launchIO {
|
||||
context.contentResolver.openInputStream(data)?.use {
|
||||
try {
|
||||
manga.editCover(Injekt.get(), it, updateManga, coverCache)
|
||||
@@ -131,7 +131,7 @@ class MangaCoverScreenModel(
|
||||
|
||||
fun deleteCustomCover(context: Context) {
|
||||
val mangaId = state.value?.id ?: return
|
||||
coroutineScope.launchIO {
|
||||
screenModelScope.launchIO {
|
||||
try {
|
||||
coverCache.deleteCustomCover(mangaId)
|
||||
updateManga.awaitUpdateCoverLastModified(mangaId)
|
||||
@@ -143,7 +143,7 @@ class MangaCoverScreenModel(
|
||||
}
|
||||
|
||||
private fun notifyCoverUpdated(context: Context) {
|
||||
coroutineScope.launch {
|
||||
screenModelScope.launch {
|
||||
snackbarHostState.showSnackbar(
|
||||
context.getString(R.string.cover_updated),
|
||||
withDismissAction = true,
|
||||
@@ -152,7 +152,7 @@ class MangaCoverScreenModel(
|
||||
}
|
||||
|
||||
private fun notifyFailedCoverUpdate(context: Context, e: Throwable) {
|
||||
coroutineScope.launch {
|
||||
screenModelScope.launch {
|
||||
snackbarHostState.showSnackbar(
|
||||
context.getString(R.string.notification_cover_update_failed),
|
||||
withDismissAction = true,
|
||||
|
||||
@@ -7,7 +7,7 @@ import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import cafe.adriel.voyager.core.model.StateScreenModel
|
||||
import cafe.adriel.voyager.core.model.coroutineScope
|
||||
import cafe.adriel.voyager.core.model.screenModelScope
|
||||
import eu.kanade.core.preference.asState
|
||||
import eu.kanade.core.util.addOrRemove
|
||||
import eu.kanade.domain.chapter.interactor.SetReadStatus
|
||||
@@ -126,9 +126,9 @@ class MangaScreenModel(
|
||||
val chapterSwipeStartAction = libraryPreferences.swipeToEndAction().get()
|
||||
val chapterSwipeEndAction = libraryPreferences.swipeToStartAction().get()
|
||||
|
||||
val relativeTime by uiPreferences.relativeTime().asState(coroutineScope)
|
||||
val relativeTime by uiPreferences.relativeTime().asState(screenModelScope)
|
||||
val dateFormat by mutableStateOf(UiPreferences.dateFormat(uiPreferences.dateFormat().get()))
|
||||
private val skipFiltered by readerPreferences.skipFiltered().asState(coroutineScope)
|
||||
private val skipFiltered by readerPreferences.skipFiltered().asState(screenModelScope)
|
||||
|
||||
val isUpdateIntervalEnabled = LibraryPreferences.MANGA_OUTSIDE_RELEASE_PERIOD in libraryPreferences.autoUpdateMangaRestrictions().get()
|
||||
|
||||
@@ -148,7 +148,7 @@ class MangaScreenModel(
|
||||
}
|
||||
|
||||
init {
|
||||
coroutineScope.launchIO {
|
||||
screenModelScope.launchIO {
|
||||
combine(
|
||||
getMangaAndChapters.subscribe(mangaId).distinctUntilChanged(),
|
||||
downloadCache.changes,
|
||||
@@ -166,7 +166,7 @@ class MangaScreenModel(
|
||||
|
||||
observeDownloads()
|
||||
|
||||
coroutineScope.launchIO {
|
||||
screenModelScope.launchIO {
|
||||
val manga = getMangaAndChapters.awaitManga(mangaId)
|
||||
val chapters = getMangaAndChapters.awaitChapters(mangaId)
|
||||
.toChapterItems(manga)
|
||||
@@ -194,7 +194,7 @@ class MangaScreenModel(
|
||||
observeTrackers()
|
||||
|
||||
// Fetch info-chapters when needed
|
||||
if (coroutineScope.isActive) {
|
||||
if (screenModelScope.isActive) {
|
||||
val fetchFromSourceTasks = listOf(
|
||||
async { if (needRefreshInfo) fetchMangaFromSource() },
|
||||
async { if (needRefreshChapter) fetchChaptersFromSource() },
|
||||
@@ -208,7 +208,7 @@ class MangaScreenModel(
|
||||
}
|
||||
|
||||
fun fetchAllFromSource(manualFetch: Boolean = true) {
|
||||
coroutineScope.launch {
|
||||
screenModelScope.launch {
|
||||
updateSuccessState { it.copy(isRefreshingData = true) }
|
||||
val fetchFromSourceTasks = listOf(
|
||||
async { fetchMangaFromSource(manualFetch) },
|
||||
@@ -236,7 +236,7 @@ class MangaScreenModel(
|
||||
if (e is HttpException && e.code == 103) return
|
||||
|
||||
logcat(LogPriority.ERROR, e)
|
||||
coroutineScope.launch {
|
||||
screenModelScope.launch {
|
||||
snackbarHostState.showSnackbar(message = with(context) { e.formattedMessage })
|
||||
}
|
||||
}
|
||||
@@ -245,7 +245,7 @@ class MangaScreenModel(
|
||||
fun toggleFavorite() {
|
||||
toggleFavorite(
|
||||
onRemoved = {
|
||||
coroutineScope.launch {
|
||||
screenModelScope.launch {
|
||||
if (!hasDownloads()) return@launch
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = context.getString(R.string.delete_downloads_for_manga),
|
||||
@@ -268,7 +268,7 @@ class MangaScreenModel(
|
||||
checkDuplicate: Boolean = true,
|
||||
) {
|
||||
val state = successState ?: return
|
||||
coroutineScope.launchIO {
|
||||
screenModelScope.launchIO {
|
||||
val manga = state.manga
|
||||
|
||||
if (isFavorited) {
|
||||
@@ -323,7 +323,7 @@ class MangaScreenModel(
|
||||
|
||||
fun showChangeCategoryDialog() {
|
||||
val manga = successState?.manga ?: return
|
||||
coroutineScope.launch {
|
||||
screenModelScope.launch {
|
||||
val categories = getCategories()
|
||||
val selection = getMangaCategoryIds(manga)
|
||||
updateSuccessState { successState ->
|
||||
@@ -345,7 +345,7 @@ class MangaScreenModel(
|
||||
}
|
||||
|
||||
fun setFetchInterval(manga: Manga, interval: Int) {
|
||||
coroutineScope.launchIO {
|
||||
screenModelScope.launchIO {
|
||||
updateManga.awaitUpdateFetchInterval(
|
||||
// Custom intervals are negative
|
||||
manga.copy(fetchInterval = -interval),
|
||||
@@ -395,7 +395,7 @@ class MangaScreenModel(
|
||||
moveMangaToCategory(categories)
|
||||
if (manga.favorite) return
|
||||
|
||||
coroutineScope.launchIO {
|
||||
screenModelScope.launchIO {
|
||||
updateManga.awaitUpdateFavorite(manga.id, true)
|
||||
}
|
||||
}
|
||||
@@ -411,7 +411,7 @@ class MangaScreenModel(
|
||||
}
|
||||
|
||||
private fun moveMangaToCategory(categoryIds: List<Long>) {
|
||||
coroutineScope.launchIO {
|
||||
screenModelScope.launchIO {
|
||||
setMangaCategories.await(mangaId, categoryIds)
|
||||
}
|
||||
}
|
||||
@@ -430,7 +430,7 @@ class MangaScreenModel(
|
||||
// Chapters list - start
|
||||
|
||||
private fun observeDownloads() {
|
||||
coroutineScope.launchIO {
|
||||
screenModelScope.launchIO {
|
||||
downloadManager.statusFlow()
|
||||
.filter { it.manga.id == successState?.manga?.id }
|
||||
.catch { error -> logcat(LogPriority.ERROR, error) }
|
||||
@@ -441,7 +441,7 @@ class MangaScreenModel(
|
||||
}
|
||||
}
|
||||
|
||||
coroutineScope.launchIO {
|
||||
screenModelScope.launchIO {
|
||||
downloadManager.progressFlow()
|
||||
.filter { it.manga.id == successState?.manga?.id }
|
||||
.catch { error -> logcat(LogPriority.ERROR, error) }
|
||||
@@ -523,7 +523,7 @@ class MangaScreenModel(
|
||||
with(context) { e.formattedMessage }
|
||||
}
|
||||
|
||||
coroutineScope.launch {
|
||||
screenModelScope.launch {
|
||||
snackbarHostState.showSnackbar(message = message)
|
||||
}
|
||||
val newManga = mangaRepository.getMangaById(mangaId)
|
||||
@@ -535,7 +535,7 @@ class MangaScreenModel(
|
||||
* @throws IllegalStateException if the swipe action is [LibraryPreferences.ChapterSwipeAction.Disabled]
|
||||
*/
|
||||
fun chapterSwipe(chapterItem: ChapterItem, swipeAction: LibraryPreferences.ChapterSwipeAction) {
|
||||
coroutineScope.launch {
|
||||
screenModelScope.launch {
|
||||
executeChapterSwipeAction(chapterItem, swipeAction)
|
||||
}
|
||||
}
|
||||
@@ -612,7 +612,7 @@ class MangaScreenModel(
|
||||
updateSuccessState { state ->
|
||||
state.copy(hasPromptedToAddBefore = true)
|
||||
}
|
||||
coroutineScope.launch {
|
||||
screenModelScope.launch {
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = context.getString(R.string.snack_add_to_library),
|
||||
actionLabel = context.getString(R.string.action_add),
|
||||
@@ -683,7 +683,7 @@ class MangaScreenModel(
|
||||
* @param read whether to mark chapters as read or unread.
|
||||
*/
|
||||
fun markChaptersRead(chapters: List<Chapter>, read: Boolean) {
|
||||
coroutineScope.launchIO {
|
||||
screenModelScope.launchIO {
|
||||
setReadStatus.await(
|
||||
read = read,
|
||||
chapters = chapters.toTypedArray(),
|
||||
@@ -707,7 +707,7 @@ class MangaScreenModel(
|
||||
* @param chapters the list of chapters to bookmark.
|
||||
*/
|
||||
fun bookmarkChapters(chapters: List<Chapter>, bookmarked: Boolean) {
|
||||
coroutineScope.launchIO {
|
||||
screenModelScope.launchIO {
|
||||
chapters
|
||||
.filterNot { it.bookmark == bookmarked }
|
||||
.map { ChapterUpdate(id = it.id, bookmark = bookmarked) }
|
||||
@@ -722,7 +722,7 @@ class MangaScreenModel(
|
||||
* @param chapters the list of chapters to delete.
|
||||
*/
|
||||
fun deleteChapters(chapters: List<Chapter>) {
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
try {
|
||||
successState?.let { state ->
|
||||
downloadManager.deleteChapters(
|
||||
@@ -738,7 +738,7 @@ class MangaScreenModel(
|
||||
}
|
||||
|
||||
private fun downloadNewChapters(chapters: List<Chapter>) {
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
val manga = successState?.manga ?: return@launchNonCancellable
|
||||
val categories = getCategories.await(manga.id).map { it.id }
|
||||
if (chapters.isEmpty() || !manga.shouldDownloadNewChapters(categories, downloadPreferences)) return@launchNonCancellable
|
||||
@@ -758,7 +758,7 @@ class MangaScreenModel(
|
||||
TriState.ENABLED_IS -> Manga.CHAPTER_SHOW_UNREAD
|
||||
TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_READ
|
||||
}
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
setMangaChapterFlags.awaitSetUnreadFilter(manga, flag)
|
||||
}
|
||||
}
|
||||
@@ -776,7 +776,7 @@ class MangaScreenModel(
|
||||
TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_DOWNLOADED
|
||||
}
|
||||
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
setMangaChapterFlags.awaitSetDownloadedFilter(manga, flag)
|
||||
}
|
||||
}
|
||||
@@ -794,7 +794,7 @@ class MangaScreenModel(
|
||||
TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_BOOKMARKED
|
||||
}
|
||||
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
setMangaChapterFlags.awaitSetBookmarkFilter(manga, flag)
|
||||
}
|
||||
}
|
||||
@@ -806,7 +806,7 @@ class MangaScreenModel(
|
||||
fun setDisplayMode(mode: Long) {
|
||||
val manga = successState?.manga ?: return
|
||||
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
setMangaChapterFlags.awaitSetDisplayMode(manga, mode)
|
||||
}
|
||||
}
|
||||
@@ -818,14 +818,14 @@ class MangaScreenModel(
|
||||
fun setSorting(sort: Long) {
|
||||
val manga = successState?.manga ?: return
|
||||
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
setMangaChapterFlags.awaitSetSortingModeOrFlipOrder(manga, sort)
|
||||
}
|
||||
}
|
||||
|
||||
fun setCurrentSettingsAsDefault(applyToExisting: Boolean) {
|
||||
val manga = successState?.manga ?: return
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
libraryPreferences.setChapterSettingsDefault(manga)
|
||||
if (applyToExisting) {
|
||||
setMangaDefaultChapterFlags.awaitAll()
|
||||
@@ -929,7 +929,7 @@ class MangaScreenModel(
|
||||
private fun observeTrackers() {
|
||||
val manga = successState?.manga ?: return
|
||||
|
||||
coroutineScope.launchIO {
|
||||
screenModelScope.launchIO {
|
||||
getTracks.subscribe(manga.id)
|
||||
.catch { logcat(LogPriority.ERROR, it) }
|
||||
.map { tracks ->
|
||||
|
||||
@@ -34,8 +34,8 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import cafe.adriel.voyager.core.model.ScreenModel
|
||||
import cafe.adriel.voyager.core.model.StateScreenModel
|
||||
import cafe.adriel.voyager.core.model.coroutineScope
|
||||
import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||
import cafe.adriel.voyager.core.model.screenModelScope
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.Navigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
@@ -188,11 +188,11 @@ data class TrackInfoDialogHomeScreen(
|
||||
) : StateScreenModel<Model.State>(State()) {
|
||||
|
||||
init {
|
||||
coroutineScope.launch {
|
||||
screenModelScope.launch {
|
||||
refreshTrackers()
|
||||
}
|
||||
|
||||
coroutineScope.launch {
|
||||
screenModelScope.launch {
|
||||
getTracks.subscribe(mangaId)
|
||||
.catch { logcat(LogPriority.ERROR, it) }
|
||||
.distinctUntilChanged()
|
||||
@@ -203,7 +203,7 @@ data class TrackInfoDialogHomeScreen(
|
||||
|
||||
fun registerEnhancedTracking(item: TrackItem) {
|
||||
item.tracker as EnhancedTracker
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
val manga = Injekt.get<GetManga>().await(mangaId) ?: return@launchNonCancellable
|
||||
try {
|
||||
val matchResult = item.tracker.match(manga) ?: throw Exception()
|
||||
@@ -294,7 +294,7 @@ private data class TrackStatusSelectorScreen(
|
||||
}
|
||||
|
||||
fun setStatus() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
tracker.setRemoteStatus(track.toDbTrack(), state.value.selection)
|
||||
}
|
||||
}
|
||||
@@ -353,7 +353,7 @@ private data class TrackChapterSelectorScreen(
|
||||
}
|
||||
|
||||
fun setChapter() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
tracker.setRemoteLastChapterRead(track.toDbTrack(), state.value.selection)
|
||||
}
|
||||
}
|
||||
@@ -407,7 +407,7 @@ private data class TrackScoreSelectorScreen(
|
||||
}
|
||||
|
||||
fun setScore() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
tracker.setRemoteScore(track.toDbTrack(), state.value.selection)
|
||||
}
|
||||
}
|
||||
@@ -533,7 +533,7 @@ private data class TrackDateSelectorScreen(
|
||||
fun setDate(millis: Long) {
|
||||
// Convert to local time
|
||||
val localMillis = millis.convertEpochMillisZone(ZoneOffset.UTC, ZoneOffset.systemDefault())
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
if (start) {
|
||||
tracker.setRemoteStartDate(track.toDbTrack(), localMillis)
|
||||
} else {
|
||||
@@ -622,7 +622,7 @@ private data class TrackDateRemoverScreen(
|
||||
fun getServiceName() = tracker.name
|
||||
|
||||
fun removeDate() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
if (start) {
|
||||
tracker.setRemoteStartDate(track.toDbTrack(), 0)
|
||||
} else {
|
||||
@@ -685,7 +685,7 @@ data class TrackerSearchScreen(
|
||||
}
|
||||
|
||||
fun trackingSearch(query: String) {
|
||||
coroutineScope.launch {
|
||||
screenModelScope.launch {
|
||||
// To show loading state
|
||||
mutableState.update { it.copy(queryResult = null, selected = null) }
|
||||
|
||||
@@ -707,7 +707,7 @@ data class TrackerSearchScreen(
|
||||
}
|
||||
|
||||
fun registerTracking(item: TrackSearch) {
|
||||
coroutineScope.launchNonCancellable { tracker.register(item, mangaId) }
|
||||
screenModelScope.launchNonCancellable { tracker.register(item, mangaId) }
|
||||
}
|
||||
|
||||
fun updateSelection(selected: TrackSearch) {
|
||||
@@ -812,13 +812,13 @@ private data class TrackerRemoveScreen(
|
||||
fun isDeletable() = tracker is DeletableTracker
|
||||
|
||||
fun deleteMangaFromService() {
|
||||
coroutineScope.launchNonCancellable {
|
||||
screenModelScope.launchNonCancellable {
|
||||
(tracker as DeletableTracker).delete(track.toDbTrack())
|
||||
}
|
||||
}
|
||||
|
||||
fun unregisterTracking(serviceId: Long) {
|
||||
coroutineScope.launchNonCancellable { deleteTrack.await(mangaId, serviceId) }
|
||||
screenModelScope.launchNonCancellable { deleteTrack.await(mangaId, serviceId) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user