improve displaying of calls messages

This commit is contained in:
adbenitez 2025-09-19 18:44:06 +02:00
parent c9816ae785
commit df6c858b92
7 changed files with 192 additions and 4 deletions

View file

@ -48,6 +48,7 @@ import org.thoughtcrime.securesms.audio.AudioSlidePlayer;
import org.thoughtcrime.securesms.components.AudioView; import org.thoughtcrime.securesms.components.AudioView;
import org.thoughtcrime.securesms.components.AvatarImageView; import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.BorderlessImageView; import org.thoughtcrime.securesms.components.BorderlessImageView;
import org.thoughtcrime.securesms.components.CallItemView;
import org.thoughtcrime.securesms.components.ConversationItemFooter; import org.thoughtcrime.securesms.components.ConversationItemFooter;
import org.thoughtcrime.securesms.components.ConversationItemThumbnail; import org.thoughtcrime.securesms.components.ConversationItemThumbnail;
import org.thoughtcrime.securesms.components.DocumentView; import org.thoughtcrime.securesms.components.DocumentView;
@ -117,6 +118,7 @@ public class ConversationItem extends BaseConversationItem
private @NonNull Stub<WebxdcView> webxdcViewStub; private @NonNull Stub<WebxdcView> webxdcViewStub;
private Stub<BorderlessImageView> stickerStub; private Stub<BorderlessImageView> stickerStub;
private Stub<VcardView> vcardViewStub; private Stub<VcardView> vcardViewStub;
private Stub<CallItemView> callViewStub;
private @Nullable EventListener eventListener; private @Nullable EventListener eventListener;
private int measureCalls; private int measureCalls;
@ -151,6 +153,7 @@ public class ConversationItem extends BaseConversationItem
this.webxdcViewStub = new Stub<>(findViewById(R.id.webxdc_view_stub)); this.webxdcViewStub = new Stub<>(findViewById(R.id.webxdc_view_stub));
this.stickerStub = new Stub<>(findViewById(R.id.sticker_view_stub)); this.stickerStub = new Stub<>(findViewById(R.id.sticker_view_stub));
this.vcardViewStub = new Stub<>(findViewById(R.id.vcard_view_stub)); this.vcardViewStub = new Stub<>(findViewById(R.id.vcard_view_stub));
this.callViewStub = new Stub<>(findViewById(R.id.call_view_stub));
this.groupSenderHolder = findViewById(R.id.group_sender_holder); this.groupSenderHolder = findViewById(R.id.group_sender_holder);
this.quoteView = findViewById(R.id.quote_view); this.quoteView = findViewById(R.id.quote_view);
this.container = findViewById(R.id.container); this.container = findViewById(R.id.container);
@ -321,6 +324,11 @@ public class ConversationItem extends BaseConversationItem
vcardViewStub.get().setFocusable(!shouldInterceptClicks(messageRecord) && batchSelected.isEmpty()); vcardViewStub.get().setFocusable(!shouldInterceptClicks(messageRecord) && batchSelected.isEmpty());
vcardViewStub.get().setClickable(batchSelected.isEmpty()); vcardViewStub.get().setClickable(batchSelected.isEmpty());
} }
if (callViewStub.resolved()) {
callViewStub.get().setFocusable(!shouldInterceptClicks(messageRecord) && batchSelected.isEmpty());
callViewStub.get().setClickable(batchSelected.isEmpty());
}
} }
private void setContentDescription() { private void setContentDescription() {
@ -337,6 +345,8 @@ public class ConversationItem extends BaseConversationItem
desc += webxdcViewStub.get().getDescription() + "\n"; desc += webxdcViewStub.get().getDescription() + "\n";
} else if (vcardViewStub.resolved() && vcardViewStub.get().getVisibility() == View.VISIBLE) { } else if (vcardViewStub.resolved() && vcardViewStub.get().getVisibility() == View.VISIBLE) {
desc += vcardViewStub.get().getDescription() + "\n"; desc += vcardViewStub.get().getDescription() + "\n";
} else if (callViewStub.resolved() && callViewStub.get().getVisibility() == View.VISIBLE) {
desc += callViewStub.get().getDescription() + "\n";
} else if (mediaThumbnailStub.resolved() && mediaThumbnailStub.get().getVisibility() == View.VISIBLE) { } else if (mediaThumbnailStub.resolved() && mediaThumbnailStub.get().getVisibility() == View.VISIBLE) {
desc += mediaThumbnailStub.get().getDescription() + "\n"; desc += mediaThumbnailStub.get().getDescription() + "\n";
} else if (stickerStub.resolved() && stickerStub.get().getVisibility() == View.VISIBLE) { } else if (stickerStub.resolved() && stickerStub.get().getVisibility() == View.VISIBLE) {
@ -398,7 +408,7 @@ public class ConversationItem extends BaseConversationItem
String text = messageRecord.getText(); String text = messageRecord.getText();
if (text.isEmpty()) { if (messageRecord.getType()==DcMsg.DC_MSG_CALL || text.isEmpty()) {
bodyText.setVisibility(View.GONE); bodyText.setVisibility(View.GONE);
} }
else { else {
@ -489,6 +499,7 @@ public class ConversationItem extends BaseConversationItem
if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE); if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE);
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE); if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE); if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE);
if (callViewStub.resolved()) callViewStub.get().setVisibility(View.GONE);
//noinspection ConstantConditions //noinspection ConstantConditions
int duration = messageRecord.getDuration(); int duration = messageRecord.getDuration();
@ -514,6 +525,7 @@ public class ConversationItem extends BaseConversationItem
if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE); if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE);
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE); if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE); if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE);
if (callViewStub.resolved()) callViewStub.get().setVisibility(View.GONE);
//noinspection ConstantConditions //noinspection ConstantConditions
documentViewStub.get().setDocument(new DocumentSlide(context, messageRecord)); documentViewStub.get().setDocument(new DocumentSlide(context, messageRecord));
@ -532,6 +544,7 @@ public class ConversationItem extends BaseConversationItem
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE); if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE); if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE); if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE);
if (callViewStub.resolved()) callViewStub.get().setVisibility(View.GONE);
webxdcViewStub.get().setWebxdc(messageRecord, context.getString(R.string.webxdc_app)); webxdcViewStub.get().setWebxdc(messageRecord, context.getString(R.string.webxdc_app));
webxdcViewStub.get().setWebxdcClickListener(new ThumbnailClickListener()); webxdcViewStub.get().setWebxdcClickListener(new ThumbnailClickListener());
@ -549,6 +562,7 @@ public class ConversationItem extends BaseConversationItem
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE); if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE); if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE);
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE); if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
if (callViewStub.resolved()) callViewStub.get().setVisibility(View.GONE);
vcardViewStub.get().setVcard(glideRequests, new VcardSlide(context, messageRecord), rpc); vcardViewStub.get().setVcard(glideRequests, new VcardSlide(context, messageRecord), rpc);
vcardViewStub.get().setVcardClickListener(new ThumbnailClickListener()); vcardViewStub.get().setVcardClickListener(new ThumbnailClickListener());
@ -560,6 +574,23 @@ public class ConversationItem extends BaseConversationItem
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
footer.setVisibility(VISIBLE); footer.setVisibility(VISIBLE);
} }
else if (messageRecord.getType()==DcMsg.DC_MSG_CALL) {
callViewStub.get().setVisibility(View.VISIBLE);
if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE);
if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE);
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE);
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE);
callViewStub.get().setCallItem(messageRecord);
callViewStub.get().setOnClickListener(passthroughClickListener);
callViewStub.get().setOnLongClickListener(passthroughClickListener);
callViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
else if (hasThumbnail(messageRecord)) { else if (hasThumbnail(messageRecord)) {
mediaThumbnailStub.get().setVisibility(View.VISIBLE); mediaThumbnailStub.get().setVisibility(View.VISIBLE);
if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE);
@ -567,6 +598,7 @@ public class ConversationItem extends BaseConversationItem
if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE); if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE);
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE); if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE); if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE);
if (callViewStub.resolved()) callViewStub.get().setVisibility(View.GONE);
Slide slide = MediaUtil.getSlideForMsg(context, messageRecord); Slide slide = MediaUtil.getSlideForMsg(context, messageRecord);
@ -606,6 +638,7 @@ public class ConversationItem extends BaseConversationItem
if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE); if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE);
if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE); if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE);
if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE); if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE);
if (callViewStub.resolved()) callViewStub.get().setVisibility(View.GONE);
bodyBubble.setBackgroundColor(Color.TRANSPARENT); bodyBubble.setBackgroundColor(Color.TRANSPARENT);
@ -626,6 +659,7 @@ public class ConversationItem extends BaseConversationItem
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE); if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE); if (webxdcViewStub.resolved()) webxdcViewStub.get().setVisibility(View.GONE);
if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE); if (vcardViewStub.resolved()) vcardViewStub.get().setVisibility(View.GONE);
if (callViewStub.resolved()) callViewStub.get().setVisibility(View.GONE);
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
@ -779,6 +813,8 @@ public class ConversationItem extends BaseConversationItem
return stickerStub.get().getFooter(); return stickerStub.get().getFooter();
} else if (hasOnlyThumbnail(messageRecord) && TextUtils.isEmpty(messageRecord.getText())) { } else if (hasOnlyThumbnail(messageRecord) && TextUtils.isEmpty(messageRecord.getText())) {
return mediaThumbnailStub.get().getFooter(); return mediaThumbnailStub.get().getFooter();
} else if (messageRecord.getType()==DcMsg.DC_MSG_CALL) {
return callViewStub.get().getFooter();
} else { } else {
return footer; return footer;
} }
@ -880,6 +916,7 @@ public class ConversationItem extends BaseConversationItem
else if (documentViewStub.resolved()) documentViewStub.get().performClick(); else if (documentViewStub.resolved()) documentViewStub.get().performClick();
else if (webxdcViewStub.resolved()) webxdcViewStub.get().performClick(); else if (webxdcViewStub.resolved()) webxdcViewStub.get().performClick();
else if (vcardViewStub.resolved()) vcardViewStub.get().performClick(); else if (vcardViewStub.resolved()) vcardViewStub.get().performClick();
else if (callViewStub.resolved()) callViewStub.get().performClick();
} }
/// Event handlers /// Event handlers

