mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-16 02:05:06 +08:00
Jitsi: handle switch to another conference, now possible since we support PiP
This commit is contained in:
parent
d5f0a6d66a
commit
5e4219cf8e
@ -18,4 +18,12 @@ package im.vector.app.features.call.conference
|
||||
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
|
||||
sealed class JitsiCallViewActions : VectorViewModelAction
|
||||
sealed class JitsiCallViewActions : VectorViewModelAction {
|
||||
data class SwitchTo(val args: VectorJitsiActivity.Args,
|
||||
val withConfirmation: Boolean) : JitsiCallViewActions()
|
||||
|
||||
/**
|
||||
* The ViewModel will either ask the View to finish, or to join another conf.
|
||||
*/
|
||||
object OnConferenceLeft: JitsiCallViewActions()
|
||||
}
|
||||
|
@ -27,4 +27,11 @@ sealed class JitsiCallViewEvents : VectorViewEvents {
|
||||
val confId: String,
|
||||
val userInfo: JitsiMeetUserInfo
|
||||
) : JitsiCallViewEvents()
|
||||
|
||||
data class ConfirmSwitchingConference(
|
||||
val args: VectorJitsiActivity.Args
|
||||
) : JitsiCallViewEvents()
|
||||
|
||||
object LeaveConference : JitsiCallViewEvents()
|
||||
object Finish : JitsiCallViewEvents()
|
||||
}
|
||||
|
@ -19,12 +19,15 @@ package im.vector.app.features.call.conference
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.themes.ThemeProvider
|
||||
import io.reactivex.disposables.Disposable
|
||||
import org.jitsi.meet.sdk.JitsiMeetUserInfo
|
||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
@ -36,7 +39,6 @@ import java.net.URL
|
||||
|
||||
class JitsiCallViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: JitsiCallViewState,
|
||||
@Assisted private val args: VectorJitsiActivity.Args,
|
||||
private val session: Session,
|
||||
private val jitsiMeetPropertiesFactory: JitsiWidgetPropertiesFactory,
|
||||
private val themeProvider: ThemeProvider
|
||||
@ -44,15 +46,23 @@ class JitsiCallViewModel @AssistedInject constructor(
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(initialState: JitsiCallViewState, args: VectorJitsiActivity.Args): JitsiCallViewModel
|
||||
fun create(initialState: JitsiCallViewState): JitsiCallViewModel
|
||||
}
|
||||
|
||||
private var currentWidgetObserver: Disposable? = null
|
||||
private val widgetService = session.widgetService()
|
||||
|
||||
private var confIsStarted = false
|
||||
private var pendingArgs: VectorJitsiActivity.Args? = null
|
||||
|
||||
init {
|
||||
widgetService.getRoomWidgetsLive(args.roomId, QueryStringValue.Equals(args.widgetId), WidgetType.Jitsi.values())
|
||||
observeWidget(initialState.roomId, initialState.widgetId)
|
||||
}
|
||||
|
||||
private fun observeWidget(roomId: String, widgetId: String) {
|
||||
confIsStarted = false
|
||||
currentWidgetObserver?.dispose()
|
||||
currentWidgetObserver = widgetService.getRoomWidgetsLive(roomId, QueryStringValue.Equals(widgetId), WidgetType.Jitsi.values())
|
||||
.asObservable()
|
||||
.distinctUntilChanged()
|
||||
.subscribe {
|
||||
@ -77,19 +87,19 @@ class JitsiCallViewModel @AssistedInject constructor(
|
||||
.disposeOnClear()
|
||||
}
|
||||
|
||||
private fun startConference(jitsiWidget: Widget) {
|
||||
val me = session.getRoomMember(session.myUserId, args.roomId)?.toMatrixItem()
|
||||
private fun startConference(jitsiWidget: Widget) = withState { state ->
|
||||
val me = session.getRoomMember(session.myUserId, state.roomId)?.toMatrixItem()
|
||||
val userInfo = JitsiMeetUserInfo().apply {
|
||||
displayName = me?.getBestName()
|
||||
avatar = me?.avatarUrl?.let { session.contentUrlResolver().resolveFullSize(it) }?.let { URL(it) }
|
||||
}
|
||||
val roomName = session.getRoomSummary(args.roomId)?.displayName
|
||||
val roomName = session.getRoomSummary(state.roomId)?.displayName
|
||||
|
||||
val ppt = widgetService.getWidgetComputedUrl(jitsiWidget, themeProvider.isLightTheme())
|
||||
?.let { url -> jitsiMeetPropertiesFactory.create(url) }
|
||||
|
||||
_viewEvents.post(JitsiCallViewEvents.StartConference(
|
||||
enableVideo = args.enableVideo,
|
||||
enableVideo = state.enableVideo,
|
||||
jitsiUrl = "https://${ppt?.domain}",
|
||||
subject = roomName ?: "",
|
||||
confId = ppt?.confId ?: "",
|
||||
@ -98,6 +108,45 @@ class JitsiCallViewModel @AssistedInject constructor(
|
||||
}
|
||||
|
||||
override fun handle(action: JitsiCallViewActions) {
|
||||
when (action) {
|
||||
is JitsiCallViewActions.SwitchTo -> handleSwitchTo(action)
|
||||
JitsiCallViewActions.OnConferenceLeft -> handleOnConferenceLeft()
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleSwitchTo(action: JitsiCallViewActions.SwitchTo) = withState { state ->
|
||||
// Check if it is the same conf
|
||||
if (action.args.roomId != state.roomId
|
||||
|| action.args.widgetId != state.widgetId) {
|
||||
if (action.withConfirmation) {
|
||||
// Ask confirmation to switch
|
||||
_viewEvents.post(JitsiCallViewEvents.ConfirmSwitchingConference(action.args))
|
||||
} else {
|
||||
// Ask the view to leave the conf, then the view will tell us when it's done, to join the new conf
|
||||
pendingArgs = action.args
|
||||
_viewEvents.post(JitsiCallViewEvents.LeaveConference)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleOnConferenceLeft() {
|
||||
val safePendingArgs = pendingArgs
|
||||
pendingArgs = null
|
||||
|
||||
if (safePendingArgs == null) {
|
||||
// Quit
|
||||
_viewEvents.post(JitsiCallViewEvents.Finish)
|
||||
} else {
|
||||
setState {
|
||||
copy(
|
||||
roomId = safePendingArgs.roomId,
|
||||
widgetId = safePendingArgs.widgetId,
|
||||
enableVideo = safePendingArgs.enableVideo,
|
||||
widget = Uninitialized
|
||||
)
|
||||
}
|
||||
observeWidget(safePendingArgs.roomId, safePendingArgs.widgetId)
|
||||
}
|
||||
}
|
||||
|
||||
companion object : MvRxViewModelFactory<JitsiCallViewModel, JitsiCallViewState> {
|
||||
@ -107,8 +156,7 @@ class JitsiCallViewModel @AssistedInject constructor(
|
||||
@JvmStatic
|
||||
override fun create(viewModelContext: ViewModelContext, state: JitsiCallViewState): JitsiCallViewModel? {
|
||||
val callActivity: VectorJitsiActivity = viewModelContext.activity()
|
||||
val callArgs: VectorJitsiActivity.Args = viewModelContext.args()
|
||||
return callActivity.viewModelFactory.create(state, callArgs)
|
||||
return callActivity.viewModelFactory.create(state)
|
||||
}
|
||||
|
||||
override fun initialState(viewModelContext: ViewModelContext): JitsiCallViewState? {
|
||||
@ -116,7 +164,8 @@ class JitsiCallViewModel @AssistedInject constructor(
|
||||
|
||||
return JitsiCallViewState(
|
||||
roomId = args.roomId,
|
||||
widgetId = args.widgetId
|
||||
widgetId = args.widgetId,
|
||||
enableVideo = args.enableVideo
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -24,5 +24,6 @@ import org.matrix.android.sdk.api.session.widgets.model.Widget
|
||||
data class JitsiCallViewState(
|
||||
val roomId: String = "",
|
||||
val widgetId: String = "",
|
||||
val enableVideo: Boolean = false,
|
||||
val widget: Async<Widget> = Uninitialized
|
||||
) : MvRxState
|
||||
|
@ -25,6 +25,7 @@ import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.widget.FrameLayout
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import com.airbnb.mvrx.Fail
|
||||
@ -32,6 +33,7 @@ import com.airbnb.mvrx.MvRx
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.viewModel
|
||||
import com.facebook.react.modules.core.PermissionListener
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.ScreenComponent
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
@ -86,12 +88,30 @@ class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMee
|
||||
jitsiViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is JitsiCallViewEvents.StartConference -> configureJitsiView(it)
|
||||
is JitsiCallViewEvents.ConfirmSwitchingConference -> handleConfirmSwitching(it)
|
||||
JitsiCallViewEvents.Finish -> finish()
|
||||
JitsiCallViewEvents.LeaveConference -> handleLeaveConference()
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
registerForBroadcastMessages()
|
||||
}
|
||||
|
||||
private fun handleLeaveConference() {
|
||||
jitsiMeetView?.leave()
|
||||
}
|
||||
|
||||
private fun handleConfirmSwitching(action: JitsiCallViewEvents.ConfirmSwitchingConference) {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(R.string.dialog_title_warning)
|
||||
.setMessage(R.string.jitsi_leave_conf_to_join_another_one_content)
|
||||
.setPositiveButton(R.string.action_switch) { _, _ ->
|
||||
jitsiViewModel.handle(JitsiCallViewActions.SwitchTo(action.args, false))
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean,
|
||||
newConfig: Configuration) {
|
||||
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
|
||||
@ -170,6 +190,14 @@ class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMee
|
||||
|
||||
override fun onNewIntent(intent: Intent?) {
|
||||
JitsiMeetActivityDelegate.onNewIntent(intent)
|
||||
|
||||
// Is it a switch to another conf?
|
||||
intent?.takeIf { it.hasExtra(MvRx.KEY_ARG) }
|
||||
?.let { intent.getParcelableExtra<Args>(MvRx.KEY_ARG) }
|
||||
?.let {
|
||||
jitsiViewModel.handle(JitsiCallViewActions.SwitchTo(it, true))
|
||||
}
|
||||
|
||||
super.onNewIntent(intent)
|
||||
}
|
||||
|
||||
@ -211,7 +239,7 @@ class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMee
|
||||
Timber.v("JitsiMeetViewListener.onConferenceTerminated()")
|
||||
// Do not finish if there is an error
|
||||
if (data["error"] == null) {
|
||||
finish()
|
||||
jitsiViewModel.handle(JitsiCallViewActions.OnConferenceLeft)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,7 @@
|
||||
<string name="action_close">Close</string>
|
||||
<string name="action_copy">Copy</string>
|
||||
<string name="action_add">Add</string>
|
||||
<string name="action_switch">Switch</string>
|
||||
<string name="action_unpublish">Unpublish</string>
|
||||
<string name="copied_to_clipboard">Copied to clipboard</string>
|
||||
<string name="disable">Disable</string>
|
||||
@ -1318,6 +1319,8 @@
|
||||
|
||||
|
||||
<string name="error_jitsi_not_supported_on_old_device">Sorry, conference calls with Jitsi are not supported on old devices (devices with Android OS below 6.0)</string>
|
||||
<string name="jitsi_leave_conf_to_join_another_one_content">Leave the current conference and switch to the other one?</string>
|
||||
|
||||
<string name="room_widget_resource_permission_title">This widget wants to use the following resources:</string>
|
||||
<string name="room_widget_resource_grant_permission">Allow</string>
|
||||
<string name="room_widget_resource_decline_permission">Block All</string>
|
||||
|
Loading…
Reference in New Issue
Block a user