Merge pull request #5858 from vector-im/feature/bma/room_api

Room now exposes methods to get the various Services
This commit is contained in:
Benoit Marty 2022-05-04 11:55:04 +02:00 committed by GitHub
commit 5076b2cdbd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
71 changed files with 565 additions and 372 deletions

1
changelog.d/5858.sdk Normal file
View file

@ -0,0 +1 @@
`Room` apis are now available by requesting the service first. For instance `Room.updateAvatar(...)` is now `Room.stateService().updateAvatar(...)`

View file

@ -21,6 +21,8 @@ import kotlinx.coroutines.flow.Flow
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.room.Room
import org.matrix.android.sdk.api.session.room.getStateEvent
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.members.RoomMemberQueryParams
import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary
import org.matrix.android.sdk.api.session.room.model.ReadReceipt
@ -45,81 +47,81 @@ class FlowRoom(private val room: Room) {
}
fun liveRoomMembers(queryParams: RoomMemberQueryParams): Flow<List<RoomMemberSummary>> {
return room.getRoomMembersLive(queryParams).asFlow()
return room.membershipService().getRoomMembersLive(queryParams).asFlow()
.startWith(room.coroutineDispatchers.io) {
room.getRoomMembers(queryParams)
room.membershipService().getRoomMembers(queryParams)
}
}
fun liveAnnotationSummary(eventId: String): Flow<Optional<EventAnnotationsSummary>> {
return room.getEventAnnotationsSummaryLive(eventId).asFlow()
return room.relationService().getEventAnnotationsSummaryLive(eventId).asFlow()
.startWith(room.coroutineDispatchers.io) {
room.getEventAnnotationsSummary(eventId).toOptional()
room.relationService().getEventAnnotationsSummary(eventId).toOptional()
}
}
fun liveTimelineEvent(eventId: String): Flow<Optional<TimelineEvent>> {
return room.getTimelineEventLive(eventId).asFlow()
return room.timelineService().getTimelineEventLive(eventId).asFlow()
.startWith(room.coroutineDispatchers.io) {
room.getTimelineEvent(eventId).toOptional()
}
}
fun liveStateEvent(eventType: String, stateKey: QueryStringValue): Flow<Optional<Event>> {
return room.getStateEventLive(eventType, stateKey).asFlow()
return room.stateService().getStateEventLive(eventType, stateKey).asFlow()
.startWith(room.coroutineDispatchers.io) {
room.getStateEvent(eventType, stateKey).toOptional()
}
}
fun liveStateEvents(eventTypes: Set<String>): Flow<List<Event>> {
return room.getStateEventsLive(eventTypes).asFlow()
return room.stateService().getStateEventsLive(eventTypes).asFlow()
.startWith(room.coroutineDispatchers.io) {
room.getStateEvents(eventTypes)
room.stateService().getStateEvents(eventTypes)
}
}
fun liveReadMarker(): Flow<Optional<String>> {
return room.getReadMarkerLive().asFlow()
return room.readService().getReadMarkerLive().asFlow()
}
fun liveReadReceipt(): Flow<Optional<String>> {
return room.getMyReadReceiptLive().asFlow()
return room.readService().getMyReadReceiptLive().asFlow()
}
fun liveEventReadReceipts(eventId: String): Flow<List<ReadReceipt>> {
return room.getEventReadReceiptsLive(eventId).asFlow()
return room.readService().getEventReadReceiptsLive(eventId).asFlow()
}
fun liveDraft(): Flow<Optional<UserDraft>> {
return room.getDraftLive().asFlow()
return room.draftService().getDraftLive().asFlow()
.startWith(room.coroutineDispatchers.io) {
room.getDraft().toOptional()
room.draftService().getDraft().toOptional()
}
}
fun liveNotificationState(): Flow<RoomNotificationState> {
return room.getLiveRoomNotificationState().asFlow()
return room.roomPushRuleService().getLiveRoomNotificationState().asFlow()
}
fun liveThreadSummaries(): Flow<List<ThreadSummary>> {
return room.getAllThreadSummariesLive().asFlow()
return room.threadsService().getAllThreadSummariesLive().asFlow()
.startWith(room.coroutineDispatchers.io) {
room.getAllThreadSummaries()
room.threadsService().getAllThreadSummaries()
}
}
fun liveThreadList(): Flow<List<ThreadRootEvent>> {
return room.getAllThreadsLive().asFlow()
return room.threadsLocalService().getAllThreadsLive().asFlow()
.startWith(room.coroutineDispatchers.io) {
room.getAllThreads()
room.threadsLocalService().getAllThreads()
}
}
fun liveLocalUnreadThreadList(): Flow<List<ThreadRootEvent>> {
return room.getMarkedThreadNotificationsLive().asFlow()
return room.threadsLocalService().getMarkedThreadNotificationsLive().asFlow()
.startWith(room.coroutineDispatchers.io) {
room.getMarkedThreadNotifications()
room.threadsLocalService().getMarkedThreadNotifications()
}
}
}

View file

@ -145,7 +145,7 @@ class CommonTestHelper(context: Context) {
* @param nbOfMessages the number of time the message will be sent
*/
fun sendTextMessage(room: Room, message: String, nbOfMessages: Int, timeout: Long = TestConstants.timeOutMillis): List<TimelineEvent> {
val timeline = room.createTimeline(null, TimelineSettings(10))
val timeline = room.timelineService().createTimeline(null, TimelineSettings(10))
timeline.start()
val sentEvents = sendTextMessagesBatched(timeline, room, message, nbOfMessages, timeout)
timeline.dispose()
@ -165,11 +165,11 @@ class CommonTestHelper(context: Context) {
.forEach { batchedMessages ->
batchedMessages.forEach { formattedMessage ->
if (rootThreadEventId != null) {
room.replyInThread(
room.relationService().replyInThread(
rootThreadEventId = rootThreadEventId,
replyInThreadText = formattedMessage)
} else {
room.sendTextMessage(formattedMessage)
room.sendService().sendTextMessage(formattedMessage)
}
}
waitWithLatch(timeout) { latch ->
@ -214,7 +214,7 @@ class CommonTestHelper(context: Context) {
numberOfMessages: Int,
rootThreadEventId: String,
timeout: Long = TestConstants.timeOutMillis): List<TimelineEvent> {
val timeline = room.createTimeline(null, TimelineSettings(10))
val timeline = room.timelineService().createTimeline(null, TimelineSettings(10))
timeline.start()
val sentEvents = sendTextMessagesBatched(timeline, room, message, numberOfMessages, timeout, rootThreadEventId)
timeline.dispose()

View file

@ -70,7 +70,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) {
if (encryptedRoom) {
testHelper.waitWithLatch { latch ->
val room = aliceSession.getRoom(roomId)!!
room.enableEncryption()
room.roomCryptoService().enableEncryption()
val roomSummaryLive = room.getRoomSummaryLive()
val roomSummaryObserver = object : Observer<Optional<RoomSummary>> {
override fun onChanged(roomSummary: Optional<RoomSummary>) {
@ -109,7 +109,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) {
}
}
bobRoomSummariesLive.observeForever(newRoomObserver)
aliceRoom.invite(bobSession.myUserId)
aliceRoom.membershipService().invite(bobSession.myUserId)
}
testHelper.waitWithLatch { latch ->
@ -117,6 +117,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) {
val roomJoinedObserver = object : Observer<List<RoomSummary>> {
override fun onChanged(t: List<RoomSummary>?) {
if (bobSession.getRoom(aliceRoomId)
?.membershipService()
?.getRoomMember(bobSession.myUserId)
?.membership == Membership.JOIN) {
bobRoomSummariesLive.removeObserver(this)
@ -161,7 +162,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) {
val samSession = testHelper.createAccount(TestConstants.USER_SAM, defaultSessionParams)
testHelper.runBlockingTest {
room.invite(samSession.myUserId, null)
room.membershipService().invite(samSession.myUserId, null)
}
testHelper.runBlockingTest {
@ -261,6 +262,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) {
val newRoomObserver = object : Observer<List<RoomSummary>> {
override fun onChanged(t: List<RoomSummary>?) {
if (bob.getRoom(roomId)
?.membershipService()
?.getRoomMember(bob.myUserId)
?.membership == Membership.JOIN) {
bobRoomSummariesLive.removeObserver(this)
@ -373,13 +375,13 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) {
val room = aliceSession.getRoom(roomId)!!
testHelper.runBlockingTest {
room.enableEncryption()
room.roomCryptoService().enableEncryption()
}
val sessions = mutableListOf(aliceSession)
for (index in 1 until numberOfMembers) {
val session = testHelper.createAccount("User_$index", defaultSessionParams)
testHelper.runBlockingTest(timeout = 600_000) { room.invite(session.myUserId, null) }
testHelper.runBlockingTest(timeout = 600_000) { room.membershipService().invite(session.myUserId, null) }
println("TEST -> " + session.myUserId + " invited")
testHelper.runBlockingTest { session.roomService().joinRoom(room.roomId, null, emptyList()) }
println("TEST -> " + session.myUserId + " joined")

View file

@ -42,6 +42,7 @@ import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.getRoomSummary
import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.api.session.room.failure.JoinRoomFailure
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.send.SendState
@ -88,7 +89,7 @@ class E2eeSanityTests : InstrumentedTest {
otherAccounts.forEach {
testHelper.runBlockingTest {
Log.v("#E2E TEST", "Alice invites ${it.myUserId}")
aliceRoomPOV.invite(it.myUserId)
aliceRoomPOV.membershipService().invite(it.myUserId)
}
}
@ -130,7 +131,7 @@ class E2eeSanityTests : InstrumentedTest {
newAccount.forEach {
testHelper.runBlockingTest {
Log.v("#E2E TEST", "Alice invites ${it.myUserId}")
aliceRoomPOV.invite(it.myUserId)
aliceRoomPOV.membershipService().invite(it.myUserId)
}
}
@ -525,10 +526,10 @@ class E2eeSanityTests : InstrumentedTest {
}
private fun sendMessageInRoom(aliceRoomPOV: Room, text: String): String? {
aliceRoomPOV.sendTextMessage(text)
aliceRoomPOV.sendService().sendTextMessage(text)
var sentEventId: String? = null
testHelper.waitWithLatch(4 * TestConstants.timeOutMillis) { latch ->
val timeline = aliceRoomPOV.createTimeline(null, TimelineSettings(60))
val timeline = aliceRoomPOV.timelineService().createTimeline(null, TimelineSettings(60))
timeline.start()
testHelper.retryPeriodicallyWithLatch(latch) {

View file

@ -30,6 +30,7 @@ import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventCon
import org.matrix.android.sdk.api.session.events.model.content.RoomKeyContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.CryptoTestHelper

View file

@ -98,7 +98,7 @@ class UnwedgingTest : InstrumentedTest {
val roomFromBobPOV = bobSession.getRoom(aliceRoomId)!!
val roomFromAlicePOV = aliceSession.getRoom(aliceRoomId)!!
val bobTimeline = roomFromBobPOV.createTimeline(null, TimelineSettings(20))
val bobTimeline = roomFromBobPOV.timelineService().createTimeline(null, TimelineSettings(20))
bobTimeline.start()
val bobFinalLatch = CountDownLatch(1)
@ -129,7 +129,7 @@ class UnwedgingTest : InstrumentedTest {
messagesReceivedByBob = emptyList()
// - Alice sends a 1st message with a 1st megolm session
roomFromAlicePOV.sendTextMessage("First message")
roomFromAlicePOV.sendService().sendTextMessage("First message")
// Wait for the message to be received by Bob
testHelper.await(latch)
@ -157,7 +157,7 @@ class UnwedgingTest : InstrumentedTest {
Timber.i("## CRYPTO | testUnwedging: Alice sends a 2nd message with a 2nd megolm session")
// - Alice sends a 2nd message with a 2nd megolm session
roomFromAlicePOV.sendTextMessage("Second message")
roomFromAlicePOV.sendService().sendTextMessage("Second message")
// Wait for the message to be received by Bob
testHelper.await(latch)
@ -186,7 +186,7 @@ class UnwedgingTest : InstrumentedTest {
Timber.i("## CRYPTO | testUnwedging: Alice sends a 3rd message with a 3rd megolm session but a wedged olm session")
// - Alice sends a 3rd message with a 3rd megolm session but a wedged olm session
roomFromAlicePOV.sendTextMessage("Third message")
roomFromAlicePOV.sendService().sendTextMessage("Third message")
// Bob should not be able to decrypt, because the session key could not be sent
}
bobTimeline.removeListener(bobEventsListener)

View file

@ -49,7 +49,7 @@ class EncryptionTest : InstrumentedTest {
fun test_EncryptionEvent() {
performTest(roomShouldBeEncrypted = false) { room ->
// Send an encryption Event as an Event (and not as a state event)
room.sendEvent(
room.sendService().sendEvent(
eventType = EventType.STATE_ROOM_ENCRYPTION,
content = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent()
)
@ -61,7 +61,7 @@ class EncryptionTest : InstrumentedTest {
performTest(roomShouldBeEncrypted = true) { room ->
runBlocking {
// Send an encryption Event as a State Event
room.sendStateEvent(
room.stateService().sendStateEvent(
eventType = EventType.STATE_ROOM_ENCRYPTION,
stateKey = "",
body = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent()
@ -76,9 +76,9 @@ class EncryptionTest : InstrumentedTest {
val aliceSession = cryptoTestData.firstSession
val room = aliceSession.getRoom(cryptoTestData.roomId)!!
room.isEncrypted() shouldBe false
room.roomCryptoService().isEncrypted() shouldBe false
val timeline = room.createTimeline(null, TimelineSettings(10))
val timeline = room.timelineService().createTimeline(null, TimelineSettings(10))
val latch = CountDownLatch(1)
val timelineListener = object : Timeline.Listener {
override fun onTimelineFailure(throwable: Throwable) {
@ -106,7 +106,7 @@ class EncryptionTest : InstrumentedTest {
testHelper.await(latch)
timeline.dispose()
testHelper.waitWithLatch {
room.isEncrypted() shouldBe roomShouldBeEncrypted
room.roomCryptoService().isEncrypted() shouldBe roomShouldBeEncrypted
it.countDown()
}
cryptoTestData.cleanUp(testHelper)

View file

@ -51,6 +51,7 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxStat
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
@ -84,7 +85,7 @@ class KeyShareTests : InstrumentedTest {
val room = aliceSession.getRoom(roomId)
assertNotNull(room)
Thread.sleep(4_000)
assertTrue(room?.isEncrypted() == true)
assertTrue(room?.roomCryptoService()?.isEncrypted() == true)
val sentEventId = commonTestHelper.sendTextMessage(room!!, "My Message", 1).first().eventId
// Open a new sessionx
@ -351,7 +352,7 @@ class KeyShareTests : InstrumentedTest {
val roomAlicePov = aliceSession.getRoom(roomId)
assertNotNull(roomAlicePov)
Thread.sleep(1_000)
assertTrue(roomAlicePov?.isEncrypted() == true)
assertTrue(roomAlicePov?.roomCryptoService()?.isEncrypted() == true)
val secondEventId = commonTestHelper.sendTextMessage(roomAlicePov!!, "Message", 3)[1].eventId
// Create bob session
@ -375,7 +376,7 @@ class KeyShareTests : InstrumentedTest {
// Let alice invite bob
commonTestHelper.runBlockingTest {
roomAlicePov.invite(bobSession.myUserId, null)
roomAlicePov.membershipService().invite(bobSession.myUserId, null)
}
commonTestHelper.runBlockingTest {

View file

@ -34,6 +34,7 @@ import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventCon
import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.common.CommonTestHelper
import org.matrix.android.sdk.common.CryptoTestHelper
import org.matrix.android.sdk.common.MockOkHttpInterceptor

View file

@ -81,7 +81,7 @@ class ThreadMessagingTest : InstrumentedTest {
replyInThread.root.getRootThreadEventId().shouldBeEqualTo(initMessage.root.eventId)
// The init normal message should now be a root thread event
val timeline = aliceRoom.createTimeline(null, TimelineSettings(30))
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
timeline.start()
aliceSession.startSync(true)
@ -142,7 +142,7 @@ class ThreadMessagingTest : InstrumentedTest {
replyInThread.root.getRootThreadEventId().shouldBeEqualTo(initMessage.root.eventId)
// The init normal message should now be a root thread event
val timeline = aliceRoom.createTimeline(null, TimelineSettings(30))
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
timeline.start()
aliceSession.startSync(true)
@ -215,7 +215,7 @@ class ThreadMessagingTest : InstrumentedTest {
}
// The init normal message should now be a root thread event
val timeline = aliceRoom.createTimeline(null, TimelineSettings(30))
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
timeline.start()
aliceSession.startSync(true)
@ -310,7 +310,7 @@ class ThreadMessagingTest : InstrumentedTest {
}
// The init normal message should now be a root thread event
val timeline = aliceRoom.createTimeline(null, TimelineSettings(30))
val timeline = aliceRoom.timelineService().createTimeline(null, TimelineSettings(30))
timeline.start()
aliceSession.startSync(true)

View file

@ -58,10 +58,10 @@ class PollAggregationTest : InstrumentedTest {
val roomFromBobPOV = cryptoTestData.secondSession!!.getRoom(cryptoTestData.roomId)!!
// Bob creates a poll
roomFromBobPOV.sendPoll(PollType.DISCLOSED, pollQuestion, pollOptions)
roomFromBobPOV.sendService().sendPoll(PollType.DISCLOSED, pollQuestion, pollOptions)
aliceSession.startSync(true)
val aliceTimeline = roomFromAlicePOV.createTimeline(null, TimelineSettings(30))
val aliceTimeline = roomFromAlicePOV.timelineService().createTimeline(null, TimelineSettings(30))
aliceTimeline.start()
val TOTAL_TEST_COUNT = 7
@ -84,37 +84,37 @@ class PollAggregationTest : InstrumentedTest {
// Poll has just been created.
testInitialPollConditions(pollContent, pollSummary)
lock.countDown()
roomFromBobPOV.voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.firstOrNull()?.id ?: "")
roomFromBobPOV.sendService().voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.firstOrNull()?.id ?: "")
}
TOTAL_TEST_COUNT - 1 -> {
// Bob: Option 1
testBobVotesOption1(pollContent, pollSummary)
lock.countDown()
roomFromBobPOV.voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.get(1)?.id ?: "")
roomFromBobPOV.sendService().voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.get(1)?.id ?: "")
}
TOTAL_TEST_COUNT - 2 -> {
// Bob: Option 2
testBobChangesVoteToOption2(pollContent, pollSummary)
lock.countDown()
roomFromAlicePOV.voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.get(1)?.id ?: "")
roomFromAlicePOV.sendService().voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.get(1)?.id ?: "")
}
TOTAL_TEST_COUNT - 3 -> {
// Alice: Option 2, Bob: Option 2
testAliceAndBobVoteToOption2(pollContent, pollSummary)
lock.countDown()
roomFromAlicePOV.voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.firstOrNull()?.id ?: "")
roomFromAlicePOV.sendService().voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.firstOrNull()?.id ?: "")
}
TOTAL_TEST_COUNT - 4 -> {
// Alice: Option 1, Bob: Option 2
testAliceVotesOption1AndBobVotesOption2(pollContent, pollSummary)
lock.countDown()
roomFromBobPOV.endPoll(pollEventId)
roomFromBobPOV.sendService().endPoll(pollEventId)
}
TOTAL_TEST_COUNT - 5 -> {
// Alice: Option 1, Bob: Option 2 [poll is ended]
testEndedPoll(pollSummary)
lock.countDown()
roomFromAlicePOV.voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.get(1)?.id ?: "")
roomFromAlicePOV.sendService().voteToPoll(pollEventId, pollContent.getBestPollCreationInfo()?.answers?.get(1)?.id ?: "")
}
TOTAL_TEST_COUNT - 6 -> {
// Alice: Option 1 (ignore change), Bob: Option 2 [poll is ended]

View file

@ -75,7 +75,7 @@ class TimelineForwardPaginationTest : InstrumentedTest {
// Alice clear the cache and restart the sync
commonTestHelper.clearCacheAndSync(aliceSession)
val aliceTimeline = roomFromAlicePOV.createTimeline(null, TimelineSettings(30))
val aliceTimeline = roomFromAlicePOV.timelineService().createTimeline(null, TimelineSettings(30))
aliceTimeline.start()
// Alice sees the 10 last message of the room, and can only navigate BACKWARD

View file

@ -63,7 +63,7 @@ class TimelinePreviousLastForwardTest : InstrumentedTest {
val roomFromAlicePOV = aliceSession.getRoom(aliceRoomId)!!
val roomFromBobPOV = bobSession.getRoom(aliceRoomId)!!
val bobTimeline = roomFromBobPOV.createTimeline(null, TimelineSettings(30))
val bobTimeline = roomFromBobPOV.timelineService().createTimeline(null, TimelineSettings(30))
bobTimeline.start()
run {

View file

@ -66,7 +66,7 @@ class TimelineSimpleBackPaginationTest : InstrumentedTest {
message,
numberOfMessagesToSent)
val bobTimeline = roomFromBobPOV.createTimeline(null, TimelineSettings(30))
val bobTimeline = roomFromBobPOV.timelineService().createTimeline(null, TimelineSettings(30))
bobTimeline.start()
commonTestHelper.waitWithLatch(timeout = TestConstants.timeOutMillis * 10) {

View file

@ -72,7 +72,7 @@ class TimelineWithManyMembersTest : InstrumentedTest {
for (index in 1 until cryptoTestData.sessions.size) {
val session = cryptoTestData.sessions[index]
val roomForCurrentMember = session.getRoom(cryptoTestData.roomId)!!
val timelineForCurrentMember = roomForCurrentMember.createTimeline(null, TimelineSettings(30))
val timelineForCurrentMember = roomForCurrentMember.timelineService().createTimeline(null, TimelineSettings(30))
timelineForCurrentMember.start()
session.startSync(true)

View file

@ -29,6 +29,7 @@ import org.junit.runners.MethodSorters
import org.matrix.android.sdk.InstrumentedTest
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.room.getStateEvent
import org.matrix.android.sdk.api.session.room.model.GuestAccess
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent

View file

@ -37,6 +37,7 @@ import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.getRoomSummary
import org.matrix.android.sdk.api.session.room.getStateEvent
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry
import org.matrix.android.sdk.api.session.room.model.RoomSummary
@ -499,7 +500,7 @@ class SpaceHierarchyTest : InstrumentedTest {
))
commonTestHelper.runBlockingTest {
aliceSession.getRoom(spaceAInfo.spaceId)!!.invite(bobSession.myUserId, null)
aliceSession.getRoom(spaceAInfo.spaceId)!!.membershipService().invite(bobSession.myUserId, null)
}
commonTestHelper.runBlockingTest {
@ -509,7 +510,7 @@ class SpaceHierarchyTest : InstrumentedTest {
var bobRoomId = ""
commonTestHelper.waitWithLatch {
bobRoomId = bobSession.roomService().createRoom(CreateRoomParams().apply { name = "A Bob Room" })
bobSession.getRoom(bobRoomId)!!.invite(aliceSession.myUserId)
bobSession.getRoom(bobRoomId)!!.membershipService().invite(aliceSession.myUserId)
it.countDown()
}
@ -554,7 +555,7 @@ class SpaceHierarchyTest : InstrumentedTest {
?.setUserPowerLevel(aliceSession.myUserId, Role.Admin.value)
?.toContent()
room.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", newPowerLevelsContent!!)
room.stateService().sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", newPowerLevelsContent!!)
it.countDown()
}

View file

@ -44,7 +44,7 @@ class RoomMemberCountCondition(
// Parse the is field into prefix and number the first time
val (prefix, count) = parseIsField() ?: return false
val numMembers = room.getNumberOfJoinedMembers()
val numMembers = room.membershipService().getNumberOfJoinedMembers()
return when (prefix) {
"<" -> numMembers < count

View file

@ -44,26 +44,7 @@ import org.matrix.android.sdk.api.util.Optional
/**
* This interface defines methods to interact within a room.
*/
interface Room :
TimelineService,
ThreadsService,
ThreadsLocalService,
SendService,
DraftService,
ReadService,
TypingService,
AliasService,
TagsService,
MembershipService,
StateService,
UploadsService,
ReportingService,
RoomCallService,
RelationService,
RoomCryptoService,
RoomPushRuleService,
RoomAccountDataService,
RoomVersionService {
interface Room {
val coroutineDispatchers: MatrixCoroutineDispatchers
@ -87,4 +68,99 @@ interface Room :
* Use this room as a Space, if the type is correct.
*/
fun asSpace(): Space?
/**
* Get the TimelineService associated to this Room
*/
fun timelineService(): TimelineService
/**
* Get the ThreadsService associated to this Room
*/
fun threadsService(): ThreadsService
/**
* Get the ThreadsLocalService associated to this Room
*/
fun threadsLocalService(): ThreadsLocalService
/**
* Get the SendService associated to this Room
*/
fun sendService(): SendService
/**
* Get the DraftService associated to this Room
*/
fun draftService(): DraftService
/**
* Get the ReadService associated to this Room
*/
fun readService(): ReadService
/**
* Get the TypingService associated to this Room
*/
fun typingService(): TypingService
/**
* Get the AliasService associated to this Room
*/
fun aliasService(): AliasService
/**
* Get the TagsService associated to this Room
*/
fun tagsService(): TagsService
/**
* Get the MembershipService associated to this Room
*/
fun membershipService(): MembershipService
/**
* Get the StateService associated to this Room
*/
fun stateService(): StateService
/**
* Get the UploadsService associated to this Room
*/
fun uploadsService(): UploadsService
/**
* Get the ReportingService associated to this Room
*/
fun reportingService(): ReportingService
/**
* Get the RoomCallService associated to this Room
*/
fun roomCallService(): RoomCallService
/**
* Get the RelationService associated to this Room
*/
fun relationService(): RelationService
/**
* Get the RoomCryptoService associated to this Room
*/
fun roomCryptoService(): RoomCryptoService
/**
* Get the RoomPushRuleService associated to this Room
*/
fun roomPushRuleService(): RoomPushRuleService
/**
* Get the RoomAccountDataService associated to this Room
*/
fun roomAccountDataService(): RoomAccountDataService
/**
* Get the RoomVersionService associated to this Room
*/
fun roomVersionService(): RoomVersionService
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
*
* 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 org.matrix.android.sdk.api.session.room
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.room.timeline.TimelineEvent
/**
* Get a TimelineEvent using the TimelineService of a Room
*/
fun Room.getTimelineEvent(eventId: String): TimelineEvent? =
timelineService().getTimelineEvent(eventId)
/**
* Get a StateEvent using the StateService of a Room
*/
fun Room.getStateEvent(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): Event? =
stateService().getStateEvent(eventType, stateKey)

View file

@ -72,6 +72,7 @@ internal class ViaParameterFinder @Inject constructor(
*/
private fun getUserIdsOfJoinedMembers(roomId: String): Set<String> {
return roomGetterProvider.get().getRoom(roomId)
?.membershipService()
?.getRoomMembers(roomMemberQueryParams { memberships = listOf(Membership.JOIN) })
?.map { it.userId }
.orEmpty()
@ -84,6 +85,7 @@ internal class ViaParameterFinder @Inject constructor(
// It may not be possible for a user to join a room if there's no overlap between these
fun computeViaParamsForRestricted(roomId: String, max: Int): List<String> {
val userThatCanInvite = roomGetterProvider.get().getRoom(roomId)
?.membershipService()
?.getRoomMembers(roomMemberQueryParams { memberships = listOf(Membership.JOIN) })
?.map { it.userId }
?.filter { userCanInvite(userId, roomId) }

View file

@ -23,6 +23,7 @@ import org.matrix.android.sdk.api.session.pushrules.ContainsDisplayNameCondition
import org.matrix.android.sdk.api.session.pushrules.EventMatchCondition
import org.matrix.android.sdk.api.session.pushrules.RoomMemberCountCondition
import org.matrix.android.sdk.api.session.pushrules.SenderNotificationPermissionCondition
import org.matrix.android.sdk.api.session.room.getStateEvent
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.session.room.RoomGetter
@ -60,7 +61,7 @@ internal class DefaultConditionResolver @Inject constructor(
condition: ContainsDisplayNameCondition): Boolean {
val roomId = event.roomId ?: return false
val room = roomGetter.getRoom(roomId) ?: return false
val myDisplayName = room.getRoomMember(userId)?.displayName ?: return false
val myDisplayName = room.membershipService().getRoomMember(userId)?.displayName ?: return false
return condition.isSatisfied(event, myDisplayName)
}
}

View file

@ -18,13 +18,11 @@ package org.matrix.android.sdk.internal.session.room
import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataService
import org.matrix.android.sdk.api.session.room.alias.AliasService
import org.matrix.android.sdk.api.session.room.call.RoomCallService
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
import org.matrix.android.sdk.api.session.room.members.MembershipService
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.RoomType
@ -44,57 +42,35 @@ import org.matrix.android.sdk.api.session.room.uploads.UploadsService
import org.matrix.android.sdk.api.session.room.version.RoomVersionService
import org.matrix.android.sdk.api.session.space.Space
import org.matrix.android.sdk.api.util.Optional
import org.matrix.android.sdk.api.util.awaitCallback
import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder
import org.matrix.android.sdk.internal.session.room.state.SendStateTask
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
import org.matrix.android.sdk.internal.session.space.DefaultSpace
import java.security.InvalidParameterException
internal class DefaultRoom(override val roomId: String,
private val roomSummaryDataSource: RoomSummaryDataSource,
private val timelineService: TimelineService,
private val threadsService: ThreadsService,
private val threadsLocalService: ThreadsLocalService,
private val sendService: SendService,
private val draftService: DraftService,
private val stateService: StateService,
private val uploadsService: UploadsService,
private val reportingService: ReportingService,
private val roomCallService: RoomCallService,
private val readService: ReadService,
private val typingService: TypingService,
private val aliasService: AliasService,
private val tagsService: TagsService,
private val cryptoService: CryptoService,
private val relationService: RelationService,
private val roomMembersService: MembershipService,
private val roomPushRuleService: RoomPushRuleService,
private val roomAccountDataService: RoomAccountDataService,
private val roomVersionService: RoomVersionService,
private val sendStateTask: SendStateTask,
private val viaParameterFinder: ViaParameterFinder,
override val coroutineDispatchers: MatrixCoroutineDispatchers
) :
Room,
TimelineService by timelineService,
ThreadsService by threadsService,
ThreadsLocalService by threadsLocalService,
SendService by sendService,
DraftService by draftService,
StateService by stateService,
UploadsService by uploadsService,
ReportingService by reportingService,
RoomCallService by roomCallService,
ReadService by readService,
TypingService by typingService,
AliasService by aliasService,
TagsService by tagsService,
RelationService by relationService,
MembershipService by roomMembersService,
RoomPushRuleService by roomPushRuleService,
RoomAccountDataService by roomAccountDataService,
RoomVersionService by roomVersionService {
internal class DefaultRoom(
override val roomId: String,
private val roomSummaryDataSource: RoomSummaryDataSource,
private val roomCryptoService: RoomCryptoService,
private val timelineService: TimelineService,
private val threadsService: ThreadsService,
private val threadsLocalService: ThreadsLocalService,
private val sendService: SendService,
private val draftService: DraftService,
private val stateService: StateService,
private val uploadsService: UploadsService,
private val reportingService: ReportingService,
private val roomCallService: RoomCallService,
private val readService: ReadService,
private val typingService: TypingService,
private val aliasService: AliasService,
private val tagsService: TagsService,
private val relationService: RelationService,
private val roomMembersService: MembershipService,
private val roomPushRuleService: RoomPushRuleService,
private val roomAccountDataService: RoomAccountDataService,
private val roomVersionService: RoomVersionService,
private val viaParameterFinder: ViaParameterFinder,
override val coroutineDispatchers: MatrixCoroutineDispatchers
) : Room {
override fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>> {
return roomSummaryDataSource.getRoomSummaryLive(roomId)
@ -104,49 +80,28 @@ internal class DefaultRoom(override val roomId: String,
return roomSummaryDataSource.getRoomSummary(roomId)
}
override fun isEncrypted(): Boolean {
return cryptoService.isRoomEncrypted(roomId)
}
override fun encryptionAlgorithm(): String? {
return cryptoService.getEncryptionAlgorithm(roomId)
}
override fun shouldEncryptForInvitedMembers(): Boolean {
return cryptoService.shouldEncryptForInvitedMembers(roomId)
}
override suspend fun prepareToEncrypt() {
awaitCallback<Unit> {
cryptoService.prepareToEncrypt(roomId, it)
}
}
override suspend fun enableEncryption(algorithm: String, force: Boolean) {
when {
(!force && isEncrypted() && encryptionAlgorithm() == MXCRYPTO_ALGORITHM_MEGOLM) -> {
throw IllegalStateException("Encryption is already enabled for this room")
}
(!force && algorithm != MXCRYPTO_ALGORITHM_MEGOLM) -> {
throw InvalidParameterException("Only MXCRYPTO_ALGORITHM_MEGOLM algorithm is supported")
}
else -> {
val params = SendStateTask.Params(
roomId = roomId,
stateKey = "",
eventType = EventType.STATE_ROOM_ENCRYPTION,
body = mapOf(
"algorithm" to algorithm
)
)
sendStateTask.execute(params)
}
}
}
override fun asSpace(): Space? {
if (roomSummary()?.roomType != RoomType.SPACE) return null
return DefaultSpace(this, roomSummaryDataSource, viaParameterFinder)
}
override fun timelineService() = timelineService
override fun threadsService() = threadsService
override fun threadsLocalService() = threadsLocalService
override fun sendService() = sendService
override fun draftService() = draftService
override fun stateService() = stateService
override fun uploadsService() = uploadsService
override fun reportingService() = reportingService
override fun roomCallService() = roomCallService
override fun readService() = readService
override fun typingService() = typingService
override fun aliasService() = aliasService
override fun tagsService() = tagsService
override fun relationService() = relationService
override fun roomCryptoService() = roomCryptoService
override fun membershipService() = roomMembersService
override fun roomPushRuleService() = roomPushRuleService
override fun roomAccountDataService() = roomAccountDataService
override fun roomVersionService() = roomVersionService
}

View file

@ -28,6 +28,7 @@ import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventCon
import org.matrix.android.sdk.api.session.events.model.getRelationContent
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.PollSummaryContent
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.api.session.room.model.ReferencesAggregatedContent

View file

@ -17,13 +17,13 @@
package org.matrix.android.sdk.internal.session.room
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.internal.session.SessionScope
import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder
import org.matrix.android.sdk.internal.session.room.accountdata.DefaultRoomAccountDataService
import org.matrix.android.sdk.internal.session.room.alias.DefaultAliasService
import org.matrix.android.sdk.internal.session.room.call.DefaultRoomCallService
import org.matrix.android.sdk.internal.session.room.crypto.DefaultRoomCryptoService
import org.matrix.android.sdk.internal.session.room.draft.DefaultDraftService
import org.matrix.android.sdk.internal.session.room.membership.DefaultMembershipService
import org.matrix.android.sdk.internal.session.room.notification.DefaultRoomPushRuleService
@ -32,7 +32,6 @@ import org.matrix.android.sdk.internal.session.room.relation.DefaultRelationServ
import org.matrix.android.sdk.internal.session.room.reporting.DefaultReportingService
import org.matrix.android.sdk.internal.session.room.send.DefaultSendService
import org.matrix.android.sdk.internal.session.room.state.DefaultStateService
import org.matrix.android.sdk.internal.session.room.state.SendStateTask
import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
import org.matrix.android.sdk.internal.session.room.tags.DefaultTagsService
import org.matrix.android.sdk.internal.session.room.threads.DefaultThreadsService
@ -48,35 +47,36 @@ internal interface RoomFactory {
}
@SessionScope
internal class DefaultRoomFactory @Inject constructor(private val cryptoService: CryptoService,
private val roomSummaryDataSource: RoomSummaryDataSource,
private val timelineServiceFactory: DefaultTimelineService.Factory,
private val threadsServiceFactory: DefaultThreadsService.Factory,
private val threadsLocalServiceFactory: DefaultThreadsLocalService.Factory,
private val sendServiceFactory: DefaultSendService.Factory,
private val draftServiceFactory: DefaultDraftService.Factory,
private val stateServiceFactory: DefaultStateService.Factory,
private val uploadsServiceFactory: DefaultUploadsService.Factory,
private val reportingServiceFactory: DefaultReportingService.Factory,
private val roomCallServiceFactory: DefaultRoomCallService.Factory,
private val readServiceFactory: DefaultReadService.Factory,
private val typingServiceFactory: DefaultTypingService.Factory,
private val aliasServiceFactory: DefaultAliasService.Factory,
private val tagsServiceFactory: DefaultTagsService.Factory,
private val relationServiceFactory: DefaultRelationService.Factory,
private val membershipServiceFactory: DefaultMembershipService.Factory,
private val roomPushRuleServiceFactory: DefaultRoomPushRuleService.Factory,
private val roomVersionServiceFactory: DefaultRoomVersionService.Factory,
private val roomAccountDataServiceFactory: DefaultRoomAccountDataService.Factory,
private val sendStateTask: SendStateTask,
private val viaParameterFinder: ViaParameterFinder,
private val coroutineDispatchers: MatrixCoroutineDispatchers) :
RoomFactory {
internal class DefaultRoomFactory @Inject constructor(
private val roomSummaryDataSource: RoomSummaryDataSource,
private val timelineServiceFactory: DefaultTimelineService.Factory,
private val threadsServiceFactory: DefaultThreadsService.Factory,
private val threadsLocalServiceFactory: DefaultThreadsLocalService.Factory,
private val sendServiceFactory: DefaultSendService.Factory,
private val draftServiceFactory: DefaultDraftService.Factory,
private val stateServiceFactory: DefaultStateService.Factory,
private val uploadsServiceFactory: DefaultUploadsService.Factory,
private val reportingServiceFactory: DefaultReportingService.Factory,
private val roomCallServiceFactory: DefaultRoomCallService.Factory,
private val readServiceFactory: DefaultReadService.Factory,
private val typingServiceFactory: DefaultTypingService.Factory,
private val aliasServiceFactory: DefaultAliasService.Factory,
private val tagsServiceFactory: DefaultTagsService.Factory,
private val relationServiceFactory: DefaultRelationService.Factory,
private val roomCryptoServiceFactory: DefaultRoomCryptoService.Factory,
private val membershipServiceFactory: DefaultMembershipService.Factory,
private val roomPushRuleServiceFactory: DefaultRoomPushRuleService.Factory,
private val roomVersionServiceFactory: DefaultRoomVersionService.Factory,
private val roomAccountDataServiceFactory: DefaultRoomAccountDataService.Factory,
private val viaParameterFinder: ViaParameterFinder,
private val coroutineDispatchers: MatrixCoroutineDispatchers
) : RoomFactory {
override fun create(roomId: String): Room {
return DefaultRoom(
roomId = roomId,
roomSummaryDataSource = roomSummaryDataSource,
roomCryptoService = roomCryptoServiceFactory.create(roomId),
timelineService = timelineServiceFactory.create(roomId),
threadsService = threadsServiceFactory.create(roomId),
threadsLocalService = threadsLocalServiceFactory.create(roomId),
@ -90,13 +90,11 @@ internal class DefaultRoomFactory @Inject constructor(private val cryptoService:
typingService = typingServiceFactory.create(roomId),
aliasService = aliasServiceFactory.create(roomId),
tagsService = tagsServiceFactory.create(roomId),
cryptoService = cryptoService,
relationService = relationServiceFactory.create(roomId),
roomMembersService = membershipServiceFactory.create(roomId),
roomPushRuleService = roomPushRuleServiceFactory.create(roomId),
roomAccountDataService = roomAccountDataServiceFactory.create(roomId),
roomVersionService = roomVersionServiceFactory.create(roomId),
sendStateTask = sendStateTask,
viaParameterFinder = viaParameterFinder,
coroutineDispatchers = coroutineDispatchers
)

View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 2022 The Matrix.org Foundation C.I.C.
*
* 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 org.matrix.android.sdk.internal.session.room.crypto
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import org.matrix.android.sdk.api.session.crypto.CryptoService
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
import org.matrix.android.sdk.api.util.awaitCallback
import org.matrix.android.sdk.internal.session.room.state.SendStateTask
import java.security.InvalidParameterException
internal class DefaultRoomCryptoService @AssistedInject constructor(
@Assisted private val roomId: String,
private val cryptoService: CryptoService,
private val sendStateTask: SendStateTask,
) : RoomCryptoService {
@AssistedFactory
interface Factory {
fun create(roomId: String): DefaultRoomCryptoService
}
override fun isEncrypted(): Boolean {
return cryptoService.isRoomEncrypted(roomId)
}
override fun encryptionAlgorithm(): String? {
return cryptoService.getEncryptionAlgorithm(roomId)
}
override fun shouldEncryptForInvitedMembers(): Boolean {
return cryptoService.shouldEncryptForInvitedMembers(roomId)
}
override suspend fun prepareToEncrypt() {
awaitCallback<Unit> {
cryptoService.prepareToEncrypt(roomId, it)
}
}
override suspend fun enableEncryption(algorithm: String, force: Boolean) {
when {
(!force && isEncrypted() && encryptionAlgorithm() == MXCRYPTO_ALGORITHM_MEGOLM) -> {
throw IllegalStateException("Encryption is already enabled for this room")
}
(!force && algorithm != MXCRYPTO_ALGORITHM_MEGOLM) -> {
throw InvalidParameterException("Only MXCRYPTO_ALGORITHM_MEGOLM algorithm is supported")
}
else -> {
val params = SendStateTask.Params(
roomId = roomId,
stateKey = "",
eventType = EventType.STATE_ROOM_ENCRYPTION,
body = mapOf(
"algorithm" to algorithm
)
)
sendStateTask.execute(params)
}
}
}
}

View file

@ -60,7 +60,7 @@ internal class DefaultSpace(
}
?: viaParameterFinder.computeViaParams(roomId, 3))
room.sendStateEvent(
room.stateService().sendStateEvent(
eventType = EventType.STATE_SPACE_CHILD,
stateKey = roomId,
body = SpaceChildContent(
@ -79,7 +79,7 @@ internal class DefaultSpace(
// return
// edit state event and set via to null
room.sendStateEvent(
room.stateService().sendStateEvent(
eventType = EventType.STATE_SPACE_CHILD,
stateKey = roomId,
body = SpaceChildContent(
@ -91,19 +91,19 @@ internal class DefaultSpace(
}
override fun getChildInfo(roomId: String): SpaceChildContent? {
return room.getStateEvents(setOf(EventType.STATE_SPACE_CHILD), QueryStringValue.Equals(roomId))
return room.stateService().getStateEvents(setOf(EventType.STATE_SPACE_CHILD), QueryStringValue.Equals(roomId))
.firstOrNull()
?.content.toModel<SpaceChildContent>()
}
override suspend fun setChildrenOrder(roomId: String, order: String?) {
val existing = room.getStateEvents(setOf(EventType.STATE_SPACE_CHILD), QueryStringValue.Equals(roomId))
val existing = room.stateService().getStateEvents(setOf(EventType.STATE_SPACE_CHILD), QueryStringValue.Equals(roomId))
.firstOrNull()
?.content.toModel<SpaceChildContent>()
?: throw IllegalArgumentException("$roomId is not a child of this space")
// edit state event and set via to null
room.sendStateEvent(
room.stateService().sendStateEvent(
eventType = EventType.STATE_SPACE_CHILD,
stateKey = roomId,
body = SpaceChildContent(
@ -140,7 +140,7 @@ internal class DefaultSpace(
// }
override suspend fun setChildrenSuggested(roomId: String, suggested: Boolean) {
val existing = room.getStateEvents(setOf(EventType.STATE_SPACE_CHILD), QueryStringValue.Equals(roomId))
val existing = room.stateService().getStateEvents(setOf(EventType.STATE_SPACE_CHILD), QueryStringValue.Equals(roomId))
.firstOrNull()
?.content.toModel<SpaceChildContent>()
?: throw IllegalArgumentException("$roomId is not a child of this space")
@ -150,7 +150,7 @@ internal class DefaultSpace(
return
}
// edit state event and set via to null
room.sendStateEvent(
room.stateService().sendStateEvent(
eventType = EventType.STATE_SPACE_CHILD,
stateKey = roomId,
body = SpaceChildContent(

View file

@ -26,6 +26,7 @@ import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.RoomSortOrder
import org.matrix.android.sdk.api.session.room.getStateEvent
import org.matrix.android.sdk.api.session.room.model.GuestAccess
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
@ -258,7 +259,7 @@ internal class DefaultSpaceService @Inject constructor(
val room = roomGetter.getRoom(childRoomId)
?: throw IllegalArgumentException("Unknown Room $childRoomId")
room.sendStateEvent(
room.stateService().sendStateEvent(
eventType = EventType.STATE_SPACE_PARENT,
stateKey = parentSpaceId,
body = SpaceParentContent(
@ -276,7 +277,7 @@ internal class DefaultSpaceService @Inject constructor(
if (existingEvent != null) {
// Should i check if it was sent by me?
// we don't check power level, it will throw if you cannot do that
room.sendStateEvent(
room.stateService().sendStateEvent(
eventType = EventType.STATE_SPACE_PARENT,
stateKey = parentSpaceId,
body = SpaceParentContent(

View file

@ -26,6 +26,7 @@ import org.matrix.android.sdk.MatrixTest
import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.api.session.room.members.MembershipService
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
@ -148,14 +149,22 @@ class PushRulesConditionTest : MatrixTest {
val room2JoinedId = "2joined"
val room3JoinedId = "3joined"
val roomStub2Joined = mockk<Room> {
val roomMembershipService2 = mockk<MembershipService> {
every { getNumberOfJoinedMembers() } returns 2
}
val roomStub3Joined = mockk<Room> {
val roomMembershipService3 = mockk<MembershipService> {
every { getNumberOfJoinedMembers() } returns 3
}
val roomStub2Joined = mockk<Room> {
every { membershipService() } returns roomMembershipService2
}
val roomStub3Joined = mockk<Room> {
every { membershipService() } returns roomMembershipService3
}
val roomGetterStub = mockk<RoomGetter> {
every { getRoom(room2JoinedId) } returns roomStub2Joined
every { getRoom(room3JoinedId) } returns roomStub3Joined

View file

@ -47,6 +47,7 @@ import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.logger.LoggerTag
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import timber.log.Timber
import javax.inject.Inject

View file

@ -102,7 +102,7 @@ class AppStateHandler @Inject constructor(
if (spaceId != null) {
uSession.coroutineScope.launch(Dispatchers.IO) {
tryOrNull {
uSession.getRoom(spaceId)?.loadRoomMembersIfNeeded()
uSession.getRoom(spaceId)?.membershipService()?.loadRoomMembersIfNeeded()
}
}
}

View file

@ -127,7 +127,8 @@ class AutocompleteMemberPresenter @AssistedInject constructor(context: Context,
)
private fun createMemberItems(queryParams: RoomMemberQueryParams) =
room.getRoomMembers(queryParams)
room.membershipService()
.getRoomMembers(queryParams)
.asSequence()
.sortedBy { it.displayName }
.disambiguate()

View file

@ -30,7 +30,7 @@ class CallUserMapper(private val session: Session, private val protocolsChecker:
fun nativeRoomForVirtualRoom(roomId: String): String? {
if (!protocolsChecker.supportVirtualRooms) return null
val virtualRoom = session.getRoom(roomId) ?: return null
val virtualRoomEvent = virtualRoom.getAccountDataEvent(RoomAccountDataTypes.EVENT_TYPE_VIRTUAL_ROOM)
val virtualRoomEvent = virtualRoom.roomAccountDataService().getAccountDataEvent(RoomAccountDataTypes.EVENT_TYPE_VIRTUAL_ROOM)
return virtualRoomEvent?.content?.toModel<RoomVirtualContent>()?.nativeRoomId
}
@ -79,7 +79,7 @@ class CallUserMapper(private val session: Session, private val protocolsChecker:
private suspend fun Room.markVirtual(nativeRoomId: String) {
val virtualRoomContent = RoomVirtualContent(nativeRoomId = nativeRoomId)
updateAccountData(RoomAccountDataTypes.EVENT_TYPE_VIRTUAL_ROOM, virtualRoomContent.toContent())
roomAccountDataService().updateAccountData(RoomAccountDataTypes.EVENT_TYPE_VIRTUAL_ROOM, virtualRoomContent.toContent())
}
private suspend fun ensureVirtualRoomExists(userId: String, nativeRoomId: String): String {

View file

@ -30,7 +30,7 @@ fun WebRtcCall.getOpponentAsMatrixItem(session: Session): MatrixItem? {
roomSummary.toMatrixItem()
} else {
val userId = roomSummary.otherMemberIds.first()
return room.getRoomMember(userId)?.toMatrixItem()
return room.membershipService().getRoomMember(userId)?.toMatrixItem()
}
}
}

View file

@ -174,11 +174,10 @@ class RoomDevToolViewModel @AssistedInject constructor(
val json = adapter.fromJson(state.editedContent ?: "")
?: throw IllegalArgumentException(stringProvider.getString(R.string.dev_tools_error_no_content))
room.sendStateEvent(
room.stateService().sendStateEvent(
state.selectedEvent?.type.orEmpty(),
state.selectedEvent?.stateKey.orEmpty(),
json
)
_viewEvents.post(DevToolsViewEvents.ShowSnackMessage(stringProvider.getString(R.string.dev_tools_success_state_event)))
setState {
@ -212,7 +211,7 @@ class RoomDevToolViewModel @AssistedInject constructor(
?: throw IllegalArgumentException(stringProvider.getString(R.string.dev_tools_error_no_message_type))
if (isState) {
room.sendStateEvent(
room.stateService().sendStateEvent(
eventType,
state.sendEventDraft.stateKey.orEmpty(),
json
@ -222,7 +221,7 @@ class RoomDevToolViewModel @AssistedInject constructor(
// val validParse = MoshiProvider.providesMoshi().adapter(MessageContent::class.java).fromJson(it.sendEventDraft.content ?: "")
json.toModel<MessageContent>(catchError = false)
?: throw IllegalArgumentException(stringProvider.getString(R.string.dev_tools_error_malformed_event))
room.sendEvent(
room.sendService().sendEvent(
eventType,
json
)

View file

@ -89,6 +89,8 @@ import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.file.FileService
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.initsync.SyncStatusService
import org.matrix.android.sdk.api.session.room.getStateEvent
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
import org.matrix.android.sdk.api.session.room.model.Membership
@ -183,7 +185,7 @@ class TimelineViewModel @AssistedInject constructor(
setupPreviewUrlObservers()
room.getRoomSummaryLive()
viewModelScope.launch(Dispatchers.IO) {
tryOrNull { room.markAsRead(ReadService.MarkAsReadParams.READ_RECEIPT) }
tryOrNull { room.readService().markAsRead(ReadService.MarkAsReadParams.READ_RECEIPT) }
}
// Inform the SDK that the room is displayed
viewModelScope.launch(Dispatchers.IO) {
@ -194,7 +196,7 @@ class TimelineViewModel @AssistedInject constructor(
chatEffectManager.delegate = this
// Ensure to share the outbound session keys with all members
if (OutboundSessionKeySharingStrategy.WhenEnteringRoom == BuildConfig.outboundSessionKeySharingStrategy && room.isEncrypted()) {
if (OutboundSessionKeySharingStrategy.WhenEnteringRoom == BuildConfig.outboundSessionKeySharingStrategy && room.roomCryptoService().isEncrypted()) {
prepareForEncryption()
}
@ -250,7 +252,7 @@ class TimelineViewModel @AssistedInject constructor(
prepareToEncrypt = Loading()
viewModelScope.launch {
runCatching {
room.prepareToEncrypt()
room.roomCryptoService().prepareToEncrypt()
}.fold({
prepareToEncrypt = Success(Unit)
}, {
@ -354,7 +356,7 @@ class TimelineViewModel @AssistedInject constructor(
private fun markThreadTimelineAsReadLocal() {
initialState.rootThreadEventId?.let {
session.coroutineScope.launch {
room.markThreadAsRead(it)
room.threadsLocalService().markThreadAsRead(it)
}
}
}
@ -490,7 +492,7 @@ class TimelineViewModel @AssistedInject constructor(
private fun handleSetNewAvatar(action: RoomDetailAction.SetAvatarAction) {
viewModelScope.launch(Dispatchers.IO) {
try {
room.updateAvatar(action.newAvatarUri, action.newAvatarFileName)
room.stateService().updateAvatar(action.newAvatarUri, action.newAvatarFileName)
_viewEvents.post(RoomDetailViewEvents.ActionSuccess(action))
} catch (failure: Throwable) {
_viewEvents.post(RoomDetailViewEvents.ActionFailure(action, failure))
@ -507,7 +509,7 @@ class TimelineViewModel @AssistedInject constructor(
}
private fun handleJumpToReadReceipt(action: RoomDetailAction.JumpToReadReceipt) {
room.getUserReadReceipt(action.userId)
room.readService().getUserReadReceipt(action.userId)
?.let { handleNavigateToEvent(RoomDetailAction.NavigateToEvent(it, true)) }
}
@ -519,7 +521,7 @@ class TimelineViewModel @AssistedInject constructor(
eventId = it))
} ?: action.stickerContent
room.sendEvent(EventType.STICKER, content.toContent())
room.sendService().sendEvent(EventType.STICKER, content.toContent())
}
private fun handleStartCall(action: RoomDetailAction.StartCall) {
@ -639,7 +641,7 @@ class TimelineViewModel @AssistedInject constructor(
if (trackUnreadMessages.getAndSet(false)) {
mostRecentDisplayedEvent?.root?.eventId?.also {
session.coroutineScope.launch {
tryOrNull { room.setReadMarker(it) }
tryOrNull { room.readService().setReadMarker(it) }
}
}
mostRecentDisplayedEvent = null
@ -652,12 +654,12 @@ class TimelineViewModel @AssistedInject constructor(
}
fun getMember(userId: String): RoomMemberSummary? {
return room.getRoomMember(userId)
return room.membershipService().getRoomMember(userId)
}
private fun handleComposerFocusChange(action: RoomDetailAction.ComposerFocusChange) {
// Ensure outbound session keys
if (OutboundSessionKeySharingStrategy.WhenTyping == BuildConfig.outboundSessionKeySharingStrategy && room.isEncrypted()) {
if (OutboundSessionKeySharingStrategy.WhenTyping == BuildConfig.outboundSessionKeySharingStrategy && room.roomCryptoService().isEncrypted()) {
if (action.focused) {
// Should we add some rate limit here, or do it only once per model lifecycle?
prepareForEncryption()
@ -738,36 +740,36 @@ class TimelineViewModel @AssistedInject constructor(
// PRIVATE METHODS *****************************************************************************
private fun handleSendReaction(action: RoomDetailAction.SendReaction) {
room.sendReaction(action.targetEventId, action.reaction)
room.relationService().sendReaction(action.targetEventId, action.reaction)
}
private fun handleRedactEvent(action: RoomDetailAction.RedactAction) {
val event = room.getTimelineEvent(action.targetEventId) ?: return
room.redactEvent(event.root, action.reason)
room.sendService().redactEvent(event.root, action.reason)
}
private fun handleUndoReact(action: RoomDetailAction.UndoReaction) {
viewModelScope.launch {
tryOrNull {
room.undoReaction(action.targetEventId, action.reaction)
room.relationService().undoReaction(action.targetEventId, action.reaction)
}
}
}
private fun handleUpdateQuickReaction(action: RoomDetailAction.UpdateQuickReactAction) {
if (action.add) {
room.sendReaction(action.targetEventId, action.selectedReaction)
room.relationService().sendReaction(action.targetEventId, action.selectedReaction)
} else {
viewModelScope.launch {
tryOrNull {
room.undoReaction(action.targetEventId, action.selectedReaction)
room.relationService().undoReaction(action.targetEventId, action.selectedReaction)
}
}
}
}
private fun handleSendMedia(action: RoomDetailAction.SendMedia) {
room.sendMedias(
room.sendService().sendMedias(
action.attachments,
action.compressBeforeSending,
emptySet(),
@ -902,8 +904,8 @@ class TimelineViewModel @AssistedInject constructor(
return
}
when {
it.root.isTextMessage() -> room.resendTextMessage(it)
it.root.isAttachmentMessage() -> room.resendMediaMessage(it)
it.root.isTextMessage() -> room.sendService().resendTextMessage(it)
it.root.isAttachmentMessage() -> room.sendService().resendMediaMessage(it)
else -> {
// TODO
}
@ -919,13 +921,13 @@ class TimelineViewModel @AssistedInject constructor(
Timber.e("Cannot resend message, it is not failed, Cancel first")
return
}
room.deleteFailedEcho(it)
room.sendService().deleteFailedEcho(it)
}
}
private fun handleCancel(action: RoomDetailAction.CancelSend) {
if (action.force) {
room.cancelSend(action.eventId)
room.sendService().cancelSend(action.eventId)
return
}
val targetEventId = action.eventId
@ -935,16 +937,16 @@ class TimelineViewModel @AssistedInject constructor(
Timber.e("Cannot cancel message, it is not sending")
return
}
room.cancelSend(targetEventId)
room.sendService().cancelSend(targetEventId)
}
}
private fun handleResendAll() {
room.resendAllFailedMessages()
room.sendService().resendAllFailedMessages()
}
private fun handleRemoveAllFailedMessages() {
room.cancelAllFailedMessages()
room.sendService().cancelAllFailedMessages()
}
private fun observeEventDisplayedActions() {
@ -967,7 +969,7 @@ class TimelineViewModel @AssistedInject constructor(
}
bufferedMostRecentDisplayedEvent.root.eventId?.let { eventId ->
session.coroutineScope.launch {
tryOrNull { room.setReadReceipt(eventId) }
tryOrNull { room.readService().setReadReceipt(eventId) }
}
}
}
@ -984,14 +986,14 @@ class TimelineViewModel @AssistedInject constructor(
private fun handleMarkAllAsRead() {
setState { copy(unreadState = UnreadState.HasNoUnread) }
viewModelScope.launch {
tryOrNull { room.markAsRead(ReadService.MarkAsReadParams.BOTH) }
tryOrNull { room.readService().markAsRead(ReadService.MarkAsReadParams.BOTH) }
}
}
private fun handleReportContent(action: RoomDetailAction.ReportContent) {
viewModelScope.launch {
val event = try {
room.reportContent(action.eventId, -100, action.reason)
room.reportingService().reportContent(action.eventId, -100, action.reason)
RoomDetailViewEvents.ActionSuccess(action)
} catch (failure: Exception) {
RoomDetailViewEvents.ActionFailure(action, failure)
@ -1081,13 +1083,13 @@ class TimelineViewModel @AssistedInject constructor(
room.getTimelineEvent(action.eventId)?.let { pollTimelineEvent ->
val currentVote = pollTimelineEvent.annotations?.pollResponseSummary?.aggregatedContent?.myVote
if (currentVote != action.optionKey) {
room.voteToPoll(action.eventId, action.optionKey)
room.sendService().voteToPoll(action.eventId, action.optionKey)
}
}
}
private fun handleEndPoll(eventId: String) {
room.endPoll(eventId)
room.sendService().endPoll(eventId)
}
private fun observeSyncState() {
@ -1265,7 +1267,7 @@ class TimelineViewModel @AssistedInject constructor(
timeline.removeAllListeners()
decryptionFailureTracker.onTimeLineDisposed(room.roomId)
if (vectorPreferences.sendTypingNotifs()) {
room.userStopsTyping()
room.typingService().userStopsTyping()
}
chatEffectManager.delegate = null
chatEffectManager.dispose()

View file

@ -53,6 +53,8 @@ import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.getRoomSummary
import org.matrix.android.sdk.api.session.room.getStateEvent
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.api.session.room.model.RoomAvatarContent
import org.matrix.android.sdk.api.session.room.model.RoomEncryptionAlgorithm
@ -205,12 +207,12 @@ class MessageComposerViewModel @AssistedInject constructor(
is ParsedCommand.ErrorNotACommand -> {
// Send the text message to the room
if (state.rootThreadEventId != null) {
room.replyInThread(
room.relationService().replyInThread(
rootThreadEventId = state.rootThreadEventId,
replyInThreadText = action.text,
autoMarkdown = action.autoMarkdown)
} else {
room.sendTextMessage(action.text, autoMarkdown = action.autoMarkdown)
room.sendService().sendTextMessage(action.text, autoMarkdown = action.autoMarkdown)
}
_viewEvents.post(MessageComposerViewEvents.MessageSent)
@ -231,12 +233,12 @@ class MessageComposerViewModel @AssistedInject constructor(
is ParsedCommand.SendPlainText -> {
// Send the text message to the room, without markdown
if (state.rootThreadEventId != null) {
room.replyInThread(
room.relationService().replyInThread(
rootThreadEventId = state.rootThreadEventId,
replyInThreadText = parsedCommand.message,
autoMarkdown = false)
} else {
room.sendTextMessage(parsedCommand.message, autoMarkdown = false)
room.sendService().sendTextMessage(parsedCommand.message, autoMarkdown = false)
}
_viewEvents.post(MessageComposerViewEvents.MessageSent)
popDraft()
@ -286,13 +288,16 @@ class MessageComposerViewModel @AssistedInject constructor(
}
is ParsedCommand.SendEmote -> {
if (state.rootThreadEventId != null) {
room.replyInThread(
room.relationService().replyInThread(
rootThreadEventId = state.rootThreadEventId,
replyInThreadText = parsedCommand.message,
msgType = MessageType.MSGTYPE_EMOTE,
autoMarkdown = action.autoMarkdown)
} else {
room.sendTextMessage(parsedCommand.message, msgType = MessageType.MSGTYPE_EMOTE, autoMarkdown = action.autoMarkdown)
room.sendService().sendTextMessage(
text = parsedCommand.message,
msgType = MessageType.MSGTYPE_EMOTE,
autoMarkdown = action.autoMarkdown)
}
_viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
popDraft()
@ -300,12 +305,12 @@ class MessageComposerViewModel @AssistedInject constructor(
is ParsedCommand.SendRainbow -> {
val message = parsedCommand.message.toString()
if (state.rootThreadEventId != null) {
room.replyInThread(
room.relationService().replyInThread(
rootThreadEventId = state.rootThreadEventId,
replyInThreadText = parsedCommand.message,
formattedText = rainbowGenerator.generate(message))
} else {
room.sendFormattedTextMessage(message, rainbowGenerator.generate(message))
room.sendService().sendFormattedTextMessage(message, rainbowGenerator.generate(message))
}
_viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
popDraft()
@ -313,13 +318,13 @@ class MessageComposerViewModel @AssistedInject constructor(
is ParsedCommand.SendRainbowEmote -> {
val message = parsedCommand.message.toString()
if (state.rootThreadEventId != null) {
room.replyInThread(
room.relationService().replyInThread(
rootThreadEventId = state.rootThreadEventId,
replyInThreadText = parsedCommand.message,
msgType = MessageType.MSGTYPE_EMOTE,
formattedText = rainbowGenerator.generate(message))
} else {
room.sendFormattedTextMessage(message, rainbowGenerator.generate(message), MessageType.MSGTYPE_EMOTE)
room.sendService().sendFormattedTextMessage(message, rainbowGenerator.generate(message), MessageType.MSGTYPE_EMOTE)
}
_viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
@ -329,12 +334,12 @@ class MessageComposerViewModel @AssistedInject constructor(
val text = "[${stringProvider.getString(R.string.spoiler)}](${parsedCommand.message})"
val formattedText = "<span data-mx-spoiler>${parsedCommand.message}</span>"
if (state.rootThreadEventId != null) {
room.replyInThread(
room.relationService().replyInThread(
rootThreadEventId = state.rootThreadEventId,
replyInThreadText = text,
formattedText = formattedText)
} else {
room.sendFormattedTextMessage(
room.sendService().sendFormattedTextMessage(
text,
formattedText)
}
@ -377,7 +382,7 @@ class MessageComposerViewModel @AssistedInject constructor(
popDraft()
}
is ParsedCommand.DiscardSession -> {
if (room.isEncrypted()) {
if (room.roomCryptoService().isEncrypted()) {
session.cryptoService().discardOutboundSession(room.roomId)
_viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
popDraft()
@ -489,13 +494,13 @@ class MessageComposerViewModel @AssistedInject constructor(
if (inReplyTo != null) {
// TODO check if same content?
room.getTimelineEvent(inReplyTo)?.let {
room.editReply(state.sendMode.timelineEvent, it, action.text.toString())
room.relationService().editReply(state.sendMode.timelineEvent, it, action.text.toString())
}
} else {
val messageContent = state.sendMode.timelineEvent.getLastMessageContent()
val existingBody = messageContent?.body ?: ""
if (existingBody != action.text) {
room.editTextMessage(state.sendMode.timelineEvent,
room.relationService().editTextMessage(state.sendMode.timelineEvent,
messageContent?.msgType ?: MessageType.MSGTYPE_TEXT,
action.text,
action.autoMarkdown)
@ -507,7 +512,7 @@ class MessageComposerViewModel @AssistedInject constructor(
popDraft()
}
is SendMode.Quote -> {
room.sendQuotedTextMessage(
room.sendService().sendQuotedTextMessage(
quotedEvent = state.sendMode.timelineEvent,
text = action.text.toString(),
autoMarkdown = action.autoMarkdown,
@ -521,12 +526,12 @@ class MessageComposerViewModel @AssistedInject constructor(
// If threads are disabled this will make the fallback replies visible to clients with threads enabled
val rootThreadEventId = if (showInThread) timelineEvent.root.getRootThreadEventId() else null
state.rootThreadEventId?.let {
room.replyInThread(
room.relationService().replyInThread(
rootThreadEventId = it,
replyInThreadText = action.text.toString(),
autoMarkdown = action.autoMarkdown,
eventReplied = timelineEvent)
} ?: room.replyToMessage(
} ?: room.relationService().replyToMessage(
eventReplied = timelineEvent,
replyText = action.text.toString(),
autoMarkdown = action.autoMarkdown,
@ -552,13 +557,13 @@ class MessageComposerViewModel @AssistedInject constructor(
// Otherwise we clear the composer and remove the draft from db
setState { copy(sendMode = SendMode.Regular("", false)) }
viewModelScope.launch {
room.deleteDraft()
room.draftService().deleteDraft()
}
}
}
private fun loadDraftIfAny() {
val currentDraft = room.getDraft()
val currentDraft = room.draftService().getDraft()
setState {
copy(
// Create a sendMode from a draft and retrieve the TimelineEvent
@ -589,9 +594,9 @@ class MessageComposerViewModel @AssistedInject constructor(
private fun handleUserIsTyping(action: MessageComposerAction.UserIsTyping) {
if (vectorPreferences.sendTypingNotifs()) {
if (action.isTyping) {
room.userIsTyping()
room.typingService().userIsTyping()
} else {
room.userStopsTyping()
room.typingService().userStopsTyping()
}
}
}
@ -603,9 +608,9 @@ class MessageComposerViewModel @AssistedInject constructor(
ChatEffect.CONFETTI -> R.string.default_message_emote_confetti
ChatEffect.SNOWFALL -> R.string.default_message_emote_snow
})
room.sendTextMessage(defaultMessage, MessageType.MSGTYPE_EMOTE)
room.sendService().sendTextMessage(defaultMessage, MessageType.MSGTYPE_EMOTE)
} else {
room.sendTextMessage(sendChatEffect.message, sendChatEffect.chatEffect.toMessageType())
room.sendService().sendTextMessage(sendChatEffect.message, sendChatEffect.chatEffect.toMessageType())
}
}
@ -648,19 +653,19 @@ class MessageComposerViewModel @AssistedInject constructor(
private fun handleChangeTopicSlashCommand(changeTopic: ParsedCommand.ChangeTopic) {
launchSlashCommandFlowSuspendable(changeTopic) {
room.updateTopic(changeTopic.topic)
room.stateService().updateTopic(changeTopic.topic)
}
}
private fun handleInviteSlashCommand(invite: ParsedCommand.Invite) {
launchSlashCommandFlowSuspendable(invite) {
room.invite(invite.userId, invite.reason)
room.membershipService().invite(invite.userId, invite.reason)
}
}
private fun handleInvite3pidSlashCommand(invite: ParsedCommand.Invite3Pid) {
launchSlashCommandFlowSuspendable(invite) {
room.invite3pid(invite.threePid)
room.membershipService().invite3pid(invite.threePid)
}
}
@ -673,7 +678,7 @@ class MessageComposerViewModel @AssistedInject constructor(
?: return
launchSlashCommandFlowSuspendable(setUserPowerLevel) {
room.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", newPowerLevelsContent)
room.stateService().sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", newPowerLevelsContent)
}
}
@ -701,25 +706,25 @@ class MessageComposerViewModel @AssistedInject constructor(
private fun handleRemoveSlashCommand(removeUser: ParsedCommand.RemoveUser) {
launchSlashCommandFlowSuspendable(removeUser) {
room.remove(removeUser.userId, removeUser.reason)
room.membershipService().remove(removeUser.userId, removeUser.reason)
}
}
private fun handleBanSlashCommand(ban: ParsedCommand.BanUser) {
launchSlashCommandFlowSuspendable(ban) {
room.ban(ban.userId, ban.reason)
room.membershipService().ban(ban.userId, ban.reason)
}
}
private fun handleUnbanSlashCommand(unban: ParsedCommand.UnbanUser) {
launchSlashCommandFlowSuspendable(unban) {
room.unban(unban.userId, unban.reason)
room.membershipService().unban(unban.userId, unban.reason)
}
}
private fun handleChangeRoomNameSlashCommand(changeRoomName: ParsedCommand.ChangeRoomName) {
launchSlashCommandFlowSuspendable(changeRoomName) {
room.updateName(changeRoomName.name)
room.stateService().updateName(changeRoomName.name)
}
}
@ -735,14 +740,14 @@ class MessageComposerViewModel @AssistedInject constructor(
?.copy(displayName = changeDisplayName.displayName)
?.toContent()
?.let {
room.sendStateEvent(EventType.STATE_ROOM_MEMBER, session.myUserId, it)
room.stateService().sendStateEvent(EventType.STATE_ROOM_MEMBER, session.myUserId, it)
}
}
}
private fun handleChangeRoomAvatarSlashCommand(changeAvatar: ParsedCommand.ChangeRoomAvatar) {
launchSlashCommandFlowSuspendable(changeAvatar) {
room.sendStateEvent(EventType.STATE_ROOM_AVATAR, stateKey = "", RoomAvatarContent(changeAvatar.url).toContent())
room.stateService().sendStateEvent(EventType.STATE_ROOM_AVATAR, stateKey = "", RoomAvatarContent(changeAvatar.url).toContent())
}
}
@ -752,7 +757,7 @@ class MessageComposerViewModel @AssistedInject constructor(
?.copy(avatarUrl = changeAvatar.url)
?.toContent()
?.let {
room.sendStateEvent(EventType.STATE_ROOM_MEMBER, session.myUserId, it)
room.stateService().sendStateEvent(EventType.STATE_ROOM_MEMBER, session.myUserId, it)
}
}
}
@ -793,8 +798,8 @@ class MessageComposerViewModel @AssistedInject constructor(
}
}
rootThreadEventId?.let {
room.replyInThread(it, sequence)
} ?: room.sendTextMessage(sequence)
room.relationService().replyInThread(it, sequence)
} ?: room.sendService().sendTextMessage(sequence)
}
/**
@ -805,19 +810,19 @@ class MessageComposerViewModel @AssistedInject constructor(
when {
it.sendMode is SendMode.Regular && !it.sendMode.fromSharing -> {
setState { copy(sendMode = it.sendMode.copy(text = draft)) }
room.saveDraft(UserDraft.Regular(draft))
room.draftService().saveDraft(UserDraft.Regular(draft))
}
it.sendMode is SendMode.Reply -> {
setState { copy(sendMode = it.sendMode.copy(text = draft)) }
room.saveDraft(UserDraft.Reply(it.sendMode.timelineEvent.root.eventId!!, draft))
room.draftService().saveDraft(UserDraft.Reply(it.sendMode.timelineEvent.root.eventId!!, draft))
}
it.sendMode is SendMode.Quote -> {
setState { copy(sendMode = it.sendMode.copy(text = draft)) }
room.saveDraft(UserDraft.Quote(it.sendMode.timelineEvent.root.eventId!!, draft))
room.draftService().saveDraft(UserDraft.Quote(it.sendMode.timelineEvent.root.eventId!!, draft))
}
it.sendMode is SendMode.Edit -> {
setState { copy(sendMode = it.sendMode.copy(text = draft)) }
room.saveDraft(UserDraft.Edit(it.sendMode.timelineEvent.root.eventId!!, draft))
room.draftService().saveDraft(UserDraft.Edit(it.sendMode.timelineEvent.root.eventId!!, draft))
}
}
}
@ -838,7 +843,7 @@ class MessageComposerViewModel @AssistedInject constructor(
} else {
audioMessageHelper.stopRecording(convertForSending = true)?.let { audioType ->
if (audioType.duration > 1000) {
room.sendMedia(
room.sendService().sendMedia(
attachment = audioType.toContentAttachmentData(isVoiceMessage = true),
compressBeforeSending = false,
roomIds = emptySet(),
@ -905,7 +910,7 @@ class MessageComposerViewModel @AssistedInject constructor(
viewModelScope.launch {
playingAudioContent?.toContentAttachmentData()?.let { voiceDraft ->
val content = voiceDraft.toJsonString()
room.saveDraft(UserDraft.Voice(content))
room.draftService().saveDraft(UserDraft.Voice(content))
setState { copy(sendMode = SendMode.Voice(content)) }
}
}

View file

@ -62,7 +62,7 @@ class ViewEditHistoryViewModel @AssistedInject constructor(
viewModelScope.launch {
val data = try {
room.fetchEditHistory(eventId)
room.relationService().fetchEditHistory(eventId)
} catch (failure: Throwable) {
setState {
copy(editList = Fail(failure))

View file

@ -39,6 +39,7 @@ import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.getStateEvent
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper

View file

@ -45,18 +45,18 @@ class TimelineFactory @Inject constructor(private val session: Session, private
val settings = timelineSettingsFactory.create(rootThreadEventId)
if (!session.vectorCallService.protocolChecker.supportVirtualRooms) {
return mainRoom.createTimeline(eventId, settings)
return mainRoom.timelineService().createTimeline(eventId, settings)
}
val virtualRoomId = session.vectorCallService.userMapper.virtualRoomForNativeRoom(mainRoom.roomId)
return if (virtualRoomId == null) {
mainRoom.createTimeline(eventId, settings)
mainRoom.timelineService().createTimeline(eventId, settings)
} else {
val virtualRoom = session.getRoom(virtualRoomId)!!
MergedTimelines(
coroutineScope = coroutineScope,
mainTimeline = mainRoom.createTimeline(eventId, settings),
mainTimeline = mainRoom.timelineService().createTimeline(eventId, settings),
secondaryTimelineParams = MergedTimelines.SecondaryTimelineParams(
timeline = virtualRoom.createTimeline(null, settings),
timeline = virtualRoom.timelineService().createTimeline(null, settings),
shouldFilterTypes = true,
allowedTypes = secondaryTimelineAllowedTypes
)

View file

@ -33,6 +33,7 @@ import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.RelationType
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.message.MessageRelationContent
import org.matrix.android.sdk.api.session.room.model.message.MessageVerificationCancelContent
import javax.inject.Inject

View file

@ -34,6 +34,7 @@ import im.vector.app.features.home.room.detail.timeline.action.TimelineEventFrag
import kotlinx.coroutines.flow.map
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.flow.flow
import org.matrix.android.sdk.flow.unwrap

View file

@ -43,7 +43,7 @@ class MigrateRoomViewModel @AssistedInject constructor(
val summary = session.getRoomSummary(initialState.roomId)
setState {
copy(
currentVersion = room?.getRoomVersion(),
currentVersion = room?.roomVersionService()?.getRoomVersion(),
isPublic = summary?.isPublic ?: false,
otherMemberCount = summary?.otherMemberIds?.count() ?: 0,
knownParents = summary?.flattenParentIds ?: emptyList()

View file

@ -50,12 +50,12 @@ class UpgradeRoomViewModelTask @Inject constructor(
val room = session.getRoom(params.roomId)
?: return Result.UnknownRoom
if (!room.userMayUpgradeRoom(session.myUserId)) {
if (!room.roomVersionService().userMayUpgradeRoom(session.myUserId)) {
return Result.NotAllowed
}
val updatedRoomId = try {
room.upgradeToVersion(params.newVersion)
room.roomVersionService().upgradeToVersion(params.newVersion)
} catch (failure: Throwable) {
return Result.ErrorFailure(failure)
}
@ -65,7 +65,7 @@ class UpgradeRoomViewModelTask @Inject constructor(
params.userIdsToAutoInvite.forEach {
params.progressReporter?.invoke(false, currentStep, totalStep)
tryOrNull {
session.getRoom(updatedRoomId)?.invite(it)
session.getRoom(updatedRoomId)?.membershipService()?.invite(it)
}
currentStep++
}

View file

@ -170,7 +170,7 @@ class RoomListViewModel @AssistedInject constructor(
}
fun isPublicRoom(roomId: String): Boolean {
return session.getRoom(roomId)?.isPublic().orFalse()
return session.getRoom(roomId)?.stateService()?.isPublic().orFalse()
}
// PRIVATE METHODS *****************************************************************************
@ -254,7 +254,7 @@ class RoomListViewModel @AssistedInject constructor(
if (room != null) {
viewModelScope.launch {
try {
room.setRoomNotificationState(action.notificationState)
room.roomPushRuleService().setRoomNotificationState(action.notificationState)
} catch (failure: Exception) {
_viewEvents.post(RoomListViewEvents.Failure(failure))
}
@ -299,13 +299,13 @@ class RoomListViewModel @AssistedInject constructor(
action.tag.otherTag()
?.takeIf { room.roomSummary()?.hasTag(it).orFalse() }
?.let { tagToRemove ->
room.deleteTag(tagToRemove)
room.tagsService().deleteTag(tagToRemove)
}
// Set the tag. We do not handle the order for the moment
room.addTag(action.tag, 0.5)
room.tagsService().addTag(action.tag, 0.5)
} else {
room.deleteTag(action.tag)
room.tagsService().deleteTag(action.tag)
}
} catch (failure: Throwable) {
_viewEvents.post(RoomListViewEvents.Failure(failure))

View file

@ -85,7 +85,7 @@ class ThreadListViewModel @AssistedInject constructor(@Assisted val initialState
private fun observeThreadSummaries() {
room?.flow()
?.liveThreadSummaries()
?.map { room.enhanceThreadWithEditions(it) }
?.map { room.threadsService().enhanceThreadWithEditions(it) }
?.flowOn(room.coroutineDispatchers.io)
?.execute { asyncThreads ->
copy(threadSummaryList = asyncThreads)
@ -99,10 +99,10 @@ class ThreadListViewModel @AssistedInject constructor(@Assisted val initialState
private fun observeThreadsList() {
room?.flow()
?.liveThreadList()
?.map { room.mapEventsWithEdition(it) }
?.map { room.threadsLocalService().mapEventsWithEdition(it) }
?.map {
it.map { threadRootEvent ->
val isParticipating = room.isUserParticipatingInThread(threadRootEvent.eventId)
val isParticipating = room.threadsLocalService().isUserParticipatingInThread(threadRootEvent.eventId)
ThreadTimelineEvent(threadRootEvent, isParticipating)
}
}
@ -115,7 +115,7 @@ class ThreadListViewModel @AssistedInject constructor(@Assisted val initialState
private fun fetchThreadList() {
viewModelScope.launch {
setLoading(true)
room?.fetchThreadSummaries()
room?.threadsService()?.fetchThreadSummaries()
setLoading(false)
}
}

View file

@ -60,8 +60,8 @@ class InviteUsersToRoomViewModel @AssistedInject constructor(
selections.asFlow()
.map { user ->
when (user) {
is PendingSelection.UserPendingSelection -> room.invite(user.user.userId, null)
is PendingSelection.ThreePidPendingSelection -> room.invite3pid(user.threePid)
is PendingSelection.UserPendingSelection -> room.membershipService().invite(user.user.userId, null)
is PendingSelection.ThreePidPendingSelection -> room.membershipService().invite3pid(user.threePid)
}
}
.catch { cause ->

View file

@ -105,6 +105,7 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
val stateKey = session.myUserId
session
.getRoom(roomArgs.roomId)
?.stateService()
?.sendStateEvent(
eventType = EventType.STATE_ROOM_BEACON_INFO.first(),
stateKey = stateKey,
@ -147,7 +148,7 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
.getSafeActiveSession()
?.let { session ->
session.coroutineScope.launch(session.coroutineDispatchers.io) {
session.getRoom(roomId)?.stopLiveLocation(session.myUserId)
session.getRoom(roomId)?.stateService()?.stopLiveLocation(session.myUserId)
}
}
}
@ -174,10 +175,11 @@ class LocationSharingService : VectorService(), LocationTracker.Callback {
}
room
.stateService()
.getLiveLocationBeaconInfo(userId, true)
?.eventId
?.let {
room.sendLiveLocation(
room.sendService().sendLiveLocation(
beaconInfoEventId = it,
latitude = locationData.latitude,
longitude = locationData.longitude,

View file

@ -136,7 +136,7 @@ class LocationSharingViewModel @AssistedInject constructor(
private fun shareLocation(locationData: LocationData?, isUserLocation: Boolean) {
locationData?.let { location ->
room.sendLocation(
room.sendService().sendLocation(
latitude = location.latitude,
longitude = location.longitude,
uncertainty = location.uncertainty,

View file

@ -23,6 +23,7 @@ import kotlinx.coroutines.CoroutineScope
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.file.FileService
import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.util.MimeTypes
import java.io.File

View file

@ -135,7 +135,7 @@ class VectorAttachmentViewerActivity : AttachmentViewerActivity(), AttachmentInt
initialIndex = inMemoryData.indexOfFirst { it.eventId == args.eventId }.coerceAtLeast(0)
dataSourceFactory.createProvider(inMemoryData, room, lifecycleScope)
} else {
val events = room?.getAttachmentMessages().orEmpty()
val events = room?.timelineService()?.getAttachmentMessages().orEmpty()
initialIndex = events.indexOfFirst { it.eventId == args.eventId }.coerceAtLeast(0)
dataSourceFactory.createProvider(events, lifecycleScope)
}

View file

@ -37,6 +37,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.getRoomSummary
import org.matrix.android.sdk.api.session.getUser
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent

View file

@ -106,7 +106,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
val room = session.getRoom(roomId)
if (room != null) {
session.coroutineScope.launch {
tryOrNull { room.markAsRead(ReadService.MarkAsReadParams.READ_RECEIPT) }
tryOrNull { room.readService().markAsRead(ReadService.MarkAsReadParams.READ_RECEIPT) }
}
}
}
@ -129,7 +129,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
}
private fun sendMatrixEvent(message: String, session: Session, room: Room, context: Context?) {
room.sendTextMessage(message)
room.sendService().sendTextMessage(message)
// Create a new event to be displayed in the notification drawer, right now

View file

@ -35,7 +35,7 @@ class OutdatedEventDetector @Inject constructor(
val eventID = notifiableEvent.eventId
val roomID = notifiableEvent.roomId
val room = session.getRoom(roomID) ?: return false
return room.isEventRead(eventID)
return room.readService().isEventRead(eventID)
}
return false
}

View file

@ -38,6 +38,7 @@ import org.matrix.android.sdk.api.session.getRoomSummary
import org.matrix.android.sdk.api.session.permalinks.PermalinkData
import org.matrix.android.sdk.api.session.permalinks.PermalinkParser
import org.matrix.android.sdk.api.session.permalinks.PermalinkService
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.RoomType

View file

@ -26,6 +26,7 @@ import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.poll.PollMode
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
import org.matrix.android.sdk.api.session.room.model.message.PollType
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
@ -109,7 +110,7 @@ class CreatePollViewModel @AssistedInject constructor(
}
else -> {
when (state.mode) {
PollMode.CREATE -> room.sendPoll(state.pollType, state.question, nonEmptyOptions)
PollMode.CREATE -> room.sendService().sendPoll(state.pollType, state.question, nonEmptyOptions)
PollMode.EDIT -> sendEditedPoll(state.editedEventId!!, state.pollType, state.question, nonEmptyOptions)
}
_viewEvents.post(CreatePollViewEvents.Success)
@ -119,7 +120,7 @@ class CreatePollViewModel @AssistedInject constructor(
private fun sendEditedPoll(editedEventId: String, pollType: PollType, question: String, options: List<String>) {
val editedEvent = room.getTimelineEvent(editedEventId) ?: return
room.editPoll(editedEvent, pollType, question, options)
room.relationService().editPoll(editedEvent, pollType, question, options)
}
private fun handleOnAddOption() {

View file

@ -38,6 +38,7 @@ import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.getRoom
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.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.util.Optional
@ -93,7 +94,7 @@ class RequireActiveMembershipViewModel @AssistedInject constructor(
}
val senderId = room.getStateEvent(EventType.STATE_ROOM_MEMBER, QueryStringValue.Equals(session.myUserId))?.senderId
val senderDisplayName = senderId?.takeIf { it != session.myUserId }?.let {
room.getRoomMember(it)?.displayName ?: it
room.membershipService().getRoomMember(it)?.displayName ?: it
}
val viewEvent = when (roomSummary.membership) {
Membership.LEAVE -> {

View file

@ -87,8 +87,8 @@ class RoomMemberProfileViewModel @AssistedInject constructor(
setState {
copy(
isMine = session.myUserId == this.userId,
userMatrixItem = room?.getRoomMember(initialState.userId)?.toMatrixItem()?.let { Success(it) } ?: Uninitialized,
hasReadReceipt = room?.getUserReadReceipt(initialState.userId) != null,
userMatrixItem = room?.membershipService()?.getRoomMember(initialState.userId)?.toMatrixItem()?.let { Success(it) } ?: Uninitialized,
hasReadReceipt = room?.readService()?.getUserReadReceipt(initialState.userId) != null,
isSpace = room?.roomSummary()?.roomType == RoomType.SPACE
)
}
@ -97,7 +97,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(
viewModelScope.launch(Dispatchers.Main) {
// Do we have a room member for this id.
val roomMember = withContext(Dispatchers.Default) {
room?.getRoomMember(initialState.userId)
room?.membershipService()?.getRoomMember(initialState.userId)
}
// If not, we look for profile info on the server
if (room == null || roomMember == null) {
@ -228,7 +228,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(
viewModelScope.launch {
_viewEvents.post(RoomMemberProfileViewEvents.Loading())
try {
room.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", newPowerLevelsContent)
room.stateService().sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", newPowerLevelsContent)
_viewEvents.post(RoomMemberProfileViewEvents.OnSetPowerLevelSuccess)
} catch (failure: Throwable) {
_viewEvents.post(RoomMemberProfileViewEvents.Failure(failure))
@ -257,7 +257,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(
viewModelScope.launch {
try {
_viewEvents.post(RoomMemberProfileViewEvents.Loading())
room.invite(initialState.userId)
room.membershipService().invite(initialState.userId)
_viewEvents.post(RoomMemberProfileViewEvents.OnInviteActionSuccess)
} catch (failure: Throwable) {
_viewEvents.post(RoomMemberProfileViewEvents.Failure(failure))
@ -272,7 +272,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(
viewModelScope.launch {
try {
_viewEvents.post(RoomMemberProfileViewEvents.Loading())
room.remove(initialState.userId, action.reason)
room.membershipService().remove(initialState.userId, action.reason)
_viewEvents.post(RoomMemberProfileViewEvents.OnKickActionSuccess)
} catch (failure: Throwable) {
_viewEvents.post(RoomMemberProfileViewEvents.Failure(failure))
@ -289,9 +289,9 @@ class RoomMemberProfileViewModel @AssistedInject constructor(
try {
_viewEvents.post(RoomMemberProfileViewEvents.Loading())
if (membership == Membership.BAN) {
room.unban(initialState.userId, action.reason)
room.membershipService().unban(initialState.userId, action.reason)
} else {
room.ban(initialState.userId, action.reason)
room.membershipService().ban(initialState.userId, action.reason)
}
_viewEvents.post(RoomMemberProfileViewEvents.OnBanActionSuccess)
} catch (failure: Throwable) {

View file

@ -40,6 +40,7 @@ import org.matrix.android.sdk.api.session.Session
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.getRoom
import org.matrix.android.sdk.api.session.room.getStateEvent
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
@ -97,9 +98,9 @@ class RoomProfileViewModel @AssistedInject constructor(
copy(
roomCreateContent = async,
// This is a shortcut, we should do the next lines elsewhere, but keep it like that for the moment.
recommendedRoomVersion = room.getRecommendedVersion(),
isUsingUnstableRoomVersion = room.isUsingUnstableRoomVersion(),
canUpgradeRoom = room.userMayUpgradeRoom(session.myUserId),
recommendedRoomVersion = room.roomVersionService().getRecommendedVersion(),
isUsingUnstableRoomVersion = room.roomVersionService().isUsingUnstableRoomVersion(),
canUpgradeRoom = room.roomVersionService().userMayUpgradeRoom(session.myUserId),
isTombstoned = room.getStateEvent(EventType.STATE_ROOM_TOMBSTONE) != null
)
}
@ -144,14 +145,14 @@ class RoomProfileViewModel @AssistedInject constructor(
}
fun isPublicRoom(): Boolean {
return room.isPublic()
return room.stateService().isPublic()
}
private fun handleEnableEncryption() {
postLoading(true)
viewModelScope.launch {
val result = runCatching { room.enableEncryption() }
val result = runCatching { room.roomCryptoService().enableEncryption() }
postLoading(false)
result.onFailure { failure ->
_viewEvents.post(RoomProfileViewEvents.Failure(failure))
@ -178,7 +179,7 @@ class RoomProfileViewModel @AssistedInject constructor(
private fun handleChangeNotificationMode(action: RoomProfileAction.ChangeRoomNotificationState) {
viewModelScope.launch {
try {
room.setRoomNotificationState(action.notificationState)
room.roomPushRuleService().setRoomNotificationState(action.notificationState)
} catch (failure: Throwable) {
_viewEvents.post(RoomProfileViewEvents.Failure(failure))
}
@ -213,7 +214,7 @@ class RoomProfileViewModel @AssistedInject constructor(
_viewEvents.post(RoomProfileViewEvents.Loading())
session.coroutineScope.launch {
try {
room.enableEncryption(force = true)
room.roomCryptoService().enableEncryption(force = true)
} catch (failure: Throwable) {
Timber.e(failure, "Failed to restore encryption state in room ${room.roomId}")
_viewEvents.post(RoomProfileViewEvents.Failure(failure))

View file

@ -109,7 +109,7 @@ class RoomAliasViewModel @AssistedInject constructor(@Assisted initialState: Roo
}
viewModelScope.launch {
runCatching { room.getRoomAliases() }
runCatching { room.aliasService().getRoomAliases() }
.fold(
{
setState { copy(localAliases = Success(it.sorted())) }
@ -304,7 +304,7 @@ class RoomAliasViewModel @AssistedInject constructor(@Assisted initialState: Roo
postLoading(true)
viewModelScope.launch {
try {
room.updateCanonicalAlias(canonicalAlias, alternativeAliases)
room.stateService().updateCanonicalAlias(canonicalAlias, alternativeAliases)
setState {
copy(
isLoading = false,
@ -328,7 +328,7 @@ class RoomAliasViewModel @AssistedInject constructor(@Assisted initialState: Roo
)
}
viewModelScope.launch {
runCatching { room.addAlias(previousState.value) }
runCatching { room.aliasService().addAlias(previousState.value) }
.onFailure {
setState {
copy(

View file

@ -33,6 +33,7 @@ import org.matrix.android.sdk.api.session.Session
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.getRoom
import org.matrix.android.sdk.api.session.room.getStateEvent
import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
@ -115,7 +116,7 @@ class RoomBannedMemberListViewModel @AssistedInject constructor(@Assisted initia
}
viewModelScope.launch(Dispatchers.IO) {
try {
room.unban(roomMemberSummary.userId, null)
room.membershipService().unban(roomMemberSummary.userId, null)
} catch (failure: Throwable) {
_viewEvents.post(RoomBannedMemberListViewEvents.ToastError(stringProvider.getString(R.string.failed_to_unban)))
} finally {

View file

@ -92,7 +92,7 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState
copy(roomMemberSummaries = async)
}
if (room.isEncrypted()) {
if (room.roomCryptoService().isEncrypted()) {
room.flow().liveRoomMembers(roomMemberQueryParams)
.flatMapLatest { membersSummary ->
session.cryptoService().getLiveCryptoDeviceInfo(membersSummary.map { it.userId })
@ -197,7 +197,7 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState
private fun handleRevokeThreePidInvite(action: RoomMemberListAction.RevokeThreePidInvite) {
viewModelScope.launch {
room.sendStateEvent(
room.stateService().sendStateEvent(
eventType = EventType.STATE_ROOM_THIRD_PARTY_INVITE,
stateKey = action.stateKey,
body = emptyMap()

View file

@ -74,7 +74,7 @@ class RoomNotificationSettingsViewModel @AssistedInject constructor(
private fun handleSelectNotificationState(action: RoomNotificationSettingsAction.SelectNotificationState) {
setState { copy(isLoading = true) }
viewModelScope.launch {
runCatching { room.setRoomNotificationState(action.notificationState) }
runCatching { room.roomPushRuleService().setRoomNotificationState(action.notificationState) }
.fold(
{
setState {

View file

@ -124,7 +124,7 @@ class RoomPermissionsViewModel @AssistedInject constructor(@Assisted initialStat
}
)
}
room.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", newPowerLevelsContent.toContent())
room.stateService().sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", newPowerLevelsContent.toContent())
setState {
copy(
isLoading = false

View file

@ -70,7 +70,7 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
val homeServerCapabilities = session.homeServerCapabilitiesService().getHomeServerCapabilities()
val canUseRestricted = homeServerCapabilities
.isFeatureSupported(HomeServerCapabilities.ROOM_CAP_RESTRICTED, room.getRoomVersion())
.isFeatureSupported(HomeServerCapabilities.ROOM_CAP_RESTRICTED, room.roomVersionService().getRoomVersion())
val restrictedSupport = homeServerCapabilities.isFeatureSupported(HomeServerCapabilities.ROOM_CAP_RESTRICTED)
val couldUpgradeToRestricted = restrictedSupport == HomeServerCapabilities.RoomCapabilitySupport.SUPPORTED
@ -249,25 +249,25 @@ class RoomSettingsViewModel @AssistedInject constructor(@Assisted initialState:
when (val avatarAction = state.avatarAction) {
RoomSettingsViewState.AvatarAction.None -> Unit
RoomSettingsViewState.AvatarAction.DeleteAvatar -> {
operationList.add { room.deleteAvatar() }
operationList.add { room.stateService().deleteAvatar() }
}
is RoomSettingsViewState.AvatarAction.UpdateAvatar -> {
operationList.add { room.updateAvatar(avatarAction.newAvatarUri, avatarAction.newAvatarFileName) }
operationList.add { room.stateService().updateAvatar(avatarAction.newAvatarUri, avatarAction.newAvatarFileName) }
}
}
if (summary?.name != state.newName) {
operationList.add { room.updateName(state.newName ?: "") }
operationList.add { room.stateService().updateName(state.newName ?: "") }
}
if (summary?.topic != state.newTopic) {
operationList.add { room.updateTopic(state.newTopic ?: "") }
operationList.add { room.stateService().updateTopic(state.newTopic ?: "") }
}
if (state.newHistoryVisibility != null) {
operationList.add { room.updateHistoryReadability(state.newHistoryVisibility) }
operationList.add { room.stateService().updateHistoryReadability(state.newHistoryVisibility) }
}
if (state.newRoomJoinRules.hasChanged()) {
operationList.add { room.updateJoinRule(state.newRoomJoinRules.newJoinRules, state.newRoomJoinRules.newGuestAccess) }
operationList.add { room.stateService().updateJoinRule(state.newRoomJoinRules.newJoinRules, state.newRoomJoinRules.newGuestAccess) }
}
viewModelScope.launch {
updateLoadingState(isLoading = true)

View file

@ -43,6 +43,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.getRoomSummary
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
import org.matrix.android.sdk.api.session.room.getStateEvent
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
@ -103,7 +104,7 @@ class RoomJoinRuleChooseRestrictedViewModel @AssistedInject constructor(
var safeRule: RoomJoinRules = joinRulesContent?.joinRules ?: RoomJoinRules.INVITE
// server is not really checking that, just to be sure let's check
val restrictedSupportedByThisVersion = homeServerCapabilities
.isFeatureSupported(HomeServerCapabilities.ROOM_CAP_RESTRICTED, room.getRoomVersion())
.isFeatureSupported(HomeServerCapabilities.ROOM_CAP_RESTRICTED, room.roomVersionService().getRoomVersion())
if (safeRule == RoomJoinRules.RESTRICTED &&
!restrictedSupportedByThisVersion) {
safeRule = RoomJoinRules.INVITE
@ -191,9 +192,9 @@ class RoomJoinRuleChooseRestrictedViewModel @AssistedInject constructor(
viewModelScope.launch {
try {
when (state.currentRoomJoinRules) {
RoomJoinRules.PUBLIC -> room.setJoinRulePublic()
RoomJoinRules.INVITE -> room.setJoinRuleInviteOnly()
RoomJoinRules.RESTRICTED -> room.setJoinRuleRestricted(state.updatedAllowList.map { it.id })
RoomJoinRules.PUBLIC -> room.stateService().setJoinRulePublic()
RoomJoinRules.INVITE -> room.stateService().setJoinRuleInviteOnly()
RoomJoinRules.RESTRICTED -> room.stateService().setJoinRuleRestricted(state.updatedAllowList.map { it.id })
RoomJoinRules.KNOCK,
RoomJoinRules.PRIVATE,
null -> {
@ -294,7 +295,7 @@ class RoomJoinRuleChooseRestrictedViewModel @AssistedInject constructor(
setState { copy(updatingStatus = Loading()) }
viewModelScope.launch {
try {
room.setJoinRuleRestricted(candidates.map { it.id })
room.stateService().setJoinRuleRestricted(candidates.map { it.id })
setState { copy(updatingStatus = Success(Unit)) }
} catch (failure: Throwable) {
setState { copy(updatingStatus = Fail(failure)) }

View file

@ -73,7 +73,7 @@ class RoomUploadsViewModel @AssistedInject constructor(
viewModelScope.launch {
try {
val result = room.getUploads(20, token)
val result = room.uploadsService().getUploads(20, token)
token = result.nextToken

View file

@ -119,7 +119,7 @@ class IncomingShareViewModel @AssistedInject constructor(
is SharedData.Text -> {
state.selectedRoomIds.forEach { roomId ->
val room = session.getRoom(roomId)
room?.sendTextMessage(sharedData.text)
room?.sendService()?.sendTextMessage(sharedData.text)
}
// This is it, pass the first roomId to let the screen open it
_viewEvents.post(IncomingShareViewEvents.MultipleRoomsShareDone(state.selectedRoomIds.first()))
@ -153,6 +153,7 @@ class IncomingShareViewModel @AssistedInject constructor(
// Pick the first room to send the media
selectedRoomIds.firstOrNull()
?.let { roomId -> session.getRoom(roomId) }
?.sendService()
?.sendMedias(grouped.notPreviewables, compressMediaBeforeSending, selectedRoomIds)
// Ensure they will not be sent twice
@ -173,6 +174,7 @@ class IncomingShareViewModel @AssistedInject constructor(
// Pick the first room to send the media
selectedRoomIds.firstOrNull()
?.let { roomId -> session.getRoom(roomId) }
?.sendService()
?.sendMedias(attachmentData, compressMediaBeforeSending, selectedRoomIds)
// This is it, pass the first roomId to let the screen open it
_viewEvents.post(IncomingShareViewEvents.MultipleRoomsShareDone(selectedRoomIds.first()))

View file

@ -212,7 +212,7 @@ class SpaceListViewModel @AssistedInject constructor(@Assisted initialState: Spa
}
session.coroutineScope.launch {
orderCommands.forEach {
session.getRoom(it.spaceId)?.updateAccountData(
session.getRoom(it.spaceId)?.roomAccountDataService()?.updateAccountData(
RoomAccountDataTypes.EVENT_TYPE_SPACE_ORDER,
SpaceOrderContent(order = it.order).toContent()
)
@ -292,6 +292,7 @@ class SpaceListViewModel @AssistedInject constructor(@Assisted initialState: Spa
val rootSpaces = async.invoke().orEmpty().filter { it.flattenParentIds.isEmpty() }
val orders = rootSpaces.associate {
it.roomId to session.getRoom(it.roomId)
?.roomAccountDataService()
?.getAccountDataEvent(RoomAccountDataTypes.EVENT_TYPE_SPACE_ORDER)
?.content.toModel<SpaceOrderContent>()
?.safeOrder()

View file

@ -34,6 +34,7 @@ import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.room.getStateEvent
import org.matrix.android.sdk.api.session.room.model.Membership
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
@ -117,7 +118,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo
}
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))
val stateEvents = room.stateService().getStateEvents(setOf(EventType.BOT_OPTIONS))
var botOptionsEvent: Event? = null
val stateKey = "_$userId"
for (stateEvent in stateEvents) {
@ -196,7 +197,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo
return
}
Timber.d("Received request join rules in room $roomId")
val joinedEvents = room.getStateEvents(setOf(EventType.STATE_ROOM_JOIN_RULES))
val joinedEvents = room.stateService().getStateEvents(setOf(EventType.STATE_ROOM_JOIN_RULES))
if (joinedEvents.isNotEmpty()) {
widgetPostAPIMediator.sendObjectResponse(Event::class.java, joinedEvents.last(), eventData)
} else {
@ -316,7 +317,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo
val params = HashMap<String, Any>()
params["status"] = status
launchWidgetAPIAction(widgetPostAPIMediator, eventData) {
room.sendStateEvent(
room.stateService().sendStateEvent(
eventType = EventType.PLUMBING,
stateKey = "",
body = params
@ -341,7 +342,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo
val stateKey = "_$userId"
launchWidgetAPIAction(widgetPostAPIMediator, eventData) {
room.sendStateEvent(
room.stateService().sendStateEvent(
eventType = EventType.BOT_OPTIONS,
stateKey = stateKey,
body = content
@ -383,12 +384,12 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo
val userId = eventData["user_id"] as String
val description = "Received request to invite $userId into room $roomId"
Timber.d(description)
val member = room.getRoomMember(userId)
val member = room.membershipService().getRoomMember(userId)
if (member != null && member.membership == Membership.JOIN) {
widgetPostAPIMediator.sendSuccess(eventData)
} else {
launchWidgetAPIAction(widgetPostAPIMediator, eventData) {
room.invite(userId = userId)
room.membershipService().invite(userId = userId)
}
}
}
@ -402,7 +403,7 @@ class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roo
if (checkRoomId(widgetPostAPIMediator, eventData)) {
return
}
val numberOfJoinedMembers = room.getNumberOfJoinedMembers()
val numberOfJoinedMembers = room.membershipService().getNumberOfJoinedMembers()
widgetPostAPIMediator.sendIntegerResponse(numberOfJoinedMembers, eventData)
}