1
0
Fork 0

fix sending messages in Viber using its own button causing the last word to reappear, when trying to type right after sending

This commit is contained in:
sspanak 2024-06-10 11:54:00 +03:00 committed by Dimo Karaivanov
parent 973b967c20
commit 2962e22efa
5 changed files with 63 additions and 3 deletions

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:tools="http://schemas.android.com/tools"
android:versionCode="556"
android:versionCode="558"
android:versionName="33.0"
xmlns:android="http://schemas.android.com/apk/res/android">

View file

@ -5,6 +5,8 @@ import android.view.inputmethod.InputConnection;
import androidx.annotation.NonNull;
import io.github.sspanak.tt9.ime.helpers.CursorOps;
import io.github.sspanak.tt9.ime.helpers.SuggestionOps;
import io.github.sspanak.tt9.ime.helpers.TextField;
import io.github.sspanak.tt9.ime.modes.InputMode;
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
@ -68,6 +70,29 @@ public class AppHacks {
}
/**
* Performs extra operations when the cursor moves and returns "true" if the selection was handled, "false" otherwise.
*/
public boolean onUpdateSelection(
@NonNull InputMode inputMode,
@NonNull SuggestionOps suggestionOps,
int oldSelStart,
int oldSelEnd,
int newSelStart,
int newSelEnd,
int candidatesStart,
int candidatesEnd
) {
if (inputType.isViber() && CursorOps.isInputReset(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd)) {
inputMode.onAcceptSuggestion(suggestionOps.acceptIncomplete());
inputMode.reset();
return true;
}
return false;
}
/**
* onEnter
* Tries to guess and send the correct confirmation key code or sequence of key codes,

View file

@ -101,6 +101,20 @@ public class InputType extends StandardInputType {
return isAppField("com.termux", EditorInfo.TYPE_NULL) && field.fieldId > 0;
}
/**
* isViber
* When sending messages using the Viber's SEND button, it does so and clears the text field,
* but without notifying the keyboard. This means, after sending the message, the InputMode still
* holds the old text, while the text field is empty. Attempting to type a new word then results
* in appending to the old word. We use this hack to detect Viber and reset the InputMode upon
* sending a message.
*/
public boolean isViber() {
return isAppField("com.viber.voip", EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE);
}
public boolean isNotUs(Context context) {
return !isAppField(context.getPackageName(), EditorInfo.TYPE_NULL);
}

View file

@ -13,6 +13,7 @@ import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.db.DictionaryLoader;
import io.github.sspanak.tt9.hacks.AppHacks;
import io.github.sspanak.tt9.hacks.InputType;
import io.github.sspanak.tt9.ime.helpers.CursorOps;
import io.github.sspanak.tt9.ime.helpers.InputModeValidator;
import io.github.sspanak.tt9.ime.helpers.SuggestionOps;
import io.github.sspanak.tt9.ime.helpers.TextField;
@ -275,12 +276,16 @@ public abstract class TypingHandler extends KeyPadHandler {
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd);
// in case the app has modified the InputField and moved the cursor without notifiying us...
if (appHacks.onUpdateSelection(mInputMode, suggestionOps, oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd)) {
return;
}
// If the cursor moves while composing a word (usually, because the user has touched the screen outside the word), we must
// end typing end accept the word. Otherwise, the cursor would jump back at the end of the word, after the next key press.
// This is confusing from user perspective, so we want to avoid it.
if (
candidatesStart != -1 && candidatesEnd != -1
&& (newSelStart != candidatesEnd || newSelEnd != candidatesEnd)
CursorOps.isMovedManually(newSelStart, newSelEnd, candidatesStart, candidatesEnd)
&& !suggestionOps.isEmpty()
) {
mInputMode.onAcceptSuggestion(suggestionOps.acceptIncomplete());

View file

@ -0,0 +1,16 @@
package io.github.sspanak.tt9.ime.helpers;
public class CursorOps {
public static boolean isMovedManually(int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) {
return
candidatesStart != -1 && candidatesEnd != -1
&& (newSelStart != candidatesEnd || newSelEnd != candidatesEnd);
}
public static boolean isInputReset(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) {
return
oldSelStart > 0 && oldSelEnd > 0
&& newSelStart == 0 && newSelEnd == 0
&& candidatesStart == -1 && candidatesEnd == -1;
}
}