diff --git a/src/org/thoughtcrime/securesms/BaseConversationItem.java b/src/org/thoughtcrime/securesms/BaseConversationItem.java new file mode 100644 index 000000000..41015ae1c --- /dev/null +++ b/src/org/thoughtcrime/securesms/BaseConversationItem.java @@ -0,0 +1,125 @@ +package org.thoughtcrime.securesms; + +import android.content.Context; +import android.content.Intent; +import android.text.util.Linkify; +import android.util.AttributeSet; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; + +import com.b44t.messenger.DcChat; +import com.b44t.messenger.DcContext; +import com.b44t.messenger.DcMsg; + +import org.thoughtcrime.securesms.connect.ApplicationDcContext; +import org.thoughtcrime.securesms.connect.DcHelper; + +import java.util.HashSet; +import java.util.Set; + +public abstract class BaseConversationItem extends LinearLayout + implements BindableConversationItem +{ + protected DcMsg messageRecord; + protected DcChat dcChat; + protected TextView bodyText; + + protected final Context context; + protected final ApplicationDcContext dcContext; + + protected @NonNull Set batchSelected = new HashSet<>(); + + protected final PassthroughClickListener passthroughClickListener = new PassthroughClickListener(); + + public BaseConversationItem(Context context, AttributeSet attrs) { + super(context, attrs); + this.context = context; + this.dcContext = DcHelper.getContext(context); + } + + protected void bind(@NonNull DcMsg messageRecord, + @NonNull DcChat dcChat, + @NonNull Set batchSelected) + { + this.messageRecord = messageRecord; + this.dcChat = dcChat; + this.batchSelected = batchSelected; + } + + @Override + public void setOnClickListener(OnClickListener l) { + super.setOnClickListener(new ClickListener(l)); + } + + protected boolean shouldInterceptClicks(DcMsg messageRecord) { + return batchSelected.isEmpty() && (messageRecord.isFailed()); + } + + protected void handleDeadDropClick() { + ConversationListFragment.DeaddropQuestionHelper helper = new ConversationListFragment.DeaddropQuestionHelper(context, messageRecord); + new AlertDialog.Builder(context) + .setPositiveButton(android.R.string.ok, (dialog, which) -> { + int chatId = dcContext.decideOnContactRequest(messageRecord.getId(), DcContext.DC_DECISION_START_CHAT); + if( chatId != 0 ) { + Intent intent = new Intent(context, ConversationActivity.class); + intent.putExtra(ConversationActivity.CHAT_ID_EXTRA, chatId); + context.startActivity(intent); + } + }) + .setNegativeButton(android.R.string.cancel, null) + .setNeutralButton(helper.answerBlock, (dialog, which) -> dcContext.decideOnContactRequest(messageRecord.getId(), DcContext.DC_DECISION_BLOCK)) + .setMessage(helper.question) + .show(); + } + + protected class PassthroughClickListener implements View.OnLongClickListener, View.OnClickListener { + + @Override + public boolean onLongClick(View v) { + if (bodyText.hasSelection()) { + return false; + } + performLongClick(); + return true; + } + + @Override + public void onClick(View v) { + performClick(); + } + } + + protected class ClickListener implements View.OnClickListener { + private OnClickListener parent; + + ClickListener(@Nullable OnClickListener parent) { + this.parent = parent; + } + + public void onClick(View v) { + if (dcChat.getId() == DcChat.DC_CHAT_ID_DEADDROP && batchSelected.isEmpty()) { + handleDeadDropClick(); + } else if (!shouldInterceptClicks(messageRecord) && parent != null) { + parent.onClick(v); + } else if (messageRecord.isFailed()) { + AlertDialog d = new AlertDialog.Builder(context) + .setMessage(messageRecord.getError()) + .setTitle(R.string.error) + .setPositiveButton(R.string.ok, null) + .create(); + d.show(); + try { + //noinspection ConstantConditions + Linkify.addLinks((TextView) d.findViewById(android.R.id.message), Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES); + } catch(NullPointerException e) { + e.printStackTrace(); + } + } + } + } +} diff --git a/src/org/thoughtcrime/securesms/ConversationItem.java b/src/org/thoughtcrime/securesms/ConversationItem.java index 608e3f736..40f3e8a8d 100644 --- a/src/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/org/thoughtcrime/securesms/ConversationItem.java @@ -24,24 +24,20 @@ import android.graphics.PorterDuff; import android.graphics.Rect; import android.text.SpannableString; import android.text.TextUtils; -import android.text.util.Linkify; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.widget.Button; -import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.DimenRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; import com.b44t.messenger.DcChat; import com.b44t.messenger.DcContact; -import com.b44t.messenger.DcContext; import com.b44t.messenger.DcMsg; import org.thoughtcrime.securesms.audio.AudioSlidePlayer; @@ -53,8 +49,6 @@ import org.thoughtcrime.securesms.components.ConversationItemThumbnail; import org.thoughtcrime.securesms.components.DocumentView; import org.thoughtcrime.securesms.components.QuoteView; import org.thoughtcrime.securesms.components.emoji.EmojiTextView; -import org.thoughtcrime.securesms.connect.ApplicationDcContext; -import org.thoughtcrime.securesms.connect.DcHelper; import org.thoughtcrime.securesms.mms.AudioSlide; import org.thoughtcrime.securesms.mms.DocumentSlide; import org.thoughtcrime.securesms.mms.GlideApp; @@ -71,7 +65,6 @@ import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.util.views.Stub; -import java.util.HashSet; import java.util.Locale; import java.util.Set; @@ -83,8 +76,7 @@ import java.util.Set; * */ -public class ConversationItem extends LinearLayout - implements BindableConversationItem +public class ConversationItem extends BaseConversationItem { private static final String TAG = ConversationItem.class.getSimpleName(); @@ -93,8 +85,6 @@ public class ConversationItem extends LinearLayout private static final int MAX_MEASURE_CALLS = 3; static long PULSE_HIGHLIGHT_MILLIS = 500; - private DcMsg messageRecord; - private DcChat dcChat; private DcContact dcContact; private Locale locale; // Whether the sender's avatar and name should be shown (usually the case in group threads): @@ -104,7 +94,6 @@ public class ConversationItem extends LinearLayout protected ViewGroup bodyBubble; protected View replyView; @Nullable private QuoteView quoteView; - private TextView bodyText; private ConversationItemFooter footer; private ConversationItemFooter stickerFooter; private TextView groupSender; @@ -114,7 +103,6 @@ public class ConversationItem extends LinearLayout private ViewGroup container; private Button showFullMessage; - private @NonNull Set batchSelected = new HashSet<>(); private @NonNull Recipient conversationRecipient; private @NonNull Stub mediaThumbnailStub; private @NonNull Stub audioViewStub; @@ -127,24 +115,12 @@ public class ConversationItem extends LinearLayout private int incomingBubbleColor; private int outgoingBubbleColor; - private final PassthroughClickListener passthroughClickListener = new PassthroughClickListener(); - - private final Context context; - private final ApplicationDcContext dcContext; - public ConversationItem(Context context) { this(context, null); } public ConversationItem(Context context, AttributeSet attrs) { super(context, attrs); - this.context = context; - this.dcContext = DcHelper.getContext(context); - } - - @Override - public void setOnClickListener(OnClickListener l) { - super.setOnClickListener(new ClickListener(l)); } @Override @@ -187,11 +163,9 @@ public class ConversationItem extends LinearLayout @NonNull Recipient recipients, boolean pulseHighlight) { - this.messageRecord = messageRecord; - this.dcChat = dcChat; + bind(messageRecord, dcChat, batchSelected); this.locale = locale; this.glideRequests = glideRequests; - this.batchSelected = batchSelected; this.conversationRecipient = recipients; this.showSender = dcChat.isGroup() || messageRecord.getOverrideSenderName() != null; @@ -211,7 +185,6 @@ public class ConversationItem extends LinearLayout setMessageSpacing(context); setFooter(messageRecord, locale); setQuote(messageRecord); - } @@ -652,10 +625,6 @@ public class ConversationItem extends LinearLayout return context.getResources().getDimensionPixelOffset(dimenId); } - private boolean shouldInterceptClicks(DcMsg messageRecord) { - return batchSelected.isEmpty() && (messageRecord.isFailed()); - } - private void setGroupMessageStatus() { if (messageRecord.getType()==DcMsg.DC_MSG_STICKER) { this.groupSender.setVisibility(GONE); @@ -743,23 +712,6 @@ public class ConversationItem extends LinearLayout /// Event handlers - private void handleDeadDropClick() { - ConversationListFragment.DeaddropQuestionHelper helper = new ConversationListFragment.DeaddropQuestionHelper(context, messageRecord); - new AlertDialog.Builder(context) - .setPositiveButton(android.R.string.ok, (dialog, which) -> { - int chatId = dcContext.decideOnContactRequest(messageRecord.getId(), DcContext.DC_DECISION_START_CHAT); - if( chatId != 0 ) { - Intent intent = new Intent(context, ConversationActivity.class); - intent.putExtra(ConversationActivity.CHAT_ID_EXTRA, chatId); - context.startActivity(intent); - } - }) - .setNegativeButton(android.R.string.cancel, null) - .setNeutralButton(helper.answerBlock, (dialog, which) -> dcContext.decideOnContactRequest(messageRecord.getId(), DcContext.DC_DECISION_BLOCK)) - .setMessage(helper.question) - .show(); - } - private class ThumbnailClickListener implements SlideClickListener { public void onClick(final View v, final Slide slide) { if (dcChat.getId() == DcChat.DC_CHAT_ID_DEADDROP && batchSelected.isEmpty()) { @@ -790,50 +742,4 @@ public class ConversationItem extends LinearLayout } } } - - private class PassthroughClickListener implements View.OnLongClickListener, View.OnClickListener { - - @Override - public boolean onLongClick(View v) { - if (bodyText.hasSelection()) { - return false; - } - performLongClick(); - return true; - } - - @Override - public void onClick(View v) { - performClick(); - } - } - - private class ClickListener implements View.OnClickListener { - private OnClickListener parent; - - ClickListener(@Nullable OnClickListener parent) { - this.parent = parent; - } - - public void onClick(View v) { - if (dcChat.getId() == DcChat.DC_CHAT_ID_DEADDROP && batchSelected.isEmpty()) { - handleDeadDropClick(); - } else if (!shouldInterceptClicks(messageRecord) && parent != null) { - parent.onClick(v); - } else if (messageRecord.isFailed()) { - AlertDialog d = new AlertDialog.Builder(context) - .setMessage(messageRecord.getError()) - .setTitle(R.string.error) - .setPositiveButton(R.string.ok, null) - .create(); - d.show(); - try { - //noinspection ConstantConditions - Linkify.addLinks((TextView) d.findViewById(android.R.id.message), Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES); - } catch(NullPointerException e) { - e.printStackTrace(); - } - } - } - } } diff --git a/src/org/thoughtcrime/securesms/ConversationUpdateItem.java b/src/org/thoughtcrime/securesms/ConversationUpdateItem.java index f18b3a784..51052b077 100644 --- a/src/org/thoughtcrime/securesms/ConversationUpdateItem.java +++ b/src/org/thoughtcrime/securesms/ConversationUpdateItem.java @@ -7,7 +7,6 @@ import android.graphics.Color; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import android.util.AttributeSet; -import android.widget.LinearLayout; import android.widget.TextView; import com.b44t.messenger.DcChat; @@ -20,25 +19,17 @@ import org.thoughtcrime.securesms.recipients.Recipient; import java.util.Locale; import java.util.Set; -public class ConversationUpdateItem extends LinearLayout - implements BindableConversationItem +public class ConversationUpdateItem extends BaseConversationItem { - private Set batchSelected; - private DeliveryStatusView deliveryStatusView; - private TextView body; - private DcMsg messageRecord; private int textColor; - private final Context context; - public ConversationUpdateItem(Context context) { this(context, null); } public ConversationUpdateItem(Context context, AttributeSet attrs) { super(context, attrs); - this.context = context; } @Override @@ -47,8 +38,12 @@ public class ConversationUpdateItem extends LinearLayout initializeAttributes(); - body = findViewById(R.id.conversation_update_body); + bodyText = findViewById(R.id.conversation_update_body); deliveryStatusView = new DeliveryStatusView(findViewById(R.id.delivery_indicator)); + + bodyText.setOnLongClickListener(passthroughClickListener); + bodyText.setOnClickListener(passthroughClickListener); + } @Override @@ -60,9 +55,9 @@ public class ConversationUpdateItem extends LinearLayout @NonNull Recipient conversationRecipient, boolean pulseUpdate) { - this.batchSelected = batchSelected; - - bind(messageRecord); + bind(messageRecord, dcChat, batchSelected); + setGenericInfoRecord(messageRecord); + setSelected(batchSelected.contains(messageRecord)); } private void initializeAttributes() { @@ -85,15 +80,9 @@ public class ConversationUpdateItem extends LinearLayout return messageRecord; } - private void bind(@NonNull DcMsg messageRecord) { - this.messageRecord = messageRecord; - setGenericInfoRecord(messageRecord); - setSelected(batchSelected.contains(messageRecord)); - } - private void setGenericInfoRecord(DcMsg messageRecord) { - body.setText(messageRecord.getDisplayBody()); - body.setVisibility(VISIBLE); + bodyText.setText(messageRecord.getDisplayBody()); + bodyText.setVisibility(VISIBLE); if (!messageRecord.isOutgoing()) deliveryStatusView.setNone(); else if (messageRecord.isFailed()) deliveryStatusView.setFailed();