View file

@ -0,0 +1,72 @@
package org.thoughtcrime.securesms.components;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.b44t.messenger.DcMsg;
import org.thoughtcrime.securesms.R;
public class CallItemView extends FrameLayout {
private static final String TAG = CallItemView.class.getSimpleName();
private final @NonNull ImageView icon;
private final @NonNull TextView title;
private final @NonNull ConversationItemFooter footer;
public CallItemView(Context context) {
this(context, null);
}
public CallItemView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CallItemView(final Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
inflate(context, R.layout.call_item_view, this);
this.icon = findViewById(R.id.call_icon);
this.title = findViewById(R.id.title);
this.footer = findViewById(R.id.footer);
}
public void setCallItem(final @NonNull DcMsg dcMsg) {
title.setText(dcMsg.getText());
if (dcMsg.isOutgoing()) {
int[] attrs = new int[]{
R.attr.conversation_item_outgoing_text_secondary_color,
};
try (TypedArray ta = getContext().obtainStyledAttributes(attrs)) {
footer.setTextColor(ta.getColor(0, Color.BLACK));
icon.setColorFilter(ta.getColor(0, Color.BLACK));
}
} else {
int[] attrs = new int[]{
R.attr.conversation_item_incoming_text_secondary_color,
};
try (TypedArray ta = getContext().obtainStyledAttributes(attrs)) {
footer.setTextColor(ta.getColor(0, Color.BLACK));
}
icon.setColorFilter(getResources().getColor(R.color.delta_accent_darker));
}
}
public ConversationItemFooter getFooter() {
return footer;
}
public String getDescription() {
return title.getText() + "\n" + footer.getDescription();
}
}

