mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			210 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Matlab
		
	
		
		
			
		
	
	
			210 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Matlab
		
	
| 
											5 years ago
										 | // | ||
|  | //  Copyright (c) 2019 Open Whisper Systems. All rights reserved. | ||
|  | // | ||
|  | 
 | ||
|  | #import "OWSMediaGalleryFinder.h" | ||
|  | #import "OWSStorage.h" | ||
|  | #import "TSAttachmentStream.h" | ||
|  | #import "TSMessage.h" | ||
|  | #import "TSThread.h" | ||
|  | #import <YapDatabase/YapDatabaseAutoView.h> | ||
|  | #import <YapDatabase/YapDatabaseTransaction.h> | ||
|  | #import <YapDatabase/YapDatabaseViewTypes.h> | ||
|  | #import <YapDatabase/YapWhitelistBlacklist.h> | ||
| 
											5 years ago
										 | #import "TSAttachment.h" | ||
| 
											5 years ago
										 | 
 | ||
|  | NS_ASSUME_NONNULL_BEGIN | ||
|  | 
 | ||
|  | static NSString *const OWSMediaGalleryFinderExtensionName = @"OWSMediaGalleryFinderExtensionName"; | ||
|  | 
 | ||
|  | @interface OWSMediaGalleryFinder () | ||
|  | 
 | ||
|  | @property (nonatomic, readonly) TSThread *thread; | ||
|  | 
 | ||
|  | @end | ||
|  | 
 | ||
|  | @implementation OWSMediaGalleryFinder | ||
|  | 
 | ||
|  | - (instancetype)initWithThread:(TSThread *)thread | ||
|  | { | ||
|  |     self = [super init]; | ||
|  |     if (!self) { | ||
|  |         return self; | ||
|  |     } | ||
|  | 
 | ||
|  |     _thread = thread; | ||
|  | 
 | ||
|  |     return self; | ||
|  | } | ||
|  | 
 | ||
|  | #pragma mark - Public Finder Methods | ||
|  | 
 | ||
|  | - (NSUInteger)mediaCountWithTransaction:(YapDatabaseReadTransaction *)transaction | ||
|  | { | ||
|  |     return [[self galleryExtensionWithTransaction:transaction] numberOfItemsInGroup:self.mediaGroup]; | ||
|  | } | ||
|  | 
 | ||
|  | - (nullable NSNumber *)mediaIndexForAttachment:(TSAttachment *)attachment | ||
|  |                                    transaction:(YapDatabaseReadTransaction *)transaction | ||
|  | { | ||
|  |     NSString *groupId; | ||
|  |     NSUInteger index; | ||
|  | 
 | ||
|  |     BOOL wasFound = [[self galleryExtensionWithTransaction:transaction] getGroup:&groupId | ||
|  |                                                                            index:&index | ||
|  |                                                                           forKey:attachment.uniqueId | ||
|  |                                                                     inCollection:[TSAttachment collection]]; | ||
|  | 
 | ||
|  |     if (!wasFound) { | ||
|  |         return nil; | ||
|  |     } | ||
|  | 
 | ||
|  |     return @(index); | ||
|  | } | ||
|  | 
 | ||
|  | - (nullable TSAttachment *)oldestMediaAttachmentWithTransaction:(YapDatabaseReadTransaction *)transaction | ||
|  | { | ||
|  |     return [[self galleryExtensionWithTransaction:transaction] firstObjectInGroup:self.mediaGroup]; | ||
|  | } | ||
|  | 
 | ||
|  | - (nullable TSAttachment *)mostRecentMediaAttachmentWithTransaction:(YapDatabaseReadTransaction *)transaction | ||
|  | { | ||
|  |     return [[self galleryExtensionWithTransaction:transaction] lastObjectInGroup:self.mediaGroup]; | ||
|  | } | ||
|  | 
 | ||
|  | - (void)enumerateMediaAttachmentsWithRange:(NSRange)range | ||
|  |                                transaction:(YapDatabaseReadTransaction *)transaction | ||
|  |                                      block:(void (^)(TSAttachment *))attachmentBlock | ||
|  | { | ||
|  | 
 | ||
|  |     [[self galleryExtensionWithTransaction:transaction] | ||
|  |         enumerateKeysAndObjectsInGroup:self.mediaGroup | ||
|  |                            withOptions:0 | ||
|  |                                  range:range | ||
|  |                             usingBlock:^(NSString *_Nonnull collection, | ||
|  |                                 NSString *_Nonnull key, | ||
|  |                                 id _Nonnull object, | ||
|  |                                 NSUInteger index, | ||
|  |                                 BOOL *_Nonnull stop) { | ||
|  |                                 attachmentBlock((TSAttachment *)object); | ||
|  |                             }]; | ||
|  | } | ||
|  | 
 | ||
|  | - (BOOL)hasMediaChangesInNotifications:(NSArray<NSNotification *> *)notifications | ||
|  |                           dbConnection:(YapDatabaseConnection *)dbConnection | ||
|  | { | ||
|  |     YapDatabaseAutoViewConnection *extConnection = [dbConnection ext:OWSMediaGalleryFinderExtensionName]; | ||
|  | 
 | ||
|  |     return [extConnection hasChangesForGroup:self.mediaGroup inNotifications:notifications]; | ||
|  | } | ||
|  | 
 | ||
|  | #pragma mark - Util | ||
|  | 
 | ||
|  | - (YapDatabaseAutoViewTransaction *)galleryExtensionWithTransaction:(YapDatabaseReadTransaction *)transaction | ||
|  | { | ||
|  |     YapDatabaseAutoViewTransaction *extension = [transaction extension:OWSMediaGalleryFinderExtensionName]; | ||
| 
											5 years ago
										 | 
 | ||
| 
											5 years ago
										 |     return extension; | ||
|  | } | ||
|  | 
 | ||
|  | + (NSString *)mediaGroupWithThreadId:(NSString *)threadId | ||
|  | { | ||
|  |     return [NSString stringWithFormat:@"%@-media", threadId]; | ||
|  | } | ||
|  | 
 | ||
|  | - (NSString *)mediaGroup | ||
|  | { | ||
|  |     return [[self class] mediaGroupWithThreadId:self.thread.uniqueId]; | ||
|  | } | ||
|  | 
 | ||
|  | #pragma mark - Extension registration | ||
|  | 
 | ||
|  | + (NSString *)databaseExtensionName | ||
|  | { | ||
|  |     return OWSMediaGalleryFinderExtensionName; | ||
|  | } | ||
|  | 
 | ||
|  | + (void)asyncRegisterDatabaseExtensionsWithPrimaryStorage:(OWSStorage *)storage | ||
|  | { | ||
|  |     [storage asyncRegisterExtension:[self mediaGalleryDatabaseExtension] | ||
|  |                            withName:OWSMediaGalleryFinderExtensionName]; | ||
|  | } | ||
|  | 
 | ||
|  | + (YapDatabaseAutoView *)mediaGalleryDatabaseExtension | ||
|  | { | ||
|  |     YapDatabaseViewSorting *sorting = | ||
|  |         [YapDatabaseViewSorting withObjectBlock:^NSComparisonResult(YapDatabaseReadTransaction *_Nonnull transaction, | ||
|  |             NSString *_Nonnull group, | ||
|  |             NSString *_Nonnull collection1, | ||
|  |             NSString *_Nonnull key1, | ||
|  |             id _Nonnull object1, | ||
|  |             NSString *_Nonnull collection2, | ||
|  |             NSString *_Nonnull key2, | ||
|  |             id _Nonnull object2) { | ||
|  |             if (![object1 isKindOfClass:[TSAttachment class]]) { | ||
|  |                 return NSOrderedSame; | ||
|  |             } | ||
|  |             TSAttachment *attachment1 = (TSAttachment *)object1; | ||
|  | 
 | ||
|  |             if (![object2 isKindOfClass:[TSAttachment class]]) { | ||
|  |                 return NSOrderedSame; | ||
|  |             } | ||
|  |             TSAttachment *attachment2 = (TSAttachment *)object2; | ||
|  | 
 | ||
|  |             TSMessage *_Nullable message1 = [attachment1 fetchAlbumMessageWithTransaction:transaction]; | ||
|  |             TSMessage *_Nullable message2 = [attachment2 fetchAlbumMessageWithTransaction:transaction]; | ||
|  |             if (message1 == nil || message2 == nil) { | ||
|  |                 return NSOrderedSame; | ||
|  |             } | ||
|  | 
 | ||
|  |             if ([message1.uniqueId isEqualToString:message2.uniqueId]) { | ||
|  |                 NSUInteger index1 = [message1.attachmentIds indexOfObject:attachment1.uniqueId]; | ||
|  |                 NSUInteger index2 = [message1.attachmentIds indexOfObject:attachment2.uniqueId]; | ||
|  | 
 | ||
|  |                 if (index1 == NSNotFound || index2 == NSNotFound) { | ||
|  |                     return NSOrderedSame; | ||
|  |                 } | ||
|  |                 return [@(index1) compare:@(index2)]; | ||
|  |             } else { | ||
|  |                 return [message1 compareForSorting:message2]; | ||
|  |             } | ||
|  |         }]; | ||
|  | 
 | ||
|  |     YapDatabaseViewGrouping *grouping = | ||
|  |         [YapDatabaseViewGrouping withObjectBlock:^NSString *_Nullable(YapDatabaseReadTransaction *_Nonnull transaction, | ||
|  |             NSString *_Nonnull collection, | ||
|  |             NSString *_Nonnull key, | ||
|  |             id _Nonnull object) { | ||
|  |             // Don't include nil or not yet downloaded attachments. | ||
|  |             if (![object isKindOfClass:[TSAttachmentStream class]]) { | ||
|  |                 return nil; | ||
|  |             } | ||
|  | 
 | ||
|  |             TSAttachmentStream *attachment = (TSAttachmentStream *)object; | ||
|  |             if (attachment.albumMessageId == nil) { | ||
|  |                 return nil; | ||
|  |             } | ||
|  | 
 | ||
|  |             if (!attachment.isValidVisualMedia) { | ||
|  |                 return nil; | ||
|  |             } | ||
|  | 
 | ||
|  |             TSMessage *message = [attachment fetchAlbumMessageWithTransaction:transaction]; | ||
|  |             if (message == nil) { | ||
|  |                 return nil; | ||
|  |             } | ||
|  | 
 | ||
|  |             return [self mediaGroupWithThreadId:message.uniqueThreadId]; | ||
|  |         }]; | ||
|  | 
 | ||
|  |     YapDatabaseViewOptions *options = [YapDatabaseViewOptions new]; | ||
|  |     options.allowedCollections = | ||
|  |         [[YapWhitelistBlacklist alloc] initWithWhitelist:[NSSet setWithObject:TSAttachment.collection]]; | ||
|  | 
 | ||
|  |     return [[YapDatabaseAutoView alloc] initWithGrouping:grouping sorting:sorting versionTag:@"4" options:options]; | ||
|  | } | ||
|  | 
 | ||
|  | @end | ||
|  | 
 | ||
|  | NS_ASSUME_NONNULL_END |