diff --git a/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java b/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java index 6bf2f76a6a..128984dd9c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/WebRtcCallActivity.java @@ -17,8 +17,6 @@ package org.thoughtcrime.securesms; -import static org.thoughtcrime.securesms.components.sensors.Orientation.PORTRAIT_BOTTOM_EDGE; - import android.Manifest; import android.annotation.SuppressLint; import android.app.PictureInPictureParams; @@ -82,6 +80,8 @@ import org.whispersystems.signalservice.api.messages.calls.HangupMessage; import java.util.List; import java.util.Optional; +import static org.thoughtcrime.securesms.components.sensors.Orientation.PORTRAIT_BOTTOM_EDGE; + public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChangeDialog.Callback { private static final String TAG = Log.tag(WebRtcCallActivity.class); @@ -772,7 +772,7 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan setRequestedOrientation(feature.isPresent() ? ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); if (feature.isPresent()) { FoldingFeature foldingFeature = (FoldingFeature) feature.get(); - Rect bounds = foldingFeature.getBounds(); + Rect bounds = foldingFeature.getBounds(); if (foldingFeature.getState() == FoldingFeature.State.HALF_OPENED && bounds.top == bounds.bottom) { Log.d(TAG, "OnWindowLayoutInfo accepted: ensure call view is in table-top display mode"); viewModel.setFoldableState(WebRtcControls.FoldableState.folded(bounds.top)); diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantView.java b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantView.java index 845ede228b..09ef0bc5a4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantView.java @@ -196,6 +196,14 @@ public class CallParticipantView extends ConstraintLayout { pipAvatar.setVisibility(shouldRenderInPip ? View.VISIBLE : View.GONE); } + void hideAvatar() { + avatar.setAlpha(0f); + } + + void showAvatar() { + avatar.setAlpha(1f); + } + void useLargeAvatar() { changeAvatarParams(LARGE_AVATAR); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsLayout.java b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsLayout.java index 85b49758c1..d444d60e30 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsLayout.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsLayout.java @@ -34,6 +34,7 @@ public class CallParticipantsLayout extends FlexboxLayout { private CallParticipant focusedParticipant = null; private boolean shouldRenderInPip; private boolean isPortrait; + private boolean isIncomingRing; private LayoutStrategy layoutStrategy; public CallParticipantsLayout(@NonNull Context context) { @@ -52,13 +53,16 @@ public class CallParticipantsLayout extends FlexboxLayout { @NonNull CallParticipant focusedParticipant, boolean shouldRenderInPip, boolean isPortrait, + boolean isIncomingRing, @NonNull LayoutStrategy layoutStrategy) { this.callParticipants = callParticipants; this.focusedParticipant = focusedParticipant; this.shouldRenderInPip = shouldRenderInPip; this.isPortrait = isPortrait; + this.isIncomingRing = isIncomingRing; this.layoutStrategy = layoutStrategy; + setFlexDirection(layoutStrategy.getFlexDirection()); updateLayout(); } @@ -125,6 +129,12 @@ public class CallParticipantsLayout extends FlexboxLayout { cardView.setRadius(0); } + if (isIncomingRing) { + callParticipantView.hideAvatar(); + } else { + callParticipantView.showAvatar(); + } + if (count > 2) { callParticipantView.useSmallAvatar(); } else { diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsState.java b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsState.java index d8b8fd7844..37107f19ef 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsState.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsState.java @@ -197,6 +197,10 @@ public final class CallParticipantsState { .or(() -> includeSelf ? OptionalLong.of(1L) : OptionalLong.empty()); } + public boolean isIncomingRing() { + return callState == WebRtcViewModel.State.CALL_INCOMING; + } + public static @NonNull CallParticipantsState update(@NonNull CallParticipantsState oldState, @NonNull WebRtcViewModel webRtcViewModel, boolean enableVideo) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcCallParticipantsPage.java b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcCallParticipantsPage.java index ca89e3da8f..7a2380cad8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcCallParticipantsPage.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcCallParticipantsPage.java @@ -16,14 +16,16 @@ class WebRtcCallParticipantsPage { private final boolean isRenderInPip; private final boolean isPortrait; private final boolean isLandscapeEnabled; + private final boolean isIncomingRing; static WebRtcCallParticipantsPage forMultipleParticipants(@NonNull List callParticipants, @NonNull CallParticipant focusedParticipant, boolean isRenderInPip, boolean isPortrait, - boolean isLandscapeEnabled) + boolean isLandscapeEnabled, + boolean isIncomingRing) { - return new WebRtcCallParticipantsPage(callParticipants, focusedParticipant, false, isRenderInPip, isPortrait, isLandscapeEnabled); + return new WebRtcCallParticipantsPage(callParticipants, focusedParticipant, false, isRenderInPip, isPortrait, isLandscapeEnabled, isIncomingRing); } static WebRtcCallParticipantsPage forSingleParticipant(@NonNull CallParticipant singleParticipant, @@ -31,7 +33,7 @@ class WebRtcCallParticipantsPage { boolean isPortrait, boolean isLandscapeEnabled) { - return new WebRtcCallParticipantsPage(Collections.singletonList(singleParticipant), singleParticipant, true, isRenderInPip, isPortrait, isLandscapeEnabled); + return new WebRtcCallParticipantsPage(Collections.singletonList(singleParticipant), singleParticipant, true, isRenderInPip, isPortrait, isLandscapeEnabled, false); } private WebRtcCallParticipantsPage(@NonNull List callParticipants, @@ -39,7 +41,8 @@ class WebRtcCallParticipantsPage { boolean isSpeaker, boolean isRenderInPip, boolean isPortrait, - boolean isLandscapeEnabled) + boolean isLandscapeEnabled, + boolean isIncomingRing) { this.callParticipants = callParticipants; this.focusedParticipant = focusedParticipant; @@ -47,6 +50,7 @@ class WebRtcCallParticipantsPage { this.isRenderInPip = isRenderInPip; this.isPortrait = isPortrait; this.isLandscapeEnabled = isLandscapeEnabled; + this.isIncomingRing = isIncomingRing; } public @NonNull List getCallParticipants() { @@ -69,6 +73,10 @@ class WebRtcCallParticipantsPage { return isPortrait; } + public boolean isIncomingRing() { + return isIncomingRing; + } + public @NonNull CallParticipantsLayout.LayoutStrategy getLayoutStrategy() { return CallParticipantsLayoutStrategies.getStrategy(isPortrait, isLandscapeEnabled); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcCallParticipantsPagerAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcCallParticipantsPagerAdapter.java index 8dbcc95232..de45c1dc71 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcCallParticipantsPagerAdapter.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcCallParticipantsPagerAdapter.java @@ -86,7 +86,7 @@ class WebRtcCallParticipantsPagerAdapter extends ListAdapter groupCallSpeakerHint; private Stub groupCallFullStub; private View errorButton; private int pagerBottomMarginDp; private boolean controlsVisible = true; + private Guideline showParticipantsGuideline; private Guideline topFoldGuideline; private Guideline callScreenTopFoldGuideline; private View foldParticipantCountWrapper; private TextView foldParticipantCount; + private AvatarImageView largeHeaderAvatar; + private ConstraintSet smallHeaderConstraints; + private Guideline statusBarGuideline; + private View fullScreenShade; private WebRtcCallParticipantsPagerAdapter pagerAdapter; private WebRtcCallParticipantsRecyclerAdapter recyclerAdapter; @@ -114,11 +125,14 @@ public class WebRtcCallView extends ConstraintLayout { private final Set incomingCallViews = new HashSet<>(); private final Set topViews = new HashSet<>(); private final Set visibleViewSet = new HashSet<>(); + private final Set allTimeVisibleViews = new HashSet<>(); private final Set adjustableMarginsSet = new HashSet<>(); private final Set rotatableControls = new HashSet<>(); - private WebRtcControls controls = WebRtcControls.NONE; - private final Runnable fadeOutRunnable = () -> { + + private final ThrottledDebouncer throttledDebouncer = new ThrottledDebouncer(TRANSITION_DURATION_MILLIS); + private WebRtcControls controls = WebRtcControls.NONE; + private final Runnable fadeOutRunnable = () -> { if (isAttachedToWindow() && controls.isFadeOutEnabled()) fadeOutControls(); }; @@ -138,8 +152,11 @@ 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); @@ -148,32 +165,38 @@ public class WebRtcCallView extends ConstraintLayout { largeLocalRenderNoVideoAvatar = findViewById(R.id.call_screen_large_local_video_off_avatar); recipientName = findViewById(R.id.call_screen_recipient_name); status = findViewById(R.id.call_screen_status); + incomingRingStatus = findViewById(R.id.call_screen_incoming_ring_status); parent = findViewById(R.id.call_screen); 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); hangup = findViewById(R.id.call_screen_end_call); + hangupLabel = findViewById(R.id.call_screen_end_call_label); answerWithAudio = findViewById(R.id.call_screen_answer_with_audio); answerWithAudioLabel = findViewById(R.id.call_screen_answer_with_audio_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); callParticipantsPager = findViewById(R.id.call_screen_participants_pager); callParticipantsRecycler = findViewById(R.id.call_screen_participants_recycler); - toolbar = findViewById(R.id.call_screen_toolbar); + toolbar = findViewById(R.id.call_screen_header); startCall = findViewById(R.id.call_screen_start_call_start_call); errorButton = findViewById(R.id.call_screen_error_cancel); groupCallSpeakerHint = new Stub<>(findViewById(R.id.call_screen_group_call_speaker_hint)); groupCallFullStub = new Stub<>(findViewById(R.id.group_call_call_full_view)); + showParticipantsGuideline = findViewById(R.id.call_screen_show_participants_guideline); topFoldGuideline = findViewById(R.id.fold_top_guideline); callScreenTopFoldGuideline = findViewById(R.id.fold_top_call_screen_guideline); foldParticipantCountWrapper = findViewById(R.id.fold_show_participants_menu_counter_wrapper); foldParticipantCount = findViewById(R.id.fold_show_participants_menu_counter); + largeHeaderAvatar = findViewById(R.id.call_screen_header_avatar); + statusBarGuideline = findViewById(R.id.call_screen_status_bar_guideline); + fullScreenShade = findViewById(R.id.call_screen_full_shade); - View topGradient = findViewById(R.id.call_screen_header_gradient); 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); - View cancelStartCall = findViewById(R.id.call_screen_start_call_cancel); callParticipantsPager.setPageTransformer(new MarginPageTransformer(ViewUtil.dpToPx(4))); @@ -239,7 +262,6 @@ public class WebRtcCallView extends ConstraintLayout { controlsListener.onStartCall(videoToggle.isChecked()); } }); - cancelStartCall.setOnClickListener(v -> runIfNonNull(controlsListener, ControlsListener::onCancelStartCall)); ColorMatrix greyScaleMatrix = new ColorMatrix(); greyScaleMatrix.setSaturation(0); @@ -261,6 +283,9 @@ public class WebRtcCallView extends ConstraintLayout { rotatableControls.add(cameraDirectionToggle); rotatableControls.add(decline); rotatableControls.add(smallLocalRender.findViewById(R.id.call_participant_mic_muted)); + + smallHeaderConstraints = new ConstraintSet(); + smallHeaderConstraints.clone(getContext(), R.layout.webrtc_call_view_header_small); } @Override @@ -274,7 +299,6 @@ public class WebRtcCallView extends ConstraintLayout { @Override protected boolean fitSystemWindows(Rect insets) { - Guideline statusBarGuideline = findViewById(R.id.call_screen_status_bar_guideline); Guideline navigationBarGuideline = findViewById(R.id.call_screen_navigation_bar_guideline); statusBarGuideline.setGuidelineBegin(insets.top); @@ -327,27 +351,22 @@ public class WebRtcCallView extends ConstraintLayout { List pages = new ArrayList<>(2); if (!state.getGridParticipants().isEmpty()) { - pages.add(WebRtcCallParticipantsPage.forMultipleParticipants(state.getGridParticipants(), state.getFocusedParticipant(), state.isInPipMode(), isPortrait, isLandscapeEnabled)); + pages.add(WebRtcCallParticipantsPage.forMultipleParticipants(state.getGridParticipants(), state.getFocusedParticipant(), state.isInPipMode(), isPortrait, isLandscapeEnabled, state.isIncomingRing())); } if (state.getFocusedParticipant() != CallParticipant.EMPTY && state.getAllRemoteParticipants().size() > 1) { pages.add(WebRtcCallParticipantsPage.forSingleParticipant(state.getFocusedParticipant(), state.isInPipMode(), isPortrait, isLandscapeEnabled)); } - if ((state.getGroupCallState().isNotIdle() && state.getRemoteDevicesCount().orElse(0) > 0) || state.getGroupCallState().isConnected()) { - recipientName.setText(state.getRemoteParticipantsDescription(getContext())); - } else if (state.getGroupCallState().isNotIdle()) { - recipientName.setText(getContext().getString(R.string.WebRtcCallView__s_group_call, Recipient.resolved(recipientId).getDisplayName(getContext()))); + if (state.getCallState() == WebRtcViewModel.State.CALL_PRE_JOIN && state.getGroupCallState().isNotIdle()) { + status.setText(state.getRemoteParticipantsDescription(getContext())); } - if (state.getGroupCallState().isNotIdle() && participantCount != null) { + if (state.getGroupCallState().isNotIdle()) { String text = state.getParticipantCount() .mapToObj(String::valueOf).orElse("\u2014"); boolean enabled = state.getParticipantCount().isPresent(); - participantCount.setText(text); - participantCount.setEnabled(enabled); - foldParticipantCount.setText(text); foldParticipantCount.setEnabled(enabled); } @@ -450,20 +469,13 @@ public class WebRtcCallView extends ConstraintLayout { recipientId = recipient.getId(); + largeHeaderAvatar.setRecipient(recipient, false); + if (recipient.isGroup()) { - if (toolbar.getMenu().findItem(R.id.menu_group_call_participants_list) == null) { - toolbar.inflateMenu(R.menu.group_call); - - View showParticipants = toolbar.getMenu().findItem(R.id.menu_group_call_participants_list).getActionView(); - showParticipants.setAlpha(0); - showParticipants.setOnClickListener(unused -> showParticipantsList()); - foldParticipantCountWrapper.setOnClickListener(unused -> showParticipantsList()); - - participantCount = showParticipants.findViewById(R.id.show_participants_menu_counter); - } - } else { - recipientName.setText(recipient.getDisplayName(getContext())); + foldParticipantCountWrapper.setOnClickListener(unused -> showParticipantsList()); } + + recipientName.setText(recipient.getDisplayName(getContext())); } public void setStatus(@NonNull String status) { @@ -515,18 +527,21 @@ public class WebRtcCallView extends ConstraintLayout { visibleViewSet.clear(); if (webRtcControls.adjustForFold()) { + showParticipantsGuideline.setGuidelineBegin(-1); + showParticipantsGuideline.setGuidelineEnd(webRtcControls.getFold()); topFoldGuideline.setGuidelineEnd(webRtcControls.getFold()); callScreenTopFoldGuideline.setGuidelineEnd(webRtcControls.getFold()); - - if (webRtcControls.displayGroupMembersButton()) { - visibleViewSet.add(foldParticipantCountWrapper); - } } else { + showParticipantsGuideline.setGuidelineBegin(((LayoutParams) statusBarGuideline.getLayoutParams()).guideBegin); + showParticipantsGuideline.setGuidelineEnd(-1); topFoldGuideline.setGuidelineEnd(0); callScreenTopFoldGuideline.setGuidelineEnd(0); } - setShowParticipantsState(webRtcControls.adjustForFold()); + if (webRtcControls.displayGroupMembersButton()) { + visibleViewSet.add(foldParticipantCountWrapper); + foldParticipantCount.setClickable(webRtcControls.adjustForFold()); + } if (webRtcControls.displayStartCallControls()) { visibleViewSet.add(footerGradient); @@ -548,12 +563,6 @@ public class WebRtcCallView extends ConstraintLayout { groupCallFullStub.get().setVisibility(View.GONE); } - MenuItem item = toolbar.getMenu().findItem(R.id.menu_group_call_participants_list); - if (item != null) { - item.setVisible(webRtcControls.displayGroupMembersButton()); - item.setEnabled(webRtcControls.displayGroupMembersButton()); - } - if (webRtcControls.displayTopViews()) { visibleViewSet.addAll(topViews); } @@ -561,7 +570,9 @@ public class WebRtcCallView extends ConstraintLayout { if (webRtcControls.displayIncomingCallButtons()) { visibleViewSet.addAll(incomingCallViews); - status.setText(R.string.WebRtcCallView__signal_voice_call); + incomingRingStatus.setVisibility(VISIBLE); + incomingRingStatus.setText(R.string.WebRtcCallView__signal_call); + answer.setImageDrawable(AppCompatResources.getDrawable(getContext(), R.drawable.webrtc_call_screen_answer)); } @@ -569,12 +580,19 @@ public class WebRtcCallView extends ConstraintLayout { visibleViewSet.add(answerWithAudio); visibleViewSet.add(answerWithAudioLabel); - status.setText(R.string.WebRtcCallView__signal_video_call); + incomingRingStatus.setVisibility(VISIBLE); + incomingRingStatus.setText(R.string.WebRtcCallView__signal_video_call); + answer.setImageDrawable(AppCompatResources.getDrawable(getContext(), R.drawable.webrtc_call_screen_answer_with_video)); } + if (!webRtcControls.displayIncomingCallButtons() && !webRtcControls.displayAnswerWithAudio()){ + incomingRingStatus.setVisibility(GONE); + } + if (webRtcControls.displayAudioToggle()) { visibleViewSet.add(audioToggle); + visibleViewSet.add(audioToggleLabel); audioToggle.setControlAvailability(webRtcControls.enableHandsetInAudioToggle(), webRtcControls.enableHeadsetInAudioToggle()); @@ -584,19 +602,23 @@ 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()) { @@ -611,6 +633,14 @@ public class WebRtcCallView extends ConstraintLayout { callParticipantsRecycler.setVisibility(View.GONE); } + if (webRtcControls.showFullScreenShade()) { + fullScreenShade.setVisibility(VISIBLE); + visibleViewSet.remove(topGradient); + visibleViewSet.remove(footerGradient); + } else { + fullScreenShade.setVisibility(GONE); + } + if (webRtcControls.isFadeOutEnabled()) { if (!controls.isFadeOutEnabled()) { scheduleFadeOut(); @@ -627,20 +657,26 @@ public class WebRtcCallView extends ConstraintLayout { scheduleFadeOut(); } + boolean forceUpdate = webRtcControls.adjustForFold() && !controls.adjustForFold(); controls = webRtcControls; if (!controls.isFadeOutEnabled()) { controlsVisible = true; } + allTimeVisibleViews.addAll(visibleViewSet); + if (!visibleViewSet.equals(lastVisibleSet) || - !controls.isFadeOutEnabled()) { + !controls.isFadeOutEnabled() || + (webRtcControls.showSmallHeader() && largeHeaderAvatar.getVisibility() == View.VISIBLE) || + forceUpdate) + { if (controlsListener != null) { controlsListener.showSystemUI(); } - fadeInNewUiState(lastVisibleSet, webRtcControls.displaySmallOngoingCallButtons()); + throttledDebouncer.publish(() -> fadeInNewUiState(webRtcControls.displaySmallOngoingCallButtons(), webRtcControls.showSmallHeader())); } onWindowSystemUiVisibilityChanged(getWindowSystemUiVisibility()); @@ -660,18 +696,6 @@ public class WebRtcCallView extends ConstraintLayout { } } - private void setShowParticipantsState(boolean isFolded) { - MenuItem item = toolbar.getMenu().findItem(R.id.menu_group_call_participants_list); - - if (item != null) { - View showParticipants = item.getActionView(); - showParticipants.animate().alpha(isFolded ? 0f : 1f); - showParticipants.setClickable(!isFolded); - foldParticipantCountWrapper.animate().alpha(isFolded ? 1f : 0f); - foldParticipantCount.setClickable(isFolded); - } - } - private void expandPip(@NonNull CallParticipant localCallParticipant, @NonNull CallParticipant focusedParticipant) { pictureInPictureExpansionHelper.expand(smallLocalRenderFrame, new PictureInPictureExpansionHelper.Callback() { @Override @@ -857,16 +881,15 @@ public class WebRtcCallView extends ConstraintLayout { } } - private void fadeInNewUiState(@NonNull Set previouslyVisibleViewSet, boolean useSmallMargins) { + private void fadeInNewUiState(boolean useSmallMargins, boolean showSmallHeader) { Transition transition = new AutoTransition().setDuration(TRANSITION_DURATION_MILLIS); - TransitionManager.endTransitions(parent); TransitionManager.beginDelayedTransition(parent, transition); ConstraintSet constraintSet = new ConstraintSet(); constraintSet.clone(parent); - for (View view : SetUtil.difference(previouslyVisibleViewSet, visibleViewSet)) { + for (View view : SetUtil.difference(allTimeVisibleViews, visibleViewSet)) { constraintSet.setVisibility(view.getId(), ConstraintSet.GONE); } @@ -884,6 +907,10 @@ public class WebRtcCallView extends ConstraintLayout { adjustParticipantsRecycler(constraintSet); constraintSet.applyTo(parent); + + if (showSmallHeader) { + smallHeaderConstraints.applyTo(toolbar); + } } private void adjustParticipantsRecycler(@NonNull ConstraintSet constraintSet) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcControls.java b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcControls.java index dc5ff41f54..66b137aedb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcControls.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/WebRtcControls.java @@ -112,7 +112,7 @@ public final class WebRtcControls { } boolean displayGroupMembersButton() { - return groupCallState.isAtLeast(GroupCallState.CONNECTING); + return (groupCallState.isAtLeast(GroupCallState.CONNECTING) && hasAtLeastOneRemote) || groupCallState.isAtLeast(GroupCallState.FULL); } boolean displayEndCall() { @@ -175,6 +175,14 @@ public final class WebRtcControls { return audioOutput; } + boolean showSmallHeader() { + return isAtLeastOutgoing(); + } + + boolean showFullScreenShade() { + return isPreJoin() || isIncoming(); + } + private boolean isError() { return callState == CallState.ERROR; } diff --git a/app/src/main/res/drawable/ic_signal_logo_small.xml b/app/src/main/res/drawable/ic_signal_logo_small.xml new file mode 100644 index 0000000000..9db060d48e --- /dev/null +++ b/app/src/main/res/drawable/ic_signal_logo_small.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/show_participants_menu_view.xml b/app/src/main/res/layout/show_participants_menu_view.xml deleted file mode 100644 index 6b59fd4282..0000000000 --- a/app/src/main/res/layout/show_participants_menu_view.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - \ 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 2b90c14717..3cb762cb99 100644 --- a/app/src/main/res/layout/webrtc_call_view.xml +++ b/app/src/main/res/layout/webrtc_call_view.xml @@ -67,6 +67,12 @@ + + + + @@ -197,76 +211,188 @@ android:layout_width="56dp" android:layout_height="56dp" android:layout_marginEnd="16dp" - android:layout_marginBottom="34dp" + android:layout_marginBottom="8dp" android:scaleType="fitXY" android:visibility="gone" - app:layout_constraintBottom_toTopOf="@id/call_screen_start_call_controls" + app:layout_constraintBottom_toTopOf="@id/call_screen_button_labels_barrier" 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" /> + + + + + + + + + + + + - - + app:backgroundTint="@color/core_green" + app:cornerRadius="28dp" /> @@ -421,16 +535,16 @@ android:id="@+id/fold_show_participants_menu_counter_wrapper" android:layout_width="wrap_content" android:layout_height="56dp" - android:alpha="0" android:background="?attr/selectableItemBackground" android:gravity="center" android:minWidth="48dp" android:orientation="horizontal" android:paddingStart="16dp" android:paddingEnd="16dp" + android:visibility="gone" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toBottomOf="@id/fold_top_call_screen_guideline" - tools:background="@color/core_ultramarine"> + app:layout_constraintTop_toBottomOf="@id/call_screen_show_participants_guideline" + tools:visibility="visible"> + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/webrtc_call_view_header_small.xml b/app/src/main/res/layout/webrtc_call_view_header_small.xml new file mode 100644 index 0000000000..aa42d91acd --- /dev/null +++ b/app/src/main/res/layout/webrtc_call_view_header_small.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/webrtc_call_view_toolbar.xml b/app/src/main/res/layout/webrtc_call_view_toolbar.xml deleted file mode 100644 index 7027b7d641..0000000000 --- a/app/src/main/res/layout/webrtc_call_view_toolbar.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - diff --git a/app/src/main/res/menu/group_call.xml b/app/src/main/res/menu/group_call.xml deleted file mode 100644 index 37613907ef..0000000000 --- a/app/src/main/res/menu/group_call.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c448363184..5598c74391 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1401,13 +1401,12 @@ Calling… - Signal voice call… - Signal video call… + Signal Call + Signal Video Call Start Call Join Call Call is full The maximum number of %1$d participants has been reached for this call. Try again later. - \"%1$s\" Group Call View participants Your video is off Reconnecting… @@ -1424,6 +1423,12 @@ %1$s, %2$s, and %3$d others are in this call + Flip + Speaker + Camera + Mute + End call + In this call · %1$d person