diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h index 40041269f..e571a7850 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h @@ -19,7 +19,7 @@ #import "PublicRoomsDirectoryDataSource.h" -@protocol MXKRecentCellDataStoring; +@protocol RecentsListServiceProtocol; @class DiscussionsCount; @class MXSpace; @@ -77,17 +77,40 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange; @property (nonatomic) NSInteger serverNoticeSection; @property (nonatomic) NSInteger suggestedRoomsSection; -@property (nonatomic, readonly) NSArray> *invitesCellDataArray; -@property (nonatomic, readonly) NSArray> *favoriteCellDataArray; -@property (nonatomic, readonly) NSArray> *peopleCellDataArray; -@property (nonatomic, readonly) NSArray> *conversationCellDataArray; -@property (nonatomic, readonly) NSArray> *lowPriorityCellDataArray; -@property (nonatomic, readonly) NSArray> *serverNoticeCellDataArray; -@property (nonatomic, readonly) NSArray> *suggestedRoomCellDataArray; +@property (nonatomic, readonly) NSInteger totalVisibleItemCount; + +/** + Counts for favorited rooms. + */ +@property (nonatomic, readonly) DiscussionsCount *favoriteMissedDiscussionsCount; + +/** + Counts for direct rooms. + */ +@property (nonatomic, readonly) DiscussionsCount *directMissedDiscussionsCount; + +/** + Counts for group rooms. + */ +@property (nonatomic, readonly) DiscussionsCount *groupMissedDiscussionsCount; @property (nonatomic, readonly) SecureBackupBannerDisplay secureBackupBannerDisplay; @property (nonatomic, readonly) CrossSigningBannerDisplay crossSigningBannerDisplay; +@property (nonatomic, readonly) id recentsListService; + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithMatrixSession:(MXSession*)mxSession NS_UNAVAILABLE; + +/** + Initializer + @param mxSession session instance + @param recentsListService service instance + */ +- (instancetype)initWithMatrixSession:(MXSession*)mxSession + recentsListService:(id)recentsListService; + /** Set the delegate by specifying the selected display mode. */ @@ -164,19 +187,4 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange; */ - (void)moveRoomCell:(MXRoom*)room from:(NSIndexPath*)oldPath to:(NSIndexPath*)newPath success:(void (^)(void))moveSuccess failure:(void (^)(NSError *error))moveFailure; -/** - Counts for favorited rooms. - */ -@property (nonatomic, readonly) DiscussionsCount *favoriteMissedDiscussionsCount; - -/** - Counts for direct rooms. - */ -@property (nonatomic, readonly) DiscussionsCount *directMissedDiscussionsCount; - -/** - Counts for group rooms. - */ -@property (nonatomic, readonly) DiscussionsCount *groupMissedDiscussionsCount; - @end diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index a150dba6b..1bc561396 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -41,7 +41,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSourceTapOnDirectoryServerChange"; -@interface RecentsDataSource() +@interface RecentsDataSource() { dispatch_queue_t processingQueue; @@ -51,13 +51,13 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou // Timer to not refresh publicRoomsDirectoryDataSource on every keystroke. NSTimer *publicRoomsTriggerTimer; - - RecentsRoomListFetchersContainer *fetchersContainer; } @property (nonatomic, assign, readwrite) SecureBackupBannerDisplay secureBackupBannerDisplay; @property (nonatomic, assign, readwrite) CrossSigningBannerDisplay crossSigningBannerDisplay; +@property (nonatomic, readwrite) id recentsListService; + @property (nonatomic, strong) CrossSigningService *crossSigningService; @end @@ -66,10 +66,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou @synthesize directorySection, invitesSection, favoritesSection, peopleSection, conversationSection, lowPrioritySection, serverNoticeSection, suggestedRoomsSection, secureBackupBannerSection, crossSigningBannerSection; @synthesize hiddenCellIndexPath, droppingCellIndexPath, droppingCellBackGroundView; -- (instancetype)init +- (instancetype)initWithMatrixSession:(MXSession *)mxSession + recentsListService:(id)theRecentsListService { - self = [super init]; - if (self) + if (self = [super initWithMatrixSession:mxSession]) { processingQueue = dispatch_queue_create("RecentsDataSource", DISPATCH_QUEUE_SERIAL); @@ -89,21 +89,12 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou [self registerCellDataClass:RecentCellData.class forCellIdentifier:kMXKRecentCellIdentifier]; [self registerSpaceServiceDidBuildGraphNotification]; + self.recentsListService = theRecentsListService; + [self.recentsListService addDelegate:self]; } return self; } -- (void)finalizeInitialization -{ - [super finalizeInitialization]; - - fetchersContainer = [[RecentsRoomListFetchersContainer alloc] initWithSession:self.mxSession - mode:_recentsDataSourceMode - query:nil - space:nil]; - [fetchersContainer addDelegate:self]; -} - - (void)dealloc { [self unregisterSpaceServiceDidBuildGraphNotification]; @@ -127,82 +118,59 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou - (NSArray> *)invitesCellDataArray { - if (!fetchersContainer.shouldShowInvited) - { - return nil; - } - return [self mapRoomSummaries:fetchersContainer.invitedRoomListDataFetcher.data.rooms]; + return [self mapRoomSummaries:self.recentsListService.invitedRoomListData.rooms]; } - (NSArray> *)favoriteCellDataArray { - if (!fetchersContainer.shouldShowFavorited) - { - return nil; - } - return [self mapRoomSummaries:fetchersContainer.favoritedRoomListDataFetcher.data.rooms]; + return [self mapRoomSummaries:self.recentsListService.favoritedRoomListData.rooms]; } - (NSArray> *)peopleCellDataArray { - if (!fetchersContainer.shouldShowDirect) - { - return nil; - } - return [self mapRoomSummaries:fetchersContainer.directRoomListDataFetcher.data.rooms]; + return [self mapRoomSummaries:self.recentsListService.peopleRoomListData.rooms]; } - (NSArray> *)conversationCellDataArray { - if (!fetchersContainer.shouldShowConversation) - { - return nil; - } - return [self mapRoomSummaries:fetchersContainer.conversationRoomListDataFetcher.data.rooms]; + return [self mapRoomSummaries:self.recentsListService.conversationRoomListData.rooms]; } - (NSArray> *)lowPriorityCellDataArray { - if (!fetchersContainer.shouldShowLowPriority) - { - return nil; - } - return [self mapRoomSummaries:fetchersContainer.lowPriorityRoomListDataFetcher.data.rooms]; + return [self mapRoomSummaries:self.recentsListService.lowPriorityRoomListData.rooms]; } - (NSArray> *)serverNoticeCellDataArray { - if (!fetchersContainer.shouldShowServerNotice) - { - return nil; - } - return [self mapRoomSummaries:fetchersContainer.serverNoticeRoomListDataFetcher.data.rooms]; + return [self mapRoomSummaries:self.recentsListService.serverNoticeRoomListData.rooms]; } - (NSArray> *)suggestedRoomCellDataArray { - if (!fetchersContainer.shouldShowSuggested) - { - return nil; - } - return [self mapRoomSummaries:fetchersContainer.suggestedRoomListDataFetcher.data.rooms]; + return [self mapRoomSummaries:self.recentsListService.suggestedRoomListData.rooms]; +} + +- (NSArray> *)mapRoomSummaries:(NSArray> *)summaries + { + return [summaries vc_map:^id _Nonnull(id _Nonnull summary) { + return [[MXKRecentCellData alloc] initWithRoomSummary:summary + dataSource:self]; + }]; + } + +- (NSInteger)totalVisibleItemCount +{ + return self.recentsListService.totalVisibleItemCount; } - (DiscussionsCount *)favoriteMissedDiscussionsCount { - return fetchersContainer.favoritedMissedDiscussionsCount; + return self.recentsListService.favoritedMissedDiscussionsCount; } - (DiscussionsCount *)directMissedDiscussionsCount { - return fetchersContainer.directMissedDiscussionsCount; + return self.recentsListService.peopleMissedDiscussionsCount; } - (DiscussionsCount *)groupMissedDiscussionsCount { - return fetchersContainer.conversationMissedDiscussionsCount; -} - -- (NSArray> *)mapRoomSummaries:(NSArray> *)summaries -{ - return [summaries vc_map:^id _Nonnull(id _Nonnull summary) { - return [[MXKRecentCellData alloc] initWithRoomSummary:summary - dataSource:self]; - }]; + return self.recentsListService.conversationMissedDiscussionsCount; } #pragma mark - @@ -230,12 +198,12 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou [self updateSecureBackupBanner]; [self refreshCrossSigningBannerDisplay]; - [fetchersContainer updateMode:_recentsDataSourceMode]; + [self.recentsListService updateMode:_recentsDataSourceMode]; } - (void)setCurrentSpace:(MXSpace *)currentSpace { - [fetchersContainer updateSpace:currentSpace]; + [self.recentsListService updateSpace:currentSpace]; } - (UIView *)viewForStickyHeaderInSection:(NSInteger)section withFrame:(CGRect)frame @@ -479,7 +447,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou // Refresh is disabled during drag&drop animation" if (!self.droppingCellIndexPath) { - [fetchersContainer refresh]; + [self.recentsListService refresh]; } } @@ -723,61 +691,54 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou - (UIView *)badgeViewForHeaderTitleInHomeSection:(NSInteger)section { // Prepare a badge to display the total of missed notifications in this section. - NSUInteger totalNotificationCount = 0; - NSUInteger totalHighlightCount = 0; + id counts = nil; UIView *missedNotifAndUnreadBadgeBgView = nil; if (section == favoritesSection) { - totalNotificationCount = fetchersContainer.favoritedRoomListDataFetcher.data.counts.totalNotificationCount; - totalHighlightCount = fetchersContainer.favoritedRoomListDataFetcher.data.counts.totalHighlightCount; + counts = self.recentsListService.favoritedRoomListData.counts; } else if (section == peopleSection) { - totalNotificationCount = fetchersContainer.directRoomListDataFetcher.data.counts.totalNotificationCount; - totalHighlightCount = fetchersContainer.directRoomListDataFetcher.data.counts.totalHighlightCount; + counts = self.recentsListService.peopleRoomListData.counts; } else if (section == conversationSection) { - totalNotificationCount = fetchersContainer.conversationRoomListDataFetcher.data.counts.totalNotificationCount; - totalHighlightCount = fetchersContainer.conversationRoomListDataFetcher.data.counts.totalHighlightCount; + counts = self.recentsListService.conversationRoomListData.counts; } else if (section == lowPrioritySection) { - totalNotificationCount = fetchersContainer.lowPriorityRoomListDataFetcher.data.counts.totalNotificationCount; - totalHighlightCount = fetchersContainer.lowPriorityRoomListDataFetcher.data.counts.totalHighlightCount; + counts = self.recentsListService.lowPriorityRoomListData.counts; } else if (section == serverNoticeSection) { - totalNotificationCount = fetchersContainer.serverNoticeRoomListDataFetcher.data.counts.totalNotificationCount; - totalHighlightCount = fetchersContainer.serverNoticeRoomListDataFetcher.data.counts.totalHighlightCount; + counts = self.recentsListService.serverNoticeRoomListData.counts; } else if (section == suggestedRoomsSection) { - totalNotificationCount = fetchersContainer.suggestedRoomListDataFetcher.data.counts.totalNotificationCount; - totalHighlightCount = fetchersContainer.suggestedRoomListDataFetcher.data.counts.totalHighlightCount; + counts = self.recentsListService.suggestedRoomListData.counts; } - if (totalNotificationCount) + if (counts.totalNotificationCount) { UILabel *missedNotifAndUnreadBadgeLabel = [[UILabel alloc] init]; missedNotifAndUnreadBadgeLabel.textColor = ThemeService.shared.theme.baseTextPrimaryColor; missedNotifAndUnreadBadgeLabel.font = [UIFont boldSystemFontOfSize:14]; - if (totalNotificationCount > 1000) + if (counts.totalNotificationCount > 1000) { - CGFloat value = totalNotificationCount / 1000.0; + CGFloat value = counts.totalNotificationCount / 1000.0; missedNotifAndUnreadBadgeLabel.text = [VectorL10n largeBadgeValueKFormat:value]; } else { - missedNotifAndUnreadBadgeLabel.text = [NSString stringWithFormat:@"%tu", totalNotificationCount]; + missedNotifAndUnreadBadgeLabel.text = [NSString stringWithFormat:@"%tu", counts.totalNotificationCount]; } [missedNotifAndUnreadBadgeLabel sizeToFit]; CGFloat bgViewWidth = missedNotifAndUnreadBadgeLabel.frame.size.width + 18; - BOOL highlight = totalHighlightCount > 0; + BOOL highlight = counts.totalHighlightCount > 0; missedNotifAndUnreadBadgeBgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, bgViewWidth, 20)]; [missedNotifAndUnreadBadgeBgView.layer setCornerRadius:10]; missedNotifAndUnreadBadgeBgView.backgroundColor = highlight ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor; @@ -1365,7 +1326,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou [publicRoomsTriggerTimer invalidate]; publicRoomsTriggerTimer = nil; - [fetchersContainer stop]; + [self.recentsListService stop]; } #pragma mark - Override MXKRecentsDataSource @@ -1376,7 +1337,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou NSString *searchPattern = [patternsList componentsJoinedByString:@" "]; - [fetchersContainer updateQuery:searchPattern]; + [self.recentsListService updateQuery:searchPattern]; if (_publicRoomsDirectoryDataSource) { @@ -1526,9 +1487,9 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou [self hideCrossSigningBannerWithDisplay:self.crossSigningBannerDisplay]; } -#pragma mark - MXRoomListDataFetcherDelegate +#pragma mark - RecentsListServiceDelegate -- (void)fetcherDidChangeData:(id)fetcher +- (void)serviceDidChangeData:(id)service { // TODO: Update only updated sections [self.delegate dataSource:self didCellChange:nil]; diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSourceState.swift b/Riot/Modules/Common/Recents/DataSources/RecentsDataSourceState.swift deleted file mode 100644 index 38b959e9f..000000000 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSourceState.swift +++ /dev/null @@ -1,62 +0,0 @@ -// -// 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 - -/// The state for a room list screens. -@objcMembers -class RecentsDataSourceState: NSObject { - - // MARK: - Properties - - // MARK: Cells - let invitesCellDataArray: [MXKRecentCellDataStoring] - let favoriteCellDataArray: [MXKRecentCellDataStoring] - let peopleCellDataArray: [MXKRecentCellDataStoring] - let conversationCellDataArray: [MXKRecentCellDataStoring] - let lowPriorityCellDataArray: [MXKRecentCellDataStoring] - let serverNoticeCellDataArray: [MXKRecentCellDataStoring] - let suggestedRoomCellDataArray: [MXKRecentCellDataStoring] - - // MARK: Discussion counts - let favouriteMissedDiscussionsCount: DiscussionsCount - let directMissedDiscussionsCount: DiscussionsCount - let groupMissedDiscussionsCount: DiscussionsCount - - // MARK: - Setup - init(invitesCellDataArray: [MXKRecentCellDataStoring], - favoriteCellDataArray: [MXKRecentCellDataStoring], - peopleCellDataArray: [MXKRecentCellDataStoring], - conversationCellDataArray: [MXKRecentCellDataStoring], - lowPriorityCellDataArray: [MXKRecentCellDataStoring], - serverNoticeCellDataArray: [MXKRecentCellDataStoring], - suggestedRoomCellDataArray: [MXKRecentCellDataStoring], - favouriteMissedDiscussionsCount: DiscussionsCount, - directMissedDiscussionsCount: DiscussionsCount, - groupMissedDiscussionsCount: DiscussionsCount) { - self.invitesCellDataArray = invitesCellDataArray - self.favoriteCellDataArray = favoriteCellDataArray - self.peopleCellDataArray = peopleCellDataArray - self.conversationCellDataArray = conversationCellDataArray - self.lowPriorityCellDataArray = lowPriorityCellDataArray - self.serverNoticeCellDataArray = serverNoticeCellDataArray - self.suggestedRoomCellDataArray = suggestedRoomCellDataArray - self.favouriteMissedDiscussionsCount = favouriteMissedDiscussionsCount - self.directMissedDiscussionsCount = directMissedDiscussionsCount - self.groupMissedDiscussionsCount = groupMissedDiscussionsCount - super.init() - } -} diff --git a/Riot/Modules/Common/Recents/DataSources/DiscussionsCount.swift b/Riot/Modules/Common/Recents/Model/DiscussionsCount.swift similarity index 100% rename from Riot/Modules/Common/Recents/DataSources/DiscussionsCount.swift rename to Riot/Modules/Common/Recents/Model/DiscussionsCount.swift diff --git a/Riot/Modules/Common/Recents/CellData/RecentCellData.h b/Riot/Modules/Common/Recents/Model/RecentCellData.h similarity index 100% rename from Riot/Modules/Common/Recents/CellData/RecentCellData.h rename to Riot/Modules/Common/Recents/Model/RecentCellData.h diff --git a/Riot/Modules/Common/Recents/CellData/RecentCellData.m b/Riot/Modules/Common/Recents/Model/RecentCellData.m similarity index 100% rename from Riot/Modules/Common/Recents/CellData/RecentCellData.m rename to Riot/Modules/Common/Recents/Model/RecentCellData.m diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsRoomListContainer.swift b/Riot/Modules/Common/Recents/Service/MatrixSDK/RecentsListService.swift similarity index 82% rename from Riot/Modules/Common/Recents/DataSources/RecentsRoomListContainer.swift rename to Riot/Modules/Common/Recents/Service/MatrixSDK/RecentsListService.swift index 413a85565..f2a6a4327 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsRoomListContainer.swift +++ b/Riot/Modules/Common/Recents/Service/MatrixSDK/RecentsListService.swift @@ -17,18 +17,18 @@ import Foundation @objcMembers -public class RecentsRoomListFetchersContainer: NSObject { +public class RecentsListService: NSObject, RecentsListServiceProtocol { - public let session: MXSession + public private(set) weak var session: MXSession? public private(set) var mode: RecentsDataSourceMode public private(set) var query: String? public private(set) var space: MXSpace? // MARK: - Fetchers - public private(set) var invitedRoomListDataFetcher: MXRoomListDataFetcher? - public private(set) var favoritedRoomListDataFetcher: MXRoomListDataFetcher? - public var directRoomListDataFetcher: MXRoomListDataFetcher? { + private var invitedRoomListDataFetcher: MXRoomListDataFetcher? + private var favoritedRoomListDataFetcher: MXRoomListDataFetcher? + private var directRoomListDataFetcher: MXRoomListDataFetcher? { switch mode { case .home: return directRoomListDataFetcherForHome @@ -38,7 +38,7 @@ public class RecentsRoomListFetchersContainer: NSObject { return nil } } - public var conversationRoomListDataFetcher: MXRoomListDataFetcher? { + private var conversationRoomListDataFetcher: MXRoomListDataFetcher? { switch mode { case .home: return conversationRoomListDataFetcherForHome @@ -48,9 +48,9 @@ public class RecentsRoomListFetchersContainer: NSObject { return nil } } - public private(set) var lowPriorityRoomListDataFetcher: MXRoomListDataFetcher? - public private(set) var serverNoticeRoomListDataFetcher: MXRoomListDataFetcher? - public private(set) var suggestedRoomListDataFetcher: MXRoomListDataFetcher? + private var lowPriorityRoomListDataFetcher: MXRoomListDataFetcher? + private var serverNoticeRoomListDataFetcher: MXRoomListDataFetcher? + private var suggestedRoomListDataFetcher: MXRoomListDataFetcher? private var conversationRoomListDataFetcherForHome: MXRoomListDataFetcher? private var conversationRoomListDataFetcherForRooms: MXRoomListDataFetcher? @@ -98,10 +98,6 @@ public class RecentsRoomListFetchersContainer: NSObject { return result } - private var hideInvitedSection: Bool { - return MXSDKOptions.sharedInstance().autoAcceptRoomInvites - } - private var visibleFetchers: [MXRoomListDataFetcher] { guard let fetcherTypes = fetcherTypesForMode[mode] else { return [] @@ -138,8 +134,12 @@ public class RecentsRoomListFetchersContainer: NSObject { return result } + private var hideInvitedSection: Bool { + return MXSDKOptions.sharedInstance().autoAcceptRoomInvites + } + // swiftlint:disable weak_delegate - private let multicastDelegate: MXMulticastDelegate = MXMulticastDelegate() + private let multicastDelegate: MXMulticastDelegate = MXMulticastDelegate() // swiftlint:enable weak_delegate private var sortOptions: MXRoomListDataSortOptions { @@ -157,10 +157,17 @@ public class RecentsRoomListFetchersContainer: NSObject { // MARK: - Public API - public init(withSession session: MXSession, - mode: RecentsDataSourceMode = .home, - query: String? = nil, - space: MXSpace? = nil) { + public convenience init(withSession session: MXSession) { + self.init(withSession: session, + mode: .home, + query: nil, + space: nil) + } + + private init(withSession session: MXSession, + mode: RecentsDataSourceMode, + query: String?, + space: MXSpace?) { self.session = session self.mode = mode self.query = query @@ -170,6 +177,37 @@ public class RecentsRoomListFetchersContainer: NSObject { addRiotSettingsObserver() } + // MARK: - View Data + + public var invitedRoomListData: MXRoomListData? { + guard shouldShowInvited else { return nil } + return invitedRoomListDataFetcher?.data + } + public var favoritedRoomListData: MXRoomListData? { + guard shouldShowFavorited else { return nil } + return favoritedRoomListDataFetcher?.data + } + public var peopleRoomListData: MXRoomListData? { + guard shouldShowDirect else { return nil } + return directRoomListDataFetcher?.data + } + public var conversationRoomListData: MXRoomListData? { + guard shouldShowConversation else { return nil } + return conversationRoomListDataFetcher?.data + } + public var lowPriorityRoomListData: MXRoomListData? { + guard shouldShowLowPriority else { return nil } + return lowPriorityRoomListDataFetcher?.data + } + public var serverNoticeRoomListData: MXRoomListData? { + guard shouldShowServerNotice else { return nil } + return serverNoticeRoomListDataFetcher?.data + } + public var suggestedRoomListData: MXRoomListData? { + guard shouldShowSuggested else { return nil } + return suggestedRoomListDataFetcher?.data + } + public var favoritedMissedDiscussionsCount: DiscussionsCount { guard let data = favoritedRoomListDataFetcher?.data else { return .zero @@ -177,7 +215,7 @@ public class RecentsRoomListFetchersContainer: NSObject { return DiscussionsCount(withRoomListDataCounts: data.counts) } - public var directMissedDiscussionsCount: DiscussionsCount { + public var peopleMissedDiscussionsCount: DiscussionsCount { guard let data = directRoomListDataFetcherForPeople?.data else { return .zero } @@ -191,46 +229,8 @@ public class RecentsRoomListFetchersContainer: NSObject { return DiscussionsCount(withRoomListDataCounts: data.counts) } - public var shouldShowInvited: Bool { - return fetcherTypesForMode[mode]?.contains(.invited) ?? false - } - - public var shouldShowFavorited: Bool { - return fetcherTypesForMode[mode]?.contains(.favorited) ?? false - } - - public var shouldShowDirect: Bool { - switch mode { - case .home: - return fetcherTypesForMode[mode]?.contains(.directHome) ?? false - case .people: - return fetcherTypesForMode[mode]?.contains(.directPeople) ?? false - default: - return false - } - } - - public var shouldShowConversation: Bool { - switch mode { - case .home: - return fetcherTypesForMode[mode]?.contains(.conversationHome) ?? false - case .rooms: - return fetcherTypesForMode[mode]?.contains(.conversationRooms) ?? false - default: - return false - } - } - - public var shouldShowLowPriority: Bool { - return fetcherTypesForMode[mode]?.contains(.lowPriority) ?? false - } - - public var shouldShowServerNotice: Bool { - return fetcherTypesForMode[mode]?.contains(.serverNotice) ?? false - } - - public var shouldShowSuggested: Bool { - return fetcherTypesForMode[mode]?.contains(.suggested) ?? false + public var totalVisibleItemCount: Int { + return visibleFetchers.reduce(0, { $0 + ($1.data?.counts.numberOfRooms ?? 0) }) } public func updateMode(_ mode: RecentsDataSourceMode) { @@ -263,11 +263,11 @@ public class RecentsRoomListFetchersContainer: NSObject { // MARK: - Delegate - public func addDelegate(_ delegate: MXRoomListDataFetcherDelegate) { + public func addDelegate(_ delegate: RecentsListServiceDelegate) { multicastDelegate.addDelegate(delegate) } - public func removeDelegate(_ delegate: MXRoomListDataFetcherDelegate) { + public func removeDelegate(_ delegate: RecentsListServiceDelegate) { multicastDelegate.removeDelegate(delegate) } @@ -275,7 +275,7 @@ public class RecentsRoomListFetchersContainer: NSObject { multicastDelegate.removeAllDelegates() } - // MARK: - Private + // MARK: - Riot Settings Observer private func addRiotSettingsObserver() { NotificationCenter.default.addObserver(self, @@ -304,9 +304,56 @@ public class RecentsRoomListFetchersContainer: NSObject { } } + // MARK: - Private + + private var shouldShowInvited: Bool { + return fetcherTypesForMode[mode]?.contains(.invited) ?? false + } + + private var shouldShowFavorited: Bool { + return fetcherTypesForMode[mode]?.contains(.favorited) ?? false + } + + private var shouldShowDirect: Bool { + switch mode { + case .home: + return fetcherTypesForMode[mode]?.contains(.directHome) ?? false + case .people: + return fetcherTypesForMode[mode]?.contains(.directPeople) ?? false + default: + return false + } + } + + private var shouldShowConversation: Bool { + switch mode { + case .home: + return fetcherTypesForMode[mode]?.contains(.conversationHome) ?? false + case .rooms: + return fetcherTypesForMode[mode]?.contains(.conversationRooms) ?? false + default: + return false + } + } + + private var shouldShowLowPriority: Bool { + return fetcherTypesForMode[mode]?.contains(.lowPriority) ?? false + } + + private var shouldShowServerNotice: Bool { + return fetcherTypesForMode[mode]?.contains(.serverNotice) ?? false + } + + private var shouldShowSuggested: Bool { + return fetcherTypesForMode[mode]?.contains(.suggested) ?? false + } + private func createCommonRoomListDataFetcher(withDataTypes dataTypes: MXRoomSummaryDataTypes = [], onlySuggested: Bool = false, paginate: Bool = true) -> MXRoomListDataFetcher { + guard let session = session else { + fatalError("Session deallocated") + } let filterOptions = MXRoomListDataFilterOptions(dataTypes: dataTypes, onlySuggested: onlySuggested, query: query, @@ -410,7 +457,7 @@ public class RecentsRoomListFetchersContainer: NSObject { } private func notifyDataChange(on fetcher: MXRoomListDataFetcher) { - multicastDelegate.invoke(invocation: { $0.fetcherDidChangeData(fetcher) }) + multicastDelegate.invoke(invocation: { $0.serviceDidChangeData(self) }) } deinit { @@ -421,7 +468,7 @@ public class RecentsRoomListFetchersContainer: NSObject { // MARK: - MXRoomListDataFetcherDelegate -extension RecentsRoomListFetchersContainer: MXRoomListDataFetcherDelegate { +extension RecentsListService: MXRoomListDataFetcherDelegate { public func fetcherDidChangeData(_ fetcher: MXRoomListDataFetcher) { notifyDataChange(on: fetcher) @@ -434,7 +481,7 @@ extension RecentsRoomListFetchersContainer: MXRoomListDataFetcherDelegate { private struct FetcherTypes: OptionSet { typealias RawValue = Int let rawValue: RawValue - + init(rawValue: RawValue) { self.rawValue = rawValue } diff --git a/Riot/Modules/Common/Recents/Service/RecentsListServiceDelegate.swift b/Riot/Modules/Common/Recents/Service/RecentsListServiceDelegate.swift new file mode 100644 index 000000000..a2afaf599 --- /dev/null +++ b/Riot/Modules/Common/Recents/Service/RecentsListServiceDelegate.swift @@ -0,0 +1,25 @@ +// +// 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 + +@objc +public protocol RecentsListServiceDelegate: AnyObject { + + /// Delegate method to be called when service data updated + /// - Parameter service: service object + func serviceDidChangeData(_ service: RecentsListServiceProtocol) +} diff --git a/Riot/Modules/Common/Recents/Service/RecentsListServiceProtocol.swift b/Riot/Modules/Common/Recents/Service/RecentsListServiceProtocol.swift new file mode 100644 index 000000000..754a7f721 --- /dev/null +++ b/Riot/Modules/Common/Recents/Service/RecentsListServiceProtocol.swift @@ -0,0 +1,53 @@ +// +// 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 + +@objc +public protocol RecentsListServiceProtocol { + var session: MXSession? { get } + var mode: RecentsDataSourceMode { get } + var query: String? { get } + var space: MXSpace? { get } + + // MARK: Cells + var invitedRoomListData: MXRoomListData? { get } + var favoritedRoomListData: MXRoomListData? { get } + var peopleRoomListData: MXRoomListData? { get } + var conversationRoomListData: MXRoomListData? { get } + var lowPriorityRoomListData: MXRoomListData? { get } + var serverNoticeRoomListData: MXRoomListData? { get } + var suggestedRoomListData: MXRoomListData? { get } + + // MARK: Discussion counts + var favoritedMissedDiscussionsCount: DiscussionsCount { get } + var peopleMissedDiscussionsCount: DiscussionsCount { get } + var conversationMissedDiscussionsCount: DiscussionsCount { get } + var totalVisibleItemCount: Int { get } + + // MARK: - Methods + func updateMode(_ mode: RecentsDataSourceMode) + func updateQuery(_ query: String?) + func updateSpace(_ space: MXSpace?) + func refresh() + func stop() + + // MARK: - Delegate + + func addDelegate(_ delegate: RecentsListServiceDelegate) + func removeDelegate(_ delegate: RecentsListServiceDelegate) + func removeAllDelegates() +} diff --git a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m index bb0b4879a..4096b31b6 100644 --- a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m +++ b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m @@ -229,7 +229,9 @@ if (mainSession) { // Init the recents data source - recentsDataSource = [[UnifiedSearchRecentsDataSource alloc] initWithMatrixSession:mainSession]; + RecentsListService *recentsListService = [[RecentsListService alloc] initWithSession:mainSession]; + recentsDataSource = [[UnifiedSearchRecentsDataSource alloc] initWithMatrixSession:mainSession + recentsListService:recentsListService]; [recentsViewController displayList:recentsDataSource]; // Init the search for messages diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 9855333fc..0539a7317 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -333,7 +333,9 @@ MXLogDebug(@"[MasterTabBarController] initializeDataSources"); // Init the recents data source - recentsDataSource = [[RecentsDataSource alloc] initWithMatrixSession:mainSession]; + RecentsListService *recentsListService = [[RecentsListService alloc] initWithSession:mainSession]; + recentsDataSource = [[RecentsDataSource alloc] initWithMatrixSession:mainSession + recentsListService:recentsListService]; [self.homeViewController displayList:recentsDataSource]; [self.favouritesViewController displayList:recentsDataSource]; @@ -386,8 +388,6 @@ } } } - - [recentsDataSource finalizeInitialization]; } }