diff --git a/app/src/main/java/helium314/keyboard/latin/utils/Ktx.kt b/app/src/main/java/helium314/keyboard/latin/utils/Ktx.kt index 2c3171dd4..e3af4f329 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/Ktx.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/Ktx.kt @@ -1,9 +1,15 @@ package helium314.keyboard.latin.utils +import android.app.Activity import android.content.Context import android.content.ContextWrapper import android.content.SharedPreferences +import android.view.View +import android.widget.RelativeLayout import androidx.activity.ComponentActivity +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.commit +import helium314.keyboard.latin.R // generic extension functions @@ -67,4 +73,13 @@ fun Context.getActivity(): ComponentActivity? { return componentActivity } +// todo: should not be necessary after full pref switch to compose +fun Activity.switchTo(fragment: androidx.fragment.app.Fragment) { + (this as AppCompatActivity).supportFragmentManager.commit { + findViewById(R.id.settingsFragmentContainer).visibility = View.VISIBLE + replace(R.id.settingsFragmentContainer, fragment) + addToBackStack(null) + } +} + fun Context.prefs(): SharedPreferences = DeviceProtectedUtils.getSharedPreferences(this) diff --git a/app/src/main/java/helium314/keyboard/settings/Preference.kt b/app/src/main/java/helium314/keyboard/settings/Preference.kt index 77b3495f1..6ea75f1d5 100644 --- a/app/src/main/java/helium314/keyboard/settings/Preference.kt +++ b/app/src/main/java/helium314/keyboard/settings/Preference.kt @@ -31,7 +31,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.Hyphens import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview diff --git a/app/src/main/java/helium314/keyboard/settings/SettingsActivity.kt b/app/src/main/java/helium314/keyboard/settings/SettingsActivity.kt index 6e86c0093..f2d4add07 100644 --- a/app/src/main/java/helium314/keyboard/settings/SettingsActivity.kt +++ b/app/src/main/java/helium314/keyboard/settings/SettingsActivity.kt @@ -15,14 +15,18 @@ import kotlinx.coroutines.flow.MutableStateFlow // todo (roughly in order) // make all prefs actually work +// default buttons for toolbar key(s) customizer, icon customizer, and toolbar reorder dialog +// make a dialog wrapper that has a default button? // try moving the recomposition of pref change somewhere else, so it's not duplicated everywhere // make the pref lists more compact (compare with old settings) // try making text size similar to old state (also in dialogs) // check whether dialogs have the same colors, i think currently it's a bit inconsistent +// check dark and light theme (don't have dynamic) // rename both settingsActivities // work on todos in other files // 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 // performance @@ -40,7 +44,6 @@ import kotlinx.coroutines.flow.MutableStateFlow // merge main to implement all the new settings // consider IME insets when searching // dialogs should be rememberSaveable to survive display orientation change and stuff? -// default buttons for toolbar key(s) customizer and toolbar reorder dialog // try making old fragment back stuff work better, and try the different themes (with and without top bar) // any way to get rid of the "old" background on starting settings? probably comes from app theme, can we avoid it? // consider using simple list picker dialog (but the "full" one is probably better for language settings stuff) diff --git a/app/src/main/java/helium314/keyboard/settings/dialogs/CustomizeIconsDialog.kt b/app/src/main/java/helium314/keyboard/settings/dialogs/CustomizeIconsDialog.kt new file mode 100644 index 000000000..3034e76e6 --- /dev/null +++ b/app/src/main/java/helium314/keyboard/settings/dialogs/CustomizeIconsDialog.kt @@ -0,0 +1,142 @@ +package helium314.keyboard.settings.dialogs + +import android.graphics.drawable.VectorDrawable +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Icon +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.asImageBitmap +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 androidx.compose.ui.unit.dp +import androidx.core.content.ContextCompat +import androidx.core.graphics.drawable.toBitmap +import androidx.core.util.TypedValueCompat +import helium314.keyboard.keyboard.internal.KeyboardIconsSet +import helium314.keyboard.latin.R +import helium314.keyboard.latin.customIconNames +import helium314.keyboard.latin.utils.getStringResourceOrName +import helium314.keyboard.latin.utils.prefs +import helium314.keyboard.settings.screens.GetIcon +import kotlinx.serialization.json.Json + +@Composable +fun CustomizeIconsDialog( + prefKey: String, + onDismissRequest: () -> Unit, +) { + val state = rememberLazyListState() + val ctx = LocalContext.current + val iconsAndNames = KeyboardIconsSet.getAllIcons(ctx).keys.map { iconName -> + val name = iconName.getStringResourceOrName("", ctx) + if (name == iconName) iconName to iconName.getStringResourceOrName("label_", ctx) + else iconName to name + }.sortedBy { it.second } + var showIconDialog: Pair? by remember { mutableStateOf(null) } + val prefs = ctx.prefs() + AlertDialog( + onDismissRequest = onDismissRequest, + confirmButton = { }, // no confirm button + dismissButton = { TextButton(onClick = onDismissRequest) { Text(stringResource(R.string.dialog_close)) } }, + title = { Text(stringResource(R.string.customize_icons)) }, + text = { + LazyColumn(state = state) { + items(iconsAndNames, key = { it.first }) { (iconName, displayName) -> + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.clickable { showIconDialog = iconName to displayName } + ) { + KeyboardIconsSet.instance.GetIcon(iconName) + Text(displayName, Modifier.weight(1f)) + } + } + } + }, + ) + if (showIconDialog != null) { + val iconName = showIconDialog!!.first + val allIcons = KeyboardIconsSet.getAllIcons(ctx) + val iconsForName = allIcons[iconName].orEmpty() + val iconsSet = mutableSetOf() + iconsSet.addAll(iconsForName) + KeyboardIconsSet.getAllIcons(ctx).forEach { iconsSet.addAll(it.value) } // is this called again on UI interaction? + val icons = iconsSet.toList() + var selectedIcon by remember { mutableStateOf(KeyboardIconsSet.instance.iconIds[iconName]) } + AlertDialog( + onDismissRequest = onDismissRequest, + confirmButton = { TextButton( + onClick = { + onDismissRequest() + runCatching { + val newIcons = customIconNames(prefs).toMutableMap() + newIcons[iconName] = selectedIcon?.let { ctx.resources.getResourceEntryName(it) } ?: return@runCatching + prefs.edit().putString(prefKey, Json.encodeToString(newIcons)).apply() + KeyboardIconsSet.instance.loadIcons(ctx) + } + // todo: show outer dialog again and reload icons? + } + ) { Text(stringResource(android.R.string.ok)) } }, + dismissButton = { TextButton(onClick = onDismissRequest) { Text(stringResource(android.R.string.cancel)) } }, + title = { Text(showIconDialog!!.second) }, + text = { + LazyVerticalGrid( + columns = GridCells.Adaptive(minSize = 64.dp) + ) { + items(icons, key = { it }) { resId -> + val drawable = ContextCompat.getDrawable(ctx, resId)?.mutate() ?: return@items + val color = if (resId == selectedIcon) MaterialTheme.colorScheme.primary + else MaterialTheme.colorScheme.onSurface + CompositionLocalProvider( + LocalContentColor provides color + ) { + Box( + Modifier.size(40.dp).clickable { selectedIcon = resId }, + contentAlignment = Alignment.Center + ) { + if (drawable is VectorDrawable) + Icon(painterResource(resId), null, Modifier.fillMaxSize(0.8f)) + else { + val px = TypedValueCompat.dpToPx(40f, ctx.resources.displayMetrics).toInt() + Icon(drawable.toBitmap(px, px).asImageBitmap(), null, Modifier.fillMaxSize(0.8f)) + } + } + } + } + } + }, + ) + } +} + +@Preview +@Composable +private fun Preview() { + KeyboardIconsSet.instance.loadIcons(LocalContext.current) + CustomizeIconsDialog( + prefKey = "", + onDismissRequest = { }, + ) +} diff --git a/app/src/main/java/helium314/keyboard/settings/screens/AppearanceScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/AppearanceScreen.kt index 5c426a0a8..f6dbefe2a 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/AppearanceScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/AppearanceScreen.kt @@ -15,12 +15,15 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import helium314.keyboard.keyboard.KeyboardTheme import helium314.keyboard.latin.R +import helium314.keyboard.latin.settings.ColorsNightSettingsFragment +import helium314.keyboard.latin.settings.ColorsSettingsFragment import helium314.keyboard.latin.settings.Settings import helium314.keyboard.latin.settings.SettingsValues import helium314.keyboard.latin.utils.Log import helium314.keyboard.latin.utils.getActivity import helium314.keyboard.latin.utils.getStringResourceOrName import helium314.keyboard.latin.utils.prefs +import helium314.keyboard.latin.utils.switchTo import helium314.keyboard.settings.AllPrefs import helium314.keyboard.settings.ListPreference import helium314.keyboard.settings.NonSettingsPrefs @@ -29,10 +32,10 @@ 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.CustomizeIconsDialog @Composable fun AppearanceScreen( @@ -43,7 +46,7 @@ fun AppearanceScreen( val b = (LocalContext.current.getActivity() as? SettingsActivity2)?.prefChanged?.collectAsState() if (b?.value ?: 0 < 0) Log.v("irrelevant", "stupid way to trigger recomposition on preference change") - val dayNightMode = Settings.readDayNightPref(prefs, ctx.resources) + val dayNightMode = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && Settings.readDayNightPref(prefs, ctx.resources) val lightTheme = prefs.getString(Settings.PREF_THEME_COLORS, KeyboardTheme.THEME_LIGHT) val darkTheme = prefs.getString(Settings.PREF_THEME_COLORS_NIGHT, KeyboardTheme.THEME_DARK) SearchPrefScreen( @@ -58,7 +61,8 @@ fun AppearanceScreen( if (lightTheme == KeyboardTheme.THEME_USER) SettingsActivity2.allPrefs.map[NonSettingsPrefs.ADJUST_COLORS]!!.Preference() SettingsActivity2.allPrefs.map[Settings.PREF_THEME_KEY_BORDERS]!!.Preference() - SettingsActivity2.allPrefs.map[Settings.PREF_THEME_DAY_NIGHT]!!.Preference() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) + SettingsActivity2.allPrefs.map[Settings.PREF_THEME_DAY_NIGHT]!!.Preference() if (dayNightMode) SettingsActivity2.allPrefs.map[Settings.PREF_THEME_COLORS_NIGHT]!!.Preference() if (dayNightMode && darkTheme == KeyboardTheme.THEME_USER_NIGHT) @@ -108,7 +112,10 @@ fun createAppearancePrefs(context: Context) = listOf( Preference( name = def.title, onClick = { showDialog = true } - ) // todo: create and show the dialog + ) + if (showDialog) { + CustomizeIconsDialog(def.key) { showDialog = false } + } }, PrefDef(context, Settings.PREF_THEME_COLORS, R.string.theme_colors) { def -> val ctx = LocalContext.current @@ -139,17 +146,25 @@ fun createAppearancePrefs(context: Context) = listOf( ) }, PrefDef(context, NonSettingsPrefs.ADJUST_COLORS, R.string.select_user_colors, R.string.select_user_colors_summary) { def -> + val ctx = LocalContext.current Preference( name = def.title, description = def.description, - onClick = { SettingsDestination.navigateTo(SettingsDestination.Colors) } + onClick = { + ctx.getActivity()?.switchTo(ColorsSettingsFragment()) + //SettingsDestination.navigateTo(SettingsDestination.Colors) todo: later + } ) }, PrefDef(context, NonSettingsPrefs.ADJUST_COLORS_NIGHT, R.string.select_user_colors_night, R.string.select_user_colors_summary) { def -> + val ctx = LocalContext.current Preference( name = def.title, description = def.description, - onClick = { SettingsDestination.navigateTo(SettingsDestination.ColorsNight) } + onClick = { + ctx.getActivity()?.switchTo(ColorsNightSettingsFragment()) + //SettingsDestination.navigateTo(SettingsDestination.ColorsNight) todo: later + } ) }, PrefDef(context, Settings.PREF_THEME_KEY_BORDERS, R.string.key_borders) { def -> diff --git a/app/src/main/java/helium314/keyboard/settings/screens/MainSettingsScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/MainSettingsScreen.kt index 6b7c837ba..67dc84dcc 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/MainSettingsScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/MainSettingsScreen.kt @@ -1,10 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only package helium314.keyboard.settings.screens -import android.app.Activity -import android.view.View -import android.widget.RelativeLayout -import androidx.appcompat.app.AppCompatActivity import androidx.compose.material3.Icon import androidx.compose.material3.Surface import androidx.compose.runtime.Composable @@ -14,7 +10,6 @@ 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 androidx.fragment.app.commit import helium314.keyboard.latin.R import helium314.keyboard.latin.settings.AboutFragment import helium314.keyboard.latin.settings.AdvancedSettingsFragment @@ -26,6 +21,7 @@ import helium314.keyboard.latin.settings.PreferencesSettingsFragment import helium314.keyboard.latin.settings.ToolbarSettingsFragment import helium314.keyboard.latin.utils.JniUtils import helium314.keyboard.latin.utils.getActivity +import helium314.keyboard.latin.utils.switchTo import helium314.keyboard.settings.Preference import helium314.keyboard.settings.PreferenceCategory import helium314.keyboard.settings.SearchPrefScreen @@ -159,14 +155,6 @@ fun MainSettingsScreen( } } -fun Activity.switchTo(fragment: androidx.fragment.app.Fragment) { - (this as AppCompatActivity).supportFragmentManager.commit { - findViewById(R.id.settingsFragmentContainer).visibility = View.VISIBLE - replace(R.id.settingsFragmentContainer, fragment) - addToBackStack(null) - } -} - @Preview @Composable private fun PreviewScreen() { diff --git a/app/src/main/java/helium314/keyboard/settings/screens/TextCorrectionScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/TextCorrectionScreen.kt index 788f83dba..253424efe 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/TextCorrectionScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/TextCorrectionScreen.kt @@ -26,6 +26,7 @@ import helium314.keyboard.latin.settings.UserDictionaryListFragment import helium314.keyboard.latin.utils.Log import helium314.keyboard.latin.utils.getActivity import helium314.keyboard.latin.utils.prefs +import helium314.keyboard.latin.utils.switchTo import helium314.keyboard.settings.AllPrefs import helium314.keyboard.settings.ListPreference import helium314.keyboard.settings.NonSettingsPrefs