Fix a few minor group call UI issues.
This commit is contained in:
parent
2dcc7d284f
commit
bdc6c8c65a
10 changed files with 73 additions and 46 deletions
|
@ -59,8 +59,8 @@ public class BroadcastVideoSink implements VideoSink {
|
|||
}
|
||||
|
||||
public @NonNull RequestedSize getMaxRequestingSize() {
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int width = 1;
|
||||
int height = 1;
|
||||
|
||||
synchronized (requestingSizes) {
|
||||
for (Point size : requestingSizes.values()) {
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
|||
import org.webrtc.RendererCommon;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Encapsulates views needed to show a call participant including their
|
||||
|
@ -42,12 +43,14 @@ public class CallParticipantView extends ConstraintLayout {
|
|||
|
||||
private static final FallbackPhotoProvider FALLBACK_PHOTO_PROVIDER = new FallbackPhotoProvider();
|
||||
|
||||
private static final long DELAY_SHOWING_MISSING_MEDIA_KEYS = TimeUnit.SECONDS.toMillis(5);
|
||||
private static final int SMALL_AVATAR = ViewUtil.dpToPx(96);
|
||||
private static final int LARGE_AVATAR = ViewUtil.dpToPx(112);
|
||||
|
||||
private RecipientId recipientId;
|
||||
private boolean infoMode;
|
||||
|
||||
private AppCompatImageView backgroundAvatar;
|
||||
private AvatarImageView avatar;
|
||||
private TextureViewRenderer renderer;
|
||||
private ImageView pipAvatar;
|
||||
|
@ -74,6 +77,7 @@ public class CallParticipantView extends ConstraintLayout {
|
|||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
backgroundAvatar = findViewById(R.id.call_participant_background_avatar);
|
||||
avatar = findViewById(R.id.call_participant_item_avatar);
|
||||
pipAvatar = findViewById(R.id.call_participant_item_pip_avatar);
|
||||
renderer = findViewById(R.id.call_participant_renderer);
|
||||
|
@ -98,7 +102,7 @@ public class CallParticipantView extends ConstraintLayout {
|
|||
void setCallParticipant(@NonNull CallParticipant participant) {
|
||||
boolean participantChanged = recipientId == null || !recipientId.equals(participant.getRecipient().getId());
|
||||
recipientId = participant.getRecipient().getId();
|
||||
infoMode = participant.getRecipient().isBlocked() || !participant.isMediaKeysReceived();
|
||||
infoMode = participant.getRecipient().isBlocked() || (!participant.isMediaKeysReceived() && (System.currentTimeMillis() - participant.getAddedToCallTime()) > DELAY_SHOWING_MISSING_MEDIA_KEYS);
|
||||
|
||||
if (infoMode) {
|
||||
renderer.setVisibility(View.GONE);
|
||||
|
@ -139,7 +143,7 @@ public class CallParticipantView extends ConstraintLayout {
|
|||
|
||||
if (participantChanged || !Objects.equals(contactPhoto, participant.getRecipient().getContactPhoto())) {
|
||||
avatar.setAvatarUsingProfile(participant.getRecipient());
|
||||
AvatarUtil.loadBlurredIconIntoViewBackground(participant.getRecipient(), this, true);
|
||||
AvatarUtil.loadBlurredIconIntoImageView(participant.getRecipient(), backgroundAvatar);
|
||||
setPipAvatar(participant.getRecipient());
|
||||
contactPhoto = participant.getRecipient().getContactPhoto();
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ class WebRtcCallParticipantsRecyclerAdapter extends ListAdapter<CallParticipant,
|
|||
@Override
|
||||
void bind(@NonNull CallParticipant callParticipant) {
|
||||
callParticipantView.setCallParticipant(callParticipant);
|
||||
callParticipantView.setRenderInPip(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import java.util.Objects;
|
|||
|
||||
public final class CallParticipant {
|
||||
|
||||
public static final CallParticipant EMPTY = createRemote(new CallParticipantId(Recipient.UNKNOWN), Recipient.UNKNOWN, null, new BroadcastVideoSink(null), false, false, 0, true);
|
||||
public static final CallParticipant EMPTY = createRemote(new CallParticipantId(Recipient.UNKNOWN), Recipient.UNKNOWN, null, new BroadcastVideoSink(null), false, false, 0, true, 0);
|
||||
|
||||
private final @NonNull CallParticipantId callParticipantId;
|
||||
private final @NonNull CameraState cameraState;
|
||||
|
@ -23,6 +23,7 @@ public final class CallParticipant {
|
|||
private final boolean microphoneEnabled;
|
||||
private final long lastSpoke;
|
||||
private final boolean mediaKeysReceived;
|
||||
private final long addedToCallTime;
|
||||
|
||||
public static @NonNull CallParticipant createLocal(@NonNull CameraState cameraState,
|
||||
@NonNull BroadcastVideoSink renderer,
|
||||
|
@ -36,7 +37,8 @@ public final class CallParticipant {
|
|||
cameraState.isEnabled() && cameraState.getCameraCount() > 0,
|
||||
microphoneEnabled,
|
||||
0,
|
||||
true);
|
||||
true,
|
||||
0);
|
||||
}
|
||||
|
||||
public static @NonNull CallParticipant createRemote(@NonNull CallParticipantId callParticipantId,
|
||||
|
@ -46,9 +48,10 @@ public final class CallParticipant {
|
|||
boolean audioEnabled,
|
||||
boolean videoEnabled,
|
||||
long lastSpoke,
|
||||
boolean mediaKeysReceived)
|
||||
boolean mediaKeysReceived,
|
||||
long addedToCallTime)
|
||||
{
|
||||
return new CallParticipant(callParticipantId, recipient, identityKey, renderer, CameraState.UNKNOWN, videoEnabled, audioEnabled, lastSpoke, mediaKeysReceived);
|
||||
return new CallParticipant(callParticipantId, recipient, identityKey, renderer, CameraState.UNKNOWN, videoEnabled, audioEnabled, lastSpoke, mediaKeysReceived, addedToCallTime);
|
||||
}
|
||||
|
||||
private CallParticipant(@NonNull CallParticipantId callParticipantId,
|
||||
|
@ -59,7 +62,8 @@ public final class CallParticipant {
|
|||
boolean videoEnabled,
|
||||
boolean microphoneEnabled,
|
||||
long lastSpoke,
|
||||
boolean mediaKeysReceived)
|
||||
boolean mediaKeysReceived,
|
||||
long addedToCallTime)
|
||||
{
|
||||
this.callParticipantId = callParticipantId;
|
||||
this.recipient = recipient;
|
||||
|
@ -70,14 +74,15 @@ public final class CallParticipant {
|
|||
this.microphoneEnabled = microphoneEnabled;
|
||||
this.lastSpoke = lastSpoke;
|
||||
this.mediaKeysReceived = mediaKeysReceived;
|
||||
this.addedToCallTime = addedToCallTime;
|
||||
}
|
||||
|
||||
public @NonNull CallParticipant withIdentityKey(@NonNull IdentityKey identityKey) {
|
||||
return new CallParticipant(callParticipantId, recipient, identityKey, videoSink, cameraState, videoEnabled, microphoneEnabled, lastSpoke, mediaKeysReceived);
|
||||
return new CallParticipant(callParticipantId, recipient, identityKey, videoSink, cameraState, videoEnabled, microphoneEnabled, lastSpoke, mediaKeysReceived, addedToCallTime);
|
||||
}
|
||||
|
||||
public @NonNull CallParticipant withVideoEnabled(boolean videoEnabled) {
|
||||
return new CallParticipant(callParticipantId, recipient, identityKey, videoSink, cameraState, videoEnabled, microphoneEnabled, lastSpoke, mediaKeysReceived);
|
||||
return new CallParticipant(callParticipantId, recipient, identityKey, videoSink, cameraState, videoEnabled, microphoneEnabled, lastSpoke, mediaKeysReceived, addedToCallTime);
|
||||
}
|
||||
|
||||
public @NonNull CallParticipantId getCallParticipantId() {
|
||||
|
@ -127,6 +132,10 @@ public final class CallParticipant {
|
|||
return mediaKeysReceived;
|
||||
}
|
||||
|
||||
public long getAddedToCallTime() {
|
||||
return addedToCallTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
@ -137,6 +146,7 @@ public final class CallParticipant {
|
|||
microphoneEnabled == that.microphoneEnabled &&
|
||||
lastSpoke == that.lastSpoke &&
|
||||
mediaKeysReceived == that.mediaKeysReceived &&
|
||||
addedToCallTime == that.addedToCallTime &&
|
||||
cameraState.equals(that.cameraState) &&
|
||||
recipient.equals(that.recipient) &&
|
||||
Objects.equals(identityKey, that.identityKey) &&
|
||||
|
@ -145,7 +155,7 @@ public final class CallParticipant {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(callParticipantId, cameraState, recipient, identityKey, videoSink, videoEnabled, microphoneEnabled, lastSpoke, mediaKeysReceived);
|
||||
return Objects.hash(callParticipantId, cameraState, recipient, identityKey, videoSink, videoEnabled, microphoneEnabled, lastSpoke, mediaKeysReceived, addedToCallTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -159,6 +169,7 @@ public final class CallParticipant {
|
|||
", microphoneEnabled=" + microphoneEnabled +
|
||||
", lastSpoke=" + lastSpoke +
|
||||
", mediaKeysReceived=" + mediaKeysReceived +
|
||||
", addedToCallTime=" + addedToCallTime +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,8 @@ public class BeginCallActionProcessorDelegate extends WebRtcActionProcessor {
|
|||
true,
|
||||
false,
|
||||
0,
|
||||
true
|
||||
true,
|
||||
0
|
||||
))
|
||||
.build();
|
||||
|
||||
|
@ -91,7 +92,8 @@ public class BeginCallActionProcessorDelegate extends WebRtcActionProcessor {
|
|||
true,
|
||||
false,
|
||||
0,
|
||||
true
|
||||
true,
|
||||
0
|
||||
))
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -92,7 +92,8 @@ public class GroupActionProcessor extends DeviceAwareActionProcessor {
|
|||
Boolean.FALSE.equals(device.getAudioMuted()),
|
||||
Boolean.FALSE.equals(device.getVideoMuted()),
|
||||
device.getSpeakerTime(),
|
||||
device.getMediaKeysReceived()));
|
||||
device.getMediaKeysReceived(),
|
||||
device.getAddedTime()));
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
|
|
|
@ -115,7 +115,7 @@ public class GroupPreJoinActionProcessor extends GroupActionProcessor {
|
|||
.changeCallInfoState();
|
||||
|
||||
for (Recipient recipient : callParticipants) {
|
||||
builder.putParticipant(recipient, CallParticipant.createRemote(new CallParticipantId(recipient), recipient, null, new BroadcastVideoSink(null), true, true, 0, false));
|
||||
builder.putParticipant(recipient, CallParticipant.createRemote(new CallParticipantId(recipient), recipient, null, new BroadcastVideoSink(null), true, true, 0, false, 0));
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.util;
|
|||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.text.TextUtils;
|
||||
|
@ -12,15 +13,14 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.request.target.CustomViewTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
||||
|
@ -36,23 +36,18 @@ import java.util.concurrent.ExecutionException;
|
|||
|
||||
public final class AvatarUtil {
|
||||
|
||||
private static final String TAG = Log.tag(AvatarUtil.class);
|
||||
|
||||
private AvatarUtil() {
|
||||
}
|
||||
|
||||
public static void loadBlurredIconIntoViewBackground(@NonNull Recipient recipient, @NonNull View target) {
|
||||
loadBlurredIconIntoViewBackground(recipient, target, false);
|
||||
}
|
||||
|
||||
public static void loadBlurredIconIntoViewBackground(@NonNull Recipient recipient, @NonNull View target, boolean useSelfProfileAvatar) {
|
||||
public static void loadBlurredIconIntoImageView(@NonNull Recipient recipient, @NonNull AppCompatImageView target) {
|
||||
Context context = target.getContext();
|
||||
|
||||
ContactPhoto photo;
|
||||
|
||||
if (recipient.isSelf() && useSelfProfileAvatar) {
|
||||
if (recipient.isSelf()) {
|
||||
photo = new ProfileContactPhoto(Recipient.self(), Recipient.self().getProfileAvatar());
|
||||
} else if (recipient.getContactPhoto() == null) {
|
||||
target.setImageDrawable(null);
|
||||
target.setBackgroundColor(ContextCompat.getColor(target.getContext(), R.color.black));
|
||||
return;
|
||||
} else {
|
||||
|
@ -61,21 +56,22 @@ public final class AvatarUtil {
|
|||
|
||||
GlideApp.with(target)
|
||||
.load(photo)
|
||||
.transform(new CenterCrop(), new BlurTransformation(context, 0.25f, BlurTransformation.MAX_RADIUS))
|
||||
.transform(new BlurTransformation(context, 0.25f, BlurTransformation.MAX_RADIUS))
|
||||
.into(new CustomViewTarget<View, Drawable>(target) {
|
||||
@Override
|
||||
public void onLoadFailed(@Nullable Drawable errorDrawable) {
|
||||
target.setImageDrawable(null);
|
||||
target.setBackgroundColor(ContextCompat.getColor(target.getContext(), R.color.black));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
|
||||
target.setBackground(resource);
|
||||
target.setImageDrawable(resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResourceCleared(@Nullable Drawable placeholder) {
|
||||
target.setBackground(placeholder);
|
||||
target.setImageDrawable(placeholder);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -7,6 +7,17 @@
|
|||
tools:layout_height="match_parent"
|
||||
tools:layout_width="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/call_participant_background_avatar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@tools:sample/backgrounds/scenic" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.AvatarImageView
|
||||
android:id="@+id/call_participant_item_avatar"
|
||||
android:layout_width="112dp"
|
||||
|
@ -51,17 +62,16 @@
|
|||
|
||||
<LinearLayout
|
||||
android:id="@+id/call_participant_info_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@color/transparent_black_40"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:visibility="visible">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
|
@ -75,7 +85,9 @@
|
|||
android:id="@+id/call_participant_info_message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:lines="3"
|
||||
|
|
|
@ -172,7 +172,7 @@ public class CallParticipantListUpdateTest {
|
|||
private static CallParticipant createParticipant(long recipientId, long deMuxId) {
|
||||
Recipient recipient = new Recipient(RecipientId.from(recipientId), mock(RecipientDetails.class), true);
|
||||
|
||||
return CallParticipant.createRemote(new CallParticipantId(deMuxId, recipient.getId()), recipient, null, new BroadcastVideoSink(null), false, false, -1, false);
|
||||
return CallParticipant.createRemote(new CallParticipantId(deMuxId, recipient.getId()), recipient, null, new BroadcastVideoSink(null), false, false, -1, false, 0);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue