forked from GitHub-Mirror/riotX-android
Quick sync group management (WIP)
This commit is contained in:
parent
3199f5dcd6
commit
a3539153ef
BIN
.idea/caches/build_file_checksums.ser
generated
BIN
.idea/caches/build_file_checksums.ser
generated
Binary file not shown.
@ -1,6 +1,7 @@
|
|||||||
package im.vector.matrix.rx
|
package im.vector.matrix.rx
|
||||||
|
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
|
|
||||||
@ -10,6 +11,10 @@ class RxSession(private val session: Session) {
|
|||||||
return session.liveRoomSummaries().asObservable()
|
return session.liveRoomSummaries().asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun liveGroupSummaries(): Observable<List<GroupSummary>> {
|
||||||
|
return session.liveGroupSummaries().asObservable()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Session.rx(): RxSession {
|
fun Session.rx(): RxSession {
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
package im.vector.matrix.android.api.session
|
package im.vector.matrix.android.api.session
|
||||||
|
|
||||||
import android.support.annotation.MainThread
|
import android.support.annotation.MainThread
|
||||||
|
import im.vector.matrix.android.api.session.group.GroupService
|
||||||
import im.vector.matrix.android.api.session.room.RoomService
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
import im.vector.matrix.android.internal.auth.data.SessionParams
|
import im.vector.matrix.android.internal.auth.data.SessionParams
|
||||||
|
|
||||||
interface Session : RoomService {
|
interface Session : RoomService, GroupService {
|
||||||
|
|
||||||
val sessionParams: SessionParams
|
val sessionParams: SessionParams
|
||||||
|
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package im.vector.matrix.android.api.session.group
|
||||||
|
|
||||||
|
interface Group {
|
||||||
|
val groupId: String
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package im.vector.matrix.android.api.session.group
|
||||||
|
|
||||||
|
import android.arch.lifecycle.LiveData
|
||||||
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
|
|
||||||
|
interface GroupService {
|
||||||
|
|
||||||
|
fun getGroup(groupId: String): Group?
|
||||||
|
|
||||||
|
fun liveGroupSummaries(): LiveData<List<GroupSummary>>
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package im.vector.matrix.android.api.session.group.model
|
||||||
|
|
||||||
|
data class GroupSummary(
|
||||||
|
val groupId: String,
|
||||||
|
val displayName: String = "",
|
||||||
|
val shortDescription: String = "",
|
||||||
|
val avatarUrl: String = ""
|
||||||
|
)
|
@ -0,0 +1,19 @@
|
|||||||
|
package im.vector.matrix.android.internal.database.mapper
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.group.Group
|
||||||
|
import im.vector.matrix.android.internal.database.model.GroupEntity
|
||||||
|
import im.vector.matrix.android.internal.session.group.DefaultGroup
|
||||||
|
|
||||||
|
|
||||||
|
object GroupMapper {
|
||||||
|
|
||||||
|
internal fun map(groupEntity: GroupEntity): Group {
|
||||||
|
return DefaultGroup(
|
||||||
|
groupEntity.groupId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun GroupEntity.asDomain(): Group {
|
||||||
|
return GroupMapper.map(this)
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package im.vector.matrix.android.internal.database.mapper
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
|
import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
|
||||||
|
|
||||||
|
|
||||||
|
object GroupSummaryMapper {
|
||||||
|
|
||||||
|
internal fun map(roomSummaryEntity: GroupSummaryEntity): GroupSummary {
|
||||||
|
return GroupSummary(
|
||||||
|
roomSummaryEntity.groupId,
|
||||||
|
roomSummaryEntity.displayName,
|
||||||
|
roomSummaryEntity.shortDescription,
|
||||||
|
roomSummaryEntity.avatarUrl
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun GroupSummaryEntity.asDomain(): GroupSummary {
|
||||||
|
return GroupSummaryMapper.map(this)
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package im.vector.matrix.android.internal.database.model
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.room.model.MyMembership
|
||||||
|
import io.realm.RealmObject
|
||||||
|
import io.realm.annotations.Ignore
|
||||||
|
import io.realm.annotations.PrimaryKey
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
|
open class GroupEntity(@PrimaryKey var groupId: String = ""
|
||||||
|
|
||||||
|
) : RealmObject() {
|
||||||
|
|
||||||
|
private var membershipStr: String = MyMembership.NONE.name
|
||||||
|
|
||||||
|
@delegate:Ignore
|
||||||
|
var membership: MyMembership by Delegates.observable(MyMembership.valueOf(membershipStr)) { _, _, newValue ->
|
||||||
|
membershipStr = newValue.name
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package im.vector.matrix.android.internal.database.model
|
||||||
|
|
||||||
|
import io.realm.RealmObject
|
||||||
|
import io.realm.annotations.PrimaryKey
|
||||||
|
|
||||||
|
open class GroupSummaryEntity(@PrimaryKey var groupId: String = "",
|
||||||
|
var displayName: String = "",
|
||||||
|
var shortDescription: String = "",
|
||||||
|
var avatarUrl: String = ""
|
||||||
|
) : RealmObject() {
|
||||||
|
|
||||||
|
companion object
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package im.vector.matrix.android.internal.database.query
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.room.model.MyMembership
|
||||||
|
import im.vector.matrix.android.internal.database.model.GroupEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.GroupEntityFields
|
||||||
|
import io.realm.Realm
|
||||||
|
import io.realm.RealmQuery
|
||||||
|
import io.realm.kotlin.where
|
||||||
|
|
||||||
|
fun GroupEntity.Companion.where(realm: Realm, roomId: String): RealmQuery<GroupEntity> {
|
||||||
|
return realm.where<GroupEntity>().equalTo(GroupEntityFields.GROUP_ID, roomId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun GroupEntity.Companion.where(realm: Realm, membership: MyMembership? = null): RealmQuery<GroupEntity> {
|
||||||
|
val query = realm.where<GroupEntity>()
|
||||||
|
if (membership != null) {
|
||||||
|
query.equalTo(GroupEntityFields.MEMBERSHIP_STR, membership.name)
|
||||||
|
}
|
||||||
|
return query
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package im.vector.matrix.android.internal.database.query
|
||||||
|
|
||||||
|
import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.GroupSummaryEntityFields
|
||||||
|
import io.realm.Realm
|
||||||
|
import io.realm.RealmQuery
|
||||||
|
import io.realm.kotlin.where
|
||||||
|
|
||||||
|
fun GroupSummaryEntity.Companion.where(realm: Realm, groupId: String? = null): RealmQuery<GroupSummaryEntity> {
|
||||||
|
val query = realm.where<GroupSummaryEntity>()
|
||||||
|
if (groupId != null) {
|
||||||
|
query.equalTo(GroupSummaryEntityFields.GROUP_ID, groupId)
|
||||||
|
}
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.internal.legacy.rest.model.group;
|
package im.vector.matrix.android.internal.legacy.rest.model.group;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,10 +4,15 @@ import android.arch.lifecycle.LiveData
|
|||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.support.annotation.MainThread
|
import android.support.annotation.MainThread
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
|
import im.vector.matrix.android.api.session.group.Group
|
||||||
|
import im.vector.matrix.android.api.session.group.GroupService
|
||||||
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
import im.vector.matrix.android.api.session.room.Room
|
import im.vector.matrix.android.api.session.room.Room
|
||||||
import im.vector.matrix.android.api.session.room.RoomService
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
import im.vector.matrix.android.internal.auth.data.SessionParams
|
import im.vector.matrix.android.internal.auth.data.SessionParams
|
||||||
|
import im.vector.matrix.android.internal.session.group.GroupModule
|
||||||
|
import im.vector.matrix.android.internal.session.group.GroupSummaryUpdater
|
||||||
import im.vector.matrix.android.internal.session.room.RoomModule
|
import im.vector.matrix.android.internal.session.room.RoomModule
|
||||||
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
|
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
|
||||||
import im.vector.matrix.android.internal.session.sync.SyncModule
|
import im.vector.matrix.android.internal.session.sync.SyncModule
|
||||||
@ -28,7 +33,9 @@ class DefaultSession(override val sessionParams: SessionParams) : Session, KoinC
|
|||||||
private lateinit var scope: Scope
|
private lateinit var scope: Scope
|
||||||
|
|
||||||
private val roomSummaryObserver by inject<RoomSummaryUpdater>()
|
private val roomSummaryObserver by inject<RoomSummaryUpdater>()
|
||||||
|
private val groupSummaryUpdater by inject<GroupSummaryUpdater>()
|
||||||
private val roomService by inject<RoomService>()
|
private val roomService by inject<RoomService>()
|
||||||
|
private val groupService by inject<GroupService>()
|
||||||
private val syncThread by inject<SyncThread>()
|
private val syncThread by inject<SyncThread>()
|
||||||
private var isOpen = false
|
private var isOpen = false
|
||||||
|
|
||||||
@ -40,9 +47,11 @@ class DefaultSession(override val sessionParams: SessionParams) : Session, KoinC
|
|||||||
val sessionModule = SessionModule(sessionParams)
|
val sessionModule = SessionModule(sessionParams)
|
||||||
val syncModule = SyncModule()
|
val syncModule = SyncModule()
|
||||||
val roomModule = RoomModule()
|
val roomModule = RoomModule()
|
||||||
StandAloneContext.loadKoinModules(listOf(sessionModule, syncModule, roomModule))
|
val groupModule = GroupModule()
|
||||||
|
StandAloneContext.loadKoinModules(listOf(sessionModule, syncModule, roomModule, groupModule))
|
||||||
scope = getKoin().getOrCreateScope(SCOPE)
|
scope = getKoin().getOrCreateScope(SCOPE)
|
||||||
roomSummaryObserver.start()
|
roomSummaryObserver.start()
|
||||||
|
groupSummaryUpdater.start()
|
||||||
syncThread.start()
|
syncThread.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +61,7 @@ class DefaultSession(override val sessionParams: SessionParams) : Session, KoinC
|
|||||||
checkIsMainThread()
|
checkIsMainThread()
|
||||||
assert(isOpen)
|
assert(isOpen)
|
||||||
syncThread.kill()
|
syncThread.kill()
|
||||||
|
groupSummaryUpdater.dispose()
|
||||||
roomSummaryObserver.dispose()
|
roomSummaryObserver.dispose()
|
||||||
scope.close()
|
scope.close()
|
||||||
isOpen = false
|
isOpen = false
|
||||||
@ -89,6 +99,18 @@ class DefaultSession(override val sessionParams: SessionParams) : Session, KoinC
|
|||||||
roomService.saveLastSelectedRoom(roomSummary)
|
roomService.saveLastSelectedRoom(roomSummary)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GROUP SERVICE
|
||||||
|
|
||||||
|
override fun getGroup(groupId: String): Group? {
|
||||||
|
assert(isOpen)
|
||||||
|
return groupService.getGroup(groupId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun liveGroupSummaries(): LiveData<List<GroupSummary>> {
|
||||||
|
assert(isOpen)
|
||||||
|
return groupService.liveGroupSummaries()
|
||||||
|
}
|
||||||
|
|
||||||
// Private methods *****************************************************************************
|
// Private methods *****************************************************************************
|
||||||
|
|
||||||
private fun checkIsMainThread() {
|
private fun checkIsMainThread() {
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package im.vector.matrix.android.internal.session
|
package im.vector.matrix.android.internal.session
|
||||||
|
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import im.vector.matrix.android.api.session.group.GroupService
|
||||||
import im.vector.matrix.android.api.session.room.RoomService
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
import im.vector.matrix.android.internal.auth.data.SessionParams
|
import im.vector.matrix.android.internal.auth.data.SessionParams
|
||||||
|
import im.vector.matrix.android.internal.session.group.DefaultGroupService
|
||||||
|
import im.vector.matrix.android.internal.session.group.GroupSummaryUpdater
|
||||||
import im.vector.matrix.android.internal.session.room.DefaultRoomService
|
import im.vector.matrix.android.internal.session.room.DefaultRoomService
|
||||||
import im.vector.matrix.android.internal.session.room.RoomAvatarResolver
|
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.RoomSummaryUpdater
|
||||||
@ -58,6 +61,14 @@ class SessionModule(private val sessionParams: SessionParams) : Module {
|
|||||||
DefaultRoomService(get()) as RoomService
|
DefaultRoomService(get()) as RoomService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope(DefaultSession.SCOPE) {
|
||||||
|
GroupSummaryUpdater(get(), get())
|
||||||
|
}
|
||||||
|
|
||||||
|
scope(DefaultSession.SCOPE) {
|
||||||
|
DefaultGroupService(get()) as GroupService
|
||||||
|
}
|
||||||
|
|
||||||
}.invoke()
|
}.invoke()
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package im.vector.matrix.android.internal.session.group
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.group.Group
|
||||||
|
|
||||||
|
class DefaultGroup(override val groupId: String) : Group {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package im.vector.matrix.android.internal.session.group
|
||||||
|
|
||||||
|
import android.arch.lifecycle.LiveData
|
||||||
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import im.vector.matrix.android.api.session.group.Group
|
||||||
|
import im.vector.matrix.android.api.session.group.GroupService
|
||||||
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
|
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||||
|
import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.GroupSummaryEntityFields
|
||||||
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
|
||||||
|
class DefaultGroupService(private val monarchy: Monarchy) : GroupService {
|
||||||
|
|
||||||
|
override fun getGroup(groupId: String): Group? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun liveGroupSummaries(): LiveData<List<GroupSummary>> {
|
||||||
|
return monarchy.findAllMappedWithChanges(
|
||||||
|
{ realm -> GroupSummaryEntity.where(realm).isNotEmpty(GroupSummaryEntityFields.DISPLAY_NAME) },
|
||||||
|
{ it.asDomain() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package im.vector.matrix.android.internal.session.group
|
||||||
|
|
||||||
|
import arrow.core.Either
|
||||||
|
import arrow.core.flatMap
|
||||||
|
import arrow.core.leftIfNull
|
||||||
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
|
import im.vector.matrix.android.internal.database.model.GroupSummaryEntity
|
||||||
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.network.executeRequest
|
||||||
|
import im.vector.matrix.android.internal.session.group.model.GroupSummaryResponse
|
||||||
|
import im.vector.matrix.android.internal.util.CancelableCoroutine
|
||||||
|
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||||
|
import io.realm.kotlin.createObject
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
class GetGroupSummaryRequest(
|
||||||
|
private val groupAPI: GroupAPI,
|
||||||
|
private val monarchy: Monarchy,
|
||||||
|
private val coroutineDispatchers: MatrixCoroutineDispatchers
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun execute(groupId: String,
|
||||||
|
callback: MatrixCallback<GroupSummaryResponse>
|
||||||
|
): Cancelable {
|
||||||
|
val job = GlobalScope.launch(coroutineDispatchers.main) {
|
||||||
|
val groupOrFailure = execute(groupId)
|
||||||
|
groupOrFailure.bimap({ callback.onFailure(it) }, { callback.onSuccess(it) })
|
||||||
|
}
|
||||||
|
return CancelableCoroutine(job)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun execute(groupId: String) = withContext(coroutineDispatchers.io) {
|
||||||
|
|
||||||
|
return@withContext executeRequest<GroupSummaryResponse> {
|
||||||
|
apiCall = groupAPI.getSummary(groupId)
|
||||||
|
}.leftIfNull {
|
||||||
|
Failure.Unknown(RuntimeException("GroupSummary shouldn't be null"))
|
||||||
|
}.flatMap { groupSummary ->
|
||||||
|
try {
|
||||||
|
insertInDb(groupSummary, groupId)
|
||||||
|
Either.right(groupSummary)
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
Either.Left(Failure.Unknown(exception))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun insertInDb(groupSummary: GroupSummaryResponse, groupId: String) {
|
||||||
|
monarchy.runTransactionSync { realm ->
|
||||||
|
val groupSummaryEntity = GroupSummaryEntity.where(realm, groupId).findFirst()
|
||||||
|
?: realm.createObject(groupId)
|
||||||
|
|
||||||
|
groupSummaryEntity.avatarUrl = groupSummary.profile?.avatarUrl ?: ""
|
||||||
|
val name = groupSummary.profile?.name
|
||||||
|
groupSummaryEntity.displayName = if (name.isNullOrEmpty()) groupId else name
|
||||||
|
groupSummaryEntity.shortDescription = groupSummary.profile?.shortDescription ?: ""
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package im.vector.matrix.android.internal.session.group
|
||||||
|
|
||||||
|
import im.vector.matrix.android.internal.network.NetworkConstants
|
||||||
|
import im.vector.matrix.android.internal.session.group.model.GroupSummaryResponse
|
||||||
|
import kotlinx.coroutines.Deferred
|
||||||
|
import retrofit2.Response
|
||||||
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.Path
|
||||||
|
|
||||||
|
interface GroupAPI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request a group summary
|
||||||
|
*
|
||||||
|
* @param groupId the group id
|
||||||
|
*/
|
||||||
|
@GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "groups/{groupId}/summary")
|
||||||
|
fun getSummary(@Path("groupId") groupId: String): Deferred<Response<GroupSummaryResponse>>
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package im.vector.matrix.android.internal.session.group
|
||||||
|
|
||||||
|
import im.vector.matrix.android.internal.session.DefaultSession
|
||||||
|
import org.koin.dsl.context.ModuleDefinition
|
||||||
|
import org.koin.dsl.module.Module
|
||||||
|
import org.koin.dsl.module.module
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
|
||||||
|
class GroupModule : Module {
|
||||||
|
|
||||||
|
override fun invoke(): ModuleDefinition = module(override = true) {
|
||||||
|
|
||||||
|
scope(DefaultSession.SCOPE) {
|
||||||
|
val retrofit: Retrofit = get()
|
||||||
|
retrofit.create(GroupAPI::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
scope(DefaultSession.SCOPE) {
|
||||||
|
GetGroupSummaryRequest(get(), get(), get())
|
||||||
|
}
|
||||||
|
|
||||||
|
}.invoke()
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package im.vector.matrix.android.internal.session.group
|
||||||
|
|
||||||
|
import android.arch.lifecycle.Observer
|
||||||
|
import com.zhuinden.monarchy.Monarchy
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.session.group.Group
|
||||||
|
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||||
|
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.group.model.GroupSummaryResponse
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
|
internal class GroupSummaryUpdater(private val monarchy: Monarchy,
|
||||||
|
private val getGroupSummaryRequest: GetGroupSummaryRequest
|
||||||
|
) : Observer<Monarchy.ManagedChangeSet<GroupEntity>> {
|
||||||
|
|
||||||
|
private var isStarted = AtomicBoolean(false)
|
||||||
|
private val liveResults = monarchy.findAllManagedWithChanges { GroupEntity.where(it) }
|
||||||
|
|
||||||
|
fun start() {
|
||||||
|
if (isStarted.compareAndSet(false, true)) {
|
||||||
|
liveResults.observeForever(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dispose() {
|
||||||
|
if (isStarted.compareAndSet(true, false)) {
|
||||||
|
liveResults.removeObserver(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PRIVATE
|
||||||
|
|
||||||
|
override fun onChanged(changeSet: Monarchy.ManagedChangeSet<GroupEntity>?) {
|
||||||
|
if (changeSet == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val groups = changeSet.realmResults.map { it.asDomain() }
|
||||||
|
val indexesToUpdate = changeSet.orderedCollectionChangeSet.changes + changeSet.orderedCollectionChangeSet.insertions
|
||||||
|
updateGroupList(groups, indexesToUpdate)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun updateGroupList(groups: List<Group>, indexes: IntArray) {
|
||||||
|
indexes.forEach {
|
||||||
|
val group = groups[it]
|
||||||
|
try {
|
||||||
|
updateGroup(group)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e(e, "An error occured when updating room summaries")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateGroup(group: Group?) {
|
||||||
|
if (group == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
getGroupSummaryRequest.execute(group.groupId, object : MatrixCallback<GroupSummaryResponse> {})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package im.vector.matrix.android.internal.session.group.model
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents a community profile in the server responses.
|
||||||
|
*/
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class GroupProfile(
|
||||||
|
|
||||||
|
@Json(name = "short_description") val shortDescription: String? = null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell whether the group is public.
|
||||||
|
*/
|
||||||
|
@Json(name = "is_public") val isPublic: Boolean? = null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL for the group's avatar. May be nil.
|
||||||
|
*/
|
||||||
|
@Json(name = "avatar_url") val avatarUrl: String? = null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The group's name.
|
||||||
|
*/
|
||||||
|
@Json(name = "name") val name: String? = null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The optional HTML formatted string used to described the group.
|
||||||
|
*/
|
||||||
|
@Json(name = "long_description") val longDescription: String? = null
|
||||||
|
)
|
@ -0,0 +1,30 @@
|
|||||||
|
package im.vector.matrix.android.internal.session.group.model
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents the summary of a community in the server response.
|
||||||
|
*/
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class GroupSummaryResponse(
|
||||||
|
/**
|
||||||
|
* The group profile.
|
||||||
|
*/
|
||||||
|
@Json(name = "profile") val profile: GroupProfile? = null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The group users.
|
||||||
|
*/
|
||||||
|
@Json(name = "users_section") val usersSection: GroupSummaryUsersSection? = null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current user status.
|
||||||
|
*/
|
||||||
|
@Json(name = "user") val user: GroupSummaryUser? = null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The rooms linked to the community.
|
||||||
|
*/
|
||||||
|
@Json(name = "rooms_section") val roomsSection: GroupSummaryRoomsSection? = null
|
||||||
|
)
|
@ -0,0 +1,16 @@
|
|||||||
|
package im.vector.matrix.android.internal.session.group.model
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents the community rooms in a group summary response.
|
||||||
|
*/
|
||||||
|
data class GroupSummaryRoomsSection(
|
||||||
|
|
||||||
|
@Json(name = "total_room_count_estimate") val totalRoomCountEstimate: Int? = null,
|
||||||
|
|
||||||
|
@Json(name = "rooms") val rooms: List<String> = emptyList()
|
||||||
|
|
||||||
|
// @TODO: Check the meaning and the usage of these categories. This dictionary is empty FTM.
|
||||||
|
//public Map<Object, Object> categories;
|
||||||
|
)
|
@ -0,0 +1,21 @@
|
|||||||
|
package im.vector.matrix.android.internal.session.group.model
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents the current user status in a group summary response.
|
||||||
|
*/
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class GroupSummaryUser(
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current user membership in this community.
|
||||||
|
*/
|
||||||
|
@Json(name = "membership") val membership: String? = null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell whether the user published this community on his profile.
|
||||||
|
*/
|
||||||
|
@Json(name = "is_publicised") val isPublicised: Boolean? = null
|
||||||
|
)
|
@ -0,0 +1,20 @@
|
|||||||
|
package im.vector.matrix.android.internal.session.group.model
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents the community members in a group summary response.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class GroupSummaryUsersSection(
|
||||||
|
|
||||||
|
@Json(name = "total_user_count_estimate") val totalUserCountEstimate: Int,
|
||||||
|
|
||||||
|
@Json(name = "users") val users: List<String> = emptyList()
|
||||||
|
|
||||||
|
// @TODO: Check the meaning and the usage of these roles. This dictionary is empty FTM.
|
||||||
|
//public Map<Object, Object> roles;
|
||||||
|
)
|
@ -55,7 +55,7 @@ class DefaultTimelineHolder(private val roomId: String,
|
|||||||
.setEnablePlaceholders(false)
|
.setEnablePlaceholders(false)
|
||||||
.setPageSize(PAGE_SIZE)
|
.setPageSize(PAGE_SIZE)
|
||||||
.setInitialLoadSizeHint(PAGE_SIZE)
|
.setInitialLoadSizeHint(PAGE_SIZE)
|
||||||
.setPrefetchDistance(10)
|
.setPrefetchDistance(20)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val livePagedListBuilder = LivePagedListBuilder(domainSourceFactory, pagedListConfig).setBoundaryCallback(boundaryCallback)
|
val livePagedListBuilder = LivePagedListBuilder(domainSourceFactory, pagedListConfig).setBoundaryCallback(boundaryCallback)
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
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.internal.database.model.GroupEntity
|
||||||
|
import im.vector.matrix.android.internal.database.query.where
|
||||||
|
import im.vector.matrix.android.internal.legacy.rest.model.group.GroupsSyncResponse
|
||||||
|
import im.vector.matrix.android.internal.legacy.rest.model.group.InvitedGroupSync
|
||||||
|
import io.realm.Realm
|
||||||
|
|
||||||
|
|
||||||
|
internal class GroupSyncHandler(private val monarchy: Monarchy) {
|
||||||
|
|
||||||
|
sealed class HandlingStrategy {
|
||||||
|
data class JOINED(val data: Map<String, Any>) : HandlingStrategy()
|
||||||
|
data class INVITED(val data: Map<String, InvitedGroupSync>) : HandlingStrategy()
|
||||||
|
data class LEFT(val data: Map<String, Any>) : HandlingStrategy()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handle(roomsSyncResponse: GroupsSyncResponse) {
|
||||||
|
monarchy.runTransactionSync { realm ->
|
||||||
|
handleGroupSync(realm, GroupSyncHandler.HandlingStrategy.JOINED(roomsSyncResponse.join))
|
||||||
|
handleGroupSync(realm, GroupSyncHandler.HandlingStrategy.INVITED(roomsSyncResponse.invite))
|
||||||
|
handleGroupSync(realm, GroupSyncHandler.HandlingStrategy.LEFT(roomsSyncResponse.leave))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PRIVATE METHODS *****************************************************************************
|
||||||
|
|
||||||
|
private fun handleGroupSync(realm: Realm, handlingStrategy: HandlingStrategy) {
|
||||||
|
val groups = when (handlingStrategy) {
|
||||||
|
is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedGroup(realm, it.key) }
|
||||||
|
is HandlingStrategy.INVITED -> handlingStrategy.data.map { handleInvitedGroup(realm, it.key) }
|
||||||
|
is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftGroup(realm, it.key) }
|
||||||
|
}
|
||||||
|
realm.insertOrUpdate(groups)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleJoinedGroup(realm: Realm,
|
||||||
|
groupId: String): GroupEntity {
|
||||||
|
|
||||||
|
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
|
||||||
|
groupEntity.membership = MyMembership.JOINED
|
||||||
|
return groupEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleInvitedGroup(realm: Realm,
|
||||||
|
groupId: String): GroupEntity {
|
||||||
|
|
||||||
|
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
|
||||||
|
groupEntity.membership = MyMembership.INVITED
|
||||||
|
return groupEntity
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : handle it
|
||||||
|
private fun handleLeftGroup(realm: Realm,
|
||||||
|
groupId: String): GroupEntity {
|
||||||
|
|
||||||
|
val groupEntity = GroupEntity.where(realm, groupId).findFirst() ?: GroupEntity(groupId)
|
||||||
|
groupEntity.membership = MyMembership.LEFT
|
||||||
|
return groupEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -29,12 +29,16 @@ class SyncModule : Module {
|
|||||||
RoomSyncHandler(get(), get(), get())
|
RoomSyncHandler(get(), get(), get())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope(DefaultSession.SCOPE) {
|
||||||
|
GroupSyncHandler(get())
|
||||||
|
}
|
||||||
|
|
||||||
scope(DefaultSession.SCOPE) {
|
scope(DefaultSession.SCOPE) {
|
||||||
UserAccountDataSyncHandler(get())
|
UserAccountDataSyncHandler(get())
|
||||||
}
|
}
|
||||||
|
|
||||||
scope(DefaultSession.SCOPE) {
|
scope(DefaultSession.SCOPE) {
|
||||||
SyncResponseHandler(get(), get())
|
SyncResponseHandler(get(), get(), get())
|
||||||
}
|
}
|
||||||
|
|
||||||
scope(DefaultSession.SCOPE) {
|
scope(DefaultSession.SCOPE) {
|
||||||
|
@ -4,7 +4,8 @@ import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
|||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
internal class SyncResponseHandler(private val roomSyncHandler: RoomSyncHandler,
|
internal class SyncResponseHandler(private val roomSyncHandler: RoomSyncHandler,
|
||||||
private val userAccountDataSyncHandler: UserAccountDataSyncHandler) {
|
private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
|
||||||
|
private val groupSyncHandler: GroupSyncHandler) {
|
||||||
|
|
||||||
fun handleResponse(syncResponse: SyncResponse?, fromToken: String?, isCatchingUp: Boolean) {
|
fun handleResponse(syncResponse: SyncResponse?, fromToken: String?, isCatchingUp: Boolean) {
|
||||||
if (syncResponse == null) {
|
if (syncResponse == null) {
|
||||||
@ -14,6 +15,9 @@ internal class SyncResponseHandler(private val roomSyncHandler: RoomSyncHandler,
|
|||||||
if (syncResponse.rooms != null) {
|
if (syncResponse.rooms != null) {
|
||||||
roomSyncHandler.handle(syncResponse.rooms)
|
roomSyncHandler.handle(syncResponse.rooms)
|
||||||
}
|
}
|
||||||
|
if (syncResponse.groups != null) {
|
||||||
|
groupSyncHandler.handle(syncResponse.groups)
|
||||||
|
}
|
||||||
if (syncResponse.accountData != null) {
|
if (syncResponse.accountData != null) {
|
||||||
userAccountDataSyncHandler.handle(syncResponse.accountData)
|
userAccountDataSyncHandler.handle(syncResponse.accountData)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user