fix: defer import errors until the copy loop finishes
Errors and skips are collected while the copy loop runs and reported once it ends. The final import state is exhaustive - success, already added, invalid name, or nothing supported found - so every import run reaches a terminal state and the pipeline notification always resolves instead of lingering as an indeterminate progress bar.
This commit is contained in:
@@ -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,
|
||||
|
||||
+4
@@ -97,6 +97,10 @@ class DictionaryForegroundService : Service() {
|
||||
contentText = "${snapshot.percent}%",
|
||||
progressPercent = snapshot.percent,
|
||||
)
|
||||
} else if (snapshot == null && !isFinalizing &&
|
||||
notificationHelper.hasActiveProgressNotification()
|
||||
) {
|
||||
notificationHelper.cancelNotification()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ class DictionaryImportManager(
|
||||
val dictionariesDir = File(context.getExternalFilesDir(null), "dictionaries")
|
||||
val totalFiles = uris.size.coerceAtLeast(1)
|
||||
importedFiles.clear()
|
||||
val skippedNames = mutableListOf<String>()
|
||||
val deferredErrors = mutableListOf<String>()
|
||||
|
||||
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()
|
||||
|
||||
@@ -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<String>) : ImportOutcome
|
||||
data class InvalidFile(val message: String) : ImportOutcome
|
||||
data object NothingImported : ImportOutcome
|
||||
}
|
||||
|
||||
internal fun resolveImportOutcome(
|
||||
importedCount: Int,
|
||||
skippedNames: List<String>,
|
||||
deferredErrors: List<String>,
|
||||
): 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>) -> 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())
|
||||
}
|
||||
@@ -67,8 +67,9 @@
|
||||
<string name="dictionary_management_title">Словари</string>
|
||||
<string name="import_dictionary_button">Выбрать файлы</string>
|
||||
<string name="import_error">Не удалось импортировать словарь: %1$s</string>
|
||||
<string name="import_file_exists">Файл уже существует: %1$s</string>
|
||||
<string name="import_file_exists">Словарь уже добавлен: %1$s</string>
|
||||
<string name="import_invalid_file_name">Недопустимое имя файла: %1$s</string>
|
||||
<string name="import_nothing_imported">В выбранном нет поддерживаемых файлов словарей</string>
|
||||
<string name="dictionary_source_url_hint">URL</string>
|
||||
<string name="dictionary_source_add_button">Добавить источник</string>
|
||||
<string name="dictionary_source_duplicate">Этот URL уже существует</string>
|
||||
|
||||
@@ -65,8 +65,9 @@
|
||||
<string name="dictionary_management_title">Dictionaries</string>
|
||||
<string name="import_dictionary_button">Select files</string>
|
||||
<string name="import_error">Failed to import dictionary: %1$s</string>
|
||||
<string name="import_file_exists">File already exists: %1$s</string>
|
||||
<string name="import_file_exists">Dictionary already added: %1$s</string>
|
||||
<string name="import_invalid_file_name">Invalid file name: %1$s</string>
|
||||
<string name="import_nothing_imported">No supported dictionary files were found in the selection</string>
|
||||
<string name="dictionary_source_url_hint">URL</string>
|
||||
<string name="dictionary_source_add_button">Add source</string>
|
||||
<string name="dictionary_source_duplicate">This URL already exists</string>
|
||||
|
||||
Reference in New Issue
Block a user