diff --git a/vector/src/main/java/im/vector/app/core/resources/UserPreferencesProvider.kt b/vector/src/main/java/im/vector/app/core/resources/UserPreferencesProvider.kt index f7d7b3864e..04da5394f2 100644 --- a/vector/src/main/java/im/vector/app/core/resources/UserPreferencesProvider.kt +++ b/vector/src/main/java/im/vector/app/core/resources/UserPreferencesProvider.kt @@ -41,7 +41,14 @@ class UserPreferencesProvider @Inject constructor(private val vectorPreferences: vectorPreferences.neverShowLongClickOnRoomHelpAgain() } - fun shouldShowRoomMemberStateEvents(): Boolean { - return vectorPreferences.showRoomMemberStateEvents() + fun shouldShowJoinLeaves(): Boolean { + return vectorPreferences.showJoinLeaveMessages() } + + fun shouldShowAvatarDisplayNameChanges(): Boolean { + return vectorPreferences.showAvatarDisplayNameChangeMessages() + } + + + } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt index aff94f7157..6c19f30cf0 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt @@ -318,7 +318,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec cacheItemData.eventModel } listOf( - cacheItemData?.readReceiptsItem?.takeIf { cacheItemData.mergedHeaderModel == null }, + cacheItemData?.readReceiptsItem?.takeUnless { mergedHeaderItemFactory.isCollapsed(cacheItemData.localId) }, eventModel, cacheItemData?.mergedHeaderModel, cacheItemData?.formattedDayModel?.takeIf { eventModel != null || cacheItemData.mergedHeaderModel != null } @@ -428,6 +428,9 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec private fun getReadReceiptsByShownEvent(): Map> { val receiptsByEvent = HashMap>() + if(!userPreferencesProvider.shouldShowReadReceipts()){ + return receiptsByEvent + } var lastShownEventId: String? = null val itr = currentSnapshot.listIterator(currentSnapshot.size) while (itr.hasPrevious()) { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt index e9340feaca..cb2a067540 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt @@ -86,12 +86,11 @@ private val timelineEventVisibilityHelper: TimelineEventVisibilityHelper) { eventIdToHighlight: String?, requestModelBuild: () -> Unit, callback: TimelineEventController.Callback?): MergedMembershipEventsItem_? { - val prevSameTypeEvents = timelineEventVisibilityHelper.prevSameTypeEvents(items, currentPosition, 2, eventIdToHighlight) - return if (prevSameTypeEvents.isEmpty()) { + val mergedEvents = timelineEventVisibilityHelper.prevSameTypeEvents(items, currentPosition, 2, eventIdToHighlight) + return if (mergedEvents.isEmpty()) { null } else { var highlighted = false - val mergedEvents = (prevSameTypeEvents + listOf(event)).asReversed() val mergedData = ArrayList(mergedEvents.size) mergedEvents.forEach { mergedEvent -> if (!highlighted && mergedEvent.root.eventId == eventIdToHighlight) { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineControllerInterceptorHelper.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineControllerInterceptorHelper.kt index e8353ff264..72fdef9f7d 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineControllerInterceptorHelper.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineControllerInterceptorHelper.kt @@ -72,7 +72,7 @@ class TimelineControllerInterceptorHelper(private val positionOfReadMarker: KMut } epoxyModel.getEventIds().forEach { eventId -> adapterPositionMapping[eventId] = index - if (eventId == firstUnreadEventId && atLeastOneVisibleItemsBeforeReadMarker && epoxyModel.canAppendReadMarker()) { + if (epoxyModel.canAppendReadMarker() && eventId == firstUnreadEventId && atLeastOneVisibleItemsBeforeReadMarker) { modelsIterator.addReadMarkerItem(callback) index++ positionOfReadMarker.set(index) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineEventVisibilityHelper.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineEventVisibilityHelper.kt index 39c95a5915..e55b02fe85 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineEventVisibilityHelper.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineEventVisibilityHelper.kt @@ -29,12 +29,21 @@ import javax.inject.Inject class TimelineEventVisibilityHelper @Inject constructor(private val userPreferencesProvider: UserPreferencesProvider) { + + /** + * @param timelineEvents the events to search in + * @param index the index to start computing (inclusive) + * @param minSize the minimum number of same type events to have sequentially, otherwise will return an empty list + * @param eventIdToHighlight used to compute visibility + * + * @return a list of timeline events which have sequentially the same type following the next direction. + */ fun nextSameTypeEvents(timelineEvents: List, index: Int, minSize: Int, eventIdToHighlight: String?): List { if (index >= timelineEvents.size - 1) { return emptyList() } val timelineEvent = timelineEvents[index] - val nextSubList = timelineEvents.subList(index + 1, timelineEvents.size) + val nextSubList = timelineEvents.subList(index, timelineEvents.size) val indexOfNextDay = nextSubList.indexOfFirst { val date = it.root.localDateTime() val nextDate = timelineEvent.root.localDateTime() @@ -58,6 +67,14 @@ class TimelineEventVisibilityHelper @Inject constructor(private val userPreferen return filteredSameTypeEvents } + /** + * @param timelineEvents the events to search in + * @param index the index to start computing (inclusive) + * @param minSize the minimum number of same type events to have sequentially, otherwise will return an empty list + * @param eventIdToHighlight used to compute visibility + * + * @return a list of timeline events which have sequentially the same type following the prev direction. + */ fun prevSameTypeEvents(timelineEvents: List, index: Int, minSize: Int, eventIdToHighlight: String?): List { val prevSub = timelineEvents.subList(0, index + 1) return prevSub @@ -65,9 +82,13 @@ class TimelineEventVisibilityHelper @Inject constructor(private val userPreferen .let { nextSameTypeEvents(it, 0, minSize, eventIdToHighlight) } - .reversed() } + /** + * @param timelineEvent the event to check for visibility + * @param highlightedEventId can be checked to force visibility to true + * @return true if the event should be shown in the timeline. + */ fun shouldShowEvent(timelineEvent: TimelineEvent, highlightedEventId: String?): Boolean { // If show hidden events is true we should always display something if (userPreferencesProvider.shouldShowHiddenEvents()) { @@ -97,7 +118,8 @@ class TimelineEventVisibilityHelper @Inject constructor(private val userPreferen } if (root.getClearType() == EventType.STATE_ROOM_MEMBER) { val diff = computeMembershipDiff() - if ((diff.isJoin || diff.isPart) && !userPreferencesProvider.shouldShowRoomMemberStateEvents()) return true + if ((diff.isJoin || diff.isPart) && !userPreferencesProvider.shouldShowJoinLeaves()) return true + if ((diff.isAvatarChange || diff.isDisplaynameChange) && !userPreferencesProvider.shouldShowAvatarDisplayNameChanges()) return true } return false } @@ -110,9 +132,9 @@ class TimelineEventVisibilityHelper @Inject constructor(private val userPreferen val isJoin = isMembershipChanged && content?.membership == Membership.JOIN val isPart = isMembershipChanged && content?.membership == Membership.LEAVE && root.stateKey == root.senderId - val isJoinToJoin = !isMembershipChanged && content?.membership == Membership.JOIN - val isDisplaynameChange = isJoinToJoin && content?.displayName != prevContent?.displayName; - val isAvatarChange = isJoinToJoin && content?.avatarUrl !== prevContent?.avatarUrl + val isProfileChanged = !isMembershipChanged && content?.membership == Membership.JOIN + val isDisplaynameChange = isProfileChanged && content?.displayName != prevContent?.displayName; + val isAvatarChange = isProfileChanged && content?.avatarUrl !== prevContent?.avatarUrl return MembershipDiff( isJoin = isJoin, diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index a1151162c8..9b043cfc7c 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -357,15 +357,6 @@ class VectorPreferences @Inject constructor(private val context: Context) { return defaultPrefs.getBoolean(SETTINGS_12_24_TIMESTAMPS_KEY, false) } - /** - * Tells if all room member state events should be shown in the messages list. - * - * @return true all room member state events should be shown in the messages list. - */ - fun showRoomMemberStateEvents(): Boolean { - return defaultPrefs.getBoolean(SETTINGS_SHOW_ROOM_MEMBER_STATE_EVENTS_KEY, true) - } - /** * Tells if the join and leave membership events should be shown in the messages list. * diff --git a/vector/src/main/res/xml/vector_settings_preferences.xml b/vector/src/main/res/xml/vector_settings_preferences.xml index 6a3c60a021..1d39791ad8 100644 --- a/vector/src/main/res/xml/vector_settings_preferences.xml +++ b/vector/src/main/res/xml/vector_settings_preferences.xml @@ -88,9 +88,15 @@ + android:key="SETTINGS_SHOW_JOIN_LEAVE_MESSAGES_KEY" + android:summary="@string/settings_show_join_leave_messages_summary" + android:title="@string/settings_show_join_leave_messages" /> + +