CCSection.m 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. //
  2. // CCSection.m
  3. // Nextcloud
  4. //
  5. // Created by Marino Faggiana on 04/02/16.
  6. // Copyright (c) 2016 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 "CCSection.h"
  24. #import "CCExifGeo.h"
  25. #import "NCBridgeSwift.h"
  26. @implementation CCSectionDataSourceMetadata
  27. - (id)init {
  28. self = [super init];
  29. _allRecordsDataSource = [[NSMutableDictionary alloc] init];
  30. _allOcId = [[NSMutableArray alloc] init];
  31. _sections = [[NSMutableArray alloc] init];
  32. _sectionArrayRow = [[NSMutableDictionary alloc] init];
  33. _ocIdIndexPath = [[NSMutableDictionary alloc] init];
  34. _metadatas = [NSMutableArray new];
  35. _image = 0;
  36. _video = 0;
  37. _directories = 0;
  38. _files = 0;
  39. _totalSize = 0;
  40. return self;
  41. }
  42. - (id)copyWithZone: (NSZone *) zone
  43. {
  44. CCSectionDataSourceMetadata *sectionDataSourceMetadata = [[CCSectionDataSourceMetadata allocWithZone: zone] init];
  45. [sectionDataSourceMetadata setAllRecordsDataSource: self.allRecordsDataSource];
  46. [sectionDataSourceMetadata setAllOcId: self.allOcId];
  47. [sectionDataSourceMetadata setSections: self.sections];
  48. [sectionDataSourceMetadata setSectionArrayRow: self.sectionArrayRow];
  49. [sectionDataSourceMetadata setOcIdIndexPath: self.ocIdIndexPath];
  50. [sectionDataSourceMetadata setMetadatas: self.metadatas];
  51. [sectionDataSourceMetadata setVideo: self.video];
  52. [sectionDataSourceMetadata setImage: self.image];
  53. [sectionDataSourceMetadata setDirectories: self.directories];
  54. [sectionDataSourceMetadata setFiles: self.files];
  55. [sectionDataSourceMetadata setTotalSize: self.totalSize];
  56. return sectionDataSourceMetadata;
  57. }
  58. @end
  59. @implementation CCSectionMetadata
  60. //
  61. // orderByField : nil, date, typeFile
  62. //
  63. + (CCSectionDataSourceMetadata *)creataDataSourseSectionMetadata:(NSArray *)arrayMetadatas listProgressMetadata:(NSMutableDictionary *)listProgressMetadata groupBy:(NSString *)groupBy filterTypeFileImage:(BOOL)filterTypeFileImage filterTypeFileVideo:(BOOL)filterTypeFileVideo filterLivePhoto:(BOOL)filterLivePhoto sort:(NSString *)sort ascending:(BOOL)ascending directoryOnTop:(BOOL)directoryOnTop account:(NSString *)account
  64. {
  65. id dataSection;
  66. NSMutableDictionary *dictionaryEtagMetadataForIndexPath = [NSMutableDictionary new];
  67. CCSectionDataSourceMetadata *sectionDataSource = [CCSectionDataSourceMetadata new];
  68. NSArray *arraySoprtedMetadatas;
  69. NSMutableArray *filterocId = [NSMutableArray new];
  70. /*
  71. Live Photo
  72. */
  73. if ([CCUtility getLivePhoto] && filterLivePhoto) {
  74. for (tableMetadata *metadata in arrayMetadatas) {
  75. if ([metadata.ext isEqualToString:@"mov"] && metadata.livePhoto) {
  76. [filterocId addObject:metadata.ocId];
  77. }
  78. }
  79. }
  80. /*
  81. Metadata order
  82. */
  83. arraySoprtedMetadatas = [arrayMetadatas sortedArrayUsingComparator:^NSComparisonResult(tableMetadata *obj1, tableMetadata *obj2) {
  84. // Sort with Locale
  85. if ([sort isEqualToString:@"date"]) {
  86. if (ascending) return [obj1.date compare:obj2.date];
  87. else return [obj2.date compare:obj1.date];
  88. } else if ([sort isEqualToString:@"sessionTaskIdentifier"]) {
  89. if (ascending) return (obj1.sessionTaskIdentifier < obj2.sessionTaskIdentifier);
  90. else return (obj1.sessionTaskIdentifier > obj2.sessionTaskIdentifier);
  91. } else if ([sort isEqualToString:@"size"]) {
  92. if (ascending) return (obj1.size < obj2.size);
  93. else return (obj1.size > obj2.size);
  94. } else {
  95. if (ascending) return [obj1.fileNameView compare:obj2.fileNameView options:NSCaseInsensitiveSearch range:NSMakeRange(0,[obj1.fileNameView length]) locale:[NSLocale currentLocale]];
  96. else return [obj2.fileNameView compare:obj1.fileNameView options:NSCaseInsensitiveSearch range:NSMakeRange(0,[obj2.fileNameView length]) locale:[NSLocale currentLocale]];
  97. }
  98. }];
  99. /*
  100. Initialize datasource
  101. */
  102. NSInteger numDirectory = 0;
  103. NSInteger numDirectoryFavorite = 0;
  104. NSMutableArray *metadataFilesFavorite = [NSMutableArray new];
  105. for (tableMetadata *metadata in arraySoprtedMetadatas) {
  106. // *** LIST : DO NOT INSERT ***
  107. if ([filterocId containsObject: metadata.ocId] || (filterTypeFileImage == YES && [metadata.typeFile isEqualToString: k_metadataTypeFile_image]) || (filterTypeFileVideo == YES && [metadata.typeFile isEqualToString: k_metadataTypeFile_video])) {
  108. continue;
  109. }
  110. if ([listProgressMetadata objectForKey:metadata.ocId] && [groupBy isEqualToString:@"session"]) {
  111. [sectionDataSource.metadatas insertObject:metadata atIndex:0];
  112. } else {
  113. if (metadata.directory && directoryOnTop) {
  114. if (metadata.favorite) {
  115. [sectionDataSource.metadatas insertObject:metadata atIndex:numDirectoryFavorite++];
  116. numDirectory++;
  117. } else {
  118. [sectionDataSource.metadatas insertObject:metadata atIndex:numDirectory++];
  119. }
  120. } else {
  121. if (metadata.favorite && directoryOnTop) {
  122. [metadataFilesFavorite addObject:metadata];
  123. } else {
  124. [sectionDataSource.metadatas addObject:metadata];
  125. }
  126. }
  127. }
  128. }
  129. if (directoryOnTop && metadataFilesFavorite.count > 0) {
  130. [sectionDataSource.metadatas insertObjects:metadataFilesFavorite atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(numDirectoryFavorite, metadataFilesFavorite.count)]]; // Add Favorite files at end of favorite folders
  131. }
  132. /*
  133. sectionArrayRow
  134. */
  135. for (tableMetadata *metadata in sectionDataSource.metadatas) {
  136. if ([metadata.session length] > 0 && [groupBy isEqualToString:@"session"]) {
  137. if ([metadata.session containsString:@"wwan"]) dataSection = [@"." stringByAppendingString:metadata.session];
  138. else dataSection = metadata.session;
  139. }
  140. else if ([groupBy isEqualToString:@"none"]) dataSection = @"_none_";
  141. else if ([groupBy isEqualToString:@"date"]) dataSection = [CCUtility datetimeWithOutTime:metadata.date];
  142. else if ([groupBy isEqualToString:@"alphabetic"]) dataSection = [[metadata.fileNameView substringToIndex:1] uppercaseString];
  143. else if ([groupBy isEqualToString:@"typefile"]) dataSection = metadata.typeFile;
  144. if (!dataSection) dataSection = @"_none_";
  145. NSMutableArray *metadatasSection = [sectionDataSource.sectionArrayRow objectForKey:dataSection];
  146. if (metadatasSection) {
  147. // ROW ++
  148. [metadatasSection addObject:metadata.ocId];
  149. [sectionDataSource.sectionArrayRow setObject:metadatasSection forKey:dataSection];
  150. } else {
  151. // SECTION ++
  152. metadatasSection = [[NSMutableArray alloc] initWithObjects:metadata.ocId, nil];
  153. [sectionDataSource.sectionArrayRow setObject:metadatasSection forKey:dataSection];
  154. }
  155. if (metadata && [metadata.ocId length] > 0)
  156. [dictionaryEtagMetadataForIndexPath setObject:metadata forKey:metadata.ocId];
  157. }
  158. /*
  159. Sections order
  160. */
  161. /*
  162. BOOL ascending;
  163. if ([groupByField isEqualToString:@"date"]) ascending = NO;
  164. else ascending = YES;
  165. */
  166. NSArray *sortSections = [[sectionDataSource.sectionArrayRow allKeys] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
  167. if ([groupBy isEqualToString:@"session"]) {
  168. if ([obj1 isKindOfClass:[NSString class]] && [obj1 containsString:@"download"]) return NSOrderedAscending;
  169. if ([obj2 isKindOfClass:[NSString class]] && [obj2 containsString:@"download"]) return NSOrderedDescending;
  170. if ([obj1 isKindOfClass:[NSString class]] && [obj1 containsString:@"upload"]) return NSOrderedAscending;
  171. if ([obj2 isKindOfClass:[NSString class]] && [obj2 containsString:@"upload"]) return NSOrderedDescending;
  172. }
  173. // Directory at Top
  174. if ([obj1 isKindOfClass:[NSString class]] && [obj1 containsString: k_metadataTypeFile_directory]) return NSOrderedAscending;
  175. if ([obj2 isKindOfClass:[NSString class]] && [obj2 containsString: k_metadataTypeFile_directory]) return NSOrderedDescending;
  176. // Sort with Locale
  177. if ([obj1 isKindOfClass:[NSDate class]]) {
  178. if (ascending) return [obj1 compare:obj2];
  179. else return [obj2 compare:obj1];
  180. } else {
  181. if (ascending) return [obj1 compare:obj2 options:NSCaseInsensitiveSearch range:NSMakeRange(0,[obj1 length]) locale:[NSLocale currentLocale]];
  182. else return [obj2 compare:obj1 options:NSCaseInsensitiveSearch range:NSMakeRange(0,[obj2 length]) locale:[NSLocale currentLocale]];
  183. }
  184. }];
  185. /*
  186. create allEtag, allRecordsDataSource, ocIdIndexPath, section
  187. */
  188. NSInteger indexSection = 0;
  189. NSInteger indexRow = 0;
  190. for (id section in sortSections) {
  191. [sectionDataSource.sections addObject:section];
  192. NSArray *rows = [sectionDataSource.sectionArrayRow objectForKey:section];
  193. for (NSString *ocId in rows) {
  194. tableMetadata *metadata = [dictionaryEtagMetadataForIndexPath objectForKey:ocId];
  195. if (metadata.ocId) {
  196. [sectionDataSource.allOcId addObject:metadata.ocId];
  197. [sectionDataSource.allRecordsDataSource setObject:metadata forKey:metadata.ocId];
  198. [sectionDataSource.ocIdIndexPath setObject:[NSIndexPath indexPathForRow:indexRow inSection:indexSection] forKey:metadata.ocId];
  199. if ([metadata.typeFile isEqualToString: k_metadataTypeFile_image])
  200. sectionDataSource.image++;
  201. if ([metadata.typeFile isEqualToString: k_metadataTypeFile_video])
  202. sectionDataSource.video++;
  203. if (metadata.directory)
  204. sectionDataSource.directories++;
  205. else {
  206. sectionDataSource.files++;
  207. sectionDataSource.totalSize = sectionDataSource.totalSize + metadata.size;
  208. }
  209. indexRow++;
  210. }
  211. }
  212. indexSection++;
  213. indexRow = 0;
  214. }
  215. /*
  216. end
  217. */
  218. return sectionDataSource;
  219. }
  220. + (void)removeAllObjectsSectionDataSource:(CCSectionDataSourceMetadata *)sectionDataSource
  221. {
  222. [sectionDataSource.allRecordsDataSource removeAllObjects];
  223. [sectionDataSource.allOcId removeAllObjects];
  224. [sectionDataSource.sections removeAllObjects];
  225. [sectionDataSource.sectionArrayRow removeAllObjects];
  226. [sectionDataSource.ocIdIndexPath removeAllObjects];
  227. sectionDataSource.image = 0;
  228. sectionDataSource.video = 0;
  229. sectionDataSource.directories = 0;
  230. sectionDataSource.files = 0;
  231. sectionDataSource.totalSize = 0;
  232. }
  233. @end
  234. @implementation CCSectionDataSourceActivity
  235. - (id)init {
  236. self = [super init];
  237. _sections = [NSMutableArray new];
  238. _sectionArrayRow = [NSMutableDictionary new];
  239. return self;
  240. }
  241. @end
  242. @implementation CCSectionActivity
  243. + (CCSectionDataSourceActivity *)creataDataSourseSectionActivity:(NSArray *)records account:(NSString *)account
  244. {
  245. CCSectionDataSourceActivity *sectionDataSource = [CCSectionDataSourceActivity new];
  246. NSDate *oldDate = [NSDate date];
  247. for (tableActivity *record in records) {
  248. NSDateComponents* comps = [[NSCalendar currentCalendar] components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:record.date];
  249. NSDate *date = [[NSCalendar currentCalendar] dateFromComponents:comps];
  250. if ([oldDate compare:date] != NSOrderedSame) {
  251. [sectionDataSource.sections addObject:date];
  252. oldDate = date;
  253. }
  254. NSMutableArray *activities = [sectionDataSource.sectionArrayRow objectForKey:date];
  255. if (activities) {
  256. // ROW ++
  257. [activities addObject:record];
  258. [sectionDataSource.sectionArrayRow setObject:activities forKey:date];
  259. } else {
  260. // SECTION ++
  261. activities = [[NSMutableArray alloc] initWithObjects:record, nil];
  262. [sectionDataSource.sectionArrayRow setObject:activities forKey:date];
  263. }
  264. }
  265. return sectionDataSource;
  266. }
  267. @end