Add new call toast and remove call button labels.

This commit is contained in:
Alex Hart
2023-03-23 11:25:24 -03:00
committed by Greyson Parrelli
parent 7a2ad37333
commit 8f9713a2c0
19 changed files with 341 additions and 265 deletions

View File

@@ -58,6 +58,7 @@ import org.thoughtcrime.securesms.components.TooltipPopup;
import org.thoughtcrime.securesms.components.sensors.DeviceOrientationMonitor;
import org.thoughtcrime.securesms.components.webrtc.CallParticipantsListUpdatePopupWindow;
import org.thoughtcrime.securesms.components.webrtc.CallParticipantsState;
import org.thoughtcrime.securesms.components.webrtc.CallStateUpdatePopupWindow;
import org.thoughtcrime.securesms.components.webrtc.CallToastPopupWindow;
import org.thoughtcrime.securesms.components.webrtc.GroupCallSafetyNumberChangeNotificationUtil;
import org.thoughtcrime.securesms.components.webrtc.WebRtcAudioOutput;
@@ -112,6 +113,7 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
public static final String EXTRA_STARTED_FROM_FULLSCREEN = WebRtcCallActivity.class.getCanonicalName() + ".STARTED_FROM_FULLSCREEN";
private CallParticipantsListUpdatePopupWindow participantUpdateWindow;
private CallStateUpdatePopupWindow callStateUpdatePopupWindow;
private WifiToCellularPopupWindow wifiToCellularPopupWindow;
private DeviceOrientationMonitor deviceOrientationMonitor;
@@ -312,8 +314,9 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
callScreen = findViewById(R.id.callScreen);
callScreen.setControlsListener(new ControlsListener());
participantUpdateWindow = new CallParticipantsListUpdatePopupWindow(callScreen);
wifiToCellularPopupWindow = new WifiToCellularPopupWindow(callScreen);
participantUpdateWindow = new CallParticipantsListUpdatePopupWindow(callScreen);
callStateUpdatePopupWindow = new CallStateUpdatePopupWindow(callScreen);
wifiToCellularPopupWindow = new WifiToCellularPopupWindow(callScreen);
}
private void initializeViewModel(boolean isLandscapeEnabled) {
@@ -356,6 +359,7 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
addOnPictureInPictureModeChangedListener(info -> {
viewModel.setIsInPipMode(info.isInPictureInPictureMode());
participantUpdateWindow.setEnabled(!info.isInPictureInPictureMode());
callStateUpdatePopupWindow.setEnabled(!info.isInPictureInPictureMode());
});
}
@@ -800,6 +804,8 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
@Override
public void onMicChanged(boolean isMicEnabled) {
callStateUpdatePopupWindow.onCallStateUpdate(isMicEnabled ? CallStateUpdatePopupWindow.CallStateUpdate.MIC_ON
: CallStateUpdatePopupWindow.CallStateUpdate.MIC_OFF);
handleSetMuteAudio(!isMicEnabled);
}
@@ -851,9 +857,11 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
public void onRingGroupChanged(boolean ringGroup, boolean ringingAllowed) {
if (ringingAllowed) {
ApplicationDependencies.getSignalCallManager().setRingGroup(ringGroup);
callStateUpdatePopupWindow.onCallStateUpdate(ringGroup ? CallStateUpdatePopupWindow.CallStateUpdate.RINGING_ON
: CallStateUpdatePopupWindow.CallStateUpdate.RINGING_OFF);
} else {
ApplicationDependencies.getSignalCallManager().setRingGroup(false);
Toast.makeText(WebRtcCallActivity.this, R.string.WebRtcCallActivity__group_is_too_large_to_ring_the_participants, Toast.LENGTH_SHORT).show();
callStateUpdatePopupWindow.onCallStateUpdate(CallStateUpdatePopupWindow.CallStateUpdate.RINGING_DISABLED);
}
}
}

View File

@@ -17,7 +17,6 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.badges.BadgeImageView;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.HashSet;
import java.util.Iterator;
@@ -41,7 +40,7 @@ public class CallParticipantsListUpdatePopupWindow extends PopupWindow {
public CallParticipantsListUpdatePopupWindow(@NonNull ViewGroup parent) {
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.call_participant_list_update, parent, false),
ViewGroup.LayoutParams.MATCH_PARENT,
ViewUtil.dpToPx(94));
ViewGroup.LayoutParams.WRAP_CONTENT);
this.parent = parent;
this.avatarImageView = getContentView().findViewById(R.id.avatar);

