Jitsi call: don't show expanded add matrix icon if only widget is jitsi (also fix join state)
This commit is contained in:
parent
e259b44449
commit
d2785b69df
|
@ -31,6 +31,7 @@ import im.vector.app.core.network.WifiDetector
|
||||||
import im.vector.app.core.pushers.PushersManager
|
import im.vector.app.core.pushers.PushersManager
|
||||||
import im.vector.app.core.utils.AssetReader
|
import im.vector.app.core.utils.AssetReader
|
||||||
import im.vector.app.core.utils.DimensionConverter
|
import im.vector.app.core.utils.DimensionConverter
|
||||||
|
import im.vector.app.features.call.conference.JitsiActiveConferenceHolder
|
||||||
import im.vector.app.features.call.webrtc.WebRtcCallManager
|
import im.vector.app.features.call.webrtc.WebRtcCallManager
|
||||||
import im.vector.app.features.configuration.VectorConfiguration
|
import im.vector.app.features.configuration.VectorConfiguration
|
||||||
import im.vector.app.features.crypto.keysrequest.KeyRequestHandler
|
import im.vector.app.features.crypto.keysrequest.KeyRequestHandler
|
||||||
|
@ -65,6 +66,7 @@ import org.matrix.android.sdk.api.auth.AuthenticationService
|
||||||
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
|
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
|
||||||
import org.matrix.android.sdk.api.raw.RawService
|
import org.matrix.android.sdk.api.raw.RawService
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Component(modules = [VectorModule::class])
|
@Component(modules = [VectorModule::class])
|
||||||
|
@ -167,6 +169,8 @@ interface VectorComponent {
|
||||||
|
|
||||||
fun roomSummaryHolder(): RoomSummariesHolder
|
fun roomSummaryHolder(): RoomSummariesHolder
|
||||||
|
|
||||||
|
fun jitsiActiveConferenceHolder(): JitsiActiveConferenceHolder
|
||||||
|
|
||||||
@Component.Factory
|
@Component.Factory
|
||||||
interface Factory {
|
interface Factory {
|
||||||
fun create(@BindsInstance context: Context): VectorComponent
|
fun create(@BindsInstance context: Context): VectorComponent
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.conference
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.lifecycle.ProcessLifecycleOwner
|
||||||
|
import org.jitsi.meet.sdk.BroadcastEvent
|
||||||
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class JitsiActiveConferenceHolder @Inject constructor(context: Context) {
|
||||||
|
|
||||||
|
private var activeConference: String? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
ProcessLifecycleOwner.get().lifecycle.addObserver(JitsiBroadcastEventObserver(context, this::onBroadcastEvent))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isJoined(confId: String?): Boolean {
|
||||||
|
return confId != null && activeConference?.endsWith(confId).orFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onBroadcastEvent(broadcastEvent: BroadcastEvent) {
|
||||||
|
when (broadcastEvent.type) {
|
||||||
|
BroadcastEvent.Type.CONFERENCE_JOINED -> activeConference = broadcastEvent.extractConferenceUrl()
|
||||||
|
BroadcastEvent.Type.CONFERENCE_TERMINATED -> activeConference = null
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -87,9 +87,8 @@ import im.vector.app.core.intent.getMimeTypeFromUri
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
import im.vector.app.core.platform.showOptimizedSnackbar
|
import im.vector.app.core.platform.showOptimizedSnackbar
|
||||||
import im.vector.app.core.resources.ColorProvider
|
import im.vector.app.core.resources.ColorProvider
|
||||||
import im.vector.app.core.ui.views.CurrentCallsViewPresenter
|
|
||||||
|
|
||||||
import im.vector.app.core.ui.views.CurrentCallsView
|
import im.vector.app.core.ui.views.CurrentCallsView
|
||||||
|
import im.vector.app.core.ui.views.CurrentCallsViewPresenter
|
||||||
import im.vector.app.core.ui.views.FailedMessagesWarningView
|
import im.vector.app.core.ui.views.FailedMessagesWarningView
|
||||||
import im.vector.app.core.ui.views.NotificationAreaView
|
import im.vector.app.core.ui.views.NotificationAreaView
|
||||||
import im.vector.app.core.utils.Debouncer
|
import im.vector.app.core.utils.Debouncer
|
||||||
|
@ -831,14 +830,8 @@ class RoomDetailFragment @Inject constructor(
|
||||||
|
|
||||||
val matrixAppsMenuItem = menu.findItem(R.id.open_matrix_apps)
|
val matrixAppsMenuItem = menu.findItem(R.id.open_matrix_apps)
|
||||||
val widgetsCount = state.activeRoomWidgets.invoke()?.size ?: 0
|
val widgetsCount = state.activeRoomWidgets.invoke()?.size ?: 0
|
||||||
if (widgetsCount > 0) {
|
val hasOnlyJitsiWidget = widgetsCount == 1 && state.hasActiveJitsiWidget()
|
||||||
val actionView = matrixAppsMenuItem.actionView
|
if (widgetsCount == 0 || hasOnlyJitsiWidget) {
|
||||||
actionView
|
|
||||||
.findViewById<ImageView>(R.id.action_view_icon_image)
|
|
||||||
.setColorFilter(colorProvider.getColorFromAttribute(R.attr.colorPrimary))
|
|
||||||
actionView.findViewById<TextView>(R.id.cart_badge).setTextOrHide("$widgetsCount")
|
|
||||||
matrixAppsMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
|
|
||||||
} else {
|
|
||||||
// icon should be default color no badge
|
// icon should be default color no badge
|
||||||
val actionView = matrixAppsMenuItem.actionView
|
val actionView = matrixAppsMenuItem.actionView
|
||||||
actionView
|
actionView
|
||||||
|
@ -846,6 +839,13 @@ class RoomDetailFragment @Inject constructor(
|
||||||
.setColorFilter(ThemeUtils.getColor(requireContext(), R.attr.vctr_content_secondary))
|
.setColorFilter(ThemeUtils.getColor(requireContext(), R.attr.vctr_content_secondary))
|
||||||
actionView.findViewById<TextView>(R.id.cart_badge).isVisible = false
|
actionView.findViewById<TextView>(R.id.cart_badge).isVisible = false
|
||||||
matrixAppsMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
|
matrixAppsMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
|
||||||
|
} else {
|
||||||
|
val actionView = matrixAppsMenuItem.actionView
|
||||||
|
actionView
|
||||||
|
.findViewById<ImageView>(R.id.action_view_icon_image)
|
||||||
|
.setColorFilter(colorProvider.getColorFromAttribute(R.attr.colorPrimary))
|
||||||
|
actionView.findViewById<TextView>(R.id.cart_badge).setTextOrHide("$widgetsCount")
|
||||||
|
matrixAppsMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,8 @@ import im.vector.app.core.extensions.exhaustive
|
||||||
import im.vector.app.core.mvrx.runCatchingToAsync
|
import im.vector.app.core.mvrx.runCatchingToAsync
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
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.JitsiService
|
import im.vector.app.features.call.conference.JitsiService
|
||||||
import im.vector.app.features.call.conference.extractConferenceUrl
|
|
||||||
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
|
||||||
import im.vector.app.features.command.CommandParser
|
import im.vector.app.features.command.CommandParser
|
||||||
|
@ -67,7 +67,6 @@ import org.commonmark.renderer.html.HtmlRenderer
|
||||||
import org.jitsi.meet.sdk.BroadcastEvent
|
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.orFalse
|
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
@ -121,6 +120,7 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||||
private val chatEffectManager: ChatEffectManager,
|
private val chatEffectManager: ChatEffectManager,
|
||||||
private val directRoomHelper: DirectRoomHelper,
|
private val directRoomHelper: DirectRoomHelper,
|
||||||
private val jitsiService: JitsiService,
|
private val jitsiService: JitsiService,
|
||||||
|
private val activeConferenceHolder: JitsiActiveConferenceHolder,
|
||||||
timelineFactory: TimelineFactory
|
timelineFactory: TimelineFactory
|
||||||
) : VectorViewModel<RoomDetailViewState, RoomDetailAction, RoomDetailViewEvents>(initialState),
|
) : VectorViewModel<RoomDetailViewState, RoomDetailAction, RoomDetailViewEvents>(initialState),
|
||||||
Timeline.Listener, ChatEffectManager.Delegate, CallProtocolsChecker.Listener {
|
Timeline.Listener, ChatEffectManager.Delegate, CallProtocolsChecker.Listener {
|
||||||
|
@ -254,7 +254,8 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||||
copy(
|
copy(
|
||||||
jitsiState = jitsiState.copy(
|
jitsiState = jitsiState.copy(
|
||||||
confId = jitsiConfId,
|
confId = jitsiConfId,
|
||||||
widgetId = jitsiWidget?.widgetId
|
widgetId = jitsiWidget?.widgetId,
|
||||||
|
hasJoined = activeConferenceHolder.isJoined(jitsiConfId)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -363,9 +364,7 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||||
when (action.broadcastEvent.type) {
|
when (action.broadcastEvent.type) {
|
||||||
BroadcastEvent.Type.CONFERENCE_JOINED,
|
BroadcastEvent.Type.CONFERENCE_JOINED,
|
||||||
BroadcastEvent.Type.CONFERENCE_TERMINATED -> {
|
BroadcastEvent.Type.CONFERENCE_TERMINATED -> {
|
||||||
if (action.broadcastEvent.extractConferenceUrl()?.endsWith(state.jitsiState.confId).orFalse()) {
|
setState { copy(jitsiState = jitsiState.copy(hasJoined = activeConferenceHolder.isJoined(jitsiState.confId))) }
|
||||||
setState { copy(jitsiState = jitsiState.copy(hasJoined = action.broadcastEvent.type == BroadcastEvent.Type.CONFERENCE_JOINED)) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
|
@ -683,8 +682,9 @@ class RoomDetailViewModel @AssistedInject constructor(
|
||||||
R.id.invite -> state.canInvite
|
R.id.invite -> state.canInvite
|
||||||
R.id.open_matrix_apps -> true
|
R.id.open_matrix_apps -> true
|
||||||
R.id.voice_call -> state.isWebRTCCallOptionAvailable()
|
R.id.voice_call -> state.isWebRTCCallOptionAvailable()
|
||||||
R.id.video_call -> state.isWebRTCCallOptionAvailable() || state.jitsiState.widgetId == null || state.jitsiState.hasJoined
|
R.id.video_call -> state.isWebRTCCallOptionAvailable() || state.jitsiState.confId == null || state.jitsiState.hasJoined
|
||||||
R.id.join_conference -> state.jitsiState.widgetId != null && !state.jitsiState.hasJoined
|
// Show Join conference button only if there is an active conf id not joined. Otherwise fallback to default video disabled. ^
|
||||||
|
R.id.join_conference -> state.jitsiState.confId != null && !state.jitsiState.hasJoined
|
||||||
R.id.search -> true
|
R.id.search -> true
|
||||||
R.id.dev_tools -> vectorPreferences.developerMode()
|
R.id.dev_tools -> vectorPreferences.developerMode()
|
||||||
else -> false
|
else -> false
|
||||||
|
|
|
@ -18,7 +18,10 @@ package im.vector.app.features.home.room.detail
|
||||||
|
|
||||||
import com.airbnb.mvrx.Async
|
import com.airbnb.mvrx.Async
|
||||||
import com.airbnb.mvrx.MvRxState
|
import com.airbnb.mvrx.MvRxState
|
||||||
|
import com.airbnb.mvrx.Success
|
||||||
import com.airbnb.mvrx.Uninitialized
|
import com.airbnb.mvrx.Uninitialized
|
||||||
|
import im.vector.app.core.platform.ButtonStateView
|
||||||
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
|
@ -26,6 +29,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
import org.matrix.android.sdk.api.session.sync.SyncState
|
import org.matrix.android.sdk.api.session.sync.SyncState
|
||||||
import org.matrix.android.sdk.api.session.widgets.model.Widget
|
import org.matrix.android.sdk.api.session.widgets.model.Widget
|
||||||
|
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes the current send mode:
|
* Describes the current send mode:
|
||||||
|
@ -96,7 +100,9 @@ data class RoomDetailViewState(
|
||||||
|
|
||||||
fun isWebRTCCallOptionAvailable() = (asyncRoomSummary.invoke()?.joinedMembersCount ?: 0) <= 2
|
fun isWebRTCCallOptionAvailable() = (asyncRoomSummary.invoke()?.joinedMembersCount ?: 0) <= 2
|
||||||
|
|
||||||
fun hasActiveJitsiWidget() = jitsiState.confId != null
|
// This checks directly on the active room widgets.
|
||||||
|
// It can differs for a short period of time on the JitsiState as its computed async.
|
||||||
|
fun hasActiveJitsiWidget() = activeRoomWidgets()?.any { it.type == WidgetType.Jitsi && it.isActive }.orFalse()
|
||||||
|
|
||||||
fun isDm() = asyncRoomSummary()?.isDirect == true
|
fun isDm() = asyncRoomSummary()?.isDirect == true
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue