Skip to content

Commit d742cb9

Browse files
committed
feat: toggle dictionaries individually
1 parent f87e6b1 commit d742cb9

3 files changed

Lines changed: 85 additions & 10 deletions

File tree

app/src/main/java/helium314/keyboard/latin/DictionaryFacilitatorImpl.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package helium314.keyboard.latin
77

88
import android.Manifest
99
import android.content.Context
10+
import android.content.SharedPreferences
1011
import android.provider.UserDictionary
1112
import android.util.LruCache
1213
import helium314.keyboard.keyboard.Keyboard
@@ -60,6 +61,8 @@ import java.util.concurrent.TimeUnit
6061
*/
6162
@OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
6263
class DictionaryFacilitatorImpl : DictionaryFacilitator {
64+
private var mPrefs: SharedPreferences? = null
65+
private var mEnabledDictionariesState: Map<String, Boolean> = emptyMap()
6366
private var dictionaryGroups = listOf(DictionaryGroup())
6467

6568
@Volatile
@@ -133,6 +136,14 @@ class DictionaryFacilitatorImpl : DictionaryFacilitator {
133136
}
134137

135138
override fun usesSameSettings(locales: List<Locale>, contacts: Boolean, apps: Boolean, personalization: Boolean): Boolean {
139+
val prefs = mPrefs
140+
if (prefs != null) {
141+
val currentPrefs = prefs.all.filterKeys { it.startsWith("pref_dict_enabled_") }
142+
.mapValues { it.value as? Boolean ?: true }
143+
if (currentPrefs != mEnabledDictionariesState) {
144+
return false
145+
}
146+
}
136147
val dictGroup = dictionaryGroups[0] // settings are the same for all groups
137148
return contacts == dictGroup.hasDict(Dictionary.TYPE_CONTACTS)
138149
&& apps == dictGroup.hasDict(Dictionary.TYPE_APPS)
@@ -154,6 +165,10 @@ class DictionaryFacilitatorImpl : DictionaryFacilitator {
154165
listener: DictionaryInitializationListener?
155166
) {
156167
Log.i(TAG, "resetDictionaries, force reloading main dictionary: $forceReloadMainDictionary")
168+
val prefs = context.prefs()
169+
mPrefs = prefs
170+
mEnabledDictionariesState = prefs.all.filterKeys { it.startsWith("pref_dict_enabled_") }
171+
.mapValues { it.value as? Boolean ?: true }
157172

158173
// Initialize session word boost with context if not yet done
159174
if (sessionWordBoost == null) {

app/src/main/java/helium314/keyboard/latin/dictionary/DictionaryFactory.kt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package helium314.keyboard.latin.dictionary
88
import android.content.Context
99
import helium314.keyboard.latin.common.LocaleUtils
1010
import helium314.keyboard.latin.utils.DictionaryInfoUtils
11+
import helium314.keyboard.latin.utils.prefs
1112
import helium314.keyboard.latin.utils.Log
1213
import java.io.File
1314
import java.util.LinkedList
@@ -29,13 +30,13 @@ object DictionaryFactory {
2930
val (extracted, nonExtracted) = getAvailableDictsForLocale(locale, context, useEmojiDict)
3031
extracted.sortedBy { !it.name.endsWith(DictionaryInfoUtils.USER_DICTIONARY_SUFFIX) }.forEach {
3132
// we sort to have user dicts first, so they have priority over internal dicts of the same type
32-
checkAndAddDictionaryToListIfNewType(it, dictList, locale)
33+
checkAndAddDictionaryToListIfNewType(it, dictList, locale, context)
3334
}
3435
nonExtracted.forEach { filename ->
3536
val type = filename.substringBefore("_")
3637
if (dictList.any { it.mDictType == type }) return@forEach
3738
val extractedFile = DictionaryInfoUtils.extractAssetsDictionary(filename, locale, context) ?: return@forEach
38-
checkAndAddDictionaryToListIfNewType(extractedFile, dictList, locale)
39+
checkAndAddDictionaryToListIfNewType(extractedFile, dictList, locale, context)
3940
}
4041
return DictionaryCollection(Dictionary.TYPE_MAIN, locale, dictList, FloatArray(dictList.size) { 1f })
4142
}
@@ -64,7 +65,15 @@ object DictionaryFactory {
6465
* if [file] cannot be loaded it is deleted
6566
* if the dictionary type already exists in [dicts], the [file] is skipped
6667
*/
67-
private fun checkAndAddDictionaryToListIfNewType(file: File, dicts: MutableList<Dictionary>, locale: Locale) {
68+
private fun checkAndAddDictionaryToListIfNewType(file: File, dicts: MutableList<Dictionary>, locale: Locale, context: Context) {
69+
val header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(file)
70+
if (header != null) {
71+
val prefs = context.prefs()
72+
if (!prefs.getBoolean("pref_dict_enabled_${header.mIdString}", true)) {
73+
Log.i("DictionaryFactory", "skipping disabled dictionary ${header.mIdString}")
74+
return
75+
}
76+
}
6877
val dictionary = getDictionary(file, locale) ?: return
6978
if (dicts.any { it.mDictType == dictionary.mDictType }) {
7079
dictionary.close()

app/src/main/java/helium314/keyboard/settings/dialogs/DictionaryDialog.kt

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.padding
1313
import androidx.compose.material3.HorizontalDivider
1414
import androidx.compose.material3.LocalTextStyle
1515
import androidx.compose.material3.MaterialTheme
16+
import androidx.compose.material3.Switch
1617
import androidx.compose.material3.Text
1718
import androidx.compose.runtime.Composable
1819
import androidx.compose.runtime.getValue
@@ -29,8 +30,10 @@ import androidx.compose.ui.unit.em
2930
import helium314.keyboard.compat.locale
3031
import helium314.keyboard.latin.dictionary.Dictionary
3132
import helium314.keyboard.latin.R
33+
import helium314.keyboard.latin.common.LocaleUtils
3234
import helium314.keyboard.latin.common.LocaleUtils.localizedDisplayName
3335
import helium314.keyboard.latin.utils.DictionaryInfoUtils
36+
import helium314.keyboard.latin.utils.prefs
3437
import helium314.keyboard.latin.utils.createDictionaryTextAnnotated
3538
import helium314.keyboard.settings.DeleteButton
3639
import helium314.keyboard.settings.ExpandButton
@@ -62,16 +65,51 @@ fun DictionaryDialog(
6265
content = {
6366
Column {
6467
if (hasInternal) {
68+
val internalDicts = DictionaryInfoUtils.getAssetsDictionaryList(ctx)
69+
val best = internalDicts?.let {
70+
LocaleUtils.getBestMatch(locale, it.toList()) { dict ->
71+
DictionaryInfoUtils.extractLocaleFromAssetsDictionaryFile(dict)
72+
}
73+
}
74+
val internalId = best?.let { "main:" + it.substringAfter("_").substringBefore(".") }
75+
6576
val color = if (mainDict == null) MaterialTheme.typography.titleSmall.color
6677
else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f) // for disabled look
6778
val bottomPadding = if (mainDict == null) 12.dp else 0.dp
68-
Text(stringResource(R.string.internal_dictionary_summary),
69-
modifier = Modifier
70-
.fillMaxWidth()
71-
.padding(bottom = bottomPadding),
72-
color = color,
73-
style = MaterialTheme.typography.titleSmall
74-
)
79+
80+
if (internalId != null) {
81+
val prefs = ctx.prefs()
82+
val prefKey = "pref_dict_enabled_$internalId"
83+
var enabled by remember { mutableStateOf(prefs.getBoolean(prefKey, true)) }
84+
Row(
85+
verticalAlignment = Alignment.CenterVertically,
86+
modifier = Modifier
87+
.fillMaxWidth()
88+
.padding(bottom = bottomPadding)
89+
) {
90+
Switch(
91+
checked = enabled && (mainDict == null),
92+
enabled = mainDict == null,
93+
onCheckedChange = { isChecked ->
94+
enabled = isChecked
95+
prefs.edit().putBoolean(prefKey, isChecked).apply()
96+
},
97+
modifier = Modifier.padding(end = 8.dp)
98+
)
99+
Text(stringResource(R.string.internal_dictionary_summary),
100+
color = color,
101+
style = MaterialTheme.typography.titleSmall
102+
)
103+
}
104+
} else {
105+
Text(stringResource(R.string.internal_dictionary_summary),
106+
modifier = Modifier
107+
.fillMaxWidth()
108+
.padding(bottom = bottomPadding),
109+
color = color,
110+
style = MaterialTheme.typography.titleSmall
111+
)
112+
}
75113
}
76114
if (mainDict != null)
77115
DictionaryDetails(mainDict)
@@ -113,11 +151,24 @@ private fun DictionaryDetails(dict: File) {
113151
var showDetails by remember { mutableStateOf(false) }
114152
val title = if (type != DictionaryInfoUtils.DEFAULT_MAIN_DICT) type
115153
else stringResource(R.string.main_dictionary)
154+
val ctx = LocalContext.current
155+
val prefs = ctx.prefs()
156+
val prefKey = "pref_dict_enabled_${header.mIdString}"
157+
var enabled by remember { mutableStateOf(prefs.getBoolean(prefKey, true)) }
158+
116159
Row(
117160
horizontalArrangement = Arrangement.SpaceBetween,
118161
verticalAlignment = Alignment.CenterVertically,
119162
modifier = Modifier.fillMaxWidth()
120163
) {
164+
Switch(
165+
checked = enabled,
166+
onCheckedChange = { isChecked ->
167+
enabled = isChecked
168+
prefs.edit().putBoolean(prefKey, isChecked).apply()
169+
},
170+
modifier = Modifier.padding(end = 8.dp)
171+
)
121172
Text(title, style = MaterialTheme.typography.titleSmall, modifier = Modifier.weight(1f))
122173
DeleteButton { showDeleteDialog = true }
123174
ExpandButton { showDetails = !showDetails }

0 commit comments

Comments
 (0)