Browse Source

New Favorite view

Marino Faggiana 8 years ago
parent
commit
5051f6aa9d

+ 30 - 37
Nextcloud.xcodeproj/project.pbxproj

@@ -280,6 +280,10 @@
 		F769D39A1E9E1506006DBBB4 /* CCLocalStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = F769D3961E9E1506006DBBB4 /* CCLocalStorage.m */; };
 		F769D39B1E9E1506006DBBB4 /* CCLocalStorageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F769D3981E9E1506006DBBB4 /* CCLocalStorageCell.m */; };
 		F769D39C1E9E1506006DBBB4 /* CCLocalStorageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F769D3991E9E1506006DBBB4 /* CCLocalStorageCell.xib */; };
+		F769D3BE1E9E2519006DBBB4 /* CCFavorite.m in Sources */ = {isa = PBXBuildFile; fileRef = F769D3B81E9E2519006DBBB4 /* CCFavorite.m */; };
+		F769D3BF1E9E2519006DBBB4 /* CCFavoriteCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F769D3BA1E9E2519006DBBB4 /* CCFavoriteCell.m */; };
+		F769D3C01E9E2519006DBBB4 /* CCFavoriteCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F769D3BB1E9E2519006DBBB4 /* CCFavoriteCell.xib */; };
+		F769D3C11E9E2519006DBBB4 /* CCSynchronize.m in Sources */ = {isa = PBXBuildFile; fileRef = F769D3BD1E9E2519006DBBB4 /* CCSynchronize.m */; };
 		F77B0DF01D118A16002130FE /* UIImage+Resizing.m in Sources */ = {isa = PBXBuildFile; fileRef = F70F04CA1C889184008DAB36 /* UIImage+Resizing.m */; };
 		F77B0DF21D118A16002130FE /* CCUploadFromOtherUpp.m in Sources */ = {isa = PBXBuildFile; fileRef = F7956FCA1B4886E60085DEA3 /* CCUploadFromOtherUpp.m */; };
 		F77B0DF41D118A16002130FE /* CCMain.m in Sources */ = {isa = PBXBuildFile; fileRef = F70211FB1BAC56E9003FC03E /* CCMain.m */; };
@@ -527,8 +531,6 @@
 		F7BB14971D5B62C000ECEE68 /* libssl.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F70A63071D5B3467004E2AA5 /* libssl.a */; };
 		F7BE6E2F1D2D5C3B00106933 /* CCQuickActions.m in Sources */ = {isa = PBXBuildFile; fileRef = F7BE6E2C1D2D5C3B00106933 /* CCQuickActions.m */; };
 		F7BF1B431D51E893000854F6 /* CCLogin.m in Sources */ = {isa = PBXBuildFile; fileRef = F7BF1B401D51E893000854F6 /* CCLogin.m */; };
-		F7C00D471E2D0D0F0032160B /* CCCellOffline.m in Sources */ = {isa = PBXBuildFile; fileRef = F7C00D431E2D0D0F0032160B /* CCCellOffline.m */; };
-		F7C00D481E2D0D0F0032160B /* CCCellOffline.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7C00D441E2D0D0F0032160B /* CCCellOffline.xib */; };
 		F7C525A01E3B48B700FFE02C /* CCNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C5259F1E3B48B700FFE02C /* CCNotification.swift */; };
 		F7C525A21E3B6DA800FFE02C /* CCNotification.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7C525A11E3B6DA800FFE02C /* CCNotification.storyboard */; };
 		F7C742D81E7BD5C900D9C973 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7C742D71E7BD5C900D9C973 /* MainInterface.storyboard */; };
@@ -537,8 +539,6 @@
 		F7D6A0931D82DBFA0045AD1A /* CCControlCenterTransferCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F7D6A08C1D82DBFA0045AD1A /* CCControlCenterTransferCell.m */; };
 		F7D6A0951D82DBFA0045AD1A /* CCControlCenterTransferCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7D6A08D1D82DBFA0045AD1A /* CCControlCenterTransferCell.xib */; };
 		F7D6A0971D82DBFA0045AD1A /* CCMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = F7D6A08F1D82DBFA0045AD1A /* CCMenu.m */; };
-		F7DA62AE1E41E666003E1740 /* CCOfflinePageContent.m in Sources */ = {isa = PBXBuildFile; fileRef = F7DA62AD1E41E666003E1740 /* CCOfflinePageContent.m */; };
-		F7EC147B1E5D9C0B0046F351 /* CCSynchronize.m in Sources */ = {isa = PBXBuildFile; fileRef = F7EC147A1E5D9C0B0046F351 /* CCSynchronize.m */; };
 		F7ECBA6D1E239DCD003E6328 /* CCCreateCloud.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7ECBA6C1E239DCD003E6328 /* CCCreateCloud.swift */; };
 		F7EF0CAF1D9E95F400A9D15E /* CCSharedDBSession.m in Sources */ = {isa = PBXBuildFile; fileRef = F7EF0CAD1D9E95F400A9D15E /* CCSharedDBSession.m */; };
 		F7F06E8D1DBFACC600099AE9 /* NSBundle+CTAssetsPickerController.m in Sources */ = {isa = PBXBuildFile; fileRef = F7F06E2E1DBFACC600099AE9 /* NSBundle+CTAssetsPickerController.m */; };
@@ -620,7 +620,6 @@
 		F7F6AC4E1E525AD300E8EB45 /* CCManageCryptoCloud.m in Sources */ = {isa = PBXBuildFile; fileRef = F7F6AC4D1E525AD300E8EB45 /* CCManageCryptoCloud.m */; };
 		F7F801031D98205A007537BC /* CCCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = F7F801011D98205A007537BC /* CCCertificate.m */; };
 		F7F801051D98205A007537BC /* CCCertificate.m in Sources */ = {isa = PBXBuildFile; fileRef = F7F801011D98205A007537BC /* CCCertificate.m */; };
-		F7FB5F131E66CDCB00389481 /* CCOfflineContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = F7FB5F121E66CDCB00389481 /* CCOfflineContainer.m */; };
 		F7FB5F1C1E66EB7200389481 /* TableActivity+CoreDataClass.m in Sources */ = {isa = PBXBuildFile; fileRef = F7FB5F191E66EB7200389481 /* TableActivity+CoreDataClass.m */; };
 		F7FB5F1E1E66EB7200389481 /* TableActivity+CoreDataProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = F7FB5F1B1E66EB7200389481 /* TableActivity+CoreDataProperties.m */; };
 		F7FB5F201E66F0A400389481 /* TableActivity+CoreDataClass.m in Sources */ = {isa = PBXBuildFile; fileRef = F7FB5F191E66EB7200389481 /* TableActivity+CoreDataClass.m */; };
