From bc8055c3cd7351431a6bead015fb89ca30ce6c38 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 30 Oct 2018 18:22:29 +0100 Subject: [PATCH] Room list : handle direct rooms --- .idea/caches/build_file_checksums.ser | Bin 661 -> 659 bytes .../home/room/list/RoomCategoryItem.kt | 20 +- .../home/room/list/RoomSummaryController.kt | 38 +++- .../main/res/layout/item_room_category.xml | 1 + .../api/session/room/model/RoomSummary.kt | 3 +- .../database/mapper/RoomSummaryMapper.kt | 16 +- .../database/model/RoomSummaryEntity.kt | 2 +- .../android/internal/di/MoshiProvider.kt | 7 + .../parsing/RuntimeJsonAdapterFactory.java | 177 ++++++++++++++++++ .../internal/session/room/DefaultRoom.kt | 3 +- .../session/room/DefaultRoomService.kt | 3 +- .../internal/session/sync/RoomSyncHandler.kt | 27 +-- .../internal/session/sync/SyncModule.kt | 6 +- .../session/sync/SyncResponseHandler.kt | 13 +- .../sync/UserAccountDataSyncHandler.kt | 37 ++++ .../session/sync/model/SyncResponse.kt | 2 +- .../session/sync/model/UserAccountData.kt | 11 ++ .../model/UserAccountDataDirectMessages.kt | 10 + .../sync/model/UserAccountDataFallback.kt | 9 + .../session/sync/model/UserAccountDataSync.kt | 9 + 20 files changed, 351 insertions(+), 43 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/parsing/RuntimeJsonAdapterFactory.java create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountData.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountDataDirectMessages.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountDataFallback.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountDataSync.kt diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 5dd499e43bf8fe0023ecd7d218c1e4b5cd1cff9a..27ab41a0cfd8f56b925fa5621d37b8ec23babaef 100644 GIT binary patch delta 65 zcmV-H0KWf~1(OAkm;}X%yr+?zhz=(&RdZ!>b1!FMZf0^}lLZ1clOzGZ6Mxpspp5P$_h?8gmzapJ8-4f!BFNqE8lw$EA2~KnXDKAxXWpZ;b ZW^!R}V{d75lQID|0TGis0UMK50zSAB87cq( diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomCategoryItem.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomCategoryItem.kt index dd9b6716..549c1c52 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomCategoryItem.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomCategoryItem.kt @@ -1,16 +1,30 @@ package im.vector.riotredesign.features.home.room.list -import android.support.annotation.DrawableRes +import android.support.v4.content.ContextCompat +import android.view.ViewGroup +import android.widget.TextView import im.vector.riotredesign.R import im.vector.riotredesign.core.epoxy.KotlinModel data class RoomCategoryItem( val title: CharSequence, - @DrawableRes val expandDrawable: Int, + val isExpanded: Boolean, val listener: (() -> Unit)? = null ) : KotlinModel(R.layout.item_room_category) { - override fun bind() { + private val titleView by bind(R.id.roomCategoryTitleView) + private val rootView by bind(R.id.roomCategoryRootView) + private val tintColor by lazy { + ContextCompat.getColor(rootView.context, R.color.bluey_grey_two) + } + + override fun bind() { + val expandedArrowDrawableRes = if (isExpanded) R.drawable.ic_expand_more_white else R.drawable.ic_expand_less_white + val expandedArrowDrawable = ContextCompat.getDrawable(rootView.context, expandedArrowDrawableRes) + expandedArrowDrawable?.setTint(tintColor) + titleView.setCompoundDrawablesWithIntrinsicBounds(expandedArrowDrawable, null, null, null) + titleView.text = title + rootView.setOnClickListener { listener?.invoke() } } } diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt index b30191eb..7ff52eb2 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/room/list/RoomSummaryController.kt @@ -10,15 +10,49 @@ class RoomSummaryController(private val context: Context, private val callback: Callback? = null ) : Typed2EpoxyController, RoomSummary>() { + + private var directRoomsExpanded = true + private var groupRoomsExpanded = true + override fun buildModels(summaries: List?, selected: RoomSummary?) { + + val directRooms = summaries?.filter { it.isDirect } ?: emptyList() + val groupRooms = summaries?.filter { !it.isDirect } ?: emptyList() + RoomCategoryItem( title = "DIRECT MESSAGES", - expandDrawable = R.drawable.ic_expand_more_white + isExpanded = directRoomsExpanded, + listener = { + directRoomsExpanded = !directRoomsExpanded + setData(summaries, selected) + } ) .id("direct_messages") .addTo(this) - summaries?.forEach { + if (directRoomsExpanded) { + buildRoomModels(directRooms, selected) + } + + RoomCategoryItem( + title = "GROUPS", + isExpanded = groupRoomsExpanded, + listener = { + groupRoomsExpanded = !groupRoomsExpanded + setData(summaries, selected) + } + ) + .id("group_messages") + .addTo(this) + + if (groupRoomsExpanded) { + buildRoomModels(groupRooms, selected) + } + + } + + private fun buildRoomModels(summaries: List, selected: RoomSummary?) { + summaries.forEach { val roomSummaryViewHelper = RoomSummaryViewHelper(it) RoomSummaryItem( title = it.displayName, diff --git a/app/src/main/res/layout/item_room_category.xml b/app/src/main/res/layout/item_room_category.xml index 480b7837..587ae7d9 100644 --- a/app/src/main/res/layout/item_room_category.xml +++ b/app/src/main/res/layout/item_room_category.xml @@ -6,6 +6,7 @@ android:layout_height="wrap_content" android:clickable="true" android:focusable="true" + android:id="@+id/roomCategoryRootView" android:gravity="center_vertical" android:minHeight="24dp" android:padding="16dp" diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt index 477a391a..3d656ef1 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomSummary.kt @@ -4,5 +4,6 @@ data class RoomSummary( val roomId: String, val displayName: String = "", val topic: String = "", - val avatarUrl: String = "" + val avatarUrl: String = "", + val isDirect: Boolean ) \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt index 989b074a..c5a3547e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt @@ -11,24 +11,12 @@ object RoomSummaryMapper { roomSummaryEntity.roomId, roomSummaryEntity.displayName ?: "", roomSummaryEntity.topic ?: "", - roomSummaryEntity.avatarUrl ?: "" - ) - } - - internal fun map(roomSummary: RoomSummary): RoomSummaryEntity { - return RoomSummaryEntity( - roomSummary.roomId, - roomSummary.displayName, - roomSummary.topic, - roomSummary.avatarUrl + roomSummaryEntity.avatarUrl ?: "", + roomSummaryEntity.isDirect ) } } fun RoomSummaryEntity.asDomain(): RoomSummary { return RoomSummaryMapper.map(this) -} - -fun RoomSummaryEntity.asEntity(): RoomSummary { - return RoomSummaryMapper.map(this) } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt index 74264fd7..f5069b9c 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/RoomSummaryEntity.kt @@ -4,7 +4,6 @@ import io.realm.RealmList import io.realm.RealmObject import io.realm.annotations.PrimaryKey -// TODO to be completed open class RoomSummaryEntity(@PrimaryKey var roomId: String = "", var displayName: String? = "", var avatarUrl: String? = "", @@ -13,6 +12,7 @@ open class RoomSummaryEntity(@PrimaryKey var roomId: String = "", var heroes: RealmList = RealmList(), var joinedMembersCount: Int? = 0, var invitedMembersCount: Int? = 0, + var isDirect: Boolean = false, var isLatestSelected: Boolean = false ) : RealmObject() { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt index fdd0ed26..1cabe215 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt @@ -1,12 +1,19 @@ package im.vector.matrix.android.internal.di import com.squareup.moshi.Moshi +import im.vector.matrix.android.internal.network.parsing.RuntimeJsonAdapterFactory import im.vector.matrix.android.internal.network.parsing.UriMoshiAdapter +import im.vector.matrix.android.internal.session.sync.model.UserAccountData +import im.vector.matrix.android.internal.session.sync.model.UserAccountDataDirectMessages +import im.vector.matrix.android.internal.session.sync.model.UserAccountDataFallback object MoshiProvider { private val moshi: Moshi = Moshi.Builder() .add(UriMoshiAdapter()) + .add(RuntimeJsonAdapterFactory.of(UserAccountData::class.java, "type", UserAccountDataFallback::class.java) + .registerSubtype(UserAccountDataDirectMessages::class.java, UserAccountData.TYPE_DIRECT_MESSAGES) + ) .build() fun providesMoshi(): Moshi { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/parsing/RuntimeJsonAdapterFactory.java b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/parsing/RuntimeJsonAdapterFactory.java new file mode 100644 index 00000000..369efdde --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/network/parsing/RuntimeJsonAdapterFactory.java @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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.network.parsing; + +import com.squareup.moshi.JsonAdapter; +import com.squareup.moshi.JsonDataException; +import com.squareup.moshi.JsonReader; +import com.squareup.moshi.JsonWriter; +import com.squareup.moshi.Moshi; +import com.squareup.moshi.Types; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import javax.annotation.CheckReturnValue; + +/** + * A JsonAdapter factory for polymorphic types. This is useful when the type is not known before + * decoding the JSON. This factory's adapters expect JSON in the format of a JSON object with a + * key whose value is a label that determines the type to which to map the JSON object. + */ +public final class RuntimeJsonAdapterFactory implements JsonAdapter.Factory { + final Class baseType; + final String labelKey; + final Class fallbackType; + final Map labelToType = new LinkedHashMap<>(); + + /** + * @param baseType The base type for which this factory will create adapters. Cannot be Object. + * @param labelKey The key in the JSON object whose value determines the type to which to map the + * JSON object. + */ + @CheckReturnValue + public static RuntimeJsonAdapterFactory of(Class baseType, String labelKey, Class fallbackType) { + if (baseType == null) throw new NullPointerException("baseType == null"); + if (labelKey == null) throw new NullPointerException("labelKey == null"); + if (baseType == Object.class) { + throw new IllegalArgumentException( + "The base type must not be Object. Consider using a marker interface."); + } + return new RuntimeJsonAdapterFactory<>(baseType, labelKey, fallbackType); + } + + RuntimeJsonAdapterFactory(Class baseType, String labelKey, Class fallbackType) { + this.baseType = baseType; + this.labelKey = labelKey; + this.fallbackType = fallbackType; + } + + /** + * Register the subtype that can be created based on the label. When an unknown type is found + * during encoding an {@linkplain IllegalArgumentException} will be thrown. When an unknown label + * is found during decoding a {@linkplain JsonDataException} will be thrown. + */ + public RuntimeJsonAdapterFactory registerSubtype(Class subtype, String label) { + if (subtype == null) throw new NullPointerException("subtype == null"); + if (label == null) throw new NullPointerException("label == null"); + if (labelToType.containsKey(label) || labelToType.containsValue(subtype)) { + throw new IllegalArgumentException("Subtypes and labels must be unique."); + } + labelToType.put(label, subtype); + return this; + } + + @Override + public JsonAdapter create(Type type, Set annotations, Moshi moshi) { + if (Types.getRawType(type) != baseType || !annotations.isEmpty()) { + return null; + } + int size = labelToType.size(); + Map> labelToAdapter = new LinkedHashMap<>(size); + Map typeToLabel = new LinkedHashMap<>(size); + for (Map.Entry entry : labelToType.entrySet()) { + String label = entry.getKey(); + Type typeValue = entry.getValue(); + typeToLabel.put(typeValue, label); + labelToAdapter.put(label, moshi.adapter(typeValue)); + } + + final JsonAdapter fallbackAdapter = moshi.adapter(fallbackType); + JsonAdapter objectJsonAdapter = moshi.adapter(Object.class); + + return new RuntimeJsonAdapter(labelKey, labelToAdapter, typeToLabel, + objectJsonAdapter, fallbackAdapter).nullSafe(); + } + + static final class RuntimeJsonAdapter extends JsonAdapter { + final String labelKey; + final Map> labelToAdapter; + final Map typeToLabel; + final JsonAdapter objectJsonAdapter; + final JsonAdapter fallbackAdapter; + + RuntimeJsonAdapter(String labelKey, Map> labelToAdapter, + Map typeToLabel, JsonAdapter objectJsonAdapter, + JsonAdapter fallbackAdapter) { + this.labelKey = labelKey; + this.labelToAdapter = labelToAdapter; + this.typeToLabel = typeToLabel; + this.objectJsonAdapter = objectJsonAdapter; + this.fallbackAdapter = fallbackAdapter; + } + + @Override + public Object fromJson(JsonReader reader) throws IOException { + JsonReader.Token peekedToken = reader.peek(); + if (peekedToken != JsonReader.Token.BEGIN_OBJECT) { + throw new JsonDataException("Expected BEGIN_OBJECT but was " + peekedToken + + " at path " + reader.getPath()); + } + Object jsonValue = reader.readJsonValue(); + Map jsonObject = (Map) jsonValue; + Object label = jsonObject.get(labelKey); + if (label == null) { + throw new JsonDataException("Missing label for " + labelKey); + } + if (!(label instanceof String)) { + throw new JsonDataException("Label for '" + + labelKey + + "' must be a string but was " + + label + + ", a " + + label.getClass()); + } + JsonAdapter adapter = labelToAdapter.get(label); + if (adapter == null) { + return fallbackAdapter.fromJsonValue(jsonValue); + } + return adapter.fromJsonValue(jsonValue); + } + + @Override + public void toJson(JsonWriter writer, Object value) throws IOException { + Class type = value.getClass(); + String label = typeToLabel.get(type); + if (label == null) { + throw new IllegalArgumentException("Expected one of " + + typeToLabel.keySet() + + " but found " + + value + + ", a " + + value.getClass() + + ". Register this subtype."); + } + JsonAdapter adapter = labelToAdapter.get(label); + Map jsonValue = (Map) adapter.toJsonValue(value); + + Map valueWithLabel = new LinkedHashMap<>(1 + jsonValue.size()); + valueWithLabel.put(labelKey, label); + valueWithLabel.putAll(jsonValue); + objectJsonAdapter.toJson(writer, valueWithLabel); + } + + @Override + public String toString() { + return "RuntimeJsonAdapter(" + labelKey + ")"; + } + } +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt index 97d860ad..338f4752 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt @@ -15,6 +15,7 @@ import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntity +import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.session.room.members.LoadRoomMembersRequest import im.vector.matrix.android.internal.session.sync.SyncTokenStore @@ -36,7 +37,7 @@ data class DefaultRoom( override val roomSummary: LiveData by lazy { val liveData = monarchy .findAllMappedWithChanges( - { realm -> RoomSummaryEntity.where(realm, roomId) }, + { realm -> RoomSummaryEntity.where(realm, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) }, { from -> from.asDomain() }) Transformations.map(liveData) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt index 39e30a5f..806807c6 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt @@ -8,6 +8,7 @@ import im.vector.matrix.android.api.session.room.model.RoomSummary import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntity +import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields import im.vector.matrix.android.internal.database.query.lastSelected import im.vector.matrix.android.internal.database.query.where @@ -38,7 +39,7 @@ class DefaultRoomService(private val monarchy: Monarchy) : RoomService { override fun liveRoomSummaries(): LiveData> { return monarchy.findAllMappedWithChanges( - { realm -> RoomSummaryEntity.where(realm) }, + { realm -> RoomSummaryEntity.where(realm).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) }, { it.asDomain() } ) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt index b6fcde04..5499fbdc 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt @@ -15,6 +15,7 @@ import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync import im.vector.matrix.android.internal.session.sync.model.RoomSync import im.vector.matrix.android.internal.session.sync.model.RoomSyncEphemeral import im.vector.matrix.android.internal.session.sync.model.RoomSyncSummary +import im.vector.matrix.android.internal.session.sync.model.RoomsSyncResponse import io.realm.Realm import io.realm.kotlin.createObject @@ -29,7 +30,21 @@ internal class RoomSyncHandler(private val monarchy: Monarchy, data class LEFT(val data: Map) : HandlingStrategy() } - fun handleRoomSync(handlingStrategy: HandlingStrategy) { + fun handle(roomsSyncResponse: RoomsSyncResponse) { + handleRoomSync(RoomSyncHandler.HandlingStrategy.JOINED(roomsSyncResponse.join)) + handleRoomSync(RoomSyncHandler.HandlingStrategy.INVITED(roomsSyncResponse.invite)) + handleRoomSync(RoomSyncHandler.HandlingStrategy.LEFT(roomsSyncResponse.leave)) + + monarchy.runTransactionSync { realm -> + roomsSyncResponse.join.forEach { (roomId, roomSync) -> + handleEphemeral(realm, roomId, roomSync.ephemeral) + } + } + } + + // PRIVATE METHODS ***************************************************************************** + + private fun handleRoomSync(handlingStrategy: HandlingStrategy) { monarchy.runTransactionSync { realm -> val rooms = when (handlingStrategy) { is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) } @@ -38,18 +53,8 @@ internal class RoomSyncHandler(private val monarchy: Monarchy, } realm.insertOrUpdate(rooms) } - - if (handlingStrategy is HandlingStrategy.JOINED) { - monarchy.runTransactionSync { realm -> - handlingStrategy.data.forEach { (roomId, roomSync) -> - handleEphemeral(realm, roomId, roomSync.ephemeral) - } - } - } } - // PRIVATE METHODS ***************************************************************************** - private fun handleJoinedRoom(realm: Realm, roomId: String, roomSync: RoomSync): RoomEntity { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt index d514331d..204bb8d0 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncModule.kt @@ -30,7 +30,11 @@ class SyncModule : Module { } scope(DefaultSession.SCOPE) { - SyncResponseHandler(get()) + UserAccountDataSyncHandler(get()) + } + + scope(DefaultSession.SCOPE) { + SyncResponseHandler(get(), get()) } scope(DefaultSession.SCOPE) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt index 75874f7a..c86e8b6e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/SyncResponseHandler.kt @@ -3,21 +3,20 @@ package im.vector.matrix.android.internal.session.sync import im.vector.matrix.android.internal.session.sync.model.SyncResponse import timber.log.Timber -internal class SyncResponseHandler(private val roomSyncHandler: RoomSyncHandler) { +internal class SyncResponseHandler(private val roomSyncHandler: RoomSyncHandler, + private val userAccountDataSyncHandler: UserAccountDataSyncHandler) { fun handleResponse(syncResponse: SyncResponse?, fromToken: String?, isCatchingUp: Boolean) { if (syncResponse == null) { return } Timber.v("Handle sync response") - if (syncResponse.rooms != null) { - // joined rooms events - roomSyncHandler.handleRoomSync(RoomSyncHandler.HandlingStrategy.JOINED(syncResponse.rooms.join)) - roomSyncHandler.handleRoomSync(RoomSyncHandler.HandlingStrategy.INVITED(syncResponse.rooms.invite)) - roomSyncHandler.handleRoomSync(RoomSyncHandler.HandlingStrategy.LEFT(syncResponse.rooms.leave)) + roomSyncHandler.handle(syncResponse.rooms) + } + if (syncResponse.accountData != null) { + userAccountDataSyncHandler.handle(syncResponse.accountData) } - } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt new file mode 100644 index 00000000..5aa965fc --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/UserAccountDataSyncHandler.kt @@ -0,0 +1,37 @@ +package im.vector.matrix.android.internal.session.sync + +import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.internal.database.model.RoomSummaryEntity +import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields +import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.session.sync.model.UserAccountDataDirectMessages +import im.vector.matrix.android.internal.session.sync.model.UserAccountDataSync + +class UserAccountDataSyncHandler(private val monarchy: Monarchy) { + + fun handle(accountData: UserAccountDataSync) { + accountData.list.forEach { + when (it) { + is UserAccountDataDirectMessages -> handleDirectChatRooms(it) + else -> return@forEach + } + } + } + + private fun handleDirectChatRooms(directMessages: UserAccountDataDirectMessages) { + val newDirectRoomIds = directMessages.content.values.flatten() + monarchy.runTransactionSync { realm -> + + val oldDirectRooms = RoomSummaryEntity.where(realm).equalTo(RoomSummaryEntityFields.IS_DIRECT, true).findAll() + oldDirectRooms.forEach { it.isDirect = false } + + newDirectRoomIds.forEach { roomId -> + val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst() + if (roomSummaryEntity != null) { + roomSummaryEntity.isDirect = true + realm.insertOrUpdate(roomSummaryEntity) + } + } + } + } +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/SyncResponse.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/SyncResponse.kt index 60ac12e9..3736e7ad 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/SyncResponse.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/SyncResponse.kt @@ -10,7 +10,7 @@ data class SyncResponse( /** * The user private data. */ - @Json(name = "account_data") val accountData: Map? = emptyMap(), + @Json(name = "account_data") val accountData: UserAccountDataSync? = null, /** * The opaque token for the end. diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountData.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountData.kt new file mode 100644 index 00000000..3af72b84 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountData.kt @@ -0,0 +1,11 @@ +package im.vector.matrix.android.internal.session.sync.model + +interface UserAccountData { + + companion object { + const val TYPE_IGNORED_USER_LIST = "m.ignored_user_list" + const val TYPE_DIRECT_MESSAGES = "m.direct" + const val TYPE_PREVIEW_URLS = "org.matrix.preview_urls" + const val TYPE_WIDGETS = "m.widgets" + } +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountDataDirectMessages.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountDataDirectMessages.kt new file mode 100644 index 00000000..b6d09ac3 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountDataDirectMessages.kt @@ -0,0 +1,10 @@ +package im.vector.matrix.android.internal.session.sync.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class UserAccountDataDirectMessages( + @Json(name = "content") val content: Map> +) : UserAccountData + diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountDataFallback.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountDataFallback.kt new file mode 100644 index 00000000..4cb45373 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountDataFallback.kt @@ -0,0 +1,9 @@ +package im.vector.matrix.android.internal.session.sync.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class UserAccountDataFallback( + @Json(name = "content") val content: Map +) : UserAccountData diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountDataSync.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountDataSync.kt new file mode 100644 index 00000000..ef28238b --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/model/UserAccountDataSync.kt @@ -0,0 +1,9 @@ +package im.vector.matrix.android.internal.session.sync.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class UserAccountDataSync( + @Json(name = "events") val list: List = emptyList() +) \ No newline at end of file