mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-04-20 14:19:08 +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 {
|
||||
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.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'
|
||||
|
||||
// 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 'org.mockito:mockito-core:5.11.0'
|
||||
testImplementation 'org.mockito:mockito-inline:5.2.0'
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package helium314.keyboard.accessibility
|
||||
|
||||
import android.content.Context
|
||||
import android.media.AudioDeviceInfo
|
||||
import android.media.AudioDeviceInfo.*
|
||||
import android.media.AudioManager
|
||||
import android.os.Build
|
||||
|
|
|
@ -47,10 +47,9 @@ open class KeyboardAccessibilityDelegate<KV : KeyboardView>(
|
|||
/**
|
||||
* Called when the keyboard layout changes.
|
||||
*
|
||||
*
|
||||
* **Note:** This method will be called even if accessibility is not
|
||||
* 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?
|
||||
get() = mKeyboard
|
||||
|
|
|
@ -116,8 +116,7 @@ class MainKeyboardAccessibilityDelegate(
|
|||
*/
|
||||
private fun announceKeyboardType(keyboard: Keyboard, lastKeyboard: Keyboard) {
|
||||
val lastElementId = lastKeyboard.mId.mElementId
|
||||
val resId: Int
|
||||
resId = when (keyboard.mId.mElementId) {
|
||||
val resId = when (keyboard.mId.mElementId) {
|
||||
KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED, KeyboardId.ELEMENT_ALPHABET -> {
|
||||
if (lastElementId == KeyboardId.ELEMENT_ALPHABET
|
||||
|| lastElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED) {
|
||||
|
|
|
@ -9,7 +9,6 @@ package helium314.keyboard.event
|
|||
import android.text.SpannableStringBuilder
|
||||
import android.text.TextUtils
|
||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode
|
||||
import helium314.keyboard.latin.common.Constants
|
||||
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
|
||||
* feedback on the composing state and will typically be shown with different styling such as
|
||||
* 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) {
|
||||
// The already combined text, as described above
|
||||
|
@ -45,16 +50,6 @@ class CombinerChain(initialText: String) {
|
|||
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 {
|
||||
// The dead key combiner is always active, and always first
|
||||
mCombiners.add(DeadKeyCombiner())
|
||||
|
|
|
@ -28,7 +28,7 @@ class InputTransaction(// Initial conditions
|
|||
* @param updateType What type of shift update this requires.
|
||||
*/
|
||||
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>.
|
||||
*/
|
||||
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,
|
||||
final int labelFlags, final int backgroundType, final int x, final int y,
|
||||
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
|
||||
&& TextUtils.equals(o.mLabel, mLabel)
|
||||
&& TextUtils.equals(o.mHintLabel, mHintLabel)
|
||||
&& o.mIconName == mIconName
|
||||
&& o.mIconName.equals(mIconName)
|
||||
&& o.mBackgroundType == mBackgroundType
|
||||
&& Arrays.equals(o.mPopupKeys, mPopupKeys)
|
||||
&& TextUtils.equals(o.getOutputText(), getOutputText())
|
||||
|
@ -429,6 +429,7 @@ public class Key implements Comparable<Key> {
|
|||
return o instanceof Key && equalsInternal((Key)o);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
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;
|
||||
}
|
||||
|
||||
private final boolean isShiftedLetterActivated() {
|
||||
private boolean isShiftedLetterActivated() {
|
||||
return (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0
|
||||
&& !TextUtils.isEmpty(mHintLabel);
|
||||
}
|
||||
|
|
|
@ -35,11 +35,11 @@ public interface KeyboardActionListener {
|
|||
* Send a key code to the listener.
|
||||
*
|
||||
* @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 Constants#NOT_A_COORDINATE}. If it's called on insertion from the
|
||||
* 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 Constants#NOT_A_COORDINATE}.If it's called on insertion from the
|
||||
* suggestion strip, it should be {@link Constants#SUGGESTION_STRIP_COORDINATE}.
|
||||
|
@ -103,9 +103,9 @@ public interface KeyboardActionListener {
|
|||
|
||||
KeyboardActionListener EMPTY_LISTENER = new Adapter();
|
||||
|
||||
static int SWIPE_NO_ACTION = 0;
|
||||
static int SWIPE_MOVE_CURSOR = 1;
|
||||
static int SWIPE_SWITCH_LANGUAGE = 2;
|
||||
int SWIPE_NO_ACTION = 0;
|
||||
int SWIPE_MOVE_CURSOR = 1;
|
||||
int SWIPE_SWITCH_LANGUAGE = 2;
|
||||
|
||||
class Adapter implements KeyboardActionListener {
|
||||
@Override
|
||||
|
|
|
@ -97,9 +97,9 @@ class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inp
|
|||
return true
|
||||
}
|
||||
|
||||
private fun onMoveCursorHorizontally(_steps: Int): Boolean {
|
||||
if (_steps == 0) return false
|
||||
var steps = _steps
|
||||
private fun onMoveCursorHorizontally(rawSteps: Int): Boolean {
|
||||
if (rawSteps == 0) return false
|
||||
var steps = rawSteps
|
||||
// for RTL languages we want to invert pointer movement
|
||||
if (RichInputMethodManager.getInstance().currentSubtype.isRtlSubtype) steps = -steps
|
||||
val moveSteps: Int
|
||||
|
|
|
@ -32,6 +32,7 @@ import helium314.keyboard.latin.utils.getCodeForToolbarKey
|
|||
import helium314.keyboard.latin.utils.getCodeForToolbarKeyLongClick
|
||||
import helium314.keyboard.latin.utils.getEnabledClipboardToolbarKeys
|
||||
|
||||
@SuppressLint("CustomViewStyleable")
|
||||
class ClipboardHistoryView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet?,
|
||||
|
@ -160,7 +161,7 @@ class ClipboardHistoryView @JvmOverloads constructor(
|
|||
|
||||
private fun setupToolbarKeys() {
|
||||
// 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 }
|
||||
}
|
||||
|
||||
|
|
|
@ -236,8 +236,7 @@ final class DynamicGridKeyboard extends Keyboard {
|
|||
if (o instanceof Integer) {
|
||||
final int code = (Integer)o;
|
||||
key = getKeyByCode(keyboards, code);
|
||||
} else if (o instanceof String) {
|
||||
final String outputText = (String)o;
|
||||
} else if (o instanceof final String outputText) {
|
||||
key = getKeyByOutputText(keyboards, outputText);
|
||||
} else {
|
||||
Log.w(TAG, "Invalid object: " + o);
|
||||
|
@ -267,18 +266,20 @@ final class DynamicGridKeyboard extends Keyboard {
|
|||
return row * mVerticalStep + mVerticalGap / 2;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public List<Key> getSortedKeys() {
|
||||
synchronized (mLock) {
|
||||
if (mCachedGridKeys != null) {
|
||||
return mCachedGridKeys;
|
||||
}
|
||||
final ArrayList<Key> cachedKeys = new ArrayList<Key>(mGridKeys);
|
||||
final ArrayList<Key> cachedKeys = new ArrayList<>(mGridKeys);
|
||||
mCachedGridKeys = Collections.unmodifiableList(cachedKeys);
|
||||
return mCachedGridKeys;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public List<Key> getNearestKeys(final int x, final int y) {
|
||||
// TODO: Calculate the nearest key index in mGridKeys from x and y.
|
||||
|
@ -312,13 +313,13 @@ final class DynamicGridKeyboard extends Keyboard {
|
|||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (!(o instanceof Key)) return false;
|
||||
final Key key = (Key)o;
|
||||
if (!(o instanceof final Key key)) return false;
|
||||
if (getCode() != key.getCode()) return false;
|
||||
if (!TextUtils.equals(getLabel(), key.getLabel())) return false;
|
||||
return TextUtils.equals(getOutputText(), key.getOutputText());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GridKey: " + super.toString();
|
||||
|
|
|
@ -121,6 +121,7 @@ object RawKeyboardParser {
|
|||
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) {
|
||||
KeyboardId.ELEMENT_SYMBOLS_SHIFTED -> FUNCTIONAL_LAYOUT_SYMBOLS_SHIFTED
|
||||
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.
|
||||
*
|
||||
* <p>
|
||||
* It offers a consistent and simple interface that allows LatinIME to forget about the
|
||||
* complexity of settings and the like.
|
||||
*/
|
||||
|
@ -81,21 +81,12 @@ public final class AudioAndHapticFeedbackManager {
|
|||
if (!mSoundOn) {
|
||||
return;
|
||||
}
|
||||
final int sound;
|
||||
switch (code) {
|
||||
case KeyCode.DELETE:
|
||||
sound = AudioManager.FX_KEYPRESS_DELETE;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
final int sound = switch (code) {
|
||||
case KeyCode.DELETE -> AudioManager.FX_KEYPRESS_DELETE;
|
||||
case Constants.CODE_ENTER -> AudioManager.FX_KEYPRESS_RETURN;
|
||||
case Constants.CODE_SPACE -> AudioManager.FX_KEYPRESS_SPACEBAR;
|
||||
default -> AudioManager.FX_KEYPRESS_STANDARD;
|
||||
};
|
||||
mAudioManager.playSoundEffect(sound, mSettingsValues.mKeypressSoundVolume);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
|
||||
/**
|
||||
* Manages all interactions with Contacts DB.
|
||||
*
|
||||
* <p>
|
||||
* The manager provides an API for listening to meaning full updates by keeping a
|
||||
* measure of the current state of the content provider.
|
||||
*/
|
||||
|
@ -65,7 +65,7 @@ public class ContactsManager {
|
|||
* - How many times it has been contacted
|
||||
* - How long since the last contact.
|
||||
* - 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
|
||||
* LAST_TIME_CONTACTED or TIMES_CONTACTED counters. As a result, a frequently messaged
|
||||
* contact may still have 0 affinity.
|
||||
|
@ -101,13 +101,13 @@ public class ContactsManager {
|
|||
* The number of contacts observed in the most recent instance of
|
||||
* 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
|
||||
* rebuild.
|
||||
*/
|
||||
private AtomicInteger mHashCodeAtLastRebuild = new AtomicInteger(0);
|
||||
private final AtomicInteger mHashCodeAtLastRebuild = new AtomicInteger(0);
|
||||
|
||||
private final Context mContext;
|
||||
private final ContactsContentObserver mObserver;
|
||||
|
@ -134,7 +134,7 @@ public class ContactsManager {
|
|||
* Returns all the valid names in the Contacts DB. Callers should also
|
||||
* call {@link #updateLocalState(ArrayList)} after they are done with result
|
||||
* so that the manager can cache local state for determining updates.
|
||||
*
|
||||
* <p>
|
||||
* These names are sorted by their affinity to the user, with favorite
|
||||
* contacts appearing first.
|
||||
*/
|
||||
|
@ -183,22 +183,15 @@ public class ContactsManager {
|
|||
* Returns the number of contacts in contacts content provider.
|
||||
*/
|
||||
public int getContactCount() {
|
||||
// TODO: consider switching to a rawQuery("select count(*)...") on the database if
|
||||
// performance is a bottleneck.
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI,
|
||||
ContactsDictionaryConstants.PROJECTION_ID_ONLY, null, null, null);
|
||||
if (null == cursor) {
|
||||
// TODO: consider switching to a rawQuery("select count(*)...") on the database if performance is a bottleneck.
|
||||
try (Cursor cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI,
|
||||
ContactsDictionaryConstants.PROJECTION_ID_ONLY, null, null, null)
|
||||
) {
|
||||
if (null == cursor)
|
||||
return 0;
|
||||
}
|
||||
return cursor.getCount();
|
||||
} catch (final SQLiteException e) {
|
||||
Log.e(TAG, "SQLiteException in the remote Contacts process.", e);
|
||||
} finally {
|
||||
if (null != cursor) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
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_MICROPHONE;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Class to hold attributes of the input field.
|
||||
*/
|
||||
|
@ -162,92 +164,60 @@ public final class InputAttributes {
|
|||
}
|
||||
|
||||
private static String toInputClassString(final int inputClass) {
|
||||
switch (inputClass) {
|
||||
case InputType.TYPE_CLASS_TEXT:
|
||||
return "TYPE_CLASS_TEXT";
|
||||
case InputType.TYPE_CLASS_PHONE:
|
||||
return "TYPE_CLASS_PHONE";
|
||||
case InputType.TYPE_CLASS_NUMBER:
|
||||
return "TYPE_CLASS_NUMBER";
|
||||
case InputType.TYPE_CLASS_DATETIME:
|
||||
return "TYPE_CLASS_DATETIME";
|
||||
default:
|
||||
return String.format("unknownInputClass<0x%08x>", inputClass);
|
||||
}
|
||||
return switch (inputClass) {
|
||||
case InputType.TYPE_CLASS_TEXT -> "TYPE_CLASS_TEXT";
|
||||
case InputType.TYPE_CLASS_PHONE -> "TYPE_CLASS_PHONE";
|
||||
case InputType.TYPE_CLASS_NUMBER -> "TYPE_CLASS_NUMBER";
|
||||
case InputType.TYPE_CLASS_DATETIME -> "TYPE_CLASS_DATETIME";
|
||||
default -> String.format("unknownInputClass<0x%08x>", inputClass);
|
||||
};
|
||||
}
|
||||
|
||||
private static String toVariationString(final int inputClass, final int variation) {
|
||||
switch (inputClass) {
|
||||
case InputType.TYPE_CLASS_TEXT:
|
||||
return toTextVariationString(variation);
|
||||
case InputType.TYPE_CLASS_NUMBER:
|
||||
return toNumberVariationString(variation);
|
||||
case InputType.TYPE_CLASS_DATETIME:
|
||||
return toDatetimeVariationString(variation);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
return switch (inputClass) {
|
||||
case InputType.TYPE_CLASS_TEXT -> toTextVariationString(variation);
|
||||
case InputType.TYPE_CLASS_NUMBER -> toNumberVariationString(variation);
|
||||
case InputType.TYPE_CLASS_DATETIME -> toDatetimeVariationString(variation);
|
||||
default -> "";
|
||||
};
|
||||
}
|
||||
|
||||
private static String toTextVariationString(final int variation) {
|
||||
switch (variation) {
|
||||
case InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS:
|
||||
return " TYPE_TEXT_VARIATION_EMAIL_ADDRESS";
|
||||
case InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT:
|
||||
return "TYPE_TEXT_VARIATION_EMAIL_SUBJECT";
|
||||
case InputType.TYPE_TEXT_VARIATION_FILTER:
|
||||
return "TYPE_TEXT_VARIATION_FILTER";
|
||||
case InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE:
|
||||
return "TYPE_TEXT_VARIATION_LONG_MESSAGE";
|
||||
case InputType.TYPE_TEXT_VARIATION_NORMAL:
|
||||
return "TYPE_TEXT_VARIATION_NORMAL";
|
||||
case InputType.TYPE_TEXT_VARIATION_PASSWORD:
|
||||
return "TYPE_TEXT_VARIATION_PASSWORD";
|
||||
case InputType.TYPE_TEXT_VARIATION_PERSON_NAME:
|
||||
return "TYPE_TEXT_VARIATION_PERSON_NAME";
|
||||
case InputType.TYPE_TEXT_VARIATION_PHONETIC:
|
||||
return "TYPE_TEXT_VARIATION_PHONETIC";
|
||||
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);
|
||||
}
|
||||
return switch (variation) {
|
||||
case InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS -> " TYPE_TEXT_VARIATION_EMAIL_ADDRESS";
|
||||
case InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT -> "TYPE_TEXT_VARIATION_EMAIL_SUBJECT";
|
||||
case InputType.TYPE_TEXT_VARIATION_FILTER -> "TYPE_TEXT_VARIATION_FILTER";
|
||||
case InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE -> "TYPE_TEXT_VARIATION_LONG_MESSAGE";
|
||||
case InputType.TYPE_TEXT_VARIATION_NORMAL -> "TYPE_TEXT_VARIATION_NORMAL";
|
||||
case InputType.TYPE_TEXT_VARIATION_PASSWORD -> "TYPE_TEXT_VARIATION_PASSWORD";
|
||||
case InputType.TYPE_TEXT_VARIATION_PERSON_NAME -> "TYPE_TEXT_VARIATION_PERSON_NAME";
|
||||
case InputType.TYPE_TEXT_VARIATION_PHONETIC -> "TYPE_TEXT_VARIATION_PHONETIC";
|
||||
case InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS -> "TYPE_TEXT_VARIATION_POSTAL_ADDRESS";
|
||||
case InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE -> "TYPE_TEXT_VARIATION_SHORT_MESSAGE";
|
||||
case InputType.TYPE_TEXT_VARIATION_URI -> "TYPE_TEXT_VARIATION_URI";
|
||||
case InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD -> "TYPE_TEXT_VARIATION_VISIBLE_PASSWORD";
|
||||
case InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT -> "TYPE_TEXT_VARIATION_WEB_EDIT_TEXT";
|
||||
case InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS -> "TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS";
|
||||
case InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD -> "TYPE_TEXT_VARIATION_WEB_PASSWORD";
|
||||
default -> String.format("unknownVariation<0x%08x>", variation);
|
||||
};
|
||||
}
|
||||
|
||||
private static String toNumberVariationString(final int variation) {
|
||||
switch (variation) {
|
||||
case InputType.TYPE_NUMBER_VARIATION_NORMAL:
|
||||
return "TYPE_NUMBER_VARIATION_NORMAL";
|
||||
case InputType.TYPE_NUMBER_VARIATION_PASSWORD:
|
||||
return "TYPE_NUMBER_VARIATION_PASSWORD";
|
||||
default:
|
||||
return String.format("unknownVariation<0x%08x>", variation);
|
||||
}
|
||||
return switch (variation) {
|
||||
case InputType.TYPE_NUMBER_VARIATION_NORMAL -> "TYPE_NUMBER_VARIATION_NORMAL";
|
||||
case InputType.TYPE_NUMBER_VARIATION_PASSWORD -> "TYPE_NUMBER_VARIATION_PASSWORD";
|
||||
default -> String.format("unknownVariation<0x%08x>", variation);
|
||||
};
|
||||
}
|
||||
|
||||
private static String toDatetimeVariationString(final int variation) {
|
||||
switch (variation) {
|
||||
case InputType.TYPE_DATETIME_VARIATION_NORMAL:
|
||||
return "TYPE_DATETIME_VARIATION_NORMAL";
|
||||
case InputType.TYPE_DATETIME_VARIATION_DATE:
|
||||
return "TYPE_DATETIME_VARIATION_DATE";
|
||||
case InputType.TYPE_DATETIME_VARIATION_TIME:
|
||||
return "TYPE_DATETIME_VARIATION_TIME";
|
||||
default:
|
||||
return String.format("unknownVariation<0x%08x>", variation);
|
||||
}
|
||||
return switch (variation) {
|
||||
case InputType.TYPE_DATETIME_VARIATION_NORMAL -> "TYPE_DATETIME_VARIATION_NORMAL";
|
||||
case InputType.TYPE_DATETIME_VARIATION_DATE -> "TYPE_DATETIME_VARIATION_DATE";
|
||||
case InputType.TYPE_DATETIME_VARIATION_TIME -> "TYPE_DATETIME_VARIATION_TIME";
|
||||
default -> String.format("unknownVariation<0x%08x>", variation);
|
||||
};
|
||||
}
|
||||
|
||||
private static String toFlagsString(final int flags) {
|
||||
|
@ -272,6 +242,7 @@ public final class InputAttributes {
|
|||
}
|
||||
|
||||
// Pretty print
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
package helium314.keyboard.latin;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
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
|
||||
* became to IME context self since it ends up capable of updating its resources internally.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private @NonNull Context getDisplayContext() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S_V2) {
|
||||
// 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,
|
||||
* 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) {
|
||||
switch (inputTransaction.getRequiredShiftUpdate()) {
|
||||
case InputTransaction.SHIFT_UPDATE_LATER:
|
||||
mHandler.postUpdateShiftState();
|
||||
break;
|
||||
case InputTransaction.SHIFT_UPDATE_NOW:
|
||||
mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(),
|
||||
getCurrentRecapitalizeState());
|
||||
break;
|
||||
default: // SHIFT_NO_UPDATE
|
||||
case InputTransaction.SHIFT_UPDATE_LATER -> mHandler.postUpdateShiftState();
|
||||
case InputTransaction.SHIFT_UPDATE_NOW -> mKeyboardSwitcher
|
||||
.requestUpdatingShiftState(getCurrentAutoCapsState(), getCurrentRecapitalizeState());
|
||||
default -> {
|
||||
} // SHIFT_NO_UPDATE
|
||||
}
|
||||
if (inputTransaction.requiresUpdateSuggestions()) {
|
||||
final int inputStyle;
|
||||
|
@ -1897,6 +1892,7 @@ public class LatinIME extends InputMethodService implements
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SwitchIntDef")
|
||||
@Override
|
||||
public void onTrimMemory(int level) {
|
||||
super.onTrimMemory(level);
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
package helium314.keyboard.latin;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import helium314.keyboard.keyboard.internal.KeySpecParser;
|
||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode;
|
||||
import helium314.keyboard.latin.common.Constants;
|
||||
import helium314.keyboard.latin.common.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -18,7 +18,7 @@ import java.util.Arrays;
|
|||
|
||||
/**
|
||||
* The extended {@link SuggestedWords} class to represent punctuation suggestions.
|
||||
*
|
||||
* <p>
|
||||
* Each punctuation specification string is the key specification that can be parsed by
|
||||
* {@link KeySpecParser}.
|
||||
*/
|
||||
|
@ -44,7 +44,7 @@ public final class PunctuationSuggestions extends SuggestedWords {
|
|||
public static PunctuationSuggestions newPunctuationSuggestions(
|
||||
@Nullable final String[] punctuationSpecs) {
|
||||
if (punctuationSpecs == null || punctuationSpecs.length == 0) {
|
||||
return new PunctuationSuggestions(new ArrayList<SuggestedWordInfo>(0));
|
||||
return new PunctuationSuggestions(new ArrayList<>(0));
|
||||
}
|
||||
final ArrayList<SuggestedWordInfo> punctuationList =
|
||||
new ArrayList<>(punctuationSpecs.length);
|
||||
|
@ -99,7 +99,7 @@ public final class PunctuationSuggestions extends SuggestedWords {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@NonNull public String toString() {
|
||||
return "PunctuationSuggestions: "
|
||||
+ " 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.latin.SuggestedWords.SuggestedWordInfo;
|
||||
import helium314.keyboard.latin.common.ComposedData;
|
||||
import helium314.keyboard.latin.common.Constants;
|
||||
import helium314.keyboard.latin.common.CoordinateUtils;
|
||||
import helium314.keyboard.latin.common.InputPointers;
|
||||
import helium314.keyboard.latin.common.StringUtils;
|
||||
|
@ -167,7 +166,7 @@ public final class WordComposer {
|
|||
|
||||
/**
|
||||
* Apply a processed input event.
|
||||
*
|
||||
* <p>
|
||||
* All input events should be supported, including software/hardware events, characters as well
|
||||
* 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
|
||||
* is a capital.
|
||||
*
|
||||
* <p>
|
||||
* 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,
|
||||
* 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.
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
* 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.
|
||||
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.
|
||||
|
|
|
@ -82,12 +82,8 @@ class InputLogicHandler implements Handler.Callback {
|
|||
// Called on the Non-UI handler thread by the Handler code.
|
||||
@Override
|
||||
public boolean handleMessage(final Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_GET_SUGGESTED_WORDS:
|
||||
mLatinIME.getSuggestedWords(msg.arg1 /* inputStyle */,
|
||||
msg.arg2 /* sequenceNumber */, (OnGetSuggestedWordsCallback) msg.obj);
|
||||
break;
|
||||
}
|
||||
if (msg.what == MSG_GET_SUGGESTED_WORDS)
|
||||
mLatinIME.getSuggestedWords(msg.arg1, msg.arg2, (OnGetSuggestedWordsCallback) msg.obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -122,12 +118,7 @@ class InputLogicHandler implements Handler.Callback {
|
|||
return;
|
||||
}
|
||||
mInputLogic.mWordComposer.setBatchInputPointers(batchPointers);
|
||||
final OnGetSuggestedWordsCallback callback = new OnGetSuggestedWordsCallback() {
|
||||
@Override
|
||||
public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
|
||||
showGestureSuggestionsWithPreviewVisuals(suggestedWords, isTailBatchInput);
|
||||
}
|
||||
};
|
||||
final OnGetSuggestedWordsCallback callback = suggestedWords -> showGestureSuggestionsWithPreviewVisuals(suggestedWords, isTailBatchInput);
|
||||
getSuggestedWords(isTailBatchInput ? SuggestedWords.INPUT_STYLE_TAIL_BATCH
|
||||
: SuggestedWords.INPUT_STYLE_UPDATE_BATCH, sequenceNumber, callback);
|
||||
}
|
||||
|
@ -159,7 +150,7 @@ class InputLogicHandler implements Handler.Callback {
|
|||
|
||||
/**
|
||||
* Update a batch input.
|
||||
*
|
||||
* <p>
|
||||
* This fetches suggestions and updates the suggestion strip and the floating text preview.
|
||||
*
|
||||
* @param batchPointers the updated batch pointers.
|
||||
|
@ -168,12 +159,12 @@ class InputLogicHandler implements Handler.Callback {
|
|||
// Called on the UI thread by InputLogic.
|
||||
public void onUpdateBatchInput(final InputPointers batchPointers,
|
||||
final int sequenceNumber) {
|
||||
updateBatchInput(batchPointers, sequenceNumber, false /* isTailBatchInput */);
|
||||
updateBatchInput(batchPointers, sequenceNumber, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel a batch input.
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* <p>
|
||||
* 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,
|
||||
* 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.
|
||||
public void updateTailBatchInput(final InputPointers batchPointers,
|
||||
final int sequenceNumber) {
|
||||
updateBatchInput(batchPointers, sequenceNumber, true /* isTailBatchInput */);
|
||||
updateBatchInput(batchPointers, sequenceNumber, true);
|
||||
}
|
||||
|
||||
public void getSuggestedWords(final int inputStyle, final int sequenceNumber,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
package helium314.keyboard.latin.makedict;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.inputmethod.latin.BinaryDictionary;
|
||||
|
@ -20,7 +21,7 @@ import java.util.Arrays;
|
|||
|
||||
/**
|
||||
* Utility class for a word with a probability.
|
||||
*
|
||||
* <p>
|
||||
* This is chiefly used to iterate a dictionary.
|
||||
*/
|
||||
public final class WordProperty implements Comparable<WordProperty> {
|
||||
|
@ -150,7 +151,7 @@ public final class WordProperty implements Comparable<WordProperty> {
|
|||
|
||||
/**
|
||||
* Three-way comparison.
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
*/
|
||||
|
@ -163,15 +164,14 @@ public final class WordProperty implements Comparable<WordProperty> {
|
|||
|
||||
/**
|
||||
* Equality test.
|
||||
*
|
||||
* <p>
|
||||
* Words are equal if they have the same frequency, the same spellings, and the same
|
||||
* attributes.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof WordProperty)) return false;
|
||||
WordProperty w = (WordProperty)o;
|
||||
if (!(o instanceof WordProperty w)) return false;
|
||||
return mProbabilityInfo.equals(w.mProbabilityInfo) && mWord.equals(w.mWord)
|
||||
&& mShortcutTargets.equals(w.mShortcutTargets) && equals(mNgrams, w.mNgrams)
|
||||
&& mIsNotAWord == w.mIsNotAWord && mIsPossiblyOffensive == w.mIsPossiblyOffensive
|
||||
|
@ -199,7 +199,7 @@ public final class WordProperty implements Comparable<WordProperty> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@NonNull public String toString() {
|
||||
return CombinedFormatUtils.formatWordProperty(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public final class PermissionsActivity
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
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.
|
||||
if (mPendingRequestCode == INVALID_REQUEST_CODE) {
|
||||
final Bundle extras = getIntent().getExtras();
|
||||
final String[] permissionsToRequest =
|
||||
extras.getStringArray(EXTRA_PERMISSION_REQUESTED_PERMISSIONS);
|
||||
if (extras == null) return;
|
||||
final String[] permissionsToRequest = extras.getStringArray(EXTRA_PERMISSION_REQUESTED_PERMISSIONS);
|
||||
mPendingRequestCode = extras.getInt(EXTRA_PERMISSION_REQUEST_CODE);
|
||||
// Assuming that all supplied permissions are not granted yet, so that we don't need to
|
||||
// check them again.
|
||||
|
|
|
@ -73,6 +73,7 @@ import java.util.zip.ZipOutputStream
|
|||
* - Improve keyboard
|
||||
* - Debug settings
|
||||
*/
|
||||
@Suppress("KotlinConstantConditions") // build type might be a constant, but depends on... build type!
|
||||
class AdvancedSettingsFragment : SubScreenFragment() {
|
||||
private val libfile by lazy { File(requireContext().filesDir.absolutePath + File.separator + JniUtils.JNI_LIB_IMPORT_FILE_NAME) }
|
||||
private val backupFilePatterns by lazy { listOf(
|
||||
|
@ -436,8 +437,8 @@ class AdvancedSettingsFragment : SubScreenFragment() {
|
|||
}
|
||||
checkVersionUpgrade(requireContext())
|
||||
Settings.getInstance().startListener()
|
||||
val additionalSubtypes = Settings.readPrefAdditionalSubtypes(sharedPreferences, resources);
|
||||
updateAdditionalSubtypes(AdditionalSubtypeUtils.createAdditionalSubtypesArray(additionalSubtypes));
|
||||
val additionalSubtypes = Settings.readPrefAdditionalSubtypes(sharedPreferences, resources)
|
||||
updateAdditionalSubtypes(AdditionalSubtypeUtils.createAdditionalSubtypesArray(additionalSubtypes))
|
||||
reloadEnabledSubtypes(requireContext())
|
||||
val newDictBroadcast = Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION)
|
||||
activity?.sendBroadcast(newDictBroadcast)
|
||||
|
|
|
@ -21,7 +21,6 @@ import helium314.keyboard.latin.R;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
public final class SetupStartIndicatorView extends LinearLayout {
|
||||
public SetupStartIndicatorView(final Context context, final AttributeSet attrs) {
|
||||
|
@ -72,13 +71,13 @@ public final class SetupStartIndicatorView extends LinearLayout {
|
|||
@Override
|
||||
protected void onDraw(@NonNull final Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
final int layoutDirection = ViewCompat.getLayoutDirection(this);
|
||||
final int layoutDirection = getLayoutDirection();
|
||||
final int width = getWidth();
|
||||
final int height = getHeight();
|
||||
final float halfHeight = height / 2.0f;
|
||||
final Path path = mIndicatorPath;
|
||||
path.rewind();
|
||||
if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_RTL) {
|
||||
if (layoutDirection == View.LAYOUT_DIRECTION_RTL) {
|
||||
// Left arrow
|
||||
path.moveTo(width, 0.0f);
|
||||
path.lineTo(0.0f, halfHeight);
|
||||
|
|
|
@ -13,9 +13,9 @@ import android.graphics.Path;
|
|||
import android.util.AttributeSet;
|
||||
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 {
|
||||
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) {
|
||||
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 total step number.
|
||||
final float partionWidth = 1.0f / totalStepNum;
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(final Canvas canvas) {
|
||||
protected void onDraw(@NonNull final Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
final int xPos = (int)(getWidth() * mXRatio);
|
||||
final int height = getHeight();
|
||||
|
|
|
@ -7,10 +7,12 @@
|
|||
package helium314.keyboard.latin.suggestions;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import helium314.keyboard.keyboard.Key;
|
||||
import helium314.keyboard.keyboard.Keyboard;
|
||||
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,
|
||||
final int maxWidth, final int minWidth, final int maxRow, final Paint paint,
|
||||
final Resources res) {
|
||||
final Context context) {
|
||||
clearKeys();
|
||||
mDivider = res.getDrawable(R.drawable.more_suggestions_divider);
|
||||
mDividerWidth = mDivider.getIntrinsicWidth();
|
||||
final float padding = res.getDimension(
|
||||
R.dimen.config_more_suggestions_key_horizontal_padding);
|
||||
mDivider = ContextCompat.getDrawable(context, R.drawable.more_suggestions_divider);
|
||||
mDividerWidth = mDivider == null ? 0 : mDivider.getIntrinsicWidth();
|
||||
final float padding = context.getResources().getDimension(R.dimen.config_more_suggestions_key_horizontal_padding);
|
||||
|
||||
int row = 0;
|
||||
int index = fromIndex;
|
||||
|
@ -186,7 +187,7 @@ public final class MoreSuggestions extends Keyboard {
|
|||
mParams.mVerticalGap = mParams.mTopPadding = parentKeyboard.mVerticalGap / 2;
|
||||
mPaneView.updateKeyboardGeometry(mParams.mDefaultAbsoluteRowHeight);
|
||||
final int count = mParams.layout(suggestedWords, fromIndex, maxWidth, minWidth, maxRow,
|
||||
mPaneView.newLabelPaint(null /* key */), mResources);
|
||||
mPaneView.newLabelPaint(null /* key */), getMContext());
|
||||
mFromIndex = fromIndex;
|
||||
mToIndex = fromIndex + count;
|
||||
mSuggestedWords = suggestedWords;
|
||||
|
@ -194,7 +195,7 @@ public final class MoreSuggestions extends Keyboard {
|
|||
}
|
||||
|
||||
@Override
|
||||
public MoreSuggestions build() {
|
||||
@NonNull public MoreSuggestions build() {
|
||||
final MoreSuggestionsParam params = mParams;
|
||||
for (int index = mFromIndex; index < mToIndex; index++) {
|
||||
final int x = params.getX(index);
|
||||
|
|
|
@ -67,8 +67,8 @@ import java.util.ArrayList;
|
|||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
public final class SuggestionStripView extends RelativeLayout implements OnClickListener,
|
||||
OnLongClickListener {
|
||||
|
@ -76,7 +76,6 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
|||
void pickSuggestionManually(SuggestedWordInfo word);
|
||||
void onCodeInput(int primaryCode, int x, int y, boolean isKeyRepeat);
|
||||
void removeSuggestion(final String word);
|
||||
CharSequence getSelection();
|
||||
}
|
||||
|
||||
public static boolean DEBUG_SUGGESTIONS;
|
||||
|
@ -124,8 +123,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
|||
}
|
||||
|
||||
public void setLayoutDirection(final int layoutDirection) {
|
||||
ViewCompat.setLayoutDirection(mSuggestionStripView, layoutDirection);
|
||||
ViewCompat.setLayoutDirection(mSuggestionsStrip, layoutDirection);
|
||||
mSuggestionStripView.setLayoutDirection(layoutDirection);
|
||||
mSuggestionsStrip.setLayoutDirection(layoutDirection);
|
||||
}
|
||||
|
||||
public void showSuggestionsStrip() {
|
||||
|
@ -141,6 +140,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
|||
this(context, attrs, R.attr.suggestionStripViewStyle);
|
||||
}
|
||||
|
||||
@SuppressLint("InflateParams") // does not seem suitable here
|
||||
public SuggestionStripView(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
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);
|
||||
mMoreSuggestionsSlidingDetector = new GestureDetector(context, mMoreSuggestionsSlidingListener);
|
||||
|
||||
@SuppressLint("CustomViewStyleable")
|
||||
final TypedArray keyboardAttr = context.obtainStyledAttributes(attrs, R.styleable.Keyboard, defStyle, R.style.SuggestionStripView);
|
||||
mIncognitoIcon = keyboardAttr.getDrawable(R.styleable.Keyboard_iconIncognitoKey);
|
||||
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) {
|
||||
final int layoutDirection;
|
||||
if (!Settings.getInstance().getCurrent().mVarToolbarDirection)
|
||||
layoutDirection = ViewCompat.LAYOUT_DIRECTION_LOCALE;
|
||||
layoutDirection = View.LAYOUT_DIRECTION_LOCALE;
|
||||
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;
|
||||
}
|
||||
mStripVisibilityGroup.setLayoutDirection(layoutDirection);
|
||||
|
@ -528,7 +529,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
|||
private final GestureDetector.OnGestureListener mMoreSuggestionsSlidingListener =
|
||||
new GestureDetector.SimpleOnGestureListener() {
|
||||
@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();
|
||||
if (mToolbarContainer.getVisibility() != VISIBLE && deltaY > 0 && dy < 0) {
|
||||
return showMoreSuggestions();
|
||||
|
@ -637,7 +639,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
|
|||
AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(KeyCode.NOT_SPECIFIED, this);
|
||||
final Object tag = view.getTag();
|
||||
if (tag instanceof ToolbarKey) {
|
||||
final Integer code = getCodeForToolbarKey((ToolbarKey) tag);
|
||||
final int code = getCodeForToolbarKey((ToolbarKey) tag);
|
||||
if (code != KeyCode.UNSPECIFIED) {
|
||||
Log.d(TAG, "click toolbar key "+tag);
|
||||
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.latin.R
|
||||
import helium314.keyboard.latin.common.FileUtils
|
||||
import helium314.keyboard.latin.settings.Settings
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.math.BigInteger
|
||||
|
@ -80,13 +79,13 @@ private fun checkLayout(layoutContent: String, context: Context): Boolean? {
|
|||
params.mPopupKeyTypes.add(POPUP_KEYS_LAYOUT)
|
||||
addLocaleKeyTextsToParams(context, params, POPUP_KEYS_NORMAL)
|
||||
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))
|
||||
return null
|
||||
return true
|
||||
} catch (e: Exception) { Log.w(TAG, "error parsing custom json layout", e) }
|
||||
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))
|
||||
return null
|
||||
return false
|
||||
|
@ -94,7 +93,7 @@ private fun checkLayout(layoutContent: String, context: Context): Boolean? {
|
|||
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
|
||||
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) }
|
||||
}
|
||||
return null
|
||||
|
@ -109,19 +108,19 @@ private fun checkKeys(keys: List<List<Key.KeyParams>>): Boolean {
|
|||
Log.w(TAG, "too many rows")
|
||||
return false
|
||||
}
|
||||
if (keys.any { it.size > 20 }) {
|
||||
if (keys.any { row -> row.size > 20 }) {
|
||||
Log.w(TAG, "too many keys in one row")
|
||||
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")
|
||||
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")
|
||||
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")
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public class RecapitalizeStatus {
|
|||
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)) {
|
||||
return CAPS_MODE_ALL_UPPER;
|
||||
} else if (StringUtils.isIdenticalAfterDowncase(string)) {
|
||||
|
@ -42,14 +42,14 @@ public class RecapitalizeStatus {
|
|||
}
|
||||
|
||||
public static String modeToString(final int recapitalizeMode) {
|
||||
switch (recapitalizeMode) {
|
||||
case NOT_A_RECAPITALIZE_MODE: return "undefined";
|
||||
case CAPS_MODE_ORIGINAL_MIXED_CASE: return "mixedCase";
|
||||
case CAPS_MODE_ALL_LOWER: return "allLower";
|
||||
case CAPS_MODE_FIRST_WORD_UPPER: return "firstWordUpper";
|
||||
case CAPS_MODE_ALL_UPPER: return "allUpper";
|
||||
default: return "unknown<" + recapitalizeMode + ">";
|
||||
}
|
||||
return switch (recapitalizeMode) {
|
||||
case NOT_A_RECAPITALIZE_MODE -> "undefined";
|
||||
case CAPS_MODE_ORIGINAL_MIXED_CASE -> "mixedCase";
|
||||
case CAPS_MODE_ALL_LOWER -> "allLower";
|
||||
case CAPS_MODE_FIRST_WORD_UPPER -> "firstWordUpper";
|
||||
case CAPS_MODE_ALL_UPPER -> "allUpper";
|
||||
default -> "unknown<" + recapitalizeMode + ">";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -145,21 +145,10 @@ public class RecapitalizeStatus {
|
|||
}
|
||||
++count;
|
||||
switch (ROTATION_STYLE[mRotationStyleCurrentIndex]) {
|
||||
case CAPS_MODE_ORIGINAL_MIXED_CASE:
|
||||
mStringAfter = mStringBefore;
|
||||
break;
|
||||
case CAPS_MODE_ALL_LOWER:
|
||||
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;
|
||||
case CAPS_MODE_ALL_LOWER -> mStringAfter = mStringBefore.toLowerCase(mLocale);
|
||||
case CAPS_MODE_FIRST_WORD_UPPER -> mStringAfter = StringUtils.capitalizeEachWord(mStringBefore, mSortedSeparators, mLocale);
|
||||
case CAPS_MODE_ALL_UPPER -> mStringAfter = mStringBefore.toUpperCase(mLocale);
|
||||
default -> mStringAfter = mStringBefore;
|
||||
}
|
||||
} while (mStringAfter.equals(oldResult) && count < ROTATION_STYLE.length + 1);
|
||||
mCursorEndAfter = mCursorStartAfter + mStringAfter.length();
|
||||
|
|
|
@ -2,7 +2,6 @@ package helium314.keyboard
|
|||
|
||||
import helium314.keyboard.keyboard.internal.KeySpecParser
|
||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode
|
||||
import helium314.keyboard.latin.common.Constants
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
|
|
|
@ -867,7 +867,7 @@ private val ic = object : InputConnection {
|
|||
// update selection
|
||||
selectionStart -= beforeLength
|
||||
selectionEnd -= beforeLength
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
override fun sendKeyEvent(p0: KeyEvent): Boolean {
|
||||
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 reportFullscreenMode(p0: Boolean): 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 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 java.util.*
|
||||
|
||||
@Suppress("NonAsciiCharacters")
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(shadows = [
|
||||
ShadowLocaleManagerCompat::class,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.9.23'
|
||||
ext.kotlin_version = '1.9.24'
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
|
@ -17,7 +17,7 @@ buildscript {
|
|||
}
|
||||
|
||||
plugins {
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.23' apply false
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version "$kotlin_version"
|
||||
}
|
||||
|
||||
allprojects {
|
||||
|
|
Loading…
Add table
Reference in a new issue