mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-20 16:42:44 +02:00
Merge MatrixKit develop with commit hash: b85b736313bec0592bd1cabc68035d97f5331137
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKCellData.h"
|
||||
#import "MXKSearchCellDataStoring.h"
|
||||
|
||||
/**
|
||||
`MXKSearchCellData` modelised the data for a `MXKSearchCell` cell.
|
||||
*/
|
||||
@interface MXKSearchCellData : MXKCellData <MXKSearchCellDataStoring>
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKSearchCellData.h"
|
||||
|
||||
#import "MXKSearchDataSource.h"
|
||||
|
||||
|
||||
@implementation MXKSearchCellData
|
||||
@synthesize roomId, senderDisplayName;
|
||||
@synthesize searchResult, title, message, date, shouldShowRoomDisplayName, roomDisplayName, attachment, isAttachmentWithThumbnail, attachmentIcon;
|
||||
|
||||
- (instancetype)initWithSearchResult:(MXSearchResult *)searchResult2 andSearchDataSource:(MXKSearchDataSource *)searchDataSource
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
searchResult = searchResult2;
|
||||
|
||||
if (searchDataSource.roomEventFilter.rooms.count == 1)
|
||||
{
|
||||
// We are displaying a search within a room
|
||||
// As title, display the user id
|
||||
title = searchResult.result.sender;
|
||||
|
||||
roomId = searchDataSource.roomEventFilter.rooms[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// We are displaying a search over all user's rooms
|
||||
// As title, display the room name of this search result
|
||||
MXRoom *room = [searchDataSource.mxSession roomWithRoomId:searchResult.result.roomId];
|
||||
if (room)
|
||||
{
|
||||
title = room.summary.displayname;
|
||||
}
|
||||
else
|
||||
{
|
||||
title = searchResult.result.roomId;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (void)cellDataWithSearchResult:(MXSearchResult *)searchResult andSearchDataSource:(MXKSearchDataSource *)searchDataSource onComplete:(void (^)(id<MXKSearchCellDataStoring>))onComplete
|
||||
{
|
||||
onComplete([[self alloc] initWithSearchResult:searchResult andSearchDataSource:searchDataSource]);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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/Foundation.h>
|
||||
#import <MatrixSDK/MatrixSDK.h>
|
||||
|
||||
#import "MXKAttachment.h"
|
||||
|
||||
@class MXKSearchDataSource;
|
||||
|
||||
/**
|
||||
`MXKSearchCellDataStoring` defines a protocol a class must conform in order to store
|
||||
a search result in a cell data managed by `MXKSearchDataSource`.
|
||||
*/
|
||||
@protocol MXKSearchCellDataStoring <NSObject>
|
||||
|
||||
/**
|
||||
The room id
|
||||
*/
|
||||
@property (nonatomic) NSString *roomId;
|
||||
|
||||
@property (nonatomic, readonly) NSString *title;
|
||||
@property (nonatomic, readonly) NSString *message;
|
||||
@property (nonatomic, readonly) NSString *date;
|
||||
|
||||
// Bulk result returned by MatrixSDK
|
||||
@property (nonatomic, readonly) MXSearchResult *searchResult;
|
||||
|
||||
/**
|
||||
Tell whether the room display name should be displayed in the cell. NO by default.
|
||||
*/
|
||||
@property (nonatomic) BOOL shouldShowRoomDisplayName;
|
||||
|
||||
/**
|
||||
The room display name.
|
||||
*/
|
||||
@property (nonatomic) NSString *roomDisplayName;
|
||||
|
||||
/**
|
||||
The sender display name.
|
||||
*/
|
||||
@property (nonatomic) NSString *senderDisplayName;
|
||||
|
||||
/**
|
||||
The bubble attachment (if any).
|
||||
*/
|
||||
@property (nonatomic) MXKAttachment *attachment;
|
||||
|
||||
/**
|
||||
YES when the bubble correspond to an attachment displayed with a thumbnail (see image, video).
|
||||
*/
|
||||
@property (nonatomic, readonly) BOOL isAttachmentWithThumbnail;
|
||||
|
||||
/**
|
||||
The default icon relative to the attachment (if any).
|
||||
*/
|
||||
@property (nonatomic, readonly) UIImage* attachmentIcon;
|
||||
|
||||
|
||||
#pragma mark - Public methods
|
||||
/**
|
||||
Create a new `MXKCellData` object for a new search result cell.
|
||||
|
||||
@param searchResult Bulk result returned by MatrixSDK.
|
||||
@param searchDataSource the `MXKSearchDataSource` object that will use this instance.
|
||||
@param onComplete a block providing the newly created instance.
|
||||
*/
|
||||
+ (void)cellDataWithSearchResult:(MXSearchResult*)searchResult andSearchDataSource:(MXKSearchDataSource*)searchDataSource onComplete:(void (^)(id<MXKSearchCellDataStoring> cellData))onComplete;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKDataSource.h"
|
||||
#import "MXKSearchCellDataStoring.h"
|
||||
|
||||
#import "MXKEventFormatter.h"
|
||||
|
||||
/**
|
||||
String identifying the object used to store and prepare the cell data of a result during a message search.
|
||||
*/
|
||||
extern NSString *const kMXKSearchCellDataIdentifier;
|
||||
|
||||
/**
|
||||
The data source for `MXKSearchViewController` in case of message search.
|
||||
|
||||
Use the `initWithMatrixSession:` constructor to search in all user's rooms.
|
||||
Use the `initWithRoomId:andMatrixSession: constructor to search in a specific room.
|
||||
*/
|
||||
@interface MXKSearchDataSource : MXKDataSource <UITableViewDataSource>
|
||||
{
|
||||
@protected
|
||||
/**
|
||||
List of results retrieved from the server.
|
||||
The` MXKSearchDataSource` class stores MXKSearchCellDataStoring objects in it.
|
||||
*/
|
||||
NSMutableArray<MXKCellData*> *cellDataArray;
|
||||
}
|
||||
|
||||
/**
|
||||
The current search.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSString *searchText;
|
||||
|
||||
/**
|
||||
The room events filter which is applied during the messages search.
|
||||
*/
|
||||
@property (nonatomic) MXRoomEventFilter *roomEventFilter;
|
||||
|
||||
/**
|
||||
Total number of results available on the server.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger serverCount;
|
||||
|
||||
/**
|
||||
The events to display texts formatter.
|
||||
`MXKCellData` instances can use it to format text.
|
||||
*/
|
||||
@property (nonatomic) MXKEventFormatter *eventFormatter;
|
||||
|
||||
/**
|
||||
Flag indicating if there are still results (in the past) to get with paginateBack.
|
||||
*/
|
||||
@property (nonatomic, readonly) BOOL canPaginate;
|
||||
|
||||
/**
|
||||
Tell whether the room display name should be displayed in each result cell. NO by default.
|
||||
*/
|
||||
@property (nonatomic) BOOL shouldShowRoomDisplayName;
|
||||
|
||||
|
||||
/**
|
||||
Launch a message search homeserver side.
|
||||
|
||||
@discussion The result depends on the 'roomEventFilter' propertie.
|
||||
|
||||
@param textPattern the text to search in messages data.
|
||||
@param force tell whether the search must be launched even if the text pattern is unchanged.
|
||||
*/
|
||||
- (void)searchMessages:(NSString*)textPattern force:(BOOL)force;
|
||||
|
||||
/**
|
||||
Load more results from the past.
|
||||
*/
|
||||
- (void)paginateBack;
|
||||
|
||||
/**
|
||||
Get the data for the cell at the given index.
|
||||
|
||||
@param index the index of the cell in the array
|
||||
@return the cell data
|
||||
*/
|
||||
- (MXKCellData*)cellDataAtIndex:(NSInteger)index;
|
||||
|
||||
/**
|
||||
Convert the results of a homeserver search requests into cells.
|
||||
|
||||
This methods is in charge of filling `cellDataArray`.
|
||||
|
||||
@param roomEventResults the homeserver response as provided by MatrixSDK.
|
||||
@param onComplete the block called once complete.
|
||||
*/
|
||||
- (void)convertHomeserverResultsIntoCells:(MXSearchRoomEventResults*)roomEventResults onComplete:(dispatch_block_t)onComplete;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
Copyright 2015 OpenMarket 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 "MXKSearchDataSource.h"
|
||||
|
||||
#import "MXKSearchCellData.h"
|
||||
|
||||
#pragma mark - Constant definitions
|
||||
NSString *const kMXKSearchCellDataIdentifier = @"kMXKSearchCellDataIdentifier";
|
||||
|
||||
|
||||
@interface MXKSearchDataSource ()
|
||||
{
|
||||
/**
|
||||
The current search request.
|
||||
*/
|
||||
MXHTTPOperation *searchRequest;
|
||||
|
||||
/**
|
||||
Token that can be used to get the next batch of results in the group, if exists.
|
||||
*/
|
||||
NSString *nextBatch;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MXKSearchDataSource
|
||||
|
||||
- (instancetype)initWithMatrixSession:(MXSession *)mxSession
|
||||
{
|
||||
self = [super initWithMatrixSession:mxSession];
|
||||
if (self)
|
||||
{
|
||||
// Set default data and view classes
|
||||
// Cell data
|
||||
[self registerCellDataClass:MXKSearchCellData.class forCellIdentifier:kMXKSearchCellDataIdentifier];
|
||||
|
||||
// Set default MXEvent -> NSString formatter
|
||||
_eventFormatter = [[MXKEventFormatter alloc] initWithMatrixSession:mxSession];
|
||||
|
||||
_roomEventFilter = [[MXRoomEventFilter alloc] init];
|
||||
|
||||
cellDataArray = [NSMutableArray array];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)destroy
|
||||
{
|
||||
cellDataArray = nil;
|
||||
_eventFormatter = nil;
|
||||
|
||||
_roomEventFilter = nil;
|
||||
|
||||
[super destroy];
|
||||
}
|
||||
|
||||
- (void)searchMessages:(NSString*)textPattern force:(BOOL)force
|
||||
{
|
||||
if (force || ![_searchText isEqualToString:textPattern])
|
||||
{
|
||||
// Reset data before making the new search
|
||||
if (searchRequest)
|
||||
{
|
||||
[searchRequest cancel];
|
||||
searchRequest = nil;
|
||||
}
|
||||
|
||||
_searchText = textPattern;
|
||||
_serverCount = 0;
|
||||
_canPaginate = NO;
|
||||
nextBatch = nil;
|
||||
|
||||
self.state = MXKDataSourceStatePreparing;
|
||||
[cellDataArray removeAllObjects];
|
||||
|
||||
if (textPattern.length)
|
||||
{
|
||||
MXLogDebug(@"[MXKSearchDataSource] searchMessages: %@", textPattern);
|
||||
[self doSearch];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Refresh table display.
|
||||
self.state = MXKDataSourceStateReady;
|
||||
[self.delegate dataSource:self didCellChange:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)paginateBack
|
||||
{
|
||||
MXLogDebug(@"[MXKSearchDataSource] paginateBack");
|
||||
|
||||
self.state = MXKDataSourceStatePreparing;
|
||||
[self doSearch];
|
||||
}
|
||||
|
||||
- (MXKCellData*)cellDataAtIndex:(NSInteger)index
|
||||
{
|
||||
MXKCellData *cellData;
|
||||
if (index < cellDataArray.count)
|
||||
{
|
||||
cellData = cellDataArray[index];
|
||||
}
|
||||
|
||||
return cellData;
|
||||
}
|
||||
|
||||
- (void)convertHomeserverResultsIntoCells:(MXSearchRoomEventResults*)roomEventResults onComplete:(dispatch_block_t)onComplete
|
||||
{
|
||||
// Retrieve the MXKCellData class to manage the data
|
||||
// Note: MXKSearchDataSource only manages MXKCellData that conforms to MXKSearchCellDataStoring protocol
|
||||
// see `[registerCellDataClass:forCellIdentifier:]`
|
||||
Class class = [self cellDataClassForCellIdentifier:kMXKSearchCellDataIdentifier];
|
||||
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
|
||||
for (MXSearchResult *result in roomEventResults.results)
|
||||
{
|
||||
dispatch_group_enter(group);
|
||||
[class cellDataWithSearchResult:result andSearchDataSource:self onComplete:^(__autoreleasing id<MXKSearchCellDataStoring> cellData) {
|
||||
dispatch_group_leave(group);
|
||||
|
||||
if (cellData)
|
||||
{
|
||||
((id<MXKSearchCellDataStoring>)cellData).shouldShowRoomDisplayName = self.shouldShowRoomDisplayName;
|
||||
|
||||
// Use profile information as data to display
|
||||
MXSearchUserProfile *userProfile = result.context.profileInfo[result.result.sender];
|
||||
cellData.senderDisplayName = userProfile.displayName;
|
||||
|
||||
[self->cellDataArray insertObject:cellData atIndex:0];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
|
||||
onComplete();
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Private methods
|
||||
|
||||
// Update the MXKDataSource and notify the delegate
|
||||
- (void)setState:(MXKDataSourceState)newState
|
||||
{
|
||||
state = newState;
|
||||
|
||||
if (self.delegate)
|
||||
{
|
||||
if ([self.delegate respondsToSelector:@selector(dataSource:didStateChange:)])
|
||||
{
|
||||
[self.delegate dataSource:self didStateChange:state];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)doSearch
|
||||
{
|
||||
// Handle one request at a time
|
||||
if (searchRequest)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSDate *startDate = [NSDate date];
|
||||
|
||||
MXWeakify(self);
|
||||
searchRequest = [self.mxSession.matrixRestClient searchMessagesWithText:_searchText roomEventFilter:_roomEventFilter beforeLimit:0 afterLimit:0 nextBatch:nextBatch success:^(MXSearchRoomEventResults *roomEventResults) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
MXLogDebug(@"[MXKSearchDataSource] searchMessages: %@ (%d). Done in %.3fms - Got %tu / %tu messages", self.searchText, self.roomEventFilter.containsURL, [[NSDate date] timeIntervalSinceDate:startDate] * 1000, roomEventResults.results.count, roomEventResults.count);
|
||||
|
||||
self->searchRequest = nil;
|
||||
self->_serverCount = roomEventResults.count;
|
||||
self->nextBatch = roomEventResults.nextBatch;
|
||||
self->_canPaginate = (nil != self->nextBatch);
|
||||
|
||||
// Process HS response to cells data
|
||||
MXWeakify(self);
|
||||
[self convertHomeserverResultsIntoCells:roomEventResults onComplete:^{
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
self.state = MXKDataSourceStateReady;
|
||||
|
||||
// Provide changes information to the delegate
|
||||
NSIndexSet *insertedIndexes;
|
||||
if (roomEventResults.results.count)
|
||||
{
|
||||
insertedIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, roomEventResults.results.count)];
|
||||
}
|
||||
|
||||
[self.delegate dataSource:self didCellChange:insertedIndexes];
|
||||
}];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
self->searchRequest = nil;
|
||||
self.state = MXKDataSourceStateFailed;
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Override MXKDataSource
|
||||
|
||||
- (void)registerCellDataClass:(Class)cellDataClass forCellIdentifier:(NSString *)identifier
|
||||
{
|
||||
if ([identifier isEqualToString:kMXKSearchCellDataIdentifier])
|
||||
{
|
||||
// Sanity check
|
||||
NSAssert([cellDataClass conformsToProtocol:@protocol(MXKSearchCellDataStoring)], @"MXKSearchDataSource only manages MXKCellData that conforms to MXKSearchCellDataStoring protocol");
|
||||
}
|
||||
|
||||
[super registerCellDataClass:cellDataClass forCellIdentifier:identifier];
|
||||
}
|
||||
|
||||
- (void)cancelAllRequests
|
||||
{
|
||||
if (searchRequest)
|
||||
{
|
||||
[searchRequest cancel];
|
||||
searchRequest = nil;
|
||||
}
|
||||
|
||||
[super cancelAllRequests];
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDataSource
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
return cellDataArray.count;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
MXKCellData* cellData = [self cellDataAtIndex:indexPath.row];
|
||||
|
||||
NSString *cellIdentifier = [self.delegate cellReuseIdentifierForCellData:cellData];
|
||||
if (cellIdentifier)
|
||||
{
|
||||
UITableViewCell<MXKCellRendering> *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
|
||||
|
||||
// Make the bubble display the data
|
||||
[cell render:cellData];
|
||||
|
||||
// Disable any interactions defined in the cell
|
||||
// because we want [tableView didSelectRowAtIndexPath:] to be called
|
||||
cell.contentView.userInteractionEnabled = NO;
|
||||
|
||||
// Force background color change on selection
|
||||
cell.selectionStyle = UITableViewCellSelectionStyleDefault;
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
// Return a fake cell to prevent app from crashing.
|
||||
return [[UITableViewCell alloc] init];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user