From 370cfb65bb948236f4dfc187ac04c2dac0f62052 Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Thu, 16 Feb 2023 16:03:47 +1100 Subject: [PATCH 1/5] WIP: swap video views --- .../securesms/calls/WebRtcCallActivity.kt | 6 ++++++ .../securesms/service/WebRtcCallService.kt | 13 +++++++++++++ .../thoughtcrime/securesms/webrtc/CallManager.kt | 4 ++++ .../securesms/webrtc/CallViewModel.kt | 5 +++++ .../ic_baseline_screen_rotation_alt_24.xml | 10 ++++++++++ app/src/main/res/layout/activity_webrtc.xml | 15 +++++++++++++++ 6 files changed, 53 insertions(+) create mode 100644 app/src/main/res/drawable/ic_baseline_screen_rotation_alt_24.xml diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt index 7e732d1aa..b8901ef77 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt @@ -126,6 +126,12 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { supportActionBar?.setDisplayHomeAsUpEnabled(false) } + binding.localRendererContainer.setOnClickListener { + val swapVideoViewIntent = + WebRtcCallService.swapVideoViews(this, viewModel.videoViewSwapped) + startService(swapVideoViewIntent) + } + binding.microphoneButton.setOnClickListener { val audioEnabledIntent = WebRtcCallService.microphoneIntent(this, !viewModel.microphoneEnabled) diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt b/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt index d09933ab8..13dfa6e8b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt @@ -59,6 +59,7 @@ class WebRtcCallService : Service(), CallManager.WebRtcListener { const val ACTION_LOCAL_HANGUP = "LOCAL_HANGUP" const val ACTION_SET_MUTE_AUDIO = "SET_MUTE_AUDIO" const val ACTION_SET_MUTE_VIDEO = "SET_MUTE_VIDEO" + const val ACTION_SWAP_VIDEO_VIEW = "SWAP_VIDEO_VIEW" const val ACTION_FLIP_CAMERA = "FLIP_CAMERA" const val ACTION_UPDATE_AUDIO = "UPDATE_AUDIO" const val ACTION_WIRED_HEADSET_CHANGE = "WIRED_HEADSET_CHANGE" @@ -78,6 +79,7 @@ class WebRtcCallService : Service(), CallManager.WebRtcListener { const val EXTRA_RECIPIENT_ADDRESS = "RECIPIENT_ID" const val EXTRA_ENABLED = "ENABLED" const val EXTRA_AUDIO_COMMAND = "AUDIO_COMMAND" + const val EXTRA_SWAPPED = "is_video_swapped" const val EXTRA_MUTE = "mute_value" const val EXTRA_AVAILABLE = "enabled_value" const val EXTRA_REMOTE_DESCRIPTION = "remote_description" @@ -105,6 +107,11 @@ class WebRtcCallService : Service(), CallManager.WebRtcListener { fun acceptCallIntent(context: Context) = Intent(context, WebRtcCallService::class.java) .setAction(ACTION_ANSWER_CALL) + fun swapVideoViews(context: Context, swapped: Boolean) = + Intent(context, WebRtcCallService::class.java) + .setAction(ACTION_SWAP_VIDEO_VIEW) + .putExtra(EXTRA_SWAPPED, swapped) + fun microphoneIntent(context: Context, enabled: Boolean) = Intent(context, WebRtcCallService::class.java) .setAction(ACTION_SET_MUTE_AUDIO) @@ -285,6 +292,7 @@ class WebRtcCallService : Service(), CallManager.WebRtcListener { action == ACTION_DENY_CALL -> handleDenyCall(intent) action == ACTION_LOCAL_HANGUP -> handleLocalHangup(intent) action == ACTION_REMOTE_HANGUP -> handleRemoteHangup(intent) + action == ACTION_SWAP_VIDEO_VIEW ->handleSwapVideoView(intent) action == ACTION_SET_MUTE_AUDIO -> handleSetMuteAudio(intent) action == ACTION_SET_MUTE_VIDEO -> handleSetMuteVideo(intent) action == ACTION_FLIP_CAMERA -> handleSetCameraFlip(intent) @@ -580,6 +588,11 @@ class WebRtcCallService : Service(), CallManager.WebRtcListener { onHangup() } + private fun handleSwapVideoView(intent: Intent) { + val swapped = intent.getBooleanExtra(EXTRA_SWAPPED, false) + callManager.handleSwapVideoView(swapped) + } + private fun handleSetMuteAudio(intent: Intent) { val muted = intent.getBooleanExtra(EXTRA_MUTE, false) callManager.handleSetMuteAudio(muted) diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt index b7a9b6fd6..ed6bc94c6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt @@ -590,6 +590,10 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va } } + fun handleSwapVideoView(swapped: Boolean) { + + } + fun handleSetMuteAudio(muted: Boolean) { _audioEvents.value = AudioEnabled(!muted) peerConnection?.setAudioEnabled(!muted) diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt index 4f27e5d1a..4142a2b34 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt @@ -40,6 +40,11 @@ class CallViewModel @Inject constructor(private val callManager: CallManager): V val videoEnabled: Boolean get() = _videoEnabled + private var _videoViewSwapped: Boolean = false + + val videoViewSwapped: Boolean + get() = _videoViewSwapped + private var _microphoneEnabled: Boolean = true val microphoneEnabled: Boolean diff --git a/app/src/main/res/drawable/ic_baseline_screen_rotation_alt_24.xml b/app/src/main/res/drawable/ic_baseline_screen_rotation_alt_24.xml new file mode 100644 index 000000000..553db9c08 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_screen_rotation_alt_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/activity_webrtc.xml b/app/src/main/res/layout/activity_webrtc.xml index e497456e6..8dcb3fff0 100644 --- a/app/src/main/res/layout/activity_webrtc.xml +++ b/app/src/main/res/layout/activity_webrtc.xml @@ -111,6 +111,7 @@ android:layout_height="wrap_content"/> + + Date: Mon, 20 Feb 2023 16:58:27 +1100 Subject: [PATCH 2/5] feat: swap video views --- .../securesms/calls/WebRtcCallActivity.kt | 31 ++++++++++++--- .../securesms/webrtc/CallManager.kt | 38 +++++++++++++++++-- .../securesms/webrtc/CallViewModel.kt | 11 ++++++ .../securesms/webrtc/PeerConnectionWrapper.kt | 2 +- app/src/main/res/layout/activity_webrtc.xml | 15 +++++++- 5 files changed, 86 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt index b8901ef77..998e362e8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt @@ -126,7 +126,7 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { supportActionBar?.setDisplayHomeAsUpEnabled(false) } - binding.localRendererContainer.setOnClickListener { + binding.floatingRendererContainer.setOnClickListener { val swapVideoViewIntent = WebRtcCallService.swapVideoViews(this, viewModel.videoViewSwapped) startService(swapVideoViewIntent) @@ -341,14 +341,20 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { launch { viewModel.localVideoEnabledState.collect { isEnabled -> + binding.localFloatingRenderer.removeAllViews() binding.localRenderer.removeAllViews() if (isEnabled) { viewModel.localRenderer?.let { surfaceView -> - surfaceView.setZOrderOnTop(true) binding.localRenderer.addView(surfaceView) } + viewModel.localFloatingRenderer?.let { surfaceView -> + surfaceView.setZOrderOnTop(true) + binding.localFloatingRenderer.addView(surfaceView) + + } } - binding.localRenderer.isVisible = isEnabled + binding.localFloatingRenderer.isVisible = isEnabled && !viewModel.videoViewSwapped + binding.localRenderer.isVisible = isEnabled && viewModel.videoViewSwapped binding.enableCameraButton.isSelected = isEnabled } } @@ -356,13 +362,27 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { launch { viewModel.remoteVideoEnabledState.collect { isEnabled -> binding.remoteRenderer.removeAllViews() + binding.remoteFloatingRenderer.removeAllViews() if (isEnabled) { viewModel.remoteRenderer?.let { surfaceView -> binding.remoteRenderer.addView(surfaceView) } + viewModel.remoteFloatingRenderer?.let { surfaceView -> + surfaceView.setZOrderOnTop(true) + binding.remoteFloatingRenderer.addView(surfaceView) + } } - binding.remoteRenderer.isVisible = isEnabled - binding.remoteRecipient.isVisible = !isEnabled + binding.remoteRenderer.isVisible = isEnabled && !viewModel.videoViewSwapped + binding.remoteFloatingRenderer.isVisible = isEnabled && viewModel.videoViewSwapped + } + } + + launch { + viewModel.videoViewSwappedState.collect{ isSwapped -> + binding.remoteRenderer.isVisible = !isSwapped + binding.remoteFloatingRenderer.isVisible = isSwapped + binding.localFloatingRenderer.isVisible = !isSwapped + binding.localRenderer.isVisible = isSwapped } } } @@ -377,6 +397,7 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { override fun onStop() { super.onStop() uiJob?.cancel() + binding.remoteFloatingRenderer.removeAllViews() binding.remoteRenderer.removeAllViews() binding.localRenderer.removeAllViews() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt index ed6bc94c6..9e6847c42 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt @@ -3,7 +3,10 @@ package org.thoughtcrime.securesms.webrtc import android.content.Context import android.content.pm.PackageManager import android.telephony.TelephonyManager +import android.view.SurfaceView +import android.view.View import androidx.core.content.ContextCompat +import androidx.core.view.isVisible import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.serialization.json.Json @@ -28,6 +31,7 @@ import org.thoughtcrime.securesms.webrtc.CallManager.StateEvent.AudioDeviceUpdat import org.thoughtcrime.securesms.webrtc.CallManager.StateEvent.AudioEnabled import org.thoughtcrime.securesms.webrtc.CallManager.StateEvent.RecipientUpdate import org.thoughtcrime.securesms.webrtc.CallManager.StateEvent.VideoEnabled +import org.thoughtcrime.securesms.webrtc.CallManager.StateEvent.VideoSwapped import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCompat import org.thoughtcrime.securesms.webrtc.audio.OutgoingRinger import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager @@ -60,6 +64,7 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va SignalAudioManager.EventListener, CameraEventListener, DataChannel.Observer { sealed class StateEvent { + data class VideoSwapped(val isSwapped: Boolean): StateEvent() data class AudioEnabled(val isEnabled: Boolean): StateEvent() data class VideoEnabled(val isEnabled: Boolean): StateEvent() data class CallStateUpdate(val state: CallState): StateEvent() @@ -98,6 +103,8 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va val videoEvents = _videoEvents.asSharedFlow() private val _remoteVideoEvents = MutableStateFlow(VideoEnabled(false)) val remoteVideoEvents = _remoteVideoEvents.asSharedFlow() + private val _videoViewSwappedEvents = MutableStateFlow(VideoSwapped(false)) + val videoViewSwappedEvents = _videoViewSwappedEvents.asSharedFlow() private val stateProcessor = StateProcessor(CallState.Idle) @@ -141,8 +148,10 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va private val outgoingIceDebouncer = Debouncer(200L) var localRenderer: SurfaceViewRenderer? = null + var localFloatingRenderer: SurfaceViewRenderer? = null var remoteRotationSink: RemoteRotationVideoProxySink? = null var remoteRenderer: SurfaceViewRenderer? = null + var remoteFloatingRenderer: SurfaceViewRenderer? = null private var peerConnectionFactory: PeerConnectionFactory? = null fun clearPendingIceUpdates() { @@ -209,15 +218,26 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va // setScalingType(SCALE_ASPECT_FIT) } + localFloatingRenderer = SurfaceViewRenderer(context).apply { +// setScalingType(SCALE_ASPECT_FIT) + } remoteRenderer = SurfaceViewRenderer(context).apply { // setScalingType(SCALE_ASPECT_FIT) } + + remoteFloatingRenderer = SurfaceViewRenderer(context).apply { +// setScalingType(SCALE_ASPECT_FIT) + } + remoteRotationSink = RemoteRotationVideoProxySink() localRenderer?.init(base.eglBaseContext, null) localRenderer?.setMirror(localCameraState.activeDirection == CameraState.Direction.FRONT) + localFloatingRenderer?.init(base.eglBaseContext, null) + localFloatingRenderer?.setMirror(localCameraState.activeDirection == CameraState.Direction.FRONT) remoteRenderer?.init(base.eglBaseContext, null) + remoteFloatingRenderer?.init(base.eglBaseContext, null) remoteRotationSink!!.setSink(remoteRenderer!!) val encoderFactory = DefaultVideoEncoderFactory(base.eglBaseContext, true, true) @@ -372,12 +392,16 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va peerConnection?.dispose() peerConnection = null + localFloatingRenderer?.release() localRenderer?.release() remoteRotationSink?.release() + remoteFloatingRenderer?.release() remoteRenderer?.release() eglBase?.release() + localFloatingRenderer = null localRenderer = null + remoteFloatingRenderer = null remoteRenderer = null eglBase = null @@ -390,6 +414,7 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va _audioEvents.value = AudioEnabled(false) _videoEvents.value = VideoEnabled(false) _remoteVideoEvents.value = VideoEnabled(false) + _videoViewSwappedEvents.value = VideoSwapped(false) pendingOutgoingIceUpdates.clear() pendingIncomingIceUpdates.clear() } @@ -455,7 +480,7 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va val recipient = recipient ?: return Promise.ofFail(NullPointerException("recipient is null")) val offer = pendingOffer ?: return Promise.ofFail(NullPointerException("pendingOffer is null")) val factory = peerConnectionFactory ?: return Promise.ofFail(NullPointerException("peerConnectionFactory is null")) - val local = localRenderer ?: return Promise.ofFail(NullPointerException("localRenderer is null")) + val local = localFloatingRenderer ?: return Promise.ofFail(NullPointerException("localRenderer is null")) val base = eglBase ?: return Promise.ofFail(NullPointerException("eglBase is null")) val connection = PeerConnectionWrapper( context, @@ -500,7 +525,7 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va ?: return Promise.ofFail(NullPointerException("recipient is null")) val factory = peerConnectionFactory ?: return Promise.ofFail(NullPointerException("peerConnectionFactory is null")) - val local = localRenderer + val local = localFloatingRenderer ?: return Promise.ofFail(NullPointerException("localRenderer is null")) val base = eglBase ?: return Promise.ofFail(NullPointerException("eglBase is null")) @@ -591,7 +616,14 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va } fun handleSwapVideoView(swapped: Boolean) { - + _videoViewSwappedEvents.value = VideoSwapped(!swapped) + if (!swapped) { + peerConnection?.rotationVideoSink?.setSink(localRenderer) + remoteRotationSink?.setSink(remoteFloatingRenderer!!) + } else { + peerConnection?.rotationVideoSink?.setSink(localFloatingRenderer) + remoteRotationSink?.setSink(remoteRenderer!!) + } } fun handleSetMuteAudio(muted: Boolean) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt index 4142a2b34..bc974a725 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt @@ -32,9 +32,15 @@ class CallViewModel @Inject constructor(private val callManager: CallManager): V val localRenderer: SurfaceViewRenderer? get() = callManager.localRenderer + val localFloatingRenderer: SurfaceViewRenderer? + get() = callManager.localFloatingRenderer + val remoteRenderer: SurfaceViewRenderer? get() = callManager.remoteRenderer + val remoteFloatingRenderer: SurfaceViewRenderer? + get() = callManager.remoteFloatingRenderer + private var _videoEnabled: Boolean = false val videoEnabled: Boolean @@ -72,6 +78,11 @@ class CallViewModel @Inject constructor(private val callManager: CallManager): V val remoteVideoEnabledState get() = callManager.remoteVideoEvents.map { it.isEnabled } + val videoViewSwappedState + get() = callManager.videoViewSwappedEvents + .map { it.isSwapped } + .onEach { _videoViewSwapped = it } + var deviceRotation: Int = 0 set(value) { field = value diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/PeerConnectionWrapper.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/PeerConnectionWrapper.kt index 26d8fc223..03f69f46e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/PeerConnectionWrapper.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/PeerConnectionWrapper.kt @@ -41,7 +41,7 @@ class PeerConnectionWrapper(private val context: Context, private val mediaStream: MediaStream private val videoSource: VideoSource? private val videoTrack: VideoTrack? - private val rotationVideoSink = RotationVideoSink() + public val rotationVideoSink = RotationVideoSink() val readyForIce get() = peerConnection?.localDescription != null && peerConnection?.remoteDescription != null diff --git a/app/src/main/res/layout/activity_webrtc.xml b/app/src/main/res/layout/activity_webrtc.xml index 8dcb3fff0..70c1b92c8 100644 --- a/app/src/main/res/layout/activity_webrtc.xml +++ b/app/src/main/res/layout/activity_webrtc.xml @@ -22,6 +22,12 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center"/> + + + Date: Wed, 22 Feb 2023 16:33:39 +1100 Subject: [PATCH 3/5] minor fixes --- .../securesms/calls/WebRtcCallActivity.kt | 12 ++++++++---- .../thoughtcrime/securesms/webrtc/CallViewModel.kt | 9 ++++++++- app/src/main/res/layout/activity_webrtc.xml | 2 ++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt index 998e362e8..dc0262acb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt @@ -356,6 +356,8 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { binding.localFloatingRenderer.isVisible = isEnabled && !viewModel.videoViewSwapped binding.localRenderer.isVisible = isEnabled && viewModel.videoViewSwapped binding.enableCameraButton.isSelected = isEnabled + binding.videocamOffIcon.isVisible = !binding.localFloatingRenderer.isVisible + binding.swapViewIcon.bringToFront() } } @@ -374,15 +376,17 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { } binding.remoteRenderer.isVisible = isEnabled && !viewModel.videoViewSwapped binding.remoteFloatingRenderer.isVisible = isEnabled && viewModel.videoViewSwapped + binding.videocamOffIcon.isVisible = !binding.remoteFloatingRenderer.isVisible + binding.swapViewIcon.bringToFront() } } launch { viewModel.videoViewSwappedState.collect{ isSwapped -> - binding.remoteRenderer.isVisible = !isSwapped - binding.remoteFloatingRenderer.isVisible = isSwapped - binding.localFloatingRenderer.isVisible = !isSwapped - binding.localRenderer.isVisible = isSwapped + binding.remoteRenderer.isVisible = !isSwapped && viewModel.remoteVideoEnabled + binding.remoteFloatingRenderer.isVisible = isSwapped && viewModel.remoteVideoEnabled + binding.localFloatingRenderer.isVisible = !isSwapped && viewModel.videoEnabled + binding.localRenderer.isVisible = isSwapped && viewModel.videoEnabled } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt index bc974a725..c6cfb3788 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallViewModel.kt @@ -46,6 +46,11 @@ class CallViewModel @Inject constructor(private val callManager: CallManager): V val videoEnabled: Boolean get() = _videoEnabled + private var _remoteVideoEnabled: Boolean = false + + val remoteVideoEnabled: Boolean + get() = _remoteVideoEnabled + private var _videoViewSwapped: Boolean = false val videoViewSwapped: Boolean @@ -76,7 +81,9 @@ class CallViewModel @Inject constructor(private val callManager: CallManager): V .onEach { _videoEnabled = it } val remoteVideoEnabledState - get() = callManager.remoteVideoEvents.map { it.isEnabled } + get() = callManager.remoteVideoEvents + .map { it.isEnabled } + .onEach { _remoteVideoEnabled = it } val videoViewSwappedState get() = callManager.videoViewSwappedEvents diff --git a/app/src/main/res/layout/activity_webrtc.xml b/app/src/main/res/layout/activity_webrtc.xml index 70c1b92c8..66affa670 100644 --- a/app/src/main/res/layout/activity_webrtc.xml +++ b/app/src/main/res/layout/activity_webrtc.xml @@ -127,6 +127,7 @@ android:layout_height="0dp" android:layout_width="0dp"> Date: Wed, 22 Feb 2023 16:37:40 +1100 Subject: [PATCH 4/5] minor fix --- .../org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt | 3 +++ app/src/main/res/layout/activity_webrtc.xml | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt index dc0262acb..7ccb063b1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt @@ -356,6 +356,7 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { binding.localFloatingRenderer.isVisible = isEnabled && !viewModel.videoViewSwapped binding.localRenderer.isVisible = isEnabled && viewModel.videoViewSwapped binding.enableCameraButton.isSelected = isEnabled + binding.floatingRendererContainer.isVisible = binding.localFloatingRenderer.isVisible binding.videocamOffIcon.isVisible = !binding.localFloatingRenderer.isVisible binding.swapViewIcon.bringToFront() } @@ -377,6 +378,7 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { binding.remoteRenderer.isVisible = isEnabled && !viewModel.videoViewSwapped binding.remoteFloatingRenderer.isVisible = isEnabled && viewModel.videoViewSwapped binding.videocamOffIcon.isVisible = !binding.remoteFloatingRenderer.isVisible + binding.floatingRendererContainer.isVisible = binding.remoteFloatingRenderer.isVisible binding.swapViewIcon.bringToFront() } } @@ -387,6 +389,7 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { binding.remoteFloatingRenderer.isVisible = isSwapped && viewModel.remoteVideoEnabled binding.localFloatingRenderer.isVisible = !isSwapped && viewModel.videoEnabled binding.localRenderer.isVisible = isSwapped && viewModel.videoEnabled + binding.floatingRendererContainer.isVisible = binding.localFloatingRenderer.isVisible || binding.remoteFloatingRenderer.isVisible } } } diff --git a/app/src/main/res/layout/activity_webrtc.xml b/app/src/main/res/layout/activity_webrtc.xml index 66affa670..3510bb152 100644 --- a/app/src/main/res/layout/activity_webrtc.xml +++ b/app/src/main/res/layout/activity_webrtc.xml @@ -125,7 +125,8 @@ android:layout_marginVertical="@dimen/massive_spacing" app:layout_constraintWidth_percent="0.2" android:layout_height="0dp" - android:layout_width="0dp"> + android:layout_width="0dp" + android:visibility="invisible"> Date: Fri, 24 Feb 2023 15:07:21 +1100 Subject: [PATCH 5/5] minor fix --- .../org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt | 2 ++ app/src/main/res/layout/activity_webrtc.xml | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt index 7ccb063b1..cda8f96cb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt @@ -358,6 +358,7 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { binding.enableCameraButton.isSelected = isEnabled binding.floatingRendererContainer.isVisible = binding.localFloatingRenderer.isVisible binding.videocamOffIcon.isVisible = !binding.localFloatingRenderer.isVisible + binding.remoteRecipient.isVisible = !(binding.remoteRenderer.isVisible || binding.localRenderer.isVisible) binding.swapViewIcon.bringToFront() } } @@ -379,6 +380,7 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { binding.remoteFloatingRenderer.isVisible = isEnabled && viewModel.videoViewSwapped binding.videocamOffIcon.isVisible = !binding.remoteFloatingRenderer.isVisible binding.floatingRendererContainer.isVisible = binding.remoteFloatingRenderer.isVisible + binding.remoteRecipient.isVisible = !(binding.remoteRenderer.isVisible || binding.localRenderer.isVisible) binding.swapViewIcon.bringToFront() } } diff --git a/app/src/main/res/layout/activity_webrtc.xml b/app/src/main/res/layout/activity_webrtc.xml index 3510bb152..ebef19ce5 100644 --- a/app/src/main/res/layout/activity_webrtc.xml +++ b/app/src/main/res/layout/activity_webrtc.xml @@ -126,7 +126,8 @@ app:layout_constraintWidth_percent="0.2" android:layout_height="0dp" android:layout_width="0dp" - android:visibility="invisible"> + android:visibility="invisible" + android:background="@color/black">