From ab2a55d417c2f910e47b6dcd996564fe06c2dd49 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 11 Sep 2020 16:24:30 +0200 Subject: [PATCH 1/7] Rename member for code clarity (we also have an AudioManager) --- .../app/features/call/VectorCallViewModel.kt | 12 +++++------ .../call/WebRtcPeerConnectionManager.kt | 20 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt index cee67cd818..97a6f72177 100644 --- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt @@ -146,7 +146,7 @@ class VectorCallViewModel @AssistedInject constructor( } override fun onAudioDevicesChange(mgr: WebRtcPeerConnectionManager) { - val currentSoundDevice = mgr.audioManager.getCurrentSoundDevice() + val currentSoundDevice = mgr.callAudioManager.getCurrentSoundDevice() if (currentSoundDevice == CallAudioManager.SoundDevice.PHONE) { proximityManager.start() } else { @@ -155,7 +155,7 @@ class VectorCallViewModel @AssistedInject constructor( setState { copy( - availableSoundDevices = mgr.audioManager.getAvailableSoundDevices(), + availableSoundDevices = mgr.callAudioManager.getAvailableSoundDevices(), soundDevice = currentSoundDevice ) } @@ -182,7 +182,7 @@ class VectorCallViewModel @AssistedInject constructor( mxCall.addListener(callStateListener) - val currentSoundDevice = webRtcPeerConnectionManager.audioManager.getCurrentSoundDevice() + val currentSoundDevice = webRtcPeerConnectionManager.callAudioManager.getCurrentSoundDevice() if (currentSoundDevice == CallAudioManager.SoundDevice.PHONE) { proximityManager.start() } @@ -193,7 +193,7 @@ class VectorCallViewModel @AssistedInject constructor( callState = Success(mxCall.state), otherUserMatrixItem = item?.let { Success(it) } ?: Uninitialized, soundDevice = currentSoundDevice, - availableSoundDevices = webRtcPeerConnectionManager.audioManager.getAvailableSoundDevices(), + availableSoundDevices = webRtcPeerConnectionManager.callAudioManager.getAvailableSoundDevices(), isFrontCamera = webRtcPeerConnectionManager.currentCameraType() == CameraType.FRONT, canSwitchCamera = webRtcPeerConnectionManager.canSwitchCamera(), isHD = mxCall.isVideoCall && webRtcPeerConnectionManager.currentCaptureFormat() is CaptureFormat.HD @@ -250,10 +250,10 @@ class VectorCallViewModel @AssistedInject constructor( Unit } is VectorCallViewActions.ChangeAudioDevice -> { - webRtcPeerConnectionManager.audioManager.setCurrentSoundDevice(action.device) + webRtcPeerConnectionManager.callAudioManager.setCurrentSoundDevice(action.device) setState { copy( - soundDevice = webRtcPeerConnectionManager.audioManager.getCurrentSoundDevice() + soundDevice = webRtcPeerConnectionManager.callAudioManager.getCurrentSoundDevice() ) } } diff --git a/vector/src/main/java/im/vector/app/features/call/WebRtcPeerConnectionManager.kt b/vector/src/main/java/im/vector/app/features/call/WebRtcPeerConnectionManager.kt index b53be292c8..916df8892b 100644 --- a/vector/src/main/java/im/vector/app/features/call/WebRtcPeerConnectionManager.kt +++ b/vector/src/main/java/im/vector/app/features/call/WebRtcPeerConnectionManager.kt @@ -23,6 +23,9 @@ import im.vector.app.ActiveSessionDataSource import im.vector.app.core.services.BluetoothHeadsetReceiver import im.vector.app.core.services.CallService import im.vector.app.core.services.WiredHeadsetStateReceiver +import io.reactivex.disposables.Disposable +import io.reactivex.subjects.PublishSubject +import io.reactivex.subjects.ReplaySubject import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.extensions.tryThis import org.matrix.android.sdk.api.session.Session @@ -35,9 +38,6 @@ import org.matrix.android.sdk.api.session.room.model.call.CallAnswerContent import org.matrix.android.sdk.api.session.room.model.call.CallCandidatesContent import org.matrix.android.sdk.api.session.room.model.call.CallHangupContent import org.matrix.android.sdk.api.session.room.model.call.CallInviteContent -import io.reactivex.disposables.Disposable -import io.reactivex.subjects.PublishSubject -import io.reactivex.subjects.ReplaySubject import org.webrtc.AudioSource import org.webrtc.AudioTrack import org.webrtc.Camera1Enumerator @@ -93,7 +93,7 @@ class WebRtcPeerConnectionManager @Inject constructor( currentCallsListeners.remove(listener) } - val audioManager = CallAudioManager(context.applicationContext) { + val callAudioManager = CallAudioManager(context.applicationContext) { currentCallsListeners.forEach { tryThis { it.onAudioDevicesChange(this) } } @@ -577,7 +577,7 @@ class WebRtcPeerConnectionManager @Inject constructor( fun close() { Timber.v("## VOIP WebRtcPeerConnectionManager close() >") CallService.onNoActiveCall(context) - audioManager.stop() + callAudioManager.stop() val callToEnd = currentCall currentCall = null // This must be done in this thread @@ -631,7 +631,7 @@ class WebRtcPeerConnectionManager @Inject constructor( val createdCall = currentSession?.callSignalingService()?.createOutgoingCall(signalingRoomId, otherUserId, isVideoCall) ?: return val callContext = CallContext(createdCall) - audioManager.startForCall(createdCall) + callAudioManager.startForCall(createdCall) currentCall = callContext val name = currentSession?.getUser(createdCall.otherUserId)?.getBestName() @@ -684,7 +684,7 @@ class WebRtcPeerConnectionManager @Inject constructor( val callContext = CallContext(mxCall) currentCall = callContext - audioManager.startForCall(mxCall) + callAudioManager.startForCall(mxCall) executor.execute { callContext.remoteCandidateSource = ReplaySubject.create() } @@ -798,12 +798,12 @@ class WebRtcPeerConnectionManager @Inject constructor( Timber.v("## VOIP onWiredDeviceEvent $event") currentCall ?: return // sometimes we received un-wanted unplugged... - audioManager.wiredStateChange(event) + callAudioManager.wiredStateChange(event) } fun onWirelessDeviceEvent(event: BluetoothHeadsetReceiver.BTHeadsetPlugEvent) { Timber.v("## VOIP onWirelessDeviceEvent $event") - audioManager.bluetoothStateChange(event.plugged) + callAudioManager.bluetoothStateChange(event.plugged) } override fun onCallAnswerReceived(callAnswerContent: CallAnswerContent) { @@ -858,7 +858,7 @@ class WebRtcPeerConnectionManager @Inject constructor( */ PeerConnection.PeerConnectionState.CONNECTED -> { callContext.mxCall.state = CallState.Connected(newState) - audioManager.onCallConnected(callContext.mxCall) + callAudioManager.onCallConnected(callContext.mxCall) } /** * One or more of the ICE transports on the connection is in the "failed" state. From 236f7f8e282322185c9967ed3c80d311b71cd21a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 11 Sep 2020 16:25:30 +0200 Subject: [PATCH 2/7] Private and typo --- .../app/features/call/VectorCallViewModel.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt index 97a6f72177..77a45628fe 100644 --- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt @@ -91,23 +91,23 @@ class VectorCallViewModel @AssistedInject constructor( val proximityManager: CallProximityManager ) : VectorViewModel(initialState) { - var call: MxCall? = null + private var call: MxCall? = null - var connectionTimoutTimer: Timer? = null - var hasBeenConnectedOnce = false + private var connectionTimeoutTimer: Timer? = null + private var hasBeenConnectedOnce = false private val callStateListener = object : MxCall.StateListener { override fun onStateUpdate(call: MxCall) { val callState = call.state if (callState is CallState.Connected && callState.iceConnectionState == PeerConnection.PeerConnectionState.CONNECTED) { hasBeenConnectedOnce = true - connectionTimoutTimer?.cancel() - connectionTimoutTimer = null + connectionTimeoutTimer?.cancel() + connectionTimeoutTimer = null } else { // do we reset as long as it's moving? - connectionTimoutTimer?.cancel() + connectionTimeoutTimer?.cancel() if (hasBeenConnectedOnce) { - connectionTimoutTimer = Timer().apply { + connectionTimeoutTimer = Timer().apply { schedule(object : TimerTask() { override fun run() { session.callSignalingService().getTurnServer(object : MatrixCallback { From ba163dbf5caf773de0501e398c9e39a37b971a01 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 11 Sep 2020 16:27:11 +0200 Subject: [PATCH 3/7] Split into 4 files --- .../features/call/VectorCallViewActions.kt | 32 +++++++++++++ .../app/features/call/VectorCallViewEvents.kt | 33 +++++++++++++ .../app/features/call/VectorCallViewModel.kt | 46 ------------------- .../app/features/call/VectorCallViewState.kt | 39 ++++++++++++++++ 4 files changed, 104 insertions(+), 46 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/call/VectorCallViewActions.kt create mode 100644 vector/src/main/java/im/vector/app/features/call/VectorCallViewEvents.kt create mode 100644 vector/src/main/java/im/vector/app/features/call/VectorCallViewState.kt diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewActions.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewActions.kt new file mode 100644 index 0000000000..4ca21a0f1d --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewActions.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.call + +import im.vector.app.core.platform.VectorViewModelAction + +sealed class VectorCallViewActions : VectorViewModelAction { + object EndCall : VectorCallViewActions() + object AcceptCall : VectorCallViewActions() + object DeclineCall : VectorCallViewActions() + object ToggleMute : VectorCallViewActions() + object ToggleVideo : VectorCallViewActions() + data class ChangeAudioDevice(val device: CallAudioManager.SoundDevice) : VectorCallViewActions() + object SwitchSoundDevice : VectorCallViewActions() + object HeadSetButtonPressed : VectorCallViewActions() + object ToggleCamera : VectorCallViewActions() + object ToggleHDSD : VectorCallViewActions() +} diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewEvents.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewEvents.kt new file mode 100644 index 0000000000..b79cd5d772 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewEvents.kt @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.call + +import im.vector.app.core.platform.VectorViewEvents +import org.matrix.android.sdk.api.session.call.TurnServerResponse + +sealed class VectorCallViewEvents : VectorViewEvents { + + object DismissNoCall : VectorCallViewEvents() + data class ConnectionTimeout(val turn: TurnServerResponse?) : VectorCallViewEvents() + data class ShowSoundDeviceChooser( + val available: List, + val current: CallAudioManager.SoundDevice + ) : VectorCallViewEvents() +// data class CallAnswered(val content: CallAnswerContent) : VectorCallViewEvents() +// data class CallHangup(val content: CallHangupContent) : VectorCallViewEvents() +// object CallAccepted : VectorCallViewEvents() +} diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt index 77a45628fe..e87e7b10d2 100644 --- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt @@ -16,10 +16,8 @@ package im.vector.app.features.call -import com.airbnb.mvrx.Async import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading -import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.Success import com.airbnb.mvrx.Uninitialized @@ -27,9 +25,7 @@ import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import im.vector.app.core.extensions.exhaustive -import im.vector.app.core.platform.VectorViewEvents import im.vector.app.core.platform.VectorViewModel -import im.vector.app.core.platform.VectorViewModelAction import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.call.CallState @@ -41,48 +37,6 @@ import org.webrtc.PeerConnection import java.util.Timer import java.util.TimerTask -data class VectorCallViewState( - val callId: String? = null, - val roomId: String = "", - val isVideoCall: Boolean, - val isAudioMuted: Boolean = false, - val isVideoEnabled: Boolean = true, - val isVideoCaptureInError: Boolean = false, - val isHD: Boolean = false, - val isFrontCamera: Boolean = true, - val canSwitchCamera: Boolean = true, - val soundDevice: CallAudioManager.SoundDevice = CallAudioManager.SoundDevice.PHONE, - val availableSoundDevices: List = emptyList(), - val otherUserMatrixItem: Async = Uninitialized, - val callState: Async = Uninitialized -) : MvRxState - -sealed class VectorCallViewActions : VectorViewModelAction { - object EndCall : VectorCallViewActions() - object AcceptCall : VectorCallViewActions() - object DeclineCall : VectorCallViewActions() - object ToggleMute : VectorCallViewActions() - object ToggleVideo : VectorCallViewActions() - data class ChangeAudioDevice(val device: CallAudioManager.SoundDevice) : VectorCallViewActions() - object SwitchSoundDevice : VectorCallViewActions() - object HeadSetButtonPressed : VectorCallViewActions() - object ToggleCamera : VectorCallViewActions() - object ToggleHDSD : VectorCallViewActions() -} - -sealed class VectorCallViewEvents : VectorViewEvents { - - object DismissNoCall : VectorCallViewEvents() - data class ConnectionTimeout(val turn: TurnServerResponse?) : VectorCallViewEvents() - data class ShowSoundDeviceChooser( - val available: List, - val current: CallAudioManager.SoundDevice - ) : VectorCallViewEvents() -// data class CallAnswered(val content: CallAnswerContent) : VectorCallViewEvents() -// data class CallHangup(val content: CallHangupContent) : VectorCallViewEvents() -// object CallAccepted : VectorCallViewEvents() -} - class VectorCallViewModel @AssistedInject constructor( @Assisted initialState: VectorCallViewState, @Assisted val args: CallArgs, diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewState.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewState.kt new file mode 100644 index 0000000000..f24e810400 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewState.kt @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.call + +import com.airbnb.mvrx.Async +import com.airbnb.mvrx.MvRxState +import com.airbnb.mvrx.Uninitialized +import org.matrix.android.sdk.api.session.call.CallState +import org.matrix.android.sdk.api.util.MatrixItem + +data class VectorCallViewState( + val callId: String? = null, + val roomId: String = "", + val isVideoCall: Boolean, + val isAudioMuted: Boolean = false, + val isVideoEnabled: Boolean = true, + val isVideoCaptureInError: Boolean = false, + val isHD: Boolean = false, + val isFrontCamera: Boolean = true, + val canSwitchCamera: Boolean = true, + val soundDevice: CallAudioManager.SoundDevice = CallAudioManager.SoundDevice.PHONE, + val availableSoundDevices: List = emptyList(), + val otherUserMatrixItem: Async = Uninitialized, + val callState: Async = Uninitialized +) : MvRxState From 21a42e310fa62092b8573169804696ce8de39d9a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 11 Sep 2020 16:49:11 +0200 Subject: [PATCH 4/7] Show branch name in debug build --- .../features/settings/VectorSettingsHelpAboutFragment.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt index 129e057148..f011702dca 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsHelpAboutFragment.kt @@ -20,6 +20,7 @@ import android.content.Intent import android.net.Uri import android.provider.Settings import androidx.preference.Preference +import im.vector.app.BuildConfig import org.matrix.android.sdk.api.Matrix import im.vector.app.R import im.vector.app.core.preference.VectorPreference @@ -58,7 +59,13 @@ class VectorSettingsHelpAboutFragment @Inject constructor( // application version findPreference(VectorPreferences.SETTINGS_VERSION_PREFERENCE_KEY)!!.let { - it.summary = versionProvider.getVersion(longFormat = false, useBuildNumber = true) + it.summary = buildString { + append(versionProvider.getVersion(longFormat = false, useBuildNumber = true)) + if (BuildConfig.DEBUG) { + append(" ") + append(BuildConfig.GIT_BRANCH_NAME) + } + } it.setOnPreferenceClickListener { pref -> copyToClipboard(requireContext(), pref.summary) From 1e0bc51fa20758f566cd70f3fcbf67b967f2d094 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 11 Sep 2020 17:09:30 +0200 Subject: [PATCH 5/7] Remove singletin instance from callback param --- .../app/features/call/VectorCallViewModel.kt | 18 +++++++++--------- .../call/WebRtcPeerConnectionManager.kt | 14 +++++++------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt index e87e7b10d2..edb75441c8 100644 --- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt @@ -90,17 +90,17 @@ class VectorCallViewModel @AssistedInject constructor( override fun onCurrentCallChange(call: MxCall?) { } - override fun onCaptureStateChanged(mgr: WebRtcPeerConnectionManager) { + override fun onCaptureStateChanged() { setState { copy( - isVideoCaptureInError = mgr.capturerIsInError, - isHD = mgr.currentCaptureFormat() is CaptureFormat.HD + isVideoCaptureInError = webRtcPeerConnectionManager.capturerIsInError, + isHD = webRtcPeerConnectionManager.currentCaptureFormat() is CaptureFormat.HD ) } } - override fun onAudioDevicesChange(mgr: WebRtcPeerConnectionManager) { - val currentSoundDevice = mgr.callAudioManager.getCurrentSoundDevice() + override fun onAudioDevicesChange() { + val currentSoundDevice = webRtcPeerConnectionManager.callAudioManager.getCurrentSoundDevice() if (currentSoundDevice == CallAudioManager.SoundDevice.PHONE) { proximityManager.start() } else { @@ -109,17 +109,17 @@ class VectorCallViewModel @AssistedInject constructor( setState { copy( - availableSoundDevices = mgr.callAudioManager.getAvailableSoundDevices(), + availableSoundDevices = webRtcPeerConnectionManager.callAudioManager.getAvailableSoundDevices(), soundDevice = currentSoundDevice ) } } - override fun onCameraChange(mgr: WebRtcPeerConnectionManager) { + override fun onCameraChange() { setState { copy( - canSwitchCamera = mgr.canSwitchCamera(), - isFrontCamera = mgr.currentCameraType() == CameraType.FRONT + canSwitchCamera = webRtcPeerConnectionManager.canSwitchCamera(), + isFrontCamera = webRtcPeerConnectionManager.currentCameraType() == CameraType.FRONT ) } } diff --git a/vector/src/main/java/im/vector/app/features/call/WebRtcPeerConnectionManager.kt b/vector/src/main/java/im/vector/app/features/call/WebRtcPeerConnectionManager.kt index 916df8892b..c47ec4e35a 100644 --- a/vector/src/main/java/im/vector/app/features/call/WebRtcPeerConnectionManager.kt +++ b/vector/src/main/java/im/vector/app/features/call/WebRtcPeerConnectionManager.kt @@ -79,9 +79,9 @@ class WebRtcPeerConnectionManager @Inject constructor( interface CurrentCallListener { fun onCurrentCallChange(call: MxCall?) - fun onCaptureStateChanged(mgr: WebRtcPeerConnectionManager) {} - fun onAudioDevicesChange(mgr: WebRtcPeerConnectionManager) {} - fun onCameraChange(mgr: WebRtcPeerConnectionManager) {} + fun onCaptureStateChanged() {} + fun onAudioDevicesChange() {} + fun onCameraChange() {} } private val currentCallsListeners = emptyList().toMutableList() @@ -95,7 +95,7 @@ class WebRtcPeerConnectionManager @Inject constructor( val callAudioManager = CallAudioManager(context.applicationContext) { currentCallsListeners.forEach { - tryThis { it.onAudioDevicesChange(this) } + tryThis { it.onAudioDevicesChange() } } } @@ -174,7 +174,7 @@ class WebRtcPeerConnectionManager @Inject constructor( set(value) { field = value currentCallsListeners.forEach { - tryThis { it.onCaptureStateChanged(this) } + tryThis { it.onCaptureStateChanged() } } } @@ -741,7 +741,7 @@ class WebRtcPeerConnectionManager @Inject constructor( Timber.v("## VOIP onCameraSwitchDone isFront $isFrontCamera") cameraInUse = availableCamera.first { if (isFrontCamera) it.type == CameraType.FRONT else it.type == CameraType.BACK } currentCallsListeners.forEach { - tryThis { it.onCameraChange(this@WebRtcPeerConnectionManager) } + tryThis { it.onCameraChange() } } } @@ -767,7 +767,7 @@ class WebRtcPeerConnectionManager @Inject constructor( // videoCapturer?.stopCapture() videoCapturer?.changeCaptureFormat(format.width, format.height, format.fps) currentCaptureMode = format - currentCallsListeners.forEach { tryThis { it.onCaptureStateChanged(this) } } + currentCallsListeners.forEach { tryThis { it.onCaptureStateChanged() } } } } From 624a8ff04c9c53576cd14a330f0a87a5b9781f83 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 15 Sep 2020 12:36:27 +0200 Subject: [PATCH 6/7] Fragment transaction: allow state loss when needed --- .../im/vector/app/core/extensions/Activity.kt | 23 ++++----- .../im/vector/app/core/extensions/Fragment.kt | 48 +++++++++---------- .../app/core/extensions/FragmentManager.kt | 9 +++- .../restore/KeysBackupRestoreActivity.kt | 4 +- .../vector/app/features/home/HomeActivity.kt | 2 +- 5 files changed, 46 insertions(+), 40 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/extensions/Activity.kt b/vector/src/main/java/im/vector/app/core/extensions/Activity.kt index ee94013d1b..02806d81a9 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Activity.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Activity.kt @@ -22,36 +22,37 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentTransaction import im.vector.app.core.platform.VectorBaseActivity -fun VectorBaseActivity.addFragment(frameId: Int, fragment: Fragment) { - supportFragmentManager.commitTransaction { add(frameId, fragment) } +fun VectorBaseActivity.addFragment(frameId: Int, fragment: Fragment, allowStateLoss: Boolean = false) { + supportFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragment) } } -fun VectorBaseActivity.addFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null) { - supportFragmentManager.commitTransaction { +fun VectorBaseActivity.addFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { + supportFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragmentClass, params.toMvRxBundle(), tag) } } -fun VectorBaseActivity.replaceFragment(frameId: Int, fragment: Fragment, tag: String? = null) { - supportFragmentManager.commitTransaction { replace(frameId, fragment, tag) } +fun VectorBaseActivity.replaceFragment(frameId: Int, fragment: Fragment, tag: String? = null, allowStateLoss: Boolean = false) { + supportFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragment, tag) } } -fun VectorBaseActivity.replaceFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null) { - supportFragmentManager.commitTransaction { +fun VectorBaseActivity.replaceFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { + supportFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragmentClass, params.toMvRxBundle(), tag) } } -fun VectorBaseActivity.addFragmentToBackstack(frameId: Int, fragment: Fragment, tag: String? = null) { - supportFragmentManager.commitTransaction { replace(frameId, fragment).addToBackStack(tag) } +fun VectorBaseActivity.addFragmentToBackstack(frameId: Int, fragment: Fragment, tag: String? = null, allowStateLoss: Boolean = false) { + supportFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragment).addToBackStack(tag) } } fun VectorBaseActivity.addFragmentToBackstack(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, + allowStateLoss: Boolean = false, option: ((FragmentTransaction) -> Unit)? = null) { - supportFragmentManager.commitTransaction { + supportFragmentManager.commitTransaction(allowStateLoss) { option?.invoke(this) replace(frameId, fragmentClass, params.toMvRxBundle(), tag).addToBackStack(tag) } diff --git a/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt b/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt index 6ba250ee1b..b3e34ab6a9 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt @@ -26,62 +26,62 @@ import java.text.SimpleDateFormat import java.util.Date import java.util.Locale -fun VectorBaseFragment.addFragment(frameId: Int, fragment: Fragment) { - parentFragmentManager.commitTransaction { add(frameId, fragment) } +fun VectorBaseFragment.addFragment(frameId: Int, fragment: Fragment, allowStateLoss: Boolean = false) { + parentFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragment) } } -fun VectorBaseFragment.addFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null) { - parentFragmentManager.commitTransaction { +fun VectorBaseFragment.addFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { + parentFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragmentClass, params.toMvRxBundle(), tag) } } -fun VectorBaseFragment.replaceFragment(frameId: Int, fragment: Fragment) { - parentFragmentManager.commitTransaction { replace(frameId, fragment) } +fun VectorBaseFragment.replaceFragment(frameId: Int, fragment: Fragment, allowStateLoss: Boolean = false) { + parentFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragment) } } -fun VectorBaseFragment.replaceFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null) { - parentFragmentManager.commitTransaction { +fun VectorBaseFragment.replaceFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { + parentFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragmentClass, params.toMvRxBundle(), tag) } } -fun VectorBaseFragment.addFragmentToBackstack(frameId: Int, fragment: Fragment, tag: String? = null) { - parentFragmentManager.commitTransaction { replace(frameId, fragment, tag).addToBackStack(tag) } +fun VectorBaseFragment.addFragmentToBackstack(frameId: Int, fragment: Fragment, tag: String? = null, allowStateLoss: Boolean = false) { + parentFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragment, tag).addToBackStack(tag) } } -fun VectorBaseFragment.addFragmentToBackstack(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null) { - parentFragmentManager.commitTransaction { +fun VectorBaseFragment.addFragmentToBackstack(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { + parentFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragmentClass, params.toMvRxBundle(), tag).addToBackStack(tag) } } -fun VectorBaseFragment.addChildFragment(frameId: Int, fragment: Fragment, tag: String? = null) { - childFragmentManager.commitTransaction { add(frameId, fragment, tag) } +fun VectorBaseFragment.addChildFragment(frameId: Int, fragment: Fragment, tag: String? = null, allowStateLoss: Boolean = false) { + childFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragment, tag) } } -fun VectorBaseFragment.addChildFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null) { - childFragmentManager.commitTransaction { +fun VectorBaseFragment.addChildFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { + childFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragmentClass, params.toMvRxBundle(), tag) } } -fun VectorBaseFragment.replaceChildFragment(frameId: Int, fragment: Fragment, tag: String? = null) { - childFragmentManager.commitTransaction { replace(frameId, fragment, tag) } +fun VectorBaseFragment.replaceChildFragment(frameId: Int, fragment: Fragment, tag: String? = null, allowStateLoss: Boolean = false) { + childFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragment, tag) } } -fun VectorBaseFragment.replaceChildFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null) { - childFragmentManager.commitTransaction { +fun VectorBaseFragment.replaceChildFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { + childFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragmentClass, params.toMvRxBundle(), tag) } } -fun VectorBaseFragment.addChildFragmentToBackstack(frameId: Int, fragment: Fragment, tag: String? = null) { - childFragmentManager.commitTransaction { replace(frameId, fragment).addToBackStack(tag) } +fun VectorBaseFragment.addChildFragmentToBackstack(frameId: Int, fragment: Fragment, tag: String? = null, allowStateLoss: Boolean = false) { + childFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragment).addToBackStack(tag) } } -fun VectorBaseFragment.addChildFragmentToBackstack(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null) { - childFragmentManager.commitTransaction { +fun VectorBaseFragment.addChildFragmentToBackstack(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { + childFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragmentClass, params.toMvRxBundle(), tag).addToBackStack(tag) } } diff --git a/vector/src/main/java/im/vector/app/core/extensions/FragmentManager.kt b/vector/src/main/java/im/vector/app/core/extensions/FragmentManager.kt index 1d437c0701..49b28fb190 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/FragmentManager.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/FragmentManager.kt @@ -27,6 +27,11 @@ inline fun androidx.fragment.app.FragmentManager.commitTransactionNow(func: Frag } } -inline fun androidx.fragment.app.FragmentManager.commitTransaction(func: FragmentTransaction.() -> FragmentTransaction) { - beginTransaction().func().commit() +inline fun androidx.fragment.app.FragmentManager.commitTransaction(allowStateLoss: Boolean = false, func: FragmentTransaction.() -> FragmentTransaction) { + val transaction = beginTransaction().func() + if (allowStateLoss) { + transaction.commitAllowingStateLoss() + } else { + transaction.commit() + } } diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt index bef8788f75..40953cb5f6 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreActivity.kt @@ -87,13 +87,13 @@ class KeysBackupRestoreActivity : SimpleFragmentActivity() { viewModel.navigateEvent.observeEvent(this) { uxStateEvent -> when (uxStateEvent) { KeysBackupRestoreSharedViewModel.NAVIGATE_TO_RECOVER_WITH_KEY -> { - addFragmentToBackstack(R.id.container, KeysBackupRestoreFromKeyFragment::class.java) + addFragmentToBackstack(R.id.container, KeysBackupRestoreFromKeyFragment::class.java, allowStateLoss = true) } KeysBackupRestoreSharedViewModel.NAVIGATE_TO_SUCCESS -> { viewModel.keyVersionResult.value?.version?.let { KeysBackupBanner.onRecoverDoneForVersion(this, it) } - replaceFragment(R.id.container, KeysBackupRestoreSuccessFragment::class.java) + replaceFragment(R.id.container, KeysBackupRestoreSuccessFragment::class.java, allowStateLoss = true) } KeysBackupRestoreSharedViewModel.NAVIGATE_TO_4S -> { launch4SActivity() diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index 76de2daf54..eb024c4db1 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -121,7 +121,7 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable, UnknownDeviceDet is HomeActivitySharedAction.CloseDrawer -> drawerLayout.closeDrawer(GravityCompat.START) is HomeActivitySharedAction.OpenGroup -> { drawerLayout.closeDrawer(GravityCompat.START) - replaceFragment(R.id.homeDetailFragmentContainer, HomeDetailFragment::class.java) + replaceFragment(R.id.homeDetailFragmentContainer, HomeDetailFragment::class.java, allowStateLoss = true) } }.exhaustive } From 0077091175bbd34682f35cee645eaa3d0bd2c737 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 15 Sep 2020 12:56:37 +0200 Subject: [PATCH 7/7] Update CHANGES and clean files --- CHANGES.md | 1 + .../im/vector/app/core/extensions/Activity.kt | 36 ++++++-- .../im/vector/app/core/extensions/Fragment.kt | 88 ++++++++++++++++--- 3 files changed, 108 insertions(+), 17 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index d8556e16bc..118917fb93 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,7 @@ Bugfix 🐛: - Speakerphone is not used for ringback tone (#1644, #1645) - Back camera preview is not mirrored anymore (#1776) - Various report of people that cannot play video (#2107) + - Fix stuck on loader when launching home Translations 🗣: - diff --git a/vector/src/main/java/im/vector/app/core/extensions/Activity.kt b/vector/src/main/java/im/vector/app/core/extensions/Activity.kt index 02806d81a9..cc67f633eb 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Activity.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Activity.kt @@ -22,27 +22,53 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentTransaction import im.vector.app.core.platform.VectorBaseActivity -fun VectorBaseActivity.addFragment(frameId: Int, fragment: Fragment, allowStateLoss: Boolean = false) { +fun VectorBaseActivity.addFragment( + frameId: Int, + fragment: Fragment, + allowStateLoss: Boolean = false +) { supportFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragment) } } -fun VectorBaseActivity.addFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { +fun VectorBaseActivity.addFragment( + frameId: Int, + fragmentClass: Class, + params: Parcelable? = null, + tag: String? = null, + allowStateLoss: Boolean = false +) { supportFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragmentClass, params.toMvRxBundle(), tag) } } -fun VectorBaseActivity.replaceFragment(frameId: Int, fragment: Fragment, tag: String? = null, allowStateLoss: Boolean = false) { +fun VectorBaseActivity.replaceFragment( + frameId: Int, + fragment: Fragment, + tag: String? = null, + allowStateLoss: Boolean = false +) { supportFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragment, tag) } } -fun VectorBaseActivity.replaceFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { +fun VectorBaseActivity.replaceFragment( + frameId: Int, + fragmentClass: Class, + params: Parcelable? = null, + tag: String? = null, + allowStateLoss: Boolean = false +) { supportFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragmentClass, params.toMvRxBundle(), tag) } } -fun VectorBaseActivity.addFragmentToBackstack(frameId: Int, fragment: Fragment, tag: String? = null, allowStateLoss: Boolean = false) { +fun VectorBaseActivity.addFragmentToBackstack( + frameId: Int, + fragment: Fragment, + tag: String? = null, + allowStateLoss: Boolean = false +) { supportFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragment).addToBackStack(tag) } } diff --git a/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt b/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt index b3e34ab6a9..fbcd6900c1 100644 --- a/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt +++ b/vector/src/main/java/im/vector/app/core/extensions/Fragment.kt @@ -26,61 +26,125 @@ import java.text.SimpleDateFormat import java.util.Date import java.util.Locale -fun VectorBaseFragment.addFragment(frameId: Int, fragment: Fragment, allowStateLoss: Boolean = false) { +fun VectorBaseFragment.addFragment( + frameId: Int, + fragment: Fragment, + allowStateLoss: Boolean = false +) { parentFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragment) } } -fun VectorBaseFragment.addFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { +fun VectorBaseFragment.addFragment( + frameId: Int, + fragmentClass: Class, + params: Parcelable? = null, + tag: String? = null, + allowStateLoss: Boolean = false +) { parentFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragmentClass, params.toMvRxBundle(), tag) } } -fun VectorBaseFragment.replaceFragment(frameId: Int, fragment: Fragment, allowStateLoss: Boolean = false) { +fun VectorBaseFragment.replaceFragment( + frameId: Int, + fragment: Fragment, + allowStateLoss: Boolean = false +) { parentFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragment) } } -fun VectorBaseFragment.replaceFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { +fun VectorBaseFragment.replaceFragment( + frameId: Int, + fragmentClass: Class, + params: Parcelable? = null, + tag: String? = null, + allowStateLoss: Boolean = false +) { parentFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragmentClass, params.toMvRxBundle(), tag) } } -fun VectorBaseFragment.addFragmentToBackstack(frameId: Int, fragment: Fragment, tag: String? = null, allowStateLoss: Boolean = false) { +fun VectorBaseFragment.addFragmentToBackstack( + frameId: Int, + fragment: Fragment, + tag: String? = null, + allowStateLoss: Boolean = false +) { parentFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragment, tag).addToBackStack(tag) } } -fun VectorBaseFragment.addFragmentToBackstack(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { +fun VectorBaseFragment.addFragmentToBackstack( + frameId: Int, + fragmentClass: Class, + params: Parcelable? = null, + tag: String? = null, + allowStateLoss: Boolean = false +) { parentFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragmentClass, params.toMvRxBundle(), tag).addToBackStack(tag) } } -fun VectorBaseFragment.addChildFragment(frameId: Int, fragment: Fragment, tag: String? = null, allowStateLoss: Boolean = false) { +fun VectorBaseFragment.addChildFragment( + frameId: Int, + fragment: Fragment, + tag: String? = null, + allowStateLoss: Boolean = false +) { childFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragment, tag) } } -fun VectorBaseFragment.addChildFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { +fun VectorBaseFragment.addChildFragment( + frameId: Int, + fragmentClass: Class, + params: Parcelable? = null, + tag: String? = null, + allowStateLoss: Boolean = false +) { childFragmentManager.commitTransaction(allowStateLoss) { add(frameId, fragmentClass, params.toMvRxBundle(), tag) } } -fun VectorBaseFragment.replaceChildFragment(frameId: Int, fragment: Fragment, tag: String? = null, allowStateLoss: Boolean = false) { +fun VectorBaseFragment.replaceChildFragment( + frameId: Int, + fragment: Fragment, + tag: String? = null, + allowStateLoss: Boolean = false +) { childFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragment, tag) } } -fun VectorBaseFragment.replaceChildFragment(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { +fun VectorBaseFragment.replaceChildFragment( + frameId: Int, + fragmentClass: Class, + params: Parcelable? = null, + tag: String? = null, + allowStateLoss: Boolean = false +) { childFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragmentClass, params.toMvRxBundle(), tag) } } -fun VectorBaseFragment.addChildFragmentToBackstack(frameId: Int, fragment: Fragment, tag: String? = null, allowStateLoss: Boolean = false) { +fun VectorBaseFragment.addChildFragmentToBackstack( + frameId: Int, + fragment: Fragment, + tag: String? = null, + allowStateLoss: Boolean = false +) { childFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragment).addToBackStack(tag) } } -fun VectorBaseFragment.addChildFragmentToBackstack(frameId: Int, fragmentClass: Class, params: Parcelable? = null, tag: String? = null, allowStateLoss: Boolean = false) { +fun VectorBaseFragment.addChildFragmentToBackstack( + frameId: Int, + fragmentClass: Class, + params: Parcelable? = null, + tag: String? = null, + allowStateLoss: Boolean = false +) { childFragmentManager.commitTransaction(allowStateLoss) { replace(frameId, fragmentClass, params.toMvRxBundle(), tag).addToBackStack(tag) }