// _____ _
// |_ _| |_ _ _ ___ ___ _ __ __ _
// | | | ' \| '_/ -_) -_) ' \/ _` |_
// |_| |_||_|_| \___\___|_|_|_\__,_(_)
//
// Threema iOS Client
// Copyright (c) 2015-2020 Threema GmbH
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#import "GroupTableDataSource.h"
#import "EntityManager.h"
#import "ErrorHandler.h"
#import "PickerGroupCell.h"
#ifdef DEBUG
static const DDLogLevel ddLogLevel = DDLogLevelInfo;
#else
static const DDLogLevel ddLogLevel = DDLogLevelWarning;
#endif
@interface GroupTableDataSource ()
@property NSArray *filteredGroups;
@property NSFetchedResultsController *fetchedResultsController;
@property (nonatomic) NSMutableSet *selectedGroups;
@property EntityManager *entityManager;
@property id fetchedResultsControllerDelegate;
@property BOOL ignoreUpdates;
@end
@implementation GroupTableDataSource
+ (instancetype)groupTableDataSource {
return [[GroupTableDataSource alloc] initWithFetchedResultsControllerDelegate:nil];
}
+ (instancetype)groupTableDataSourceWithFetchedResultsControllerDelegate:(id)delegate {
return [[GroupTableDataSource alloc] initWithFetchedResultsControllerDelegate:delegate];
}
- (void)dealloc {
_fetchedResultsController.delegate = nil;
_fetchedResultsControllerDelegate = nil;
}
- (instancetype)initWithFetchedResultsControllerDelegate:(id)delegate
{
self = [super init];
if (self) {
_entityManager = [[EntityManager alloc] init];
_selectedGroups = [NSMutableSet set];
if (delegate) {
_fetchedResultsControllerDelegate = delegate;
delegate = self;
}
[self setupFetchedResultsControllerWithDelegate:delegate];
}
return self;
}
- (void)setupFetchedResultsControllerWithDelegate:(id)delegate {
NSFetchedResultsController *fetchedResultsController = [_entityManager.entityFetcher fetchedResultsControllerForGroups];
fetchedResultsController.delegate = delegate;
_fetchedResultsController = fetchedResultsController;
NSError *error = nil;
if (![_fetchedResultsController performFetch:&error]) {
DDLogError(@"Unresolved error %@, %@", error, [error userInfo]);
[ErrorHandler abortWithError: error];
}
}
-(void)filterByWords:(NSArray *)words {
if (words) {
_filteredGroups = [_entityManager.entityFetcher groupConversationsFilteredByWords:words];
} else {
_filteredGroups= nil;
}
}
- (NSSet *)selectedConversations {
NSMutableSet *conversations = [NSMutableSet setWithCapacity:[_selectedGroups count]];
for (GroupProxy *group in _selectedGroups) {
[conversations addObject:group.conversation];
}
return conversations;
}
- (NSArray *)groupsForConversations:(NSArray *)conversations {
NSMutableArray *groups = [NSMutableArray arrayWithCapacity: [conversations count]];
for (Conversation *conversation in conversations) {
GroupProxy *group = [GroupProxy groupProxyForConversation:conversation];
if ([group canSendInGroup]) {
[groups addObject:group];
}
}
return groups;
}
- (void)setIgnoreFRCUpdates:(BOOL)ignoreFRCUpdates {
_ignoreUpdates = ignoreFRCUpdates;
}
- (BOOL)ignoreFRCUpdates {
return _ignoreUpdates;
}
- (BOOL)isFiltered {
return (_filteredGroups != nil);
}
#pragma mark - Table view
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (_filteredGroups) {
return [_filteredGroups count];
}
id sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
GroupProxy *group = [self groupAtIndexPath:indexPath];
PickerGroupCell *cell = [tableView dequeueReusableCellWithIdentifier:@"PickerGroupCell"];
cell.group = group;
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return nil;
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return nil;
}
- (void)selectedCellAtIndexPath:(NSIndexPath *)indexPath selected:(BOOL)selected {
GroupProxy *group = [self groupAtIndexPath:indexPath];
if (selected) {
if (![_selectedGroups containsObject:group]) {
[_selectedGroups addObject:group];
}
} else {
[_selectedGroups enumerateObjectsUsingBlock:^(GroupProxy *tmpGroup, BOOL * _Nonnull stop) {
if ([group.groupId isEqualToData:tmpGroup.groupId]) {
[_selectedGroups removeObject:tmpGroup];
*stop = YES;
}
}];
}
}
- (GroupProxy *)groupAtIndexPath:(NSIndexPath *)indexPath {
Conversation *conversation;
if (_filteredGroups) {
conversation = [_filteredGroups objectAtIndex:indexPath.row];
} else {
conversation = [_fetchedResultsController objectAtIndexPath:indexPath];
}
return [GroupProxy groupProxyForConversation:conversation];
}
- (NSIndexPath *)indexPathForObject:(id)object {
return [_fetchedResultsController indexPathForObject:((GroupProxy *)object).conversation];
}
#pragma mark - Fetched results controller
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
if (_ignoreUpdates || _filteredGroups != nil) {
return;
}
[_fetchedResultsControllerDelegate controllerWillChangeContent:controller];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
if (_ignoreUpdates || _filteredGroups != nil) {
return;
}
[_fetchedResultsControllerDelegate controller:controller didChangeSection:sectionInfo atIndex:sectionIndex forChangeType:type];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
if (_ignoreUpdates || _filteredGroups != nil) {
return;
}
if ([anObject isKindOfClass:[Conversation class]]) {
anObject = [GroupProxy groupProxyForConversation:anObject];
}
[_fetchedResultsControllerDelegate controller:controller didChangeObject:anObject atIndexPath:indexPath forChangeType:type newIndexPath:newIndexPath];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
if (_ignoreUpdates || _filteredGroups != nil) {
return;
}
[_fetchedResultsControllerDelegate controllerDidChangeContent:controller];
}
@end