From 3e6747c88083a0cf9653d6a095f0dd015ecf2deb Mon Sep 17 00:00:00 2001 From: Mishiranu Date: Sat, 17 Sep 2016 01:18:34 +0300 Subject: [PATCH] Add "Select text" context menu option --- .../ui/ConversationFragment.java | 60 +++++++++++++++++++ .../ui/adapter/MessageAdapter.java | 9 +++ src/main/res/menu/message_context.xml | 4 ++ src/main/res/values-ru/strings.xml | 1 + src/main/res/values/strings.xml | 1 + 5 files changed, 75 insertions(+) diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index c6f6b8cd3..da6f6da0e 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -12,6 +12,8 @@ import android.content.IntentSender.SendIntentException; import android.os.Bundle; import android.os.Handler; import android.text.InputType; +import android.text.Selection; +import android.text.Spannable; import android.util.Log; import android.util.Pair; import android.view.ContextMenu; @@ -38,6 +40,8 @@ import android.widget.Toast; import net.java.otr4j.session.SessionStatus; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -536,6 +540,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa activity.getMenuInflater().inflate(R.menu.message_context, menu); menu.setHeaderTitle(R.string.message_options); MenuItem copyText = menu.findItem(R.id.copy_text); + MenuItem selectText = menu.findItem(R.id.select_text); MenuItem retryDecryption = menu.findItem(R.id.retry_decryption); MenuItem correctMessage = menu.findItem(R.id.correct_message); MenuItem shareWith = menu.findItem(R.id.share_with); @@ -548,6 +553,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa && !GeoHelper.isGeoUri(m.getBody()) && m.treatAsDownloadable() != Message.Decision.MUST) { copyText.setVisible(true); + selectText.setVisible(METHOD_START_SELECTION != null); } if (m.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) { retryDecryption.setVisible(true); @@ -597,6 +603,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa case R.id.copy_text: copyText(selectedMessage); return true; + case R.id.select_text: + selectText(selectedMessage); + return true; case R.id.correct_message: correctMessage(selectedMessage); return true; @@ -656,6 +665,30 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } } + private void selectText(Message message) { + final int index; + synchronized (this.messageList) { + index = this.messageList.indexOf(message); + } + if (index >= 0) { + final int first = this.messagesView.getFirstVisiblePosition(); + final int last = first + this.messagesView.getChildCount(); + if (index >= first && index < last) { + final View view = this.messagesView.getChildAt(index - first); + final TextView messageBody = this.messageListAdapter.getMessageBody(view); + if (messageBody != null) { + final Spannable text = (Spannable) messageBody.getText(); + Selection.setSelection(text, 0, text.length()); + try { + Object editor = FIELD_EDITOR != null ? FIELD_EDITOR.get(messageBody) : messageBody; + METHOD_START_SELECTION.invoke(editor); + } catch (Exception e) { + } + } + } + } + } + private void deleteFile(Message message) { if (activity.xmppConnectionService.getFileBackend().deleteFile(message)) { message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED)); @@ -1430,4 +1463,31 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } } + private static final Field FIELD_EDITOR; + private static final Method METHOD_START_SELECTION; + + static { + Field editor; + try { + editor = TextView.class.getDeclaredField("mEditor"); + editor.setAccessible(true); + } catch (Exception e) { + editor = null; + } + FIELD_EDITOR = editor; + Class editorClass = editor != null ? editor.getType() : TextView.class; + String[] startSelectionNames = {"startSelectionActionMode", "startSelectionActionModeWithSelection"}; + Method startSelection = null; + for (String startSelectionName : startSelectionNames) { + try { + startSelection = editorClass.getDeclaredMethod(startSelectionName); + startSelection.setAccessible(true); + break; + } catch (Exception e) { + startSelection = null; + } + } + METHOD_START_SELECTION = startSelection; + } + } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 9e2b3ba7d..30a5dd6ed 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -736,6 +736,15 @@ public class MessageAdapter extends ArrayAdapter { this.mUseGreenBackground = activity.useGreenBackground(); } + public TextView getMessageBody(View view) { + final Object tag = view.getTag(); + if (tag instanceof ViewHolder) { + final ViewHolder viewHolder = (ViewHolder) tag; + return viewHolder.messageBody; + } + return null; + } + public interface OnContactPictureClicked { void onContactPictureClicked(Message message); } diff --git a/src/main/res/menu/message_context.xml b/src/main/res/menu/message_context.xml index bc8acede0..9bdbbcea8 100644 --- a/src/main/res/menu/message_context.xml +++ b/src/main/res/menu/message_context.xml @@ -5,6 +5,10 @@ android:id="@+id/copy_text" android:title="@string/copy_text" android:visible="false"/> + Проверьте размер %1$s на %2$s Опции сообщения Копировать текст + Выбрать текст Копировать адрес ссылки Отправить ещё раз URL файла diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 22d89a812..1d53a278a 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -362,6 +362,7 @@ Check %1$s size on %2$s Message options Copy text + Select text Copy original URL Send again File URL