diff --git a/app/src/main/java/com/example/research/common/util/NotificationHelper.kt b/app/src/main/java/com/example/research/common/util/NotificationHelper.kt index 3df875c..c4a1ecd 100644 --- a/app/src/main/java/com/example/research/common/util/NotificationHelper.kt +++ b/app/src/main/java/com/example/research/common/util/NotificationHelper.kt @@ -93,6 +93,8 @@ class NotificationHelper(private val context: Context) { notificationManager.cancel(NOTIFICATION_ID) } + fun hasActiveProgressNotification(): Boolean = lastNotificationKey != 0 + fun showUnifiedProgressNotification( title: String, contentText: String, diff --git a/app/src/main/java/com/example/research/feature/download/service/DictionaryForegroundService.kt b/app/src/main/java/com/example/research/feature/download/service/DictionaryForegroundService.kt index 2716c1f..dccbb8c 100644 --- a/app/src/main/java/com/example/research/feature/download/service/DictionaryForegroundService.kt +++ b/app/src/main/java/com/example/research/feature/download/service/DictionaryForegroundService.kt @@ -97,6 +97,10 @@ class DictionaryForegroundService : Service() { contentText = "${snapshot.percent}%", progressPercent = snapshot.percent, ) + } else if (snapshot == null && + notificationHelper.hasActiveProgressNotification() + ) { + notificationHelper.cancelNotification() } } } diff --git a/app/src/main/java/com/example/research/feature/import/DictionaryImportManager.kt b/app/src/main/java/com/example/research/feature/import/DictionaryImportManager.kt index 8d744f8..9bc86ea 100644 --- a/app/src/main/java/com/example/research/feature/import/DictionaryImportManager.kt +++ b/app/src/main/java/com/example/research/feature/import/DictionaryImportManager.kt @@ -36,6 +36,8 @@ class DictionaryImportManager( val dictionariesDir = File(context.getExternalFilesDir(null), "dictionaries") val totalFiles = uris.size.coerceAtLeast(1) importedFiles.clear() + val skippedNames = mutableListOf() + val deferredErrors = mutableListOf() if (!dictionariesDir.exists()) { dictionariesDir.mkdirs() @@ -46,9 +48,7 @@ class DictionaryImportManager( currentCoroutineContext().ensureActive() val fileName = getFileName(uri) ?: continue if (SafeFileName.validate(fileName) == null) { - mutableImportState.value = ImportState.Error( - context.getString(R.string.import_invalid_file_name, fileName) - ) + deferredErrors += context.getString(R.string.import_invalid_file_name, fileName) continue } val lowerFileName = fileName.lowercase() @@ -65,9 +65,7 @@ class DictionaryImportManager( val destFile = File(dictionariesDir, fileName) if (destFile.exists()) { - mutableImportState.value = ImportState.Error( - context.getString(R.string.import_file_exists, fileName) - ) + skippedNames += fileName continue } @@ -115,7 +113,17 @@ class DictionaryImportManager( currentCoroutineContext().ensureActive() - mutableImportState.value = ImportState.Success + mutableImportState.value = resolveImportOutcome( + importedCount = importedFiles.size, + skippedNames = skippedNames, + deferredErrors = deferredErrors, + ).toImportState( + existsMessage = { names -> + context.getString(R.string.import_file_exists, names.joinToString(separator = ", ")) + }, + invalidMessage = { message -> message }, + nothingImportedMessage = { context.getString(R.string.import_nothing_imported) }, + ) } catch (e: CancellationException) { cleanupImportedFiles() diff --git a/app/src/main/java/com/example/research/feature/import/ImportOutcome.kt b/app/src/main/java/com/example/research/feature/import/ImportOutcome.kt new file mode 100644 index 0000000..00973f7 --- /dev/null +++ b/app/src/main/java/com/example/research/feature/import/ImportOutcome.kt @@ -0,0 +1,32 @@ +package com.example.research.feature.import + +import com.example.research.ui.settings.ImportState + +internal sealed interface ImportOutcome { + data object Imported : ImportOutcome + data class AlreadyExists(val names: List) : ImportOutcome + data class InvalidFile(val message: String) : ImportOutcome + data object NothingImported : ImportOutcome +} + +internal fun resolveImportOutcome( + importedCount: Int, + skippedNames: List, + deferredErrors: List, +): ImportOutcome = when { + importedCount > 0 -> ImportOutcome.Imported + skippedNames.isNotEmpty() -> ImportOutcome.AlreadyExists(skippedNames) + deferredErrors.isNotEmpty() -> ImportOutcome.InvalidFile(deferredErrors.first()) + else -> ImportOutcome.NothingImported +} + +internal fun ImportOutcome.toImportState( + existsMessage: (List) -> String, + invalidMessage: (String) -> String, + nothingImportedMessage: () -> String, +): ImportState = when (this) { + ImportOutcome.Imported -> ImportState.Success + is ImportOutcome.AlreadyExists -> ImportState.Error(existsMessage(names)) + is ImportOutcome.InvalidFile -> ImportState.Error(invalidMessage(message)) + ImportOutcome.NothingImported -> ImportState.Error(nothingImportedMessage()) +} diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index d67a7b1..9fb677e 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -68,8 +68,9 @@ Словари Выбрать файлы Не удалось импортировать словарь: %1$s - Файл уже существует: %1$s + Словарь уже добавлен: %1$s Недопустимое имя файла: %1$s + В выбранном нет поддерживаемых файлов словарей URL Добавить источник Этот URL уже существует diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a6eba8e..e69a723 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -66,8 +66,9 @@ Dictionaries Select files Failed to import dictionary: %1$s - File already exists: %1$s + Dictionary already added: %1$s Invalid file name: %1$s + No supported dictionary files were found in the selection URL Add source This URL already exists