123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728 |
- // _____ _
- // |_ _| |_ _ _ ___ ___ _ __ __ _
- // | | | ' \| '_/ -_) -_) ' \/ _` |_
- // |_| |_||_|_| \___\___|_|_|_\__,_(_)
- //
- // Threema iOS Client
- // Copyright (c) 2014-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 <https://www.gnu.org/licenses/>.
- #import "EntityFetcher.h"
- #import "DatabaseManager.h"
- #import "AbstractGroupMessage.h"
- #import "MyIdentityStore.h"
- #import "Contact.h"
- #import "UserSettings.h"
- #import "BaseMessage.h"
- #import "BundleUtil.h"
- #import "TextMessage.h"
- #import "LicenseStore.h"
- #import "NonceHasher.h"
- #ifdef DEBUG
- static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
- #else
- static const DDLogLevel ddLogLevel = DDLogLevelWarning;
- #endif
- @interface EntityFetcher ()
- @property NSManagedObjectContext *managedObjectContext;
- @end
- @implementation EntityFetcher
- /*
- - (instancetype)init
- {
- self = [super init];
- if (self) {
- _managedObjectContext = [[DatabaseManager dbManager] getManagedObjectContext:![NSThread isMainThread]];
- }
- return self;
- }
- */
- - (instancetype)initWith:(NSManagedObjectContext *) managedObjectContext {
- self = [super init];
- if (self) {
- _managedObjectContext = managedObjectContext;
- }
- return self;
- }
- - (id)getManagedObjectById:(NSManagedObjectID *)objectID {
- return [_managedObjectContext objectWithID: objectID];
- }
- - (BaseMessage *)ownMessageWithId:(NSData *)messageId {
- return [self singleEntityNamed:@"Message" withPredicate: @"id == %@ AND isOwn == YES", messageId];
- }
- - (BaseMessage *)messageWithId:(NSData *)messageId {
- return [self singleEntityNamed:@"Message" withPredicate: @"id == %@", messageId];
- }
- - (BaseMessage *)messageWithId:(NSData *)messageId conversation:(Conversation *)conversation {
- return [self singleEntityNamed:@"Message" withPredicate: @"id == %@ AND conversation == %@", messageId, conversation];
- }
- - (NSArray *)quoteMessagesContaining:(NSString *)searchText message:(BaseMessage *)message inConversation:(Conversation *)conversation {
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO]];
- NSArray *textMessages = [self entitiesNamed:@"TextMessage" fetchLimit:0 sortedBy:sortDescriptors withPredicate: @"text contains[cd] %@ AND conversation == %@ && date < %@", searchText, conversation, message.date];
- NSArray *imageMessages = [self entitiesNamed:@"ImageMessage" fetchLimit:0 sortedBy:sortDescriptors withPredicate: @"conversation == %@ && date < %@", conversation, message.date];
- NSArray *fileMessages = [self entitiesNamed:@"FileMessage" fetchLimit:0 sortedBy:sortDescriptors withPredicate: @"conversation == %@ && date < %@", conversation, message.date];
- NSArray *locationMessages = [self entitiesNamed:@"LocationMessage" fetchLimit:0 sortedBy:sortDescriptors withPredicate: @"conversation == %@ && date < %@", conversation, message.date];
-
- if (imageMessages.count > 0 || fileMessages.count > 0 || locationMessages.count > 0) {
- NSMutableArray *allMessages = [NSMutableArray arrayWithArray:textMessages];
- [allMessages addObjectsFromArray:imageMessages];
- [allMessages addObjectsFromArray:fileMessages];
- [allMessages addObjectsFromArray:locationMessages];
-
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO]];
- [allMessages sortUsingDescriptors:(NSArray *)sortDescriptors];
- return allMessages;
- } else {
- return textMessages;
- }
- }
- - (NSArray *)messagesContaining:(NSString *)searchText inConversation:(Conversation *)conversation {
- NSArray *textMessages = [self textMessagesContaining:searchText inConversation:conversation fetchLimit:0];
- NSArray *ballotMessages = [self ballotMessagesContaining:searchText inConversation:conversation fetchLimit:0];
- NSArray *fileMessages = [self fileMessagesContaining:searchText inConversation:conversation fetchLimit:0];
-
- if ([ballotMessages count] > 0 || [fileMessages count] > 0) {
- NSMutableArray *allMessages = [NSMutableArray arrayWithArray:textMessages];
- [allMessages addObjectsFromArray:ballotMessages];
- [allMessages addObjectsFromArray:fileMessages];
-
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO]];
- [allMessages sortUsingDescriptors:(NSArray *)sortDescriptors];
- return allMessages;
- } else {
- return textMessages;
- }
- }
- - (NSArray *)textMessagesContaining:(NSString *)searchText inConversation:(Conversation *)conversation fetchLimit:(NSInteger)fetchLimit {
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO]];
- return [self entitiesNamed:@"TextMessage" fetchLimit:fetchLimit sortedBy:sortDescriptors withPredicate: @"text contains[cd] %@ AND conversation == %@", searchText, conversation];
- }
- - (NSArray *)ballotMessagesContaining:(NSString *)searchText inConversation:(Conversation *)conversation fetchLimit:(NSInteger)fetchLimit {
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO]];
- return [self entitiesNamed:@"BallotMessage" fetchLimit:fetchLimit sortedBy:sortDescriptors withPredicate: @"ballot.title contains[cd] %@ AND conversation == %@", searchText, conversation];
- }
- - (NSArray *)fileMessagesContaining:(NSString *)searchText inConversation:(Conversation *)conversation fetchLimit:(NSInteger)fetchLimit {
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO]];
- return [self entitiesNamed:@"FileMessage" fetchLimit:fetchLimit sortedBy:sortDescriptors withPredicate: @"fileName contains[cd] %@ AND conversation == %@", searchText, conversation];
- }
- - (Conversation *)conversationForGroupId:(NSData *)groupId {
- return [self singleEntityNamed:@"Conversation" withPredicate: @"groupId == %@", groupId];
- }
- - (Conversation *)conversationForContact:(Contact *)contact {
- return [self singleEntityNamed:@"Conversation" withPredicate: @"contact == %@ AND groupId == nil", contact];
- }
- - (Conversation *)conversationForIdentity:(NSString *)identity {
- return [self singleEntityNamed:@"Conversation" withPredicate: @"contact.identity == %@ AND groupId == nil", identity];
- }
- - (NSArray *)conversationsForMember:(Contact *)contact {
- return [self allEntitiesNamed:@"Conversation" sortedBy:nil withPredicate: @"%@ IN members", contact];
- }
- - (Conversation *)conversationForGroupMessage:(AbstractGroupMessage *)message {
- /* is this a group that we started? */
- if ([message.groupCreator isEqualToString:[MyIdentityStore sharedMyIdentityStore].identity]) {
- return [self singleEntityNamed:@"Conversation" withPredicate: @"contact == nil AND groupId == %@", message.groupId];
- } else {
- return [self singleEntityNamed:@"Conversation" withPredicate: @"contact.identity == %@ AND groupId == %@", message.groupCreator, message.groupId];
- }
- }
- - (Contact *)contactForId:(NSString *)identity {
- return [self singleEntityNamed:@"Contact" withPredicate: @"identity == %@", identity];
- }
- - (Contact *)contactForId:(NSString *)identity error:(NSError **)error {
- NSError *err;
- Contact *contact = [self singleEntityNamed:@"Contact" error:&err withPredicate:@"identity == %@", identity];
- if (err) {
- *error = err;
- return nil;
- } else {
- return contact;
- }
- }
- - (NSArray *)allContacts {
- return [self allEntitiesNamed:@"Contact" sortedBy:nil withPredicate:nil];
- }
- - (NSArray *)allGatewayContacts {
- return [self allEntitiesNamed:@"Contact" sortedBy:nil withPredicate: @"identity beginswith '*'"];
- }
- - (NSArray *)contactsWithVerificationLevel:(NSInteger)verificationLevel {
- return [self allEntitiesNamed:@"Contact" sortedBy:nil withPredicate: @"verificationLevel == %@", [NSNumber numberWithInteger:verificationLevel]];
- }
- - (NSArray *)contactsWithFeatureMaskNil {
- return [self allEntitiesNamed:@"Contact" sortedBy:nil withPredicate: @"featureLevel == nil"];
- }
-
- - (NSArray *)contactsFilteredByWords:(NSArray *)searchWords {
- NSMutableArray *predicates = [NSMutableArray array];
-
- if ([UserSettings sharedUserSettings].hideStaleContacts) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"state == %d", kStateActive];
- [predicates addObject:predicate];
- }
- for (NSString *searchWord in searchWords) {
- if (searchWord.length > 0) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstName contains[cd] %@ or lastName contains[cd] %@ or identity contains[c] %@ or publicNickname contains[cd] %@", searchWord, searchWord, searchWord, searchWord];
- [predicates addObject:predicate];
- }
- }
- NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Contact"];
- [fetchRequest setFetchBatchSize:100];
- [fetchRequest setPredicate:[NSCompoundPredicate andPredicateWithSubpredicates:predicates]];
- NSArray *sortDescriptors = [self nameSortDescriptors];
- [fetchRequest setSortDescriptors:sortDescriptors];
- return [self executeFetchRequest:fetchRequest];
- }
- - (NSArray *)contactsFilteredByWords:(NSArray *)searchWords forContactTypes:(ContactTypes)types list:(ContactList)contactList members:(NSMutableSet *)members {
- NSMutableArray *predicates = [NSMutableArray array];
-
- if (types == ContactsNoGateway) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not identity beginswith '*'"];
- [predicates addObject:predicate];
- } else if (types == ContactsNoEchoEcho) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not identity beginswith 'ECHOECHO'"];
- [predicates addObject:predicate];
- }
- else if (types == ContactsGatewayOnly) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"identity beginswith '*'"];
- [predicates addObject:predicate];
- } else if (types == ContactsNoGatewayNoEchoecho) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not identity beginswith '*'"];
- [predicates addObject:predicate];
- predicate = [NSPredicate predicateWithFormat:@"not identity BEGINSWITH 'ECHOECHO'"];
- [predicates addObject:predicate];
- }
-
- if ([UserSettings sharedUserSettings].hideStaleContacts) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"state == %d", kStateActive];
- [predicates addObject:predicate];
- }
-
- if (contactList == ContactListWork) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"workContact == %@", @1];
- [predicates addObject:predicate];
- } else {
- if (contactList == ContactListContacts) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"workContact == %@", @0];
- [predicates addObject:predicate];
- }
- }
-
- for (NSString *searchWord in searchWords) {
- if (searchWord.length > 0) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstName contains[cd] %@ or lastName contains[cd] %@ or identity contains[c] %@ or publicNickname contains[cd] %@", searchWord, searchWord, searchWord, searchWord];
- [predicates addObject:predicate];
- }
- }
-
- NSMutableArray *allPredicates = [NSMutableArray array];
- [allPredicates addObject:[NSCompoundPredicate andPredicateWithSubpredicates:predicates]];
-
- if ([UserSettings sharedUserSettings].hideStaleContacts) {
- if (members.count > 0) {
- for (Contact *contact in members) {
- NSMutableArray *andPredicates = [NSMutableArray array];
- NSPredicate *memberPredicate = [NSPredicate predicateWithFormat:@"identity == %@", contact.identity];
- [andPredicates addObject:memberPredicate];
- for (NSString *searchWord in searchWords) {
- if (searchWord.length > 0) {
- NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:@"firstName contains[cd] %@ or lastName contains[cd] %@ or identity contains[c] %@ or publicNickname contains[cd] %@", searchWord, searchWord, searchWord, searchWord];
- [andPredicates addObject:searchPredicate];
- }
- }
- [allPredicates addObject:[NSCompoundPredicate andPredicateWithSubpredicates:andPredicates]];
- }
- }
- }
-
- NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Contact"];
- [fetchRequest setFetchBatchSize:100];
- [fetchRequest setPredicate:[NSCompoundPredicate orPredicateWithSubpredicates:allPredicates]];
-
- NSArray *sortDescriptors = [self nameSortDescriptors];
- [fetchRequest setSortDescriptors:sortDescriptors];
-
- return [self executeFetchRequest:fetchRequest];
- }
- - (NSArray *)allGroupConversations {
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"groupName" ascending:YES]];
-
- return [self allEntitiesNamed:@"Conversation" sortedBy:sortDescriptors withPredicate:@"groupId != nil"];
- }
- - (NSArray *)groupConversationsForContact:(Contact *)contact {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%@ IN members", contact, contact];
- NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Conversation"];
- fetchRequest.predicate = predicate;
-
- return [self executeFetchRequest:fetchRequest];
- }
- - (NSArray *)groupConversationsFilteredByWords:(NSArray *)searchWords {
- NSMutableArray *predicates = [NSMutableArray array];
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"groupId != nil"];
- [predicates addObject:predicate];
-
- for (NSString *searchWord in searchWords) {
- if (searchWord.length > 0) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"groupName contains[cd] %@", searchWord];
- [predicates addObject:predicate];
- }
- }
-
- NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Conversation"];
- [fetchRequest setFetchBatchSize:100];
- [fetchRequest setPredicate:[NSCompoundPredicate andPredicateWithSubpredicates:predicates]];
-
- return [self executeFetchRequest:fetchRequest];
- }
- - (NSArray *)allConversations {
- return [self allEntitiesNamed:@"Conversation" sortedBy:nil withPredicate:nil];
- }
- - (NSArray *)allConversationsSorted {
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"marked" ascending:NO], [NSSortDescriptor sortDescriptorWithKey:@"lastMessage.date" ascending:NO]];
- return [self allEntitiesNamed:@"Conversation" sortedBy:sortDescriptors withPredicate:nil];
- }
- - (NSArray *)conversationsWithNegativeUnreadMessageCount {
- return [self allEntitiesNamed:@"Conversation" sortedBy:nil withPredicate:@"unreadMessageCount == %@", [NSNumber numberWithInt:-1]];
- }
- - (NSString *)displayNameForContactId:(NSString *)identity {
- /* Is this our own identity? */
- if ([identity isEqual:[MyIdentityStore sharedMyIdentityStore].identity])
- return [BundleUtil localizedStringForKey:@"me"];
-
- Contact *contact = [self contactForId:identity];
- if (contact == nil) {
- return identity;
- }
-
- return contact.displayName;
- }
- - (Ballot *)ballotForBallotId:(NSData *)ballotId {
- return [self singleEntityNamed:@"Ballot" withPredicate: @"id == %@", ballotId];
- }
- - (NSInteger)countBallotsForConversation:(Conversation *)conversation {
- return [self countEntityNamed:@"Ballot" withPredicate:@"conversation == %@", conversation];
- }
- - (NSInteger)countOpenBallotsForConversation:(Conversation *)conversation {
- return [self countEntityNamed:@"Ballot" withPredicate:@"conversation == %@ && state == %d", conversation, kBallotStateOpen];
- }
- - (NSInteger)countMediaMessagesForConversation:(Conversation *)conversation {
- NSInteger numImages = [self countEntityNamed:@"ImageMessage" withPredicate:@"conversation == %@", conversation];
- NSInteger numVideos = [self countEntityNamed:@"VideoMessage" withPredicate:@"conversation == %@", conversation];
- NSInteger numFiles = [self countEntityNamed:@"FileMessage" withPredicate:@"conversation == %@", conversation];
- return numImages + numVideos + numFiles;
- }
- - (NSArray *)imageMessagesForConversation:(Conversation *)conversation {
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES]];
- return [self allEntitiesNamed:@"ImageMessage" sortedBy:sortDescriptors withPredicate:@"conversation == %@", conversation];
- }
- - (NSArray *)videoMessagesForConversation:(Conversation *)conversation {
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES]];
- return [self allEntitiesNamed:@"VideoMessage" sortedBy:sortDescriptors withPredicate:@"conversation == %@", conversation];
- }
- - (NSArray *)fileMessagesForConversation:(Conversation *)conversation {
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES]];
- return [self allEntitiesNamed:@"FileMessage" sortedBy:sortDescriptors withPredicate:@"conversation == %@", conversation];
- }
- - (NSArray *)fileMessagesWOStickersForConversation:(Conversation *)conversation {
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"date" ascending:YES]];
- return [self allEntitiesNamed:@"FileMessage" sortedBy:sortDescriptors withPredicate:@"(conversation == %@) AND (type != 2)", conversation];
- }
- - (BallotChoice *)ballotChoiceForBallotId:(NSData *)ballotId choiceId:(NSNumber *)choiceId {
- return [self singleEntityNamed:@"BallotChoice" withPredicate: @"id == %@ AND ballot.id == %@", choiceId, ballotId];
- }
- - (BOOL)isMessageAlreadyInDb:(AbstractMessage *)message {
- id result;
-
- if ([message isKindOfClass:[AbstractGroupMessage class]]) {
- result = [self singleEntityNamed:@"Message" withPredicate:@"id == %@ AND sender.identity == %@",
- message.messageId, message.fromIdentity];
- } else {
- result = [self singleEntityNamed:@"Message" withPredicate:@"id == %@ AND conversation.contact.identity == %@",
- message.messageId, message.fromIdentity];
- }
-
-
- return result != nil;
- }
- - (BOOL)isNonceAlreadyInDb:(AbstractMessage *)message {
- id result;
-
- NSData *hashedNonce = [NonceHasher hashedNonce:message.nonce];
- result = [self singleEntityNamed:@"Nonce" withPredicate:@"nonce == %@ OR nonce == %@", message.nonce, hashedNonce];
-
- return result != nil;
- }
- - (Group *)groupForGroupId:(NSData *)groupId groupCreator:(NSString *)groupCreator {
- return [self singleEntityNamed:@"Group" withPredicate: @"groupId == %@ AND groupCreator == %@", groupId, groupCreator];
- }
- - (Group *)groupForConversation:(Conversation *)conversation {
- /* is this a group that we started? */
- if (conversation.isGroup) {
- if (conversation.contact) {
- return [self singleEntityNamed:@"Group" withPredicate: @"groupId == %@ AND groupCreator == %@", conversation.groupId, conversation.contact.identity];
- } else {
- return [self singleEntityNamed:@"Group" withPredicate: @"groupId == %@ AND groupCreator == nil", conversation.groupId];
- }
- }
-
- return nil;
- }
- - (LastGroupSyncRequest *)lastGroupSyncRequestFor:(NSData *)groupId groupCreator:(NSString *)groupCreator sinceDate:(NSDate *)sinceDate {
- return [self singleEntityNamed:@"LastGroupSyncRequest" withPredicate: @"groupId == %@ AND groupCreator == %@ AND lastSyncRequest >= %@", groupId, groupCreator, sinceDate];
- }
- - (NSFetchRequest *)fetchRequestForEntity:(NSString *)entityName {
- NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
- fetchRequest.entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:_managedObjectContext];
-
- return fetchRequest;
- }
- - (NSArray *)executeFetchRequest:(NSFetchRequest *)fetchRequest {
- __block NSError *error;
- __block NSArray *result;
- [_managedObjectContext performBlockAndWait:^{
- result = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
- }];
-
- if (result == nil) {
- DDLogError(@"Error in fetch request: %@, %@", error, [error userInfo]);
- return nil;
- } else {
- return result;
- }
- }
- - (NSInteger)executeCountFetchRequest:(NSFetchRequest *)fetchRequest {
- __block NSError *error;
- __block NSUInteger count;
- [_managedObjectContext performBlockAndWait:^{
- count = [_managedObjectContext countForFetchRequest:fetchRequest error:&error];
- }];
-
- if (count != NSNotFound) {
- return count;
- } else {
- return 0;
- }
- }
- - (NSArray *)nameSortDescriptors {
- NSArray *sortDescriptors;
- if ([UserSettings sharedUserSettings].sortOrderFirstName) {
- sortDescriptors = @[
- [NSSortDescriptor sortDescriptorWithKey:@"sortIndex" ascending:YES],
- [NSSortDescriptor sortDescriptorWithKey:@"firstName" ascending:YES selector:@selector(localizedStandardCompare:)],
- [NSSortDescriptor sortDescriptorWithKey:@"lastName" ascending:YES selector:@selector(localizedStandardCompare:)],
- [NSSortDescriptor sortDescriptorWithKey:@"publicNickname" ascending:YES selector:@selector(localizedStandardCompare:)]
- ];
- } else {
- sortDescriptors = @[
- [NSSortDescriptor sortDescriptorWithKey:@"sortIndex" ascending:YES],
- [NSSortDescriptor sortDescriptorWithKey:@"lastName" ascending:YES selector:@selector(localizedStandardCompare:)],
- [NSSortDescriptor sortDescriptorWithKey:@"firstName" ascending:YES selector:@selector(localizedStandardCompare:)],
- [NSSortDescriptor sortDescriptorWithKey:@"publicNickname" ascending:YES selector:@selector(localizedStandardCompare:)]
- ];
- }
-
- return sortDescriptors;
- }
- - (NSFetchedResultsController *)fetchedResultsControllerForContactTypes:(ContactTypes)types list:(ContactList)contactList members:(NSMutableSet *)members {
- NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
- NSEntityDescription *entity = [NSEntityDescription entityForName:@"Contact" inManagedObjectContext:_managedObjectContext];
- [fetchRequest setEntity:entity];
- [fetchRequest setFetchBatchSize:100];
-
- NSMutableArray *predicates = [NSMutableArray array];
-
- if (types == ContactsNoGateway) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not identity beginswith '*'"];
- [predicates addObject:predicate];
- } else if (types == ContactsNoEchoEcho) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not identity beginswith 'ECHOECHO'"];
- [predicates addObject:predicate];
- } else if (types == ContactsGatewayOnly) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"identity beginswith '*'"];
- [predicates addObject:predicate];
- } else if (types == ContactsNoGatewayNoEchoecho) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not identity beginswith '*'"];
- [predicates addObject:predicate];
- predicate = [NSPredicate predicateWithFormat:@"not identity beginswith 'ECHOECHO'"];
- [predicates addObject:predicate];
- }
-
- if ([UserSettings sharedUserSettings].hideStaleContacts) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"state == %d", kStateActive];
- [predicates addObject:predicate];
- }
-
- if (contactList == ContactListWork) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"workContact == %@ ", @1];
- [predicates addObject:predicate];
- } else {
- if (contactList == ContactListContactsAndWork) {
- // do not predicate for work contacts
- } else {
- if ([LicenseStore requiresLicenseKey]) {
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"workContact == %@ ", @0];
- [predicates addObject:predicate];
- }
- }
- }
-
- NSMutableArray *allPredicates = [NSMutableArray array];
- [allPredicates addObject:[NSCompoundPredicate andPredicateWithSubpredicates:predicates]];
-
- if ([UserSettings sharedUserSettings].hideStaleContacts) {
- if (members.count > 0) {
- for (Contact *contact in members) {
- NSPredicate *memberPredicate = [NSPredicate predicateWithFormat:@"identity == %@", contact.identity];
- [allPredicates addObject:memberPredicate];
- }
- }
- }
-
- [fetchRequest setPredicate:[NSCompoundPredicate orPredicateWithSubpredicates:allPredicates]];
- NSArray *sortDescriptors = [self nameSortDescriptors];
- [fetchRequest setSortDescriptors:sortDescriptors];
-
- NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_managedObjectContext sectionNameKeyPath:@"sortIndex" cacheName:nil];
-
- return fetchedResultsController;
- }
- - (NSFetchedResultsController *)fetchedResultsControllerForGroups {
- NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
- NSEntityDescription *entity = [NSEntityDescription entityForName:@"Conversation" inManagedObjectContext:_managedObjectContext];
- [fetchRequest setEntity:entity];
- [fetchRequest setFetchBatchSize:20];
- fetchRequest.predicate = [NSPredicate predicateWithFormat:@"groupId != nil"];
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"groupName" ascending:YES]];
- [fetchRequest setSortDescriptors:sortDescriptors];
-
- NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_managedObjectContext sectionNameKeyPath:nil cacheName:nil];
-
- return fetchedResultsController;
- }
- - (NSFetchedResultsController *)fetchedResultsControllerForConversations {
- NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
- NSEntityDescription *entity = [NSEntityDescription entityForName:@"Conversation" inManagedObjectContext:_managedObjectContext];
- [fetchRequest setEntity:entity];
- [fetchRequest setFetchBatchSize:20];
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"marked" ascending:NO], [NSSortDescriptor sortDescriptorWithKey:@"lastMessage.date" ascending:NO]];
- [fetchRequest setSortDescriptors:sortDescriptors];
-
- NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_managedObjectContext sectionNameKeyPath:nil cacheName:nil];
- return fetchedResultsController;
- }
- - (NSFetchedResultsController *)fetchedResultsControllerForWebClientSessions {
- NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
- NSEntityDescription *entity = [NSEntityDescription entityForName:@"WebClientSession" inManagedObjectContext:_managedObjectContext];
- [fetchRequest setEntity:entity];
- [fetchRequest setFetchBatchSize:20];
-
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"active" ascending:NO], [NSSortDescriptor sortDescriptorWithKey:@"lastConnection" ascending:NO]];
- [fetchRequest setSortDescriptors:sortDescriptors];
-
- NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_managedObjectContext sectionNameKeyPath:nil cacheName:nil];
-
- return fetchedResultsController;
- }
- - (WebClientSession *)webClientSessionForInitiatorPermanentPublicKeyHash:(NSString *)hash {
- return [self singleEntityNamed:@"WebClientSession" withPredicate:@"initiatorPermanentPublicKeyHash == %@", hash];
- }
- - (WebClientSession *)webClientSessionForPrivateKey:(NSData *)privateKey {
- return [self singleEntityNamed:@"WebClientSession" withPredicate:@"privateKey == %@", privateKey];
- }
- - (WebClientSession *)activeWebClientSession {
- return [self singleEntityNamed:@"WebClientSession" withPredicate:@"active == YES"];
- }
- - (NSArray *)allWebClientSessions {
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"lastConnection" ascending:YES]];
- return [self allEntitiesNamed:@"WebClientSession" sortedBy:sortDescriptors withPredicate:nil];
- }
- - (NSArray *)allActiveWebClientSessions {
- NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"lastConnection" ascending:YES]];
- return [self allEntitiesNamed:@"WebClientSession" sortedBy:sortDescriptors withPredicate:@"active == YES"];
- }
- - (NSArray *)allNotPermanentWebClientSessions {
- return [self allEntitiesNamed:@"WebClientSession" sortedBy:nil withPredicate:@"permanent == NO"];
- }
- #pragma mark - private
- - (NSInteger)countEntityNamed:(NSString *)name withPredicate:(NSString *) predicate, ... {
- va_list args;
- va_start(args, predicate);
-
- NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
- fetchRequest.entity = [NSEntityDescription entityForName:name inManagedObjectContext:_managedObjectContext];
- fetchRequest.predicate = [NSPredicate predicateWithFormat:predicate arguments: args];
-
- return [self executeCountFetchRequest: fetchRequest];
- }
- - (id)singleEntityNamed:(NSString *)name withPredicate:(NSString *) predicate, ... {
- va_list args;
- va_start(args, predicate);
-
- NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
- fetchRequest.entity = [NSEntityDescription entityForName:name inManagedObjectContext:_managedObjectContext];
- fetchRequest.predicate = [NSPredicate predicateWithFormat:predicate arguments: args];
- fetchRequest.fetchLimit = 1;
-
- NSArray *result = [self executeFetchRequest:fetchRequest];
-
- if (result != nil && [result count] > 0) {
- return [result objectAtIndex: 0];
- } else {
- return nil;
- }
- }
- - (id)singleEntityNamed:(NSString *)name error:(NSError **)error withPredicate:(NSString *) predicate, ... {
- va_list args;
- va_start(args, predicate);
-
- NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
- fetchRequest.entity = [NSEntityDescription entityForName:name inManagedObjectContext:_managedObjectContext];
- fetchRequest.predicate = [NSPredicate predicateWithFormat:predicate arguments: args];
- fetchRequest.fetchLimit = 1;
-
- NSArray *result = [self executeFetchRequest:fetchRequest];
-
- if (result == nil) {
- NSDictionary *userInfo = @{
- NSLocalizedDescriptionKey: NSLocalizedString(@"Operation was unsuccessful.", nil),
- NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"The operation timed out.", nil),
- NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Have you tried turning it off and on again?", nil)
- };
- *error = [NSError errorWithDomain:NSCocoaErrorDomain code:-57 userInfo:userInfo];
- return nil;
- } else {
- if ( [result count] > 0) {
- return [result objectAtIndex: 0];
- } else {
- return nil;
- }
- }
- }
- - (NSArray *)entitiesNamed:(NSString *)name fetchLimit:(NSInteger)fetchLimit sortedBy:(NSArray *)sortDescriptors withPredicate:(NSString *) predicate, ... {
- va_list args;
- va_start(args, predicate);
-
- return [self entitiesNamed:name fetchLimit:fetchLimit sortedBy:sortDescriptors withPredicate:predicate arguments:args];
- }
- - (NSArray *)allEntitiesNamed:(NSString *)name sortedBy:(NSArray *)sortDescriptors withPredicate:(NSString *) predicate, ... {
- va_list args;
- va_start(args, predicate);
-
- return [self entitiesNamed:name fetchLimit:0 sortedBy:sortDescriptors withPredicate:predicate arguments:args];
- }
- - (NSArray *)entitiesNamed:(NSString *)name fetchLimit:(NSInteger)fetchLimit sortedBy:(NSArray *)sortDescriptors withPredicate:(NSString *) predicate arguments:(va_list)args {
-
- NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
- fetchRequest.entity = [NSEntityDescription entityForName:name inManagedObjectContext:_managedObjectContext];
-
- if (fetchLimit > 0) {
- fetchRequest.fetchLimit = fetchLimit;
- }
-
- if (predicate) {
- fetchRequest.predicate = [NSPredicate predicateWithFormat:predicate arguments: args];
- }
-
- if (sortDescriptors) {
- fetchRequest.sortDescriptors = sortDescriptors;
- }
-
- return [self executeFetchRequest:fetchRequest];
- }
- - (Tag *)tagForName:(NSString *)name {
- return [self singleEntityNamed:@"Tag" withPredicate:@"name == %@", name];
- }
- @end
|