From ca210f2b6dcc6a7650aaaa2cd02805471ebbc622 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Wed, 9 Aug 2023 11:47:50 -0300 Subject: [PATCH] Add denial dialogs for call links. --- .../securesms/WebRtcCallActivity.java | 30 +++++++++++++++++++ .../securesms/events/WebRtcViewModel.kt | 2 ++ .../webrtc/CallLinkDisconnectReason.kt | 18 +++++++++++ .../webrtc/CallLinkJoiningActionProcessor.kt | 16 ++++++++++ .../service/webrtc/state/CallInfoState.kt | 4 ++- .../state/WebRtcServiceStateBuilder.java | 6 ++++ app/src/main/res/values/strings.xml | 10 ++++++- 7 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallLinkDisconnectReason.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java b/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java index faf00dbb17..95ab93eb5e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java @@ -81,6 +81,7 @@ import org.thoughtcrime.securesms.recipients.LiveRecipient; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.safety.SafetyNumberBottomSheet; +import org.thoughtcrime.securesms.service.webrtc.CallLinkDisconnectReason; import org.thoughtcrime.securesms.service.webrtc.SignalCallManager; import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.util.BottomSheetUtil; @@ -145,6 +146,7 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan private ThrottledDebouncer requestNewSizesThrottle; private PictureInPictureParams.Builder pipBuilderParams; private LifecycleDisposable lifecycleDisposable; + private long lastCallLinkDisconnectDialogShowTime; private Disposable ephemeralStateDisposable = Disposable.empty(); @@ -842,6 +844,18 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan handleUntrustedIdentity(event); break; } + if (event.getCallLinkDisconnectReason() != null && event.getCallLinkDisconnectReason().getPostedAt() > lastCallLinkDisconnectDialogShowTime) { + lastCallLinkDisconnectDialogShowTime = System.currentTimeMillis(); + + if (event.getCallLinkDisconnectReason() instanceof CallLinkDisconnectReason.RemovedFromCall) { + displayRemovedFromCallLinkDialog(); + } else if (event.getCallLinkDisconnectReason() instanceof CallLinkDisconnectReason.DeniedRequestToJoinCall) { + displayDeniedRequestToJoinCallLinkDialog(); + } else { + throw new AssertionError("Unexpected reason: " + event.getCallLinkDisconnectReason()); + } + } + boolean enableVideo = event.getLocalParticipant().getCameraState().getCameraCount() > 0 && enableVideoIfAvailable; viewModel.updateFromWebRtcViewModel(event, enableVideo); @@ -863,6 +877,22 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan } } + private void displayRemovedFromCallLinkDialog() { + new MaterialAlertDialogBuilder(this) + .setTitle(R.string.WebRtcCallActivity__removed_from_call) + .setMessage(R.string.WebRtcCallActivity__someone_has_removed_you_from_the_call) + .setPositiveButton(android.R.string.ok, null) + .show(); + } + + private void displayDeniedRequestToJoinCallLinkDialog() { + new MaterialAlertDialogBuilder(this) + .setTitle(R.string.WebRtcCallActivity__join_request_denied) + .setMessage(R.string.WebRtcCallActivity__your_request_to_join_this_call_has_been_denied) + .setPositiveButton(android.R.string.ok, null) + .show(); + } + private void handleCallPreJoin(@NonNull WebRtcViewModel event) { if (event.getGroupState().isNotIdle()) { callScreen.setStatusFromGroupCallState(event.getGroupState()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/events/WebRtcViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/events/WebRtcViewModel.kt index 9e5420c0e1..e7d2e71591 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/events/WebRtcViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/events/WebRtcViewModel.kt @@ -5,6 +5,7 @@ import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink import org.thoughtcrime.securesms.events.CallParticipant.Companion.createLocal import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId +import org.thoughtcrime.securesms.service.webrtc.CallLinkDisconnectReason import org.thoughtcrime.securesms.service.webrtc.PendingParticipantCollection import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager @@ -96,6 +97,7 @@ class WebRtcViewModel(state: WebRtcServiceState) { val participantLimit: Long? = state.callInfoState.participantLimit val pendingParticipants: PendingParticipantCollection = state.callInfoState.pendingParticipants val isCallLink: Boolean = state.callInfoState.callRecipient.isCallLink + val callLinkDisconnectReason: CallLinkDisconnectReason? = state.callInfoState.callLinkDisconnectReason @get:JvmName("shouldRingGroup") val ringGroup: Boolean = state.getCallSetupState(state.callInfoState.activePeer?.callId).ringGroup diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallLinkDisconnectReason.kt b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallLinkDisconnectReason.kt new file mode 100644 index 0000000000..0539220091 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallLinkDisconnectReason.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2023 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.service.webrtc + +/** + * Describes why a user was not able to join a call link. + * + * Note: postedAt is kept as a long to ensure Java compatibility. + */ +sealed interface CallLinkDisconnectReason { + val postedAt: Long + + data class RemovedFromCall(override val postedAt: Long = System.currentTimeMillis()) : CallLinkDisconnectReason + data class DeniedRequestToJoinCall(override val postedAt: Long = System.currentTimeMillis()) : CallLinkDisconnectReason +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallLinkJoiningActionProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallLinkJoiningActionProcessor.kt index 6ffb8fd453..ca08434b7d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallLinkJoiningActionProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/CallLinkJoiningActionProcessor.kt @@ -6,6 +6,7 @@ package org.thoughtcrime.securesms.service.webrtc import org.signal.core.util.logging.Log +import org.signal.ringrtc.GroupCall import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState /** @@ -25,4 +26,19 @@ class CallLinkJoiningActionProcessor( return currentState } + + override fun handleGroupCallEnded(currentState: WebRtcServiceState, groupCallHash: Int, groupCallEndReason: GroupCall.GroupCallEndReason): WebRtcServiceState { + val serviceState = super.handleGroupCallEnded(currentState, groupCallHash, groupCallEndReason) + + val callLinkDisconnectReason = when (groupCallEndReason) { + GroupCall.GroupCallEndReason.DENIED_REQUEST_TO_JOIN_CALL -> CallLinkDisconnectReason.DeniedRequestToJoinCall() + GroupCall.GroupCallEndReason.REMOVED_FROM_CALL -> CallLinkDisconnectReason.RemovedFromCall() + else -> null + } + + return serviceState.builder() + .changeCallInfoState() + .setCallLinkDisconnectReason(callLinkDisconnectReason) + .build() + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/state/CallInfoState.kt b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/state/CallInfoState.kt index 285be5641b..511aa45993 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/state/CallInfoState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/state/CallInfoState.kt @@ -9,6 +9,7 @@ import org.thoughtcrime.securesms.events.WebRtcViewModel import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.ringrtc.RemotePeer +import org.thoughtcrime.securesms.service.webrtc.CallLinkDisconnectReason import org.thoughtcrime.securesms.service.webrtc.PendingParticipantCollection /** @@ -28,7 +29,8 @@ data class CallInfoState( var identityChangedRecipients: MutableSet = mutableSetOf(), var remoteDevicesCount: OptionalLong = OptionalLong.empty(), var participantLimit: Long? = null, - var pendingParticipants: PendingParticipantCollection = PendingParticipantCollection() + var pendingParticipants: PendingParticipantCollection = PendingParticipantCollection(), + var callLinkDisconnectReason: CallLinkDisconnectReason? = null ) { val remoteCallParticipants: List diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/state/WebRtcServiceStateBuilder.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/state/WebRtcServiceStateBuilder.java index f5136d8e93..41f5feecfb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/state/WebRtcServiceStateBuilder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/state/WebRtcServiceStateBuilder.java @@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.ringrtc.Camera; import org.thoughtcrime.securesms.ringrtc.CameraState; import org.thoughtcrime.securesms.ringrtc.RemotePeer; +import org.thoughtcrime.securesms.service.webrtc.CallLinkDisconnectReason; import org.thoughtcrime.securesms.service.webrtc.WebRtcActionProcessor; import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager; import org.webrtc.PeerConnection; @@ -358,5 +359,10 @@ public class WebRtcServiceStateBuilder { toBuild.setPendingParticipants(toBuild.getPendingParticipants().withDenial(participant)); return this; } + + public @NonNull CallInfoStateBuilder setCallLinkDisconnectReason(@Nullable CallLinkDisconnectReason callLinkDisconnectReason) { + toBuild.setCallLinkDisconnectReason(callLinkDisconnectReason); + return this; + } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f3e1df0880..917f8dab0e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1761,7 +1761,15 @@ %1$d person waiting %1$d people waiting - + + Join request denied + + Your request to join this call has been denied. + + Removed from call + + Someone has removed you from the call. + Signal Call