mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-05-16 23:12:47 +00:00
357 lines
16 KiB
Kotlin
357 lines
16 KiB
Kotlin
package helium314.keyboard.settings.screens
|
|
|
|
import android.content.Context
|
|
import android.os.Build
|
|
import android.widget.Toast
|
|
import androidx.compose.material3.Icon
|
|
import androidx.compose.material3.Surface
|
|
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.draw.scale
|
|
import androidx.compose.ui.platform.LocalContext
|
|
import androidx.compose.ui.res.painterResource
|
|
import androidx.compose.ui.res.stringResource
|
|
import androidx.compose.ui.tooling.preview.Preview
|
|
import helium314.keyboard.keyboard.KeyboardLayoutSet
|
|
import helium314.keyboard.keyboard.internal.keyboard_parser.RawKeyboardParser
|
|
import helium314.keyboard.latin.BuildConfig
|
|
import helium314.keyboard.latin.R
|
|
import helium314.keyboard.latin.SystemBroadcastReceiver
|
|
import helium314.keyboard.latin.common.splitOnWhitespace
|
|
import helium314.keyboard.latin.settings.DebugSettings
|
|
import helium314.keyboard.latin.settings.Settings
|
|
import helium314.keyboard.latin.utils.CUSTOM_FUNCTIONAL_LAYOUT_NORMAL
|
|
import helium314.keyboard.latin.utils.CUSTOM_FUNCTIONAL_LAYOUT_SYMBOLS
|
|
import helium314.keyboard.latin.utils.CUSTOM_FUNCTIONAL_LAYOUT_SYMBOLS_SHIFTED
|
|
import helium314.keyboard.latin.utils.CUSTOM_LAYOUT_PREFIX
|
|
import helium314.keyboard.latin.utils.Log
|
|
import helium314.keyboard.latin.utils.checkLayout
|
|
import helium314.keyboard.latin.utils.getCustomLayoutFile
|
|
import helium314.keyboard.latin.utils.getCustomLayoutFiles
|
|
import helium314.keyboard.latin.utils.getLayoutDisplayName
|
|
import helium314.keyboard.latin.utils.getStringResourceOrName
|
|
import helium314.keyboard.latin.utils.prefs
|
|
import helium314.keyboard.settings.AllPrefs
|
|
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
|
|
import helium314.keyboard.settings.SliderPreference
|
|
import helium314.keyboard.settings.SwitchPreference
|
|
import helium314.keyboard.settings.Theme
|
|
import helium314.keyboard.settings.dialogs.CustomizeLayoutDialog
|
|
import helium314.keyboard.settings.dialogs.ListPickerDialog
|
|
import helium314.keyboard.settings.dialogs.TextInputDialog
|
|
import helium314.keyboard.settings.keyboardNeedsReload
|
|
import kotlinx.coroutines.Job
|
|
import kotlinx.coroutines.delay
|
|
import kotlinx.coroutines.launch
|
|
import java.io.File
|
|
|
|
@Composable
|
|
fun AdvancedSettingsScreen(
|
|
onClickBack: () -> Unit,
|
|
) {
|
|
val prefs = LocalContext.current.prefs()
|
|
SearchPrefScreen(
|
|
onClickBack = onClickBack,
|
|
title = stringResource(R.string.settings_screen_advanced),
|
|
) {
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_ALWAYS_INCOGNITO_MODE]!!.Preference()
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_KEY_LONGPRESS_TIMEOUT]!!.Preference()
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_SPACE_HORIZONTAL_SWIPE]!!.Preference()
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_SPACE_VERTICAL_SWIPE]!!.Preference()
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_DELETE_SWIPE]!!.Preference()
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_SPACE_TO_CHANGE_LANG]!!.Preference()
|
|
SettingsActivity2.allPrefs.map[Settings.PREFS_LONG_PRESS_SYMBOLS_FOR_NUMPAD]!!.Preference()
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_ENABLE_EMOJI_ALT_PHYSICAL_KEY]!!.Preference()
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_SHOW_SETUP_WIZARD_ICON]!!.Preference()
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_ABC_AFTER_SYMBOL_SPACE]!!.Preference() // todo: this is ugly
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_ABC_AFTER_EMOJI]!!.Preference() // todo: this is ugly
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_ABC_AFTER_CLIP]!!.Preference() // todo: this is ugly
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_CUSTOM_CURRENCY_KEY]!!.Preference()
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_MORE_POPUP_KEYS]!!.Preference()
|
|
SettingsActivity2.allPrefs.map[NonSettingsPrefs.CUSTOM_SYMBOLS_NUMBER_LAYOUTS]!!.Preference()
|
|
SettingsActivity2.allPrefs.map[NonSettingsPrefs.CUSTOM_FUNCTIONAL_LAYOUTS]!!.Preference()
|
|
SettingsActivity2.allPrefs.map[NonSettingsPrefs.BACKUP_RESTORE]!!.Preference()
|
|
if (BuildConfig.DEBUG || prefs.getBoolean(DebugSettings.PREF_SHOW_DEBUG_SETTINGS, false))
|
|
SettingsActivity2.allPrefs.map[NonSettingsPrefs.DEBUG_SETTINGS]!!.Preference() // todo: maybe move to main screen?
|
|
PreferenceCategory(
|
|
stringResource(R.string.settings_category_experimental)
|
|
) {
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_EMOJI_MAX_SDK]!!.Preference()
|
|
SettingsActivity2.allPrefs.map[Settings.PREF_URL_DETECTION]!!.Preference()
|
|
if (BuildConfig.BUILD_TYPE != "nouserlib")
|
|
SettingsActivity2.allPrefs.map[NonSettingsPrefs.LOAD_GESTURE_LIB]!!.Preference()
|
|
}
|
|
}
|
|
}
|
|
|
|
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_KEY_LONGPRESS_TIMEOUT, R.string.prefs_key_longpress_timeout_settings) {
|
|
SliderPreference(
|
|
name = it.title,
|
|
pref = it.key,
|
|
default = 300,
|
|
range = 100f..700f,
|
|
description = { stringResource(R.string.abbreviation_unit_milliseconds, it.toString()) }
|
|
)
|
|
},
|
|
PrefDef(context, Settings.PREF_SPACE_HORIZONTAL_SWIPE, R.string.show_horizontal_space_swipe) { def ->
|
|
val items = listOf(
|
|
stringResource(R.string.space_swipe_move_cursor_entry) to "move_cursor",
|
|
stringResource(R.string.switch_language) to "switch_language",
|
|
stringResource(R.string.space_swipe_toggle_numpad_entry) to "toggle_numpad",
|
|
stringResource(R.string.action_none) to "none",
|
|
)
|
|
ListPreference(def, items, "move_cursor")
|
|
},
|
|
PrefDef(context, Settings.PREF_SPACE_VERTICAL_SWIPE, R.string.show_vertical_space_swipe) { def ->
|
|
val items = listOf(
|
|
stringResource(R.string.space_swipe_move_cursor_entry) to "move_cursor",
|
|
stringResource(R.string.switch_language) to "switch_language",
|
|
stringResource(R.string.space_swipe_toggle_numpad_entry) to "toggle_numpad",
|
|
stringResource(R.string.action_none) to "none",
|
|
)
|
|
ListPreference(def, items, "none")
|
|
},
|
|
PrefDef(context, Settings.PREF_DELETE_SWIPE, R.string.delete_swipe, R.string.delete_swipe_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(
|
|
def = it,
|
|
default = true
|
|
)
|
|
},
|
|
PrefDef(context, Settings.PREFS_LONG_PRESS_SYMBOLS_FOR_NUMPAD, R.string.prefs_long_press_symbol_for_numpad) {
|
|
SwitchPreference(
|
|
def = it,
|
|
default = 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_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) }
|
|
},
|
|
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_EMOJI, R.string.switch_keyboard_after, R.string.after_emoji) {
|
|
SwitchPreference(
|
|
def = it,
|
|
default = false
|
|
)
|
|
},
|
|
PrefDef(context, Settings.PREF_ABC_AFTER_CLIP, R.string.switch_keyboard_after, R.string.after_clip) {
|
|
SwitchPreference(
|
|
def = it,
|
|
default = false
|
|
)
|
|
},
|
|
PrefDef(context, Settings.PREF_CUSTOM_CURRENCY_KEY, R.string.customize_currencies) { def ->
|
|
var showDialog by remember { mutableStateOf(false) }
|
|
Preference(
|
|
name = def.title,
|
|
onClick = { showDialog = true }
|
|
)
|
|
if (showDialog) {
|
|
val prefs = LocalContext.current.prefs()
|
|
TextInputDialog(
|
|
onDismissRequest = { showDialog = false },
|
|
textInputLabel = { Text(stringResource(R.string.customize_currencies_detail)) },
|
|
initialText = prefs.getString(def.key, "")!!,
|
|
onConfirmed = { prefs.edit().putString(def.key, it).apply(); KeyboardLayoutSet.onSystemLocaleChanged() },
|
|
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 } }
|
|
)
|
|
}
|
|
},
|
|
PrefDef(context, Settings.PREF_MORE_POPUP_KEYS, R.string.show_popup_keys_title) { def ->
|
|
val items = listOf(
|
|
stringResource(R.string.show_popup_keys_normal) to "normal",
|
|
stringResource(R.string.show_popup_keys_main) to "main",
|
|
stringResource(R.string.show_popup_keys_more) to "more",
|
|
stringResource(R.string.show_popup_keys_all) to "all",
|
|
)
|
|
ListPreference(def, items, "main") { KeyboardLayoutSet.onSystemLocaleChanged() }
|
|
},
|
|
PrefDef(context, NonSettingsPrefs.CUSTOM_SYMBOLS_NUMBER_LAYOUTS, R.string.customize_symbols_number_layouts) { def ->
|
|
var showDialog by remember { mutableStateOf(false) }
|
|
val ctx = LocalContext.current
|
|
var layout: String? by remember { mutableStateOf(null) }
|
|
Preference(
|
|
name = def.title,
|
|
onClick = { showDialog = true }
|
|
)
|
|
if (showDialog) {
|
|
ListPickerDialog(
|
|
onDismissRequest = { showDialog = false },
|
|
showRadioButtons = false,
|
|
confirmImmediately = true,
|
|
items = RawKeyboardParser.symbolAndNumberLayouts,
|
|
getItemName = { it.getStringResourceOrName("layout_", ctx) },
|
|
onItemSelected = { layout = it },
|
|
title = { Text(def.title) }
|
|
)
|
|
}
|
|
if (layout != null) {
|
|
val customLayoutName = getCustomLayoutFiles(ctx).firstOrNull { it.name.startsWith("$CUSTOM_LAYOUT_PREFIX$layout.")}?.name
|
|
val originalLayout = if (customLayoutName != null) null
|
|
else {
|
|
ctx.assets.list("layouts")?.firstOrNull { it.startsWith("$layout.") }
|
|
?.let { ctx.assets.open("layouts" + File.separator + it).reader().readText() }
|
|
}
|
|
CustomizeLayoutDialog(
|
|
layoutName = customLayoutName ?: "$CUSTOM_LAYOUT_PREFIX$layout.",
|
|
startContent = originalLayout,
|
|
displayName = layout?.getStringResourceOrName("layout_", ctx),
|
|
onDismissRequest = { layout = null}
|
|
)
|
|
}
|
|
},
|
|
PrefDef(context, NonSettingsPrefs.CUSTOM_FUNCTIONAL_LAYOUTS, R.string.customize_functional_key_layouts) { def ->
|
|
var showDialog by remember { mutableStateOf(false) }
|
|
val ctx = LocalContext.current
|
|
var layout: String? by remember { mutableStateOf(null) }
|
|
Preference(
|
|
name = def.title,
|
|
onClick = { showDialog = true }
|
|
)
|
|
if (showDialog) {
|
|
ListPickerDialog(
|
|
onDismissRequest = { showDialog = false },
|
|
showRadioButtons = false,
|
|
confirmImmediately = true,
|
|
items = listOf(CUSTOM_FUNCTIONAL_LAYOUT_NORMAL, CUSTOM_FUNCTIONAL_LAYOUT_SYMBOLS, CUSTOM_FUNCTIONAL_LAYOUT_SYMBOLS_SHIFTED)
|
|
.map { it.substringBeforeLast(".") },
|
|
getItemName = { it.substringAfter(CUSTOM_LAYOUT_PREFIX).getStringResourceOrName("layout_", ctx) },
|
|
onItemSelected = { layout = it },
|
|
title = { Text(def.title) }
|
|
)
|
|
}
|
|
if (layout != null) {
|
|
val customLayoutName = getCustomLayoutFiles(ctx).map { it.name }
|
|
.firstOrNull { it.startsWith("$layout.") }
|
|
val originalLayout = if (customLayoutName != null) null
|
|
else {
|
|
val defaultLayoutName = if (Settings.getInstance().isTablet) "functional_keys_tablet.json" else "functional_keys.json"
|
|
ctx.assets.open("layouts" + File.separator + defaultLayoutName).reader().readText()
|
|
}
|
|
CustomizeLayoutDialog(
|
|
layoutName = customLayoutName ?: "$CUSTOM_LAYOUT_PREFIX$layout.",
|
|
startContent = originalLayout,
|
|
displayName = layout?.substringAfter(CUSTOM_LAYOUT_PREFIX)?.getStringResourceOrName("layout_", ctx),
|
|
onDismissRequest = { layout = null}
|
|
)
|
|
}
|
|
},
|
|
PrefDef(context, NonSettingsPrefs.BACKUP_RESTORE, R.string.backup_restore_title) {
|
|
var showDialog by remember { mutableStateOf(false) }
|
|
Preference(
|
|
name = it.title,
|
|
onClick = { showDialog = true }
|
|
)
|
|
// if (showDialog) todo: show the dialog
|
|
},
|
|
PrefDef(context, NonSettingsPrefs.DEBUG_SETTINGS, R.string.debug_settings_title) {
|
|
Preference(
|
|
name = it.title,
|
|
onClick = { SettingsDestination.navigateTo(SettingsDestination.Debug) }
|
|
) {
|
|
Icon(
|
|
painter = painterResource(R.drawable.ic_arrow_left),
|
|
modifier = Modifier.scale(-1f, 1f),
|
|
contentDescription = null
|
|
)
|
|
}
|
|
},
|
|
PrefDef(context, Settings.PREF_EMOJI_MAX_SDK, R.string.prefs_key_emoji_max_sdk) {
|
|
SliderPreference(
|
|
name = it.title,
|
|
pref = it.key,
|
|
default = Build.VERSION.SDK_INT,
|
|
range = 21f..35f,
|
|
description = {
|
|
"Android " + when(it) {
|
|
21 -> "5.0"
|
|
22 -> "5.1"
|
|
23 -> "6"
|
|
24 -> "7.0"
|
|
25 -> "7.1"
|
|
26 -> "8.0"
|
|
27 -> "8.1"
|
|
28 -> "9"
|
|
29 -> "10"
|
|
30 -> "11"
|
|
31 -> "12"
|
|
32 -> "12L"
|
|
33 -> "13"
|
|
34 -> "14"
|
|
35 -> "15"
|
|
else -> "version unknown"
|
|
}
|
|
},
|
|
onValueChanged = { keyboardNeedsReload = true }
|
|
)
|
|
},
|
|
PrefDef(context, Settings.PREF_URL_DETECTION, R.string.url_detection_title, R.string.url_detection_summary) {
|
|
SwitchPreference(
|
|
def = it,
|
|
default = false
|
|
)
|
|
},
|
|
PrefDef(context, NonSettingsPrefs.LOAD_GESTURE_LIB, R.string.load_gesture_library, R.string.load_gesture_library_summary) {
|
|
var showDialog by remember { mutableStateOf(false) }
|
|
Preference(
|
|
name = it.title,
|
|
onClick = { showDialog = true }
|
|
)
|
|
// if (showDialog) todo: show the dialog, or launch that thing
|
|
},
|
|
)
|
|
|
|
@Preview
|
|
@Composable
|
|
private fun Preview() {
|
|
SettingsActivity2.allPrefs = AllPrefs(LocalContext.current)
|
|
Theme(true) {
|
|
Surface {
|
|
AdvancedSettingsScreen { }
|
|
}
|
|
}
|
|
}
|