@@ -1426,6 +1425,13 @@
 		F769D3971E9E1506006DBBB4 /* CCLocalStorageCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCLocalStorageCell.h; sourceTree = "<group>"; };
 		F769D3981E9E1506006DBBB4 /* CCLocalStorageCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCLocalStorageCell.m; sourceTree = "<group>"; };
 		F769D3991E9E1506006DBBB4 /* CCLocalStorageCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CCLocalStorageCell.xib; sourceTree = "<group>"; };
+		F769D3B71E9E2519006DBBB4 /* CCFavorite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCFavorite.h; sourceTree = "<group>"; };
+		F769D3B81E9E2519006DBBB4 /* CCFavorite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCFavorite.m; sourceTree = "<group>"; };
+		F769D3B91E9E2519006DBBB4 /* CCFavoriteCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCFavoriteCell.h; sourceTree = "<group>"; };
+		F769D3BA1E9E2519006DBBB4 /* CCFavoriteCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCFavoriteCell.m; sourceTree = "<group>"; };
+		F769D3BB1E9E2519006DBBB4 /* CCFavoriteCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CCFavoriteCell.xib; sourceTree = "<group>"; };
+		F769D3BC1E9E2519006DBBB4 /* CCSynchronize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSynchronize.h; sourceTree = "<group>"; };
+		F769D3BD1E9E2519006DBBB4 /* CCSynchronize.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCSynchronize.m; sourceTree = "<group>"; };
 		F76A75E01E83D42B005AFFF4 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/CTAssetsPicker.strings; sourceTree = "<group>"; };
 		F76A75E11E83D42B005AFFF4 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/SwiftWebVC.strings; sourceTree = "<group>"; };
 		F76A75E21E83D42B005AFFF4 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/BKPasscodeView.strings; sourceTree = "<group>"; };
@@ -1508,9 +1514,6 @@
 		F7BFCCBF1B68C21900548E76 /* CCManageAsset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCManageAsset.m; sourceTree = "<group>"; };
 		F7BFCCC01B68C21900548E76 /* CCManageLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCManageLocation.h; sourceTree = "<group>"; };
 		F7BFCCC11B68C21900548E76 /* CCManageLocation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCManageLocation.m; sourceTree = "<group>"; };
-		F7C00D421E2D0D0F0032160B /* CCCellOffline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCCellOffline.h; sourceTree = "<group>"; };
-		F7C00D431E2D0D0F0032160B /* CCCellOffline.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCCellOffline.m; sourceTree = "<group>"; };
-		F7C00D441E2D0D0F0032160B /* CCCellOffline.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CCCellOffline.xib; sourceTree = "<group>"; };
 		F7C00D4A1E2D10BB0032160B /* cryptocloud 7.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "cryptocloud 7.xcdatamodel"; sourceTree = "<group>"; };
 		F7C0F46E1C8880540059EC54 /* ShareViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ShareViewController.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
 		F7C0F46F1C8880540059EC54 /* ShareViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ShareViewController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
@@ -1555,11 +1558,7 @@
 		F7D96F0D1D99498600A587A5 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
 		F7D96F0E1D99498700A587A5 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Intro.strings; sourceTree = "<group>"; };
 		F7D96F0F1D99498700A587A5 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Error.strings; sourceTree = "<group>"; };
-		F7DA62AC1E41E666003E1740 /* CCOfflinePageContent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCOfflinePageContent.h; sourceTree = "<group>"; };
-		F7DA62AD1E41E666003E1740 /* CCOfflinePageContent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCOfflinePageContent.m; sourceTree = "<group>"; };
 		F7E456D41C89D54A00BD63F0 /* Share Ext-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Share Ext-Bridging-Header.h"; sourceTree = "<group>"; };
-		F7EC14791E5D9C0B0046F351 /* CCSynchronize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSynchronize.h; sourceTree = "<group>"; };
-		F7EC147A1E5D9C0B0046F351 /* CCSynchronize.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCSynchronize.m; sourceTree = "<group>"; };
 		F7ECBA6C1E239DCD003E6328 /* CCCreateCloud.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CCCreateCloud.swift; sourceTree = "<group>"; };
 		F7EF0CAC1D9E95EC00A9D15E /* CCSharedDBSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = CCSharedDBSession.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
 		F7EF0CAD1D9E95F400A9D15E /* CCSharedDBSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = CCSharedDBSession.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
@@ -1695,8 +1694,6 @@
 		F7F6AC4D1E525AD300E8EB45 /* CCManageCryptoCloud.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCManageCryptoCloud.m; sourceTree = "<group>"; };
 		F7F801001D98205A007537BC /* CCCertificate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCCertificate.h; sourceTree = "<group>"; };
 		F7F801011D98205A007537BC /* CCCertificate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCCertificate.m; sourceTree = "<group>"; };
-		F7FB5F111E66CDCB00389481 /* CCOfflineContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCOfflineContainer.h; sourceTree = "<group>"; };
-		F7FB5F121E66CDCB00389481 /* CCOfflineContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCOfflineContainer.m; sourceTree = "<group>"; };
 		F7FB5F181E66EB7200389481 /* TableActivity+CoreDataClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TableActivity+CoreDataClass.h"; sourceTree = "<group>"; };
 		F7FB5F191E66EB7200389481 /* TableActivity+CoreDataClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TableActivity+CoreDataClass.m"; sourceTree = "<group>"; };
 		F7FB5F1A1E66EB7200389481 /* TableActivity+CoreDataProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TableActivity+CoreDataProperties.h"; sourceTree = "<group>"; };
@@ -2904,6 +2901,20 @@
 			path = "Local storage";
 			sourceTree = "<group>";
 		};
+		F769D3B61E9E2519006DBBB4 /* Favorite */ = {
+			isa = PBXGroup;
+			children = (
+				F769D3B71E9E2519006DBBB4 /* CCFavorite.h */,
+				F769D3B81E9E2519006DBBB4 /* CCFavorite.m */,
+				F769D3B91E9E2519006DBBB4 /* CCFavoriteCell.h */,
+				F769D3BA1E9E2519006DBBB4 /* CCFavoriteCell.m */,
+				F769D3BB1E9E2519006DBBB4 /* CCFavoriteCell.xib */,
+				F769D3BC1E9E2519006DBBB4 /* CCSynchronize.h */,
+				F769D3BD1E9E2519006DBBB4 /* CCSynchronize.m */,
+			);
+			path = Favorite;
+			sourceTree = "<group>";
+		};
 		F77F86401B4ABF6D009F0A10 /* Table */ = {
 			isa = PBXGroup;
 			children = (
@@ -3074,23 +3085,6 @@
 			path = Utility;
 			sourceTree = "<group>";
 		};
-		F7C00D411E2D0D0F0032160B /* Favorite */ = {
-			isa = PBXGroup;
-			children = (
-				F7C00D421E2D0D0F0032160B /* CCCellOffline.h */,
-				F7C00D431E2D0D0F0032160B /* CCCellOffline.m */,
-				F7C00D441E2D0D0F0032160B /* CCCellOffline.xib */,
-				F7FB5F111E66CDCB00389481 /* CCOfflineContainer.h */,
-				F7FB5F121E66CDCB00389481 /* CCOfflineContainer.m */,
-				F7DA62AC1E41E666003E1740 /* CCOfflinePageContent.h */,
-				F7DA62AD1E41E666003E1740 /* CCOfflinePageContent.m */,
-				F7EC14791E5D9C0B0046F351 /* CCSynchronize.h */,
-				F7EC147A1E5D9C0B0046F351 /* CCSynchronize.m */,
-			);
-			name = Favorite;
-			path = Offline;
-			sourceTree = "<group>";
-		};
 		F7C0F46D1C8880540059EC54 /* Share */ = {
 			isa = PBXGroup;
 			children = (
@@ -3375,6 +3369,7 @@
 				F70211F31BAC56E9003FC03E /* Main */,
 				F720E02A1E48C74C001A4B9E /* Actions */,
 				F7ECBA6B1E239DCD003E6328 /* Create */,
+				F769D3B61E9E2519006DBBB4 /* Favorite */,
 				F7E95CEC1AC40BA40060D08E /* FileSystem */,
 				F744BE911BEBB2EE004FFF66 /* Intro */,
 				F7F54CAC1E5B143100E19C62 /* Library */,
@@ -3385,7 +3380,6 @@
 				F7F9E3451BC26B19004B9223 /* Move */,
 				F74D3DB81BAC1941000BAE4B /* Networking */,
 				F7C5259A1E3B441D00FFE02C /* Notification */,
-				F7C00D411E2D0D0F0032160B /* Favorite */,
 				F7FCFFD51D70798C000E6E29 /* PeekPop */,
 				F719FDAE1CF06645004895D0 /* PhotosCameraUpload */,
 				F7BE6E2A1D2D5C3B00106933 /* QuickActions */,
@@ -3770,7 +3764,6 @@
 				F75ADF451DC75FFE008A7347 /* CCLogin.storyboard in Resources */,
 				F77B0EEA1D118A16002130FE /* ZSSbold@2x.png in Resources */,
 				F77B0EEB1D118A16002130FE /* ZSSrightjustify@2x.png in Resources */,
-				F7C00D481E2D0D0F0032160B /* CCCellOffline.xib in Resources */,
 				F77B0EEC1D118A16002130FE /* ZSSindent@2x.png in Resources */,
 				F7F54CED1E5B14C700E19C62 /* ImageSelectedOn@3x.png in Resources */,
 				F77B0EED1D118A16002130FE /* Reader-Mark-N@2x.png in Resources */,
@@ -3923,6 +3916,7 @@
 				F77B0F861D118A16002130FE /* LMMediaPlayerView.bundle in Resources */,
 				F77B0F8A1D118A16002130FE /* CCCellMain.xib in Resources */,
 				F77B0F8C1D118A16002130FE /* CCCellMainTransfer.xib in Resources */,
+				F769D3C01E9E2519006DBBB4 /* CCFavoriteCell.xib in Resources */,
 				F77B0F8E1D118A16002130FE /* LMMediaPlayerView.xib in Resources */,
 				F75797AE1E81356C00187A1B /* CTAssetsPicker.strings in Resources */,
 				F77B0F8F1D118A16002130FE /* ZSSunlink@2x.png in Resources */,
@@ -4146,7 +4140,6 @@
 				F7659A581DC0B760004860C4 /* NSIndexPath+PSTCollectionViewAdditions.m in Sources */,
 				F7659A681DC0B760004860C4 /* PSTCollectionViewUpdateItem.m in Sources */,
 				F7F54D061E5B14C800E19C62 /* MWCaptionView.m in Sources */,
-				F7C00D471E2D0D0F0032160B /* CCCellOffline.m in Sources */,
 				F77B0E071D118A16002130FE /* ioapi.c in Sources */,
 				F73CCDF11DC13776007E38D8 /* XLFormStepCounterCell.m in Sources */,
 				F73CCE1F1DC13776007E38D8 /* XLForm.m in Sources */,
@@ -4189,6 +4182,7 @@
 				F77B0E221D118A16002130FE /* CCManageLocation.m in Sources */,
 				F77B0E231D118A16002130FE /* CCSharePermissionOC.m in Sources */,
 				F77B0E241D118A16002130FE /* HRColorCursor.m in Sources */,
+				F769D3C11E9E2519006DBBB4 /* CCSynchronize.m in Sources */,
 				F708CF851E56E8CC00271D8B /* TableShare+CoreDataClass.m in Sources */,
 				F75AE3C71E9D12900088BB09 /* SwiftyAvatar.swift in Sources */,
 				F708CF9A1E56E8CC00271D8B /* TableAccount+CoreDataProperties.m in Sources */,
@@ -4207,8 +4201,6 @@
 				F77B0E321D118A16002130FE /* HRCgUtil.m in Sources */,
 				F7F06EB71DBFACC600099AE9 /* CTAssetsGridViewFooter.m in Sources */,
 				F7F06EB91DBFACC600099AE9 /* CTAssetsGridViewLayout.m in Sources */,
-				F7DA62AE1E41E666003E1740 /* CCOfflinePageContent.m in Sources */,
-				F7FB5F131E66CDCB00389481 /* CCOfflineContainer.m in Sources */,
 				F77B0E351D118A16002130FE /* NYXImagesHelper.m in Sources */,
 				F73CCE171DC13776007E38D8 /* XLFormTextView.m in Sources */,
 				F77B0E361D118A16002130FE /* ZSSBarButtonItem.m in Sources */,
@@ -4220,6 +4212,7 @@
 				F77B0E411D118A16002130FE /* CCSplit.m in Sources */,
 				F77B0E421D118A16002130FE /* ReaderMainPagebar.m in Sources */,
 				F77B0E431D118A16002130FE /* ReaderThumbsView.m in Sources */,
+				F769D3BE1E9E2519006DBBB4 /* CCFavorite.m in Sources */,
 				F73CCDFD1DC13776007E38D8 /* XLFormViewController.m in Sources */,
 				F73CCDDF1DC13776007E38D8 /* XLFormDateCell.m in Sources */,
 				F73CCE1B1DC13776007E38D8 /* XLFormValidationStatus.m in Sources */,
@@ -4293,6 +4286,7 @@
 				F7F06EA51DBFACC600099AE9 /* CTAssetItemViewController.m in Sources */,
 				F7659A5A1DC0B760004860C4 /* PSTCollectionView.m in Sources */,
 				F7BF1B431D51E893000854F6 /* CCLogin.m in Sources */,
+				F769D3BF1E9E2519006DBBB4 /* CCFavoriteCell.m in Sources */,
 				F77B0E7D1D118A16002130FE /* CYRTextStorage.m in Sources */,
 				F77B0E7E1D118A16002130FE /* ThumbsViewController.m in Sources */,
 				F77B0E801D118A16002130FE /* ZSSRichTextEditor.m in Sources */,
@@ -4358,7 +4352,6 @@
 				F73CCDEF1DC13776007E38D8 /* XLFormSliderCell.m in Sources */,
 				F77B0EB51D118A16002130FE /* RECommonFunctions.m in Sources */,
 				F73CCE111DC13776007E38D8 /* XLFormRightDetailCell.m in Sources */,
-				F7EC147B1E5D9C0B0046F351 /* CCSynchronize.m in Sources */,
 				F73CCDE71DC13776007E38D8 /* XLFormLeftRightSelectorCell.m in Sources */,
 				F77B0EB61D118A16002130FE /* MBProgressHUD.m in Sources */,
 				F77B0EB71D118A16002130FE /* ReaderThumbRequest.m in Sources */,

+ 2 - 2
iOSClient/AppDelegate.h

@@ -40,8 +40,8 @@
 #import "CCQuickActions.h"
 #import "CCMain.h"
 #import "CCPhotosCameraUpload.h"
-#import "CCOfflineContainer.h"
 #import "CCSettings.h"
+#import "CCFavorite.h"
 
 @interface AppDelegate : UIResponder <UIApplicationDelegate, BKPasscodeLockScreenManagerDelegate, BKPasscodeViewControllerDelegate, LMMediaPlayerViewDelegate, TWMessageBarStyleSheet, CCNetworkingDelegate>
 
@@ -135,7 +135,7 @@
 @property (nonatomic, strong) CCMain *homeMain;
 @property (nonatomic, strong) CCPhotosCameraUpload *activePhotosCameraUpload;
 @property (nonatomic, retain) CCDetail *activeDetail;
-@property (nonatomic, retain) CCOfflineContainer *activeOffline;
+@property (nonatomic, retain) CCFavorite *activeFavorite;
 @property (nonatomic, retain) CCSettings *activeSettings;
 
 @property (nonatomic, strong) NSMutableDictionary *listMainVC;

+ 0 - 1
iOSClient/AppDelegate.m

@@ -28,7 +28,6 @@
 #import "CCNetworking.h"
 #import "CCCoreData.h"
 #import "CCCrypto.h"
-#import "CCOfflineContainer.h"
 #import "CCManageAsset.h"
 #import "CCGraphics.h"
 #import "CCPhotosCameraUpload.h"

+ 58 - 0
iOSClient/Favorite/CCFavorite.h

@@ -0,0 +1,58 @@
+//
+//  CCFavorite.h
+//  Crypto Cloud Technology Nextcloud
+//
+//  Created by Marino Faggiana on 16/01/17.
+//  Copyright (c) 2017 TWS. All rights reserved.
+//
+//  Author Marino Faggiana <m.faggiana@twsweb.it>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <UIKit/UIKit.h>
+
+#import "CCDetail.h"
+#import "UIScrollView+EmptyDataSet.h"
+#import "TWMessageBarManager.h"
+#import "AHKActionSheet.h"
+#import "CCFavoriteCell.h"
+#import "CCUtility.h"
+#import "CCCoreData.h"
+#import "CCMain.h"
+#import "CCGraphics.h"
+#import "CCAccountWeb.h"
+#import "CCBancomat.h"
+#import "CCCartaDiCredito.h"
+#import "CCCartaIdentita.h"
+#import "CCContoCorrente.h"
+#import "CCNote.h"
+#import "CCPassaporto.h"
+#import "CCPatenteGuida.h"
+
+@interface CCFavorite : UIViewController <UITableViewDataSource, UITableViewDelegate, UIDocumentInteractionControllerDelegate, UIActionSheetDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate, CCAccountWebDelegate, CCBancomatDelegate, CCCartaDiCreditoDelegate, CCCartaIdentitaDelegate, CCContoCorrenteDelegate, CCNoteDelegate, CCPassaportoDelegate, CCPatenteGuidaDelegate>
+
+@property (nonatomic, weak) IBOutlet UITableView *tableView;
+
+@property (nonatomic, strong) CCMetadata *metadata;
+@property (nonatomic, strong) NSString *serverUrl;
+@property (nonatomic, strong) NSString *titleViewControl;
+
+@property (nonatomic, weak) CCDetail *detailViewController;
+@property (nonatomic, strong) UIDocumentInteractionController *docController;
+
+- (void)reloadDatasource;
+- (void)readFolderWithForced:(BOOL)forced serverUrl:(NSString *)serverUrl;
+
+@end

+ 858 - 0
iOSClient/Favorite/CCFavorite.m

@@ -0,0 +1,858 @@
+//
+//  CCFavorite.m
+//  Crypto Cloud Technology Nextcloud
+//
+//  Created by Marino Faggiana on 16/01/17.
+//  Copyright (c) 2017 TWS. All rights reserved.
+//
+//  Author Marino Faggiana <m.faggiana@twsweb.it>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "CCFavorite.h"
+
+#import "AppDelegate.h"
+
+#ifdef CUSTOM_BUILD
+    #import "CustomSwift.h"
+#else
+    #import "Nextcloud-Swift.h"
+#endif
+
+@interface CCFavorite () <CCActionsDeleteDelegate, CCActionsSettingFavoriteDelegate>
+{
+    NSArray *dataSource;
+    BOOL _reloadDataSource;
+}
+@end
+
+@implementation CCFavorite
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    
+    // Custom Cell
+    [self.tableView registerNib:[UINib nibWithNibName:@"CCFavoriteCell" bundle:nil] forCellReuseIdentifier:@"Cell"];
+
+    // dataSource
+    dataSource = [NSMutableArray new];
+    
+    // Metadata
+    _metadata = [CCMetadata new];
+    
+    self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 1)];
+    self.tableView.separatorColor = COLOR_SEPARATOR_TABLE;
+    self.tableView.emptyDataSetDelegate = self;
+    self.tableView.emptyDataSetSource = self;
+    self.tableView.allowsMultipleSelectionDuringEditing = NO;
+    
+    // calculate _serverUrl
+    if ([self.pageType isEqualToString:k_pageOfflineFavorites] && !_serverUrl)
+        _serverUrl = nil;
+    
+    if ([self.pageType isEqualToString:k_pageOfflineOffline] && !_serverUrl)
+        _serverUrl = nil;
+    
+    if ([self.pageType isEqualToString:k_pageOfflineLocal] && !_serverUrl)
+        _serverUrl = [CCUtility getDirectoryLocal];
+    
+    // Title & color
+    self.title = _titleViewControl;
+}
+
+// Apparirà
+- (void)viewWillAppear:(BOOL)animated
+{
+    [super viewWillAppear:animated];
+    
+    // Color
+    [CCAspect aspectNavigationControllerBar:self.navigationController.navigationBar encrypted:NO online:[app.reachability isReachable] hidden:NO];
+    [CCAspect aspectTabBar:self.tabBarController.tabBar hidden:NO];
+    
+    // Plus Button
+    [app plusButtonVisibile:true];
+    
+    [self reloadDatasource];
+}
+
+// E' arrivato
+- (void)viewDidAppear:(BOOL)animated
+{
+    [super viewDidAppear:animated];
+        
+    // update Badge
+    [app updateApplicationIconBadgeNumber];
+}
+
+- (void)didReceiveMemoryWarning {
+    [super didReceiveMemoryWarning];
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ==== DZNEmptyDataSetSource ====
+#pragma --------------------------------------------------------------------------------------------
+
+- (BOOL)emptyDataSetShouldDisplay:(UIScrollView *)scrollView
+{
+    // only for root
+    if (!_serverUrl || [_serverUrl isEqualToString:[CCUtility getDirectoryLocal]])
+        return YES;
+    else
+        return NO;
+}
+
+- (CGFloat)spaceHeightForEmptyDataSet:(UIScrollView *)scrollView
+{
+    return 0.0f;
+}
+
+- (CGFloat)verticalOffsetForEmptyDataSet:(UIScrollView *)scrollView
+{
+    return - self.navigationController.navigationBar.frame.size.height;
+}
+
+- (UIColor *)backgroundColorForEmptyDataSet:(UIScrollView *)scrollView
+{
+    return [UIColor whiteColor];
+}
+
+- (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView
+{
+    return [UIImage imageNamed:image_brandBackgroundLite];
+}
+
+- (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView
+{
+    NSString *text;
+    
+    if ([self.pageType isEqualToString:k_pageOfflineFavorites] || [self.pageType isEqualToString:k_pageOfflineOffline])
+        text = [NSString stringWithFormat:@"%@", @""];
+    
+    if ([self.pageType isEqualToString:k_pageOfflineLocal])
+        text = [NSString stringWithFormat:@"%@", @""];
+    
+    NSDictionary *attributes = @{NSFontAttributeName:[UIFont boldSystemFontOfSize:20.0f], NSForegroundColorAttributeName:COLOR_BRAND};
+    
+    return [[NSAttributedString alloc] initWithString:text attributes:attributes];
+}
+
+- (NSAttributedString *)descriptionForEmptyDataSet:(UIScrollView *)scrollView
+{
+    NSString *text;
+    
+    if ([self.pageType isEqualToString:k_pageOfflineFavorites])
+        text = [NSString stringWithFormat:@"\n%@", NSLocalizedString(@"_tutorial_favorite_view_", nil)];
+    
+    if ([self.pageType isEqualToString:k_pageOfflineOffline])
+        text = [NSString stringWithFormat:@"\n%@", NSLocalizedString(@"_tutorial_offline_view_", nil)];
+        
+    if ([self.pageType isEqualToString:k_pageOfflineLocal])
+        text = [NSString stringWithFormat:@"\n%@", NSLocalizedString(@"_tutorial_local_view_", nil)];
+    
+    NSMutableParagraphStyle *paragraph = [NSMutableParagraphStyle new];
+    paragraph.lineBreakMode = NSLineBreakByWordWrapping;
+    paragraph.alignment = NSTextAlignmentCenter;
+    
+    NSDictionary *attributes = @{NSFontAttributeName: [UIFont systemFontOfSize:14.0], NSForegroundColorAttributeName: [UIColor lightGrayColor], NSParagraphStyleAttributeName: paragraph};
+    
+    return [[NSAttributedString alloc] initWithString:text attributes:attributes];
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ===== UIDocumentInteractionController <delegate> =====
+#pragma --------------------------------------------------------------------------------------------
+
+- (void)documentInteractionControllerDidDismissOptionsMenu:(UIDocumentInteractionController *)controller
+{
+    // evitiamo il rimando della eventuale photo e/o video
+    if ([CCCoreData getCameraUploadActiveAccount:app.activeAccount]) {
+        
+        [CCCoreData setCameraUploadDatePhoto:[NSDate date]];
+        [CCCoreData setCameraUploadDateVideo:[NSDate date]];
+    }
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ===== Delete <delegate> =====
+#pragma--------------------------------------------------------------------------------------------
+
+- (void)deleteFileOrFolderFailure:(CCMetadataNet *)metadataNet message:(NSString *)message errorCode:(NSInteger)errorCode
+{
+    NSLog(@"[LOG] Delete error %@", message);
+}
+
+- (void)deleteFileOrFolderSuccess:(CCMetadataNet *)metadataNet
+{
+    [self reloadDatasource];
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ===== Favorite <delegate> =====
+#pragma--------------------------------------------------------------------------------------------
+
+- (void)settingFavoriteFailure:(CCMetadataNet *)metadataNet message:(NSString *)message errorCode:(NSInteger)errorCode
+{
+    NSLog(@"[LOG] Remove Favorite error %@", message);
+}
+
+- (void)settingFavoriteSuccess:(CCMetadataNet *)metadataNet
+{
+    [CCCoreData setMetadataFavoriteFileID:metadataNet.fileID favorite:[metadataNet.options boolValue] activeAccount:app.activeAccount context:nil];
+ 
+    [self reloadDatasource];
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ==== Download Thumbnail <Delegate> ====
+#pragma --------------------------------------------------------------------------------------------
+
+- (void)downloadThumbnailSuccess:(CCMetadataNet *)metadataNet
+{
+    // i am in Favorites
+    if ([_pageType isEqualToString:k_pageOfflineFavorites] || [_pageType isEqualToString:k_pageOfflineOffline])
+        [self reloadDatasource];
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ==== Download <Delegate> ====
+#pragma --------------------------------------------------------------------------------------------
+
+- (void)downloadFileFailure:(NSString *)fileID serverUrl:(NSString *)serverUrl selector:(NSString *)selector message:(NSString *)message errorCode:(NSInteger)errorCode
+{    
+    [app messageNotification:@"_download_file_" description:message visible:YES delay:k_dismissAfterSecond type:TWMessageBarMessageTypeError];
+    
+    [app updateApplicationIconBadgeNumber];
+}
+
+- (void)downloadFileSuccess:(NSString *)fileID serverUrl:(NSString *)serverUrl selector:(NSString *)selector selectorPost:(NSString *)selectorPost
+{
+    _metadata = [CCCoreData getMetadataWithPreficate:[NSPredicate predicateWithFormat:@"(fileID == %@) AND (account == %@)", fileID, app.activeAccount] context:nil];
+    
+    // File exists
+    if ([self shouldPerformSegue])
+        [self performSegueWithIdentifier:@"segueDetail" sender:self];
+    
+    [app updateApplicationIconBadgeNumber];
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ===== menu =====
+#pragma--------------------------------------------------------------------------------------------
+
+- (void)openModel:(CCMetadata *)metadata
+{
+    UIViewController *viewController;
+    BOOL isLocal = NO;
+    NSString *serverUrl = [CCCoreData getServerUrlFromDirectoryID:_metadata.directoryID activeAccount:app.activeAccount];
+    
+    if ([self.pageType isEqualToString:k_pageOfflineLocal])
+        isLocal = YES;
+    
+    if ([metadata.model isEqualToString:@"cartadicredito"])
+        viewController = [[CCCartaDiCredito alloc] initWithDelegate:self fileName:metadata.fileName uuid:metadata.uuid fileID:metadata.fileID isLocal:isLocal serverUrl:serverUrl];
+    
+    if ([metadata.model isEqualToString:@"bancomat"])
+        viewController = [[CCBancomat alloc] initWithDelegate:self fileName:metadata.fileName uuid:metadata.uuid fileID:metadata.fileID isLocal:isLocal serverUrl:serverUrl];
+    
+    if ([metadata.model isEqualToString:@"contocorrente"])
+        viewController = [[CCContoCorrente alloc] initWithDelegate:self fileName:metadata.fileName uuid:metadata.uuid fileID:metadata.fileID isLocal:isLocal serverUrl:serverUrl];
+    
+    if ([metadata.model isEqualToString:@"accountweb"])
+        viewController = [[CCAccountWeb alloc] initWithDelegate:self fileName:metadata.fileName uuid:metadata.uuid fileID:metadata.fileID isLocal:isLocal serverUrl:serverUrl];
+    
+    if ([metadata.model isEqualToString:@"patenteguida"])
+        viewController = [[CCPatenteGuida alloc] initWithDelegate:self fileName:metadata.fileName uuid:metadata.uuid fileID:metadata.fileID isLocal:isLocal serverUrl:serverUrl];
+    
+    if ([metadata.model isEqualToString:@"cartaidentita"])
+        viewController = [[CCCartaIdentita alloc] initWithDelegate:self fileName:metadata.fileName uuid:metadata.uuid fileID:metadata.fileID isLocal:isLocal serverUrl:serverUrl];
+    
+    if ([metadata.model isEqualToString:@"passaporto"])
+        viewController = [[CCPassaporto alloc] initWithDelegate:self fileName:metadata.fileName uuid:metadata.uuid fileID:metadata.fileID isLocal:isLocal serverUrl:serverUrl];
+    
+    if ([metadata.model isEqualToString:@"note"]) {
+        
+        viewController = [[CCNote alloc] initWithDelegate:self fileName:metadata.fileName uuid:metadata.uuid fileID:metadata.fileID isLocal:isLocal serverUrl:serverUrl];
+        
+        UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
+        
+        [self presentViewController:navigationController animated:YES completion:nil];
+        
+    } else {
+        
+        UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
+        
+        [navigationController setModalPresentationStyle:UIModalPresentationFormSheet];
+        
+        [self presentViewController:navigationController animated:YES completion:nil];
+    }
+}
+
+- (void)openWith:(CCMetadata *)metadata
+{
+    NSString *fileNamePath;
+    
+    if ([_pageType isEqualToString:k_pageOfflineFavorites] || [_pageType isEqualToString:k_pageOfflineOffline])
+        fileNamePath = [NSString stringWithFormat:@"%@/%@", app.directoryUser, metadata.fileID];
+    
+    if ([_pageType isEqualToString:k_pageOfflineLocal])
+        fileNamePath = [NSString stringWithFormat:@"%@/%@", _serverUrl, metadata.fileNameData];
+        
+    if ([[NSFileManager defaultManager] fileExistsAtPath:fileNamePath]) {
+        
+        [[NSFileManager defaultManager] removeItemAtPath:[NSTemporaryDirectory() stringByAppendingString:metadata.fileNamePrint] error:nil];
+        [[NSFileManager defaultManager] linkItemAtPath:fileNamePath toPath:[NSTemporaryDirectory() stringByAppendingString:metadata.fileNamePrint] error:nil];
+        
+        NSURL *url = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingString:metadata.fileNamePrint]];
+        
+        _docController = [UIDocumentInteractionController interactionControllerWithURL:url];
+        _docController.delegate = self;
+        
+        [_docController presentOptionsMenuFromRect:self.view.frame inView:self.view animated:YES];
+    }
+}
+
+- (void)requestDeleteMetadata:(CCMetadata *)metadata indexPath:(NSIndexPath *)indexPath
+{
+    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
+        
+    [alertController addAction: [UIAlertAction actionWithTitle:NSLocalizedString(@"_delete_", nil) style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) {
+                                                               
+        if ([_pageType isEqualToString:k_pageOfflineFavorites] || [_pageType isEqualToString:k_pageOfflineOffline]) {
+                                                                   
+            [[CCActions sharedInstance] deleteFileOrFolder:metadata delegate:self];
+        }
+                                                               
+        if ([_pageType isEqualToString:k_pageOfflineLocal]) {
+                                                                   
+            NSString *fileNamePath = [NSString stringWithFormat:@"%@/%@", _serverUrl, metadata.fileNameData];
+            NSString *iconPath = [NSString stringWithFormat:@"%@/.%@.ico", _serverUrl, metadata.fileNameData];
+                                                                   
+            [[NSFileManager defaultManager] removeItemAtPath:fileNamePath error:nil];
+            [[NSFileManager defaultManager] removeItemAtPath:iconPath error:nil];
+        }
+                                                               
+        [self reloadDatasource];
+    }]];
+        
+        
+    [alertController addAction: [UIAlertAction actionWithTitle:NSLocalizedString(@"_cancel_", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
+    }]];
+        
+    alertController.popoverPresentationController.sourceView = self.view;
+    alertController.popoverPresentationController.sourceRect = [self.tableView rectForRowAtIndexPath:indexPath];
+        
+    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
+        [alertController.view layoutIfNeeded];
+        
+    [self presentViewController:alertController animated:YES completion:nil];
+}
+
+-(void)cellButtonDownWasTapped:(id)sender
+{
+    CGPoint touchPoint = [sender convertPoint:CGPointZero toView:self.tableView];
+    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:touchPoint];
+    CCMetadata *metadata = [CCMetadata new];
+    UIImage *iconHeader;
+    
+    if ([_pageType isEqualToString:k_pageOfflineLocal]) {
+        
+        NSString *cameraFolderName = [CCCoreData getCameraUploadFolderNameActiveAccount:app.activeAccount];
+        NSString *cameraFolderPath = [CCCoreData getCameraUploadFolderPathActiveAccount:app.activeAccount activeUrl:app.activeUrl];
+        
+        metadata = [CCUtility insertFileSystemInMetadata:[dataSource objectAtIndex:indexPath.row] directory:_serverUrl activeAccount:app.activeAccount cameraFolderName:cameraFolderName cameraFolderPath:cameraFolderPath];
+        
+    } else {
+        
+        metadata = [dataSource objectAtIndex:indexPath.row];
+    }
+    
+    AHKActionSheet *actionSheet = [[AHKActionSheet alloc] initWithView:self.view title:nil];
+    
+    actionSheet.animationDuration = 0.2;
+    
+    actionSheet.blurRadius = 0.0f;
+    actionSheet.blurTintColor = [UIColor colorWithWhite:0.0f alpha:0.50f];
+    
+    actionSheet.buttonHeight = 50.0;
+    actionSheet.cancelButtonHeight = 50.0f;
+    actionSheet.separatorHeight = 5.0f;
+    
+    actionSheet.automaticallyTintButtonImages = @(NO);
+    
+    actionSheet.encryptedButtonTextAttributes = @{ NSFontAttributeName:[UIFont systemFontOfSize:16], NSForegroundColorAttributeName:COLOR_CRYPTOCLOUD };
+    actionSheet.buttonTextAttributes = @{ NSFontAttributeName:[UIFont systemFontOfSize:16], NSForegroundColorAttributeName:COLOR_TEXT_ANTHRACITE };
+    actionSheet.cancelButtonTextAttributes = @{ NSFontAttributeName:[UIFont systemFontOfSize:16], NSForegroundColorAttributeName:COLOR_BRAND };
+    actionSheet.disableButtonTextAttributes = @{ NSFontAttributeName:[UIFont systemFontOfSize:16], NSForegroundColorAttributeName:COLOR_TEXT_ANTHRACITE };
+    
+    actionSheet.separatorColor = COLOR_SEPARATOR_TABLE;
+    actionSheet.cancelButtonTitle = NSLocalizedString(@"_cancel_",nil);
+    
+    // assegnamo l'immagine anteprima se esiste, altrimenti metti quella standars
+    if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"%@/%@.ico", app.directoryUser, metadata.fileID]])
+        iconHeader = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.ico", app.directoryUser, metadata.fileID]];
+    else
+        iconHeader = [UIImage imageNamed:metadata.iconName];
+    
+    [actionSheet addButtonWithTitle: metadata.fileNamePrint
+                              image: iconHeader
+                    backgroundColor: COLOR_TABBAR
+                             height: 50.0
+                               type: AHKActionSheetButtonTypeDisabled
+                            handler: nil
+    ];
+
+    // ONLY Root Favorites : Remove file/folder Favorites
+    if (_serverUrl == nil && [_pageType isEqualToString:k_pageOfflineFavorites]) {
+        
+        [actionSheet addButtonWithTitle:NSLocalizedString(@"_remove_favorites_", nil) image:[UIImage imageNamed:image_actionSheetOffline] backgroundColor:[UIColor whiteColor] height: 50.0 type:AHKActionSheetButtonTypeDefault handler:^(AHKActionSheet *as) {
+                                    
+            [self.tableView setEditing:NO animated:YES];
+            [[CCActions sharedInstance] settingFavorite:metadata favorite:NO delegate:self];
+        }];
+    }
+    
+    // ONLY Root Offline : Remove file/folder offline
+    if (_serverUrl == nil && [_pageType isEqualToString:k_pageOfflineOffline]) {
+        
+        [actionSheet addButtonWithTitle:NSLocalizedString(@"_remove_offline_", nil) image:[UIImage imageNamed:image_actionSheetOffline] backgroundColor:[UIColor whiteColor] height: 50.0 type:AHKActionSheetButtonTypeDefault handler:^(AHKActionSheet *as) {
+                                    
+            if (metadata.directory) {
+                                        
+                // remove tag offline for all folder/subfolder/file
+                NSString *relativeRoot = [CCCoreData getServerUrlFromDirectoryID:metadata.directoryID activeAccount:app.activeAccount];
+                NSString *dirServerUrl = [CCUtility stringAppendServerUrl:relativeRoot addFileName:metadata.fileNameData];
+                NSArray *directories = [CCCoreData getOfflineDirectoryActiveAccount:app.activeAccount];
+                                        
+                for (TableDirectory *directory in directories)
+                    if ([directory.serverUrl containsString:dirServerUrl]) {
+                        [CCCoreData setOfflineDirectoryServerUrl:directory.serverUrl offline:NO activeAccount:app.activeAccount];
+                        [CCCoreData removeOfflineAllFileFromServerUrl:directory.serverUrl activeAccount:app.activeAccount];
+                    }
+                                        
+            } else {
+                                        
+                [CCCoreData setOfflineLocalFileID:metadata.fileID offline:NO activeAccount:app.activeAccount];
+            }
+                                    
+            [self.tableView setEditing:NO animated:YES];
+                                    
+            [self reloadDatasource];
+        }];
+    }
+    
+    // Share
+    if (_metadata.cryptated == NO && app.hasServerShareSupport) {
+        
+        [actionSheet addButtonWithTitle:NSLocalizedString(@"_share_", nil)
+                                  image:[UIImage imageNamed:image_actionSheetShare]
+                        backgroundColor:[UIColor whiteColor]
+                                 height: 50.0
+                                   type:AHKActionSheetButtonTypeDefault
+                                handler:^(AHKActionSheet *as) {
+                                    
+                                    // close swipe
+                                    [self setEditing:NO animated:YES];
+                                    
+                                    [app.activeMain openWindowShare:metadata];
+                                }];
+    }
+
+    // NO Directory - NO Template
+    if (metadata.directory == NO && [metadata.type isEqualToString:k_metadataType_template] == NO) {
+        
+        [actionSheet addButtonWithTitle:NSLocalizedString(@"_open_in_", nil) image:[UIImage imageNamed:image_actionSheetOpenIn] backgroundColor:[UIColor whiteColor] height: 50.0 type:AHKActionSheetButtonTypeDefault handler:^(AHKActionSheet *as) {
+            
+            [self.tableView setEditing:NO animated:YES];
+            [self openWith:metadata];
+        }];
+    }
+    
+    [actionSheet addButtonWithTitle:NSLocalizedString(@"_delete_", nil) image:[UIImage imageNamed:image_delete] backgroundColor:[UIColor whiteColor] height: 50.0 type:AHKActionSheetButtonTypeDestructive handler:^(AHKActionSheet *as) {
+        
+        [self requestDeleteMetadata:metadata indexPath:indexPath];
+    }];
+
+    
+    [actionSheet show];
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ==== Table ====
+#pragma --------------------------------------------------------------------------------------------
+
+- (CCMetadata *)setSelfMetadataFromIndexPath:(NSIndexPath *)indexPath
+{
+    CCMetadata *metadata;
+    
+    if ([_pageType isEqualToString:k_pageOfflineFavorites] || [_pageType isEqualToString:k_pageOfflineOffline]) {
+        
+        NSManagedObject *record = [dataSource objectAtIndex:indexPath.row];
+        metadata = [CCCoreData getMetadataWithPreficate:[NSPredicate predicateWithFormat:@"(fileID == %@) AND (account == %@)", [record valueForKey:@"fileID"], app.activeAccount] context:nil];
+    }
+
+    if ([_pageType isEqualToString:k_pageOfflineLocal]) {
+        
+        NSString *cameraFolderName = [CCCoreData getCameraUploadFolderNameActiveAccount:app.activeAccount];
+        NSString *cameraFolderPath = [CCCoreData getCameraUploadFolderPathActiveAccount:app.activeAccount activeUrl:app.activeUrl];
+        
+        metadata = [CCUtility insertFileSystemInMetadata:[dataSource objectAtIndex:indexPath.row] directory:_serverUrl activeAccount:app.activeAccount cameraFolderName:cameraFolderName cameraFolderPath:cameraFolderPath];
+    }
+    
+    return metadata;
+}
+
+- (void)readFolderWithForced:(BOOL)forced serverUrl:(NSString *)serverUrl
+{
+    [self reloadDatasource];
+}
+
+- (void)reloadDatasource
+{
+    if ([_pageType isEqualToString:k_pageOfflineFavorites]) {
+        
+        NSMutableArray *metadatas = [NSMutableArray new];
+        NSArray *recordsTableMetadata ;
+        
+        if (!_serverUrl) {
+            
+            recordsTableMetadata = [CCCoreData  getTableMetadataWithPredicate:[NSPredicate predicateWithFormat:@"(account == %@) AND (favorite == 1)", app.activeAccount] context:nil];
+            
+        } else {
+            
+            NSString *directoryID = [CCCoreData getDirectoryIDFromServerUrl:_serverUrl activeAccount:app.activeAccount];
+            recordsTableMetadata = [CCCoreData getTableMetadataWithPredicate:[NSPredicate predicateWithFormat:@"(account == %@) AND (directoryID == %@)", app.activeAccount, directoryID] fieldOrder:[CCUtility getOrderSettings]  ascending:[CCUtility getAscendingSettings]];
+        }
+        
+        CCSectionDataSourceMetadata *sectionDataSource = [CCSectionMetadata creataDataSourseSectionMetadata:recordsTableMetadata listProgressMetadata:nil groupByField:nil replaceDateToExifDate:NO activeAccount:app.activeAccount];
+        
+        NSArray *fileIDs = [sectionDataSource.sectionArrayRow objectForKey:@"_none_"];
+        for (NSString *fileID in fileIDs)
+            [metadatas addObject:[sectionDataSource.allRecordsDataSource objectForKey:fileID]];
+        
+        dataSource = [NSArray arrayWithArray:metadatas];
+    }
+
+    if ([_pageType isEqualToString:k_pageOfflineOffline]) {
+        
+        NSMutableArray *metadatas = [NSMutableArray new];
+        NSArray *recordsTableMetadata ;
+        
+        if (!_serverUrl) {
+            
+            recordsTableMetadata = [CCCoreData getHomeOfflineActiveAccount:app.activeAccount directoryUser:app.directoryUser fieldOrder:[CCUtility getOrderSettings] ascending:[CCUtility getAscendingSettings]];
+            
+        } else {
+            
+            NSString *directoryID = [CCCoreData getDirectoryIDFromServerUrl:_serverUrl activeAccount:app.activeAccount];
+            recordsTableMetadata = [CCCoreData getTableMetadataWithPredicate:[NSPredicate predicateWithFormat:@"(account == %@) AND (directoryID == %@)", app.activeAccount, directoryID] fieldOrder:[CCUtility getOrderSettings]  ascending:[CCUtility getAscendingSettings]];
+        }
+        
+        CCSectionDataSourceMetadata *sectionDataSource = [CCSectionMetadata creataDataSourseSectionMetadata:recordsTableMetadata listProgressMetadata:nil groupByField:nil replaceDateToExifDate:NO activeAccount:app.activeAccount];
+            
+        NSArray *fileIDs = [sectionDataSource.sectionArrayRow objectForKey:@"_none_"];
+        for (NSString *fileID in fileIDs)
+            [metadatas addObject:[sectionDataSource.allRecordsDataSource objectForKey:fileID]];
+            
+        dataSource = [NSArray arrayWithArray:metadatas];
+    }
+    
+    if ([_pageType isEqualToString:k_pageOfflineLocal]) {
+        
+        NSArray *subpaths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:_serverUrl error:nil];
+        NSMutableArray *metadatas = [NSMutableArray new];
+        
+        for (NSString *subpath in subpaths)
+            if (![[subpath lastPathComponent] hasPrefix:@"."])
+                [metadatas addObject:subpath];
+        
+        dataSource = [NSArray arrayWithArray:metadatas];
+    }
+    
+    [self.tableView reloadData];
+}
+
+- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    return 60;
+}
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
+{
+    return 1;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+    return [dataSource count];
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    CCCellOffline *cell = (CCCellOffline *)[tableView dequeueReusableCellWithIdentifier:@"OfflineCell" forIndexPath:indexPath];
+    CCMetadata *metadata;
+    
+    // separator
+    cell.separatorInset = UIEdgeInsetsMake(0.f, 60.f, 0.f, 0.f);
+    
+    // Initialize
+    cell.statusImageView.image = nil;
+    cell.offlineImageView.image = nil;
+    
+    // change color selection
+    UIView *selectionColor = [[UIView alloc] init];
+    selectionColor.backgroundColor = COLOR_SELECT_BACKGROUND;
+    cell.selectedBackgroundView = selectionColor;
+    
+    // i am in Favorites OR i am in Offline
+    if ([_pageType isEqualToString:k_pageOfflineFavorites] || [_pageType isEqualToString:k_pageOfflineOffline]) {
+        
+        metadata = [dataSource objectAtIndex:indexPath.row];
+        
+        cell.fileImageView.image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.ico", app.directoryUser, metadata.fileID]];
+        
+        if (_serverUrl == nil) {
+            
+            if ([_pageType isEqualToString:k_pageOfflineFavorites])
+                cell.offlineImageView.image = [UIImage imageNamed:image_favorite];
+            if ([_pageType isEqualToString:k_pageOfflineOffline])
+                cell.offlineImageView.image = [UIImage imageNamed:image_offline];
+        }
+        
+        if (cell.fileImageView.image == nil && metadata.thumbnailExists)
+            [[CCActions sharedInstance] downloadTumbnail:metadata delegate:self];
+    }
+
+    // i am in local
+    if ([_pageType isEqualToString:k_pageOfflineLocal]) {
+        
+        NSString *cameraFolderName = [CCCoreData getCameraUploadFolderNameActiveAccount:app.activeAccount];
+        NSString *cameraFolderPath = [CCCoreData getCameraUploadFolderPathActiveAccount:app.activeAccount activeUrl:app.activeUrl];
+        
+        metadata = [CCUtility insertFileSystemInMetadata:[dataSource objectAtIndex:indexPath.row] directory:_serverUrl activeAccount:app.activeAccount cameraFolderName:cameraFolderName cameraFolderPath:cameraFolderPath];
+        
+        cell.fileImageView.image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/.%@.ico", _serverUrl, metadata.fileNamePrint]];
+        
+        if (!cell.fileImageView.image) {
+            
+            UIImage *icon = [CCGraphics createNewImageFrom:metadata.fileID directoryUser:_serverUrl fileNameTo:metadata.fileID fileNamePrint:metadata.fileNamePrint size:@"m" imageForUpload:NO typeFile:metadata.typeFile writePreview:NO optimizedFileName:[CCUtility getOptimizedPhoto]];
+            
+            if (icon) {
+                [CCGraphics saveIcoWithFileID:metadata.fileNamePrint image:icon writeToFile:[NSString stringWithFormat:@"%@/.%@.ico", _serverUrl, metadata.fileNamePrint] copy:NO move:NO fromPath:nil toPath:nil];
+                cell.fileImageView.image = icon;
+            }
+        }
+    }
+    
+    // ButtonDown Tapped
+    [cell.buttonDown addTarget:self action:@selector(cellButtonDownWasTapped:) forControlEvents:UIControlEventTouchUpInside];
+    
+    // encrypted color
+    if (metadata.cryptated) {
+        cell.labelTitle.textColor = COLOR_CRYPTOCLOUD;
+    } else {
+        cell.labelTitle.textColor = [UIColor blackColor];
+    }
+    
+    // File name
+    cell.labelTitle.text = metadata.fileNamePrint;
+    cell.labelInfoFile.text = @"";
+    
+    // Immagine del file, se non c'è l'anteprima mettiamo quella standard
+    if (cell.fileImageView.image == nil)
+        cell.fileImageView.image = [UIImage imageNamed:metadata.iconName];
+    
+    // it's encrypted ???
+    if (metadata.cryptated && [metadata.type isEqualToString: k_metadataType_template] == NO)
+        cell.statusImageView.image = [UIImage imageNamed:image_lock];
+    
+    // text and length
+    if (metadata.directory) {
+        
+        cell.labelInfoFile.text = [CCUtility dateDiff:metadata.date];
+        cell.accessoryType = UITableViewCellAccessoryNone;
+        //cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+          
+    } else {
+        
+        NSString *date = [CCUtility dateDiff:metadata.date];
+        NSString *length = [CCUtility transformedSize:metadata.size];
+        
+        if ([metadata.type isEqualToString: k_metadataType_template])
+            cell.labelInfoFile.text = [NSString stringWithFormat:@"%@", date];
+        
+        if ([metadata.type isEqualToString: k_metadataType_file] || [metadata.type isEqualToString: k_metadataType_local]) {
+            
+            BOOL fileExists = NO;
+            
+            if ([_pageType isEqualToString:k_pageOfflineLocal])
+                fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"%@/%@", _serverUrl, metadata.fileName]];
+            
+            if ([_pageType isEqualToString:k_pageOfflineFavorites] || [_pageType isEqualToString:k_pageOfflineOffline])
+                fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"%@/%@", app.directoryUser, metadata.fileID]];
+            
+            if (fileExists)
+                cell.labelInfoFile.text = [NSString stringWithFormat:@"%@ • %@", date, length];
+            else
+                cell.labelInfoFile.text = [NSString stringWithFormat:@"%@ ◦ %@", date, length];
+        }
+        
+        cell.accessoryType = UITableViewCellAccessoryNone;
+        
+    }
+    
+    return cell;
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    // deselect row
+    [tableView deselectRowAtIndexPath:indexPath animated:YES];
+    
+    _metadata = [self setSelfMetadataFromIndexPath:indexPath];
+    
+    // if is in download [do not touch]
+    if ([_metadata.session length] > 0 && [_metadata.session containsString:@"download"])
+        return;
+    
+    // File
+    if (([_metadata.type isEqualToString: k_metadataType_file] || [_metadata.type isEqualToString: k_metadataType_local]) && _metadata.directory == NO) {
+        
+        // i am in local
+        if ([_pageType isEqualToString:k_pageOfflineLocal]) {
+            
+            if ([self shouldPerformSegue])
+                [self performSegueWithIdentifier:@"segueDetail" sender:self];
+
+        } else {
+            
+            if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"%@/%@", app.directoryUser, _metadata.fileID]]) {
+            
+                // File exists
+                if ([self shouldPerformSegue])
+                    [self performSegueWithIdentifier:@"segueDetail" sender:self];
+
+            } else {
+            
+                // File do not exists
+                NSString *serverUrl = [CCCoreData getServerUrlFromDirectoryID:_metadata.directoryID activeAccount:_metadata.account];
+
+                [[CCNetworking sharedNetworking] downloadFile:_metadata serverUrl:serverUrl downloadData:YES downloadPlist:NO selector:selectorLoadFileView selectorPost:nil session:k_download_session taskStatus:k_taskStatusResume delegate:self];
+            }
+        }
+    }
+    
+    // Model
+    if ([self.metadata.type isEqualToString: k_metadataType_template])
+        [self openModel:self.metadata];
+    
+    // Directory
+    if (_metadata.directory)
+        [self performSegueDirectoryWithControlPasscode];
+}
+
+-(void)performSegueDirectoryWithControlPasscode
+{
+    CCFavorite *vc = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"CCFavoriteCCFavorite"];
+    
+    NSString *serverUrl;
+    
+    if (([_pageType isEqualToString:k_pageOfflineFavorites] || [_pageType isEqualToString:k_pageOfflineOffline]) && !_serverUrl) {
+    
+        serverUrl = [CCCoreData getServerUrlFromDirectoryID:_metadata.directoryID activeAccount:app.activeAccount];
+        
+    } else {
+        
+        serverUrl = _serverUrl;
+    }
+        
+    vc.serverUrl = [CCUtility stringAppendServerUrl:serverUrl addFileName:_metadata.fileNameData];
+    vc.pageType = _pageType;
+    vc.titleViewControl = _metadata.fileNamePrint;
+    
+    [self.navigationController pushViewController:vc animated:YES];
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ===== Navigation ====
+#pragma --------------------------------------------------------------------------------------------
+
+- (BOOL)shouldPerformSegue
+{
+    // if i am in background -> exit
+    if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground) return NO;
+    
+    // if i am not window -> exit
+    if (self.view.window == NO)
+        return NO;
+    
+    // Collapsed but i am in detail -> exit
+    if (self.splitViewController.isCollapsed)
+        if (self.detailViewController.isViewLoaded && self.detailViewController.view.window) return NO;
+    
+    // Video in run -> exit
+    if (self.detailViewController.photoBrowser.currentVideoPlayerViewController.isViewLoaded && self.detailViewController.photoBrowser.currentVideoPlayerViewController.view.window) return NO;
+    
+    return YES;
+}
+
+-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
+{
+    id viewController = segue.destinationViewController;
+    
+    if ([viewController isKindOfClass:[UINavigationController class]]) {
+        UINavigationController *nav = viewController;
+        _detailViewController = (CCDetail *)nav.topViewController;
+    } else {
+        _detailViewController = segue.destinationViewController;
+    }
+    
+    NSMutableArray *allRecordsDataSourceImagesVideos = [NSMutableArray new];
+    
+    if ([self.pageType isEqualToString:k_pageOfflineFavorites] || [self.pageType isEqualToString:k_pageOfflineOffline]) {
+        
+        for (CCMetadata *metadata in dataSource) {
+            if ([metadata.typeFile isEqualToString: k_metadataTypeFile_image] || [metadata.typeFile isEqualToString: k_metadataTypeFile_video])
+                [allRecordsDataSourceImagesVideos addObject:metadata];
+        }
+    }
+    
+    if ([self.pageType isEqualToString:k_pageOfflineLocal]) {
+        
+        NSString *cameraFolderName = [CCCoreData getCameraUploadFolderNameActiveAccount:app.activeAccount];
+        NSString *cameraFolderPath = [CCCoreData getCameraUploadFolderPathActiveAccount:app.activeAccount activeUrl:app.activeUrl];
+        
+        for (NSString *fileName in dataSource) {
+            
+            CCMetadata *metadata = [CCMetadata new];
+            metadata = [CCUtility insertFileSystemInMetadata:fileName directory:_serverUrl activeAccount:app.activeAccount cameraFolderName:cameraFolderName cameraFolderPath:cameraFolderPath];
+            
+            if ([metadata.typeFile isEqualToString: k_metadataTypeFile_image] || [metadata.typeFile isEqualToString: k_metadataTypeFile_video])
+                [allRecordsDataSourceImagesVideos addObject:metadata];
+        }
+        
+        _detailViewController.sourceDirectoryLocal = YES;
+    }
+    
+    _detailViewController.metadataDetail = _metadata;
+    _detailViewController.dateFilterQuery = nil;
+    _detailViewController.isCameraUpload = NO;
+    _detailViewController.dataSourceImagesVideos = allRecordsDataSourceImagesVideos;
+
+    
+    [_detailViewController setTitle:_metadata.fileNamePrint];
+}
+
+@end

