CCMedia.m 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  1. //
  2. // CCMedia.m
  3. // Nextcloud iOS
  4. //
  5. // Created by Marino Faggiana on 29/07/15.
  6. // Copyright (c) 2017 TWS. All rights reserved.
  7. //
  8. // Author Marino Faggiana <m.faggiana@twsweb.it>
  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 "CCMedia.h"
  24. #import "AppDelegate.h"
  25. #import "CCManageAutoUpload.h"
  26. #import "TOScrollBar.h"
  27. #import "NCBridgeSwift.h"
  28. @interface CCMedia ()
  29. {
  30. AppDelegate *appDelegate;
  31. NSMutableArray *selectedMetadatas;
  32. CCSectionDataSourceMetadata *sectionDataSource;
  33. NSString *saveDirectoryID, *saveServerUrl;
  34. BOOL filterTypeFileImage;
  35. BOOL filterTypeFileVideo;
  36. BOOL isSearchMode;
  37. BOOL isEditMode;
  38. TOScrollBar *scrollBar;
  39. NSMutableDictionary *saveEtagForStartDirectory;
  40. // Fix Crash Thumbnail + collectionView ReloadData ?
  41. NSInteger counterThumbnail;
  42. BOOL collectionViewReloadDataInProgress;
  43. }
  44. @end
  45. @implementation CCMedia
  46. #pragma --------------------------------------------------------------------------------------------
  47. #pragma mark ===== Init =====
  48. #pragma --------------------------------------------------------------------------------------------
  49. - (id)initWithCoder:(NSCoder *)aDecoder
  50. {
  51. if (self = [super initWithCoder:aDecoder]) {
  52. appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  53. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(triggerProgressTask:) name:@"NotificationProgressTask" object:nil];
  54. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeTheming) name:@"changeTheming" object:nil];
  55. appDelegate.activeMedia = self;
  56. }
  57. return self;
  58. }
  59. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
  60. {
  61. self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  62. if (self) {
  63. appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  64. }
  65. return self;
  66. }
  67. #pragma --------------------------------------------------------------------------------------------
  68. #pragma mark ===== View =====
  69. #pragma --------------------------------------------------------------------------------------------
  70. - (void)viewDidLoad
  71. {
  72. [super viewDidLoad];
  73. saveEtagForStartDirectory = [NSMutableDictionary new];
  74. selectedMetadatas = [NSMutableArray new];
  75. self.addMetadatasFromUpload = [NSMutableArray new];
  76. // empty Data Source
  77. self.collectionView.emptyDataSetDelegate = self;
  78. self.collectionView.emptyDataSetSource = self;
  79. // scroll bar
  80. scrollBar = [TOScrollBar new];
  81. [self.collectionView to_addScrollBar:scrollBar];
  82. scrollBar.handleTintColor = [NCBrandColor sharedInstance].brand;
  83. scrollBar.handleWidth = 20;
  84. scrollBar.handleMinimiumHeight = 20;
  85. scrollBar.trackWidth = 0;
  86. scrollBar.edgeInset = 12;
  87. // Query data source
  88. [self queryDatasourceWithReloadData:YES];
  89. }
  90. - (void)viewDidAppear:(BOOL)animated
  91. {
  92. [super viewDidAppear:animated];
  93. // Color
  94. [appDelegate aspectNavigationControllerBar:self.navigationController.navigationBar online:[appDelegate.reachability isReachable] hidden:NO];
  95. [appDelegate aspectTabBar:self.tabBarController.tabBar hidden:NO];
  96. // Plus Button
  97. [appDelegate plusButtonVisibile:true];
  98. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.001 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) {
  99. [self reloadDatasource:nil action:k_action_NULL];
  100. });
  101. }
  102. - (void)viewSafeAreaInsetsDidChange
  103. {
  104. [super viewSafeAreaInsetsDidChange];
  105. self.collectionView.contentInset = self.view.safeAreaInsets;
  106. }
  107. - (void)changeTheming
  108. {
  109. if (self.isViewLoaded && self.view.window)
  110. [appDelegate changeTheming:self];
  111. scrollBar.handleTintColor = [NCBrandColor sharedInstance].brand;
  112. [self.collectionView reloadData];
  113. }
  114. - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
  115. {
  116. [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
  117. // Before rotation
  118. [coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
  119. if (self.view.frame.size.width == ([[UIScreen mainScreen] bounds].size.width*([[UIScreen mainScreen] bounds].size.width<[[UIScreen mainScreen] bounds].size.height))+([[UIScreen mainScreen] bounds].size.height*([[UIScreen mainScreen] bounds].size.width>[[UIScreen mainScreen] bounds].size.height))) {
  120. // Portrait
  121. } else {
  122. // Landscape
  123. }
  124. }];
  125. }
  126. #pragma --------------------------------------------------------------------------------------------
  127. #pragma mark ===== Gestione Grafica Window =====
  128. #pragma --------------------------------------------------------------------------------------------
  129. - (void)setUINavigationBarDefault
  130. {
  131. [appDelegate aspectNavigationControllerBar:self.navigationController.navigationBar online:[appDelegate.reachability isReachable] hidden:NO];
  132. // curront folder search
  133. NSString *directory = [[NCManageDatabase sharedInstance] getAccountStartDirectoryMediaTabView:[CCUtility getHomeServerUrlActiveUrl:appDelegate.activeUrl]];
  134. NSString *home = [CCUtility getHomeServerUrlActiveUrl:appDelegate.activeUrl];
  135. NSString *folder = @"";
  136. if (home.length > 0) {
  137. folder = [directory stringByReplacingOccurrencesOfString:home withString:@""];
  138. }
  139. // Title
  140. NSString *title;
  141. if (folder.length == 0) {
  142. title = NSLocalizedString(@"_media_", nil);
  143. } else {
  144. title = [NSString stringWithFormat:@"%@: %@", NSLocalizedString(@"_media_", nil), [folder substringFromIndex:1]];
  145. }
  146. self.navigationItem.titleView = nil;
  147. self.navigationItem.title = title;
  148. if (isSearchMode) {
  149. [CCGraphics addImageToTitle:title colorTitle:[NCBrandColor sharedInstance].brandText imageTitle:[CCGraphics changeThemingColorImage:[UIImage imageNamed:@"load"] multiplier:2 color:[NCBrandColor sharedInstance].brandText] imageRight:YES navigationItem:self.navigationItem];
  150. }
  151. // Button Item RIGHT
  152. UIBarButtonItem *buttonSelect = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"select"] style:UIBarButtonItemStylePlain target:self action:@selector(editingModeYES)];
  153. if ([sectionDataSource.allRecordsDataSource count] > 0) {
  154. self.navigationItem.rightBarButtonItems = [[NSArray alloc] initWithObjects:buttonSelect, nil];
  155. } else {
  156. self.navigationItem.rightBarButtonItems = nil;
  157. }
  158. // Button Item LEFT
  159. UIBarButtonItem *buttonStartDirectoryPhotosTab = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"folderMedia"] style:UIBarButtonItemStylePlain target:self action:@selector(selectStartDirectoryPhotosTab)];
  160. UIBarButtonItem *buttonImageFilterYesPhotosTab = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"imageno"] style:UIBarButtonItemStylePlain target:self action:@selector(buttonVideoFilterYes)];
  161. UIBarButtonItem *buttonImageFilterNoPhotosTab = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"imageyes"] style:UIBarButtonItemStylePlain target:self action:@selector(buttonVideoFilterNo)];
  162. UIBarButtonItem *buttonVideoFilterYesPhotosTab = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"videono"] style:UIBarButtonItemStylePlain target:self action:@selector(buttonImageFilterNo)];
  163. UIBarButtonItem *buttonVideoFilterNoPhotosTab = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"videoyes"] style:UIBarButtonItemStylePlain target:self action:@selector(buttonImageFilterYes)];
  164. if (filterTypeFileImage && filterTypeFileVideo) {
  165. self.navigationItem.leftBarButtonItems = [[NSArray alloc] initWithObjects:buttonStartDirectoryPhotosTab, buttonImageFilterYesPhotosTab, buttonVideoFilterYesPhotosTab,nil];
  166. } else if (filterTypeFileImage) {
  167. self.navigationItem.leftBarButtonItems = [[NSArray alloc] initWithObjects:buttonStartDirectoryPhotosTab, buttonImageFilterYesPhotosTab, buttonVideoFilterNoPhotosTab,nil];
  168. } else if (filterTypeFileVideo) {
  169. self.navigationItem.leftBarButtonItems = [[NSArray alloc] initWithObjects:buttonStartDirectoryPhotosTab, buttonImageFilterNoPhotosTab, buttonVideoFilterYesPhotosTab,nil];
  170. } else {
  171. self.navigationItem.leftBarButtonItems = [[NSArray alloc] initWithObjects:buttonStartDirectoryPhotosTab, buttonImageFilterNoPhotosTab, buttonVideoFilterNoPhotosTab,nil];
  172. }
  173. }
  174. - (void)setUINavigationBarSelected
  175. {
  176. UIBarButtonItem *buttonDelete = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"delete"] style:UIBarButtonItemStylePlain target:self action:@selector(deleteSelectedFiles)];
  177. // UIBarButtonItem *buttonOpenIn = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"openFile"] style:UIBarButtonItemStylePlain target:self action:@selector(openSelectedFiles)];
  178. UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"_cancel_", nil) style:UIBarButtonItemStylePlain target:self action:@selector(editingModeNO)];
  179. self.navigationItem.rightBarButtonItems = [[NSArray alloc] initWithObjects:cancelButton, nil];
  180. self.navigationItem.leftBarButtonItems = [[NSArray alloc] initWithObjects:buttonDelete, nil];
  181. // Title
  182. self.navigationItem.title = [NSString stringWithFormat:@"%@ : %lu / %lu", NSLocalizedString(@"_selected_", nil), (unsigned long)[selectedMetadatas count], (unsigned long)[sectionDataSource.allRecordsDataSource count]];
  183. }
  184. - (void)cellSelect:(BOOL)select indexPath:(NSIndexPath *)indexPath metadata:(tableMetadata *)metadata
  185. {
  186. UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
  187. UIVisualEffectView *effect = [cell viewWithTag:200];
  188. UIImageView *checked = [cell viewWithTag:300];
  189. if (select) {
  190. effect.hidden = NO;
  191. effect.alpha = 0.4;
  192. checked.hidden = NO;
  193. [selectedMetadatas addObject:metadata];
  194. } else {
  195. effect.hidden = YES;
  196. checked.hidden = YES;
  197. [selectedMetadatas removeObject:metadata];
  198. }
  199. // Title
  200. self.navigationItem.title = [NSString stringWithFormat:@"%@ : %lu / %lu", NSLocalizedString(@"_selected_", nil), (unsigned long)[selectedMetadatas count], (unsigned long)[sectionDataSource.allRecordsDataSource count]];
  201. }
  202. - (void)scrollToTop
  203. {
  204. [self.collectionView setContentOffset:CGPointMake(0, - self.collectionView.contentInset.top) animated:NO];
  205. }
  206. - (void)getGeoLocationForSection:(NSInteger)section
  207. {
  208. NSString *addLocation = @"";
  209. NSArray *fileIDsForKey = [sectionDataSource.sectionArrayRow objectForKey:[sectionDataSource.sections objectAtIndex:section]];
  210. for (NSString *fileID in fileIDsForKey) {
  211. tableLocalFile *localFile = [[NCManageDatabase sharedInstance] getTableLocalFileWithPredicate:[NSPredicate predicateWithFormat:@"fileID == %@", fileID]];
  212. if ([localFile.exifLatitude floatValue] > 0 || [localFile.exifLongitude floatValue] > 0) {
  213. NSString *location = [[NCManageDatabase sharedInstance] getLocationFromGeoLatitude:localFile.exifLatitude longitude:localFile.exifLongitude];
  214. addLocation = [NSString stringWithFormat:@"%@, %@", addLocation, location];
  215. }
  216. }
  217. }
  218. #pragma --------------------------------------------------------------------------------------------
  219. #pragma mark ==== DZNEmptyDataSetSource Methods ====
  220. #pragma --------------------------------------------------------------------------------------------
  221. - (UIColor *)backgroundColorForEmptyDataSet:(UIScrollView *)scrollView
  222. {
  223. return [NCBrandColor sharedInstance].backgroundView;
  224. }
  225. - (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView
  226. {
  227. return [CCGraphics changeThemingColorImage:[UIImage imageNamed:@"mediaNoRecord"] multiplier:2 color:[NCBrandColor sharedInstance].graySoft];
  228. }
  229. - (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView
  230. {
  231. NSString *text;
  232. if (isSearchMode) {
  233. text = [NSString stringWithFormat:@"\n%@", NSLocalizedString(@"_search_in_progress_", nil)];
  234. } else {
  235. text = [NSString stringWithFormat:@"\n%@", NSLocalizedString(@"_tutorial_photo_view_", nil)];
  236. }
  237. NSDictionary *attributes = @{NSFontAttributeName:[UIFont boldSystemFontOfSize:20.0f], NSForegroundColorAttributeName:[UIColor lightGrayColor]};
  238. return [[NSAttributedString alloc] initWithString:text attributes:attributes];
  239. }
  240. /*
  241. #pragma --------------------------------------------------------------------------------------------
  242. #pragma mark ===== openSelectedFiles =====
  243. #pragma--------------------------------------------------------------------------------------------
  244. - (void)openSelectedFiles
  245. {
  246. NSMutableArray *dataToShare = [[NSMutableArray alloc] init];
  247. for (tableMetadata *metadata in selectedMetadatas) {
  248. NSString *fileNamePath = [CCUtility getDirectoryProviderStorageFileID:metadata.fileID fileName:metadata.fileNameView];
  249. if ([CCUtility fileProviderStorageExists:metadata.fileID fileName:metadata.fileNameView]) {
  250. if ([metadata.typeFile isEqualToString: k_metadataTypeFile_image]) {
  251. NSData *data = [NSData dataWithData:UIImageJPEGRepresentation([UIImage imageWithContentsOfFile:fileNamePath], 0.9)];
  252. [dataToShare addObject:data];
  253. }
  254. if ([metadata.typeFile isEqualToString: k_metadataTypeFile_video]) {
  255. [dataToShare addObject:[NSURL fileURLWithPath:fileNamePath]];
  256. }
  257. }
  258. }
  259. if ([dataToShare count] > 0) {
  260. UIActivityViewController* activityViewController = [[UIActivityViewController alloc] initWithActivityItems:dataToShare applicationActivities:nil];
  261. // iPad
  262. activityViewController.popoverPresentationController.barButtonItem = self.navigationItem.rightBarButtonItems.lastObject;
  263. self.navigationItem.leftBarButtonItem.enabled = NO;
  264. self.navigationItem.rightBarButtonItem.enabled = NO;
  265. [self presentViewController:activityViewController animated:YES completion:^{
  266. [activityViewController setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
  267. self.navigationItem.leftBarButtonItem.enabled = YES;
  268. self.navigationItem.rightBarButtonItem.enabled = YES;
  269. [self editingModeNO];
  270. if (completed) {
  271. [self.collectionView reloadData];
  272. }
  273. }];
  274. }];
  275. }
  276. }
  277. */
  278. #pragma --------------------------------------------------------------------------------------------
  279. #pragma mark ===== Download =====
  280. #pragma--------------------------------------------------------------------------------------------
  281. - (void)triggerProgressTask:(NSNotification *)notification
  282. {
  283. //NSDictionary *dict = notification.userInfo;
  284. //float progress = [[dict valueForKey:@"progress"] floatValue];
  285. }
  286. - (void)downloadFileSuccessFailure:(NSString *)fileName fileID:(NSString *)fileID serverUrl:(NSString *)serverUrl selector:(NSString *)selector errorMessage:(NSString *)errorMessage errorCode:(NSInteger)errorCode
  287. {
  288. if (errorCode == 0) {
  289. NSIndexPath *indexPath;
  290. BOOL existsIcon = NO;
  291. if (fileID) {
  292. existsIcon = [[NSFileManager defaultManager] fileExistsAtPath:[CCUtility getDirectoryProviderStorageIconFileID:fileID fileNameView:fileName]];
  293. indexPath = [sectionDataSource.fileIDIndexPath objectForKey:fileID];
  294. }
  295. if ([self indexPathIsValid:indexPath] && existsIcon) {
  296. UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
  297. if (cell) {
  298. UIImageView *imageView = (UIImageView *)[cell viewWithTag:100];
  299. UIVisualEffectView *effect = [cell viewWithTag:200];
  300. UIImageView *checked = [cell viewWithTag:300];
  301. imageView.image = [UIImage imageWithContentsOfFile:[CCUtility getDirectoryProviderStorageIconFileID:fileID fileNameView:fileName]];
  302. effect.hidden = YES;
  303. checked.hidden = YES;
  304. }
  305. }
  306. } else {
  307. [appDelegate messageNotification:@"_download_selected_files_" description:@"_error_download_photobrowser_" visible:YES delay:k_dismissAfterSecond type:TWMessageBarMessageTypeError errorCode:errorCode];
  308. }
  309. }
  310. #pragma --------------------------------------------------------------------------------------------
  311. #pragma mark ===== Delete =====
  312. #pragma--------------------------------------------------------------------------------------------
  313. - (void)deleteFile:(NSArray *)metadatas e2ee:(BOOL)e2ee
  314. {
  315. [[NCMainCommon sharedInstance ] deleteFileWithMetadatas:metadatas e2ee:false serverUrl:@"" folderFileID:@"" completion:^(NSInteger errorCode, NSString *message) {
  316. [[NCMainCommon sharedInstance] reloadDatasourceWithServerUrl:nil fileID:nil action:k_action_NULL];
  317. }];
  318. [self editingModeNO];
  319. }
  320. - (void)deleteSelectedFiles
  321. {
  322. if ([selectedMetadatas count] == 0)
  323. return;
  324. UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
  325. [alertController addAction: [UIAlertAction actionWithTitle:NSLocalizedString(@"_delete_", nil)
  326. style:UIAlertActionStyleDestructive
  327. handler:^(UIAlertAction *action) {
  328. [self deleteFile:selectedMetadatas e2ee:false];
  329. }]];
  330. [alertController addAction: [UIAlertAction actionWithTitle:NSLocalizedString(@"_cancel_", nil)
  331. style:UIAlertActionStyleCancel
  332. handler:^(UIAlertAction *action) {
  333. }]];
  334. alertController.popoverPresentationController.barButtonItem = self.navigationItem.leftBarButtonItems.firstObject;
  335. if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
  336. [alertController.view layoutIfNeeded];
  337. [self presentViewController:alertController animated:YES completion:NULL];
  338. }
  339. #pragma --------------------------------------------------------------------------------------------
  340. #pragma mark ==== Download Thumbnail ====
  341. #pragma --------------------------------------------------------------------------------------------
  342. - (void)downloadThumbnail:(tableMetadata *)metadata indexPath:(NSIndexPath *)indexPath
  343. {
  344. if (![saveDirectoryID isEqualToString:metadata.directoryID]) {
  345. saveDirectoryID = metadata.directoryID;
  346. saveServerUrl = [[NCManageDatabase sharedInstance] getServerUrl:metadata.directoryID];
  347. if (!saveServerUrl)
  348. return;
  349. }
  350. counterThumbnail++;
  351. CGFloat width = [[NCUtility sharedInstance] getScreenWidthForPreview];
  352. CGFloat height = [[NCUtility sharedInstance] getScreenHeightForPreview];
  353. OCnetworking *ocNetworking = [[OCnetworking alloc] initWithDelegate:nil metadataNet:nil withUser:appDelegate.activeUser withUserID:appDelegate.activeUserID withPassword:appDelegate.activePassword withUrl:appDelegate.activeUrl];
  354. [ocNetworking downloadPreviewWithMetadata:metadata serverUrl:saveServerUrl withWidth:width andHeight:height completion:^(NSString *message, NSInteger errorCode) {
  355. counterThumbnail--;
  356. if (errorCode == 0 && [[NSFileManager defaultManager] fileExistsAtPath:[CCUtility getDirectoryProviderStorageIconFileID:metadata.fileID fileNameView:metadata.fileNameView]] && [self indexPathIsValid:indexPath] && !collectionViewReloadDataInProgress) {
  357. [self.collectionView reloadItemsAtIndexPaths:@[indexPath]];
  358. }
  359. }];
  360. }
  361. #pragma --------------------------------------------------------------------------------------------
  362. #pragma mark ==== Change Start directory ====
  363. #pragma --------------------------------------------------------------------------------------------
  364. - (void)moveServerUrlTo:(NSString *)serverUrlTo title:(NSString *)title
  365. {
  366. NSString *oldStartDirectoryMediaTabView = [[NCManageDatabase sharedInstance] getAccountStartDirectoryMediaTabView:[CCUtility getHomeServerUrlActiveUrl:appDelegate.activeUrl]];
  367. if (![serverUrlTo isEqualToString:oldStartDirectoryMediaTabView]) {
  368. // Save Start Directory
  369. [[NCManageDatabase sharedInstance] setAccountStartDirectoryMediaTabView:serverUrlTo];
  370. // search PhotoVideo with new start directory
  371. [self searchPhotoVideo];
  372. }
  373. }
  374. - (void)selectStartDirectoryPhotosTab
  375. {
  376. UINavigationController* navigationController = [[UIStoryboard storyboardWithName:@"CCMove" bundle:nil] instantiateViewControllerWithIdentifier:@"CCMove"];
  377. CCMove *viewController = (CCMove *)navigationController.topViewController;
  378. viewController.delegate = self;
  379. viewController.move.title = NSLocalizedString(@"_select_dir_media_tab_", nil);
  380. viewController.tintColor = [NCBrandColor sharedInstance].brandText;
  381. viewController.barTintColor = [NCBrandColor sharedInstance].brand;
  382. viewController.tintColorTitle = [NCBrandColor sharedInstance].brandText;
  383. viewController.networkingOperationQueue = appDelegate.netQueue;
  384. viewController.hideCreateFolder = YES;
  385. // E2EE
  386. viewController.includeDirectoryE2EEncryption = NO;
  387. [navigationController setModalPresentationStyle:UIModalPresentationFormSheet];
  388. [self presentViewController:navigationController animated:YES completion:nil];
  389. }
  390. #pragma --------------------------------------------------------------------------------------------
  391. #pragma mark ==== Filter Image Video====
  392. #pragma --------------------------------------------------------------------------------------------
  393. - (void)buttonImageFilterYes
  394. {
  395. filterTypeFileImage = !filterTypeFileImage;
  396. [self reloadDatasource:nil action:k_action_NULL];
  397. }
  398. - (void)buttonImageFilterNo
  399. {
  400. if (filterTypeFileVideo) {
  401. filterTypeFileVideo = NO;
  402. } else {
  403. filterTypeFileImage = !filterTypeFileImage;
  404. }
  405. [self reloadDatasource:nil action:k_action_NULL];
  406. }
  407. - (void)buttonVideoFilterYes
  408. {
  409. if (filterTypeFileImage) {
  410. filterTypeFileImage = NO;
  411. } else {
  412. filterTypeFileVideo = !filterTypeFileVideo;
  413. }
  414. [self reloadDatasource:nil action:k_action_NULL];
  415. }
  416. - (void)buttonVideoFilterNo
  417. {
  418. filterTypeFileVideo = !filterTypeFileVideo;
  419. [self reloadDatasource:nil action:k_action_NULL];
  420. }
  421. #pragma --------------------------------------------------------------------------------------------
  422. #pragma mark ==== Search Photo/Video ====
  423. #pragma --------------------------------------------------------------------------------------------
  424. - (void)searchSuccessFailure:(CCMetadataNet *)metadataNet metadatas:(NSArray *)metadatas message:(NSString *)message errorCode:(NSInteger)errorCode
  425. {
  426. isSearchMode = NO;
  427. if (![metadataNet.account isEqualToString:appDelegate.activeAccount] || errorCode != 0) {
  428. [self reloadDatasource:nil action:k_action_NULL];
  429. } else {
  430. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
  431. // Clear all Hardcoded new foto/video from CCNetworking
  432. [self.addMetadatasFromUpload removeAllObjects];
  433. [[NCManageDatabase sharedInstance] createTablePhotos:metadatas];
  434. dispatch_async(dispatch_get_main_queue(), ^{
  435. [self reloadDatasource:nil action:k_action_NULL];
  436. });
  437. // Update date
  438. [[NCManageDatabase sharedInstance] setAccountDateSearchContentTypeImageVideo:[NSDate date]];
  439. // Save etag
  440. [saveEtagForStartDirectory setObject:metadataNet.etag forKey:metadataNet.serverUrl];
  441. });
  442. }
  443. }
  444. - (void)searchPhotoVideo
  445. {
  446. // test
  447. if (appDelegate.activeAccount.length == 0 || isSearchMode)
  448. return;
  449. // WAITING FOR d:creationdate
  450. //
  451. // tableAccount *account = [[NCManageDatabase sharedInstance] getAccountActive];
  452. // account.dateSearchContentTypeImageVideo
  453. NSString *startDirectory = [[NCManageDatabase sharedInstance] getAccountStartDirectoryMediaTabView:[CCUtility getHomeServerUrlActiveUrl:appDelegate.activeUrl]];
  454. OCnetworking *ocNetworking = [[OCnetworking alloc] initWithDelegate:self metadataNet:nil withUser:appDelegate.activeUser withUserID:appDelegate.activeUserID withPassword:appDelegate.activePassword withUrl:appDelegate.activeUrl];
  455. [ocNetworking readFile:nil serverUrl:startDirectory account:appDelegate.activeAccount success:^(tableMetadata *metadata) {
  456. if (![metadata.etag isEqualToString:[saveEtagForStartDirectory objectForKey:startDirectory]] || sectionDataSource.allRecordsDataSource.count == 0) {
  457. isSearchMode = YES;
  458. [self editingModeNO];
  459. [[CCActions sharedInstance] search:startDirectory fileName:@"" etag:metadata.etag depth:@"infinity" date:[NSDate distantPast] contenType:@[@"image/%", @"video/%"] selector:selectorSearchContentType delegate:self];
  460. } else {
  461. [self reloadDatasource:nil action:k_action_NULL];
  462. }
  463. } failure:^(NSString *message, NSInteger errorCode) {
  464. }];
  465. }
  466. #pragma --------------------------------------------------------------------------------------------
  467. #pragma mark ==== Datasource ====
  468. #pragma --------------------------------------------------------------------------------------------
  469. - (void)reloadDatasource:(NSString *)fileID action:(NSInteger)action
  470. {
  471. // test
  472. if (appDelegate.activeAccount.length == 0 || self.view.window == nil) {
  473. return;
  474. }
  475. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  476. collectionViewReloadDataInProgress = YES;
  477. CCSectionDataSourceMetadata *sectionDataSourceTemp = [self queryDatasourceWithReloadData:NO];
  478. dispatch_async(dispatch_get_main_queue(), ^{
  479. if (isEditMode)
  480. [self setUINavigationBarSelected];
  481. else
  482. [self setUINavigationBarDefault];
  483. sectionDataSource = sectionDataSourceTemp;
  484. [self.collectionView reloadData];
  485. [self.collectionView performBatchUpdates:^{} completion:^(BOOL finished) {
  486. collectionViewReloadDataInProgress = NO;
  487. }];
  488. });
  489. });
  490. }
  491. - (CCSectionDataSourceMetadata *)queryDatasourceWithReloadData:(BOOL)withReloadData
  492. {
  493. // test
  494. if (appDelegate.activeAccount.length == 0) {
  495. return nil;
  496. }
  497. CCSectionDataSourceMetadata *sectionDataSourceTemp = [CCSectionDataSourceMetadata new];
  498. NSArray *metadatas = [[NCManageDatabase sharedInstance] getTablePhotosWithAddMetadatasFromUpload:self.addMetadatasFromUpload];
  499. sectionDataSourceTemp = [CCSectionMetadata creataDataSourseSectionMetadata:metadatas listProgressMetadata:nil groupByField:@"date" filterFileID:appDelegate.filterFileID filterTypeFileImage:filterTypeFileImage filterTypeFileVideo:filterTypeFileVideo activeAccount:appDelegate.activeAccount];
  500. if (withReloadData) {
  501. sectionDataSource = sectionDataSourceTemp;
  502. [self.collectionView reloadData];
  503. }
  504. return sectionDataSourceTemp;
  505. }
  506. - (void)editingModeYES
  507. {
  508. [self.collectionView setAllowsMultipleSelection:true];
  509. isEditMode = true;
  510. [selectedMetadatas removeAllObjects];
  511. [self setUINavigationBarSelected];
  512. collectionViewReloadDataInProgress = YES;
  513. [self.collectionView reloadData];
  514. [self.collectionView performBatchUpdates:^{} completion:^(BOOL finished) {
  515. collectionViewReloadDataInProgress = NO;
  516. }];
  517. }
  518. - (void)editingModeNO
  519. {
  520. [self.collectionView setAllowsMultipleSelection:false];
  521. isEditMode = false;
  522. [selectedMetadatas removeAllObjects];
  523. [self setUINavigationBarDefault];
  524. collectionViewReloadDataInProgress = YES;
  525. [self.collectionView reloadData];
  526. [self.collectionView performBatchUpdates:^{} completion:^(BOOL finished) {
  527. collectionViewReloadDataInProgress = NO;
  528. }];
  529. }
  530. #pragma --------------------------------------------------------------------------------------------
  531. #pragma mark ==== Collection ====
  532. #pragma --------------------------------------------------------------------------------------------
  533. - (BOOL)indexPathIsValid:(NSIndexPath *)indexPath
  534. {
  535. return indexPath.section < [self numberOfSectionsInCollectionView:self.collectionView] && indexPath.row < [self collectionView:self.collectionView numberOfItemsInSection:indexPath.section];
  536. }
  537. - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
  538. {
  539. return [[sectionDataSource.sectionArrayRow allKeys] count];
  540. }
  541. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
  542. {
  543. return [[sectionDataSource.sectionArrayRow objectForKey:[sectionDataSource.sections objectAtIndex:section]] count];
  544. }
  545. - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
  546. {
  547. UIInterfaceOrientation orientationOnLunch = [[UIApplication sharedApplication] statusBarOrientation];
  548. if (orientationOnLunch == UIInterfaceOrientationPortrait)
  549. return CGSizeMake(collectionView.frame.size.width / 5.1f, collectionView.frame.size.width / 5.1f);
  550. else
  551. return CGSizeMake(collectionView.frame.size.width / 7.1f, collectionView.frame.size.width / 7.1f);
  552. }
  553. -(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section
  554. {
  555. if ([sectionDataSource.sections count] - 1 == section)
  556. return CGSizeMake(collectionView.frame.size.width, 50);
  557. return CGSizeZero;
  558. }
  559. - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
  560. {
  561. if (kind == UICollectionElementKindSectionHeader) {
  562. UICollectionReusableView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"header" forIndexPath:indexPath];
  563. //headerView.backgroundColor = COLOR_GROUPBY_BAR_NO_BLUR;
  564. [self getGeoLocationForSection:indexPath.section];
  565. UILabel *titleLabel = (UILabel *)[headerView viewWithTag:100];
  566. titleLabel.textColor = [UIColor blackColor];
  567. if (sectionDataSource.sections.count > indexPath.section)
  568. titleLabel.text = [CCUtility getTitleSectionDate:[sectionDataSource.sections objectAtIndex:indexPath.section]];
  569. return headerView;
  570. }
  571. if (kind == UICollectionElementKindSectionFooter) {
  572. UICollectionReusableView *footerView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"footer" forIndexPath:indexPath];
  573. UILabel *titleLabel = (UILabel *)[footerView viewWithTag:100];
  574. titleLabel.textColor = [UIColor grayColor];
  575. titleLabel.text = [NSString stringWithFormat:@"%lu %@, %lu %@", (long)sectionDataSource.image, NSLocalizedString(@"photo", nil), (long)sectionDataSource.video, NSLocalizedString(@"_video_", nil)];
  576. return footerView;
  577. }
  578. return nil;
  579. }
  580. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
  581. {
  582. UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
  583. UIImageView *imageView = (UIImageView *)[cell viewWithTag:100];
  584. UIVisualEffectView *effect = [cell viewWithTag:200];
  585. UIImageView *checkedOverlay = [cell viewWithTag:300];
  586. checkedOverlay.image = [UIImage imageNamed:@"checked"];
  587. UIImageView *videoOverlay = [cell viewWithTag:400];
  588. videoOverlay.image = [UIImage imageNamed:@"VideoOverlay"];
  589. NSArray *metadatasForKey = [sectionDataSource.sectionArrayRow objectForKey:[sectionDataSource.sections objectAtIndex:indexPath.section]];
  590. if ([metadatasForKey count] > indexPath.row) {
  591. NSString *fileID = [metadatasForKey objectAtIndex:indexPath.row];
  592. tableMetadata *metadata = [sectionDataSource.allRecordsDataSource objectForKey:fileID];
  593. // Image
  594. if ([[NSFileManager defaultManager] fileExistsAtPath:[CCUtility getDirectoryProviderStorageIconFileID:metadata.fileID fileNameView:metadata.fileNameView]]) {
  595. // insert Image
  596. imageView.image = [UIImage imageWithContentsOfFile:[CCUtility getDirectoryProviderStorageIconFileID:metadata.fileID fileNameView:metadata.fileNameView]];
  597. } else {
  598. imageView.image = [UIImage imageNamed:@"file_photo"];
  599. if (metadata.thumbnailExists && ![CCUtility fileProviderStorageIconExists:metadata.fileID fileNameView:metadata.fileNameView]) {
  600. [self downloadThumbnail:metadata indexPath:indexPath];
  601. }
  602. }
  603. // Cheched Overlay
  604. if (cell.selected) {
  605. checkedOverlay.hidden = NO;
  606. effect.hidden = NO;
  607. effect.alpha = 0.4;
  608. } else {
  609. checkedOverlay.hidden = YES;
  610. effect.hidden = YES;
  611. }
  612. // Video Overlay
  613. if ([metadata.typeFile isEqualToString: k_metadataTypeFile_video]) {
  614. videoOverlay.hidden = NO;
  615. } else {
  616. videoOverlay.hidden = YES;
  617. }
  618. }
  619. return cell;
  620. }
  621. - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
  622. {
  623. NSArray *metadatasForKey = [sectionDataSource.sectionArrayRow objectForKey:[sectionDataSource.sections objectAtIndex:indexPath.section]];
  624. if ([metadatasForKey count] > indexPath.row) {
  625. NSString *fileID = [metadatasForKey objectAtIndex:indexPath.row];
  626. self.metadata = [sectionDataSource.allRecordsDataSource objectForKey:fileID];
  627. if (isEditMode) {
  628. [self cellSelect:YES indexPath:indexPath metadata:self.metadata];
  629. } else {
  630. if ([self shouldPerformSegue])
  631. [self performSegueWithIdentifier:@"segueDetail" sender:self];
  632. }
  633. }
  634. }
  635. - (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
  636. {
  637. // test
  638. if (isEditMode == NO)
  639. return;
  640. NSArray *metadatasForKey = [sectionDataSource.sectionArrayRow objectForKey:[sectionDataSource.sections objectAtIndex:indexPath.section]];
  641. if ([metadatasForKey count] > indexPath.row) {
  642. NSString *fileID = [metadatasForKey objectAtIndex:indexPath.row];
  643. self.metadata = [sectionDataSource.allRecordsDataSource objectForKey:fileID];
  644. [self cellSelect:NO indexPath:indexPath metadata:self.metadata];
  645. }
  646. }
  647. #pragma --------------------------------------------------------------------------------------------
  648. #pragma mark ===== Navigation ====
  649. #pragma --------------------------------------------------------------------------------------------
  650. - (BOOL)shouldPerformSegue
  651. {
  652. if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground)
  653. return NO;
  654. // Not in first plain ? exit
  655. if (self.view.window == NO)
  656. return NO;
  657. // Collapsed but in first plain in detail exit
  658. if (self.splitViewController.isCollapsed)
  659. if (self.detailViewController.isViewLoaded && self.detailViewController.view.window)
  660. return NO;
  661. // check if metadata is invalidated
  662. if ([[NCManageDatabase sharedInstance] isTableInvalidated:self.metadata]) {
  663. return NO;
  664. }
  665. // ok perform segue
  666. return YES;
  667. }
  668. -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
  669. {
  670. id controller = segue.destinationViewController;
  671. if ([controller isKindOfClass:[UINavigationController class]]) {
  672. UINavigationController *navigationController = controller;
  673. self.detailViewController = (CCDetail *)navigationController.topViewController;
  674. } else {
  675. self.detailViewController = segue.destinationViewController;
  676. }
  677. NSMutableArray *photoDataSource = [NSMutableArray new];
  678. for (NSString *fileID in sectionDataSource.allFileID) {
  679. tableMetadata *metadata = [sectionDataSource.allRecordsDataSource objectForKey:fileID];
  680. if ([metadata.typeFile isEqualToString: k_metadataTypeFile_image])
  681. [photoDataSource addObject:metadata];
  682. }
  683. self.detailViewController.photoDataSource = photoDataSource;
  684. self.detailViewController.metadataDetail = self.metadata;
  685. self.detailViewController.dateFilterQuery = self.metadata.date;
  686. [self.detailViewController setTitle:self.metadata.fileName];
  687. }
  688. @end