diff --git a/app/src/main/java/eu/kanade/presentation/library/components/SyncFavoritesProgressDialog.kt b/app/src/main/java/eu/kanade/presentation/library/components/SyncFavoritesProgressDialog.kt index a5cd86c05..3b1b01724 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/SyncFavoritesProgressDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/SyncFavoritesProgressDialog.kt @@ -15,7 +15,6 @@ import androidx.compose.ui.window.DialogProperties import exh.favorites.FavoritesSyncStatus import kotlinx.coroutines.delay import tachiyomi.core.common.i18n.stringResource -import tachiyomi.domain.manga.model.Manga import tachiyomi.i18n.MR import tachiyomi.i18n.sy.SYMR import kotlin.time.Duration.Companion.seconds @@ -23,7 +22,6 @@ import kotlin.time.Duration.Companion.seconds data class SyncFavoritesProgressProperties( val title: String, val text: String, - val canDismiss: Boolean, val positiveButtonText: String? = null, val positiveButton: (() -> Unit)? = null, val negativeButtonText: String? = null, @@ -34,18 +32,23 @@ data class SyncFavoritesProgressProperties( fun SyncFavoritesProgressDialog( status: FavoritesSyncStatus, setStatusIdle: () -> Unit, - openManga: (Manga) -> Unit, + openManga: (Long) -> Unit, ) { val context = LocalContext.current val properties by produceState(initialValue = null, status) { when (status) { is FavoritesSyncStatus.BadLibraryState.MangaInMultipleCategories -> value = SyncFavoritesProgressProperties( title = context.stringResource(SYMR.strings.favorites_sync_error), - text = context.stringResource(SYMR.strings.favorites_sync_bad_library_state, status.message), - canDismiss = false, + text = context.stringResource( + SYMR.strings.favorites_sync_bad_library_state, + context.stringResource( + SYMR.strings.favorites_sync_gallery_in_multiple_categories, status.mangaTitle, + status.categories.joinToString(), + ), + ), positiveButtonText = context.stringResource(SYMR.strings.show_gallery), positiveButton = { - openManga(status.manga) + openManga(status.mangaId) setStatusIdle() }, negativeButtonText = context.stringResource(MR.strings.action_ok), @@ -53,31 +56,122 @@ fun SyncFavoritesProgressDialog( ) is FavoritesSyncStatus.CompleteWithErrors -> value = SyncFavoritesProgressProperties( title = context.stringResource(SYMR.strings.favorites_sync_done_errors), - text = context.stringResource(SYMR.strings.favorites_sync_done_errors_message, status.message), - canDismiss = false, - positiveButtonText = context.stringResource(MR.strings.action_ok), - positiveButton = setStatusIdle, - ) - is FavoritesSyncStatus.Error -> value = SyncFavoritesProgressProperties( - title = context.stringResource(SYMR.strings.favorites_sync_error), - text = context.stringResource(SYMR.strings.favorites_sync_error_string, status.message), - canDismiss = false, + text = context.stringResource( + SYMR.strings.favorites_sync_done_errors_message, + status.messages.joinToString(separator = "\n") { + when (it) { + is FavoritesSyncStatus.SyncError.GallerySyncError.GalleryAddFail -> + context.stringResource(SYMR.strings.favorites_sync_failed_to_add_to_local) + + context.stringResource( + SYMR.strings.favorites_sync_failed_to_add_to_local_error, it.title, it.reason, + ) + is FavoritesSyncStatus.SyncError.GallerySyncError.InvalidGalleryFail -> + context.stringResource(SYMR.strings.favorites_sync_failed_to_add_to_local) + + context.stringResource( + SYMR.strings.favorites_sync_failed_to_add_to_local_unknown_type, it.title, it.url, + ) + is FavoritesSyncStatus.SyncError.GallerySyncError.UnableToAddGalleryToRemote -> + context.stringResource(SYMR.strings.favorites_sync_unable_to_add_to_remote, it.title, it.gid) + FavoritesSyncStatus.SyncError.GallerySyncError.UnableToDeleteFromRemote -> + context.stringResource(SYMR.strings.favorites_sync_unable_to_delete) + } + } + ), positiveButtonText = context.stringResource(MR.strings.action_ok), positiveButton = setStatusIdle, ) is FavoritesSyncStatus.Idle -> value = null - is FavoritesSyncStatus.Initializing, is FavoritesSyncStatus.Processing -> { + is FavoritesSyncStatus.Initializing -> { value = SyncFavoritesProgressProperties( title = context.stringResource(SYMR.strings.favorites_syncing), - text = status.message, - canDismiss = false, + text = context.stringResource(SYMR.strings.favorites_sync_initializing), ) - if (status is FavoritesSyncStatus.Processing && status.title != null) { + } + + is FavoritesSyncStatus.SyncError -> value = SyncFavoritesProgressProperties( + title = context.stringResource(SYMR.strings.favorites_sync_error), + text = context.stringResource( + SYMR.strings.favorites_sync_error_string, + when (status) { + FavoritesSyncStatus.SyncError.NotLoggedInSyncError -> context.stringResource(SYMR.strings.please_login) + FavoritesSyncStatus.SyncError.FailedToFetchFavorites -> + context.stringResource(SYMR.strings.favorites_sync_failed_to_featch) + is FavoritesSyncStatus.SyncError.UnknownSyncError -> + context.stringResource(SYMR.strings.favorites_sync_unknown_error, status.message) + is FavoritesSyncStatus.SyncError.GallerySyncError.GalleryAddFail -> + context.stringResource(SYMR.strings.favorites_sync_failed_to_add_to_local) + + context.stringResource( + SYMR.strings.favorites_sync_failed_to_add_to_local_error, status.title, status.reason, + ) + is FavoritesSyncStatus.SyncError.GallerySyncError.InvalidGalleryFail -> + context.stringResource(SYMR.strings.favorites_sync_failed_to_add_to_local) + + context.stringResource( + SYMR.strings.favorites_sync_failed_to_add_to_local_unknown_type, status.title, status.url, + ) + is FavoritesSyncStatus.SyncError.GallerySyncError.UnableToAddGalleryToRemote -> + context.stringResource(SYMR.strings.favorites_sync_unable_to_add_to_remote, status.title, status.gid) + FavoritesSyncStatus.SyncError.GallerySyncError.UnableToDeleteFromRemote -> + context.stringResource(SYMR.strings.favorites_sync_unable_to_delete) + } + ), + positiveButtonText = context.stringResource(MR.strings.action_ok), + positiveButton = setStatusIdle, + ) + is FavoritesSyncStatus.Processing -> { + val properties = SyncFavoritesProgressProperties( + title = context.stringResource(SYMR.strings.favorites_syncing), + text = when (status) { + FavoritesSyncStatus.Processing.VerifyingLibrary -> + context.stringResource(SYMR.strings.favorites_sync_verifying_library) + FavoritesSyncStatus.Processing.DownloadingFavorites -> + context.stringResource(SYMR.strings.favorites_sync_downloading) + FavoritesSyncStatus.Processing.CalculatingRemoteChanges -> + context.stringResource(SYMR.strings.favorites_sync_calculating_remote_changes) + FavoritesSyncStatus.Processing.CalculatingLocalChanges -> + context.stringResource(SYMR.strings.favorites_sync_calculating_local_changes) + FavoritesSyncStatus.Processing.SyncingCategoryNames -> + context.stringResource(SYMR.strings.favorites_sync_syncing_category_names) + is FavoritesSyncStatus.Processing.RemovingRemoteGalleries -> + context.stringResource(SYMR.strings.favorites_sync_removing_galleries, status.galleryCount) + is FavoritesSyncStatus.Processing.AddingGalleryToRemote -> + if (status.isThrottling) { + context.stringResource( + SYMR.strings.favorites_sync_processing_throttle, + context.stringResource(SYMR.strings.favorites_sync_adding_to_remote, status.index, status.total) + ) + } else { + context.stringResource(SYMR.strings.favorites_sync_adding_to_remote, status.index, status.total) + } + is FavoritesSyncStatus.Processing.RemovingGalleryFromLocal -> + context.stringResource(SYMR.strings.favorites_sync_remove_from_local, status.index, status.total) + is FavoritesSyncStatus.Processing.AddingGalleryToLocal -> + if (status.isThrottling) { + context.stringResource( + SYMR.strings.favorites_sync_processing_throttle, + context.stringResource(SYMR.strings.favorites_sync_add_to_local, status.index, status.total) + ) + } else { + context.stringResource(SYMR.strings.favorites_sync_add_to_local, status.index, status.total) + } + + FavoritesSyncStatus.Processing.CleaningUp -> + context.stringResource(SYMR.strings.favorites_sync_cleaning_up) + }, + ) + value = properties + if ( + status is FavoritesSyncStatus.Processing.AddingGalleryToRemote || + status is FavoritesSyncStatus.Processing.AddingGalleryToLocal + ) { delay(5.seconds) - value = SyncFavoritesProgressProperties( - title = context.stringResource(SYMR.strings.favorites_syncing), - text = status.delayedMessage ?: status.message, - canDismiss = false, + value = properties.copy( + text = when (status) { + is FavoritesSyncStatus.Processing.AddingGalleryToRemote -> + properties.text + "\n\n" + status.title + is FavoritesSyncStatus.Processing.AddingGalleryToLocal -> + properties.text + "\n\n" + status.title + else -> properties.text + }, ) } } @@ -112,8 +206,8 @@ fun SyncFavoritesProgressDialog( } }, properties = DialogProperties( - dismissOnClickOutside = dialog.canDismiss, - dismissOnBackPress = dialog.canDismiss, + dismissOnClickOutside = false, + dismissOnBackPress = false, ), ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt index ef2f7e157..31944b961 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryTab.kt @@ -335,7 +335,7 @@ data object LibraryTab : Tab { SyncFavoritesProgressDialog( status = screenModel.favoritesSync.status.collectAsState().value, setStatusIdle = { screenModel.favoritesSync.status.value = FavoritesSyncStatus.Idle(context) }, - openManga = { navigator.push(MangaScreen(it.id)) }, + openManga = { navigator.push(MangaScreen(it)) }, ) // SY <-- diff --git a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt index 92db1fe96..49b6b8862 100644 --- a/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt +++ b/app/src/main/java/exh/favorites/FavoritesSyncHelper.kt @@ -64,18 +64,18 @@ class FavoritesSyncHelper(val context: Context) { ?: EHentai(0, true, context) } - private val storage = LocalFavoritesStorage() + private val storage by lazy { LocalFavoritesStorage() } - private val galleryAdder = GalleryAdder() + private val galleryAdder by lazy { GalleryAdder() } - private val throttleManager = EHentaiThrottleManager() + private val throttleManager by lazy { EHentaiThrottleManager() } private var wifiLock: WifiManager.WifiLock? = null private var wakeLock: PowerManager.WakeLock? = null - private val logger = xLog() + private val logger by lazy { xLog() } - val status: MutableStateFlow = MutableStateFlow(FavoritesSyncStatus.Idle(context)) + val status: MutableStateFlow = MutableStateFlow(FavoritesSyncStatus.Idle) @Synchronized fun runSync(scope: CoroutineScope) { @@ -83,7 +83,7 @@ class FavoritesSyncHelper(val context: Context) { return } - status.value = FavoritesSyncStatus.Initializing(context) + status.value = FavoritesSyncStatus.Initializing scope.launch(Dispatchers.IO) { beginSync() } } @@ -91,13 +91,12 @@ class FavoritesSyncHelper(val context: Context) { private suspend fun beginSync() { // Check if logged in if (!prefs.enableExhentai().get()) { - status.value = FavoritesSyncStatus.Error(context.stringResource(SYMR.strings.please_login)) + status.value = FavoritesSyncStatus.SyncError.NotLoggedInSyncError return } // Validate library state - status.value = - FavoritesSyncStatus.Processing(context.stringResource(SYMR.strings.favorites_sync_verifying_library)) + status.value = FavoritesSyncStatus.Processing.VerifyingLibrary val libraryManga = getLibraryManga.await() val seenManga = HashSet(libraryManga.size) libraryManga.forEach { (manga) -> @@ -106,7 +105,7 @@ class FavoritesSyncHelper(val context: Context) { if (manga.id in seenManga) { val inCategories = getCategories.await(manga.id) status.value = FavoritesSyncStatus.BadLibraryState - .MangaInMultipleCategories(manga, inCategories, context) + .MangaInMultipleCategories(manga.id, manga.title, inCategories.map { it.name }) logger.w(context.stringResource(SYMR.strings.favorites_sync_gallery_multiple_categories_error, manga.id)) return @@ -117,17 +116,15 @@ class FavoritesSyncHelper(val context: Context) { // Download remote favorites val favorites = try { - status.value = - FavoritesSyncStatus.Processing(context.stringResource(SYMR.strings.favorites_sync_downloading)) + status.value = FavoritesSyncStatus.Processing.DownloadingFavorites exh.fetchFavorites() } catch (e: Exception) { - status.value = - FavoritesSyncStatus.Error(context.stringResource(SYMR.strings.favorites_sync_failed_to_featch)) + status.value = FavoritesSyncStatus.SyncError.FailedToFetchFavorites logger.e(context.stringResource(SYMR.strings.favorites_sync_could_not_fetch), e) return } - val errorList = mutableListOf() + val errorList = mutableListOf() try { // Take wake + wifi locks @@ -157,23 +154,17 @@ class FavoritesSyncHelper(val context: Context) { // Do not update galleries while syncing favorites EHentaiUpdateWorker.cancelBackground(context) - status.value = FavoritesSyncStatus.Processing( - context.stringResource(SYMR.strings.favorites_sync_calculating_remote_changes), - ) + status.value = FavoritesSyncStatus.Processing.CalculatingRemoteChanges val remoteChanges = storage.getChangedRemoteEntries(favorites.first) val localChanges = if (prefs.exhReadOnlySync().get()) { null // Do not build local changes if they are not going to be applied } else { - status.value = FavoritesSyncStatus.Processing( - context.stringResource(SYMR.strings.favorites_sync_calculating_local_changes), - ) + status.value = FavoritesSyncStatus.Processing.CalculatingLocalChanges storage.getChangedDbEntries() } // Apply remote categories - status.value = FavoritesSyncStatus.Processing( - context.stringResource(SYMR.strings.favorites_sync_syncing_category_names), - ) + status.value = FavoritesSyncStatus.Processing.SyncingCategoryNames applyRemoteCategories(favorites.second) // Apply change sets @@ -182,8 +173,7 @@ class FavoritesSyncHelper(val context: Context) { applyChangeSetToRemote(errorList, localChanges) } - status.value = - FavoritesSyncStatus.Processing(context.stringResource(SYMR.strings.favorites_sync_cleaning_up)) + status.value = FavoritesSyncStatus.Processing.CleaningUp storage.snapshotEntries() withUIContext { @@ -194,9 +184,7 @@ class FavoritesSyncHelper(val context: Context) { logger.w(context.stringResource(SYMR.strings.favorites_sync_ignoring_exception), e) return } catch (e: Exception) { - status.value = FavoritesSyncStatus.Error( - context.stringResource(SYMR.strings.favorites_sync_unknown_error, e.message.orEmpty()), - ) + status.value = FavoritesSyncStatus.SyncError.UnknownSyncError(e.message.orEmpty()) logger.e(context.stringResource(SYMR.strings.favorites_sync_sync_error), e) return } finally { @@ -215,7 +203,7 @@ class FavoritesSyncHelper(val context: Context) { } if (errorList.isEmpty()) { - status.value = FavoritesSyncStatus.Idle(context) + status.value = FavoritesSyncStatus.Idle } else { status.value = FavoritesSyncStatus.CompleteWithErrors(errorList) } @@ -249,7 +237,7 @@ class FavoritesSyncHelper(val context: Context) { } } - private suspend fun addGalleryRemote(errorList: MutableList, gallery: FavoriteEntry) { + private suspend fun addGalleryRemote(errorList: MutableList, gallery: FavoriteEntry) { val url = "${exh.baseUrl}/gallerypopups.php?gid=${gallery.gid}&t=${gallery.token}&act=addfav" val request = POST( @@ -263,13 +251,16 @@ class FavoritesSyncHelper(val context: Context) { ) if (!explicitlyRetryExhRequest(10, request)) { - val errorString = "Unable to add gallery to remote server: '${gallery.title}' (GID: ${gallery.gid})!" + val error = FavoritesSyncStatus.SyncError.GallerySyncError.UnableToAddGalleryToRemote( + gallery.title, + gallery.gid + ) if (prefs.exhLenientSync().get()) { - errorList += errorString + errorList += error } else { - status.value = FavoritesSyncStatus.Error(errorString) - throw IgnoredException(errorString) + status.value = error + throw IgnoredException(error) } } } @@ -293,12 +284,13 @@ class FavoritesSyncHelper(val context: Context) { return success } - private suspend fun applyChangeSetToRemote(errorList: MutableList, changeSet: ChangeSet) { + private suspend fun applyChangeSetToRemote( + errorList: MutableList, + changeSet: ChangeSet, + ) { // Apply removals if (changeSet.removed.isNotEmpty()) { - status.value = FavoritesSyncStatus.Processing( - context.stringResource(SYMR.strings.favorites_sync_removing_galleries, changeSet.removed.size), - ) + status.value = FavoritesSyncStatus.Processing.RemovingRemoteGalleries(changeSet.removed.size) val formBody = FormBody.Builder() .add("ddact", "delete") @@ -315,13 +307,11 @@ class FavoritesSyncHelper(val context: Context) { ) if (!explicitlyRetryExhRequest(10, request)) { - val errorString = context.stringResource(SYMR.strings.favorites_sync_unable_to_delete) - if (prefs.exhLenientSync().get()) { - errorList += errorString + errorList += FavoritesSyncStatus.SyncError.GallerySyncError.UnableToDeleteFromRemote } else { - status.value = FavoritesSyncStatus.Error(errorString) - throw IgnoredException(errorString) + status.value = FavoritesSyncStatus.SyncError.GallerySyncError.UnableToDeleteFromRemote + throw IgnoredException(FavoritesSyncStatus.SyncError.GallerySyncError.UnableToDeleteFromRemote) } } } @@ -329,10 +319,10 @@ class FavoritesSyncHelper(val context: Context) { // Apply additions throttleManager.resetThrottle() changeSet.added.forEachIndexed { index, it -> - status.value = FavoritesSyncStatus.Processing( - message = context.stringResource(SYMR.strings.favorites_sync_adding_to_remote, index + 1, changeSet.added.size), - isThrottle = needWarnThrottle(), - context = context, + status.value = FavoritesSyncStatus.Processing.AddingGalleryToRemote( + index = index + 1, + total = changeSet.added.size, + isThrottling = needWarnThrottle(), title = it.title, ) @@ -342,14 +332,17 @@ class FavoritesSyncHelper(val context: Context) { } } - private suspend fun applyChangeSetToLocal(errorList: MutableList, changeSet: ChangeSet) { + private suspend fun applyChangeSetToLocal( + errorList: MutableList, + changeSet: ChangeSet, + ) { val removedManga = mutableListOf() // Apply removals changeSet.removed.forEachIndexed { index, it -> - status.value = FavoritesSyncStatus.Processing( - context.stringResource(SYMR.strings.favorites_sync_remove_from_local, index + 1, changeSet.removed.size), - title = it.title, + status.value = FavoritesSyncStatus.Processing.RemovingGalleryFromLocal( + index = index + 1, + total = changeSet.removed.size, ) val url = it.getUrl() @@ -379,10 +372,10 @@ class FavoritesSyncHelper(val context: Context) { // Apply additions throttleManager.resetThrottle() changeSet.added.forEachIndexed { index, it -> - status.value = FavoritesSyncStatus.Processing( - message = context.stringResource(SYMR.strings.favorites_sync_add_to_local, index + 1, changeSet.added.size), - isThrottle = needWarnThrottle(), - context = context, + status.value = FavoritesSyncStatus.Processing.AddingGalleryToLocal( + index = index + 1, + total = changeSet.added.size, + isThrottling = needWarnThrottle(), title = it.title, ) @@ -405,24 +398,23 @@ class FavoritesSyncHelper(val context: Context) { return@forEachIndexed } - val errorString = context.stringResource(SYMR.strings.favorites_sync_failed_to_add_to_local) + - when (result) { - is GalleryAddEvent.Fail.Error -> context.stringResource( - SYMR.strings.favorites_sync_failed_to_add_to_local_error, it.title, result.logMessage, - ) - is GalleryAddEvent.Fail.UnknownType -> context.stringResource( - SYMR.strings.favorites_sync_failed_to_add_to_local_unknown_type, it.title, result.galleryUrl, - ) - is GalleryAddEvent.Fail.UnknownSource -> context.stringResource( - SYMR.strings.favorites_sync_failed_to_add_to_local_unknown_type, it.title, result.galleryUrl, - ) - } + val error = when (result) { + is GalleryAddEvent.Fail.Error -> FavoritesSyncStatus.SyncError.GallerySyncError.GalleryAddFail( + it.title, result.logMessage, + ) + is GalleryAddEvent.Fail.UnknownType -> FavoritesSyncStatus.SyncError.GallerySyncError.InvalidGalleryFail( + it.title, result.galleryUrl, + ) + is GalleryAddEvent.Fail.UnknownSource -> FavoritesSyncStatus.SyncError.GallerySyncError.InvalidGalleryFail( + it.title, result.galleryUrl, + ) + } if (prefs.exhLenientSync().get()) { - errorList += errorString + errorList += error } else { - status.value = FavoritesSyncStatus.Error(errorString) - throw IgnoredException(errorString) + status.value = error + throw IgnoredException(error) } } else if (result is GalleryAddEvent.Success) { insertedMangaCategories += categories[it.category].id to result.manga @@ -438,59 +430,74 @@ class FavoritesSyncHelper(val context: Context) { private fun needWarnThrottle() = throttleManager.throttleTime >= THROTTLE_WARN - class IgnoredException(message: String) : RuntimeException(message) + class IgnoredException(message: FavoritesSyncStatus.SyncError.GallerySyncError) : RuntimeException(message.toString()) companion object { private val THROTTLE_WARN = 1.seconds } } +@Serializable sealed class FavoritesSyncStatus { - abstract val message: String - - data class Error(override val message: String) : FavoritesSyncStatus() - data class Idle(override val message: String) : FavoritesSyncStatus() { - constructor(context: Context) : this(context.stringResource(SYMR.strings.favorites_sync_waiting_for_start)) - } - sealed class BadLibraryState : FavoritesSyncStatus() { - data class MangaInMultipleCategories( - val manga: Manga, - val categories: List, - override val message: String, - ) : BadLibraryState() { - constructor(manga: Manga, categories: List, context: Context) : - this( - manga = manga, - categories = categories, - message = context.stringResource( - SYMR.strings.favorites_sync_gallery_in_multiple_categories, manga.title, - categories.joinToString { - it.name - }, - ), - ) + @Serializable + sealed class SyncError : FavoritesSyncStatus() { + @Serializable + data object NotLoggedInSyncError : SyncError() + @Serializable + data object FailedToFetchFavorites : SyncError() + @Serializable + data class UnknownSyncError(val message: String) : SyncError() + @Serializable + sealed class GallerySyncError : SyncError() { + @Serializable + data class UnableToAddGalleryToRemote(val title: String, val gid: String): GallerySyncError() + @Serializable + data object UnableToDeleteFromRemote : GallerySyncError() + @Serializable + data class GalleryAddFail(val title: String, val reason: String): GallerySyncError() + @Serializable + data class InvalidGalleryFail(val title: String, val url: String): GallerySyncError() } } - data class Initializing(override val message: String) : FavoritesSyncStatus() { - constructor(context: Context) : this(context.stringResource(SYMR.strings.favorites_sync_initializing)) + @Serializable + data object Idle : FavoritesSyncStatus() + @Serializable + sealed class BadLibraryState : FavoritesSyncStatus() { + @Serializable + data class MangaInMultipleCategories( + val mangaId: Long, + val mangaTitle: String, + val categories: List, + ) : BadLibraryState() } - data class Processing( - override val message: String, - val title: String? = null, - ) : FavoritesSyncStatus() { - constructor(message: String, isThrottle: Boolean, context: Context, title: String?) : - this( - if (isThrottle) { - context.stringResource(SYMR.strings.favorites_sync_processing_throttle, message) - } else { - message - }, - title, - ) - - val delayedMessage get() = if (title != null) this.message + "\n\n" + title else null - } - data class CompleteWithErrors(val messages: List) : FavoritesSyncStatus() { - override val message: String = messages.joinToString("\n") + @Serializable + data object Initializing : FavoritesSyncStatus() + @Serializable + sealed class Processing : FavoritesSyncStatus() { + data object VerifyingLibrary : Processing() + data object DownloadingFavorites : Processing() + data object CalculatingRemoteChanges : Processing() + data object CalculatingLocalChanges : Processing() + data object SyncingCategoryNames : Processing() + data class RemovingRemoteGalleries(val galleryCount: Int) : Processing() + data class AddingGalleryToRemote( + val index: Int, + val total: Int, + val isThrottling: Boolean, + val title: String, + ) : Processing() + data class RemovingGalleryFromLocal( + val index: Int, + val total: Int, + ) : Processing() + data class AddingGalleryToLocal( + val index: Int, + val total: Int, + val isThrottling: Boolean, + val title: String, + ) : Processing() + data object CleaningUp : Processing() } + @Serializable + data class CompleteWithErrors(val messages: List) : FavoritesSyncStatus() } diff --git a/i18n-sy/src/commonMain/moko-resources/base/strings.xml b/i18n-sy/src/commonMain/moko-resources/base/strings.xml index 7d04330cb..dfa631e1f 100644 --- a/i18n-sy/src/commonMain/moko-resources/base/strings.xml +++ b/i18n-sy/src/commonMain/moko-resources/base/strings.xml @@ -515,6 +515,7 @@ Removing %1$d galleries from remote server Unable to delete galleries from the remote servers! Adding gallery %1$d of %2$d to remote server + Unable to add gallery to remote server: '%1$s' (GID: %2$s)! Removing gallery %1$d of %2$d from local library Adding gallery %1$d of %2$d to local library Remote gallery does not exist, skipping: %1$s!