+ 45 - 0
iOSClient/Favorite/CCFavoriteCell.h

@@ -0,0 +1,45 @@
+//
+//  CCFavoriteCell.h
+//  Crypto Cloud Technology Nextcloud
+//
+//  Created by Marino Faggiana on 05/05/15.
+//  Copyright (c) 2014 TWS. All rights reserved.
+//
+//  Author Marino Faggiana <m.faggiana@twsweb.it>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface CCFavoriteCell : UITableViewCell
+
+@property(nonatomic, weak) IBOutlet UIImageView *fileImageView;
+@property(nonatomic, weak) IBOutlet UIImageView *statusImageView;
+@property(nonatomic, weak) IBOutlet UIImageView *offlineImageView;
+
+@property(nonatomic, weak) IBOutlet UILabel *labelTitle;
+@property(nonatomic, weak) IBOutlet UILabel *labelInfoFile;
+
+@property(nonatomic, weak) IBOutlet UIButton *buttonDown;
+
+@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *constraints;
+
+//Last position of the scroll of the swipe
+@property (nonatomic, assign) CGFloat lastContentOffset;
+
+//Index path of the cell swipe gesture ocured
+@property (nonatomic, strong) NSIndexPath *indexPath;
+
+@end

+ 68 - 0
iOSClient/Favorite/CCFavoriteCell.m

