Update camera permission UI for voice calls.
This commit is contained in:
parent
a99db2b16e
commit
b36b00a11c
6 changed files with 216 additions and 65 deletions
|
@ -29,13 +29,14 @@ import android.media.AudioManager;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.Rational;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.core.app.PictureInPictureModeChangedInfo;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.util.Consumer;
|
||||
import androidx.lifecycle.LiveDataReactiveStreams;
|
||||
|
@ -116,6 +117,7 @@ import io.reactivex.rxjava3.core.BackpressureStrategy;
|
|||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
|
||||
import static org.thoughtcrime.securesms.components.sensors.Orientation.PORTRAIT_BOTTOM_EDGE;
|
||||
import static org.thoughtcrime.securesms.permissions.PermissionDeniedBottomSheet.showPermissionFragment;
|
||||
|
||||
public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChangeDialog.Callback, ReactWithAnyEmojiBottomSheetDialogFragment.Callback {
|
||||
|
||||
|
@ -165,7 +167,7 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
|
|||
private boolean enterPipOnResume;
|
||||
private long lastProcessedIntentTimestamp;
|
||||
private WebRtcViewModel previousEvent = null;
|
||||
|
||||
private boolean isAskingForPermission;
|
||||
private Disposable ephemeralStateDisposable = Disposable.empty();
|
||||
|
||||
@Override
|
||||
|
@ -237,6 +239,12 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
|
|||
initializePendingParticipantFragmentListener();
|
||||
|
||||
WindowUtil.setNavigationBarColor(this, ContextCompat.getColor(this, R.color.signal_dark_colorSurface));
|
||||
|
||||
if (!hasCameraPermission() & !hasAudioPermission()) {
|
||||
askCameraAudioPermissions(() -> handleSetMuteVideo(false));
|
||||
} else if (!hasAudioPermission()) {
|
||||
askAudioPermissions(() -> {});
|
||||
}
|
||||
}
|
||||
|
||||
private void registerSystemPipChangeListeners() {
|
||||
|
@ -299,7 +307,7 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
|
|||
Log.i(TAG, "onPause");
|
||||
super.onPause();
|
||||
|
||||
if (!viewModel.isCallStarting()) {
|
||||
if (!isAskingForPermission && !viewModel.isCallStarting()) {
|
||||
CallParticipantsState state = viewModel.getCallParticipantsStateSnapshot();
|
||||
if (state != null && state.getCallState().isPreJoinOrNetworkUnavailable()) {
|
||||
finish();
|
||||
|
@ -666,15 +674,8 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
|
|||
Recipient recipient = viewModel.getRecipient().get();
|
||||
|
||||
if (!recipient.equals(Recipient.UNKNOWN)) {
|
||||
String recipientDisplayName = recipient.getDisplayName(this);
|
||||
|
||||
Permissions.with(this)
|
||||
.request(Manifest.permission.CAMERA)
|
||||
.ifNecessary()
|
||||
.withRationaleDialog(getString(R.string.WebRtcCallActivity__to_call_s_signal_needs_access_to_your_camera, recipientDisplayName), R.drawable.ic_video_solid_24_tinted)
|
||||
.withPermanentDenialDialog(getString(R.string.WebRtcCallActivity__to_call_s_signal_needs_access_to_your_camera, recipientDisplayName))
|
||||
.onAllGranted(() -> ApplicationDependencies.getSignalCallManager().setEnableVideo(!muted))
|
||||
.execute();
|
||||
Runnable onGranted = () -> ApplicationDependencies.getSignalCallManager().setEnableVideo(!muted);
|
||||
askCameraPermissions(onGranted);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -683,36 +684,26 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
|
|||
}
|
||||
|
||||
private void handleAnswerWithAudio() {
|
||||
Permissions.with(this)
|
||||
.request(Manifest.permission.RECORD_AUDIO)
|
||||
.ifNecessary()
|
||||
.withRationaleDialog(getString(R.string.WebRtcCallActivity_to_answer_the_call_give_signal_access_to_your_microphone),
|
||||
R.drawable.ic_mic_solid_24)
|
||||
.withPermanentDenialDialog(getString(R.string.WebRtcCallActivity_signal_requires_microphone_and_camera_permissions_in_order_to_make_or_receive_calls))
|
||||
.onAllGranted(() -> {
|
||||
callScreen.setStatus(getString(R.string.RedPhone_answering));
|
||||
|
||||
ApplicationDependencies.getSignalCallManager().acceptCall(false);
|
||||
})
|
||||
.onAnyDenied(this::handleDenyCall)
|
||||
.execute();
|
||||
Runnable onGranted = () -> {
|
||||
callScreen.setStatus(getString(R.string.RedPhone_answering));
|
||||
ApplicationDependencies.getSignalCallManager().acceptCall(false);
|
||||
};
|
||||
askAudioPermissions(onGranted);
|
||||
}
|
||||
|
||||
private void handleAnswerWithVideo() {
|
||||
Permissions.with(this)
|
||||
.request(Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA)
|
||||
.ifNecessary()
|
||||
.withRationaleDialog(getString(R.string.WebRtcCallActivity_to_answer_the_call_give_signal_access_to_your_microphone_and_camera), R.drawable.ic_mic_solid_24, R.drawable.ic_video_solid_24_tinted)
|
||||
.withPermanentDenialDialog(getString(R.string.WebRtcCallActivity_signal_requires_microphone_and_camera_permissions_in_order_to_make_or_receive_calls))
|
||||
.onAllGranted(() -> {
|
||||
callScreen.setStatus(getString(R.string.RedPhone_answering));
|
||||
|
||||
ApplicationDependencies.getSignalCallManager().acceptCall(true);
|
||||
|
||||
handleSetMuteVideo(false);
|
||||
})
|
||||
.onAnyDenied(this::handleDenyCall)
|
||||
.execute();
|
||||
Runnable onGranted = () -> {
|
||||
callScreen.setStatus(getString(R.string.RedPhone_answering));
|
||||
ApplicationDependencies.getSignalCallManager().acceptCall(true);
|
||||
handleSetMuteVideo(false);
|
||||
};
|
||||
if (!hasCameraPermission() &!hasAudioPermission()) {
|
||||
askCameraAudioPermissions(onGranted);
|
||||
} else if (!hasAudioPermission()) {
|
||||
askAudioPermissions(onGranted);
|
||||
} else {
|
||||
askCameraPermissions(onGranted);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDenyCall() {
|
||||
|
@ -996,6 +987,85 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
|
|||
}
|
||||
}
|
||||
|
||||
private boolean hasCameraPermission() {
|
||||
return Permissions.hasAll(this, Manifest.permission.CAMERA);
|
||||
}
|
||||
|
||||
private boolean hasAudioPermission() {
|
||||
return Permissions.hasAll(this, Manifest.permission.RECORD_AUDIO);
|
||||
}
|
||||
|
||||
private void askCameraPermissions(@NonNull Runnable onGranted) {
|
||||
if (!isAskingForPermission) {
|
||||
isAskingForPermission = true;
|
||||
Permissions.with(this)
|
||||
.request(Manifest.permission.CAMERA)
|
||||
.ifNecessary()
|
||||
.withRationaleDialog(getString(R.string.WebRtcCallActivity__allow_access_camera), getString(R.string.WebRtcCallActivity__to_enable_video_allow_camera), false, R.drawable.symbol_video_24)
|
||||
.onAnyResult(() -> isAskingForPermission = false)
|
||||
.onAllGranted(() -> {
|
||||
onGranted.run();
|
||||
findViewById(R.id.missing_permissions_container).setVisibility(View.GONE);
|
||||
})
|
||||
.onAnyDenied(() -> Toast.makeText(this, R.string.WebRtcCallActivity__signal_needs_camera_access_enable_video, Toast.LENGTH_LONG).show())
|
||||
.onAnyPermanentlyDenied(() -> showPermissionFragment(R.string.WebRtcCallActivity__allow_access_camera, R.string.WebRtcCallActivity__to_enable_video).show(getSupportFragmentManager(), BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG))
|
||||
.execute();
|
||||
}
|
||||
}
|
||||
|
||||
private void askAudioPermissions(@NonNull Runnable onGranted) {
|
||||
if (!isAskingForPermission) {
|
||||
isAskingForPermission = true;
|
||||
Permissions.with(this)
|
||||
.request(Manifest.permission.RECORD_AUDIO)
|
||||
.ifNecessary()
|
||||
.withRationaleDialog(getString(R.string.WebRtcCallActivity__allow_access_microphone), getString(R.string.WebRtcCallActivity__to_start_call_microphone), false, R.drawable.ic_mic_24)
|
||||
.onAnyResult(() -> isAskingForPermission = false)
|
||||
.onAllGranted(onGranted)
|
||||
.onAnyDenied(() -> {
|
||||
Toast.makeText(this, R.string.WebRtcCallActivity__signal_needs_microphone_start_call, Toast.LENGTH_LONG).show();
|
||||
handleDenyCall();
|
||||
})
|
||||
.onAnyPermanentlyDenied(() -> showPermissionFragment(R.string.WebRtcCallActivity__allow_access_microphone, R.string.WebRtcCallActivity__to_start_call).show(getSupportFragmentManager(), BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG))
|
||||
.execute();
|
||||
}
|
||||
}
|
||||
|
||||
public void askCameraAudioPermissions(@NonNull Runnable onGranted) {
|
||||
if (!isAskingForPermission) {
|
||||
isAskingForPermission = true;
|
||||
Permissions.with(this)
|
||||
.request(Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA)
|
||||
.ifNecessary()
|
||||
.withRationaleDialog(getString(R.string.WebRtcCallActivity__allow_access_camera_microphone), getString(R.string.WebRtcCallActivity__to_start_call_camera_microphone), false, R.drawable.ic_mic_24, R.drawable.symbol_video_24)
|
||||
.onAnyResult(() -> isAskingForPermission = false)
|
||||
.onSomePermanentlyDenied(deniedPermissions -> {
|
||||
if (deniedPermissions.containsAll(List.of(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO))) {
|
||||
showPermissionFragment(R.string.WebRtcCallActivity__allow_access_camera_microphone, R.string.WebRtcCallActivity__to_start_call).show(getSupportFragmentManager(), BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG);
|
||||
} else if (deniedPermissions.contains(Manifest.permission.CAMERA)) {
|
||||
showPermissionFragment(R.string.WebRtcCallActivity__allow_access_camera, R.string.WebRtcCallActivity__to_enable_video).show(getSupportFragmentManager(), BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG);
|
||||
} else {
|
||||
showPermissionFragment(R.string.WebRtcCallActivity__allow_access_microphone, R.string.WebRtcCallActivity__to_start_call).show(getSupportFragmentManager(), BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG);
|
||||
}
|
||||
})
|
||||
.onAllGranted(onGranted)
|
||||
.onSomeGranted(permissions -> {
|
||||
if (permissions.contains(Manifest.permission.CAMERA)) {
|
||||
findViewById(R.id.missing_permissions_container).setVisibility(View.GONE);
|
||||
}
|
||||
})
|
||||
.onSomeDenied(deniedPermissions -> {
|
||||
if (deniedPermissions.contains(Manifest.permission.RECORD_AUDIO)) {
|
||||
Toast.makeText(this, R.string.WebRtcCallActivity__signal_needs_microphone_start_call, Toast.LENGTH_LONG).show();
|
||||
handleDenyCall();
|
||||
} else {
|
||||
Toast.makeText(this, R.string.WebRtcCallActivity__signal_needs_camera_access_enable_video, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
})
|
||||
.execute();
|
||||
}
|
||||
}
|
||||
|
||||
private void startCall(boolean isVideoCall) {
|
||||
enableVideoIfAvailable = isVideoCall;
|
||||
|
||||
|
@ -1037,6 +1107,11 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAudioPermissionsRequested(Runnable onGranted) {
|
||||
askAudioPermissions(onGranted);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAudioOutputChanged(@NonNull WebRtcAudioOutput audioOutput) {
|
||||
maybeDisplaySpeakerphonePopup(audioOutput);
|
||||
|
@ -1072,9 +1147,12 @@ 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);
|
||||
Runnable onGranted = () -> {
|
||||
callStateUpdatePopupWindow.onCallStateUpdate(isMicEnabled ? CallStateUpdatePopupWindow.CallStateUpdate.MIC_ON
|
||||
: CallStateUpdatePopupWindow.CallStateUpdate.MIC_OFF);
|
||||
handleSetMuteAudio(!isMicEnabled);
|
||||
};
|
||||
askAudioPermissions(onGranted);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
package org.thoughtcrime.securesms.components.webrtc;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
|
@ -54,6 +55,7 @@ import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto;
|
|||
import org.thoughtcrime.securesms.events.CallParticipant;
|
||||
import org.thoughtcrime.securesms.events.WebRtcViewModel;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.ringrtc.CameraState;
|
||||
|
@ -127,6 +129,8 @@ public class WebRtcCallView extends InsetAwareConstraintLayout {
|
|||
private MultiReactionBurstLayout reactionViews;
|
||||
private ComposeView raiseHandSnackbar;
|
||||
private Barrier pipBottomBoundaryBarrier;
|
||||
private View missingPermissionContainer;
|
||||
private MaterialButton allowAccessButton;
|
||||
|
||||
|
||||
|
||||
|
@ -207,6 +211,8 @@ public class WebRtcCallView extends InsetAwareConstraintLayout {
|
|||
reactionViews = findViewById(R.id.call_screen_reactions_container);
|
||||
raiseHandSnackbar = findViewById(R.id.call_screen_raise_hand_view);
|
||||
pipBottomBoundaryBarrier = findViewById(R.id.pip_bottom_boundary_barrier);
|
||||
missingPermissionContainer = findViewById(R.id.missing_permissions_container);
|
||||
allowAccessButton = findViewById(R.id.allow_access_button);
|
||||
|
||||
View decline = findViewById(R.id.call_screen_decline_call);
|
||||
View answerLabel = findViewById(R.id.call_screen_answer_call_label);
|
||||
|
@ -262,10 +268,16 @@ public class WebRtcCallView extends InsetAwareConstraintLayout {
|
|||
});
|
||||
|
||||
videoToggle.setOnCheckedChangeListener((v, isOn) -> {
|
||||
if (!hasCameraPermission()) {
|
||||
videoToggle.setChecked(false);
|
||||
}
|
||||
runIfNonNull(controlsListener, listener -> listener.onVideoChanged(isOn));
|
||||
});
|
||||
|
||||
micToggle.setOnCheckedChangeListener((v, isOn) -> {
|
||||
if (!hasAudioPermission()) {
|
||||
micToggle.setChecked(false);
|
||||
}
|
||||
runIfNonNull(controlsListener, listener -> listener.onMicChanged(isOn));
|
||||
});
|
||||
|
||||
|
@ -301,10 +313,13 @@ public class WebRtcCallView extends InsetAwareConstraintLayout {
|
|||
ViewUtil.setBottomMargin(smallLocalAudioIndicator, audioIndicatorMargin);
|
||||
|
||||
startCall.setOnClickListener(v -> {
|
||||
if (controlsListener != null) {
|
||||
startCall.setEnabled(false);
|
||||
controlsListener.onStartCall(videoToggle.isChecked());
|
||||
}
|
||||
Runnable onGranted = () -> {
|
||||
if (controlsListener != null) {
|
||||
startCall.setEnabled(false);
|
||||
controlsListener.onStartCall(videoToggle.isChecked());
|
||||
}
|
||||
};
|
||||
runIfNonNull(controlsListener, listener -> listener.onAudioPermissionsRequested(onGranted));
|
||||
});
|
||||
|
||||
ColorMatrix greyScaleMatrix = new ColorMatrix();
|
||||
|
@ -365,6 +380,12 @@ public class WebRtcCallView extends InsetAwareConstraintLayout {
|
|||
onBarrierBottomChanged(bottom);
|
||||
}
|
||||
});
|
||||
|
||||
missingPermissionContainer.setVisibility(hasCameraPermission() ? View.GONE : View.VISIBLE);
|
||||
|
||||
allowAccessButton.setOnClickListener(v -> {
|
||||
runIfNonNull(controlsListener, listener -> listener.onVideoChanged(videoToggle.isEnabled()));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -405,7 +426,7 @@ public class WebRtcCallView extends InsetAwareConstraintLayout {
|
|||
}
|
||||
|
||||
public void setMicEnabled(boolean isMicEnabled) {
|
||||
micToggle.setChecked(isMicEnabled, false);
|
||||
micToggle.setChecked(hasAudioPermission() && isMicEnabled, false);
|
||||
}
|
||||
|
||||
public void setPendingParticipantsViewListener(@Nullable PendingParticipantsView.Listener listener) {
|
||||
|
@ -424,6 +445,14 @@ public class WebRtcCallView extends InsetAwareConstraintLayout {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean hasCameraPermission() {
|
||||
return Permissions.hasAll(getContext(), Manifest.permission.CAMERA);
|
||||
}
|
||||
|
||||
private boolean hasAudioPermission() {
|
||||
return Permissions.hasAll(getContext(), Manifest.permission.RECORD_AUDIO);
|
||||
}
|
||||
|
||||
public void updateCallParticipants(@NonNull CallParticipantsViewState callParticipantsViewState) {
|
||||
lastState = callParticipantsViewState;
|
||||
|
||||
|
@ -503,7 +532,7 @@ public class WebRtcCallView extends InsetAwareConstraintLayout {
|
|||
});
|
||||
|
||||
|
||||
videoToggle.setChecked(localCallParticipant.isVideoEnabled(), false);
|
||||
videoToggle.setChecked(hasCameraPermission() && localCallParticipant.isVideoEnabled(), false);
|
||||
smallLocalRender.setRenderInPip(true);
|
||||
smallLocalRender.setCallParticipant(localCallParticipant);
|
||||
smallLocalRender.setMirror(localCallParticipant.getCameraDirection() == CameraState.Direction.FRONT);
|
||||
|
@ -984,5 +1013,6 @@ public class WebRtcCallView extends InsetAwareConstraintLayout {
|
|||
void onCallInfoClicked();
|
||||
void onNavigateUpClicked();
|
||||
void toggleControls();
|
||||
void onAudioPermissionsRequested(Runnable onGranted);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,6 +113,10 @@ public class Permissions {
|
|||
return withRationaleDialog(null, title, details, true, headers);
|
||||
}
|
||||
|
||||
public PermissionsBuilder withRationaleDialog(@NonNull String title, @NonNull String details, boolean cancelable, @NonNull @DrawableRes int... headers) {
|
||||
return withRationaleDialog(null, title, details, cancelable, headers);
|
||||
}
|
||||
|
||||
public PermissionsBuilder withRationaleDialog(@Nullable String message, @Nullable String title, @Nullable String details, boolean cancelable, @NonNull @DrawableRes int... headers) {
|
||||
this.rationalDialogHeader = headers;
|
||||
this.rationaleDialogMessage = message;
|
||||
|
|
|
@ -406,25 +406,15 @@ public class CommunicationActions {
|
|||
}
|
||||
|
||||
private static void startVideoCallInternal(@NonNull CallContext callContext, @NonNull Recipient recipient, boolean fromCallLink) {
|
||||
callContext.getPermissionsBuilder()
|
||||
.request(Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA)
|
||||
.ifNecessary()
|
||||
.withRationaleDialog(callContext.getContext().getString(R.string.ConversationActivity_signal_needs_the_microphone_and_camera_permissions_in_order_to_call_s, recipient.getDisplayName(callContext.getContext())),
|
||||
R.drawable.ic_mic_solid_24,
|
||||
R.drawable.ic_video_solid_24_tinted)
|
||||
.withPermanentDenialDialog(callContext.getContext().getString(R.string.ConversationActivity_signal_needs_the_microphone_and_camera_permissions_in_order_to_call_s, recipient.getDisplayName(callContext.getContext())))
|
||||
.onAllGranted(() -> {
|
||||
ApplicationDependencies.getSignalCallManager().startPreJoinCall(recipient);
|
||||
ApplicationDependencies.getSignalCallManager().startPreJoinCall(recipient);
|
||||
|
||||
Intent activityIntent = new Intent(callContext.getContext(), WebRtcCallActivity.class);
|
||||
Intent activityIntent = new Intent(callContext.getContext(), WebRtcCallActivity.class);
|
||||
|
||||
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra(WebRtcCallActivity.EXTRA_ENABLE_VIDEO_IF_AVAILABLE, true)
|
||||
.putExtra(WebRtcCallActivity.EXTRA_STARTED_FROM_CALL_LINK, fromCallLink);
|
||||
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra(WebRtcCallActivity.EXTRA_ENABLE_VIDEO_IF_AVAILABLE, true)
|
||||
.putExtra(WebRtcCallActivity.EXTRA_STARTED_FROM_CALL_LINK, fromCallLink);
|
||||
|
||||
callContext.startActivity(activityIntent);
|
||||
})
|
||||
.execute();
|
||||
callContext.startActivity(activityIntent);
|
||||
}
|
||||
|
||||
private static void handleE164Link(Activity activity, String e164) {
|
||||
|
|
|
@ -64,10 +64,39 @@
|
|||
android:gravity="center_horizontal"
|
||||
android:textAppearance="@style/Signal.Text.BodyMedium"
|
||||
android:textColor="@color/core_white"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/call_screen_recipient_name"
|
||||
tools:text="Signal Calling..." />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/missing_permissions_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/call_screen_status"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/missing_permissions_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
style="@style/Signal.Text.Body"
|
||||
android:text="@string/WebRtcCallActivity__to_enable_video_allow_camera" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/allow_access_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
style="@style/Signal.Widget.Button.Large.Tonal"
|
||||
android:text="@string/CameraXFragment_allow_access" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -1936,6 +1936,26 @@
|
|||
<string name="WebRtcCallActivity__removed_from_call">Removed from call</string>
|
||||
<!-- Message of dialog displayed when a user is removed from a call link -->
|
||||
<string name="WebRtcCallActivity__someone_has_removed_you_from_the_call">Someone has removed you from the call.</string>
|
||||
<!-- Dialog title asking users for camera and microphone permission -->
|
||||
<string name="WebRtcCallActivity__allow_access_camera_microphone">Allow access to your camera and microphone</string>
|
||||
<!-- Dialog title asking users for microphone permission -->
|
||||
<string name="WebRtcCallActivity__allow_access_microphone">Allow access to your microphone</string>
|
||||
<!-- Dialog title asking users for camera permission -->
|
||||
<string name="WebRtcCallActivity__allow_access_camera">Allow access to your camera</string>
|
||||
<!-- Dialog description explaining why camera and microphone permissions are needed to start or join a call -->
|
||||
<string name="WebRtcCallActivity__to_start_call_camera_microphone">To start or join a call, allow Signal access to your camera and microphone.</string>
|
||||
<!-- Dialog description explaining why microphone permissions are needed to start or join a call -->
|
||||
<string name="WebRtcCallActivity__to_start_call_microphone">To start or join a call, allow Signal access to your microphone.</string>
|
||||
<!-- Dialog description explaining why camera permissions are needed to enable a user's video in a call -->
|
||||
<string name="WebRtcCallActivity__to_enable_video_allow_camera">To enable your video, allow Signal access to your camera.</string>
|
||||
<!-- Toast describing why microphone permissions are needed to start or join a call -->
|
||||
<string name="WebRtcCallActivity__signal_needs_microphone_start_call">Signal needs microphone permissions to start or join a call.</string>
|
||||
<!-- Toast describing why camera permissions are needed to enable a video in a call -->
|
||||
<string name="WebRtcCallActivity__signal_needs_camera_access_enable_video">Signal needs camera access to enable your video</string>
|
||||
<!-- Dialog description that will explain the steps needed to give microphone permissions -->
|
||||
<string name="WebRtcCallActivity__to_start_call">To start or join a call:</string>
|
||||
<!-- Dialog description that will explain the steps needed to give camera permissions -->
|
||||
<string name="WebRtcCallActivity__to_enable_video">To enable your video:</string>
|
||||
|
||||
<!-- WebRtcCallView -->
|
||||
<string name="WebRtcCallView__signal_call">Signal Call</string>
|
||||
|
|
Loading…
Add table
Reference in a new issue