some todos

This commit is contained in:
Helium314 2025-02-06 22:45:37 +01:00
parent 5f87dbc9cc
commit 00304855f2
18 changed files with 216 additions and 318 deletions

View file

@ -27,11 +27,11 @@ class AllPrefs(context: Context) {
fun filter(searchTerm: String): List<PrefDef> {
val term = searchTerm.lowercase()
val results = mutableSetOf<PrefDef>()
list.forEach { if (it.title.lowercase().startsWith(term)) results.add(it) }
list.forEach { if (it.title.lowercase().split(' ').any { it.startsWith(term) }) results.add(it) }
list.forEach {
if (it.description?.lowercase()?.split(' ')?.any { it.startsWith(term) } == true)
results.add(it)
list.forEach { def -> if (def.title.lowercase().startsWith(term)) results.add(def) }
list.forEach { def -> if (def.title.lowercase().split(' ').any { it.startsWith(term) }) results.add(def) }
list.forEach { def ->
if (def.description?.lowercase()?.split(' ')?.any { it.startsWith(term) } == true)
results.add(def)
}
return results.toList()
}

View file

@ -6,7 +6,6 @@ import androidx.annotation.DrawableRes
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxWidth
@ -48,6 +47,7 @@ import helium314.keyboard.settings.dialogs.ListPickerDialog
import helium314.keyboard.settings.dialogs.ReorderDialog
import helium314.keyboard.settings.dialogs.SliderDialog
import helium314.keyboard.settings.screens.GetIcon
import kotlin.math.roundToInt
// partially taken from StreetComplete / SCEE
@ -187,6 +187,7 @@ fun <T: Number> SliderPreference(
description: @Composable (T) -> String,
default: T,
range: ClosedFloatingPointRange<Float>,
stepSize: Int? = null,
onValueChanged: (Float) -> Unit = { },
) {
val ctx = LocalContext.current
@ -203,7 +204,7 @@ fun <T: Number> SliderPreference(
name = name,
onClick = { showDialog = true },
modifier = modifier,
description = description(initialValue as T)
description = description(initialValue)
)
if (showDialog)
SliderDialog(
@ -215,11 +216,16 @@ fun <T: Number> SliderPreference(
initialValue = initialValue.toFloat(),
range = range,
positionString = {
description((if (default is Int) it.toInt() else it) as T)
@Suppress("UNCHECKED_CAST")
description((if (default is Int) it.roundToInt() else it) as T)
},
onValueChanged = onValueChanged,
showDefault = true,
onDefault = { prefs.edit().remove(pref).apply() }
onDefault = { prefs.edit().remove(pref).apply() },
intermediateSteps = stepSize?.let {
// this is not nice, but slider wants it like this...
((range.endInclusive - range.start) / it - 1).toInt()
}
)
}
@ -299,6 +305,7 @@ fun ReorderSwitchPreference(def: PrefDef, default: String) {
private class KeyAndState(var name: String, var state: Boolean)
@Suppress("UNCHECKED_CAST")
private fun <T: Any> getPrefOfType(prefs: SharedPreferences, key: String, default: T): T =
when (default) {
is String -> prefs.getString(key, default)

View file

@ -14,28 +14,27 @@ import helium314.keyboard.latin.utils.prefs
import kotlinx.coroutines.flow.MutableStateFlow
// todo (roughly in order)
// work on todos in other files
// maybe move some large prefs out of their screens into separate files (backup/restore!)
// use better / more structured and clear names and arrangement of files
// the prefDef and AllPrefs, also be clear about pref <-> key <-> prefKey (all used, probably should be latter)
// there is a lot more ambiguous naming...
// dialogs should be rememberSaveable to survive display orientation change and stuff?
// check dark and light theme (don't have dynamic)
// any way to get rid of the "old" background on starting settings? probably comes from app theme, can we avoid it?
// rename both settingsActivities
// calling KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext()) while keyboard is showing shows just full screen background
// but reload while keyboard is showing would be great (isn't it at least semi-done when changing one-handed mode?)
// use better / more structured and clear names and arrangement of files
// the prefDef and AllPrefs, also be clear about pref <-> key <-> prefKey (all used, probably should be latter)
// there is a lot more ambiguous naming...
// animations when stuff (dis)appears
// LaunchedEffect, AnimatedVisibility
// bg image inconsistent about being on toolbar or not (is this new?)
// maybe move some large prefs out of their screens into separate files (backup/restore!)
// performance
// find a nice way of testing (probably add logs for measuring time and recompositions)
// consider that stuff in composables can get called quite often on any changes
// -> use remember for things that are slow, but be careful they don't change from outside the composable
// dialogs should be rememberSaveable to survive display orientation change and stuff?
// try making old fragment back stuff work better, and try the different themes (with and without top bar, it should only appear for old fragments)
// PRs adding prefs -> need to do before continuing
// 1263 (no response for several weeks now...)
// merge main to implement all the new settings
// really use the restart dialog for debug settings stuff?
// could do it the old way, and hide debug settings from search
// what should be done, but not in this PR
// in general: changes to anything outside the new settings (unless necessary), and changes to how screens / fragments work

View file

@ -25,7 +25,7 @@ fun Theme(dark: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit
if (dark) dynamicDarkColorScheme(LocalContext.current)
else dynamicLightColorScheme(LocalContext.current)
} else {
// todo: more colors
// todo (later): more colors
if (dark) darkColorScheme(
primary = colorResource(R.color.accent),
)

View file

@ -95,7 +95,7 @@ fun CustomizeIconsDialog(
val iconsForName = allIcons[iconName].orEmpty()
val iconsSet = mutableSetOf<Int>()
iconsSet.addAll(iconsForName)
KeyboardIconsSet.getAllIcons(ctx).forEach { iconsSet.addAll(it.value) } // todo: is this called again on UI interaction?
KeyboardIconsSet.getAllIcons(ctx).forEach { iconsSet.addAll(it.value) }
val icons = iconsSet.toList()
var selectedIcon by remember { mutableStateOf(KeyboardIconsSet.instance.iconIds[iconName]) }
ThreeButtonAlertDialog(

View file

@ -1,58 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-only
package helium314.keyboard.settings.dialogs
import android.widget.Toast
import androidx.compose.foundation.layout.imePadding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.window.DialogProperties
import helium314.keyboard.latin.R
import helium314.keyboard.latin.utils.Log
import helium314.keyboard.latin.utils.checkLayout
import helium314.keyboard.latin.utils.getCustomLayoutFile
import helium314.keyboard.latin.utils.getLayoutDisplayName
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@Composable
fun CustomizeLayoutDialog(
layoutName: String,
onDismissRequest: () -> Unit,
startContent: String? = null,
displayName: String? = null,
) {
val ctx = LocalContext.current
val file = getCustomLayoutFile(layoutName, ctx)
val scope = rememberCoroutineScope()
var job: Job? = null
TextInputDialog(
onDismissRequest = onDismissRequest,
onConfirmed = { },
initialText = startContent ?: file.readText(),
title = { Text(displayName ?: getLayoutDisplayName(layoutName)) },
checkTextValid = {
val valid = checkLayout(it, ctx)
job?.cancel()
if (!valid) {
job = scope.launch {
delay(3000)
val message = Log.getLog(10)
.lastOrNull { it.tag == "CustomLayoutUtils" }?.message
?.split("\n")?.take(2)?.joinToString("\n")
Toast.makeText(ctx, ctx.getString(R.string.layout_error, message), Toast.LENGTH_LONG).show()
}
}
valid
},
singleLine = false,
modifier = Modifier.imePadding(),
// decorFitsSystemWindows = false is necessary so the dialog is not covered by keyboard
// but this also stops the background from being darkened... great idea to combine both
properties = DialogProperties(decorFitsSystemWindows = false)
)
}

View file

@ -1,22 +1,30 @@
// SPDX-License-Identifier: GPL-3.0-only
package helium314.keyboard.settings.dialogs
import android.widget.Toast
import androidx.compose.foundation.layout.imePadding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.window.DialogProperties
import helium314.keyboard.latin.R
import helium314.keyboard.latin.utils.Log
import helium314.keyboard.latin.utils.checkLayout
import helium314.keyboard.latin.utils.getCustomLayoutFile
import helium314.keyboard.latin.utils.getLayoutDisplayName
import helium314.keyboard.latin.utils.onCustomLayoutFileListChanged
import helium314.keyboard.settings.keyboardNeedsReload
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
// todo: height MUST respect keyboard, or it's impossible to fill the bottom part
@Composable
fun LayoutEditDialog(
onDismissRequest: () -> Unit,
@ -26,9 +34,9 @@ fun LayoutEditDialog(
) {
val ctx = LocalContext.current
val file = getCustomLayoutFile(layoutName, ctx)
val initialText = startContent ?: file.readText()
val scope = rememberCoroutineScope()
var job: Job? = null
var showDeleteConfirmation by remember { mutableStateOf(false) }
// todo: try make it really full width, at least if we have a json file
TextInputDialog(
onDismissRequest = onDismissRequest,
onConfirmed = {
@ -45,12 +53,27 @@ fun LayoutEditDialog(
onCustomLayoutFileListChanged()
keyboardNeedsReload = true
},
initialText = initialText,
initialText = startContent ?: file.readText(),
singleLine = false,
title = { Text(displayName ?: getLayoutDisplayName(layoutName)) },
checkTextValid = {
checkLayout(it, ctx) // todo: toast with reason why it doesn't work -> should re-do getting the reason
val valid = checkLayout(it, ctx)
job?.cancel()
if (!valid) {
job = scope.launch {
delay(3000)
val message = Log.getLog(10)
.lastOrNull { it.tag == "CustomLayoutUtils" }?.message
?.split("\n")?.take(2)?.joinToString("\n")
Toast.makeText(ctx, ctx.getString(R.string.layout_error, message), Toast.LENGTH_LONG).show()
}
}
valid
},
modifier = Modifier.imePadding(),
// decorFitsSystemWindows = false is necessary so the dialog is not covered by keyboard
// but this also stops the background from being darkened... great idea to combine both
properties = DialogProperties(decorFitsSystemWindows = false)
)
if (showDeleteConfirmation)
ConfirmationDialog(

View file

@ -93,7 +93,6 @@ fun ToolbarKeysCustomizer(
)
}
// todo: show updated ToolbarKeysCustomizer after ok / default? because default button
@Composable
private fun ToolbarKeyCustomizer(
key: ToolbarKey,

View file

@ -64,7 +64,7 @@ fun createAboutPrefs(context: Context) = listOf(
name = it.title,
description = it.description,
onClick = { },
icon = R.drawable.ic_launcher_foreground // todo: maybe use the bitmap trick here?
icon = R.drawable.ic_launcher_foreground // use the bitmap trick here if we really want the colored icon
)
},
PrefDef(context, NonSettingsPrefs.VERSION, R.string.version) {
@ -137,7 +137,7 @@ fun createAboutPrefs(context: Context) = listOf(
icon = R.drawable.ic_settings_about_github_foreground
)
},
PrefDef(context, NonSettingsPrefs.SAVE_LOG, R.string.save_log) {
PrefDef(context, NonSettingsPrefs.SAVE_LOG, R.string.save_log) { def ->
val ctx = LocalContext.current
val scope = rememberCoroutineScope()
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
@ -150,8 +150,8 @@ fun createAboutPrefs(context: Context) = listOf(
}
}
Preference(
name = it.title,
description = it.description,
name = def.title,
description = def.description,
onClick = {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
.addCategory(Intent.CATEGORY_OPENABLE)

View file

@ -68,7 +68,6 @@ import helium314.keyboard.settings.ListPreference
import helium314.keyboard.settings.NonSettingsPrefs
import helium314.keyboard.settings.PrefDef
import helium314.keyboard.settings.Preference
import helium314.keyboard.settings.PreferenceCategory
import helium314.keyboard.settings.SearchPrefScreen
import helium314.keyboard.settings.SettingsActivity2
import helium314.keyboard.settings.SettingsDestination
@ -76,8 +75,8 @@ import helium314.keyboard.settings.SliderPreference
import helium314.keyboard.settings.SwitchPreference
import helium314.keyboard.settings.Theme
import helium314.keyboard.settings.dialogs.ConfirmationDialog
import helium314.keyboard.settings.dialogs.CustomizeLayoutDialog
import helium314.keyboard.settings.dialogs.InfoDialog
import helium314.keyboard.settings.dialogs.LayoutEditDialog
import helium314.keyboard.settings.dialogs.ListPickerDialog
import helium314.keyboard.settings.dialogs.TextInputDialog
import helium314.keyboard.settings.keyboardNeedsReload
@ -130,16 +129,15 @@ fun AdvancedSettingsScreen(
@SuppressLint("ApplySharedPref")
fun createAdvancedPrefs(context: Context) = listOf(
PrefDef(context, Settings.PREF_ALWAYS_INCOGNITO_MODE, R.string.incognito, R.string.prefs_force_incognito_mode_summary) {
SwitchPreference(
def = it,
default = false
)
PrefDef(context, Settings.PREF_ALWAYS_INCOGNITO_MODE,
R.string.incognito, R.string.prefs_force_incognito_mode_summary)
{
SwitchPreference(it, false)
},
PrefDef(context, Settings.PREF_KEY_LONGPRESS_TIMEOUT, R.string.prefs_key_longpress_timeout_settings) {
PrefDef(context, Settings.PREF_KEY_LONGPRESS_TIMEOUT, R.string.prefs_key_longpress_timeout_settings) { def ->
SliderPreference(
name = it.title,
pref = it.key,
name = def.title,
pref = def.key,
default = 300,
range = 100f..700f,
description = { stringResource(R.string.abbreviation_unit_milliseconds, it.toString()) }
@ -164,53 +162,36 @@ fun createAdvancedPrefs(context: Context) = listOf(
ListPreference(def, items, "none")
},
PrefDef(context, Settings.PREF_DELETE_SWIPE, R.string.delete_swipe, R.string.delete_swipe_summary) {
SwitchPreference(
def = it,
default = true
)
SwitchPreference(it, true)
},
PrefDef(context, Settings.PREF_SPACE_TO_CHANGE_LANG, R.string.prefs_long_press_keyboard_to_change_lang, R.string.prefs_long_press_keyboard_to_change_lang_summary) {
SwitchPreference(
def = it,
default = true
)
PrefDef(context, Settings.PREF_SPACE_TO_CHANGE_LANG,
R.string.prefs_long_press_keyboard_to_change_lang,
R.string.prefs_long_press_keyboard_to_change_lang_summary)
{
SwitchPreference(it, true)
},
PrefDef(context, Settings.PREFS_LONG_PRESS_SYMBOLS_FOR_NUMPAD, R.string.prefs_long_press_symbol_for_numpad) {
SwitchPreference(
def = it,
default = false
)
SwitchPreference(it, false)
},
PrefDef(context, Settings.PREF_ENABLE_EMOJI_ALT_PHYSICAL_KEY, R.string.prefs_enable_emoji_alt_physical_key, R.string.prefs_enable_emoji_alt_physical_key_summary) {
SwitchPreference(
def = it,
default = true
)
PrefDef(context, Settings.PREF_ENABLE_EMOJI_ALT_PHYSICAL_KEY, R.string.prefs_enable_emoji_alt_physical_key,
R.string.prefs_enable_emoji_alt_physical_key_summary)
{
SwitchPreference(it, true)
},
PrefDef(context, Settings.PREF_SHOW_SETUP_WIZARD_ICON, R.string.prefs_enable_emoji_alt_physical_key_summary) {
val ctx = LocalContext.current
SwitchPreference(
def = it,
default = true
) { SystemBroadcastReceiver.toggleAppIcon(ctx) }
SwitchPreference(it, true) { SystemBroadcastReceiver.toggleAppIcon(ctx) }
},
PrefDef(context, Settings.PREF_ABC_AFTER_SYMBOL_SPACE, R.string.switch_keyboard_after, R.string.after_symbol_and_space) {
SwitchPreference(
def = it,
default = true
)
PrefDef(context, Settings.PREF_ABC_AFTER_SYMBOL_SPACE,
R.string.switch_keyboard_after, R.string.after_symbol_and_space)
{
SwitchPreference(it, true)
},
PrefDef(context, Settings.PREF_ABC_AFTER_EMOJI, R.string.switch_keyboard_after, R.string.after_emoji) {
SwitchPreference(
def = it,
default = false
)
SwitchPreference(it, false)
},
PrefDef(context, Settings.PREF_ABC_AFTER_CLIP, R.string.switch_keyboard_after, R.string.after_clip) {
SwitchPreference(
def = it,
default = false
)
SwitchPreference(it, false)
},
PrefDef(context, Settings.PREF_CUSTOM_CURRENCY_KEY, R.string.customize_currencies) { def ->
var showDialog by remember { mutableStateOf(false) }
@ -228,7 +209,7 @@ fun createAdvancedPrefs(context: Context) = listOf(
title = { Text(stringResource(R.string.customize_currencies)) },
neutralButtonText = if (prefs.contains(def.key)) stringResource(R.string.button_default) else null,
onNeutral = { prefs.edit().remove(def.key).apply(); KeyboardLayoutSet.onSystemLocaleChanged() },
checkTextValid = { it.splitOnWhitespace().none { it.length > 8 } }
checkTextValid = { text -> text.splitOnWhitespace().none { it.length > 8 } }
)
}
},
@ -267,7 +248,7 @@ fun createAdvancedPrefs(context: Context) = listOf(
ctx.assets.list("layouts")?.firstOrNull { it.startsWith("$layout.") }
?.let { ctx.assets.open("layouts" + File.separator + it).reader().readText() }
}
CustomizeLayoutDialog(
LayoutEditDialog(
layoutName = customLayoutName ?: "$CUSTOM_LAYOUT_PREFIX$layout.",
startContent = originalLayout,
displayName = layout?.getStringResourceOrName("layout_", ctx),
@ -303,7 +284,7 @@ fun createAdvancedPrefs(context: Context) = listOf(
val defaultLayoutName = if (Settings.getInstance().isTablet) "functional_keys_tablet.json" else "functional_keys.json"
ctx.assets.open("layouts" + File.separator + defaultLayoutName).reader().readText()
}
CustomizeLayoutDialog(
LayoutEditDialog(
layoutName = customLayoutName ?: "$CUSTOM_LAYOUT_PREFIX$layout.",
startContent = originalLayout,
displayName = layout?.substringAfter(CUSTOM_LAYOUT_PREFIX)?.getStringResourceOrName("layout_", ctx),
@ -324,9 +305,9 @@ fun createAdvancedPrefs(context: Context) = listOf(
"custom_background_image.*".toRegex(),
"custom_font".toRegex(),
) }
val backupLauncher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode != Activity.RESULT_OK) return@rememberLauncherForActivityResult
val uri = it.data?.data ?: return@rememberLauncherForActivityResult
val backupLauncher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode != Activity.RESULT_OK) return@rememberLauncherForActivityResult
val uri = result.data?.data ?: return@rememberLauncherForActivityResult
// zip all files matching the backup patterns
// essentially this is the typed words information, and user-added dictionaries
val filesDir = ctx.filesDir ?: return@rememberLauncherForActivityResult
@ -382,9 +363,9 @@ fun createAdvancedPrefs(context: Context) = listOf(
}
wait.await()
}
val restoreLauncher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode != Activity.RESULT_OK) return@rememberLauncherForActivityResult
val uri = it.data?.data ?: return@rememberLauncherForActivityResult
val restoreLauncher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode != Activity.RESULT_OK) return@rememberLauncherForActivityResult
val uri = result.data?.data ?: return@rememberLauncherForActivityResult
val wait = CountDownLatch(1)
ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute {
try {
@ -490,10 +471,10 @@ fun createAdvancedPrefs(context: Context) = listOf(
)
}
},
PrefDef(context, Settings.PREF_EMOJI_MAX_SDK, R.string.prefs_key_emoji_max_sdk) {
PrefDef(context, Settings.PREF_EMOJI_MAX_SDK, R.string.prefs_key_emoji_max_sdk) { def ->
SliderPreference(
name = it.title,
pref = it.key,
name = def.title,
pref = def.key,
default = Build.VERSION.SDK_INT,
range = 21f..35f,
description = {
@ -520,18 +501,15 @@ fun createAdvancedPrefs(context: Context) = listOf(
)
},
PrefDef(context, Settings.PREF_URL_DETECTION, R.string.url_detection_title, R.string.url_detection_summary) {
SwitchPreference(
def = it,
default = false
)
SwitchPreference(it, false)
},
PrefDef(context, NonSettingsPrefs.LOAD_GESTURE_LIB, R.string.load_gesture_library, R.string.load_gesture_library_summary) {
PrefDef(context, NonSettingsPrefs.LOAD_GESTURE_LIB, R.string.load_gesture_library, R.string.load_gesture_library_summary) { def ->
var showDialog by remember { mutableStateOf(false) }
val ctx = LocalContext.current
val prefs = ctx.prefs()
val abi = Build.SUPPORTED_ABIS[0]
val libFile = File(ctx.filesDir.absolutePath + File.separator + JniUtils.JNI_LIB_IMPORT_FILE_NAME)
fun renameToLibfileAndRestart(file: File, checksum: String) {
fun renameToLibFileAndRestart(file: File, checksum: String) {
libFile.delete()
// store checksum in default preferences (soo JniUtils)
prefs.edit().putString(Settings.PREF_LIBRARY_CHECKSUM, checksum).commit()
@ -539,9 +517,9 @@ fun createAdvancedPrefs(context: Context) = listOf(
Runtime.getRuntime().exit(0) // exit will restart the app, so library will be loaded
}
var tempFilePath: String? by remember { mutableStateOf(null) }
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode != Activity.RESULT_OK) return@rememberLauncherForActivityResult
val uri = it.data?.data ?: return@rememberLauncherForActivityResult
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode != Activity.RESULT_OK) return@rememberLauncherForActivityResult
val uri = result.data?.data ?: return@rememberLauncherForActivityResult
val tmpfile = File(ctx.filesDir.absolutePath + File.separator + "tmplib")
try {
val otherTemporaryFile = File(ctx.filesDir.absolutePath + File.separator + "tmpfile")
@ -556,12 +534,12 @@ fun createAdvancedPrefs(context: Context) = listOf(
val checksum = ChecksumCalculator.checksum(tmpfile.inputStream()) ?: ""
if (checksum == JniUtils.expectedDefaultChecksum()) {
renameToLibfileAndRestart(tmpfile, checksum)
renameToLibFileAndRestart(tmpfile, checksum)
} else {
tempFilePath = tmpfile.absolutePath
AlertDialog.Builder(ctx)
.setMessage(ctx.getString(R.string.checksum_mismatch_message, abi))
.setPositiveButton(android.R.string.ok) { _, _ -> renameToLibfileAndRestart(tmpfile, checksum) }
.setPositiveButton(android.R.string.ok) { _, _ -> renameToLibFileAndRestart(tmpfile, checksum) }
.setNegativeButton(android.R.string.cancel) { _, _ -> tmpfile.delete() }
.show()
}
@ -571,7 +549,7 @@ fun createAdvancedPrefs(context: Context) = listOf(
}
}
Preference(
name = it.title,
name = def.title,
onClick = { showDialog = true }
)
if (showDialog) {
@ -596,13 +574,13 @@ fun createAdvancedPrefs(context: Context) = listOf(
if (tempFilePath != null)
ConfirmationDialog(
onDismissRequest = {
File(tempFilePath).delete()
File(tempFilePath!!).delete()
tempFilePath = null
},
text = { Text(stringResource(R.string.checksum_mismatch_message, abi))},
onConfirmed = {
val tempFile = File(tempFilePath)
renameToLibfileAndRestart(tempFile, ChecksumCalculator.checksum(tempFile.inputStream()) ?: "")
val tempFile = File(tempFilePath!!)
renameToLibFileAndRestart(tempFile, ChecksumCalculator.checksum(tempFile.inputStream()) ?: "")
}
)
},

View file

@ -111,7 +111,7 @@ fun createAppearancePrefs(context: Context) = listOf(
KeyboardTheme.STYLE_MATERIAL
) {
if (it != KeyboardTheme.STYLE_HOLO) {
// todo: use defaults once they exist
// todo (later): use defaults once they exist
if (prefs.getString(Settings.PREF_THEME_COLORS, "") == KeyboardTheme.THEME_HOLO_WHITE)
prefs.edit().putString(Settings.PREF_THEME_COLORS, KeyboardTheme.THEME_LIGHT).apply()
if (prefs.getString(Settings.PREF_THEME_COLORS_NIGHT, "") == KeyboardTheme.THEME_HOLO_WHITE)
@ -121,9 +121,7 @@ fun createAppearancePrefs(context: Context) = listOf(
},
PrefDef(context, Settings.PREF_ICON_STYLE, R.string.icon_style) { def ->
val ctx = LocalContext.current
val items = KeyboardTheme.STYLES.map {
it.getStringResourceOrName("style_name_", ctx) to it
}
val items = KeyboardTheme.STYLES.map { it.getStringResourceOrName("style_name_", ctx) to it }
ListPreference(
def,
items,
@ -200,28 +198,30 @@ fun createAppearancePrefs(context: Context) = listOf(
}
)
},
PrefDef(context, Settings.PREF_THEME_KEY_BORDERS, R.string.key_borders) { def ->
SwitchPreference(def, false)
PrefDef(context, Settings.PREF_THEME_KEY_BORDERS, R.string.key_borders) {
SwitchPreference(it, false)
},
PrefDef(context, Settings.PREF_THEME_DAY_NIGHT, R.string.day_night_mode, R.string.day_night_mode_summary) { def ->
SwitchPreference(def, Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { keyboardNeedsReload = true }
PrefDef(context, Settings.PREF_THEME_DAY_NIGHT, R.string.day_night_mode, R.string.day_night_mode_summary) {
SwitchPreference(it, Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { keyboardNeedsReload = true }
},
PrefDef(context, Settings.PREF_NAVBAR_COLOR, R.string.theme_navbar, R.string.day_night_mode_summary) { def ->
SwitchPreference(def, Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
PrefDef(context, Settings.PREF_NAVBAR_COLOR, R.string.theme_navbar, R.string.day_night_mode_summary) {
SwitchPreference(it, Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
},
PrefDef(context, NonSettingsPrefs.BACKGROUND_IMAGE, R.string.customize_background_image) { def ->
BackgroundImagePref(def, false)
PrefDef(context, NonSettingsPrefs.BACKGROUND_IMAGE, R.string.customize_background_image) {
BackgroundImagePref(it, false)
},
PrefDef(context, NonSettingsPrefs.BACKGROUND_IMAGE_LANDSCAPE, R.string.customize_background_image_landscape, R.string.summary_customize_background_image_landscape) { def ->
BackgroundImagePref(def, true)
PrefDef(context, NonSettingsPrefs.BACKGROUND_IMAGE_LANDSCAPE,
R.string.customize_background_image_landscape, R.string.summary_customize_background_image_landscape)
{
BackgroundImagePref(it, true)
},
PrefDef(context, Settings.PREF_ENABLE_SPLIT_KEYBOARD, R.string.enable_split_keyboard) {
SwitchPreference(it, false)
},
PrefDef(context, Settings.PREF_SPLIT_SPACER_SCALE, R.string.split_spacer_scale) {
PrefDef(context, Settings.PREF_SPLIT_SPACER_SCALE, R.string.split_spacer_scale) { def ->
SliderPreference(
name = it.title,
pref = it.key,
name = def.title,
pref = def.key,
default = SettingsValues.DEFAULT_SIZE_SCALE,
range = 0.5f..2f,
description = { "${(100 * it).toInt()}%" }
@ -230,19 +230,19 @@ fun createAppearancePrefs(context: Context) = listOf(
PrefDef(context, Settings.PREF_NARROW_KEY_GAPS, R.string.prefs_narrow_key_gaps) {
SwitchPreference(it, false) { keyboardNeedsReload = true }
},
PrefDef(context, Settings.PREF_KEYBOARD_HEIGHT_SCALE, R.string.prefs_keyboard_height_scale) {
PrefDef(context, Settings.PREF_KEYBOARD_HEIGHT_SCALE, R.string.prefs_keyboard_height_scale) { def ->
SliderPreference(
name = it.title,
pref = it.key,
name = def.title,
pref = def.key,
default = SettingsValues.DEFAULT_SIZE_SCALE,
range = 0.5f..1.5f,
description = { "${(100 * it).toInt()}%" }
) { keyboardNeedsReload = true }
},
PrefDef(context, Settings.PREF_BOTTOM_PADDING_SCALE, R.string.prefs_bottom_padding_scale) {
PrefDef(context, Settings.PREF_BOTTOM_PADDING_SCALE, R.string.prefs_bottom_padding_scale) { def ->
SliderPreference(
name = it.title,
pref = it.key,
name = def.title,
pref = def.key,
default = SettingsValues.DEFAULT_SIZE_SCALE,
range = 0f..5f,
description = { "${(100 * it).toInt()}%" }
@ -280,7 +280,7 @@ fun createAppearancePrefs(context: Context) = listOf(
val tempFile = File(DeviceProtectedUtils.getFilesDir(context), "temp_file")
FileUtils.copyContentUriToNewFile(uri, ctx, tempFile)
try {
val typeface = Typeface.createFromFile(tempFile)
Typeface.createFromFile(tempFile)
fontFile.delete()
tempFile.renameTo(fontFile)
Settings.clearCachedTypeface()

View file

@ -16,8 +16,8 @@ fun ColorsScreen(
onClickBack: () -> Unit
) {
var availableColors by remember { mutableStateOf(emptyList<ColorSetting>()) } // todo: type?
// todo: save / load / type selection here? or in ... menu as previously?
var availableColors by remember { mutableStateOf(emptyList<ColorSetting>()) } // todo (later): type?
// todo (later): save / load / type selection here? or in ... menu as previously?
SearchScreen(
title = stringResource(if (night) R.string.select_user_colors_night else R.string.select_user_colors),
onClickBack = onClickBack,

View file

@ -70,7 +70,7 @@ fun createDebugPrefs(context: Context) = listOf(
if (!it) prefs.edit().putBoolean(DebugSettings.PREF_SHOW_SUGGESTION_INFOS, false).apply()
showConfirmDialog = true
}
if (showConfirmDialog) { // todo: maybe do it differently?
if (showConfirmDialog) {
ConfirmationDialog(
onDismissRequest = { showConfirmDialog = false },
onConfirmed = { Runtime.getRuntime().exit(0) },
@ -84,7 +84,7 @@ fun createDebugPrefs(context: Context) = listOf(
PrefDef(context, DebugSettings.PREF_FORCE_NON_DISTINCT_MULTITOUCH, R.string.prefs_force_non_distinct_multitouch) { def ->
var showConfirmDialog by remember { mutableStateOf(false) }
SwitchPreference(def, false) { showConfirmDialog = true }
if (showConfirmDialog) { // todo: maybe do it differently?
if (showConfirmDialog) {
ConfirmationDialog(
onDismissRequest = { showConfirmDialog = false },
onConfirmed = { Runtime.getRuntime().exit(0) },

View file

@ -53,29 +53,21 @@ fun GestureTypingScreen(
fun createGestureTypingPrefs(context: Context) = listOf(
PrefDef(context, Settings.PREF_GESTURE_INPUT, R.string.gesture_input, R.string.gesture_input_summary) {
SwitchPreference(
def = it,
default = true
)
SwitchPreference(it, true)
},
PrefDef(context, Settings.PREF_GESTURE_PREVIEW_TRAIL, R.string.gesture_preview_trail) {
SwitchPreference(
def = it,
default = true
)
SwitchPreference(it, true)
},
PrefDef(context, Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT, R.string.gesture_floating_preview_static, R.string.gesture_floating_preview_static_summary) {
SwitchPreference(
def = it,
default = true
)
PrefDef(context, Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT,
R.string.gesture_floating_preview_static, R.string.gesture_floating_preview_static_summary)
{
SwitchPreference(it, true)
},
PrefDef(context, Settings.PREF_GESTURE_FLOATING_PREVIEW_DYNAMIC, R.string.gesture_floating_preview_text, R.string.gesture_floating_preview_dynamic_summary) {
PrefDef(context, Settings.PREF_GESTURE_FLOATING_PREVIEW_DYNAMIC,
R.string.gesture_floating_preview_text, R.string.gesture_floating_preview_dynamic_summary)
{ def ->
val ctx = LocalContext.current
SwitchPreference(
def = it,
default = true
) {
SwitchPreference(def, true) {
// is this complexity and 2 pref keys for one setting really needed?
// default value is based on system reduced motion
val default = Settings.readGestureDynamicPreviewDefault(ctx)
@ -86,15 +78,12 @@ fun createGestureTypingPrefs(context: Context) = listOf(
}
},
PrefDef(context, Settings.PREF_GESTURE_SPACE_AWARE, R.string.gesture_space_aware, R.string.gesture_space_aware_summary) {
SwitchPreference(
def = it,
default = false
)
SwitchPreference(it, false)
},
PrefDef(context, Settings.PREF_GESTURE_FAST_TYPING_COOLDOWN, R.string.gesture_fast_typing_cooldown) {
PrefDef(context, Settings.PREF_GESTURE_FAST_TYPING_COOLDOWN, R.string.gesture_fast_typing_cooldown) { def ->
SliderPreference(
name = it.title,
pref = it.key,
name = def.title,
pref = def.key,
default = 500,
range = 0f..500f,
description = {
@ -103,18 +92,14 @@ fun createGestureTypingPrefs(context: Context) = listOf(
}
)
},
PrefDef(context, Settings.PREF_GESTURE_TRAIL_FADEOUT_DURATION, R.string.gesture_trail_fadeout_duration) {
// todo: there is some weird stuff going on
// for some uses there is an additional 100 ms delay
// see config_gesture_trail_fadeout_start_delay
// -> check whether this should be changes, or at least made less complicated
PrefDef(context, Settings.PREF_GESTURE_TRAIL_FADEOUT_DURATION, R.string.gesture_trail_fadeout_duration) { def ->
SliderPreference(
name = it.title,
pref = it.key,
name = def.title,
pref = def.key,
default = 800,
range = 100f..1900f,
description = { stringResource(R.string.abbreviation_unit_milliseconds, (it + 100).toString()) },
// todo: 50 ms steps?
stepSize = 10,
) { keyboardNeedsReload = true }
},
)

View file

@ -104,7 +104,9 @@ fun createPreferencesPrefs(context: Context) = listOf(
PrefDef(context, Settings.PREF_SOUND_ON, R.string.sound_on_keypress) {
SwitchPreference(it, false)
},
PrefDef(context, Settings.PREF_ENABLE_CLIPBOARD_HISTORY, R.string.enable_clipboard_history, R.string.enable_clipboard_history_summary) {
PrefDef(context, Settings.PREF_ENABLE_CLIPBOARD_HISTORY,
R.string.enable_clipboard_history, R.string.enable_clipboard_history_summary)
{
SwitchPreference(it, true)
},
PrefDef(context, Settings.PREF_SHOW_NUMBER_ROW, R.string.number_row, R.string.number_row_summary) {
@ -130,7 +132,9 @@ fun createPreferencesPrefs(context: Context) = listOf(
PrefDef(context, Settings.PREF_SHOW_EMOJI_KEY, R.string.show_emoji_key) {
SwitchPreference(it, false)
},
PrefDef(context, Settings.PREF_REMOVE_REDUNDANT_POPUPS, R.string.remove_redundant_popups, R.string.remove_redundant_popups_summary) {
PrefDef(context, Settings.PREF_REMOVE_REDUNDANT_POPUPS,
R.string.remove_redundant_popups, R.string.remove_redundant_popups_summary)
{
SwitchPreference(it, false) { keyboardNeedsReload = true }
},
PrefDef(context, Settings.PREF_CLIPBOARD_HISTORY_RETENTION_TIME, R.string.clipboard_history_retention_time) { def ->
@ -174,7 +178,7 @@ fun createPreferencesPrefs(context: Context) = listOf(
},
)
// todo: not good to have it hardcoded, but reading a bunch of files may be noticeably slow
// todo (later): not good to have it hardcoded, but reading a bunch of files may be noticeably slow
private val localesWithLocalizedNumberRow = listOf("ar", "bn", "fa", "gu", "hi", "kn", "mr", "ne", "ur")
@Preview

View file

@ -93,84 +93,61 @@ fun createCorrectionPrefs(context: Context) = listOf(
)
}
},
PrefDef(context,
Settings.PREF_BLOCK_POTENTIALLY_OFFENSIVE,
R.string.prefs_block_potentially_offensive_title,
R.string.prefs_block_potentially_offensive_summary
PrefDef(context, Settings.PREF_BLOCK_POTENTIALLY_OFFENSIVE,
R.string.prefs_block_potentially_offensive_title, R.string.prefs_block_potentially_offensive_summary
) {
SwitchPreference(it, true)
},
PrefDef(context,
Settings.PREF_AUTO_CORRECTION,
R.string.autocorrect,
R.string.auto_correction_summary
PrefDef(context, Settings.PREF_AUTO_CORRECTION,
R.string.autocorrect, R.string.auto_correction_summary
) {
SwitchPreference(it, true)
},
PrefDef(context,
Settings.PREF_MORE_AUTO_CORRECTION,
R.string.more_autocorrect,
R.string.more_autocorrect_summary
PrefDef(context, Settings.PREF_MORE_AUTO_CORRECTION,
R.string.more_autocorrect, R.string.more_autocorrect_summary
) {
SwitchPreference(it, true) // todo: shouldn't it better be false?
SwitchPreference(it, true) // todo (later): shouldn't it better be false?
},
PrefDef(context,
Settings.PREF_AUTOCORRECT_SHORTCUTS,
R.string.auto_correct_shortcuts,
R.string.auto_correct_shortcuts_summary
PrefDef(context, Settings.PREF_AUTOCORRECT_SHORTCUTS,
R.string.auto_correct_shortcuts, R.string.auto_correct_shortcuts_summary
) {
SwitchPreference(it, true)
},
PrefDef(context,
Settings.PREF_AUTO_CORRECTION_CONFIDENCE,
R.string.auto_correction_confidence,
) { def ->
PrefDef(context, Settings.PREF_AUTO_CORRECTION_CONFIDENCE, R.string.auto_correction_confidence) {
val items = listOf(
stringResource(R.string.auto_correction_threshold_mode_modest) to "0",
stringResource(R.string.auto_correction_threshold_mode_aggressive) to "1",
stringResource(R.string.auto_correction_threshold_mode_very_aggressive) to "2",
)
ListPreference(def, items, "0")
ListPreference(it, items, "0")
},
PrefDef(context,
Settings.PREF_AUTO_CAP,
R.string.auto_cap,
R.string.auto_cap_summary
PrefDef(context, Settings.PREF_AUTO_CAP,
R.string.auto_cap, R.string.auto_cap_summary
) {
SwitchPreference(it, true)
},
PrefDef(context,
Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD,
R.string.use_double_space_period,
R.string.use_double_space_period_summary
PrefDef(context, Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD,
R.string.use_double_space_period, R.string.use_double_space_period_summary
) {
SwitchPreference(it, true)
},
PrefDef(context,
Settings.PREF_AUTOSPACE_AFTER_PUNCTUATION,
R.string.autospace_after_punctuation,
R.string.autospace_after_punctuation_summary
PrefDef(context, Settings.PREF_AUTOSPACE_AFTER_PUNCTUATION,
R.string.autospace_after_punctuation, R.string.autospace_after_punctuation_summary
) {
SwitchPreference(it, false)
},
PrefDef(context,
Settings.PREF_SHOW_SUGGESTIONS,
R.string.prefs_show_suggestions,
R.string.prefs_show_suggestions_summary
PrefDef(context, Settings.PREF_SHOW_SUGGESTIONS,
R.string.prefs_show_suggestions, R.string.prefs_show_suggestions_summary
) {
SwitchPreference(it, true)
},
PrefDef(context,
Settings.PREF_ALWAYS_SHOW_SUGGESTIONS,
R.string.prefs_always_show_suggestions,
R.string.prefs_always_show_suggestions_summary
PrefDef(context, Settings.PREF_ALWAYS_SHOW_SUGGESTIONS,
R.string.prefs_always_show_suggestions, R.string.prefs_always_show_suggestions_summary
) {
SwitchPreference(it, false)
},
PrefDef(context,
Settings.PREF_KEY_USE_PERSONALIZED_DICTS,
R.string.use_personalized_dicts,
R.string.use_personalized_dicts_summary
PrefDef(context, Settings.PREF_KEY_USE_PERSONALIZED_DICTS,
R.string.use_personalized_dicts, R.string.use_personalized_dicts_summary
) { prefDef ->
var showConfirmDialog by remember { mutableStateOf(false) }
SwitchPreference(
@ -193,31 +170,23 @@ fun createCorrectionPrefs(context: Context) = listOf(
}
},
PrefDef(context,
Settings.PREF_BIGRAM_PREDICTIONS,
R.string.bigram_prediction,
R.string.bigram_prediction_summary
PrefDef(context, Settings.PREF_BIGRAM_PREDICTIONS,
R.string.bigram_prediction, R.string.bigram_prediction_summary
) {
SwitchPreference(it, true) { keyboardNeedsReload = true }
},
PrefDef(context,
Settings.PREF_CENTER_SUGGESTION_TEXT_TO_ENTER,
R.string.center_suggestion_text_to_enter,
R.string.center_suggestion_text_to_enter_summary
PrefDef(context, Settings.PREF_CENTER_SUGGESTION_TEXT_TO_ENTER,
R.string.center_suggestion_text_to_enter, R.string.center_suggestion_text_to_enter_summary
) {
SwitchPreference(it, false)
},
PrefDef(context,
Settings.PREF_SUGGEST_CLIPBOARD_CONTENT,
R.string.suggest_clipboard_content,
R.string.suggest_clipboard_content_summary
PrefDef(context, Settings.PREF_SUGGEST_CLIPBOARD_CONTENT,
R.string.suggest_clipboard_content, R.string.suggest_clipboard_content_summary
) {
SwitchPreference(it, true)
},
PrefDef(context,
Settings.PREF_USE_CONTACTS,
R.string.use_contacts_dict,
R.string.use_contacts_dict_summary
PrefDef(context, Settings.PREF_USE_CONTACTS,
R.string.use_contacts_dict, R.string.use_contacts_dict_summary
) { def ->
val activity = LocalContext.current.getActivity() ?: return@PrefDef
var granted by remember { mutableStateOf(PermissionsUtil.checkAllPermissionsGranted(activity, Manifest.permission.READ_CONTACTS)) }
@ -237,10 +206,8 @@ fun createCorrectionPrefs(context: Context) = listOf(
}
)
},
PrefDef(context,
Settings.PREF_ADD_TO_PERSONAL_DICTIONARY,
R.string.add_to_personal_dictionary,
R.string.add_to_personal_dictionary_summary
PrefDef(context, Settings.PREF_ADD_TO_PERSONAL_DICTIONARY,
R.string.add_to_personal_dictionary, R.string.add_to_personal_dictionary_summary
) {
SwitchPreference(it, false)
},

View file

@ -63,19 +63,19 @@ fun ToolbarScreen(
}
fun createToolbarPrefs(context: Context) = listOf(
PrefDef(context, Settings.PREF_TOOLBAR_KEYS, R.string.toolbar_keys) { def ->
ReorderSwitchPreference(def, defaultToolbarPref)
PrefDef(context, Settings.PREF_TOOLBAR_KEYS, R.string.toolbar_keys) {
ReorderSwitchPreference(it, defaultToolbarPref)
},
PrefDef(context, Settings.PREF_PINNED_TOOLBAR_KEYS, R.string.pinned_toolbar_keys) { def ->
ReorderSwitchPreference(def, defaultPinnedToolbarPref)
PrefDef(context, Settings.PREF_PINNED_TOOLBAR_KEYS, R.string.pinned_toolbar_keys) {
ReorderSwitchPreference(it, defaultPinnedToolbarPref)
},
PrefDef(context, Settings.PREF_CLIPBOARD_TOOLBAR_KEYS, R.string.clipboard_toolbar_keys) { def ->
ReorderSwitchPreference(def, defaultClipboardToolbarPref)
PrefDef(context, Settings.PREF_CLIPBOARD_TOOLBAR_KEYS, R.string.clipboard_toolbar_keys) {
ReorderSwitchPreference(it, defaultClipboardToolbarPref)
},
PrefDef(context, NonSettingsPrefs.CUSTOM_KEY_CODES, R.string.customize_toolbar_key_codes) { def ->
PrefDef(context, NonSettingsPrefs.CUSTOM_KEY_CODES, R.string.customize_toolbar_key_codes) {
var showDialog by remember { mutableStateOf(false) }
Preference(
name = def.title,
name = it.title,
onClick = { showDialog = true },
)
if (showDialog)
@ -84,29 +84,23 @@ fun createToolbarPrefs(context: Context) = listOf(
onDismissRequest = { showDialog = false }
)
},
PrefDef(context, Settings.PREF_QUICK_PIN_TOOLBAR_KEYS, R.string.quick_pin_toolbar_keys, R.string.quick_pin_toolbar_keys_summary) { def ->
SwitchPreference(
def,
false,
) { keyboardNeedsReload = true }
PrefDef(context, Settings.PREF_QUICK_PIN_TOOLBAR_KEYS,
R.string.quick_pin_toolbar_keys, R.string.quick_pin_toolbar_keys_summary)
{
SwitchPreference(it, false,) { keyboardNeedsReload = true }
},
PrefDef(context, Settings.PREF_AUTO_SHOW_TOOLBAR, R.string.auto_show_toolbar, R.string.auto_show_toolbar_summary) { def ->
SwitchPreference(
def,
false,
)
PrefDef(context, Settings.PREF_AUTO_SHOW_TOOLBAR, R.string.auto_show_toolbar, R.string.auto_show_toolbar_summary)
{
SwitchPreference(it, false,)
},
PrefDef(context, Settings.PREF_AUTO_HIDE_TOOLBAR, R.string.auto_hide_toolbar, R.string.auto_hide_toolbar_summary) { def ->
SwitchPreference(
def,
false,
)
PrefDef(context, Settings.PREF_AUTO_HIDE_TOOLBAR, R.string.auto_hide_toolbar, R.string.auto_hide_toolbar_summary)
{
SwitchPreference(it, false,)
},
PrefDef(context, Settings.PREF_VARIABLE_TOOLBAR_DIRECTION, R.string.var_toolbar_direction, R.string.var_toolbar_direction_summary) { def ->
SwitchPreference(
def,
true,
)
PrefDef(context, Settings.PREF_VARIABLE_TOOLBAR_DIRECTION,
R.string.var_toolbar_direction, R.string.var_toolbar_direction_summary)
{
SwitchPreference(it, true,)
}
)

View file

@ -969,5 +969,5 @@ New dictionary:
<!-- Confirmation message when resetting all custom icons -->
<string name="customize_icons_reset_message">Really reset all customized icons?</string>
<!-- Dialog message when restart of the app is required (sometimes actually does start again) -->
<string name="message_restart_required">A restart is required to apply the changes. Quit now?</string>
<string name="message_restart_required">Application restart is required to apply the changes. Quit now?</string>
</resources>