@@ -0,0 +1,68 @@
+//
+//  CCFavoriteCell.m
+//  Crypto Cloud Technology Nextcloud
+//
+//  Created by Marino Faggiana on 05/05/15.
+//  Copyright (c) 2014 TWS. All rights reserved.
+//
+//  Author Marino Faggiana <m.faggiana@twsweb.it>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "CCFavoriteCell.h"
+
+@implementation CCFavoriteCell
+
+- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
+{
+    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
+    if (self) {
+        // Initialization code
+
+        
+    }
+    return self;
+}
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated
+{
+    [super setSelected:selected animated:animated];
+
+    // Configure the view for the selected state
+}
+
+- (void)layoutSubviews {
+    
+    [super layoutSubviews];
+    
+    for (NSLayoutConstraint *constraint in self.constraints) {
+        constraint.constant = self.frame.size.width - self.contentView.frame.size.width;
+    }
+}
+
+///-----------------------------------
+/// @name scrollViewWillBeginDecelerating
+///-----------------------------------
+
+/**
+ * Method to initialize the position where we make the swipe in order to detect the direction
+ *
+ * @param UIScrollView -> scrollView
+ */
+- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView {
+    _lastContentOffset = scrollView.contentOffset.x;
+}
+
+@end

+ 107 - 0
iOSClient/Favorite/CCFavoriteCell.xib

