mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-20 16:42:44 +02:00
Merge branch 'ismail/5068_start_thread' into ismail/5096_thread_notifications
This commit is contained in:
@@ -1826,27 +1826,31 @@ static NSArray<NSNumber*> *initialSyncSilentErrorsHTTPStatusCodes;
|
||||
|
||||
dispatch_group_t dispatchGroup = dispatch_group_create();
|
||||
|
||||
for (MXRoomSummary *summary in mxSession.roomsSummaries)
|
||||
for (MXRoom *room in mxSession.rooms)
|
||||
{
|
||||
dispatch_group_enter(dispatchGroup);
|
||||
[summary.mxSession eventWithEventId:summary.lastMessage.eventId
|
||||
inRoom:summary.roomId
|
||||
success:^(MXEvent *event) {
|
||||
|
||||
if (event)
|
||||
{
|
||||
if (summary.lastMessage.others == nil)
|
||||
MXRoomSummary *summary = room.summary;
|
||||
if (summary)
|
||||
{
|
||||
dispatch_group_enter(dispatchGroup);
|
||||
[summary.mxSession eventWithEventId:summary.lastMessage.eventId
|
||||
inRoom:summary.roomId
|
||||
success:^(MXEvent *event) {
|
||||
|
||||
if (event)
|
||||
{
|
||||
summary.lastMessage.others = [NSMutableDictionary dictionary];
|
||||
if (summary.lastMessage.others == nil)
|
||||
{
|
||||
summary.lastMessage.others = [NSMutableDictionary dictionary];
|
||||
}
|
||||
summary.lastMessage.others[@"lastEventDate"] = [eventFormatter dateStringFromEvent:event withTime:YES];
|
||||
[self->mxSession.store.roomSummaryStore storeSummary:summary];
|
||||
}
|
||||
summary.lastMessage.others[@"lastEventDate"] = [eventFormatter dateStringFromEvent:event withTime:YES];
|
||||
[self->mxSession.store storeSummaryForRoom:summary.roomId summary:summary];
|
||||
}
|
||||
|
||||
dispatch_group_leave(dispatchGroup);
|
||||
} failure:^(NSError *error) {
|
||||
dispatch_group_leave(dispatchGroup);
|
||||
}];
|
||||
|
||||
dispatch_group_leave(dispatchGroup);
|
||||
} failure:^(NSError *error) {
|
||||
dispatch_group_leave(dispatchGroup);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{
|
||||
|
||||
@@ -33,7 +33,6 @@ typedef enum : NSUInteger {
|
||||
MXKAttachmentTypeAudio,
|
||||
MXKAttachmentTypeVoiceMessage,
|
||||
MXKAttachmentTypeVideo,
|
||||
MXKAttachmentTypeLocation,
|
||||
MXKAttachmentTypeFile,
|
||||
MXKAttachmentTypeSticker
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ NSString *const kMXKAttachmentFileNameBase = @"attatchment";
|
||||
else
|
||||
{
|
||||
// Note: mxEvent.eventType is supposed to be MXEventTypeRoomMessage here.
|
||||
NSString *msgtype = eventContent[@"msgtype"];
|
||||
NSString *msgtype = eventContent[kMXMessageTypeKey];
|
||||
if ([msgtype isEqualToString:kMXMessageTypeImage])
|
||||
{
|
||||
_type = MXKAttachmentTypeImage;
|
||||
@@ -109,12 +109,6 @@ NSString *const kMXKAttachmentFileNameBase = @"attatchment";
|
||||
_type = MXKAttachmentTypeVideo;
|
||||
MXJSONModelSetDictionary(_thumbnailInfo, eventContent[@"info"][@"thumbnail_info"]);
|
||||
}
|
||||
else if ([msgtype isEqualToString:kMXMessageTypeLocation])
|
||||
{
|
||||
// Not supported yet
|
||||
// _type = MXKAttachmentTypeLocation;
|
||||
return nil;
|
||||
}
|
||||
else if ([msgtype isEqualToString:kMXMessageTypeFile])
|
||||
{
|
||||
_type = MXKAttachmentTypeFile;
|
||||
@@ -125,7 +119,7 @@ NSString *const kMXKAttachmentFileNameBase = @"attatchment";
|
||||
}
|
||||
}
|
||||
|
||||
MXJSONModelSetString(_originalFileName, eventContent[@"body"]);
|
||||
MXJSONModelSetString(_originalFileName, eventContent[kMXMessageBodyKey]);
|
||||
MXJSONModelSetDictionary(_contentInfo, eventContent[@"info"]);
|
||||
MXJSONModelSetMXJSONModel(contentFile, MXEncryptedContentFile, eventContent[@"file"]);
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ static NSAttributedString *messageSeparator = nil;
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add all components of the provided message
|
||||
for (MXKRoomBubbleComponent* component in cellData.bubbleComponents)
|
||||
{
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *messageType = self.event.content[@"msgtype"];
|
||||
NSString *messageType = self.event.content[kMXMessageTypeKey];
|
||||
|
||||
if (!messageType || !([messageType isEqualToString:kMXMessageTypeText] || [messageType isEqualToString:kMXMessageTypeNotice] || [messageType isEqualToString:kMXMessageTypeEmote]))
|
||||
{
|
||||
|
||||
@@ -605,6 +605,25 @@ extern NSString *const kMXKRoomDataSourceTimelineErrorErrorKey;
|
||||
success:(void (^)(NSString *eventId))success
|
||||
failure:(void (^)(NSError *error))failure;
|
||||
|
||||
/**
|
||||
Send a location message to a room.
|
||||
|
||||
While sending, a fake event will be echoed in the messages list.
|
||||
Once complete, this local echo will be replaced by the event saved by the homeserver.
|
||||
|
||||
@param latitude the location's latitude
|
||||
@param longitude the location's longitude
|
||||
@param description an optional description
|
||||
@param success A block object called when the operation succeeds. It returns
|
||||
the event id of the event generated on the homeserver
|
||||
@param failure A block object called when the operation fails.
|
||||
*/
|
||||
- (void)sendLocationWithLatitude:(double)latitude
|
||||
longitude:(double)longitude
|
||||
description:(NSString *)description
|
||||
success:(void (^)(NSString *))success
|
||||
failure:(void (^)(NSError *))failure;
|
||||
|
||||
/**
|
||||
Send a generic non state event to a room.
|
||||
|
||||
|
||||
@@ -2062,6 +2062,29 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sendLocationWithLatitude:(double)latitude
|
||||
longitude:(double)longitude
|
||||
description:(NSString *)description
|
||||
success:(void (^)(NSString *))success
|
||||
failure:(void (^)(NSError *))failure
|
||||
{
|
||||
__block MXEvent *localEchoEvent = nil;
|
||||
|
||||
// Make the request to the homeserver
|
||||
[_room sendLocationWithLatitude:latitude
|
||||
longitude:longitude
|
||||
description:description
|
||||
localEcho:&localEchoEvent
|
||||
success:success failure:failure];
|
||||
|
||||
if (localEchoEvent)
|
||||
{
|
||||
// Make the data source digest this fake local echo message
|
||||
[self queueEventForProcessing:localEchoEvent withRoomState:self.roomState direction:MXTimelineDirectionForwards];
|
||||
[self processQueuedEvents:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sendEventOfType:(MXEventTypeString)eventTypeString content:(NSDictionary<NSString*, id>*)msgContent success:(void (^)(NSString *eventId))success failure:(void (^)(NSError *error))failure
|
||||
{
|
||||
__block MXEvent *localEchoEvent = nil;
|
||||
@@ -2099,7 +2122,7 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
|
||||
else if ([event.type isEqualToString:kMXEventTypeStringRoomMessage])
|
||||
{
|
||||
// And retry the send the message according to its type
|
||||
NSString *msgType = event.content[@"msgtype"];
|
||||
NSString *msgType = event.content[kMXMessageTypeKey];
|
||||
if ([msgType isEqualToString:kMXMessageTypeText] || [msgType isEqualToString:kMXMessageTypeEmote])
|
||||
{
|
||||
// Resend the Matrix event by reusing the existing echo
|
||||
@@ -2860,7 +2883,7 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSString *messageType = event.content[@"msgtype"];
|
||||
NSString *messageType = event.content[kMXMessageTypeKey];
|
||||
if (messageType == nil || [messageType isEqualToString:@"m.bad.encrypted"]) {
|
||||
return NO;
|
||||
}
|
||||
@@ -4058,7 +4081,7 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
|
||||
|
||||
if ([self canPerformActionOnEvent:event])
|
||||
{
|
||||
NSString *messageType = event.content[@"msgtype"];
|
||||
NSString *messageType = event.content[kMXMessageTypeKey];
|
||||
|
||||
if ([messageType isEqualToString:kMXMessageTypeKeyVerificationRequest])
|
||||
{
|
||||
@@ -4101,7 +4124,7 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
|
||||
{
|
||||
MXEvent *event = [self eventWithEventId:eventId];
|
||||
BOOL isRoomMessage = event.eventType == MXEventTypeRoomMessage;
|
||||
NSString *messageType = event.content[@"msgtype"];
|
||||
NSString *messageType = event.content[kMXMessageTypeKey];
|
||||
|
||||
return isRoomMessage
|
||||
&& ([messageType isEqualToString:kMXMessageTypeText] || [messageType isEqualToString:kMXMessageTypeEmote])
|
||||
@@ -4122,7 +4145,7 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
|
||||
}
|
||||
else
|
||||
{
|
||||
editableTextMessage = event.content[@"body"];
|
||||
editableTextMessage = event.content[kMXMessageBodyKey];
|
||||
}
|
||||
|
||||
return editableTextMessage;
|
||||
@@ -4239,7 +4262,7 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
|
||||
NSString *sanitizedText = [self sanitizedMessageText:text];
|
||||
NSString *formattedText = [self htmlMessageFromSanitizedText:sanitizedText];
|
||||
|
||||
NSString *eventBody = event.content[@"body"];
|
||||
NSString *eventBody = event.content[kMXMessageBodyKey];
|
||||
NSString *eventFormattedBody = event.content[@"formatted_body"];
|
||||
|
||||
if (![sanitizedText isEqualToString:eventBody] && (!eventFormattedBody || ![formattedText isEqualToString:eventFormattedBody]))
|
||||
|
||||
@@ -45,6 +45,11 @@
|
||||
return [MatrixKitL10n messageReplyToSenderSentAFile];
|
||||
}
|
||||
|
||||
- (NSString *)senderSentTheirLocation
|
||||
{
|
||||
return [MatrixKitL10n messageReplyToSenderSentTheirLocation];
|
||||
}
|
||||
|
||||
- (NSString *)messageToReplyToPrefix
|
||||
{
|
||||
return [MatrixKitL10n messageReplyToMessageToReplyToPrefix];
|
||||
|
||||
@@ -46,7 +46,14 @@
|
||||
|
||||
- (MXSession *)mxSession
|
||||
{
|
||||
return dataSource.mxSession;
|
||||
MXSession *session = dataSource.mxSession;
|
||||
|
||||
if (session == nil)
|
||||
{
|
||||
session = roomSummary.mxSession;
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
- (NSString*)lastEventDate
|
||||
|
||||
@@ -25,52 +25,6 @@
|
||||
|
||||
#pragma mark - Constant definitions
|
||||
NSString *const kMXKRecentCellIdentifier = @"kMXKRecentCellIdentifier";
|
||||
static NSTimeInterval const roomSummaryChangeThrottlerDelay = .5;
|
||||
|
||||
|
||||
@interface MXKSessionRecentsDataSource ()
|
||||
{
|
||||
MXKRoomDataSourceManager *roomDataSourceManager;
|
||||
|
||||
/**
|
||||
Internal array used to regulate change notifications.
|
||||
Cell data changes are stored instantly in this array.
|
||||
These changes are reported to the delegate only if no server sync is in progress.
|
||||
*/
|
||||
NSMutableArray *internalCellDataArray;
|
||||
|
||||
/**
|
||||
Store the current search patterns list.
|
||||
*/
|
||||
NSArray* searchPatternsList;
|
||||
|
||||
/**
|
||||
Do not react on every summary change
|
||||
*/
|
||||
MXThrottler *roomSummaryChangeThrottler;
|
||||
|
||||
/**
|
||||
Last received suggested rooms per space ID
|
||||
*/
|
||||
NSMutableDictionary<NSString*, NSArray<MXSpaceChildInfo *> *> *lastSuggestedRooms;
|
||||
|
||||
/**
|
||||
Event listener of the current space used to update the UI if an event occurs.
|
||||
*/
|
||||
id spaceEventsListener;
|
||||
|
||||
/**
|
||||
Observer used to reload data when the space service is initialised
|
||||
*/
|
||||
id spaceServiceDidInitialiseObserver;
|
||||
}
|
||||
|
||||
/**
|
||||
Additional suggestedRooms related to the current selected Space
|
||||
*/
|
||||
@property (nonatomic, strong) NSArray<MXSpaceChildInfo *> *suggestedRooms;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MXKSessionRecentsDataSource
|
||||
|
||||
@@ -79,474 +33,52 @@ static NSTimeInterval const roomSummaryChangeThrottlerDelay = .5;
|
||||
self = [super initWithMatrixSession:matrixSession];
|
||||
if (self)
|
||||
{
|
||||
roomDataSourceManager = [MXKRoomDataSourceManager sharedManagerForMatrixSession:self.mxSession];
|
||||
// Update here data source state
|
||||
if (state != MXKDataSourceStateReady)
|
||||
{
|
||||
state = MXKDataSourceStateReady;
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(dataSource:didStateChange:)])
|
||||
{
|
||||
[self.delegate dataSource:self didStateChange:state];
|
||||
}
|
||||
}
|
||||
|
||||
internalCellDataArray = [NSMutableArray array];
|
||||
filteredCellDataArray = nil;
|
||||
|
||||
lastSuggestedRooms = [NSMutableDictionary new];
|
||||
|
||||
// Set default data and view classes
|
||||
[self registerCellDataClass:MXKRecentCellData.class forCellIdentifier:kMXKRecentCellIdentifier];
|
||||
|
||||
roomSummaryChangeThrottler = [[MXThrottler alloc] initWithMinimumDelay:roomSummaryChangeThrottlerDelay];
|
||||
|
||||
[[MXKAppSettings standardAppSettings] addObserver:self forKeyPath:@"showAllRoomsInHomeSpace" options:0 context:nil];
|
||||
// And inform the delegate about the update
|
||||
[self.delegate dataSource:self didCellChange:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)destroy
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXRoomSummaryDidChangeNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXKRoomDataSourceSyncStatusChanged object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionNewRoomNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionDidLeaveRoomNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionDirectRoomsDidChangeNotification object:nil];
|
||||
|
||||
if (spaceServiceDidInitialiseObserver) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:spaceServiceDidInitialiseObserver];
|
||||
}
|
||||
|
||||
[roomSummaryChangeThrottler cancelAll];
|
||||
roomSummaryChangeThrottler = nil;
|
||||
|
||||
cellDataArray = nil;
|
||||
internalCellDataArray = nil;
|
||||
filteredCellDataArray = nil;
|
||||
lastSuggestedRooms = nil;
|
||||
|
||||
searchPatternsList = nil;
|
||||
|
||||
[[MXKAppSettings standardAppSettings] removeObserver:self forKeyPath:@"showAllRoomsInHomeSpace" context:nil];
|
||||
|
||||
[super destroy];
|
||||
}
|
||||
|
||||
- (void)didMXSessionStateChange
|
||||
{
|
||||
if (MXSessionStateStoreDataReady <= self.mxSession.state)
|
||||
{
|
||||
// Check whether some data have been already load
|
||||
if (0 == internalCellDataArray.count)
|
||||
{
|
||||
[self loadData];
|
||||
}
|
||||
else if (!roomDataSourceManager.isServerSyncInProgress)
|
||||
{
|
||||
// Sort cell data and notify the delegate
|
||||
[self sortCellDataAndNotifyChanges];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setCurrentSpace:(MXSpace *)currentSpace
|
||||
{
|
||||
if (_currentSpace == currentSpace)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_currentSpace && spaceEventsListener)
|
||||
{
|
||||
[_currentSpace.room removeListener:spaceEventsListener];
|
||||
}
|
||||
|
||||
_currentSpace = currentSpace;
|
||||
|
||||
self.suggestedRooms = _currentSpace ? lastSuggestedRooms[_currentSpace.spaceId] : nil;
|
||||
[self updateSuggestedRooms];
|
||||
|
||||
MXWeakify(self);
|
||||
spaceEventsListener = [self.currentSpace.room listenToEvents:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self updateSuggestedRooms];
|
||||
}];
|
||||
}
|
||||
|
||||
-(void)setSuggestedRooms:(NSArray<MXSpaceChildInfo *> *)suggestedRooms
|
||||
{
|
||||
_suggestedRooms = suggestedRooms;
|
||||
[self loadData];
|
||||
}
|
||||
|
||||
-(void)updateSuggestedRooms
|
||||
{
|
||||
if (self.currentSpace)
|
||||
{
|
||||
NSString *currentSpaceId = self.currentSpace.spaceId;
|
||||
MXWeakify(self);
|
||||
[self.mxSession.spaceService getSpaceChildrenForSpaceWithId:currentSpaceId suggestedOnly:YES limit:5 maxDepth:1 paginationToken:nil success:^(MXSpaceChildrenSummary * _Nonnull childrenSummary) {
|
||||
MXLogDebug(@"[MXKSessionRecentsDataSource] getSpaceChildrenForSpaceWithId %@: %ld found", self.currentSpace.spaceId, childrenSummary.childInfos.count);
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->lastSuggestedRooms[currentSpaceId] = childrenSummary.childInfos;
|
||||
if ([self.currentSpace.spaceId isEqual:currentSpaceId]) {
|
||||
self.suggestedRooms = childrenSummary.childInfos;
|
||||
}
|
||||
} failure:^(NSError * _Nonnull error) {
|
||||
MXLogError(@"[MXKSessionRecentsDataSource] getSpaceChildrenForSpaceWithId failed with error: %@", error);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (NSInteger)numberOfCells
|
||||
{
|
||||
if (filteredCellDataArray)
|
||||
{
|
||||
return filteredCellDataArray.count;
|
||||
}
|
||||
return cellDataArray.count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (BOOL)hasUnread
|
||||
{
|
||||
// Check all current cells
|
||||
// Use numberOfRowsInSection methods so that we take benefit of the filtering
|
||||
for (NSUInteger i = 0; i < self.numberOfCells; i++)
|
||||
{
|
||||
id<MXKRecentCellDataStoring> cellData = [self cellDataAtIndex:i];
|
||||
if (cellData.hasUnread)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)searchWithPatterns:(NSArray*)patternsList
|
||||
{
|
||||
if (patternsList.count)
|
||||
{
|
||||
searchPatternsList = patternsList;
|
||||
|
||||
if (filteredCellDataArray)
|
||||
{
|
||||
[filteredCellDataArray removeAllObjects];
|
||||
}
|
||||
else
|
||||
{
|
||||
filteredCellDataArray = [NSMutableArray arrayWithCapacity:cellDataArray.count];
|
||||
}
|
||||
|
||||
for (id<MXKRecentCellDataStoring> cellData in cellDataArray)
|
||||
{
|
||||
for (NSString* pattern in patternsList)
|
||||
{
|
||||
if (cellData.roomDisplayname && [cellData.roomDisplayname rangeOfString:pattern options:NSCaseInsensitiveSearch].location != NSNotFound)
|
||||
{
|
||||
[filteredCellDataArray addObject:cellData];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
filteredCellDataArray = nil;
|
||||
searchPatternsList = nil;
|
||||
}
|
||||
|
||||
[self.delegate dataSource:self didCellChange:nil];
|
||||
}
|
||||
|
||||
- (id<MXKRecentCellDataStoring>)cellDataAtIndex:(NSInteger)index
|
||||
{
|
||||
if (filteredCellDataArray)
|
||||
{
|
||||
if (index < filteredCellDataArray.count)
|
||||
{
|
||||
return filteredCellDataArray[index];
|
||||
}
|
||||
}
|
||||
else if (index < cellDataArray.count)
|
||||
{
|
||||
return cellDataArray[index];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (CGFloat)cellHeightAtIndex:(NSInteger)index
|
||||
{
|
||||
if (self.delegate)
|
||||
{
|
||||
id<MXKRecentCellDataStoring> cellData = [self cellDataAtIndex:index];
|
||||
|
||||
Class<MXKCellRendering> class = [self.delegate cellViewClassForCellData:cellData];
|
||||
return [class heightForCellData:cellData withMaximumWidth:0];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma mark - Events processing
|
||||
|
||||
/**
|
||||
Filtering in this method won't have any effect anymore. This class is not maintained.
|
||||
*/
|
||||
- (void)loadData
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXRoomSummaryDidChangeNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXKRoomDataSourceSyncStatusChanged object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionNewRoomNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionDidLeaveRoomNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionDirectRoomsDidChangeNotification object:nil];
|
||||
|
||||
if (!self.mxSession.spaceService.isInitialised && !spaceServiceDidInitialiseObserver) {
|
||||
MXWeakify(self);
|
||||
spaceServiceDidInitialiseObserver = [[NSNotificationCenter defaultCenter] addObserverForName:MXSpaceService.didInitialise object:self.mxSession.spaceService queue:nil usingBlock:^(NSNotification * _Nonnull note) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self loadData];
|
||||
}];
|
||||
}
|
||||
|
||||
// Reset the table
|
||||
[internalCellDataArray removeAllObjects];
|
||||
|
||||
// Retrieve the MXKCellData class to manage the data
|
||||
Class class = [self cellDataClassForCellIdentifier:kMXKRecentCellIdentifier];
|
||||
NSAssert([class conformsToProtocol:@protocol(MXKRecentCellDataStoring)], @"MXKSessionRecentsDataSource only manages MXKCellData that conforms to MXKRecentCellDataStoring protocol");
|
||||
|
||||
NSDate *startDate = [NSDate date];
|
||||
|
||||
for (MXRoomSummary *roomSummary in self.mxSession.roomsSummaries)
|
||||
{
|
||||
// Filter out private rooms with conference users
|
||||
if (!roomSummary.isConferenceUserRoom // @TODO Abstract this condition with roomSummary.hiddenFromUser
|
||||
&& !roomSummary.hiddenFromUser)
|
||||
{
|
||||
id<MXKRecentCellDataStoring> cellData = [[class alloc] initWithRoomSummary:roomSummary dataSource:self];
|
||||
if (cellData)
|
||||
{
|
||||
[internalCellDataArray addObject:cellData];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (MXSpaceChildInfo *childInfo in _suggestedRooms)
|
||||
{
|
||||
id<MXRoomSummaryProtocol> summary = [[MXRoomSummary alloc] initWithSpaceChildInfo:childInfo];
|
||||
id<MXKRecentCellDataStoring> cellData = [[class alloc] initWithRoomSummary:summary
|
||||
dataSource:self];
|
||||
if (cellData)
|
||||
{
|
||||
[internalCellDataArray addObject:cellData];
|
||||
}
|
||||
}
|
||||
|
||||
MXLogDebug(@"[MXKSessionRecentsDataSource] Loaded %tu recents in %.3fms", self.mxSession.rooms.count, [[NSDate date] timeIntervalSinceDate:startDate] * 1000);
|
||||
|
||||
// Make sure all rooms have a last message
|
||||
[self.mxSession fixRoomsSummariesLastMessage];
|
||||
|
||||
// Report loaded array except if sync is in progress
|
||||
if (!roomDataSourceManager.isServerSyncInProgress)
|
||||
{
|
||||
[self sortCellDataAndNotifyChanges];
|
||||
}
|
||||
|
||||
// Listen to MXSession rooms count changes
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didMXSessionHaveNewRoom:) name:kMXSessionNewRoomNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didMXSessionDidLeaveRoom:) name:kMXSessionDidLeaveRoomNotification object:nil];
|
||||
|
||||
// Listen to the direct rooms list
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didDirectRoomsChange:) name:kMXSessionDirectRoomsDidChangeNotification object:nil];
|
||||
|
||||
// Listen to MXRoomSummary
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRoomSummaryChanged:) name:kMXRoomSummaryDidChangeNotification object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didMXSessionStateChange) name:kMXKRoomDataSourceSyncStatusChanged object:nil];
|
||||
}
|
||||
|
||||
- (void)didDirectRoomsChange:(NSNotification *)notif
|
||||
{
|
||||
// Inform the delegate about the update
|
||||
[self.delegate dataSource:self didCellChange:nil];
|
||||
}
|
||||
|
||||
- (void)didRoomSummaryChanged:(NSNotification *)notif
|
||||
{
|
||||
[roomSummaryChangeThrottler throttle:^{
|
||||
[self didRoomSummaryChanged2:notif];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)didRoomSummaryChanged2:(NSNotification *)notif
|
||||
{
|
||||
MXRoomSummary *roomSummary = notif.object;
|
||||
if (roomSummary.mxSession == self.mxSession && internalCellDataArray.count)
|
||||
{
|
||||
// Find the index of the related cell data
|
||||
NSInteger index = NSNotFound;
|
||||
for (index = 0; index < internalCellDataArray.count; index++)
|
||||
{
|
||||
id<MXKRecentCellDataStoring> theRoomData = [internalCellDataArray objectAtIndex:index];
|
||||
if (theRoomData.roomSummary == roomSummary)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < internalCellDataArray.count)
|
||||
{
|
||||
if (roomSummary.hiddenFromUser)
|
||||
{
|
||||
[internalCellDataArray removeObjectAtIndex:index];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a new instance to not modify the content of 'cellDataArray' (the copy is not a deep copy).
|
||||
Class class = [self cellDataClassForCellIdentifier:kMXKRecentCellIdentifier];
|
||||
id<MXKRecentCellDataStoring> cellData = [[class alloc] initWithRoomSummary:roomSummary dataSource:self];
|
||||
if (cellData)
|
||||
{
|
||||
[internalCellDataArray replaceObjectAtIndex:index withObject:cellData];
|
||||
}
|
||||
}
|
||||
|
||||
// Report change except if sync is in progress
|
||||
if (!roomDataSourceManager.isServerSyncInProgress)
|
||||
{
|
||||
[self sortCellDataAndNotifyChanges];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXLogDebug(@"[MXKSessionRecentsDataSource] didRoomLastMessageChanged: Cannot find the changed room summary for %@ (%@). It is probably not managed by this recents data source", roomSummary.roomId, roomSummary);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Inform the delegate that all the room summaries have been updated.
|
||||
[self.delegate dataSource:self didCellChange:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didMXSessionHaveNewRoom:(NSNotification *)notif
|
||||
{
|
||||
MXSession *mxSession = notif.object;
|
||||
if (mxSession == self.mxSession)
|
||||
{
|
||||
NSString *roomId = notif.userInfo[kMXSessionNotificationRoomIdKey];
|
||||
|
||||
// Add the room if there is not yet a cell for it
|
||||
id<MXKRecentCellDataStoring> roomData = [self cellDataWithRoomId:roomId];
|
||||
if (nil == roomData)
|
||||
{
|
||||
MXLogDebug(@"MXKSessionRecentsDataSource] Add newly joined room: %@", roomId);
|
||||
|
||||
// Retrieve the MXKCellData class to manage the data
|
||||
Class class = [self cellDataClassForCellIdentifier:kMXKRecentCellIdentifier];
|
||||
|
||||
MXRoomSummary *roomSummary = [mxSession roomSummaryWithRoomId:roomId];
|
||||
id<MXKRecentCellDataStoring> cellData = [[class alloc] initWithRoomSummary:roomSummary dataSource:self];
|
||||
if (cellData)
|
||||
{
|
||||
[internalCellDataArray addObject:cellData];
|
||||
|
||||
// Report change except if sync is in progress
|
||||
if (!roomDataSourceManager.isServerSyncInProgress)
|
||||
{
|
||||
[self sortCellDataAndNotifyChanges];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didMXSessionDidLeaveRoom:(NSNotification *)notif
|
||||
{
|
||||
MXSession *mxSession = notif.object;
|
||||
if (mxSession == self.mxSession)
|
||||
{
|
||||
NSString *roomId = notif.userInfo[kMXSessionNotificationRoomIdKey];
|
||||
id<MXKRecentCellDataStoring> roomData = [self cellDataWithRoomId:roomId];
|
||||
|
||||
if (roomData)
|
||||
{
|
||||
MXLogDebug(@"MXKSessionRecentsDataSource] Remove left room: %@", roomId);
|
||||
|
||||
[internalCellDataArray removeObject:roomData];
|
||||
|
||||
// Report change except if sync is in progress
|
||||
if (!roomDataSourceManager.isServerSyncInProgress)
|
||||
{
|
||||
[self sortCellDataAndNotifyChanges];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Order cells
|
||||
- (void)sortCellDataAndNotifyChanges
|
||||
{
|
||||
// Order them by origin_server_ts
|
||||
[internalCellDataArray sortUsingComparator:^NSComparisonResult(id<MXKRecentCellDataStoring> cellData1, id<MXKRecentCellDataStoring> cellData2)
|
||||
{
|
||||
return [cellData1.roomSummary.lastMessage compareOriginServerTs:cellData2.roomSummary.lastMessage];
|
||||
}];
|
||||
|
||||
// Snapshot the cell data array
|
||||
cellDataArray = [internalCellDataArray copy];
|
||||
|
||||
// Update search result if any
|
||||
if (searchPatternsList)
|
||||
{
|
||||
[self searchWithPatterns:searchPatternsList];
|
||||
}
|
||||
|
||||
// Update here data source state
|
||||
if (state != MXKDataSourceStateReady)
|
||||
{
|
||||
state = MXKDataSourceStateReady;
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(dataSource:didStateChange:)])
|
||||
{
|
||||
[self.delegate dataSource:self didStateChange:state];
|
||||
}
|
||||
}
|
||||
|
||||
// And inform the delegate about the update
|
||||
[self.delegate dataSource:self didCellChange:nil];
|
||||
}
|
||||
|
||||
// Find the cell data that stores information about the given room id
|
||||
- (id<MXKRecentCellDataStoring>)cellDataWithRoomId:(NSString*)roomId
|
||||
{
|
||||
id<MXKRecentCellDataStoring> theRoomData;
|
||||
|
||||
NSMutableArray *dataArray = internalCellDataArray;
|
||||
if (!roomDataSourceManager.isServerSyncInProgress)
|
||||
{
|
||||
dataArray = cellDataArray;
|
||||
}
|
||||
|
||||
for (id<MXKRecentCellDataStoring> roomData in dataArray)
|
||||
{
|
||||
if ([roomData.roomSummary.roomId isEqualToString:roomId])
|
||||
{
|
||||
theRoomData = roomData;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return theRoomData;
|
||||
}
|
||||
|
||||
#pragma mark - KVO
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath
|
||||
ofObject:(id)object
|
||||
change:(NSDictionary *)change
|
||||
context:(void *)context
|
||||
{
|
||||
if (object == [MXKAppSettings standardAppSettings] && [keyPath isEqualToString:@"showAllRoomsInHomeSpace"])
|
||||
{
|
||||
if (self.currentSpace == nil)
|
||||
{
|
||||
[self loadData];
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
date = [searchDataSource.eventFormatter dateStringFromEvent:searchResult.result withTime:YES];
|
||||
|
||||
// Code from [MXEventFormatter stringFromEvent] for the particular case of a text message
|
||||
message = [searchResult.result.content[@"body"] isKindOfClass:[NSString class]] ? searchResult.result.content[@"body"] : nil;
|
||||
message = [searchResult.result.content[kMXMessageBodyKey] isKindOfClass:[NSString class]] ? searchResult.result.content[kMXMessageBodyKey] : nil;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user