diff --git a/app/src/main/java/helium314/keyboard/latin/common/Colors.kt b/app/src/main/java/helium314/keyboard/latin/common/Colors.kt index 0f8f45a9c..4306eefee 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/Colors.kt +++ b/app/src/main/java/helium314/keyboard/latin/common/Colors.kt @@ -43,7 +43,7 @@ interface Colors { /** use to check whether colors have changed, for colors (in)directly derived from context, * e.g. night mode or potentially changing system colors */ - fun haveColorsChanged(context: Context): Boolean + fun haveColorsChanged(context: Context): Boolean = false /** get the colorInt */ @ColorInt fun get(color: ColorType): Int @@ -58,7 +58,27 @@ interface Colors { fun setBackground(view: View, color: ColorType) /** returns a colored drawable selected from [attr], which must contain using R.styleable.KeyboardView_* */ - fun selectAndColorDrawable(attr: TypedArray, color: ColorType): Drawable + fun selectAndColorDrawable(attr: TypedArray, color: ColorType): Drawable { + val drawable = when (color) { + KEY_BACKGROUND, BACKGROUND, ACTION_KEY_MORE_KEYS_BACKGROUND, MORE_KEYS_BACKGROUND -> + attr.getDrawable(R.styleable.KeyboardView_keyBackground) + FUNCTIONAL_KEY_BACKGROUND -> attr.getDrawable(R.styleable.KeyboardView_functionalKeyBackground) + SPACE_BAR_BACKGROUND -> { + if (hasKeyBorders) attr.getDrawable(R.styleable.KeyboardView_spacebarBackground) + else attr.getDrawable(R.styleable.KeyboardView_spacebarNoBorderBackground) + } + ACTION_KEY_BACKGROUND -> { + if (themeStyle == STYLE_HOLO && hasKeyBorders) // no borders has a very small pressed drawable otherwise + attr.getDrawable(R.styleable.KeyboardView_functionalKeyBackground) + else + attr.getDrawable(R.styleable.KeyboardView_keyBackground) + } + else -> null // keyBackground + }?.mutate() ?: attr.getDrawable(R.styleable.KeyboardView_keyBackground)?.mutate()!! // keyBackground always exists + + setColor(drawable, color) + return drawable + } } @RequiresApi(Build.VERSION_CODES.S) @@ -306,28 +326,6 @@ class DynamicColors(context: Context, override val themeStyle: String, override else -> colorFilter(get(color)) } - override fun selectAndColorDrawable(attr: TypedArray, color: ColorType): Drawable { - val drawable = when (color) { - KEY_BACKGROUND, BACKGROUND, ACTION_KEY_MORE_KEYS_BACKGROUND, MORE_KEYS_BACKGROUND -> - attr.getDrawable(R.styleable.KeyboardView_keyBackground) - FUNCTIONAL_KEY_BACKGROUND -> attr.getDrawable(R.styleable.KeyboardView_functionalKeyBackground) - SPACE_BAR_BACKGROUND -> { - if (hasKeyBorders) attr.getDrawable(R.styleable.KeyboardView_spacebarBackground) - else attr.getDrawable(R.styleable.KeyboardView_spacebarNoBorderBackground) - } - ACTION_KEY_BACKGROUND -> { - if (themeStyle == STYLE_HOLO && hasKeyBorders) // no borders has a very small pressed drawable otherwise - attr.getDrawable(R.styleable.KeyboardView_functionalKeyBackground) - else - attr.getDrawable(R.styleable.KeyboardView_keyBackground) - } - else -> null // keyBackground - }?.mutate() ?: attr.getDrawable(R.styleable.KeyboardView_keyBackground)?.mutate()!! // keyBackground always exists - - setColor(drawable, color) - return drawable - } - override fun setBackground(view: View, color: ColorType) { if (view.background == null) view.setBackgroundColor(Color.WHITE) // set white to make the color filters work @@ -398,8 +396,6 @@ class DefaultColors ( private val toolbarKeyStateList = activatedStateList(suggestionText, darken(darken(suggestionText))) private var backgroundSetupDone = false - override fun haveColorsChanged(context: Context) = false - init { if (themeStyle == STYLE_HOLO && keyboardBackground == null) { val darkerBackground = adjustLuminosityAndKeepAlpha(background, -0.2f) @@ -539,28 +535,6 @@ class DefaultColors ( ACTION_KEY_ICON -> actionKeyIconColorFilter else -> colorFilter(get(color)) // create color filter (not great for performance, so the frequently used filters should be stored) } - - override fun selectAndColorDrawable(attr: TypedArray, color: ColorType): Drawable { - val drawable = when (color) { - KEY_BACKGROUND, BACKGROUND, ACTION_KEY_MORE_KEYS_BACKGROUND, MORE_KEYS_BACKGROUND -> - attr.getDrawable(R.styleable.KeyboardView_keyBackground) - FUNCTIONAL_KEY_BACKGROUND -> attr.getDrawable(R.styleable.KeyboardView_functionalKeyBackground) - SPACE_BAR_BACKGROUND -> { - if (hasKeyBorders) attr.getDrawable(R.styleable.KeyboardView_spacebarBackground) - else attr.getDrawable(R.styleable.KeyboardView_spacebarNoBorderBackground) - } - ACTION_KEY_BACKGROUND -> { - if (themeStyle == STYLE_HOLO && hasKeyBorders) // no borders has a very small pressed drawable otherwise - attr.getDrawable(R.styleable.KeyboardView_functionalKeyBackground) - else - attr.getDrawable(R.styleable.KeyboardView_keyBackground) - } - else -> null // keyBackground - }?.mutate() ?: attr.getDrawable(R.styleable.KeyboardView_keyBackground)?.mutate()!! // keyBackground always exists - - setColor(drawable, color) - return drawable - } } private fun colorFilter(color: Int, mode: BlendModeCompat = BlendModeCompat.MODULATE): ColorFilter { diff --git a/app/src/main/java/helium314/keyboard/latin/settings/ColorsSettingsFragment.kt b/app/src/main/java/helium314/keyboard/latin/settings/ColorsSettingsFragment.kt index 0abb808a2..b4840e86a 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/ColorsSettingsFragment.kt +++ b/app/src/main/java/helium314/keyboard/latin/settings/ColorsSettingsFragment.kt @@ -1,5 +1,4 @@ // SPDX-License-Identifier: GPL-3.0-only - package helium314.keyboard.latin.settings import android.content.res.Configuration @@ -37,18 +36,22 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi get() = prefs.getBoolean(Settings.PREF_SHOW_ALL_COLORS, false) set(value) { prefs.edit().putBoolean(Settings.PREF_SHOW_ALL_COLORS, value).apply() } private val prefs by lazy { DeviceProtectedUtils.getSharedPreferences(requireContext()) } - private val colorPrefs = listOf( - Settings.PREF_COLOR_BACKGROUND_SUFFIX, - Settings.PREF_COLOR_KEYS_SUFFIX, - Settings.PREF_COLOR_FUNCTIONAL_KEYS_SUFFIX, - Settings.PREF_COLOR_SPACEBAR_SUFFIX, - Settings.PREF_COLOR_TEXT_SUFFIX, - Settings.PREF_COLOR_HINT_TEXT_SUFFIX, - Settings.PREF_COLOR_SUGGESTION_TEXT_SUFFIX, - Settings.PREF_COLOR_SPACEBAR_TEXT_SUFFIX, - Settings.PREF_COLOR_ACCENT_SUFFIX, - Settings.PREF_COLOR_GESTURE_SUFFIX, - ) + + private val colorPrefsAndNames by lazy { + listOf( + Settings.PREF_COLOR_BACKGROUND_SUFFIX to R.string.select_color_background, + Settings.PREF_COLOR_KEYS_SUFFIX to R.string.select_color_key_background, + Settings.PREF_COLOR_FUNCTIONAL_KEYS_SUFFIX to R.string.select_color_functional_key_background, + Settings.PREF_COLOR_SPACEBAR_SUFFIX to R.string.select_color_spacebar_background, + Settings.PREF_COLOR_TEXT_SUFFIX to R.string.select_color_key, + Settings.PREF_COLOR_HINT_TEXT_SUFFIX to R.string.select_color_key_hint, + Settings.PREF_COLOR_SUGGESTION_TEXT_SUFFIX to R.string.select_color_suggestion, + Settings.PREF_COLOR_SPACEBAR_TEXT_SUFFIX to R.string.select_color_spacebar_text, + Settings.PREF_COLOR_ACCENT_SUFFIX to R.string.select_color_accent, + Settings.PREF_COLOR_GESTURE_SUFFIX to R.string.select_color_gesture, + ).map { it.first to requireContext().getString(it.second) } + } + private val colorPrefsToHideInitially by lazy { listOf(Settings.PREF_COLOR_SUGGESTION_TEXT_SUFFIX,Settings.PREF_COLOR_SPACEBAR_TEXT_SUFFIX, Settings.PREF_COLOR_GESTURE_SUFFIX) + if (prefs.getBoolean(Settings.PREF_THEME_KEY_BORDERS, false)) listOf(Settings.PREF_COLOR_SPACEBAR_SUFFIX) @@ -57,22 +60,22 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi override fun onResume() { super.onResume() + if (isNight != ResourceUtils.isNight(requireContext().resources)) { + // reload to get the right configuration + forceOppositeTheme = true + reloadKeyboard(false) + } val activity = activity if (activity is AppCompatActivity) { val actionBar = activity.supportActionBar ?: return actionBar.setTitle(titleResId) } - if (isNight != ResourceUtils.isNight(requireContext().resources)) { - // reload to get the right configuration - prefs.edit { putBoolean(Settings.PREF_FORCE_OPPOSITE_THEME, true) } - reloadKeyboard(false) - } activity?.addMenuProvider(this) } override fun onPause() { super.onPause() - prefs.edit { putBoolean(Settings.PREF_FORCE_OPPOSITE_THEME, false) } + forceOppositeTheme = false if (isNight != ResourceUtils.isNight(requireContext().resources)) // reload again so the correct configuration is applied KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext()) @@ -105,28 +108,16 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi private fun updateColorPrefs() { binding.colorSettingsContainer.removeAllViews() - val colorPrefNames = listOf( - R.string.select_color_background, - R.string.select_color_key_background, - R.string.select_color_functional_key_background, - R.string.select_color_spacebar_background, - R.string.select_color_key, - R.string.select_color_key_hint, - R.string.select_color_suggestion, - R.string.select_color_spacebar_text, - R.string.select_color_accent, - R.string.select_color_gesture, - ).map { requireContext().getString(it) } val prefPrefix = if (isNight) Settings.PREF_THEME_USER_COLOR_NIGHT_PREFIX else Settings.PREF_THEME_USER_COLOR_PREFIX - colorPrefs.forEachIndexed { index, colorPref -> + colorPrefsAndNames.forEachIndexed { index, (colorPref, colorPrefName) -> val autoColor = prefs.getBoolean(prefPrefix + colorPref + Settings.PREF_AUTO_USER_COLOR_SUFFIX, true) if (!moreColors && colorPref in colorPrefsToHideInitially && autoColor) return@forEachIndexed val csb = ColorSettingBinding.inflate(layoutInflater, binding.colorSettingsContainer, true) csb.root.tag = index csb.colorSwitch.isChecked = !autoColor - csb.colorPreview.setColorFilter(Settings.readUserColor(prefs, requireContext(), colorPrefs[index], isNight)) - csb.colorText.text = colorPrefNames[index] + csb.colorPreview.setColorFilter(Settings.readUserColor(prefs, requireContext(), colorPref, isNight)) + csb.colorText.text = colorPrefName if (!csb.colorSwitch.isChecked) { csb.colorSummary.setText(R.string.auto_user_color) } @@ -142,14 +133,14 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi val clickListener = View.OnClickListener { val hidden = RichInputMethodManager.getInstance().inputMethodManager.hideSoftInputFromWindow(binding.dummyText.windowToken, 0) - val initialColor = Settings.readUserColor(prefs, requireContext(), colorPrefs[index], isNight) + val initialColor = Settings.readUserColor(prefs, requireContext(), colorPref, isNight) val picker = ColorPickerView(requireContext()) picker.showAlpha(colorPref != Settings.PREF_COLOR_BACKGROUND_SUFFIX) // background behind background looks broken and sometimes is dark, sometimes light picker.showHex(true) picker.showPreview(true) picker.color = initialColor picker.addColorObserver { observer -> - prefs.edit { putInt(prefPrefix + colorPrefs[index], observer.color) } + prefs.edit { putInt(prefPrefix + colorPref, observer.color) } if (!csb.colorSwitch.isChecked) { prefs.edit { putBoolean(prefPrefix + colorPref + Settings.PREF_AUTO_USER_COLOR_SUFFIX, false) } csb.colorSwitch.setOnCheckedChangeListener(null) @@ -163,7 +154,7 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi } val builder = AlertDialog.Builder(requireContext()) builder - .setTitle(colorPrefNames[index]) + .setTitle(colorPrefName) .setView(picker) .setNegativeButton(android.R.string.cancel) { _, _ -> // If the slider is disabled, we simply want to close the dialog when no color is selected. @@ -183,7 +174,7 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi // Reset the color and the color picker to their initial state builder.setNeutralButton(R.string.button_default) { _, _ -> csb.colorSwitch.isChecked = false - val resetColor = Settings.readUserColor(prefs, requireContext(), colorPrefs[index], isNight) + val resetColor = Settings.readUserColor(prefs, requireContext(), colorPref, isNight) picker.color = resetColor csb.colorSwitch.toggle() } @@ -207,23 +198,12 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi private fun updateColorPreviews() { binding.colorSettingsContainer.forEach { view -> val index = view.tag as Int - val color = Settings.readUserColor(prefs, requireContext(), colorPrefs[index], isNight) + val color = Settings.readUserColor(prefs, requireContext(), colorPrefsAndNames[index].first, isNight) view.findViewById(R.id.color_preview)?.setColorFilter(color) } } private fun reloadKeyboard(show: Boolean) { - // todo: any way to make some kind of "light update" to keyboard? - // only reloading main keyboard view is necessary... - // or get an actual (live) preview instead of the full keyboard? - // or accelerate keyboard inflate, a big here issue is emojiCategory creating many keyboards -// KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext()) -// if (!show) return -// Thread.sleep(100) // some pause is necessary to avoid visual glitches -// RichInputMethodManager.getInstance().inputMethodManager.showSoftInput(binding.dummyText, 0) -// return - - // todo: fix slowdowns and sometimes showing glitches with above, then move away from executor ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute { KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext()) if (!show) return@execute @@ -234,6 +214,9 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi } } + companion object { + var forceOppositeTheme = false + } } class ColorsNightSettingsFragment : ColorsSettingsFragment() { diff --git a/app/src/main/java/helium314/keyboard/latin/settings/Settings.java b/app/src/main/java/helium314/keyboard/latin/settings/Settings.java index 957928d52..315987a27 100644 --- a/app/src/main/java/helium314/keyboard/latin/settings/Settings.java +++ b/app/src/main/java/helium314/keyboard/latin/settings/Settings.java @@ -153,8 +153,6 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public static final String PREF_PINNED_CLIPS = "pinned_clips"; public static final String PREF_VERSION_CODE = "version_code"; - // used as a workaround against keyboard not showing edited theme in ColorsSettingsFragment - public static final String PREF_FORCE_OPPOSITE_THEME = "force_opposite_theme"; public static final String PREF_SHOW_ALL_COLORS = "show_all_colors"; public static final String PREF_LIBRARY_CHECKSUM = "lib_checksum"; @@ -174,7 +172,6 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang // preferences that are not used in SettingsValues and thus should not trigger reload when changed private static final HashSet dontReloadOnChanged = new HashSet<>() {{ - add(PREF_FORCE_OPPOSITE_THEME); add(PREF_PINNED_CLIPS); add(PREF_LAST_SHOWN_EMOJI_CATEGORY_PAGE_ID); add(PREF_LAST_SHOWN_EMOJI_CATEGORY_ID); @@ -594,7 +591,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public static Colors getColorsForCurrentTheme(final Context context, final SharedPreferences prefs) { boolean isNight = ResourceUtils.isNight(context.getResources()); - if (prefs.getBoolean(PREF_FORCE_OPPOSITE_THEME, false)) isNight = !isNight; + if (ColorsSettingsFragment.Companion.getForceOppositeTheme()) isNight = !isNight; final String themeColors = (isNight && readDayNightPref(prefs, context.getResources())) ? prefs.getString(Settings.PREF_THEME_COLORS_NIGHT, KeyboardTheme.THEME_DARKER) : prefs.getString(Settings.PREF_THEME_COLORS, KeyboardTheme.THEME_LIGHT);