@@ -15,6 +15,7 @@ import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -33,6 +34,7 @@ import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.widget.ImageViewCompat;
+import androidx.databinding.DataBindingUtil;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.chip.ChipGroup;
import com.google.android.material.color.MaterialColors;
@@ -45,6 +47,11 @@ import eu.siacs.conversations.AppSettings;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
+import eu.siacs.conversations.databinding.ItemMessageDateBubbleBinding;
+import eu.siacs.conversations.databinding.ItemMessageReceivedBinding;
+import eu.siacs.conversations.databinding.ItemMessageRtpSessionBinding;
+import eu.siacs.conversations.databinding.ItemMessageSentBinding;
+import eu.siacs.conversations.databinding.ItemMessageStatusBinding;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Conversational;
@@ -175,15 +182,12 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
private void displayStatus(
- final ViewHolder viewHolder,
+ final BubbleMessageItemViewHolder viewHolder,
final Message message,
final int type,
final BubbleColor bubbleColor) {
final int mergedStatus = message.getStatus();
final boolean error;
- if (viewHolder.indicatorReceived != null) {
- viewHolder.indicatorReceived.setVisibility(View.GONE);
- }
final Transferable transferable = message.getTransferable();
final boolean multiReceived =
message.getConversation().getMode() == Conversation.MODE_MULTI
@@ -207,32 +211,35 @@ public class MessageAdapter extends ArrayAdapter<Message> {
fileSize = null;
error = message.getStatus() == Message.STATUS_SEND_FAILED;
}
- if (type == SENT) {
+ if (type == SENT && viewHolder instanceof EndBubbleMessageItemViewHolder endViewHolder) {
final @DrawableRes Integer receivedIndicator =
getMessageStatusAsDrawable(message, mergedStatus);
if (receivedIndicator == null) {
- viewHolder.indicatorReceived.setVisibility(View.INVISIBLE);
+ endViewHolder.indicatorReceived().setVisibility(View.INVISIBLE);
} else {
- viewHolder.indicatorReceived.setImageResource(receivedIndicator);
+ endViewHolder.indicatorReceived().setImageResource(receivedIndicator);
if (mergedStatus == Message.STATUS_SEND_FAILED) {
- setImageTintError(viewHolder.indicatorReceived);
+ setImageTintError(endViewHolder.indicatorReceived());
} else {
- setImageTint(viewHolder.indicatorReceived, bubbleColor);
+ setImageTint(endViewHolder.indicatorReceived(), bubbleColor);
}
- viewHolder.indicatorReceived.setVisibility(View.VISIBLE);
+ endViewHolder.indicatorReceived().setVisibility(View.VISIBLE);
}
}
final var additionalStatusInfo = getAdditionalStatusInfo(message, mergedStatus);
if (error && type == SENT) {
- viewHolder.time.setTextColor(
- MaterialColors.getColor(
- viewHolder.time, com.google.android.material.R.attr.colorError));
+ viewHolder
+ .time()
+ .setTextColor(
+ MaterialColors.getColor(
+ viewHolder.time(),
+ com.google.android.material.R.attr.colorError));
} else {
- setTextColor(viewHolder.time, bubbleColor);
+ setTextColor(viewHolder.time(), bubbleColor);
}
if (message.getEncryption() == Message.ENCRYPTION_NONE) {
- viewHolder.indicator.setVisibility(View.GONE);
+ viewHolder.indicator().setVisibility(View.GONE);
} else {
boolean verified = false;
if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) {
@@ -246,29 +253,27 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
}
if (verified) {
- viewHolder.indicator.setImageResource(R.drawable.ic_verified_user_24dp);
+ viewHolder.indicator().setImageResource(R.drawable.ic_verified_user_24dp);
} else {
- viewHolder.indicator.setImageResource(R.drawable.ic_lock_24dp);
+ viewHolder.indicator().setImageResource(R.drawable.ic_lock_24dp);
}
if (error && type == SENT) {
- setImageTintError(viewHolder.indicator);
+ setImageTintError(viewHolder.indicator());
} else {
- setImageTint(viewHolder.indicator, bubbleColor);
+ setImageTint(viewHolder.indicator(), bubbleColor);
}
- viewHolder.indicator.setVisibility(View.VISIBLE);
+ viewHolder.indicator().setVisibility(View.VISIBLE);
}
- if (viewHolder.edit_indicator != null) {
- if (message.edited()) {
- viewHolder.edit_indicator.setVisibility(View.VISIBLE);
- if (error && type == SENT) {
- setImageTintError(viewHolder.edit_indicator);
- } else {
- setImageTint(viewHolder.edit_indicator, bubbleColor);
- }
+ if (message.edited()) {
+ viewHolder.editIndicator().setVisibility(View.VISIBLE);
+ if (error && type == SENT) {
+ setImageTintError(viewHolder.editIndicator());
} else {
- viewHolder.edit_indicator.setVisibility(View.GONE);
+ setImageTint(viewHolder.editIndicator(), bubbleColor);
}
+ } else {
+ viewHolder.editIndicator().setVisibility(View.GONE);
}
final String formattedTime =
@@ -305,7 +310,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
}
final var timeInfo = timeInfoBuilder.build();
- viewHolder.time.setText(Joiner.on(" \u00B7 ").join(timeInfo));
+ viewHolder.time().setText(Joiner.on(" \u00B7 ").join(timeInfo));
}
public static @DrawableRes Integer getMessageStatusAsDrawable(
@@ -354,29 +359,34 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
private void displayInfoMessage(
- ViewHolder viewHolder, CharSequence text, final BubbleColor bubbleColor) {
- viewHolder.download_button.setVisibility(View.GONE);
- viewHolder.audioPlayer.setVisibility(View.GONE);
- viewHolder.image.setVisibility(View.GONE);
- viewHolder.messageBody.setVisibility(View.VISIBLE);
- viewHolder.messageBody.setText(text);
- viewHolder.messageBody.setTextColor(
- bubbleToOnSurfaceVariant(viewHolder.messageBody, bubbleColor));
- viewHolder.messageBody.setTextIsSelectable(false);
+ BubbleMessageItemViewHolder viewHolder,
+ CharSequence text,
+ final BubbleColor bubbleColor) {
+ viewHolder.downloadButton().setVisibility(View.GONE);
+ viewHolder.audioPlayer().setVisibility(View.GONE);
+ viewHolder.image().setVisibility(View.GONE);
+ viewHolder.messageBody().setVisibility(View.VISIBLE);
+ viewHolder.messageBody().setText(text);
+ viewHolder
+ .messageBody()
+ .setTextColor(bubbleToOnSurfaceVariant(viewHolder.messageBody(), bubbleColor));
+ viewHolder.messageBody().setTextIsSelectable(false);
}
private void displayEmojiMessage(
- final ViewHolder viewHolder, final String body, final BubbleColor bubbleColor) {
- viewHolder.download_button.setVisibility(View.GONE);
- viewHolder.audioPlayer.setVisibility(View.GONE);
- viewHolder.image.setVisibility(View.GONE);
- viewHolder.messageBody.setVisibility(View.VISIBLE);
- setTextColor(viewHolder.messageBody, bubbleColor);
+ final BubbleMessageItemViewHolder viewHolder,
+ final String body,
+ final BubbleColor bubbleColor) {
+ viewHolder.downloadButton().setVisibility(View.GONE);
+ viewHolder.audioPlayer().setVisibility(View.GONE);
+ viewHolder.image().setVisibility(View.GONE);
+ viewHolder.messageBody().setVisibility(View.VISIBLE);
+ setTextColor(viewHolder.messageBody(), bubbleColor);
final Spannable span = new SpannableString(body);
float size = Emoticons.isEmoji(body) ? 3.0f : 2.0f;
span.setSpan(
new RelativeSizeSpan(size), 0, body.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- viewHolder.messageBody.setText(span);
+ viewHolder.messageBody().setText(span);
}
private void applyQuoteSpan(
@@ -462,14 +472,16 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
private void displayTextMessage(
- final ViewHolder viewHolder, final Message message, final BubbleColor bubbleColor) {
- viewHolder.download_button.setVisibility(View.GONE);
- viewHolder.image.setVisibility(View.GONE);
- viewHolder.audioPlayer.setVisibility(View.GONE);
- viewHolder.messageBody.setVisibility(View.VISIBLE);
- setTextColor(viewHolder.messageBody, bubbleColor);
- setTextSize(viewHolder.messageBody, this.bubbleDesign.largeFont);
- viewHolder.messageBody.setTypeface(null, Typeface.NORMAL);
+ final BubbleMessageItemViewHolder viewHolder,
+ final Message message,
+ final BubbleColor bubbleColor) {
+ viewHolder.downloadButton().setVisibility(View.GONE);
+ viewHolder.image().setVisibility(View.GONE);
+ viewHolder.audioPlayer().setVisibility(View.GONE);
+ viewHolder.messageBody().setVisibility(View.VISIBLE);
+ setTextColor(viewHolder.messageBody(), bubbleColor);
+ setTextSize(viewHolder.messageBody(), this.bubbleDesign.largeFont);
+ viewHolder.messageBody().setTypeface(null, Typeface.NORMAL);
if (message.getBody() != null) {
final String nick = UIHelper.getMessageDisplayName(message);
@@ -485,7 +497,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
if (hasMeCommand) {
body.replace(0, Message.ME_COMMAND.length(), String.format("%s ", nick));
}
- boolean startsWithQuote = handleTextQuotes(viewHolder.messageBody, body, bubbleColor);
+ boolean startsWithQuote = handleTextQuotes(viewHolder.messageBody(), body, bubbleColor);
if (!message.isPrivateMessage()) {
if (hasMeCommand) {
body.setSpan(
@@ -519,7 +531,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
body.setSpan(
new ForegroundColorSpan(
- bubbleToOnSurfaceVariant(viewHolder.messageBody, bubbleColor)),
+ bubbleToOnSurfaceVariant(viewHolder.messageBody(), bubbleColor)),
0,
privateMarkerIndex,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -563,83 +575,94 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
}
- StylingHelper.format(body, viewHolder.messageBody.getCurrentTextColor());
+ StylingHelper.format(body, viewHolder.messageBody().getCurrentTextColor());
MyLinkify.addLinks(body, true);
if (highlightedTerm != null) {
- StylingHelper.highlight(viewHolder.messageBody, body, highlightedTerm);
+ StylingHelper.highlight(viewHolder.messageBody(), body, highlightedTerm);
}
- viewHolder.messageBody.setAutoLinkMask(0);
- viewHolder.messageBody.setText(body);
- viewHolder.messageBody.setMovementMethod(ClickableMovementMethod.getInstance());
+ viewHolder.messageBody().setAutoLinkMask(0);
+ viewHolder.messageBody().setText(body);
+ viewHolder.messageBody().setMovementMethod(ClickableMovementMethod.getInstance());
} else {
- viewHolder.messageBody.setText("");
- viewHolder.messageBody.setTextIsSelectable(false);
+ viewHolder.messageBody().setText("");
+ viewHolder.messageBody().setTextIsSelectable(false);
}
}
private void displayDownloadableMessage(
- ViewHolder viewHolder,
+ final BubbleMessageItemViewHolder viewHolder,
final Message message,
- String text,
+ final String text,
final BubbleColor bubbleColor) {
toggleWhisperInfo(viewHolder, message, bubbleColor);
- viewHolder.image.setVisibility(View.GONE);
- viewHolder.audioPlayer.setVisibility(View.GONE);
- viewHolder.download_button.setVisibility(View.VISIBLE);
- viewHolder.download_button.setText(text);
+ viewHolder.image().setVisibility(View.GONE);
+ viewHolder.audioPlayer().setVisibility(View.GONE);
+ viewHolder.downloadButton().setVisibility(View.VISIBLE);
+ viewHolder.downloadButton().setText(text);
final var attachment = Attachment.of(message);
final @DrawableRes int imageResource = MediaAdapter.getImageDrawable(attachment);
- viewHolder.download_button.setIconResource(imageResource);
- viewHolder.download_button.setOnClickListener(
- v -> ConversationFragment.downloadFile(activity, message));
+ viewHolder.downloadButton().setIconResource(imageResource);
+ viewHolder
+ .downloadButton()
+ .setOnClickListener(v -> ConversationFragment.downloadFile(activity, message));
}
private void displayOpenableMessage(
- ViewHolder viewHolder, final Message message, final BubbleColor bubbleColor) {
+ final BubbleMessageItemViewHolder viewHolder,
+ final Message message,
+ final BubbleColor bubbleColor) {
toggleWhisperInfo(viewHolder, message, bubbleColor);
- viewHolder.image.setVisibility(View.GONE);
- viewHolder.audioPlayer.setVisibility(View.GONE);
- viewHolder.download_button.setVisibility(View.VISIBLE);
- viewHolder.download_button.setText(
- activity.getString(
- R.string.open_x_file,
- UIHelper.getFileDescriptionString(activity, message)));
+ viewHolder.image().setVisibility(View.GONE);
+ viewHolder.audioPlayer().setVisibility(View.GONE);
+ viewHolder.downloadButton().setVisibility(View.VISIBLE);
+ viewHolder
+ .downloadButton()
+ .setText(
+ activity.getString(
+ R.string.open_x_file,
+ UIHelper.getFileDescriptionString(activity, message)));
final var attachment = Attachment.of(message);
final @DrawableRes int imageResource = MediaAdapter.getImageDrawable(attachment);
- viewHolder.download_button.setIconResource(imageResource);
- viewHolder.download_button.setOnClickListener(v -> openDownloadable(message));
+ viewHolder.downloadButton().setIconResource(imageResource);
+ viewHolder.downloadButton().setOnClickListener(v -> openDownloadable(message));
}
private void displayLocationMessage(
- ViewHolder viewHolder, final Message message, final BubbleColor bubbleColor) {
+ final BubbleMessageItemViewHolder viewHolder,
+ final Message message,
+ final BubbleColor bubbleColor) {
toggleWhisperInfo(viewHolder, message, bubbleColor);
- viewHolder.image.setVisibility(View.GONE);
- viewHolder.audioPlayer.setVisibility(View.GONE);
- viewHolder.download_button.setVisibility(View.VISIBLE);
- viewHolder.download_button.setText(R.string.show_location);
+ viewHolder.image().setVisibility(View.GONE);
+ viewHolder.audioPlayer().setVisibility(View.GONE);
+ viewHolder.downloadButton().setVisibility(View.VISIBLE);
+ viewHolder.downloadButton().setText(R.string.show_location);
final var attachment = Attachment.of(message);
final @DrawableRes int imageResource = MediaAdapter.getImageDrawable(attachment);
- viewHolder.download_button.setIconResource(imageResource);
- viewHolder.download_button.setOnClickListener(v -> showLocation(message));
+ viewHolder.downloadButton().setIconResource(imageResource);
+ viewHolder.downloadButton().setOnClickListener(v -> showLocation(message));
}
private void displayAudioMessage(
- ViewHolder viewHolder, Message message, final BubbleColor bubbleColor) {
+ final BubbleMessageItemViewHolder viewHolder,
+ Message message,
+ final BubbleColor bubbleColor) {
toggleWhisperInfo(viewHolder, message, bubbleColor);
- viewHolder.image.setVisibility(View.GONE);
- viewHolder.download_button.setVisibility(View.GONE);
- final RelativeLayout audioPlayer = viewHolder.audioPlayer;
+ viewHolder.image().setVisibility(View.GONE);
+ viewHolder.downloadButton().setVisibility(View.GONE);
+ final RelativeLayout audioPlayer = viewHolder.audioPlayer();
audioPlayer.setVisibility(View.VISIBLE);
AudioPlayer.ViewHolder.get(audioPlayer).setBubbleColor(bubbleColor);
this.audioPlayer.init(audioPlayer, message);
}
private void displayMediaPreviewMessage(
- ViewHolder viewHolder, final Message message, final BubbleColor bubbleColor) {
+ final BubbleMessageItemViewHolder viewHolder,
+ final Message message,
+ final BubbleColor bubbleColor) {
toggleWhisperInfo(viewHolder, message, bubbleColor);
- viewHolder.download_button.setVisibility(View.GONE);
- viewHolder.audioPlayer.setVisibility(View.GONE);
- viewHolder.image.setVisibility(View.VISIBLE);
+ viewHolder.downloadButton().setVisibility(View.GONE);
+ viewHolder.audioPlayer().setVisibility(View.GONE);
+ viewHolder.image().setVisibility(View.VISIBLE);
final FileParams params = message.getFileParams();
final float target = activity.getResources().getDimension(R.dimen.image_preview_width);
final int scaledW;
@@ -659,13 +682,15 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
final LinearLayout.LayoutParams layoutParams =
new LinearLayout.LayoutParams(scaledW, scaledH);
- viewHolder.image.setLayoutParams(layoutParams);
- activity.loadBitmap(message, viewHolder.image);
- viewHolder.image.setOnClickListener(v -> openDownloadable(message));
+ viewHolder.image().setLayoutParams(layoutParams);
+ activity.loadBitmap(message, viewHolder.image());
+ viewHolder.image().setOnClickListener(v -> openDownloadable(message));
}
private void toggleWhisperInfo(
- ViewHolder viewHolder, final Message message, final BubbleColor bubbleColor) {
+ final BubbleMessageItemViewHolder viewHolder,
+ final Message message,
+ final BubbleColor bubbleColor) {
if (message.isPrivateMessage()) {
final String privateMarker;
if (message.getStatus() <= Message.STATUS_RECEIVED) {
@@ -680,7 +705,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
final SpannableString body = new SpannableString(privateMarker);
body.setSpan(
new ForegroundColorSpan(
- bubbleToOnSurfaceVariant(viewHolder.messageBody, bubbleColor)),
+ bubbleToOnSurfaceVariant(viewHolder.messageBody(), bubbleColor)),
0,
privateMarker.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -689,14 +714,14 @@ public class MessageAdapter extends ArrayAdapter<Message> {
0,
privateMarker.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- viewHolder.messageBody.setText(body);
- viewHolder.messageBody.setVisibility(View.VISIBLE);
+ viewHolder.messageBody().setText(body);
+ viewHolder.messageBody().setVisibility(View.VISIBLE);
} else {
- viewHolder.messageBody.setVisibility(View.GONE);
+ viewHolder.messageBody().setVisibility(View.GONE);
}
}
- private void loadMoreMessages(Conversation conversation) {
+ private void loadMoreMessages(final Conversation conversation) {
conversation.setLastClearHistory(0, null);
activity.xmppConnectionService.updateConversation(conversation);
conversation.setHasMessagesLeftOnServer(true);
@@ -722,88 +747,96 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
}
+ private MessageItemViewHolder getViewHolder(
+ final View view, final @NonNull ViewGroup parent, final int type) {
+ if (view != null && view.getTag() instanceof MessageItemViewHolder messageItemViewHolder) {
+ return messageItemViewHolder;
+ } else {
+ final MessageItemViewHolder viewHolder =
+ switch (type) {
+ case RTP_SESSION ->
+ new RtpSessionMessageItemViewHolder(
+ DataBindingUtil.inflate(
+ LayoutInflater.from(parent.getContext()),
+ R.layout.item_message_rtp_session,
+ parent,
+ false));
+ case DATE_SEPARATOR ->
+ new DateSeperatorMessageItemViewHolder(
+ DataBindingUtil.inflate(
+ LayoutInflater.from(parent.getContext()),
+ R.layout.item_message_date_bubble,
+ parent,
+ false));
+ case STATUS ->
+ new StatusMessageItemViewHolder(
+ DataBindingUtil.inflate(
+ LayoutInflater.from(parent.getContext()),
+ R.layout.item_message_status,
+ parent,
+ false));
+ case SENT ->
+ new EndBubbleMessageItemViewHolder(
+ DataBindingUtil.inflate(
+ LayoutInflater.from(parent.getContext()),
+ R.layout.item_message_sent,
+ parent,
+ false));
+ case RECEIVED ->
+ new StartBubbleMessageItemViewHolder(
+ DataBindingUtil.inflate(
+ LayoutInflater.from(parent.getContext()),
+ R.layout.item_message_received,
+ parent,
+ false));
+ default -> throw new AssertionError("Unable to create ViewHolder for type");
+ };
+ viewHolder.itemView.setTag(viewHolder);
+ return viewHolder;
+ }
+ }
+
@NonNull
@Override
public View getView(final int position, View view, final @NonNull ViewGroup parent) {
final Message message = getItem(position);
+ final int type = getItemViewType(message);
+ final MessageItemViewHolder viewHolder = getViewHolder(view, parent, type);
+
+ if (type == DATE_SEPARATOR
+ && viewHolder instanceof DateSeperatorMessageItemViewHolder messageItemViewHolder) {
+ return render(message, messageItemViewHolder);
+ }
+
+ if (type == RTP_SESSION
+ && viewHolder instanceof RtpSessionMessageItemViewHolder messageItemViewHolder) {
+ return render(message, messageItemViewHolder);
+ }
+
+ if (type == STATUS
+ && viewHolder instanceof StatusMessageItemViewHolder messageItemViewHolder) {
+ return render(message, messageItemViewHolder);
+ }
+
+ if ((type == SENT || type == RECEIVED)
+ && viewHolder instanceof BubbleMessageItemViewHolder messageItemViewHolder) {
+ // TODO: type is represented by the class of viewHolder. we can get rid of that
+ return render(position, message, type, messageItemViewHolder);
+ }
+
+ throw new AssertionError();
+ }
+
+ private View render(
+ final int position,
+ final Message message,
+ final int type,
+ final BubbleMessageItemViewHolder viewHolder) {
final boolean omemoEncryption = message.getEncryption() == Message.ENCRYPTION_AXOLOTL;
final boolean isInValidSession =
message.isValidInSession() && (!omemoEncryption || message.isTrusted());
final Conversational conversation = message.getConversation();
final Account account = conversation.getAccount();
- final int type = getItemViewType(message);
- ViewHolder viewHolder;
- if (view == null) {
- viewHolder = new ViewHolder();
- switch (type) {
- case DATE_SEPARATOR:
- view =
- activity.getLayoutInflater()
- .inflate(R.layout.item_message_date_bubble, parent, false);
- viewHolder.status_message = view.findViewById(R.id.message_body);
- viewHolder.message_box = view.findViewById(R.id.message_box);
- break;
- case RTP_SESSION:
- view =
- activity.getLayoutInflater()
- .inflate(R.layout.item_message_rtp_session, parent, false);
- viewHolder.status_message = view.findViewById(R.id.message_body);
- viewHolder.message_box = view.findViewById(R.id.message_box);
- viewHolder.indicatorReceived = view.findViewById(R.id.indicator_received);
- break;
- case SENT:
- view =
- activity.getLayoutInflater()
- .inflate(R.layout.item_message_sent, parent, false);
- viewHolder.root = (ConstraintLayout) view;
- viewHolder.message_box = view.findViewById(R.id.message_box);
- viewHolder.contact_picture = view.findViewById(R.id.message_photo);
- viewHolder.download_button = view.findViewById(R.id.download_button);
- viewHolder.indicator = view.findViewById(R.id.security_indicator);
- viewHolder.edit_indicator = view.findViewById(R.id.edit_indicator);
- viewHolder.image = view.findViewById(R.id.message_image);
- viewHolder.messageBody = view.findViewById(R.id.message_body);
- viewHolder.time = view.findViewById(R.id.message_time);
- viewHolder.indicatorReceived = view.findViewById(R.id.indicator_received);
- viewHolder.audioPlayer = view.findViewById(R.id.audio_player);
- viewHolder.reactions = view.findViewById(R.id.reactions);
- break;
- case RECEIVED:
- view =
- activity.getLayoutInflater()
- .inflate(R.layout.item_message_received, parent, false);
- viewHolder.root = (ConstraintLayout) view;
- viewHolder.message_box = view.findViewById(R.id.message_box);
- viewHolder.contact_picture = view.findViewById(R.id.message_photo);
- viewHolder.download_button = view.findViewById(R.id.download_button);
- viewHolder.indicator = view.findViewById(R.id.security_indicator);
- viewHolder.edit_indicator = view.findViewById(R.id.edit_indicator);
- viewHolder.image = view.findViewById(R.id.message_image);
- viewHolder.messageBody = view.findViewById(R.id.message_body);
- viewHolder.time = view.findViewById(R.id.message_time);
- viewHolder.indicatorReceived = view.findViewById(R.id.indicator_received);
- viewHolder.encryption = view.findViewById(R.id.message_encryption);
- viewHolder.audioPlayer = view.findViewById(R.id.audio_player);
- viewHolder.reactions = view.findViewById(R.id.reactions);
- break;
- case STATUS:
- view =
- activity.getLayoutInflater()
- .inflate(R.layout.item_message_status, parent, false);
- viewHolder.contact_picture = view.findViewById(R.id.message_photo);
- viewHolder.status_message = view.findViewById(R.id.status_message);
- viewHolder.load_more_messages = view.findViewById(R.id.load_more_messages);
- break;
- default:
- throw new AssertionError("Unknown view type");
- }
- view.setTag(viewHolder);
- } else {
- viewHolder = (ViewHolder) view.getTag();
- if (viewHolder == null) {
- return view;
- }
- }
final boolean colorfulBackground = this.bubbleDesign.colorfulChatBubbles;
final BubbleColor bubbleColor;
@@ -817,149 +850,46 @@ public class MessageAdapter extends ArrayAdapter<Message> {
bubbleColor = colorfulBackground ? BubbleColor.TERTIARY : BubbleColor.SURFACE_HIGH;
}
- if (type == DATE_SEPARATOR) {
- if (UIHelper.today(message.getTimeSent())) {
- viewHolder.status_message.setText(R.string.today);
- } else if (UIHelper.yesterday(message.getTimeSent())) {
- viewHolder.status_message.setText(R.string.yesterday);
- } else {
- viewHolder.status_message.setText(
- DateUtils.formatDateTime(
- activity,
- message.getTimeSent(),
- DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR));
- }
- if (colorfulBackground) {
- setBackgroundTint(viewHolder.message_box, BubbleColor.PRIMARY);
- setTextColor(viewHolder.status_message, BubbleColor.PRIMARY);
- } else {
- setBackgroundTint(viewHolder.message_box, BubbleColor.SURFACE_HIGH);
- setTextColor(viewHolder.status_message, BubbleColor.SURFACE_HIGH);
- }
- return view;
- } else if (type == RTP_SESSION) {
- final boolean received = message.getStatus() <= Message.STATUS_RECEIVED;
- final RtpSessionStatus rtpSessionStatus = RtpSessionStatus.of(message.getBody());
- final long duration = rtpSessionStatus.duration;
- if (received) {
- if (duration > 0) {
- viewHolder.status_message.setText(
- activity.getString(
- R.string.incoming_call_duration_timestamp,
- TimeFrameUtils.resolve(activity, duration),
- UIHelper.readableTimeDifferenceFull(
- activity, message.getTimeSent())));
- } else if (rtpSessionStatus.successful) {
- viewHolder.status_message.setText(R.string.incoming_call);
- } else {
- viewHolder.status_message.setText(
- activity.getString(
- R.string.missed_call_timestamp,
- UIHelper.readableTimeDifferenceFull(
- activity, message.getTimeSent())));
- }
- } else {
- if (duration > 0) {
- viewHolder.status_message.setText(
- activity.getString(
- R.string.outgoing_call_duration_timestamp,
- TimeFrameUtils.resolve(activity, duration),
- UIHelper.readableTimeDifferenceFull(
- activity, message.getTimeSent())));
- } else {
- viewHolder.status_message.setText(
- activity.getString(
- R.string.outgoing_call_timestamp,
- UIHelper.readableTimeDifferenceFull(
- activity, message.getTimeSent())));
- }
- }
- if (colorfulBackground) {
- setBackgroundTint(viewHolder.message_box, BubbleColor.SECONDARY);
- setTextColor(viewHolder.status_message, BubbleColor.SECONDARY);
- setImageTint(viewHolder.indicatorReceived, BubbleColor.SECONDARY);
- } else {
- setBackgroundTint(viewHolder.message_box, BubbleColor.SURFACE_HIGH);
- setTextColor(viewHolder.status_message, BubbleColor.SURFACE_HIGH);
- setImageTint(viewHolder.indicatorReceived, BubbleColor.SURFACE_HIGH);
- }
- viewHolder.indicatorReceived.setImageResource(
- RtpSessionStatus.getDrawable(received, rtpSessionStatus.successful));
- return view;
- } else if (type == STATUS) {
- if ("LOAD_MORE".equals(message.getBody())) {
- viewHolder.status_message.setVisibility(View.GONE);
- viewHolder.contact_picture.setVisibility(View.GONE);
- viewHolder.load_more_messages.setVisibility(View.VISIBLE);
- viewHolder.load_more_messages.setOnClickListener(
- v -> loadMoreMessages((Conversation) message.getConversation()));
- } else {
- viewHolder.status_message.setVisibility(View.VISIBLE);
- viewHolder.load_more_messages.setVisibility(View.GONE);
- viewHolder.status_message.setText(message.getBody());
- boolean showAvatar;
- if (conversation.getMode() == Conversation.MODE_SINGLE) {
- showAvatar = true;
- AvatarWorkerTask.loadAvatar(
- message, viewHolder.contact_picture, R.dimen.avatar_on_status_message);
- } else if (message.getCounterpart() != null
- || message.getTrueCounterpart() != null
- || (message.getCounterparts() != null
- && !message.getCounterparts().isEmpty())) {
- showAvatar = true;
- AvatarWorkerTask.loadAvatar(
- message, viewHolder.contact_picture, R.dimen.avatar_on_status_message);
- } else {
- showAvatar = false;
- }
- if (showAvatar) {
- viewHolder.contact_picture.setAlpha(0.5f);
- viewHolder.contact_picture.setVisibility(View.VISIBLE);
- } else {
- viewHolder.contact_picture.setVisibility(View.GONE);
- }
- }
- return view;
+ final var mergeIntoTop = mergeIntoTop(position, message);
+ final var mergeIntoBottom = mergeIntoBottom(position, message);
+ final var showAvatar =
+ bubbleDesign.showAvatars
+ || (type == RECEIVED
+ && message.getConversation().getMode() == Conversation.MODE_MULTI);
+ setBubblePadding(viewHolder.root(), mergeIntoTop, mergeIntoBottom);
+ if (showAvatar) {
+ final var requiresAvatar = type == SENT ? !mergeIntoBottom : !mergeIntoTop;
+ setRequiresAvatar(viewHolder, requiresAvatar);
+ AvatarWorkerTask.loadAvatar(message, viewHolder.contactPicture(), R.dimen.avatar);
} else {
- // sent and received bubbles
- final var mergeIntoTop = mergeIntoTop(position, message);
- final var mergeIntoBottom = mergeIntoBottom(position, message);
- final var showAvatar =
- bubbleDesign.showAvatars
- || (type == RECEIVED
- && message.getConversation().getMode()
- == Conversation.MODE_MULTI);
- setBubblePadding(viewHolder.root, mergeIntoTop, mergeIntoBottom);
- if (showAvatar) {
- final var requiresAvatar = type == SENT ? !mergeIntoBottom : !mergeIntoTop;
- setRequiresAvatar(viewHolder, requiresAvatar);
- AvatarWorkerTask.loadAvatar(message, viewHolder.contact_picture, R.dimen.avatar);
- } else {
- viewHolder.contact_picture.setVisibility(View.GONE);
- }
- setAvatarDistance(viewHolder.message_box, type, showAvatar);
- viewHolder.message_box.setClipToOutline(true);
+ viewHolder.contactPicture().setVisibility(View.GONE);
}
-
- resetClickListener(viewHolder.message_box, viewHolder.messageBody);
-
- viewHolder.contact_picture.setOnClickListener(
- v -> {
- if (MessageAdapter.this.mOnContactPictureClickedListener != null) {
- MessageAdapter.this.mOnContactPictureClickedListener
- .onContactPictureClicked(message);
- }
- });
- viewHolder.contact_picture.setOnLongClickListener(
- v -> {
- if (MessageAdapter.this.mOnContactPictureLongClickedListener != null) {
- MessageAdapter.this.mOnContactPictureLongClickedListener
- .onContactPictureLongClicked(v, message);
- return true;
- } else {
- return false;
- }
- });
+ setAvatarDistance(viewHolder.messageBox(), type, showAvatar);
+ viewHolder.messageBox().setClipToOutline(true);
+
+ resetClickListener(viewHolder.messageBox(), viewHolder.messageBody());
+
+ viewHolder
+ .contactPicture()
+ .setOnClickListener(
+ v -> {
+ if (MessageAdapter.this.mOnContactPictureClickedListener != null) {
+ MessageAdapter.this.mOnContactPictureClickedListener
+ .onContactPictureClicked(message);
+ }
+ });
+ viewHolder
+ .contactPicture()
+ .setOnLongClickListener(
+ v -> {
+ if (MessageAdapter.this.mOnContactPictureLongClickedListener != null) {
+ MessageAdapter.this.mOnContactPictureLongClickedListener
+ .onContactPictureLongClicked(v, message);
+ return true;
+ } else {
+ return false;
+ }
+ });
final Transferable transferable = message.getTransferable();
final boolean unInitiatedButKnownSize = MessageUtils.unInitiatedButKnownSize(message);
@@ -1017,8 +947,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
} else {
displayInfoMessage(
viewHolder, activity.getString(R.string.install_openkeychain), bubbleColor);
- viewHolder.message_box.setOnClickListener(this::promptOpenKeychainInstall);
- viewHolder.messageBody.setOnClickListener(this::promptOpenKeychainInstall);
+ viewHolder.messageBox().setOnClickListener(this::promptOpenKeychainInstall);
+ viewHolder.messageBody().setOnClickListener(this::promptOpenKeychainInstall);
}
} else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
displayInfoMessage(
@@ -1061,38 +991,153 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
}
- setBackgroundTint(viewHolder.message_box, bubbleColor);
- setTextColor(viewHolder.messageBody, bubbleColor);
+ setBackgroundTint(viewHolder.messageBox(), bubbleColor);
+ setTextColor(viewHolder.messageBody(), bubbleColor);
- if (type == RECEIVED) {
- setTextColor(viewHolder.encryption, bubbleColor);
+ if (type == RECEIVED
+ && viewHolder instanceof StartBubbleMessageItemViewHolder startViewHolder) {
+ setTextColor(startViewHolder.encryption(), bubbleColor);
if (isInValidSession) {
- viewHolder.encryption.setVisibility(View.GONE);
+ startViewHolder.encryption().setVisibility(View.GONE);
} else {
- viewHolder.encryption.setVisibility(View.VISIBLE);
+ startViewHolder.encryption().setVisibility(View.VISIBLE);
if (omemoEncryption && !message.isTrusted()) {
- viewHolder.encryption.setText(R.string.not_trusted);
+ startViewHolder.encryption().setText(R.string.not_trusted);
} else {
- viewHolder.encryption.setText(
- CryptoHelper.encryptionTypeToText(message.getEncryption()));
+ startViewHolder
+ .encryption()
+ .setText(CryptoHelper.encryptionTypeToText(message.getEncryption()));
}
}
BindingAdapters.setReactionsOnReceived(
- viewHolder.reactions,
+ viewHolder.reactions(),
message.getAggregatedReactions(),
reactions -> sendReactions(message, reactions),
emoji -> showDetailedReaction(message, emoji),
() -> addReaction(message));
} else if (type == SENT) {
BindingAdapters.setReactionsOnSent(
- viewHolder.reactions,
+ viewHolder.reactions(),
message.getAggregatedReactions(),
reactions -> sendReactions(message, reactions),
emoji -> showDetailedReaction(message, emoji));
}
displayStatus(viewHolder, message, type, bubbleColor);
- return view;
+ return viewHolder.root();
+ }
+
+ private View render(
+ final Message message, final DateSeperatorMessageItemViewHolder viewHolder) {
+ final boolean colorfulBackground = this.bubbleDesign.colorfulChatBubbles;
+ if (UIHelper.today(message.getTimeSent())) {
+ viewHolder.binding.messageBody.setText(R.string.today);
+ } else if (UIHelper.yesterday(message.getTimeSent())) {
+ viewHolder.binding.messageBody.setText(R.string.yesterday);
+ } else {
+ viewHolder.binding.messageBody.setText(
+ DateUtils.formatDateTime(
+ activity,
+ message.getTimeSent(),
+ DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR));
+ }
+ if (colorfulBackground) {
+ setBackgroundTint(viewHolder.binding.messageBox, BubbleColor.PRIMARY);
+ setTextColor(viewHolder.binding.messageBody, BubbleColor.PRIMARY);
+ } else {
+ setBackgroundTint(viewHolder.binding.messageBox, BubbleColor.SURFACE_HIGH);
+ setTextColor(viewHolder.binding.messageBody, BubbleColor.SURFACE_HIGH);
+ }
+ return viewHolder.binding.getRoot();
+ }
+
+ private View render(final Message message, final RtpSessionMessageItemViewHolder viewHolder) {
+ final boolean colorfulBackground = this.bubbleDesign.colorfulChatBubbles;
+ final boolean received = message.getStatus() <= Message.STATUS_RECEIVED;
+ final RtpSessionStatus rtpSessionStatus = RtpSessionStatus.of(message.getBody());
+ final long duration = rtpSessionStatus.duration;
+ if (received) {
+ if (duration > 0) {
+ viewHolder.binding.messageBody.setText(
+ activity.getString(
+ R.string.incoming_call_duration_timestamp,
+ TimeFrameUtils.resolve(activity, duration),
+ UIHelper.readableTimeDifferenceFull(
+ activity, message.getTimeSent())));
+ } else if (rtpSessionStatus.successful) {
+ viewHolder.binding.messageBody.setText(R.string.incoming_call);
+ } else {
+ viewHolder.binding.messageBody.setText(
+ activity.getString(
+ R.string.missed_call_timestamp,
+ UIHelper.readableTimeDifferenceFull(
+ activity, message.getTimeSent())));
+ }
+ } else {
+ if (duration > 0) {
+ viewHolder.binding.messageBody.setText(
+ activity.getString(
+ R.string.outgoing_call_duration_timestamp,
+ TimeFrameUtils.resolve(activity, duration),
+ UIHelper.readableTimeDifferenceFull(
+ activity, message.getTimeSent())));
+ } else {
+ viewHolder.binding.messageBody.setText(
+ activity.getString(
+ R.string.outgoing_call_timestamp,
+ UIHelper.readableTimeDifferenceFull(
+ activity, message.getTimeSent())));
+ }
+ }
+ if (colorfulBackground) {
+ setBackgroundTint(viewHolder.binding.messageBox, BubbleColor.SECONDARY);
+ setTextColor(viewHolder.binding.messageBody, BubbleColor.SECONDARY);
+ setImageTint(viewHolder.binding.indicatorReceived, BubbleColor.SECONDARY);
+ } else {
+ setBackgroundTint(viewHolder.binding.messageBox, BubbleColor.SURFACE_HIGH);
+ setTextColor(viewHolder.binding.messageBody, BubbleColor.SURFACE_HIGH);
+ setImageTint(viewHolder.binding.indicatorReceived, BubbleColor.SURFACE_HIGH);
+ }
+ viewHolder.binding.indicatorReceived.setImageResource(
+ RtpSessionStatus.getDrawable(received, rtpSessionStatus.successful));
+ return viewHolder.binding.getRoot();
+ }
+
+ private View render(final Message message, final StatusMessageItemViewHolder viewHolder) {
+ final var conversation = message.getConversation();
+ if ("LOAD_MORE".equals(message.getBody())) {
+ viewHolder.binding.statusMessage.setVisibility(View.GONE);
+ viewHolder.binding.messagePhoto.setVisibility(View.GONE);
+ viewHolder.binding.loadMoreMessages.setVisibility(View.VISIBLE);
+ viewHolder.binding.loadMoreMessages.setOnClickListener(
+ v -> loadMoreMessages((Conversation) message.getConversation()));
+ } else {
+ viewHolder.binding.statusMessage.setVisibility(View.VISIBLE);
+ viewHolder.binding.loadMoreMessages.setVisibility(View.GONE);
+ viewHolder.binding.statusMessage.setText(message.getBody());
+ boolean showAvatar;
+ if (conversation.getMode() == Conversation.MODE_SINGLE) {
+ showAvatar = true;
+ AvatarWorkerTask.loadAvatar(
+ message, viewHolder.binding.messagePhoto, R.dimen.avatar_on_status_message);
+ } else if (message.getCounterpart() != null
+ || message.getTrueCounterpart() != null
+ || (message.getCounterparts() != null
+ && !message.getCounterparts().isEmpty())) {
+ showAvatar = true;
+ AvatarWorkerTask.loadAvatar(
+ message, viewHolder.binding.messagePhoto, R.dimen.avatar_on_status_message);
+ } else {
+ showAvatar = false;
+ }
+ if (showAvatar) {
+ viewHolder.binding.messagePhoto.setAlpha(0.5f);
+ viewHolder.binding.messagePhoto.setVisibility(View.VISIBLE);
+ } else {
+ viewHolder.binding.messagePhoto.setVisibility(View.GONE);
+ }
+ }
+ return viewHolder.binding.getRoot();
}
private void setAvatarDistance(
@@ -1138,20 +1183,21 @@ public class MessageAdapter extends ArrayAdapter<Message> {
root.setPadding(horizontal, top, horizontal, bottom);
}
- private void setRequiresAvatar(final ViewHolder viewHolder, final boolean requiresAvatar) {
- final var layoutParams = viewHolder.contact_picture.getLayoutParams();
+ private void setRequiresAvatar(
+ final BubbleMessageItemViewHolder viewHolder, final boolean requiresAvatar) {
+ final var layoutParams = viewHolder.contactPicture().getLayoutParams();
if (requiresAvatar) {
- final var resources = viewHolder.contact_picture.getResources();
+ final var resources = viewHolder.contactPicture().getResources();
final var avatarSize = resources.getDimensionPixelSize(R.dimen.bubble_avatar_size);
layoutParams.height = avatarSize;
- viewHolder.contact_picture.setVisibility(View.VISIBLE);
- viewHolder.message_box.setMinimumHeight(avatarSize);
+ viewHolder.contactPicture().setVisibility(View.VISIBLE);
+ viewHolder.messageBox().setMinimumHeight(avatarSize);
} else {
layoutParams.height = 0;
- viewHolder.contact_picture.setVisibility(View.INVISIBLE);
- viewHolder.message_box.setMinimumHeight(0);
+ viewHolder.contactPicture().setVisibility(View.INVISIBLE);
+ viewHolder.messageBox().setMinimumHeight(0);
}
- viewHolder.contact_picture.setLayoutParams(layoutParams);
+ viewHolder.contactPicture().setLayoutParams(layoutParams);
}
private boolean mergeIntoTop(final int position, final Message message) {
@@ -1307,7 +1353,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
void onContactPictureLongClicked(View v, Message message);
}
- private static void setBackgroundTint(final View view, final BubbleColor bubbleColor) {
+ private static void setBackgroundTint(final LinearLayout view, final BubbleColor bubbleColor) {
view.setBackgroundTintList(bubbleToColorStateList(view, bubbleColor));
}
@@ -1425,22 +1471,209 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
}
- private static class ViewHolder {
-
- private ConstraintLayout root;
- public MaterialButton load_more_messages;
- public ImageView edit_indicator;
- public RelativeLayout audioPlayer;
- protected LinearLayout message_box;
- protected MaterialButton download_button;
- protected ImageView image;
- protected ImageView indicator;
- protected ImageView indicatorReceived;
- protected TextView time;
- protected TextView messageBody;
- protected ImageView contact_picture;
- protected TextView status_message;
- protected TextView encryption;
- protected ChipGroup reactions;
+ private abstract static class MessageItemViewHolder /*extends RecyclerView.ViewHolder*/ {
+
+ private View itemView;
+
+ private MessageItemViewHolder(@NonNull View itemView) {
+ this.itemView = itemView;
+ }
+ }
+
+ private abstract static class BubbleMessageItemViewHolder extends MessageItemViewHolder {
+
+ private BubbleMessageItemViewHolder(@NonNull View itemView) {
+ super(itemView);
+ }
+
+ public abstract ConstraintLayout root();
+
+ protected abstract ImageView editIndicator();
+
+ protected abstract RelativeLayout audioPlayer();
+
+ protected abstract LinearLayout messageBox();
+
+ protected abstract MaterialButton downloadButton();
+
+ protected abstract ImageView image();
+
+ // TODO rename into indicatorSecurity()
+ protected abstract ImageView indicator();
+
+ protected abstract TextView time();
+
+ protected abstract TextView messageBody();
+
+ protected abstract ImageView contactPicture();
+
+ protected abstract ChipGroup reactions();
+ }
+
+ private static class StartBubbleMessageItemViewHolder extends BubbleMessageItemViewHolder {
+
+ private final ItemMessageReceivedBinding binding;
+
+ public StartBubbleMessageItemViewHolder(@NonNull ItemMessageReceivedBinding binding) {
+ super(binding.getRoot());
+ this.binding = binding;
+ }
+
+ @Override
+ public ConstraintLayout root() {
+ return (ConstraintLayout) this.binding.getRoot();
+ }
+
+ @Override
+ protected ImageView editIndicator() {
+ return this.binding.editIndicator;
+ }
+
+ @Override
+ protected RelativeLayout audioPlayer() {
+ return this.binding.messageContent.audioPlayer;
+ }
+
+ @Override
+ protected LinearLayout messageBox() {
+ return this.binding.messageBox;
+ }
+
+ @Override
+ protected MaterialButton downloadButton() {
+ return this.binding.messageContent.downloadButton;
+ }
+
+ @Override
+ protected ImageView image() {
+ return this.binding.messageContent.messageImage;
+ }
+
+ protected ImageView indicator() {
+ return this.binding.securityIndicator;
+ }
+
+ @Override
+ protected TextView time() {
+ return this.binding.messageTime;
+ }
+
+ @Override
+ protected TextView messageBody() {
+ return this.binding.messageContent.messageBody;
+ }
+
+ protected TextView encryption() {
+ return this.binding.messageEncryption;
+ }
+
+ @Override
+ protected ImageView contactPicture() {
+ return this.binding.messagePhoto;
+ }
+
+ @Override
+ protected ChipGroup reactions() {
+ return this.binding.reactions;
+ }
+ }
+
+ private static class EndBubbleMessageItemViewHolder extends BubbleMessageItemViewHolder {
+
+ private final ItemMessageSentBinding binding;
+
+ private EndBubbleMessageItemViewHolder(@NonNull ItemMessageSentBinding binding) {
+ super(binding.getRoot());
+ this.binding = binding;
+ }
+
+ @Override
+ public ConstraintLayout root() {
+ return (ConstraintLayout) this.binding.getRoot();
+ }
+
+ @Override
+ protected ImageView editIndicator() {
+ return this.binding.editIndicator;
+ }
+
+ @Override
+ protected RelativeLayout audioPlayer() {
+ return this.binding.messageContent.audioPlayer;
+ }
+
+ @Override
+ protected LinearLayout messageBox() {
+ return this.binding.messageBox;
+ }
+
+ @Override
+ protected MaterialButton downloadButton() {
+ return this.binding.messageContent.downloadButton;
+ }
+
+ @Override
+ protected ImageView image() {
+ return this.binding.messageContent.messageImage;
+ }
+
+ @Override
+ protected ImageView indicator() {
+ return this.binding.securityIndicator;
+ }
+
+ protected ImageView indicatorReceived() {
+ return this.binding.indicatorReceived;
+ }
+
+ @Override
+ protected TextView time() {
+ return this.binding.messageTime;
+ }
+
+ @Override
+ protected TextView messageBody() {
+ return this.binding.messageContent.messageBody;
+ }
+
+ @Override
+ protected ImageView contactPicture() {
+ return this.binding.messagePhoto;
+ }
+
+ @Override
+ protected ChipGroup reactions() {
+ return this.binding.reactions;
+ }
+ }
+
+ private static class DateSeperatorMessageItemViewHolder extends MessageItemViewHolder {
+
+ private final ItemMessageDateBubbleBinding binding;
+
+ private DateSeperatorMessageItemViewHolder(@NonNull ItemMessageDateBubbleBinding binding) {
+ super(binding.getRoot());
+ this.binding = binding;
+ }
+ }
+
+ private static class RtpSessionMessageItemViewHolder extends MessageItemViewHolder {
+
+ private final ItemMessageRtpSessionBinding binding;
+
+ private RtpSessionMessageItemViewHolder(@NonNull ItemMessageRtpSessionBinding binding) {
+ super(binding.getRoot());
+ this.binding = binding;
+ }
+ }
+
+ private static class StatusMessageItemViewHolder extends MessageItemViewHolder {
+
+ private final ItemMessageStatusBinding binding;
+
+ private StatusMessageItemViewHolder(@NonNull ItemMessageStatusBinding binding) {
+ super(binding.getRoot());
+ this.binding = binding;
+ }
}
}