Skip to content

Commit b1d177a

Browse files
committed
improvement(import): improve 'cache error' message
Title: Failed to cache file **Dialog content:** oaz: Cello error 2. This is often caused by a bug in the app you used to select the file. Please try the following fixes: • Try re-importing the file • Ensure there is sufficient free space on your device • Ensure you are connected to the internet • Copy the file to your device and try again • Open the file using your device's file browser app 'Copy debug info' provides the stack trace, then title + content Fixes 19616
1 parent 27cfffd commit b1d177a

File tree

4 files changed

+61
-16
lines changed

4 files changed

+61
-16
lines changed

AnkiDroid/src/main/java/com/ichi2/anki/IntentHandler.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ class IntentHandler : AbstractIntentHandler() {
226226
is ImportResult.Failure -> {
227227
Timber.i("File import failed")
228228
// Don't import the file if it didn't load properly or doesn't have apkg extension
229-
showImportUnsuccessfulDialog(this, importResult.humanReadableMessage, true)
229+
showImportUnsuccessfulDialog(this, importResult, true)
230230
}
231231
}
232232
}

AnkiDroid/src/main/java/com/ichi2/utils/ImportUtils.kt

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,10 @@ object ImportUtils {
139139
} catch (e: Exception) {
140140
CrashReportService.sendExceptionReport(e, "handleFileImport")
141141
Timber.e(e, "failed to handle import intent")
142-
ImportResult.Failure(context.getString(R.string.import_error_handle_exception, e.localizedMessage), e)
142+
ImportResult.Failure(
143+
humanReadableMessage = context.getString(R.string.import_error_handle_exception, e.localizedMessage),
144+
exception = e,
145+
)
143146
}
144147
}
145148

