From 120734ff41380cfedf87b2f1c68549db6ead7cc2 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Wed, 28 May 2025 22:31:18 +0200 Subject: [PATCH] avoid issues when resetting DictionaryFacilitatorImpl see GH-801 (probably does not fix the OnePlus issue) --- .../latin/DictionaryFacilitatorImpl.kt | 9 ++++--- .../keyboard/latin/DictionaryFactory.kt | 2 +- .../latin/utils/DictionaryInfoUtils.kt | 24 ++++++++++++------- .../settings/screens/DictionaryScreen.kt | 4 ++-- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorImpl.kt b/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorImpl.kt index 13800aa7c..1174f850d 100644 --- a/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorImpl.kt +++ b/app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorImpl.kt @@ -716,9 +716,12 @@ private class DictionaryGroup( private val scope = CoroutineScope(Dispatchers.IO) // words cannot be (permanently) removed from some dictionaries, so we use a blacklist for "removing" words - private val blacklistFile = context?.let { - File(it.filesDir.absolutePath + File.separator + "blacklists" + File.separator + locale.toLanguageTag() + ".txt") - .also { it.parentFile?.mkdirs() } + private val blacklistFile = if (context?.filesDir == null) null + else { + val file = File(context.filesDir.absolutePath + File.separator + "blacklists" + File.separator + locale.toLanguageTag() + ".txt") + if (file.isDirectory) file.delete() // this apparently was an issue in some versions + if (file.mkdirs()) file + else null } private val blacklist = hashSetOf().apply { diff --git a/app/src/main/java/helium314/keyboard/latin/DictionaryFactory.kt b/app/src/main/java/helium314/keyboard/latin/DictionaryFactory.kt index 545511808..bd86960b3 100644 --- a/app/src/main/java/helium314/keyboard/latin/DictionaryFactory.kt +++ b/app/src/main/java/helium314/keyboard/latin/DictionaryFactory.kt @@ -34,7 +34,7 @@ object DictionaryFactory { nonExtracted.forEach { filename -> val type = filename.substringBefore("_") if (dictList.any { it.mDictType == type }) return@forEach - val extractedFile = DictionaryInfoUtils.extractAssetsDictionary(filename, locale, context) + val extractedFile = DictionaryInfoUtils.extractAssetsDictionary(filename, locale, context) ?: return@forEach checkAndAddDictionaryToListNewType(extractedFile, dictList, locale) } return DictionaryCollection(Dictionary.TYPE_MAIN, locale, dictList, FloatArray(dictList.size) { 1f }) diff --git a/app/src/main/java/helium314/keyboard/latin/utils/DictionaryInfoUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/DictionaryInfoUtils.kt index e98079c91..8715d2d4c 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/DictionaryInfoUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/DictionaryInfoUtils.kt @@ -90,18 +90,19 @@ object DictionaryInfoUtils { fun getCacheDirectories(context: Context) = File(getWordListCacheDirectory(context)).listFiles().orEmpty() /** Find out the cache directory associated with a specific locale. */ - fun getCacheDirectoryForLocale(locale: Locale, context: Context): String { + fun getCacheDirectoryForLocale(locale: Locale, context: Context): String? { val relativeDirectoryName = replaceFileNameDangerousCharacters(locale.toLanguageTag()) val absoluteDirectoryName = getWordListCacheDirectory(context) + File.separator + relativeDirectoryName val directory = File(absoluteDirectoryName) if (!directory.exists() && !directory.mkdirs()) { Log.e(TAG, "Could not create the directory for locale $locale") + return null } return absoluteDirectoryName } fun getCachedDictsForLocale(locale: Locale, context: Context) = - File(getCacheDirectoryForLocale(locale, context)).listFiles().orEmpty() + getCacheDirectoryForLocale(locale, context)?.let { File(it).listFiles() }.orEmpty() fun getDictionaryFileHeaderOrNull(file: File, offset: Long, length: Long): DictionaryHeader? { return try { @@ -135,12 +136,19 @@ object DictionaryInfoUtils { return dictionaryFileName.substringAfter("_").substringBefore(".").constructLocale() } - fun extractAssetsDictionary(dictionaryFileName: String, locale: Locale, context: Context): File { - val targetFile = File(getCacheDirectoryForLocale(locale, context), "${dictionaryFileName.substringBefore("_")}.dict") - FileUtils.copyStreamToNewFile( - context.assets.open(ASSETS_DICTIONARY_FOLDER + File.separator + dictionaryFileName), - targetFile - ) + // actually we could extract assets dicts to unprotected storage + fun extractAssetsDictionary(dictionaryFileName: String, locale: Locale, context: Context): File? { + val cacheDir = getCacheDirectoryForLocale(locale, context) ?: return null + val targetFile = File(cacheDir, "${dictionaryFileName.substringBefore("_")}.dict") + try { + FileUtils.copyStreamToNewFile( + context.assets.open(ASSETS_DICTIONARY_FOLDER + File.separator + dictionaryFileName), + targetFile + ) + } catch (e: IOException) { + Log.e(TAG, "Could not extract assets dictionary $dictionaryFileName") + return null + } return targetFile } diff --git a/app/src/main/java/helium314/keyboard/settings/screens/DictionaryScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/DictionaryScreen.kt index d7359533d..dc64cadd8 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/DictionaryScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/DictionaryScreen.kt @@ -142,8 +142,8 @@ fun DictionaryScreen( fun getUserAndInternalDictionaries(context: Context, locale: Locale): Pair, Boolean> { val userDicts = mutableListOf() var hasInternalDict = false - val userLocaleDir = File(DictionaryInfoUtils.getCacheDirectoryForLocale(locale, context)) - if (userLocaleDir.exists() && userLocaleDir.isDirectory) { + val userLocaleDir = DictionaryInfoUtils.getCacheDirectoryForLocale(locale, context)?.let { File(it) } + if (userLocaleDir?.exists() == true && userLocaleDir.isDirectory) { userLocaleDir.listFiles()?.forEach { if (it.name.endsWith(DictionaryInfoUtils.USER_DICTIONARY_SUFFIX)) userDicts.add(it)