mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-05-17 15:32:48 +00:00
Clipboard suggestions (#647)
This commit is contained in:
parent
21124a5a45
commit
bdab98c2c9
17 changed files with 213 additions and 18 deletions
|
@ -3,6 +3,7 @@
|
|||
package helium314.keyboard.compat;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipDescription;
|
||||
import android.content.ClipboardManager;
|
||||
import android.os.Build;
|
||||
|
||||
|
@ -29,4 +30,11 @@ public class ClipboardManagerCompat {
|
|||
}
|
||||
}
|
||||
|
||||
public static Boolean getClipSensitivity(final ClipDescription cd) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
return cd != null && cd.getExtras() != null && cd.getExtras().getBoolean("android.content.extra.IS_SENSITIVE");
|
||||
}
|
||||
return null; // can't determine
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,12 +4,24 @@ package helium314.keyboard.latin
|
|||
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.text.InputType
|
||||
import android.text.TextUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import androidx.core.view.isGone
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import helium314.keyboard.compat.ClipboardManagerCompat
|
||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode
|
||||
import helium314.keyboard.latin.common.ColorType
|
||||
import helium314.keyboard.latin.common.isValidNumber
|
||||
import helium314.keyboard.latin.databinding.ClipboardSuggestionBinding
|
||||
import helium314.keyboard.latin.settings.Settings
|
||||
import helium314.keyboard.latin.utils.DeviceProtectedUtils
|
||||
import helium314.keyboard.latin.utils.InputTypeUtils
|
||||
import helium314.keyboard.latin.utils.ToolbarKey
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class ClipboardHistoryManager(
|
||||
|
@ -18,6 +30,7 @@ class ClipboardHistoryManager(
|
|||
|
||||
private lateinit var clipboardManager: ClipboardManager
|
||||
private var onHistoryChangeListener: OnHistoryChangeListener? = null
|
||||
private var clipboardSuggestionView: View? = null
|
||||
|
||||
fun onCreate() {
|
||||
clipboardManager = latinIME.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
|
@ -36,6 +49,7 @@ class ClipboardHistoryManager(
|
|||
// Make sure we read clipboard content only if history settings is set
|
||||
if (latinIME.mSettings.current?.mClipboardHistoryEnabled == true) {
|
||||
fetchPrimaryClip()
|
||||
dontShowCurrentSuggestion = false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,6 +104,7 @@ class ClipboardHistoryManager(
|
|||
if (onHistoryChangeListener != null) {
|
||||
onHistoryChangeListener?.onClipboardHistoryEntriesRemoved(pos, count)
|
||||
}
|
||||
removeClipboardSuggestion()
|
||||
}
|
||||
|
||||
fun canRemove(index: Int) = historyEntries.getOrNull(index)?.isPinned != true
|
||||
|
@ -131,6 +146,11 @@ class ClipboardHistoryManager(
|
|||
return clipData.getItemAt(0)?.coerceToText(latinIME) ?: ""
|
||||
}
|
||||
|
||||
private fun isClipSensitive(inputType: Int): Boolean {
|
||||
ClipboardManagerCompat.getClipSensitivity(clipboardManager.primaryClip?.description)?.let { return it }
|
||||
return InputTypeUtils.isPasswordInputType(inputType)
|
||||
}
|
||||
|
||||
// pinned clips are stored in default shared preferences, not in device protected preferences!
|
||||
private fun loadPinnedClips() {
|
||||
val pinnedClipString = Settings.readPinnedClipString(latinIME)
|
||||
|
@ -156,8 +176,66 @@ class ClipboardHistoryManager(
|
|||
fun onClipboardHistoryEntryMoved(from: Int, to: Int)
|
||||
}
|
||||
|
||||
fun getClipboardSuggestionView(editorInfo: EditorInfo?, parent: ViewGroup?): View? {
|
||||
// maybe no need to create a new view
|
||||
// but a cache has to consider a few possible changes, so better don't implement without need
|
||||
clipboardSuggestionView = null
|
||||
|
||||
// get the content, or return null
|
||||
if (!latinIME.mSettings.current.mSuggestClipboardContent) return null
|
||||
if (dontShowCurrentSuggestion) return null
|
||||
if (parent == null) return null
|
||||
val clipData = clipboardManager.primaryClip ?: return null
|
||||
if (clipData.itemCount == 0 || clipData.description?.hasMimeType("text/*") == false) return null
|
||||
val clipItem = clipData.getItemAt(0) ?: return null
|
||||
val timeStamp = ClipboardManagerCompat.getClipTimestamp(clipData) ?: System.currentTimeMillis()
|
||||
if (System.currentTimeMillis() - timeStamp > RECENT_TIME_MILLIS) return null
|
||||
val content = clipItem.coerceToText(latinIME)
|
||||
if (TextUtils.isEmpty(content)) return null
|
||||
val inputType = editorInfo?.inputType ?: InputType.TYPE_NULL
|
||||
if (InputTypeUtils.isNumberInputType(inputType) && !content.isValidNumber()) return null
|
||||
|
||||
// create the view
|
||||
val binding = ClipboardSuggestionBinding.inflate(LayoutInflater.from(latinIME), parent, false)
|
||||
val textView = binding.clipboardSuggestionText
|
||||
textView.text = if (isClipSensitive(inputType)) "*".repeat(content.length) else content
|
||||
val clipIcon = latinIME.mKeyboardSwitcher.keyboard.mIconsSet.getIconDrawable(ToolbarKey.CLIPBOARD.name.lowercase())
|
||||
textView.setCompoundDrawablesRelativeWithIntrinsicBounds(clipIcon, null, null, null)
|
||||
textView.setOnClickListener {
|
||||
dontShowCurrentSuggestion = true
|
||||
latinIME.onTextInput(content.toString())
|
||||
AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(KeyCode.NOT_SPECIFIED, it);
|
||||
binding.root.isGone = true
|
||||
}
|
||||
val closeButton = binding.clipboardSuggestionClose
|
||||
closeButton.setImageDrawable(latinIME.mKeyboardSwitcher.keyboard.mIconsSet.getIconDrawable(ToolbarKey.CLOSE_HISTORY.name.lowercase()))
|
||||
closeButton.setOnClickListener { removeClipboardSuggestion() }
|
||||
|
||||
val colors = latinIME.mSettings.current.mColors
|
||||
textView.setTextColor(colors.get(ColorType.KEY_TEXT))
|
||||
clipIcon?.let { colors.setColor(it, ColorType.KEY_ICON) }
|
||||
colors.setColor(closeButton, ColorType.REMOVE_SUGGESTION_ICON)
|
||||
colors.setBackground(binding.root, ColorType.CLIPBOARD_SUGGESTION_BACKGROUND)
|
||||
|
||||
clipboardSuggestionView = binding.root
|
||||
return clipboardSuggestionView
|
||||
}
|
||||
|
||||
private fun removeClipboardSuggestion() {
|
||||
dontShowCurrentSuggestion = true
|
||||
val csv = clipboardSuggestionView ?: return
|
||||
if (csv.parent != null && !csv.isGone) {
|
||||
// clipboard view is shown ->
|
||||
latinIME.setNeutralSuggestionStrip()
|
||||
latinIME.mHandler.postResumeSuggestions(false)
|
||||
}
|
||||
csv.isGone = true
|
||||
}
|
||||
|
||||
companion object {
|
||||
// store pinned clips in companion object so they survive a keyboard switch (which destroys the current instance)
|
||||
private val historyEntries: MutableList<ClipboardHistoryEntry> = ArrayList()
|
||||
private var dontShowCurrentSuggestion: Boolean = false
|
||||
const val RECENT_TIME_MILLIS = 3 * 60 * 1000L // 3 minutes (for clipboard suggestions)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1029,12 +1029,11 @@ public class LatinIME extends InputMethodService implements
|
|||
// Space state must be updated before calling updateShiftState
|
||||
switcher.requestUpdatingShiftState(getCurrentAutoCapsState(), getCurrentRecapitalizeState());
|
||||
}
|
||||
// This will set the punctuation suggestions if next word suggestion is off;
|
||||
// otherwise it will clear the suggestion strip.
|
||||
// Set neutral suggestions and show the toolbar if the "Auto show toolbar" setting is enabled.
|
||||
if (!mHandler.hasPendingResumeSuggestions()) {
|
||||
mHandler.cancelUpdateSuggestionStrip();
|
||||
setNeutralSuggestionStrip();
|
||||
if (hasSuggestionStripView() && currentSettingsValues.mAutoShowToolbar) {
|
||||
if (hasSuggestionStripView() && currentSettingsValues.mAutoShowToolbar && !tryShowClipboardSuggestion()) {
|
||||
mSuggestionStripView.setToolbarVisibility(true);
|
||||
}
|
||||
}
|
||||
|
@ -1330,7 +1329,7 @@ public class LatinIME extends InputMethodService implements
|
|||
// Without this function the inline autofill suggestions will not be visible
|
||||
mHandler.cancelResumeSuggestions();
|
||||
|
||||
mSuggestionStripView.setInlineSuggestionsView(inlineSuggestionView);
|
||||
mSuggestionStripView.setExternalSuggestionView(inlineSuggestionView);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1652,13 +1651,33 @@ public class LatinIME extends InputMethodService implements
|
|||
updateStateAfterInputTransaction(completeInputTransaction);
|
||||
}
|
||||
|
||||
// This will show either an empty suggestion strip (if prediction is enabled) or
|
||||
// punctuation suggestions (if it's disabled).
|
||||
// The toolbar will be shown automatically if the relevant setting is enabled
|
||||
/**
|
||||
* Checks if a recent clipboard suggestion is available. If available, it is set in suggestion strip.
|
||||
* returns whether a clipboard suggestion has been set.
|
||||
*/
|
||||
public boolean tryShowClipboardSuggestion() {
|
||||
final View clipboardView = mClipboardHistoryManager.getClipboardSuggestionView(getCurrentInputEditorInfo(), mSuggestionStripView);
|
||||
if (clipboardView != null && hasSuggestionStripView()) {
|
||||
mSuggestionStripView.setExternalSuggestionView(clipboardView);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// This will first try showing a clipboard suggestion. On success, the toolbar will be hidden
|
||||
// if the "Auto hide toolbar" is enabled. Otherwise, an empty suggestion strip (if prediction
|
||||
// is enabled) or punctuation suggestions (if it's disabled) will be set.
|
||||
// Then, the toolbar will be shown automatically if the relevant setting is enabled
|
||||
// and there is a selection of text or it's the start of a line.
|
||||
@Override
|
||||
public void setNeutralSuggestionStrip() {
|
||||
final SettingsValues currentSettings = mSettings.getCurrent();
|
||||
if (tryShowClipboardSuggestion()) {
|
||||
// clipboard suggestion has been set
|
||||
if (hasSuggestionStripView() && currentSettings.mAutoHideToolbar)
|
||||
mSuggestionStripView.setToolbarVisibility(false);
|
||||
return;
|
||||
}
|
||||
final SuggestedWords neutralSuggestions = currentSettings.mBigramPredictionEnabled
|
||||
? SuggestedWords.getEmptyInstance()
|
||||
: currentSettings.mSpacingAndPunctuations.mSuggestPuncList;
|
||||
|
|
|
@ -286,6 +286,7 @@ class DynamicColors(context: Context, override val themeStyle: String, override
|
|||
KEY_BACKGROUND -> keyBackground
|
||||
ACTION_KEY_POPUP_KEYS_BACKGROUND -> if (themeStyle == STYLE_HOLO) adjustedBackground else accent
|
||||
STRIP_BACKGROUND -> if (!hasKeyBorders && themeStyle == STYLE_MATERIAL) adjustedBackground else background
|
||||
CLIPBOARD_SUGGESTION_BACKGROUND -> doubleAdjustedBackground
|
||||
NAVIGATION_BAR -> navBar
|
||||
MORE_SUGGESTIONS_HINT, SUGGESTED_WORD, SUGGESTION_TYPED_WORD, SUGGESTION_VALID_WORD -> adjustedKeyText
|
||||
ACTION_KEY_ICON, TOOL_BAR_EXPAND_KEY -> Color.WHITE
|
||||
|
@ -467,7 +468,7 @@ class DefaultColors (
|
|||
CLIPBOARD_PIN, SHIFT_KEY_ICON -> accent
|
||||
AUTOFILL_BACKGROUND_CHIP -> if (themeStyle == STYLE_MATERIAL && !hasKeyBorders) background else adjustedBackground
|
||||
GESTURE_PREVIEW, POPUP_KEYS_BACKGROUND, MORE_SUGGESTIONS_BACKGROUND, KEY_PREVIEW -> adjustedBackground
|
||||
TOOL_BAR_EXPAND_KEY_BACKGROUND -> doubleAdjustedBackground
|
||||
TOOL_BAR_EXPAND_KEY_BACKGROUND, CLIPBOARD_SUGGESTION_BACKGROUND -> doubleAdjustedBackground
|
||||
GESTURE_TRAIL -> gesture
|
||||
KEY_TEXT, REMOVE_SUGGESTION_ICON, FUNCTIONAL_KEY_TEXT, KEY_ICON -> keyText
|
||||
KEY_HINT_TEXT -> keyHintText
|
||||
|
@ -519,7 +520,7 @@ class DefaultColors (
|
|||
view.setBackgroundColor(Color.WHITE) // set white to make the color filters work
|
||||
when (color) {
|
||||
KEY_PREVIEW, POPUP_KEYS_BACKGROUND -> view.background.colorFilter = adjustedBackgroundFilter
|
||||
FUNCTIONAL_KEY_BACKGROUND, KEY_BACKGROUND, MORE_SUGGESTIONS_WORD_BACKGROUND, SPACE_BAR_BACKGROUND, STRIP_BACKGROUND -> setColor(view.background, color)
|
||||
FUNCTIONAL_KEY_BACKGROUND, KEY_BACKGROUND, MORE_SUGGESTIONS_WORD_BACKGROUND, SPACE_BAR_BACKGROUND, STRIP_BACKGROUND, CLIPBOARD_SUGGESTION_BACKGROUND -> setColor(view.background, color)
|
||||
ONE_HANDED_MODE_BUTTON -> setColor(view.background, if (keyboardBackground == null) MAIN_BACKGROUND else STRIP_BACKGROUND)
|
||||
MORE_SUGGESTIONS_BACKGROUND -> view.background.colorFilter = backgroundFilter
|
||||
MAIN_BACKGROUND -> {
|
||||
|
@ -658,6 +659,7 @@ enum class ColorType {
|
|||
ONE_HANDED_MODE_BUTTON,
|
||||
REMOVE_SUGGESTION_ICON,
|
||||
STRIP_BACKGROUND,
|
||||
CLIPBOARD_SUGGESTION_BACKGROUND,
|
||||
SUGGESTED_WORD,
|
||||
SUGGESTION_AUTO_CORRECT,
|
||||
SUGGESTION_TYPED_WORD,
|
||||
|
|
|
@ -103,6 +103,10 @@ fun String.splitOnFirstSpacesOnly(): List<String> {
|
|||
return out
|
||||
}
|
||||
|
||||
fun CharSequence.isValidNumber(): Boolean {
|
||||
return this.toString().toDoubleOrNull() != null
|
||||
}
|
||||
|
||||
fun String.decapitalize(locale: Locale): String {
|
||||
if (isEmpty() || !this[0].isUpperCase())
|
||||
return this
|
||||
|
|
|
@ -1648,7 +1648,11 @@ public final class InputLogic {
|
|||
final SuggestedWords suggestedWords = holder.get(null,
|
||||
Constants.GET_SUGGESTED_WORDS_TIMEOUT);
|
||||
if (suggestedWords != null) {
|
||||
mSuggestionStripViewAccessor.showSuggestionStrip(suggestedWords);
|
||||
// Prefer clipboard suggestions (if available and setting is enabled) over beginning of sentence predictions.
|
||||
if (!(suggestedWords.mInputStyle == SuggestedWords.INPUT_STYLE_BEGINNING_OF_SENTENCE_PREDICTION
|
||||
&& mLatinIME.tryShowClipboardSuggestion())) {
|
||||
mSuggestionStripViewAccessor.showSuggestionStrip(suggestedWords);
|
||||
}
|
||||
}
|
||||
if (DebugFlags.DEBUG_ENABLED) {
|
||||
long runTimeMillis = System.currentTimeMillis() - startTimeMillis;
|
||||
|
|
|
@ -107,6 +107,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
|||
public static final String PREF_AUTOSPACE_AFTER_PUNCTUATION = "autospace_after_punctuation";
|
||||
public static final String PREF_ALWAYS_INCOGNITO_MODE = "always_incognito_mode";
|
||||
public static final String PREF_BIGRAM_PREDICTIONS = "next_word_prediction";
|
||||
public static final String PREF_SUGGEST_CLIPBOARD_CONTENT = "suggest_clipboard_content";
|
||||
public static final String PREF_GESTURE_INPUT = "gesture_input";
|
||||
public static final String PREF_VIBRATION_DURATION_SETTINGS = "vibration_duration_settings";
|
||||
public static final String PREF_KEYPRESS_SOUND_VOLUME = "keypress_sound_volume";
|
||||
|
|
|
@ -125,6 +125,7 @@ public class SettingsValues {
|
|||
public final int mScoreLimitForAutocorrect;
|
||||
private final boolean mSuggestionsEnabledPerUserSettings;
|
||||
private final boolean mOverrideShowingSuggestions;
|
||||
public final boolean mSuggestClipboardContent;
|
||||
public final SettingsValuesForSuggestion mSettingsValuesForSuggestion;
|
||||
public final boolean mIncognitoModeEnabled;
|
||||
public final boolean mLongPressSymbolsForNumpad;
|
||||
|
@ -179,6 +180,7 @@ public class SettingsValues {
|
|||
mScoreLimitForAutocorrect = (mAutoCorrectionThreshold < 0) ? 600000 // very aggressive
|
||||
: (mAutoCorrectionThreshold < 0.07 ? 800000 : 950000); // aggressive or modest
|
||||
mBigramPredictionEnabled = readBigramPredictionEnabled(prefs, res);
|
||||
mSuggestClipboardContent = readSuggestClipboardContent(prefs, res);
|
||||
mDoubleSpacePeriodTimeout = res.getInteger(R.integer.config_double_space_period_timeout);
|
||||
mHasHardwareKeyboard = Settings.readHasHardwareKeyboard(res.getConfiguration());
|
||||
final float displayWidthDp = TypedValueCompat.pxToDp(res.getDisplayMetrics().widthPixels, res.getDisplayMetrics());
|
||||
|
@ -327,6 +329,12 @@ public class SettingsValues {
|
|||
R.bool.config_default_next_word_prediction));
|
||||
}
|
||||
|
||||
private static boolean readSuggestClipboardContent (SharedPreferences prefs,
|
||||
final Resources res) {
|
||||
return prefs.getBoolean(Settings.PREF_SUGGEST_CLIPBOARD_CONTENT, res.getBoolean(
|
||||
R.bool.config_default_suggest_clipboard_content));
|
||||
}
|
||||
|
||||
private static float readAutoCorrectionThreshold(final Resources res,
|
||||
final SharedPreferences prefs) {
|
||||
final String currentAutoCorrectionSetting = Settings.readAutoCorrectConfidence(prefs, res);
|
||||
|
|
|
@ -26,7 +26,6 @@ import android.util.AttributeSet;
|
|||
import android.util.TypedValue;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
|
@ -59,7 +58,6 @@ import helium314.keyboard.latin.settings.Settings;
|
|||
import helium314.keyboard.latin.settings.SettingsValues;
|
||||
import helium314.keyboard.latin.suggestions.PopupSuggestionsView.MoreSuggestionsListener;
|
||||
import helium314.keyboard.latin.utils.DeviceProtectedUtils;
|
||||
import helium314.keyboard.latin.utils.DialogUtilsKt;
|
||||
import helium314.keyboard.latin.utils.Log;
|
||||
import helium314.keyboard.latin.utils.ToolbarKey;
|
||||
import helium314.keyboard.latin.utils.ToolbarUtilsKt;
|
||||
|
@ -69,7 +67,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
|
||||
public final class SuggestionStripView extends RelativeLayout implements OnClickListener,
|
||||
OnLongClickListener {
|
||||
|
@ -110,7 +107,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
|||
|
||||
private final SuggestionStripLayoutHelper mLayoutHelper;
|
||||
private final StripVisibilityGroup mStripVisibilityGroup;
|
||||
private boolean isInlineAutofillSuggestionsVisible = false; // Required to disable the more suggestions if inline autofill suggestions are visible
|
||||
private boolean isExternalSuggestionVisible = false; // Required to disable the more suggestions if other suggestions are visible
|
||||
|
||||
private static class StripVisibilityGroup {
|
||||
private final View mSuggestionStripView;
|
||||
|
@ -258,7 +255,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
|||
: km.isKeyguardLocked();
|
||||
mToolbarExpandKey.setOnClickListener(hideToolbarKeys ? null : this);
|
||||
mPinnedKeys.setVisibility(hideToolbarKeys ? GONE : mSuggestionsStrip.getVisibility());
|
||||
isInlineAutofillSuggestionsVisible = false;
|
||||
isExternalSuggestionVisible = false;
|
||||
}
|
||||
|
||||
public void setRtl(final boolean isRtlLanguage) {
|
||||
|
@ -281,9 +278,9 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
|||
getContext(), mSuggestedWords, mSuggestionsStrip, this);
|
||||
}
|
||||
|
||||
public void setInlineSuggestionsView(final View view) {
|
||||
public void setExternalSuggestionView(final View view) {
|
||||
clear();
|
||||
isInlineAutofillSuggestionsVisible = true;
|
||||
isExternalSuggestionVisible = true;
|
||||
mSuggestionsStrip.addView(view);
|
||||
if (Settings.getInstance().getCurrent().mAutoHideToolbar)
|
||||
setToolbarVisibility(false);
|
||||
|
@ -548,7 +545,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
|||
public boolean onInterceptTouchEvent(final MotionEvent me) {
|
||||
|
||||
// Disable More Suggestions if inline autofill suggestions is visible
|
||||
if(isInlineAutofillSuggestionsVisible) {
|
||||
if(isExternalSuggestionVisible) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ public final class InputTypeUtils implements InputType {
|
|||
TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD;
|
||||
private static final int TEXT_VISIBLE_PASSWORD_INPUT_TYPE =
|
||||
TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
|
||||
private static final int TEXT_NUMBER_INPUT_TYPE =
|
||||
TYPE_CLASS_NUMBER | TYPE_NUMBER_FLAG_DECIMAL;
|
||||
private static final int[] SUPPRESSING_AUTO_SPACES_FIELD_VARIATION = {
|
||||
InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS,
|
||||
InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS,
|
||||
|
@ -46,6 +48,10 @@ public final class InputTypeUtils implements InputType {
|
|||
return variation == TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
|
||||
}
|
||||
|
||||
public static boolean isNumberInputType(final int inputType) {
|
||||
return (inputType & TEXT_NUMBER_INPUT_TYPE) != 0;
|
||||
}
|
||||
|
||||
public static boolean isEmailVariation(final int variation) {
|
||||
return variation == TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|
||||
|| isWebEmailAddressVariation(variation);
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2020 The Android Open Source Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="#14000000">
|
||||
<item
|
||||
android:bottom="5dp"
|
||||
android:left="5dp"
|
||||
android:right="5dp"
|
||||
android:shape="rectangle"
|
||||
android:top="5dp">
|
||||
<shape>
|
||||
<corners android:radius="32dp"/>
|
||||
<stroke android:color="#1F000000" android:width="1dp"/>
|
||||
<solid android:color="#FFFFFFFF"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
31
app/src/main/res/layout/clipboard_suggestion.xml
Normal file
31
app/src/main/res/layout/clipboard_suggestion.xml
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:background="@drawable/clipboard_suggestion_background"
|
||||
android:gravity="center"
|
||||
android:paddingRight="12dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
<TextView
|
||||
android:id="@+id/clipboard_suggestion_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/spoken_clipboard_suggestion"
|
||||
android:drawablePadding="3dp"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:hapticFeedbackEnabled="false"
|
||||
android:soundEffectsEnabled="false"
|
||||
android:singleLine="true"
|
||||
android:gravity="center"
|
||||
android:ellipsize="end"
|
||||
android:textStyle="bold"
|
||||
style="?android:attr/textAppearanceSmall" />
|
||||
<ImageView
|
||||
android:id="@+id/clipboard_suggestion_close"
|
||||
android:src="@drawable/ic_close"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center" />
|
||||
|
||||
</LinearLayout>
|
|
@ -51,6 +51,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_horizontal"
|
||||
android:hapticFeedbackEnabled="false"
|
||||
android:soundEffectsEnabled="false" />
|
||||
<LinearLayout
|
||||
|
|
|
@ -96,6 +96,9 @@
|
|||
<dimen name="config_more_suggestions_modal_tolerance">32.0dp</dimen>
|
||||
<fraction name="config_more_suggestions_info_ratio">18%</fraction>
|
||||
|
||||
<!-- Common clipboard suggestion configuration. -->
|
||||
<bool name="config_default_suggest_clipboard_content">true</bool>
|
||||
|
||||
<!-- Common gesture trail parameters -->
|
||||
<!-- Minimum distance between gesture trail sampling points. -->
|
||||
<dimen name="config_gesture_trail_min_sampling_distance">9.6dp</dimen>
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
<!-- Spoken description of a suggestion when nothing is specified and the field is blank. -->
|
||||
<string name="spoken_empty_suggestion">No suggestion</string>
|
||||
<!-- Spoken description of a suggestion when clipboard content appears as a suggestion. -->
|
||||
<string name="spoken_clipboard_suggestion">Clipboard suggestion</string>
|
||||
|
||||
<!-- Spoken description for unknown keyboard keys. -->
|
||||
<string name="spoken_description_unknown">Unknown character</string>
|
||||
|
|
|
@ -134,6 +134,10 @@
|
|||
<string name="bigram_prediction">Next-word suggestions</string>
|
||||
<!-- Description for "next word suggestion" option. This displays suggestions even when there is no input, based on the previous word. -->
|
||||
<string name="bigram_prediction_summary">Use the previous word in making suggestions</string>
|
||||
<!-- Option to enable the suggestion of clipboard content. -->
|
||||
<string name="suggest_clipboard_content">Suggest clipboard content</string>
|
||||
<!-- Description for the "suggest clipboard content" option. This makes the primary clipboard content visible in the suggestion strip view. -->
|
||||
<string name="suggest_clipboard_content_summary">Show recently copied clipboard content as a suggestion</string>
|
||||
<!-- Option to enable gesture input. The user can input a word by tracing the letters of a word without releasing the finger from the screen. [CHAR LIMIT=30]-->
|
||||
<string name="gesture_input">Enable gesture typing</string>
|
||||
<!-- Description for "gesture_input" option. The user can input a word by tracing the letters of a word without releasing the finger from the screen. [CHAR LIMIT=65]-->
|
||||
|
|
|
@ -108,6 +108,13 @@
|
|||
android:defaultValue="@bool/config_center_suggestion_text_to_enter"
|
||||
android:persistent="true" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="suggest_clipboard_content"
|
||||
android:title="@string/suggest_clipboard_content"
|
||||
android:defaultValue="@bool/config_default_suggest_clipboard_content"
|
||||
android:summary="@string/suggest_clipboard_content_summary"
|
||||
android:persistent="true" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="use_contacts"
|
||||
android:title="@string/use_contacts_dict"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue