From 8f9713a2c08dc2f6a86281ffec91cc0a5033198c Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Thu, 23 Mar 2023 11:25:24 -0300 Subject: [PATCH] Add new call toast and remove call button labels. --- .../securesms/WebRtcCallActivity.java | 14 +- ...CallParticipantsListUpdatePopupWindow.java | 3 +- .../webrtc/CallStateUpdatePopupWindow.kt | 102 ++++++++ .../components/webrtc/WebRtcCallView.java | 26 +- ...l_participant_update_window_background.xml | 4 +- .../drawable/symbol_bell_ring_compact_16.xml | 17 ++ .../drawable/symbol_bell_slash_compact_16.xml | 15 ++ .../drawable/symbol_bell_slash_fill_24.xml | 18 ++ .../res/drawable/symbol_mic_compact_16.xml | 12 + .../main/res/drawable/symbol_mic_fill_24.xml | 4 +- .../res/drawable/symbol_mic_fill_white_24.xml | 12 + .../drawable/symbol_mic_slash_compact_16.xml | 21 ++ .../webrtc_call_screen_mic_toggle.xml | 2 +- .../webrtc_call_screen_mic_toggle_small.xml | 2 +- .../layout/call_participant_list_update.xml | 52 ++-- app/src/main/res/layout/call_state_update.xml | 57 +++++ app/src/main/res/layout/webrtc_call_view.xml | 227 ++---------------- .../layout/webrtc_call_view_header_large.xml | 6 +- app/src/main/res/values/strings.xml | 12 + 19 files changed, 341 insertions(+), 265 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallStateUpdatePopupWindow.kt create mode 100644 app/src/main/res/drawable/symbol_bell_ring_compact_16.xml create mode 100644 app/src/main/res/drawable/symbol_bell_slash_compact_16.xml create mode 100644 app/src/main/res/drawable/symbol_bell_slash_fill_24.xml create mode 100644 app/src/main/res/drawable/symbol_mic_compact_16.xml create mode 100644 app/src/main/res/drawable/symbol_mic_fill_white_24.xml create mode 100644 app/src/main/res/drawable/symbol_mic_slash_compact_16.xml create mode 100644 app/src/main/res/layout/call_state_update.xml diff --git a/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java b/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java index b73865d83b..c9209cca6f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java @@ -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); } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsListUpdatePopupWindow.java b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsListUpdatePopupWindow.java index 46a3381724..7dfd77463a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsListUpdatePopupWindow.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsListUpdatePopupWindow.java @@ -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); diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallStateUpdatePopupWindow.kt b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallStateUpdatePopupWindow.kt new file mode 100644 index 0000000000..b790286036 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallStateUpdatePopupWindow.kt @@ -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(R.id.icon) + private val descriptionView = contentView.findViewById(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) + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcCallView.java b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcCallView.java index 3fe9643bb8..a5a2b641cf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcCallView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcCallView.java @@ -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(); diff --git a/app/src/main/res/drawable/call_participant_update_window_background.xml b/app/src/main/res/drawable/call_participant_update_window_background.xml index 99759155d9..132f8fa813 100644 --- a/app/src/main/res/drawable/call_participant_update_window_background.xml +++ b/app/src/main/res/drawable/call_participant_update_window_background.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/drawable/symbol_bell_ring_compact_16.xml b/app/src/main/res/drawable/symbol_bell_ring_compact_16.xml new file mode 100644 index 0000000000..602828090a --- /dev/null +++ b/app/src/main/res/drawable/symbol_bell_ring_compact_16.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/app/src/main/res/drawable/symbol_bell_slash_compact_16.xml b/app/src/main/res/drawable/symbol_bell_slash_compact_16.xml new file mode 100644 index 0000000000..31c7dcd3e8 --- /dev/null +++ b/app/src/main/res/drawable/symbol_bell_slash_compact_16.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable/symbol_bell_slash_fill_24.xml b/app/src/main/res/drawable/symbol_bell_slash_fill_24.xml new file mode 100644 index 0000000000..0e26ecf7b3 --- /dev/null +++ b/app/src/main/res/drawable/symbol_bell_slash_fill_24.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/app/src/main/res/drawable/symbol_mic_compact_16.xml b/app/src/main/res/drawable/symbol_mic_compact_16.xml new file mode 100644 index 0000000000..e68f69b652 --- /dev/null +++ b/app/src/main/res/drawable/symbol_mic_compact_16.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/symbol_mic_fill_24.xml b/app/src/main/res/drawable/symbol_mic_fill_24.xml index 2900bd4f8d..422c3e0fd8 100644 --- a/app/src/main/res/drawable/symbol_mic_fill_24.xml +++ b/app/src/main/res/drawable/symbol_mic_fill_24.xml @@ -4,9 +4,9 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/app/src/main/res/drawable/symbol_mic_fill_white_24.xml b/app/src/main/res/drawable/symbol_mic_fill_white_24.xml new file mode 100644 index 0000000000..2900bd4f8d --- /dev/null +++ b/app/src/main/res/drawable/symbol_mic_fill_white_24.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/symbol_mic_slash_compact_16.xml b/app/src/main/res/drawable/symbol_mic_slash_compact_16.xml new file mode 100644 index 0000000000..d889bc41f5 --- /dev/null +++ b/app/src/main/res/drawable/symbol_mic_slash_compact_16.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/app/src/main/res/drawable/webrtc_call_screen_mic_toggle.xml b/app/src/main/res/drawable/webrtc_call_screen_mic_toggle.xml index 3819f37186..a5e735a894 100644 --- a/app/src/main/res/drawable/webrtc_call_screen_mic_toggle.xml +++ b/app/src/main/res/drawable/webrtc_call_screen_mic_toggle.xml @@ -3,7 +3,7 @@ - + diff --git a/app/src/main/res/drawable/webrtc_call_screen_mic_toggle_small.xml b/app/src/main/res/drawable/webrtc_call_screen_mic_toggle_small.xml index feb7505a1c..ff8dae20df 100644 --- a/app/src/main/res/drawable/webrtc_call_screen_mic_toggle_small.xml +++ b/app/src/main/res/drawable/webrtc_call_screen_mic_toggle_small.xml @@ -19,7 +19,7 @@ android:left="4dp" android:right="4dp" android:drawable="@drawable/webrtc_call_screen_circle_checked" /> - + \ No newline at end of file diff --git a/app/src/main/res/layout/call_participant_list_update.xml b/app/src/main/res/layout/call_participant_list_update.xml index 331305da6e..ca449f1710 100644 --- a/app/src/main/res/layout/call_participant_list_update.xml +++ b/app/src/main/res/layout/call_participant_list_update.xml @@ -1,24 +1,28 @@ + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:minHeight="94dp" + tools:viewBindingIgnore="true"> + android:background="@drawable/call_participant_update_window_background" + android:elevation="4dp"> + app:layout_constraintVertical_bias="1.0" + app:layout_goneMarginStart="24dp" + tools:text="Kiera joined" /> \ No newline at end of file diff --git a/app/src/main/res/layout/call_state_update.xml b/app/src/main/res/layout/call_state_update.xml new file mode 100644 index 0000000000..d8da7a2bed --- /dev/null +++ b/app/src/main/res/layout/call_state_update.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/webrtc_call_view.xml b/app/src/main/res/layout/webrtc_call_view.xml index 749a8f07bb..95bf8a700d 100644 --- a/app/src/main/res/layout/webrtc_call_view.xml +++ b/app/src/main/res/layout/webrtc_call_view.xml @@ -1,9 +1,9 @@ + tools:parentTag="org.thoughtcrime.securesms.components.webrtc.WebRtcCallView" + tools:viewBindingIgnore="true"> @@ -216,247 +216,108 @@ android:layout_height="@dimen/webrtc_button_size" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" - android:layout_marginBottom="8dp" + android:layout_marginBottom="30dp" + android:contentDescription="@string/WebRtcCallView__speaker" android:scaleType="fitXY" android:visibility="gone" - android:contentDescription="@string/WebRtcCallView__speaker" - app:layout_constraintBottom_toTopOf="@id/call_screen_button_labels_barrier" + app:layout_constraintBottom_toTopOf="@id/call_screen_start_call_controls" app:layout_constraintEnd_toStartOf="@id/call_screen_camera_direction_toggle" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintStart_toStartOf="parent" app:srcCompat="@drawable/webrtc_call_screen_speaker_toggle" tools:visibility="visible" /> - - - - - - - - - - - - - - - - - - - - New call + + + Ringing on + + Ringing off + + Group is too large to ring the participants + + Mic on + + Mic off +