Architecture update

This commit is contained in:
ismailgulek
2021-10-04 17:28:21 +03:00
parent e43ce3d15b
commit 5200dbdde4
11 changed files with 277 additions and 243 deletions
@@ -1,60 +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
/// Noticiations counts per section
@objcMembers
public class DiscussionsCount: NSObject {
/// Number of notified rooms with regular notifications
public let numberOfNotified: Int
/// Number of highlighted rooms with mentions like notications
public let numberOfHighlighted: Int
/// Number of rooms that has unsent messages in it
public let numberOfUnsent: Int
/// Flag indicating is there any unsent
public var hasUnsent: Bool {
return numberOfUnsent > 0
}
/// Flag indicating is there any highlight
public var hasHighlight: Bool {
return numberOfHighlighted > 0
}
public static let zero: DiscussionsCount = DiscussionsCount(numberOfNotified: 0,
numberOfHighlighted: 0,
numberOfUnsent: 0)
public init(numberOfNotified: Int,
numberOfHighlighted: Int,
numberOfUnsent: Int) {
self.numberOfNotified = numberOfNotified
self.numberOfHighlighted = numberOfHighlighted
self.numberOfUnsent = numberOfUnsent
super.init()
}
public init(withRoomListDataCounts counts: MXRoomListDataCounts) {
self.numberOfNotified = counts.numberOfNotifiedRooms
self.numberOfHighlighted = counts.numberOfHighlightedRooms + counts.numberOfInvitedRooms
self.numberOfUnsent = counts.numberOfUnsentRooms
super.init()
}
}
@@ -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<id<MXKRecentCellDataStoring>> *invitesCellDataArray;
@property (nonatomic, readonly) NSArray<id<MXKRecentCellDataStoring>> *favoriteCellDataArray;
@property (nonatomic, readonly) NSArray<id<MXKRecentCellDataStoring>> *peopleCellDataArray;
@property (nonatomic, readonly) NSArray<id<MXKRecentCellDataStoring>> *conversationCellDataArray;
@property (nonatomic, readonly) NSArray<id<MXKRecentCellDataStoring>> *lowPriorityCellDataArray;
@property (nonatomic, readonly) NSArray<id<MXKRecentCellDataStoring>> *serverNoticeCellDataArray;
@property (nonatomic, readonly) NSArray<id<MXKRecentCellDataStoring>> *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<RecentsListServiceProtocol> 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<RecentsListServiceProtocol>)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
@@ -41,7 +41,7 @@
NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSourceTapOnDirectoryServerChange";
@interface RecentsDataSource() <SecureBackupBannerCellDelegate, CrossSigningSetupBannerCellDelegate, MXRoomListDataFetcherDelegate>
@interface RecentsDataSource() <SecureBackupBannerCellDelegate, CrossSigningSetupBannerCellDelegate, RecentsListServiceDelegate>
{
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<RecentsListServiceProtocol> 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<RecentsListServiceProtocol>)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<id<MXKRecentCellDataStoring>> *)invitesCellDataArray
{
if (!fetchersContainer.shouldShowInvited)
{
return nil;
}
return [self mapRoomSummaries:fetchersContainer.invitedRoomListDataFetcher.data.rooms];
return [self mapRoomSummaries:self.recentsListService.invitedRoomListData.rooms];
}
- (NSArray<id<MXKRecentCellDataStoring>> *)favoriteCellDataArray
{
if (!fetchersContainer.shouldShowFavorited)
{
return nil;
}
return [self mapRoomSummaries:fetchersContainer.favoritedRoomListDataFetcher.data.rooms];
return [self mapRoomSummaries:self.recentsListService.favoritedRoomListData.rooms];
}
- (NSArray<id<MXKRecentCellDataStoring>> *)peopleCellDataArray
{
if (!fetchersContainer.shouldShowDirect)
{
return nil;
}
return [self mapRoomSummaries:fetchersContainer.directRoomListDataFetcher.data.rooms];
return [self mapRoomSummaries:self.recentsListService.peopleRoomListData.rooms];
}
- (NSArray<id<MXKRecentCellDataStoring>> *)conversationCellDataArray
{
if (!fetchersContainer.shouldShowConversation)
{
return nil;
}
return [self mapRoomSummaries:fetchersContainer.conversationRoomListDataFetcher.data.rooms];
return [self mapRoomSummaries:self.recentsListService.conversationRoomListData.rooms];
}
- (NSArray<id<MXKRecentCellDataStoring>> *)lowPriorityCellDataArray
{
if (!fetchersContainer.shouldShowLowPriority)
{
return nil;
}
return [self mapRoomSummaries:fetchersContainer.lowPriorityRoomListDataFetcher.data.rooms];
return [self mapRoomSummaries:self.recentsListService.lowPriorityRoomListData.rooms];
}
- (NSArray<id<MXKRecentCellDataStoring>> *)serverNoticeCellDataArray
{
if (!fetchersContainer.shouldShowServerNotice)
{
return nil;
}
return [self mapRoomSummaries:fetchersContainer.serverNoticeRoomListDataFetcher.data.rooms];
return [self mapRoomSummaries:self.recentsListService.serverNoticeRoomListData.rooms];
}
- (NSArray<id<MXKRecentCellDataStoring>> *)suggestedRoomCellDataArray
{
if (!fetchersContainer.shouldShowSuggested)
{
return nil;
}
return [self mapRoomSummaries:fetchersContainer.suggestedRoomListDataFetcher.data.rooms];
return [self mapRoomSummaries:self.recentsListService.suggestedRoomListData.rooms];
}
- (NSArray<id<MXKRecentCellDataStoring>> *)mapRoomSummaries:(NSArray<id<MXRoomSummaryProtocol>> *)summaries
{
return [summaries vc_map:^id _Nonnull(id<MXRoomSummaryProtocol> _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<id<MXKRecentCellDataStoring>> *)mapRoomSummaries:(NSArray<id<MXRoomSummaryProtocol>> *)summaries
{
return [summaries vc_map:^id _Nonnull(id<MXRoomSummaryProtocol> _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<MXRoomListDataCounts> 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<MXRoomListDataFetcher>)fetcher
- (void)serviceDidChangeData:(id<RecentsListServiceProtocol>)service
{
// TODO: Update only updated sections
[self.delegate dataSource:self didCellChange:nil];
@@ -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()
}
}
@@ -1,455 +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
@objcMembers
public class RecentsRoomListFetchersContainer: NSObject {
public let 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? {
switch mode {
case .home:
return directRoomListDataFetcherForHome
case .people:
return directRoomListDataFetcherForPeople
default:
return nil
}
}
public var conversationRoomListDataFetcher: MXRoomListDataFetcher? {
switch mode {
case .home:
return conversationRoomListDataFetcherForHome
case .rooms:
return conversationRoomListDataFetcherForRooms
default:
return nil
}
}
public private(set) var lowPriorityRoomListDataFetcher: MXRoomListDataFetcher?
public private(set) var serverNoticeRoomListDataFetcher: MXRoomListDataFetcher?
public private(set) var suggestedRoomListDataFetcher: MXRoomListDataFetcher?
private var conversationRoomListDataFetcherForHome: MXRoomListDataFetcher?
private var conversationRoomListDataFetcherForRooms: MXRoomListDataFetcher?
private var directRoomListDataFetcherForHome: MXRoomListDataFetcher?
private var directRoomListDataFetcherForPeople: MXRoomListDataFetcher?
// MARK: - Private
private var fetcherTypesForMode: [RecentsDataSourceMode: FetcherTypes] = [
.home: [.invited, .favorited, .directHome, .conversationHome, .lowPriority, .serverNotice, .suggested],
.favourites: [.favorited],
.people: [.directPeople],
.rooms: [.conversationRooms, .suggested]
]
private var allFetchers: [MXRoomListDataFetcher] {
var result: [MXRoomListDataFetcher] = []
if let fetcher = invitedRoomListDataFetcher {
result.append(fetcher)
}
if let fetcher = favoritedRoomListDataFetcher {
result.append(fetcher)
}
if let fetcher = directRoomListDataFetcherForHome {
result.append(fetcher)
}
if let fetcher = directRoomListDataFetcherForPeople {
result.append(fetcher)
}
if let fetcher = conversationRoomListDataFetcherForHome {
result.append(fetcher)
}
if let fetcher = conversationRoomListDataFetcherForRooms {
result.append(fetcher)
}
if let fetcher = lowPriorityRoomListDataFetcher {
result.append(fetcher)
}
if let fetcher = serverNoticeRoomListDataFetcher {
result.append(fetcher)
}
if let fetcher = suggestedRoomListDataFetcher {
result.append(fetcher)
}
return result
}
private var hideInvitedSection: Bool {
return MXSDKOptions.sharedInstance().autoAcceptRoomInvites
}
private var visibleFetchers: [MXRoomListDataFetcher] {
guard let fetcherTypes = fetcherTypesForMode[mode] else {
return []
}
var result: [MXRoomListDataFetcher] = []
if let fetcher = invitedRoomListDataFetcher, fetcherTypes.contains(.invited) {
result.append(fetcher)
}
if let fetcher = favoritedRoomListDataFetcher, fetcherTypes.contains(.favorited) {
result.append(fetcher)
}
if let fetcher = directRoomListDataFetcherForHome, fetcherTypes.contains(.directHome) {
result.append(fetcher)
}
if let fetcher = directRoomListDataFetcherForPeople, fetcherTypes.contains(.directPeople) {
result.append(fetcher)
}
if let fetcher = conversationRoomListDataFetcherForHome, fetcherTypes.contains(.conversationHome) {
result.append(fetcher)
}
if let fetcher = conversationRoomListDataFetcherForRooms, fetcherTypes.contains(.conversationRooms) {
result.append(fetcher)
}
if let fetcher = lowPriorityRoomListDataFetcher, fetcherTypes.contains(.lowPriority) {
result.append(fetcher)
}
if let fetcher = serverNoticeRoomListDataFetcher, fetcherTypes.contains(.serverNotice) {
result.append(fetcher)
}
if let fetcher = suggestedRoomListDataFetcher,
fetcherTypes.contains(.suggested) {
result.append(fetcher)
}
return result
}
// swiftlint:disable weak_delegate
private let multicastDelegate: MXMulticastDelegate<MXRoomListDataFetcherDelegate> = MXMulticastDelegate()
// swiftlint:enable weak_delegate
private var sortOptions: MXRoomListDataSortOptions {
switch mode {
case .home:
let pinMissed = RiotSettings.shared.pinRoomsWithMissedNotificationsOnHome
let pinUnread = RiotSettings.shared.pinRoomsWithUnreadMessagesOnHome
return MXRoomListDataSortOptions(missedNotificationsFirst: pinMissed,
unreadMessagesFirst: pinUnread)
default:
return MXRoomListDataSortOptions(missedNotificationsFirst: false,
unreadMessagesFirst: false)
}
}
// MARK: - Public API
public init(withSession session: MXSession,
mode: RecentsDataSourceMode = .home,
query: String? = nil,
space: MXSpace? = nil) {
self.session = session
self.mode = mode
self.query = query
self.space = space
super.init()
createFetchers()
addRiotSettingsObserver()
}
public var favoritedMissedDiscussionsCount: DiscussionsCount {
guard let data = favoritedRoomListDataFetcher?.data else {
return .zero
}
return DiscussionsCount(withRoomListDataCounts: data.counts)
}
public var directMissedDiscussionsCount: DiscussionsCount {
guard let data = directRoomListDataFetcherForPeople?.data else {
return .zero
}
return DiscussionsCount(withRoomListDataCounts: data.counts)
}
public var conversationMissedDiscussionsCount: DiscussionsCount {
guard let data = conversationRoomListDataFetcherForRooms?.data else {
return .zero
}
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 func updateMode(_ mode: RecentsDataSourceMode) {
self.mode = mode
if let fetcher = favoritedRoomListDataFetcher {
updateFavoritedFetcher(fetcher, for: mode)
}
allFetchers.forEach({ notifyDataChange(on: $0) })
}
public func updateQuery(_ query: String?) {
self.query = query
visibleFetchers.forEach({ $0.fetchOptions.filterOptions.query = query })
}
public func updateSpace(_ space: MXSpace?) {
self.space = space
allFetchers.forEach({ $0.fetchOptions.filterOptions.space = space })
}
public func refresh() {
allFetchers.forEach({ $0.fetchOptions.sortOptions = sortOptions })
}
public func stop() {
removeRiotSettingsObserver()
removeAllDelegates()
allFetchers.forEach({ $0.stop() })
}
// MARK: - Delegate
public func addDelegate(_ delegate: MXRoomListDataFetcherDelegate) {
multicastDelegate.addDelegate(delegate)
}
public func removeDelegate(_ delegate: MXRoomListDataFetcherDelegate) {
multicastDelegate.removeDelegate(delegate)
}
public func removeAllDelegates() {
multicastDelegate.removeAllDelegates()
}
// MARK: - Private
private func addRiotSettingsObserver() {
NotificationCenter.default.addObserver(self,
selector: #selector(userDefaultsUpdated(_:)),
name: .userDefaultValueUpdated,
object: nil)
}
private func removeRiotSettingsObserver() {
NotificationCenter.default.removeObserver(self,
name: .userDefaultValueUpdated,
object: nil)
}
@objc
private func userDefaultsUpdated(_ notification: Notification) {
guard let key = notification.object as? String else {
return
}
switch key {
case RiotSettings.UserDefaultsKeys.pinRoomsWithMissedNotificationsOnHome,
RiotSettings.UserDefaultsKeys.pinRoomsWithUnreadMessagesOnHome:
refresh()
default:
break
}
}
private func createCommonRoomListDataFetcher(withDataTypes dataTypes: MXRoomSummaryDataTypes = [],
onlySuggested: Bool = false,
paginate: Bool = true) -> MXRoomListDataFetcher {
let filterOptions = MXRoomListDataFilterOptions(dataTypes: dataTypes,
onlySuggested: onlySuggested,
query: query,
space: space)
let fetchOptions = MXRoomListDataFetchOptions(filterOptions: filterOptions,
sortOptions: sortOptions,
async: false)
let fetcher = session.roomListDataManager.fetcher(withOptions: fetchOptions)
if paginate {
fetcher.addDelegate(self)
fetcher.paginate()
}
return fetcher
}
private func createDirectRoomListDataFetcherForHome() -> MXRoomListDataFetcher {
let fetcher = createCommonRoomListDataFetcher(withDataTypes: [.direct], paginate: false)
updateDirectFetcher(fetcher, for: .home)
fetcher.addDelegate(self)
fetcher.paginate()
return fetcher
}
private func createDirectRoomListDataFetcherForPeople() -> MXRoomListDataFetcher {
let fetcher = createCommonRoomListDataFetcher(withDataTypes: [.direct], paginate: false)
updateDirectFetcher(fetcher, for: .people)
fetcher.addDelegate(self)
fetcher.paginate()
return fetcher
}
private func createConversationRoomListDataFetcherForHome() -> MXRoomListDataFetcher {
let fetcher = createCommonRoomListDataFetcher(withDataTypes: [], paginate: false)
updateConversationFetcher(fetcher, for: .home)
fetcher.addDelegate(self)
fetcher.paginate()
return fetcher
}
private func createConversationRoomListDataFetcherForRooms() -> MXRoomListDataFetcher {
let fetcher = createCommonRoomListDataFetcher(withDataTypes: [], paginate: false)
updateConversationFetcher(fetcher, for: .rooms)
fetcher.addDelegate(self)
fetcher.paginate()
return fetcher
}
private func createFetchers() {
if !hideInvitedSection {
invitedRoomListDataFetcher = createCommonRoomListDataFetcher(withDataTypes: [.invited])
}
favoritedRoomListDataFetcher = createCommonRoomListDataFetcher(withDataTypes: [.favorited])
directRoomListDataFetcherForHome = createDirectRoomListDataFetcherForHome()
directRoomListDataFetcherForPeople = createDirectRoomListDataFetcherForPeople()
conversationRoomListDataFetcherForHome = createConversationRoomListDataFetcherForHome()
conversationRoomListDataFetcherForRooms = createConversationRoomListDataFetcherForRooms()
lowPriorityRoomListDataFetcher = createCommonRoomListDataFetcher(withDataTypes: [.lowPriority])
serverNoticeRoomListDataFetcher = createCommonRoomListDataFetcher(withDataTypes: [.serverNotice])
suggestedRoomListDataFetcher = createCommonRoomListDataFetcher(onlySuggested: true)
}
private func updateDirectFetcher(_ fetcher: MXRoomListDataFetcher, for mode: RecentsDataSourceMode) {
switch mode {
case .home:
fetcher.fetchOptions.filterOptions.notDataTypes = [.invited, .lowPriority]
case .people:
fetcher.fetchOptions.filterOptions.notDataTypes = [.lowPriority]
default:
break
}
}
private func updateFavoritedFetcher(_ fetcher: MXRoomListDataFetcher, for mode: RecentsDataSourceMode) {
switch mode {
case .home:
fetcher.fetchOptions.sortOptions = sortOptions
case .favourites:
let newSortOptions = sortOptions
newSortOptions.favoriteTag = true
fetcher.fetchOptions.sortOptions = newSortOptions
default:
break
}
}
private func updateConversationFetcher(_ fetcher: MXRoomListDataFetcher, for mode: RecentsDataSourceMode) {
var notDataTypes: MXRoomSummaryDataTypes = [.hidden, .conferenceUser, .direct, .lowPriority, .serverNotice, .space]
switch mode {
case .home:
notDataTypes.insert([.invited, .favorited])
fetcher.fetchOptions.filterOptions.notDataTypes = notDataTypes
case .rooms:
if hideInvitedSection {
notDataTypes.insert(.invited)
}
fetcher.fetchOptions.filterOptions.notDataTypes = notDataTypes
default:
break
}
}
private func notifyDataChange(on fetcher: MXRoomListDataFetcher) {
multicastDelegate.invoke(invocation: { $0.fetcherDidChangeData(fetcher) })
}
deinit {
stop()
}
}
// MARK: - MXRoomListDataFetcherDelegate
extension RecentsRoomListFetchersContainer: MXRoomListDataFetcherDelegate {
public func fetcherDidChangeData(_ fetcher: MXRoomListDataFetcher) {
notifyDataChange(on: fetcher)
}
}
// MARK: - FetcherTypes
private struct FetcherTypes: OptionSet {
typealias RawValue = Int
let rawValue: RawValue
init(rawValue: RawValue) {
self.rawValue = rawValue
}
static let invited = FetcherTypes(rawValue: 1 << 0)
static let favorited = FetcherTypes(rawValue: 1 << 1)
static let directHome = FetcherTypes(rawValue: 1 << 2)
static let directPeople = FetcherTypes(rawValue: 1 << 3)
static let conversationHome = FetcherTypes(rawValue: 1 << 4)
static let conversationRooms = FetcherTypes(rawValue: 1 << 5)
static let lowPriority = FetcherTypes(rawValue: 1 << 6)
static let serverNotice = FetcherTypes(rawValue: 1 << 7)
static let suggested = FetcherTypes(rawValue: 1 << 8)
static let none: FetcherTypes = []
static let all: FetcherTypes = [
.invited, .favorited, .directHome, .directPeople, .conversationHome, .conversationRooms, .lowPriority, .serverNotice, .suggested]
}