Merge pull request #6319 from vector-im/feature/bma/stateEventQuery

Enforce query on state event
This commit is contained in:
Benoit Marty 2022-06-16 17:13:17 +02:00 committed by GitHub
commit 8238cd7f57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 109 additions and 80 deletions

1
changelog.d/6319.sdk Normal file
View File

@ -0,0 +1 @@
Create `QueryStateEventValue` to do query on `stateKey` for State Event. Also remove the default parameter values for those type.

View File

@ -18,7 +18,7 @@ package org.matrix.android.sdk.flow
import androidx.lifecycle.asFlow import androidx.lifecycle.asFlow
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.api.session.room.getStateEvent import org.matrix.android.sdk.api.session.room.getStateEvent
@ -67,17 +67,17 @@ class FlowRoom(private val room: Room) {
} }
} }
fun liveStateEvent(eventType: String, stateKey: QueryStringValue): Flow<Optional<Event>> { fun liveStateEvent(eventType: String, stateKey: QueryStateEventValue): Flow<Optional<Event>> {
return room.stateService().getStateEventLive(eventType, stateKey).asFlow() return room.stateService().getStateEventLive(eventType, stateKey).asFlow()
.startWith(room.coroutineDispatchers.io) { .startWith(room.coroutineDispatchers.io) {
room.getStateEvent(eventType, stateKey).toOptional() room.getStateEvent(eventType, stateKey).toOptional()
} }
} }
fun liveStateEvents(eventTypes: Set<String>): Flow<List<Event>> { fun liveStateEvents(eventTypes: Set<String>, stateKey: QueryStateEventValue): Flow<List<Event>> {
return room.stateService().getStateEventsLive(eventTypes).asFlow() return room.stateService().getStateEventsLive(eventTypes, stateKey).asFlow()
.startWith(room.coroutineDispatchers.io) { .startWith(room.coroutineDispatchers.io) {
room.stateService().getStateEvents(eventTypes) room.stateService().getStateEvents(eventTypes, stateKey)
} }
} }

View File

