From 7a825231fbb2338ef44b86943d0fdd0c4e977b63 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 17 Apr 2019 18:25:21 +0200 Subject: [PATCH] run keyboard listeners on background executor --- .../conversations/ui/widget/EditMessage.java | 302 +++++++++--------- 1 file changed, 155 insertions(+), 147 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/ui/widget/EditMessage.java b/src/main/java/eu/siacs/conversations/ui/widget/EditMessage.java index 359571dd3..1ce695ab3 100644 --- a/src/main/java/eu/siacs/conversations/ui/widget/EditMessage.java +++ b/src/main/java/eu/siacs/conversations/ui/widget/EditMessage.java @@ -19,176 +19,184 @@ import android.view.KeyEvent; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + import eu.siacs.conversations.Config; import eu.siacs.conversations.R; public class EditMessage extends EmojiWrapperEditText { - private static final InputFilter SPAN_FILTER = (source, start, end, dest, dstart, dend) -> source instanceof Spanned ? source.toString() : source; - protected Handler mTypingHandler = new Handler(); - protected KeyboardListener keyboardListener; - private OnCommitContentListener mCommitContentListener = null; - private String[] mimeTypes = null; - private boolean isUserTyping = false; - protected Runnable mTypingTimeout = new Runnable() { - @Override - public void run() { - if (isUserTyping && keyboardListener != null) { - keyboardListener.onTypingStopped(); - isUserTyping = false; - } - } - }; - private boolean lastInputWasTab = false; + private static final InputFilter SPAN_FILTER = (source, start, end, dest, dstart, dend) -> source instanceof Spanned ? source.toString() : source; + private final ExecutorService executor = Executors.newSingleThreadExecutor(); + protected Handler mTypingHandler = new Handler(); + protected KeyboardListener keyboardListener; + private OnCommitContentListener mCommitContentListener = null; + private String[] mimeTypes = null; + private boolean isUserTyping = false; + private final Runnable mTypingTimeout = new Runnable() { + @Override + public void run() { + if (isUserTyping && keyboardListener != null) { + keyboardListener.onTypingStopped(); + isUserTyping = false; + } + } + }; + private boolean lastInputWasTab = false; - public EditMessage(Context context, AttributeSet attrs) { - super(context, attrs); - } + public EditMessage(Context context, AttributeSet attrs) { + super(context, attrs); + } - public EditMessage(Context context) { - super(context); - } + public EditMessage(Context context) { + super(context); + } - @Override - public boolean onKeyDown(int keyCode, KeyEvent e) { - if (keyCode == KeyEvent.KEYCODE_ENTER && !e.isShiftPressed()) { - lastInputWasTab = false; - if (keyboardListener != null && keyboardListener.onEnterPressed()) { - return true; - } - } else if (keyCode == KeyEvent.KEYCODE_TAB && !e.isAltPressed() && !e.isCtrlPressed()) { - if (keyboardListener != null && keyboardListener.onTabPressed(this.lastInputWasTab)) { - lastInputWasTab = true; - return true; - } - } else { - lastInputWasTab = false; - } - return super.onKeyDown(keyCode, e); - } + @Override + public boolean onKeyDown(int keyCode, KeyEvent e) { + if (keyCode == KeyEvent.KEYCODE_ENTER && !e.isShiftPressed()) { + lastInputWasTab = false; + if (keyboardListener != null && keyboardListener.onEnterPressed()) { + return true; + } + } else if (keyCode == KeyEvent.KEYCODE_TAB && !e.isAltPressed() && !e.isCtrlPressed()) { + if (keyboardListener != null && keyboardListener.onTabPressed(this.lastInputWasTab)) { + lastInputWasTab = true; + return true; + } + } else { + lastInputWasTab = false; + } + return super.onKeyDown(keyCode, e); + } - @Override - public int getAutofillType() { - return AUTOFILL_TYPE_NONE; - } + @Override + public int getAutofillType() { + return AUTOFILL_TYPE_NONE; + } - @Override - public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { - super.onTextChanged(text, start, lengthBefore, lengthAfter); - lastInputWasTab = false; - if (this.mTypingHandler != null && this.keyboardListener != null) { - this.mTypingHandler.removeCallbacks(mTypingTimeout); - this.mTypingHandler.postDelayed(mTypingTimeout, Config.TYPING_TIMEOUT * 1000); - final int length = text.length(); - if (!isUserTyping && length > 0) { - this.isUserTyping = true; - this.keyboardListener.onTypingStarted(); - } else if (length == 0) { - this.isUserTyping = false; - this.keyboardListener.onTextDeleted(); - } - this.keyboardListener.onTextChanged(); - } - } - public void setKeyboardListener(KeyboardListener listener) { - this.keyboardListener = listener; - if (listener != null) { - this.isUserTyping = false; - } - } + @Override + public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { + super.onTextChanged(text, start, lengthBefore, lengthAfter); + lastInputWasTab = false; + if (this.mTypingHandler != null && this.keyboardListener != null) { + executor.execute(() -> triggerKeyboardEvents(text.length())); + } + } - @Override - public boolean onTextContextMenuItem(int id) { - if (id == android.R.id.paste) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - return super.onTextContextMenuItem(android.R.id.pasteAsPlainText); - } else { - Editable editable = getEditableText(); - InputFilter[] filters = editable.getFilters(); - InputFilter[] tempFilters = new InputFilter[filters != null ? filters.length + 1 : 1]; - if (filters != null) { - System.arraycopy(filters, 0, tempFilters, 1, filters.length); - } - tempFilters[0] = SPAN_FILTER; - editable.setFilters(tempFilters); - try { - return super.onTextContextMenuItem(id); - } finally { - editable.setFilters(filters); - } - } - } else { - return super.onTextContextMenuItem(id); - } - } + private void triggerKeyboardEvents(final int length) { + this.mTypingHandler.removeCallbacks(mTypingTimeout); + this.mTypingHandler.postDelayed(mTypingTimeout, Config.TYPING_TIMEOUT * 1000); + if (!isUserTyping && length > 0) { + this.isUserTyping = true; + this.keyboardListener.onTypingStarted(); + } else if (length == 0) { + this.isUserTyping = false; + this.keyboardListener.onTextDeleted(); + } + this.keyboardListener.onTextChanged(); + } - public void setRichContentListener(String[] mimeTypes, OnCommitContentListener listener) { - this.mimeTypes = mimeTypes; - this.mCommitContentListener = listener; - } + public void setKeyboardListener(KeyboardListener listener) { + this.keyboardListener = listener; + if (listener != null) { + this.isUserTyping = false; + } + } - public void insertAsQuote(String text) { - text = text.replaceAll("(\n *){2,}", "\n").replaceAll("(^|\n)", "$1> ").replaceAll("\n$", ""); - Editable editable = getEditableText(); - int position = getSelectionEnd(); - if (position == -1) position = editable.length(); - if (position > 0 && editable.charAt(position - 1) != '\n') { - editable.insert(position++, "\n"); - } - editable.insert(position, text); - position += text.length(); - editable.insert(position++, "\n"); - if (position < editable.length() && editable.charAt(position) != '\n') { - editable.insert(position, "\n"); - } - setSelection(position); - } + @Override + public boolean onTextContextMenuItem(int id) { + if (id == android.R.id.paste) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return super.onTextContextMenuItem(android.R.id.pasteAsPlainText); + } else { + Editable editable = getEditableText(); + InputFilter[] filters = editable.getFilters(); + InputFilter[] tempFilters = new InputFilter[filters != null ? filters.length + 1 : 1]; + if (filters != null) { + System.arraycopy(filters, 0, tempFilters, 1, filters.length); + } + tempFilters[0] = SPAN_FILTER; + editable.setFilters(tempFilters); + try { + return super.onTextContextMenuItem(id); + } finally { + editable.setFilters(filters); + } + } + } else { + return super.onTextContextMenuItem(id); + } + } - @Override - public InputConnection onCreateInputConnection(EditorInfo editorInfo) { - final InputConnection ic = super.onCreateInputConnection(editorInfo); + public void setRichContentListener(String[] mimeTypes, OnCommitContentListener listener) { + this.mimeTypes = mimeTypes; + this.mCommitContentListener = listener; + } - if (mimeTypes != null && mCommitContentListener != null && ic != null) { - EditorInfoCompat.setContentMimeTypes(editorInfo, mimeTypes); - return InputConnectionCompat.createWrapper(ic, editorInfo, (inputContentInfo, flags, opts) -> EditMessage.this.mCommitContentListener.onCommitContent(inputContentInfo, flags, opts, mimeTypes)); - } else { - return ic; - } - } + public void insertAsQuote(String text) { + text = text.replaceAll("(\n *){2,}", "\n").replaceAll("(^|\n)", "$1> ").replaceAll("\n$", ""); + Editable editable = getEditableText(); + int position = getSelectionEnd(); + if (position == -1) position = editable.length(); + if (position > 0 && editable.charAt(position - 1) != '\n') { + editable.insert(position++, "\n"); + } + editable.insert(position, text); + position += text.length(); + editable.insert(position++, "\n"); + if (position < editable.length() && editable.charAt(position) != '\n') { + editable.insert(position, "\n"); + } + setSelection(position); + } - public void refreshIme() { - SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(getContext()); - final boolean usingEnterKey = p.getBoolean("display_enter_key", getResources().getBoolean(R.bool.display_enter_key)); - final boolean enterIsSend = p.getBoolean("enter_is_send", getResources().getBoolean(R.bool.enter_is_send)); + @Override + public InputConnection onCreateInputConnection(EditorInfo editorInfo) { + final InputConnection ic = super.onCreateInputConnection(editorInfo); - if (usingEnterKey && enterIsSend) { - setInputType(getInputType() & (~InputType.TYPE_TEXT_FLAG_MULTI_LINE)); - setInputType(getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE)); - } else if (usingEnterKey) { - setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE); - setInputType(getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE)); - } else { - setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE); - setInputType(getInputType() | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE); - } - } + if (mimeTypes != null && mCommitContentListener != null && ic != null) { + EditorInfoCompat.setContentMimeTypes(editorInfo, mimeTypes); + return InputConnectionCompat.createWrapper(ic, editorInfo, (inputContentInfo, flags, opts) -> EditMessage.this.mCommitContentListener.onCommitContent(inputContentInfo, flags, opts, mimeTypes)); + } else { + return ic; + } + } - public interface OnCommitContentListener { - boolean onCommitContent(InputContentInfoCompat inputContentInfo, int flags, Bundle opts, String[] mimeTypes); - } + public void refreshIme() { + SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(getContext()); + final boolean usingEnterKey = p.getBoolean("display_enter_key", getResources().getBoolean(R.bool.display_enter_key)); + final boolean enterIsSend = p.getBoolean("enter_is_send", getResources().getBoolean(R.bool.enter_is_send)); - public interface KeyboardListener { - boolean onEnterPressed(); + if (usingEnterKey && enterIsSend) { + setInputType(getInputType() & (~InputType.TYPE_TEXT_FLAG_MULTI_LINE)); + setInputType(getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE)); + } else if (usingEnterKey) { + setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE); + setInputType(getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE)); + } else { + setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE); + setInputType(getInputType() | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE); + } + } - void onTypingStarted(); + public interface OnCommitContentListener { + boolean onCommitContent(InputContentInfoCompat inputContentInfo, int flags, Bundle opts, String[] mimeTypes); + } - void onTypingStopped(); + public interface KeyboardListener { + boolean onEnterPressed(); - void onTextDeleted(); + void onTypingStarted(); - void onTextChanged(); + void onTypingStopped(); - boolean onTabPressed(boolean repeated); - } + void onTextDeleted(); + + void onTextChanged(); + + boolean onTabPressed(boolean repeated); + } }