avoid issues when resetting DictionaryFacilitatorImpl

see GH-801 (probably does not fix the OnePlus issue)
This commit is contained in:
Helium314 2025-05-28 22:31:18 +02:00
parent 0d5159c2d7
commit 120734ff41
4 changed files with 25 additions and 14 deletions

View file

@ -716,9 +716,12 @@ private class DictionaryGroup(
private val scope = CoroutineScope(Dispatchers.IO) private val scope = CoroutineScope(Dispatchers.IO)
// words cannot be (permanently) removed from some dictionaries, so we use a blacklist for "removing" words // words cannot be (permanently) removed from some dictionaries, so we use a blacklist for "removing" words
private val blacklistFile = context?.let { private val blacklistFile = if (context?.filesDir == null) null
File(it.filesDir.absolutePath + File.separator + "blacklists" + File.separator + locale.toLanguageTag() + ".txt") else {
.also { it.parentFile?.mkdirs() } 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<String>().apply { private val blacklist = hashSetOf<String>().apply {

View file

@ -34,7 +34,7 @@ object DictionaryFactory {
nonExtracted.forEach { filename -> nonExtracted.forEach { filename ->
val type = filename.substringBefore("_") val type = filename.substringBefore("_")
if (dictList.any { it.mDictType == type }) return@forEach 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) checkAndAddDictionaryToListNewType(extractedFile, dictList, locale)
} }
return DictionaryCollection(Dictionary.TYPE_MAIN, locale, dictList, FloatArray(dictList.size) { 1f }) return DictionaryCollection(Dictionary.TYPE_MAIN, locale, dictList, FloatArray(dictList.size) { 1f })

View file

@ -90,18 +90,19 @@ object DictionaryInfoUtils {
fun getCacheDirectories(context: Context) = File(getWordListCacheDirectory(context)).listFiles().orEmpty() fun getCacheDirectories(context: Context) = File(getWordListCacheDirectory(context)).listFiles().orEmpty()
/** Find out the cache directory associated with a specific locale. */ /** 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 relativeDirectoryName = replaceFileNameDangerousCharacters(locale.toLanguageTag())
val absoluteDirectoryName = getWordListCacheDirectory(context) + File.separator + relativeDirectoryName val absoluteDirectoryName = getWordListCacheDirectory(context) + File.separator + relativeDirectoryName
val directory = File(absoluteDirectoryName) val directory = File(absoluteDirectoryName)
if (!directory.exists() && !directory.mkdirs()) { if (!directory.exists() && !directory.mkdirs()) {
Log.e(TAG, "Could not create the directory for locale $locale") Log.e(TAG, "Could not create the directory for locale $locale")
return null
} }
return absoluteDirectoryName return absoluteDirectoryName
} }
fun getCachedDictsForLocale(locale: Locale, context: Context) = 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? { fun getDictionaryFileHeaderOrNull(file: File, offset: Long, length: Long): DictionaryHeader? {
return try { return try {
@ -135,12 +136,19 @@ object DictionaryInfoUtils {
return dictionaryFileName.substringAfter("_").substringBefore(".").constructLocale() return dictionaryFileName.substringAfter("_").substringBefore(".").constructLocale()
} }
fun extractAssetsDictionary(dictionaryFileName: String, locale: Locale, context: Context): File { // actually we could extract assets dicts to unprotected storage
val targetFile = File(getCacheDirectoryForLocale(locale, context), "${dictionaryFileName.substringBefore("_")}.dict") fun extractAssetsDictionary(dictionaryFileName: String, locale: Locale, context: Context): File? {
FileUtils.copyStreamToNewFile( val cacheDir = getCacheDirectoryForLocale(locale, context) ?: return null
context.assets.open(ASSETS_DICTIONARY_FOLDER + File.separator + dictionaryFileName), val targetFile = File(cacheDir, "${dictionaryFileName.substringBefore("_")}.dict")
targetFile 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 return targetFile
} }

View file

@ -142,8 +142,8 @@ fun DictionaryScreen(
fun getUserAndInternalDictionaries(context: Context, locale: Locale): Pair<List<File>, Boolean> { fun getUserAndInternalDictionaries(context: Context, locale: Locale): Pair<List<File>, Boolean> {
val userDicts = mutableListOf<File>() val userDicts = mutableListOf<File>()
var hasInternalDict = false var hasInternalDict = false
val userLocaleDir = File(DictionaryInfoUtils.getCacheDirectoryForLocale(locale, context)) val userLocaleDir = DictionaryInfoUtils.getCacheDirectoryForLocale(locale, context)?.let { File(it) }
if (userLocaleDir.exists() && userLocaleDir.isDirectory) { if (userLocaleDir?.exists() == true && userLocaleDir.isDirectory) {
userLocaleDir.listFiles()?.forEach { userLocaleDir.listFiles()?.forEach {
if (it.name.endsWith(DictionaryInfoUtils.USER_DICTIONARY_SUFFIX)) if (it.name.endsWith(DictionaryInfoUtils.USER_DICTIONARY_SUFFIX))
userDicts.add(it) userDicts.add(it)