Merge pull request #4014 from vector-im/feature/fga/hide_jitsi_event

Jitsi: introduces ConferenceEvent
This commit is contained in:
Benoit Marty 2021-09-17 18:07:33 +02:00 committed by GitHub
commit f418683da5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 59 additions and 45 deletions

1
changelog.d/4014.misc Normal file
View file

@ -0,0 +1 @@
Introduces ConferenceEvent to abstract usage of Jitsi BroadcastEvent class.

View file

@ -28,20 +28,21 @@ import com.facebook.react.bridge.JavaOnlyMap
import org.jitsi.meet.sdk.BroadcastEmitter import org.jitsi.meet.sdk.BroadcastEmitter
import org.jitsi.meet.sdk.BroadcastEvent import org.jitsi.meet.sdk.BroadcastEvent
import org.jitsi.meet.sdk.JitsiMeet import org.jitsi.meet.sdk.JitsiMeet
import org.matrix.android.sdk.api.extensions.tryOrNull import timber.log.Timber
private const val CONFERENCE_URL_DATA_KEY = "url" private const val CONFERENCE_URL_DATA_KEY = "url"
fun BroadcastEvent.extractConferenceUrl(): String? { sealed class ConferenceEvent(open val data: Map<String, Any>) {
return when (type) { data class Terminated(override val data: Map<String, Any>) : ConferenceEvent(data)
BroadcastEvent.Type.CONFERENCE_TERMINATED, data class WillJoin(override val data: Map<String, Any>) : ConferenceEvent(data)
BroadcastEvent.Type.CONFERENCE_WILL_JOIN, data class Joined(override val data: Map<String, Any>) : ConferenceEvent(data)
BroadcastEvent.Type.CONFERENCE_JOINED -> data[CONFERENCE_URL_DATA_KEY] as? String
else -> null fun extractConferenceUrl(): String? {
return data[CONFERENCE_URL_DATA_KEY] as? String
} }
} }
class JitsiBroadcastEmitter(private val context: Context) { class ConferenceEventEmitter(private val context: Context) {
fun emitConferenceEnded() { fun emitConferenceEnded() {
val broadcastEventData = JavaOnlyMap.of(CONFERENCE_URL_DATA_KEY, JitsiMeet.getCurrentConference()) val broadcastEventData = JavaOnlyMap.of(CONFERENCE_URL_DATA_KEY, JitsiMeet.getCurrentConference())
@ -49,8 +50,9 @@ class JitsiBroadcastEmitter(private val context: Context) {
} }
} }
class JitsiBroadcastEventObserver(private val context: Context, class ConferenceEventObserver(private val context: Context,
private val onBroadcastEvent: (BroadcastEvent) -> Unit) : LifecycleObserver { private val onBroadcastEvent: (ConferenceEvent) -> Unit)
: LifecycleObserver {
// See https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-android-sdk#listening-for-broadcasted-events // See https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-android-sdk#listening-for-broadcasted-events
private val broadcastReceiver = object : BroadcastReceiver() { private val broadcastReceiver = object : BroadcastReceiver() {
@ -61,8 +63,10 @@ class JitsiBroadcastEventObserver(private val context: Context,
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun unregisterForBroadcastMessages() { fun unregisterForBroadcastMessages() {
tryOrNull("Unable to unregister receiver") { try {
LocalBroadcastManager.getInstance(context).unregisterReceiver(broadcastReceiver) LocalBroadcastManager.getInstance(context).unregisterReceiver(broadcastReceiver)
} catch (throwable: Throwable) {
Timber.v("Unable to unregister receiver")
} }
} }
@ -72,13 +76,23 @@ class JitsiBroadcastEventObserver(private val context: Context,
for (type in BroadcastEvent.Type.values()) { for (type in BroadcastEvent.Type.values()) {
intentFilter.addAction(type.action) intentFilter.addAction(type.action)
} }
tryOrNull("Unable to register receiver") { try {
LocalBroadcastManager.getInstance(context).registerReceiver(broadcastReceiver, intentFilter) LocalBroadcastManager.getInstance(context).registerReceiver(broadcastReceiver, intentFilter)
} catch (throwable: Throwable) {
Timber.v("Unable to register receiver")
} }
} }
private fun onBroadcastReceived(intent: Intent) { private fun onBroadcastReceived(intent: Intent) {
val event = BroadcastEvent(intent) val event = BroadcastEvent(intent)
onBroadcastEvent(event) val conferenceEvent = when (event.type) {
BroadcastEvent.Type.CONFERENCE_JOINED -> ConferenceEvent.Joined(event.data)
BroadcastEvent.Type.CONFERENCE_TERMINATED -> ConferenceEvent.Terminated(event.data)
BroadcastEvent.Type.CONFERENCE_WILL_JOIN -> ConferenceEvent.WillJoin(event.data)
else -> null
}
if (conferenceEvent != null) {
onBroadcastEvent(conferenceEvent)
}
} }
} }

View file

@ -18,7 +18,6 @@ package im.vector.app.features.call.conference
import android.content.Context import android.content.Context
import androidx.lifecycle.ProcessLifecycleOwner import androidx.lifecycle.ProcessLifecycleOwner
import org.jitsi.meet.sdk.BroadcastEvent
import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.orFalse
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -29,18 +28,18 @@ class JitsiActiveConferenceHolder @Inject constructor(context: Context) {
private var activeConference: String? = null private var activeConference: String? = null
init { init {
ProcessLifecycleOwner.get().lifecycle.addObserver(JitsiBroadcastEventObserver(context, this::onBroadcastEvent)) ProcessLifecycleOwner.get().lifecycle.addObserver(ConferenceEventObserver(context, this::onBroadcastEvent))
} }
fun isJoined(confId: String?): Boolean { fun isJoined(confId: String?): Boolean {
return confId != null && activeConference?.endsWith(confId).orFalse() return confId != null && activeConference?.endsWith(confId).orFalse()
} }
private fun onBroadcastEvent(broadcastEvent: BroadcastEvent) { private fun onBroadcastEvent(conferenceEvent: ConferenceEvent) {
when (broadcastEvent.type) { when (conferenceEvent) {
BroadcastEvent.Type.CONFERENCE_JOINED -> activeConference = broadcastEvent.extractConferenceUrl() is ConferenceEvent.Joined -> activeConference = conferenceEvent.extractConferenceUrl()
BroadcastEvent.Type.CONFERENCE_TERMINATED -> activeConference = null is ConferenceEvent.Terminated -> activeConference = null
else -> Unit else -> Unit
} }
} }
} }

View file

@ -39,13 +39,13 @@ import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivityJitsiBinding import im.vector.app.databinding.ActivityJitsiBinding
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import org.jitsi.meet.sdk.BroadcastEvent
import org.jitsi.meet.sdk.JitsiMeet import org.jitsi.meet.sdk.JitsiMeet
import org.jitsi.meet.sdk.JitsiMeetActivityDelegate import org.jitsi.meet.sdk.JitsiMeetActivityDelegate
import org.jitsi.meet.sdk.JitsiMeetActivityInterface import org.jitsi.meet.sdk.JitsiMeetActivityInterface
import org.jitsi.meet.sdk.JitsiMeetConferenceOptions import org.jitsi.meet.sdk.JitsiMeetConferenceOptions
import org.jitsi.meet.sdk.JitsiMeetView import org.jitsi.meet.sdk.JitsiMeetView
import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.util.JsonDict
import timber.log.Timber import timber.log.Timber
import java.net.URL import java.net.URL
import javax.inject.Inject import javax.inject.Inject
@ -87,7 +87,7 @@ class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMee
JitsiCallViewEvents.LeaveConference -> handleLeaveConference() JitsiCallViewEvents.LeaveConference -> handleLeaveConference()
}.exhaustive }.exhaustive
} }
lifecycle.addObserver(JitsiBroadcastEventObserver(this, this::onBroadcastEvent)) lifecycle.addObserver(ConferenceEventObserver(this, this::onBroadcastEvent))
} }
override fun onResume() { override fun onResume() {
@ -113,7 +113,7 @@ class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMee
jitsiMeetView?.dispose() jitsiMeetView?.dispose()
// Fake emitting CONFERENCE_TERMINATED event when currentConf is not null (probably when closing the PiP screen). // Fake emitting CONFERENCE_TERMINATED event when currentConf is not null (probably when closing the PiP screen).
if (currentConf != null) { if (currentConf != null) {
JitsiBroadcastEmitter(this).emitConferenceEnded() ConferenceEventEmitter(this).emitConferenceEnded()
} }
JitsiMeetActivityDelegate.onHostDestroy(this) JitsiMeetActivityDelegate.onHostDestroy(this)
super.onDestroy() super.onDestroy()
@ -223,15 +223,15 @@ class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMee
JitsiMeetActivityDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults) JitsiMeetActivityDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults)
} }
private fun onBroadcastEvent(event: BroadcastEvent) { private fun onBroadcastEvent(event: ConferenceEvent) {
Timber.v("Broadcast received: ${event.type}") Timber.v("Broadcast received: $event")
when (event.type) { when (event) {
BroadcastEvent.Type.CONFERENCE_TERMINATED -> onConferenceTerminated(event.data) is ConferenceEvent.Terminated -> onConferenceTerminated(event.data)
else -> Unit else -> Unit
} }
} }
private fun onConferenceTerminated(data: Map<String, Any>) { private fun onConferenceTerminated(data: JsonDict) {
Timber.v("JitsiMeetViewListener.onConferenceTerminated()") Timber.v("JitsiMeetViewListener.onConferenceTerminated()")
// Do not finish if there is an error // Do not finish if there is an error
if (data["error"] == null) { if (data["error"] == null) {

View file

@ -19,7 +19,7 @@ package im.vector.app.features.home.room.detail
import android.net.Uri import android.net.Uri
import android.view.View import android.view.View
import im.vector.app.core.platform.VectorViewModelAction import im.vector.app.core.platform.VectorViewModelAction
import org.jitsi.meet.sdk.BroadcastEvent import im.vector.app.features.call.conference.ConferenceEvent
import org.matrix.android.sdk.api.session.content.ContentAttachmentData import org.matrix.android.sdk.api.session.content.ContentAttachmentData
import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent
@ -97,7 +97,7 @@ sealed class RoomDetailAction : VectorViewModelAction {
data class EnsureNativeWidgetAllowed(val widget: Widget, data class EnsureNativeWidgetAllowed(val widget: Widget,
val userJustAccepted: Boolean, val userJustAccepted: Boolean,
val grantedEvents: RoomDetailViewEvents) : RoomDetailAction() val grantedEvents: RoomDetailViewEvents) : RoomDetailAction()
data class UpdateJoinJitsiCallStatus(val jitsiEvent: BroadcastEvent): RoomDetailAction() data class UpdateJoinJitsiCallStatus(val conferenceEvent: ConferenceEvent): RoomDetailAction()
data class OpenOrCreateDm(val userId: String) : RoomDetailAction() data class OpenOrCreateDm(val userId: String) : RoomDetailAction()
data class JumpToReadReceipt(val userId: String) : RoomDetailAction() data class JumpToReadReceipt(val userId: String) : RoomDetailAction()

View file

@ -123,8 +123,9 @@ import im.vector.app.features.attachments.preview.AttachmentsPreviewArgs
import im.vector.app.features.attachments.toGroupedContentAttachmentData import im.vector.app.features.attachments.toGroupedContentAttachmentData
import im.vector.app.features.call.SharedKnownCallsViewModel import im.vector.app.features.call.SharedKnownCallsViewModel
import im.vector.app.features.call.VectorCallActivity import im.vector.app.features.call.VectorCallActivity
import im.vector.app.features.call.conference.JitsiBroadcastEmitter import im.vector.app.features.call.conference.ConferenceEvent
import im.vector.app.features.call.conference.JitsiBroadcastEventObserver import im.vector.app.features.call.conference.ConferenceEventEmitter
import im.vector.app.features.call.conference.ConferenceEventObserver
import im.vector.app.features.call.conference.JitsiCallViewModel import im.vector.app.features.call.conference.JitsiCallViewModel
import im.vector.app.features.call.webrtc.WebRtcCallManager import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.command.Command import im.vector.app.features.command.Command
@ -184,7 +185,6 @@ import nl.dionsegijn.konfetti.models.Shape
import nl.dionsegijn.konfetti.models.Size import nl.dionsegijn.konfetti.models.Size
import org.billcarsonfr.jsonviewer.JSonViewerDialog import org.billcarsonfr.jsonviewer.JSonViewerDialog
import org.commonmark.parser.Parser import org.commonmark.parser.Parser
import org.jitsi.meet.sdk.BroadcastEvent
import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.content.ContentAttachmentData import org.matrix.android.sdk.api.session.content.ContentAttachmentData
@ -324,7 +324,7 @@ class RoomDetailFragment @Inject constructor(
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
lifecycle.addObserver(JitsiBroadcastEventObserver(vectorBaseActivity, this::onBroadcastJitsiEvent)) lifecycle.addObserver(ConferenceEventObserver(vectorBaseActivity, this::onBroadcastJitsiEvent))
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
sharedActionViewModel = activityViewModelProvider.get(MessageSharedActionViewModel::class.java) sharedActionViewModel = activityViewModelProvider.get(MessageSharedActionViewModel::class.java)
knownCallsViewModel = activityViewModelProvider.get(SharedKnownCallsViewModel::class.java) knownCallsViewModel = activityViewModelProvider.get(SharedKnownCallsViewModel::class.java)
@ -366,10 +366,10 @@ class RoomDetailFragment @Inject constructor(
knownCallsViewModel knownCallsViewModel
.liveKnownCalls .liveKnownCalls
.observe(viewLifecycleOwner, { .observe(viewLifecycleOwner) {
currentCallsViewPresenter.updateCall(callManager.getCurrentCall(), it) currentCallsViewPresenter.updateCall(callManager.getCurrentCall(), it)
invalidateOptionsMenu() invalidateOptionsMenu()
}) }
roomDetailViewModel.selectSubscribe(RoomDetailViewState::canShowJumpToReadMarker, RoomDetailViewState::unreadState) { _, _ -> roomDetailViewModel.selectSubscribe(RoomDetailViewState::canShowJumpToReadMarker, RoomDetailViewState::unreadState) { _, _ ->
updateJumpToReadMarkerViewVisibility() updateJumpToReadMarkerViewVisibility()
@ -454,11 +454,11 @@ class RoomDetailFragment @Inject constructor(
} }
private fun leaveJitsiConference() { private fun leaveJitsiConference() {
JitsiBroadcastEmitter(vectorBaseActivity).emitConferenceEnded() ConferenceEventEmitter(vectorBaseActivity).emitConferenceEnded()
} }
private fun onBroadcastJitsiEvent(jitsiEvent: BroadcastEvent) { private fun onBroadcastJitsiEvent(conferenceEvent: ConferenceEvent) {
roomDetailViewModel.handle(RoomDetailAction.UpdateJoinJitsiCallStatus(jitsiEvent)) roomDetailViewModel.handle(RoomDetailAction.UpdateJoinJitsiCallStatus(conferenceEvent))
} }
private fun onCannotRecord() { private fun onCannotRecord() {

View file

@ -40,6 +40,7 @@ import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.features.call.conference.JitsiActiveConferenceHolder import im.vector.app.features.call.conference.JitsiActiveConferenceHolder
import im.vector.app.features.attachments.toContentAttachmentData import im.vector.app.features.attachments.toContentAttachmentData
import im.vector.app.features.call.conference.ConferenceEvent
import im.vector.app.features.call.conference.JitsiService import im.vector.app.features.call.conference.JitsiService
import im.vector.app.features.call.lookup.CallProtocolsChecker import im.vector.app.features.call.lookup.CallProtocolsChecker
import im.vector.app.features.call.webrtc.WebRtcCallManager import im.vector.app.features.call.webrtc.WebRtcCallManager
@ -66,7 +67,6 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.commonmark.parser.Parser import org.commonmark.parser.Parser
import org.commonmark.renderer.html.HtmlRenderer import org.commonmark.renderer.html.HtmlRenderer
import org.jitsi.meet.sdk.BroadcastEvent
import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.MatrixPatterns import org.matrix.android.sdk.api.MatrixPatterns
import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.extensions.tryOrNull
@ -368,12 +368,12 @@ class RoomDetailViewModel @AssistedInject constructor(
} }
return@withState return@withState
} }
when (action.jitsiEvent.type) { when (action.conferenceEvent) {
BroadcastEvent.Type.CONFERENCE_JOINED, is ConferenceEvent.Joined,
BroadcastEvent.Type.CONFERENCE_TERMINATED -> { is ConferenceEvent.Terminated -> {
setState { copy(jitsiState = jitsiState.copy(hasJoined = activeConferenceHolder.isJoined(jitsiState.confId))) } setState { copy(jitsiState = jitsiState.copy(hasJoined = activeConferenceHolder.isJoined(jitsiState.confId))) }
} }
else -> Unit else -> Unit
} }
} }