Jitsi call: don't show expanded add matrix icon if only widget is jitsi (also fix join state)

This commit is contained in:
ganfra 2021-07-27 19:16:38 +02:00
parent e259b44449
commit d2785b69df
5 changed files with 75 additions and 19 deletions

View File

@ -31,6 +31,7 @@ import im.vector.app.core.network.WifiDetector
import im.vector.app.core.pushers.PushersManager
import im.vector.app.core.utils.AssetReader
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.configuration.VectorConfiguration
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.raw.RawService
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
import javax.inject.Singleton
@Component(modules = [VectorModule::class])
@ -167,6 +169,8 @@ interface VectorComponent {
fun roomSummaryHolder(): RoomSummariesHolder
fun jitsiActiveConferenceHolder(): JitsiActiveConferenceHolder
@Component.Factory
interface Factory {
fun create(@BindsInstance context: Context): VectorComponent

View File

@ -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
}
}
}

View File

@ -87,9 +87,8 @@ import im.vector.app.core.intent.getMimeTypeFromUri
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.platform.showOptimizedSnackbar
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.CurrentCallsViewPresenter
import im.vector.app.core.ui.views.FailedMessagesWarningView
import im.vector.app.core.ui.views.NotificationAreaView
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 widgetsCount = state.activeRoomWidgets.invoke()?.size ?: 0
if (widgetsCount > 0) {
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)
} else {
val hasOnlyJitsiWidget = widgetsCount == 1 && state.hasActiveJitsiWidget()
if (widgetsCount == 0 || hasOnlyJitsiWidget) {
// icon should be default color no badge
val actionView = matrixAppsMenuItem.actionView
actionView
@ -846,6 +839,13 @@ class RoomDetailFragment @Inject constructor(
.setColorFilter(ThemeUtils.getColor(requireContext(), R.attr.vctr_content_secondary))
actionView.findViewById<TextView>(R.id.cart_badge).isVisible = false
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)
}
}
}

View File

@ -38,8 +38,8 @@ import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.mvrx.runCatchingToAsync
import im.vector.app.core.platform.VectorViewModel
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.extractConferenceUrl
import im.vector.app.features.call.lookup.CallProtocolsChecker
import im.vector.app.features.call.webrtc.WebRtcCallManager
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.matrix.android.sdk.api.MatrixCallback
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.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session
@ -121,6 +120,7 @@ class RoomDetailViewModel @AssistedInject constructor(
private val chatEffectManager: ChatEffectManager,
private val directRoomHelper: DirectRoomHelper,
private val jitsiService: JitsiService,
private val activeConferenceHolder: JitsiActiveConferenceHolder,
timelineFactory: TimelineFactory
) : VectorViewModel<RoomDetailViewState, RoomDetailAction, RoomDetailViewEvents>(initialState),
Timeline.Listener, ChatEffectManager.Delegate, CallProtocolsChecker.Listener {
@ -254,7 +254,8 @@ class RoomDetailViewModel @AssistedInject constructor(
copy(
jitsiState = jitsiState.copy(
confId = jitsiConfId,
widgetId = jitsiWidget?.widgetId
widgetId = jitsiWidget?.widgetId,
hasJoined = activeConferenceHolder.isJoined(jitsiConfId)
)
)
}
@ -363,9 +364,7 @@ class RoomDetailViewModel @AssistedInject constructor(
when (action.broadcastEvent.type) {
BroadcastEvent.Type.CONFERENCE_JOINED,
BroadcastEvent.Type.CONFERENCE_TERMINATED -> {
if (action.broadcastEvent.extractConferenceUrl()?.endsWith(state.jitsiState.confId).orFalse()) {
setState { copy(jitsiState = jitsiState.copy(hasJoined = action.broadcastEvent.type == BroadcastEvent.Type.CONFERENCE_JOINED)) }
}
setState { copy(jitsiState = jitsiState.copy(hasJoined = activeConferenceHolder.isJoined(jitsiState.confId))) }
}
else -> Unit
}
@ -683,8 +682,9 @@ class RoomDetailViewModel @AssistedInject constructor(
R.id.invite -> state.canInvite
R.id.open_matrix_apps -> true
R.id.voice_call -> state.isWebRTCCallOptionAvailable()
R.id.video_call -> state.isWebRTCCallOptionAvailable() || state.jitsiState.widgetId == null || state.jitsiState.hasJoined
R.id.join_conference -> state.jitsiState.widgetId != null && !state.jitsiState.hasJoined
R.id.video_call -> state.isWebRTCCallOptionAvailable() || state.jitsiState.confId == 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.dev_tools -> vectorPreferences.developerMode()
else -> false

View File

@ -18,7 +18,10 @@ package im.vector.app.features.home.room.detail
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MvRxState
import com.airbnb.mvrx.Success
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.room.members.ChangeMembershipState
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.sync.SyncState
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:
@ -96,7 +100,9 @@ data class RoomDetailViewState(
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
}