From 7df8b3a9bf690a48d072f22ecc5f1ee16a06d192 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 29 May 2020 12:23:36 +0200 Subject: [PATCH] Widgets: observe wellknown for integ config and open Jitsi in browser --- .../java/im/vector/matrix/rx/RxSession.kt | 2 +- .../IntegrationManagerService.kt | 2 +- .../api/session/widgets/WidgetService.kt | 3 +- .../session/widgets/model}/Widget.kt | 5 +- .../api/session/widgets/model/WidgetTypes.kt | 64 ++++++++++++ .../database/model/SessionRealmModule.kt | 3 +- ...WellknownIntegrationManagerConfigEntity.kt | 29 ++++++ .../integrationmanager/IntegrationManager.kt | 99 +++++++++++-------- .../IntegrationManagerConfigExtractor.kt | 15 ++- .../session/widgets/DefaultWidgetService.kt | 1 + .../widgets/DefaultWidgetURLFormatter.kt | 2 +- .../internal/session/widgets/WidgetManager.kt | 1 + .../widgets/helper/UserAccountWidgets.kt | 2 +- .../session/widgets/helper/WidgetFactory.kt | 14 ++- .../home/room/detail/RoomDetailFragment.kt | 3 +- .../home/room/detail/RoomDetailViewEvents.kt | 2 +- .../home/room/detail/RoomDetailViewState.kt | 2 +- .../sticker/StickerPickerActionHandler.kt | 3 +- .../detail/sticker/StickerPickerConstants.kt | 1 - .../detail/widget/RoomWidgetController.kt | 2 +- .../home/room/detail/widget/RoomWidgetItem.kt | 2 +- .../detail/widget/RoomWidgetsBannerView.kt | 2 +- .../detail/widget/RoomWidgetsBottomSheet.kt | 13 ++- .../features/navigation/DefaultNavigator.kt | 2 +- .../riotx/features/navigation/Navigator.kt | 8 +- .../settings/VectorSettingsGeneralFragment.kt | 4 +- .../features/widgets/WidgetArgsBuilder.kt | 2 +- .../riotx/features/widgets/WidgetViewState.kt | 9 +- .../RoomWidgetPermissionViewState.kt | 2 +- 29 files changed, 213 insertions(+), 86 deletions(-) rename matrix-sdk-android/src/main/java/im/vector/matrix/android/{internal/session/widgets => api/session/widgets/model}/Widget.kt (89%) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/model/WidgetTypes.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/WellknownIntegrationManagerConfigEntity.kt diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt index 9dfd9e1fbe..45c13f2182 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt @@ -36,7 +36,7 @@ import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo import im.vector.matrix.android.internal.crypto.store.PrivateKeysInfo import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataEvent -import im.vector.matrix.android.internal.session.widgets.Widget +import im.vector.matrix.android.api.session.widgets.model.Widget import io.reactivex.Observable import io.reactivex.Single diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/integrationmanager/IntegrationManagerService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/integrationmanager/IntegrationManagerService.kt index bdb7e6375c..3992370785 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/integrationmanager/IntegrationManagerService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/integrationmanager/IntegrationManagerService.kt @@ -27,7 +27,7 @@ interface IntegrationManagerService { //No-op } - fun onConfigurationChanged(config: IntegrationManagerConfig) { + fun onConfigurationChanged(configs: List) { //No-op } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/WidgetService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/WidgetService.kt index f0475a657c..372ec1a3de 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/WidgetService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/WidgetService.kt @@ -20,9 +20,8 @@ import androidx.lifecycle.LiveData import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.query.QueryStringValue import im.vector.matrix.android.api.session.events.model.Content -import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.util.Cancelable -import im.vector.matrix.android.internal.session.widgets.Widget +import im.vector.matrix.android.api.session.widgets.model.Widget interface WidgetService { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/Widget.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/model/Widget.kt similarity index 89% rename from matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/Widget.kt rename to matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/model/Widget.kt index 4224a15777..6928efce73 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/Widget.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/model/Widget.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package im.vector.matrix.android.internal.session.widgets +package im.vector.matrix.android.api.session.widgets.model import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.room.sender.SenderInfo @@ -26,7 +26,8 @@ data class Widget( val widgetId: String, val senderInfo: SenderInfo?, val isAddedByMe: Boolean, - val computedUrl: String? + val computedUrl: String?, + val type: WidgetType ) { val isActive = widgetContent.isActive() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/model/WidgetTypes.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/model/WidgetTypes.kt new file mode 100644 index 0000000000..650aadf444 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/widgets/model/WidgetTypes.kt @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020 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.matrix.android.api.session.widgets.model + +sealed class WidgetType(open val preferred: String, open val legacy: String) { + object Jitsi : WidgetType("m.jitsi", "jitsi") + object TradingView : WidgetType("m.tradingview", "m.tradingview") + object Spotify : WidgetType("m.spotify", "m.spotify") + object Video : WidgetType("m.video", "m.video") + object GoogleDoc : WidgetType("m.googledoc", "m.googledoc") + object GoogleCalendar : WidgetType("m.googlecalendar", "m.googlecalendar") + object Etherpad : WidgetType("m.etherpad", "m.etherpad") + object StickerPicker : WidgetType("m.stickerpicker", "m.stickerpicker") + object Grafana : WidgetType("m.grafana", "m.grafana") + object Custom : WidgetType("m.custom", "m.custom") + object IntegrationManager : WidgetType("m.integration_manager", "m.integration_manager") + data class Fallback(override val preferred: String, override val legacy: String) : WidgetType(preferred, legacy) + + fun matches(type: String?): Boolean { + return type == preferred || type == legacy + } + + fun values(): Set{ + return setOf(preferred, legacy) + } + + companion object { + + private val DEFINED_TYPES = listOf( + Jitsi, + TradingView, + Spotify, + Video, + GoogleDoc, + GoogleCalendar, + Etherpad, + StickerPicker, + Grafana, + Custom, + IntegrationManager + ) + + fun fromString(type: String): WidgetType { + val matchingType = DEFINED_TYPES.firstOrNull { + it.matches(type) + } + return matchingType ?: Fallback(type, type) + } + } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/SessionRealmModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/SessionRealmModule.kt index 03cdbfdf4e..9eceb56141 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/SessionRealmModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/SessionRealmModule.kt @@ -56,6 +56,7 @@ import io.realm.annotations.RealmModule RoomMemberSummaryEntity::class, CurrentStateEventEntity::class, UserAccountDataEntity::class, - ScalarTokenEntity::class + ScalarTokenEntity::class, + WellknownIntegrationManagerConfigEntity::class ]) internal class SessionRealmModule diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/WellknownIntegrationManagerConfigEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/WellknownIntegrationManagerConfigEntity.kt new file mode 100644 index 0000000000..56d66782aa --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/WellknownIntegrationManagerConfigEntity.kt @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020 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.matrix.android.internal.database.model + +import io.realm.RealmObject +import io.realm.annotations.PrimaryKey + +internal open class WellknownIntegrationManagerConfigEntity( + @PrimaryKey var id: Long = 0, + var apiUrl: String = "", + var uiUrl: String = "" +) : RealmObject() { + + companion object +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/integrationmanager/IntegrationManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/integrationmanager/IntegrationManager.kt index 474b360605..3186b4bcd0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/integrationmanager/IntegrationManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/integrationmanager/IntegrationManager.kt @@ -19,14 +19,19 @@ package im.vector.matrix.android.internal.session.integrationmanager import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleRegistry +import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.R import im.vector.matrix.android.api.MatrixCallback +import im.vector.matrix.android.api.auth.wellknown.WellknownResult import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.integrationmanager.IntegrationManagerConfig import im.vector.matrix.android.api.session.integrationmanager.IntegrationManagerService import im.vector.matrix.android.api.session.widgets.model.WidgetContent +import im.vector.matrix.android.api.session.widgets.model.WidgetType import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.api.util.NoOpCancellable +import im.vector.matrix.android.internal.database.model.WellknownIntegrationManagerConfigEntity +import im.vector.matrix.android.internal.di.UserId import im.vector.matrix.android.internal.extensions.observeNotNull import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountData @@ -38,6 +43,9 @@ import im.vector.matrix.android.internal.session.widgets.helper.extractWidgetSeq import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.util.StringProvider +import im.vector.matrix.android.internal.util.awaitTransaction +import im.vector.matrix.android.internal.wellknown.GetWellknownTask +import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject @@ -54,14 +62,16 @@ import javax.inject.Inject * */ @SessionScope -internal class IntegrationManager @Inject constructor(private val taskExecutor: TaskExecutor, +internal class IntegrationManager @Inject constructor(@UserId private val userId: String, + private val taskExecutor: TaskExecutor, + private val monarchy: Monarchy, private val stringProvider: StringProvider, private val updateUserAccountDataTask: UpdateUserAccountDataTask, private val accountDataDataSource: AccountDataDataSource, + private val getWellknownTask: GetWellknownTask, private val configExtractor: IntegrationManagerConfigExtractor, private val widgetFactory: WidgetFactory) { - private val currentConfigs = ArrayList() private val lifecycleOwner: LifecycleOwner = LifecycleOwner { lifecycleRegistry } private val lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(lifecycleOwner) @@ -80,7 +90,9 @@ internal class IntegrationManager @Inject constructor(private val taskExecutor: } fun start() { + refreshWellknown() lifecycleRegistry.currentState = Lifecycle.State.STARTED + observeWellknownConfig() accountDataDataSource .getLiveAccountDataEvent(UserAccountData.TYPE_ALLOWED_WIDGETS) .observeNotNull(lifecycleOwner) { @@ -102,13 +114,7 @@ internal class IntegrationManager @Inject constructor(private val taskExecutor: .observeNotNull(lifecycleOwner) { val integrationManagerContent = it.getOrNull()?.asIntegrationManagerWidgetContent() val config = integrationManagerContent?.extractIntegrationManagerConfig() - val accountConfig = currentConfigs.firstOrNull { currentConfig -> - currentConfig.kind == IntegrationManagerConfig.Kind.ACCOUNT - } - if (config != null && accountConfig == null) { - currentConfigs.add(config) - notifyConfigurationChanged(config) - } + updateCurrentConfigs(IntegrationManagerConfig.Kind.ACCOUNT, config) } } @@ -209,12 +215,11 @@ internal class IntegrationManager @Inject constructor(private val taskExecutor: return currentContent?.native?.get(widgetType)?.get(domain) ?: false } - private fun notifyConfigurationChanged(config: IntegrationManagerConfig) { - Timber.v("On configuration changed : $config") + private fun notifyConfigurationChanged() { synchronized(listeners) { listeners.forEach { try { - it.onConfigurationChanged(config) + it.onConfigurationChanged(currentConfigs) } catch (t: Throwable) { Timber.e(t, "Failed to notify listener") } @@ -248,30 +253,6 @@ internal class IntegrationManager @Inject constructor(private val taskExecutor: } } - /* - private fun getStoreWellknownIM(): List { - val prefs = context.getSharedPreferences(PREFS_IM, Context.MODE_PRIVATE) - return prefs.getString(WELLKNOWN_KEY, null)?.let { - try { - Gson().fromJson>(it, - object : TypeToken>() {}.type) - } catch (any: Throwable) { - emptyList() - } - } ?: emptyList() - } - - private fun setStoreWellknownIM(list: List) { - val prefs = context.getSharedPreferences(PREFS_IM, Context.MODE_PRIVATE) - try { - val serialized = Gson().toJson(list) - prefs.edit().putString(WELLKNOWN_KEY, serialized).apply() - } catch (any: Throwable) { - //nop - } - } - */ - private fun WidgetContent.extractIntegrationManagerConfig(): IntegrationManagerConfig? { if (url.isNullOrBlank()) { return null @@ -287,14 +268,50 @@ internal class IntegrationManager @Inject constructor(private val taskExecutor: private fun UserAccountDataEvent.asIntegrationManagerWidgetContent(): WidgetContent? { return extractWidgetSequence(widgetFactory) .filter { - it.widgetContent.type == INTEGRATION_MANAGER_WIDGET + WidgetType.IntegrationManager == it.type } .firstOrNull()?.widgetContent } - companion object { - private const val INTEGRATION_MANAGER_WIDGET = "m.integration_manager" - private const val PREFS_IM = "IntegrationManager.Storage" - private const val WELLKNOWN_KEY = "WellKnown" + private fun refreshWellknown() { + taskExecutor.executorScope.launch { + val params = GetWellknownTask.Params(matrixId = userId) + val wellknownResult = try { + getWellknownTask.execute(params) + } catch (failure: Throwable) { + Timber.v("Get wellknown failed: $failure") + null + } + if (wellknownResult != null && wellknownResult is WellknownResult.Prompt) { + val config = configExtractor.extract(wellknownResult.wellKnown) ?: return@launch + Timber.v("Extracted config: $config") + monarchy.awaitTransaction { + it.insertOrUpdate(config) + } + } + } + } + + private fun observeWellknownConfig() { + val liveData = monarchy.findAllMappedWithChanges( + { it.where(WellknownIntegrationManagerConfigEntity::class.java) }, + { IntegrationManagerConfig(it.uiUrl, it.apiUrl, IntegrationManagerConfig.Kind.HOMESERVER) } + ) + liveData.observeNotNull(lifecycleOwner) { + val config = it.firstOrNull() + updateCurrentConfigs(IntegrationManagerConfig.Kind.HOMESERVER, config) + } + } + + private fun updateCurrentConfigs(kind: IntegrationManagerConfig.Kind, config: IntegrationManagerConfig?) { + val hasBeenRemoved = currentConfigs.removeAll { currentConfig -> + currentConfig.kind == kind + } + if (config != null) { + currentConfigs.add(config) + } + if (hasBeenRemoved || config != null) { + notifyConfigurationChanged() + } } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/integrationmanager/IntegrationManagerConfigExtractor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/integrationmanager/IntegrationManagerConfigExtractor.kt index 3792ea4231..5a1a51f36f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/integrationmanager/IntegrationManagerConfigExtractor.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/integrationmanager/IntegrationManagerConfigExtractor.kt @@ -17,13 +17,12 @@ package im.vector.matrix.android.internal.session.integrationmanager import im.vector.matrix.android.api.auth.data.WellKnown -import im.vector.matrix.android.api.session.integrationmanager.IntegrationManagerConfig +import im.vector.matrix.android.internal.database.model.WellknownIntegrationManagerConfigEntity import javax.inject.Inject internal class IntegrationManagerConfigExtractor @Inject constructor() { - fun extract(wellKnown: WellKnown): List { - val managers = ArrayList() + fun extract(wellKnown: WellKnown): WellknownIntegrationManagerConfigEntity? { wellKnown.integrations?.get("managers")?.let { (it as? List<*>)?.let { configs -> configs.forEach { config -> @@ -33,16 +32,16 @@ internal class IntegrationManagerConfigExtractor @Inject constructor() { if (apiUrl != null && apiUrl.startsWith("https://") && uiUrl!!.startsWith("https://")) { - managers.add(IntegrationManagerConfig( + + return WellknownIntegrationManagerConfigEntity( apiUrl = apiUrl, - uiUrl = uiUrl, - kind = IntegrationManagerConfig.Kind.HOMESERVER - )) + uiUrl = uiUrl + ) } } } } } - return managers + return null } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetService.kt index 6cd13f3bea..de37b55b2a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetService.kt @@ -23,6 +23,7 @@ import im.vector.matrix.android.api.session.events.model.Content import im.vector.matrix.android.api.session.widgets.WidgetPostAPIMediator import im.vector.matrix.android.api.session.widgets.WidgetService import im.vector.matrix.android.api.session.widgets.WidgetURLFormatter +import im.vector.matrix.android.api.session.widgets.model.Widget import im.vector.matrix.android.api.util.Cancelable import javax.inject.Inject diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetURLFormatter.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetURLFormatter.kt index 04f01dddb3..3391bf0818 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetURLFormatter.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/DefaultWidgetURLFormatter.kt @@ -45,7 +45,7 @@ internal class DefaultWidgetURLFormatter @Inject constructor(private val integra integrationManager.removeListener(this) } - override fun onConfigurationChanged(config: IntegrationManagerConfig) { + override fun onConfigurationChanged(configs: List) { setupWithConfiguration() } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/WidgetManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/WidgetManager.kt index d273faa972..0741e5b55e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/WidgetManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/WidgetManager.kt @@ -30,6 +30,7 @@ import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.integrationmanager.IntegrationManagerService import im.vector.matrix.android.api.session.room.model.PowerLevelsContent import im.vector.matrix.android.api.session.room.powerlevels.PowerLevelsHelper +import im.vector.matrix.android.api.session.widgets.model.Widget import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.internal.di.UserId import im.vector.matrix.android.internal.session.SessionScope diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/helper/UserAccountWidgets.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/helper/UserAccountWidgets.kt index e8ec46a9f9..113047246e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/helper/UserAccountWidgets.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/helper/UserAccountWidgets.kt @@ -20,7 +20,7 @@ import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.util.JsonDict import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataEvent -import im.vector.matrix.android.internal.session.widgets.Widget +import im.vector.matrix.android.api.session.widgets.model.Widget internal fun UserAccountDataEvent.extractWidgetSequence(widgetFactory: WidgetFactory): Sequence { return content.asSequence() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/helper/WidgetFactory.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/helper/WidgetFactory.kt index 4cc8a23682..4091b6defd 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/helper/WidgetFactory.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/widgets/helper/WidgetFactory.kt @@ -19,12 +19,13 @@ package im.vector.matrix.android.internal.session.widgets.helper import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.sender.SenderInfo +import im.vector.matrix.android.api.session.widgets.model.Widget import im.vector.matrix.android.api.session.widgets.model.WidgetContent +import im.vector.matrix.android.api.session.widgets.model.WidgetType import im.vector.matrix.android.internal.di.SessionDatabase import im.vector.matrix.android.internal.di.UserId import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper import im.vector.matrix.android.internal.session.user.UserDataSource -import im.vector.matrix.android.internal.session.widgets.Widget import io.realm.Realm import io.realm.RealmConfiguration import java.net.URLEncoder @@ -38,6 +39,7 @@ internal class WidgetFactory @Inject constructor(@SessionDatabase private val re val widgetContent = widgetEvent.content.toModel() if (widgetContent?.url == null) return null val widgetId = widgetEvent.stateKey ?: return null + val type = widgetContent.type ?: return null val senderInfo = if (widgetEvent.senderId == null || widgetEvent.roomId == null) { null } else { @@ -54,7 +56,15 @@ internal class WidgetFactory @Inject constructor(@SessionDatabase private val re } val isAddedByMe = widgetEvent.senderId == userId val computedUrl = widgetContent.computeURL(widgetEvent.roomId) - return Widget(widgetContent, widgetEvent, widgetId, senderInfo, isAddedByMe, computedUrl) + return Widget( + widgetContent = widgetContent, + event = widgetEvent, + widgetId = widgetId, + senderInfo = senderInfo, + isAddedByMe = isAddedByMe, + computedUrl = computedUrl, + type = WidgetType.fromString(type) + ) } private fun WidgetContent.computeURL(roomId: String?): String? { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt index fb38a4f08e..6058fe9ec6 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt @@ -83,6 +83,7 @@ import im.vector.matrix.android.api.session.room.send.SendState import im.vector.matrix.android.api.session.room.timeline.Timeline import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.api.session.room.timeline.getLastMessageContent +import im.vector.matrix.android.api.session.widgets.model.WidgetType import im.vector.matrix.android.api.util.MatrixItem import im.vector.matrix.android.api.util.toMatrixItem import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt @@ -337,7 +338,7 @@ class RoomDetailFragment @Inject constructor( context = requireContext(), roomId = roomDetailArgs.roomId, integId = null, - screen = StickerPickerConstants.WIDGET_NAME + screen = WidgetType.StickerPicker.preferred ) } .setNegativeButton(R.string.no, null) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewEvents.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewEvents.kt index 815b4abde1..73ce95eda2 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewEvents.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewEvents.kt @@ -17,7 +17,7 @@ package im.vector.riotx.features.home.room.detail import androidx.annotation.StringRes -import im.vector.matrix.android.internal.session.widgets.Widget +import im.vector.matrix.android.api.session.widgets.model.Widget import im.vector.riotx.core.platform.VectorViewEvents import im.vector.riotx.features.command.Command import java.io.File diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewState.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewState.kt index 691b85362b..3079059b8f 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewState.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewState.kt @@ -27,7 +27,7 @@ import im.vector.matrix.android.api.session.room.timeline.TimelineEvent import im.vector.matrix.android.api.session.sync.SyncState import im.vector.matrix.android.api.session.user.model.User import im.vector.matrix.android.api.util.MatrixItem -import im.vector.matrix.android.internal.session.widgets.Widget +import im.vector.matrix.android.api.session.widgets.model.Widget /** * Describes the current send mode: diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerActionHandler.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerActionHandler.kt index 6227fe9658..3b939892b5 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerActionHandler.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerActionHandler.kt @@ -17,6 +17,7 @@ package im.vector.riotx.features.home.room.detail.sticker import im.vector.matrix.android.api.session.Session +import im.vector.matrix.android.api.session.widgets.model.WidgetType import im.vector.riotx.features.home.room.detail.RoomDetailViewEvents import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -26,7 +27,7 @@ class StickerPickerActionHandler @Inject constructor(private val session: Sessio suspend fun handle(): RoomDetailViewEvents = withContext(Dispatchers.Default) { // Search for the sticker picker widget in the user account - val stickerWidget = session.widgetService().getUserWidgets(setOf(StickerPickerConstants.WIDGET_NAME)).firstOrNull() + val stickerWidget = session.widgetService().getUserWidgets(WidgetType.StickerPicker.values()).firstOrNull { it.isActive } if (stickerWidget == null || stickerWidget.computedUrl.isNullOrBlank()) { RoomDetailViewEvents.DisplayPromptForIntegrationManager } else { diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerConstants.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerConstants.kt index 6176aca7ab..8068eafc85 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerConstants.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/sticker/StickerPickerConstants.kt @@ -17,6 +17,5 @@ package im.vector.riotx.features.home.room.detail.sticker object StickerPickerConstants { - const val WIDGET_NAME = "m.stickerpicker" const val STICKER_PICKER_REQUEST_CODE = 16000 } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetController.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetController.kt index f09509777c..1fe85d0264 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetController.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetController.kt @@ -17,7 +17,7 @@ package im.vector.riotx.features.home.room.detail.widget import com.airbnb.epoxy.TypedEpoxyController -import im.vector.matrix.android.internal.session.widgets.Widget +import im.vector.matrix.android.api.session.widgets.model.Widget import javax.inject.Inject /** diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetItem.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetItem.kt index d62ee807f5..f6dd2ab361 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetItem.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetItem.kt @@ -20,7 +20,7 @@ import android.widget.TextView import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import com.airbnb.epoxy.EpoxyModelWithHolder -import im.vector.matrix.android.internal.session.widgets.Widget +import im.vector.matrix.android.api.session.widgets.model.Widget import im.vector.riotx.R import im.vector.riotx.core.epoxy.VectorEpoxyHolder diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetsBannerView.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetsBannerView.kt index e4225e5f8d..48a5c20558 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetsBannerView.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetsBannerView.kt @@ -20,7 +20,7 @@ import android.content.Context import android.util.AttributeSet import android.view.View import android.widget.RelativeLayout -import im.vector.matrix.android.internal.session.widgets.Widget +import im.vector.matrix.android.api.session.widgets.model.Widget import im.vector.riotx.R import kotlinx.android.synthetic.main.view_room_widgets_banner.view.* diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetsBottomSheet.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetsBottomSheet.kt index 28d16125b3..de38dc6bba 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetsBottomSheet.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/widget/RoomWidgetsBottomSheet.kt @@ -21,13 +21,15 @@ import androidx.recyclerview.widget.RecyclerView import butterknife.BindView import com.airbnb.mvrx.parentFragmentViewModel import com.airbnb.mvrx.withState -import im.vector.matrix.android.internal.session.widgets.Widget +import im.vector.matrix.android.api.session.widgets.model.Widget +import im.vector.matrix.android.api.session.widgets.model.WidgetType import im.vector.riotx.R import im.vector.riotx.core.di.ScreenComponent import im.vector.riotx.core.extensions.cleanup import im.vector.riotx.core.extensions.configureWith import im.vector.riotx.core.platform.VectorBaseBottomSheetDialogFragment import im.vector.riotx.core.resources.ColorProvider +import im.vector.riotx.core.utils.openUrlInExternalBrowser import im.vector.riotx.features.home.room.detail.RoomDetailViewModel import im.vector.riotx.features.home.room.detail.RoomDetailViewState import im.vector.riotx.features.navigation.Navigator @@ -73,8 +75,13 @@ class RoomWidgetsBottomSheet : VectorBaseBottomSheetDialogFragment(), RoomWidget } override fun didSelectWidget(widget: Widget) = withState(roomDetailViewModel) { - navigator.openRoomWidget(requireContext(), it.roomId, widget) - dismiss() + if (widget.type == WidgetType.Jitsi) { + openUrlInExternalBrowser(requireContext(), widget.computedUrl) + dismiss() + } else { + navigator.openRoomWidget(requireContext(), it.roomId, widget) + dismiss() + } } companion object { diff --git a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt index 39b3116696..bc7cfc8156 100644 --- a/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/riotx/features/navigation/DefaultNavigator.kt @@ -31,7 +31,7 @@ import im.vector.matrix.android.api.session.crypto.verification.IncomingSasVerif import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom import im.vector.matrix.android.api.session.terms.TermsService import im.vector.matrix.android.api.util.MatrixItem -import im.vector.matrix.android.internal.session.widgets.Widget +import im.vector.matrix.android.api.session.widgets.model.Widget import im.vector.riotx.R import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.core.error.fatalError diff --git a/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt b/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt index e231493a59..79de5b3dbb 100644 --- a/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt +++ b/vector/src/main/java/im/vector/riotx/features/navigation/Navigator.kt @@ -24,7 +24,7 @@ import androidx.fragment.app.Fragment import im.vector.matrix.android.api.session.room.model.roomdirectory.PublicRoom import im.vector.matrix.android.api.session.terms.TermsService import im.vector.matrix.android.api.util.MatrixItem -import im.vector.matrix.android.internal.session.widgets.Widget +import im.vector.matrix.android.api.session.widgets.model.Widget import im.vector.riotx.features.home.room.detail.sticker.StickerPickerConstants import im.vector.riotx.features.media.ImageContentRenderer import im.vector.riotx.features.media.VideoContentRenderer @@ -83,9 +83,9 @@ interface Navigator { requestCode: Int = ReviewTermsActivity.TERMS_REQUEST_CODE) fun openStickerPicker(fragment: Fragment, - roomId: String, - widget: Widget, - requestCode: Int = StickerPickerConstants.STICKER_PICKER_REQUEST_CODE) + roomId: String, + widget: Widget, + requestCode: Int = StickerPickerConstants.STICKER_PICKER_REQUEST_CODE) fun openIntegrationManager(context: Context, roomId: String, integId: String?, screen: String?) diff --git a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsGeneralFragment.kt b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsGeneralFragment.kt index 35fa3c4cbf..709d23abd7 100644 --- a/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsGeneralFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/settings/VectorSettingsGeneralFragment.kt @@ -98,13 +98,11 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() { } private val integrationServiceListener = object : IntegrationManagerService.Listener { - override fun onConfigurationChanged(config: IntegrationManagerConfig) { - super.onConfigurationChanged(config) + override fun onConfigurationChanged(configs: List) { refreshIntegrationManagerSettings() } override fun onIsEnabledChanged(enabled: Boolean) { - super.onIsEnabledChanged(enabled) refreshIntegrationManagerSettings() } } diff --git a/vector/src/main/java/im/vector/riotx/features/widgets/WidgetArgsBuilder.kt b/vector/src/main/java/im/vector/riotx/features/widgets/WidgetArgsBuilder.kt index d7c6829707..d39614e3b7 100644 --- a/vector/src/main/java/im/vector/riotx/features/widgets/WidgetArgsBuilder.kt +++ b/vector/src/main/java/im/vector/riotx/features/widgets/WidgetArgsBuilder.kt @@ -16,7 +16,7 @@ package im.vector.riotx.features.widgets -import im.vector.matrix.android.internal.session.widgets.Widget +import im.vector.matrix.android.api.session.widgets.model.Widget import im.vector.riotx.core.di.ActiveSessionHolder import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/riotx/features/widgets/WidgetViewState.kt b/vector/src/main/java/im/vector/riotx/features/widgets/WidgetViewState.kt index fb211dd400..2242efc82f 100644 --- a/vector/src/main/java/im/vector/riotx/features/widgets/WidgetViewState.kt +++ b/vector/src/main/java/im/vector/riotx/features/widgets/WidgetViewState.kt @@ -20,9 +20,9 @@ import androidx.annotation.StringRes import com.airbnb.mvrx.Async import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.Uninitialized -import im.vector.matrix.android.internal.session.widgets.Widget +import im.vector.matrix.android.api.session.widgets.model.Widget +import im.vector.matrix.android.api.session.widgets.model.WidgetType import im.vector.riotx.R -import im.vector.riotx.features.home.room.detail.sticker.StickerPickerConstants enum class WidgetStatus { UNKNOWN, @@ -31,14 +31,13 @@ enum class WidgetStatus { } enum class WidgetKind(@StringRes val nameRes: Int, val screenId: String?) { - ROOM(R.string.room_widget_activity_title,null), - STICKER_PICKER(R.string.title_activity_choose_sticker, StickerPickerConstants.WIDGET_NAME), + ROOM(R.string.room_widget_activity_title, null), + STICKER_PICKER(R.string.title_activity_choose_sticker, WidgetType.StickerPicker.preferred), INTEGRATION_MANAGER(0, null); fun isAdmin(): Boolean { return this == STICKER_PICKER || this == INTEGRATION_MANAGER } - } data class WidgetViewState( diff --git a/vector/src/main/java/im/vector/riotx/features/widgets/permissions/RoomWidgetPermissionViewState.kt b/vector/src/main/java/im/vector/riotx/features/widgets/permissions/RoomWidgetPermissionViewState.kt index 0b3a61b0f8..38553bdf39 100644 --- a/vector/src/main/java/im/vector/riotx/features/widgets/permissions/RoomWidgetPermissionViewState.kt +++ b/vector/src/main/java/im/vector/riotx/features/widgets/permissions/RoomWidgetPermissionViewState.kt @@ -19,7 +19,7 @@ package im.vector.riotx.features.widgets.permissions import com.airbnb.mvrx.Async import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.Uninitialized -import im.vector.matrix.android.internal.session.widgets.Widget +import im.vector.matrix.android.api.session.widgets.model.Widget import im.vector.riotx.features.widgets.WidgetArgs data class RoomWidgetPermissionViewState(