@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12086"/>
+        <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CustomCellFileAndDirectory"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <tableViewCell contentMode="scaleToFill" selectionStyle="blue" indentationWidth="0.0" reuseIdentifier="Cell" rowHeight="60" id="2" userLabel="CCFavoriteCell" customClass="CCFavoriteCell">
+            <rect key="frame" x="0.0" y="0.0" width="600" height="60"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxY="YES"/>
+            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="2" id="sQq-jC-UEV">
+                <rect key="frame" x="0.0" y="0.0" width="600" height="59.5"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <view alpha="0.10000000149011612" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hzp-7C-oyF" userLabel="Gray">
+                        <rect key="frame" x="0.0" y="0.0" width="60" height="60"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                        <color key="backgroundColor" red="0.66666666669999997" green="0.66666666669999997" blue="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                    </view>
+                    <label opaque="NO" userInteractionEnabled="NO" tag="101" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QNC-8X-DAC">
+                        <rect key="frame" x="68" y="13" width="473" height="20"/>
+                        <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                        <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                        <nil key="highlightedColor"/>
+                    </label>
+                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5">
+                        <rect key="frame" x="8" y="11" width="40" height="40"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="40" id="7r4-ao-ayY"/>
+                            <constraint firstAttribute="height" constant="40" id="cGI-9B-eWe"/>
+                        </constraints>
+                    </imageView>
+                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="DQR-yN-JaH">
+                        <rect key="frame" x="37" y="40" width="15" height="15"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="15" id="O4C-De-dnI"/>
+                            <constraint firstAttribute="height" constant="15" id="bun-Ao-Ysu"/>
+                        </constraints>
+                    </imageView>
+                    <label opaque="NO" userInteractionEnabled="NO" tag="102" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p7I-KN-FVZ">
+                        <rect key="frame" x="68" y="33" width="473" height="15"/>
+                        <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                        <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
+                        <nil key="highlightedColor"/>
+                    </label>
+                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="dhG-hb-z3n" userLabel="Offline Image View">
+                        <rect key="frame" x="4" y="40" width="15" height="15"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="15" id="ZiA-bt-IkC"/>
+                            <constraint firstAttribute="height" constant="15" id="aQq-XY-pNM"/>
+                        </constraints>
+                    </imageView>
+                    <button opaque="NO" alpha="0.40000000000000002" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6B9-Jc-esJ" userLabel="buttonDown">
+                        <rect key="frame" x="541" y="0.0" width="60" height="60"/>
+                        <constraints>
+                            <constraint firstAttribute="height" constant="60" id="PcN-jN-71v"/>
+                            <constraint firstAttribute="width" constant="60" id="bAG-EX-HKe"/>
+                        </constraints>
+                        <state key="normal" image="buttonDown"/>
+                    </button>
+                </subviews>
+                <constraints>
+                    <constraint firstItem="p7I-KN-FVZ" firstAttribute="leading" secondItem="DQR-yN-JaH" secondAttribute="trailing" constant="16" id="2xR-G4-B2S"/>
+                    <constraint firstItem="dhG-hb-z3n" firstAttribute="top" secondItem="sQq-jC-UEV" secondAttribute="topMargin" constant="32" id="4Zy-SY-nfT"/>
+                    <constraint firstItem="QNC-8X-DAC" firstAttribute="trailing" secondItem="sQq-jC-UEV" secondAttribute="trailingMargin" constant="-51" id="7zt-c0-CsI"/>
+                    <constraint firstItem="6B9-Jc-esJ" firstAttribute="centerY" secondItem="5" secondAttribute="centerY" constant="-1" id="EoB-vw-kgn"/>
+                    <constraint firstAttribute="centerY" secondItem="5" secondAttribute="centerY" constant="-1.5" id="FQP-wg-vPF"/>
+                    <constraint firstItem="DQR-yN-JaH" firstAttribute="top" secondItem="p7I-KN-FVZ" secondAttribute="top" constant="6.5" id="K6B-gJ-8Fp"/>
+                    <constraint firstItem="p7I-KN-FVZ" firstAttribute="leading" secondItem="5" secondAttribute="trailing" constant="20" id="K7G-0u-f8E"/>
+                    <constraint firstItem="5" firstAttribute="bottom" secondItem="p7I-KN-FVZ" secondAttribute="bottom" constant="3" id="MuE-C8-4UJ"/>
+                    <constraint firstItem="QNC-8X-DAC" firstAttribute="leading" secondItem="5" secondAttribute="trailing" constant="20" id="UYc-Al-a4h"/>
+                    <constraint firstItem="dhG-hb-z3n" firstAttribute="leading" secondItem="sQq-jC-UEV" secondAttribute="leadingMargin" constant="-4" id="dNM-6x-zkx"/>
+                    <constraint firstItem="5" firstAttribute="leading" secondItem="sQq-jC-UEV" secondAttribute="leadingMargin" id="ha0-VA-fF9"/>
+                    <constraint firstItem="p7I-KN-FVZ" firstAttribute="trailing" secondItem="sQq-jC-UEV" secondAttribute="trailingMargin" constant="-51" id="kaB-WS-bDl"/>
+                    <constraint firstItem="5" firstAttribute="top" secondItem="QNC-8X-DAC" secondAttribute="top" constant="-2" id="lyH-lh-z03"/>
+                    <constraint firstItem="6B9-Jc-esJ" firstAttribute="leading" secondItem="QNC-8X-DAC" secondAttribute="trailing" id="mBS-nt-t6R"/>
+                    <constraint firstItem="5" firstAttribute="top" secondItem="sQq-jC-UEV" secondAttribute="topMargin" constant="3" id="pRH-CQ-O4x"/>
+                </constraints>
+            </tableViewCellContentView>
+            <connections>
+                <outlet property="buttonDown" destination="6B9-Jc-esJ" id="tb8-y2-OM0"/>
+                <outlet property="fileImageView" destination="5" id="6"/>
+                <outlet property="labelInfoFile" destination="p7I-KN-FVZ" id="5Yb-hH-k73"/>
+                <outlet property="labelTitle" destination="QNC-8X-DAC" id="dFX-Cb-8IE"/>
+                <outlet property="offlineImageView" destination="dhG-hb-z3n" id="IGh-6c-M89"/>
+                <outlet property="statusImageView" destination="DQR-yN-JaH" id="UmC-pt-kjV"/>
+                <outletCollection property="constraints" destination="mBS-nt-t6R" id="4sz-P1-CPa"/>
+            </connections>
+            <point key="canvasLocation" x="316" y="128"/>
+        </tableViewCell>
+    </objects>
+    <resources>
+        <image name="buttonDown" width="25" height="25"/>
+    </resources>
+    <simulatedMetricsContainer key="defaultSimulatedMetrics">
+        <simulatedStatusBarMetrics key="statusBar"/>
+        <simulatedOrientationMetrics key="orientation"/>
+        <simulatedScreenMetrics key="destination" type="retina4_7.fullscreen"/>
+    </simulatedMetricsContainer>
+</document>

