mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 05:31:21 +03:00
Check native widget permissions
This commit is contained in:
parent
3ce1e3e5d9
commit
c911d9c7ff
9 changed files with 129 additions and 25 deletions
|
@ -26,6 +26,7 @@ import com.squareup.inject.assisted.AssistedInject
|
|||
import im.vector.app.core.platform.VectorViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.call.WebRtcPeerConnectionManager
|
||||
import org.jitsi.meet.sdk.JitsiMeetUserInfo
|
||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||
|
@ -43,7 +44,8 @@ class JitsiCallViewModel @AssistedInject constructor(
|
|||
@Assisted initialState: JitsiCallViewState,
|
||||
@Assisted val args: VectorJitsiActivity.Args,
|
||||
val session: Session,
|
||||
val webRtcPeerConnectionManager: WebRtcPeerConnectionManager
|
||||
val webRtcPeerConnectionManager: WebRtcPeerConnectionManager,
|
||||
val stringProvider: StringProvider
|
||||
) : VectorViewModel<JitsiCallViewState, JitsiCallViewActions, JitsiCallViewEvents>(initialState) {
|
||||
|
||||
@AssistedInject.Factory
|
||||
|
@ -71,7 +73,7 @@ class JitsiCallViewModel @AssistedInject constructor(
|
|||
if (jitsiWidget != null) {
|
||||
val uri = Uri.parse(jitsiWidget.computedUrl)
|
||||
val confId = uri.getQueryParameter("confId")
|
||||
val ppt = jitsiWidget.computedUrl?.let { JitsiWidgetProperties(it) }
|
||||
val ppt = jitsiWidget.computedUrl?.let { JitsiWidgetProperties(it, stringProvider) }
|
||||
setState {
|
||||
copy(
|
||||
widget = Success(jitsiWidget),
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
package im.vector.app.features.call.conference
|
||||
|
||||
import android.net.Uri
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
|
||||
class JitsiWidgetProperties(private val uriString: String) {
|
||||
val domain: String by lazy { configs["conferenceDomain"] ?: DEFAULT_JITSI_DOMAIN }
|
||||
class JitsiWidgetProperties(private val uriString: String, val stringProvider: StringProvider) {
|
||||
val domain: String by lazy { configs["conferenceDomain"] ?: stringProvider.getString(R.string.preferred_jitsi_domain) }
|
||||
val displayName: String? by lazy { configs["displayName"] }
|
||||
val avatarUrl: String? by lazy { configs["avatarUrl"] }
|
||||
|
||||
|
@ -34,4 +36,3 @@ class JitsiWidgetProperties(private val uriString: String) {
|
|||
}
|
||||
}
|
||||
|
||||
private const val DEFAULT_JITSI_DOMAIN = "jitsi.riot.im"
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageStickerConte
|
|||
import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent
|
||||
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
import org.matrix.android.sdk.api.session.widgets.model.Widget
|
||||
|
||||
sealed class RoomDetailAction : VectorViewModelAction {
|
||||
data class UserIsTyping(val isTyping: Boolean) : RoomDetailAction()
|
||||
|
@ -83,4 +84,5 @@ sealed class RoomDetailAction : VectorViewModelAction {
|
|||
object ManageIntegrations: RoomDetailAction()
|
||||
data class AddJitsiWidget(val video: Boolean): RoomDetailAction()
|
||||
data class RemoveWidget(val widgetId: String): RoomDetailAction()
|
||||
data class EnsureNativeWidgetAllowed(val widget: Widget, val grantedEvents: RoomDetailViewEvents) : RoomDetailAction()
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ import im.vector.app.features.room.RequireActiveMembershipAction
|
|||
import im.vector.app.features.room.RequireActiveMembershipViewEvents
|
||||
import im.vector.app.features.room.RequireActiveMembershipViewModel
|
||||
import im.vector.app.features.room.RequireActiveMembershipViewState
|
||||
import im.vector.app.features.widgets.permissions.RoomWidgetPermissionViewModel
|
||||
import im.vector.app.features.widgets.permissions.RoomWidgetPermissionViewState
|
||||
import kotlinx.android.synthetic.main.activity_room_detail.*
|
||||
import kotlinx.android.synthetic.main.merge_overlay_waiting_view.*
|
||||
import javax.inject.Inject
|
||||
|
@ -42,7 +44,8 @@ import javax.inject.Inject
|
|||
class RoomDetailActivity :
|
||||
VectorBaseActivity(),
|
||||
ToolbarConfigurable,
|
||||
RequireActiveMembershipViewModel.Factory {
|
||||
RequireActiveMembershipViewModel.Factory,
|
||||
RoomWidgetPermissionViewModel.Factory {
|
||||
|
||||
override fun getLayoutRes() = R.layout.activity_room_detail
|
||||
|
||||
|
@ -57,6 +60,12 @@ class RoomDetailActivity :
|
|||
return requireActiveMembershipViewModelFactory.create(initialState.copy(roomId = currentRoomId ?: ""))
|
||||
}
|
||||
|
||||
@Inject
|
||||
lateinit var permissionsViewModelFactory: RoomWidgetPermissionViewModel.Factory
|
||||
override fun create(initialState: RoomWidgetPermissionViewState): RoomWidgetPermissionViewModel {
|
||||
return permissionsViewModelFactory.create(initialState)
|
||||
}
|
||||
|
||||
override fun injectWith(injector: ScreenComponent) {
|
||||
super.injectWith(injector)
|
||||
injector.inject(this)
|
||||
|
|
|
@ -151,6 +151,9 @@ import im.vector.app.features.settings.VectorSettingsActivity
|
|||
import im.vector.app.features.share.SharedData
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import im.vector.app.features.widgets.WidgetActivity
|
||||
import im.vector.app.features.widgets.WidgetArgs
|
||||
import im.vector.app.features.widgets.WidgetKind
|
||||
import im.vector.app.features.widgets.permissions.RoomWidgetPermissionBottomSheet
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.permalinks.PermalinkFactory
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
|
@ -223,7 +226,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
AttachmentTypeSelectorView.Callback,
|
||||
AttachmentsHelper.Callback,
|
||||
// RoomWidgetsBannerView.Callback,
|
||||
ActiveCallView.Callback {
|
||||
ActiveCallView.Callback{
|
||||
|
||||
companion object {
|
||||
|
||||
|
@ -360,10 +363,35 @@ class RoomDetailFragment @Inject constructor(
|
|||
is RoomDetailViewEvents.JoinJitsiConference -> joinJitsiRoom(it.widget, it.withVideo)
|
||||
RoomDetailViewEvents.ShowWaitingView -> vectorBaseActivity.showWaitingView()
|
||||
RoomDetailViewEvents.HideWaitingView -> vectorBaseActivity.hideWaitingView()
|
||||
is RoomDetailViewEvents.RequestNativeWidgetPermission -> requestNativeWidgetPermission(it)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestNativeWidgetPermission(it: RoomDetailViewEvents.RequestNativeWidgetPermission) {
|
||||
val tag = RoomWidgetPermissionBottomSheet::class.java.name
|
||||
val dFrag = childFragmentManager
|
||||
.findFragmentByTag(tag) as? RoomWidgetPermissionBottomSheet
|
||||
if (dFrag != null && dFrag.dialog?.isShowing == true && !dFrag.isRemoving) {
|
||||
return
|
||||
} else {
|
||||
RoomWidgetPermissionBottomSheet
|
||||
.newInstance(WidgetArgs(
|
||||
baseUrl = it.domain,
|
||||
kind = WidgetKind.ROOM,
|
||||
roomId = roomDetailArgs.roomId,
|
||||
widgetId = it.widget.widgetId
|
||||
)).apply {
|
||||
directListener = { granted ->
|
||||
if (granted) {
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnsureNativeWidgetAllowed(it.widget, it.grantedEvents))
|
||||
}
|
||||
}
|
||||
}
|
||||
.show(childFragmentManager, tag)
|
||||
}
|
||||
}
|
||||
|
||||
private fun openIntegrationManager(screen: String? = null) {
|
||||
navigator.openIntegrationManager(
|
||||
fragment = this,
|
||||
|
@ -376,11 +404,18 @@ class RoomDetailFragment @Inject constructor(
|
|||
private fun setupConfBannerView() {
|
||||
activeConferenceView.callback = object : ActiveConferenceView.Callback {
|
||||
override fun onTapJoinAudio(jitsiWidget: Widget) {
|
||||
joinJitsiRoom(jitsiWidget, false)
|
||||
// need to check if allowed first
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnsureNativeWidgetAllowed(
|
||||
jitsiWidget,
|
||||
RoomDetailViewEvents.JoinJitsiConference(jitsiWidget, false))
|
||||
)
|
||||
}
|
||||
|
||||
override fun onTapJoinVideo(jitsiWidget: Widget) {
|
||||
joinJitsiRoom(jitsiWidget, true)
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnsureNativeWidgetAllowed(
|
||||
jitsiWidget,
|
||||
RoomDetailViewEvents.JoinJitsiConference(jitsiWidget, true))
|
||||
)
|
||||
}
|
||||
|
||||
override fun onDelete(jitsiWidget: Widget) {
|
||||
|
|
|
@ -73,6 +73,7 @@ sealed class RoomDetailViewEvents : VectorViewEvents {
|
|||
|
||||
object OpenIntegrationManager: RoomDetailViewEvents()
|
||||
object OpenActiveWidgetBottomSheet: RoomDetailViewEvents()
|
||||
data class RequestNativeWidgetPermission(val widget: Widget, val domain: String, val grantedEvents: RoomDetailViewEvents) : RoomDetailViewEvents()
|
||||
|
||||
object MessageSent : SendMessageResult()
|
||||
data class JoinRoomCommandSuccess(val roomId: String) : SendMessageResult()
|
||||
|
|
|
@ -281,6 +281,7 @@ class RoomDetailViewModel @AssistedInject constructor(
|
|||
is RoomDetailAction.ManageIntegrations -> handleManageIntegrations()
|
||||
is RoomDetailAction.AddJitsiWidget -> handleAddJitsiConference(action)
|
||||
is RoomDetailAction.RemoveWidget -> handleDeleteWidget(action.widgetId)
|
||||
is RoomDetailAction.EnsureNativeWidgetAllowed -> handleCheckWidgetAllowed(action)
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
|
@ -411,6 +412,25 @@ class RoomDetailViewModel @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleCheckWidgetAllowed(action: RoomDetailAction.EnsureNativeWidgetAllowed) {
|
||||
val widget = action.widget
|
||||
val domain = action.widget.widgetContent.data["domain"] as? String ?: ""
|
||||
val isAllowed = if (widget.type == WidgetType.Jitsi) {
|
||||
widget.senderInfo?.userId == session.myUserId
|
||||
|| session.integrationManagerService().isNativeWidgetDomainAllowed(
|
||||
action.widget.type.preferred,
|
||||
domain
|
||||
)
|
||||
} else false
|
||||
|
||||
if (isAllowed) {
|
||||
_viewEvents.post(action.grantedEvents)
|
||||
} else {
|
||||
// we need to request permission
|
||||
_viewEvents.post(RoomDetailViewEvents.RequestNativeWidgetPermission(widget, domain, action.grantedEvents))
|
||||
}
|
||||
}
|
||||
|
||||
private fun startTrackingUnreadMessages() {
|
||||
trackUnreadMessages.set(true)
|
||||
setState { copy(canShowJumpToReadMarker = false) }
|
||||
|
|
|
@ -48,6 +48,9 @@ class RoomWidgetPermissionBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
|||
injector.inject(this)
|
||||
}
|
||||
|
||||
// Use this if you don't need to full activity view model
|
||||
var directListener: ((Boolean) -> Unit)? = null
|
||||
|
||||
override fun invalidate() = withState(viewModel) { state ->
|
||||
super.invalidate()
|
||||
val permissionData = state.permissionData() ?: return@withState
|
||||
|
@ -89,6 +92,7 @@ class RoomWidgetPermissionBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
|||
fun doDecline() {
|
||||
viewModel.handle(RoomWidgetPermissionActions.BlockWidget)
|
||||
// optimistic dismiss
|
||||
directListener?.invoke(false)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
|
@ -96,6 +100,7 @@ class RoomWidgetPermissionBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
|||
fun doAccept() {
|
||||
viewModel.handle(RoomWidgetPermissionActions.AllowWidget)
|
||||
// optimistic dismiss
|
||||
directListener?.invoke(true)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ import org.matrix.android.sdk.api.session.Session
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.session.widgets.model.WidgetType
|
||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||
import org.matrix.android.sdk.rx.rx
|
||||
import timber.log.Timber
|
||||
import java.net.URL
|
||||
|
@ -57,20 +59,33 @@ class RoomWidgetPermissionViewModel @AssistedInject constructor(@Assisted val in
|
|||
}
|
||||
// TODO check from widget urls the perms that should be shown?
|
||||
// For now put all
|
||||
val infoShared = listOf(
|
||||
R.string.room_widget_permission_display_name,
|
||||
R.string.room_widget_permission_avatar_url,
|
||||
R.string.room_widget_permission_user_id,
|
||||
R.string.room_widget_permission_theme,
|
||||
R.string.room_widget_permission_widget_id,
|
||||
R.string.room_widget_permission_room_id
|
||||
)
|
||||
RoomWidgetPermissionViewState.WidgetPermissionData(
|
||||
widget = widget,
|
||||
isWebviewWidget = true,
|
||||
permissionsList = infoShared,
|
||||
widgetDomain = domain
|
||||
)
|
||||
if (widget.type == WidgetType.Jitsi) {
|
||||
val infoShared = listOf(
|
||||
R.string.room_widget_permission_display_name,
|
||||
R.string.room_widget_permission_avatar_url
|
||||
)
|
||||
RoomWidgetPermissionViewState.WidgetPermissionData(
|
||||
widget = widget,
|
||||
isWebviewWidget = false,
|
||||
permissionsList = infoShared,
|
||||
widgetDomain = widget.widgetContent.data["domain"] as? String
|
||||
)
|
||||
} else {
|
||||
val infoShared = listOf(
|
||||
R.string.room_widget_permission_display_name,
|
||||
R.string.room_widget_permission_avatar_url,
|
||||
R.string.room_widget_permission_user_id,
|
||||
R.string.room_widget_permission_theme,
|
||||
R.string.room_widget_permission_widget_id,
|
||||
R.string.room_widget_permission_room_id
|
||||
)
|
||||
RoomWidgetPermissionViewState.WidgetPermissionData(
|
||||
widget = widget,
|
||||
isWebviewWidget = true,
|
||||
permissionsList = infoShared,
|
||||
widgetDomain = domain
|
||||
)
|
||||
}
|
||||
}
|
||||
.execute {
|
||||
copy(permissionData = it)
|
||||
|
@ -91,7 +106,14 @@ class RoomWidgetPermissionViewModel @AssistedInject constructor(@Assisted val in
|
|||
if (state.permissionData()?.isWebviewWidget.orFalse()) {
|
||||
WidgetPermissionsHelper(integrationManagerService, widgetService).changePermission(state.roomId, widgetId, false)
|
||||
} else {
|
||||
// TODO JITSI
|
||||
awaitCallback<Unit> {
|
||||
session.integrationManagerService().setNativeWidgetDomainAllowed(
|
||||
state.permissionData.invoke()?.widget?.type?.preferred ?: "",
|
||||
state.permissionData.invoke()?.widgetDomain ?: "",
|
||||
false,
|
||||
it
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
Timber.v("Failure revoking widget: ${state.widgetId}")
|
||||
|
@ -109,7 +131,14 @@ class RoomWidgetPermissionViewModel @AssistedInject constructor(@Assisted val in
|
|||
if (state.permissionData()?.isWebviewWidget.orFalse()) {
|
||||
WidgetPermissionsHelper(integrationManagerService, widgetService).changePermission(state.roomId, widgetId, true)
|
||||
} else {
|
||||
// TODO JITSI
|
||||
awaitCallback<Unit> {
|
||||
session.integrationManagerService().setNativeWidgetDomainAllowed(
|
||||
state.permissionData.invoke()?.widget?.type?.preferred ?: "",
|
||||
state.permissionData.invoke()?.widgetDomain ?: "",
|
||||
true,
|
||||
it
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
Timber.v("Failure allowing widget: ${state.widgetId}")
|
||||
|
|
Loading…
Reference in a new issue