View File

@@ -0,0 +1,102 @@
package org.thoughtcrime.securesms.components.webrtc
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.PopupWindow
import android.widget.TextView
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.util.Debouncer
import java.util.concurrent.TimeUnit
/**
* Popup window which is displayed whenever the call state changes from user input.
*/
class CallStateUpdatePopupWindow(private val parent: ViewGroup) : PopupWindow(
LayoutInflater.from(parent.context).inflate(R.layout.call_state_update, parent, false),
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
) {
private var enabled: Boolean = true
private var pendingUpdate: CallStateUpdate? = null
private var lastUpdate: CallStateUpdate? = null
private val dismissDebouncer = Debouncer(2, TimeUnit.SECONDS)
private val iconView = contentView.findViewById<ImageView>(R.id.icon)
private val descriptionView = contentView.findViewById<TextView>(R.id.description)
init {
setOnDismissListener {
val pending = pendingUpdate
if (pending != null) {
onCallStateUpdate(pending)
}
}
}
fun setEnabled(enabled: Boolean) {
this.enabled = enabled
if (!enabled) {
dismissDebouncer.clear()
dismiss()
}
}
fun onCallStateUpdate(callStateUpdate: CallStateUpdate) {
if (isShowing && lastUpdate == callStateUpdate) {
dismissDebouncer.publish { dismiss() }
} else if (isShowing) {
dismissDebouncer.clear()
pendingUpdate = callStateUpdate
dismiss()
} else {
pendingUpdate = null
lastUpdate = callStateUpdate
presentCallState(callStateUpdate)
show()
}
}
private fun presentCallState(callStateUpdate: CallStateUpdate) {
if (callStateUpdate.iconRes == null) {
iconView.setImageDrawable(null)
} else {
iconView.setImageResource(callStateUpdate.iconRes)
}
descriptionView.setText(callStateUpdate.stringRes)
}
private fun show() {
if (!enabled) {
return
}
showAtLocation(parent, Gravity.TOP or Gravity.START, 0, 0)
measureChild()
update()
dismissDebouncer.publish { dismiss() }
}
private fun measureChild() {
contentView.measure(
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
)
}
enum class CallStateUpdate(
@DrawableRes val iconRes: Int?,
@StringRes val stringRes: Int
) {
RINGING_ON(R.drawable.symbol_bell_ring_compact_16, R.string.CallStateUpdatePopupWindow__ringing_on),
RINGING_OFF(R.drawable.symbol_bell_slash_compact_16, R.string.CallStateUpdatePopupWindow__ringing_off),
RINGING_DISABLED(null, R.string.CallStateUpdatePopupWindow__group_is_too_large),
MIC_ON(R.drawable.symbol_mic_compact_16, R.string.CallStateUpdatePopupWindow__mic_on),
MIC_OFF(R.drawable.symbol_mic_slash_compact_16, R.string.CallStateUpdatePopupWindow__mic_off)
}
}

View File