@ -19,7 +19,7 @@ package org.matrix.android.sdk.flow
import androidx.lifecycle.asFlow import androidx.lifecycle.asFlow
import androidx.paging.PagedList import androidx.paging.PagedList
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
@ -179,7 +179,7 @@ class FlowSession(private val session: Session) {
fun liveRoomWidgets( fun liveRoomWidgets(
roomId: String, roomId: String,
widgetId: QueryStringValue, widgetId: QueryStateEventValue,
widgetTypes: Set<String>? = null, widgetTypes: Set<String>? = null,
excludedTypes: Set<String>? = null excludedTypes: Set<String>? = null
): Flow<List<Widget>> { ): Flow<List<Widget>> {

View File

@ -28,6 +28,7 @@ import org.junit.runner.RunWith
import org.junit.runners.JUnit4 import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.InstrumentedTest
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.getStateEvent import org.matrix.android.sdk.api.session.room.getStateEvent
@ -73,27 +74,37 @@ class SpaceCreationTest : InstrumentedTest {
// assertEquals(topic, syncedSpace.asRoom().roomSummary()?., "Room topic should be set") // assertEquals(topic, syncedSpace.asRoom().roomSummary()?., "Room topic should be set")
assertNotNull("Space should be found by Id", syncedSpace) assertNotNull("Space should be found by Id", syncedSpace)
val creationEvent = syncedSpace!!.asRoom().getStateEvent(EventType.STATE_ROOM_CREATE) val createContent = syncedSpace!!.asRoom()
val createContent = creationEvent?.content.toModel<RoomCreateContent>() .getStateEvent(EventType.STATE_ROOM_CREATE, QueryStringValue.IsEmpty)
?.content
?.toModel<RoomCreateContent>()
assertEquals("Room type should be space", RoomType.SPACE, createContent?.type) assertEquals("Room type should be space", RoomType.SPACE, createContent?.type)
var powerLevelsContent: PowerLevelsContent? = null var powerLevelsContent: PowerLevelsContent? = null
commonTestHelper.waitWithLatch { latch -> commonTestHelper.waitWithLatch { latch ->
commonTestHelper.retryPeriodicallyWithLatch(latch) { commonTestHelper.retryPeriodicallyWithLatch(latch) {
val toModel = syncedSpace.asRoom().getStateEvent(EventType.STATE_ROOM_POWER_LEVELS)?.content.toModel<PowerLevelsContent>() powerLevelsContent = syncedSpace.asRoom()
powerLevelsContent = toModel .getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
toModel != null ?.content
?.toModel<PowerLevelsContent>()
powerLevelsContent != null
} }
} }
assertEquals("Space-rooms should be created with a power level for events_default of 100", 100, powerLevelsContent?.eventsDefault) assertEquals("Space-rooms should be created with a power level for events_default of 100", 100, powerLevelsContent?.eventsDefault)
val guestAccess = syncedSpace.asRoom().getStateEvent(EventType.STATE_ROOM_GUEST_ACCESS)?.content val guestAccess = syncedSpace.asRoom()
?.toModel<RoomGuestAccessContent>()?.guestAccess .getStateEvent(EventType.STATE_ROOM_GUEST_ACCESS, QueryStringValue.IsEmpty)
?.content
?.toModel<RoomGuestAccessContent>()
?.guestAccess
assertEquals("Public space room should be peekable by guest", GuestAccess.CanJoin, guestAccess) assertEquals("Public space room should be peekable by guest", GuestAccess.CanJoin, guestAccess)
val historyVisibility = syncedSpace.asRoom().getStateEvent(EventType.STATE_ROOM_HISTORY_VISIBILITY)?.content val historyVisibility = syncedSpace.asRoom()
?.toModel<RoomHistoryVisibilityContent>()?.historyVisibility .getStateEvent(EventType.STATE_ROOM_HISTORY_VISIBILITY, QueryStringValue.IsEmpty)
?.content
?.toModel<RoomHistoryVisibilityContent>()
?.historyVisibility
assertEquals("Public space room should be world readable", RoomHistoryVisibility.WORLD_READABLE, historyVisibility) assertEquals("Public space room should be world readable", RoomHistoryVisibility.WORLD_READABLE, historyVisibility)
} }

View File

@ -569,8 +569,9 @@ class SpaceHierarchyTest : InstrumentedTest {
commonTestHelper.waitWithLatch { commonTestHelper.waitWithLatch {
val room = bobSession.getRoom(bobRoomId)!! val room = bobSession.getRoom(bobRoomId)!!
val currentPLContent = room val currentPLContent = room
.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS) .getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
?.let { it.content.toModel<PowerLevelsContent>() } ?.content
.toModel<PowerLevelsContent>()
val newPowerLevelsContent = currentPLContent val newPowerLevelsContent = currentPLContent
?.setUserPowerLevel(aliceSession.myUserId, Role.Admin.value) ?.setUserPowerLevel(aliceSession.myUserId, Role.Admin.value)
@ -583,7 +584,7 @@ class SpaceHierarchyTest : InstrumentedTest {
commonTestHelper.waitWithLatch { latch -> commonTestHelper.waitWithLatch { latch ->
commonTestHelper.retryPeriodicallyWithLatch(latch) { commonTestHelper.retryPeriodicallyWithLatch(latch) {
val powerLevelsHelper = aliceSession.getRoom(bobRoomId)!! val powerLevelsHelper = aliceSession.getRoom(bobRoomId)!!
.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS) .getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
?.content ?.content
?.toModel<PowerLevelsContent>() ?.toModel<PowerLevelsContent>()
?.let { PowerLevelsHelper(it) } ?.let { PowerLevelsHelper(it) }

View File

@ -16,6 +16,11 @@
package org.matrix.android.sdk.api.query package org.matrix.android.sdk.api.query
/**
* Only a subset of [QueryStringValue] are applicable to query the `stateKey` of a state event.
*/
sealed interface QueryStateEventValue
/** /**
* Basic query language. All these cases are mutually exclusive. * Basic query language. All these cases are mutually exclusive.
*/ */
@ -33,22 +38,22 @@ sealed interface QueryStringValue {
/** /**
* The tested field has to be not null. * The tested field has to be not null.
*/ */
object IsNotNull : QueryStringValue object IsNotNull : QueryStringValue, QueryStateEventValue
/** /**
* The tested field has to be empty. * The tested field has to be empty.
*/ */
object IsEmpty : QueryStringValue object IsEmpty : QueryStringValue, QueryStateEventValue
/** /**
* The tested field has to not empty. * The tested field has to be not empty.
*/ */
object IsNotEmpty : QueryStringValue object IsNotEmpty : QueryStringValue, QueryStateEventValue
/** /**
* Interface to check String content. * Interface to check String content.
*/ */
sealed interface ContentQueryStringValue : QueryStringValue { sealed interface ContentQueryStringValue : QueryStringValue, QueryStateEventValue {
val string: String val string: String
val case: Case val case: Case
} }

View File

@ -16,18 +16,21 @@
package org.matrix.android.sdk.api.session.room package org.matrix.android.sdk.api.session.room
import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
/** /**
* Get a TimelineEvent using the TimelineService of a Room. * Get a TimelineEvent using the TimelineService of a Room.
* @param eventId The id of the event to retrieve
*/ */
fun Room.getTimelineEvent(eventId: String): TimelineEvent? = fun Room.getTimelineEvent(eventId: String): TimelineEvent? =
timelineService().getTimelineEvent(eventId) timelineService().getTimelineEvent(eventId)
/** /**
* Get a StateEvent using the StateService of a Room. * Get a StateEvent using the StateService of a Room.
* @param eventType The type of the event, see [org.matrix.android.sdk.api.session.events.model.EventType].
* @param stateKey the query which will be done on the stateKey.
*/ */
fun Room.getStateEvent(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): Event? = fun Room.getStateEvent(eventType: String, stateKey: QueryStateEventValue): Event? =
stateService().getStateEvent(eventType, stateKey) stateService().getStateEvent(eventType, stateKey)

View File

@ -18,7 +18,7 @@ package org.matrix.android.sdk.api.session.room.state
import android.net.Uri import android.net.Uri
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.session.room.model.GuestAccess
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
@ -93,28 +93,28 @@ interface StateService {
* @param eventType An eventType. * @param eventType An eventType.
* @param stateKey the query which will be done on the stateKey * @param stateKey the query which will be done on the stateKey
*/ */
fun getStateEvent(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): Event? fun getStateEvent(eventType: String, stateKey: QueryStateEventValue): Event?
/** /**
* Get a live state event of the room. * Get a live state event of the room.
* @param eventType An eventType. * @param eventType An eventType.
* @param stateKey the query which will be done on the stateKey * @param stateKey the query which will be done on the stateKey
*/ */
fun getStateEventLive(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): LiveData<Optional<Event>> fun getStateEventLive(eventType: String, stateKey: QueryStateEventValue): LiveData<Optional<Event>>
/** /**
* Get state events of the room. * Get state events of the room.
* @param eventTypes Set of eventType. If empty, all state events will be returned * @param eventTypes Set of eventType. If empty, all state events will be returned
* @param stateKey the query which will be done on the stateKey * @param stateKey the query which will be done on the stateKey
*/ */
fun getStateEvents(eventTypes: Set<String>, stateKey: QueryStringValue = QueryStringValue.NoCondition): List<Event> fun getStateEvents(eventTypes: Set<String>, stateKey: QueryStateEventValue): List<Event>
/** /**
* Get live state events of the room. * Get live state events of the room.
* @param eventTypes Set of eventType to observe. If empty, all state events will be observed * @param eventTypes Set of eventType to observe. If empty, all state events will be observed
* @param stateKey the query which will be done on the stateKey * @param stateKey the query which will be done on the stateKey
*/ */
fun getStateEventsLive(eventTypes: Set<String>, stateKey: QueryStringValue = QueryStringValue.NoCondition): LiveData<List<Event>> fun getStateEventsLive(eventTypes: Set<String>, stateKey: QueryStateEventValue): LiveData<List<Event>>
suspend fun setJoinRulePublic() suspend fun setJoinRulePublic()
suspend fun setJoinRuleInviteOnly() suspend fun setJoinRuleInviteOnly()

View File

@ -26,7 +26,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
* Return true if a room can be joined by anyone (RoomJoinRules.PUBLIC). * Return true if a room can be joined by anyone (RoomJoinRules.PUBLIC).
*/ */
fun StateService.isPublic(): Boolean { fun StateService.isPublic(): Boolean {
return getStateEvent(EventType.STATE_ROOM_JOIN_RULES, QueryStringValue.NoCondition) return getStateEvent(EventType.STATE_ROOM_JOIN_RULES, QueryStringValue.IsEmpty)
?.content ?.content
?.toModel<RoomJoinRulesContent>() ?.toModel<RoomJoinRulesContent>()
?.joinRules == RoomJoinRules.PUBLIC ?.joinRules == RoomJoinRules.PUBLIC

View File

@ -17,7 +17,7 @@
package org.matrix.android.sdk.api.session.widgets package org.matrix.android.sdk.api.session.widgets
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.widgets.model.Widget import org.matrix.android.sdk.api.session.widgets.model.Widget
@ -49,7 +49,7 @@ interface WidgetService {
*/ */
fun getRoomWidgets( fun getRoomWidgets(
roomId: String, roomId: String,
widgetId: QueryStringValue = QueryStringValue.NoCondition, widgetId: QueryStateEventValue,
widgetTypes: Set<String>? = null, widgetTypes: Set<String>? = null,
excludedTypes: Set<String>? = null excludedTypes: Set<String>? = null
): List<Widget> ): List<Widget>
@ -70,7 +70,7 @@ interface WidgetService {
*/ */
fun getRoomWidgetsLive( fun getRoomWidgetsLive(
roomId: String, roomId: String,
widgetId: QueryStringValue = QueryStringValue.NoCondition, widgetId: QueryStateEventValue,
widgetTypes: Set<String>? = null, widgetTypes: Set<String>? = null,
excludedTypes: Set<String>? = null excludedTypes: Set<String>? = null
): LiveData<List<Widget>> ): LiveData<List<Widget>>

View File

@ -101,7 +101,7 @@ internal class ViaParameterFinder @Inject constructor(
} }
fun userCanInvite(userId: String, roomId: String): Boolean { fun userCanInvite(userId: String, roomId: String): Boolean {
val powerLevelsHelper = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition) val powerLevelsHelper = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
?.content?.toModel<PowerLevelsContent>() ?.content?.toModel<PowerLevelsContent>()
?.let { PowerLevelsHelper(it) } ?.let { PowerLevelsHelper(it) }

View File

@ -15,6 +15,7 @@
*/ */
package org.matrix.android.sdk.internal.session.pushers package org.matrix.android.sdk.internal.session.pushers
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.events.model.toModel
@ -55,7 +56,7 @@ internal class DefaultConditionResolver @Inject constructor(
val roomId = event.roomId ?: return false val roomId = event.roomId ?: return false
val room = roomGetter.getRoom(roomId) ?: return false val room = roomGetter.getRoom(roomId) ?: return false
val powerLevelsContent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS) val powerLevelsContent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
?.content ?.content
?.toModel<PowerLevelsContent>() ?.toModel<PowerLevelsContent>()
?: PowerLevelsContent() ?: PowerLevelsContent()

View File

@ -386,7 +386,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
} }
private fun getPowerLevelsHelper(roomId: String): PowerLevelsHelper? { private fun getPowerLevelsHelper(roomId: String): PowerLevelsHelper? {
return stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition) return stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
?.content?.toModel<PowerLevelsContent>() ?.content?.toModel<PowerLevelsContent>()
?.let { PowerLevelsHelper(it) } ?.let { PowerLevelsHelper(it) }
} }

View File

@ -60,7 +60,7 @@ internal class DefaultLeaveRoomTask @Inject constructor(
val roomCreateStateEvent = stateEventDataSource.getStateEvent( val roomCreateStateEvent = stateEventDataSource.getStateEvent(
roomId = roomId, roomId = roomId,
eventType = EventType.STATE_ROOM_CREATE, eventType = EventType.STATE_ROOM_CREATE,
stateKey = QueryStringValue.NoCondition stateKey = QueryStringValue.IsEmpty,
) )
// Server is not cleaning predecessor rooms, so we also try to left them // Server is not cleaning predecessor rooms, so we also try to left them
val predecessorRoomId = roomCreateStateEvent?.getClearContent()?.toModel<RoomCreateContent>()?.predecessor?.roomId val predecessorRoomId = roomCreateStateEvent?.getClearContent()?.toModel<RoomCreateContent>()?.predecessor?.roomId

View File

@ -22,6 +22,7 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.EventType
@ -54,19 +55,19 @@ internal class DefaultStateService @AssistedInject constructor(
fun create(roomId: String): DefaultStateService fun create(roomId: String): DefaultStateService
} }
override fun getStateEvent(eventType: String, stateKey: QueryStringValue): Event? { override fun getStateEvent(eventType: String, stateKey: QueryStateEventValue): Event? {
return stateEventDataSource.getStateEvent(roomId, eventType, stateKey) return stateEventDataSource.getStateEvent(roomId, eventType, stateKey)
} }
override fun getStateEventLive(eventType: String, stateKey: QueryStringValue): LiveData<Optional<Event>> { override fun getStateEventLive(eventType: String, stateKey: QueryStateEventValue): LiveData<Optional<Event>> {
return stateEventDataSource.getStateEventLive(roomId, eventType, stateKey) return stateEventDataSource.getStateEventLive(roomId, eventType, stateKey)
} }
override fun getStateEvents(eventTypes: Set<String>, stateKey: QueryStringValue): List<Event> { override fun getStateEvents(eventTypes: Set<String>, stateKey: QueryStateEventValue): List<Event> {
return stateEventDataSource.getStateEvents(roomId, eventTypes, stateKey) return stateEventDataSource.getStateEvents(roomId, eventTypes, stateKey)
} }
override fun getStateEventsLive(eventTypes: Set<String>, stateKey: QueryStringValue): LiveData<List<Event>> { override fun getStateEventsLive(eventTypes: Set<String>, stateKey: QueryStateEventValue): LiveData<List<Event>> {
return stateEventDataSource.getStateEventsLive(roomId, eventTypes, stateKey) return stateEventDataSource.getStateEventsLive(roomId, eventTypes, stateKey)
} }

View File

@ -22,6 +22,7 @@ import com.zhuinden.monarchy.Monarchy
import io.realm.Realm import io.realm.Realm
import io.realm.RealmQuery import io.realm.RealmQuery
import io.realm.kotlin.where import io.realm.kotlin.where
import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.Optional
@ -40,13 +41,13 @@ internal class StateEventDataSource @Inject constructor(
private val queryStringValueProcessor: QueryStringValueProcessor private val queryStringValueProcessor: QueryStringValueProcessor
) { ) {
fun getStateEvent(roomId: String, eventType: String, stateKey: QueryStringValue): Event? { fun getStateEvent(roomId: String, eventType: String, stateKey: QueryStateEventValue): Event? {
return realmSessionProvider.withRealm { realm -> return realmSessionProvider.withRealm { realm ->
buildStateEventQuery(realm, roomId, setOf(eventType), stateKey).findFirst()?.root?.asDomain() buildStateEventQuery(realm, roomId, setOf(eventType), stateKey).findFirst()?.root?.asDomain()
} }
} }
fun getStateEventLive(roomId: String, eventType: String, stateKey: QueryStringValue): LiveData<Optional<Event>> { fun getStateEventLive(roomId: String, eventType: String, stateKey: QueryStateEventValue): LiveData<Optional<Event>> {
val liveData = monarchy.findAllMappedWithChanges( val liveData = monarchy.findAllMappedWithChanges(
{ realm -> buildStateEventQuery(realm, roomId, setOf(eventType), stateKey) }, { realm -> buildStateEventQuery(realm, roomId, setOf(eventType), stateKey) },
{ it.root?.asDomain() } { it.root?.asDomain() }
@ -56,7 +57,7 @@ internal class StateEventDataSource @Inject constructor(
} }
} }
fun getStateEvents(roomId: String, eventTypes: Set<String>, stateKey: QueryStringValue): List<Event> { fun getStateEvents(roomId: String, eventTypes: Set<String>, stateKey: QueryStateEventValue): List<Event> {
return realmSessionProvider.withRealm { realm -> return realmSessionProvider.withRealm { realm ->
buildStateEventQuery(realm, roomId, eventTypes, stateKey) buildStateEventQuery(realm, roomId, eventTypes, stateKey)
.findAll() .findAll()
@ -66,7 +67,7 @@ internal class StateEventDataSource @Inject constructor(
} }
} }
fun getStateEventsLive(roomId: String, eventTypes: Set<String>, stateKey: QueryStringValue): LiveData<List<Event>> { fun getStateEventsLive(roomId: String, eventTypes: Set<String>, stateKey: QueryStateEventValue): LiveData<List<Event>> {
val liveData = monarchy.findAllMappedWithChanges( val liveData = monarchy.findAllMappedWithChanges(
{ realm -> buildStateEventQuery(realm, roomId, eventTypes, stateKey) }, { realm -> buildStateEventQuery(realm, roomId, eventTypes, stateKey) },
{ it.root?.asDomain() } { it.root?.asDomain() }
@ -80,7 +81,7 @@ internal class StateEventDataSource @Inject constructor(
realm: Realm, realm: Realm,
roomId: String, roomId: String,
eventTypes: Set<String>, eventTypes: Set<String>,
stateKey: QueryStringValue stateKey: QueryStateEventValue
): RealmQuery<CurrentStateEventEntity> { ): RealmQuery<CurrentStateEventEntity> {
return with(queryStringValueProcessor) { return with(queryStringValueProcessor) {
realm.where<CurrentStateEventEntity>() realm.where<CurrentStateEventEntity>()
@ -90,7 +91,8 @@ internal class StateEventDataSource @Inject constructor(
`in`(CurrentStateEventEntityFields.TYPE, eventTypes.toTypedArray()) `in`(CurrentStateEventEntityFields.TYPE, eventTypes.toTypedArray())
} }
} }
.process(CurrentStateEventEntityFields.STATE_KEY, stateKey) // It's OK to cast stateKey as QueryStringValue
.process(CurrentStateEventEntityFields.STATE_KEY, stateKey as QueryStringValue)
} }
} }
} }

View File

@ -46,7 +46,7 @@ internal class LiveRoomStateListener(
stateEventDataSource.getStateEventsLive( stateEventDataSource.getStateEventsLive(
roomId = roomId, roomId = roomId,
eventTypes = setOf(EventType.STATE_ROOM_MEMBER), eventTypes = setOf(EventType.STATE_ROOM_MEMBER),
stateKey = QueryStringValue.NoCondition, stateKey = QueryStringValue.IsNotNull,
) )
} }

View File

@ -71,7 +71,7 @@ internal class DefaultRoomVersionService @AssistedInject constructor(
} }
override fun userMayUpgradeRoom(userId: String): Boolean { override fun userMayUpgradeRoom(userId: String): Boolean {
val powerLevelsHelper = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition) val powerLevelsHelper = stateEventDataSource.getStateEvent(roomId, EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
?.content?.toModel<PowerLevelsContent>() ?.content?.toModel<PowerLevelsContent>()
?.let { PowerLevelsHelper(it) } ?.let { PowerLevelsHelper(it) }

View File

@ -252,7 +252,7 @@ internal class DefaultSpaceService @Inject constructor(
val powerLevelsEvent = stateEventDataSource.getStateEvent( val powerLevelsEvent = stateEventDataSource.getStateEvent(
roomId = parentSpaceId, roomId = parentSpaceId,
eventType = EventType.STATE_ROOM_POWER_LEVELS, eventType = EventType.STATE_ROOM_POWER_LEVELS,
stateKey = QueryStringValue.NoCondition stateKey = QueryStringValue.IsEmpty
) )
val powerLevelsContent = powerLevelsEvent?.content?.toModel<PowerLevelsContent>() val powerLevelsContent = powerLevelsEvent?.content?.toModel<PowerLevelsContent>()
?: throw UnsupportedOperationException("Cannot add canonical child, missing powerlevel") ?: throw UnsupportedOperationException("Cannot add canonical child, missing powerlevel")

View File

@ -17,7 +17,7 @@
package org.matrix.android.sdk.internal.session.widgets package org.matrix.android.sdk.internal.session.widgets
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.widgets.WidgetPostAPIMediator import org.matrix.android.sdk.api.session.widgets.WidgetPostAPIMediator
import org.matrix.android.sdk.api.session.widgets.WidgetService import org.matrix.android.sdk.api.session.widgets.WidgetService
@ -43,7 +43,7 @@ internal class DefaultWidgetService @Inject constructor(
override fun getRoomWidgets( override fun getRoomWidgets(
roomId: String, roomId: String,
widgetId: QueryStringValue, widgetId: QueryStateEventValue,
widgetTypes: Set<String>?, widgetTypes: Set<String>?,
excludedTypes: Set<String>? excludedTypes: Set<String>?
): List<Widget> { ): List<Widget> {
@ -56,7 +56,7 @@ internal class DefaultWidgetService @Inject constructor(
override fun getRoomWidgetsLive( override fun getRoomWidgetsLive(
roomId: String, roomId: String,
widgetId: QueryStringValue, widgetId: QueryStateEventValue,
widgetTypes: Set<String>?, widgetTypes: Set<String>?,
excludedTypes: Set<String>? excludedTypes: Set<String>?
): LiveData<List<Widget>> { ): LiveData<List<Widget>> {

View File

@ -21,6 +21,7 @@ import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry import androidx.lifecycle.LifecycleRegistry
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Transformations import androidx.lifecycle.Transformations
import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.SessionLifecycleObserver import org.matrix.android.sdk.api.session.SessionLifecycleObserver
@ -71,7 +72,7 @@ internal class WidgetManager @Inject constructor(
fun getRoomWidgetsLive( fun getRoomWidgetsLive(
roomId: String, roomId: String,
widgetId: QueryStringValue = QueryStringValue.NoCondition, widgetId: QueryStateEventValue,
widgetTypes: Set<String>? = null, widgetTypes: Set<String>? = null,
excludedTypes: Set<String>? = null excludedTypes: Set<String>? = null
): LiveData<List<Widget>> { ): LiveData<List<Widget>> {
@ -88,7 +89,7 @@ internal class WidgetManager @Inject constructor(
fun getRoomWidgets( fun getRoomWidgets(
roomId: String, roomId: String,
widgetId: QueryStringValue = QueryStringValue.NoCondition, widgetId: QueryStateEventValue,
widgetTypes: Set<String>? = null, widgetTypes: Set<String>? = null,
excludedTypes: Set<String>? = null excludedTypes: Set<String>? = null
): List<Widget> { ): List<Widget> {
@ -199,7 +200,7 @@ internal class WidgetManager @Inject constructor(
val powerLevelsEvent = stateEventDataSource.getStateEvent( val powerLevelsEvent = stateEventDataSource.getStateEvent(
roomId = roomId, roomId = roomId,
eventType = EventType.STATE_ROOM_POWER_LEVELS, eventType = EventType.STATE_ROOM_POWER_LEVELS,
stateKey = QueryStringValue.NoCondition stateKey = QueryStringValue.IsEmpty
) )
val powerLevelsContent = powerLevelsEvent?.content?.toModel<PowerLevelsContent>() ?: return false val powerLevelsContent = powerLevelsEvent?.content?.toModel<PowerLevelsContent>() ?: return false
return PowerLevelsHelper(powerLevelsContent).isUserAllowedToSend(userId, true, EventType.STATE_ROOM_WIDGET_LEGACY) return PowerLevelsHelper(powerLevelsContent).isUserAllowedToSend(userId, true, EventType.STATE_ROOM_WIDGET_LEGACY)

View File

@ -32,6 +32,7 @@ import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.json.JSONObject import org.json.JSONObject
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.EventType
@ -59,7 +60,7 @@ class RoomDevToolViewModel @AssistedInject constructor(
init { init {
session.getRoom(initialState.roomId) session.getRoom(initialState.roomId)
?.flow() ?.flow()
?.liveStateEvents(emptySet()) ?.liveStateEvents(emptySet(), QueryStringValue.IsNotNull)
?.execute { async -> ?.execute { async ->
copy(stateEvents = async) copy(stateEvents = async)
} }

View File

@ -294,7 +294,7 @@ class TimelineViewModel @AssistedInject constructor(
session.flow() session.flow()
.liveRoomWidgets( .liveRoomWidgets(
roomId = initialState.roomId, roomId = initialState.roomId,
widgetId = QueryStringValue.NoCondition widgetId = QueryStringValue.IsNotNull
) )
.map { widgets -> .map { widgets ->
widgets.filter { it.isActive } widgets.filter { it.isActive }
@ -1239,7 +1239,7 @@ class TimelineViewModel @AssistedInject constructor(
setState { copy(asyncInviter = Success(it)) } setState { copy(asyncInviter = Success(it)) }
} }
} }
room.getStateEvent(EventType.STATE_ROOM_TOMBSTONE)?.also { room.getStateEvent(EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty)?.also {
setState { copy(tombstoneEvent = it) } setState { copy(tombstoneEvent = it) }
} }
} }

View File

@ -683,7 +683,7 @@ class MessageComposerViewModel @AssistedInject constructor(
} }
private fun handleSetUserPowerLevel(setUserPowerLevel: ParsedCommand.SetUserPowerLevel) { private fun handleSetUserPowerLevel(setUserPowerLevel: ParsedCommand.SetUserPowerLevel) {
val newPowerLevelsContent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS) val newPowerLevelsContent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
?.content ?.content
?.toModel<PowerLevelsContent>() ?.toModel<PowerLevelsContent>()
?.setUserPowerLevel(setUserPowerLevel.userId, setUserPowerLevel.powerLevel) ?.setUserPowerLevel(setUserPowerLevel.userId, setUserPowerLevel.powerLevel)

View File

@ -222,7 +222,7 @@ class MergedHeaderItemFactory @Inject constructor(
} }
val mergeId = mergedEventIds.joinToString(separator = "_") { it.toString() } val mergeId = mergedEventIds.joinToString(separator = "_") { it.toString() }
val powerLevelsHelper = activeSessionHolder.getSafeActiveSession()?.getRoom(event.roomId) val powerLevelsHelper = activeSessionHolder.getSafeActiveSession()?.getRoom(event.roomId)
?.let { it.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition)?.content?.toModel<PowerLevelsContent>() } ?.let { it.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)?.content?.toModel<PowerLevelsContent>() }
?.let { PowerLevelsHelper(it) } ?.let { PowerLevelsHelper(it) }
val currentUserId = activeSessionHolder.getSafeActiveSession()?.myUserId ?: "" val currentUserId = activeSessionHolder.getSafeActiveSession()?.myUserId ?: ""
val attributes = MergedRoomCreationItem.Attributes( val attributes = MergedRoomCreationItem.Attributes(

View File

@ -32,7 +32,7 @@ class PowerLevelsFlowFactory(private val room: Room) {
fun createFlow(): Flow<PowerLevelsContent> { fun createFlow(): Flow<PowerLevelsContent> {
return room.flow() return room.flow()
.liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition) .liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
.mapOptional { it.content.toModel<PowerLevelsContent>() } .mapOptional { it.content.toModel<PowerLevelsContent>() }
.flowOn(Dispatchers.Default) .flowOn(Dispatchers.Default)
.unwrap() .unwrap()

View File

@ -91,7 +91,7 @@ class RoomProfileViewModel @AssistedInject constructor(
} }
private fun observeRoomCreateContent(flowRoom: FlowRoom) { private fun observeRoomCreateContent(flowRoom: FlowRoom) {
flowRoom.liveStateEvent(EventType.STATE_ROOM_CREATE, QueryStringValue.NoCondition) flowRoom.liveStateEvent(EventType.STATE_ROOM_CREATE, QueryStringValue.IsEmpty)
.mapOptional { it.content.toModel<RoomCreateContent>() } .mapOptional { it.content.toModel<RoomCreateContent>() }
.unwrap() .unwrap()
.execute { async -> .execute { async ->
@ -101,7 +101,7 @@ class RoomProfileViewModel @AssistedInject constructor(
recommendedRoomVersion = room.roomVersionService().getRecommendedVersion(), recommendedRoomVersion = room.roomVersionService().getRecommendedVersion(),
isUsingUnstableRoomVersion = room.roomVersionService().isUsingUnstableRoomVersion(), isUsingUnstableRoomVersion = room.roomVersionService().isUsingUnstableRoomVersion(),
canUpgradeRoom = room.roomVersionService().userMayUpgradeRoom(session.myUserId), canUpgradeRoom = room.roomVersionService().userMayUpgradeRoom(session.myUserId),
isTombstoned = room.getStateEvent(EventType.STATE_ROOM_TOMBSTONE) != null isTombstoned = room.getStateEvent(EventType.STATE_ROOM_TOMBSTONE, QueryStringValue.IsEmpty) != null
) )
} }
} }

View File

@ -167,7 +167,7 @@ class RoomAliasViewModel @AssistedInject constructor(
*/ */
private fun observeRoomCanonicalAlias() { private fun observeRoomCanonicalAlias() {
room.flow() room.flow()
.liveStateEvent(EventType.STATE_ROOM_CANONICAL_ALIAS, QueryStringValue.NoCondition) .liveStateEvent(EventType.STATE_ROOM_CANONICAL_ALIAS, QueryStringValue.IsEmpty)
.mapOptional { it.content.toModel<RoomCanonicalAliasContent>() } .mapOptional { it.content.toModel<RoomCanonicalAliasContent>() }
.unwrap() .unwrap()
.setOnEach { .setOnEach {

View File

@ -84,7 +84,7 @@ class RoomMemberListViewModel @AssistedInject constructor(
combine( combine(
room.flow().liveRoomMembers(roomMemberQueryParams), room.flow().liveRoomMembers(roomMemberQueryParams),
room.flow() room.flow()
.liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition) .liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
.mapOptional { it.content.toModel<PowerLevelsContent>() } .mapOptional { it.content.toModel<PowerLevelsContent>() }
.unwrap() .unwrap()
) { roomMembers, powerLevelsContent -> ) { roomMembers, powerLevelsContent ->
@ -146,7 +146,8 @@ class RoomMemberListViewModel @AssistedInject constructor(
} }
private fun observeThirdPartyInvites() { private fun observeThirdPartyInvites() {
room.flow().liveStateEvents(setOf(EventType.STATE_ROOM_THIRD_PARTY_INVITE)) room.flow()
.liveStateEvents(setOf(EventType.STATE_ROOM_THIRD_PARTY_INVITE), QueryStringValue.IsNotNull)
.execute { async -> .execute { async ->
copy(threePidInvites = async) copy(threePidInvites = async)
} }

View File

@ -158,7 +158,7 @@ class RoomSettingsViewModel @AssistedInject constructor(
private fun observeRoomHistoryVisibility() { private fun observeRoomHistoryVisibility() {
room.flow() room.flow()
.liveStateEvent(EventType.STATE_ROOM_HISTORY_VISIBILITY, QueryStringValue.NoCondition) .liveStateEvent(EventType.STATE_ROOM_HISTORY_VISIBILITY, QueryStringValue.IsEmpty)
.mapOptional { it.content.toModel<RoomHistoryVisibilityContent>() } .mapOptional { it.content.toModel<RoomHistoryVisibilityContent>() }
.unwrap() .unwrap()
.mapNotNull { it.historyVisibility } .mapNotNull { it.historyVisibility }
@ -169,7 +169,7 @@ class RoomSettingsViewModel @AssistedInject constructor(
private fun observeJoinRule() { private fun observeJoinRule() {
room.flow() room.flow()
.liveStateEvent(EventType.STATE_ROOM_JOIN_RULES, QueryStringValue.NoCondition) .liveStateEvent(EventType.STATE_ROOM_JOIN_RULES, QueryStringValue.IsEmpty)
.mapOptional { it.content.toModel<RoomJoinRulesContent>() } .mapOptional { it.content.toModel<RoomJoinRulesContent>() }
.unwrap() .unwrap()
.mapNotNull { it.joinRules } .mapNotNull { it.joinRules }
@ -180,7 +180,7 @@ class RoomSettingsViewModel @AssistedInject constructor(
private fun observeGuestAccess() { private fun observeGuestAccess() {
room.flow() room.flow()
.liveStateEvent(EventType.STATE_ROOM_GUEST_ACCESS, QueryStringValue.NoCondition) .liveStateEvent(EventType.STATE_ROOM_GUEST_ACCESS, QueryStringValue.IsEmpty)
.mapOptional { it.content.toModel<RoomGuestAccessContent>() } .mapOptional { it.content.toModel<RoomGuestAccessContent>() }
.unwrap() .unwrap()
.mapNotNull { it.guestAccess } .mapNotNull { it.guestAccess }
@ -194,7 +194,7 @@ class RoomSettingsViewModel @AssistedInject constructor(
*/ */
private fun observeRoomAvatar() { private fun observeRoomAvatar() {
room.flow() room.flow()
.liveStateEvent(EventType.STATE_ROOM_AVATAR, QueryStringValue.NoCondition) .liveStateEvent(EventType.STATE_ROOM_AVATAR, QueryStringValue.IsEmpty)
.mapOptional { it.content.toModel<RoomAvatarContent>() } .mapOptional { it.content.toModel<RoomAvatarContent>() }
.unwrap() .unwrap()
.setOnEach { .setOnEach {

View File

@ -70,7 +70,7 @@ class RoomJoinRuleChooseRestrictedViewModel @AssistedInject constructor(
private fun initializeForRoom(roomId: String) { private fun initializeForRoom(roomId: String) {
room = session.getRoom(roomId)!! room = session.getRoom(roomId)!!
session.getRoomSummary(roomId)?.let { roomSummary -> session.getRoomSummary(roomId)?.let { roomSummary ->
val joinRulesContent = room.getStateEvent(EventType.STATE_ROOM_JOIN_RULES, QueryStringValue.NoCondition) val joinRulesContent = room.getStateEvent(EventType.STATE_ROOM_JOIN_RULES, QueryStringValue.IsEmpty)
?.content ?.content
?.toModel<RoomJoinRulesContent>() ?.toModel<RoomJoinRulesContent>()
val initialAllowList = joinRulesContent?.allowList val initialAllowList = joinRulesContent?.allowList

View File

@ -33,6 +33,7 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import okhttp3.internal.toImmutableList import okhttp3.internal.toImmutableList
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.query.RoomCategoryFilter import org.matrix.android.sdk.api.query.RoomCategoryFilter
import org.matrix.android.sdk.api.query.SpaceFilter import org.matrix.android.sdk.api.query.SpaceFilter
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
@ -59,7 +60,7 @@ class SpaceLeaveAdvancedViewModel @AssistedInject constructor(
val space = session.getRoom(initialState.spaceId) val space = session.getRoom(initialState.spaceId)
val spaceSummary = space?.roomSummary() val spaceSummary = space?.roomSummary()
val powerLevelsEvent = space?.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS) val powerLevelsEvent = space?.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
powerLevelsEvent?.content?.toModel<PowerLevelsContent>()?.let { powerLevelsContent -> powerLevelsEvent?.content?.toModel<PowerLevelsContent>()?.let { powerLevelsContent ->
val powerLevelsHelper = PowerLevelsHelper(powerLevelsContent) val powerLevelsHelper = PowerLevelsHelper(powerLevelsContent)
val isAdmin = powerLevelsHelper.getUserRole(session.myUserId) is Role.Admin val isAdmin = powerLevelsHelper.getUserRole(session.myUserId) is Role.Admin

View File

@ -121,7 +121,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(
} }
val userId = eventData["user_id"] as String val userId = eventData["user_id"] as String
Timber.d("Received request to get options for bot $userId in room $roomId requested") Timber.d("Received request to get options for bot $userId in room $roomId requested")
val stateEvents = room.stateService().getStateEvents(setOf(EventType.BOT_OPTIONS)) val stateEvents = room.stateService().getStateEvents(setOf(EventType.BOT_OPTIONS), QueryStringValue.IsNotNull)
var botOptionsEvent: Event? = null var botOptionsEvent: Event? = null
val stateKey = "_$userId" val stateKey = "_$userId"
for (stateEvent in stateEvents) { for (stateEvent in stateEvents) {
@ -155,7 +155,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(
Timber.d("## canSendEvent() : eventType $eventType isState $isState") Timber.d("## canSendEvent() : eventType $eventType isState $isState")
val powerLevelsEvent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS) val powerLevelsEvent = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
val powerLevelsContent = powerLevelsEvent?.content?.toModel<PowerLevelsContent>() val powerLevelsContent = powerLevelsEvent?.content?.toModel<PowerLevelsContent>()
val canSend = if (powerLevelsContent == null) { val canSend = if (powerLevelsContent == null) {
false false
@ -202,7 +202,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(
return return
} }
Timber.d("Received request join rules in room $roomId") Timber.d("Received request join rules in room $roomId")
val joinedEvents = room.stateService().getStateEvents(setOf(EventType.STATE_ROOM_JOIN_RULES)) val joinedEvents = room.stateService().getStateEvents(setOf(EventType.STATE_ROOM_JOIN_RULES), QueryStringValue.IsEmpty)
if (joinedEvents.isNotEmpty()) { if (joinedEvents.isNotEmpty()) {
widgetPostAPIMediator.sendObjectResponse(Event::class.java, joinedEvents.last(), eventData) widgetPostAPIMediator.sendObjectResponse(Event::class.java, joinedEvents.last(), eventData)
} else { } else {
@ -222,7 +222,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(
} }
Timber.d("Received request to get widget in room $roomId") Timber.d("Received request to get widget in room $roomId")
val responseData = ArrayList<JsonDict>() val responseData = ArrayList<JsonDict>()
val allWidgets = session.widgetService().getRoomWidgets(roomId) + session.widgetService().getUserWidgets() val allWidgets = session.widgetService().getRoomWidgets(roomId, QueryStringValue.IsNotNull) + session.widgetService().getUserWidgets()
for (widget in allWidgets) { for (widget in allWidgets) {
val map = widget.event.toContent() val map = widget.event.toContent()
responseData.add(map) responseData.add(map)

View File

@ -111,7 +111,7 @@ class WidgetViewModel @AssistedInject constructor(
if (room == null) { if (room == null) {
return return
} }
room.flow().liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition) room.flow().liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty)
.mapOptional { it.content.toModel<PowerLevelsContent>() } .mapOptional { it.content.toModel<PowerLevelsContent>() }
.unwrap() .unwrap()
.map { .map {