+ 50 - 0
iOSClient/Favorite/CCSynchronize.h

@@ -0,0 +1,50 @@
+//
+//  CCSynchronize.h
+//  Crypto Cloud Technology Nextcloud
+//
+//  Created by Marino Faggiana on 19/10/16.
+//  Copyright (c) 2016 TWS. All rights reserved.
+//
+//  Author Marino Faggiana <m.faggiana@twsweb.it>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import <Foundation/Foundation.h>
+
+#import "CCMetadata.h"
+#import "CCHud.h"
+#import "CCCellMain.h"
+
+@interface CCSynchronize : NSObject
+
+@property (nonatomic, strong) CCHud *hud;
+
++ (CCSynchronize *)sharedSynchronize;
+
+@property (nonatomic, strong) NSMutableOrderedSet *foldersInSynchronized;
+
+- (void)readListingFavorites;
+- (void)readOffline;
+
+- (void)addFavoriteFolder:(NSString *)serverUrl;
+- (void)addOfflineFolder:(NSString *)serverUrl;
+
+- (void)verifyChangeMedatas:(NSArray *)allRecordMetadatas serverUrl:(NSString *)serverUrl account:(NSString *)account withDownload:(BOOL)withDownload;
+
+- (BOOL)synchronizeFolderAnimationDirectory:(NSArray *)directory setGraphicsFolder:(BOOL)setGraphicsFolder;
+
+- (void)readFolderServerUrl:(NSString *)serverUrl directoryID:(NSString *)directoryID selector:(NSString *)selector;
+
+@end

+ 604 - 0
iOSClient/Favorite/CCSynchronize.m