View file

@ -54,8 +54,7 @@ public class ConversationItemFooter extends LinearLayout {
if (attrs != null) { if (attrs != null) {
try (TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.ConversationItemFooter, 0, 0)) { try (TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.ConversationItemFooter, 0, 0)) {
textColor = typedArray.getInt(R.styleable.ConversationItemFooter_footer_text_color, getResources().getColor(R.color.core_white)); setTextColor(typedArray.getInt(R.styleable.ConversationItemFooter_footer_text_color, getResources().getColor(R.color.core_white)));
setTextColor(textColor);
} }
} }
} }
@ -77,7 +76,8 @@ public class ConversationItemFooter extends LinearLayout {
presentDeliveryStatus(messageRecord); presentDeliveryStatus(messageRecord);
} }
private void setTextColor(int color) { public void setTextColor(int color) {
textColor = color;
dateView.setTextColor(color); dateView.setTextColor(color);
editedView.setTextColor(color); editedView.setTextColor(color);
bookmarkIndicatorView.setColorFilter(color); bookmarkIndicatorView.setColorFilter(color);

View file

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minWidth="210dp"
android:orientation="horizontal"
android:gravity="center_vertical"
android:focusable="true">
<LinearLayout android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="16dp"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:singleLine="true"
android:fontFamily="sans-serif"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="?conversation_item_outgoing_text_primary_color"
tools:text="Incoming call" />
<org.thoughtcrime.securesms.components.ConversationItemFooter
android:id="@+id/footer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:gravity="start"
android:clipChildren="false"
android:clipToPadding="false"
/>
</LinearLayout>
<ImageView
android:id="@+id/call_icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:contentDescription="@null"
android:src="@drawable/baseline_call_24"
/>
</LinearLayout>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<org.thoughtcrime.securesms.components.CallItemView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/call_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
tools:visibility="visible"/>

View file

@ -172,6 +172,16 @@
android:layout_marginLeft="@dimen/message_bubble_horizontal_padding" android:layout_marginLeft="@dimen/message_bubble_horizontal_padding"
android:layout_marginRight="@dimen/message_bubble_horizontal_padding" /> android:layout_marginRight="@dimen/message_bubble_horizontal_padding" />
<ViewStub
android:id="@+id/call_view_stub"
android:layout="@layout/conversation_item_call"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/message_bubble_top_padding"
android:layout_marginBottom="@dimen/message_bubble_collapsed_footer_padding"
android:layout_marginLeft="@dimen/message_bubble_horizontal_padding"
android:layout_marginRight="@dimen/message_bubble_horizontal_padding" />
<org.thoughtcrime.securesms.components.emoji.AutoScaledEmojiTextView <org.thoughtcrime.securesms.components.emoji.AutoScaledEmojiTextView
android:id="@+id/conversation_item_body" android:id="@+id/conversation_item_body"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -154,6 +154,16 @@
android:layout_marginLeft="@dimen/message_bubble_horizontal_padding" android:layout_marginLeft="@dimen/message_bubble_horizontal_padding"
android:layout_marginRight="@dimen/message_bubble_horizontal_padding" /> android:layout_marginRight="@dimen/message_bubble_horizontal_padding" />
<ViewStub
android:id="@+id/call_view_stub"
android:layout="@layout/conversation_item_call"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/message_bubble_top_padding"
android:layout_marginBottom="@dimen/message_bubble_collapsed_footer_padding"
android:layout_marginLeft="@dimen/message_bubble_horizontal_padding"
android:layout_marginRight="@dimen/message_bubble_horizontal_padding" />
<org.thoughtcrime.securesms.components.emoji.AutoScaledEmojiTextView <org.thoughtcrime.securesms.components.emoji.AutoScaledEmojiTextView
android:id="@+id/conversation_item_body" android:id="@+id/conversation_item_body"
android:layout_width="wrap_content" android:layout_width="wrap_content"