diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java index 1b0c7ca17b..3fca08669a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -2134,7 +2134,7 @@ public class ConversationActivity extends PassphraseRequiredActivity joinGroupCallButton.setVisibility(hasActiveCall ? View.VISIBLE : View.GONE); }); - groupCallViewModel.canJoinGroupCall().observe(this, canJoin -> joinGroupCallButton.setText(canJoin ? R.string.ConversationActivity_join : R.string.ConversationActivity_full)); + groupCallViewModel.groupCallHasCapacity().observe(this, hasCapacity -> joinGroupCallButton.setText(hasCapacity ? R.string.ConversationActivity_join : R.string.ConversationActivity_full)); } private void showStickerIntroductionTooltip() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java index 0ba2fb84c3..a67548fe1b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java @@ -50,15 +50,18 @@ public final class ConversationUpdateItem extends LinearLayout private TextView body; private TextView actionButton; - private LiveRecipient sender; private ConversationMessage conversationMessage; + private Recipient conversationRecipient; private Optional nextMessageRecord; private MessageRecord messageRecord; private LiveData displayBody; private EventListener eventListener; private final UpdateObserver updateObserver = new UpdateObserver(); - private final SenderObserver senderObserver = new SenderObserver(); + + private final PresentOnChange presentOnChange = new PresentOnChange(); + private final RecipientObserverManager senderObserver = new RecipientObserverManager(presentOnChange); + private final RecipientObserverManager groupObserver = new RecipientObserverManager(presentOnChange); public ConversationUpdateItem(Context context) { super(context); @@ -91,7 +94,7 @@ public final class ConversationUpdateItem extends LinearLayout { this.batchSelected = batchSelected; - bind(lifecycleOwner, conversationMessage, nextMessageRecord); + bind(lifecycleOwner, conversationMessage, nextMessageRecord, conversationRecipient); } @Override @@ -106,20 +109,26 @@ public final class ConversationUpdateItem extends LinearLayout private void bind(@NonNull LifecycleOwner lifecycleOwner, @NonNull ConversationMessage conversationMessage, - @NonNull Optional nextMessageRecord) + @NonNull Optional nextMessageRecord, + @NonNull Recipient conversationRecipient) { - this.conversationMessage = conversationMessage; - this.messageRecord = conversationMessage.getMessageRecord(); - this.nextMessageRecord = nextMessageRecord; + this.conversationMessage = conversationMessage; + this.messageRecord = conversationMessage.getMessageRecord(); + this.nextMessageRecord = nextMessageRecord; + this.conversationRecipient = conversationRecipient; - observeSender(lifecycleOwner, messageRecord.getIndividualRecipient()); + senderObserver.observe(lifecycleOwner, messageRecord.getIndividualRecipient()); + + if (conversationRecipient.isActiveGroup() && conversationMessage.getMessageRecord().isGroupCall()) { + groupObserver.observe(lifecycleOwner, conversationRecipient); + } else { + groupObserver.observe(lifecycleOwner, null); + } UpdateDescription updateDescription = Objects.requireNonNull(messageRecord.getUpdateDisplayBody(getContext())); LiveData liveUpdateMessage = LiveUpdateMessage.fromMessageDescription(getContext(), updateDescription, ContextCompat.getColor(getContext(), R.color.conversation_item_update_text_color)); LiveData spannableMessage = loading(liveUpdateMessage); - present(conversationMessage, nextMessageRecord); - observeDisplayBody(lifecycleOwner, spannableMessage); } @@ -132,16 +141,31 @@ public final class ConversationUpdateItem extends LinearLayout public void unbind() { } - private void observeSender(@NonNull LifecycleOwner lifecycleOwner, @Nullable Recipient recipient) { - if (sender != null) { - sender.getLiveData().removeObserver(senderObserver); + static final class RecipientObserverManager { + + private final Observer recipientObserver; + + private LiveRecipient recipient; + + RecipientObserverManager(@NonNull Observer observer){ + this.recipientObserver = observer; } - if (recipient != null) { - sender = recipient.live(); - sender.getLiveData().observe(lifecycleOwner, senderObserver); - } else { - sender = null; + public void observe(@NonNull LifecycleOwner lifecycleOwner, @Nullable Recipient recipient) { + if (this.recipient != null) { + this.recipient.getLiveData().removeObserver(recipientObserver); + } + + if (recipient != null) { + this.recipient = recipient.live(); + this.recipient.getLiveData().observe(lifecycleOwner, recipientObserver); + } else { + this.recipient = null; + } + } + + @NonNull Recipient getObservedRecipient() { + return recipient.get(); } } @@ -168,7 +192,7 @@ public final class ConversationUpdateItem extends LinearLayout } } - private void present(ConversationMessage conversationMessage, @NonNull Optional nextMessageRecord) { + private void present(ConversationMessage conversationMessage, @NonNull Optional nextMessageRecord, @NonNull Recipient conversationRecipient) { if (batchSelected.contains(conversationMessage)) setSelected(true); else setSelected(false); @@ -195,7 +219,7 @@ public final class ConversationUpdateItem extends LinearLayout } } - if (text != 0) { + if (text != 0 && conversationRecipient.isGroup() && conversationRecipient.isActiveGroup()) { actionButton.setText(text); actionButton.setVisibility(VISIBLE); actionButton.setOnClickListener(v -> { @@ -218,11 +242,14 @@ public final class ConversationUpdateItem extends LinearLayout super.setOnClickListener(new InternalClickListener(l)); } - private final class SenderObserver implements Observer { + private final class PresentOnChange implements Observer { @Override public void onChanged(Recipient recipient) { - present(conversationMessage, nextMessageRecord); + if (recipient.getId() == conversationRecipient.getId()) { + conversationRecipient = recipient; + } + present(conversationMessage, nextMessageRecord, conversationRecipient); } } @@ -253,7 +280,7 @@ public final class ConversationUpdateItem extends LinearLayout return; } - final Recipient sender = ConversationUpdateItem.this.sender.get(); + final Recipient sender = ConversationUpdateItem.this.senderObserver.getObservedRecipient(); IdentityUtil.getRemoteIdentityKey(getContext(), sender).addListener(new ListenableFuture.Listener>() { @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ui/groupcall/GroupCallViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ui/groupcall/GroupCallViewModel.java index bd961624a9..e795a25330 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ui/groupcall/GroupCallViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ui/groupcall/GroupCallViewModel.java @@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.ringrtc.RemotePeer; import org.thoughtcrime.securesms.service.WebRtcCallService; import org.thoughtcrime.securesms.util.FeatureFlags; +import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import java.util.Objects; @@ -23,31 +24,37 @@ public class GroupCallViewModel extends ViewModel { private static final String TAG = Log.tag(GroupCallViewModel.class); - private final MutableLiveData activeGroupCall; - private final MutableLiveData canJoin; + private final MutableLiveData activeGroup; + private final MutableLiveData ongoingGroupCall; + private final LiveData activeGroupCall; + private final MutableLiveData groupCallHasCapacity; private @Nullable Recipient currentRecipient; GroupCallViewModel() { - this.activeGroupCall = new MutableLiveData<>(false); - this.canJoin = new MutableLiveData<>(false); + this.activeGroup = new MutableLiveData<>(false); + this.ongoingGroupCall = new MutableLiveData<>(false); + this.groupCallHasCapacity = new MutableLiveData<>(false); + this.activeGroupCall = LiveDataUtil.combineLatest(activeGroup, ongoingGroupCall, (active, ongoing) -> active && ongoing); } public @NonNull LiveData hasActiveGroupCall() { return activeGroupCall; } - public @NonNull LiveData canJoinGroupCall() { - return canJoin; + public @NonNull LiveData groupCallHasCapacity() { + return groupCallHasCapacity; } public void onRecipientChange(@NonNull Context context, @Nullable Recipient recipient) { + activeGroup.postValue(recipient != null && recipient.isActiveGroup()); + if (Objects.equals(currentRecipient, recipient)) { return; } - activeGroupCall.postValue(false); - canJoin.postValue(false); + ongoingGroupCall.postValue(false); + groupCallHasCapacity.postValue(false); currentRecipient = recipient; @@ -67,10 +74,10 @@ public class GroupCallViewModel extends ViewModel { public void onGroupCallPeekEvent(@NonNull GroupCallPeekEvent groupCallPeekEvent) { if (isGroupCallCapable(currentRecipient) && groupCallPeekEvent.getGroupRecipientId().equals(currentRecipient.getId())) { - Log.i(TAG, "update UI with call event: active call: " + groupCallPeekEvent.hasActiveCall() + " canJoin: " + groupCallPeekEvent.canJoinCall()); + Log.i(TAG, "update UI with call event: ongoing call: " + groupCallPeekEvent.isOngoing() + " hasCapacity: " + groupCallPeekEvent.callHasCapacity()); - activeGroupCall.postValue(groupCallPeekEvent.hasActiveCall()); - canJoin.postValue(groupCallPeekEvent.canJoinCall()); + ongoingGroupCall.postValue(groupCallPeekEvent.isOngoing()); + groupCallHasCapacity.postValue(groupCallPeekEvent.callHasCapacity()); } else { Log.i(TAG, "Ignore call event for different recipient."); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/events/GroupCallPeekEvent.java b/app/src/main/java/org/thoughtcrime/securesms/events/GroupCallPeekEvent.java index 79e0f02f68..93728f87b2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/events/GroupCallPeekEvent.java +++ b/app/src/main/java/org/thoughtcrime/securesms/events/GroupCallPeekEvent.java @@ -22,11 +22,11 @@ public final class GroupCallPeekEvent { return groupRecipientId; } - public boolean hasActiveCall() { + public boolean isOngoing() { return eraId != null && deviceCount > 0; } - public boolean canJoinCall() { - return hasActiveCall() && deviceCount < deviceLimit; + public boolean callHasCapacity() { + return isOngoing() && deviceCount < deviceLimit; } }