From 22d46417641840b9fc5c04247f6c4f64b64eff4c Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 22 Jul 2021 22:35:15 +0200 Subject: [PATCH 1/5] [Spaces] Show suggested in room lists #4501 - Request space suggested rooms in `RecentsDataSource` --- .../Recents/DataSources/RecentsDataSource.m | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 8679134d0..9672f7d47 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -1228,25 +1228,22 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou // FIXME manage multi accounts MXKSessionRecentsDataSource *recentsDataSource = displayedRecentsDataSourceArray[0]; - NSMutableArray> *cells = [NSMutableArray new]; - NSInteger count = recentsDataSource.numberOfCells; - - for (NSUInteger index = 0; index < count; index++) + if (self.currentSpace) { - id cell = [recentsDataSource cellDataAtIndex:index]; - if (self.currentSpace == nil || [self.currentSpace isRoomAChildWithRoomId:cell.roomSummary.roomId]) - { - [cells addObject:cell]; - } + [self.mxSession.spaceService getSpaceChildrenForSpaceWithId:self.currentSpace.spaceId suggestedOnly:YES limit:5 success:^(MXSpaceChildrenSummary * _Nonnull childrenSummary) { + MXLogDebug(@"[RecentDataSource] getSpaceChildrenForSpaceWithId : %@", childrenSummary.childInfos); + for (MXSpaceChildInfo *childInfo in childrenSummary.childInfos) + { + MXLogDebug(@"[RecentDataSource] getSpaceChildrenForSpaceWithId : %@", [self.mxSession roomWithRoomId:childInfo.childRoomId]); + } + [self computeRecentCellsWithRecentsDataSource:recentsDataSource completion:onComplete]; + } failure:^(NSError * _Nonnull error) { + MXLogError(@"[RecentDataSource] getSpaceChildrenForSpaceWithId failed with error: %@", error); + [self computeRecentCellsWithRecentsDataSource:recentsDataSource completion:onComplete]; + }]; } - MXWeakify(self); - [self computeStateAsyncWithCells:cells recentsDataSourceMode:self.recentsDataSourceMode matrixSession:recentsDataSource.mxSession onComplete:^(RecentsDataSourceState *newState) { - MXStrongifyAndReturnIfNil(self); - - self->state = newState; - onComplete(); - }]; + [self computeRecentCellsWithRecentsDataSource:recentsDataSource completion:onComplete]; } else { @@ -1254,6 +1251,29 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou } } +- (void)computeRecentCellsWithRecentsDataSource:(MXKSessionRecentsDataSource*) recentsDataSource completion:(void (^)(void))onComplete +{ + NSMutableArray> *cells = [NSMutableArray new]; + NSInteger count = recentsDataSource.numberOfCells; + + for (NSUInteger index = 0; index < count; index++) + { + id cell = [recentsDataSource cellDataAtIndex:index]; + if (self.currentSpace == nil || [self.currentSpace isRoomAChildWithRoomId:cell.roomSummary.roomId]) + { + [cells addObject:cell]; + } + } + + MXWeakify(self); + [self computeStateAsyncWithCells:cells recentsDataSourceMode:self.recentsDataSourceMode matrixSession:recentsDataSource.mxSession onComplete:^(RecentsDataSourceState *newState) { + MXStrongifyAndReturnIfNil(self); + + self->state = newState; + onComplete(); + }]; +} + - (void)computeStateAsyncWithCells:(NSArray> *)cells recentsDataSourceMode:(RecentsDataSourceMode)recentsDataSourceMode matrixSession:(MXSession*)mxSession From ac174fafdab2da44bd44faee856f52ed8973e714 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Thu, 29 Jul 2021 23:24:34 +0200 Subject: [PATCH 2/5] [Spaces] Show suggested in room lists #4501 - Show suggested rooms section in home screen (no actions) - Show suggested rooms section in rooms screen (no actions) --- Riot/Assets/en.lproj/Vector.strings | 1 + Riot/Categories/MXSpaceChildInfo.swift | 33 ++++ Riot/Generated/Strings.swift | 4 + .../Common/Recents/CellData/RecentCellData.m | 3 +- .../Recents/DataSources/RecentsDataSource.h | 4 +- .../Recents/DataSources/RecentsDataSource.m | 171 ++++++++++++------ .../DataSources/RecentsDataSourceState.swift | 3 + .../Recents/Views/RecentTableViewCell.m | 11 +- Riot/Modules/Home/HomeViewController.m | 3 +- .../Home/Views/RoomCollectionViewCell.m | 11 +- Riot/Modules/Rooms/RoomsViewController.m | 12 +- 11 files changed, 188 insertions(+), 68 deletions(-) create mode 100644 Riot/Categories/MXSpaceChildInfo.swift diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index e77f1a74f..6b3a35c98 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -189,6 +189,7 @@ "room_recents_low_priority_section" = "LOW PRIORITY"; "room_recents_server_notice_section" = "SYSTEM ALERTS"; "room_recents_invites_section" = "INVITES"; +"room_recents_suggested_rooms_section" = "SUGGESTED ROOMS"; "room_recents_start_chat_with" = "Start chat"; "room_recents_create_empty_room" = "Create room"; "room_recents_join_room" = "Join room"; diff --git a/Riot/Categories/MXSpaceChildInfo.swift b/Riot/Categories/MXSpaceChildInfo.swift new file mode 100644 index 000000000..01a5fa1f6 --- /dev/null +++ b/Riot/Categories/MXSpaceChildInfo.swift @@ -0,0 +1,33 @@ +// +// Copyright 2021 New Vector Ltd +// +// 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. +// + +import Foundation + +extension MXSpaceChildInfo { + func setRoomAvatarImage(in mxkImageView: MXKImageView, mediaManager: MXMediaManager) { + // Use the room display name to prepare the default avatar image. + let avatarDisplayName = self.name + let avatarImage = AvatarGenerator.generateAvatar(forText: avatarDisplayName) + + if let avatarUrl = self.avatarUrl { + mxkImageView.enableInMemoryCache = true + mxkImageView.setImageURI(avatarUrl, withType: nil, andImageOrientation: .up, toFitViewSize: mxkImageView.frame.size, with: MXThumbnailingMethodCrop, previewImage: avatarImage, mediaManager: mediaManager) + } else { + mxkImageView.image = avatarImage + } + mxkImageView.contentMode = .scaleAspectFill + } +} diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index e95e33ecd..17f595fa7 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -3402,6 +3402,10 @@ internal enum VectorL10n { internal static var roomRecentsStartChatWith: String { return VectorL10n.tr("Vector", "room_recents_start_chat_with") } + /// SUGGESTED ROOMS + internal static var roomRecentsSuggestedRoomsSection: String { + return VectorL10n.tr("Vector", "room_recents_suggested_rooms_section") + } /// Can't find this room. Make sure it exists internal static var roomRecentsUnknownRoomErrorMessage: String { return VectorL10n.tr("Vector", "room_recents_unknown_room_error_message") diff --git a/Riot/Modules/Common/Recents/CellData/RecentCellData.m b/Riot/Modules/Common/Recents/CellData/RecentCellData.m index a9def48fd..9d4e3dea8 100644 --- a/Riot/Modules/Common/Recents/CellData/RecentCellData.m +++ b/Riot/Modules/Common/Recents/CellData/RecentCellData.m @@ -18,6 +18,7 @@ #import "RecentCellData.h" #import "MXRoom+Riot.h" +#import "MatrixSDK-Swift.h" @implementation RecentCellData // trick to hide the mother class property as it is readonly one. @@ -57,7 +58,7 @@ - (void)update { [super update]; - roomDisplayname = self.roomSummary.displayname; + roomDisplayname = self.spaceChildInfo ? self.spaceChildInfo.name: self.roomSummary.displayname; if (!roomDisplayname.length) { roomDisplayname = [NSBundle mxk_localizedStringForKey:@"room_displayname_empty_room"]; diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h index 404cc3e36..a12e72d67 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h @@ -74,6 +74,7 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange; @property (nonatomic) NSInteger conversationSection; @property (nonatomic) NSInteger lowPrioritySection; @property (nonatomic) NSInteger serverNoticeSection; +@property (nonatomic) NSInteger suggestedRoomsSection; @property (nonatomic, readonly) NSArray* invitesCellDataArray; @property (nonatomic, readonly) NSArray* favoriteCellDataArray; @@ -81,6 +82,7 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange; @property (nonatomic, readonly) NSArray* conversationCellDataArray; @property (nonatomic, readonly) NSArray* lowPriorityCellDataArray; @property (nonatomic, readonly) NSArray* serverNoticeCellDataArray; +@property (nonatomic, readonly) NSArray* suggestedRoomCellDataArray; @property (nonatomic, readonly) SecureBackupBannerDisplay secureBackupBannerDisplay; @property (nonatomic, readonly) CrossSigningBannerDisplay crossSigningBannerDisplay; @@ -100,8 +102,6 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange; */ @property (nonatomic) PublicRoomsDirectoryDataSource *publicRoomsDirectoryDataSource; -@property (nonatomic, strong) MXSpace *currentSpace; - /** Refresh the recents data source and notify its delegate. */ diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index f1a110692..a8cccbefc 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -34,6 +34,7 @@ #define RECENTSDATASOURCE_SECTION_LOWPRIORITY 0x10 #define RECENTSDATASOURCE_SECTION_SERVERNOTICE 0x20 #define RECENTSDATASOURCE_SECTION_PEOPLE 0x40 +#define RECENTSDATASOURCE_SECTION_SUGGESTED 0x80 #define RECENTSDATASOURCE_DEFAULT_SECTION_HEADER_HEIGHT 30.0 @@ -56,11 +57,12 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou @property (nonatomic, assign, readwrite) CrossSigningBannerDisplay crossSigningBannerDisplay; @property (nonatomic, strong) CrossSigningService *crossSigningService; +@property (nonatomic, strong) NSArray *lastSuggestedRooms; @end @implementation RecentsDataSource -@synthesize directorySection, invitesSection, favoritesSection, peopleSection, conversationSection, lowPrioritySection, serverNoticeSection, secureBackupBannerSection, crossSigningBannerSection; +@synthesize directorySection, invitesSection, favoritesSection, peopleSection, conversationSection, lowPrioritySection, serverNoticeSection, suggestedRoomsSection, secureBackupBannerSection, crossSigningBannerSection; @synthesize hiddenCellIndexPath, droppingCellIndexPath, droppingCellBackGroundView; - (instancetype)init @@ -82,6 +84,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou conversationSection = -1; lowPrioritySection = -1; serverNoticeSection = -1; + suggestedRoomsSection = -1; _areSectionsShrinkable = NO; shrinkedSectionsBitMask = 0; @@ -129,6 +132,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou { return state.serverNoticeCellDataArray; } +- (NSArray *)suggestedRoomCellDataArray +{ + return state.suggestedRoomCellDataArray; +} - (NSUInteger)missedFavouriteDiscussionsCount { @@ -166,16 +173,6 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou return state.unsentMessagesGroupDiscussionsCount; } -- (void)setCurrentSpace:(MXSpace *)currentSpace -{ - MXLogDebug(@"[Spaces] setCurrentSpace %@", currentSpace.spaceId); - - _currentSpace = currentSpace; - [self refreshRoomsSection:^{ - [self.delegate dataSource:self didCellChange:nil]; - }]; -} - #pragma mark - - (void)setDelegate:(id)delegate andRecentsDataSourceMode:(RecentsDataSourceMode)recentsDataSourceMode @@ -479,6 +476,9 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou // Check whether all data sources are ready before rendering recents if (self.state == MXKDataSourceStateReady) { + + MXLogDebug(@"[Spaces] numberOfSectionsInTableView: suggestedRoomCellDataArray %ld", self->state.suggestedRoomCellDataArray.count); + crossSigningBannerSection = secureBackupBannerSection = directorySection = favoritesSection = peopleSection = conversationSection = lowPrioritySection = invitesSection = serverNoticeSection = -1; if (self.crossSigningBannerDisplay != CrossSigningBannerDisplayNone) @@ -520,6 +520,11 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou { serverNoticeSection = sectionsCount++; } + + if (self.suggestedRoomCellDataArray.count > 0) + { + suggestedRoomsSection = sectionsCount++; + } } return sectionsCount; @@ -572,6 +577,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou { count = self.invitesCellDataArray.count; } + else if (section == suggestedRoomsSection && !(shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION_SUGGESTED)) + { + count = self.suggestedRoomCellDataArray.count; + } // Adjust this count according to the potential dragged cell. if ([self isMovingCellSection:section]) @@ -653,6 +662,11 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou title = NSLocalizedStringFromTable(@"room_recents_invites_section", @"Vector", nil); } } + else if (section == suggestedRoomsSection) + { + count = self.suggestedRoomCellDataArray.count; + title = NSLocalizedStringFromTable(@"room_recents_suggested_rooms_section", @"Vector", nil); + } if (count) { @@ -704,6 +718,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou { sectionArray = self.serverNoticeCellDataArray; } + else if (section == suggestedRoomsSection) + { + sectionArray = self.suggestedRoomCellDataArray; + } BOOL highlight = NO; for (id cellData in sectionArray) @@ -789,6 +807,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou { sectionBitwise = RECENTSDATASOURCE_SECTION_INVITES; } + else if (section == suggestedRoomsSection) + { + sectionBitwise = RECENTSDATASOURCE_SECTION_SUGGESTED; + } } if (sectionBitwise) @@ -986,6 +1008,13 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou cellData = self.invitesCellDataArray[cellDataIndex]; } } + else if (tableSection == suggestedRoomsSection) + { + if (cellDataIndex < self.suggestedRoomCellDataArray.count) + { + cellData = self.suggestedRoomCellDataArray[cellDataIndex]; + } + } return cellData; } @@ -1042,9 +1071,19 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou { id cellDataStoring = cellDataArray[index]; - if ([roomId isEqualToString:cellDataStoring.roomSummary.roomId] && (matrixSession == cellDataStoring.roomSummary.room.mxSession)) + if (cellDataStoring.roomSummary) { - return index; + if ([roomId isEqualToString:cellDataStoring.roomSummary.roomId] && (matrixSession == cellDataStoring.roomSummary.room.mxSession)) + { + return index; + } + } + else if (cellDataStoring.spaceChildInfo) + { + if ([roomId isEqualToString:cellDataStoring.spaceChildInfo.name]) + { + return index; + } } } } @@ -1146,7 +1185,22 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou indexPath = [NSIndexPath indexPathForRow:index inSection:serverNoticeSection]; } } - + + if (!indexPath && (suggestedRoomsSection >= 0)) + { + index = [self cellIndexPosWithRoomId:roomId andMatrixSession:matrixSession within:self.serverNoticeCellDataArray]; + + if (index != NSNotFound) + { + // Check whether the low priority rooms are shrinked + if (shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION_SUGGESTED) + { + return nil; + } + indexPath = [NSIndexPath indexPathForRow:index inSection:serverNoticeSection]; + } + } + return indexPath; } @@ -1155,29 +1209,29 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou - (void)refreshRoomsSection:(void (^)(void))onComplete; { - secureBackupBannerSection = directorySection = favoritesSection = peopleSection = conversationSection = lowPrioritySection = serverNoticeSection = invitesSection = -1; + secureBackupBannerSection = directorySection = favoritesSection = peopleSection = conversationSection = lowPrioritySection = serverNoticeSection = suggestedRoomsSection = invitesSection = -1; if (displayedRecentsDataSourceArray.count > 0) { // FIXME manage multi accounts MXKSessionRecentsDataSource *recentsDataSource = displayedRecentsDataSourceArray[0]; - if (self.currentSpace) + NSMutableArray> *cells = [NSMutableArray new]; + NSInteger count = recentsDataSource.numberOfCells; + + for (NSUInteger index = 0; index < count; index++) { - [self.mxSession.spaceService getSpaceChildrenForSpaceWithId:self.currentSpace.spaceId suggestedOnly:YES limit:5 success:^(MXSpaceChildrenSummary * _Nonnull childrenSummary) { - MXLogDebug(@"[RecentDataSource] getSpaceChildrenForSpaceWithId : %@", childrenSummary.childInfos); - for (MXSpaceChildInfo *childInfo in childrenSummary.childInfos) - { - MXLogDebug(@"[RecentDataSource] getSpaceChildrenForSpaceWithId : %@", [self.mxSession roomWithRoomId:childInfo.childRoomId]); - } - [self computeRecentCellsWithRecentsDataSource:recentsDataSource completion:onComplete]; - } failure:^(NSError * _Nonnull error) { - MXLogError(@"[RecentDataSource] getSpaceChildrenForSpaceWithId failed with error: %@", error); - [self computeRecentCellsWithRecentsDataSource:recentsDataSource completion:onComplete]; - }]; + id cell = [recentsDataSource cellDataAtIndex:index]; + [cells addObject:cell]; } - - [self computeRecentCellsWithRecentsDataSource:recentsDataSource completion:onComplete]; + + MXWeakify(self); + [self computeStateAsyncWithCells:cells recentsDataSourceMode:self.recentsDataSourceMode matrixSession:recentsDataSource.mxSession onComplete:^(RecentsDataSourceState *newState) { + MXStrongifyAndReturnIfNil(self); + + self->state = newState; + onComplete(); + }]; } else { @@ -1185,32 +1239,6 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou } } -- (void)computeRecentCellsWithRecentsDataSource:(MXKSessionRecentsDataSource*) recentsDataSource completion:(void (^)(void))onComplete -{ - NSMutableArray> *cells = [NSMutableArray new]; - NSInteger count = recentsDataSource.numberOfCells; - - NSDate *startDate = [NSDate new]; - MXLogDebug(@"[Spaces] starting filtering rooms"); - for (NSUInteger index = 0; index < count; index++) - { - id cell = [recentsDataSource cellDataAtIndex:index]; - if (self.currentSpace == nil || [self.mxSession.spaceService isRoomWithId:cell.roomSummary.roomId descendantOf:self.currentSpace.spaceId]) - { - [cells addObject:cell]; - } - } - MXLogDebug(@"[Spaces] ended filtering rooms after %f", [[NSDate new] timeIntervalSinceDate:startDate]); - - MXWeakify(self); - [self computeStateAsyncWithCells:cells recentsDataSourceMode:self.recentsDataSourceMode matrixSession:recentsDataSource.mxSession onComplete:^(RecentsDataSourceState *newState) { - MXStrongifyAndReturnIfNil(self); - - self->state = newState; - onComplete(); - }]; -} - - (void)computeStateAsyncWithCells:(NSArray> *)cells recentsDataSourceMode:(RecentsDataSourceMode)recentsDataSourceMode matrixSession:(MXSession*)mxSession @@ -1236,7 +1264,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou NSMutableArray> *conversationCellDataArray = [NSMutableArray new]; NSMutableArray> *lowPriorityCellDataArray = [NSMutableArray new]; NSMutableArray> *serverNoticeCellDataArray = [NSMutableArray new]; - + NSMutableArray> *suggestedRoomCellDataArray = [NSMutableArray new]; + MissedDiscussionsCount *favouriteMissedDiscussionsCount = [MissedDiscussionsCount new]; MissedDiscussionsCount *directMissedDiscussionsCount = [MissedDiscussionsCount new]; MissedDiscussionsCount *groupMissedDiscussionsCount = [MissedDiscussionsCount new]; @@ -1272,6 +1301,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou { [peopleCellDataArray addObject:recentCellDataStoring]; } + else if (recentCellDataStoring.spaceChildInfo != nil) + { + [suggestedRoomCellDataArray addObject:recentCellDataStoring]; + } else { // Hide spaces from home (keep space invites) @@ -1310,8 +1343,12 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou } else if (recentsDataSourceMode == RecentsDataSourceModeRooms) { + if (recentCellDataStoring.spaceChildInfo) + { + [suggestedRoomCellDataArray addObject:recentCellDataStoring]; + } // Consider only non direct rooms. - if (!room.isDirect) + else if (!room.isDirect) { // Keep only the invites, the favourites and the rooms without tag and room type different from space if (room.summary.membership == MXMembershipInvite) @@ -1405,6 +1442,15 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou // Sort each rooms collection by considering first the rooms with some missed notifs, the rooms with unread, then the others. comparator = ^NSComparisonResult(id recentCellData1, id recentCellData2) { + if (recentCellData1.spaceChildInfo && !recentCellData2.spaceChildInfo) + { + return NSOrderedDescending; + } + if (recentCellData2.spaceChildInfo && !recentCellData1.spaceChildInfo) + { + return NSOrderedAscending; + } + if (recentCellData1.roomSummary.room.sentStatus != RoomSentStatusOk && recentCellData2.roomSummary.room.sentStatus == RoomSentStatusOk) { @@ -1474,6 +1520,15 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou // Sort each rooms collection by considering first the rooms with some unread messages then the others. comparator = ^NSComparisonResult(id recentCellData1, id recentCellData2) { + if (recentCellData1.spaceChildInfo && !recentCellData2.spaceChildInfo) + { + return NSOrderedDescending; + } + if (recentCellData2.spaceChildInfo && !recentCellData1.spaceChildInfo) + { + return NSOrderedAscending; + } + if (recentCellData1.roomSummary.room.sentStatus != RoomSentStatusOk && recentCellData2.roomSummary.room.sentStatus == RoomSentStatusOk) { @@ -1546,6 +1601,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou } MXLogDebug(@"[RecentsDataSource] refreshRoomsSections: Done in %.0fms", [[NSDate date] timeIntervalSinceDate:startDate] * 1000); + MXLogDebug(@"[Spaces] refreshRoomsSections with %ld suggested room", suggestedRoomCellDataArray.count); return [[RecentsDataSourceState alloc] initWithInvitesCellDataArray:invitesCellDataArray @@ -1554,6 +1610,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou conversationCellDataArray:conversationCellDataArray lowPriorityCellDataArray:lowPriorityCellDataArray serverNoticeCellDataArray:serverNoticeCellDataArray + suggestedRoomCellDataArray:suggestedRoomCellDataArray favouriteMissedDiscussionsCount:favouriteMissedDiscussionsCount directMissedDiscussionsCount:directMissedDiscussionsCount groupMissedDiscussionsCount:groupMissedDiscussionsCount diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSourceState.swift b/Riot/Modules/Common/Recents/DataSources/RecentsDataSourceState.swift index 5f7b376dd..1cadbec71 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSourceState.swift +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSourceState.swift @@ -29,6 +29,7 @@ class RecentsDataSourceState: NSObject { let conversationCellDataArray: [MXKRecentCellDataStoring] let lowPriorityCellDataArray: [MXKRecentCellDataStoring] let serverNoticeCellDataArray: [MXKRecentCellDataStoring] + let suggestedRoomCellDataArray: [MXKRecentCellDataStoring] // MARK: Notifications counts let favouriteMissedDiscussionsCount: MissedDiscussionsCount @@ -47,6 +48,7 @@ class RecentsDataSourceState: NSObject { conversationCellDataArray: [MXKRecentCellDataStoring], lowPriorityCellDataArray: [MXKRecentCellDataStoring], serverNoticeCellDataArray: [MXKRecentCellDataStoring], + suggestedRoomCellDataArray: [MXKRecentCellDataStoring], favouriteMissedDiscussionsCount: MissedDiscussionsCount, directMissedDiscussionsCount: MissedDiscussionsCount, groupMissedDiscussionsCount: MissedDiscussionsCount, @@ -58,6 +60,7 @@ class RecentsDataSourceState: NSObject { self.conversationCellDataArray = conversationCellDataArray self.lowPriorityCellDataArray = lowPriorityCellDataArray self.serverNoticeCellDataArray = serverNoticeCellDataArray + self.suggestedRoomCellDataArray = suggestedRoomCellDataArray self.favouriteMissedDiscussionsCount = favouriteMissedDiscussionsCount self.directMissedDiscussionsCount = directMissedDiscussionsCount self.groupMissedDiscussionsCount = groupMissedDiscussionsCount diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index 37e70eed6..7174b4744 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -91,7 +91,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; self.lastEventDate.text = roomCellData.lastEventDate; // Manage lastEventAttributedTextMessage optional property - if ([roomCellData respondsToSelector:@selector(lastEventAttributedTextMessage)]) + if (!roomCellData.spaceChildInfo && [roomCellData respondsToSelector:@selector(lastEventAttributedTextMessage)]) { // Force the default text color for the last message (cancel highlighted message color) NSMutableAttributedString *lastEventDescription = [[NSMutableAttributedString alloc] initWithAttributedString:roomCellData.lastEventAttributedTextMessage]; @@ -141,7 +141,14 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; self.directRoomBorderView.hidden = !roomCellData.roomSummary.room.isDirect; - [roomCellData.roomSummary setRoomAvatarImageIn:self.roomAvatar]; + if (roomCellData.spaceChildInfo) + { + [roomCellData.spaceChildInfo setRoomAvatarImageIn:self.roomAvatar mediaManager:roomCellData.recentsDataSource.mxSession.mediaManager]; + } + else + { + [roomCellData.roomSummary setRoomAvatarImageIn:self.roomAvatar]; + } } else { diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index 74fef7d37..d86313b39 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -856,7 +856,8 @@ + recentsDataSource.peopleCellDataArray.count + recentsDataSource.conversationCellDataArray.count + recentsDataSource.lowPriorityCellDataArray.count - + recentsDataSource.serverNoticeCellDataArray.count; + + recentsDataSource.serverNoticeCellDataArray.count + + recentsDataSource.suggestedRoomCellDataArray.count; } @end diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index 1c53b20e2..0c49a9149 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -147,7 +147,14 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; self.directRoomBorderView.hidden = !roomCellData.roomSummary.room.isDirect; - [roomCellData.roomSummary setRoomAvatarImageIn:self.roomAvatar]; + if (roomCellData.roomSummary) + { + [roomCellData.roomSummary setRoomAvatarImageIn:self.roomAvatar]; + } + else + { + [roomCellData.spaceChildInfo setRoomAvatarImageIn:self.roomAvatar mediaManager:roomCellData.recentsDataSource.mxSession.mediaManager]; + } } } @@ -188,7 +195,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; { if (roomCellData) { - return roomCellData.roomSummary.roomId; + return roomCellData.spaceChildInfo ? roomCellData.spaceChildInfo.childRoomId : roomCellData.roomSummary.roomId; } return nil; } diff --git a/Riot/Modules/Rooms/RoomsViewController.m b/Riot/Modules/Rooms/RoomsViewController.m index 979b30610..19a37050b 100644 --- a/Riot/Modules/Rooms/RoomsViewController.m +++ b/Riot/Modules/Rooms/RoomsViewController.m @@ -103,8 +103,13 @@ - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { - // Hide the header to merge Invites and Rooms into a single list. - return 0.0; + if ([tableView numberOfSections] <= 1) + { + // Hide the header to merge Invites and Rooms into a single list. + return 0.0; + } + + return [super tableView:tableView heightForHeaderInSection:section]; } #pragma mark - @@ -155,7 +160,8 @@ - (NSUInteger)totalItemCounts { return recentsDataSource.conversationCellDataArray.count - + recentsDataSource.invitesCellDataArray.count; + + recentsDataSource.invitesCellDataArray.count + + recentsDataSource.suggestedRoomCellDataArray.count; } @end From 495c4831ed8cbfe37e534729f3dc68f58386aad8 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Tue, 3 Aug 2021 13:45:22 +0200 Subject: [PATCH 3/5] [Spaces] Show suggested in room lists #4501 - Preview suggested rooms --- Riot/Model/Room/RoomPreviewData.h | 8 ++++++++ Riot/Model/Room/RoomPreviewData.m | 16 ++++++++++++++++ .../Recents/DataSources/RecentsDataSource.m | 15 ++++++++++++--- .../Common/Recents/RecentsViewController.m | 12 ++++++++++++ Riot/Modules/Home/HomeViewController.m | 9 ++++++++- 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/Riot/Model/Room/RoomPreviewData.h b/Riot/Model/Room/RoomPreviewData.h index c10295617..f6f51bdca 100644 --- a/Riot/Model/Room/RoomPreviewData.h +++ b/Riot/Model/Room/RoomPreviewData.h @@ -97,6 +97,14 @@ */ - (instancetype)initWithPublicRoom:(MXPublicRoom*)publicRoom andSession:(MXSession*)mxSession; +/** + Contructors. + + @param childInfo MXSpaceChildInfo instance that describes the child. + @param mxSession the session to open the room preview with. + */ +- (instancetype)initWithSpaceChildInfo:(MXSpaceChildInfo*)childInfo andSession:(MXSession*)mxSession; + /** Attempt to peek into the room to get room data (state, messages history, etc). diff --git a/Riot/Model/Room/RoomPreviewData.m b/Riot/Model/Room/RoomPreviewData.m index 74738367a..07ece4510 100644 --- a/Riot/Model/Room/RoomPreviewData.m +++ b/Riot/Model/Room/RoomPreviewData.m @@ -16,6 +16,7 @@ */ #import "RoomPreviewData.h" +#import @implementation RoomPreviewData @@ -79,6 +80,21 @@ return self; } +- (instancetype)initWithSpaceChildInfo:(MXSpaceChildInfo*)childInfo andSession:(MXSession*)mxSession +{ + self = [self init]; + if (self) + { + _roomId = childInfo.childRoomId; + _roomName = childInfo.name; + _roomAvatarUrl = childInfo.avatarUrl; + _roomTopic = childInfo.topic; + _numJoinedMembers = childInfo.activeMemberCount; + _mxSession = mxSession; + } + return self; +} + - (void)dealloc { if (_roomDataSource) diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 963ca2703..dbb26f8bc 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -57,7 +57,6 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou @property (nonatomic, assign, readwrite) CrossSigningBannerDisplay crossSigningBannerDisplay; @property (nonatomic, strong) CrossSigningService *crossSigningService; -@property (nonatomic, strong) NSArray *lastSuggestedRooms; @end @@ -1301,7 +1300,12 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou } else if (recentCellDataStoring.spaceChildInfo != nil) { - [suggestedRoomCellDataArray addObject:recentCellDataStoring]; + MXRoomSummary *roomSummary = [mxSession roomSummaryWithRoomId:recentCellDataStoring.spaceChildInfo.childRoomId]; + BOOL isJoined = roomSummary.membership == MXMembershipJoin || roomSummary.membershipTransitionState == MXMembershipTransitionStateJoined; + if (!isJoined) + { + [suggestedRoomCellDataArray addObject:recentCellDataStoring]; + } } else { @@ -1343,7 +1347,12 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou { if (recentCellDataStoring.spaceChildInfo) { - [suggestedRoomCellDataArray addObject:recentCellDataStoring]; + MXRoomSummary *roomSummary = [mxSession roomSummaryWithRoomId:recentCellDataStoring.spaceChildInfo.childRoomId]; + BOOL isJoined = roomSummary.membership == MXMembershipJoin || roomSummary.membershipTransitionState == MXMembershipTransitionStateJoined; + if (!isJoined) + { + [suggestedRoomCellDataArray addObject:recentCellDataStoring]; + } } // Consider only non direct rooms. else if (!room.isDirect) diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index e76a83cab..72de7f836 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -2051,6 +2051,18 @@ [self dispayRoomWithRoomId:roomId inMatrixSession:matrixSession]; } +- (void)recentListViewController:(MXKRecentListViewController *)recentListViewController didSelectSuggestedRoom:(MXSpaceChildInfo *)childInfo +{ + RoomPreviewData *previewData = [[RoomPreviewData alloc] initWithSpaceChildInfo:childInfo andSession:self.mainSession]; + [self startActivityIndicator]; + MXWeakify(self); + [previewData peekInRoom:^(BOOL succeeded) { + MXStrongifyAndReturnIfNil(self); + [self stopActivityIndicator]; + [[AppDelegate theDelegate].masterTabBarController showRoomPreview:previewData]; + }]; +} + #pragma mark - UISearchBarDelegate - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index d86313b39..c1c89ba4e 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -557,7 +557,14 @@ id renderedCellData = (id)roomCollectionViewCell.renderedCellData; - [self.delegate recentListViewController:self didSelectRoom:renderedCellData.roomSummary.roomId inMatrixSession:renderedCellData.roomSummary.room.mxSession]; + if (renderedCellData.spaceChildInfo) + { + [self.delegate recentListViewController:self didSelectSuggestedRoom:renderedCellData.spaceChildInfo]; + } + else + { + [self.delegate recentListViewController:self didSelectRoom:renderedCellData.roomSummary.roomId inMatrixSession:renderedCellData.roomSummary.room.mxSession]; + } } // Hide the keyboard when user select a room From 41bfde70719d8c8a2c11dc38afe0a019416e9814 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Mon, 16 Aug 2021 07:57:30 +0200 Subject: [PATCH 4/5] [Spaces] Show suggested in room lists #4501 - Update after code review --- Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m | 4 ++-- Riot/Modules/Home/HomeViewController.m | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 51ea199e3..1b1c5e0c9 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -1298,7 +1298,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou { [peopleCellDataArray addObject:recentCellDataStoring]; } - else if (recentCellDataStoring.spaceChildInfo != nil) + else if (recentCellDataStoring.isSuggestedRoom) { MXRoomSummary *roomSummary = [mxSession roomSummaryWithRoomId:recentCellDataStoring.spaceChildInfo.childRoomId]; BOOL isJoined = roomSummary.membership == MXMembershipJoin || roomSummary.membershipTransitionState == MXMembershipTransitionStateJoined; @@ -1345,7 +1345,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou } else if (recentsDataSourceMode == RecentsDataSourceModeRooms) { - if (recentCellDataStoring.spaceChildInfo) + if (recentCellDataStoring.isSuggestedRoom) { MXRoomSummary *roomSummary = [mxSession roomSummaryWithRoomId:recentCellDataStoring.spaceChildInfo.childRoomId]; BOOL isJoined = roomSummary.membership == MXMembershipJoin || roomSummary.membershipTransitionState == MXMembershipTransitionStateJoined; diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index c1c89ba4e..be537d6d7 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -557,7 +557,7 @@ id renderedCellData = (id)roomCollectionViewCell.renderedCellData; - if (renderedCellData.spaceChildInfo) + if (renderedCellData.isSuggestedRoom) { [self.delegate recentListViewController:self didSelectSuggestedRoom:renderedCellData.spaceChildInfo]; } From 33ba0b3e90637e33e185e20283a9062875cd6f55 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Mon, 16 Aug 2021 10:33:10 +0200 Subject: [PATCH 5/5] [Spaces] Show suggested in room lists #4501 - Update after code review --- ...paceChildInfo.swift => MXKImageView.swift} | 21 +++++++++---------- .../Recents/Views/RecentTableViewCell.m | 4 ++-- .../Home/Views/RoomCollectionViewCell.m | 4 ++-- 3 files changed, 14 insertions(+), 15 deletions(-) rename Riot/Categories/{MXSpaceChildInfo.swift => MXKImageView.swift} (51%) diff --git a/Riot/Categories/MXSpaceChildInfo.swift b/Riot/Categories/MXKImageView.swift similarity index 51% rename from Riot/Categories/MXSpaceChildInfo.swift rename to Riot/Categories/MXKImageView.swift index 01a5fa1f6..5f32960ed 100644 --- a/Riot/Categories/MXSpaceChildInfo.swift +++ b/Riot/Categories/MXKImageView.swift @@ -16,18 +16,17 @@ import Foundation -extension MXSpaceChildInfo { - func setRoomAvatarImage(in mxkImageView: MXKImageView, mediaManager: MXMediaManager) { - // Use the room display name to prepare the default avatar image. - let avatarDisplayName = self.name - let avatarImage = AvatarGenerator.generateAvatar(forText: avatarDisplayName) - - if let avatarUrl = self.avatarUrl { - mxkImageView.enableInMemoryCache = true - mxkImageView.setImageURI(avatarUrl, withType: nil, andImageOrientation: .up, toFitViewSize: mxkImageView.frame.size, with: MXThumbnailingMethodCrop, previewImage: avatarImage, mediaManager: mediaManager) +extension MXKImageView { + @objc func vc_setRoomAvatarImage(with url: String?, displayName: String, mediaManager: MXMediaManager) { + // Use the display name to prepare the default avatar image. + let avatarImage = AvatarGenerator.generateAvatar(forText: displayName) + + if let avatarUrl = url { + self.enableInMemoryCache = true + self.setImageURI(avatarUrl, withType: nil, andImageOrientation: .up, toFitViewSize: self.frame.size, with: MXThumbnailingMethodCrop, previewImage: avatarImage, mediaManager: mediaManager) } else { - mxkImageView.image = avatarImage + self.image = avatarImage } - mxkImageView.contentMode = .scaleAspectFill + self.contentMode = .scaleAspectFill } } diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index 7174b4744..7fc01bf9c 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -143,11 +143,11 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (roomCellData.spaceChildInfo) { - [roomCellData.spaceChildInfo setRoomAvatarImageIn:self.roomAvatar mediaManager:roomCellData.recentsDataSource.mxSession.mediaManager]; + [self.roomAvatar vc_setRoomAvatarImageWith:roomCellData.spaceChildInfo.avatarUrl displayName:roomCellData.spaceChildInfo.name mediaManager:roomCellData.recentsDataSource.mxSession.mediaManager]; } else { - [roomCellData.roomSummary setRoomAvatarImageIn:self.roomAvatar]; + [self.roomAvatar vc_setRoomAvatarImageWith:roomCellData.roomSummary.avatar displayName:roomCellData.roomSummary.displayname mediaManager:roomCellData.roomSummary.mxSession.mediaManager]; } } else diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index 0c49a9149..ae407cdc2 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -149,11 +149,11 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (roomCellData.roomSummary) { - [roomCellData.roomSummary setRoomAvatarImageIn:self.roomAvatar]; + [self.roomAvatar vc_setRoomAvatarImageWith:roomCellData.roomSummary.avatar displayName:roomCellData.roomSummary.displayname mediaManager:roomCellData.roomSummary.mxSession.mediaManager]; } else { - [roomCellData.spaceChildInfo setRoomAvatarImageIn:self.roomAvatar mediaManager:roomCellData.recentsDataSource.mxSession.mediaManager]; + [self.roomAvatar vc_setRoomAvatarImageWith:roomCellData.spaceChildInfo.avatarUrl displayName:roomCellData.spaceChildInfo.name mediaManager:roomCellData.recentsDataSource.mxSession.mediaManager]; } } }