Merge pull request #7424 from vector-im/feature/eric/msc3773
Implements MSC3773 (Thread Notifications)
This commit is contained in:
		
						commit
						29d3856ef2
					
				
							
								
								
									
										1
									
								
								changelog.d/7424.misc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								changelog.d/7424.misc
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					Gets thread notifications from sync response
 | 
				
			||||||
@ -97,6 +97,14 @@ data class RoomSummary(
 | 
				
			|||||||
         * Number of unread and highlighted message in this room.
 | 
					         * Number of unread and highlighted message in this room.
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        val highlightCount: Int = 0,
 | 
					        val highlightCount: Int = 0,
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Number of threads with unread messages in this room.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        val threadNotificationCount: Int = 0,
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Number of threads with highlighted messages in this room.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        val threadHighlightCount: Int = 0,
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * True if this room has unread messages.
 | 
					         * True if this room has unread messages.
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
 | 
				
			|||||||
@ -47,6 +47,11 @@ data class RoomSync(
 | 
				
			|||||||
         */
 | 
					         */
 | 
				
			||||||
        @Json(name = "unread_notifications") val unreadNotifications: RoomSyncUnreadNotifications? = null,
 | 
					        @Json(name = "unread_notifications") val unreadNotifications: RoomSyncUnreadNotifications? = null,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * The count of threads with unread notifications (not the total # of notifications in all threads).
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        @Json(name = "unread_thread_notifications") val unreadThreadNotifications: Map<String, RoomSyncUnreadThreadNotifications>? = null,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * The room summary.
 | 
					         * The room summary.
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2022 The Matrix.org Foundation C.I.C.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package org.matrix.android.sdk.api.session.sync.model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.squareup.moshi.Json
 | 
				
			||||||
 | 
					import com.squareup.moshi.JsonClass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@JsonClass(generateAdapter = true)
 | 
				
			||||||
 | 
					data class RoomSyncUnreadThreadNotifications(
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * The number of threads with unread messages that match the push notification rules.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        @Json(name = "notification_count") val notificationCount: Int? = null,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * The number of threads with highlighted unread messages (subset of notifications).
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        @Json(name = "highlight_count") val highlightCount: Int? = null
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@ -57,6 +57,7 @@ import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo037
 | 
				
			|||||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo038
 | 
					import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo038
 | 
				
			||||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo039
 | 
					import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo039
 | 
				
			||||||
import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo040
 | 
					import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo040
 | 
				
			||||||
 | 
					import org.matrix.android.sdk.internal.database.migration.MigrateSessionTo041
 | 
				
			||||||
import org.matrix.android.sdk.internal.util.Normalizer
 | 
					import org.matrix.android.sdk.internal.util.Normalizer
 | 
				
			||||||
import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
 | 
					import org.matrix.android.sdk.internal.util.database.MatrixRealmMigration
 | 
				
			||||||
import javax.inject.Inject
 | 
					import javax.inject.Inject
 | 
				
			||||||
@ -65,7 +66,7 @@ internal class RealmSessionStoreMigration @Inject constructor(
 | 
				
			|||||||
        private val normalizer: Normalizer
 | 
					        private val normalizer: Normalizer
 | 
				
			||||||
) : MatrixRealmMigration(
 | 
					) : MatrixRealmMigration(
 | 
				
			||||||
        dbName = "Session",
 | 
					        dbName = "Session",
 | 
				
			||||||
        schemaVersion = 40L,
 | 
					        schemaVersion = 41L,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Forces all RealmSessionStoreMigration instances to be equal.
 | 
					     * Forces all RealmSessionStoreMigration instances to be equal.
 | 
				
			||||||
@ -115,5 +116,6 @@ internal class RealmSessionStoreMigration @Inject constructor(
 | 
				
			|||||||
        if (oldVersion < 38) MigrateSessionTo038(realm).perform()
 | 
					        if (oldVersion < 38) MigrateSessionTo038(realm).perform()
 | 
				
			||||||
        if (oldVersion < 39) MigrateSessionTo039(realm).perform()
 | 
					        if (oldVersion < 39) MigrateSessionTo039(realm).perform()
 | 
				
			||||||
        if (oldVersion < 40) MigrateSessionTo040(realm).perform()
 | 
					        if (oldVersion < 40) MigrateSessionTo040(realm).perform()
 | 
				
			||||||
 | 
					        if (oldVersion < 41) MigrateSessionTo041(realm).perform()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -61,6 +61,8 @@ internal class RoomSummaryMapper @Inject constructor(
 | 
				
			|||||||
                otherMemberIds = roomSummaryEntity.otherMemberIds.toList(),
 | 
					                otherMemberIds = roomSummaryEntity.otherMemberIds.toList(),
 | 
				
			||||||
                highlightCount = roomSummaryEntity.highlightCount,
 | 
					                highlightCount = roomSummaryEntity.highlightCount,
 | 
				
			||||||
                notificationCount = roomSummaryEntity.notificationCount,
 | 
					                notificationCount = roomSummaryEntity.notificationCount,
 | 
				
			||||||
 | 
					                threadHighlightCount = roomSummaryEntity.threadHighlightCount,
 | 
				
			||||||
 | 
					                threadNotificationCount = roomSummaryEntity.threadNotificationCount,
 | 
				
			||||||
                hasUnreadMessages = roomSummaryEntity.hasUnreadMessages,
 | 
					                hasUnreadMessages = roomSummaryEntity.hasUnreadMessages,
 | 
				
			||||||
                tags = tags,
 | 
					                tags = tags,
 | 
				
			||||||
                typingUsers = typingUsers,
 | 
					                typingUsers = typingUsers,
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2022 The Matrix.org Foundation C.I.C.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package org.matrix.android.sdk.internal.database.migration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import io.realm.DynamicRealm
 | 
				
			||||||
 | 
					import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields
 | 
				
			||||||
 | 
					import org.matrix.android.sdk.internal.util.database.RealmMigrator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					internal class MigrateSessionTo041(realm: DynamicRealm) : RealmMigrator(realm, 41) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun doMigrate(realm: DynamicRealm) {
 | 
				
			||||||
 | 
					        realm.schema.get("RoomSummaryEntity")
 | 
				
			||||||
 | 
					                ?.addField(RoomSummaryEntityFields.THREAD_HIGHLIGHT_COUNT, Int::class.java)
 | 
				
			||||||
 | 
					                ?.addField(RoomSummaryEntityFields.THREAD_NOTIFICATION_COUNT, Int::class.java)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -115,6 +115,16 @@ internal open class RoomSummaryEntity(
 | 
				
			|||||||
            if (value != field) field = value
 | 
					            if (value != field) field = value
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var threadNotificationCount: Int = 0
 | 
				
			||||||
 | 
					        set(value) {
 | 
				
			||||||
 | 
					            if (value != field) field = value
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var threadHighlightCount: Int = 0
 | 
				
			||||||
 | 
					        set(value) {
 | 
				
			||||||
 | 
					            if (value != field) field = value
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var readMarkerId: String? = null
 | 
					    var readMarkerId: String? = null
 | 
				
			||||||
        set(value) {
 | 
					        set(value) {
 | 
				
			||||||
            if (value != field) field = value
 | 
					            if (value != field) field = value
 | 
				
			||||||
 | 
				
			|||||||
@ -110,8 +110,7 @@ internal fun RealmQuery<TimelineEventEntity>.filterEvents(filters: TimelineEvent
 | 
				
			|||||||
        endGroup()
 | 
					        endGroup()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (filters.filterUseless) {
 | 
					    if (filters.filterUseless) {
 | 
				
			||||||
        not()
 | 
					        not().equalTo(TimelineEventEntityFields.ROOT.IS_USELESS, true)
 | 
				
			||||||
                .equalTo(TimelineEventEntityFields.ROOT.IS_USELESS, true)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (filters.filterEdits) {
 | 
					    if (filters.filterEdits) {
 | 
				
			||||||
        not().like(TimelineEventEntityFields.ROOT.CONTENT, TimelineEventFilter.Content.EDIT)
 | 
					        not().like(TimelineEventEntityFields.ROOT.CONTENT, TimelineEventFilter.Content.EDIT)
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,7 @@ internal object FilterFactory {
 | 
				
			|||||||
                limit = numberOfEvents,
 | 
					                limit = numberOfEvents,
 | 
				
			||||||
//                senders = listOf(userId),
 | 
					//                senders = listOf(userId),
 | 
				
			||||||
//                relationSenders = userId?.let { listOf(it) },
 | 
					//                relationSenders = userId?.let { listOf(it) },
 | 
				
			||||||
                relationTypes = listOf(RelationType.THREAD)
 | 
					                relationTypes = listOf(RelationType.THREAD),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -37,7 +37,7 @@ internal object FilterFactory {
 | 
				
			|||||||
                limit = numberOfEvents,
 | 
					                limit = numberOfEvents,
 | 
				
			||||||
                containsUrl = true,
 | 
					                containsUrl = true,
 | 
				
			||||||
                types = listOf(EventType.MESSAGE),
 | 
					                types = listOf(EventType.MESSAGE),
 | 
				
			||||||
                lazyLoadMembers = true
 | 
					                lazyLoadMembers = true,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -55,30 +55,23 @@ internal object FilterFactory {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun createDefaultRoomFilter(): RoomEventFilter {
 | 
					    fun createDefaultRoomFilter(): RoomEventFilter {
 | 
				
			||||||
        return RoomEventFilter(
 | 
					        return RoomEventFilter(lazyLoadMembers = true)
 | 
				
			||||||
                lazyLoadMembers = true
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun createElementRoomFilter(): RoomEventFilter {
 | 
					    fun createElementRoomFilter(): RoomEventFilter {
 | 
				
			||||||
        return RoomEventFilter(
 | 
					        return RoomEventFilter(
 | 
				
			||||||
                lazyLoadMembers = true
 | 
					                lazyLoadMembers = true,
 | 
				
			||||||
                // TODO Enable this for optimization
 | 
					                // TODO Enable this for optimization
 | 
				
			||||||
                // types = (listOfSupportedEventTypes + listOfSupportedStateEventTypes).toMutableList()
 | 
					                // types = (listOfSupportedEventTypes + listOfSupportedStateEventTypes).toMutableList()
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun createElementTimelineFilter(): RoomEventFilter? {
 | 
					    private fun createElementTimelineFilter(): RoomEventFilter? {
 | 
				
			||||||
        return null // RoomEventFilter().apply {
 | 
					        return RoomEventFilter(enableUnreadThreadNotifications = true)
 | 
				
			||||||
        // TODO Enable this for optimization
 | 
					 | 
				
			||||||
        // types = listOfSupportedEventTypes.toMutableList()
 | 
					 | 
				
			||||||
        // }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun createElementStateFilter(): RoomEventFilter {
 | 
					    private fun createElementStateFilter(): RoomEventFilter {
 | 
				
			||||||
        return RoomEventFilter(
 | 
					        return RoomEventFilter(lazyLoadMembers = true)
 | 
				
			||||||
                lazyLoadMembers = true
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Get only managed types by Element
 | 
					    // Get only managed types by Element
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.session.filter
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import com.squareup.moshi.Json
 | 
					import com.squareup.moshi.Json
 | 
				
			||||||
import com.squareup.moshi.JsonClass
 | 
					import com.squareup.moshi.JsonClass
 | 
				
			||||||
 | 
					import org.matrix.android.sdk.api.session.sync.model.RoomSync
 | 
				
			||||||
import org.matrix.android.sdk.internal.di.MoshiProvider
 | 
					import org.matrix.android.sdk.internal.di.MoshiProvider
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -74,9 +75,15 @@ internal data class RoomEventFilter(
 | 
				
			|||||||
         */
 | 
					         */
 | 
				
			||||||
        @Json(name = "contains_url") val containsUrl: Boolean? = null,
 | 
					        @Json(name = "contains_url") val containsUrl: Boolean? = null,
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * If true, enables lazy-loading of membership events. See Lazy-loading room members for more information. Defaults to false.
 | 
					         * If true, enables lazy-loading of membership events.
 | 
				
			||||||
 | 
					         * See Lazy-loading room members for more information.
 | 
				
			||||||
 | 
					         * Defaults to false.
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        @Json(name = "lazy_load_members") val lazyLoadMembers: Boolean? = null
 | 
					        @Json(name = "lazy_load_members") val lazyLoadMembers: Boolean? = null,
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * If true, this will opt-in for the server to return unread threads notifications in [RoomSync].
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        @Json(name = "unread_thread_notifications") val enableUnreadThreadNotifications: Boolean? = null,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun toJSONString(): String {
 | 
					    fun toJSONString(): String {
 | 
				
			||||||
@ -92,6 +99,7 @@ internal data class RoomEventFilter(
 | 
				
			|||||||
                rooms != null ||
 | 
					                rooms != null ||
 | 
				
			||||||
                notRooms != null ||
 | 
					                notRooms != null ||
 | 
				
			||||||
                containsUrl != null ||
 | 
					                containsUrl != null ||
 | 
				
			||||||
                lazyLoadMembers != null)
 | 
					                lazyLoadMembers != null ||
 | 
				
			||||||
 | 
					                enableUnreadThreadNotifications != null)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -39,6 +39,7 @@ import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
 | 
				
			|||||||
import org.matrix.android.sdk.api.session.room.send.SendState
 | 
					import org.matrix.android.sdk.api.session.room.send.SendState
 | 
				
			||||||
import org.matrix.android.sdk.api.session.sync.model.RoomSyncSummary
 | 
					import org.matrix.android.sdk.api.session.sync.model.RoomSyncSummary
 | 
				
			||||||
import org.matrix.android.sdk.api.session.sync.model.RoomSyncUnreadNotifications
 | 
					import org.matrix.android.sdk.api.session.sync.model.RoomSyncUnreadNotifications
 | 
				
			||||||
 | 
					import org.matrix.android.sdk.api.session.sync.model.RoomSyncUnreadThreadNotifications
 | 
				
			||||||
import org.matrix.android.sdk.internal.crypto.EventDecryptor
 | 
					import org.matrix.android.sdk.internal.crypto.EventDecryptor
 | 
				
			||||||
import org.matrix.android.sdk.internal.crypto.crosssigning.DefaultCrossSigningService
 | 
					import org.matrix.android.sdk.internal.crypto.crosssigning.DefaultCrossSigningService
 | 
				
			||||||
import org.matrix.android.sdk.internal.database.mapper.ContentMapper
 | 
					import org.matrix.android.sdk.internal.database.mapper.ContentMapper
 | 
				
			||||||
@ -91,6 +92,7 @@ internal class RoomSummaryUpdater @Inject constructor(
 | 
				
			|||||||
            membership: Membership? = null,
 | 
					            membership: Membership? = null,
 | 
				
			||||||
            roomSummary: RoomSyncSummary? = null,
 | 
					            roomSummary: RoomSyncSummary? = null,
 | 
				
			||||||
            unreadNotifications: RoomSyncUnreadNotifications? = null,
 | 
					            unreadNotifications: RoomSyncUnreadNotifications? = null,
 | 
				
			||||||
 | 
					            unreadThreadNotifications: Map<String, RoomSyncUnreadThreadNotifications>? = null,
 | 
				
			||||||
            updateMembers: Boolean = false,
 | 
					            updateMembers: Boolean = false,
 | 
				
			||||||
            inviterId: String? = null,
 | 
					            inviterId: String? = null,
 | 
				
			||||||
            aggregator: SyncResponsePostTreatmentAggregator? = null
 | 
					            aggregator: SyncResponsePostTreatmentAggregator? = null
 | 
				
			||||||
@ -111,6 +113,14 @@ internal class RoomSummaryUpdater @Inject constructor(
 | 
				
			|||||||
        roomSummaryEntity.highlightCount = unreadNotifications?.highlightCount ?: 0
 | 
					        roomSummaryEntity.highlightCount = unreadNotifications?.highlightCount ?: 0
 | 
				
			||||||
        roomSummaryEntity.notificationCount = unreadNotifications?.notificationCount ?: 0
 | 
					        roomSummaryEntity.notificationCount = unreadNotifications?.notificationCount ?: 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        roomSummaryEntity.threadHighlightCount = unreadThreadNotifications
 | 
				
			||||||
 | 
					                ?.count { (it.value.highlightCount ?: 0) > 0 }
 | 
				
			||||||
 | 
					                ?: 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        roomSummaryEntity.threadNotificationCount = unreadThreadNotifications
 | 
				
			||||||
 | 
					                ?.count { (it.value.notificationCount ?: 0) > 0 }
 | 
				
			||||||
 | 
					                ?: 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (membership != null) {
 | 
					        if (membership != null) {
 | 
				
			||||||
            roomSummaryEntity.membership = membership
 | 
					            roomSummaryEntity.membership = membership
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -140,7 +140,7 @@ internal class DefaultSyncTask @Inject constructor(
 | 
				
			|||||||
                        executeRequest(globalErrorReceiver) {
 | 
					                        executeRequest(globalErrorReceiver) {
 | 
				
			||||||
                            syncAPI.sync(
 | 
					                            syncAPI.sync(
 | 
				
			||||||
                                    params = requestParams,
 | 
					                                    params = requestParams,
 | 
				
			||||||
                                    readTimeOut = readTimeOut
 | 
					                                    readTimeOut = readTimeOut,
 | 
				
			||||||
                            )
 | 
					                            )
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@ -178,7 +178,7 @@ internal class DefaultSyncTask @Inject constructor(
 | 
				
			|||||||
            syncRequestStateTracker.setSyncRequestState(
 | 
					            syncRequestStateTracker.setSyncRequestState(
 | 
				
			||||||
                    SyncRequestState.IncrementalSyncParsing(
 | 
					                    SyncRequestState.IncrementalSyncParsing(
 | 
				
			||||||
                            rooms = nbRooms,
 | 
					                            rooms = nbRooms,
 | 
				
			||||||
                            toDevice = nbToDevice
 | 
					                            toDevice = nbToDevice,
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            syncResponseHandler.handleResponse(syncResponse, token, null)
 | 
					            syncResponseHandler.handleResponse(syncResponse, token, null)
 | 
				
			||||||
 | 
				
			|||||||
@ -287,6 +287,7 @@ internal class RoomSyncHandler @Inject constructor(
 | 
				
			|||||||
                Membership.JOIN,
 | 
					                Membership.JOIN,
 | 
				
			||||||
                roomSync.summary,
 | 
					                roomSync.summary,
 | 
				
			||||||
                roomSync.unreadNotifications,
 | 
					                roomSync.unreadNotifications,
 | 
				
			||||||
 | 
					                roomSync.unreadThreadNotifications,
 | 
				
			||||||
                updateMembers = hasRoomMember,
 | 
					                updateMembers = hasRoomMember,
 | 
				
			||||||
                aggregator = aggregator
 | 
					                aggregator = aggregator
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
@ -372,7 +373,8 @@ internal class RoomSyncHandler @Inject constructor(
 | 
				
			|||||||
        roomEntity.chunks.clearWith { it.deleteOnCascade(deleteStateEvents = true, canDeleteRoot = true) }
 | 
					        roomEntity.chunks.clearWith { it.deleteOnCascade(deleteStateEvents = true, canDeleteRoot = true) }
 | 
				
			||||||
        roomTypingUsersHandler.handle(realm, roomId, null)
 | 
					        roomTypingUsersHandler.handle(realm, roomId, null)
 | 
				
			||||||
        roomChangeMembershipStateDataSource.setMembershipFromSync(roomId, Membership.LEAVE)
 | 
					        roomChangeMembershipStateDataSource.setMembershipFromSync(roomId, Membership.LEAVE)
 | 
				
			||||||
        roomSummaryUpdater.update(realm, roomId, membership, roomSync.summary, roomSync.unreadNotifications, aggregator = aggregator)
 | 
					        roomSummaryUpdater.update(realm, roomId, membership, roomSync.summary,
 | 
				
			||||||
 | 
					                roomSync.unreadNotifications, roomSync.unreadThreadNotifications, aggregator = aggregator)
 | 
				
			||||||
        return roomEntity
 | 
					        return roomEntity
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -18,6 +18,7 @@ package im.vector.app.features.home.room.detail
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import android.net.Uri
 | 
					import android.net.Uri
 | 
				
			||||||
import androidx.annotation.IdRes
 | 
					import androidx.annotation.IdRes
 | 
				
			||||||
 | 
					import androidx.lifecycle.asFlow
 | 
				
			||||||
import com.airbnb.mvrx.Async
 | 
					import com.airbnb.mvrx.Async
 | 
				
			||||||
import com.airbnb.mvrx.Fail
 | 
					import com.airbnb.mvrx.Fail
 | 
				
			||||||
import com.airbnb.mvrx.Loading
 | 
					import com.airbnb.mvrx.Loading
 | 
				
			||||||
@ -408,21 +409,40 @@ class TimelineViewModel @AssistedInject constructor(
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    private fun observeLocalThreadNotifications() {
 | 
					    private fun observeLocalThreadNotifications() {
 | 
				
			||||||
        if (room == null) return
 | 
					        if (room == null) return
 | 
				
			||||||
        room.flow()
 | 
					        val threadNotificationsSupported = session.homeServerCapabilitiesService().getHomeServerCapabilities().canUseThreadReadReceiptsAndNotifications
 | 
				
			||||||
                .liveLocalUnreadThreadList()
 | 
					        if (threadNotificationsSupported) {
 | 
				
			||||||
                .execute {
 | 
					            room.getRoomSummaryLive()
 | 
				
			||||||
                    val threadList = it.invoke()
 | 
					                    .asFlow()
 | 
				
			||||||
                    val isUserMentioned = threadList?.firstOrNull { threadRootEvent ->
 | 
					                    .onEach {
 | 
				
			||||||
                        threadRootEvent.root.threadDetails?.threadNotificationState == ThreadNotificationState.NEW_HIGHLIGHTED_MESSAGE
 | 
					                        it.getOrNull()?.let {
 | 
				
			||||||
                    }?.let { true } ?: false
 | 
					                            setState {
 | 
				
			||||||
                    val numberOfLocalUnreadThreads = threadList?.size ?: 0
 | 
					                                copy(
 | 
				
			||||||
                    copy(
 | 
					                                        threadNotificationBadgeState = ThreadNotificationBadgeState(
 | 
				
			||||||
                            threadNotificationBadgeState = ThreadNotificationBadgeState(
 | 
					                                                numberOfLocalUnreadThreads = it.threadNotificationCount + it.threadHighlightCount,
 | 
				
			||||||
                                    numberOfLocalUnreadThreads = numberOfLocalUnreadThreads,
 | 
					                                                isUserMentioned = it.threadHighlightCount > 0,
 | 
				
			||||||
                                    isUserMentioned = isUserMentioned
 | 
					                                        )
 | 
				
			||||||
                            )
 | 
					                                )
 | 
				
			||||||
                    )
 | 
					                            }
 | 
				
			||||||
                }
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    .launchIn(viewModelScope)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            room.flow()
 | 
				
			||||||
 | 
					                    .liveLocalUnreadThreadList()
 | 
				
			||||||
 | 
					                    .execute {
 | 
				
			||||||
 | 
					                        val threadList = it.invoke()
 | 
				
			||||||
 | 
					                        val isUserMentioned = threadList?.firstOrNull { threadRootEvent ->
 | 
				
			||||||
 | 
					                            threadRootEvent.root.threadDetails?.threadNotificationState == ThreadNotificationState.NEW_HIGHLIGHTED_MESSAGE
 | 
				
			||||||
 | 
					                        } != null
 | 
				
			||||||
 | 
					                        val numberOfLocalUnreadThreads = threadList?.size ?: 0
 | 
				
			||||||
 | 
					                        copy(
 | 
				
			||||||
 | 
					                                threadNotificationBadgeState = ThreadNotificationBadgeState(
 | 
				
			||||||
 | 
					                                        numberOfLocalUnreadThreads = numberOfLocalUnreadThreads,
 | 
				
			||||||
 | 
					                                        isUserMentioned = isUserMentioned
 | 
				
			||||||
 | 
					                                )
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun handle(action: RoomDetailAction) {
 | 
					    override fun handle(action: RoomDetailAction) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user