From 23f8c307a367fc34672cbae9c1b14577bc836fe6 Mon Sep 17 00:00:00 2001 From: Arnaud Ringenbach Date: Wed, 2 Mar 2022 11:12:44 +0100 Subject: [PATCH 1/8] Use only latest profiles in the timeline (labs) --- Config/BuildSettings.swift | 1 + Riot/Assets/en.lproj/Vector.strings | 1 + Riot/Generated/Strings.swift | 4 ++++ Riot/Managers/Settings/RiotSettings.swift | 10 ++++++++- .../Models/Room/MXKRoomBubbleCellData.m | 8 +++++-- .../MXKRoomBubbleCellDataWithAppendingMode.m | 7 +++++-- .../Modules/Settings/SettingsViewController.m | 21 ++++++++++++++++++- changelog.d/5726.change | 1 + 8 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 changelog.d/5726.change diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 8c7ebba3fa..0e99b67222 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -311,6 +311,7 @@ final class BuildSettings: NSObject { static var isRoomScreenEnableMessageBubblesByDefault: Bool { return self.roomScreenTimelineDefaultStyleIdentifier == .bubble } + static let roomScreenUseOnlyLatestProfiles: Bool = false /// Allow split view detail view stacking static let allowSplitViewDetailsScreenStacking: Bool = true diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 19ea216697..ee6a0deea4 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -619,6 +619,7 @@ Tap the + to start adding people."; "settings_labs_enable_ringing_for_group_calls" = "Ring for group calls"; "settings_labs_enabled_polls" = "Polls"; "settings_labs_enable_threads" = "Threaded messaging"; +"settings_labs_use_only_latest_profiles" = "Use only latest profiles"; "settings_version" = "Version %@"; "settings_olm_version" = "Olm Version %@"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 7b790ae06b..3acc4803ea 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -4935,6 +4935,10 @@ public class VectorL10n: NSObject { public static var settingsLabsMessageReaction: String { return VectorL10n.tr("Vector", "settings_labs_message_reaction") } + /// Use only latest profiles + public static var settingsLabsUseOnlyLatestProfiles: String { + return VectorL10n.tr("Vector", "settings_labs_use_only_latest_profiles") + } /// LINKS public static var settingsLinks: String { return VectorL10n.tr("Vector", "settings_links") diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift index fdff093ce1..f2e23c637a 100644 --- a/Riot/Managers/Settings/RiotSettings.swift +++ b/Riot/Managers/Settings/RiotSettings.swift @@ -200,10 +200,18 @@ final class RiotSettings: NSObject { @UserDefault(key: "roomScreenEnableMessageBubbles", defaultValue: BuildSettings.isRoomScreenEnableMessageBubblesByDefault, storage: defaults) var roomScreenEnableMessageBubbles - + var roomTimelineStyleIdentifier: RoomTimelineStyleIdentifier { return self.roomScreenEnableMessageBubbles ? .bubble : .plain } + + /// A setting used to display the latest known profile (display name + avatar) in the timeline + /// for the sender, rather than the profile at the time of the event. + /// + /// Note: this is set up from Room perspective, which means that if a user updates their profile after + /// leaving a Room, it will show up the latest profile used in the Room rather than the latest overall. + @UserDefault(key: "roomScreenUseOnlyLatestProfiles", defaultValue: BuildSettings.roomScreenUseOnlyLatestProfiles, storage: defaults) + var roomScreenUseOnlyLatestProfiles // MARK: - Room Contextual Menu diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m index 4eefae18dd..51f6c0e055 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m @@ -26,6 +26,8 @@ #import "MXKTools.h" +#import "GeneratedInterface-Swift.h" + @implementation MXKRoomBubbleCellData @synthesize senderId, targetId, roomId, senderDisplayName, senderAvatarUrl, senderAvatarPlaceholder, targetDisplayName, targetAvatarUrl, targetAvatarPlaceholder, isEncryptedRoom, isPaginationFirstBubble, shouldHideSenderInformation, date, isIncoming, isAttachmentWithThumbnail, isAttachmentWithIcon, attachment, senderFlair; @synthesize textMessage, attributedTextMessage, attributedTextMessageWithoutPositioningSpace; @@ -55,8 +57,10 @@ - (instancetype)initWithEvent:(MXEvent *)event andRoomState:(MXRoomState *)roomS senderId = event.sender; targetId = [event.type isEqualToString:kMXEventTypeStringRoomMember] ? event.stateKey : nil; roomId = roomDataSource.roomId; - senderDisplayName = [roomDataSource.eventFormatter senderDisplayNameForEvent:event withRoomState:roomState]; - senderAvatarUrl = [roomDataSource.eventFormatter senderAvatarUrlForEvent:event withRoomState:roomState]; + + MXRoomState *profileRoomState = RiotSettings.shared.roomScreenUseOnlyLatestProfiles ? roomDataSource2.roomState : roomState; + senderDisplayName = [roomDataSource.eventFormatter senderDisplayNameForEvent:event withRoomState:profileRoomState]; + senderAvatarUrl = [roomDataSource.eventFormatter senderAvatarUrlForEvent:event withRoomState:profileRoomState]; senderAvatarPlaceholder = nil; targetDisplayName = [roomDataSource.eventFormatter targetDisplayNameForEvent:event withRoomState:roomState]; targetAvatarUrl = [roomDataSource.eventFormatter targetAvatarUrlForEvent:event withRoomState:roomState]; diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataWithAppendingMode.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataWithAppendingMode.m index 6790bddf7d..11892cbbed 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataWithAppendingMode.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataWithAppendingMode.m @@ -16,6 +16,8 @@ #import "MXKRoomBubbleCellDataWithAppendingMode.h" +#import "GeneratedInterface-Swift.h" + static NSAttributedString *messageSeparator = nil; @implementation MXKRoomBubbleCellDataWithAppendingMode @@ -46,8 +48,9 @@ - (BOOL)addEvent:(MXEvent*)event andRoomState:(MXRoomState*)roomState } // Check sender information - NSString *eventSenderName = [roomDataSource.eventFormatter senderDisplayNameForEvent:event withRoomState:roomState]; - NSString *eventSenderAvatar = [roomDataSource.eventFormatter senderAvatarUrlForEvent:event withRoomState:roomState]; + MXRoomState *profileRoomState = RiotSettings.shared.roomScreenUseOnlyLatestProfiles ? roomDataSource.roomState : roomState; + NSString *eventSenderName = [roomDataSource.eventFormatter senderDisplayNameForEvent:event withRoomState:profileRoomState]; + NSString *eventSenderAvatar = [roomDataSource.eventFormatter senderAvatarUrlForEvent:event withRoomState:profileRoomState]; if ((self.senderDisplayName || eventSenderName) && ([self.senderDisplayName isEqualToString:eventSenderName] == NO)) { diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 00088a4f79..3832fabfde 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -159,7 +159,8 @@ typedef NS_ENUM(NSUInteger, LABS_ENABLE) { LABS_ENABLE_RINGING_FOR_GROUP_CALLS_INDEX = 0, LABS_ENABLE_THREADS_INDEX, - LABS_ENABLE_MESSAGE_BUBBLES_INDEX + LABS_ENABLE_MESSAGE_BUBBLES_INDEX, + LABS_USE_ONLY_LATEST_PROFILES_INDEX }; typedef NS_ENUM(NSUInteger, SECURITY) @@ -572,6 +573,7 @@ - (void)updateSections [sectionLabs addRowWithTag:LABS_ENABLE_RINGING_FOR_GROUP_CALLS_INDEX]; [sectionLabs addRowWithTag:LABS_ENABLE_THREADS_INDEX]; [sectionLabs addRowWithTag:LABS_ENABLE_MESSAGE_BUBBLES_INDEX]; + [sectionLabs addRowWithTag:LABS_USE_ONLY_LATEST_PROFILES_INDEX]; sectionLabs.headerTitle = [VectorL10n settingsLabs]; if (sectionLabs.hasAnyRows) { @@ -2462,6 +2464,18 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N { cell = [self buildMessageBubblesCellForTableView:tableView atIndexPath:indexPath]; } + else if (row == LABS_USE_ONLY_LATEST_PROFILES_INDEX) + { + MXKTableViewCellWithLabelAndSwitch *labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; + + labelAndSwitchCell.mxkLabel.text = VectorL10n.settingsLabsUseOnlyLatestProfiles; + labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.roomScreenUseOnlyLatestProfiles; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; + + [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleUseOnlyLatestProfiles:) forControlEvents:UIControlEventTouchUpInside]; + + cell = labelAndSwitchCell; + } } else if (section == SECTION_TAG_FLAIR) { @@ -3244,6 +3258,11 @@ - (void)toggleCommunityFlair:(UISwitch *)sender } } +- (void)toggleUseOnlyLatestProfiles:(UISwitch *)sender +{ + RiotSettings.shared.roomScreenUseOnlyLatestProfiles = sender.isOn; +} + - (void)markAllAsRead:(id)sender { // Feedback: disable button and run activity indicator diff --git a/changelog.d/5726.change b/changelog.d/5726.change new file mode 100644 index 0000000000..153f1fda3e --- /dev/null +++ b/changelog.d/5726.change @@ -0,0 +1 @@ +Labs/Room: Add a setting to use only latest sender profiles From d8a015230a64f707778f3e824c6b683e486e9955 Mon Sep 17 00:00:00 2001 From: Arnaud Ringenbach Date: Wed, 2 Mar 2022 15:51:01 +0100 Subject: [PATCH 2/8] Handle use only latest profile live refreshes --- .../Models/Room/MXKRoomBubbleCellData.m | 12 +++++++++ .../Room/MXKRoomBubbleCellDataStoring.h | 7 +++++ .../MatrixKit/Models/Room/MXKRoomDataSource.m | 26 +++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m index 51f6c0e055..e371a59252 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m @@ -107,6 +107,18 @@ - (void)dealloc bubbleComponents = nil; } +- (void)refreshProfileWithRoomDataSource:(MXKRoomDataSource *)roomDataSource2 +{ + if (self.events.firstObject) + { + MXEvent* firstEvent = self.events.firstObject; + senderDisplayName = [roomDataSource.eventFormatter senderDisplayNameForEvent:firstEvent + withRoomState:roomDataSource2.roomState]; + senderAvatarUrl = [roomDataSource.eventFormatter senderAvatarUrlForEvent:firstEvent + withRoomState:roomDataSource2.roomState]; + } +} + - (NSUInteger)updateEvent:(NSString *)eventId withEvent:(MXEvent *)event { NSUInteger count = 0; diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h index 5ec4b9cb7d..1866f93582 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h @@ -231,6 +231,13 @@ */ - (instancetype)initWithEvent:(MXEvent*)event andRoomState:(MXRoomState*)roomState andRoomDataSource:(MXKRoomDataSource*)roomDataSource; +/** + Refreshes the avatar and display name if needed. Should be used only if `roomScreenUseOnlyLatestProfiles` is enabled. + + @param roomDataSource the `MXKRoomDataSource` object that will use this instance. + */ +- (void)refreshProfileWithRoomDataSource:(MXKRoomDataSource*)roomDataSource; + /** Update the event because its sent state changed or it is has been redacted. diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m index 3e4d7e5d62..e71086bcff 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m @@ -34,6 +34,8 @@ #import "MXKSendReplyEventStringLocalizer.h" #import "MXKSlashCommands.h" +#import "GeneratedInterface-Swift.h" + const BOOL USE_THREAD_TIMELINE = YES; #pragma mark - Constant definitions @@ -1009,6 +1011,11 @@ - (void)refreshEventListeners:(NSArray *)liveEventTypesFilterForMessages liveEventsListener = [_timeline listenToEventsOfTypes:liveEventTypesFilterForMessages onEvent:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { MXStrongifyAndReturnIfNil(self); + + if (RiotSettings.shared.roomScreenUseOnlyLatestProfiles && event.eventType == MXEventTypeRoomMember && event.isUserProfileChange) + { + [self refreshProfilesIfNeeded]; + } if (MXTimelineDirectionForwards == direction) { @@ -4321,4 +4328,23 @@ - (void)virtualRoomsDidChange:(NSNotification *)notification self.secondaryRoomId = [self.mxSession virtualRoomOf:self.roomId]; } +#pragma mark - Use Only Latest Profiles + +/** + Refreshes the avatars and display names if needed. This has no effect + if `roomScreenUseOnlyLatestProfiles` is disabled. + */ +- (void)refreshProfilesIfNeeded +{ + if (RiotSettings.shared.roomScreenUseOnlyLatestProfiles) + { + @synchronized (bubbles) { + for (id bubble in bubbles) + { + [bubble refreshProfileWithRoomDataSource:self]; + } + } + } +} + @end From 7ae815760e51cedcfc2bd731545f10d77258445e Mon Sep 17 00:00:00 2001 From: Arnaud Ringenbach Date: Wed, 2 Mar 2022 16:17:33 +0100 Subject: [PATCH 3/8] Add more restrictive test to detect an avatar change event --- Riot/Utils/EventFormatter.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index 88c504bf0f..8258108994 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -425,7 +425,9 @@ - (NSString*)senderAvatarUrlForEvent:(MXEvent*)event withRoomState:(MXRoomState* // Check whether this avatar url is updated by the current event (This happens in case of new joined member) NSString* membership = event.content[@"membership"]; - if (membership && [membership isEqualToString:@"join"] && [event.content[@"avatar_url"] length]) + NSString* eventAvatarUrl = event.content[@"avatar_url"]; + NSString* prevEventAvatarUrl = event.prevContent[@"avatar_url"]; + if (membership && [membership isEqualToString:@"join"] && [eventAvatarUrl length] && ![eventAvatarUrl isEqualToString:prevEventAvatarUrl]) { // Use the actual avatar senderAvatarUrl = event.content[@"avatar_url"]; From d17e7e00ea2a4b696d5b909a0ff1ae23be1c6204 Mon Sep 17 00:00:00 2001 From: Arnaud Ringenbach Date: Thu, 3 Mar 2022 10:12:08 +0100 Subject: [PATCH 4/8] Rename `dataSource2` parameters and handle target profiles --- .../Models/Room/MXKRoomBubbleCellData.m | 32 ++++++++++++------- .../Room/MXKRoomBubbleCellDataStoring.h | 4 +-- .../MXKRoomBubbleCellDataWithAppendingMode.m | 4 +-- .../MatrixKit/Models/Room/MXKRoomDataSource.m | 2 +- .../Room/CellData/RoomBubbleCellData.m | 4 +-- .../Search/DataSources/RoomSearchDataSource.m | 6 ++-- 6 files changed, 29 insertions(+), 23 deletions(-) diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m index e371a59252..4279df0736 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m @@ -37,12 +37,12 @@ @implementation MXKRoomBubbleCellData #pragma mark - MXKRoomBubbleCellDataStoring -- (instancetype)initWithEvent:(MXEvent *)event andRoomState:(MXRoomState *)roomState andRoomDataSource:(MXKRoomDataSource *)roomDataSource2 +- (instancetype)initWithEvent:(MXEvent *)event andRoomState:(MXRoomState *)roomState andRoomDataSource:(MXKRoomDataSource *)roomDataSource { self = [self init]; if (self) { - roomDataSource = roomDataSource2; + self->roomDataSource = roomDataSource; // Initialize read receipts self.readReceipts = [NSMutableDictionary dictionary]; @@ -58,12 +58,12 @@ - (instancetype)initWithEvent:(MXEvent *)event andRoomState:(MXRoomState *)roomS targetId = [event.type isEqualToString:kMXEventTypeStringRoomMember] ? event.stateKey : nil; roomId = roomDataSource.roomId; - MXRoomState *profileRoomState = RiotSettings.shared.roomScreenUseOnlyLatestProfiles ? roomDataSource2.roomState : roomState; + MXRoomState *profileRoomState = RiotSettings.shared.roomScreenUseOnlyLatestProfiles ? roomDataSource.roomState : roomState; senderDisplayName = [roomDataSource.eventFormatter senderDisplayNameForEvent:event withRoomState:profileRoomState]; senderAvatarUrl = [roomDataSource.eventFormatter senderAvatarUrlForEvent:event withRoomState:profileRoomState]; senderAvatarPlaceholder = nil; - targetDisplayName = [roomDataSource.eventFormatter targetDisplayNameForEvent:event withRoomState:roomState]; - targetAvatarUrl = [roomDataSource.eventFormatter targetAvatarUrlForEvent:event withRoomState:roomState]; + targetDisplayName = [roomDataSource.eventFormatter targetDisplayNameForEvent:event withRoomState:profileRoomState]; + targetAvatarUrl = [roomDataSource.eventFormatter targetAvatarUrlForEvent:event withRoomState:profileRoomState]; targetAvatarPlaceholder = nil; isEncryptedRoom = roomState.isEncrypted; isIncoming = ([event.sender isEqualToString:roomDataSource.mxSession.myUser.userId] == NO); @@ -107,16 +107,24 @@ - (void)dealloc bubbleComponents = nil; } -- (void)refreshProfileWithRoomDataSource:(MXKRoomDataSource *)roomDataSource2 +- (void)refreshProfile { - if (self.events.firstObject) + MXRoomState *roomState = roomDataSource.roomState; + MXEvent* firstEvent = self.events.firstObject; + + if (firstEvent == nil || roomState == nil) { - MXEvent* firstEvent = self.events.firstObject; - senderDisplayName = [roomDataSource.eventFormatter senderDisplayNameForEvent:firstEvent - withRoomState:roomDataSource2.roomState]; - senderAvatarUrl = [roomDataSource.eventFormatter senderAvatarUrlForEvent:firstEvent - withRoomState:roomDataSource2.roomState]; + return; } + + senderDisplayName = [roomDataSource.eventFormatter senderDisplayNameForEvent:firstEvent + withRoomState:roomState]; + senderAvatarUrl = [roomDataSource.eventFormatter senderAvatarUrlForEvent:firstEvent + withRoomState:roomState]; + targetDisplayName = [roomDataSource.eventFormatter targetDisplayNameForEvent:firstEvent + withRoomState:roomState]; + targetAvatarUrl = [roomDataSource.eventFormatter targetAvatarUrlForEvent:firstEvent + withRoomState:roomState]; } - (NSUInteger)updateEvent:(NSString *)eventId withEvent:(MXEvent *)event diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h index 1866f93582..90eb21fb16 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h @@ -233,10 +233,8 @@ /** Refreshes the avatar and display name if needed. Should be used only if `roomScreenUseOnlyLatestProfiles` is enabled. - - @param roomDataSource the `MXKRoomDataSource` object that will use this instance. */ -- (void)refreshProfileWithRoomDataSource:(MXKRoomDataSource*)roomDataSource; +- (void)refreshProfile; /** Update the event because its sent state changed or it is has been redacted. diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataWithAppendingMode.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataWithAppendingMode.m index 11892cbbed..5baec1dd5e 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataWithAppendingMode.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataWithAppendingMode.m @@ -24,9 +24,9 @@ @implementation MXKRoomBubbleCellDataWithAppendingMode #pragma mark - MXKRoomBubbleCellDataStoring -- (instancetype)initWithEvent:(MXEvent *)event andRoomState:(MXRoomState *)roomState andRoomDataSource:(MXKRoomDataSource *)roomDataSource2 +- (instancetype)initWithEvent:(MXEvent *)event andRoomState:(MXRoomState *)roomState andRoomDataSource:(MXKRoomDataSource *)roomDataSource { - self = [super initWithEvent:event andRoomState:roomState andRoomDataSource:roomDataSource2]; + self = [super initWithEvent:event andRoomState:roomState andRoomDataSource:roomDataSource]; if (self) { // Set default settings diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m index e71086bcff..ddda2f26d8 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m @@ -4341,7 +4341,7 @@ - (void)refreshProfilesIfNeeded @synchronized (bubbles) { for (id bubble in bubbles) { - [bubble refreshProfileWithRoomDataSource:self]; + [bubble refreshProfile]; } } } diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index a1c8e02cc3..70ad44a482 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -60,9 +60,9 @@ - (instancetype)init return self; } -- (instancetype)initWithEvent:(MXEvent *)event andRoomState:(MXRoomState *)roomState andRoomDataSource:(MXKRoomDataSource *)roomDataSource2 +- (instancetype)initWithEvent:(MXEvent *)event andRoomState:(MXRoomState *)roomState andRoomDataSource:(MXKRoomDataSource *)roomDataSource { - self = [super initWithEvent:event andRoomState:roomState andRoomDataSource:roomDataSource2]; + self = [super initWithEvent:event andRoomState:roomState andRoomDataSource:roomDataSource]; if (self) { diff --git a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m index 8be145b512..9c0530a7ba 100644 --- a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m +++ b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m @@ -33,12 +33,12 @@ @interface RoomSearchDataSource () @implementation RoomSearchDataSource -- (instancetype)initWithRoomDataSource:(MXKRoomDataSource *)roomDataSource2 +- (instancetype)initWithRoomDataSource:(MXKRoomDataSource *)roomDataSource { - self = [super initWithMatrixSession:roomDataSource2.mxSession]; + self = [super initWithMatrixSession:roomDataSource.mxSession]; if (self) { - roomDataSource = roomDataSource2; + self->roomDataSource = roomDataSource; // The messages search is limited to the room data. self.roomEventFilter.rooms = @[roomDataSource.roomId]; From f78a428eb22bb6aafbb4eaf73620c85a9b94637e Mon Sep 17 00:00:00 2001 From: Arnaud Ringenbach Date: Thu, 3 Mar 2022 11:19:09 +0100 Subject: [PATCH 5/8] Revamp refreshProfiles as setRoomState --- .../MatrixKit/Models/Room/MXKRoomBubbleCellData.m | 11 +++++------ .../Models/Room/MXKRoomBubbleCellDataStoring.h | 8 ++++++-- .../Modules/MatrixKit/Models/Room/MXKRoomDataSource.m | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m index 4279df0736..6bd995ecef 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m @@ -59,12 +59,12 @@ - (instancetype)initWithEvent:(MXEvent *)event andRoomState:(MXRoomState *)roomS roomId = roomDataSource.roomId; MXRoomState *profileRoomState = RiotSettings.shared.roomScreenUseOnlyLatestProfiles ? roomDataSource.roomState : roomState; - senderDisplayName = [roomDataSource.eventFormatter senderDisplayNameForEvent:event withRoomState:profileRoomState]; - senderAvatarUrl = [roomDataSource.eventFormatter senderAvatarUrlForEvent:event withRoomState:profileRoomState]; + [self setRoomState:profileRoomState]; senderAvatarPlaceholder = nil; - targetDisplayName = [roomDataSource.eventFormatter targetDisplayNameForEvent:event withRoomState:profileRoomState]; - targetAvatarUrl = [roomDataSource.eventFormatter targetAvatarUrlForEvent:event withRoomState:profileRoomState]; targetAvatarPlaceholder = nil; + + // Encryption status should always rely on the `MXRoomState` + // from the event rather than the latest. isEncryptedRoom = roomState.isEncrypted; isIncoming = ([event.sender isEqualToString:roomDataSource.mxSession.myUser.userId] == NO); @@ -107,9 +107,8 @@ - (void)dealloc bubbleComponents = nil; } -- (void)refreshProfile +- (void)setRoomState:(MXRoomState *)roomState; { - MXRoomState *roomState = roomDataSource.roomState; MXEvent* firstEvent = self.events.firstObject; if (firstEvent == nil || roomState == nil) diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h index 90eb21fb16..d37587f716 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataStoring.h @@ -232,9 +232,13 @@ - (instancetype)initWithEvent:(MXEvent*)event andRoomState:(MXRoomState*)roomState andRoomDataSource:(MXKRoomDataSource*)roomDataSource; /** - Refreshes the avatar and display name if needed. Should be used only if `roomScreenUseOnlyLatestProfiles` is enabled. + Sets the `MXRoomState` for a buble cell. This allows to adapt the display + of a cell with a different room state than its historical. This won't update critical + flag/status, such as `isEncryptedRoom`. + + @param roomState the `MXRoomState` to use for this cell. */ -- (void)refreshProfile; +- (void)setRoomState:(MXRoomState *)roomState; /** Update the event because its sent state changed or it is has been redacted. diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m index ddda2f26d8..f1365af055 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m @@ -4341,7 +4341,7 @@ - (void)refreshProfilesIfNeeded @synchronized (bubbles) { for (id bubble in bubbles) { - [bubble refreshProfile]; + [bubble setRoomState:self.roomState]; } } } From e273a46d5f8eb29a9206e8b7ee1da87ca01275a8 Mon Sep 17 00:00:00 2001 From: Arnaud Ringenbach Date: Thu, 3 Mar 2022 11:32:33 +0100 Subject: [PATCH 6/8] Use senderAvatarUrl instead of dictionnary --- Riot/Utils/EventFormatter.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index 8258108994..ded35e8af0 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -430,7 +430,7 @@ - (NSString*)senderAvatarUrlForEvent:(MXEvent*)event withRoomState:(MXRoomState* if (membership && [membership isEqualToString:@"join"] && [eventAvatarUrl length] && ![eventAvatarUrl isEqualToString:prevEventAvatarUrl]) { // Use the actual avatar - senderAvatarUrl = event.content[@"avatar_url"]; + senderAvatarUrl = eventAvatarUrl; } // We ignore non mxc avatar url (The identicons are removed here). From 2488b80866f41228ff9ee1719807ccda855eaf3e Mon Sep 17 00:00:00 2001 From: Arnaud Ringenbach Date: Thu, 3 Mar 2022 14:10:01 +0100 Subject: [PATCH 7/8] Remove duplicated `roomScreenUseOnlyLatestProfiles` setting test --- Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m index f1365af055..b433e69747 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m @@ -1012,7 +1012,7 @@ - (void)refreshEventListeners:(NSArray *)liveEventTypesFilterForMessages MXStrongifyAndReturnIfNil(self); - if (RiotSettings.shared.roomScreenUseOnlyLatestProfiles && event.eventType == MXEventTypeRoomMember && event.isUserProfileChange) + if (event.eventType == MXEventTypeRoomMember && event.isUserProfileChange) { [self refreshProfilesIfNeeded]; } From 7afa150be194bc35928d5005dbac5134cbfdf2d1 Mon Sep 17 00:00:00 2001 From: Arnaud Ringenbach Date: Fri, 4 Mar 2022 15:48:59 +0100 Subject: [PATCH 8/8] Rename `profile` as `userAvatarAndName` --- Config/BuildSettings.swift | 2 +- Riot/Assets/en.lproj/Vector.strings | 2 +- Riot/Generated/Strings.swift | 6 +++--- Riot/Managers/Settings/RiotSettings.swift | 8 ++++---- .../Models/Room/MXKRoomBubbleCellData.m | 7 +++++-- .../MXKRoomBubbleCellDataWithAppendingMode.m | 9 ++++++--- .../MatrixKit/Models/Room/MXKRoomDataSource.m | 4 ++-- Riot/Modules/Settings/SettingsViewController.m | 16 ++++++++-------- 8 files changed, 30 insertions(+), 24 deletions(-) diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 0e99b67222..c3a93065ea 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -311,7 +311,7 @@ final class BuildSettings: NSObject { static var isRoomScreenEnableMessageBubblesByDefault: Bool { return self.roomScreenTimelineDefaultStyleIdentifier == .bubble } - static let roomScreenUseOnlyLatestProfiles: Bool = false + static let roomScreenUseOnlyLatestUserAvatarAndName: Bool = false /// Allow split view detail view stacking static let allowSplitViewDetailsScreenStacking: Bool = true diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index ee6a0deea4..437b1cb12e 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -619,7 +619,7 @@ Tap the + to start adding people."; "settings_labs_enable_ringing_for_group_calls" = "Ring for group calls"; "settings_labs_enabled_polls" = "Polls"; "settings_labs_enable_threads" = "Threaded messaging"; -"settings_labs_use_only_latest_profiles" = "Use only latest profiles"; +"settings_labs_use_only_latest_user_avatar_and_name" = "Show latest avatar and name for users in message history"; "settings_version" = "Version %@"; "settings_olm_version" = "Olm Version %@"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 3acc4803ea..15b0ea6a25 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -4935,9 +4935,9 @@ public class VectorL10n: NSObject { public static var settingsLabsMessageReaction: String { return VectorL10n.tr("Vector", "settings_labs_message_reaction") } - /// Use only latest profiles - public static var settingsLabsUseOnlyLatestProfiles: String { - return VectorL10n.tr("Vector", "settings_labs_use_only_latest_profiles") + /// Show latest avatar and name for users in message history + public static var settingsLabsUseOnlyLatestUserAvatarAndName: String { + return VectorL10n.tr("Vector", "settings_labs_use_only_latest_user_avatar_and_name") } /// LINKS public static var settingsLinks: String { diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift index f2e23c637a..e034f28f51 100644 --- a/Riot/Managers/Settings/RiotSettings.swift +++ b/Riot/Managers/Settings/RiotSettings.swift @@ -205,13 +205,13 @@ final class RiotSettings: NSObject { return self.roomScreenEnableMessageBubbles ? .bubble : .plain } - /// A setting used to display the latest known profile (display name + avatar) in the timeline - /// for the sender, rather than the profile at the time of the event. + /// A setting used to display the latest known display name and avatar in the timeline + /// for both the sender and target, rather than the profile at the time of the event. /// /// Note: this is set up from Room perspective, which means that if a user updates their profile after /// leaving a Room, it will show up the latest profile used in the Room rather than the latest overall. - @UserDefault(key: "roomScreenUseOnlyLatestProfiles", defaultValue: BuildSettings.roomScreenUseOnlyLatestProfiles, storage: defaults) - var roomScreenUseOnlyLatestProfiles + @UserDefault(key: "roomScreenUseOnlyLatestUserAvatarAndName", defaultValue: BuildSettings.roomScreenUseOnlyLatestUserAvatarAndName, storage: defaults) + var roomScreenUseOnlyLatestUserAvatarAndName // MARK: - Room Contextual Menu diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m index 6bd995ecef..a9f7dabd80 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellData.m @@ -58,8 +58,11 @@ - (instancetype)initWithEvent:(MXEvent *)event andRoomState:(MXRoomState *)roomS targetId = [event.type isEqualToString:kMXEventTypeStringRoomMember] ? event.stateKey : nil; roomId = roomDataSource.roomId; - MXRoomState *profileRoomState = RiotSettings.shared.roomScreenUseOnlyLatestProfiles ? roomDataSource.roomState : roomState; - [self setRoomState:profileRoomState]; + // If `roomScreenUseOnlyLatestUserAvatarAndName`is enabled, the avatar and name are + // displayed from the latest room state perspective rather than the historical. + MXRoomState *latestRoomState = roomDataSource.roomState; + MXRoomState *displayRoomState = RiotSettings.shared.roomScreenUseOnlyLatestUserAvatarAndName ? latestRoomState : roomState; + [self setRoomState:displayRoomState]; senderAvatarPlaceholder = nil; targetAvatarPlaceholder = nil; diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataWithAppendingMode.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataWithAppendingMode.m index 5baec1dd5e..70dda19a33 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataWithAppendingMode.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleCellDataWithAppendingMode.m @@ -48,9 +48,12 @@ - (BOOL)addEvent:(MXEvent*)event andRoomState:(MXRoomState*)roomState } // Check sender information - MXRoomState *profileRoomState = RiotSettings.shared.roomScreenUseOnlyLatestProfiles ? roomDataSource.roomState : roomState; - NSString *eventSenderName = [roomDataSource.eventFormatter senderDisplayNameForEvent:event withRoomState:profileRoomState]; - NSString *eventSenderAvatar = [roomDataSource.eventFormatter senderAvatarUrlForEvent:event withRoomState:profileRoomState]; + // If `roomScreenUseOnlyLatestUserAvatarAndName`is enabled, the avatar and name are + // displayed from the latest room state perspective rather than the historical. + MXRoomState *latestRoomState = roomDataSource.roomState; + MXRoomState *displayRoomState = RiotSettings.shared.roomScreenUseOnlyLatestUserAvatarAndName ? latestRoomState : roomState; + NSString *eventSenderName = [roomDataSource.eventFormatter senderDisplayNameForEvent:event withRoomState:displayRoomState]; + NSString *eventSenderAvatar = [roomDataSource.eventFormatter senderAvatarUrlForEvent:event withRoomState:displayRoomState]; if ((self.senderDisplayName || eventSenderName) && ([self.senderDisplayName isEqualToString:eventSenderName] == NO)) { diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m index b433e69747..1a2466a51f 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m @@ -4332,11 +4332,11 @@ - (void)virtualRoomsDidChange:(NSNotification *)notification /** Refreshes the avatars and display names if needed. This has no effect - if `roomScreenUseOnlyLatestProfiles` is disabled. + if `roomScreenUseOnlyLatestUserAvatarAndName` is disabled. */ - (void)refreshProfilesIfNeeded { - if (RiotSettings.shared.roomScreenUseOnlyLatestProfiles) + if (RiotSettings.shared.roomScreenUseOnlyLatestUserAvatarAndName) { @synchronized (bubbles) { for (id bubble in bubbles) diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 3832fabfde..fd931a2a5a 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -160,7 +160,7 @@ typedef NS_ENUM(NSUInteger, LABS_ENABLE) LABS_ENABLE_RINGING_FOR_GROUP_CALLS_INDEX = 0, LABS_ENABLE_THREADS_INDEX, LABS_ENABLE_MESSAGE_BUBBLES_INDEX, - LABS_USE_ONLY_LATEST_PROFILES_INDEX + LABS_USE_ONLY_LATEST_USER_AVATAR_AND_NAME_INDEX }; typedef NS_ENUM(NSUInteger, SECURITY) @@ -573,7 +573,7 @@ - (void)updateSections [sectionLabs addRowWithTag:LABS_ENABLE_RINGING_FOR_GROUP_CALLS_INDEX]; [sectionLabs addRowWithTag:LABS_ENABLE_THREADS_INDEX]; [sectionLabs addRowWithTag:LABS_ENABLE_MESSAGE_BUBBLES_INDEX]; - [sectionLabs addRowWithTag:LABS_USE_ONLY_LATEST_PROFILES_INDEX]; + [sectionLabs addRowWithTag:LABS_USE_ONLY_LATEST_USER_AVATAR_AND_NAME_INDEX]; sectionLabs.headerTitle = [VectorL10n settingsLabs]; if (sectionLabs.hasAnyRows) { @@ -2464,15 +2464,15 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N { cell = [self buildMessageBubblesCellForTableView:tableView atIndexPath:indexPath]; } - else if (row == LABS_USE_ONLY_LATEST_PROFILES_INDEX) + else if (row == LABS_USE_ONLY_LATEST_USER_AVATAR_AND_NAME_INDEX) { MXKTableViewCellWithLabelAndSwitch *labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; - labelAndSwitchCell.mxkLabel.text = VectorL10n.settingsLabsUseOnlyLatestProfiles; - labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.roomScreenUseOnlyLatestProfiles; + labelAndSwitchCell.mxkLabel.text = VectorL10n.settingsLabsUseOnlyLatestUserAvatarAndName; + labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.roomScreenUseOnlyLatestUserAvatarAndName; labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; - [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleUseOnlyLatestProfiles:) forControlEvents:UIControlEventTouchUpInside]; + [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleUseOnlyLatestUserAvatarAndName:) forControlEvents:UIControlEventTouchUpInside]; cell = labelAndSwitchCell; } @@ -3258,9 +3258,9 @@ - (void)toggleCommunityFlair:(UISwitch *)sender } } -- (void)toggleUseOnlyLatestProfiles:(UISwitch *)sender +- (void)toggleUseOnlyLatestUserAvatarAndName:(UISwitch *)sender { - RiotSettings.shared.roomScreenUseOnlyLatestProfiles = sender.isOn; + RiotSettings.shared.roomScreenUseOnlyLatestUserAvatarAndName = sender.isOn; } - (void)markAllAsRead:(id)sender