@@ -76,11 +76,8 @@ public class WebRtcCallView extends ConstraintLayout {
public static final int CONTROLS_HEIGHT = 98;
private WebRtcAudioOutputToggleButton audioToggle;
private TextView audioToggleLabel;
private AccessibleToggleButton videoToggle;
private TextView videoToggleLabel;
private AccessibleToggleButton micToggle;
private TextView micToggleLabel;
private ViewGroup smallLocalRenderFrame;
private CallParticipantView smallLocalRender;
private View largeLocalRenderFrame;
@@ -96,14 +93,10 @@ public class WebRtcCallView extends ConstraintLayout {
private RecipientId recipientId;
private ImageView answer;
private ImageView cameraDirectionToggle;
private TextView cameraDirectionToggleLabel;
private AccessibleToggleButton ringToggle;
private TextView ringToggleLabel;
private PictureInPictureGestureHelper pictureInPictureGestureHelper;
private ImageView hangup;
private TextView hangupLabel;
private View answerWithoutVideo;
private View answerWithoutVideoLabel;
private View topGradient;
private View footerGradient;
private View startCallControls;
@@ -166,11 +159,8 @@ public class WebRtcCallView extends ConstraintLayout {
super.onFinishInflate();
audioToggle = findViewById(R.id.call_screen_speaker_toggle);
audioToggleLabel = findViewById(R.id.call_screen_speaker_toggle_label);
videoToggle = findViewById(R.id.call_screen_video_toggle);
videoToggleLabel = findViewById(R.id.call_screen_video_toggle_label);
micToggle = findViewById(R.id.call_screen_audio_mic_toggle);
micToggleLabel = findViewById(R.id.call_screen_audio_mic_toggle_label);
smallLocalRenderFrame = findViewById(R.id.call_screen_pip);
smallLocalRender = findViewById(R.id.call_screen_small_local_renderer);
largeLocalRenderFrame = findViewById(R.id.call_screen_large_local_renderer_frame);
@@ -184,13 +174,9 @@ public class WebRtcCallView extends ConstraintLayout {
participantsParent = findViewById(R.id.call_screen_participants_parent);
answer = findViewById(R.id.call_screen_answer_call);
cameraDirectionToggle = findViewById(R.id.call_screen_camera_direction_toggle);
cameraDirectionToggleLabel = findViewById(R.id.call_screen_camera_direction_toggle_label);
ringToggle = findViewById(R.id.call_screen_audio_ring_toggle);
ringToggleLabel = findViewById(R.id.call_screen_audio_ring_toggle_label);
hangup = findViewById(R.id.call_screen_end_call);
hangupLabel = findViewById(R.id.call_screen_end_call_label);
answerWithoutVideo = findViewById(R.id.call_screen_answer_without_video);
answerWithoutVideoLabel = findViewById(R.id.call_screen_answer_without_video_label);
topGradient = findViewById(R.id.call_screen_header_gradient);
footerGradient = findViewById(R.id.call_screen_footer_gradient);
startCallControls = findViewById(R.id.call_screen_start_call_controls);
@@ -212,8 +198,6 @@ public class WebRtcCallView extends ConstraintLayout {
fullScreenShade = findViewById(R.id.call_screen_full_shade);
View decline = findViewById(R.id.call_screen_decline_call);
View answerLabel = findViewById(R.id.call_screen_answer_call_label);
View declineLabel = findViewById(R.id.call_screen_decline_call_label);
callParticipantsPager.setPageTransformer(new MarginPageTransformer(ViewUtil.dpToPx(4)));
@@ -238,9 +222,7 @@ public class WebRtcCallView extends ConstraintLayout {
topViews.add(topGradient);
incomingCallViews.add(answer);
incomingCallViews.add(answerLabel);
incomingCallViews.add(decline);
incomingCallViews.add(declineLabel);
incomingCallViews.add(footerGradient);
incomingCallViews.add(incomingRingStatus);
@@ -639,7 +621,6 @@ public class WebRtcCallView extends ConstraintLayout {
if (webRtcControls.displayAnswerWithoutVideo()) {
visibleViewSet.add(answerWithoutVideo);
visibleViewSet.add(answerWithoutVideoLabel);
answer.setImageDrawable(AppCompatResources.getDrawable(getContext(), R.drawable.webrtc_call_screen_answer_with_video));
}
@@ -650,7 +631,6 @@ public class WebRtcCallView extends ConstraintLayout {
if (webRtcControls.displayAudioToggle()) {
visibleViewSet.add(audioToggle);
visibleViewSet.add(audioToggleLabel);
audioToggle.setControlAvailability(webRtcControls.enableHandsetInAudioToggle(),
webRtcControls.enableHeadsetInAudioToggle());
@@ -660,23 +640,19 @@ public class WebRtcCallView extends ConstraintLayout {
if (webRtcControls.displayCameraToggle()) {
visibleViewSet.add(cameraDirectionToggle);
visibleViewSet.add(cameraDirectionToggleLabel);
}
if (webRtcControls.displayEndCall()) {
visibleViewSet.add(hangup);
visibleViewSet.add(hangupLabel);
visibleViewSet.add(footerGradient);
}
if (webRtcControls.displayMuteAudio()) {
visibleViewSet.add(micToggle);
visibleViewSet.add(micToggleLabel);
}
if (webRtcControls.displayVideoToggle()) {
visibleViewSet.add(videoToggle);
visibleViewSet.add(videoToggleLabel);
}
if (webRtcControls.displaySmallOngoingCallButtons()) {
@@ -701,9 +677,9 @@ public class WebRtcCallView extends ConstraintLayout {
if (webRtcControls.displayRingToggle()) {
visibleViewSet.add(ringToggle);
visibleViewSet.add(ringToggleLabel);
}
if (webRtcControls.isFadeOutEnabled()) {
if (!controls.isFadeOutEnabled()) {
scheduleFadeOut();