@@ -234,9 +237,13 @@ object ImportUtils {
234237
filename = ensureValidLength(filename)
235238
tempOutDir = Uri.fromFile(File(context.cacheDir, filename)).encodedPath!!
236239

237-
copyFileToCache(context, importPathUri, tempOutDir).asErrorDetails(context)?.let { details ->
240+
copyFileToCache(context, importPathUri, tempOutDir).asErrorDetails()?.let { details ->
238241
CrashReportService.sendExceptionReport(details.exceptionForReport, "ImportUtils")
239-
return ImportResult.Failure(details.userFacingString, details.userFacingException)
242+
return ImportResult.Failure(
243+
title = details.buildTitle(context),
244+
humanReadableMessage = details.buildHumanReadableMessage(context),
245+
exception = details.userFacingException,
246+
)
240247
}
241248
sendShowImportFileDialogMsg(tempOutDir)
242249
return ImportResult.Success
@@ -317,7 +324,7 @@ object ImportUtils {
317324
exitActivity: Boolean,
318325
) {
319326
Timber.d("showImportUnsuccessfulDialog() message %s", failure.humanReadableMessage)
320-
val title = activity.resources.getString(R.string.import_title_error)
327+
val title = failure.title ?: activity.getString(R.string.import_title_error)
321328
val dialog =
322329
AlertDialog.Builder(activity).show {
323330
title(text = title)
@@ -376,28 +383,46 @@ object ImportUtils {
376383

377384
data object ContentProviderCrashed : CacheFileResult()
378385

379-
fun asErrorDetails(context: Context): ErrorDetails? =
386+
fun asErrorDetails(): CacheErrorDetails? =
380387
when (this) {
381388
is Success -> null
382389
is Error ->
383-
ErrorDetails(
390+
CacheErrorDetails(
384391
exceptionForReport = exception,
385-
userFacingString = context.getString(R.string.import_error_copy_to_cache),
386392
userFacingException = exception,
387393
)
388394
is ContentProviderCrashed ->
389-
ErrorDetails(
395+
CacheErrorDetails(
390396
exceptionForReport = ManuallyReportedException("Content provider crashed"),
391-
userFacingString = context.getString(R.string.import_error_copy_to_cache),
392397
userFacingException = null,
393398
)
394399
}
395400

396-
data class ErrorDetails(
401+
data class CacheErrorDetails(
397402
val exceptionForReport: Exception,
398-
val userFacingString: String,
399403
val userFacingException: Exception?,
400-
)
404+
) {
405+
fun buildTitle(context: Context) = context.getString(R.string.import_error_copy_to_cache_title)
406+
407+
fun buildHumanReadableMessage(context: Context) =
408+
buildString {
409+
// "oaz: Cello error 2."
410+
if (userFacingException != null) {
411+
appendLine(userFacingException.message)
412+
appendLine()
413+
}
414+
415+
// "This is often caused by the file provider, try these fixes:"
416+
val suggestedFixes =
417+
buildString {
418+
// build a bulleted list of suggested fixes
419+
for (line in context.resources.getStringArray(R.array.import_cache_error_resolutions)) {
420+
appendLine("\u2022 $line")
421+
}
422+
}
423+
append(context.getString(R.string.import_error_copy_to_cache_explanation, suggestedFixes))
424+
}
425+
}
401426
}
402427

403428
companion object {
@@ -515,13 +540,18 @@ sealed class ImportResult {
515540
data class Failure(
516541
val humanReadableMessage: String,
517542
val exception: Exception? = null,
543+
val title: String? = null,
518544
) : ImportResult() {
519545
fun toDebugInfo(): String? {
520546
if (exception == null) return null
521547
return buildString {
522-
appendLine(humanReadableMessage)
523-
appendLine()
524548
appendLine(exception.stackTraceToString())
549+
if (title != null) {
550+
appendLine()
551+
appendLine(title)
552+
}
553+
appendLine()
554+
appendLine(humanReadableMessage)
525555
}
526556
}
527557
}

AnkiDroid/src/main/res/values/02-strings.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@
160160
<string name="import_error_not_apkg_extension">Filename “%s” doesn’t have .apkg or .colpkg extension</string>
161161
<string name="import_error_load_imported_database">Anki Database (.anki2) replacements are not yet supported. Please see the manual for replacement instructions.</string>
162162
<string name="import_error_content_provider">The selected file couldn’t be imported automatically by AnkiDroid. Please see the user manual for how to manually import Anki files: \n%s</string>
163-
<string name="import_error_copy_to_cache">Failed to cache file (possibly out of storage space)</string>
163+
<string name="import_error_copy_to_cache_title">Failed to cache file</string>
164+
<string name="import_error_copy_to_cache_explanation" comment="The substitution is a list of suggested fixes in bullet point form">This is often caused by a bug in the app you used to select the file. Please try the following fixes:\n\n%s</string>
164165
<string name="import_interrupted">Import interrupted: AnkiDroid was closed</string>
165166
<string name="export_ready_title">Export ready</string>
166167
<string name="export_send_no_handlers">No applications available to handle apkg. Saving…</string>

AnkiDroid/src/main/res/values/03-dialogs.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,4 +268,18 @@ also changes the interval of the card"
268268
<string name="tts_error_dialog_reason_text">The text to speech engine <b>%1$s</b> does not support the following language: <b>%2$s</b></string>
269269
<string name="tts_error_dialog_change_button_text">Change engine</string>
270270
<string name="tts_error_dialog_supported_voices_button_text">Voice options</string>
271+
272+
<string-array name="import_cache_error_resolutions">
273+
<item>@string/import_error_resolution_try_again</item>
274+
<item>@string/import_error_resolution_free_up_space</item>
275+
<item>@string/import_error_resolution_check_internet</item>
276+
<item>@string/import_error_resolution_copy_to_device</item>
277+
<item>@string/import_error_resolution_select_file</item>
278+
</string-array>
279+
280+
<string name="import_error_resolution_try_again">Try re-importing the file</string>
281+
<string name="import_error_resolution_free_up_space">Ensure there is sufficient free space on your device</string>
282+
<string name="import_error_resolution_check_internet">Ensure you are connected to the internet</string>
283+
<string name="import_error_resolution_copy_to_device">Copy the file to your device and try again</string>
284+
<string name="import_error_resolution_select_file">Open the file using your device’s file browser app</string>
271285
</resources>

0 commit comments

Comments
 (0)