Show TLD popup keys (#1399)

* Add option to replace period key's popup keys with the locale-specific top level domains for URL and email inputs. On by default.
Also change the wide keyboard's '.com' key to use the same TLD list.
Tweak TLD list order, putting default ones first, so that .com is the first TLD.

* Enable TLD hint
Avoid TLD popups on tablet
Revert to using set for TLDs, and insert default ones first
Move setting one slot up
Tweak setting description
Update docs

* Preserve case on period key

* Prevent non-TLD hints on period key
This commit is contained in:
Eran Leshem 2025-03-13 17:31:03 +02:00 committed by GitHub
parent d05a59e4ed
commit 18a328cd2b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 52 additions and 21 deletions

View file

@ -100,8 +100,6 @@ __Planned features and improvements:__
* Add and enable emoji dictionaries by default (if available for language) * Add and enable emoji dictionaries by default (if available for language)
* Clearer / more intuitive arrangement of settings * Clearer / more intuitive arrangement of settings
* Maybe hide some less used settings by default (similar to color customization) * Maybe hide some less used settings by default (similar to color customization)
* Make use of the `.com` key in URL fields (currently only available for tablets)
* With language-dependent TLDs
* [Bug fixes](https://github.com/Helium314/HeliBoard/issues?q=is%3Aissue+is%3Aopen+label%3Abug) * [Bug fixes](https://github.com/Helium314/HeliBoard/issues?q=is%3Aissue+is%3Aopen+label%3Abug)
__What will _not_ be added:__ __What will _not_ be added:__

View file

@ -15,7 +15,7 @@
{ "$": "keyboard_state_selector", "emojiKeyEnabled": { "$": "keyboard_state_selector", "alphabet": { "label": "emoji" }}}, { "$": "keyboard_state_selector", "emojiKeyEnabled": { "$": "keyboard_state_selector", "alphabet": { "label": "emoji" }}},
{ "$": "keyboard_state_selector", "symbols": { "label": "numpad" }}, { "$": "keyboard_state_selector", "symbols": { "label": "numpad" }},
{ "label": "space" }, { "label": "space" },
{ "label": "period", "labelFlags": 1073741824 }, { "label": "period" },
{ "label": "action", "width": 0.15 } { "label": "action", "width": 0.15 }
] ]
] ]

View file

