Skip to content

Commit 40de17c

Browse files
committed
solve some todos in SubtypeDialog
1 parent 47070c1 commit 40de17c

File tree

4 files changed

+91
-48
lines changed

4 files changed

+91
-48
lines changed

Diff for: app/src/main/java/helium314/keyboard/latin/utils/LayoutUtils.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ object LayoutUtils {
1818
.apply { addAll(context.resources.getStringArray(R.array.predefined_layouts)) }
1919
if (locale.script() == ScriptUtils.SCRIPT_LATIN)
2020
return context.resources.getStringArray(R.array.predefined_layouts).toList()
21-
return SubtypeSettings.getSubtypesForLocale(locale).mapNotNullTo(HashSet()) { it.mainLayoutName() }
21+
return SubtypeSettings.getResourceSubtypesForLocale(locale).mapNotNullTo(HashSet()) { it.mainLayoutName() }
2222
}
2323

2424
fun getLMainLayoutsForLocales(locales: List<Locale>, context: Context): Collection<String> =

Diff for: app/src/main/java/helium314/keyboard/latin/utils/SubtypeLocaleUtils.java

+15-2
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,21 @@ private static String getReplacementString(@NonNull final InputMethodSubtype sub
224224
}
225225

226226
@NonNull
227-
public static String getSubtypeDisplayNameInSystemLocale(
228-
@NonNull final InputMethodSubtype subtype) {
227+
public static String getDisplayNameInSystemLocale(@NonNull final String mainLayoutName, @NonNull final Locale locale) {
228+
final String displayName = getMainLayoutDisplayName(mainLayoutName);
229+
if (displayName != null) // works for custom and latin layouts
230+
return displayName;
231+
// we have some locale-specific layout
232+
for (InputMethodSubtype subtype : SubtypeSettings.INSTANCE.getResourceSubtypesForLocale(locale)) {
233+
final String main = LayoutType.Companion.getMainLayoutFromExtraValue(subtype.getExtraValue());
234+
if (mainLayoutName.equals(main))
235+
return getSubtypeDisplayNameInSystemLocale(subtype);
236+
}
237+
return mainLayoutName; // should never happen...
238+
}
239+
240+
@NonNull
241+
public static String getSubtypeDisplayNameInSystemLocale(@NonNull final InputMethodSubtype subtype) {
229242
final Locale displayLocale = ConfigurationCompatKt.locale(sResources.getConfiguration());
230243
return getSubtypeDisplayNameInternal(subtype, displayLocale);
231244
}

Diff for: app/src/main/java/helium314/keyboard/latin/utils/SubtypeSettings.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ object SubtypeSettings {
137137
return !resourceSubtypesByLocale[locale].isNullOrEmpty()
138138
}
139139

140-
fun getSubtypesForLocale(locale: Locale): List<InputMethodSubtype> = resourceSubtypesByLocale[locale].orEmpty()
140+
fun getResourceSubtypesForLocale(locale: Locale): List<InputMethodSubtype> = resourceSubtypesByLocale[locale].orEmpty()
141141

142142
fun getAvailableSubtypeLocales(): Collection<Locale> {
143143
require(initialized)

Diff for: app/src/main/java/helium314/keyboard/settings/dialogs/SubtypeDialog.kt

+74-44
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package helium314.keyboard.settings.dialogs
33
import android.content.Context
44
import android.view.inputmethod.InputMethodSubtype
55
import androidx.compose.foundation.clickable
6+
import androidx.compose.foundation.layout.Arrangement
67
import androidx.compose.foundation.layout.Box
78
import androidx.compose.foundation.layout.Column
89
import androidx.compose.foundation.layout.Row
@@ -12,6 +13,7 @@ import androidx.compose.foundation.rememberScrollState
1213
import androidx.compose.foundation.verticalScroll
1314
import androidx.compose.material3.DropdownMenu
1415
import androidx.compose.material3.DropdownMenuItem
16+
import androidx.compose.material3.HorizontalDivider
1517
import androidx.compose.material3.Icon
1618
import androidx.compose.material3.IconButton
1719
import androidx.compose.material3.MaterialTheme
@@ -58,20 +60,16 @@ import helium314.keyboard.latin.utils.SubtypeSettings
5860
import helium314.keyboard.latin.utils.SubtypeUtilsAdditional
5961
import helium314.keyboard.latin.utils.getDictionaryLocales
6062
import helium314.keyboard.latin.utils.getStringResourceOrName
63+
import helium314.keyboard.latin.utils.locale
6164
import helium314.keyboard.latin.utils.prefs
6265
import helium314.keyboard.settings.screens.GetIcon
6366
import java.util.Locale
6467

6568
// todo:
6669
// save when "editing" a resource subtypes is not working
67-
// default buttons missing
68-
// string resources
69-
// dialog doesn't look good...
7070
// settings upgrade to move the override settings to extra values, and actually use them (via getSelectedSubtype, not RichIMM)
7171
@Composable
7272
fun SubtypeDialog(
73-
// could also use InputMethodSubtype if there is any advantage
74-
// but as soon as anything is changed we will need an additional subtype anyway...
7573
onDismissRequest: () -> Unit,
7674
subtype: InputMethodSubtype,
7775
onConfirmed: (SettingsSubtype) -> Unit,
@@ -99,8 +97,9 @@ fun SubtypeDialog(
9997
text = {
10098
Column(
10199
modifier = Modifier.verticalScroll(scrollState),
100+
verticalArrangement = Arrangement.spacedBy(8.dp),
102101
) {
103-
WithSmallTitle("main layout") {
102+
WithSmallTitle(stringResource(R.string.keyboard_layout_set)) {
104103
val appLayouts = LayoutUtils.getAvailableLayouts(LayoutType.MAIN, ctx, currentSubtype.locale)
105104
val customLayouts = LayoutUtilsCustom.getLayoutFiles(LayoutType.MAIN, ctx, currentSubtype.locale).map { it.name }
106105
DropDownField(
@@ -110,18 +109,17 @@ fun SubtypeDialog(
110109
currentSubtype = currentSubtype.withLayout(LayoutType.MAIN, it)
111110
}
112111
) {
113-
// todo: displayName can be complicated and may require an inputmethodsubtype...
114-
// maybe search for stuff in resource subtypes?
115-
Text(it)
112+
Text(SubtypeLocaleUtils.getDisplayNameInSystemLocale(it, currentSubtype.locale))
116113
// todo: edit button? or only for selected layout? and delete button?
114+
// yes, even just to make clear what is custom
117115
}
118116
}
119117
WithSmallTitle(stringResource(R.string.secondary_locale)) {
120118
TextButton(onClick = { showSecondaryLocaleDialog = true }) {
121119
val text = currentSubtype.getExtraValueOf(ExtraValue.SECONDARY_LOCALES)
122120
?.split(Separators.KV)?.joinToString(", ") {
123121
LocaleUtils.getLocaleDisplayNameInSystemLocale(it.constructLocale(), ctx)
124-
} ?: "none"
122+
} ?: stringResource(R.string.action_none)
125123
Text(text, Modifier.fillMaxWidth(), style = MaterialTheme.typography.bodyLarge)
126124
}
127125
}
@@ -131,32 +129,56 @@ fun SubtypeDialog(
131129
Text("not yet implemented")
132130
}
133131
// todo: this looks strange without the title
134-
TextButton(onClick = { showKeyOrderDialog = true })
135-
{ Text(stringResource(R.string.popup_order), Modifier.fillMaxWidth(), style = MaterialTheme.typography.bodyLarge) }
136-
TextButton(onClick = { showHintOrderDialog = true })
137-
{ Text(stringResource(R.string.hint_source), Modifier.fillMaxWidth(), style = MaterialTheme.typography.bodyLarge) }
138-
if (currentSubtype.locale.script() == SCRIPT_LATIN)
132+
Row {
133+
TextButton(onClick = { showKeyOrderDialog = true }, Modifier.weight(1f))
134+
{ Text(stringResource(R.string.popup_order), style = MaterialTheme.typography.bodyLarge) }
135+
DefaultButton(
136+
{ currentSubtype = currentSubtype.without(ExtraValue.POPUP_ORDER) },
137+
currentSubtype.getExtraValueOf(ExtraValue.POPUP_ORDER) == null
138+
)
139+
}
140+
Row {
141+
TextButton(onClick = { showHintOrderDialog = true }, Modifier.weight(1f))
142+
{ Text(stringResource(R.string.hint_source), style = MaterialTheme.typography.bodyLarge) }
143+
DefaultButton(
144+
{ currentSubtype = currentSubtype.without(ExtraValue.HINT_ORDER) },
145+
currentSubtype.getExtraValueOf(ExtraValue.HINT_ORDER) == null
146+
)
147+
}
148+
if (currentSubtype.locale.script() == SCRIPT_LATIN) {
139149
WithSmallTitle(stringResource(R.string.show_popup_keys_title)) {
140150
val explicitValue = currentSubtype.getExtraValueOf(ExtraValue.MORE_POPUPS)
141151
val value = explicitValue ?: prefs.getString(Settings.PREF_MORE_POPUP_KEYS, Defaults.PREF_MORE_POPUP_KEYS)!!
142-
TextButton(onClick = { showMorePopupsDialog = true }, Modifier.fillMaxWidth())
152+
Row {
153+
TextButton(onClick = { showMorePopupsDialog = true }, Modifier.weight(1f))
143154
{ Text(stringResource(morePopupKeysResId(value))) }
155+
DefaultButton(
156+
{ currentSubtype = currentSubtype.without(ExtraValue.MORE_POPUPS) },
157+
explicitValue == null
158+
)
159+
}
144160
}
145-
if (hasLocalizedNumberRow(currentSubtype.locale, ctx))
161+
}
162+
if (hasLocalizedNumberRow(currentSubtype.locale, ctx)) {
146163
Row {
164+
val checked = currentSubtype.getExtraValueOf(ExtraValue.LOCALIZED_NUMBER_ROW)?.toBoolean()
147165
Text(stringResource(R.string.localized_number_row), Modifier.weight(1f))
148166
Switch(
149-
checked = currentSubtype.getExtraValueOf(ExtraValue.LOCALIZED_NUMBER_ROW)?.toBoolean()
150-
?: prefs.getBoolean(Settings.PREF_LOCALIZED_NUMBER_ROW, Defaults.PREF_LOCALIZED_NUMBER_ROW),
167+
checked = checked ?: prefs.getBoolean(Settings.PREF_LOCALIZED_NUMBER_ROW, Defaults.PREF_LOCALIZED_NUMBER_ROW),
151168
onCheckedChange = {
152169
currentSubtype = currentSubtype.with(ExtraValue.LOCALIZED_NUMBER_ROW, it.toString())
153170
}
154171
)
155-
// todo: default button?
172+
DefaultButton(
173+
{ currentSubtype = currentSubtype.without(ExtraValue.LOCALIZED_NUMBER_ROW) },
174+
checked == null
175+
)
156176
}
177+
}
178+
HorizontalDivider()
179+
Text(stringResource(R.string.settings_screen_secondary_layouts), style = MaterialTheme.typography.titleMedium)
157180
LayoutType.entries.forEach { type ->
158181
if (type == LayoutType.MAIN) return@forEach
159-
// todo: also some default button, to be shown when necessary, uses currentSubtype.withoutLayout(type)
160182
WithSmallTitle(stringResource(type.displayNameId)) {
161183
val explicitLayout = currentSubtype.layoutName(type)
162184
val layout = explicitLayout ?: Settings.readDefaultLayoutName(type, prefs)
@@ -167,10 +189,12 @@ fun SubtypeDialog(
167189
selectedItem = layout,
168190
onSelected = {
169191
currentSubtype = currentSubtype.withLayout(type, it)
170-
}
192+
},
193+
onDefault = { currentSubtype = currentSubtype.withoutLayout(type) },
194+
isDefault = explicitLayout == null
171195
) {
172196
val displayName = if (LayoutUtilsCustom.isCustomLayout(it)) LayoutUtilsCustom.getDisplayName(it)
173-
else it.getStringResourceOrName("layout_", ctx)
197+
else it.getStringResourceOrName("layout_", ctx)
174198
Text(displayName)
175199
// content is name, and if it's user layout there is an edit button
176200
// also maybe there should be an "add" button similar to the old settings
@@ -183,8 +207,8 @@ fun SubtypeDialog(
183207
if (showSecondaryLocaleDialog)
184208
MultiListPickerDialog(
185209
onDismissRequest = { showSecondaryLocaleDialog = false },
186-
onConfirmed = {
187-
val newValue = it.joinToString(Separators.KV) { it.toLanguageTag() }
210+
onConfirmed = { locales ->
211+
val newValue = locales.joinToString(Separators.KV) { it.toLanguageTag() }
188212
currentSubtype = if (newValue.isEmpty()) currentSubtype.without(ExtraValue.SECONDARY_LOCALES)
189213
else currentSubtype.with(ExtraValue.SECONDARY_LOCALES, newValue)
190214
},
@@ -201,8 +225,8 @@ fun SubtypeDialog(
201225
title = stringResource(R.string.popup_order),
202226
showDefault = setting != null,
203227
onConfirmed = {
204-
if (it == null) currentSubtype = currentSubtype.without(ExtraValue.POPUP_ORDER)
205-
else currentSubtype = currentSubtype.with(ExtraValue.POPUP_ORDER, it)
228+
currentSubtype = if (it == null) currentSubtype.without(ExtraValue.POPUP_ORDER)
229+
else currentSubtype.with(ExtraValue.POPUP_ORDER, it)
206230
}
207231
)
208232
}
@@ -214,13 +238,12 @@ fun SubtypeDialog(
214238
title = stringResource(R.string.hint_source),
215239
showDefault = setting != null,
216240
onConfirmed = {
217-
if (it == null) currentSubtype = currentSubtype.without(ExtraValue.HINT_ORDER)
218-
else currentSubtype = currentSubtype.with(ExtraValue.HINT_ORDER, it)
241+
currentSubtype = if (it == null) currentSubtype.without(ExtraValue.HINT_ORDER)
242+
else currentSubtype.with(ExtraValue.HINT_ORDER, it)
219243
}
220244
)
221245
}
222246
if (showMorePopupsDialog) {
223-
// todo: default button in here? or next to the pref?
224247
val items = listOf(POPUP_KEYS_NORMAL, POPUP_KEYS_MAIN, POPUP_KEYS_MORE, POPUP_KEYS_ALL)
225248
val explicitValue = currentSubtype.getExtraValueOf(ExtraValue.MORE_POPUPS)
226249
val value = explicitValue ?: prefs.getString(Settings.PREF_MORE_POPUP_KEYS, Defaults.PREF_MORE_POPUP_KEYS)
@@ -262,7 +285,7 @@ private fun PopupOrderDialog(
262285
var checked by rememberSaveable { mutableStateOf(item.state) }
263286
Row(verticalAlignment = Alignment.CenterVertically) {
264287
KeyboardIconsSet.instance.GetIcon(item.name)
265-
val text = item.name.lowercase().getStringResourceOrName("", ctx)
288+
val text = item.name.lowercase().getStringResourceOrName("popup_keys_", ctx)
266289
Text(text, Modifier.weight(1f))
267290
Switch(
268291
checked = checked,
@@ -290,6 +313,8 @@ private fun <T>DropDownField(
290313
items: List<T>,
291314
selectedItem: T,
292315
onSelected: (T) -> Unit,
316+
isDefault: Boolean? = null,
317+
onDefault: () -> Unit = {},
293318
itemContent: @Composable (T) -> Unit,
294319
) {
295320
var expanded by remember { mutableStateOf(false) }
@@ -299,7 +324,7 @@ private fun <T>DropDownField(
299324
) {
300325
Row(
301326
verticalAlignment = Alignment.CenterVertically,
302-
modifier = Modifier.padding(start = 8.dp, end = 8.dp, bottom = 4.dp)
327+
modifier = Modifier.padding(start = 8.dp, bottom = 4.dp)
303328
) {
304329
Box(Modifier.weight(1f)) {
305330
itemContent(selectedItem)
@@ -310,10 +335,12 @@ private fun <T>DropDownField(
310335
) {
311336
Icon(
312337
painterResource(R.drawable.ic_arrow_left),
313-
null,
338+
"show dropdown",
314339
Modifier.rotate(-90f)
315340
)
316341
}
342+
if (isDefault != null)
343+
DefaultButton(onDefault, isDefault)
317344
}
318345
}
319346
DropdownMenu(
@@ -329,16 +356,19 @@ private fun <T>DropDownField(
329356
}
330357
}
331358

332-
// get locales with same script as main locale, but different language
333-
// todo: do we need any sort of force-ascii like in old variant?
334-
// now we use hi-Latn and sr-Latn for the relevant subtypes, so it should be fine
335-
// only potential issue is the Latn-default if we don't have the script for a locale,
336-
// but in that case we should rather add the script to ScriptUtils
337-
private fun getAvailableSecondaryLocales(context: Context, mainLocale: Locale): List<Locale> {
338-
val locales = getDictionaryLocales(context)
339-
locales.removeAll {
340-
// it.language == mainLocale.language || it.script() != mainLocale.script()
341-
it == mainLocale || it.script() != mainLocale.script() // todo: check whether this is fine, otherwise go back to the variant above
359+
@Composable
360+
private fun DefaultButton(
361+
onDefault: () -> Unit,
362+
isDefault: Boolean
363+
) {
364+
IconButton(
365+
onClick = onDefault,
366+
enabled = !isDefault
367+
) {
368+
Icon(painterResource(R.drawable.sym_keyboard_settings_holo), "default") // todo: more understandable icon!
342369
}
343-
return locales.toList()
370+
344371
}
372+
373+
private fun getAvailableSecondaryLocales(context: Context, mainLocale: Locale): List<Locale> =
374+
getDictionaryLocales(context).filter { it != mainLocale && it.script() == mainLocale.script() }

0 commit comments

Comments
 (0)