Add option to replace emoji key with different action

This commit is contained in:
Aleksandras Kostarevas 2024-06-21 20:12:11 +03:00
parent 0b48de4ac9
commit bf47b3f17c
13 changed files with 94 additions and 31 deletions

View File

@ -248,6 +248,9 @@ public final class Constants {
// Code value representing the code is not specified.
public static final int CODE_UNSPECIFIED = -15;
public static final int CODE_ACTION_0 = -1050;
public static final int CODE_ACTION_MAX = CODE_ACTION_0 + 100;
public static boolean isLetterCode(final int code) {
return code >= CODE_SPACE;
}

View File

@ -79,6 +79,7 @@ public final class KeyboardId {
public final EditorInfo mEditorInfo;
public final boolean mClobberSettingsKey;
public final boolean mBottomEmojiKeyEnabled;
public final int mBottomActionKeyId;
public final String mCustomActionLabel;
public final boolean mHasShortcutKey;
public final boolean mIsSplitLayout;
@ -95,6 +96,7 @@ public final class KeyboardId {
mEditorInfo = params.mEditorInfo;
mClobberSettingsKey = params.mNoSettingsKey;
mBottomEmojiKeyEnabled = params.mBottomEmojiKeyEnabled;
mBottomActionKeyId = params.mBottomActionKeyId;
mCustomActionLabel = (mEditorInfo.actionLabel != null)
? mEditorInfo.actionLabel.toString() : null;
mHasShortcutKey = params.mVoiceInputKeyEnabled;
@ -114,6 +116,7 @@ public final class KeyboardId {
id.mClobberSettingsKey,
id.mHasShortcutKey,
id.mBottomEmojiKeyEnabled,
id.mBottomActionKeyId,
id.isMultiLine(),
id.imeAction(),
id.mCustomActionLabel,
@ -136,6 +139,7 @@ public final class KeyboardId {
&& other.mClobberSettingsKey == mClobberSettingsKey
&& other.mHasShortcutKey == mHasShortcutKey
&& other.mBottomEmojiKeyEnabled == mBottomEmojiKeyEnabled
&& other.mBottomActionKeyId == mBottomActionKeyId
&& other.isMultiLine() == isMultiLine()
&& other.imeAction() == imeAction()
&& TextUtils.equals(other.mCustomActionLabel, mCustomActionLabel)

View File

@ -119,6 +119,7 @@ public final class KeyboardLayoutSet {
boolean mVoiceInputKeyEnabled;
boolean mNoSettingsKey;
boolean mBottomEmojiKeyEnabled;
int mBottomActionKeyId;
RichInputMethodSubtype mSubtype;
boolean mIsSpellChecker;
int mKeyboardWidth;
@ -324,8 +325,9 @@ public final class KeyboardLayoutSet {
return this;
}
public Builder setBottomEmojiKeyEnabled(final boolean enabled) {
public Builder setBottomActionKey(final boolean enabled, final int action) {
mParams.mBottomEmojiKeyEnabled = enabled;
mParams.mBottomActionKeyId = action;
return this;
}

View File

@ -127,7 +127,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
builder.setKeyboardGeometry(keyboardWidth, keyboardHeight);
builder.setSubtype(mRichImm.getCurrentSubtype());
builder.setVoiceInputKeyEnabled(settingsValues.mShowsVoiceInputKey);
builder.setBottomEmojiKeyEnabled(mLatinIMELegacy.shouldShowEmojiKey());
builder.setBottomActionKey(settingsValues.mShowsActionKey, settingsValues.mActionKeyId);
builder.setSplitLayoutEnabledByUser(ProductionFlags.IS_SPLIT_KEYBOARD_SUPPORTED
&& settingsValues.mIsSplitKeyboardEnabled);
builder.setNumberRow(settingsValues.mIsNumberRowEnabled);

View File

@ -171,11 +171,6 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
mParams = params;
mParams.mKeyStyles.addDynamicKeyStyle("bottomEmojiKeyStyle",
"!icon/emoji_normal_key|!code/key_emoji",
2,
2);
params.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
}
@ -186,6 +181,13 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
public KeyboardBuilder<KP> load(final int xmlId, final KeyboardId id) {
mParams.mId = id;
final String actionKeySpec = "!icon/action_" + id.mBottomActionKeyId + "|!code/action_" + id.mBottomActionKeyId;
mParams.mKeyStyles.addDynamicKeyStyle("bottomEmojiKeyStyle",
actionKeySpec,
2,
2);
final XmlResourceParser parser = mResources.getXml(xmlId);
try {
parseKeyboard(parser);

View File

@ -16,12 +16,16 @@
package org.futo.inputmethod.keyboard.internal;
import static org.futo.inputmethod.latin.common.Constants.CODE_ACTION_0;
import static org.futo.inputmethod.latin.common.Constants.CODE_UNSPECIFIED;
import org.futo.inputmethod.latin.common.Constants;
import java.util.HashMap;
public final class KeyboardCodesSet {
public static final String PREFIX_CODE = "!code/";
public static final String ACTION_CODE_PREFIX = "action_";
private static final HashMap<String, Integer> sNameToIdMap = new HashMap<>();
@ -30,6 +34,11 @@ public final class KeyboardCodesSet {
}
public static int getCode(final String name) {
if(name.startsWith(ACTION_CODE_PREFIX)) {
int id = CODE_ACTION_0 + Integer.parseInt(name.substring(ACTION_CODE_PREFIX.length()));
if(id >= CODE_UNSPECIFIED) throw new RuntimeException("Action ID too high!");
return id;
}
Integer id = sNameToIdMap.get(name);
if (id == null) throw new RuntimeException("Unknown key code: " + name);
return DEFAULT[id];

View File

@ -532,6 +532,13 @@ public class LatinIMELegacy implements KeyboardActionListener,
}
}
}
public void triggerAction(int actionId) {
final LatinIMELegacy latinImeLegacy = getOwnerInstance();
if (latinImeLegacy != null) {
((LatinIME) (latinImeLegacy.getInputMethodService())).getUixManager().triggerAction(actionId);
}
}
}
static final class SubtypeState {
@ -1943,13 +1950,6 @@ public class LatinIMELegacy implements KeyboardActionListener,
return mRichImm.shouldOfferSwitchingToNextInputMethod(token, fallbackValue);
}
public boolean shouldShowEmojiKey() {
// TODO: Revisit here to reorganize the settings. Probably we can/should use different
// strategy once the implementation of
// {@link InputMethodManager#shouldOfferSwitchingToNextInputMethod} is defined well.
return mSettings.getCurrent().isEmojiKeyEnabled();
}
private void setNavigationBarVisibility(final boolean visible) {
((LatinIME)mInputMethodService).updateNavigationBarVisibility(visible);
}

View File

@ -674,6 +674,14 @@ public final class InputLogic {
*/
private void handleFunctionalEvent(final Event event, final InputTransaction inputTransaction,
final int currentKeyboardScriptId, final LatinIMELegacy.UIHandler handler) {
if(event.mKeyCode <= Constants.CODE_ACTION_MAX && event.mKeyCode >= Constants.CODE_ACTION_0) {
final int actionId = event.mKeyCode - Constants.CODE_ACTION_0;
handler.triggerAction(actionId);
return;
}
switch (event.mKeyCode) {
case Constants.CODE_DELETE:
handleBackspaceEvent(event, inputTransaction, currentKeyboardScriptId);

View File

@ -101,8 +101,9 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_ENABLE_METRICS_LOGGING = "pref_enable_metrics_logging";
public static final String PREF_SHOW_EMOJI_KEY =
public static final String PREF_SHOW_ACTION_KEY =
"pref_show_emoji_key";
public static final String PREF_ACTION_KEY_ID = "pref_action_key_id";
public static final String PREF_ENABLE_NUMBER_ROW = "pref_enable_number_row";
@ -261,10 +262,6 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
R.integer.config_key_preview_linger_timeout))));
}
public static boolean readShowsEmojiKey(final SharedPreferences prefs) {
return prefs.getBoolean(PREF_SHOW_EMOJI_KEY, true);
}
public static String readPrefAdditionalSubtypes(final SharedPreferences prefs,
final Resources res) {
final String predefinedPrefSubtypes = AdditionalSubtypeUtils.createPrefSubtypes(

View File

@ -67,7 +67,9 @@ public class SettingsValues {
public final boolean mKeyPreviewPopupOn;
public final boolean mShowsVoiceInputKey;
public final boolean mIncludesOtherImesInLanguageSwitchList;
public final boolean mShowsEmojiKey;
public final boolean mShowsActionKey;
public final int mActionKeyId;
public final boolean mUseContactsDict;
public final boolean mUsePersonalizedDicts;
public final boolean mUseDoubleSpacePeriod;
@ -142,7 +144,8 @@ public class SettingsValues {
mIncludesOtherImesInLanguageSwitchList = Settings.ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS
? prefs.getBoolean(Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST, false)
: true /* forcibly */;
mShowsEmojiKey = Settings.readShowsEmojiKey(prefs);
mShowsActionKey = prefs.getBoolean(Settings.PREF_SHOW_ACTION_KEY, true);
mActionKeyId = prefs.getInt(Settings.PREF_ACTION_KEY_ID, 0);
mIsNumberRowEnabled = prefs.getBoolean(Settings.PREF_ENABLE_NUMBER_ROW, false);
mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true);
mUsePersonalizedDicts = prefs.getBoolean(Settings.PREF_KEY_USE_PERSONALIZED_DICTS, true);
@ -270,10 +273,6 @@ public class SettingsValues {
return mInputAttributes.mShouldInsertSpacesAutomatically;
}
public boolean isEmojiKeyEnabled() {
return mShowsEmojiKey;
}
public boolean isSameInputType(final EditorInfo editorInfo) {
return mInputAttributes.isSameInputType(editorInfo);
}
@ -384,8 +383,10 @@ public class SettingsValues {
sb.append("" + mShowsVoiceInputKey);
sb.append("\n mIncludesOtherImesInLanguageSwitchList = ");
sb.append("" + mIncludesOtherImesInLanguageSwitchList);
sb.append("\n mShowsEmojiKey = ");
sb.append("" + mShowsEmojiKey);
sb.append("\n mShowsActionKey = ");
sb.append("" + mShowsActionKey);
sb.append("\n mActionKeyId = ");
sb.append("" + mActionKeyId);
sb.append("\n mUseContactsDict = ");
sb.append("" + mUseContactsDict);
sb.append("\n mUsePersonalizedDicts = ");

View File

@ -24,6 +24,8 @@ import androidx.datastore.preferences.core.floatPreferencesKey
import com.google.android.material.color.DynamicColors
import org.futo.inputmethod.keyboard.internal.KeyboardIconsSet
import org.futo.inputmethod.latin.R
import org.futo.inputmethod.latin.uix.actions.ActionRegistry
import org.futo.inputmethod.latin.uix.actions.AllActions
import org.futo.inputmethod.latin.uix.theme.DarkColorScheme
import kotlin.math.roundToInt
@ -270,10 +272,13 @@ class BasicThemeProvider(val context: Context, val overrideColorScheme: ColorSch
addIcon(KeyboardIconsSet.NAME_ZWNJ_KEY, R.drawable.sym_keyboard_zwnj_lxx_dark, onBackground)
addIcon(KeyboardIconsSet.NAME_ZWJ_KEY, R.drawable.sym_keyboard_zwj_lxx_dark, onPrimary)
addIcon(KeyboardIconsSet.NAME_EMOJI_ACTION_KEY, R.drawable.smile, onPrimary)
addIcon(KeyboardIconsSet.NAME_EMOJI_NORMAL_KEY, R.drawable.smile, onBackground)
AllActions.forEachIndexed { i, it ->
addIcon("action_${i}", it.icon, onBackground)
}
// No good replacements for these icons yet, but we set them anyway for setTint
overrideDrawable(R.styleable.Keyboard_iconEnterKey, R.drawable.sym_keyboard_return_lxx_light, enterKeyForeground)
overrideDrawable(R.styleable.Keyboard_iconGoKey, R.drawable.sym_keyboard_go_lxx_light, enterKeyForeground)

View File

@ -664,6 +664,14 @@ class UixManager(private val latinIME: LatinIME) {
}
}
fun triggerAction(id: Int) {
if(currWindowAction == null) {
onActionActivated(
AllActions.getOrNull(id) ?: throw IllegalArgumentException("No such action with ID $id")
)
}
}
fun requestForgetWord(suggestedWordInfo: SuggestedWords.SuggestedWordInfo) {
keyboardManagerForAction.requestDialog(
latinIME.getString(R.string.blacklist_from_suggestions, suggestedWordInfo.mWord),

View File

@ -1,12 +1,15 @@
package org.futo.inputmethod.latin.uix.settings.pages
import android.preference.PreferenceManager
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.booleanResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.content.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.navigation.NavHostController
@ -18,14 +21,18 @@ import org.futo.inputmethod.latin.settings.Settings
import org.futo.inputmethod.latin.settings.Settings.PREF_VIBRATION_DURATION_SETTINGS
import org.futo.inputmethod.latin.uix.SHOW_EMOJI_SUGGESTIONS
import org.futo.inputmethod.latin.uix.SettingsKey
import org.futo.inputmethod.latin.uix.actions.AllActions
import org.futo.inputmethod.latin.uix.actions.ClipboardHistoryEnabled
import org.futo.inputmethod.latin.uix.settings.DropDownPicker
import org.futo.inputmethod.latin.uix.settings.ScreenTitle
import org.futo.inputmethod.latin.uix.settings.ScrollableList
import org.futo.inputmethod.latin.uix.settings.SettingItem
import org.futo.inputmethod.latin.uix.settings.SettingSlider
import org.futo.inputmethod.latin.uix.settings.SettingSliderSharedPrefsInt
import org.futo.inputmethod.latin.uix.settings.SettingToggleDataStore
import org.futo.inputmethod.latin.uix.settings.SettingToggleSharedPrefs
import org.futo.inputmethod.latin.uix.settings.useDataStore
import org.futo.inputmethod.latin.uix.settings.useSharedPrefsInt
import kotlin.math.roundToInt
val vibrationDurationSetting = SettingsKey(
@ -75,11 +82,28 @@ fun TypingScreen(navController: NavHostController = rememberNavController()) {
)
SettingToggleSharedPrefs(
title = "Emoji key",
subtitle = "Show the emoji key on the bottom row",
key = Settings.PREF_SHOW_EMOJI_KEY,
title = "Action key enabled",
subtitle = "Show the action key on the bottom row",
key = Settings.PREF_SHOW_ACTION_KEY,
default = true
)
val emojiKey = useSharedPrefsInt(key = Settings.PREF_ACTION_KEY_ID, default = 0)
SettingItem(title = "Action key") {
DropDownPicker(
label = "",
options = AllActions,
selection = AllActions[emojiKey.value],
onSet = {
emojiKey.setValue(AllActions.indexOf(it))
},
getDisplayName = {
context.getString(it.name)
},
modifier = Modifier.width(180.dp)
)
}
SettingToggleSharedPrefs(
title = stringResource(R.string.auto_cap),
subtitle = stringResource(R.string.auto_cap_summary),