mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-04-30 20:08:26 +00:00
move preferences to their own screen, for easier editing with preview
This commit is contained in:
parent
e1be94112e
commit
245c0f1678
3 changed files with 324 additions and 320 deletions
|
@ -1,12 +1,34 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
package helium314.keyboard.settings
|
package helium314.keyboard.settings
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.text.method.LinkMovementMethod
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
import helium314.keyboard.latin.BuildConfig
|
||||||
import helium314.keyboard.latin.R
|
import helium314.keyboard.latin.R
|
||||||
|
import helium314.keyboard.latin.settings.DebugSettings
|
||||||
|
import helium314.keyboard.latin.utils.DeviceProtectedUtils
|
||||||
|
import helium314.keyboard.latin.utils.Log
|
||||||
|
import helium314.keyboard.latin.utils.SpannableStringUtils
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AboutScreen(
|
fun AboutScreen(
|
||||||
|
@ -25,6 +47,116 @@ fun AboutScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createAboutPrefs(context: Context) = listOf(
|
||||||
|
PrefDef(context, NonSettingsPrefs.APP, R.string.english_ime_name, R.string.app_slogan) {
|
||||||
|
Preference(
|
||||||
|
name = it.title,
|
||||||
|
description = it.description,
|
||||||
|
onClick = { },
|
||||||
|
icon = R.drawable.ic_launcher_foreground
|
||||||
|
)
|
||||||
|
},
|
||||||
|
PrefDef(context, NonSettingsPrefs.VERSION, R.string.version) {
|
||||||
|
var count by rememberSaveable { mutableIntStateOf(0) }
|
||||||
|
val ctx = LocalContext.current
|
||||||
|
val prefs = DeviceProtectedUtils.getSharedPreferences(ctx)
|
||||||
|
Preference(
|
||||||
|
name = it.title,
|
||||||
|
description = stringResource(R.string.version_text, BuildConfig.VERSION_NAME),
|
||||||
|
onClick = {
|
||||||
|
if (prefs.getBoolean(DebugSettings.PREF_SHOW_DEBUG_SETTINGS, false) || BuildConfig.DEBUG)
|
||||||
|
return@Preference
|
||||||
|
count++
|
||||||
|
if (count < 5) return@Preference
|
||||||
|
prefs.edit().putBoolean(DebugSettings.PREF_SHOW_DEBUG_SETTINGS, true).apply()
|
||||||
|
Toast.makeText(ctx, R.string.prefs_debug_settings_enabled, Toast.LENGTH_LONG).show()
|
||||||
|
},
|
||||||
|
icon = R.drawable.ic_settings_about_foreground
|
||||||
|
)
|
||||||
|
},
|
||||||
|
PrefDef(context, NonSettingsPrefs.LICENSE, R.string.license, R.string.gnu_gpl) {
|
||||||
|
val ctx = LocalContext.current
|
||||||
|
Preference(
|
||||||
|
name = it.title,
|
||||||
|
description = it.description,
|
||||||
|
onClick = {
|
||||||
|
val intent = Intent()
|
||||||
|
intent.data = "https://github.com/Helium314/HeliBoard/blob/main/LICENSE-GPL-3".toUri()
|
||||||
|
intent.action = Intent.ACTION_VIEW
|
||||||
|
ctx.startActivity(intent)
|
||||||
|
},
|
||||||
|
icon = R.drawable.ic_settings_about_license_foreground
|
||||||
|
)
|
||||||
|
},
|
||||||
|
PrefDef(context, NonSettingsPrefs.HIDDEN_FEATURES, R.string.hidden_features_title, R.string.hidden_features_summary) {
|
||||||
|
val ctx = LocalContext.current
|
||||||
|
Preference(
|
||||||
|
name = it.title,
|
||||||
|
description = it.description,
|
||||||
|
onClick = {
|
||||||
|
// Compose dialogs are in a rather sad state. They don't understand HTML, and don't scroll without customization.
|
||||||
|
// this should be re-done in compose, but... bah
|
||||||
|
val link = ("<a href=\"https://developer.android.com/reference/android/content/Context#createDeviceProtectedStorageContext()\">"
|
||||||
|
+ ctx.getString(R.string.hidden_features_text) + "</a>")
|
||||||
|
val message = ctx.getString(R.string.hidden_features_message, link)
|
||||||
|
val dialogMessage = SpannableStringUtils.fromHtml(message)
|
||||||
|
val builder = androidx.appcompat.app.AlertDialog.Builder(ctx)
|
||||||
|
.setIcon(R.drawable.ic_settings_about_hidden_features)
|
||||||
|
.setTitle(R.string.hidden_features_title)
|
||||||
|
.setMessage(dialogMessage)
|
||||||
|
.setPositiveButton(R.string.dialog_close, null)
|
||||||
|
.create()
|
||||||
|
builder.show()
|
||||||
|
(builder.findViewById<View>(android.R.id.message) as TextView).movementMethod = LinkMovementMethod.getInstance()
|
||||||
|
},
|
||||||
|
icon = R.drawable.ic_settings_about_hidden_features_foreground
|
||||||
|
)
|
||||||
|
},
|
||||||
|
PrefDef(context, NonSettingsPrefs.GITHUB, R.string.about_github_link) {
|
||||||
|
val ctx = LocalContext.current
|
||||||
|
Preference(
|
||||||
|
name = it.title,
|
||||||
|
description = it.description,
|
||||||
|
onClick = {
|
||||||
|
val intent = Intent()
|
||||||
|
intent.data = "https://github.com/Helium314/HeliBoard".toUri()
|
||||||
|
intent.action = Intent.ACTION_VIEW
|
||||||
|
ctx.startActivity(intent)
|
||||||
|
},
|
||||||
|
icon = R.drawable.ic_settings_about_github_foreground
|
||||||
|
)
|
||||||
|
},
|
||||||
|
PrefDef(context, NonSettingsPrefs.SAVE_LOG, R.string.save_log) {
|
||||||
|
val ctx = LocalContext.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||||
|
if (result.resultCode != Activity.RESULT_OK) return@rememberLauncherForActivityResult
|
||||||
|
val uri = result.data?.data ?: return@rememberLauncherForActivityResult
|
||||||
|
scope.launch(Dispatchers.IO) {
|
||||||
|
ctx.getActivity()?.contentResolver?.openOutputStream(uri)?.use { os ->
|
||||||
|
os.bufferedWriter().use { it.write(Log.getLog().joinToString("\n")) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Preference(
|
||||||
|
name = it.title,
|
||||||
|
description = it.description,
|
||||||
|
onClick = {
|
||||||
|
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
|
||||||
|
.addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
.putExtra(
|
||||||
|
Intent.EXTRA_TITLE,
|
||||||
|
ctx.getString(R.string.english_ime_name)
|
||||||
|
.replace(" ", "_") + "_log_${System.currentTimeMillis()}.txt"
|
||||||
|
)
|
||||||
|
.setType("text/plain")
|
||||||
|
launcher.launch(intent)
|
||||||
|
},
|
||||||
|
icon = R.drawable.ic_settings_about_log_foreground
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun Preview() {
|
private fun Preview() {
|
||||||
|
|
|
@ -1,42 +1,11 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
package helium314.keyboard.settings
|
package helium314.keyboard.settings
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.ContextWrapper
|
import android.content.ContextWrapper
|
||||||
import android.content.Intent
|
|
||||||
import android.text.method.LinkMovementMethod
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.TextView
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.core.net.toUri
|
|
||||||
import helium314.keyboard.latin.BuildConfig
|
|
||||||
import helium314.keyboard.latin.R
|
|
||||||
import helium314.keyboard.latin.permissions.PermissionsUtil
|
|
||||||
import helium314.keyboard.latin.settings.DebugSettings
|
|
||||||
import helium314.keyboard.latin.settings.Settings
|
|
||||||
import helium314.keyboard.latin.settings.UserDictionaryListFragment
|
|
||||||
import helium314.keyboard.latin.utils.DeviceProtectedUtils
|
|
||||||
import helium314.keyboard.latin.utils.Log
|
|
||||||
import helium314.keyboard.latin.utils.SpannableStringUtils
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
class AllPrefs(context: Context) {
|
class AllPrefs(context: Context) {
|
||||||
private val list = createPrefDefs(context)
|
private val list = createPrefDefs(context)
|
||||||
|
@ -78,295 +47,7 @@ class PrefDef(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this will be looooooong
|
private fun createPrefDefs(context: Context) = createAboutPrefs(context) + createCorrectionPrefs(context)
|
||||||
private fun createPrefDefs(context: Context) = listOf(
|
|
||||||
// ---------------- correction ------------------
|
|
||||||
PrefDef(context, NonSettingsPrefs.EDIT_PERSONAL_DICTIONARY, R.string.edit_personal_dictionary) {
|
|
||||||
val ctx = LocalContext.current
|
|
||||||
Preference(
|
|
||||||
name = stringResource(R.string.edit_personal_dictionary),
|
|
||||||
onClick = { ctx.getActivity()?.switchTo(UserDictionaryListFragment()) },
|
|
||||||
)
|
|
||||||
},
|
|
||||||
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
|
|
||||||
) {
|
|
||||||
SwitchPreference(it, true)
|
|
||||||
},
|
|
||||||
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?
|
|
||||||
},
|
|
||||||
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 ->
|
|
||||||
var showDialog by remember { mutableStateOf(false) }
|
|
||||||
// todo: arrays are arranged in a rather absurd way... this should be improved
|
|
||||||
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",
|
|
||||||
)
|
|
||||||
val prefs = DeviceProtectedUtils.getSharedPreferences(LocalContext.current)
|
|
||||||
val selected = items.firstOrNull { it.second == prefs.getString(def.key, "0") }
|
|
||||||
Preference(
|
|
||||||
name = def.title,
|
|
||||||
description = selected?.first,
|
|
||||||
onClick = { showDialog = true }
|
|
||||||
)
|
|
||||||
if (showDialog) {
|
|
||||||
ListPickerDialog(
|
|
||||||
onDismissRequest = {showDialog = false },
|
|
||||||
items = items,
|
|
||||||
onItemSelected = {
|
|
||||||
if (it != selected)
|
|
||||||
prefs.edit().putString(def.key, it.second).apply()
|
|
||||||
},
|
|
||||||
selectedItem = selected,
|
|
||||||
title = { Text(def.title) },
|
|
||||||
getItemName = { it.first }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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
|
|
||||||
) {
|
|
||||||
SwitchPreference(it, true)
|
|
||||||
},
|
|
||||||
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
|
|
||||||
) {
|
|
||||||
SwitchPreference(it, true)
|
|
||||||
},
|
|
||||||
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 ->
|
|
||||||
var showConfirmDialog by remember { mutableStateOf(false) }
|
|
||||||
SwitchPreference(
|
|
||||||
prefDef,
|
|
||||||
true,
|
|
||||||
allowCheckedChange = {
|
|
||||||
showConfirmDialog = !it
|
|
||||||
it
|
|
||||||
}
|
|
||||||
)
|
|
||||||
if (showConfirmDialog) {
|
|
||||||
val prefs = DeviceProtectedUtils.getSharedPreferences(LocalContext.current)
|
|
||||||
ConfirmationDialog(
|
|
||||||
onDismissRequest = { showConfirmDialog = false },
|
|
||||||
onConfirmed = {
|
|
||||||
prefs.edit().putBoolean(prefDef.key, false).apply()
|
|
||||||
},
|
|
||||||
text = { Text(stringResource(R.string.disable_personalized_dicts_message)) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
PrefDef(context,
|
|
||||||
Settings.PREF_BIGRAM_PREDICTIONS,
|
|
||||||
R.string.bigram_prediction,
|
|
||||||
R.string.bigram_prediction_summary
|
|
||||||
) {
|
|
||||||
SwitchPreference(it, true) { themeChanged = 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
|
|
||||||
) {
|
|
||||||
SwitchPreference(it, false)
|
|
||||||
},
|
|
||||||
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
|
|
||||||
) {
|
|
||||||
val activity = LocalContext.current.getActivity() ?: return@PrefDef
|
|
||||||
var granted by remember { mutableStateOf(PermissionsUtil.checkAllPermissionsGranted(activity, Manifest.permission.READ_CONTACTS)) }
|
|
||||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) {
|
|
||||||
granted = it
|
|
||||||
}
|
|
||||||
SwitchPreference(
|
|
||||||
it,
|
|
||||||
false,
|
|
||||||
allowCheckedChange = {
|
|
||||||
if (it && !granted) {
|
|
||||||
launcher.launch(Manifest.permission.READ_CONTACTS)
|
|
||||||
false
|
|
||||||
} else true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
PrefDef(context,
|
|
||||||
Settings.PREF_ADD_TO_PERSONAL_DICTIONARY,
|
|
||||||
R.string.add_to_personal_dictionary,
|
|
||||||
R.string.add_to_personal_dictionary_summary
|
|
||||||
) {
|
|
||||||
SwitchPreference(it, false)
|
|
||||||
},
|
|
||||||
// ---------------- about ------------------
|
|
||||||
PrefDef(context, NonSettingsPrefs.APP, R.string.english_ime_name, R.string.app_slogan) {
|
|
||||||
Preference(
|
|
||||||
name = it.title,
|
|
||||||
description = it.description,
|
|
||||||
onClick = { },
|
|
||||||
icon = R.drawable.ic_launcher_foreground
|
|
||||||
)
|
|
||||||
},
|
|
||||||
PrefDef(context, NonSettingsPrefs.VERSION, R.string.version) {
|
|
||||||
var count by rememberSaveable { mutableIntStateOf(0) }
|
|
||||||
val ctx = LocalContext.current
|
|
||||||
val prefs = DeviceProtectedUtils.getSharedPreferences(ctx)
|
|
||||||
Preference(
|
|
||||||
name = it.title,
|
|
||||||
description = stringResource(R.string.version_text, BuildConfig.VERSION_NAME),
|
|
||||||
onClick = {
|
|
||||||
if (prefs.getBoolean(DebugSettings.PREF_SHOW_DEBUG_SETTINGS, false) || BuildConfig.DEBUG)
|
|
||||||
return@Preference
|
|
||||||
count++
|
|
||||||
if (count < 5) return@Preference
|
|
||||||
prefs.edit().putBoolean(DebugSettings.PREF_SHOW_DEBUG_SETTINGS, true).apply()
|
|
||||||
Toast.makeText(ctx, R.string.prefs_debug_settings_enabled, Toast.LENGTH_LONG).show()
|
|
||||||
},
|
|
||||||
icon = R.drawable.ic_settings_about_foreground
|
|
||||||
)
|
|
||||||
},
|
|
||||||
PrefDef(context, NonSettingsPrefs.LICENSE, R.string.license, R.string.gnu_gpl) {
|
|
||||||
val ctx = LocalContext.current
|
|
||||||
Preference(
|
|
||||||
name = it.title,
|
|
||||||
description = it.description,
|
|
||||||
onClick = {
|
|
||||||
val intent = Intent()
|
|
||||||
intent.data = "https://github.com/Helium314/HeliBoard/blob/main/LICENSE-GPL-3".toUri()
|
|
||||||
intent.action = Intent.ACTION_VIEW
|
|
||||||
ctx.startActivity(intent)
|
|
||||||
},
|
|
||||||
icon = R.drawable.ic_settings_about_license_foreground
|
|
||||||
)
|
|
||||||
},
|
|
||||||
PrefDef(context, NonSettingsPrefs.HIDDEN_FEATURES, R.string.hidden_features_title, R.string.hidden_features_summary) {
|
|
||||||
val ctx = LocalContext.current
|
|
||||||
Preference(
|
|
||||||
name = it.title,
|
|
||||||
description = it.description,
|
|
||||||
onClick = {
|
|
||||||
// Compose dialogs are in a rather sad state. They don't understand HTML, and don't scroll without customization.
|
|
||||||
// this should be re-done in compose, but... bah
|
|
||||||
val link = ("<a href=\"https://developer.android.com/reference/android/content/Context#createDeviceProtectedStorageContext()\">"
|
|
||||||
+ ctx.getString(R.string.hidden_features_text) + "</a>")
|
|
||||||
val message = ctx.getString(R.string.hidden_features_message, link)
|
|
||||||
val dialogMessage = SpannableStringUtils.fromHtml(message)
|
|
||||||
val builder = androidx.appcompat.app.AlertDialog.Builder(ctx)
|
|
||||||
.setIcon(R.drawable.ic_settings_about_hidden_features)
|
|
||||||
.setTitle(R.string.hidden_features_title)
|
|
||||||
.setMessage(dialogMessage)
|
|
||||||
.setPositiveButton(R.string.dialog_close, null)
|
|
||||||
.create()
|
|
||||||
builder.show()
|
|
||||||
(builder.findViewById<View>(android.R.id.message) as TextView).movementMethod = LinkMovementMethod.getInstance()
|
|
||||||
},
|
|
||||||
icon = R.drawable.ic_settings_about_hidden_features_foreground
|
|
||||||
)
|
|
||||||
},
|
|
||||||
PrefDef(context, NonSettingsPrefs.GITHUB, R.string.about_github_link) {
|
|
||||||
val ctx = LocalContext.current
|
|
||||||
Preference(
|
|
||||||
name = it.title,
|
|
||||||
description = it.description,
|
|
||||||
onClick = {
|
|
||||||
val intent = Intent()
|
|
||||||
intent.data = "https://github.com/Helium314/HeliBoard".toUri()
|
|
||||||
intent.action = Intent.ACTION_VIEW
|
|
||||||
ctx.startActivity(intent)
|
|
||||||
},
|
|
||||||
icon = R.drawable.ic_settings_about_github_foreground
|
|
||||||
)
|
|
||||||
},
|
|
||||||
PrefDef(context, NonSettingsPrefs.SAVE_LOG, R.string.save_log) {
|
|
||||||
val ctx = LocalContext.current
|
|
||||||
val scope = rememberCoroutineScope()
|
|
||||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
|
||||||
if (result.resultCode != Activity.RESULT_OK) return@rememberLauncherForActivityResult
|
|
||||||
val uri = result.data?.data ?: return@rememberLauncherForActivityResult
|
|
||||||
scope.launch(Dispatchers.IO) {
|
|
||||||
ctx.getActivity()?.contentResolver?.openOutputStream(uri)?.use { os ->
|
|
||||||
os.bufferedWriter().use { it.write(Log.getLog().joinToString("\n")) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Preference(
|
|
||||||
name = it.title,
|
|
||||||
description = it.description,
|
|
||||||
onClick = {
|
|
||||||
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
|
|
||||||
.addCategory(Intent.CATEGORY_OPENABLE)
|
|
||||||
.putExtra(
|
|
||||||
Intent.EXTRA_TITLE,
|
|
||||||
ctx.getString(R.string.english_ime_name)
|
|
||||||
.replace(" ", "_") + "_log_${System.currentTimeMillis()}.txt"
|
|
||||||
)
|
|
||||||
.setType("text/plain")
|
|
||||||
launcher.launch(intent)
|
|
||||||
},
|
|
||||||
icon = R.drawable.ic_settings_about_log_foreground
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
// todo: move somewhere else
|
// todo: move somewhere else
|
||||||
fun Context.getActivity(): ComponentActivity? {
|
fun Context.getActivity(): ComponentActivity? {
|
||||||
|
|
|
@ -1,17 +1,28 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
package helium314.keyboard.settings
|
package helium314.keyboard.settings
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import helium314.keyboard.latin.R
|
import helium314.keyboard.latin.R
|
||||||
|
import helium314.keyboard.latin.permissions.PermissionsUtil
|
||||||
import helium314.keyboard.latin.settings.Settings
|
import helium314.keyboard.latin.settings.Settings
|
||||||
|
import helium314.keyboard.latin.settings.UserDictionaryListFragment
|
||||||
import helium314.keyboard.latin.utils.DeviceProtectedUtils
|
import helium314.keyboard.latin.utils.DeviceProtectedUtils
|
||||||
import helium314.keyboard.latin.utils.Log
|
import helium314.keyboard.latin.utils.Log
|
||||||
|
|
||||||
|
@ -67,6 +78,186 @@ fun TextCorrectionScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createCorrectionPrefs(context: Context) = listOf(
|
||||||
|
PrefDef(context, NonSettingsPrefs.EDIT_PERSONAL_DICTIONARY, R.string.edit_personal_dictionary) {
|
||||||
|
val ctx = LocalContext.current
|
||||||
|
Preference(
|
||||||
|
name = stringResource(R.string.edit_personal_dictionary),
|
||||||
|
onClick = { ctx.getActivity()?.switchTo(UserDictionaryListFragment()) },
|
||||||
|
)
|
||||||
|
},
|
||||||
|
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
|
||||||
|
) {
|
||||||
|
SwitchPreference(it, true)
|
||||||
|
},
|
||||||
|
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?
|
||||||
|
},
|
||||||
|
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 ->
|
||||||
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
|
// todo: arrays are arranged in a rather absurd way... this should be improved
|
||||||
|
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",
|
||||||
|
)
|
||||||
|
val prefs = DeviceProtectedUtils.getSharedPreferences(LocalContext.current)
|
||||||
|
val selected = items.firstOrNull { it.second == prefs.getString(def.key, "0") }
|
||||||
|
Preference(
|
||||||
|
name = def.title,
|
||||||
|
description = selected?.first,
|
||||||
|
onClick = { showDialog = true }
|
||||||
|
)
|
||||||
|
if (showDialog) {
|
||||||
|
ListPickerDialog(
|
||||||
|
onDismissRequest = {showDialog = false },
|
||||||
|
items = items,
|
||||||
|
onItemSelected = {
|
||||||
|
if (it != selected)
|
||||||
|
prefs.edit().putString(def.key, it.second).apply()
|
||||||
|
},
|
||||||
|
selectedItem = selected,
|
||||||
|
title = { Text(def.title) },
|
||||||
|
getItemName = { it.first }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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
|
||||||
|
) {
|
||||||
|
SwitchPreference(it, true)
|
||||||
|
},
|
||||||
|
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
|
||||||
|
) {
|
||||||
|
SwitchPreference(it, true)
|
||||||
|
},
|
||||||
|
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 ->
|
||||||
|
var showConfirmDialog by remember { mutableStateOf(false) }
|
||||||
|
SwitchPreference(
|
||||||
|
prefDef,
|
||||||
|
true,
|
||||||
|
allowCheckedChange = {
|
||||||
|
showConfirmDialog = !it
|
||||||
|
it
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (showConfirmDialog) {
|
||||||
|
val prefs = DeviceProtectedUtils.getSharedPreferences(LocalContext.current)
|
||||||
|
ConfirmationDialog(
|
||||||
|
onDismissRequest = { showConfirmDialog = false },
|
||||||
|
onConfirmed = {
|
||||||
|
prefs.edit().putBoolean(prefDef.key, false).apply()
|
||||||
|
},
|
||||||
|
text = { Text(stringResource(R.string.disable_personalized_dicts_message)) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
PrefDef(context,
|
||||||
|
Settings.PREF_BIGRAM_PREDICTIONS,
|
||||||
|
R.string.bigram_prediction,
|
||||||
|
R.string.bigram_prediction_summary
|
||||||
|
) {
|
||||||
|
SwitchPreference(it, true) { themeChanged = 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
|
||||||
|
) {
|
||||||
|
SwitchPreference(it, false)
|
||||||
|
},
|
||||||
|
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
|
||||||
|
) {
|
||||||
|
val activity = LocalContext.current.getActivity() ?: return@PrefDef
|
||||||
|
var granted by remember { mutableStateOf(PermissionsUtil.checkAllPermissionsGranted(activity, Manifest.permission.READ_CONTACTS)) }
|
||||||
|
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) {
|
||||||
|
granted = it
|
||||||
|
}
|
||||||
|
SwitchPreference(
|
||||||
|
it,
|
||||||
|
false,
|
||||||
|
allowCheckedChange = {
|
||||||
|
if (it && !granted) {
|
||||||
|
launcher.launch(Manifest.permission.READ_CONTACTS)
|
||||||
|
false
|
||||||
|
} else true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
PrefDef(context,
|
||||||
|
Settings.PREF_ADD_TO_PERSONAL_DICTIONARY,
|
||||||
|
R.string.add_to_personal_dictionary,
|
||||||
|
R.string.add_to_personal_dictionary_summary
|
||||||
|
) {
|
||||||
|
SwitchPreference(it, false)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun PreferencePreview() {
|
private fun PreferencePreview() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue