Merge branch 'feature/invites' into develop

This commit is contained in:
ganfra
2019-05-17 17:38:09 +02:00
56 changed files with 665 additions and 219 deletions

View File

@ -22,7 +22,6 @@ import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toContent
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.MyMembership
import im.vector.matrix.android.api.session.room.model.RoomMember
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
import im.vector.matrix.android.api.session.room.model.message.MessageType
@ -78,7 +77,7 @@ object RoomDataHelper {
fun fakeInitialSync(monarchy: Monarchy, roomId: String) {
monarchy.runTransactionSync { realm ->
val roomEntity = realm.createObject<RoomEntity>(roomId)
roomEntity.membership = MyMembership.JOINED
roomEntity.membership = Membership.JOIN
val eventList = createFakeListOfEvents(10)
val chunkEntity = realm.createObject<ChunkEntity>().apply {
nextToken = null

View File

@ -21,7 +21,7 @@ import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.api.session.room.timeline.Timeline
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.matrix.android.internal.session.room.EventRelationExtractor
import im.vector.matrix.android.internal.session.room.members.SenderRoomMemberExtractor
import im.vector.matrix.android.internal.session.room.membership.SenderRoomMemberExtractor
import im.vector.matrix.android.internal.session.room.timeline.DefaultTimeline
import im.vector.matrix.android.internal.session.room.timeline.TimelineEventFactory
import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEventPersistor

View File

@ -17,7 +17,7 @@
package im.vector.matrix.android.api.session.room
import androidx.lifecycle.LiveData
import im.vector.matrix.android.api.session.room.members.RoomMembersService
import im.vector.matrix.android.api.session.room.members.MembershipService
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.read.ReadService
import im.vector.matrix.android.api.session.room.send.SendService
@ -27,7 +27,7 @@ import im.vector.matrix.android.api.session.room.timeline.TimelineService
/**
* This interface defines methods to interact within a room.
*/
interface Room : TimelineService, SendService, ReadService, RoomMembersService, StateService {
interface Room : TimelineService, SendService, ReadService, MembershipService, StateService {
/**
* The roomId of this room

View File

@ -24,9 +24,9 @@ import im.vector.matrix.android.api.session.room.model.RoomMember
import im.vector.matrix.android.api.util.Cancelable
/**
* This interface defines methods to retrieve room members of a room. It's implemented at the room level.
* This interface defines methods to handling membership. It's implemented at the room level.
*/
interface RoomMembersService {
interface MembershipService {
/**
* This methods load all room members if it was done yet.
@ -54,4 +54,15 @@ interface RoomMembersService {
*/
fun invite(userId: String, callback: MatrixCallback<Unit>)
/**
* Join the room
*/
fun join(callback: MatrixCallback<Unit>)
/**
* Leave the room.
*
*/
fun leave(callback: MatrixCallback<Unit>)
}

View File

@ -19,10 +19,12 @@ package im.vector.matrix.android.api.session.room.model
import com.squareup.moshi.Json
/**
* Represents the membership of a user on a room. Linked to a [RoomMember]
* Represents the membership of a user on a room
*/
enum class Membership(val value: String) {
NONE("none"),
@Json(name = "invite")
INVITE("invite"),
@ -38,4 +40,8 @@ enum class Membership(val value: String) {
@Json(name = "ban")
BAN("ban");
fun isLeft(): Boolean {
return this == KNOCK || this == LEAVE || this == BAN
}
}

View File

@ -1,27 +0,0 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.room.model
/**
* Represents the membership of the current auth user on a room.
*/
enum class MyMembership {
JOINED,
LEFT,
INVITED,
NONE
}

View File

@ -31,7 +31,8 @@ data class RoomSummary(
val isDirect: Boolean = false,
val lastMessage: Event? = null,
val otherMemberIds: List<String> = emptyList(),
var notificationCount: Int = 0,
var highlightCount: Int = 0,
var tags: List<RoomTag> = emptyList()
val notificationCount: Int = 0,
val highlightCount: Int = 0,
val tags: List<RoomTag> = emptyList(),
val membership: Membership = Membership.NONE
)

View File

@ -86,10 +86,9 @@ internal fun ChunkEntity.add(roomId: String,
isUnlinked: Boolean = false) {
assertIsManaged()
if (event.eventId.isNullOrEmpty() || this.events.fastContains(event.eventId)) {
if (event.eventId != null && events.fastContains(event.eventId)) {
return
}
var currentDisplayIndex = lastDisplayIndex(direction, 0)
if (direction == PaginationDirection.FORWARDS) {
currentDisplayIndex += 1

View File

@ -20,7 +20,7 @@ import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.UnsignedData
import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.di.MoshiProvider
import java.util.*
internal object EventMapper {
@ -29,7 +29,7 @@ internal object EventMapper {
val uds = if (event.unsignedData == null) null
else MoshiProvider.providesMoshi().adapter(UnsignedData::class.java).toJson(event.unsignedData)
val eventEntity = EventEntity()
eventEntity.eventId = event.eventId ?: ""
eventEntity.eventId = event.eventId ?: UUID.randomUUID().toString()
eventEntity.roomId = event.roomId ?: roomId
eventEntity.content = ContentMapper.map(event.content)
val resolvedPrevContent = event.prevContent ?: event.unsignedData?.prevContent

View File

@ -37,7 +37,8 @@ internal object RoomSummaryMapper {
otherMemberIds = roomSummaryEntity.otherMemberIds.toList(),
highlightCount = roomSummaryEntity.highlightCount,
notificationCount = roomSummaryEntity.notificationCount,
tags = tags
tags = tags,
membership = roomSummaryEntity.membership
)
}
}

View File

@ -16,7 +16,7 @@
package im.vector.matrix.android.internal.database.model
import im.vector.matrix.android.api.session.room.model.MyMembership
import im.vector.matrix.android.api.session.room.model.Membership
import io.realm.RealmObject
import io.realm.annotations.Ignore
import io.realm.annotations.PrimaryKey
@ -26,10 +26,10 @@ internal open class GroupEntity(@PrimaryKey var groupId: String = ""
) : RealmObject() {
private var membershipStr: String = MyMembership.NONE.name
private var membershipStr: String = Membership.NONE.name
@delegate:Ignore
var membership: MyMembership by Delegates.observable(MyMembership.valueOf(membershipStr)) { _, _, newValue ->
var membership: Membership by Delegates.observable(Membership.valueOf(membershipStr)) { _, _, newValue ->
membershipStr = newValue.name
}

View File

@ -16,7 +16,7 @@
package im.vector.matrix.android.internal.database.model
import im.vector.matrix.android.api.session.room.model.MyMembership
import im.vector.matrix.android.api.session.room.model.Membership
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.Ignore
@ -30,10 +30,10 @@ internal open class RoomEntity(@PrimaryKey var roomId: String = "",
var areAllMembersLoaded: Boolean = false
) : RealmObject() {
private var membershipStr: String = MyMembership.NONE.name
private var membershipStr: String = Membership.NONE.name
@delegate:Ignore
var membership: MyMembership by Delegates.observable(MyMembership.valueOf(membershipStr)) { _, _, newValue ->
var membership: Membership by Delegates.observable(Membership.valueOf(membershipStr)) { _, _, newValue ->
membershipStr = newValue.name
}

View File

@ -16,9 +16,12 @@
package im.vector.matrix.android.internal.database.model
import im.vector.matrix.android.api.session.room.model.Membership
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.Ignore
import io.realm.annotations.PrimaryKey
import kotlin.properties.Delegates
internal open class RoomSummaryEntity(@PrimaryKey var roomId: String = "",
var displayName: String? = "",
@ -35,6 +38,13 @@ internal open class RoomSummaryEntity(@PrimaryKey var roomId: String = "",
var tags: RealmList<RoomTagEntity> = RealmList()
) : RealmObject() {
private var membershipStr: String = Membership.NONE.name
@delegate:Ignore
var membership: Membership by Delegates.observable(Membership.valueOf(membershipStr)) { _, _, newValue ->
membershipStr = newValue.name
}
companion object
}

View File

@ -16,7 +16,7 @@
package im.vector.matrix.android.internal.database.query
import im.vector.matrix.android.api.session.room.model.MyMembership
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.internal.database.model.GroupEntity
import im.vector.matrix.android.internal.database.model.GroupEntityFields
import io.realm.Realm
@ -27,7 +27,7 @@ internal fun GroupEntity.Companion.where(realm: Realm, roomId: String): RealmQue
return realm.where<GroupEntity>().equalTo(GroupEntityFields.GROUP_ID, roomId)
}
internal fun GroupEntity.Companion.where(realm: Realm, membership: MyMembership? = null): RealmQuery<GroupEntity> {
internal fun GroupEntity.Companion.where(realm: Realm, membership: Membership? = null): RealmQuery<GroupEntity> {
val query = realm.where<GroupEntity>()
if (membership != null) {
query.equalTo(GroupEntityFields.MEMBERSHIP_STR, membership.name)

View File

@ -16,7 +16,7 @@
package im.vector.matrix.android.internal.database.query
import im.vector.matrix.android.api.session.room.model.MyMembership
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.model.RoomEntityFields
@ -28,7 +28,7 @@ internal fun RoomEntity.Companion.where(realm: Realm, roomId: String): RealmQuer
return realm.where<RoomEntity>().equalTo(RoomEntityFields.ROOM_ID, roomId)
}
internal fun RoomEntity.Companion.where(realm: Realm, membership: MyMembership? = null): RealmQuery<RoomEntity> {
internal fun RoomEntity.Companion.where(realm: Realm, membership: Membership? = null): RealmQuery<RoomEntity> {
val query = realm.where<RoomEntity>()
if (membership != null) {
query.equalTo(RoomEntityFields.MEMBERSHIP_STR, membership.name)

View File

@ -37,8 +37,8 @@ import im.vector.matrix.android.internal.session.room.DefaultRoomService
import im.vector.matrix.android.internal.session.room.EventRelationsAggregationUpdater
import im.vector.matrix.android.internal.session.room.RoomAvatarResolver
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
import im.vector.matrix.android.internal.session.room.members.RoomDisplayNameResolver
import im.vector.matrix.android.internal.session.room.members.RoomMemberDisplayNameResolver
import im.vector.matrix.android.internal.session.room.membership.RoomDisplayNameResolver
import im.vector.matrix.android.internal.session.room.membership.RoomMemberDisplayNameResolver
import im.vector.matrix.android.internal.session.room.prune.EventsPruner
import im.vector.matrix.android.internal.session.signout.DefaultSignOutService
import im.vector.matrix.android.internal.session.user.DefaultUserService

View File

@ -20,7 +20,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.Transformations
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.api.session.room.members.RoomMembersService
import im.vector.matrix.android.api.session.room.members.MembershipService
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.read.ReadService
import im.vector.matrix.android.api.session.room.send.SendService
@ -39,13 +39,13 @@ internal class DefaultRoom(
private val sendService: SendService,
private val stateService: StateService,
private val readService: ReadService,
private val roomMembersService: RoomMembersService
private val roomMembersService: MembershipService
) : Room,
TimelineService by timelineService,
SendService by sendService,
StateService by stateService,
ReadService by readService,
RoomMembersService by roomMembersService {
TimelineService by timelineService,
SendService by sendService,
StateService by stateService,
ReadService by readService,
MembershipService by roomMembersService {
override val roomSummary: LiveData<RoomSummary> by lazy {
val liveRealmData = RealmLiveData<RoomSummaryEntity>(monarchy.realmConfiguration) { realm ->

View File

@ -18,17 +18,21 @@ package im.vector.matrix.android.internal.session.room
import im.vector.matrix.android.api.session.events.model.Content
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.room.model.annotation.ReactionContent
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
import im.vector.matrix.android.api.session.room.model.create.CreateRoomResponse
import im.vector.matrix.android.internal.network.NetworkConstants
import im.vector.matrix.android.internal.session.room.invite.InviteBody
import im.vector.matrix.android.internal.session.room.members.RoomMembersResponse
import im.vector.matrix.android.internal.session.room.membership.RoomMembersResponse
import im.vector.matrix.android.internal.session.room.membership.joining.InviteBody
import im.vector.matrix.android.internal.session.room.send.SendResponse
import im.vector.matrix.android.internal.session.room.timeline.EventContextResponse
import im.vector.matrix.android.internal.session.room.timeline.PaginationResponse
import retrofit2.Call
import retrofit2.http.*
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Path
import retrofit2.http.Query
internal interface RoomAPI {
@ -173,4 +177,24 @@ internal interface RoomAPI {
@Path("eventType") eventType: String,
@Body content: Content?
): Call<SendResponse>
/**
* Join the given room.
*
* @param roomId the room id
* @param params the request body
*/
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/join")
fun join(@Path("roomId") roomId: String,
@Body params: Map<String, String>): Call<Unit>
/**
* Leave the given room.
*
* @param roomId the room id
* @param params the request body
*/
@POST(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/leave")
fun leave(@Path("roomId") roomId: String,
@Body params: Map<String, String>): Call<Unit>
}

View File

@ -20,14 +20,14 @@ import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.auth.data.Credentials
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.MyMembership
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.RoomAvatarContent
import im.vector.matrix.android.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.query.prev
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.room.members.RoomMembers
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
internal class RoomAvatarResolver(private val monarchy: Monarchy,
private val credentials: Credentials) {
@ -48,7 +48,7 @@ internal class RoomAvatarResolver(private val monarchy: Monarchy,
}
val roomMembers = RoomMembers(realm, roomId)
val members = roomMembers.getLoaded()
if (roomEntity?.membership == MyMembership.INVITED) {
if (roomEntity?.membership == Membership.INVITE) {
if (members.size == 1) {
res = members.entries.first().value.avatarUrl
} else if (members.size > 1) {
@ -57,9 +57,9 @@ internal class RoomAvatarResolver(private val monarchy: Monarchy,
}
} else {
// detect if it is a room with no more than 2 members (i.e. an alone or a 1:1 chat)
if (roomMembers.getNumberOfJoinedMembers() == 1 && members.isNotEmpty()) {
if (members.size == 1) {
res = members.entries.first().value.avatarUrl
} else if (roomMembers.getNumberOfMembers() == 2 && members.size > 1) {
} else if (members.size == 2) {
val firstOtherMember = members.filterKeys { it != credentials.userId }.values.firstOrNull()
res = firstOtherMember?.avatarUrl
}

View File

@ -18,10 +18,12 @@ package im.vector.matrix.android.internal.session.room
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.internal.session.room.invite.InviteTask
import im.vector.matrix.android.internal.session.room.members.DefaultRoomMembersService
import im.vector.matrix.android.internal.session.room.members.LoadRoomMembersTask
import im.vector.matrix.android.internal.session.room.members.SenderRoomMemberExtractor
import im.vector.matrix.android.internal.session.room.membership.DefaultMembershipService
import im.vector.matrix.android.internal.session.room.membership.LoadRoomMembersTask
import im.vector.matrix.android.internal.session.room.membership.SenderRoomMemberExtractor
import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
import im.vector.matrix.android.internal.session.room.membership.leaving.LeaveRoomTask
import im.vector.matrix.android.internal.session.room.read.DefaultReadService
import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask
import im.vector.matrix.android.internal.session.room.send.DefaultSendService
@ -34,24 +36,26 @@ import im.vector.matrix.android.internal.session.room.timeline.PaginationTask
import im.vector.matrix.android.internal.session.room.timeline.TimelineEventFactory
import im.vector.matrix.android.internal.task.TaskExecutor
internal class RoomFactory(private val loadRoomMembersTask: LoadRoomMembersTask,
internal class RoomFactory(private val monarchy: Monarchy,
private val eventFactory: LocalEchoEventFactory,
private val taskExecutor: TaskExecutor,
private val loadRoomMembersTask: LoadRoomMembersTask,
private val inviteTask: InviteTask,
private val sendStateTask: SendStateTask,
private val monarchy: Monarchy,
private val paginationTask: PaginationTask,
private val contextOfEventTask: GetContextOfEventTask,
private val setReadMarkersTask: SetReadMarkersTask,
private val eventFactory: LocalEchoEventFactory,
private val taskExecutor: TaskExecutor) {
private val joinRoomTask: JoinRoomTask,
private val leaveRoomTask: LeaveRoomTask) {
fun instantiate(roomId: String): Room {
val roomMemberExtractor = SenderRoomMemberExtractor(roomId)
val timelineEventFactory = TimelineEventFactory(roomMemberExtractor, EventRelationExtractor())
val timelineService = DefaultTimelineService(roomId, monarchy, taskExecutor, contextOfEventTask, timelineEventFactory, paginationTask)
val timelineService = DefaultTimelineService(roomId, monarchy, taskExecutor, timelineEventFactory, contextOfEventTask, paginationTask)
val sendService = DefaultSendService(roomId, eventFactory, monarchy)
val stateService = DefaultStateService(roomId, sendStateTask, taskExecutor)
val roomMembersService = DefaultRoomMembersService(roomId, monarchy, loadRoomMembersTask, inviteTask, taskExecutor)
val readService = DefaultReadService(roomId, monarchy, setReadMarkersTask, taskExecutor)
val stateService = DefaultStateService(roomId, taskExecutor, sendStateTask)
val roomMembersService = DefaultMembershipService(roomId, monarchy, taskExecutor, loadRoomMembersTask, inviteTask, joinRoomTask, leaveRoomTask)
val readService = DefaultReadService(roomId, monarchy, taskExecutor, setReadMarkersTask)
return DefaultRoom(
roomId,

View File

@ -19,10 +19,14 @@ package im.vector.matrix.android.internal.session.room
import im.vector.matrix.android.internal.session.DefaultSession
import im.vector.matrix.android.internal.session.room.create.CreateRoomTask
import im.vector.matrix.android.internal.session.room.create.DefaultCreateRoomTask
import im.vector.matrix.android.internal.session.room.invite.DefaultInviteTask
import im.vector.matrix.android.internal.session.room.invite.InviteTask
import im.vector.matrix.android.internal.session.room.members.DefaultLoadRoomMembersTask
import im.vector.matrix.android.internal.session.room.members.LoadRoomMembersTask
import im.vector.matrix.android.internal.session.room.membership.DefaultLoadRoomMembersTask
import im.vector.matrix.android.internal.session.room.membership.LoadRoomMembersTask
import im.vector.matrix.android.internal.session.room.membership.joining.DefaultInviteTask
import im.vector.matrix.android.internal.session.room.membership.joining.DefaultJoinRoomTask
import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
import im.vector.matrix.android.internal.session.room.membership.leaving.DefaultLeaveRoomTask
import im.vector.matrix.android.internal.session.room.membership.leaving.LeaveRoomTask
import im.vector.matrix.android.internal.session.room.read.DefaultSetReadMarkersTask
import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask
import im.vector.matrix.android.internal.session.room.send.LocalEchoEventFactory
@ -71,7 +75,7 @@ class RoomModule {
}
scope(DefaultSession.SCOPE) {
RoomFactory(get(), get(), get(), get(), get(), get(), get(), get(), get())
RoomFactory(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get())
}
scope(DefaultSession.SCOPE) {
@ -82,6 +86,14 @@ class RoomModule {
DefaultInviteTask(get()) as InviteTask
}
scope(DefaultSession.SCOPE) {
DefaultJoinRoomTask(get()) as JoinRoomTask
}
scope(DefaultSession.SCOPE) {
DefaultLeaveRoomTask(get()) as LeaveRoomTask
}
scope(DefaultSession.SCOPE) {
DefaultSendStateTask(get()) as SendStateTask
}

View File

@ -21,6 +21,7 @@ package im.vector.matrix.android.internal.session.room
import im.vector.matrix.android.api.auth.data.Credentials
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.RoomTopicContent
import im.vector.matrix.android.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.database.model.EventEntity
@ -28,8 +29,8 @@ import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
import im.vector.matrix.android.internal.database.query.latestEvent
import im.vector.matrix.android.internal.database.query.prev
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.room.members.RoomDisplayNameResolver
import im.vector.matrix.android.internal.session.room.members.RoomMembers
import im.vector.matrix.android.internal.session.room.membership.RoomDisplayNameResolver
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
import im.vector.matrix.android.internal.session.sync.model.RoomSyncSummary
import im.vector.matrix.android.internal.session.sync.model.RoomSyncUnreadNotifications
import io.realm.Realm
@ -41,11 +42,12 @@ internal class RoomSummaryUpdater(private val credentials: Credentials,
fun update(realm: Realm,
roomId: String,
membership: Membership? = null,
roomSummary: RoomSyncSummary? = null,
unreadNotifications: RoomSyncUnreadNotifications? = null) {
val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst()
?: realm.createObject(roomId)
?: realm.createObject(roomId)
if (roomSummary != null) {
if (roomSummary.heroes.isNotEmpty()) {
@ -65,8 +67,11 @@ internal class RoomSummaryUpdater(private val credentials: Credentials,
if (unreadNotifications?.notificationCount != null) {
roomSummaryEntity.notificationCount = unreadNotifications.notificationCount
}
if (membership != null) {
roomSummaryEntity.membership = membership
}
val lastEvent = EventEntity.latestEvent(realm, roomId, includedTypes = listOf(EventType.MESSAGE))
val lastEvent = EventEntity.latestEvent(realm, roomId)
val lastTopicEvent = EventEntity.where(realm, roomId, EventType.STATE_ROOM_TOPIC).prev()?.asDomain()
val otherRoomMembers = RoomMembers(realm, roomId).getLoaded().filterKeys { it != credentials.userId }
roomSummaryEntity.displayName = roomDisplayNameResolver.resolve(roomId).toString()

View File

@ -16,28 +16,32 @@
*
*/
package im.vector.matrix.android.internal.session.room.members
package im.vector.matrix.android.internal.session.room.membership
import androidx.lifecycle.LiveData
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.members.RoomMembersService
import im.vector.matrix.android.api.session.room.members.MembershipService
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.RoomMember
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.session.room.invite.InviteTask
import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
import im.vector.matrix.android.internal.session.room.membership.leaving.LeaveRoomTask
import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith
import im.vector.matrix.android.internal.util.fetchCopied
internal class DefaultRoomMembersService(private val roomId: String,
private val monarchy: Monarchy,
private val loadRoomMembersTask: LoadRoomMembersTask,
private val inviteTask: InviteTask,
private val taskExecutor: TaskExecutor
) : RoomMembersService {
internal class DefaultMembershipService(private val roomId: String,
private val monarchy: Monarchy,
private val taskExecutor: TaskExecutor,
private val loadRoomMembersTask: LoadRoomMembersTask,
private val inviteTask: InviteTask,
private val joinTask: JoinRoomTask,
private val leaveRoomTask: LeaveRoomTask
) : MembershipService {
override fun loadRoomMembersIfNeeded(): Cancelable {
val params = LoadRoomMembersTask.Params(roomId, Membership.LEAVE)
@ -68,4 +72,18 @@ internal class DefaultRoomMembersService(private val roomId: String,
.dispatchTo(callback)
.executeBy(taskExecutor)
}
override fun join(callback: MatrixCallback<Unit>) {
val params = JoinRoomTask.Params(roomId)
joinTask.configureWith(params)
.dispatchTo(callback)
.executeBy(taskExecutor)
}
override fun leave(callback: MatrixCallback<Unit>) {
val params = LeaveRoomTask.Params(roomId)
leaveRoomTask.configureWith(params)
.dispatchTo(callback)
.executeBy(taskExecutor)
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.room.members
package im.vector.matrix.android.internal.session.room.membership
import arrow.core.Try
import com.zhuinden.monarchy.Monarchy

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.room.members
package im.vector.matrix.android.internal.session.room.membership
import android.content.Context
import com.zhuinden.monarchy.Monarchy
@ -22,7 +22,7 @@ import im.vector.matrix.android.R
import im.vector.matrix.android.api.auth.data.Credentials
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.MyMembership
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.RoomAliasesContent
import im.vector.matrix.android.api.session.room.model.RoomCanonicalAliasContent
import im.vector.matrix.android.api.session.room.model.RoomNameContent
@ -77,24 +77,17 @@ internal class RoomDisplayNameResolver(private val context: Context,
}
val roomMembers = RoomMembers(realm, roomId)
val otherRoomMembers = roomMembers.getLoaded()
.filterKeys { it != credentials.userId }
if (roomEntity?.membership == MyMembership.INVITED) {
//TODO handle invited
/*
if (currentUser != null
&& !othersActiveMembers.isEmpty()
&& !TextUtils.isEmpty(currentUser!!.mSender)) {
// extract who invited us to the room
name = context.getString(R.string.room_displayname_invite_from, roomState.resolve(currentUser!!.mSender))
val loadedMembers = roomMembers.getLoaded()
val otherRoomMembers = loadedMembers.filterKeys { it != credentials.userId }
if (roomEntity?.membership == Membership.INVITE) {
val inviteMeEvent = roomMembers.queryRoomMemberEvent(credentials.userId).findFirst()
val inviterId = inviteMeEvent?.sender
name = if (inviterId != null && otherRoomMembers.containsKey(inviterId)) {
roomMemberDisplayNameResolver.resolve(inviterId, otherRoomMembers)
} else {
name = context.getString(R.string.room_displayname_room_invite)
context.getString(R.string.room_displayname_room_invite)
}
*/
name = context.getString(R.string.room_displayname_room_invite)
} else {
val roomSummary = RoomSummaryEntity.where(realm, roomId).findFirst()
val memberIds = if (roomSummary?.heroes?.isNotEmpty() == true) {
roomSummary.heroes

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.room.members
package im.vector.matrix.android.internal.session.room.membership
import im.vector.matrix.android.api.session.room.model.RoomMember

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.room.members
package im.vector.matrix.android.internal.session.room.membership
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.room.members
package im.vector.matrix.android.internal.session.room.membership
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.room.members
package im.vector.matrix.android.internal.session.room.membership
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel

View File

@ -5,7 +5,7 @@
* 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
* 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,
@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.room.invite
package im.vector.matrix.android.internal.session.room.membership.joining
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.room.invite
package im.vector.matrix.android.internal.session.room.membership.joining
import arrow.core.Try
import im.vector.matrix.android.internal.network.executeRequest

View File

@ -0,0 +1,38 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.room.membership.joining
import arrow.core.Try
import im.vector.matrix.android.internal.network.executeRequest
import im.vector.matrix.android.internal.session.room.RoomAPI
import im.vector.matrix.android.internal.task.Task
internal interface JoinRoomTask : Task<JoinRoomTask.Params, Unit> {
data class Params(
val roomId: String
)
}
internal class DefaultJoinRoomTask(private val roomAPI: RoomAPI) : JoinRoomTask {
override fun execute(params: JoinRoomTask.Params): Try<Unit> {
return executeRequest {
apiCall = roomAPI.join(params.roomId, HashMap())
}
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.room.membership.leaving
import arrow.core.Try
import im.vector.matrix.android.internal.network.executeRequest
import im.vector.matrix.android.internal.session.room.RoomAPI
import im.vector.matrix.android.internal.task.Task
internal interface LeaveRoomTask : Task<LeaveRoomTask.Params, Unit> {
data class Params(
val roomId: String
)
}
internal class DefaultLeaveRoomTask(private val roomAPI: RoomAPI) : LeaveRoomTask {
override fun execute(params: LeaveRoomTask.Params): Try<Unit> {
return executeRequest {
apiCall = roomAPI.leave(params.roomId, HashMap())
}
}
}

View File

@ -27,8 +27,8 @@ import im.vector.matrix.android.internal.util.fetchCopied
internal class DefaultReadService(private val roomId: String,
private val monarchy: Monarchy,
private val setReadMarkersTask: SetReadMarkersTask,
private val taskExecutor: TaskExecutor) : ReadService {
private val taskExecutor: TaskExecutor,
private val setReadMarkersTask: SetReadMarkersTask) : ReadService {
override fun markAllAsRead(callback: MatrixCallback<Unit>) {
val latestEvent = getLatestEvent()

View File

@ -23,8 +23,8 @@ import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith
internal class DefaultStateService(private val roomId: String,
private val sendStateTask: SendStateTask,
private val taskExecutor: TaskExecutor) : StateService {
private val taskExecutor: TaskExecutor,
private val sendStateTask: SendStateTask) : StateService {
override fun updateTopic(topic: String, callback: MatrixCallback<Unit>) {
val params = SendStateTask.Params(roomId,

View File

@ -28,8 +28,8 @@ import im.vector.matrix.android.internal.util.fetchCopyMap
internal class DefaultTimelineService(private val roomId: String,
private val monarchy: Monarchy,
private val taskExecutor: TaskExecutor,
private val contextOfEventTask: GetContextOfEventTask,
private val timelineEventFactory: TimelineEventFactory,
private val contextOfEventTask: GetContextOfEventTask,
private val paginationTask: PaginationTask
) : TimelineService {

View File

@ -20,7 +20,7 @@ import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.matrix.android.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.session.room.EventRelationExtractor
import im.vector.matrix.android.internal.session.room.members.SenderRoomMemberExtractor
import im.vector.matrix.android.internal.session.room.membership.SenderRoomMemberExtractor
import io.realm.Realm
internal class TimelineEventFactory(

View File

@ -17,7 +17,7 @@
package im.vector.matrix.android.internal.session.sync
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.room.model.MyMembership
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.internal.database.model.GroupEntity
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.sync.model.GroupsSyncResponse
@ -56,7 +56,7 @@ internal class GroupSyncHandler(private val monarchy: Monarchy) {
groupId: String): GroupEntity {
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
groupEntity.membership = MyMembership.JOINED
groupEntity.membership = Membership.JOIN
return groupEntity
}
@ -64,7 +64,7 @@ internal class GroupSyncHandler(private val monarchy: Monarchy) {
groupId: String): GroupEntity {
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
groupEntity.membership = MyMembership.INVITED
groupEntity.membership = Membership.INVITE
return groupEntity
}
@ -74,7 +74,7 @@ internal class GroupSyncHandler(private val monarchy: Monarchy) {
groupId: String): GroupEntity {
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
groupEntity.membership = MyMembership.LEFT
groupEntity.membership = Membership.LEAVE
return groupEntity
}

View File

@ -20,7 +20,7 @@ import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.MyMembership
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.tag.RoomTagContent
import im.vector.matrix.android.internal.database.helper.addAll
import im.vector.matrix.android.internal.database.helper.addOrUpdate
@ -69,7 +69,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
val rooms = when (handlingStrategy) {
is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) }
is HandlingStrategy.INVITED -> handlingStrategy.data.map { handleInvitedRoom(realm, it.key, it.value) }
is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftRoom(it.key, it.value) }
is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftRoom(realm, it.key, it.value) }
}
realm.insertOrUpdate(rooms)
}
@ -83,11 +83,10 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
val roomEntity = RoomEntity.where(realm, roomId).findFirst()
?: realm.createObject(roomId)
if (roomEntity.membership == MyMembership.INVITED) {
if (roomEntity.membership == Membership.INVITE) {
roomEntity.chunks.deleteAllFromRealm()
}
roomEntity.membership = MyMembership.JOINED
roomEntity.membership = Membership.JOIN
val lastChunk = ChunkEntity.findLastLiveChunkFromRoom(realm, roomId)
val isInitialSync = lastChunk == null
@ -121,8 +120,8 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
}
}
}
roomSummaryUpdater.update(realm, roomId, roomSync.summary, roomSync.unreadNotifications)
eventRelationsAggregationUpdater.update(realm,roomId,roomSync.timeline?.events)
eventRelationsAggregationUpdater.update(realm, roomId, roomSync.timeline?.events)
roomSummaryUpdater.update(realm, roomId, Membership.JOIN, roomSync.summary, roomSync.unreadNotifications)
if (roomSync.ephemeral != null && roomSync.ephemeral.events.isNotEmpty()) {
handleEphemeral(realm, roomId, roomSync.ephemeral)
@ -131,7 +130,6 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
if (roomSync.accountData != null && roomSync.accountData.events.isNullOrEmpty().not()) {
handleRoomAccountDataEvents(realm, roomId, roomSync.accountData)
}
return roomEntity
}
@ -139,26 +137,28 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
roomId: String,
roomSync:
InvitedRoomSync): RoomEntity {
Timber.v("Handle invited sync for room $roomId")
val roomEntity = RoomEntity()
roomEntity.roomId = roomId
roomEntity.membership = MyMembership.INVITED
val roomEntity = RoomEntity.where(realm, roomId).findFirst()
?: realm.createObject(roomId)
roomEntity.membership = Membership.INVITE
if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) {
val chunkEntity = handleTimelineEvents(realm, roomId, roomSync.inviteState.events)
roomEntity.addOrUpdate(chunkEntity)
}
roomSummaryUpdater.update(realm, roomId, Membership.INVITE)
return roomEntity
}
// TODO : handle it
private fun handleLeftRoom(roomId: String,
private fun handleLeftRoom(realm: Realm,
roomId: String,
roomSync: RoomSync): RoomEntity {
return RoomEntity().apply {
this.roomId = roomId
this.membership = MyMembership.LEFT
}
val roomEntity = RoomEntity.where(realm, roomId).findFirst()
?: realm.createObject(roomId)
roomEntity.membership = Membership.LEAVE
roomEntity.chunks.deleteAllFromRealm()
roomSummaryUpdater.update(realm, roomId, Membership.LEAVE, roomSync.summary, roomSync.unreadNotifications)
return roomEntity
}
private fun handleTimelineEvents(realm: Realm,

View File

@ -23,7 +23,7 @@ import im.vector.matrix.android.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.database.model.UserEntity
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.room.members.RoomMembers
import im.vector.matrix.android.internal.session.room.membership.RoomMembers
import im.vector.matrix.android.internal.task.Task
import im.vector.matrix.android.internal.util.tryTransactionSync