Skip to content

Commit

Permalink
add customize icons dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
Helium314 committed Feb 1, 2025
1 parent e016d13 commit 315ac3b
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 21 deletions.
15 changes: 15 additions & 0 deletions app/src/main/java/helium314/keyboard/latin/utils/Ktx.kt
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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<RelativeLayout>(R.id.settingsFragmentContainer).visibility = View.VISIBLE
replace(R.id.settingsFragmentContainer, fragment)
addToBackStack(null)
}
}

fun Context.prefs(): SharedPreferences = DeviceProtectedUtils.getSharedPreferences(this)
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String, String>? 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<Int>()
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 = { },
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(
Expand All @@ -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(
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 ->
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -159,14 +155,6 @@ fun MainSettingsScreen(
}
}

fun Activity.switchTo(fragment: androidx.fragment.app.Fragment) {
(this as AppCompatActivity).supportFragmentManager.commit {
findViewById<RelativeLayout>(R.id.settingsFragmentContainer).visibility = View.VISIBLE
replace(R.id.settingsFragmentContainer, fragment)
addToBackStack(null)
}
}

@Preview
@Composable
private fun PreviewScreen() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 315ac3b

Please sign in to comment.