2019-12-31 18:19:35 +01:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2013 The Android Open Source Project
|
2023-10-17 13:44:01 +02:00
|
|
|
* modified
|
|
|
|
* SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
|
2019-12-31 18:19:35 +01:00
|
|
|
*/
|
|
|
|
|
2024-01-31 18:32:43 +01:00
|
|
|
package helium314.keyboard.latin.settings;
|
2019-12-31 18:19:35 +01:00
|
|
|
|
2022-02-20 16:14:12 +01:00
|
|
|
import android.annotation.SuppressLint;
|
2019-12-31 18:19:35 +01:00
|
|
|
import android.content.Context;
|
|
|
|
import android.content.SharedPreferences;
|
|
|
|
import android.content.pm.ApplicationInfo;
|
|
|
|
import android.content.res.Configuration;
|
|
|
|
import android.content.res.Resources;
|
2024-01-26 16:42:35 +01:00
|
|
|
import android.graphics.BitmapFactory;
|
2023-09-12 14:21:40 +02:00
|
|
|
import android.graphics.Color;
|
2025-01-17 21:47:13 +01:00
|
|
|
import android.graphics.Typeface;
|
2024-01-26 16:42:35 +01:00
|
|
|
import android.graphics.drawable.BitmapDrawable;
|
|
|
|
import android.graphics.drawable.Drawable;
|
2019-12-31 18:19:35 +01:00
|
|
|
import android.os.Build;
|
2023-09-12 14:21:40 +02:00
|
|
|
import android.util.TypedValue;
|
|
|
|
import android.view.ContextThemeWrapper;
|
2022-02-20 16:14:12 +01:00
|
|
|
import android.view.Gravity;
|
2023-07-30 08:34:29 +02:00
|
|
|
|
2023-09-01 08:08:36 +02:00
|
|
|
import androidx.annotation.NonNull;
|
2024-01-26 16:42:35 +01:00
|
|
|
import androidx.annotation.Nullable;
|
2024-05-18 10:30:46 +02:00
|
|
|
import androidx.annotation.StringRes;
|
2023-09-12 14:21:40 +02:00
|
|
|
import androidx.core.content.ContextCompat;
|
2024-02-13 08:23:07 +01:00
|
|
|
import androidx.preference.PreferenceManager;
|
2023-09-01 08:08:36 +02:00
|
|
|
|
2024-03-12 01:42:25 +04:00
|
|
|
import helium314.keyboard.keyboard.KeyboardActionListener;
|
2024-01-31 18:32:43 +01:00
|
|
|
import helium314.keyboard.keyboard.KeyboardTheme;
|
2024-02-14 11:08:44 +01:00
|
|
|
import helium314.keyboard.keyboard.internal.keyboard_parser.LocaleKeyboardInfosKt;
|
2024-01-31 18:32:43 +01:00
|
|
|
import helium314.keyboard.latin.AudioAndHapticFeedbackManager;
|
|
|
|
import helium314.keyboard.latin.InputAttributes;
|
|
|
|
import helium314.keyboard.latin.R;
|
|
|
|
import helium314.keyboard.latin.common.Colors;
|
|
|
|
import helium314.keyboard.latin.common.LocaleUtils;
|
|
|
|
import helium314.keyboard.latin.utils.AdditionalSubtypeUtils;
|
|
|
|
import helium314.keyboard.latin.utils.ColorUtilKt;
|
|
|
|
import helium314.keyboard.latin.utils.DeviceProtectedUtils;
|
|
|
|
import helium314.keyboard.latin.utils.JniUtils;
|
|
|
|
import helium314.keyboard.latin.utils.Log;
|
|
|
|
import helium314.keyboard.latin.utils.ResourceUtils;
|
|
|
|
import helium314.keyboard.latin.utils.RunInLocaleKt;
|
|
|
|
import helium314.keyboard.latin.utils.StatsUtils;
|
|
|
|
import helium314.keyboard.latin.utils.SubtypeSettingsKt;
|
2024-09-23 20:45:23 +02:00
|
|
|
import helium314.keyboard.latin.utils.ToolbarKey;
|
|
|
|
import helium314.keyboard.latin.utils.ToolbarUtilsKt;
|
2019-12-31 18:19:35 +01:00
|
|
|
|
2024-01-04 18:59:28 +01:00
|
|
|
import java.io.File;
|
2023-08-11 00:58:33 +02:00
|
|
|
import java.util.ArrayList;
|
2025-01-17 20:10:16 +01:00
|
|
|
import java.util.Arrays;
|
2023-11-04 13:38:24 +01:00
|
|
|
import java.util.HashSet;
|
2023-08-11 00:58:33 +02:00
|
|
|
import java.util.List;
|
2019-12-31 18:19:35 +01:00
|
|
|
import java.util.Locale;
|
2024-09-23 20:45:23 +02:00
|
|
|
import java.util.Map;
|
2019-12-31 18:19:35 +01:00
|
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
|
|
|
|
|
|
public final class Settings implements SharedPreferences.OnSharedPreferenceChangeListener {
|
|
|
|
private static final String TAG = Settings.class.getSimpleName();
|
|
|
|
// Settings screens
|
|
|
|
public static final String SCREEN_DEBUG = "screen_debug";
|
|
|
|
public static final String SCREEN_GESTURE = "screen_gesture";
|
2024-01-28 13:55:11 +01:00
|
|
|
|
2024-01-28 14:23:38 +01:00
|
|
|
// theme-related stuff
|
2023-09-01 00:35:40 +02:00
|
|
|
public static final String PREF_THEME_STYLE = "theme_style";
|
2024-08-25 18:46:29 +02:00
|
|
|
public static final String PREF_ICON_STYLE = "icon_style";
|
2024-01-28 14:23:38 +01:00
|
|
|
public static final String PREF_THEME_COLORS = "theme_colors";
|
|
|
|
public static final String PREF_THEME_COLORS_NIGHT = "theme_colors_night";
|
2022-01-29 15:58:04 +01:00
|
|
|
public static final String PREF_THEME_KEY_BORDERS = "theme_key_borders";
|
|
|
|
public static final String PREF_THEME_DAY_NIGHT = "theme_auto_day_night";
|
2023-09-12 14:21:40 +02:00
|
|
|
public static final String PREF_THEME_USER_COLOR_PREFIX = "theme_color_";
|
|
|
|
public static final String PREF_THEME_USER_COLOR_NIGHT_PREFIX = "theme_dark_color_";
|
|
|
|
public static final String PREF_COLOR_KEYS_SUFFIX = "keys";
|
2023-10-23 23:55:19 +02:00
|
|
|
public static final String PREF_COLOR_FUNCTIONAL_KEYS_SUFFIX = "functional_keys";
|
|
|
|
public static final String PREF_COLOR_SPACEBAR_SUFFIX = "spacebar";
|
|
|
|
public static final String PREF_COLOR_SPACEBAR_TEXT_SUFFIX = "spacebar_text";
|
2023-09-12 14:21:40 +02:00
|
|
|
public static final String PREF_COLOR_ACCENT_SUFFIX = "accent";
|
2023-11-17 07:50:58 +01:00
|
|
|
public static final String PREF_COLOR_GESTURE_SUFFIX = "gesture";
|
2023-09-12 14:21:40 +02:00
|
|
|
public static final String PREF_COLOR_TEXT_SUFFIX = "text";
|
2023-12-31 17:05:57 +01:00
|
|
|
public static final String PREF_COLOR_SUGGESTION_TEXT_SUFFIX = "suggestion_text";
|
2023-09-12 14:21:40 +02:00
|
|
|
public static final String PREF_COLOR_HINT_TEXT_SUFFIX = "hint_text";
|
|
|
|
public static final String PREF_COLOR_BACKGROUND_SUFFIX = "background";
|
|
|
|
public static final String PREF_AUTO_USER_COLOR_SUFFIX = "_auto";
|
2024-05-18 20:27:22 +02:00
|
|
|
public static final String PREF_ALL_COLORS_SUFFIX = "all_colors";
|
2024-09-23 20:45:23 +02:00
|
|
|
public static final String PREF_CUSTOM_ICON_NAMES = "custom_icon_names";
|
|
|
|
public static final String PREF_TOOLBAR_CUSTOM_KEY_CODES = "toolbar_custom_key_codes";
|
|
|
|
public static final String PREF_TOOLBAR_CUSTOM_LONGPRESS_CODES = "toolbar_custom_longpress_codes";
|
2024-01-28 14:23:38 +01:00
|
|
|
|
|
|
|
public static final String PREF_AUTO_CAP = "auto_cap";
|
|
|
|
public static final String PREF_VIBRATE_ON = "vibrate_on";
|
2025-01-12 20:28:23 +01:00
|
|
|
public static final String PREF_VIBRATE_IN_DND_MODE = "vibrate_in_dnd_mode";
|
2024-01-28 14:23:38 +01:00
|
|
|
public static final String PREF_SOUND_ON = "sound_on";
|
|
|
|
public static final String PREF_POPUP_ON = "popup_on";
|
|
|
|
public static final String PREF_AUTO_CORRECTION = "auto_correction";
|
|
|
|
public static final String PREF_MORE_AUTO_CORRECTION = "more_auto_correction";
|
|
|
|
public static final String PREF_AUTO_CORRECTION_CONFIDENCE = "auto_correction_confidence";
|
2025-01-14 22:19:44 +01:00
|
|
|
public static final String PREF_AUTOCORRECT_SHORTCUTS = "autocorrect_shortcuts";
|
2024-05-01 00:33:57 -04:00
|
|
|
public static final String PREF_CENTER_SUGGESTION_TEXT_TO_ENTER = "center_suggestion_text_to_enter";
|
2019-12-31 18:19:35 +01:00
|
|
|
public static final String PREF_SHOW_SUGGESTIONS = "show_suggestions";
|
2024-01-28 14:23:38 +01:00
|
|
|
public static final String PREF_ALWAYS_SHOW_SUGGESTIONS = "always_show_suggestions";
|
|
|
|
public static final String PREF_KEY_USE_PERSONALIZED_DICTS = "use_personalized_dicts";
|
|
|
|
public static final String PREF_KEY_USE_DOUBLE_SPACE_PERIOD = "use_double_space_period";
|
|
|
|
public static final String PREF_BLOCK_POTENTIALLY_OFFENSIVE = "block_potentially_offensive";
|
2024-06-01 22:27:41 +02:00
|
|
|
public static final String PREF_SHOW_LANGUAGE_SWITCH_KEY = "show_language_switch_key";
|
2024-01-28 14:23:38 +01:00
|
|
|
public static final String PREF_LANGUAGE_SWITCH_KEY = "language_switch_key";
|
|
|
|
public static final String PREF_SHOW_EMOJI_KEY = "show_emoji_key";
|
2024-03-27 07:04:59 +02:00
|
|
|
public static final String PREF_VARIABLE_TOOLBAR_DIRECTION = "var_toolbar_direction";
|
2024-01-28 14:23:38 +01:00
|
|
|
public static final String PREF_ADDITIONAL_SUBTYPES = "additional_subtypes";
|
|
|
|
public static final String PREF_ENABLE_SPLIT_KEYBOARD = "split_keyboard";
|
|
|
|
public static final String PREF_SPLIT_SPACER_SCALE = "split_spacer_scale";
|
|
|
|
public static final String PREF_KEYBOARD_HEIGHT_SCALE = "keyboard_height_scale";
|
|
|
|
public static final String PREF_BOTTOM_PADDING_SCALE = "bottom_padding_scale";
|
2024-03-12 01:42:25 +04:00
|
|
|
public static final String PREF_SPACE_HORIZONTAL_SWIPE = "horizontal_space_swipe";
|
|
|
|
public static final String PREF_SPACE_VERTICAL_SWIPE = "vertical_space_swipe";
|
2024-01-28 14:23:38 +01:00
|
|
|
public static final String PREF_DELETE_SWIPE = "delete_swipe";
|
|
|
|
public static final String PREF_AUTOSPACE_AFTER_PUNCTUATION = "autospace_after_punctuation";
|
|
|
|
public static final String PREF_ALWAYS_INCOGNITO_MODE = "always_incognito_mode";
|
2019-12-31 18:19:35 +01:00
|
|
|
public static final String PREF_BIGRAM_PREDICTIONS = "next_word_prediction";
|
2024-07-06 00:14:54 +03:00
|
|
|
public static final String PREF_SUGGEST_CLIPBOARD_CONTENT = "suggest_clipboard_content";
|
2019-12-31 18:19:35 +01:00
|
|
|
public static final String PREF_GESTURE_INPUT = "gesture_input";
|
2024-01-28 14:23:38 +01:00
|
|
|
public static final String PREF_VIBRATION_DURATION_SETTINGS = "vibration_duration_settings";
|
|
|
|
public static final String PREF_KEYPRESS_SOUND_VOLUME = "keypress_sound_volume";
|
|
|
|
public static final String PREF_KEY_LONGPRESS_TIMEOUT = "key_longpress_timeout";
|
|
|
|
public static final String PREF_ENABLE_EMOJI_ALT_PHYSICAL_KEY = "enable_emoji_alt_physical_key";
|
|
|
|
public static final String PREF_GESTURE_PREVIEW_TRAIL = "gesture_preview_trail";
|
|
|
|
public static final String PREF_GESTURE_FLOATING_PREVIEW_TEXT = "gesture_floating_preview_text";
|
2024-07-24 23:08:50 -06:00
|
|
|
public static final String PREF_GESTURE_FLOATING_PREVIEW_DYNAMIC = "gesture_floating_preview_dynamic";
|
|
|
|
public static final String PREF_GESTURE_DYNAMIC_PREVIEW_FOLLOW_SYSTEM = "gesture_dynamic_preview_follow_system";
|
2024-01-28 14:23:38 +01:00
|
|
|
public static final String PREF_GESTURE_SPACE_AWARE = "gesture_space_aware";
|
2024-06-26 13:00:06 -06:00
|
|
|
public static final String PREF_GESTURE_FAST_TYPING_COOLDOWN = "gesture_fast_typing_cooldown";
|
2024-07-24 23:08:50 -06:00
|
|
|
public static final String PREF_GESTURE_TRAIL_FADEOUT_DURATION = "gesture_trail_fadeout_duration";
|
2024-01-28 14:23:38 +01:00
|
|
|
public static final String PREF_SHOW_SETUP_WIZARD_ICON = "show_setup_wizard_icon";
|
2024-02-01 08:51:17 +01:00
|
|
|
public static final String PREF_USE_CONTACTS = "use_contacts";
|
2024-04-07 10:03:08 +02:00
|
|
|
public static final String PREFS_LONG_PRESS_SYMBOLS_FOR_NUMPAD = "long_press_symbols_for_numpad";
|
2024-01-28 14:23:38 +01:00
|
|
|
|
|
|
|
// one-handed mode gravity, enablement and scale, stored separately per orientation
|
|
|
|
public static final String PREF_ONE_HANDED_MODE_PREFIX = "one_handed_mode_enabled_p_";
|
|
|
|
public static final String PREF_ONE_HANDED_GRAVITY_PREFIX = "one_handed_mode_gravity_p_";
|
|
|
|
public static final String PREF_ONE_HANDED_SCALE_PREFIX = "one_handed_mode_scale_p_";
|
|
|
|
|
|
|
|
public static final String PREF_SHOW_NUMBER_ROW = "show_number_row";
|
|
|
|
public static final String PREF_LOCALIZED_NUMBER_ROW = "localized_number_row";
|
2024-06-29 20:34:32 +02:00
|
|
|
public static final String PREF_CUSTOM_CURRENCY_KEY = "custom_currency_key";
|
2024-01-28 14:23:38 +01:00
|
|
|
|
|
|
|
public static final String PREF_SHOW_HINTS = "show_hints";
|
2024-01-31 16:54:31 +01:00
|
|
|
public static final String PREF_POPUP_KEYS_ORDER = "popup_keys_order";
|
|
|
|
public static final String PREF_POPUP_KEYS_LABELS_ORDER = "popup_keys_labels_order";
|
2024-01-28 14:23:38 +01:00
|
|
|
public static final String PREF_SHOW_POPUP_HINTS = "show_popup_hints";
|
2024-01-31 16:54:31 +01:00
|
|
|
public static final String PREF_MORE_POPUP_KEYS = "more_popup_keys";
|
2021-04-29 14:58:59 -04:00
|
|
|
|
2021-10-24 17:17:48 +05:30
|
|
|
public static final String PREF_SPACE_TO_CHANGE_LANG = "prefs_long_press_keyboard_to_change_lang";
|
2024-01-28 14:23:38 +01:00
|
|
|
|
|
|
|
public static final String PREF_ENABLE_CLIPBOARD_HISTORY = "enable_clipboard_history";
|
|
|
|
public static final String PREF_CLIPBOARD_HISTORY_RETENTION_TIME = "clipboard_history_retention_time";
|
|
|
|
|
|
|
|
public static final String PREF_SECONDARY_LOCALES_PREFIX = "secondary_locales_";
|
|
|
|
public static final String PREF_ADD_TO_PERSONAL_DICTIONARY = "add_to_personal_dictionary";
|
|
|
|
public static final String PREF_NAVBAR_COLOR = "navbar_color";
|
|
|
|
public static final String PREF_NARROW_KEY_GAPS = "narrow_key_gaps";
|
2024-03-06 22:07:38 +01:00
|
|
|
public static final String PREF_ENABLED_SUBTYPES = "enabled_subtypes";
|
|
|
|
public static final String PREF_SELECTED_SUBTYPE = "selected_subtype";
|
2024-01-28 14:23:38 +01:00
|
|
|
public static final String PREF_USE_SYSTEM_LOCALES = "use_system_locales";
|
|
|
|
public static final String PREF_URL_DETECTION = "url_detection";
|
|
|
|
public static final String PREF_DONT_SHOW_MISSING_DICTIONARY_DIALOG = "dont_show_missing_dict_dialog";
|
2024-05-27 20:34:26 +02:00
|
|
|
public static final String PREF_QUICK_PIN_TOOLBAR_KEYS = "quick_pin_toolbar_keys";
|
2024-01-28 14:23:38 +01:00
|
|
|
public static final String PREF_PINNED_TOOLBAR_KEYS = "pinned_toolbar_keys";
|
|
|
|
public static final String PREF_TOOLBAR_KEYS = "toolbar_keys";
|
2024-06-01 15:32:12 +03:00
|
|
|
public static final String PREF_AUTO_SHOW_TOOLBAR = "auto_show_toolbar";
|
|
|
|
public static final String PREF_AUTO_HIDE_TOOLBAR = "auto_hide_toolbar";
|
2024-05-01 23:41:11 +02:00
|
|
|
public static final String PREF_CLIPBOARD_TOOLBAR_KEYS = "clipboard_toolbar_keys";
|
2024-07-10 17:23:10 +02:00
|
|
|
public static final String PREF_ABC_AFTER_EMOJI = "abc_after_emoji";
|
|
|
|
public static final String PREF_ABC_AFTER_CLIP = "abc_after_clip";
|
|
|
|
public static final String PREF_ABC_AFTER_SYMBOL_SPACE = "abc_after_symbol_space";
|
2024-07-13 09:13:14 +02:00
|
|
|
public static final String PREF_REMOVE_REDUNDANT_POPUPS = "remove_redundant_popups";
|
2024-08-28 22:08:00 +02:00
|
|
|
public static final String PREF_SPACE_BAR_TEXT = "space_bar_text";
|
2023-08-30 11:45:30 +02:00
|
|
|
|
2019-12-31 18:19:35 +01:00
|
|
|
// Emoji
|
2025-01-12 21:08:20 +01:00
|
|
|
public static final String PREF_EMOJI_MAX_SDK = "emoji_max_sdk";
|
2019-12-31 18:19:35 +01:00
|
|
|
public static final String PREF_EMOJI_RECENT_KEYS = "emoji_recent_keys";
|
|
|
|
public static final String PREF_LAST_SHOWN_EMOJI_CATEGORY_ID = "last_shown_emoji_category_id";
|
2021-01-22 13:57:47 +01:00
|
|
|
public static final String PREF_LAST_SHOWN_EMOJI_CATEGORY_PAGE_ID = "last_shown_emoji_category_page_id";
|
2019-12-31 18:19:35 +01:00
|
|
|
|
2023-11-04 13:38:24 +01:00
|
|
|
public static final String PREF_PINNED_CLIPS = "pinned_clips";
|
2024-01-28 13:55:11 +01:00
|
|
|
public static final String PREF_VERSION_CODE = "version_code";
|
2024-05-18 20:27:22 +02:00
|
|
|
public static final String PREF_SHOW_MORE_COLORS = "show_more_colors";
|
2024-01-28 18:05:38 +01:00
|
|
|
public static final String PREF_LIBRARY_CHECKSUM = "lib_checksum";
|
2023-09-12 14:43:50 +02:00
|
|
|
|
2019-12-31 18:19:35 +01:00
|
|
|
private static final float UNDEFINED_PREFERENCE_VALUE_FLOAT = -1.0f;
|
|
|
|
private static final int UNDEFINED_PREFERENCE_VALUE_INT = -1;
|
|
|
|
|
|
|
|
private Context mContext;
|
|
|
|
private SharedPreferences mPrefs;
|
|
|
|
private SettingsValues mSettingsValues;
|
|
|
|
private final ReentrantLock mSettingsValuesLock = new ReentrantLock();
|
|
|
|
|
2024-01-26 16:42:35 +01:00
|
|
|
// static cache for background images to avoid potentially slow reload on every settings reload
|
2025-01-17 20:10:16 +01:00
|
|
|
private final static Drawable[] sCachedBackgroundImages = new Drawable[4];
|
2025-01-17 21:47:13 +01:00
|
|
|
private static Typeface sCachedTypeface;
|
2024-09-23 20:45:23 +02:00
|
|
|
private Map<String, Integer> mCustomToolbarKeyCodes = null;
|
|
|
|
private Map<String, Integer> mCustomToolbarLongpressCodes = null;
|
2024-01-26 16:42:35 +01:00
|
|
|
|
2019-12-31 18:19:35 +01:00
|
|
|
private static final Settings sInstance = new Settings();
|
|
|
|
|
2023-11-17 07:50:58 +01:00
|
|
|
// preferences that are not used in SettingsValues and thus should not trigger reload when changed
|
2023-11-04 13:38:24 +01:00
|
|
|
private static final HashSet<String> dontReloadOnChanged = new HashSet<>() {{
|
|
|
|
add(PREF_PINNED_CLIPS);
|
|
|
|
add(PREF_LAST_SHOWN_EMOJI_CATEGORY_PAGE_ID);
|
|
|
|
add(PREF_LAST_SHOWN_EMOJI_CATEGORY_ID);
|
|
|
|
add(PREF_EMOJI_RECENT_KEYS);
|
|
|
|
add(PREF_DONT_SHOW_MISSING_DICTIONARY_DIALOG);
|
2024-03-06 22:07:38 +01:00
|
|
|
add(PREF_SELECTED_SUBTYPE);
|
2023-11-04 13:38:24 +01:00
|
|
|
}};
|
|
|
|
|
2019-12-31 18:19:35 +01:00
|
|
|
public static Settings getInstance() {
|
|
|
|
return sInstance;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void init(final Context context) {
|
|
|
|
sInstance.onCreate(context);
|
|
|
|
}
|
|
|
|
|
|
|
|
private Settings() {
|
|
|
|
// Intentional empty constructor for singleton.
|
|
|
|
}
|
|
|
|
|
|
|
|
private void onCreate(final Context context) {
|
|
|
|
mContext = context;
|
2021-05-04 11:22:16 -04:00
|
|
|
mPrefs = DeviceProtectedUtils.getSharedPreferences(context);
|
2019-12-31 18:19:35 +01:00
|
|
|
mPrefs.registerOnSharedPreferenceChangeListener(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onDestroy() {
|
|
|
|
mPrefs.unregisterOnSharedPreferenceChangeListener(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
|
2023-11-04 13:38:24 +01:00
|
|
|
if (dontReloadOnChanged.contains(key))
|
|
|
|
return;
|
2019-12-31 18:19:35 +01:00
|
|
|
mSettingsValuesLock.lock();
|
|
|
|
try {
|
|
|
|
if (mSettingsValues == null) {
|
|
|
|
// TODO: Introduce a static function to register this class and ensure that
|
|
|
|
// loadSettings must be called before "onSharedPreferenceChanged" is called.
|
|
|
|
Log.w(TAG, "onSharedPreferenceChanged called before loadSettings.");
|
|
|
|
return;
|
|
|
|
}
|
2024-09-23 20:45:23 +02:00
|
|
|
mCustomToolbarLongpressCodes = null;
|
|
|
|
mCustomToolbarKeyCodes = null;
|
2019-12-31 18:19:35 +01:00
|
|
|
loadSettings(mContext, mSettingsValues.mLocale, mSettingsValues.mInputAttributes);
|
|
|
|
StatsUtils.onLoadSettings(mSettingsValues);
|
|
|
|
} finally {
|
|
|
|
mSettingsValuesLock.unlock();
|
|
|
|
}
|
2024-01-01 13:36:02 +01:00
|
|
|
if (PREF_ADDITIONAL_SUBTYPES.equals(key)) {
|
2023-08-25 17:33:29 +02:00
|
|
|
final String additionalSubtypes = readPrefAdditionalSubtypes(prefs, mContext.getResources());
|
|
|
|
SubtypeSettingsKt.updateAdditionalSubtypes(AdditionalSubtypeUtils.createAdditionalSubtypesArray(additionalSubtypes));
|
|
|
|
}
|
2019-12-31 18:19:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void loadSettings(final Context context, final Locale locale,
|
2023-09-01 08:08:36 +02:00
|
|
|
@NonNull final InputAttributes inputAttributes) {
|
2019-12-31 18:19:35 +01:00
|
|
|
mSettingsValuesLock.lock();
|
|
|
|
mContext = context;
|
|
|
|
try {
|
|
|
|
final SharedPreferences prefs = mPrefs;
|
2023-12-15 10:59:38 +01:00
|
|
|
Log.i(TAG, "loadSettings");
|
2024-01-23 20:41:36 +01:00
|
|
|
mSettingsValues = RunInLocaleKt.runInLocale(context, locale,
|
2024-01-25 14:05:39 +01:00
|
|
|
ctx -> new SettingsValues(ctx, prefs, ctx.getResources(), inputAttributes));
|
2019-12-31 18:19:35 +01:00
|
|
|
} finally {
|
|
|
|
mSettingsValuesLock.unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-02 21:47:25 +01:00
|
|
|
public void stopListener() {
|
|
|
|
mPrefs.unregisterOnSharedPreferenceChangeListener(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void startListener() {
|
|
|
|
mPrefs.registerOnSharedPreferenceChangeListener(this);
|
|
|
|
}
|
|
|
|
|
2019-12-31 18:19:35 +01:00
|
|
|
// TODO: Remove this method and add proxy method to SettingsValues.
|
|
|
|
public SettingsValues getCurrent() {
|
|
|
|
return mSettingsValues;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int readScreenMetrics(final Resources res) {
|
|
|
|
return res.getInteger(R.integer.config_screen_metrics);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Accessed from the settings interface, hence public
|
2024-01-28 18:05:38 +01:00
|
|
|
public static boolean readKeypressSoundEnabled(final SharedPreferences prefs, final Resources res) {
|
2023-09-10 21:39:56 +02:00
|
|
|
return prefs.getBoolean(PREF_SOUND_ON, res.getBoolean(R.bool.config_default_sound_enabled));
|
2019-12-31 18:19:35 +01:00
|
|
|
}
|
|
|
|
|
2024-01-28 18:05:38 +01:00
|
|
|
public static boolean readVibrationEnabled(final SharedPreferences prefs, final Resources res) {
|
2023-12-29 12:08:32 +01:00
|
|
|
return prefs.getBoolean(PREF_VIBRATE_ON, res.getBoolean(R.bool.config_default_vibration_enabled))
|
|
|
|
&& AudioAndHapticFeedbackManager.getInstance().hasVibrator();
|
2019-12-31 18:19:35 +01:00
|
|
|
}
|
|
|
|
|
2023-09-10 21:39:56 +02:00
|
|
|
public static boolean readAutoCorrectEnabled(final SharedPreferences prefs) {
|
2019-12-31 18:19:35 +01:00
|
|
|
return prefs.getBoolean(PREF_AUTO_CORRECTION, true);
|
|
|
|
}
|
|
|
|
|
2024-01-23 12:29:14 +01:00
|
|
|
public static boolean readMoreAutoCorrectEnabled(final SharedPreferences prefs) {
|
|
|
|
return prefs.getBoolean(PREF_MORE_AUTO_CORRECTION, true);
|
|
|
|
}
|
|
|
|
|
2024-01-01 13:16:49 +01:00
|
|
|
public void toggleAutoCorrect() {
|
|
|
|
mPrefs.edit().putBoolean(Settings.PREF_AUTO_CORRECTION, !readAutoCorrectEnabled(mPrefs)).apply();
|
|
|
|
}
|
|
|
|
|
2024-01-28 18:05:38 +01:00
|
|
|
public static String readAutoCorrectConfidence(final SharedPreferences prefs, final Resources res) {
|
2022-08-29 21:59:53 +01:00
|
|
|
return prefs.getString(PREF_AUTO_CORRECTION_CONFIDENCE,
|
|
|
|
res.getString(R.string.auto_correction_threshold_mode_index_modest));
|
|
|
|
}
|
|
|
|
|
2024-05-01 00:33:57 -04:00
|
|
|
public static boolean readCenterSuggestionTextToEnter(final SharedPreferences prefs, final Resources res) {
|
|
|
|
return prefs.getBoolean(PREF_CENTER_SUGGESTION_TEXT_TO_ENTER, res.getBoolean(R.bool.config_center_suggestion_text_to_enter));
|
|
|
|
}
|
|
|
|
|
2024-01-28 18:05:38 +01:00
|
|
|
public static boolean readBlockPotentiallyOffensive(final SharedPreferences prefs, final Resources res) {
|
2019-12-31 18:19:35 +01:00
|
|
|
return prefs.getBoolean(PREF_BLOCK_POTENTIALLY_OFFENSIVE,
|
|
|
|
res.getBoolean(R.bool.config_block_potentially_offensive));
|
|
|
|
}
|
|
|
|
|
2023-09-16 22:18:31 +02:00
|
|
|
public static boolean readGestureInputEnabled(final SharedPreferences prefs) {
|
|
|
|
return JniUtils.sHaveGestureLib && prefs.getBoolean(PREF_GESTURE_INPUT, true);
|
2019-12-31 18:19:35 +01:00
|
|
|
}
|
|
|
|
|
2024-07-24 23:08:50 -06:00
|
|
|
public static boolean readGestureDynamicPreviewEnabled(final SharedPreferences prefs, final Context context) {
|
|
|
|
final boolean followSystem = prefs.getBoolean(PREF_GESTURE_DYNAMIC_PREVIEW_FOLLOW_SYSTEM, true);
|
|
|
|
final boolean defValue = readGestureDynamicPreviewDefault(context);
|
|
|
|
final boolean curValue = prefs.getBoolean(Settings.PREF_GESTURE_FLOATING_PREVIEW_DYNAMIC, defValue);
|
|
|
|
return followSystem ? defValue : curValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean readGestureDynamicPreviewDefault(final Context context) {
|
|
|
|
// if transitions are disabled for the system (reduced motion), moving preview should be disabled
|
|
|
|
return android.provider.Settings.System.getFloat(
|
|
|
|
context.getContentResolver(),
|
|
|
|
android.provider.Settings.Global.TRANSITION_ANIMATION_SCALE,
|
|
|
|
1.0f
|
|
|
|
) != 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int readGestureFastTypingCooldown(final SharedPreferences prefs, final Resources res) {
|
|
|
|
final int milliseconds = prefs.getInt(
|
|
|
|
PREF_GESTURE_FAST_TYPING_COOLDOWN, UNDEFINED_PREFERENCE_VALUE_INT);
|
|
|
|
return (milliseconds != UNDEFINED_PREFERENCE_VALUE_INT) ? milliseconds
|
|
|
|
: readDefaultGestureFastTypingCooldown(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int readDefaultGestureFastTypingCooldown(final Resources res) {
|
|
|
|
return res.getInteger(R.integer.config_gesture_static_time_threshold_after_fast_typing);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int readGestureTrailFadeoutDuration(final SharedPreferences prefs, final Resources res) {
|
|
|
|
final int milliseconds = prefs.getInt(
|
|
|
|
PREF_GESTURE_TRAIL_FADEOUT_DURATION, UNDEFINED_PREFERENCE_VALUE_INT);
|
|
|
|
return (milliseconds != UNDEFINED_PREFERENCE_VALUE_INT) ? milliseconds
|
|
|
|
: readDefaultGestureTrailFadeoutDuration(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int readDefaultGestureTrailFadeoutDuration(final Resources res) {
|
|
|
|
return res.getInteger(R.integer.config_gesture_trail_fadeout_duration_default);
|
|
|
|
}
|
|
|
|
|
2024-01-28 18:05:38 +01:00
|
|
|
public static boolean readKeyPreviewPopupEnabled(final SharedPreferences prefs, final Resources res) {
|
2024-05-19 15:26:57 +02:00
|
|
|
final boolean defaultKeyPreviewPopup = res.getBoolean(R.bool.config_default_key_preview_popup);
|
2019-12-31 18:19:35 +01:00
|
|
|
return prefs.getBoolean(PREF_POPUP_ON, defaultKeyPreviewPopup);
|
|
|
|
}
|
|
|
|
|
2020-09-27 16:41:15 +02:00
|
|
|
public static boolean readAlwaysIncognitoMode(final SharedPreferences prefs) {
|
2020-10-02 12:40:57 +02:00
|
|
|
return prefs.getBoolean(PREF_ALWAYS_INCOGNITO_MODE, false);
|
2019-12-31 18:19:35 +01:00
|
|
|
}
|
|
|
|
|
2024-01-01 13:16:49 +01:00
|
|
|
public void toggleAlwaysIncognitoMode() {
|
|
|
|
mPrefs.edit().putBoolean(Settings.PREF_ALWAYS_INCOGNITO_MODE, !readAlwaysIncognitoMode(mPrefs)).apply();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-01-28 18:05:38 +01:00
|
|
|
public static String readPrefAdditionalSubtypes(final SharedPreferences prefs, final Resources res) {
|
2019-12-31 18:19:35 +01:00
|
|
|
final String predefinedPrefSubtypes = AdditionalSubtypeUtils.createPrefSubtypes(
|
|
|
|
res.getStringArray(R.array.predefined_subtypes));
|
2024-01-01 13:36:02 +01:00
|
|
|
return prefs.getString(PREF_ADDITIONAL_SUBTYPES, predefinedPrefSubtypes);
|
2019-12-31 18:19:35 +01:00
|
|
|
}
|
|
|
|
|
2024-01-28 18:05:38 +01:00
|
|
|
public static void writePrefAdditionalSubtypes(final SharedPreferences prefs, final String prefSubtypes) {
|
2024-01-01 13:36:02 +01:00
|
|
|
prefs.edit().putString(PREF_ADDITIONAL_SUBTYPES, prefSubtypes).apply();
|
2019-12-31 18:19:35 +01:00
|
|
|
}
|
|
|
|
|
2024-05-26 20:25:13 +02:00
|
|
|
public static float readKeypressSoundVolume(final SharedPreferences prefs) {
|
|
|
|
return prefs.getFloat(PREF_KEYPRESS_SOUND_VOLUME, UNDEFINED_PREFERENCE_VALUE_FLOAT);
|
2019-12-31 18:19:35 +01:00
|
|
|
}
|
|
|
|
|
2024-01-28 18:05:38 +01:00
|
|
|
public static int readKeyLongpressTimeout(final SharedPreferences prefs, final Resources res) {
|
2019-12-31 18:19:35 +01:00
|
|
|
final int milliseconds = prefs.getInt(
|
|
|
|
PREF_KEY_LONGPRESS_TIMEOUT, UNDEFINED_PREFERENCE_VALUE_INT);
|
|
|
|
return (milliseconds != UNDEFINED_PREFERENCE_VALUE_INT) ? milliseconds
|
|
|
|
: readDefaultKeyLongpressTimeout(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int readDefaultKeyLongpressTimeout(final Resources res) {
|
|
|
|
return res.getInteger(R.integer.config_default_longpress_key_timeout);
|
|
|
|
}
|
|
|
|
|
2024-05-26 20:25:13 +02:00
|
|
|
public static int readKeypressVibrationDuration(final SharedPreferences prefs) {
|
|
|
|
return prefs.getInt(PREF_VIBRATION_DURATION_SETTINGS, UNDEFINED_PREFERENCE_VALUE_INT);
|
2019-12-31 18:19:35 +01:00
|
|
|
}
|
|
|
|
|
2022-02-18 21:08:29 +01:00
|
|
|
public static boolean readClipboardHistoryEnabled(final SharedPreferences prefs) {
|
|
|
|
return prefs.getBoolean(PREF_ENABLE_CLIPBOARD_HISTORY, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int readClipboardHistoryRetentionTime(final SharedPreferences prefs,
|
|
|
|
final Resources res) {
|
|
|
|
final int minutes = prefs.getInt(
|
|
|
|
PREF_CLIPBOARD_HISTORY_RETENTION_TIME, UNDEFINED_PREFERENCE_VALUE_INT);
|
|
|
|
return (minutes != UNDEFINED_PREFERENCE_VALUE_INT) ? minutes
|
|
|
|
: readDefaultClipboardHistoryRetentionTime(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int readDefaultClipboardHistoryRetentionTime(final Resources res) {
|
|
|
|
return res.getInteger(R.integer.config_clipboard_history_retention_time);
|
|
|
|
}
|
2019-12-31 18:19:35 +01:00
|
|
|
|
2024-03-12 01:42:25 +04:00
|
|
|
public static int readHorizontalSpaceSwipe(final SharedPreferences prefs) {
|
|
|
|
return switch (prefs.getString(PREF_SPACE_HORIZONTAL_SWIPE, "none")) {
|
|
|
|
case "move_cursor" -> KeyboardActionListener.SWIPE_MOVE_CURSOR;
|
|
|
|
case "switch_language" -> KeyboardActionListener.SWIPE_SWITCH_LANGUAGE;
|
2024-07-09 14:26:23 -06:00
|
|
|
case "toggle_numpad" -> KeyboardActionListener.SWIPE_TOGGLE_NUMPAD;
|
2024-03-12 01:42:25 +04:00
|
|
|
default -> KeyboardActionListener.SWIPE_NO_ACTION;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int readVerticalSpaceSwipe(final SharedPreferences prefs) {
|
|
|
|
return switch (prefs.getString(PREF_SPACE_VERTICAL_SWIPE, "none")) {
|
|
|
|
case "move_cursor" -> KeyboardActionListener.SWIPE_MOVE_CURSOR;
|
|
|
|
case "switch_language" -> KeyboardActionListener.SWIPE_SWITCH_LANGUAGE;
|
2024-07-09 14:26:23 -06:00
|
|
|
case "toggle_numpad" -> KeyboardActionListener.SWIPE_TOGGLE_NUMPAD;
|
2024-03-12 01:42:25 +04:00
|
|
|
default -> KeyboardActionListener.SWIPE_NO_ACTION;
|
|
|
|
};
|
2020-01-18 16:26:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean readDeleteSwipeEnabled(final SharedPreferences prefs) {
|
|
|
|
return prefs.getBoolean(PREF_DELETE_SWIPE, true);
|
|
|
|
}
|
|
|
|
|
2022-03-21 15:09:39 +01:00
|
|
|
public static boolean readAutospaceAfterPunctuationEnabled(final SharedPreferences prefs) {
|
|
|
|
return prefs.getBoolean(PREF_AUTOSPACE_AFTER_PUNCTUATION, false);
|
2022-03-17 07:11:26 +01:00
|
|
|
}
|
|
|
|
|
2023-12-19 00:27:19 +01:00
|
|
|
public static boolean readFullscreenModeAllowed(final Resources res) {
|
|
|
|
return res.getBoolean(R.bool.config_fullscreen_mode_allowed);
|
2019-12-31 18:19:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean readShowSetupWizardIcon(final SharedPreferences prefs,
|
2020-04-23 20:29:26 +04:00
|
|
|
final Context context) {
|
2019-12-31 18:19:35 +01:00
|
|
|
if (!prefs.contains(PREF_SHOW_SETUP_WIZARD_ICON)) {
|
|
|
|
final ApplicationInfo appInfo = context.getApplicationInfo();
|
|
|
|
final boolean isApplicationInSystemImage =
|
|
|
|
(appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
|
|
|
|
// Default value
|
|
|
|
return !isApplicationInSystemImage;
|
|
|
|
}
|
|
|
|
return prefs.getBoolean(PREF_SHOW_SETUP_WIZARD_ICON, false);
|
|
|
|
}
|
|
|
|
|
2023-12-18 17:30:53 +01:00
|
|
|
public static boolean readOneHandedModeEnabled(final SharedPreferences prefs, final boolean portrait) {
|
2024-01-01 13:36:02 +01:00
|
|
|
return prefs.getBoolean(PREF_ONE_HANDED_MODE_PREFIX + portrait, false);
|
2022-02-20 16:14:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void writeOneHandedModeEnabled(final boolean enabled) {
|
2024-01-28 18:05:38 +01:00
|
|
|
mPrefs.edit().putBoolean(PREF_ONE_HANDED_MODE_PREFIX +
|
|
|
|
(getCurrent().mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT), enabled).apply();
|
2023-12-18 17:30:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public static float readOneHandedModeScale(final SharedPreferences prefs, final boolean portrait) {
|
2024-01-01 13:36:02 +01:00
|
|
|
return prefs.getFloat(PREF_ONE_HANDED_SCALE_PREFIX + portrait, 1f);
|
2023-12-18 17:30:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void writeOneHandedModeScale(final Float scale) {
|
2024-01-28 18:05:38 +01:00
|
|
|
mPrefs.edit().putFloat(PREF_ONE_HANDED_SCALE_PREFIX +
|
|
|
|
(getCurrent().mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT), scale).apply();
|
2022-02-20 16:14:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@SuppressLint("RtlHardcoded")
|
2023-12-18 17:30:53 +01:00
|
|
|
public static int readOneHandedModeGravity(final SharedPreferences prefs, final boolean portrait) {
|
2024-01-01 13:36:02 +01:00
|
|
|
return prefs.getInt(PREF_ONE_HANDED_GRAVITY_PREFIX + portrait, Gravity.LEFT);
|
2022-02-20 16:14:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void writeOneHandedModeGravity(final int gravity) {
|
2024-01-28 18:05:38 +01:00
|
|
|
mPrefs.edit().putInt(PREF_ONE_HANDED_GRAVITY_PREFIX +
|
|
|
|
(getCurrent().mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT), gravity).apply();
|
2022-02-20 16:14:12 +01:00
|
|
|
}
|
|
|
|
|
2019-12-31 18:19:35 +01:00
|
|
|
public static boolean readHasHardwareKeyboard(final Configuration conf) {
|
|
|
|
// The standard way of finding out whether we have a hardware keyboard. This code is taken
|
|
|
|
// from InputMethodService#onEvaluateInputShown, which canonically determines this.
|
|
|
|
// In a nutshell, we have a keyboard if the configuration says the type of hardware keyboard
|
|
|
|
// is NOKEYS and if it's not hidden (e.g. folded inside the device).
|
|
|
|
return conf.keyboard != Configuration.KEYBOARD_NOKEYS
|
|
|
|
&& conf.hardKeyboardHidden != Configuration.HARDKEYBOARDHIDDEN_YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void writeEmojiRecentKeys(final SharedPreferences prefs, String str) {
|
|
|
|
prefs.edit().putString(PREF_EMOJI_RECENT_KEYS, str).apply();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String readEmojiRecentKeys(final SharedPreferences prefs) {
|
|
|
|
return prefs.getString(PREF_EMOJI_RECENT_KEYS, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void writeLastShownEmojiCategoryId(
|
|
|
|
final SharedPreferences prefs, final int categoryId) {
|
|
|
|
prefs.edit().putInt(PREF_LAST_SHOWN_EMOJI_CATEGORY_ID, categoryId).apply();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int readLastShownEmojiCategoryId(
|
|
|
|
final SharedPreferences prefs, final int defValue) {
|
|
|
|
return prefs.getInt(PREF_LAST_SHOWN_EMOJI_CATEGORY_ID, defValue);
|
|
|
|
}
|
|
|
|
|
2021-01-22 13:57:47 +01:00
|
|
|
public static void writeLastShownEmojiCategoryPageId(
|
|
|
|
final SharedPreferences prefs, final int categoryId) {
|
|
|
|
prefs.edit().putInt(PREF_LAST_SHOWN_EMOJI_CATEGORY_PAGE_ID, categoryId).apply();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int readLastShownEmojiCategoryPageId(
|
|
|
|
final SharedPreferences prefs, final int defValue) {
|
|
|
|
return prefs.getInt(PREF_LAST_SHOWN_EMOJI_CATEGORY_PAGE_ID, defValue);
|
|
|
|
}
|
2023-06-26 23:47:21 +02:00
|
|
|
|
2024-02-13 08:23:07 +01:00
|
|
|
public static String readPinnedClipString(final Context context) {
|
|
|
|
try {
|
|
|
|
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
|
|
|
return prefs.getString(PREF_PINNED_CLIPS, "");
|
|
|
|
} catch (final IllegalStateException e) {
|
|
|
|
// SharedPreferences in credential encrypted storage are not available until after user is unlocked
|
|
|
|
return "";
|
|
|
|
}
|
2023-11-04 13:38:24 +01:00
|
|
|
}
|
|
|
|
|
2024-02-13 08:23:07 +01:00
|
|
|
public static void writePinnedClipString(final Context context, final String clips) {
|
|
|
|
try {
|
|
|
|
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
|
|
|
prefs.edit().putString(PREF_PINNED_CLIPS, clips).apply();
|
|
|
|
} catch (final IllegalStateException e) {
|
|
|
|
// SharedPreferences in credential encrypted storage are not available until after user is unlocked
|
|
|
|
}
|
2023-11-04 13:38:24 +01:00
|
|
|
}
|
|
|
|
|
2024-02-05 09:33:06 +01:00
|
|
|
public static int readMorePopupKeysPref(final SharedPreferences prefs) {
|
2024-07-12 20:55:38 +02:00
|
|
|
return switch (prefs.getString(Settings.PREF_MORE_POPUP_KEYS, "main")) {
|
2024-02-14 11:08:44 +01:00
|
|
|
case "all" -> LocaleKeyboardInfosKt.POPUP_KEYS_ALL;
|
|
|
|
case "more" -> LocaleKeyboardInfosKt.POPUP_KEYS_MORE;
|
2024-07-12 20:55:38 +02:00
|
|
|
case "normal" -> LocaleKeyboardInfosKt.POPUP_KEYS_NORMAL;
|
|
|
|
default -> LocaleKeyboardInfosKt.POPUP_KEYS_MAIN;
|
2023-11-19 21:16:23 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2024-01-26 16:42:35 +01:00
|
|
|
@Nullable public static Drawable readUserBackgroundImage(final Context context, final boolean night) {
|
2025-01-17 20:10:16 +01:00
|
|
|
final boolean landscape = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
|
|
|
|
final int index = (night ? 1 : 0) + (landscape ? 2 : 0);
|
|
|
|
if (sCachedBackgroundImages[index] != null) return sCachedBackgroundImages[index];
|
|
|
|
|
|
|
|
File image = getCustomBackgroundFile(context, night, landscape);
|
|
|
|
if (!image.isFile() && landscape)
|
|
|
|
image = getCustomBackgroundFile(context, night, false); // fall back to portrait image for historic reasons
|
2024-01-26 16:42:35 +01:00
|
|
|
if (!image.isFile()) return null;
|
|
|
|
try {
|
2025-01-17 20:10:16 +01:00
|
|
|
sCachedBackgroundImages[index] = new BitmapDrawable(context.getResources(), BitmapFactory.decodeFile(image.getAbsolutePath()));
|
|
|
|
return sCachedBackgroundImages[index];
|
2024-01-26 16:42:35 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-01-17 20:10:16 +01:00
|
|
|
public static File getCustomBackgroundFile(final Context context, final boolean night, final boolean landscape) {
|
|
|
|
return new File(DeviceProtectedUtils.getFilesDir(context), "custom_background_image" + (landscape ? "_landscape" : "") + (night ? "_night" : ""));
|
2024-01-26 16:42:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean readDayNightPref(final SharedPreferences prefs, final Resources res) {
|
|
|
|
return prefs.getBoolean(PREF_THEME_DAY_NIGHT, res.getBoolean(R.bool.day_night_default));
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void clearCachedBackgroundImages() {
|
2025-01-17 20:10:16 +01:00
|
|
|
Arrays.fill(sCachedBackgroundImages, null);
|
2024-01-26 16:42:35 +01:00
|
|
|
}
|
|
|
|
|
2024-01-28 10:42:42 +01:00
|
|
|
public static List<Locale> getSecondaryLocales(final SharedPreferences prefs, final Locale mainLocale) {
|
|
|
|
final String localesString = prefs.getString(PREF_SECONDARY_LOCALES_PREFIX + mainLocale.toLanguageTag(), "");
|
2023-08-25 17:33:29 +02:00
|
|
|
|
|
|
|
final ArrayList<Locale> locales = new ArrayList<>();
|
2024-01-28 10:42:42 +01:00
|
|
|
for (String languageTag : localesString.split(";")) {
|
|
|
|
if (languageTag.isEmpty()) continue;
|
|
|
|
locales.add(LocaleUtils.constructLocale(languageTag));
|
2023-08-25 17:33:29 +02:00
|
|
|
}
|
|
|
|
return locales;
|
|
|
|
}
|
|
|
|
|
2024-01-28 10:42:42 +01:00
|
|
|
public static void setSecondaryLocales(final SharedPreferences prefs, final Locale mainLocale, final List<Locale> locales) {
|
2023-08-25 17:33:29 +02:00
|
|
|
if (locales.isEmpty()) {
|
2024-02-01 19:46:44 +01:00
|
|
|
prefs.edit().putString(PREF_SECONDARY_LOCALES_PREFIX + mainLocale.toLanguageTag(), "").apply();
|
2023-08-25 17:33:29 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
final StringBuilder sb = new StringBuilder();
|
2024-01-28 10:42:42 +01:00
|
|
|
for (Locale locale : locales) {
|
|
|
|
sb.append(";").append(locale.toLanguageTag());
|
2023-06-26 23:47:21 +02:00
|
|
|
}
|
2024-02-01 19:46:44 +01:00
|
|
|
prefs.edit().putString(PREF_SECONDARY_LOCALES_PREFIX + mainLocale.toLanguageTag(), sb.toString()).apply();
|
2023-06-26 23:47:21 +02:00
|
|
|
}
|
|
|
|
|
2023-09-01 00:35:40 +02:00
|
|
|
public static Colors getColorsForCurrentTheme(final Context context, final SharedPreferences prefs) {
|
2023-09-12 14:43:50 +02:00
|
|
|
boolean isNight = ResourceUtils.isNight(context.getResources());
|
2024-02-01 18:40:47 +01:00
|
|
|
if (ColorsSettingsFragment.Companion.getForceOppositeTheme()) isNight = !isNight;
|
2024-06-30 18:21:23 +02:00
|
|
|
else isNight = isNight && readDayNightPref(prefs, context.getResources());
|
|
|
|
final String themeColors = (isNight)
|
2024-04-06 12:17:30 +06:00
|
|
|
? prefs.getString(Settings.PREF_THEME_COLORS_NIGHT, KeyboardTheme.THEME_DARK)
|
2023-10-20 21:16:53 +02:00
|
|
|
: prefs.getString(Settings.PREF_THEME_COLORS, KeyboardTheme.THEME_LIGHT);
|
|
|
|
final String themeStyle = prefs.getString(Settings.PREF_THEME_STYLE, KeyboardTheme.STYLE_MATERIAL);
|
2023-07-20 12:38:07 +02:00
|
|
|
|
2024-06-30 18:21:23 +02:00
|
|
|
return KeyboardTheme.getThemeColors(themeColors, themeStyle, context, prefs, isNight);
|
2023-07-20 12:38:07 +02:00
|
|
|
}
|
|
|
|
|
2023-09-12 14:21:40 +02:00
|
|
|
public static int readUserColor(final SharedPreferences prefs, final Context context, final String colorName, final boolean isNight) {
|
|
|
|
final String pref = getColorPref(colorName, isNight);
|
|
|
|
if (prefs.getBoolean(pref + PREF_AUTO_USER_COLOR_SUFFIX, true)) {
|
|
|
|
return determineAutoColor(prefs, context, colorName, isNight);
|
|
|
|
}
|
|
|
|
if (prefs.contains(pref))
|
|
|
|
return prefs.getInt(pref, Color.GRAY);
|
|
|
|
else return determineAutoColor(prefs, context, colorName, isNight);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String getColorPref(final String color, final boolean isNight) {
|
|
|
|
return (isNight ? PREF_THEME_USER_COLOR_NIGHT_PREFIX : PREF_THEME_USER_COLOR_PREFIX) + color;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static int determineAutoColor(final SharedPreferences prefs, final Context context, final String color, final boolean isNight) {
|
|
|
|
switch (color) {
|
|
|
|
case PREF_COLOR_ACCENT_SUFFIX:
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
|
|
|
// try determining accent color on Android 10 & 11, accent is not available in resources
|
|
|
|
final Context wrapper = new ContextThemeWrapper(context, android.R.style.Theme_DeviceDefault);
|
|
|
|
final TypedValue value = new TypedValue();
|
|
|
|
if (wrapper.getTheme().resolveAttribute(android.R.attr.colorAccent, value, true))
|
|
|
|
return value.data;
|
|
|
|
}
|
|
|
|
return ContextCompat.getColor(getDayNightContext(context, isNight), R.color.accent);
|
2023-11-17 07:50:58 +01:00
|
|
|
case PREF_COLOR_GESTURE_SUFFIX:
|
|
|
|
return readUserColor(prefs, context, PREF_COLOR_ACCENT_SUFFIX, isNight);
|
2023-12-31 17:05:57 +01:00
|
|
|
case PREF_COLOR_SUGGESTION_TEXT_SUFFIX:
|
|
|
|
return readUserColor(prefs, context, PREF_COLOR_TEXT_SUFFIX, isNight);
|
2023-09-12 14:21:40 +02:00
|
|
|
case PREF_COLOR_TEXT_SUFFIX:
|
|
|
|
// base it on background color, and not key, because it's also used for suggestions
|
2023-11-03 12:59:23 +01:00
|
|
|
final int background = readUserColor(prefs, context, PREF_COLOR_BACKGROUND_SUFFIX, isNight);
|
|
|
|
if (ColorUtilKt.isBrightColor(background)) {
|
|
|
|
// but if key borders are enabled, we still want reasonable contrast
|
|
|
|
if (!prefs.getBoolean(Settings.PREF_THEME_KEY_BORDERS, false)
|
|
|
|
|| ColorUtilKt.isGoodContrast(Color.BLACK, readUserColor(prefs, context, PREF_COLOR_KEYS_SUFFIX, isNight)))
|
|
|
|
return Color.BLACK;
|
|
|
|
else
|
|
|
|
return Color.GRAY;
|
|
|
|
}
|
2023-09-12 14:21:40 +02:00
|
|
|
else return Color.WHITE;
|
|
|
|
case PREF_COLOR_HINT_TEXT_SUFFIX:
|
|
|
|
if (ColorUtilKt.isBrightColor(readUserColor(prefs, context, PREF_COLOR_KEYS_SUFFIX, isNight))) return Color.DKGRAY;
|
2023-10-23 23:55:19 +02:00
|
|
|
else return readUserColor(prefs, context, PREF_COLOR_TEXT_SUFFIX, isNight);
|
2023-09-12 14:21:40 +02:00
|
|
|
case PREF_COLOR_KEYS_SUFFIX:
|
|
|
|
return ColorUtilKt.brightenOrDarken(readUserColor(prefs, context, PREF_COLOR_BACKGROUND_SUFFIX, isNight), isNight);
|
2023-10-23 23:55:19 +02:00
|
|
|
case PREF_COLOR_FUNCTIONAL_KEYS_SUFFIX:
|
|
|
|
return ColorUtilKt.brightenOrDarken(readUserColor(prefs, context, PREF_COLOR_KEYS_SUFFIX, isNight), true);
|
|
|
|
case PREF_COLOR_SPACEBAR_SUFFIX:
|
|
|
|
return readUserColor(prefs, context, PREF_COLOR_KEYS_SUFFIX, isNight);
|
|
|
|
case PREF_COLOR_SPACEBAR_TEXT_SUFFIX:
|
2023-10-24 00:36:24 +02:00
|
|
|
final int spacebar = readUserColor(prefs, context, PREF_COLOR_SPACEBAR_SUFFIX, isNight);
|
|
|
|
final int hintText = readUserColor(prefs, context, PREF_COLOR_HINT_TEXT_SUFFIX, isNight);
|
2023-11-03 12:59:23 +01:00
|
|
|
if (ColorUtilKt.isGoodContrast(hintText, spacebar)) return hintText & 0x80FFFFFF; // add some transparency
|
|
|
|
final int text = readUserColor(prefs, context, PREF_COLOR_TEXT_SUFFIX, isNight);
|
|
|
|
if (ColorUtilKt.isGoodContrast(text, spacebar)) return text & 0x80FFFFFF;
|
|
|
|
if (ColorUtilKt.isBrightColor(spacebar)) return Color.BLACK & 0x80FFFFFF;
|
|
|
|
else return Color.WHITE & 0x80FFFFFF;
|
2023-09-12 14:21:40 +02:00
|
|
|
case PREF_COLOR_BACKGROUND_SUFFIX:
|
|
|
|
default:
|
|
|
|
return ContextCompat.getColor(getDayNightContext(context, isNight), R.color.keyboard_background);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Context getDayNightContext(final Context context, final boolean wantNight) {
|
2024-01-01 17:42:26 +01:00
|
|
|
final boolean isNight = ResourceUtils.isNight(context.getResources());
|
2023-09-12 14:21:40 +02:00
|
|
|
if (isNight == wantNight)
|
|
|
|
return context;
|
|
|
|
final Configuration config = new Configuration(context.getResources().getConfiguration());
|
|
|
|
final int night = config.uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
|
|
|
final int uiModeWithNightBitsZero = config.uiMode - night;
|
|
|
|
config.uiMode = uiModeWithNightBitsZero + (wantNight ? Configuration.UI_MODE_NIGHT_YES : Configuration.UI_MODE_NIGHT_NO);
|
|
|
|
final ContextThemeWrapper wrapper = new ContextThemeWrapper(context, R.style.platformActivityTheme);
|
|
|
|
wrapper.applyOverrideConfiguration(config);
|
|
|
|
return wrapper;
|
|
|
|
}
|
|
|
|
|
2024-05-11 15:41:00 +02:00
|
|
|
public boolean isTablet() {
|
|
|
|
return mContext.getResources().getInteger(R.integer.config_screen_metrics) >= 3;
|
|
|
|
}
|
2024-05-18 10:30:46 +02:00
|
|
|
|
|
|
|
public int getStringResIdByName(final String name) {
|
|
|
|
return mContext.getResources().getIdentifier(name, "string", mContext.getPackageName());
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getInLocale(@StringRes final int resId, final Locale locale) {
|
|
|
|
return RunInLocaleKt.runInLocale(mContext, locale, (ctx) -> ctx.getString(resId));
|
|
|
|
}
|
2024-06-29 20:34:32 +02:00
|
|
|
|
|
|
|
public String readCustomCurrencyKey() {
|
|
|
|
return mPrefs.getString(PREF_CUSTOM_CURRENCY_KEY, "");
|
|
|
|
}
|
2024-09-23 20:45:23 +02:00
|
|
|
|
|
|
|
public Integer getCustomToolbarKeyCode(ToolbarKey key) {
|
|
|
|
if (mCustomToolbarKeyCodes == null)
|
|
|
|
mCustomToolbarKeyCodes = ToolbarUtilsKt.readCustomKeyCodes(mPrefs);
|
|
|
|
return mCustomToolbarKeyCodes.get(key.name());
|
|
|
|
}
|
|
|
|
|
|
|
|
public Integer getCustomToolbarLongpressCode(ToolbarKey key) {
|
|
|
|
if (mCustomToolbarLongpressCodes == null)
|
|
|
|
mCustomToolbarLongpressCodes = ToolbarUtilsKt.readCustomLongpressCodes(mPrefs);
|
|
|
|
return mCustomToolbarLongpressCodes.get(key.name());
|
|
|
|
}
|
2025-01-17 21:47:13 +01:00
|
|
|
|
|
|
|
public static File getCustomFontFile(final Context context) {
|
|
|
|
return new File(DeviceProtectedUtils.getFilesDir(context), "custom_font");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Nullable
|
|
|
|
public Typeface readCustomTypeface() {
|
|
|
|
// dammit, dann würde wenns keins gibt bei jedem zugriff gesucht -> 2 variablen nehmen? custom und hasCustom?
|
|
|
|
// ein clear brauchen wir sowieso on theme changed (und auch triggern wenn man ne font setzt/löscht)
|
|
|
|
// try/catch!
|
|
|
|
if (sCachedTypeface == null) {
|
|
|
|
try {
|
|
|
|
sCachedTypeface = Typeface.createFromFile(getCustomFontFile(mContext));
|
|
|
|
} catch (Exception e) { }
|
|
|
|
}
|
|
|
|
return sCachedTypeface;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void clearCachedTypeface() {
|
|
|
|
sCachedTypeface = null;
|
|
|
|
}
|
2023-07-20 12:38:07 +02:00
|
|
|
}
|