@ -44,7 +44,7 @@ class LocaleKeyboardInfos(dataStream: InputStream?, locale: Locale) {
"mns" -> Key.LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO "mns" -> Key.LABEL_FLAGS_FOLLOW_KEY_LETTER_RATIO
else -> 0 else -> 0
} }
val tlds = getLocaleTlds(locale) // todo: USE IT val tlds = getLocaleTlds(locale)
init { init {
readStream(dataStream, false, true) readStream(dataStream, false, true)
@ -89,12 +89,6 @@ class LocaleKeyboardInfos(dataStream: InputStream?, locale: Locale) {
} }
} }
fun addDefaultTlds(locale: Locale) {
if ((locale.language != "en" && euroLocales.matches(locale.language)) || euroCountries.matches(locale.country))
tlds.add(".eu")
tlds.addAll(defaultTlds.splitOnWhitespace())
}
/** Pair(extraKeysLeft, extraKeysRight) */ /** Pair(extraKeysLeft, extraKeysRight) */
fun getTabletExtraKeys(elementId: Int): Pair<List<KeyData>, List<KeyData>> { fun getTabletExtraKeys(elementId: Int): Pair<List<KeyData>, List<KeyData>> {
val flags = Key.LABEL_FLAGS_FONT_DEFAULT val flags = Key.LABEL_FLAGS_FONT_DEFAULT
@ -205,7 +199,6 @@ private fun createLocaleKeyTexts(context: Context, params: KeyboardParams, popup
if (locale == params.mId.locale) return@forEach if (locale == params.mId.locale) return@forEach
lkt.addFile(getStreamForLocale(locale, context), true) lkt.addFile(getStreamForLocale(locale, context), true)
} }
lkt.addDefaultTlds(params.mId.locale)
when (popupKeysSetting) { when (popupKeysSetting) {
POPUP_KEYS_MAIN -> lkt.addFile(context.assets.open("$LOCALE_TEXTS_FOLDER/more_popups_main.txt"), false) POPUP_KEYS_MAIN -> lkt.addFile(context.assets.open("$LOCALE_TEXTS_FOLDER/more_popups_main.txt"), false)
POPUP_KEYS_MORE -> lkt.addFile(context.assets.open("$LOCALE_TEXTS_FOLDER/more_popups_more.txt"), false) POPUP_KEYS_MORE -> lkt.addFile(context.assets.open("$LOCALE_TEXTS_FOLDER/more_popups_more.txt"), false)
@ -227,19 +220,27 @@ private fun getStreamForLocale(locale: Locale, context: Context) =
} }
private fun getLocaleTlds(locale: Locale): LinkedHashSet<String> { private fun getLocaleTlds(locale: Locale): LinkedHashSet<String> {
val tlds = getDefaultTlds(locale)
val ccLower = locale.country.lowercase() val ccLower = locale.country.lowercase()
val tlds = LinkedHashSet<String>()
if (ccLower.isEmpty() || locale.language == SubtypeLocaleUtils.NO_LANGUAGE) if (ccLower.isEmpty() || locale.language == SubtypeLocaleUtils.NO_LANGUAGE)
return tlds return tlds
specialCountryTlds.forEach { specialCountryTlds.forEach {
if (ccLower != it.first) return@forEach if (ccLower != it.first) return@forEach
tlds.addAll(it.second.splitOnWhitespace()) tlds.addAll(it.second.splitOnWhitespace())
return tlds return@getLocaleTlds tlds
} }
tlds.add(".$ccLower") tlds.add(".$ccLower")
return tlds return tlds
} }
private fun getDefaultTlds(locale: Locale): LinkedHashSet<String> {
val tlds = linkedSetOf<String>()
tlds.addAll(defaultTlds.splitOnWhitespace())
if ((locale.language != "en" && euroLocales.matches(locale.language)) || euroCountries.matches(locale.country))
tlds.add(".eu")
return tlds
}
fun clearCache() = localeKeyboardInfosCache.clear() fun clearCache() = localeKeyboardInfosCache.clear()
// cache the texts, so they don't need to be read over and over // cache the texts, so they don't need to be read over and over

View file

@ -24,6 +24,7 @@ import helium314.keyboard.latin.common.StringUtils
import helium314.keyboard.latin.settings.Settings import helium314.keyboard.latin.settings.Settings
import helium314.keyboard.latin.spellcheck.AndroidSpellCheckerService import helium314.keyboard.latin.spellcheck.AndroidSpellCheckerService
import helium314.keyboard.latin.utils.InputTypeUtils import helium314.keyboard.latin.utils.InputTypeUtils
import helium314.keyboard.latin.utils.LayoutType
import helium314.keyboard.latin.utils.Log import helium314.keyboard.latin.utils.Log
import helium314.keyboard.latin.utils.ToolbarKey import helium314.keyboard.latin.utils.ToolbarKey
import helium314.keyboard.latin.utils.getCodeForToolbarKey import helium314.keyboard.latin.utils.getCodeForToolbarKey
@ -482,8 +483,7 @@ sealed interface KeyData : AbstractKeyData {
KeyLabel.DELETE -> "!icon/delete_key|!code/key_delete" KeyLabel.DELETE -> "!icon/delete_key|!code/key_delete"
KeyLabel.SHIFT -> "${getShiftLabel(params)}|!code/key_shift" KeyLabel.SHIFT -> "${getShiftLabel(params)}|!code/key_shift"
// KeyLabel.EMOJI -> "!icon/emoji_normal_key|!code/key_emoji" // KeyLabel.EMOJI -> "!icon/emoji_normal_key|!code/key_emoji"
// todo (later): label and popupKeys for .com should be in localeKeyTexts, handled similar to currency key KeyLabel.COM -> params.mLocaleKeyboardInfos.tlds.first()
KeyLabel.COM -> ".com"
KeyLabel.LANGUAGE_SWITCH -> "!icon/language_switch_key|!code/key_language_switch" KeyLabel.LANGUAGE_SWITCH -> "!icon/language_switch_key|!code/key_language_switch"
KeyLabel.ZWNJ -> "!icon/zwnj_key|\u200C" KeyLabel.ZWNJ -> "!icon/zwnj_key|\u200C"
KeyLabel.CURRENCY -> params.mLocaleKeyboardInfos.currencyKey.first KeyLabel.CURRENCY -> params.mLocaleKeyboardInfos.currencyKey.first
@ -526,8 +526,11 @@ sealed interface KeyData : AbstractKeyData {
return when (label) { return when (label) {
KeyLabel.ALPHA, KeyLabel.SYMBOL_ALPHA, KeyLabel.SYMBOL -> Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR KeyLabel.ALPHA, KeyLabel.SYMBOL_ALPHA, KeyLabel.SYMBOL -> Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR
KeyLabel.COMMA -> Key.LABEL_FLAGS_HAS_POPUP_HINT KeyLabel.COMMA -> Key.LABEL_FLAGS_HAS_POPUP_HINT
// essentially this only changes the appearance of the armenian period key in holo theme // essentially the first term only changes the appearance of the armenian period key in holo theme
KeyLabel.PERIOD -> Key.LABEL_FLAGS_HAS_POPUP_HINT and if (params.mId.isAlphabetKeyboard) params.mLocaleKeyboardInfos.labelFlags else 0 KeyLabel.PERIOD -> (Key.LABEL_FLAGS_HAS_POPUP_HINT and
if (params.mId.isAlphabetKeyboard) params.mLocaleKeyboardInfos.labelFlags else 0) or
(if (shouldShowTldPopups(params)) 0 else Key.LABEL_FLAGS_DISABLE_HINT_LABEL) or
Key.LABEL_FLAGS_PRESERVE_CASE
KeyLabel.ACTION -> { KeyLabel.ACTION -> {
Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_AUTO_X_SCALE or Key.LABEL_FLAGS_PRESERVE_CASE or Key.LABEL_FLAGS_AUTO_X_SCALE or
Key.LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR or Key.LABEL_FLAGS_FOLLOW_KEY_LABEL_RATIO or Key.LABEL_FLAGS_FOLLOW_FUNCTIONAL_TEXT_COLOR or
@ -546,12 +549,12 @@ sealed interface KeyData : AbstractKeyData {
private fun getAdditionalPopupKeys(params: KeyboardParams): PopupSet<AbstractKeyData>? { private fun getAdditionalPopupKeys(params: KeyboardParams): PopupSet<AbstractKeyData>? {
if (groupId == GROUP_COMMA) return SimplePopups(getCommaPopupKeys(params)) if (groupId == GROUP_COMMA) return SimplePopups(getCommaPopupKeys(params))
if (groupId == GROUP_PERIOD) return SimplePopups(getPunctuationPopupKeys(params)) if (groupId == GROUP_PERIOD) return getPeriodPopups(params)
if (groupId == GROUP_ENTER) return getActionKeyPopupKeys(params) if (groupId == GROUP_ENTER) return getActionKeyPopupKeys(params)
if (groupId == GROUP_NO_DEFAULT_POPUP) return null if (groupId == GROUP_NO_DEFAULT_POPUP) return null
return when (label) { return when (label) {
KeyLabel.COMMA -> SimplePopups(getCommaPopupKeys(params)) KeyLabel.COMMA -> SimplePopups(getCommaPopupKeys(params))
KeyLabel.PERIOD -> SimplePopups(getPunctuationPopupKeys(params)) KeyLabel.PERIOD -> getPeriodPopups(params)
KeyLabel.ACTION -> getActionKeyPopupKeys(params) KeyLabel.ACTION -> getActionKeyPopupKeys(params)
KeyLabel.SHIFT -> { KeyLabel.SHIFT -> {
if (params.mId.isAlphabetKeyboard) SimplePopups( if (params.mId.isAlphabetKeyboard) SimplePopups(
@ -561,13 +564,27 @@ sealed interface KeyData : AbstractKeyData {
) )
) else null // why the alphabet popup keys actually? ) else null // why the alphabet popup keys actually?
} }
KeyLabel.COM -> SimplePopups(listOf(Key.POPUP_KEYS_HAS_LABELS, ".net", ".org", ".gov", ".edu")) KeyLabel.COM -> SimplePopups(
listOf(Key.POPUP_KEYS_HAS_LABELS).plus(params.mLocaleKeyboardInfos.tlds.drop(1))
)
KeyLabel.ZWNJ -> SimplePopups(listOf("!icon/zwj_key|\u200D")) KeyLabel.ZWNJ -> SimplePopups(listOf("!icon/zwj_key|\u200D"))
// only add currency popups if there are none defined on the key // only add currency popups if there are none defined on the key
KeyLabel.CURRENCY -> if (popup.isEmpty()) SimplePopups(params.mLocaleKeyboardInfos.currencyKey.second) else null KeyLabel.CURRENCY -> if (popup.isEmpty()) SimplePopups(params.mLocaleKeyboardInfos.currencyKey.second) else null
else -> null else -> null
} }
} }
private fun getPeriodPopups(params: KeyboardParams): SimplePopups =
SimplePopups(
if (shouldShowTldPopups(params)) params.mLocaleKeyboardInfos.tlds
else getPunctuationPopupKeys(params)
)
private fun shouldShowTldPopups(params: KeyboardParams): Boolean =
(Settings.getInstance().current.mShowTldPopupKeys
&& params.mId.mSubtype.layouts[LayoutType.FUNCTIONAL] != "functional_keys_tablet"
&& params.mId.mMode in setOf(KeyboardId.MODE_URL, KeyboardId.MODE_EMAIL))
} }
/** /**

View file

@ -122,6 +122,7 @@ object Defaults {
const val PREF_POPUP_KEYS_ORDER = POPUP_KEYS_ORDER_DEFAULT const val PREF_POPUP_KEYS_ORDER = POPUP_KEYS_ORDER_DEFAULT
const val PREF_POPUP_KEYS_LABELS_ORDER = POPUP_KEYS_LABEL_DEFAULT const val PREF_POPUP_KEYS_LABELS_ORDER = POPUP_KEYS_LABEL_DEFAULT
const val PREF_SHOW_POPUP_HINTS = false const val PREF_SHOW_POPUP_HINTS = false
const val PREF_SHOW_TLD_POPUP_KEYS = true
const val PREF_MORE_POPUP_KEYS = "main" const val PREF_MORE_POPUP_KEYS = "main"
const val PREF_SPACE_TO_CHANGE_LANG = true const val PREF_SPACE_TO_CHANGE_LANG = true
const val PREF_LANGUAGE_SWIPE_DISTANCE = 5 const val PREF_LANGUAGE_SWIPE_DISTANCE = 5

View file

@ -131,6 +131,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_POPUP_KEYS_LABELS_ORDER = "popup_keys_labels_order"; public static final String PREF_POPUP_KEYS_LABELS_ORDER = "popup_keys_labels_order";
public static final String PREF_SHOW_POPUP_HINTS = "show_popup_hints"; public static final String PREF_SHOW_POPUP_HINTS = "show_popup_hints";
public static final String PREF_MORE_POPUP_KEYS = "more_popup_keys"; public static final String PREF_MORE_POPUP_KEYS = "more_popup_keys";
public static final String PREF_SHOW_TLD_POPUP_KEYS = "show_tld_popup_keys";
public static final String PREF_SPACE_TO_CHANGE_LANG = "prefs_long_press_keyboard_to_change_lang"; public static final String PREF_SPACE_TO_CHANGE_LANG = "prefs_long_press_keyboard_to_change_lang";
public static final String PREF_LANGUAGE_SWIPE_DISTANCE = "language_swipe_distance"; public static final String PREF_LANGUAGE_SWIPE_DISTANCE = "language_swipe_distance";

View file

@ -65,6 +65,7 @@ public class SettingsValues {
public final boolean mShowNumberRowHints; public final boolean mShowNumberRowHints;
public final boolean mShowsHints; public final boolean mShowsHints;
public final boolean mShowsPopupHints; public final boolean mShowsPopupHints;
public final boolean mShowTldPopupKeys;
public final boolean mSpaceForLangChange; public final boolean mSpaceForLangChange;
public final boolean mShowsEmojiKey; public final boolean mShowsEmojiKey;
public final boolean mVarToolbarDirection; public final boolean mVarToolbarDirection;
@ -172,6 +173,7 @@ public class SettingsValues {
mShowNumberRowHints = prefs.getBoolean(Settings.PREF_SHOW_NUMBER_ROW_HINTS, Defaults.PREF_SHOW_NUMBER_ROW_HINTS); mShowNumberRowHints = prefs.getBoolean(Settings.PREF_SHOW_NUMBER_ROW_HINTS, Defaults.PREF_SHOW_NUMBER_ROW_HINTS);
mShowsHints = prefs.getBoolean(Settings.PREF_SHOW_HINTS, Defaults.PREF_SHOW_HINTS); mShowsHints = prefs.getBoolean(Settings.PREF_SHOW_HINTS, Defaults.PREF_SHOW_HINTS);
mShowsPopupHints = prefs.getBoolean(Settings.PREF_SHOW_POPUP_HINTS, Defaults.PREF_SHOW_POPUP_HINTS); mShowsPopupHints = prefs.getBoolean(Settings.PREF_SHOW_POPUP_HINTS, Defaults.PREF_SHOW_POPUP_HINTS);
mShowTldPopupKeys = prefs.getBoolean(Settings.PREF_SHOW_TLD_POPUP_KEYS, Defaults.PREF_SHOW_TLD_POPUP_KEYS);
mSpaceForLangChange = prefs.getBoolean(Settings.PREF_SPACE_TO_CHANGE_LANG, Defaults.PREF_SPACE_TO_CHANGE_LANG); mSpaceForLangChange = prefs.getBoolean(Settings.PREF_SPACE_TO_CHANGE_LANG, Defaults.PREF_SPACE_TO_CHANGE_LANG);
mShowsEmojiKey = prefs.getBoolean(Settings.PREF_SHOW_EMOJI_KEY, Defaults.PREF_SHOW_EMOJI_KEY); mShowsEmojiKey = prefs.getBoolean(Settings.PREF_SHOW_EMOJI_KEY, Defaults.PREF_SHOW_EMOJI_KEY);
mVarToolbarDirection = prefs.getBoolean(Settings.PREF_VARIABLE_TOOLBAR_DIRECTION, Defaults.PREF_VARIABLE_TOOLBAR_DIRECTION); mVarToolbarDirection = prefs.getBoolean(Settings.PREF_VARIABLE_TOOLBAR_DIRECTION, Defaults.PREF_VARIABLE_TOOLBAR_DIRECTION);

View file

@ -46,6 +46,7 @@ fun PreferencesScreen(
Settings.PREF_POPUP_KEYS_LABELS_ORDER else null, Settings.PREF_POPUP_KEYS_LABELS_ORDER else null,
Settings.PREF_POPUP_KEYS_ORDER, Settings.PREF_POPUP_KEYS_ORDER,
Settings.PREF_SHOW_POPUP_HINTS, Settings.PREF_SHOW_POPUP_HINTS,
Settings.PREF_SHOW_TLD_POPUP_KEYS,
Settings.PREF_POPUP_ON, Settings.PREF_POPUP_ON,
if (AudioAndHapticFeedbackManager.getInstance().hasVibrator()) if (AudioAndHapticFeedbackManager.getInstance().hasVibrator())
Settings.PREF_VIBRATE_ON else null, Settings.PREF_VIBRATE_ON else null,
@ -89,6 +90,12 @@ fun createPreferencesSettings(context: Context) = listOf(
Setting(context, Settings.PREF_POPUP_KEYS_ORDER, R.string.popup_order) { Setting(context, Settings.PREF_POPUP_KEYS_ORDER, R.string.popup_order) {
ReorderSwitchPreference(it, Defaults.PREF_POPUP_KEYS_ORDER) ReorderSwitchPreference(it, Defaults.PREF_POPUP_KEYS_ORDER)
}, },
Setting(
context, Settings.PREF_SHOW_TLD_POPUP_KEYS, R.string.show_tld_popup_keys,
R.string.show_tld_popup_keys_summary
) {
SwitchPreference(it, Defaults.PREF_SHOW_TLD_POPUP_KEYS) { KeyboardSwitcher.getInstance().setThemeNeedsReload() }
},
Setting(context, Settings.PREF_SHOW_POPUP_HINTS, R.string.show_popup_hints, R.string.show_popup_hints_summary) { Setting(context, Settings.PREF_SHOW_POPUP_HINTS, R.string.show_popup_hints, R.string.show_popup_hints_summary) {
SwitchPreference(it, Defaults.PREF_SHOW_POPUP_HINTS) { KeyboardSwitcher.getInstance().setThemeNeedsReload() } SwitchPreference(it, Defaults.PREF_SHOW_POPUP_HINTS) { KeyboardSwitcher.getInstance().setThemeNeedsReload() }
}, },

View file

@ -249,6 +249,10 @@
<string name="hint_source">Select hint source</string> <string name="hint_source">Select hint source</string>
<!-- Title of the setting to set popup key order --> <!-- Title of the setting to set popup key order -->
<string name="popup_order">Select popup key order</string> <string name="popup_order">Select popup key order</string>
<!-- Title of the setting to show TLD popup keys -->
<string name="show_tld_popup_keys">Show TLD popup keys</string>
<!-- Description of the setting to show TLD popup keys -->
<string name="show_tld_popup_keys_summary">Replace period key popups with top level domains when typing URLs and email addresses</string>
<!-- Names of the popup key classes --> <!-- Names of the popup key classes -->
<string name="popup_keys_number" tools:keep="@string/popup_keys_number">Number row</string> <string name="popup_keys_number" tools:keep="@string/popup_keys_number">Number row</string>
<string name="popup_keys_language" tools:keep="@string/popup_keys_language">Language</string> <string name="popup_keys_language" tools:keep="@string/popup_keys_language">Language</string>

View file

@ -89,7 +89,7 @@ Usually the label is what is displayed on the key. However, there are some speci
* _symbol_alpha_: toggle alpha / symbol keyboard * _symbol_alpha_: toggle alpha / symbol keyboard
* _numpad_: toggle numpad layout * _numpad_: toggle numpad layout
* _emoji_: switch to emoji view * _emoji_: switch to emoji view
* _com_: display common TLDs (.com and similar, currently not localized) * _com_: display common TLDs (.com and similar, localized)
* _language_switch_: language switch key * _language_switch_: language switch key
* _action_: the action (enter) key * _action_: the action (enter) key
* _delete_: delete key * _delete_: delete key