mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-06-08 15:47:43 +00:00
upgrade build.gradle and do some code inspection stuff
This commit is contained in:
parent
f825436449
commit
528bbb4f7f
33 changed files with 192 additions and 256 deletions
|
@ -90,14 +90,22 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'androidx.core:core-ktx:1.12.0'
|
// androidx
|
||||||
|
implementation 'androidx.core:core-ktx:1.13.1'
|
||||||
implementation 'androidx.preference:preference:1.2.1'
|
implementation 'androidx.preference:preference:1.2.1'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.3.2'
|
implementation 'androidx.recyclerview:recyclerview:1.3.2'
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3"
|
|
||||||
implementation 'com.github.martin-stone:hsv-alpha-color-picker-android:3.1.0'
|
|
||||||
implementation 'androidx.autofill:autofill:1.1.0'
|
implementation 'androidx.autofill:autofill:1.1.0'
|
||||||
|
|
||||||
|
// kotlin
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3"
|
||||||
|
// when kotlin-serialization is enabled, Android Studio stops complaining about "Unresolved reference: serializer", but the build fails
|
||||||
|
// implementation "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||||
|
|
||||||
|
// color picker for user-defined colors
|
||||||
|
implementation 'com.github.martin-stone:hsv-alpha-color-picker-android:3.1.0'
|
||||||
|
|
||||||
|
// test
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
testImplementation 'org.mockito:mockito-core:5.11.0'
|
testImplementation 'org.mockito:mockito-core:5.11.0'
|
||||||
testImplementation 'org.mockito:mockito-inline:5.2.0'
|
testImplementation 'org.mockito:mockito-inline:5.2.0'
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
package helium314.keyboard.accessibility
|
package helium314.keyboard.accessibility
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.media.AudioDeviceInfo
|
|
||||||
import android.media.AudioDeviceInfo.*
|
import android.media.AudioDeviceInfo.*
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
|
|
@ -47,10 +47,9 @@ open class KeyboardAccessibilityDelegate<KV : KeyboardView>(
|
||||||
/**
|
/**
|
||||||
* Called when the keyboard layout changes.
|
* Called when the keyboard layout changes.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* **Note:** This method will be called even if accessibility is not
|
* **Note:** This method will be called even if accessibility is not
|
||||||
* enabled.
|
* enabled.
|
||||||
* @param keyboard The keyboard that is being set to the wrapping view.
|
* [keyboard]: The keyboard that is being set to the wrapping view.
|
||||||
*/
|
*/
|
||||||
open var keyboard: Keyboard?
|
open var keyboard: Keyboard?
|
||||||
get() = mKeyboard
|
get() = mKeyboard
|
||||||
|
|
|
@ -116,8 +116,7 @@ class MainKeyboardAccessibilityDelegate(
|
||||||
*/
|
*/
|
||||||
private fun announceKeyboardType(keyboard: Keyboard, lastKeyboard: Keyboard) {
|
private fun announceKeyboardType(keyboard: Keyboard, lastKeyboard: Keyboard) {
|
||||||
val lastElementId = lastKeyboard.mId.mElementId
|
val lastElementId = lastKeyboard.mId.mElementId
|
||||||
val resId: Int
|
val resId = when (keyboard.mId.mElementId) {
|
||||||
resId = when (keyboard.mId.mElementId) {
|
|
||||||
KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED, KeyboardId.ELEMENT_ALPHABET -> {
|
KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED, KeyboardId.ELEMENT_ALPHABET -> {
|
||||||
if (lastElementId == KeyboardId.ELEMENT_ALPHABET
|
if (lastElementId == KeyboardId.ELEMENT_ALPHABET
|
||||||
|| lastElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) {
|
|| lastElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) {
|
||||||
|
|
|
@ -9,7 +9,6 @@ package helium314.keyboard.event
|
||||||
import android.text.SpannableStringBuilder
|
import android.text.SpannableStringBuilder
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode
|
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode
|
||||||
import helium314.keyboard.latin.common.Constants
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,6 +22,12 @@ import java.util.*
|
||||||
* finished combining part, will be shown normally as the composing string, while the second is
|
* finished combining part, will be shown normally as the composing string, while the second is
|
||||||
* feedback on the composing state and will typically be shown with different styling such as
|
* feedback on the composing state and will typically be shown with different styling such as
|
||||||
* a colored background.
|
* a colored background.
|
||||||
|
*
|
||||||
|
* The combiner chain takes events as inputs and outputs code points and combining state.
|
||||||
|
* For example, if the input language is Japanese, the combining chain will typically perform
|
||||||
|
* kana conversion. This takes a string for initial text, taken to be present before the
|
||||||
|
* cursor: we'll start after this.
|
||||||
|
* @param initialText The text that has already been combined so far.
|
||||||
*/
|
*/
|
||||||
class CombinerChain(initialText: String) {
|
class CombinerChain(initialText: String) {
|
||||||
// The already combined text, as described above
|
// The already combined text, as described above
|
||||||
|
@ -45,16 +50,6 @@ class CombinerChain(initialText: String) {
|
||||||
mCombiners.add(HangulCombiner())
|
mCombiners.add(HangulCombiner())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an combiner chain.
|
|
||||||
*
|
|
||||||
* The combiner chain takes events as inputs and outputs code points and combining state.
|
|
||||||
* For example, if the input language is Japanese, the combining chain will typically perform
|
|
||||||
* kana conversion. This takes a string for initial text, taken to be present before the
|
|
||||||
* cursor: we'll start after this.
|
|
||||||
*
|
|
||||||
* @param initialText The text that has already been combined so far.
|
|
||||||
*/
|
|
||||||
init {
|
init {
|
||||||
// The dead key combiner is always active, and always first
|
// The dead key combiner is always active, and always first
|
||||||
mCombiners.add(DeadKeyCombiner())
|
mCombiners.add(DeadKeyCombiner())
|
||||||
|
|
|
@ -28,7 +28,7 @@ class InputTransaction(// Initial conditions
|
||||||
* @param updateType What type of shift update this requires.
|
* @param updateType What type of shift update this requires.
|
||||||
*/
|
*/
|
||||||
fun requireShiftUpdate(updateType: Int) {
|
fun requireShiftUpdate(updateType: Int) {
|
||||||
requiredShiftUpdate = Math.max(requiredShiftUpdate, updateType)
|
requiredShiftUpdate = requiredShiftUpdate.coerceAtLeast(updateType)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -191,7 +191,7 @@ public class Key implements Comparable<Key> {
|
||||||
/**
|
/**
|
||||||
* Constructor for a key on <code>PopupKeyKeyboard</code> and on <code>MoreSuggestions</code>.
|
* Constructor for a key on <code>PopupKeyKeyboard</code> and on <code>MoreSuggestions</code>.
|
||||||
*/
|
*/
|
||||||
public Key(@Nullable final String label, final String iconName, final int code,
|
public Key(@Nullable final String label, @NonNull final String iconName, final int code,
|
||||||
@Nullable final String outputText, @Nullable final String hintLabel,
|
@Nullable final String outputText, @Nullable final String hintLabel,
|
||||||
final int labelFlags, final int backgroundType, final int x, final int y,
|
final int labelFlags, final int backgroundType, final int x, final int y,
|
||||||
final int width, final int height, final int horizontalGap, final int verticalGap) {
|
final int width, final int height, final int horizontalGap, final int verticalGap) {
|
||||||
|
@ -404,7 +404,7 @@ public class Key implements Comparable<Key> {
|
||||||
&& o.mCode == mCode
|
&& o.mCode == mCode
|
||||||
&& TextUtils.equals(o.mLabel, mLabel)
|
&& TextUtils.equals(o.mLabel, mLabel)
|
||||||
&& TextUtils.equals(o.mHintLabel, mHintLabel)
|
&& TextUtils.equals(o.mHintLabel, mHintLabel)
|
||||||
&& o.mIconName == mIconName
|
&& o.mIconName.equals(mIconName)
|
||||||
&& o.mBackgroundType == mBackgroundType
|
&& o.mBackgroundType == mBackgroundType
|
||||||
&& Arrays.equals(o.mPopupKeys, mPopupKeys)
|
&& Arrays.equals(o.mPopupKeys, mPopupKeys)
|
||||||
&& TextUtils.equals(o.getOutputText(), getOutputText())
|
&& TextUtils.equals(o.getOutputText(), getOutputText())
|
||||||
|
@ -429,6 +429,7 @@ public class Key implements Comparable<Key> {
|
||||||
return o instanceof Key && equalsInternal((Key)o);
|
return o instanceof Key && equalsInternal((Key)o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return toShortString() + " " + getX() + "," + getY() + " " + getWidth() + "x" + getHeight();
|
return toShortString() + " " + getX() + "," + getY() + " " + getWidth() + "x" + getHeight();
|
||||||
|
@ -654,7 +655,7 @@ public class Key implements Comparable<Key> {
|
||||||
return (mLabelFlags & LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL) != 0;
|
return (mLabelFlags & LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final boolean isShiftedLetterActivated() {
|
private boolean isShiftedLetterActivated() {
|
||||||
return (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0
|
return (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0
|
||||||
&& !TextUtils.isEmpty(mHintLabel);
|
&& !TextUtils.isEmpty(mHintLabel);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,11 +35,11 @@ public interface KeyboardActionListener {
|
||||||
* Send a key code to the listener.
|
* Send a key code to the listener.
|
||||||
*
|
*
|
||||||
* @param primaryCode this is the code of the key that was pressed
|
* @param primaryCode this is the code of the key that was pressed
|
||||||
* @param x x-coordinate pixel of touched event. If {@link #onCodeInput} is not called by
|
* @param x x-coordinate pixel of touched event. If onCodeInput is not called by
|
||||||
* {@link PointerTracker} or so, the value should be
|
* {@link PointerTracker} or so, the value should be
|
||||||
* {@link Constants#NOT_A_COORDINATE}. If it's called on insertion from the
|
* {@link Constants#NOT_A_COORDINATE}. If it's called on insertion from the
|
||||||
* suggestion strip, it should be {@link Constants#SUGGESTION_STRIP_COORDINATE}.
|
* suggestion strip, it should be {@link Constants#SUGGESTION_STRIP_COORDINATE}.
|
||||||
* @param y y-coordinate pixel of touched event. If {@link #onCodeInput} is not called by
|
* @param y y-coordinate pixel of touched event. If #onCodeInput is not called by
|
||||||
* {@link PointerTracker} or so, the value should be
|
* {@link PointerTracker} or so, the value should be
|
||||||
* {@link Constants#NOT_A_COORDINATE}.If it's called on insertion from the
|
* {@link Constants#NOT_A_COORDINATE}.If it's called on insertion from the
|
||||||
* suggestion strip, it should be {@link Constants#SUGGESTION_STRIP_COORDINATE}.
|
* suggestion strip, it should be {@link Constants#SUGGESTION_STRIP_COORDINATE}.
|
||||||
|
@ -103,9 +103,9 @@ public interface KeyboardActionListener {
|
||||||
|
|
||||||
KeyboardActionListener EMPTY_LISTENER = new Adapter();
|
KeyboardActionListener EMPTY_LISTENER = new Adapter();
|
||||||
|
|
||||||
static int SWIPE_NO_ACTION = 0;
|
int SWIPE_NO_ACTION = 0;
|
||||||
static int SWIPE_MOVE_CURSOR = 1;
|
int SWIPE_MOVE_CURSOR = 1;
|
||||||
static int SWIPE_SWITCH_LANGUAGE = 2;
|
int SWIPE_SWITCH_LANGUAGE = 2;
|
||||||
|
|
||||||
class Adapter implements KeyboardActionListener {
|
class Adapter implements KeyboardActionListener {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -97,9 +97,9 @@ class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inp
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onMoveCursorHorizontally(_steps: Int): Boolean {
|
private fun onMoveCursorHorizontally(rawSteps: Int): Boolean {
|
||||||
if (_steps == 0) return false
|
if (rawSteps == 0) return false
|
||||||
var steps = _steps
|
var steps = rawSteps
|
||||||
// for RTL languages we want to invert pointer movement
|
// for RTL languages we want to invert pointer movement
|
||||||
if (RichInputMethodManager.getInstance().currentSubtype.isRtlSubtype) steps = -steps
|
if (RichInputMethodManager.getInstance().currentSubtype.isRtlSubtype) steps = -steps
|
||||||
val moveSteps: Int
|
val moveSteps: Int
|
||||||
|
|
|
@ -32,6 +32,7 @@ import helium314.keyboard.latin.utils.getCodeForToolbarKey
|
||||||
import helium314.keyboard.latin.utils.getCodeForToolbarKeyLongClick
|
import helium314.keyboard.latin.utils.getCodeForToolbarKeyLongClick
|
||||||
import helium314.keyboard.latin.utils.getEnabledClipboardToolbarKeys
|
import helium314.keyboard.latin.utils.getEnabledClipboardToolbarKeys
|
||||||
|
|
||||||
|
@SuppressLint("CustomViewStyleable")
|
||||||
class ClipboardHistoryView @JvmOverloads constructor(
|
class ClipboardHistoryView @JvmOverloads constructor(
|
||||||
context: Context,
|
context: Context,
|
||||||
attrs: AttributeSet?,
|
attrs: AttributeSet?,
|
||||||
|
@ -160,7 +161,7 @@ class ClipboardHistoryView @JvmOverloads constructor(
|
||||||
|
|
||||||
private fun setupToolbarKeys() {
|
private fun setupToolbarKeys() {
|
||||||
// set layout params
|
// set layout params
|
||||||
val toolbarKeyLayoutParams = LayoutParams(getResources().getDimensionPixelSize(R.dimen.config_suggestions_strip_edge_key_width), LayoutParams.MATCH_PARENT)
|
val toolbarKeyLayoutParams = LayoutParams(resources.getDimensionPixelSize(R.dimen.config_suggestions_strip_edge_key_width), LayoutParams.MATCH_PARENT)
|
||||||
toolbarKeys.forEach { it.layoutParams = toolbarKeyLayoutParams }
|
toolbarKeys.forEach { it.layoutParams = toolbarKeyLayoutParams }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -236,8 +236,7 @@ final class DynamicGridKeyboard extends Keyboard {
|
||||||
if (o instanceof Integer) {
|
if (o instanceof Integer) {
|
||||||
final int code = (Integer)o;
|
final int code = (Integer)o;
|
||||||
key = getKeyByCode(keyboards, code);
|
key = getKeyByCode(keyboards, code);
|
||||||
} else if (o instanceof String) {
|
} else if (o instanceof final String outputText) {
|
||||||
final String outputText = (String)o;
|
|
||||||
key = getKeyByOutputText(keyboards, outputText);
|
key = getKeyByOutputText(keyboards, outputText);
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Invalid object: " + o);
|
Log.w(TAG, "Invalid object: " + o);
|
||||||
|
@ -267,18 +266,20 @@ final class DynamicGridKeyboard extends Keyboard {
|
||||||
return row * mVerticalStep + mVerticalGap / 2;
|
return row * mVerticalStep + mVerticalGap / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public List<Key> getSortedKeys() {
|
public List<Key> getSortedKeys() {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (mCachedGridKeys != null) {
|
if (mCachedGridKeys != null) {
|
||||||
return mCachedGridKeys;
|
return mCachedGridKeys;
|
||||||
}
|
}
|
||||||
final ArrayList<Key> cachedKeys = new ArrayList<Key>(mGridKeys);
|
final ArrayList<Key> cachedKeys = new ArrayList<>(mGridKeys);
|
||||||
mCachedGridKeys = Collections.unmodifiableList(cachedKeys);
|
mCachedGridKeys = Collections.unmodifiableList(cachedKeys);
|
||||||
return mCachedGridKeys;
|
return mCachedGridKeys;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public List<Key> getNearestKeys(final int x, final int y) {
|
public List<Key> getNearestKeys(final int x, final int y) {
|
||||||
// TODO: Calculate the nearest key index in mGridKeys from x and y.
|
// TODO: Calculate the nearest key index in mGridKeys from x and y.
|
||||||
|
@ -312,13 +313,13 @@ final class DynamicGridKeyboard extends Keyboard {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object o) {
|
public boolean equals(final Object o) {
|
||||||
if (!(o instanceof Key)) return false;
|
if (!(o instanceof final Key key)) return false;
|
||||||
final Key key = (Key)o;
|
|
||||||
if (getCode() != key.getCode()) return false;
|
if (getCode() != key.getCode()) return false;
|
||||||
if (!TextUtils.equals(getLabel(), key.getLabel())) return false;
|
if (!TextUtils.equals(getLabel(), key.getLabel())) return false;
|
||||||
return TextUtils.equals(getOutputText(), key.getOutputText());
|
return TextUtils.equals(getOutputText(), key.getOutputText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "GridKey: " + super.toString();
|
return "GridKey: " + super.toString();
|
||||||
|
|
|
@ -121,6 +121,7 @@ object RawKeyboardParser {
|
||||||
else -> params.mId.mSubtype.keyboardLayoutSetName.substringBeforeLast("+")
|
else -> params.mId.mSubtype.keyboardLayoutSetName.substringBeforeLast("+")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo (later, see also keyboardParser): use Settings.getInstance().current.mSingleFunctionalLayout
|
||||||
private fun getFunctionalLayoutName(params: KeyboardParams) = when (params.mId.mElementId) {
|
private fun getFunctionalLayoutName(params: KeyboardParams) = when (params.mId.mElementId) {
|
||||||
KeyboardId.ELEMENT_SYMBOLS_SHIFTED -> FUNCTIONAL_LAYOUT_SYMBOLS_SHIFTED
|
KeyboardId.ELEMENT_SYMBOLS_SHIFTED -> FUNCTIONAL_LAYOUT_SYMBOLS_SHIFTED
|
||||||
KeyboardId.ELEMENT_SYMBOLS -> FUNCTIONAL_LAYOUT_SYMBOLS
|
KeyboardId.ELEMENT_SYMBOLS -> FUNCTIONAL_LAYOUT_SYMBOLS
|
||||||
|
|
|
@ -18,7 +18,7 @@ import helium314.keyboard.latin.settings.SettingsValues;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class gathers audio feedback and haptic feedback functions.
|
* This class gathers audio feedback and haptic feedback functions.
|
||||||
*
|
* <p>
|
||||||
* It offers a consistent and simple interface that allows LatinIME to forget about the
|
* It offers a consistent and simple interface that allows LatinIME to forget about the
|
||||||
* complexity of settings and the like.
|
* complexity of settings and the like.
|
||||||
*/
|
*/
|
||||||
|
@ -81,21 +81,12 @@ public final class AudioAndHapticFeedbackManager {
|
||||||
if (!mSoundOn) {
|
if (!mSoundOn) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final int sound;
|
final int sound = switch (code) {
|
||||||
switch (code) {
|
case KeyCode.DELETE -> AudioManager.FX_KEYPRESS_DELETE;
|
||||||
case KeyCode.DELETE:
|
case Constants.CODE_ENTER -> AudioManager.FX_KEYPRESS_RETURN;
|
||||||
sound = AudioManager.FX_KEYPRESS_DELETE;
|
case Constants.CODE_SPACE -> AudioManager.FX_KEYPRESS_SPACEBAR;
|
||||||
break;
|
default -> AudioManager.FX_KEYPRESS_STANDARD;
|
||||||
case Constants.CODE_ENTER:
|
};
|
||||||
sound = AudioManager.FX_KEYPRESS_RETURN;
|
|
||||||
break;
|
|
||||||
case Constants.CODE_SPACE:
|
|
||||||
sound = AudioManager.FX_KEYPRESS_SPACEBAR;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
sound = AudioManager.FX_KEYPRESS_STANDARD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mAudioManager.playSoundEffect(sound, mSettingsValues.mKeypressSoundVolume);
|
mAudioManager.playSoundEffect(sound, mSettingsValues.mKeypressSoundVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages all interactions with Contacts DB.
|
* Manages all interactions with Contacts DB.
|
||||||
*
|
* <p>
|
||||||
* The manager provides an API for listening to meaning full updates by keeping a
|
* The manager provides an API for listening to meaning full updates by keeping a
|
||||||
* measure of the current state of the content provider.
|
* measure of the current state of the content provider.
|
||||||
*/
|
*/
|
||||||
|
@ -65,7 +65,7 @@ public class ContactsManager {
|
||||||
* - How many times it has been contacted
|
* - How many times it has been contacted
|
||||||
* - How long since the last contact.
|
* - How long since the last contact.
|
||||||
* - Whether the contact is in the visible group (i.e., Contacts list).
|
* - Whether the contact is in the visible group (i.e., Contacts list).
|
||||||
*
|
* <p>
|
||||||
* Note: This affinity is limited by the fact that some apps currently do not update the
|
* Note: This affinity is limited by the fact that some apps currently do not update the
|
||||||
* LAST_TIME_CONTACTED or TIMES_CONTACTED counters. As a result, a frequently messaged
|
* LAST_TIME_CONTACTED or TIMES_CONTACTED counters. As a result, a frequently messaged
|
||||||
* contact may still have 0 affinity.
|
* contact may still have 0 affinity.
|
||||||
|
@ -101,13 +101,13 @@ public class ContactsManager {
|
||||||
* The number of contacts observed in the most recent instance of
|
* The number of contacts observed in the most recent instance of
|
||||||
* contacts content provider.
|
* contacts content provider.
|
||||||
*/
|
*/
|
||||||
private AtomicInteger mContactCountAtLastRebuild = new AtomicInteger(0);
|
private final AtomicInteger mContactCountAtLastRebuild = new AtomicInteger(0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The hash code of list of valid contacts names in the most recent dictionary
|
* The hash code of list of valid contacts names in the most recent dictionary
|
||||||
* rebuild.
|
* rebuild.
|
||||||
*/
|
*/
|
||||||
private AtomicInteger mHashCodeAtLastRebuild = new AtomicInteger(0);
|
private final AtomicInteger mHashCodeAtLastRebuild = new AtomicInteger(0);
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final ContactsContentObserver mObserver;
|
private final ContactsContentObserver mObserver;
|
||||||
|
@ -134,7 +134,7 @@ public class ContactsManager {
|
||||||
* Returns all the valid names in the Contacts DB. Callers should also
|
* Returns all the valid names in the Contacts DB. Callers should also
|
||||||
* call {@link #updateLocalState(ArrayList)} after they are done with result
|
* call {@link #updateLocalState(ArrayList)} after they are done with result
|
||||||
* so that the manager can cache local state for determining updates.
|
* so that the manager can cache local state for determining updates.
|
||||||
*
|
* <p>
|
||||||
* These names are sorted by their affinity to the user, with favorite
|
* These names are sorted by their affinity to the user, with favorite
|
||||||
* contacts appearing first.
|
* contacts appearing first.
|
||||||
*/
|
*/
|
||||||
|
@ -183,22 +183,15 @@ public class ContactsManager {
|
||||||
* Returns the number of contacts in contacts content provider.
|
* Returns the number of contacts in contacts content provider.
|
||||||
*/
|
*/
|
||||||
public int getContactCount() {
|
public int getContactCount() {
|
||||||
// TODO: consider switching to a rawQuery("select count(*)...") on the database if
|
// TODO: consider switching to a rawQuery("select count(*)...") on the database if performance is a bottleneck.
|
||||||
// performance is a bottleneck.
|
try (Cursor cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI,
|
||||||
Cursor cursor = null;
|
ContactsDictionaryConstants.PROJECTION_ID_ONLY, null, null, null)
|
||||||
try {
|
) {
|
||||||
cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI,
|
if (null == cursor)
|
||||||
ContactsDictionaryConstants.PROJECTION_ID_ONLY, null, null, null);
|
|
||||||
if (null == cursor) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
return cursor.getCount();
|
return cursor.getCount();
|
||||||
} catch (final SQLiteException e) {
|
} catch (final SQLiteException e) {
|
||||||
Log.e(TAG, "SQLiteException in the remote Contacts process.", e);
|
Log.e(TAG, "SQLiteException in the remote Contacts process.", e);
|
||||||
} finally {
|
|
||||||
if (null != cursor) {
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ import java.util.Arrays;
|
||||||
import static helium314.keyboard.latin.common.Constants.ImeOption.NO_FLOATING_GESTURE_PREVIEW;
|
import static helium314.keyboard.latin.common.Constants.ImeOption.NO_FLOATING_GESTURE_PREVIEW;
|
||||||
import static helium314.keyboard.latin.common.Constants.ImeOption.NO_MICROPHONE;
|
import static helium314.keyboard.latin.common.Constants.ImeOption.NO_MICROPHONE;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to hold attributes of the input field.
|
* Class to hold attributes of the input field.
|
||||||
*/
|
*/
|
||||||
|
@ -162,92 +164,60 @@ public final class InputAttributes {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String toInputClassString(final int inputClass) {
|
private static String toInputClassString(final int inputClass) {
|
||||||
switch (inputClass) {
|
return switch (inputClass) {
|
||||||
case InputType.TYPE_CLASS_TEXT:
|
case InputType.TYPE_CLASS_TEXT -> "TYPE_CLASS_TEXT";
|
||||||
return "TYPE_CLASS_TEXT";
|
case InputType.TYPE_CLASS_PHONE -> "TYPE_CLASS_PHONE";
|
||||||
case InputType.TYPE_CLASS_PHONE:
|
case InputType.TYPE_CLASS_NUMBER -> "TYPE_CLASS_NUMBER";
|
||||||
return "TYPE_CLASS_PHONE";
|
case InputType.TYPE_CLASS_DATETIME -> "TYPE_CLASS_DATETIME";
|
||||||
case InputType.TYPE_CLASS_NUMBER:
|
default -> String.format("unknownInputClass<0x%08x>", inputClass);
|
||||||
return "TYPE_CLASS_NUMBER";
|
};
|
||||||
case InputType.TYPE_CLASS_DATETIME:
|
|
||||||
return "TYPE_CLASS_DATETIME";
|
|
||||||
default:
|
|
||||||
return String.format("unknownInputClass<0x%08x>", inputClass);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String toVariationString(final int inputClass, final int variation) {
|
private static String toVariationString(final int inputClass, final int variation) {
|
||||||
switch (inputClass) {
|
return switch (inputClass) {
|
||||||
case InputType.TYPE_CLASS_TEXT:
|
case InputType.TYPE_CLASS_TEXT -> toTextVariationString(variation);
|
||||||
return toTextVariationString(variation);
|
case InputType.TYPE_CLASS_NUMBER -> toNumberVariationString(variation);
|
||||||
case InputType.TYPE_CLASS_NUMBER:
|
case InputType.TYPE_CLASS_DATETIME -> toDatetimeVariationString(variation);
|
||||||
return toNumberVariationString(variation);
|
default -> "";
|
||||||
case InputType.TYPE_CLASS_DATETIME:
|
};
|
||||||
return toDatetimeVariationString(variation);
|
|
||||||
default:
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String toTextVariationString(final int variation) {
|
private static String toTextVariationString(final int variation) {
|
||||||
switch (variation) {
|
return switch (variation) {
|
||||||
case InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS:
|
case InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS -> " TYPE_TEXT_VARIATION_EMAIL_ADDRESS";
|
||||||
return " TYPE_TEXT_VARIATION_EMAIL_ADDRESS";
|
case InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT -> "TYPE_TEXT_VARIATION_EMAIL_SUBJECT";
|
||||||
case InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT:
|
case InputType.TYPE_TEXT_VARIATION_FILTER -> "TYPE_TEXT_VARIATION_FILTER";
|
||||||
return "TYPE_TEXT_VARIATION_EMAIL_SUBJECT";
|
case InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE -> "TYPE_TEXT_VARIATION_LONG_MESSAGE";
|
||||||
case InputType.TYPE_TEXT_VARIATION_FILTER:
|
case InputType.TYPE_TEXT_VARIATION_NORMAL -> "TYPE_TEXT_VARIATION_NORMAL";
|
||||||
return "TYPE_TEXT_VARIATION_FILTER";
|
case InputType.TYPE_TEXT_VARIATION_PASSWORD -> "TYPE_TEXT_VARIATION_PASSWORD";
|
||||||
case InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE:
|
case InputType.TYPE_TEXT_VARIATION_PERSON_NAME -> "TYPE_TEXT_VARIATION_PERSON_NAME";
|
||||||
return "TYPE_TEXT_VARIATION_LONG_MESSAGE";
|
case InputType.TYPE_TEXT_VARIATION_PHONETIC -> "TYPE_TEXT_VARIATION_PHONETIC";
|
||||||
case InputType.TYPE_TEXT_VARIATION_NORMAL:
|
case InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS -> "TYPE_TEXT_VARIATION_POSTAL_ADDRESS";
|
||||||
return "TYPE_TEXT_VARIATION_NORMAL";
|
case InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE -> "TYPE_TEXT_VARIATION_SHORT_MESSAGE";
|
||||||
case InputType.TYPE_TEXT_VARIATION_PASSWORD:
|
case InputType.TYPE_TEXT_VARIATION_URI -> "TYPE_TEXT_VARIATION_URI";
|
||||||
return "TYPE_TEXT_VARIATION_PASSWORD";
|
case InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD -> "TYPE_TEXT_VARIATION_VISIBLE_PASSWORD";
|
||||||
case InputType.TYPE_TEXT_VARIATION_PERSON_NAME:
|
case InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT -> "TYPE_TEXT_VARIATION_WEB_EDIT_TEXT";
|
||||||
return "TYPE_TEXT_VARIATION_PERSON_NAME";
|
case InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS -> "TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS";
|
||||||
case InputType.TYPE_TEXT_VARIATION_PHONETIC:
|
case InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD -> "TYPE_TEXT_VARIATION_WEB_PASSWORD";
|
||||||
return "TYPE_TEXT_VARIATION_PHONETIC";
|
default -> String.format("unknownVariation<0x%08x>", variation);
|
||||||
case InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS:
|
};
|
||||||
return "TYPE_TEXT_VARIATION_POSTAL_ADDRESS";
|
|
||||||
case InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE:
|
|
||||||
return "TYPE_TEXT_VARIATION_SHORT_MESSAGE";
|
|
||||||
case InputType.TYPE_TEXT_VARIATION_URI:
|
|
||||||
return "TYPE_TEXT_VARIATION_URI";
|
|
||||||
case InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD:
|
|
||||||
return "TYPE_TEXT_VARIATION_VISIBLE_PASSWORD";
|
|
||||||
case InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT:
|
|
||||||
return "TYPE_TEXT_VARIATION_WEB_EDIT_TEXT";
|
|
||||||
case InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS:
|
|
||||||
return "TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS";
|
|
||||||
case InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD:
|
|
||||||
return "TYPE_TEXT_VARIATION_WEB_PASSWORD";
|
|
||||||
default:
|
|
||||||
return String.format("unknownVariation<0x%08x>", variation);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String toNumberVariationString(final int variation) {
|
private static String toNumberVariationString(final int variation) {
|
||||||
switch (variation) {
|
return switch (variation) {
|
||||||
case InputType.TYPE_NUMBER_VARIATION_NORMAL:
|
case InputType.TYPE_NUMBER_VARIATION_NORMAL -> "TYPE_NUMBER_VARIATION_NORMAL";
|
||||||
return "TYPE_NUMBER_VARIATION_NORMAL";
|
case InputType.TYPE_NUMBER_VARIATION_PASSWORD -> "TYPE_NUMBER_VARIATION_PASSWORD";
|
||||||
case InputType.TYPE_NUMBER_VARIATION_PASSWORD:
|
default -> String.format("unknownVariation<0x%08x>", variation);
|
||||||
return "TYPE_NUMBER_VARIATION_PASSWORD";
|
};
|
||||||
default:
|
|
||||||
return String.format("unknownVariation<0x%08x>", variation);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String toDatetimeVariationString(final int variation) {
|
private static String toDatetimeVariationString(final int variation) {
|
||||||
switch (variation) {
|
return switch (variation) {
|
||||||
case InputType.TYPE_DATETIME_VARIATION_NORMAL:
|
case InputType.TYPE_DATETIME_VARIATION_NORMAL -> "TYPE_DATETIME_VARIATION_NORMAL";
|
||||||
return "TYPE_DATETIME_VARIATION_NORMAL";
|
case InputType.TYPE_DATETIME_VARIATION_DATE -> "TYPE_DATETIME_VARIATION_DATE";
|
||||||
case InputType.TYPE_DATETIME_VARIATION_DATE:
|
case InputType.TYPE_DATETIME_VARIATION_TIME -> "TYPE_DATETIME_VARIATION_TIME";
|
||||||
return "TYPE_DATETIME_VARIATION_DATE";
|
default -> String.format("unknownVariation<0x%08x>", variation);
|
||||||
case InputType.TYPE_DATETIME_VARIATION_TIME:
|
};
|
||||||
return "TYPE_DATETIME_VARIATION_TIME";
|
|
||||||
default:
|
|
||||||
return String.format("unknownVariation<0x%08x>", variation);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String toFlagsString(final int flags) {
|
private static String toFlagsString(final int flags) {
|
||||||
|
@ -272,6 +242,7 @@ public final class InputAttributes {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pretty print
|
// Pretty print
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format(
|
return String.format(
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
package helium314.keyboard.latin;
|
package helium314.keyboard.latin;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -783,6 +784,7 @@ public class LatinIME extends InputMethodService implements
|
||||||
* Starts from {@link android.os.Build.VERSION_CODES#S_V2}, the returning context object has
|
* Starts from {@link android.os.Build.VERSION_CODES#S_V2}, the returning context object has
|
||||||
* became to IME context self since it ends up capable of updating its resources internally.
|
* became to IME context self since it ends up capable of updating its resources internally.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
private @NonNull Context getDisplayContext() {
|
private @NonNull Context getDisplayContext() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S_V2) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S_V2) {
|
||||||
// IME context sources is now managed by WindowProviderService from Android 12L.
|
// IME context sources is now managed by WindowProviderService from Android 12L.
|
||||||
|
@ -1104,10 +1106,6 @@ public class LatinIME extends InputMethodService implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharSequence getSelection() {
|
|
||||||
return mInputLogic.mConnection.getSelectedText(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is called when the user has clicked on the extracted text view,
|
* This is called when the user has clicked on the extracted text view,
|
||||||
* when running in fullscreen mode. The default implementation hides
|
* when running in fullscreen mode. The default implementation hides
|
||||||
|
@ -1667,14 +1665,11 @@ public class LatinIME extends InputMethodService implements
|
||||||
*/
|
*/
|
||||||
private void updateStateAfterInputTransaction(final InputTransaction inputTransaction) {
|
private void updateStateAfterInputTransaction(final InputTransaction inputTransaction) {
|
||||||
switch (inputTransaction.getRequiredShiftUpdate()) {
|
switch (inputTransaction.getRequiredShiftUpdate()) {
|
||||||
case InputTransaction.SHIFT_UPDATE_LATER:
|
case InputTransaction.SHIFT_UPDATE_LATER -> mHandler.postUpdateShiftState();
|
||||||
mHandler.postUpdateShiftState();
|
case InputTransaction.SHIFT_UPDATE_NOW -> mKeyboardSwitcher
|
||||||
break;
|
.requestUpdatingShiftState(getCurrentAutoCapsState(), getCurrentRecapitalizeState());
|
||||||
case InputTransaction.SHIFT_UPDATE_NOW:
|
default -> {
|
||||||
mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(),
|
} // SHIFT_NO_UPDATE
|
||||||
getCurrentRecapitalizeState());
|
|
||||||
break;
|
|
||||||
default: // SHIFT_NO_UPDATE
|
|
||||||
}
|
}
|
||||||
if (inputTransaction.requiresUpdateSuggestions()) {
|
if (inputTransaction.requiresUpdateSuggestions()) {
|
||||||
final int inputStyle;
|
final int inputStyle;
|
||||||
|
@ -1897,6 +1892,7 @@ public class LatinIME extends InputMethodService implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SwitchIntDef")
|
||||||
@Override
|
@Override
|
||||||
public void onTrimMemory(int level) {
|
public void onTrimMemory(int level) {
|
||||||
super.onTrimMemory(level);
|
super.onTrimMemory(level);
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
|
|
||||||
package helium314.keyboard.latin;
|
package helium314.keyboard.latin;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import helium314.keyboard.keyboard.internal.KeySpecParser;
|
import helium314.keyboard.keyboard.internal.KeySpecParser;
|
||||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode;
|
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode;
|
||||||
import helium314.keyboard.latin.common.Constants;
|
|
||||||
import helium314.keyboard.latin.common.StringUtils;
|
import helium314.keyboard.latin.common.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -18,7 +18,7 @@ import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The extended {@link SuggestedWords} class to represent punctuation suggestions.
|
* The extended {@link SuggestedWords} class to represent punctuation suggestions.
|
||||||
*
|
* <p>
|
||||||
* Each punctuation specification string is the key specification that can be parsed by
|
* Each punctuation specification string is the key specification that can be parsed by
|
||||||
* {@link KeySpecParser}.
|
* {@link KeySpecParser}.
|
||||||
*/
|
*/
|
||||||
|
@ -44,7 +44,7 @@ public final class PunctuationSuggestions extends SuggestedWords {
|
||||||
public static PunctuationSuggestions newPunctuationSuggestions(
|
public static PunctuationSuggestions newPunctuationSuggestions(
|
||||||
@Nullable final String[] punctuationSpecs) {
|
@Nullable final String[] punctuationSpecs) {
|
||||||
if (punctuationSpecs == null || punctuationSpecs.length == 0) {
|
if (punctuationSpecs == null || punctuationSpecs.length == 0) {
|
||||||
return new PunctuationSuggestions(new ArrayList<SuggestedWordInfo>(0));
|
return new PunctuationSuggestions(new ArrayList<>(0));
|
||||||
}
|
}
|
||||||
final ArrayList<SuggestedWordInfo> punctuationList =
|
final ArrayList<SuggestedWordInfo> punctuationList =
|
||||||
new ArrayList<>(punctuationSpecs.length);
|
new ArrayList<>(punctuationSpecs.length);
|
||||||
|
@ -99,7 +99,7 @@ public final class PunctuationSuggestions extends SuggestedWords {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
@NonNull public String toString() {
|
||||||
return "PunctuationSuggestions: "
|
return "PunctuationSuggestions: "
|
||||||
+ " words=" + Arrays.toString(mSuggestedWordInfoList.toArray());
|
+ " words=" + Arrays.toString(mSuggestedWordInfoList.toArray());
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ import helium314.keyboard.keyboard.KeyboardSwitcher;
|
||||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode;
|
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode;
|
||||||
import helium314.keyboard.latin.SuggestedWords.SuggestedWordInfo;
|
import helium314.keyboard.latin.SuggestedWords.SuggestedWordInfo;
|
||||||
import helium314.keyboard.latin.common.ComposedData;
|
import helium314.keyboard.latin.common.ComposedData;
|
||||||
import helium314.keyboard.latin.common.Constants;
|
|
||||||
import helium314.keyboard.latin.common.CoordinateUtils;
|
import helium314.keyboard.latin.common.CoordinateUtils;
|
||||||
import helium314.keyboard.latin.common.InputPointers;
|
import helium314.keyboard.latin.common.InputPointers;
|
||||||
import helium314.keyboard.latin.common.StringUtils;
|
import helium314.keyboard.latin.common.StringUtils;
|
||||||
|
@ -167,7 +166,7 @@ public final class WordComposer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply a processed input event.
|
* Apply a processed input event.
|
||||||
*
|
* <p>
|
||||||
* All input events should be supported, including software/hardware events, characters as well
|
* All input events should be supported, including software/hardware events, characters as well
|
||||||
* as deletions, multiple inputs and gestures.
|
* as deletions, multiple inputs and gestures.
|
||||||
*
|
*
|
||||||
|
@ -320,7 +319,7 @@ public final class WordComposer {
|
||||||
/**
|
/**
|
||||||
* Whether this composer is composing or about to compose a word in which only the first letter
|
* Whether this composer is composing or about to compose a word in which only the first letter
|
||||||
* is a capital.
|
* is a capital.
|
||||||
*
|
* <p>
|
||||||
* If we do have a composing word, we just return whether the word has indeed only its first
|
* If we do have a composing word, we just return whether the word has indeed only its first
|
||||||
* character capitalized. If we don't, then we return a value based on the capitalized mode,
|
* character capitalized. If we don't, then we return a value based on the capitalized mode,
|
||||||
* which tell us what is likely to happen for the next composing word.
|
* which tell us what is likely to happen for the next composing word.
|
||||||
|
@ -370,7 +369,7 @@ public final class WordComposer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the caps mode at the start of composing.
|
* Saves the caps mode at the start of composing.
|
||||||
*
|
* <p>
|
||||||
* WordComposer needs to know about the caps mode for several reasons. The first is, we need
|
* WordComposer needs to know about the caps mode for several reasons. The first is, we need
|
||||||
* to know after the fact what the reason was, to register the correct form into the user
|
* to know after the fact what the reason was, to register the correct form into the user
|
||||||
* history dictionary: if the word was automatically capitalized, we should insert it in
|
* history dictionary: if the word was automatically capitalized, we should insert it in
|
||||||
|
@ -385,7 +384,7 @@ public final class WordComposer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Before fetching suggestions, we don't necessarily know about the capitalized mode yet.
|
* Before fetching suggestions, we don't necessarily know about the capitalized mode yet.
|
||||||
*
|
* <p>
|
||||||
* If we don't have a composing word yet, we take a note of this mode so that we can then
|
* If we don't have a composing word yet, we take a note of this mode so that we can then
|
||||||
* supply this information to the suggestion process. If we have a composing word, then
|
* supply this information to the suggestion process. If we have a composing word, then
|
||||||
* the previous mode has priority over this.
|
* the previous mode has priority over this.
|
||||||
|
|
|
@ -58,7 +58,7 @@ object LocaleUtils {
|
||||||
// The compared locales are fully identical. This is the best match level.
|
// The compared locales are fully identical. This is the best match level.
|
||||||
private const val LOCALE_FULL_MATCH = 30
|
private const val LOCALE_FULL_MATCH = 30
|
||||||
|
|
||||||
const val LOCALE_GOOD_MATCH = LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
|
const val LOCALE_GOOD_MATCH = LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return how well a tested locale matches a reference locale.
|
* Return how well a tested locale matches a reference locale.
|
||||||
|
|
|
@ -82,12 +82,8 @@ class InputLogicHandler implements Handler.Callback {
|
||||||
// Called on the Non-UI handler thread by the Handler code.
|
// Called on the Non-UI handler thread by the Handler code.
|
||||||
@Override
|
@Override
|
||||||
public boolean handleMessage(final Message msg) {
|
public boolean handleMessage(final Message msg) {
|
||||||
switch (msg.what) {
|
if (msg.what == MSG_GET_SUGGESTED_WORDS)
|
||||||
case MSG_GET_SUGGESTED_WORDS:
|
mLatinIME.getSuggestedWords(msg.arg1, msg.arg2, (OnGetSuggestedWordsCallback) msg.obj);
|
||||||
mLatinIME.getSuggestedWords(msg.arg1 /* inputStyle */,
|
|
||||||
msg.arg2 /* sequenceNumber */, (OnGetSuggestedWordsCallback) msg.obj);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,12 +118,7 @@ class InputLogicHandler implements Handler.Callback {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mInputLogic.mWordComposer.setBatchInputPointers(batchPointers);
|
mInputLogic.mWordComposer.setBatchInputPointers(batchPointers);
|
||||||
final OnGetSuggestedWordsCallback callback = new OnGetSuggestedWordsCallback() {
|
final OnGetSuggestedWordsCallback callback = suggestedWords -> showGestureSuggestionsWithPreviewVisuals(suggestedWords, isTailBatchInput);
|
||||||
@Override
|
|
||||||
public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
|
|
||||||
showGestureSuggestionsWithPreviewVisuals(suggestedWords, isTailBatchInput);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
getSuggestedWords(isTailBatchInput ? SuggestedWords.INPUT_STYLE_TAIL_BATCH
|
getSuggestedWords(isTailBatchInput ? SuggestedWords.INPUT_STYLE_TAIL_BATCH
|
||||||
: SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber, callback);
|
: SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber, callback);
|
||||||
}
|
}
|
||||||
|
@ -159,7 +150,7 @@ class InputLogicHandler implements Handler.Callback {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a batch input.
|
* Update a batch input.
|
||||||
*
|
* <p>
|
||||||
* This fetches suggestions and updates the suggestion strip and the floating text preview.
|
* This fetches suggestions and updates the suggestion strip and the floating text preview.
|
||||||
*
|
*
|
||||||
* @param batchPointers the updated batch pointers.
|
* @param batchPointers the updated batch pointers.
|
||||||
|
@ -168,12 +159,12 @@ class InputLogicHandler implements Handler.Callback {
|
||||||
// Called on the UI thread by InputLogic.
|
// Called on the UI thread by InputLogic.
|
||||||
public void onUpdateBatchInput(final InputPointers batchPointers,
|
public void onUpdateBatchInput(final InputPointers batchPointers,
|
||||||
final int sequenceNumber) {
|
final int sequenceNumber) {
|
||||||
updateBatchInput(batchPointers, sequenceNumber, false /* isTailBatchInput */);
|
updateBatchInput(batchPointers, sequenceNumber, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel a batch input.
|
* Cancel a batch input.
|
||||||
*
|
* <p>
|
||||||
* Note that as opposed to updateTailBatchInput, we do the UI side of this immediately on the
|
* Note that as opposed to updateTailBatchInput, we do the UI side of this immediately on the
|
||||||
* same thread, rather than get this to call a method in LatinIME. This is because
|
* same thread, rather than get this to call a method in LatinIME. This is because
|
||||||
* canceling a batch input does not necessitate the long operation of pulling suggestions.
|
* canceling a batch input does not necessitate the long operation of pulling suggestions.
|
||||||
|
@ -187,7 +178,7 @@ class InputLogicHandler implements Handler.Callback {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trigger an update for a tail batch input.
|
* Trigger an update for a tail batch input.
|
||||||
*
|
* <p>
|
||||||
* A tail batch input is the last update for a gesture, the one that is triggered after the
|
* A tail batch input is the last update for a gesture, the one that is triggered after the
|
||||||
* user lifts their finger. This method schedules fetching suggestions on the non-UI thread,
|
* user lifts their finger. This method schedules fetching suggestions on the non-UI thread,
|
||||||
* then when the suggestions are computed it comes back on the UI thread to update the
|
* then when the suggestions are computed it comes back on the UI thread to update the
|
||||||
|
@ -199,7 +190,7 @@ class InputLogicHandler implements Handler.Callback {
|
||||||
// Called on the UI thread by InputLogic.
|
// Called on the UI thread by InputLogic.
|
||||||
public void updateTailBatchInput(final InputPointers batchPointers,
|
public void updateTailBatchInput(final InputPointers batchPointers,
|
||||||
final int sequenceNumber) {
|
final int sequenceNumber) {
|
||||||
updateBatchInput(batchPointers, sequenceNumber, true /* isTailBatchInput */);
|
updateBatchInput(batchPointers, sequenceNumber, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getSuggestedWords(final int inputStyle, final int sequenceNumber,
|
public void getSuggestedWords(final int inputStyle, final int sequenceNumber,
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
package helium314.keyboard.latin.makedict;
|
package helium314.keyboard.latin.makedict;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.BinaryDictionary;
|
import com.android.inputmethod.latin.BinaryDictionary;
|
||||||
|
@ -20,7 +21,7 @@ import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for a word with a probability.
|
* Utility class for a word with a probability.
|
||||||
*
|
* <p>
|
||||||
* This is chiefly used to iterate a dictionary.
|
* This is chiefly used to iterate a dictionary.
|
||||||
*/
|
*/
|
||||||
public final class WordProperty implements Comparable<WordProperty> {
|
public final class WordProperty implements Comparable<WordProperty> {
|
||||||
|
@ -150,7 +151,7 @@ public final class WordProperty implements Comparable<WordProperty> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Three-way comparison.
|
* Three-way comparison.
|
||||||
*
|
* <p>
|
||||||
* A Word x is greater than a word y if x has a higher frequency. If they have the same
|
* A Word x is greater than a word y if x has a higher frequency. If they have the same
|
||||||
* frequency, they are sorted in lexicographic order.
|
* frequency, they are sorted in lexicographic order.
|
||||||
*/
|
*/
|
||||||
|
@ -163,15 +164,14 @@ public final class WordProperty implements Comparable<WordProperty> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equality test.
|
* Equality test.
|
||||||
*
|
* <p>
|
||||||
* Words are equal if they have the same frequency, the same spellings, and the same
|
* Words are equal if they have the same frequency, the same spellings, and the same
|
||||||
* attributes.
|
* attributes.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (o == this) return true;
|
if (o == this) return true;
|
||||||
if (!(o instanceof WordProperty)) return false;
|
if (!(o instanceof WordProperty w)) return false;
|
||||||
WordProperty w = (WordProperty)o;
|
|
||||||
return mProbabilityInfo.equals(w.mProbabilityInfo) && mWord.equals(w.mWord)
|
return mProbabilityInfo.equals(w.mProbabilityInfo) && mWord.equals(w.mWord)
|
||||||
&& mShortcutTargets.equals(w.mShortcutTargets) && equals(mNgrams, w.mNgrams)
|
&& mShortcutTargets.equals(w.mShortcutTargets) && equals(mNgrams, w.mNgrams)
|
||||||
&& mIsNotAWord == w.mIsNotAWord && mIsPossiblyOffensive == w.mIsPossiblyOffensive
|
&& mIsNotAWord == w.mIsNotAWord && mIsPossiblyOffensive == w.mIsPossiblyOffensive
|
||||||
|
@ -199,7 +199,7 @@ public final class WordProperty implements Comparable<WordProperty> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
@NonNull public String toString() {
|
||||||
return CombinedFormatUtils.formatWordProperty(this);
|
return CombinedFormatUtils.formatWordProperty(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ public final class PermissionsActivity
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(Bundle outState) {
|
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
outState.putInt(EXTRA_PERMISSION_REQUEST_CODE, mPendingRequestCode);
|
outState.putInt(EXTRA_PERMISSION_REQUEST_CODE, mPendingRequestCode);
|
||||||
}
|
}
|
||||||
|
@ -68,8 +68,8 @@ public final class PermissionsActivity
|
||||||
// Only do request when there is no pending request to avoid duplicated requests.
|
// Only do request when there is no pending request to avoid duplicated requests.
|
||||||
if (mPendingRequestCode == INVALID_REQUEST_CODE) {
|
if (mPendingRequestCode == INVALID_REQUEST_CODE) {
|
||||||
final Bundle extras = getIntent().getExtras();
|
final Bundle extras = getIntent().getExtras();
|
||||||
final String[] permissionsToRequest =
|
if (extras == null) return;
|
||||||
extras.getStringArray(EXTRA_PERMISSION_REQUESTED_PERMISSIONS);
|
final String[] permissionsToRequest = extras.getStringArray(EXTRA_PERMISSION_REQUESTED_PERMISSIONS);
|
||||||
mPendingRequestCode = extras.getInt(EXTRA_PERMISSION_REQUEST_CODE);
|
mPendingRequestCode = extras.getInt(EXTRA_PERMISSION_REQUEST_CODE);
|
||||||
// Assuming that all supplied permissions are not granted yet, so that we don't need to
|
// Assuming that all supplied permissions are not granted yet, so that we don't need to
|
||||||
// check them again.
|
// check them again.
|
||||||
|
|
|
@ -73,6 +73,7 @@ import java.util.zip.ZipOutputStream
|
||||||
* - Improve keyboard
|
* - Improve keyboard
|
||||||
* - Debug settings
|
* - Debug settings
|
||||||
*/
|
*/
|
||||||
|
@Suppress("KotlinConstantConditions") // build type might be a constant, but depends on... build type!
|
||||||
class AdvancedSettingsFragment : SubScreenFragment() {
|
class AdvancedSettingsFragment : SubScreenFragment() {
|
||||||
private val libfile by lazy { File(requireContext().filesDir.absolutePath + File.separator + JniUtils.JNI_LIB_IMPORT_FILE_NAME) }
|
private val libfile by lazy { File(requireContext().filesDir.absolutePath + File.separator + JniUtils.JNI_LIB_IMPORT_FILE_NAME) }
|
||||||
private val backupFilePatterns by lazy { listOf(
|
private val backupFilePatterns by lazy { listOf(
|
||||||
|
@ -436,8 +437,8 @@ class AdvancedSettingsFragment : SubScreenFragment() {
|
||||||
}
|
}
|
||||||
checkVersionUpgrade(requireContext())
|
checkVersionUpgrade(requireContext())
|
||||||
Settings.getInstance().startListener()
|
Settings.getInstance().startListener()
|
||||||
val additionalSubtypes = Settings.readPrefAdditionalSubtypes(sharedPreferences, resources);
|
val additionalSubtypes = Settings.readPrefAdditionalSubtypes(sharedPreferences, resources)
|
||||||
updateAdditionalSubtypes(AdditionalSubtypeUtils.createAdditionalSubtypesArray(additionalSubtypes));
|
updateAdditionalSubtypes(AdditionalSubtypeUtils.createAdditionalSubtypesArray(additionalSubtypes))
|
||||||
reloadEnabledSubtypes(requireContext())
|
reloadEnabledSubtypes(requireContext())
|
||||||
val newDictBroadcast = Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION)
|
val newDictBroadcast = Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION)
|
||||||
activity?.sendBroadcast(newDictBroadcast)
|
activity?.sendBroadcast(newDictBroadcast)
|
||||||
|
|
|
@ -21,7 +21,6 @@ import helium314.keyboard.latin.R;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.content.res.AppCompatResources;
|
import androidx.appcompat.content.res.AppCompatResources;
|
||||||
import androidx.appcompat.widget.AppCompatTextView;
|
import androidx.appcompat.widget.AppCompatTextView;
|
||||||
import androidx.core.view.ViewCompat;
|
|
||||||
|
|
||||||
public final class SetupStartIndicatorView extends LinearLayout {
|
public final class SetupStartIndicatorView extends LinearLayout {
|
||||||
public SetupStartIndicatorView(final Context context, final AttributeSet attrs) {
|
public SetupStartIndicatorView(final Context context, final AttributeSet attrs) {
|
||||||
|
@ -72,13 +71,13 @@ public final class SetupStartIndicatorView extends LinearLayout {
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(@NonNull final Canvas canvas) {
|
protected void onDraw(@NonNull final Canvas canvas) {
|
||||||
super.onDraw(canvas);
|
super.onDraw(canvas);
|
||||||
final int layoutDirection = ViewCompat.getLayoutDirection(this);
|
final int layoutDirection = getLayoutDirection();
|
||||||
final int width = getWidth();
|
final int width = getWidth();
|
||||||
final int height = getHeight();
|
final int height = getHeight();
|
||||||
final float halfHeight = height / 2.0f;
|
final float halfHeight = height / 2.0f;
|
||||||
final Path path = mIndicatorPath;
|
final Path path = mIndicatorPath;
|
||||||
path.rewind();
|
path.rewind();
|
||||||
if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) {
|
if (layoutDirection == View.LAYOUT_DIRECTION_RTL) {
|
||||||
// Left arrow
|
// Left arrow
|
||||||
path.moveTo(width, 0.0f);
|
path.moveTo(width, 0.0f);
|
||||||
path.lineTo(0.0f, halfHeight);
|
path.lineTo(0.0f, halfHeight);
|
||||||
|
|
|
@ -13,9 +13,9 @@ import android.graphics.Path;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import helium314.keyboard.latin.R;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import androidx.core.view.ViewCompat;
|
import helium314.keyboard.latin.R;
|
||||||
|
|
||||||
public final class SetupStepIndicatorView extends View {
|
public final class SetupStepIndicatorView extends View {
|
||||||
private final Path mIndicatorPath = new Path();
|
private final Path mIndicatorPath = new Path();
|
||||||
|
@ -29,17 +29,17 @@ public final class SetupStepIndicatorView extends View {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIndicatorPosition(final int stepPos, final int totalStepNum) {
|
public void setIndicatorPosition(final int stepPos, final int totalStepNum) {
|
||||||
final int layoutDirection = ViewCompat.getLayoutDirection(this);
|
final int layoutDirection = getLayoutDirection();
|
||||||
// The indicator position is the center of the partition that is equally divided into
|
// The indicator position is the center of the partition that is equally divided into
|
||||||
// the total step number.
|
// the total step number.
|
||||||
final float partionWidth = 1.0f / totalStepNum;
|
final float partionWidth = 1.0f / totalStepNum;
|
||||||
final float pos = stepPos * partionWidth + partionWidth / 2.0f;
|
final float pos = stepPos * partionWidth + partionWidth / 2.0f;
|
||||||
mXRatio = (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) ? 1.0f - pos : pos;
|
mXRatio = (layoutDirection == View.LAYOUT_DIRECTION_RTL) ? 1.0f - pos : pos;
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(final Canvas canvas) {
|
protected void onDraw(@NonNull final Canvas canvas) {
|
||||||
super.onDraw(canvas);
|
super.onDraw(canvas);
|
||||||
final int xPos = (int)(getWidth() * mXRatio);
|
final int xPos = (int)(getWidth() * mXRatio);
|
||||||
final int height = getHeight();
|
final int height = getHeight();
|
||||||
|
|
|
@ -7,10 +7,12 @@
|
||||||
package helium314.keyboard.latin.suggestions;
|
package helium314.keyboard.latin.suggestions;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import helium314.keyboard.keyboard.Key;
|
import helium314.keyboard.keyboard.Key;
|
||||||
import helium314.keyboard.keyboard.Keyboard;
|
import helium314.keyboard.keyboard.Keyboard;
|
||||||
import helium314.keyboard.keyboard.internal.KeyboardBuilder;
|
import helium314.keyboard.keyboard.internal.KeyboardBuilder;
|
||||||
|
@ -45,12 +47,11 @@ public final class MoreSuggestions extends Keyboard {
|
||||||
|
|
||||||
public int layout(final SuggestedWords suggestedWords, final int fromIndex,
|
public int layout(final SuggestedWords suggestedWords, final int fromIndex,
|
||||||
final int maxWidth, final int minWidth, final int maxRow, final Paint paint,
|
final int maxWidth, final int minWidth, final int maxRow, final Paint paint,
|
||||||
final Resources res) {
|
final Context context) {
|
||||||
clearKeys();
|
clearKeys();
|
||||||
mDivider = res.getDrawable(R.drawable.more_suggestions_divider);
|
mDivider = ContextCompat.getDrawable(context, R.drawable.more_suggestions_divider);
|
||||||
mDividerWidth = mDivider.getIntrinsicWidth();
|
mDividerWidth = mDivider == null ? 0 : mDivider.getIntrinsicWidth();
|
||||||
final float padding = res.getDimension(
|
final float padding = context.getResources().getDimension(R.dimen.config_more_suggestions_key_horizontal_padding);
|
||||||
R.dimen.config_more_suggestions_key_horizontal_padding);
|
|
||||||
|
|
||||||
int row = 0;
|
int row = 0;
|
||||||
int index = fromIndex;
|
int index = fromIndex;
|
||||||
|
@ -186,7 +187,7 @@ public final class MoreSuggestions extends Keyboard {
|
||||||
mParams.mVerticalGap = mParams.mTopPadding = parentKeyboard.mVerticalGap / 2;
|
mParams.mVerticalGap = mParams.mTopPadding = parentKeyboard.mVerticalGap / 2;
|
||||||
mPaneView.updateKeyboardGeometry(mParams.mDefaultAbsoluteRowHeight);
|
mPaneView.updateKeyboardGeometry(mParams.mDefaultAbsoluteRowHeight);
|
||||||
final int count = mParams.layout(suggestedWords, fromIndex, maxWidth, minWidth, maxRow,
|
final int count = mParams.layout(suggestedWords, fromIndex, maxWidth, minWidth, maxRow,
|
||||||
mPaneView.newLabelPaint(null /* key */), mResources);
|
mPaneView.newLabelPaint(null /* key */), getMContext());
|
||||||
mFromIndex = fromIndex;
|
mFromIndex = fromIndex;
|
||||||
mToIndex = fromIndex + count;
|
mToIndex = fromIndex + count;
|
||||||
mSuggestedWords = suggestedWords;
|
mSuggestedWords = suggestedWords;
|
||||||
|
@ -194,7 +195,7 @@ public final class MoreSuggestions extends Keyboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MoreSuggestions build() {
|
@NonNull public MoreSuggestions build() {
|
||||||
final MoreSuggestionsParam params = mParams;
|
final MoreSuggestionsParam params = mParams;
|
||||||
for (int index = mFromIndex; index < mToIndex; index++) {
|
for (int index = mFromIndex; index < mToIndex; index++) {
|
||||||
final int x = params.getX(index);
|
final int x = params.getX(index);
|
||||||
|
|
|
@ -67,8 +67,8 @@ import java.util.ArrayList;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.widget.PopupMenu;
|
import androidx.appcompat.widget.PopupMenu;
|
||||||
import androidx.core.view.ViewCompat;
|
|
||||||
|
|
||||||
public final class SuggestionStripView extends RelativeLayout implements OnClickListener,
|
public final class SuggestionStripView extends RelativeLayout implements OnClickListener,
|
||||||
OnLongClickListener {
|
OnLongClickListener {
|
||||||
|
@ -76,7 +76,6 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
void pickSuggestionManually(SuggestedWordInfo word);
|
void pickSuggestionManually(SuggestedWordInfo word);
|
||||||
void onCodeInput(int primaryCode, int x, int y, boolean isKeyRepeat);
|
void onCodeInput(int primaryCode, int x, int y, boolean isKeyRepeat);
|
||||||
void removeSuggestion(final String word);
|
void removeSuggestion(final String word);
|
||||||
CharSequence getSelection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean DEBUG_SUGGESTIONS;
|
public static boolean DEBUG_SUGGESTIONS;
|
||||||
|
@ -124,8 +123,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLayoutDirection(final int layoutDirection) {
|
public void setLayoutDirection(final int layoutDirection) {
|
||||||
ViewCompat.setLayoutDirection(mSuggestionStripView, layoutDirection);
|
mSuggestionStripView.setLayoutDirection(layoutDirection);
|
||||||
ViewCompat.setLayoutDirection(mSuggestionsStrip, layoutDirection);
|
mSuggestionsStrip.setLayoutDirection(layoutDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showSuggestionsStrip() {
|
public void showSuggestionsStrip() {
|
||||||
|
@ -141,6 +140,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
this(context, attrs, R.attr.suggestionStripViewStyle);
|
this(context, attrs, R.attr.suggestionStripViewStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("InflateParams") // does not seem suitable here
|
||||||
public SuggestionStripView(final Context context, final AttributeSet attrs, final int defStyle) {
|
public SuggestionStripView(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||||
super(context, attrs, defStyle);
|
super(context, attrs, defStyle);
|
||||||
final Colors colors = Settings.getInstance().getCurrent().mColors;
|
final Colors colors = Settings.getInstance().getCurrent().mColors;
|
||||||
|
@ -183,6 +183,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
R.dimen.config_more_suggestions_modal_tolerance);
|
R.dimen.config_more_suggestions_modal_tolerance);
|
||||||
mMoreSuggestionsSlidingDetector = new GestureDetector(context, mMoreSuggestionsSlidingListener);
|
mMoreSuggestionsSlidingDetector = new GestureDetector(context, mMoreSuggestionsSlidingListener);
|
||||||
|
|
||||||
|
@SuppressLint("CustomViewStyleable")
|
||||||
final TypedArray keyboardAttr = context.obtainStyledAttributes(attrs, R.styleable.Keyboard, defStyle, R.style.SuggestionStripView);
|
final TypedArray keyboardAttr = context.obtainStyledAttributes(attrs, R.styleable.Keyboard, defStyle, R.style.SuggestionStripView);
|
||||||
mIncognitoIcon = keyboardAttr.getDrawable(R.styleable.Keyboard_iconIncognitoKey);
|
mIncognitoIcon = keyboardAttr.getDrawable(R.styleable.Keyboard_iconIncognitoKey);
|
||||||
mToolbarArrowIcon = keyboardAttr.getDrawable(R.styleable.Keyboard_iconToolbarKey);
|
mToolbarArrowIcon = keyboardAttr.getDrawable(R.styleable.Keyboard_iconToolbarKey);
|
||||||
|
@ -262,9 +263,9 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
public void setRtl(final boolean isRtlLanguage) {
|
public void setRtl(final boolean isRtlLanguage) {
|
||||||
final int layoutDirection;
|
final int layoutDirection;
|
||||||
if (!Settings.getInstance().getCurrent().mVarToolbarDirection)
|
if (!Settings.getInstance().getCurrent().mVarToolbarDirection)
|
||||||
layoutDirection = ViewCompat.LAYOUT_DIRECTION_LOCALE;
|
layoutDirection = View.LAYOUT_DIRECTION_LOCALE;
|
||||||
else{
|
else{
|
||||||
layoutDirection = isRtlLanguage ? ViewCompat.LAYOUT_DIRECTION_RTL : ViewCompat.LAYOUT_DIRECTION_LTR;
|
layoutDirection = isRtlLanguage ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
|
||||||
mRtl = isRtlLanguage ? -1 : 1;
|
mRtl = isRtlLanguage ? -1 : 1;
|
||||||
}
|
}
|
||||||
mStripVisibilityGroup.setLayoutDirection(layoutDirection);
|
mStripVisibilityGroup.setLayoutDirection(layoutDirection);
|
||||||
|
@ -528,7 +529,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
private final GestureDetector.OnGestureListener mMoreSuggestionsSlidingListener =
|
private final GestureDetector.OnGestureListener mMoreSuggestionsSlidingListener =
|
||||||
new GestureDetector.SimpleOnGestureListener() {
|
new GestureDetector.SimpleOnGestureListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onScroll(MotionEvent down, MotionEvent me, float deltaX, float deltaY) {
|
public boolean onScroll(@Nullable MotionEvent down, @NonNull MotionEvent me, float deltaX, float deltaY) {
|
||||||
|
if (down == null) return false;
|
||||||
final float dy = me.getY() - down.getY();
|
final float dy = me.getY() - down.getY();
|
||||||
if (mToolbarContainer.getVisibility() != VISIBLE && deltaY > 0 && dy < 0) {
|
if (mToolbarContainer.getVisibility() != VISIBLE && deltaY > 0 && dy < 0) {
|
||||||
return showMoreSuggestions();
|
return showMoreSuggestions();
|
||||||
|
@ -637,7 +639,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
||||||
AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(KeyCode.NOT_SPECIFIED, this);
|
AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(KeyCode.NOT_SPECIFIED, this);
|
||||||
final Object tag = view.getTag();
|
final Object tag = view.getTag();
|
||||||
if (tag instanceof ToolbarKey) {
|
if (tag instanceof ToolbarKey) {
|
||||||
final Integer code = getCodeForToolbarKey((ToolbarKey) tag);
|
final int code = getCodeForToolbarKey((ToolbarKey) tag);
|
||||||
if (code != KeyCode.UNSPECIFIED) {
|
if (code != KeyCode.UNSPECIFIED) {
|
||||||
Log.d(TAG, "click toolbar key "+tag);
|
Log.d(TAG, "click toolbar key "+tag);
|
||||||
mListener.onCodeInput(code, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
|
mListener.onCodeInput(code, Constants.SUGGESTION_STRIP_COORDINATE, Constants.SUGGESTION_STRIP_COORDINATE, false);
|
||||||
|
|
|
@ -18,7 +18,6 @@ import helium314.keyboard.keyboard.internal.keyboard_parser.RawKeyboardParser
|
||||||
import helium314.keyboard.keyboard.internal.keyboard_parser.addLocaleKeyTextsToParams
|
import helium314.keyboard.keyboard.internal.keyboard_parser.addLocaleKeyTextsToParams
|
||||||
import helium314.keyboard.latin.R
|
import helium314.keyboard.latin.R
|
||||||
import helium314.keyboard.latin.common.FileUtils
|
import helium314.keyboard.latin.common.FileUtils
|
||||||
import helium314.keyboard.latin.settings.Settings
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
|
@ -80,13 +79,13 @@ private fun checkLayout(layoutContent: String, context: Context): Boolean? {
|
||||||
params.mPopupKeyTypes.add(POPUP_KEYS_LAYOUT)
|
params.mPopupKeyTypes.add(POPUP_KEYS_LAYOUT)
|
||||||
addLocaleKeyTextsToParams(context, params, POPUP_KEYS_NORMAL)
|
addLocaleKeyTextsToParams(context, params, POPUP_KEYS_NORMAL)
|
||||||
try {
|
try {
|
||||||
val keys = RawKeyboardParser.parseJsonString(layoutContent).map { it.mapNotNull { it.compute(params)?.toKeyParams(params) } }
|
val keys = RawKeyboardParser.parseJsonString(layoutContent).map { row -> row.mapNotNull { it.compute(params)?.toKeyParams(params) } }
|
||||||
if (!checkKeys(keys))
|
if (!checkKeys(keys))
|
||||||
return null
|
return null
|
||||||
return true
|
return true
|
||||||
} catch (e: Exception) { Log.w(TAG, "error parsing custom json layout", e) }
|
} catch (e: Exception) { Log.w(TAG, "error parsing custom json layout", e) }
|
||||||
try {
|
try {
|
||||||
val keys = RawKeyboardParser.parseSimpleString(layoutContent).map { it.map { it.toKeyParams(params) } }
|
val keys = RawKeyboardParser.parseSimpleString(layoutContent).map { row -> row.map { it.toKeyParams(params) } }
|
||||||
if (!checkKeys(keys))
|
if (!checkKeys(keys))
|
||||||
return null
|
return null
|
||||||
return false
|
return false
|
||||||
|
@ -94,7 +93,7 @@ private fun checkLayout(layoutContent: String, context: Context): Boolean? {
|
||||||
if (layoutContent.startsWith("[")) {
|
if (layoutContent.startsWith("[")) {
|
||||||
// layout can't be loaded, assume it's json -> load json layout again because the error message shown to the user is from the most recent error
|
// layout can't be loaded, assume it's json -> load json layout again because the error message shown to the user is from the most recent error
|
||||||
try {
|
try {
|
||||||
RawKeyboardParser.parseJsonString(layoutContent).map { it.mapNotNull { it.compute(params)?.toKeyParams(params) } }
|
RawKeyboardParser.parseJsonString(layoutContent).map { row -> row.mapNotNull { it.compute(params)?.toKeyParams(params) } }
|
||||||
} catch (e: Exception) { Log.w(TAG, "error parsing custom json layout", e) }
|
} catch (e: Exception) { Log.w(TAG, "error parsing custom json layout", e) }
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
|
@ -109,19 +108,19 @@ private fun checkKeys(keys: List<List<Key.KeyParams>>): Boolean {
|
||||||
Log.w(TAG, "too many rows")
|
Log.w(TAG, "too many rows")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (keys.any { it.size > 20 }) {
|
if (keys.any { row -> row.size > 20 }) {
|
||||||
Log.w(TAG, "too many keys in one row")
|
Log.w(TAG, "too many keys in one row")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (keys.any { it.any { ((it.mLabel?.length ?: 0) > 6) } }) {
|
if (keys.any { row -> row.any { ((it.mLabel?.length ?: 0) > 6) } }) {
|
||||||
Log.w(TAG, "too long text on key")
|
Log.w(TAG, "too long text on key")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (keys.any { it.any { (it.mPopupKeys?.size ?: 0) > 20 } }) {
|
if (keys.any { row -> row.any { (it.mPopupKeys?.size ?: 0) > 20 } }) {
|
||||||
Log.w(TAG, "too many popup keys on a key")
|
Log.w(TAG, "too many popup keys on a key")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (keys.any { it.any { it.mPopupKeys?.any { (it.mLabel?.length ?: 0) > 10 } == true } }) {
|
if (keys.any { row -> row.any { it.mPopupKeys?.any { popupKey -> (popupKey.mLabel?.length ?: 0) > 10 } == true } }) {
|
||||||
Log.w(TAG, "too long text on popup key")
|
Log.w(TAG, "too long text on popup key")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ public class RecapitalizeStatus {
|
||||||
CAPS_MODE_ALL_UPPER
|
CAPS_MODE_ALL_UPPER
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final int getStringMode(final String string, final int[] sortedSeparators) {
|
private static int getStringMode(final String string, final int[] sortedSeparators) {
|
||||||
if (StringUtils.isIdenticalAfterUpcase(string)) {
|
if (StringUtils.isIdenticalAfterUpcase(string)) {
|
||||||
return CAPS_MODE_ALL_UPPER;
|
return CAPS_MODE_ALL_UPPER;
|
||||||
} else if (StringUtils.isIdenticalAfterDowncase(string)) {
|
} else if (StringUtils.isIdenticalAfterDowncase(string)) {
|
||||||
|
@ -42,14 +42,14 @@ public class RecapitalizeStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String modeToString(final int recapitalizeMode) {
|
public static String modeToString(final int recapitalizeMode) {
|
||||||
switch (recapitalizeMode) {
|
return switch (recapitalizeMode) {
|
||||||
case NOT_A_RECAPITALIZE_MODE: return "undefined";
|
case NOT_A_RECAPITALIZE_MODE -> "undefined";
|
||||||
case CAPS_MODE_ORIGINAL_MIXED_CASE: return "mixedCase";
|
case CAPS_MODE_ORIGINAL_MIXED_CASE -> "mixedCase";
|
||||||
case CAPS_MODE_ALL_LOWER: return "allLower";
|
case CAPS_MODE_ALL_LOWER -> "allLower";
|
||||||
case CAPS_MODE_FIRST_WORD_UPPER: return "firstWordUpper";
|
case CAPS_MODE_FIRST_WORD_UPPER -> "firstWordUpper";
|
||||||
case CAPS_MODE_ALL_UPPER: return "allUpper";
|
case CAPS_MODE_ALL_UPPER -> "allUpper";
|
||||||
default: return "unknown<" + recapitalizeMode + ">";
|
default -> "unknown<" + recapitalizeMode + ">";
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -145,21 +145,10 @@ public class RecapitalizeStatus {
|
||||||
}
|
}
|
||||||
++count;
|
++count;
|
||||||
switch (ROTATION_STYLE[mRotationStyleCurrentIndex]) {
|
switch (ROTATION_STYLE[mRotationStyleCurrentIndex]) {
|
||||||
case CAPS_MODE_ORIGINAL_MIXED_CASE:
|
case CAPS_MODE_ALL_LOWER -> mStringAfter = mStringBefore.toLowerCase(mLocale);
|
||||||
mStringAfter = mStringBefore;
|
case CAPS_MODE_FIRST_WORD_UPPER -> mStringAfter = StringUtils.capitalizeEachWord(mStringBefore, mSortedSeparators, mLocale);
|
||||||
break;
|
case CAPS_MODE_ALL_UPPER -> mStringAfter = mStringBefore.toUpperCase(mLocale);
|
||||||
case CAPS_MODE_ALL_LOWER:
|
default -> mStringAfter = mStringBefore;
|
||||||
mStringAfter = mStringBefore.toLowerCase(mLocale);
|
|
||||||
break;
|
|
||||||
case CAPS_MODE_FIRST_WORD_UPPER:
|
|
||||||
mStringAfter = StringUtils.capitalizeEachWord(mStringBefore, mSortedSeparators,
|
|
||||||
mLocale);
|
|
||||||
break;
|
|
||||||
case CAPS_MODE_ALL_UPPER:
|
|
||||||
mStringAfter = mStringBefore.toUpperCase(mLocale);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
mStringAfter = mStringBefore;
|
|
||||||
}
|
}
|
||||||
} while (mStringAfter.equals(oldResult) && count < ROTATION_STYLE.length + 1);
|
} while (mStringAfter.equals(oldResult) && count < ROTATION_STYLE.length + 1);
|
||||||
mCursorEndAfter = mCursorStartAfter + mStringAfter.length();
|
mCursorEndAfter = mCursorStartAfter + mStringAfter.length();
|
||||||
|
|
|
@ -2,7 +2,6 @@ package helium314.keyboard
|
||||||
|
|
||||||
import helium314.keyboard.keyboard.internal.KeySpecParser
|
import helium314.keyboard.keyboard.internal.KeySpecParser
|
||||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode
|
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode
|
||||||
import helium314.keyboard.latin.common.Constants
|
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
|
|
|
@ -867,7 +867,7 @@ private val ic = object : InputConnection {
|
||||||
// update selection
|
// update selection
|
||||||
selectionStart -= beforeLength
|
selectionStart -= beforeLength
|
||||||
selectionEnd -= beforeLength
|
selectionEnd -= beforeLength
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
override fun sendKeyEvent(p0: KeyEvent): Boolean {
|
override fun sendKeyEvent(p0: KeyEvent): Boolean {
|
||||||
if (p0.action != KeyEvent.ACTION_DOWN) return true // only change the text on key down, like RichInputConnection does
|
if (p0.action != KeyEvent.ACTION_DOWN) return true // only change the text on key down, like RichInputConnection does
|
||||||
|
@ -908,7 +908,7 @@ private val ic = object : InputConnection {
|
||||||
override fun clearMetaKeyStates(p0: Int): Boolean = TODO("Not yet implemented")
|
override fun clearMetaKeyStates(p0: Int): Boolean = TODO("Not yet implemented")
|
||||||
override fun reportFullscreenMode(p0: Boolean): Boolean = TODO("Not yet implemented")
|
override fun reportFullscreenMode(p0: Boolean): Boolean = TODO("Not yet implemented")
|
||||||
override fun performPrivateCommand(p0: String?, p1: Bundle?): Boolean = TODO("Not yet implemented")
|
override fun performPrivateCommand(p0: String?, p1: Bundle?): Boolean = TODO("Not yet implemented")
|
||||||
override fun getHandler(): Handler? = TODO("Not yet implemented")
|
override fun getHandler(): Handler = TODO("Not yet implemented")
|
||||||
override fun closeConnection() = TODO("Not yet implemented")
|
override fun closeConnection() = TODO("Not yet implemented")
|
||||||
override fun commitContent(p0: InputContentInfo, p1: Int, p2: Bundle?): Boolean = TODO("Not yet implemented")
|
override fun commitContent(p0: InputContentInfo, p1: Int, p2: Bundle?): Boolean = TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.robolectric.annotation.Implements
|
||||||
import org.robolectric.shadows.ShadowLog
|
import org.robolectric.shadows.ShadowLog
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@Suppress("NonAsciiCharacters")
|
||||||
@RunWith(RobolectricTestRunner::class)
|
@RunWith(RobolectricTestRunner::class)
|
||||||
@Config(shadows = [
|
@Config(shadows = [
|
||||||
ShadowLocaleManagerCompat::class,
|
ShadowLocaleManagerCompat::class,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.9.23'
|
ext.kotlin_version = '1.9.24'
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
|
@ -17,7 +17,7 @@ buildscript {
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.23' apply false
|
id 'org.jetbrains.kotlin.plugin.serialization' version "$kotlin_version"
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue