diff --git a/matrixConsole.xcodeproj/project.pbxproj b/matrixConsole.xcodeproj/project.pbxproj index 62ef93e3c..d43d7ba02 100644 --- a/matrixConsole.xcodeproj/project.pbxproj +++ b/matrixConsole.xcodeproj/project.pbxproj @@ -20,6 +20,7 @@ F021FBEF1A5EF57300EA3AE6 /* MediaLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = F021FBEE1A5EF57300EA3AE6 /* MediaLoader.m */; }; F021FBF21A5F1F8E00EA3AE6 /* MediaManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F021FBF11A5F1F8E00EA3AE6 /* MediaManager.m */; }; F024098219E7D177006E741B /* tab_recents@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F024098119E7D177006E741B /* tab_recents@2x.png */; }; + F02900BB1A63C71E00356F7D /* ConsoleTools.m in Sources */ = {isa = PBXBuildFile; fileRef = F02900BA1A63C71E00356F7D /* ConsoleTools.m */; }; F02BCE231A1A5A2B00543B47 /* play.png in Resources */ = {isa = PBXBuildFile; fileRef = F02BCE221A1A5A2B00543B47 /* play.png */; }; F02D707619F1DC9E007B47D3 /* RoomMemberTableCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F02D707519F1DC9E007B47D3 /* RoomMemberTableCell.m */; }; F03C47111A02952800E445AB /* CustomAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = F03C47101A02952800E445AB /* CustomAlert.m */; }; @@ -89,6 +90,8 @@ F021FBF01A5F1F8E00EA3AE6 /* MediaManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaManager.h; sourceTree = ""; }; F021FBF11A5F1F8E00EA3AE6 /* MediaManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MediaManager.m; sourceTree = ""; }; F024098119E7D177006E741B /* tab_recents@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "tab_recents@2x.png"; sourceTree = ""; }; + F02900B91A63C71E00356F7D /* ConsoleTools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConsoleTools.h; sourceTree = ""; }; + F02900BA1A63C71E00356F7D /* ConsoleTools.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConsoleTools.m; sourceTree = ""; }; F02BCE221A1A5A2B00543B47 /* play.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = play.png; sourceTree = ""; }; F02D707419F1DC9E007B47D3 /* RoomMemberTableCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomMemberTableCell.h; sourceTree = ""; }; F02D707519F1DC9E007B47D3 /* RoomMemberTableCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomMemberTableCell.m; sourceTree = ""; }; @@ -206,6 +209,8 @@ F021FBEC1A5EF57300EA3AE6 /* API */ = { isa = PBXGroup; children = ( + F02900B91A63C71E00356F7D /* ConsoleTools.h */, + F02900BA1A63C71E00356F7D /* ConsoleTools.m */, F021FBED1A5EF57300EA3AE6 /* MediaLoader.h */, F021FBEE1A5EF57300EA3AE6 /* MediaLoader.m */, F021FBF01A5F1F8E00EA3AE6 /* MediaManager.h */, @@ -501,6 +506,7 @@ F05B955F19DEED8A008761B0 /* MatrixHandler.m in Sources */, F021FBEF1A5EF57300EA3AE6 /* MediaLoader.m in Sources */, F03EF5FB19F171EB00A0EE52 /* SettingsViewController.m in Sources */, + F02900BB1A63C71E00356F7D /* ConsoleTools.m in Sources */, F01A0FF31A27314B009FAE2F /* RoomMessageComponent.m in Sources */, F03EF5FA19F171EB00A0EE52 /* RoomViewController.m in Sources */, F03EF5F819F171EB00A0EE52 /* MasterTabBarController.m in Sources */, diff --git a/matrixConsole/API/MediaLoader.m b/matrixConsole/API/MediaLoader.m index e426a29e7..b988d8c25 100644 --- a/matrixConsole/API/MediaLoader.m +++ b/matrixConsole/API/MediaLoader.m @@ -16,6 +16,7 @@ #import "MediaManager.h" #import "MatrixHandler.h" +#import "ConsoleTools.h" NSString *const kMediaDownloadProgressNotification = @"kMediaDownloadProgressNotification"; NSString *const kMediaUploadProgressNotification = @"kMediaUploadProgressNotification"; @@ -144,7 +145,7 @@ NSString *const kMediaLoaderProgressDownloadRateKey = @"kMediaLoaderProgressDown NSString* progressString = [NSString stringWithFormat:@"%@ / %@", [NSByteCountFormatter stringFromByteCount:downloadData.length countStyle:NSByteCountFormatterCountStyleFile], [NSByteCountFormatter stringFromByteCount:expectedSize countStyle:NSByteCountFormatterCountStyleFile]]; [dict setValue:progressString forKey:kMediaLoaderProgressStringKey]; - [dict setValue:[MediaManager formatSecondsInterval:dataRemainingTime] forKey:kMediaLoaderProgressRemaingTimeKey]; + [dict setValue:[ConsoleTools formatSecondsInterval:dataRemainingTime] forKey:kMediaLoaderProgressRemaingTimeKey]; NSString* downloadRateStr = [NSString stringWithFormat:@"%@/s", [NSByteCountFormatter stringFromByteCount:meanRate * 1024 countStyle:NSByteCountFormatterCountStyleFile]]; [dict setValue:downloadRateStr forKey:kMediaLoaderProgressDownloadRateKey]; @@ -180,7 +181,7 @@ NSString *const kMediaLoaderProgressDownloadRateKey = @"kMediaLoaderProgressDown if (downloadData.length) { // Cache the downloaded data - NSString *cacheFilePath = [MediaManager cacheMediaData:downloadData forURL:mediaURL mimeType:mimeType]; + NSString *cacheFilePath = [MediaManager cacheMediaData:downloadData forURL:mediaURL andType:mimeType]; // Call registered block if (onMediaReady) { onMediaReady(cacheFilePath); diff --git a/matrixConsole/API/MediaManager.h b/matrixConsole/API/MediaManager.h index 8c47797f5..0b0671f01 100644 --- a/matrixConsole/API/MediaManager.h +++ b/matrixConsole/API/MediaManager.h @@ -28,28 +28,17 @@ extern NSString *const kMediaDownloadDidFailNotification; + (id)sharedInstance; -+ (NSString*)formatSecondsInterval:(CGFloat)secondsInterval; - -+ (UIImage *)resize:(UIImage *)image toFitInSize:(CGSize)size; +// Launch data download from the provided URL. Return a mediaLoader reference in order to let the user cancel this action. ++ (MediaLoader*)downloadMedia:(NSString*)mediaURL mimeType:(NSString *)mimeType; +// Check whether a download is already running for this media url. Return loader if any ++ (MediaLoader*)existingDownloaderForURL:(NSString*)url; // Load a picture from the local cache (Do not start any remote requests) -+ (UIImage*)loadCachePicture:(NSString*)pictureURL; - -// Launch picture downloading. Return a mediaLoader reference in order to let the user cancel this action. -+ (MediaLoader*)downloadPicture:(NSString*)pictureURL; - -// Prepare a media from the local cache or download it if it is not available yet. -// In this second case a mediaLoader reference is returned in order to let the user cancel this action. -+ (MediaLoader*)prepareMedia:(NSString *)mediaURL - mimeType:(NSString *)mimeType - success:(blockMediaLoader_onMediaReady)success - failure:(blockMediaLoader_onError)failure; - -// Check whether a media loader is already running for this media url. Return loader if any -+ (MediaLoader*)mediaLoaderForURL:(NSString*)url; - -+ (NSString *)cacheMediaData:(NSData *)mediaData forURL:(NSString *)mediaURL mimeType:(NSString *)mimeType; - ++ (UIImage*)loadCachePictureForURL:(NSString*)pictureURL; +// Store in cache the provided data for the media URL, return the path of the resulting file ++ (NSString*)cacheMediaData:(NSData *)mediaData forURL:(NSString *)mediaURL andType:(NSString *)mimeType; +// Return the cache path deduced from media URL and type ++ (NSString*)cachePathForMediaURL:(NSString*)mediaURL andType:(NSString *)mimeType; + (NSUInteger)cacheSize; + (void)clearCache; diff --git a/matrixConsole/API/MediaManager.m b/matrixConsole/API/MediaManager.m index 5284eaf09..8d29e9880 100644 --- a/matrixConsole/API/MediaManager.m +++ b/matrixConsole/API/MediaManager.m @@ -29,155 +29,69 @@ static MediaManager *sharedMediaManager = nil; @implementation MediaManager // Table of mediaLoaders in progress -static NSMutableDictionary* pendingMediaLoadersByURL = nil; +static NSMutableDictionary* downloadTableByURL = nil; + (id)sharedInstance { @synchronized(self) { - if(sharedMediaManager == nil) + if(sharedMediaManager == nil) { sharedMediaManager = [[self alloc] init]; + // Create download table here + downloadTableByURL = [[NSMutableDictionary alloc] init]; + } } return sharedMediaManager; } -+ (NSString*)formatSecondsInterval:(CGFloat)secondsInterval { - NSMutableString* formattedString = [[NSMutableString alloc] init]; - - if (secondsInterval < 1) { - [formattedString appendString:@"< 1s"]; - } else if (secondsInterval < 60) - { - [formattedString appendFormat:@"%ds", (int)secondsInterval]; - } - else if (secondsInterval < 3600) - { - [formattedString appendFormat:@"%dm %2ds", (int)(secondsInterval/60), ((int)secondsInterval) % 60]; - } - else if (secondsInterval >= 3600) - { - [formattedString appendFormat:@"%dh %dm %ds", (int)(secondsInterval / 3600), - ((int)(secondsInterval) % 3600) / 60, - (int)(secondsInterval) % 60]; - } - [formattedString appendString:@" left"]; - - return formattedString; -} +#pragma mark - Media Download -+ (UIImage *)resize:(UIImage *)image toFitInSize:(CGSize)size { - UIImage *resizedImage = image; - - // Check whether resize is required - if (size.width && size.height) { - CGFloat width = image.size.width; - CGFloat height = image.size.height; - - if (width > size.width) { - height = (height * size.width) / width; - height = floorf(height / 2) * 2; - width = size.width; - } - if (height > size.height) { - width = (width * size.height) / height; - width = floorf(width / 2) * 2; - height = size.height; - } - - if (width != image.size.width || height != image.size.height) { - // Create the thumbnail - CGSize imageSize = CGSizeMake(width, height); - UIGraphicsBeginImageContext(imageSize); - -// // set to the top quality -// CGContextRef context = UIGraphicsGetCurrentContext(); -// CGContextSetInterpolationQuality(context, kCGInterpolationHigh); - - CGRect thumbnailRect = CGRectMake(0, 0, 0, 0); - thumbnailRect.origin = CGPointMake(0.0,0.0); - thumbnailRect.size.width = imageSize.width; - thumbnailRect.size.height = imageSize.height; - - [image drawInRect:thumbnailRect]; - resizedImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - } - } - - return resizedImage; -} - -+ (id)downloadPicture:(NSString*)pictureURL { - if ([pictureURL hasPrefix:kMediaManagerPrefixForDummyURL] == NO) { - // Create a media loader to download picture ++ (MediaLoader*)downloadMedia:(NSString*)mediaURL mimeType:(NSString *)mimeType { + if ([mediaURL hasPrefix:kMediaManagerPrefixForDummyURL] == NO) { + // Create a media loader to download data MediaLoader *mediaLoader = [[MediaLoader alloc] init]; - [self setMediaLoader:mediaLoader forURL:pictureURL]; - [mediaLoader downloadMedia:pictureURL mimeType:@"image/jpeg" success:^(NSString *cacheFilePath) { - [self removeMediaLoaderWithUrl:pictureURL]; - [[NSNotificationCenter defaultCenter] postNotificationName:kMediaDownloadDidFinishNotification object:pictureURL userInfo:nil]; + // Report this loader + [downloadTableByURL setValue:mediaLoader forKey:mediaURL]; + + // Launch download + [mediaLoader downloadMedia:mediaURL mimeType:mimeType success:^(NSString *cacheFilePath) { + [downloadTableByURL removeObjectForKey:mediaURL]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMediaDownloadDidFinishNotification object:mediaURL userInfo:nil]; } failure:^(NSError *error) { - [self removeMediaLoaderWithUrl:pictureURL]; - NSLog(@"Failed to download image (%@): %@", pictureURL, error); - [[NSNotificationCenter defaultCenter] postNotificationName:kMediaDownloadDidFailNotification object:pictureURL userInfo:nil]; + [downloadTableByURL removeObjectForKey:mediaURL]; + NSLog(@"Failed to download image (%@): %@", mediaURL, error); + [[NSNotificationCenter defaultCenter] postNotificationName:kMediaDownloadDidFailNotification object:mediaURL userInfo:nil]; }]; return mediaLoader; } - [[NSNotificationCenter defaultCenter] postNotificationName:kMediaDownloadDidFailNotification object:pictureURL userInfo:nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:kMediaDownloadDidFailNotification object:mediaURL userInfo:nil]; return nil; } -+ (id)prepareMedia:(NSString *)mediaURL - mimeType:(NSString *)mimeType - success:(blockMediaLoader_onMediaReady)success - failure:(blockMediaLoader_onError)failure { - id ret = nil; - // Check cache - NSString* filename = [MediaManager getCacheFileNameFor:mediaURL mimeType:mimeType]; - if ([[NSFileManager defaultManager] fileExistsAtPath:filename]) { - if (success) { - // Reply synchronously - success (filename); - } - } - else if ([mediaURL hasPrefix:kMediaManagerPrefixForDummyURL] == NO) { - // Create a media loader to download media content - MediaLoader *mediaLoader = [[MediaLoader alloc] init]; - [mediaLoader downloadMedia:mediaURL mimeType:mimeType success:success failure:failure]; - ret = mediaLoader; - } else { - NSLog(@"Load tmp media from cache failed: %@", mediaURL); - if (failure){ - failure(nil); - } - } - return ret; -} - // try to find out a media loader from a media URL -+ (id)mediaLoaderForURL:(NSString*)url { - if (pendingMediaLoadersByURL && url) { - return [pendingMediaLoadersByURL valueForKey:url]; ++ (id)existingDownloaderForURL:(NSString*)url { + if (downloadTableByURL && url) { + return [downloadTableByURL valueForKey:url]; } return nil; } -+ (void)setMediaLoader:(MediaLoader*)mediaLoader forURL:(NSString*)url { - if (!pendingMediaLoadersByURL) { - pendingMediaLoadersByURL = [[NSMutableDictionary alloc] init]; +#pragma mark - Cache Handling + ++ (UIImage*)loadCachePictureForURL:(NSString*)pictureURL { + UIImage* res = nil; + NSString* filename = [MediaManager cachePathForMediaURL:pictureURL andType:@"image/jpeg"]; + + if ([[NSFileManager defaultManager] fileExistsAtPath:filename]) { + NSData* imageContent = [NSData dataWithContentsOfFile:filename options:(NSDataReadingMappedAlways | NSDataReadingUncached) error:nil]; + if (imageContent) { + res = [[UIImage alloc] initWithData:imageContent]; + } } - // sanity check - if (mediaLoader && url) { - [pendingMediaLoadersByURL setValue:mediaLoader forKey:url]; - } + return res; } -+ (void)removeMediaLoaderWithUrl:(NSString*)url { - if (url) { - [pendingMediaLoadersByURL removeObjectForKey:url]; - } -} - -+ (NSString*)cacheMediaData:(NSData*)mediaData forURL:(NSString *)mediaURL mimeType:(NSString *)mimeType { - NSString* filename = [MediaManager getCacheFileNameFor:mediaURL mimeType:mimeType]; ++ (NSString*)cacheMediaData:(NSData*)mediaData forURL:(NSString *)mediaURL andType:(NSString *)mimeType { + NSString* filename = [MediaManager cachePathForMediaURL:mediaURL andType:mimeType]; if ([mediaData writeToFile:filename atomically:YES]) { return filename; @@ -186,6 +100,26 @@ static NSMutableDictionary* pendingMediaLoadersByURL = nil; } } ++ (NSString*)cachePathForMediaURL:(NSString*)mediaURL andType:(NSString *)mimeType { + NSString *fileName; + if ([mimeType isEqualToString:@"image/jpeg"]) { + fileName = [NSString stringWithFormat:@"ima%lu.jpg", (unsigned long)mediaURL.hash]; + } else if ([mimeType isEqualToString:@"video/mp4"]) { + fileName = [NSString stringWithFormat:@"video%lu.mp4", (unsigned long)mediaURL.hash]; + } else if ([mimeType isEqualToString:@"video/quicktime"]) { + fileName = [NSString stringWithFormat:@"video%lu.mov", (unsigned long)mediaURL.hash]; + } else { + NSString *extension = @""; + NSArray *components = [mediaURL componentsSeparatedByString:@"."]; + if (components && components.count > 1) { + extension = [components lastObject]; + } + fileName = [NSString stringWithFormat:@"%lu.%@", (unsigned long)mediaURL.hash, extension]; + } + + return [[MediaManager getCachePath] stringByAppendingPathComponent:fileName]; +} + + (void)clearCache { NSError *error = nil; @@ -246,22 +180,6 @@ static NSMutableDictionary* pendingMediaLoadersByURL = nil; return (NSUInteger)[MediaManager folderSize:mediaCachePath]; } -#pragma mark - Cache handling - -+ (UIImage*)loadCachePicture:(NSString*)pictureURL { - UIImage* res = nil; - NSString* filename = [MediaManager getCacheFileNameFor:pictureURL mimeType:@"image/jpeg"]; - - if ([[NSFileManager defaultManager] fileExistsAtPath:filename]) { - NSData* imageContent = [NSData dataWithContentsOfFile:filename options:(NSDataReadingMappedAlways | NSDataReadingUncached) error:nil]; - if (imageContent) { - res = [[UIImage alloc] initWithData:imageContent]; - } - } - - return res; -} - + (NSString*)getCachePath { NSString *cachePath = nil; @@ -280,24 +198,4 @@ static NSMutableDictionary* pendingMediaLoadersByURL = nil; return cachePath; } -+ (NSString*)getCacheFileNameFor:(NSString*)mediaURL mimeType:(NSString *)mimeType { - NSString *fileName; - if ([mimeType isEqualToString:@"image/jpeg"]) { - fileName = [NSString stringWithFormat:@"ima%lu.jpg", (unsigned long)mediaURL.hash]; - } else if ([mimeType isEqualToString:@"video/mp4"]) { - fileName = [NSString stringWithFormat:@"video%lu.mp4", (unsigned long)mediaURL.hash]; - } else if ([mimeType isEqualToString:@"video/quicktime"]) { - fileName = [NSString stringWithFormat:@"video%lu.mov", (unsigned long)mediaURL.hash]; - } else { - NSString *extension = @""; - NSArray *components = [mediaURL componentsSeparatedByString:@"."]; - if (components && components.count > 1) { - extension = [components lastObject]; - } - fileName = [NSString stringWithFormat:@"%lu.%@", (unsigned long)mediaURL.hash, extension]; - } - - return [[MediaManager getCachePath] stringByAppendingPathComponent:fileName]; -} - @end diff --git a/matrixConsole/API/UploadManager.m b/matrixConsole/API/UploadManager.m index 4780e1a5d..615aa5888 100644 --- a/matrixConsole/API/UploadManager.m +++ b/matrixConsole/API/UploadManager.m @@ -16,6 +16,7 @@ #import "UploadManager.h" #import "MediaManager.h" +#import "ConsoleTools.h" NSString *const kUploadManagerUploadStartTimeKey = @"kUploadManagerUploadStartTimeKey"; NSString *const kUploadManagerStatsStartTimeKey = @"kUploadManagerUploadStartTimeKey"; @@ -85,7 +86,7 @@ static NSMutableDictionary* statsByURL = nil; NSString* progressString = [NSString stringWithFormat:@"%@ / %@", [NSByteCountFormatter stringFromByteCount:totalBytesWritten countStyle:NSByteCountFormatterCountStyleFile], [NSByteCountFormatter stringFromByteCount:totalBytesExpectedToWrite countStyle:NSByteCountFormatterCountStyleFile]]; [dict setValue:progressString forKey:kMediaLoaderProgressStringKey]; - [dict setValue:[MediaManager formatSecondsInterval:dataRemainingTime] forKey:kMediaLoaderProgressRemaingTimeKey]; + [dict setValue:[ConsoleTools formatSecondsInterval:dataRemainingTime] forKey:kMediaLoaderProgressRemaingTimeKey]; NSString* downloadRateStr = [NSString stringWithFormat:@"%@/s", [NSByteCountFormatter stringFromByteCount:dataRate * 1024 countStyle:NSByteCountFormatterCountStyleFile]]; [dict setValue:downloadRateStr forKey:kMediaLoaderProgressDownloadRateKey]; diff --git a/matrixConsole/View/CustomImageView.m b/matrixConsole/View/CustomImageView.m index d112d2ebd..0dad2ff67 100644 --- a/matrixConsole/View/CustomImageView.m +++ b/matrixConsole/View/CustomImageView.m @@ -403,7 +403,7 @@ _hideActivityIndicator = hideActivityIndicator; if (hideActivityIndicator) { [self stopActivityIndicator]; - } else if ([MediaManager mediaLoaderForURL:imageURL]) { + } else if ([MediaManager existingDownloaderForURL:imageURL]) { // Loading is in progress, start activity indicator [self startActivityIndicator]; } @@ -421,7 +421,7 @@ } // Check whether the image download is in progress - MediaLoader* loader = [MediaManager mediaLoaderForURL:imageURL]; + MediaLoader* loader = [MediaManager existingDownloaderForURL:imageURL]; if (loader) { // Set preview until the image is loaded self.image = previewImage; @@ -434,7 +434,7 @@ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadEnd:) name:kMediaDownloadDidFailNotification object:nil]; } else { // Retrieve the image from cache - UIImage* image = [MediaManager loadCachePicture:imageURL]; + UIImage* image = [MediaManager loadCachePictureForURL:imageURL]; if (image) { self.image = image; [self stopActivityIndicator]; @@ -449,7 +449,7 @@ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadProgress:) name:kMediaDownloadProgressNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadEnd:) name:kMediaDownloadDidFinishNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadEnd:) name:kMediaDownloadDidFailNotification object:nil]; - [MediaManager downloadPicture:imageURL]; + [MediaManager downloadMedia:imageURL mimeType:@"image/jpeg"]; } } } @@ -462,7 +462,7 @@ if ([url isEqualToString:imageURL]) { [self stopActivityIndicator]; // update the image - UIImage* image = [MediaManager loadCachePicture:imageURL]; + UIImage* image = [MediaManager loadCachePictureForURL:imageURL]; if (image) { self.image = image; } diff --git a/matrixConsole/View/RoomMessageTableCell.m b/matrixConsole/View/RoomMessageTableCell.m index 7f2aba8b7..815324d7b 100644 --- a/matrixConsole/View/RoomMessageTableCell.m +++ b/matrixConsole/View/RoomMessageTableCell.m @@ -95,7 +95,7 @@ if (self.message.attachmentURL) { // check if there is a downlad in progress - MediaLoader *loader = [MediaManager mediaLoaderForURL:self.message.attachmentURL]; + MediaLoader *loader = [MediaManager existingDownloaderForURL:self.message.attachmentURL]; NSDictionary *dict = loader.downloadStatsDict; @@ -124,7 +124,7 @@ - (void)cancelDownload { // get the linked medida loader - MediaLoader *loader = [MediaManager mediaLoaderForURL:self.message.attachmentURL]; + MediaLoader *loader = [MediaManager existingDownloaderForURL:self.message.attachmentURL]; if (loader) { [loader cancel]; } diff --git a/matrixConsole/ViewController/MemberViewController.m b/matrixConsole/ViewController/MemberViewController.m index 2e6f7778e..9077ac373 100644 --- a/matrixConsole/ViewController/MemberViewController.m +++ b/matrixConsole/ViewController/MemberViewController.m @@ -165,14 +165,14 @@ if (_mxRoomMember.avatarUrl) { // Check whether the image download is in progress - id loader = [MediaManager mediaLoaderForURL:_mxRoomMember.avatarUrl]; + id loader = [MediaManager existingDownloaderForURL:_mxRoomMember.avatarUrl]; if (loader) { // Add observers [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadEnd:) name:kMediaDownloadDidFinishNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadEnd:) name:kMediaDownloadDidFailNotification object:nil]; } else { // Retrieve the image from cache - UIImage* image = [MediaManager loadCachePicture:_mxRoomMember.avatarUrl]; + UIImage* image = [MediaManager loadCachePictureForURL:_mxRoomMember.avatarUrl]; if (image) { [self.memberThumbnailButton setImage:image forState:UIControlStateNormal]; [self.memberThumbnailButton setImage:image forState:UIControlStateHighlighted]; @@ -184,7 +184,7 @@ // Add observers [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadEnd:) name:kMediaDownloadDidFinishNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadEnd:) name:kMediaDownloadDidFailNotification object:nil]; - imageLoader = [MediaManager downloadPicture:_mxRoomMember.avatarUrl]; + imageLoader = [MediaManager downloadMedia:_mxRoomMember.avatarUrl mimeType:@"image/jpeg"]; } } } else { @@ -205,7 +205,7 @@ if ([url isEqualToString:_mxRoomMember.avatarUrl]) { // update the image - UIImage* image = [MediaManager loadCachePicture:_mxRoomMember.avatarUrl]; + UIImage* image = [MediaManager loadCachePictureForURL:_mxRoomMember.avatarUrl]; if (image == nil) { image = [UIImage imageNamed:@"default-profile"]; } diff --git a/matrixConsole/ViewController/RoomViewController.m b/matrixConsole/ViewController/RoomViewController.m index 6fe9e42db..4f2bbafc3 100644 --- a/matrixConsole/ViewController/RoomViewController.m +++ b/matrixConsole/ViewController/RoomViewController.m @@ -30,6 +30,7 @@ #import "MediaManager.h" #import "UploadManager.h" +#import "ConsoleTools.h" #define ROOMVIEWCONTROLLER_TYPING_TIMEOUT_MS 20000 @@ -78,6 +79,8 @@ NSString *const kCmdResetUserPowerLevel = @"/deop"; NSString *AVAudioSessionCategory; MPMoviePlayerController *videoPlayer; MPMoviePlayerController *tmpVideoPlayer; + NSString *selectedVideoURL; + NSString *selectedVideoCachePath; // used to trap the slide to close the keyboard UIView* inputAccessoryView; @@ -344,7 +347,7 @@ NSString *const kCmdResetUserPowerLevel = @"/deop"; __weak typeof(self) weakSelf = self; NSString* url = ((RoomMessageTableCell*)view).message.attachmentURL; - MediaLoader *loader = [MediaManager mediaLoaderForURL:url]; + MediaLoader *loader = [MediaManager existingDownloaderForURL:url]; // offer to cancel a download only if there is a pending one if (loader) { @@ -355,7 +358,7 @@ NSString *const kCmdResetUserPowerLevel = @"/deop"; self.actionMenu.cancelButtonIndex = [self.actionMenu addActionWithTitle:@"OK" style:CustomAlertActionStyleDefault handler:^(CustomAlert *alert) { // get again the loader, the cell could have been reused. - MediaLoader *loader = [MediaManager mediaLoaderForURL:url]; + MediaLoader *loader = [MediaManager existingDownloaderForURL:url]; if (loader) { [loader cancel]; } @@ -915,22 +918,16 @@ NSString *const kCmdResetUserPowerLevel = @"/deop"; selector:@selector(moviePlayerWillExitFullscreen:) name:MPMoviePlayerWillExitFullscreenNotification object:videoPlayer]; - [MediaManager prepareMedia:url mimeType:mimetype success:^(NSString *cacheFilePath) { - if (cacheFilePath) { - if (tmpCachedAttachments == nil) { - tmpCachedAttachments = [NSMutableArray array]; - } - if ([tmpCachedAttachments indexOfObject:cacheFilePath]) { - [tmpCachedAttachments addObject:cacheFilePath]; - } - } - videoPlayer.contentURL = [NSURL fileURLWithPath:cacheFilePath]; + selectedVideoURL = url; + selectedVideoCachePath = [MediaManager cachePathForMediaURL:selectedVideoURL andType:mimetype]; + if ([[NSFileManager defaultManager] fileExistsAtPath:selectedVideoCachePath]) { + videoPlayer.contentURL = [NSURL fileURLWithPath:selectedVideoCachePath]; [videoPlayer play]; - } failure:^(NSError *error) { - [self hideAttachmentView]; - //Alert user - [[AppDelegate theDelegate] showErrorAsAlert:error]; - }]; + } else { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadEnd:) name:kMediaDownloadDidFinishNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadEnd:) name:kMediaDownloadDidFailNotification object:nil]; + [MediaManager downloadMedia:selectedVideoURL mimeType:mimetype]; + } } } } else if (msgtype == RoomMessageTypeAudio) { @@ -938,9 +935,32 @@ NSString *const kCmdResetUserPowerLevel = @"/deop"; } } +- (void)onMediaDownloadEnd:(NSNotification *)notif { + if ([notif.object isKindOfClass:[NSString class]]) { + NSString* url = notif.object; + if ([url isEqualToString:selectedVideoURL]) { + // remove the observers + [[NSNotificationCenter defaultCenter] removeObserver:self name:kMediaDownloadDidFinishNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:kMediaDownloadDidFailNotification object:nil]; + + if ([[NSFileManager defaultManager] fileExistsAtPath:selectedVideoCachePath]) { + videoPlayer.contentURL = [NSURL fileURLWithPath:selectedVideoCachePath]; + [videoPlayer play]; + } else { + NSLog(@"Video Download failed"); // TODO we should notify user + [self hideAttachmentView]; + } + } + } +} + - (void)hideAttachmentView { + selectedVideoURL = nil; + selectedVideoCachePath = nil; [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerWillExitFullscreenNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:kMediaDownloadDidFinishNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:kMediaDownloadDidFailNotification object:nil]; [self dismissCustomImageView]; @@ -989,7 +1009,7 @@ NSString *const kCmdResetUserPowerLevel = @"/deop"; if (videoThumbnail && selectedVideo) { // Prepare video thumbnail description NSUInteger thumbnailSize = ROOM_MESSAGE_MAX_ATTACHMENTVIEW_WIDTH; - UIImage *thumbnail = [MediaManager resize:videoThumbnail toFitInSize:CGSizeMake(thumbnailSize, thumbnailSize)]; + UIImage *thumbnail = [ConsoleTools resize:videoThumbnail toFitInSize:CGSizeMake(thumbnailSize, thumbnailSize)]; NSMutableDictionary *thumbnailInfo = [[NSMutableDictionary alloc] init]; [thumbnailInfo setValue:@"image/jpeg" forKey:@"mimetype"]; [thumbnailInfo setValue:[NSNumber numberWithUnsignedInteger:(NSUInteger)thumbnail.size.width] forKey:@"w"]; @@ -1405,7 +1425,7 @@ NSString *const kCmdResetUserPowerLevel = @"/deop"; } UIImage *preview = nil; if (message.previewURL) { - preview = [MediaManager loadCachePicture:message.previewURL]; + preview = [MediaManager loadCachePictureForURL:message.previewURL]; } [cell.attachmentView setImageURL:url withPreviewImage:preview]; @@ -2010,7 +2030,7 @@ NSString *const kCmdResetUserPowerLevel = @"/deop"; // We store temporarily the image in cache, use the localId to build temporary url NSString *dummyURL = [NSString stringWithFormat:@"%@%@", kMediaManagerPrefixForDummyURL, localEvent.eventId]; NSData *imageData = UIImageJPEGRepresentation(image, 0.5); - NSString *cacheFilePath = [MediaManager cacheMediaData:imageData forURL:dummyURL mimeType:@"image/jpeg"]; + NSString *cacheFilePath = [MediaManager cacheMediaData:imageData forURL:dummyURL andType:@"image/jpeg"]; if (cacheFilePath) { if (tmpCachedAttachments == nil) { tmpCachedAttachments = [NSMutableArray array]; diff --git a/matrixConsole/ViewController/SettingsViewController.m b/matrixConsole/ViewController/SettingsViewController.m index 0f97e0844..30ceac8ff 100644 --- a/matrixConsole/ViewController/SettingsViewController.m +++ b/matrixConsole/ViewController/SettingsViewController.m @@ -455,14 +455,14 @@ NSString* const kCommandsDescriptionText = @"The following commands are availabl currentPictureURL = [avatar_url isEqual:[NSNull null]] ? nil : avatar_url; if (currentPictureURL) { // Check whether the image download is in progress - id loader = [MediaManager mediaLoaderForURL:currentPictureURL]; + id loader = [MediaManager existingDownloaderForURL:currentPictureURL]; if (loader) { // Add observers [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadEnd:) name:kMediaDownloadDidFinishNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadEnd:) name:kMediaDownloadDidFailNotification object:nil]; } else { // Retrieve the image from cache - UIImage* image = [MediaManager loadCachePicture:currentPictureURL]; + UIImage* image = [MediaManager loadCachePictureForURL:currentPictureURL]; if (image) { [self updateAvatarImage:image]; } else { @@ -473,7 +473,7 @@ NSString* const kCommandsDescriptionText = @"The following commands are availabl // Add observers [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadEnd:) name:kMediaDownloadDidFinishNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaDownloadEnd:) name:kMediaDownloadDidFailNotification object:nil]; - imageLoader = [MediaManager downloadPicture:currentPictureURL]; + imageLoader = [MediaManager downloadMedia:currentPictureURL mimeType:@"image/jpeg"]; } } } else { @@ -490,7 +490,7 @@ NSString* const kCommandsDescriptionText = @"The following commands are availabl if ([url isEqualToString:currentPictureURL]) { // update the image - UIImage* image = [MediaManager loadCachePicture:currentPictureURL]; + UIImage* image = [MediaManager loadCachePictureForURL:currentPictureURL]; if (image == nil) { image = [UIImage imageNamed:@"default-profile"]; }