CCViewerImage.m 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. //
  2. // CCDetail.m
  3. // Nextcloud
  4. //
  5. // Created by Marino Faggiana on 16/01/15.
  6. // Copyright (c) 2017 Marino Faggiana. All rights reserved.
  7. //
  8. // Author Marino Faggiana <marino.faggiana@nextcloud.com>
  9. //
  10. // This program is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. #import "CCViewerImage.h"
  24. #import "AppDelegate.h"
  25. #import "CCMain.h"
  26. #import "NCUchardet.h"
  27. #import "NCBridgeSwift.h"
  28. @interface CCViewerImage ()
  29. {
  30. AppDelegate *appDelegate;
  31. NSInteger indexNowVisible;
  32. NSString *ocIdNowVisible;
  33. NSString *fileNameExtension;
  34. }
  35. @end
  36. @implementation CCViewerImage
  37. #pragma --------------------------------------------------------------------------------------------
  38. #pragma mark ===== init =====
  39. #pragma --------------------------------------------------------------------------------------------
  40. - (id)initWithCoder:(NSCoder *)aDecoder
  41. {
  42. if (self = [super initWithCoder:aDecoder]) {
  43. appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  44. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeTheming) name:@"changeTheming" object:nil];
  45. self.metadataDetail = [tableMetadata new];
  46. self.photos = [[NSMutableArray alloc] init];
  47. self.photoDataSource = [NSMutableArray new];
  48. indexNowVisible = -1;
  49. ocIdNowVisible = nil;
  50. }
  51. return self;
  52. }
  53. #pragma --------------------------------------------------------------------------------------------
  54. #pragma mark ===== View =====
  55. #pragma --------------------------------------------------------------------------------------------
  56. - (void)viewDidLoad
  57. {
  58. [super viewDidLoad];
  59. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(insertGeocoderLocation:) name:@"insertGeocoderLocation" object:nil];
  60. [self changeTheming];
  61. }
  62. - (void)changeTheming
  63. {
  64. [appDelegate changeTheming:self tableView:nil collectionView:nil form:false];
  65. self.edgesForExtendedLayout = UIRectEdgeAll;
  66. [self viewImage];
  67. }
  68. #pragma --------------------------------------------------------------------------------------------
  69. #pragma mark ===== View Image =====
  70. #pragma --------------------------------------------------------------------------------------------
  71. - (void)viewImage
  72. {
  73. self.photoBrowser = [[MWPhotoBrowser alloc] initWithDelegate:self];
  74. indexNowVisible = -1;
  75. ocIdNowVisible = nil;
  76. [self.photos removeAllObjects];
  77. // if not images, exit
  78. if ([self.photoDataSource count] == 0)
  79. return;
  80. NSUInteger index = 0;
  81. for (tableMetadata *metadata in self.photoDataSource) {
  82. // start from here ?
  83. if (self.metadataDetail.ocId && [metadata.ocId isEqualToString:self.metadataDetail.ocId])
  84. [self.photoBrowser setCurrentPhotoIndex:index];
  85. [self.photos addObject:[MWPhoto photoWithImage:nil]];
  86. // add directory
  87. index++;
  88. }
  89. // PhotoBrowser
  90. if ([NCBrandOptions sharedInstance].disable_openin_file) {
  91. self.photoBrowser.displayActionButton = NO;
  92. } else {
  93. self.photoBrowser.displayActionButton = YES;
  94. }
  95. self.photoBrowser.displayDeleteButton = YES;
  96. if ([CCUtility isFolderEncrypted:_metadataDetail.serverUrl account:appDelegate.activeAccount]) // E2EE
  97. self.photoBrowser.displayShareButton = NO;
  98. else
  99. self.photoBrowser.displayShareButton = YES;
  100. self.photoBrowser.displayNavArrows = YES;
  101. self.photoBrowser.displaySelectionButtons = NO;
  102. self.photoBrowser.alwaysShowControls = NO;
  103. self.photoBrowser.zoomPhotosToFill = NO;
  104. self.photoBrowser.autoPlayOnAppear = NO;
  105. self.photoBrowser.delayToHideElements = 15;
  106. if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
  107. self.photoBrowser.enableSwipeToDismiss = NO;
  108. if (self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) {
  109. [self addChildViewController:self.photoBrowser];
  110. [self.view addSubview:self.photoBrowser.view];
  111. [self.photoBrowser didMoveToParentViewController:self];
  112. } else {
  113. [self.navigationController pushViewController:self.photoBrowser animated:NO];
  114. }
  115. self.navigationController.navigationBar.topItem.title = _metadataDetail.fileNameView;
  116. }
  117. - (NSUInteger)numberOfPhotosInPhotoBrowser:(MWPhotoBrowser *)photoBrowser
  118. {
  119. return [self.photoDataSource count];
  120. }
  121. - (NSString *)photoBrowser:(MWPhotoBrowser *)photoBrowser titleForPhotoAtIndex:(NSUInteger)index
  122. {
  123. tableMetadata *metadata = [self.photoDataSource objectAtIndex:index];
  124. NSString *titleDir = metadata.fileNameView;
  125. self.title = titleDir;
  126. return titleDir;
  127. }
  128. - (void)photoBrowser:(MWPhotoBrowser *)photoBrowser didDisplayPhotoAtIndex:(NSUInteger)index
  129. {
  130. tableMetadata *metadata = [self.photoDataSource objectAtIndex:index];
  131. indexNowVisible = index;
  132. ocIdNowVisible = metadata.ocId;
  133. photoBrowser.toolbar.hidden = NO;
  134. // Download image ?
  135. if (metadata) {
  136. NSInteger status;
  137. tableMetadata *metadataDB = [[NCManageDatabase sharedInstance] getMetadataWithPredicate:[NSPredicate predicateWithFormat:@"ocId == %@", metadata.ocId]];
  138. if (metadataDB) {
  139. status = metadataDB.status;
  140. } else {
  141. status = k_metadataStatusNormal;
  142. }
  143. if ([CCUtility fileProviderStorageExists:metadata.ocId fileNameView:metadata.fileNameView] == NO && status == k_metadataStatusNormal) {
  144. if ([[NSFileManager defaultManager] fileExistsAtPath:[CCUtility getDirectoryProviderStorageIconOcId:metadata.ocId fileNameView:metadata.fileNameView]] == NO && metadata.hasPreview) {
  145. [CCGraphics addImageToTitle:NSLocalizedString(@"_...loading..._", nil) colorTitle:NCBrandColor.sharedInstance.brandText imageTitle:[CCGraphics changeThemingColorImage:[UIImage imageNamed:@"load"] multiplier:2 color:NCBrandColor.sharedInstance.brandText] imageRight:NO navigationItem:self.navigationItem];
  146. CGFloat width = [[NCUtility sharedInstance] getScreenWidthForPreview];
  147. CGFloat height = [[NCUtility sharedInstance] getScreenHeightForPreview];
  148. [[OCNetworking sharedManager] downloadPreviewWithAccount:appDelegate.activeAccount metadata:metadata withWidth:width andHeight:height completion:^(NSString *account, UIImage *image, NSString *message, NSInteger errorCode) {
  149. self.navigationItem.titleView = nil;
  150. self.title = metadata.fileNameView;
  151. if (errorCode == 0 && [account isEqualToString:appDelegate.activeAccount]) {
  152. [self.photoBrowser reloadData];
  153. }
  154. }];
  155. } else {
  156. [self downloadPhotoBrowser:metadata];
  157. }
  158. }
  159. }
  160. // Title
  161. if (metadata)
  162. self.title = metadata.fileNameView;
  163. }
  164. - (id <MWPhoto>)photoBrowser:(MWPhotoBrowser *)photoBrowser photoAtIndex:(NSUInteger)index
  165. {
  166. UIImage *image;
  167. tableMetadata *metadata = [self.photoDataSource objectAtIndex:index];
  168. if (index < self.photos.count) {
  169. if (metadata.ocId) {
  170. UIImage *imagePreview = [UIImage imageWithContentsOfFile:[CCUtility getDirectoryProviderStorageIconOcId:metadata.ocId fileNameView:metadata.fileNameView]];
  171. // if (!imagePreview) imagePreview = [CCGraphics changeThemingColorImage:[UIImage imageNamed:@"file_photo"] multiplier:3 color:[NCBrandColor.sharedInstance icon]];
  172. if ([metadata.typeFile isEqualToString: k_metadataTypeFile_image]) {
  173. NSString *fileImage = [CCUtility getDirectoryProviderStorageOcId:metadata.ocId fileNameView:metadata.fileNameView];
  174. NSString *ext = [CCUtility getExtension:metadata.fileNameView];
  175. if ([ext isEqualToString:@"GIF"]) image = [UIImage animatedImageWithAnimatedGIFURL:[NSURL fileURLWithPath:fileImage]];
  176. else image = [UIImage imageWithContentsOfFile:fileImage];
  177. if (image) {
  178. MWPhoto *photo = [MWPhoto photoWithImage:image];
  179. // Location ??
  180. [self setLocationCaptionPhoto:photo ocId:metadata.ocId];
  181. [self.photos replaceObjectAtIndex:index withObject:photo];
  182. } else {
  183. if (metadata.status == k_metadataStatusDownloadError) {
  184. [self.photos replaceObjectAtIndex:index withObject:[MWPhoto photoWithImage:[UIImage imageNamed:@"filePreviewError"]]];
  185. } else {
  186. if (imagePreview)
  187. [self.photos replaceObjectAtIndex:index withObject:[MWPhoto photoWithImage:imagePreview]];
  188. }
  189. }
  190. }
  191. if ([metadata.typeFile isEqualToString: k_metadataTypeFile_video]) {
  192. if ([CCUtility fileProviderStorageExists:metadata.ocId fileNameView:metadata.fileNameView]) {
  193. NSURL *url = [NSURL fileURLWithPath:[CCUtility getDirectoryProviderStorageOcId:metadata.ocId fileNameView:metadata.fileNameView]];
  194. MWPhoto *video = [MWPhoto photoWithImage:[CCGraphics thumbnailImageForVideo:url atTime:1.0]];
  195. video.videoURL = url;
  196. [self.photos replaceObjectAtIndex:index withObject:video];
  197. } else {
  198. if (metadata.status == k_metadataStatusDownloadError) {
  199. [self.photos replaceObjectAtIndex:index withObject:[MWPhoto photoWithImage:[UIImage imageNamed:@"filePreviewError"]]];
  200. } else {
  201. if (imagePreview)
  202. [self.photos replaceObjectAtIndex:index withObject:[MWPhoto photoWithImage:imagePreview]];
  203. }
  204. }
  205. }
  206. if ([metadata.typeFile isEqualToString: k_metadataTypeFile_audio]) {
  207. if ([CCUtility fileProviderStorageExists:metadata.ocId fileNameView:metadata.fileNameView]) {
  208. MWPhoto *audio;
  209. UIImage *audioImage;
  210. NSURL *url = [NSURL fileURLWithPath:[CCUtility getDirectoryProviderStorageOcId:metadata.ocId fileNameView:metadata.fileNameView]];
  211. if ([[NSFileManager defaultManager] fileExistsAtPath:[CCUtility getDirectoryProviderStorageIconOcId:metadata.ocId fileNameView:metadata.fileNameView]]) {
  212. audioImage = [UIImage imageWithContentsOfFile:[CCUtility getDirectoryProviderStorageIconOcId:metadata.ocId fileNameView:metadata.fileNameView]];
  213. } else {
  214. audioImage = [UIImage imageNamed:@"notaMusic"]; //[CCGraphics scaleImage:[UIImage imageNamed:@"notaMusic"] toSize:CGSizeMake(200, 200) isAspectRation:YES];
  215. }
  216. audio = [MWPhoto photoWithImage:audioImage];
  217. audio.videoURL = url;
  218. [self.photos replaceObjectAtIndex:index withObject:audio];
  219. } else {
  220. if (metadata.status == k_metadataStatusDownloadError) {
  221. [self.photos replaceObjectAtIndex:index withObject:[MWPhoto photoWithImage:[UIImage imageNamed:@"filePreviewError"]]];
  222. } else {
  223. if (imagePreview)
  224. [self.photos replaceObjectAtIndex:index withObject:[MWPhoto photoWithImage:imagePreview]];
  225. }
  226. }
  227. }
  228. }
  229. // energy saving memory
  230. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  231. int iPrev = (int)index - 2;
  232. if (iPrev >= 0) {
  233. if ([self.photos objectAtIndex:iPrev] != nil)
  234. [self.photos replaceObjectAtIndex:iPrev withObject:[MWPhoto photoWithImage:nil]];
  235. }
  236. int iNext = (int)index + 2;
  237. if (iNext < _photos.count) {
  238. if ([self.photos objectAtIndex:iNext] != nil)
  239. [self.photos replaceObjectAtIndex:iNext withObject:[MWPhoto photoWithImage:nil]];
  240. }
  241. });
  242. return [self.photos objectAtIndex:index];
  243. }
  244. return nil;
  245. }
  246. - (void)photoBrowser:(MWPhotoBrowser *)photoBrowser actionButtonPressedForPhotoAtIndex:(NSUInteger)index
  247. {
  248. }
  249. - (void)photoBrowser:(MWPhotoBrowser *)photoBrowser shareButtonPressedForPhotoAtIndex:(NSUInteger)index
  250. {
  251. }
  252. - (void)photoBrowser:(MWPhotoBrowser *)photoBrowser deleteButtonPressedForPhotoAtIndex:(NSUInteger)index deleteButton:(UIBarButtonItem *)deleteButton
  253. {
  254. }
  255. - (void)photoBrowserDidFinishPresentation:(MWPhotoBrowser *)photoBrowser
  256. {
  257. [self.navigationController popViewControllerAnimated:YES];
  258. }
  259. - (void)downloadPhotoBrowserSuccessFailure:(tableMetadata *)metadata selector:(NSString *)selector errorCode:(NSInteger)errorCode
  260. {
  261. // if a message for a directory of these
  262. if (![metadata.ocId isEqualToString:ocIdNowVisible])
  263. return;
  264. // Title
  265. self.navigationItem.titleView = nil;
  266. self.title = metadata.fileNameView;
  267. if (errorCode == 0) {
  268. // verifico se esiste l'icona e se la posso creare
  269. if ([[NSFileManager defaultManager] fileExistsAtPath:[CCUtility getDirectoryProviderStorageIconOcId:metadata.ocId fileNameView:metadata.fileNameView]] == NO) {
  270. [CCGraphics createNewImageFrom:metadata.fileNameView ocId:metadata.ocId extension:[metadata.fileNameView pathExtension] filterGrayScale:NO typeFile:metadata.typeFile writeImage:YES];
  271. }
  272. [self.photoBrowser reloadData];
  273. } else {
  274. [[NCContentPresenter shared] messageNotification:@"_download_selected_files_" description:@"_error_download_photobrowser_" delay:k_dismissAfterSecond type:messageTypeError errorCode:errorCode];
  275. [self.navigationController popViewControllerAnimated:YES];
  276. }
  277. }
  278. - (void)downloadPhotoBrowser:(tableMetadata *)metadata
  279. {
  280. tableMetadata *metadataForDownload = [[NCManageDatabase sharedInstance] initNewMetadata:metadata];
  281. metadataForDownload.session = k_download_session;
  282. metadataForDownload.sessionError = @"";
  283. metadataForDownload.sessionSelector = selectorLoadViewImage;
  284. metadataForDownload.status = k_metadataStatusWaitDownload;
  285. // Add Metadata for Download
  286. (void)[[NCManageDatabase sharedInstance] addMetadata:metadataForDownload];
  287. [[NCMainCommon sharedInstance] reloadDatasourceWithServerUrl:metadata.serverUrl ocId:metadataForDownload.ocId action:k_action_MOD];
  288. [appDelegate startLoadAutoDownloadUpload];
  289. [CCGraphics addImageToTitle:NSLocalizedString(@"_...loading..._", nil) colorTitle:NCBrandColor.sharedInstance.brandText imageTitle:[CCGraphics changeThemingColorImage:[UIImage imageNamed:@"load"] multiplier:2 color:NCBrandColor.sharedInstance.brandText] imageRight:NO navigationItem:self.navigationItem];
  290. }
  291. - (void)insertGeocoderLocation:(NSNotification *)notification
  292. {
  293. if (notification.userInfo.count == 0)
  294. return;
  295. NSString *ocId = [[notification.userInfo allKeys] objectAtIndex:0];
  296. //NSDate *date = [[notification.userInfo allValues] objectAtIndex:0];
  297. // test [Chrash V 1.14,15]
  298. if (indexNowVisible >= [self.photos count])
  299. return;
  300. if ([ocId isEqualToString:ocIdNowVisible]) {
  301. MWPhoto *photo = [self.photos objectAtIndex:indexNowVisible];
  302. [self setLocationCaptionPhoto:photo ocId:ocId];
  303. [self.photoBrowser reloadData];
  304. }
  305. }
  306. - (void)setLocationCaptionPhoto:(MWPhoto *)photo ocId:(NSString *)ocId
  307. {
  308. tableLocalFile *localFile;
  309. // read Geocoder
  310. localFile = [[NCManageDatabase sharedInstance] getTableLocalFileWithPredicate:[NSPredicate predicateWithFormat:@"ocId == %@", ocId]];
  311. if ([localFile.exifLatitude doubleValue] != 0 || [localFile.exifLongitude doubleValue] != 0) {
  312. // Fix BUG Geo latitude & longitude
  313. if ([localFile.exifLatitude doubleValue] == 9999 || [localFile.exifLongitude doubleValue] == 9999) {
  314. tableMetadata *metadata = [[NCManageDatabase sharedInstance] getMetadataWithPredicate:[NSPredicate predicateWithFormat:@"ocId == %@", ocId]];
  315. if (metadata) {
  316. [[CCExifGeo sharedInstance] setExifLocalTableEtag:metadata];
  317. }
  318. }
  319. [[CCExifGeo sharedInstance] setGeocoderEtag:ocId exifDate:localFile.exifDate latitude:localFile.exifLatitude longitude:localFile.exifLongitude];
  320. localFile = [[NCManageDatabase sharedInstance] getTableLocalFileWithPredicate:[NSPredicate predicateWithFormat:@"ocId == %@", ocId]];
  321. if ([localFile.exifLatitude floatValue] != 0 || [localFile.exifLongitude floatValue] != 0) {
  322. NSString *location = [[NCManageDatabase sharedInstance] getLocationFromGeoLatitude:localFile.exifLatitude longitude:localFile.exifLongitude];
  323. if ([localFile.exifDate isEqualToDate:[NSDate distantPast]] == NO && location) {
  324. NSString *localizedDateTime = [NSDateFormatter localizedStringFromDate:localFile.exifDate dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterMediumStyle];
  325. photo.caption = [NSString stringWithFormat:NSLocalizedString(@"%@\n%@", nil), localizedDateTime, location];
  326. }
  327. }
  328. }
  329. }
  330. @end