mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-22 01:22:46 +02:00
Refactor recents data source to use new room list data fetchers
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// 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,18 +19,19 @@
|
||||
|
||||
#import "PublicRoomsDirectoryDataSource.h"
|
||||
|
||||
@protocol MXKRecentCellDataStoring;
|
||||
@class DiscussionsCount;
|
||||
/**
|
||||
List the different modes used to prepare the recents data source.
|
||||
Each mode corresponds to an application tab: Home, Favourites, People and Rooms.
|
||||
*/
|
||||
typedef enum : NSUInteger
|
||||
typedef NS_ENUM(NSInteger, RecentsDataSourceMode)
|
||||
{
|
||||
RecentsDataSourceModeHome,
|
||||
RecentsDataSourceModeFavourites,
|
||||
RecentsDataSourceModePeople,
|
||||
RecentsDataSourceModeRooms
|
||||
|
||||
} RecentsDataSourceMode;
|
||||
};
|
||||
|
||||
/**
|
||||
List the different secure backup banners that could be displayed.
|
||||
@@ -73,12 +74,12 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange;
|
||||
@property (nonatomic) NSInteger lowPrioritySection;
|
||||
@property (nonatomic) NSInteger serverNoticeSection;
|
||||
|
||||
@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<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) SecureBackupBannerDisplay secureBackupBannerDisplay;
|
||||
@property (nonatomic, readonly) CrossSigningBannerDisplay crossSigningBannerDisplay;
|
||||
@@ -160,43 +161,18 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange;
|
||||
- (void)moveRoomCell:(MXRoom*)room from:(NSIndexPath*)oldPath to:(NSIndexPath*)newPath success:(void (^)(void))moveSuccess failure:(void (^)(NSError *error))moveFailure;
|
||||
|
||||
/**
|
||||
The current number of the favourite rooms with missed notifications.
|
||||
Counts for favorited rooms.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger missedFavouriteDiscussionsCount;
|
||||
@property (nonatomic, readonly) DiscussionsCount *favoriteMissedDiscussionsCount;
|
||||
|
||||
/**
|
||||
The current number of the favourite rooms with unread highlighted messages.
|
||||
Counts for direct rooms.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger missedHighlightFavouriteDiscussionsCount;
|
||||
@property (nonatomic, readonly) DiscussionsCount *directMissedDiscussionsCount;
|
||||
|
||||
/**
|
||||
The current number of the direct chats with missed notifications, including the invites.
|
||||
Counts for group rooms.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger missedDirectDiscussionsCount;
|
||||
|
||||
/**
|
||||
The current number of the direct chats with unread highlighted messages.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger missedHighlightDirectDiscussionsCount;
|
||||
|
||||
/**
|
||||
The current number of the direct chats with unsent messages.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger unsentMessagesDirectDiscussionsCount;
|
||||
|
||||
/**
|
||||
The current number of the group chats with missed notifications, including the invites.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger missedGroupDiscussionsCount;
|
||||
|
||||
/**
|
||||
The current number of the group chats with unread highlighted messages.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger missedHighlightGroupDiscussionsCount;
|
||||
|
||||
/**
|
||||
The current number of the group chats with unsent messages.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger unsentMessagesGroupDiscussionsCount;
|
||||
@property (nonatomic, readonly) DiscussionsCount *groupMissedDiscussionsCount;
|
||||
|
||||
@end
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#import "MXRoom+Riot.h"
|
||||
#import "MXSession+Riot.h"
|
||||
#import "NSArray+Element.h"
|
||||
|
||||
#import "Riot-Swift.h"
|
||||
|
||||
@@ -39,7 +40,7 @@
|
||||
|
||||
NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSourceTapOnDirectoryServerChange";
|
||||
|
||||
@interface RecentsDataSource() <SecureBackupBannerCellDelegate, CrossSigningSetupBannerCellDelegate>
|
||||
@interface RecentsDataSource() <SecureBackupBannerCellDelegate, CrossSigningSetupBannerCellDelegate, MXRoomListDataFetcherDelegate>
|
||||
{
|
||||
RecentsDataSourceState *state;
|
||||
dispatch_queue_t processingQueue;
|
||||
@@ -50,6 +51,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
|
||||
// Timer to not refresh publicRoomsDirectoryDataSource on every keystroke.
|
||||
NSTimer *publicRoomsTriggerTimer;
|
||||
|
||||
RecentsRoomListFetchersContainer *fetchersContainer;
|
||||
}
|
||||
|
||||
@property (nonatomic, assign, readwrite) SecureBackupBannerDisplay secureBackupBannerDisplay;
|
||||
@@ -88,6 +91,16 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)finalizeInitialization
|
||||
{
|
||||
[super finalizeInitialization];
|
||||
|
||||
fetchersContainer = [[RecentsRoomListFetchersContainer alloc] initWithSession:self.mxSession
|
||||
mode:_recentsDataSourceMode
|
||||
query:nil];
|
||||
[fetchersContainer addDelegate:self];
|
||||
}
|
||||
|
||||
- (void)resetSectionIndexes
|
||||
{
|
||||
crossSigningBannerSection = -1;
|
||||
@@ -104,67 +117,77 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (NSArray *)invitesCellDataArray
|
||||
- (NSArray<id<MXKRecentCellDataStoring>> *)invitesCellDataArray
|
||||
{
|
||||
return state.invitesCellDataArray;
|
||||
if (!fetchersContainer.shouldShowInvited)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
return [self mapRoomSummaries:fetchersContainer.invitedRoomListDataFetcher.data.rooms];
|
||||
}
|
||||
- (NSArray *)favoriteCellDataArray
|
||||
- (NSArray<id<MXKRecentCellDataStoring>> *)favoriteCellDataArray
|
||||
{
|
||||
return state.favoriteCellDataArray;
|
||||
if (!fetchersContainer.shouldShowFavorited)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
return [self mapRoomSummaries:fetchersContainer.favoritedRoomListDataFetcher.data.rooms];
|
||||
}
|
||||
- (NSArray *)peopleCellDataArray
|
||||
- (NSArray<id<MXKRecentCellDataStoring>> *)peopleCellDataArray
|
||||
{
|
||||
return state.peopleCellDataArray;
|
||||
if (!fetchersContainer.shouldShowDirect)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
return [self mapRoomSummaries:fetchersContainer.directRoomListDataFetcher.data.rooms];
|
||||
}
|
||||
- (NSArray *)conversationCellDataArray
|
||||
- (NSArray<id<MXKRecentCellDataStoring>> *)conversationCellDataArray
|
||||
{
|
||||
return state.conversationCellDataArray;
|
||||
if (!fetchersContainer.shouldShowConversation)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
return [self mapRoomSummaries:fetchersContainer.conversationRoomListDataFetcher.data.rooms];
|
||||
}
|
||||
- (NSArray *)lowPriorityCellDataArray
|
||||
- (NSArray<id<MXKRecentCellDataStoring>> *)lowPriorityCellDataArray
|
||||
{
|
||||
return state.lowPriorityCellDataArray;
|
||||
if (!fetchersContainer.shouldShowLowPriority)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
return [self mapRoomSummaries:fetchersContainer.lowPriorityRoomListDataFetcher.data.rooms];
|
||||
}
|
||||
- (NSArray *)serverNoticeCellDataArray
|
||||
- (NSArray<id<MXKRecentCellDataStoring>> *)serverNoticeCellDataArray
|
||||
{
|
||||
return state.serverNoticeCellDataArray;
|
||||
if (!fetchersContainer.shouldShowServerNotice)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
return [self mapRoomSummaries:fetchersContainer.serverNoticeRoomListDataFetcher.data.rooms];
|
||||
}
|
||||
|
||||
- (NSUInteger)missedFavouriteDiscussionsCount
|
||||
- (DiscussionsCount *)favoriteMissedDiscussionsCount
|
||||
{
|
||||
return state.favouriteMissedDiscussionsCount.count;
|
||||
}
|
||||
- (NSUInteger)missedHighlightFavouriteDiscussionsCount
|
||||
{
|
||||
return state.favouriteMissedDiscussionsCount.highlightCount;
|
||||
return fetchersContainer.favoritedMissedDiscussionsCount;
|
||||
}
|
||||
|
||||
- (NSUInteger)missedDirectDiscussionsCount
|
||||
- (DiscussionsCount *)directMissedDiscussionsCount
|
||||
{
|
||||
return state.directMissedDiscussionsCount.count;
|
||||
}
|
||||
- (NSUInteger)missedHighlightDirectDiscussionsCount
|
||||
{
|
||||
return state.directMissedDiscussionsCount.highlightCount;
|
||||
return fetchersContainer.directMissedDiscussionsCount;
|
||||
}
|
||||
|
||||
- (NSUInteger)missedGroupDiscussionsCount
|
||||
- (DiscussionsCount *)groupMissedDiscussionsCount
|
||||
{
|
||||
return state.groupMissedDiscussionsCount.count;
|
||||
}
|
||||
- (NSUInteger)groupMissedDiscussionsCount
|
||||
{
|
||||
return state.favouriteMissedDiscussionsCount.highlightCount;
|
||||
return fetchersContainer.conversationMissedDiscussionsCount;
|
||||
}
|
||||
|
||||
- (NSUInteger)unsentMessagesDirectDiscussionsCount
|
||||
- (NSArray<id<MXKRecentCellDataStoring>> *)mapRoomSummaries:(NSArray<id<MXRoomSummaryProtocol>> *)summaries
|
||||
{
|
||||
return state.unsentMessagesDirectDiscussionsCount;
|
||||
return [summaries vc_map:^id _Nonnull(id<MXRoomSummaryProtocol> _Nonnull summary) {
|
||||
return [[MXKRecentCellData alloc] initWithRoomSummary:summary
|
||||
dataSource:self];
|
||||
}];
|
||||
}
|
||||
- (NSUInteger)unsentMessagesGroupDiscussionsCount
|
||||
{
|
||||
return state.unsentMessagesGroupDiscussionsCount;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@@ -190,8 +213,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
}
|
||||
|
||||
[self updateSecureBackupBanner];
|
||||
[self forceRefresh];
|
||||
[self refreshCrossSigningBannerDisplay];
|
||||
[fetchersContainer updateMode:_recentsDataSourceMode];
|
||||
}
|
||||
|
||||
- (UIView *)viewForStickyHeaderInSection:(NSInteger)section withFrame:(CGRect)frame
|
||||
@@ -418,10 +441,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
// Refresh is disabled during drag&drop animation"
|
||||
if (!self.droppingCellIndexPath)
|
||||
{
|
||||
[self refreshRoomsSection:^{
|
||||
// And inform the delegate about the update
|
||||
[self.delegate dataSource:self didCellChange:nil];
|
||||
}];
|
||||
[fetchersContainer refresh];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,13 +491,13 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
favoritesSection = sectionsCount++;
|
||||
}
|
||||
|
||||
if (_recentsDataSourceMode == RecentsDataSourceModeHome)
|
||||
if (self.peopleCellDataArray.count > 0 || _recentsDataSourceMode == RecentsDataSourceModeHome)
|
||||
{
|
||||
peopleSection = sectionsCount++;
|
||||
}
|
||||
|
||||
// Keep visible the main rooms section even if it is empty, except on favourites screen.
|
||||
if (_recentsDataSourceMode != RecentsDataSourceModeFavourites)
|
||||
if (self.conversationCellDataArray.count > 0 || _recentsDataSourceMode == RecentsDataSourceModeHome)
|
||||
{
|
||||
conversationSection = sectionsCount++;
|
||||
}
|
||||
@@ -651,57 +671,56 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
- (UIView *)badgeViewForHeaderTitleInHomeSection:(NSInteger)section
|
||||
{
|
||||
// Prepare a badge to display the total of missed notifications in this section.
|
||||
NSUInteger count = 0;
|
||||
NSArray *sectionArray;
|
||||
NSUInteger totalNotificationCount = 0;
|
||||
NSUInteger totalHighlightCount = 0;
|
||||
UIView *missedNotifAndUnreadBadgeBgView = nil;
|
||||
|
||||
if (section == favoritesSection)
|
||||
{
|
||||
sectionArray = self.favoriteCellDataArray;
|
||||
totalNotificationCount = fetchersContainer.favoritedRoomListDataFetcher.data.counts.totalNotificationCount;
|
||||
totalHighlightCount = fetchersContainer.favoritedRoomListDataFetcher.data.counts.totalHighlightCount;
|
||||
}
|
||||
else if (section == peopleSection)
|
||||
{
|
||||
sectionArray = self.peopleCellDataArray;
|
||||
totalNotificationCount = fetchersContainer.directRoomListDataFetcher.data.counts.totalNotificationCount;
|
||||
totalHighlightCount = fetchersContainer.directRoomListDataFetcher.data.counts.totalHighlightCount;
|
||||
}
|
||||
else if (section == conversationSection)
|
||||
{
|
||||
sectionArray = self.conversationCellDataArray;
|
||||
totalNotificationCount = fetchersContainer.conversationRoomListDataFetcher.data.counts.totalNotificationCount;
|
||||
totalHighlightCount = fetchersContainer.conversationRoomListDataFetcher.data.counts.totalHighlightCount;
|
||||
}
|
||||
else if (section == lowPrioritySection)
|
||||
{
|
||||
sectionArray = self.lowPriorityCellDataArray;
|
||||
totalNotificationCount = fetchersContainer.lowPriorityRoomListDataFetcher.data.counts.totalNotificationCount;
|
||||
totalHighlightCount = fetchersContainer.lowPriorityRoomListDataFetcher.data.counts.totalHighlightCount;
|
||||
}
|
||||
else if (section == serverNoticeSection)
|
||||
{
|
||||
sectionArray = self.serverNoticeCellDataArray;
|
||||
totalNotificationCount = fetchersContainer.serverNoticeRoomListDataFetcher.data.counts.totalNotificationCount;
|
||||
totalHighlightCount = fetchersContainer.serverNoticeRoomListDataFetcher.data.counts.totalHighlightCount;
|
||||
}
|
||||
|
||||
BOOL highlight = NO;
|
||||
for (id<MXKRecentCellDataStoring> cellData in sectionArray)
|
||||
{
|
||||
count += cellData.notificationCount;
|
||||
highlight |= (cellData.highlightCount > 0);
|
||||
}
|
||||
|
||||
if (count)
|
||||
if (totalNotificationCount)
|
||||
{
|
||||
UILabel *missedNotifAndUnreadBadgeLabel = [[UILabel alloc] init];
|
||||
missedNotifAndUnreadBadgeLabel.textColor = ThemeService.shared.theme.baseTextPrimaryColor;
|
||||
missedNotifAndUnreadBadgeLabel.font = [UIFont boldSystemFontOfSize:14];
|
||||
if (count > 1000)
|
||||
if (totalNotificationCount > 1000)
|
||||
{
|
||||
CGFloat value = count / 1000.0;
|
||||
CGFloat value = totalNotificationCount / 1000.0;
|
||||
missedNotifAndUnreadBadgeLabel.text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"large_badge_value_k_format", @"Vector", nil), value];
|
||||
}
|
||||
else
|
||||
{
|
||||
missedNotifAndUnreadBadgeLabel.text = [NSString stringWithFormat:@"%tu", count];
|
||||
missedNotifAndUnreadBadgeLabel.text = [NSString stringWithFormat:@"%tu", totalNotificationCount];
|
||||
}
|
||||
|
||||
[missedNotifAndUnreadBadgeLabel sizeToFit];
|
||||
|
||||
CGFloat bgViewWidth = missedNotifAndUnreadBadgeLabel.frame.size.width + 18;
|
||||
|
||||
BOOL highlight = 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;
|
||||
@@ -1013,7 +1032,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
{
|
||||
id<MXKRecentCellDataStoring> cellDataStoring = cellDataArray[index];
|
||||
|
||||
if ([roomId isEqualToString:cellDataStoring.roomSummary.roomId] && (matrixSession == cellDataStoring.roomSummary.room.mxSession))
|
||||
if ([roomId isEqualToString:cellDataStoring.roomSummary.roomId] && cellDataStoring.mxSession == matrixSession)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
@@ -1121,389 +1140,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
return indexPath;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - MXKDataSourceDelegate
|
||||
|
||||
- (void)refreshRoomsSection:(void (^)(void))onComplete
|
||||
{
|
||||
if (displayedRecentsDataSourceArray.count > 0)
|
||||
{
|
||||
// FIXME manage multi accounts
|
||||
MXKSessionRecentsDataSource *recentsDataSource = displayedRecentsDataSourceArray[0];
|
||||
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *cells = [NSMutableArray new];
|
||||
NSInteger count = recentsDataSource.numberOfCells;
|
||||
|
||||
for (NSUInteger index = 0; index < count; index++)
|
||||
{
|
||||
id<MXKRecentCellDataStoring> cell = [recentsDataSource cellDataAtIndex:index];
|
||||
[cells addObject:cell];
|
||||
}
|
||||
|
||||
MXWeakify(self);
|
||||
[self computeStateAsyncWithCells:cells recentsDataSourceMode:self.recentsDataSourceMode matrixSession:recentsDataSource.mxSession onComplete:^(RecentsDataSourceState *newState) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
self->state = newState;
|
||||
onComplete();
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
onComplete();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)computeStateAsyncWithCells:(NSArray<id<MXKRecentCellDataStoring>> *)cells
|
||||
recentsDataSourceMode:(RecentsDataSourceMode)recentsDataSourceMode
|
||||
matrixSession:(MXSession*)mxSession
|
||||
onComplete:(void (^)(RecentsDataSourceState *newState))onComplete
|
||||
{
|
||||
dispatch_async(processingQueue, ^{
|
||||
RecentsDataSourceState *newState = [RecentsDataSource computeStateWithCells:cells recentsDataSourceMode:recentsDataSourceMode matrixSession:mxSession];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
onComplete(newState);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
+ (RecentsDataSourceState *)computeStateWithCells:(NSArray<id<MXKRecentCellDataStoring>> *)cells
|
||||
recentsDataSourceMode:(RecentsDataSourceMode)recentsDataSourceMode
|
||||
matrixSession:(MXSession*)mxSession
|
||||
{
|
||||
NSDate *startDate = [NSDate date];
|
||||
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *invitesCellDataArray = [NSMutableArray new];
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *favoriteCellDataArray = [NSMutableArray new];
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *peopleCellDataArray = [NSMutableArray new];
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *conversationCellDataArray = [NSMutableArray new];
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *lowPriorityCellDataArray = [NSMutableArray new];
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *serverNoticeCellDataArray = [NSMutableArray new];
|
||||
|
||||
MissedDiscussionsCount *favouriteMissedDiscussionsCount = [MissedDiscussionsCount new];
|
||||
MissedDiscussionsCount *directMissedDiscussionsCount = [MissedDiscussionsCount new];
|
||||
MissedDiscussionsCount *groupMissedDiscussionsCount = [MissedDiscussionsCount new];
|
||||
NSUInteger unsentMessagesDirectDiscussionsCount = 0;
|
||||
NSUInteger unsentMessagesGroupDiscussionsCount = 0;
|
||||
|
||||
for (id<MXKRecentCellDataStoring> recentCellDataStoring in cells)
|
||||
{
|
||||
MXRoom* room = recentCellDataStoring.roomSummary.room;
|
||||
|
||||
if (recentsDataSourceMode == RecentsDataSourceModeHome)
|
||||
{
|
||||
if (room.accountData.tags[kMXRoomTagServerNotice])
|
||||
{
|
||||
[serverNoticeCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
else if (room.accountData.tags[kMXRoomTagFavourite])
|
||||
{
|
||||
[favoriteCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
else if (room.accountData.tags[kMXRoomTagLowPriority])
|
||||
{
|
||||
[lowPriorityCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
else if (room.summary.membership == MXMembershipInvite)
|
||||
{
|
||||
if (!MXSDKOptions.sharedInstance.autoAcceptRoomInvites)
|
||||
{
|
||||
[invitesCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
}
|
||||
else if (room.isDirect)
|
||||
{
|
||||
[peopleCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hide spaces from home (keep space invites)
|
||||
if (room.summary.roomType != MXRoomTypeSpace)
|
||||
{
|
||||
[conversationCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (recentsDataSourceMode == RecentsDataSourceModeFavourites)
|
||||
{
|
||||
// Keep only the favourites rooms.
|
||||
if (room.accountData.tags[kMXRoomTagFavourite])
|
||||
{
|
||||
[favoriteCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
}
|
||||
else if (recentsDataSourceMode == RecentsDataSourceModePeople)
|
||||
{
|
||||
// Keep only the direct rooms which are not low priority
|
||||
if (room.isDirect && !room.accountData.tags[kMXRoomTagLowPriority])
|
||||
{
|
||||
if (room.summary.membership == MXMembershipInvite)
|
||||
{
|
||||
if (!MXSDKOptions.sharedInstance.autoAcceptRoomInvites)
|
||||
{
|
||||
[invitesCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
[conversationCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (recentsDataSourceMode == RecentsDataSourceModeRooms)
|
||||
{
|
||||
// Consider only non direct rooms.
|
||||
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)
|
||||
{
|
||||
if (!MXSDKOptions.sharedInstance.autoAcceptRoomInvites)
|
||||
{
|
||||
[invitesCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
}
|
||||
else if ((!room.accountData.tags.count || room.accountData.tags[kMXRoomTagFavourite]) && room.summary.roomType != MXRoomTypeSpace)
|
||||
{
|
||||
[conversationCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update missed conversations counts
|
||||
NSUInteger notificationCount = recentCellDataStoring.roomSummary.notificationCount;
|
||||
|
||||
// Ignore the regular notification count if the room is in 'mentions only" mode at the Riot level.
|
||||
if (room.isMentionsOnly)
|
||||
{
|
||||
// Only the highlighted missed messages must be considered here.
|
||||
notificationCount = recentCellDataStoring.roomSummary.highlightCount;
|
||||
}
|
||||
|
||||
if (notificationCount)
|
||||
{
|
||||
if (room.accountData.tags[kMXRoomTagFavourite])
|
||||
{
|
||||
favouriteMissedDiscussionsCount.count ++;
|
||||
|
||||
if (recentCellDataStoring.roomSummary.highlightCount)
|
||||
{
|
||||
favouriteMissedDiscussionsCount.highlightCount ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (room.isDirect)
|
||||
{
|
||||
directMissedDiscussionsCount.count ++;
|
||||
|
||||
if (recentCellDataStoring.roomSummary.highlightCount)
|
||||
{
|
||||
directMissedDiscussionsCount.highlightCount ++;
|
||||
}
|
||||
}
|
||||
else if (!room.accountData.tags.count || room.accountData.tags[kMXRoomTagFavourite])
|
||||
{
|
||||
groupMissedDiscussionsCount.count ++;
|
||||
|
||||
if (recentCellDataStoring.roomSummary.highlightCount)
|
||||
{
|
||||
groupMissedDiscussionsCount.highlightCount ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (room.summary.membership == MXMembershipInvite)
|
||||
{
|
||||
if (room.isDirect)
|
||||
{
|
||||
directMissedDiscussionsCount.count ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
groupMissedDiscussionsCount.highlightCount ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (room.sentStatus != RoomSentStatusOk)
|
||||
{
|
||||
if (room.isDirect)
|
||||
{
|
||||
unsentMessagesDirectDiscussionsCount ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsentMessagesGroupDiscussionsCount ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (recentsDataSourceMode == RecentsDataSourceModeHome)
|
||||
{
|
||||
BOOL pinMissedNotif = RiotSettings.shared.pinRoomsWithMissedNotificationsOnHome;
|
||||
BOOL pinUnread = RiotSettings.shared.pinRoomsWithUnreadMessagesOnHome;
|
||||
NSComparator comparator = nil;
|
||||
|
||||
if (pinMissedNotif)
|
||||
{
|
||||
// Sort each rooms collection by considering first the rooms with some missed notifs, the rooms with unread, then the others.
|
||||
comparator = ^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) {
|
||||
|
||||
if (recentCellData1.roomSummary.room.sentStatus != RoomSentStatusOk
|
||||
&& recentCellData2.roomSummary.room.sentStatus == RoomSentStatusOk)
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
|
||||
if (recentCellData2.roomSummary.room.sentStatus != RoomSentStatusOk
|
||||
&& recentCellData1.roomSummary.room.sentStatus == RoomSentStatusOk)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
|
||||
if (recentCellData1.highlightCount)
|
||||
{
|
||||
if (recentCellData2.highlightCount)
|
||||
{
|
||||
return NSOrderedSame;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
}
|
||||
else if (recentCellData2.highlightCount)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
else if (recentCellData1.notificationCount)
|
||||
{
|
||||
if (recentCellData2.notificationCount)
|
||||
{
|
||||
return NSOrderedSame;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
}
|
||||
else if (recentCellData2.notificationCount)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
else if (pinUnread)
|
||||
{
|
||||
if (recentCellData1.hasUnread)
|
||||
{
|
||||
if (recentCellData2.hasUnread)
|
||||
{
|
||||
return NSOrderedSame;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
}
|
||||
else if (recentCellData2.hasUnread)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
}
|
||||
|
||||
return NSOrderedSame;
|
||||
};
|
||||
}
|
||||
else if (pinUnread)
|
||||
{
|
||||
// Sort each rooms collection by considering first the rooms with some unread messages then the others.
|
||||
comparator = ^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) {
|
||||
|
||||
if (recentCellData1.roomSummary.room.sentStatus != RoomSentStatusOk
|
||||
&& recentCellData2.roomSummary.room.sentStatus == RoomSentStatusOk)
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
|
||||
if (recentCellData2.roomSummary.room.sentStatus != RoomSentStatusOk
|
||||
&& recentCellData1.roomSummary.room.sentStatus == RoomSentStatusOk)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
|
||||
if (recentCellData1.hasUnread)
|
||||
{
|
||||
if (recentCellData2.hasUnread)
|
||||
{
|
||||
return NSOrderedSame;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
}
|
||||
else if (recentCellData2.hasUnread)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
|
||||
return NSOrderedSame;
|
||||
};
|
||||
}
|
||||
|
||||
if (comparator)
|
||||
{
|
||||
// Sort the rooms collections
|
||||
[favoriteCellDataArray sortUsingComparator:comparator];
|
||||
[peopleCellDataArray sortUsingComparator:comparator];
|
||||
[conversationCellDataArray sortUsingComparator:comparator];
|
||||
[lowPriorityCellDataArray sortUsingComparator:comparator];
|
||||
[serverNoticeCellDataArray sortUsingComparator:comparator];
|
||||
}
|
||||
}
|
||||
else if (favoriteCellDataArray.count > 0 && recentsDataSourceMode == RecentsDataSourceModeFavourites)
|
||||
{
|
||||
// Sort them according to their tag order
|
||||
[favoriteCellDataArray sortUsingComparator:^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) {
|
||||
|
||||
return [mxSession compareRoomsByTag:kMXRoomTagFavourite room1:recentCellData1.roomSummary.room room2:recentCellData2.roomSummary.room];
|
||||
|
||||
}];
|
||||
}
|
||||
else if (conversationCellDataArray.count > 0 && (recentsDataSourceMode == RecentsDataSourceModeRooms || recentsDataSourceMode == RecentsDataSourceModePeople))
|
||||
{
|
||||
[conversationCellDataArray sortUsingComparator:^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) {
|
||||
|
||||
if (recentCellData1.roomSummary.room.sentStatus != RoomSentStatusOk
|
||||
&& recentCellData2.roomSummary.room.sentStatus == RoomSentStatusOk)
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
|
||||
if (recentCellData2.roomSummary.room.sentStatus != RoomSentStatusOk
|
||||
&& recentCellData1.roomSummary.room.sentStatus == RoomSentStatusOk)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
|
||||
return NSOrderedAscending;
|
||||
}];
|
||||
}
|
||||
|
||||
MXLogDebug(@"[RecentsDataSource] refreshRoomsSections: Done in %.0fms", [[NSDate date] timeIntervalSinceDate:startDate] * 1000);
|
||||
|
||||
return [[RecentsDataSourceState alloc]
|
||||
initWithInvitesCellDataArray:invitesCellDataArray
|
||||
favoriteCellDataArray:favoriteCellDataArray
|
||||
peopleCellDataArray:peopleCellDataArray
|
||||
conversationCellDataArray:conversationCellDataArray
|
||||
lowPriorityCellDataArray:lowPriorityCellDataArray
|
||||
serverNoticeCellDataArray:serverNoticeCellDataArray
|
||||
favouriteMissedDiscussionsCount:favouriteMissedDiscussionsCount
|
||||
directMissedDiscussionsCount:directMissedDiscussionsCount
|
||||
groupMissedDiscussionsCount:groupMissedDiscussionsCount
|
||||
unsentMessagesDirectDiscussionsCount:unsentMessagesDirectDiscussionsCount
|
||||
unsentMessagesGroupDiscussionsCount:unsentMessagesGroupDiscussionsCount];
|
||||
}
|
||||
|
||||
- (void)dataSource:(MXKDataSource*)dataSource didCellChange:(id)changes
|
||||
{
|
||||
// Refresh is disabled during drag&drop animation
|
||||
@@ -1523,12 +1161,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
// 1 - call [super thisNewMethod]
|
||||
// 2 - call [self refreshRoomsSections]
|
||||
|
||||
// refresh the sections
|
||||
[self refreshRoomsSection:^{
|
||||
// Call super to keep update readyRecentsDataSourceArray.
|
||||
[super dataSource:dataSource didCellChange:changes];
|
||||
}];
|
||||
|
||||
// Call super to keep update readyRecentsDataSourceArray.
|
||||
[super dataSource:dataSource didCellChange:changes];
|
||||
}
|
||||
|
||||
#pragma mark - Drag & Drop handling
|
||||
@@ -1597,6 +1231,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
|
||||
[publicRoomsTriggerTimer invalidate];
|
||||
publicRoomsTriggerTimer = nil;
|
||||
|
||||
[fetchersContainer stop];
|
||||
}
|
||||
|
||||
#pragma mark - Override MXKRecentsDataSource
|
||||
@@ -1604,11 +1240,13 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
- (void)searchWithPatterns:(NSArray *)patternsList
|
||||
{
|
||||
[super searchWithPatterns:patternsList];
|
||||
|
||||
NSString *searchPattern = [patternsList componentsJoinedByString:@" "];
|
||||
|
||||
[fetchersContainer updateQuery:searchPattern];
|
||||
|
||||
if (_publicRoomsDirectoryDataSource)
|
||||
{
|
||||
NSString *searchPattern = [patternsList componentsJoinedByString:@" "];
|
||||
|
||||
// Do not send a /publicRooms request for every keystroke
|
||||
// Let user finish typing
|
||||
[publicRoomsTriggerTimer invalidate];
|
||||
@@ -1755,4 +1393,12 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
[self hideCrossSigningBannerWithDisplay:self.crossSigningBannerDisplay];
|
||||
}
|
||||
|
||||
#pragma mark - MXRoomListDataFetcherDelegate
|
||||
|
||||
- (void)fetcherDidChangeData:(id<MXRoomListDataFetcher>)fetcher
|
||||
{
|
||||
// TODO: Update only updated sections
|
||||
[self.delegate dataSource:self didCellChange:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -30,15 +30,10 @@ class RecentsDataSourceState: NSObject {
|
||||
let lowPriorityCellDataArray: [MXKRecentCellDataStoring]
|
||||
let serverNoticeCellDataArray: [MXKRecentCellDataStoring]
|
||||
|
||||
// MARK: Notifications counts
|
||||
let favouriteMissedDiscussionsCount: MissedDiscussionsCount
|
||||
let directMissedDiscussionsCount: MissedDiscussionsCount
|
||||
let groupMissedDiscussionsCount: MissedDiscussionsCount
|
||||
|
||||
// MARK: Unsent counts
|
||||
let unsentMessagesDirectDiscussionsCount: UInt
|
||||
let unsentMessagesGroupDiscussionsCount: UInt
|
||||
|
||||
// MARK: Discussion counts
|
||||
let favouriteMissedDiscussionsCount: DiscussionsCount
|
||||
let directMissedDiscussionsCount: DiscussionsCount
|
||||
let groupMissedDiscussionsCount: DiscussionsCount
|
||||
|
||||
// MARK: - Setup
|
||||
init(invitesCellDataArray: [MXKRecentCellDataStoring],
|
||||
@@ -47,11 +42,9 @@ class RecentsDataSourceState: NSObject {
|
||||
conversationCellDataArray: [MXKRecentCellDataStoring],
|
||||
lowPriorityCellDataArray: [MXKRecentCellDataStoring],
|
||||
serverNoticeCellDataArray: [MXKRecentCellDataStoring],
|
||||
favouriteMissedDiscussionsCount: MissedDiscussionsCount,
|
||||
directMissedDiscussionsCount: MissedDiscussionsCount,
|
||||
groupMissedDiscussionsCount: MissedDiscussionsCount,
|
||||
unsentMessagesDirectDiscussionsCount: UInt,
|
||||
unsentMessagesGroupDiscussionsCount: UInt) {
|
||||
favouriteMissedDiscussionsCount: DiscussionsCount,
|
||||
directMissedDiscussionsCount: DiscussionsCount,
|
||||
groupMissedDiscussionsCount: DiscussionsCount) {
|
||||
self.invitesCellDataArray = invitesCellDataArray
|
||||
self.favoriteCellDataArray = favoriteCellDataArray
|
||||
self.peopleCellDataArray = peopleCellDataArray
|
||||
@@ -61,19 +54,6 @@ class RecentsDataSourceState: NSObject {
|
||||
self.favouriteMissedDiscussionsCount = favouriteMissedDiscussionsCount
|
||||
self.directMissedDiscussionsCount = directMissedDiscussionsCount
|
||||
self.groupMissedDiscussionsCount = groupMissedDiscussionsCount
|
||||
self.unsentMessagesDirectDiscussionsCount = unsentMessagesDirectDiscussionsCount
|
||||
self.unsentMessagesGroupDiscussionsCount = unsentMessagesGroupDiscussionsCount
|
||||
super.init()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Noticiations counts per section
|
||||
@objcMembers
|
||||
class MissedDiscussionsCount: NSObject {
|
||||
/// Regular notifications
|
||||
var count: UInt = 0
|
||||
|
||||
/// Mentions like notications
|
||||
var highlightCount: UInt = 0
|
||||
}
|
||||
|
||||
@@ -0,0 +1,430 @@
|
||||
//
|
||||
// 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?
|
||||
|
||||
// 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?
|
||||
|
||||
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],
|
||||
.favourites: [.favorited],
|
||||
.people: [.directPeople],
|
||||
.rooms: [.conversationRooms]
|
||||
]
|
||||
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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) {
|
||||
self.session = session
|
||||
self.mode = mode
|
||||
self.query = query
|
||||
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 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 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,
|
||||
paginate: Bool = true) -> MXRoomListDataFetcher {
|
||||
let filterOptions = MXRoomListDataFilterOptions(dataTypes: dataTypes,
|
||||
query: query)
|
||||
|
||||
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])
|
||||
}
|
||||
|
||||
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]
|
||||
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 none: FetcherTypes = []
|
||||
static let all: FetcherTypes = [
|
||||
.invited, .favorited, .directHome, .directPeople, .conversationHome, .conversationRooms, .lowPriority, .serverNotice]
|
||||
}
|
||||
Reference in New Issue
Block a user