Allow selecting text and quoting the selection (Cheogram)
(cherry picked from commit e46be58711
)
This commit is contained in:
parent
f486f6c4e5
commit
f5ef2825d7
9 changed files with 78 additions and 8 deletions
|
@ -0,0 +1,47 @@
|
|||
package de.monocles.chat;
|
||||
|
||||
import android.view.ActionMode;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.TextView;
|
||||
|
||||
import eu.siacs.conversations.R;
|
||||
import eu.siacs.conversations.ui.adapter.MessageAdapter;
|
||||
|
||||
public class MessageTextActionModeCallback implements ActionMode.Callback {
|
||||
final MessageAdapter adapter;
|
||||
final TextView text;
|
||||
|
||||
public MessageTextActionModeCallback(MessageAdapter adapter, TextView text) {
|
||||
this.adapter = adapter;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateActionMode(final ActionMode mode, final Menu menu) {
|
||||
final MenuInflater inflater = mode.getMenuInflater();
|
||||
inflater.inflate(R.menu.message_text_actions, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(final ActionMode mode, final MenuItem item) {
|
||||
if (item.getItemId() == R.id.quote) {
|
||||
int start = text.getSelectionStart();
|
||||
int end = text.getSelectionEnd();
|
||||
if (start < 0 || end < 0) return false;
|
||||
adapter.quoteText(text.getText().subSequence(start, end).toString(), null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode) {}
|
||||
}
|
|
@ -1038,6 +1038,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
|
|||
|
||||
public static class MergeSeparator {
|
||||
}
|
||||
|
||||
public SpannableStringBuilder getSpannableBody(GetThumbnailForCid thumbnailer, Drawable fallbackImg) {
|
||||
final Element html = getHtml();
|
||||
if (html == null || Build.VERSION.SDK_INT < 24) {
|
||||
|
@ -1060,6 +1061,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
|
|||
},
|
||||
(opening, tag, output, xmlReader) -> {}
|
||||
));
|
||||
|
||||
// Make images clickable and long-clickable with BetterLinkMovementMethod
|
||||
ImageSpan[] imageSpans = spannable.getSpans(0, spannable.length(), ImageSpan.class);
|
||||
for (ImageSpan span : imageSpans) {
|
||||
|
@ -1083,7 +1085,6 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public Element getHtml() {
|
||||
return getHtml(false);
|
||||
}
|
||||
|
|
|
@ -1573,6 +1573,7 @@ public class ConversationFragment extends XmppFragment
|
|||
messageListAdapter.setOnContactPictureClicked(this);
|
||||
messageListAdapter.setOnContactPictureLongClicked(this);
|
||||
messageListAdapter.setOnInlineImageLongClicked(this);
|
||||
messageListAdapter.setConversationFragment(this);
|
||||
binding.messagesView.setAdapter(messageListAdapter);
|
||||
registerForContextMenu(binding.messagesView);
|
||||
registerForContextMenu(binding.textSendButton);
|
||||
|
@ -1693,6 +1694,7 @@ public class ConversationFragment extends XmppFragment
|
|||
messageListAdapter.setOnContactPictureClicked(null);
|
||||
messageListAdapter.setOnContactPictureLongClicked(null);
|
||||
messageListAdapter.setOnInlineImageLongClicked(null);
|
||||
messageListAdapter.setConversationFragment(null);
|
||||
binding.conversationViewPager.setAdapter(null);
|
||||
if (conversation != null) conversation.setupViewPager(null, null, false, null);
|
||||
}
|
||||
|
@ -1704,7 +1706,7 @@ public class ConversationFragment extends XmppFragment
|
|||
|
||||
}
|
||||
|
||||
private void quoteText(String text, String user) {
|
||||
public void quoteText(String text, String user) {
|
||||
if (binding.textinput.isEnabled()) {
|
||||
String username = "";
|
||||
if (user != null && user.length() > 0) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package eu.siacs.conversations.ui.adapter;
|
||||
|
||||
import de.monocles.chat.BobTransfer;
|
||||
import de.monocles.chat.MessageTextActionModeCallback;
|
||||
import de.monocles.chat.Util;
|
||||
import eu.siacs.conversations.ui.widget.ClickableMovementMethod;
|
||||
import eu.siacs.conversations.utils.Compatibility;
|
||||
|
@ -166,6 +167,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
|
|||
private final boolean mForceNames;
|
||||
private final Map<String, WebxdcUpdate> lastWebxdcUpdate = new HashMap<>();
|
||||
private String readmarkervalue;
|
||||
private ConversationFragment mConversationFragment = null;
|
||||
|
||||
|
||||
public MessageAdapter(final XmppActivity activity, final List<Message> messages, final boolean forceNames) {
|
||||
super(activity, 0, messages);
|
||||
|
@ -658,7 +661,6 @@ public class MessageAdapter extends ArrayAdapter<Message> {
|
|||
return startsWithQuote;
|
||||
}
|
||||
|
||||
|
||||
private SpannableStringBuilder getSpannableBody(final Message message) {
|
||||
Drawable fallbackImg = ResourcesCompat.getDrawable(activity.getResources(), activity.getThemeResource(R.attr.ic_attach_photo, R.drawable.ic_attach_photo), null);
|
||||
return message.getMergedBody((cid) -> {
|
||||
|
@ -1496,6 +1498,10 @@ public class MessageAdapter extends ArrayAdapter<Message> {
|
|||
}
|
||||
}
|
||||
|
||||
if (viewHolder.messageBody != null) {
|
||||
viewHolder.messageBody.setCustomSelectionActionModeCallback(new MessageTextActionModeCallback(this, viewHolder.messageBody));
|
||||
}
|
||||
|
||||
if (viewHolder.thread_identicon != null) {
|
||||
viewHolder.thread_identicon.setVisibility(GONE);
|
||||
final Element thread = message.getThread();
|
||||
|
@ -1947,8 +1953,12 @@ public class MessageAdapter extends ArrayAdapter<Message> {
|
|||
this.highlightedTerm = terms == null ? null : StylingHelper.filterHighlightedWords(terms);
|
||||
}
|
||||
|
||||
public interface OnQuoteListener {
|
||||
void onQuote(String text, String user);
|
||||
public void setConversationFragment(ConversationFragment frag) {
|
||||
mConversationFragment = frag;
|
||||
}
|
||||
|
||||
public void quoteText(String text, String user) {
|
||||
if (mConversationFragment != null) mConversationFragment.quoteText(text, null);
|
||||
}
|
||||
|
||||
public interface OnContactPictureClicked {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:autoLink="web"
|
||||
android:longClickable="false"
|
||||
android:textIsSelectable="true"
|
||||
android:textAppearance="@style/TextAppearance.Conversations.Body1" />
|
||||
|
||||
<de.monocles.chat.ReadMoreTextView
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
android:visible="false" />
|
||||
<item
|
||||
android:id="@+id/quote_message"
|
||||
android:title="@string/quote"
|
||||
android:title="@string/reply"
|
||||
android:visible="false" />
|
||||
<item
|
||||
android:id="@+id/delete_message"
|
||||
|
|
9
src/main/res/menu/message_text_actions.xml
Normal file
9
src/main/res/menu/message_text_actions.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/quote"
|
||||
android:title="@string/quote"
|
||||
android:orderInCategory="1"/>
|
||||
|
||||
</menu>
|
|
@ -623,7 +623,7 @@
|
|||
<string name="copy_to_clipboard">In Zwischenablage kopieren</string>
|
||||
<string name="message_copied_to_clipboard">Nachricht in Zwischenablage kopiert</string>
|
||||
<string name="message">Nachricht</string>
|
||||
<string name="quote">Antworten</string>
|
||||
<string name="quote">Zitieren</string>
|
||||
<string name="show_error_message">Zeige Fehlermeldung</string>
|
||||
<string name="error_message">Fehlermeldung</string>
|
||||
<string name="data_saver_enabled">Datensparmodus aktiviert</string>
|
||||
|
|
|
@ -579,7 +579,7 @@
|
|||
<string name="copy_to_clipboard">Copy to clipboard</string>
|
||||
<string name="message_copied_to_clipboard">Message copied to clipboard</string>
|
||||
<string name="message">Message</string>
|
||||
<string name="quote">Reply</string>
|
||||
<string name="quote">Quote</string>
|
||||
<string name="show_error_message">Show error message</string>
|
||||
<string name="error_message">Error message</string>
|
||||
<string name="data_saver_enabled">Data saver enabled</string>
|
||||
|
|
Loading…
Add table
Reference in a new issue