mirror of
https://github.com/element-hq/element-android
synced 2024-11-24 02:15:35 +03:00
Merge pull request #4014 from vector-im/feature/fga/hide_jitsi_event
Jitsi: introduces ConferenceEvent
This commit is contained in:
commit
f418683da5
7 changed files with 59 additions and 45 deletions
1
changelog.d/4014.misc
Normal file
1
changelog.d/4014.misc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Introduces ConferenceEvent to abstract usage of Jitsi BroadcastEvent class.
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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,17 +28,17 @@ 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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,9 +368,9 @@ 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
|
||||||
|
|
Loading…
Reference in a new issue