mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-25 11:20:47 +01:00
Add Group Call peeking in the Conversation view.
This commit is contained in:
committed by
Greyson Parrelli
parent
2729eb9f5f
commit
01f143667f
@@ -25,6 +25,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ShortcutManager;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
@@ -82,6 +83,7 @@ import com.annimon.stream.Stream;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.request.target.CustomTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
@@ -135,6 +137,7 @@ import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationGroupViewModel.GroupActiveState;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationMessage.ConversationMessageFactory;
|
||||
import org.thoughtcrime.securesms.conversation.ui.error.SafetyNumberChangeDialog;
|
||||
import org.thoughtcrime.securesms.conversation.ui.groupcall.GroupCallViewModel;
|
||||
import org.thoughtcrime.securesms.conversation.ui.mentions.MentionsPickerViewModel;
|
||||
import org.thoughtcrime.securesms.conversationlist.model.MessageResult;
|
||||
import org.thoughtcrime.securesms.crypto.SecurityEvent;
|
||||
@@ -159,6 +162,7 @@ import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.ReactionRecord;
|
||||
import org.thoughtcrime.securesms.database.model.StickerRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.events.GroupCallPeekEvent;
|
||||
import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
|
||||
import org.thoughtcrime.securesms.giph.ui.GiphyActivity;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeException;
|
||||
@@ -369,6 +373,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
||||
private View requestingMemberBanner;
|
||||
private View cancelJoinRequest;
|
||||
private Stub<View> mentionsSuggestions;
|
||||
private MaterialButton joinGroupCallButton;
|
||||
|
||||
private LinkPreviewViewModel linkPreviewViewModel;
|
||||
private ConversationSearchViewModel searchViewModel;
|
||||
@@ -377,6 +382,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
||||
private InviteReminderModel inviteReminderModel;
|
||||
private ConversationGroupViewModel groupViewModel;
|
||||
private MentionsPickerViewModel mentionsViewModel;
|
||||
private GroupCallViewModel groupCallViewModel;
|
||||
|
||||
private LiveRecipient recipient;
|
||||
private long threadId;
|
||||
@@ -426,6 +432,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
||||
initializeViewModel(args);
|
||||
initializeGroupViewModel();
|
||||
initializeMentionsViewModel();
|
||||
initializeGroupCallViewModel();
|
||||
initializeEnabledCheck();
|
||||
initializePendingRequestsBanner();
|
||||
initializeGroupV1MigrationsBanners();
|
||||
@@ -532,6 +539,10 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
||||
.enqueue();
|
||||
}
|
||||
|
||||
if (groupCallViewModel != null) {
|
||||
groupCallViewModel.peekGroupCall(this);
|
||||
}
|
||||
|
||||
setVisibleThread(threadId);
|
||||
ConversationUtil.refreshRecipientShortcuts();
|
||||
}
|
||||
@@ -816,6 +827,9 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
||||
} else if (isGroupConversation()) {
|
||||
if (isActiveV2Group && FeatureFlags.groupCalling()) {
|
||||
inflater.inflate(R.menu.conversation_callable_groupv2, menu);
|
||||
if (groupCallViewModel != null && Boolean.TRUE.equals(groupCallViewModel.hasActiveGroupCall().getValue())) {
|
||||
hideMenuItem(menu, R.id.menu_video_secure);
|
||||
}
|
||||
}
|
||||
|
||||
inflater.inflate(R.menu.conversation_group_options, menu);
|
||||
@@ -1895,6 +1909,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
||||
noLongerMemberBanner = findViewById(R.id.conversation_no_longer_member_banner);
|
||||
requestingMemberBanner = findViewById(R.id.conversation_requesting_banner);
|
||||
cancelJoinRequest = findViewById(R.id.conversation_cancel_request);
|
||||
joinGroupCallButton = findViewById(R.id.conversation_group_cal_join);
|
||||
|
||||
container.addOnKeyboardShownListener(this);
|
||||
inputPanel.setListener(this);
|
||||
@@ -1949,6 +1964,8 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
||||
inlineAttachmentButton.setOnClickListener(v -> handleAddAttachment());
|
||||
|
||||
reactionOverlay.setOnReactionSelectedListener(this);
|
||||
|
||||
joinGroupCallButton.setOnClickListener(v -> handleVideo(getRecipient()));
|
||||
}
|
||||
|
||||
protected void initializeActionBar() {
|
||||
@@ -2105,6 +2122,21 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
||||
});
|
||||
}
|
||||
|
||||
public void initializeGroupCallViewModel() {
|
||||
groupCallViewModel = ViewModelProviders.of(this, new GroupCallViewModel.Factory()).get(GroupCallViewModel.class);
|
||||
|
||||
recipient.observe(this, r -> {
|
||||
groupCallViewModel.onRecipientChange(this, r);
|
||||
});
|
||||
|
||||
groupCallViewModel.hasActiveGroupCall().observe(this, hasActiveCall -> {
|
||||
invalidateOptionsMenu();
|
||||
joinGroupCallButton.setVisibility(hasActiveCall ? View.VISIBLE : View.GONE);
|
||||
});
|
||||
|
||||
groupCallViewModel.canJoinGroupCall().observe(this, canJoin -> joinGroupCallButton.setText(canJoin ? R.string.ConversationActivity_join : R.string.ConversationActivity_full));
|
||||
}
|
||||
|
||||
private void showStickerIntroductionTooltip() {
|
||||
TextSecurePreferences.setMediaKeyboardMode(this, MediaKeyboardMode.STICKER);
|
||||
inputPanel.setMediaKeyboardToggleMode(true);
|
||||
@@ -2218,6 +2250,10 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
||||
if (mentionsViewModel != null) {
|
||||
mentionsViewModel.onRecipientChange(recipient);
|
||||
}
|
||||
|
||||
if (groupCallViewModel != null) {
|
||||
groupCallViewModel.onRecipientChange(this, recipient);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
@@ -2239,6 +2275,13 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||
public void onGroupCallPeekEvent(@NonNull GroupCallPeekEvent event) {
|
||||
if (groupCallViewModel != null) {
|
||||
groupCallViewModel.onGroupCallPeekEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeReceivers() {
|
||||
securityUpdateReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
@@ -2396,8 +2439,13 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
||||
private void setActionBarColor(MaterialColor color) {
|
||||
ActionBar supportActionBar = getSupportActionBar();
|
||||
if (supportActionBar == null) throw new AssertionError();
|
||||
supportActionBar.setBackgroundDrawable(new ColorDrawable(color.toActionBarColor(this)));
|
||||
int actionBarColor = color.toActionBarColor(this);
|
||||
supportActionBar.setBackgroundDrawable(new ColorDrawable(actionBarColor));
|
||||
WindowUtil.setStatusBarColor(getWindow(), color.toStatusBarColor(this));
|
||||
|
||||
joinGroupCallButton.setTextColor(actionBarColor);
|
||||
joinGroupCallButton.setIconTint(ColorStateList.valueOf(actionBarColor));
|
||||
joinGroupCallButton.setRippleColor(ColorStateList.valueOf(actionBarColor));
|
||||
}
|
||||
|
||||
private void setBlockedUserState(Recipient recipient, boolean isSecureText, boolean isDefaultSms) {
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.BindableConversationItem;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.VerifyIdentityActivity;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
|
||||
import org.thoughtcrime.securesms.database.model.GroupCallUpdateDetailsUtil;
|
||||
import org.thoughtcrime.securesms.database.model.LiveUpdateMessage;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.UpdateDescription;
|
||||
@@ -182,13 +183,16 @@ public final class ConversationUpdateItem extends LinearLayout
|
||||
}
|
||||
});
|
||||
} else if (conversationMessage.getMessageRecord().isGroupCall()) {
|
||||
|
||||
UpdateDescription updateDescription = MessageRecord.getGroupCallUpdateDescription(getContext(), conversationMessage.getMessageRecord().getBody(), true);
|
||||
Collection<UUID> uuids = updateDescription.getMentioned();
|
||||
|
||||
int text = 0;
|
||||
if (Util.hasItems(uuids)) {
|
||||
text = uuids.contains(TextSecurePreferences.getLocalUuid(getContext())) ? R.string.ConversationUpdateItem_return_to_call : R.string.ConversationUpdateItem_join_call;
|
||||
if (GroupCallUpdateDetailsUtil.parse(conversationMessage.getMessageRecord().getBody()).getIsCallFull()) {
|
||||
text = R.string.ConversationUpdateItem_call_is_full;
|
||||
} else {
|
||||
text = uuids.contains(TextSecurePreferences.getLocalUuid(getContext())) ? R.string.ConversationUpdateItem_return_to_call : R.string.ConversationUpdateItem_join_call;
|
||||
}
|
||||
}
|
||||
|
||||
if (text != 0) {
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package org.thoughtcrime.securesms.conversation.ui.groupcall;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import org.thoughtcrime.securesms.events.GroupCallPeekEvent;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
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 java.util.Objects;
|
||||
|
||||
public class GroupCallViewModel extends ViewModel {
|
||||
|
||||
private static final String TAG = Log.tag(GroupCallViewModel.class);
|
||||
|
||||
private final MutableLiveData<Boolean> activeGroupCall;
|
||||
private final MutableLiveData<Boolean> canJoin;
|
||||
|
||||
private @Nullable Recipient currentRecipient;
|
||||
|
||||
GroupCallViewModel() {
|
||||
this.activeGroupCall = new MutableLiveData<>(false);
|
||||
this.canJoin = new MutableLiveData<>(false);
|
||||
}
|
||||
|
||||
public @NonNull LiveData<Boolean> hasActiveGroupCall() {
|
||||
return activeGroupCall;
|
||||
}
|
||||
|
||||
public @NonNull LiveData<Boolean> canJoinGroupCall() {
|
||||
return canJoin;
|
||||
}
|
||||
|
||||
public void onRecipientChange(@NonNull Context context, @Nullable Recipient recipient) {
|
||||
if (Objects.equals(currentRecipient, recipient)) {
|
||||
return;
|
||||
}
|
||||
|
||||
activeGroupCall.postValue(false);
|
||||
canJoin.postValue(false);
|
||||
|
||||
currentRecipient = recipient;
|
||||
|
||||
peekGroupCall(context);
|
||||
}
|
||||
|
||||
public void peekGroupCall(@NonNull Context context) {
|
||||
if (isGroupCallCapable(currentRecipient)) {
|
||||
Log.i(TAG, "peek call for " + currentRecipient.getId());
|
||||
Intent intent = new Intent(context, WebRtcCallService.class);
|
||||
intent.setAction(WebRtcCallService.ACTION_GROUP_CALL_PEEK)
|
||||
.putExtra(WebRtcCallService.EXTRA_REMOTE_PEER, new RemotePeer(currentRecipient.getId()));
|
||||
|
||||
context.startService(intent);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
activeGroupCall.postValue(groupCallPeekEvent.hasActiveCall());
|
||||
canJoin.postValue(groupCallPeekEvent.canJoinCall());
|
||||
} else {
|
||||
Log.i(TAG, "Ignore call event for different recipient.");
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isGroupCallCapable(@Nullable Recipient recipient) {
|
||||
return recipient != null && recipient.isActiveGroup() && recipient.isPushV2Group() && FeatureFlags.groupCalling();
|
||||
}
|
||||
|
||||
public static final class Factory implements ViewModelProvider.Factory {
|
||||
@Override
|
||||
public @NonNull <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
|
||||
//noinspection ConstantConditions
|
||||
return modelClass.cast(new GroupCallViewModel());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user