Widget: continue working on interaction with SDK. Not sure yet how to manage properly distinction between room and "admin" widgets.
This commit is contained in:
parent
3faf42be53
commit
00fd067c6b
|
@ -31,6 +31,7 @@ import im.vector.matrix.android.api.session.file.FileService
|
|||
import im.vector.matrix.android.api.session.group.GroupService
|
||||
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
|
||||
import im.vector.matrix.android.api.session.identity.IdentityService
|
||||
import im.vector.matrix.android.api.session.integrationmanager.IntegrationManagerService
|
||||
import im.vector.matrix.android.api.session.profile.ProfileService
|
||||
import im.vector.matrix.android.api.session.pushers.PushersService
|
||||
import im.vector.matrix.android.api.session.room.RoomDirectoryService
|
||||
|
@ -65,8 +66,7 @@ interface Session :
|
|||
HomeServerCapabilitiesService,
|
||||
SecureStorageService,
|
||||
AccountDataService,
|
||||
AccountService,
|
||||
WidgetService {
|
||||
AccountService {
|
||||
|
||||
/**
|
||||
* The params associated to the session
|
||||
|
@ -155,6 +155,16 @@ interface Session :
|
|||
*/
|
||||
fun identityService(): IdentityService
|
||||
|
||||
/**
|
||||
* Returns the widget service associated with the session
|
||||
*/
|
||||
fun widgetService(): WidgetService
|
||||
|
||||
/**
|
||||
* Returns the integration manager service associated with the session
|
||||
*/
|
||||
fun integrationManagerService(): IntegrationManagerService
|
||||
|
||||
/**
|
||||
* Add a listener to the session.
|
||||
* @param listener the listener to add.
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package im.vector.matrix.android.internal.session.integrationmanager
|
||||
package im.vector.matrix.android.api.session.integrationmanager
|
||||
|
||||
data class IntegrationManagerConfig(
|
||||
val uiUrl: String,
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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.integrationmanager
|
||||
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
|
||||
interface IntegrationManagerService {
|
||||
|
||||
fun getOrderedConfigs(): List<IntegrationManagerConfig>
|
||||
|
||||
fun getPreferredConfig(): IntegrationManagerConfig
|
||||
|
||||
fun isIntegrationEnabled(): Boolean
|
||||
|
||||
fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
fun setWidgetAllowed(stateEventId: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
fun isWidgetAllowed(stateEventId: String): Boolean
|
||||
|
||||
fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
fun isNativeWidgetAllowed(widgetType: String, domain: String?): Boolean
|
||||
}
|
|
@ -48,11 +48,30 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
|
|||
return if (eventType.isNotEmpty() && userId.isNotEmpty()) {
|
||||
val powerLevel = getUserPowerLevel(userId)
|
||||
val minimumPowerLevel = powerLevelsContent.events[eventType]
|
||||
?: if (EventType.isStateEvent(eventType)) {
|
||||
powerLevelsContent.stateDefault
|
||||
} else {
|
||||
powerLevelsContent.eventsDefault
|
||||
}
|
||||
?: if (EventType.isStateEvent(eventType)) {
|
||||
powerLevelsContent.stateDefault
|
||||
} else {
|
||||
powerLevelsContent.eventsDefault
|
||||
}
|
||||
powerLevel >= minimumPowerLevel
|
||||
} else false
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell if an user can send an event of a certain type
|
||||
*
|
||||
* @param eventType the event type to check for
|
||||
* @param userId the user id
|
||||
* @return true if the user can send this type of event
|
||||
*/
|
||||
fun isAllowedToSend(isState: Boolean, userId: String): Boolean {
|
||||
return if (userId.isNotEmpty()) {
|
||||
val powerLevel = getUserPowerLevel(userId)
|
||||
val minimumPowerLevel = if (isState) {
|
||||
powerLevelsContent.stateDefault
|
||||
} else {
|
||||
powerLevelsContent.eventsDefault
|
||||
}
|
||||
powerLevel >= minimumPowerLevel
|
||||
} else false
|
||||
}
|
||||
|
|
|
@ -20,6 +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.Event
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
|
||||
interface StateService {
|
||||
|
@ -27,7 +29,9 @@ interface StateService {
|
|||
/**
|
||||
* Update the topic of the room
|
||||
*/
|
||||
fun updateTopic(topic: String, callback: MatrixCallback<Unit>)
|
||||
fun updateTopic(topic: String, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
fun sendStateEvent(eventType: String, stateKey: String?, body: JsonDict, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
||||
fun getStateEvent(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): Event?
|
||||
|
||||
|
|
|
@ -58,10 +58,11 @@ interface WidgetPostAPIMediator {
|
|||
/**
|
||||
* Send an object response
|
||||
*
|
||||
* @param klass the class of the response
|
||||
* @param response the response
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
fun sendObjectResponse(response: JsonDict?, eventData: JsonDict)
|
||||
fun <T> sendObjectResponse(klass: Class<T>, response: T?, eventData: JsonDict)
|
||||
|
||||
/**
|
||||
* Send success
|
||||
|
@ -82,6 +83,6 @@ interface WidgetPostAPIMediator {
|
|||
/**
|
||||
* Triggered when a widget is posting
|
||||
*/
|
||||
fun handleWidgetRequest(data: JsonDict): Boolean
|
||||
fun handleWidgetRequest(eventData: JsonDict): Boolean
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package im.vector.matrix.android.api.session.widgets
|
||||
|
||||
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
|
||||
|
@ -35,6 +36,23 @@ interface WidgetService {
|
|||
excludedTypes: Set<String>? = null
|
||||
): List<Widget>
|
||||
|
||||
fun getRoomWidgetsLive(
|
||||
roomId: String,
|
||||
widgetId: QueryStringValue = QueryStringValue.NoCondition,
|
||||
widgetTypes: Set<String>? = null,
|
||||
excludedTypes: Set<String>? = null
|
||||
): LiveData<List<Widget>>
|
||||
|
||||
fun getUserWidgets(
|
||||
widgetTypes: Set<String>? = null,
|
||||
excludedTypes: Set<String>? = null
|
||||
): List<Widget>
|
||||
|
||||
fun getUserWidgetsLive(
|
||||
widgetTypes: Set<String>? = null,
|
||||
excludedTypes: Set<String>? = null
|
||||
): LiveData<List<Widget>>
|
||||
|
||||
fun createRoomWidget(roomId: String, widgetId: String, content: Content, callback: MatrixCallback<Widget>): Cancelable
|
||||
|
||||
fun destroyRoomWidget(roomId: String, widgetId: String, callback: MatrixCallback<Unit>): Cancelable
|
||||
|
|
|
@ -34,6 +34,7 @@ import im.vector.matrix.android.api.session.crypto.CryptoService
|
|||
import im.vector.matrix.android.api.session.file.FileService
|
||||
import im.vector.matrix.android.api.session.group.GroupService
|
||||
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
|
||||
import im.vector.matrix.android.api.session.integrationmanager.IntegrationManagerService
|
||||
import im.vector.matrix.android.api.session.profile.ProfileService
|
||||
import im.vector.matrix.android.api.session.pushers.PushersService
|
||||
import im.vector.matrix.android.api.session.room.RoomDirectoryService
|
||||
|
@ -46,7 +47,6 @@ import im.vector.matrix.android.api.session.sync.SyncState
|
|||
import im.vector.matrix.android.api.session.terms.TermsService
|
||||
import im.vector.matrix.android.api.session.user.UserService
|
||||
import im.vector.matrix.android.api.session.widgets.WidgetService
|
||||
import im.vector.matrix.android.api.session.widgets.WidgetURLBuilder
|
||||
import im.vector.matrix.android.internal.auth.SessionParamsStore
|
||||
import im.vector.matrix.android.internal.crypto.DefaultCryptoService
|
||||
import im.vector.matrix.android.internal.crypto.crosssigning.ShieldTrustUpdater
|
||||
|
@ -54,13 +54,11 @@ import im.vector.matrix.android.internal.database.LiveEntityObserver
|
|||
import im.vector.matrix.android.internal.di.SessionId
|
||||
import im.vector.matrix.android.internal.di.WorkManagerProvider
|
||||
import im.vector.matrix.android.internal.session.identity.DefaultIdentityService
|
||||
import im.vector.matrix.android.internal.session.integrationmanager.IntegrationManager
|
||||
import im.vector.matrix.android.internal.session.room.timeline.TimelineEventDecryptor
|
||||
import im.vector.matrix.android.internal.session.sync.SyncTokenStore
|
||||
import im.vector.matrix.android.internal.session.sync.job.SyncThread
|
||||
import im.vector.matrix.android.internal.session.sync.job.SyncWorker
|
||||
import im.vector.matrix.android.internal.session.widgets.WidgetDependenciesHolder
|
||||
import im.vector.matrix.android.internal.session.widgets.WidgetManager
|
||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -109,6 +107,7 @@ internal class DefaultSession @Inject constructor(
|
|||
private val timelineEventDecryptor: TimelineEventDecryptor,
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val defaultIdentityService: DefaultIdentityService,
|
||||
private val integrationManagerService: IntegrationManagerService,
|
||||
private val taskExecutor: TaskExecutor,
|
||||
private val widgetDependenciesHolder: WidgetDependenciesHolder,
|
||||
private val shieldTrustUpdater: ShieldTrustUpdater)
|
||||
|
@ -128,8 +127,7 @@ internal class DefaultSession @Inject constructor(
|
|||
HomeServerCapabilitiesService by homeServerCapabilitiesService.get(),
|
||||
ProfileService by profileService.get(),
|
||||
AccountDataService by accountDataService.get(),
|
||||
AccountService by accountService.get(),
|
||||
WidgetService by widgetService.get() {
|
||||
AccountService by accountService.get() {
|
||||
|
||||
override val sharedSecretStorageService: SharedSecretStorageService
|
||||
get() = _sharedSecretStorageService.get()
|
||||
|
@ -243,6 +241,10 @@ internal class DefaultSession @Inject constructor(
|
|||
|
||||
override fun identityService() = defaultIdentityService
|
||||
|
||||
override fun widgetService(): WidgetService = widgetService.get()
|
||||
|
||||
override fun integrationManagerService() = integrationManagerService
|
||||
|
||||
override fun addListener(listener: Session.Listener) {
|
||||
sessionListeners.addListener(listener)
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import im.vector.matrix.android.internal.session.group.GetGroupDataWorker
|
|||
import im.vector.matrix.android.internal.session.group.GroupModule
|
||||
import im.vector.matrix.android.internal.session.homeserver.HomeServerCapabilitiesModule
|
||||
import im.vector.matrix.android.internal.session.identity.IdentityModule
|
||||
import im.vector.matrix.android.internal.session.integrationmanager.IntegrationManagerModule
|
||||
import im.vector.matrix.android.internal.session.openid.OpenIdModule
|
||||
import im.vector.matrix.android.internal.session.profile.ProfileModule
|
||||
import im.vector.matrix.android.internal.session.pushers.AddHttpPusherWorker
|
||||
|
@ -76,6 +77,7 @@ import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
|||
PushersModule::class,
|
||||
OpenIdModule::class,
|
||||
WidgetModule::class,
|
||||
IntegrationManagerModule::class,
|
||||
IdentityModule::class,
|
||||
TermsModule::class,
|
||||
AccountDataModule::class,
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.session.integrationmanager
|
||||
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.integrationmanager.IntegrationManagerConfig
|
||||
import im.vector.matrix.android.api.session.integrationmanager.IntegrationManagerService
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultIntegrationManagerService @Inject constructor(private val integrationManager: IntegrationManager) : IntegrationManagerService {
|
||||
|
||||
override fun getOrderedConfigs(): List<IntegrationManagerConfig> {
|
||||
return integrationManager.getOrderedConfigs()
|
||||
}
|
||||
|
||||
override fun getPreferredConfig(): IntegrationManagerConfig {
|
||||
return integrationManager.getPreferredConfig()
|
||||
}
|
||||
|
||||
override fun isIntegrationEnabled(): Boolean {
|
||||
return integrationManager.isIntegrationEnabled()
|
||||
}
|
||||
|
||||
override fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return integrationManager.setIntegrationEnabled(enable, callback)
|
||||
}
|
||||
|
||||
override fun setWidgetAllowed(stateEventId: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return integrationManager.setWidgetAllowed(stateEventId, allowed, callback)
|
||||
}
|
||||
|
||||
override fun isWidgetAllowed(stateEventId: String): Boolean {
|
||||
return integrationManager.isWidgetAllowed(stateEventId)
|
||||
}
|
||||
|
||||
override fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return integrationManager.setNativeWidgetDomainAllowed(widgetType, domain, allowed, callback)
|
||||
}
|
||||
|
||||
override fun isNativeWidgetAllowed(widgetType: String, domain: String?): Boolean {
|
||||
return integrationManager.isNativeWidgetAllowed(widgetType, domain)
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ import androidx.lifecycle.LifecycleRegistry
|
|||
import im.vector.matrix.android.R
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
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.widgets.model.WidgetContent
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.api.util.NoOpCancellable
|
||||
|
@ -31,7 +32,7 @@ import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAcco
|
|||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataEvent
|
||||
import im.vector.matrix.android.internal.session.user.accountdata.AccountDataDataSource
|
||||
import im.vector.matrix.android.internal.session.user.accountdata.UpdateUserAccountDataTask
|
||||
import im.vector.matrix.android.internal.session.widgets.helper.extractWidgets
|
||||
import im.vector.matrix.android.internal.session.widgets.helper.extractWidgetSequence
|
||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||
import im.vector.matrix.android.internal.task.configureWith
|
||||
import im.vector.matrix.android.internal.util.StringProvider
|
||||
|
@ -294,7 +295,7 @@ internal class IntegrationManager @Inject constructor(private val taskExecutor:
|
|||
}
|
||||
|
||||
private fun UserAccountDataEvent.asIntegrationManagerWidgetContent(): WidgetContent? {
|
||||
return extractWidgets()
|
||||
return extractWidgetSequence()
|
||||
.filter {
|
||||
it.type == INTEGRATION_MANAGER_WIDGET
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
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 javax.inject.Inject
|
||||
|
||||
internal class IntegrationManagerConfigExtractor @Inject constructor() {
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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.session.integrationmanager
|
||||
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import im.vector.matrix.android.api.session.integrationmanager.IntegrationManagerService
|
||||
|
||||
@Module
|
||||
internal abstract class IntegrationManagerModule {
|
||||
|
||||
@Binds
|
||||
abstract fun bindIntegrationManagerService(integrationManagerService: DefaultIntegrationManagerService): IntegrationManagerService
|
||||
}
|
|
@ -24,6 +24,8 @@ import im.vector.matrix.android.api.query.QueryStringValue
|
|||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import im.vector.matrix.android.api.session.room.state.StateService
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import im.vector.matrix.android.api.util.Optional
|
||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||
import im.vector.matrix.android.internal.task.configureWith
|
||||
|
@ -55,17 +57,29 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private
|
|||
return stateEventDataSource.getStateEventsLive(roomId, eventTypes, stateKey)
|
||||
}
|
||||
|
||||
override fun updateTopic(topic: String, callback: MatrixCallback<Unit>) {
|
||||
val params = SendStateTask.Params(roomId,
|
||||
EventType.STATE_ROOM_TOPIC,
|
||||
mapOf(
|
||||
"topic" to topic
|
||||
))
|
||||
|
||||
sendStateTask
|
||||
override fun sendStateEvent(
|
||||
eventType: String,
|
||||
stateKey: String?,
|
||||
body: JsonDict,
|
||||
callback: MatrixCallback<Unit>
|
||||
): Cancelable {
|
||||
val params = SendStateTask.Params(
|
||||
roomId = roomId,
|
||||
eventType = eventType,
|
||||
body = body
|
||||
)
|
||||
return sendStateTask
|
||||
.configureWith(params) {
|
||||
this.callback = callback
|
||||
}
|
||||
.executeBy(taskExecutor)
|
||||
}
|
||||
|
||||
override fun updateTopic(topic: String, callback: MatrixCallback<Unit>): Cancelable {
|
||||
return sendStateEvent(
|
||||
eventType = EventType.STATE_ROOM_TOPIC,
|
||||
body = mapOf("topic" to topic),
|
||||
callback = callback
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import javax.inject.Inject
|
|||
internal interface SendStateTask : Task<SendStateTask.Params, Unit> {
|
||||
data class Params(
|
||||
val roomId: String,
|
||||
val stateKey: String? = null,
|
||||
val eventType: String,
|
||||
val body: JsonDict
|
||||
)
|
||||
|
@ -38,7 +39,20 @@ internal class DefaultSendStateTask @Inject constructor(
|
|||
|
||||
override suspend fun execute(params: SendStateTask.Params) {
|
||||
return executeRequest(eventBus) {
|
||||
apiCall = roomAPI.sendStateEvent(params.roomId, params.eventType, params.body)
|
||||
apiCall = if (params.stateKey == null) {
|
||||
roomAPI.sendStateEvent(
|
||||
roomId = params.roomId,
|
||||
stateEventType = params.eventType,
|
||||
params = params.body
|
||||
)
|
||||
} else {
|
||||
roomAPI.sendStateEvent(
|
||||
roomId = params.roomId,
|
||||
stateEventType = params.eventType,
|
||||
stateKey = params.stateKey,
|
||||
params = params.body
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,10 +27,10 @@ import timber.log.Timber
|
|||
import java.util.HashMap
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultWidgetPostAPIMediator @Inject constructor(moshi: Moshi,
|
||||
internal class DefaultWidgetPostAPIMediator @Inject constructor(private val moshi: Moshi,
|
||||
private val widgetPostMessageAPIProvider: WidgetPostMessageAPIProvider) : WidgetPostAPIMediator {
|
||||
|
||||
private val adapter = moshi.adapter<JsonDict>(JSON_DICT_PARAMETERIZED_TYPE)
|
||||
private val jsonAdapter = moshi.adapter<JsonDict>(JSON_DICT_PARAMETERIZED_TYPE)
|
||||
|
||||
private var handler: WidgetPostAPIMediator.Handler? = null
|
||||
private var webView: WebView? = null
|
||||
|
@ -58,7 +58,7 @@ internal class DefaultWidgetPostAPIMediator @Inject constructor(moshi: Moshi,
|
|||
fun onWidgetEvent(jsonEventData: String) {
|
||||
Timber.d("BRIDGE onWidgetEvent : $jsonEventData")
|
||||
try {
|
||||
val dataAsDict = adapter.fromJson(jsonEventData)
|
||||
val dataAsDict = jsonAdapter.fromJson(jsonEventData)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val eventData = (dataAsDict?.get("event.data") as? JsonDict) ?: return
|
||||
onWidgetMessage(eventData)
|
||||
|
@ -111,11 +111,12 @@ internal class DefaultWidgetPostAPIMediator @Inject constructor(moshi: Moshi,
|
|||
* @param response the response
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
override fun sendObjectResponse(response: JsonDict?, eventData: JsonDict) {
|
||||
override fun <T> sendObjectResponse(klass: Class<T>, response: T?, eventData: JsonDict) {
|
||||
var jsString: String? = null
|
||||
if (response != null) {
|
||||
val objectAdapter = moshi.adapter(klass)
|
||||
try {
|
||||
jsString = "JSON.parse('${adapter.toJson(response)}')"
|
||||
jsString = "JSON.parse('${objectAdapter.toJson(response)}')"
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## sendObjectResponse() : toJson failed ")
|
||||
}
|
||||
|
@ -130,7 +131,7 @@ internal class DefaultWidgetPostAPIMediator @Inject constructor(moshi: Moshi,
|
|||
*/
|
||||
override fun sendSuccess(eventData: JsonDict) {
|
||||
val successResponse = mapOf("success" to true)
|
||||
sendObjectResponse(successResponse, eventData)
|
||||
sendObjectResponse(Map::class.java, successResponse, eventData)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,7 +148,7 @@ internal class DefaultWidgetPostAPIMediator @Inject constructor(moshi: Moshi,
|
|||
val subMap = HashMap<String, String>()
|
||||
subMap["message"] = message
|
||||
params["error"] = subMap
|
||||
sendObjectResponse(params, eventData)
|
||||
sendObjectResponse(Map::class.java, params, eventData)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package im.vector.matrix.android.internal.session.widgets
|
||||
|
||||
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
|
||||
|
@ -42,6 +43,18 @@ internal class DefaultWidgetService @Inject constructor(private val widgetManage
|
|||
return widgetManager.getRoomWidgets(roomId, widgetId, widgetTypes, excludedTypes)
|
||||
}
|
||||
|
||||
override fun getRoomWidgetsLive(roomId: String, widgetId: QueryStringValue, widgetTypes: Set<String>?, excludedTypes: Set<String>?): LiveData<List<Widget>> {
|
||||
return widgetManager.getRoomWidgetsLive(roomId, widgetId, widgetTypes, excludedTypes)
|
||||
}
|
||||
|
||||
override fun getUserWidgetsLive(widgetTypes: Set<String>?, excludedTypes: Set<String>?): LiveData<List<Widget>> {
|
||||
return widgetManager.getUserWidgetsLive(widgetTypes, excludedTypes)
|
||||
}
|
||||
|
||||
override fun getUserWidgets(widgetTypes: Set<String>?, excludedTypes: Set<String>?): List<Widget> {
|
||||
return widgetManager.getUserWidgets(widgetTypes, excludedTypes)
|
||||
}
|
||||
|
||||
override fun createRoomWidget(roomId: String, widgetId: String, content: Content, callback: MatrixCallback<Widget>): Cancelable {
|
||||
return widgetManager.createWidget(roomId, widgetId, content, callback)
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import im.vector.matrix.android.api.session.events.model.Event
|
|||
import im.vector.matrix.android.api.session.widgets.model.WidgetContent
|
||||
|
||||
data class Widget(
|
||||
private val widgetContent: WidgetContent,
|
||||
private val event: Event? = null
|
||||
val widgetContent: WidgetContent,
|
||||
val event: Event? = null
|
||||
)
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ package im.vector.matrix.android.internal.session.widgets
|
|||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LifecycleRegistry
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Transformations
|
||||
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
|
||||
|
@ -34,8 +36,9 @@ import im.vector.matrix.android.internal.session.SessionScope
|
|||
import im.vector.matrix.android.internal.session.integrationmanager.IntegrationManager
|
||||
import im.vector.matrix.android.internal.session.room.state.StateEventDataSource
|
||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountData
|
||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataEvent
|
||||
import im.vector.matrix.android.internal.session.user.accountdata.AccountDataDataSource
|
||||
import im.vector.matrix.android.internal.session.widgets.helper.extractWidgets
|
||||
import im.vector.matrix.android.internal.session.widgets.helper.extractWidgetSequence
|
||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||
import im.vector.matrix.android.internal.task.launchToCallback
|
||||
import java.util.HashMap
|
||||
|
@ -66,6 +69,19 @@ internal class WidgetManager @Inject constructor(private val integrationManager:
|
|||
lifecycleRegistry.currentState = Lifecycle.State.DESTROYED
|
||||
}
|
||||
|
||||
fun getRoomWidgetsLive(
|
||||
roomId: String,
|
||||
widgetId: QueryStringValue = QueryStringValue.NoCondition,
|
||||
widgetTypes: Set<String>? = null,
|
||||
excludedTypes: Set<String>? = null
|
||||
): LiveData<List<Widget>> {
|
||||
// Get all im.vector.modular.widgets state events in the room
|
||||
val liveWidgetEvents = stateEventDataSource.getStateEventsLive(roomId, setOf(WIDGET_EVENT_TYPE), widgetId)
|
||||
return Transformations.map(liveWidgetEvents) { widgetEvents ->
|
||||
widgetEvents.mapEventsToWidgets(widgetTypes, excludedTypes)
|
||||
}
|
||||
}
|
||||
|
||||
fun getRoomWidgets(
|
||||
roomId: String,
|
||||
widgetId: QueryStringValue = QueryStringValue.NoCondition,
|
||||
|
@ -74,6 +90,12 @@ internal class WidgetManager @Inject constructor(private val integrationManager:
|
|||
): List<Widget> {
|
||||
// Get all im.vector.modular.widgets state events in the room
|
||||
val widgetEvents: List<Event> = stateEventDataSource.getStateEvents(roomId, setOf(WIDGET_EVENT_TYPE), widgetId)
|
||||
return widgetEvents.mapEventsToWidgets(widgetTypes, excludedTypes)
|
||||
}
|
||||
|
||||
private fun List<Event>.mapEventsToWidgets(widgetTypes: Set<String>? = null,
|
||||
excludedTypes: Set<String>? = null): List<Widget> {
|
||||
val widgetEvents = this
|
||||
// Widget id -> widget
|
||||
val widgets: MutableMap<String, Widget> = HashMap()
|
||||
// Order widgetEvents with the last event first
|
||||
|
@ -102,12 +124,27 @@ internal class WidgetManager @Inject constructor(private val integrationManager:
|
|||
return widgets.values.toList()
|
||||
}
|
||||
|
||||
fun getUserWidgetsLive(
|
||||
widgetTypes: Set<String>? = null,
|
||||
excludedTypes: Set<String>? = null
|
||||
): LiveData<List<Widget>> {
|
||||
val widgetsAccountData = accountDataDataSource.getLiveAccountDataEvent(UserAccountData.TYPE_WIDGETS)
|
||||
return Transformations.map(widgetsAccountData) {
|
||||
it.getOrNull()?.mapToWidgets(widgetTypes, excludedTypes) ?: emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
fun getUserWidgets(
|
||||
widgetTypes: Set<String>? = null,
|
||||
excludedTypes: Set<String>? = null
|
||||
): List<Widget> {
|
||||
val widgetsAccountData = accountDataDataSource.getAccountDataEvent(UserAccountData.TYPE_WIDGETS) ?: return emptyList()
|
||||
return widgetsAccountData.extractWidgets()
|
||||
return widgetsAccountData.mapToWidgets(widgetTypes, excludedTypes)
|
||||
}
|
||||
|
||||
private fun UserAccountDataEvent.mapToWidgets(widgetTypes: Set<String>? = null,
|
||||
excludedTypes: Set<String>? = null): List<Widget> {
|
||||
return extractWidgetSequence()
|
||||
.filter {
|
||||
val widgetType = it.type ?: return@filter false
|
||||
(widgetTypes == null || widgetTypes.contains(widgetType))
|
||||
|
|
|
@ -20,7 +20,7 @@ import im.vector.matrix.android.R
|
|||
import im.vector.matrix.android.api.session.widgets.WidgetURLBuilder
|
||||
import im.vector.matrix.android.internal.session.SessionScope
|
||||
import im.vector.matrix.android.internal.session.integrationmanager.IntegrationManager
|
||||
import im.vector.matrix.android.internal.session.integrationmanager.IntegrationManagerConfig
|
||||
import im.vector.matrix.android.api.session.integrationmanager.IntegrationManagerConfig
|
||||
import im.vector.matrix.android.internal.session.widgets.token.GetScalarTokenTask
|
||||
import im.vector.matrix.android.internal.util.StringProvider
|
||||
import java.net.URLEncoder
|
||||
|
|
|
@ -21,7 +21,7 @@ import im.vector.matrix.android.api.session.events.model.toModel
|
|||
import im.vector.matrix.android.api.session.widgets.model.WidgetContent
|
||||
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataEvent
|
||||
|
||||
internal fun UserAccountDataEvent.extractWidgets(): Sequence<WidgetContent> {
|
||||
internal fun UserAccountDataEvent.extractWidgetSequence(): Sequence<WidgetContent> {
|
||||
return content.asSequence()
|
||||
.mapNotNull {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
|
|
@ -99,7 +99,8 @@ import im.vector.riotx.features.signout.soft.SoftLogoutFragment
|
|||
import im.vector.riotx.features.terms.ReviewTermsFragment
|
||||
import im.vector.riotx.features.userdirectory.KnownUsersFragment
|
||||
import im.vector.riotx.features.userdirectory.UserDirectoryFragment
|
||||
import im.vector.riotx.features.widgets.RoomWidgetFragment
|
||||
import im.vector.riotx.features.widgets.admin.AdminWidgetFragment
|
||||
import im.vector.riotx.features.widgets.room.RoomWidgetFragment
|
||||
|
||||
@Module
|
||||
interface FragmentModule {
|
||||
|
@ -479,11 +480,6 @@ interface FragmentModule {
|
|||
@FragmentKey(SharedSecuredStorageKeyFragment::class)
|
||||
fun bindSharedSecuredStorageKeyFragment(fragment: SharedSecuredStorageKeyFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(RoomWidgetFragment::class)
|
||||
fun bindWidgetFragment(fragment: RoomWidgetFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(SetIdentityServerFragment::class)
|
||||
|
@ -498,4 +494,14 @@ interface FragmentModule {
|
|||
@IntoMap
|
||||
@FragmentKey(ReviewTermsFragment::class)
|
||||
fun bindReviewTermsFragment(fragment: ReviewTermsFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(RoomWidgetFragment::class)
|
||||
fun bindRoomWidgetFragment(fragment: RoomWidgetFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(AdminWidgetFragment::class)
|
||||
fun bindAdminWidgetFragment(fragment: AdminWidgetFragment): Fragment
|
||||
}
|
||||
|
|
|
@ -215,6 +215,10 @@ class DefaultNavigator @Inject constructor(
|
|||
fragment.startActivityForResult(intent, requestCode)
|
||||
}
|
||||
|
||||
override fun openIntegrationManager(context: Context) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
private fun startActivity(context: Context, intent: Intent, buildTask: Boolean) {
|
||||
if (buildTask) {
|
||||
val stackBuilder = TaskStackBuilder.create(context)
|
||||
|
|
|
@ -76,4 +76,7 @@ interface Navigator {
|
|||
baseUrl: String,
|
||||
token: String?,
|
||||
requestCode: Int = ReviewTermsActivity.TERMS_REQUEST_CODE)
|
||||
|
||||
fun openIntegrationManager(context: Context, integId: String?, integType: String?)
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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.riotx.features.widgets
|
||||
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.widgets.WidgetPostAPIMediator
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
|
||||
class WidgetAPICallback(private val postAPIMediator: WidgetPostAPIMediator,
|
||||
private val eventData: JsonDict,
|
||||
private val stringProvider: StringProvider) : MatrixCallback<Unit> {
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
super.onFailure(failure)
|
||||
postAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_failed_to_send_request), eventData)
|
||||
}
|
||||
|
||||
override fun onSuccess(data: Unit) {
|
||||
super.onSuccess(data)
|
||||
postAPIMediator.sendSuccess(eventData)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* 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.riotx.features.widgets
|
||||
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import im.vector.matrix.android.api.query.QueryStringValue
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.matrix.android.api.session.events.model.EventType
|
||||
import im.vector.matrix.android.api.session.events.model.toModel
|
||||
import im.vector.matrix.android.api.session.room.model.Membership
|
||||
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.WidgetPostAPIMediator
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.resources.StringProvider
|
||||
import im.vector.riotx.features.navigation.Navigator
|
||||
import timber.log.Timber
|
||||
import java.util.HashMap
|
||||
|
||||
class WidgetPostAPIHandler(private val context: Context,
|
||||
private val roomId: String,
|
||||
private val navigator: Navigator,
|
||||
private val stringProvider: StringProvider,
|
||||
private val widgetPostAPIMediator: WidgetPostAPIMediator,
|
||||
private val session: Session) : WidgetPostAPIMediator.Handler {
|
||||
|
||||
private val room = session.getRoom(roomId)!!
|
||||
|
||||
override fun handleWidgetRequest(eventData: JsonDict): Boolean {
|
||||
return when (eventData["action"] as String?) {
|
||||
"integration_manager_open" -> handleIntegrationManagerOpenAction(eventData).run { true }
|
||||
"bot_options" -> getBotOptions(eventData).run { true }
|
||||
"can_send_event" -> canSendEvent(eventData).run { true }
|
||||
//"close_scalar" -> finish().run { true }
|
||||
"get_membership_count" -> getMembershipCount(eventData).run { true }
|
||||
//"get_widgets" -> getWidgets(eventData).run { true }
|
||||
//"invite" -> inviteUser(eventData).run { true }
|
||||
"join_rules_state" -> getJoinRules(eventData).run { true }
|
||||
"membership_state" -> getMembershipState(eventData).run { true }
|
||||
"set_bot_options" -> setBotOptions(eventData).run { true }
|
||||
"set_bot_power" -> setBotPower(eventData).run { true }
|
||||
"set_plumbing_state" -> setPlumbingState(eventData).run { true }
|
||||
//"set_widget" -> setWidget(eventData).run { true }
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleIntegrationManagerOpenAction(eventData: JsonDict) {
|
||||
var integType: String? = null
|
||||
var integId: String? = null
|
||||
val data = eventData["data"]
|
||||
data
|
||||
.takeIf { it is Map<*, *> }
|
||||
?.let {
|
||||
val dict = data as Map<*, *>
|
||||
|
||||
dict["integType"]
|
||||
.takeIf { it is String }
|
||||
?.let { integType = it as String }
|
||||
|
||||
dict["integId"]
|
||||
.takeIf { it is String }
|
||||
?.let { integId = it as String }
|
||||
|
||||
// Add "type_" as a prefix
|
||||
integType?.let { integType = "type_$integType" }
|
||||
}
|
||||
navigator.openIntegrationManager(context, integId, integType)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the latest botOptions event
|
||||
*
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
private fun getBotOptions(eventData: JsonDict) {
|
||||
if (checkRoomId(eventData) || checkUserId(eventData)) {
|
||||
return
|
||||
}
|
||||
val userId = eventData["user_id"] as String
|
||||
Timber.d("Received request to get options for bot $userId in room $roomId requested")
|
||||
val stateEvents = room.getStateEvents(setOf(EventType.BOT_OPTIONS))
|
||||
var botOptionsEvent: Event? = null
|
||||
val stateKey = "_$userId"
|
||||
for (stateEvent in stateEvents) {
|
||||
if (TextUtils.equals(stateEvent.stateKey, stateKey)) {
|
||||
if (null == botOptionsEvent || stateEvent.ageLocalTs ?: 0 > botOptionsEvent.ageLocalTs ?: 0) {
|
||||
botOptionsEvent = stateEvent
|
||||
}
|
||||
}
|
||||
}
|
||||
if (null != botOptionsEvent) {
|
||||
Timber.d("Received request to get options for bot $userId returns $botOptionsEvent")
|
||||
widgetPostAPIMediator.sendObjectResponse(Event::class.java, botOptionsEvent, eventData)
|
||||
} else {
|
||||
Timber.d("Received request to get options for bot $userId returns null")
|
||||
widgetPostAPIMediator.sendObjectResponse(Event::class.java, null, eventData)
|
||||
}
|
||||
}
|
||||
|
||||
private fun canSendEvent(eventData: JsonDict) {
|
||||
if (checkRoomId(eventData)) {
|
||||
return
|
||||
}
|
||||
Timber.d("Received request canSendEvent in room $roomId")
|
||||
if (room.roomSummary()?.membership != Membership.JOIN) {
|
||||
widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_must_be_in_room), eventData)
|
||||
return
|
||||
}
|
||||
|
||||
val eventType = eventData["event_type"] as String
|
||||
val isState = eventData["is_state"] as Boolean
|
||||
|
||||
Timber.d("## canSendEvent() : eventType $eventType isState $isState")
|
||||
|
||||
val powerLevelsEvent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS)
|
||||
val powerLevelsContent = powerLevelsEvent?.content?.toModel<PowerLevelsContent>()
|
||||
val canSend = if (powerLevelsContent == null) {
|
||||
false
|
||||
} else {
|
||||
PowerLevelsHelper(powerLevelsContent).isAllowedToSend(eventType, session.myUserId)
|
||||
}
|
||||
if (canSend) {
|
||||
Timber.d("## canSendEvent() returns true")
|
||||
widgetPostAPIMediator.sendBoolResponse(true, eventData)
|
||||
} else {
|
||||
Timber.d("## canSendEvent() returns widget_integration_no_permission_in_room")
|
||||
widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_no_permission_in_room), eventData)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the membership state
|
||||
*
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
private fun getMembershipState(eventData: JsonDict) {
|
||||
if (checkRoomId(eventData) || checkUserId(eventData)) {
|
||||
return
|
||||
}
|
||||
val userId = eventData["user_id"] as String
|
||||
Timber.d("membership_state of $userId in room $roomId requested")
|
||||
val roomMemberStateEvent = room.getStateEvent(EventType.STATE_ROOM_MEMBER, stateKey = QueryStringValue.Equals(userId, QueryStringValue.Case.SENSITIVE))
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the latest joined room event
|
||||
*
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
private fun getJoinRules(eventData: JsonDict) {
|
||||
if (checkRoomId(eventData)) {
|
||||
return
|
||||
}
|
||||
Timber.d("Received request join rules in room $roomId")
|
||||
val joinedEvents = room.getStateEvents(setOf(EventType.STATE_ROOM_JOIN_RULES))
|
||||
if (joinedEvents.isNotEmpty()) {
|
||||
widgetPostAPIMediator.sendObjectResponse(Event::class.java, joinedEvents.last(), eventData)
|
||||
} else {
|
||||
widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_failed_to_send_request), eventData)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the 'plumbing state"
|
||||
*
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
private fun setPlumbingState(eventData: JsonDict) {
|
||||
if (checkRoomId(eventData)) {
|
||||
return
|
||||
}
|
||||
val description = "Received request to set plumbing state to status " + eventData["status"] + " in room " + roomId + " requested"
|
||||
Timber.d(description)
|
||||
|
||||
val status = eventData["status"] as String
|
||||
|
||||
val params = HashMap<String, Any>()
|
||||
params["status"] = status
|
||||
room.sendStateEvent(
|
||||
eventType = EventType.PLUMBING,
|
||||
stateKey = null,
|
||||
body = params,
|
||||
callback = WidgetAPICallback(widgetPostAPIMediator, eventData, stringProvider)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the bot options
|
||||
*
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
private fun setBotOptions(eventData: JsonDict) {
|
||||
if (checkRoomId(eventData) || checkUserId(eventData)) {
|
||||
return
|
||||
}
|
||||
val userId = eventData["user_id"] as String
|
||||
val description = "Received request to set options for bot $userId in room $roomId"
|
||||
Timber.d(description)
|
||||
val content = eventData["content"] as JsonDict
|
||||
val stateKey = "_$userId"
|
||||
room.sendStateEvent(
|
||||
eventType = EventType.BOT_OPTIONS,
|
||||
stateKey = stateKey,
|
||||
body = content,
|
||||
callback = WidgetAPICallback(widgetPostAPIMediator, eventData, stringProvider))
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the bot power levels
|
||||
*
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
private fun setBotPower(eventData: JsonDict) {
|
||||
if (checkRoomId(eventData) || checkUserId(eventData)) {
|
||||
return
|
||||
}
|
||||
val userId = eventData["user_id"] as String
|
||||
val description = "Received request to set power level to " + eventData["level"] + " for bot " + userId + " in room " + roomId
|
||||
Timber.d(description)
|
||||
val level = eventData["level"] as Int
|
||||
if (level >= 0) {
|
||||
// TODO
|
||||
//room.updateUserPowerLevels(userId, level, WidgetApiCallback(eventData, description))
|
||||
} else {
|
||||
Timber.e("## setBotPower() : Power level must be positive integer.")
|
||||
widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_positive_power_level), eventData)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the number of members in the rooms
|
||||
*
|
||||
* @param eventData the modular data
|
||||
*/
|
||||
private fun getMembershipCount(eventData: JsonDict) {
|
||||
if (checkRoomId(eventData)) {
|
||||
return
|
||||
}
|
||||
val numberOfJoinedMembers = room.getNumberOfJoinedMembers()
|
||||
widgetPostAPIMediator.sendIntegerResponse(numberOfJoinedMembers, eventData)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if roomId is present in the event and match
|
||||
* Send response and return true in case of error
|
||||
*
|
||||
* @return true in case of error
|
||||
*/
|
||||
private fun checkRoomId(eventData: JsonDict): Boolean {
|
||||
val roomIdInEvent = eventData["room_id"] as String?
|
||||
// Check if param is present
|
||||
if (null == roomIdInEvent) {
|
||||
widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_missing_room_id), eventData)
|
||||
return true
|
||||
}
|
||||
|
||||
if (!TextUtils.equals(roomIdInEvent, roomId)) {
|
||||
widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_room_not_visible), eventData)
|
||||
return true
|
||||
}
|
||||
|
||||
// OK
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if userId is present in the event
|
||||
* Send response and return true in case of error
|
||||
*
|
||||
* @return true in case of error
|
||||
*/
|
||||
private fun checkUserId(eventData: JsonDict): Boolean {
|
||||
val userIdInEvent = eventData["user_id"] as String?
|
||||
// Check if param is present
|
||||
if (null == userIdInEvent) {
|
||||
widgetPostAPIMediator.sendError(stringProvider.getString(R.string.widget_integration_missing_user_id), eventData)
|
||||
return true
|
||||
}
|
||||
// OK
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.widgets
|
||||
package im.vector.riotx.features.widgets.admin
|
||||
|
||||
import im.vector.riotx.core.platform.VectorViewModelAction
|
||||
|
||||
sealed class RoomWidgetAction : VectorViewModelAction
|
||||
sealed class AdminWidgetAction : VectorViewModelAction
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.riotx.features.widgets.admin
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class AdminWidgetFragment @Inject constructor(
|
||||
private val viewModelFactory: AdminWidgetViewModel.Factory
|
||||
) : VectorBaseFragment(), AdminWidgetViewModel.Factory by viewModelFactory {
|
||||
|
||||
private val viewModel: AdminWidgetViewModel by fragmentViewModel()
|
||||
|
||||
override fun getLayoutResId() = R.layout.fragment_admin_widget
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
// Initialize your view, subscribe to viewModel...
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
// Clear your view, unsubscribe...
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) { state ->
|
||||
Timber.v("Invalidate with state: $state")
|
||||
}
|
||||
}
|
|
@ -14,16 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.widgets
|
||||
package im.vector.riotx.features.widgets.admin
|
||||
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import im.vector.riotx.core.platform.VectorViewEvents
|
||||
|
||||
// Example of data:
|
||||
// {
|
||||
// "event.data": {
|
||||
// "action": "get_widgets",
|
||||
// "room_id": "!byqyNXFYAGirEulaEm:matrix.org",
|
||||
// "_id": "1526370173321-0.55myregve98-1"
|
||||
// }
|
||||
// }
|
||||
typealias WidgetEventData = Map<String, JsonDict>
|
||||
sealed class AdminWidgetViewEvents : VectorViewEvents
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.widgets
|
||||
package im.vector.riotx.features.widgets.admin
|
||||
|
||||
import com.airbnb.mvrx.ActivityViewModelContext
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
|
@ -22,22 +22,20 @@ import com.airbnb.mvrx.MvRxViewModelFactory
|
|||
import com.airbnb.mvrx.ViewModelContext
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
|
||||
class RoomWidgetViewModel @AssistedInject constructor(@Assisted initialState: WidgetViewState,
|
||||
private val session: Session)
|
||||
: VectorViewModel<WidgetViewState, RoomWidgetAction, RoomWidgetViewEvents>(initialState) {
|
||||
class AdminWidgetViewModel @AssistedInject constructor(@Assisted initialState: AdminWidgetViewState)
|
||||
: VectorViewModel<AdminWidgetViewState, AdminWidgetAction, AdminWidgetViewEvents>(initialState) {
|
||||
|
||||
@AssistedInject.Factory
|
||||
interface Factory {
|
||||
fun create(initialState: WidgetViewState): RoomWidgetViewModel
|
||||
fun create(initialState: AdminWidgetViewState): AdminWidgetViewModel
|
||||
}
|
||||
|
||||
companion object : MvRxViewModelFactory<RoomWidgetViewModel, WidgetViewState> {
|
||||
companion object : MvRxViewModelFactory<AdminWidgetViewModel, AdminWidgetViewState> {
|
||||
|
||||
@JvmStatic
|
||||
override fun create(viewModelContext: ViewModelContext, state: WidgetViewState): RoomWidgetViewModel? {
|
||||
override fun create(viewModelContext: ViewModelContext, state: AdminWidgetViewState): AdminWidgetViewModel? {
|
||||
val factory = when (viewModelContext) {
|
||||
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
|
||||
is ActivityViewModelContext -> viewModelContext.activity as? Factory
|
||||
|
@ -46,7 +44,7 @@ class RoomWidgetViewModel @AssistedInject constructor(@Assisted initialState: Wi
|
|||
}
|
||||
}
|
||||
|
||||
override fun handle(action: RoomWidgetAction) {
|
||||
//TODO
|
||||
override fun handle(action: AdminWidgetAction) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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.riotx.features.widgets.admin
|
||||
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
|
||||
data class AdminWidgetViewState(val boolean: Boolean = false) : MvRxState
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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.riotx.features.widgets.room
|
||||
|
||||
import im.vector.riotx.core.platform.VectorViewModelAction
|
||||
|
||||
sealed class RoomWidgetAction : VectorViewModelAction {
|
||||
data class OnWebViewStartedToLoad(val url: String) : RoomWidgetAction()
|
||||
data class OnWebViewLoadingError(val url: String) : RoomWidgetAction()
|
||||
data class OnWebViewLoadingSuccess(val url: String) : RoomWidgetAction()
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.widgets
|
||||
package im.vector.riotx.features.widgets.room
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
|
@ -22,6 +22,8 @@ import android.view.View
|
|||
import com.airbnb.mvrx.args
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.matrix.android.api.session.widgets.WidgetPostAPIMediator
|
||||
import im.vector.matrix.android.api.util.JsonDict
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.platform.VectorBaseFragment
|
||||
import im.vector.riotx.features.webview.WebViewEventListener
|
||||
|
@ -34,12 +36,15 @@ import javax.inject.Inject
|
|||
|
||||
@Parcelize
|
||||
data class WidgetArgs(
|
||||
val widgetId: String
|
||||
val baseUrl: String,
|
||||
val kind: WidgetKind,
|
||||
val roomId: String,
|
||||
val widgetId: String? = null
|
||||
) : Parcelable
|
||||
|
||||
class RoomWidgetFragment @Inject constructor(
|
||||
private val viewModelFactory: RoomWidgetViewModel.Factory
|
||||
) : VectorBaseFragment(), RoomWidgetViewModel.Factory by viewModelFactory, WebViewEventListener {
|
||||
) : VectorBaseFragment(), RoomWidgetViewModel.Factory by viewModelFactory, WebViewEventListener, WidgetPostAPIMediator.Handler {
|
||||
|
||||
private val fragmentArgs: WidgetArgs by args()
|
||||
private val viewModel: RoomWidgetViewModel by fragmentViewModel()
|
||||
|
@ -49,10 +54,12 @@ class RoomWidgetFragment @Inject constructor(
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
widgetWebView.setupForWidget(this)
|
||||
viewModel.getPostAPIMediator().initialize(widgetWebView, this)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
viewModel.getPostAPIMediator().clear()
|
||||
widgetWebView.clearAfterWidget()
|
||||
}
|
||||
|
||||
|
@ -77,6 +84,7 @@ class RoomWidgetFragment @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onPageStarted(url: String) {
|
||||
|
||||
}
|
||||
|
||||
override fun onPageFinished(url: String) {
|
||||
|
@ -85,4 +93,8 @@ class RoomWidgetFragment @Inject constructor(
|
|||
|
||||
override fun onPageError(url: String, errorCode: Int, description: String) {
|
||||
}
|
||||
|
||||
override fun handleWidgetRequest(eventData: JsonDict): Boolean {
|
||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.widgets
|
||||
package im.vector.riotx.features.widgets.room
|
||||
|
||||
import im.vector.riotx.core.platform.VectorViewEvents
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* 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.riotx.features.widgets.room
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.airbnb.mvrx.ActivityViewModelContext
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import com.squareup.inject.assisted.Assisted
|
||||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.query.QueryStringValue
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class RoomWidgetViewModel @AssistedInject constructor(@Assisted val initialState: WidgetViewState,
|
||||
private val session: Session)
|
||||
: VectorViewModel<WidgetViewState, RoomWidgetAction, RoomWidgetViewEvents>(initialState) {
|
||||
|
||||
@AssistedInject.Factory
|
||||
interface Factory {
|
||||
fun create(initialState: WidgetViewState): RoomWidgetViewModel
|
||||
}
|
||||
|
||||
companion object : MvRxViewModelFactory<RoomWidgetViewModel, WidgetViewState> {
|
||||
|
||||
@JvmStatic
|
||||
override fun create(viewModelContext: ViewModelContext, state: WidgetViewState): RoomWidgetViewModel? {
|
||||
val factory = when (viewModelContext) {
|
||||
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
|
||||
is ActivityViewModelContext -> viewModelContext.activity as? Factory
|
||||
}
|
||||
return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
|
||||
}
|
||||
}
|
||||
|
||||
private val widgetService = session.widgetService()
|
||||
private val integrationManagerService = session.integrationManagerService()
|
||||
private val widgetBuilder = widgetService.getWidgetURLBuilder()
|
||||
private val postAPIMediator = widgetService.getWidgetPostAPIMediator()
|
||||
|
||||
init {
|
||||
refreshPermissionStatus()
|
||||
}
|
||||
|
||||
fun getPostAPIMediator() = postAPIMediator
|
||||
|
||||
override fun handle(action: RoomWidgetAction) {
|
||||
when (action) {
|
||||
is RoomWidgetAction.OnWebViewLoadingError -> handleWebViewLoadingError(action.url)
|
||||
is RoomWidgetAction.OnWebViewLoadingSuccess -> handleWebViewLoadingSuccess(action.url)
|
||||
is RoomWidgetAction.OnWebViewStartedToLoad -> handleWebViewStartLoading(action.url)
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshPermissionStatus() {
|
||||
if (initialState.widgetKind == WidgetKind.USER || initialState.widgetKind == WidgetKind.INTEGRATION_MANAGER) {
|
||||
onWidgetAllowed()
|
||||
} else {
|
||||
val widgetId = initialState.widgetId
|
||||
if (widgetId == null) {
|
||||
setState { copy(status = WidgetStatus.WIDGET_NOT_ALLOWED) }
|
||||
return
|
||||
}
|
||||
val roomWidget = widgetService.getRoomWidgets(initialState.roomId, widgetId = QueryStringValue.Equals(widgetId, QueryStringValue.Case.SENSITIVE)).firstOrNull()
|
||||
if (roomWidget == null) {
|
||||
setState { copy(status = WidgetStatus.WIDGET_NOT_ALLOWED) }
|
||||
return
|
||||
}
|
||||
if (roomWidget.event?.senderId == session.myUserId) {
|
||||
onWidgetAllowed()
|
||||
} else {
|
||||
val stateEventId = roomWidget.event?.eventId
|
||||
// This should not happen
|
||||
if (stateEventId == null) {
|
||||
setState { copy(status = WidgetStatus.WIDGET_NOT_ALLOWED) }
|
||||
return
|
||||
}
|
||||
val isAllowed = integrationManagerService.isWidgetAllowed(stateEventId)
|
||||
if (!isAllowed) {
|
||||
setState { copy(status = WidgetStatus.WIDGET_NOT_ALLOWED) }
|
||||
} else {
|
||||
onWidgetAllowed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onWidgetAllowed() {
|
||||
setState {
|
||||
copy(status = WidgetStatus.WIDGET_ALLOWED, formattedURL = Loading())
|
||||
}
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val formattedUrl = widgetBuilder.build(initialState.baseUrl)
|
||||
setState { copy(formattedURL = Success(formattedUrl)) }
|
||||
} catch (failure: Throwable) {
|
||||
setState { copy(formattedURL = Fail(failure)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleWebViewStartLoading(url: String) {
|
||||
}
|
||||
|
||||
private fun handleWebViewLoadingSuccess(url: String) {
|
||||
}
|
||||
|
||||
private fun handleWebViewLoadingError(url: String) {
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.features.widgets
|
||||
package im.vector.riotx.features.widgets.room
|
||||
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
|
@ -26,8 +26,17 @@ enum class WidgetStatus {
|
|||
WIDGET_ALLOWED
|
||||
}
|
||||
|
||||
enum class WidgetKind {
|
||||
ROOM,
|
||||
USER,
|
||||
INTEGRATION_MANAGER
|
||||
}
|
||||
|
||||
data class WidgetViewState(
|
||||
val widgetId: String,
|
||||
val roomId: String,
|
||||
val baseUrl: String,
|
||||
val widgetId: String? = null,
|
||||
val widgetKind: WidgetKind,
|
||||
val status: WidgetStatus = WidgetStatus.UNKNOWN,
|
||||
val formattedURL: Async<String> = Uninitialized,
|
||||
val webviewLoadedUrl: Async<String> = Uninitialized,
|
||||
|
@ -36,5 +45,10 @@ data class WidgetViewState(
|
|||
val createdByMe: Boolean = false
|
||||
) : MvRxState {
|
||||
|
||||
constructor(widgetArgs: WidgetArgs) : this(widgetId = widgetArgs.widgetId)
|
||||
constructor(widgetArgs: WidgetArgs) : this(
|
||||
widgetKind = widgetArgs.kind,
|
||||
baseUrl = widgetArgs.baseUrl,
|
||||
roomId = widgetArgs.roomId,
|
||||
widgetId = widgetArgs.widgetId
|
||||
)
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.riotx.features.widgets.room
|
||||
|
||||
interface WidgetParams {
|
||||
val params: Map<String, String>
|
||||
}
|
||||
|
||||
class IntegrationManagerParams(
|
||||
private val widgetId: String? = null,
|
||||
private val screenId: String? = null) : WidgetParams {
|
||||
|
||||
override val params: Map<String, String> by lazy {
|
||||
buildParams()
|
||||
}
|
||||
|
||||
private fun buildParams(): Map<String, String> {
|
||||
val map = HashMap<String, String>()
|
||||
if (widgetId != null) {
|
||||
map["integ_id"] = widgetId
|
||||
}
|
||||
if (screenId != null) {
|
||||
map["screen"] = screenId
|
||||
}
|
||||
return map
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/rootConstraintLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="AdminWidgetFragment"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
Reference in New Issue