@@ -0,0 +1,604 @@
+//
+//  CCSynchronize.m
+//  Crypto Cloud Technology Nextcloud
+//
+//  Created by Marino Faggiana on 19/10/16.
+//  Copyright (c) 2016 TWS. All rights reserved.
+//
+//  Author Marino Faggiana <m.faggiana@twsweb.it>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+#import "CCSynchronize.h"
+
+#import "AppDelegate.h"
+#import "CCCoreData.h"
+#import "CCMain.h"
+
+#ifdef CUSTOM_BUILD
+    #import "CustomSwift.h"
+#else
+    #import "Nextcloud-Swift.h"
+#endif
+
+
+@interface CCSynchronize () <CCActionsListingFavoritesDelegate>
+{
+    // local
+}
+@end
+
+@implementation CCSynchronize
+
++ (CCSynchronize *)sharedSynchronize {
+    
+    static CCSynchronize *sharedSynchronize;
+    
+    @synchronized(self)
+    {
+        if (!sharedSynchronize) {
+            
+            sharedSynchronize = [CCSynchronize new];
+            
+            sharedSynchronize.foldersInSynchronized = [NSMutableOrderedSet new];
+        }
+        return sharedSynchronize;
+    }
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ===== Read Listing Favorites =====
+#pragma --------------------------------------------------------------------------------------------
+
+- (void)readListingFavorites
+{
+    // test
+    if (app.activeAccount.length == 0)
+        return;
+    
+    // verify is offline procedure is in progress selectorDownloadSynchronize
+    if ([[app verifyExistsInQueuesDownloadSelector:selectorDownloadSynchronize] count] > 0)
+        return;
+    
+    [[CCActions sharedInstance] listingFavorites:@"" delegate:self];
+}
+
+- (void)addFavoriteFolder:(NSString *)serverUrl
+{
+    NSString *directoryID = [CCCoreData getDirectoryIDFromServerUrl:serverUrl activeAccount:app.activeAccount];
+    NSString *selector;
+    CCMetadataNet *metadataNet = [[CCMetadataNet alloc] initWithAccount:app.activeAccount];
+    
+    metadataNet.action = actionReadFolder;
+    metadataNet.directoryID = directoryID;
+    metadataNet.priority = NSOperationQueuePriorityNormal;
+    
+    if ([CCUtility getFavoriteOffline])
+        selector = selectorReadFolderWithDownload;
+    else
+        selector = selectorReadFolder;
+    
+    metadataNet.selector = selector;
+    metadataNet.serverUrl = serverUrl;
+    
+    [app addNetworkingOperationQueue:app.netQueue delegate:self metadataNet:metadataNet];
+}
+
+- (void)listingFavoritesSuccess:(CCMetadataNet *)metadataNet metadatas:(NSArray *)metadatas
+{
+    // verify active user
+    TableAccount *record = [CCCoreData getActiveAccount];
+    
+    if (![record.account isEqualToString:metadataNet.account])
+        return;
+    
+    NSString *father = @"";
+    NSMutableArray *filesID = [NSMutableArray new];
+    
+    for (CCMetadata *metadata in metadatas) {
+        
+        // type of file
+        NSInteger typeFilename = [CCUtility getTypeFileName:metadata.fileName];
+        
+        // do not insert cryptated favorite file
+        if (typeFilename == k_metadataTypeFilenameCrypto || typeFilename == k_metadataTypeFilenamePlist)
+            continue;
+
+        // Delete Record NOT in session
+        [CCCoreData deleteMetadataWithPredicate:[NSPredicate predicateWithFormat:@"(account == %@) AND (directoryID == %@) AND (fileID = %@) AND ((session == NULL) OR (session == ''))", app.activeAccount, metadata.directoryID, metadata.fileID]];
+        
+        // end test, insert in CoreData
+        [CCCoreData addMetadata:metadata activeAccount:app.activeAccount activeUrl:app.activeUrl context:nil];
+        
+        // insert for test NOT favorite
+        [filesID addObject:metadata.fileID];
+        
+        // ---- Synchronized ----
+        
+        // Get ServerUrl
+        NSString* serverUrl = [CCCoreData getServerUrlFromDirectoryID:metadata.directoryID activeAccount:app.activeAccount];
+        serverUrl = [CCUtility stringAppendServerUrl:serverUrl addFileName:metadata.fileNameData];
+        
+        if (![serverUrl containsString:father]) {
+            
+            if (metadata.directory) {
+                
+                NSString *directoryID = [CCCoreData getDirectoryIDFromServerUrl:serverUrl activeAccount:app.activeAccount];
+                NSString *selector;
+                
+                if ([CCUtility getFavoriteOffline])
+                    selector = selectorReadFolderWithDownload;
+                else
+                    selector = selectorReadFolder;
+                
+                [self readFolderServerUrl:serverUrl directoryID:directoryID selector:selector];
+                
+            } else {
+                
+                if ([CCUtility getFavoriteOffline])
+                    [self readFile:metadata withDownload:YES];
+                else
+                    [self readFile:metadata withDownload:NO];
+            }
+            
+            father = serverUrl;
+        }
+    }
+    
+    // Verify remove favorite
+    NSArray *allRecordFavorite = [CCCoreData getTableMetadataWithPredicate:[NSPredicate predicateWithFormat:@"(account == %@) AND (favorite == 1)", app.activeAccount] context:nil];
+    
+    for (TableMetadata *tableMetadata in allRecordFavorite)
+        if (![filesID containsObject:tableMetadata.fileID])
+            [CCCoreData setMetadataFavoriteFileID:tableMetadata.fileID favorite:NO activeAccount:app.activeAccount context:nil];
+    
+    [[NSNotificationCenter defaultCenter] postNotificationName:@"clearDateReadDataSource" object:nil];
+}
+
+- (void)listingFavoritesFailure:(CCMetadataNet *)metadataNet message:(NSString *)message errorCode:(NSInteger)errorCode
+{
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ===== Read Offline =====
+#pragma --------------------------------------------------------------------------------------------
+
+- (void)readOffline
+{
+    // test
+    if (app.activeAccount.length == 0)
+        return;
+    
+    // verify is offline procedure is in progress selectorDownloadSynchronize
+    if ([[app verifyExistsInQueuesDownloadSelector:selectorDownloadSynchronize] count] > 0)
+        return;
+    
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
+        
+        NSString *father = @"";
+        NSArray *directories = [CCCoreData getOfflineDirectoryActiveAccount:app.activeAccount];
+
+        for (TableDirectory *directory in directories) {
+        
+            if (![directory.serverUrl containsString:father]) {
+             
+                father = directory.serverUrl;
+                [self readFolderServerUrl:directory.serverUrl directoryID:directory.directoryID selector:selectorReadFolder];
+            }
+        }
+        
+        NSArray *metadatas = [CCCoreData getOfflineLocalFileActiveAccount:app.activeAccount directoryUser:app.directoryUser];
+        
+        for (CCMetadata *metadata in metadatas) {
+            
+            [self readFile:metadata withDownload:YES];
+        }
+    });
+}
+
+//
+// Add Folder offline
+//
+- (void)addOfflineFolder:(NSString *)serverUrl
+{
+    NSString *directoryID = [CCCoreData getDirectoryIDFromServerUrl:serverUrl activeAccount:app.activeAccount];
+    
+    // Set offline directory
+    [CCCoreData setOfflineDirectoryServerUrl:serverUrl offline:YES activeAccount:app.activeAccount];
+    
+    CCMetadataNet *metadataNet = [[CCMetadataNet alloc] initWithAccount:app.activeAccount];
+    
+    metadataNet.action = actionReadFolder;
+    metadataNet.directoryID = directoryID;
+    metadataNet.priority = NSOperationQueuePriorityNormal;
+    metadataNet.selector = selectorReadFolder;
+    metadataNet.serverUrl = serverUrl;
+    
+    [app addNetworkingOperationQueue:app.netQueue delegate:self metadataNet:metadataNet];    
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ===== Read Folder =====
+#pragma --------------------------------------------------------------------------------------------
+
+// MULTI THREAD
+- (void)readFolderServerUrl:(NSString *)serverUrl directoryID:(NSString *)directoryID selector:(NSString *)selector
+{
+    CCMetadataNet *metadataNet = [[CCMetadataNet alloc] initWithAccount:app.activeAccount];
+    
+    metadataNet.action = actionReadFolder;
+    metadataNet.directoryID = directoryID;
+    metadataNet.priority = NSOperationQueuePriorityNormal;
+    metadataNet.selector = selector;
+    metadataNet.serverUrl = serverUrl;
+    
+    dispatch_async(dispatch_get_main_queue(), ^{
+        [app addNetworkingOperationQueue:app.netQueue delegate:self metadataNet:metadataNet];
+    });
+    
+    NSLog(@"[LOG] %@ directory : %@", selector, serverUrl);
+}
+
+- (void)readFolderFailure:(CCMetadataNet *)metadataNet message:(NSString *)message errorCode:(NSInteger)errorCode
+{
+    // verify active user
+    TableAccount *recordAccount = [CCCoreData getActiveAccount];
+    
+    // Folder not present, remove it
+    if (errorCode == 404 && [recordAccount.account isEqualToString:metadataNet.account])
+        [CCCoreData deleteDirectoryAndSubDirectory:metadataNet.serverUrl activeAccount:app.activeAccount];
+}
+
+// MULTI THREAD
+- (void)readFolderSuccess:(CCMetadataNet *)metadataNet permissions:(NSString *)permissions etag:(NSString *)etag metadatas:(NSArray *)metadatas
+{
+    TableAccount *recordAccount = [CCCoreData getActiveAccount];
+    
+    __block NSMutableArray *metadatasForVerifyChange = [NSMutableArray new];
+    
+    if ([recordAccount.account isEqualToString:metadataNet.account] == NO)
+        return;
+    
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
+        
+        NSArray *recordsInSessions = [CCCoreData getTableMetadataWithPredicate:[NSPredicate predicateWithFormat:@"(account == %@) AND (directoryID == %@) AND (session != NULL) AND (session != '')", app.activeAccount, metadataNet.directoryID] context:nil];
+        
+        // ----- Test : (DELETE) -----
+        
+        NSMutableArray *metadatasNotPresents = [[NSMutableArray alloc] init];
+        NSArray *tableMetadatas = [CCCoreData getTableMetadataWithPredicate:[NSPredicate predicateWithFormat:@"(account == %@) AND (directoryID == %@) AND ((session == NULL) OR (session == ''))", app.activeAccount, metadataNet.directoryID] context:nil];
+        
+        for (TableMetadata *tableMetadata in tableMetadatas) {
+            
+            // reject cryptated
+            if (tableMetadata.cryptated)
+                continue;
+            
+            BOOL fileIDFound = NO;
+            
+            for (CCMetadata *metadata in metadatas) {
+                
+                if ([tableMetadata.fileID isEqualToString:metadata.fileID]) {
+                    fileIDFound = YES;
+                    break;
+                }
+            }
+            
+            if (!fileIDFound)
+                [metadatasNotPresents addObject:[CCCoreData insertEntityInMetadata:tableMetadata]];
+        }
+        
+        dispatch_async(dispatch_get_main_queue(), ^{
+            
+            // delete metadata not present
+            for (CCMetadata *metadata in metadatasNotPresents) {
+                
+                [CCCoreData deleteFile:metadata serverUrl:metadataNet.serverUrl directoryUser:app.directoryUser activeAccount:app.activeAccount];
+            }
+            
+            if ([metadatasNotPresents count] > 0)
+                [app.activeMain reloadDatasource:metadataNet.serverUrl fileID:nil selector:nil];
+        });
+        
+        // ----- Test : (MODIFY) -----
+        
+        for (CCMetadata *metadata in metadatas) {
+            
+            // reject cryptated
+            if (metadata.cryptated)
+                continue;
+            
+            // dir recursive
+            if (metadata.directory) {
+                
+                NSString *serverUrl = [CCUtility stringAppendServerUrl:metadataNet.serverUrl addFileName:metadata.fileNameData];
+                NSString *directoryID = [CCCoreData getDirectoryIDFromServerUrl:serverUrl activeAccount:app.activeAccount];
+                    
+                // Verify if do not exists this Metadata
+                if (![CCCoreData getTableMetadataWithPreficate:[NSPredicate predicateWithFormat:@"(account == %@) AND (fileID == %@)", metadataNet.account, metadata.fileID]]) {
+                    
+                    dispatch_async(dispatch_get_main_queue(), ^{
+                        [CCCoreData addMetadata:metadata activeAccount:app.activeAccount activeUrl:app.activeUrl context:nil];
+                    });
+                }
+              
+                // Load if different etag
+                
+                TableDirectory *tableDirectory = [CCCoreData getTableDirectoryWithPreficate:[NSPredicate predicateWithFormat:@"(account == %@) AND (serverUrl == %@)", metadataNet.account, serverUrl]];
+                
+                if (![tableDirectory.rev isEqualToString:metadata.rev]) {
+                    
+                    [self readFolderServerUrl:serverUrl directoryID:directoryID selector:metadataNet.selector];
+                    [CCCoreData updateDirectoryEtagServerUrl:serverUrl etag:metadata.rev activeAccount:metadataNet.account];
+                }
+                
+            } else {
+            
+                if ([metadataNet.selector isEqualToString:selectorReadFolderWithDownload]) {
+                    
+                    // It's in session
+                    BOOL recordInSession = NO;
+                    for (TableMetadata *record in recordsInSessions) {
+                        if ([record.fileID isEqualToString:metadata.fileID]) {
+                            recordInSession = YES;
+                            break;
+                        }
+                    }
+                    
+                    if (recordInSession)
+                        continue;
+            
+                    // Ohhhh INSERT
+                    [metadatasForVerifyChange addObject:metadata];
+                }
+                
+                if ([metadataNet.selector isEqualToString:selectorReadFolder]) {
+                    
+                    // Verify if do not exists this Metadata
+                    if (![CCCoreData getTableMetadataWithPreficate:[NSPredicate predicateWithFormat:@"(account == %@) AND (fileID == %@)", metadataNet.account, metadata.fileID]]) {
+                    
+                        dispatch_async(dispatch_get_main_queue(), ^{
+                            [CCCoreData addMetadata:metadata activeAccount:metadataNet.account activeUrl:metadataNet.serverUrl context:nil];
+                        });
+                    }
+                }
+            }
+        }
+        
+        if ([metadatasForVerifyChange count] > 0)
+            [self verifyChangeMedatas:metadatasForVerifyChange serverUrl:metadataNet.serverUrl account:metadataNet.account withDownload:YES];
+    });
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ===== Read File =====
+#pragma --------------------------------------------------------------------------------------------
+
+- (void)readFile:(CCMetadata *)metadata withDownload:(BOOL)withDownload
+{
+    NSString *serverUrl = [CCCoreData getServerUrlFromDirectoryID:metadata.directoryID activeAccount:app.activeAccount];
+    if (serverUrl == nil) return;
+        
+    CCMetadataNet *metadataNet = [[CCMetadataNet alloc] initWithAccount:app.activeAccount];
+        
+    metadataNet.action = actionReadFile;
+    metadataNet.fileID = metadata.fileID;
+    metadataNet.fileName = metadata.fileName;
+    metadataNet.fileNamePrint = metadata.fileNamePrint;
+    metadataNet.options = [NSNumber numberWithBool:withDownload] ;
+    metadataNet.priority = NSOperationQueuePriorityLow;
+    metadataNet.selector = selectorReadFile;
+    metadataNet.serverUrl = serverUrl;
+    
+    [app addNetworkingOperationQueue:app.netQueue delegate:self metadataNet:metadataNet];
+}
+
+- (void)readFileFailure:(CCMetadataNet *)metadataNet message:(NSString *)message errorCode:(NSInteger)errorCode
+{
+    // verify active user
+    TableAccount *recordAccount = [CCCoreData getActiveAccount];
+    
+    // File not present, remove it
+    if (errorCode == 404 && [recordAccount.account isEqualToString:metadataNet.account]) {
+        [CCCoreData deleteLocalFileWithPredicate:[NSPredicate predicateWithFormat:@"(account == %@) AND (fileID == %@)", metadataNet.account, metadataNet.fileID]];
+        [CCCoreData deleteMetadataWithPredicate:[NSPredicate predicateWithFormat:@"(account == %@) AND (fileID == %@)", metadataNet.account, metadataNet.fileID]];
+    }
+}
+
+- (void)readFileSuccess:(CCMetadataNet *)metadataNet metadata:(CCMetadata *)metadata
+{
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
+        
+        BOOL withDownload = [metadataNet.options boolValue];
+        
+        [self verifyChangeMedatas:[[NSArray alloc] initWithObjects:metadata, nil] serverUrl:metadataNet.serverUrl account:app.activeAccount withDownload:withDownload];
+    });
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ===== Verify Metadatas =====
+#pragma --------------------------------------------------------------------------------------------
+
+// MULTI THREAD
+- (void)verifyChangeMedatas:(NSArray *)allRecordMetadatas serverUrl:(NSString *)serverUrl account:(NSString *)account withDownload:(BOOL)withDownload
+{
+    NSMutableArray *metadatas = [[NSMutableArray alloc] init];
+    
+    for (CCMetadata *metadata in allRecordMetadatas) {
+        
+        BOOL changeRev = NO;
+        
+        // change account
+        if ([metadata.account isEqualToString:account] == NO)
+            return;
+        
+        // no dir
+        if (metadata.directory)
+            continue;
+        
+        TableLocalFile *record = [TableLocalFile MR_findFirstWithPredicate:[NSPredicate predicateWithFormat:@"(account == %@) AND (fileID == %@)", app.activeAccount, metadata.fileID]];
+        
+        if (withDownload) {
+            
+            if (![record.rev isEqualToString:metadata.rev])
+                changeRev = YES;
+            
+        } else {
+            
+            if (record && ![record.rev isEqualToString:metadata.rev]) // it must be in TableRecord
+                changeRev = YES;
+        }
+        
+        if (changeRev) {
+            
+            if ([metadata.type isEqualToString: k_metadataType_file]) {
+                
+                // remove file and ico
+                [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@/%@", app.directoryUser, metadata.fileID] error:nil];
+                [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@/%@.ico", app.directoryUser, metadata.fileID] error:nil];
+            }
+            
+            if ([metadata.type isEqualToString: k_metadataType_template]) {
+                
+                // remove model
+                [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@/%@", app.directoryUser, metadata.fileName] error:nil];
+            }
+            
+            [metadatas addObject:metadata];
+        }
+    }
+    
+    dispatch_async(dispatch_get_main_queue(), ^{
+        if ([metadatas count])
+            [self SynchronizeMetadatas:metadatas serverUrl:serverUrl withDownload:withDownload];
+    });
+}
+
+// MAIN THREAD
+- (void)SynchronizeMetadatas:(NSArray *)metadatas serverUrl:(NSString *)serverUrl withDownload:(BOOL)withDownload
+{
+    // HUD
+    if ([metadatas count] > 50 && withDownload) {
+        if (!_hud) _hud = [[CCHud alloc] initWithView:[[[UIApplication sharedApplication] delegate] window]];
+        [_hud visibleIndeterminateHud];
+    }
+    
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void) {
+        
+        NSString *oldDirectoryID, *serverUrl;
+
+        for (CCMetadata *metadata in metadatas) {
+        
+            NSString *selector, *selectorPost;
+            BOOL downloadData = NO, downloadPlist = NO;
+        
+            // it's a offline ?
+            BOOL isOffline = [CCCoreData isOfflineLocalFileID:metadata.fileID activeAccount:app.activeAccount];
+        
+            if (isOffline)
+                selectorPost = selectorAddOffline;
+        
+            if ([metadata.type isEqualToString: k_metadataType_file]) {
+                downloadData = YES;
+                selector = selectorDownloadSynchronize;
+            }
+        
+            if ([metadata.type isEqualToString: k_metadataType_template]) {
+                downloadPlist = YES;
+                selector = selectorLoadPlist;
+            }
+            
+            // Clear date for dorce refresh view
+            if (![oldDirectoryID isEqualToString:metadata.directoryID]) {
+                serverUrl = [CCCoreData getServerUrlFromDirectoryID:metadata.directoryID activeAccount:app.activeAccount];
+                oldDirectoryID = metadata.directoryID;
+                [CCCoreData clearDateReadAccount:app.activeAccount serverUrl:serverUrl directoryID:nil];
+            }
+            
+            [CCCoreData addMetadata:metadata activeAccount:app.activeAccount activeUrl:serverUrl context:nil];
+        
+            CCMetadataNet *metadataNet = [[CCMetadataNet alloc] initWithAccount:app.activeAccount];
+            
+            metadataNet.action = actionDownloadFile;
+            metadataNet.metadata = metadata;
+            metadataNet.downloadData = downloadData;
+            metadataNet.downloadPlist = downloadPlist;
+            metadataNet.selector = selector;
+            metadataNet.selectorPost = selectorPost;
+            metadataNet.serverUrl = serverUrl;
+            metadataNet.session = k_download_session;
+            metadataNet.taskStatus = k_taskStatusResume;
+
+            [app addNetworkingOperationQueue:app.netQueueDownload delegate:app.activeMain metadataNet:metadataNet];
+        }
+    
+        [[CCSynchronize sharedSynchronize] synchronizeFolderAnimationDirectory:[[NSArray alloc] initWithObjects:serverUrl, nil] setGraphicsFolder:YES];
+        
+        [app.activeMain reloadDatasource:serverUrl fileID:nil selector:nil];
+        
+        [_hud hideHud];
+    });
+}
+
+#pragma --------------------------------------------------------------------------------------------
+#pragma mark ===== Synchronize Folder Animation =====
+#pragma --------------------------------------------------------------------------------------------
+
+- (BOOL)synchronizeFolderAnimationDirectory:(NSArray *)directory setGraphicsFolder:(BOOL)setGraphicsFolder
+{
+    BOOL animation = NO;
+    BOOL isAtLeastOneInAnimation = NO;
+    NSMutableOrderedSet *serversUrlInDownload = [NSMutableOrderedSet new];
+    
+    // test
+    if ([directory count] == 0 && [self.foldersInSynchronized count] == 0)
+        return isAtLeastOneInAnimation;
+    
+    if (directory)
+        [self.foldersInSynchronized addObjectsFromArray:directory];
+    else
+        directory = [[NSArray alloc] initWithArray:self.foldersInSynchronized.array];
+    
+    // Active in download
+    NSMutableArray *metadatasNet = [app verifyExistsInQueuesDownloadSelector:selectorDownloadSynchronize];
+    
+    for (CCMetadataNet *metadataNet in metadatasNet)
+        [serversUrlInDownload addObject:metadataNet.serverUrl];
+    
+    // Animation ON/OFF
+    
+    for (NSString *serverUrl in directory) {
+        
+        animation = [serversUrlInDownload containsObject:serverUrl];
+        
+        if (animation)
+            isAtLeastOneInAnimation = YES;
+        else
+            [self.foldersInSynchronized removeObject:serverUrl];
+        
+        if (setGraphicsFolder) {
+            
+            NSString *serverUrlOffline = [CCUtility deletingLastPathComponentFromServerUrl:serverUrl];
+            CCMain *viewController = [app.listMainVC objectForKey:serverUrlOffline];
+            if (viewController)
+                [viewController synchronizeFolderGraphicsServerUrl:serverUrl animation:animation];
+        }
+    }
+    
+    return isAtLeastOneInAnimation;
+}
+
+
+@end

+ 6 - 32
iOSClient/Main/Main.storyboard

@@ -189,33 +189,6 @@
             </objects>
             <point key="canvasLocation" x="9212" y="1217.5412293853074"/>
         </scene>
-        <!--Offline Container-->
-        <scene sceneID="AYB-62-j4s">
-            <objects>
-                <viewController id="rwz-Z7-lr8" customClass="CCOfflineContainer" sceneMemberID="viewController">
-                    <layoutGuides>
-                        <viewControllerLayoutGuide type="top" id="dzn-ww-83z"/>
-                        <viewControllerLayoutGuide type="bottom" id="tXj-pi-tXG"/>
-                    </layoutGuides>
-                    <view key="view" contentMode="scaleToFill" id="HtS-Rb-W2J">
-                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
-                    </view>
-                    <navigationItem key="navigationItem" id="2FU-76-z2B"/>
-                </viewController>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="fXh-VU-vqk" userLabel="First Responder" sceneMemberID="firstResponder"/>
-            </objects>
-            <point key="canvasLocation" x="5857" y="1218"/>
-        </scene>
-        <!--Page View Controller-->
-        <scene sceneID="UZ5-5e-kso">
-            <objects>
-                <pageViewController storyboardIdentifier="OfflinePageViewController" autoresizesArchivedViewToFullSize="NO" transitionStyle="scroll" navigationOrientation="horizontal" spineLocation="none" id="ryN-QC-jWF" sceneMemberID="viewController"/>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="gHN-MZ-CSY" userLabel="First Responder" sceneMemberID="firstResponder"/>
-            </objects>
-            <point key="canvasLocation" x="6487" y="1218"/>
-        </scene>
         <!--Photos Camera Upload-->
         <scene sceneID="kWr-RF-gdq">
             <objects>
@@ -606,17 +579,17 @@
                     </navigationBar>
                     <nil name="viewControllers"/>
                     <connections>
-                        <segue destination="rwz-Z7-lr8" kind="relationship" relationship="rootViewController" id="sp7-ug-USE"/>
+                        <segue destination="6uw-SF-2Qu" kind="relationship" relationship="rootViewController" id="CFg-zI-VEB"/>
                     </connections>
                 </navigationController>
                 <placeholder placeholderIdentifier="IBFirstResponder" id="NME-vT-pfd" userLabel="First Responder" sceneMemberID="firstResponder"/>
             </objects>
             <point key="canvasLocation" x="5857" y="327"/>
         </scene>
-        <!--Offline Page Content-->
+        <!--Favorite-->
         <scene sceneID="33n-4d-goO">
             <objects>
-                <viewController storyboardIdentifier="OfflinePageContent" id="6uw-SF-2Qu" customClass="CCOfflinePageContent" sceneMemberID="viewController">
+                <viewController storyboardIdentifier="CCFavorite" id="6uw-SF-2Qu" customClass="CCFavorite" sceneMemberID="viewController">
                     <layoutGuides>
                         <viewControllerLayoutGuide type="top" id="kXv-QP-Tlq"/>
                         <viewControllerLayoutGuide type="bottom" id="Y8a-Ua-b9s"/>
@@ -637,6 +610,7 @@
                         </subviews>
                         <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                     </view>
+                    <navigationItem key="navigationItem" id="udr-5M-kHz"/>
                     <connections>
                         <outlet property="tableView" destination="Pes-cJ-S4N" id="Fxj-3r-MCL"/>
                         <segue destination="mtc-lf-PRo" kind="showDetail" identifier="segueDetail" id="45n-bF-9RO"/>
@@ -644,7 +618,7 @@
                 </viewController>
                 <placeholder placeholderIdentifier="IBFirstResponder" id="d5y-uw-vht" userLabel="First Responder" sceneMemberID="firstResponder"/>
             </objects>
-            <point key="canvasLocation" x="7125.6000000000004" y="1217.5412293853074"/>
+            <point key="canvasLocation" x="5857" y="1218"/>
         </scene>
         <!--View Controller-->
         <scene sceneID="60G-IQ-Axc">
@@ -809,6 +783,6 @@
         <image name="tabBarPhotos" width="25" height="21"/>
     </resources>
     <inferredMetricsTieBreakers>
-        <segue reference="1IV-5w-SfJ"/>
+        <segue reference="45n-bF-9RO"/>
     </inferredMetricsTieBreakers>
 </document>