Allow deleting imported dictionaries and voice input models

This commit is contained in:
Aleksandras Kostarevas 2024-04-01 16:48:39 -05:00
parent 626477a027
commit 31b5fe933e
4 changed files with 108 additions and 11 deletions

View File

@ -266,6 +266,18 @@ object ResourceHelper {
Dictionary.TYPE_MAIN
)
}
fun deleteResourceForLanguage(context: Context, kind: FileKind, locale: Locale) {
val setting = kind.preferencesKeyFor(locale.toString())
val value = runBlocking { context.getSetting(setting, "") }
if(value.isNotBlank()) {
runBlocking { context.setSetting(setting, "") }
val file = File(context.getExternalFilesDir(null), value)
file.delete()
}
LatinIMELegacy.mPendingDictionaryUpdate = true
}
}
class ImportResourceActivity : ComponentActivity() {
@ -314,7 +326,7 @@ class ImportResourceActivity : ComponentActivity() {
applicationContext.setSetting(key, outputFileName)
}
}
LatinIMELegacy.mPendingDictionaryUpdate = true;
LatinIMELegacy.mPendingDictionaryUpdate = true
finish()
}
}

View File

@ -6,6 +6,7 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
@ -15,6 +16,8 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
@ -33,6 +36,7 @@ import org.futo.inputmethod.latin.uix.VERBOSE_PROGRESS
import org.futo.inputmethod.latin.uix.getSetting
import org.futo.inputmethod.latin.uix.voiceinput.downloader.DownloadActivity
import org.futo.inputmethod.latin.xlm.UserDictionaryObserver
import org.futo.inputmethod.updates.openURI
import org.futo.voiceinput.shared.ModelDoesNotExistException
import org.futo.voiceinput.shared.RecognizerView
import org.futo.voiceinput.shared.RecognizerViewListener
@ -224,15 +228,18 @@ private class VoiceInputNoModelWindow(val locale: Locale) : ActionWindow {
@Composable
override fun WindowContents(keyboardShown: Boolean) {
val context = LocalContext.current
Box(modifier = Modifier
.fillMaxSize()
.clickable(enabled = true,
onClickLabel = null,
onClick = { TODO() },
onClick = {
context.openURI("https://keyboard.futo.org/voice-input-models", true)
},
role = null,
indication = null,
interactionSource = remember { MutableInteractionSource() })) {
Text("No model available for ${locale.displayLanguage}, tap to check options?", modifier = Modifier.align(Alignment.Center))
Text("No voice input model installed for ${locale.displayLanguage}, tap to check options?", modifier = Modifier.align(Alignment.Center).padding(8.dp), textAlign = TextAlign.Center)
}
}

View File

@ -1,7 +1,13 @@
package org.futo.inputmethod.latin.uix.settings.pages
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@ -20,6 +26,7 @@ import org.futo.inputmethod.latin.uix.settings.ScreenTitle
import org.futo.inputmethod.latin.uix.settings.ScrollableList
import org.futo.inputmethod.latin.uix.settings.Tip
import org.futo.inputmethod.latin.uix.settings.openLanguageSettings
import org.futo.inputmethod.latin.uix.youAreImporting
import org.futo.inputmethod.latin.utils.SubtypeLocaleUtils
import org.futo.inputmethod.latin.xlm.ModelPaths
import org.futo.inputmethod.updates.openURI
@ -31,11 +38,69 @@ data class LanguageOptions(
val transformerModel: String?
)
@Composable
fun ConfirmDeleteResourceDialog(
onDismissRequest: () -> Unit,
onConfirmation: () -> Unit,
dialogTitle: String,
dialogText: String,
) {
AlertDialog(
icon = {
Icon(painterResource(id = R.drawable.delete), contentDescription = "Example Icon")
},
title = {
Text(text = dialogTitle)
},
text = {
Text(text = dialogText)
},
onDismissRequest = {
onDismissRequest()
},
confirmButton = {
TextButton(
onClick = {
onConfirmation()
}
) {
Text("Delete")
}
},
dismissButton = {
TextButton(
onClick = {
onDismissRequest()
}
) {
Text("Cancel")
}
}
)
}
data class DeleteInfo(
val locale: Locale,
val kind: FileKind
)
@Preview
@Composable
fun LanguagesScreen(navController: NavHostController = rememberNavController()) {
val context = LocalContext.current
val deleteDialogInfo: MutableState<DeleteInfo?> = remember { mutableStateOf(null) }
if(deleteDialogInfo.value != null) {
val info = deleteDialogInfo.value!!
ConfirmDeleteResourceDialog(
onDismissRequest = { deleteDialogInfo.value = null },
onConfirmation = {
ResourceHelper.deleteResourceForLanguage(context, info.kind, info.locale)
deleteDialogInfo.value = null
},
dialogTitle = "Delete ${info.kind.youAreImporting()} for ${info.locale.displayLanguage}?",
dialogText = "If deleted, the imported ${info.kind.youAreImporting()} file for ${info.locale.displayLanguage} will be deleted. If there is no built-in fallback for this language, the feature may cease to function. You can always download and re-import a different ${info.kind.youAreImporting()} file."
)
}
ScrollableList {
ScreenTitle("Languages", showBack = true, navController)
@ -55,10 +120,7 @@ fun LanguagesScreen(navController: NavHostController = rememberNavController())
val voiceInputModelName = ResourceHelper.tryFindingVoiceInputModelForLocale(context, locale)?.name?.let { stringResource(it) }
val dictionaryName = runBlocking { ResourceHelper.findFileForKind(context, locale, FileKind.Dictionary) }?.let {
"Imported Dictionary"
} ?: if(BinaryDictionaryGetter.getDictionaryFiles(locale, context, false, false).let {
println("DICTIONARIES FOR ${locale.displayLanguage}: ${it.toList().map { it.mFilename }.joinToString(",")}")
it
}.isNotEmpty()) {
} ?: if(BinaryDictionaryGetter.getDictionaryFiles(locale, context, false, false).isNotEmpty()) {
"Built-in Dictionary"
} else {
null
@ -80,7 +142,11 @@ fun LanguagesScreen(navController: NavHostController = rememberNavController())
title = options.voiceInputModel ?: "None",
style = options.voiceInputModel?.let { NavigationItemStyle.HomeTertiary } ?: NavigationItemStyle.MiscNoArrow,
navigate = {
context.openURI("https://keyboard.futo.org/voice-input-models", true)
if(runBlocking { ResourceHelper.findFileForKind(context, locale, FileKind.VoiceInput) } == null) {
context.openURI("https://keyboard.futo.org/voice-input-models", true)
} else {
deleteDialogInfo.value = DeleteInfo(locale, FileKind.VoiceInput)
}
},
icon = painterResource(id = R.drawable.mic_fill)
)
@ -88,7 +154,14 @@ fun LanguagesScreen(navController: NavHostController = rememberNavController())
title = options.dictionary ?: "None",
style = options.dictionary?.let { NavigationItemStyle.HomeTertiary } ?: NavigationItemStyle.MiscNoArrow,
navigate = {
context.openURI("https://codeberg.org/Helium314/aosp-dictionaries#dictionaries", true)
if(runBlocking { ResourceHelper.findFileForKind(context, locale, FileKind.Dictionary) } == null) {
context.openURI(
"https://codeberg.org/Helium314/aosp-dictionaries#dictionaries",
true
)
} else {
deleteDialogInfo.value = DeleteInfo(locale, FileKind.Dictionary)
}
},
icon = painterResource(id = R.drawable.book)
)
@ -96,7 +169,11 @@ fun LanguagesScreen(navController: NavHostController = rememberNavController())
title = options.transformerModel ?: "None",
style = options.transformerModel?.let { NavigationItemStyle.HomeTertiary } ?: NavigationItemStyle.MiscNoArrow,
navigate = {
context.openURI("https://keyboard.futo.org/models", true)
if(options.transformerModel == null) {
context.openURI("https://keyboard.futo.org/models", true)
} else {
navController.navigate("models")
}
},
icon = painterResource(id = R.drawable.cpu)
)

View File

@ -25,6 +25,7 @@ import org.futo.inputmethod.latin.xlm.ModelInfo
import org.futo.inputmethod.latin.xlm.ModelPaths
import org.futo.inputmethod.updates.openURI
import java.net.URLEncoder
import java.util.Locale
@Composable
fun ModelNavigationItem(navController: NavHostController, name: String, isPrimary: Boolean, path: String) {
@ -68,7 +69,7 @@ fun ModelListScreen(navController: NavHostController = rememberNavController())
modelsByLanguage.forEach { item ->
Spacer(modifier = Modifier.height(32.dp))
ScreenTitle(item.key)
ScreenTitle(Locale(item.key).displayLanguage)
item.value.forEach { model ->
val name = if (model.finetune_count > 0) {