瀏覽代碼

Add class offline

Marino Faggiana 6 年之前
父節點
當前提交
fb494d00eb

+ 30 - 30
Nextcloud.xcodeproj/project.pbxproj

@@ -163,13 +163,13 @@
 		F732BA061D76CE1500E9878B /* CCNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F732BA041D76CE1500E9878B /* CCNetworking.m */; };
 		F732BA0B1D76DBA500E9878B /* CCNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = F732BA041D76CE1500E9878B /* CCNetworking.m */; };
 		F734E5891F019D860060CB77 /* UIScrollView+EmptyDataSet.m in Sources */ = {isa = PBXBuildFile; fileRef = F73CCE241DC13788007E38D8 /* UIScrollView+EmptyDataSet.m */; };
-		F7381ED221821281000B1560 /* NCOfflineListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7381ECB21821280000B1560 /* NCOfflineListCell.swift */; };
-		F7381ED321821281000B1560 /* NCOffline.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7381ECC21821280000B1560 /* NCOffline.swift */; };
-		F7381ED421821281000B1560 /* NCOfflineGridCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7381ECD21821280000B1560 /* NCOfflineGridCell.swift */; };
-		F7381ED521821281000B1560 /* NCOfflineHeaderFooterMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7381ECE21821280000B1560 /* NCOfflineHeaderFooterMenu.swift */; };
-		F7381ED621821281000B1560 /* NCOffline.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7381ECF21821280000B1560 /* NCOffline.storyboard */; };
-		F7381ED721821281000B1560 /* NCOfflineGridCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7381ED021821280000B1560 /* NCOfflineGridCell.xib */; };
-		F7381ED821821281000B1560 /* NCOfflineListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7381ED121821280000B1560 /* NCOfflineListCell.xib */; };
+		F7381EE1218218C9000B1560 /* NCOffline.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7381EDA218218C9000B1560 /* NCOffline.swift */; };
+		F7381EE2218218C9000B1560 /* NCOfflineListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7381EDB218218C9000B1560 /* NCOfflineListCell.xib */; };
+		F7381EE3218218C9000B1560 /* NCOfflineGridCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7381EDC218218C9000B1560 /* NCOfflineGridCell.swift */; };
+		F7381EE4218218C9000B1560 /* NCOfflineHeaderFooterMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7381EDD218218C9000B1560 /* NCOfflineHeaderFooterMenu.swift */; };
+		F7381EE5218218C9000B1560 /* NCOffline.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7381EDE218218C9000B1560 /* NCOffline.storyboard */; };
+		F7381EE6218218C9000B1560 /* NCOfflineListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7381EDF218218C9000B1560 /* NCOfflineListCell.swift */; };
+		F7381EE7218218C9000B1560 /* NCOfflineGridCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7381EE0218218C9000B1560 /* NCOfflineGridCell.xib */; };
 		F738E8421F90FFD100F95C8E /* NCManageEndToEndEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = F738E8411F90FFD100F95C8E /* NCManageEndToEndEncryption.m */; };
 		F73B4EEE1F470D9100BBEE4B /* Big5Freq.tab in Resources */ = {isa = PBXBuildFile; fileRef = F73B4EAD1F470D9100BBEE4B /* Big5Freq.tab */; };
 		F73B4EEF1F470D9100BBEE4B /* CharDistribution.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F73B4EAE1F470D9100BBEE4B /* CharDistribution.cpp */; };
@@ -947,13 +947,13 @@
 		F732093B201B81E4008A0888 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = "<group>"; };
 		F732BA031D76CE1500E9878B /* CCNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCNetworking.h; sourceTree = "<group>"; };
 		F732BA041D76CE1500E9878B /* CCNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCNetworking.m; sourceTree = "<group>"; };
-		F7381ECB21821280000B1560 /* NCOfflineListCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOfflineListCell.swift; sourceTree = "<group>"; };
-		F7381ECC21821280000B1560 /* NCOffline.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOffline.swift; sourceTree = "<group>"; };
-		F7381ECD21821280000B1560 /* NCOfflineGridCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOfflineGridCell.swift; sourceTree = "<group>"; };
-		F7381ECE21821280000B1560 /* NCOfflineHeaderFooterMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOfflineHeaderFooterMenu.swift; sourceTree = "<group>"; };
-		F7381ECF21821280000B1560 /* NCOffline.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCOffline.storyboard; sourceTree = "<group>"; };
-		F7381ED021821280000B1560 /* NCOfflineGridCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCOfflineGridCell.xib; sourceTree = "<group>"; };
-		F7381ED121821280000B1560 /* NCOfflineListCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCOfflineListCell.xib; sourceTree = "<group>"; };
+		F7381EDA218218C9000B1560 /* NCOffline.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOffline.swift; sourceTree = "<group>"; };
+		F7381EDB218218C9000B1560 /* NCOfflineListCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCOfflineListCell.xib; sourceTree = "<group>"; };
+		F7381EDC218218C9000B1560 /* NCOfflineGridCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOfflineGridCell.swift; sourceTree = "<group>"; };
+		F7381EDD218218C9000B1560 /* NCOfflineHeaderFooterMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOfflineHeaderFooterMenu.swift; sourceTree = "<group>"; };
+		F7381EDE218218C9000B1560 /* NCOffline.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCOffline.storyboard; sourceTree = "<group>"; };
+		F7381EDF218218C9000B1560 /* NCOfflineListCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOfflineListCell.swift; sourceTree = "<group>"; };
+		F7381EE0218218C9000B1560 /* NCOfflineGridCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCOfflineGridCell.xib; sourceTree = "<group>"; };
 		F738E8401F90FFD100F95C8E /* NCManageEndToEndEncryption.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NCManageEndToEndEncryption.h; sourceTree = "<group>"; };
 		F738E8411F90FFD100F95C8E /* NCManageEndToEndEncryption.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NCManageEndToEndEncryption.m; sourceTree = "<group>"; };
 		F73B4EAD1F470D9100BBEE4B /* Big5Freq.tab */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Big5Freq.tab; sourceTree = "<group>"; };
@@ -2132,16 +2132,16 @@
 			path = "Notification Service Extension";
 			sourceTree = "<group>";
 		};
-		F7381ECA21821280000B1560 /* Offline */ = {
+		F7381ED9218218A4000B1560 /* Offline */ = {
 			isa = PBXGroup;
 			children = (
-				F7381ECB21821280000B1560 /* NCOfflineListCell.swift */,
-				F7381ECC21821280000B1560 /* NCOffline.swift */,
-				F7381ECD21821280000B1560 /* NCOfflineGridCell.swift */,
-				F7381ECE21821280000B1560 /* NCOfflineHeaderFooterMenu.swift */,
-				F7381ECF21821280000B1560 /* NCOffline.storyboard */,
-				F7381ED021821280000B1560 /* NCOfflineGridCell.xib */,
-				F7381ED121821280000B1560 /* NCOfflineListCell.xib */,
+				F7381EDE218218C9000B1560 /* NCOffline.storyboard */,
+				F7381EDA218218C9000B1560 /* NCOffline.swift */,
+				F7381EDC218218C9000B1560 /* NCOfflineGridCell.swift */,
+				F7381EE0218218C9000B1560 /* NCOfflineGridCell.xib */,
+				F7381EDD218218C9000B1560 /* NCOfflineHeaderFooterMenu.swift */,
+				F7381EDF218218C9000B1560 /* NCOfflineListCell.swift */,
+				F7381EDB218218C9000B1560 /* NCOfflineListCell.xib */,
 			);
 			path = Offline;
 			sourceTree = "<group>";
@@ -3466,7 +3466,7 @@
 				F7F9E3451BC26B19004B9223 /* Move */,
 				F74D3DB81BAC1941000BAE4B /* Networking */,
 				F7C5259A1E3B441D00FFE02C /* Notification */,
-				F7381ECA21821280000B1560 /* Offline */,
+				F7381ED9218218A4000B1560 /* Offline */,
 				F7FCFFD51D70798C000E6E29 /* PeekPop */,
 				F7BE6E2A1D2D5C3B00106933 /* QuickActions */,
 				F7FE125B1BAC03FB0041924B /* Security */,
@@ -3813,6 +3813,7 @@
 				F7F54CF91E5B14C700E19C62 /* PlayButtonOverlayLargeTap@3x.png in Resources */,
 				F7D4233D1F0596AC009C9782 /* Reader-Button-N@3x.png in Resources */,
 				F73B4EF21F470D9100BBEE4B /* EUCTWFreq.tab in Resources */,
+				F7381EE7218218C9000B1560 /* NCOfflineGridCell.xib in Resources */,
 				F7622FDB2175FCC0000383FF /* ActionSheetCollectionItemCell.xib in Resources */,
 				F700222C1EC479840080073F /* Custom.xcassets in Resources */,
 				F758B45A212C564000515F55 /* Scan.storyboard in Resources */,
@@ -3821,7 +3822,6 @@
 				F7F54CF81E5B14C700E19C62 /* PlayButtonOverlayLargeTap@2x.png in Resources */,
 				F73B4EEE1F470D9100BBEE4B /* Big5Freq.tab in Resources */,
 				F7D4233B1F0596AC009C9782 /* Reader-Button-N.png in Resources */,
-				F7381ED721821281000B1560 /* NCOfflineGridCell.xib in Resources */,
 				F7F54CF31E5B14C700E19C62 /* ImageSelectedSmallOn@3x.png in Resources */,
 				F7D423441F0596AC009C9782 /* Reader-Mark-N.png in Resources */,
 				F7F54CFA1E5B14C700E19C62 /* UIBarButtonItemArrowLeft.png in Resources */,
@@ -3851,7 +3851,6 @@
 				F7D4233C1F0596AC009C9782 /* Reader-Button-N@2x.png in Resources */,
 				F729B92B217A2E4E00FE2150 /* NCActionSheetHeaderView.xib in Resources */,
 				F7D423411F0596AC009C9782 /* Reader-Export.png in Resources */,
-				F7381ED621821281000B1560 /* NCOffline.storyboard in Resources */,
 				F77B0F481D118A16002130FE /* synchronized.gif in Resources */,
 				F7417DB5216CFE8E007D05F5 /* NCTrashGridCell.xib in Resources */,
 				F7D4233E1F0596AC009C9782 /* Reader-Email.png in Resources */,
@@ -3859,10 +3858,11 @@
 				F7D423361F0596AC009C9782 /* AppIcon-167.png in Resources */,
 				F7F54CF71E5B14C700E19C62 /* PlayButtonOverlayLargeTap.png in Resources */,
 				F710E8111EF95C9C00DC2427 /* ImagesIntro.xcassets in Resources */,
-				F7381ED821821281000B1560 /* NCOfflineListCell.xib in Resources */,
+				F7381EE2218218C9000B1560 /* NCOfflineListCell.xib in Resources */,
 				F77B0F4D1D118A16002130FE /* CCShare.storyboard in Resources */,
 				F7F54D021E5B14C700E19C62 /* UIBarButtonItemGrid@3x.png in Resources */,
 				F7F54CEA1E5B14C700E19C62 /* ImageSelectedOff@3x.png in Resources */,
+				F7381EE5218218C9000B1560 /* NCOffline.storyboard in Resources */,
 				F7F54CF11E5B14C700E19C62 /* ImageSelectedSmallOn.png in Resources */,
 				F762CB1B1EACB66200B38484 /* XLForm.bundle in Resources */,
 				F712AC9D2175E56F0061158E /* CTAssetsPicker.xcassets in Resources */,
@@ -4175,6 +4175,7 @@
 				F7B1FBC71E72E3D1001781FE /* SwiftWebVC.swift in Sources */,
 				F7622FB62175FCC0000383FF /* ActionSheetCancelButtonAppearance.swift in Sources */,
 				F7DC5FEC1F011EB700A903C7 /* MGSwipeButton.m in Sources */,
+				F7381EE4218218C9000B1560 /* NCOfflineHeaderFooterMenu.swift in Sources */,
 				F7D423801F0596C6009C9782 /* ReaderMainPagebar.m in Sources */,
 				F712ACAA2175E56F0061158E /* NSNumberFormatter+CTAssetsPickerController.m in Sources */,
 				F762CB061EACB66200B38484 /* XLFormTextViewCell.m in Sources */,
@@ -4214,7 +4215,6 @@
 				F7622FB92175FCC0000383FF /* ActionSheetSectionMarginAppearance.swift in Sources */,
 				F7622FC72175FCC0000383FF /* UIView+Empty.swift in Sources */,
 				F70022CB1EC4C9100080073F /* OCSharedDto.m in Sources */,
-				F7381ED221821281000B1560 /* NCOfflineListCell.swift in Sources */,
 				F7CA1ED320E7E3FE002CC65E /* PKStopDownloadButton.m in Sources */,
 				F712ACA12175E56F0061158E /* CTAssetsViewControllerTransition.m in Sources */,
 				F762CB111EACB66200B38484 /* NSString+XLFormAdditions.m in Sources */,
@@ -4230,6 +4230,7 @@
 				F762CB081EACB66200B38484 /* XLFormOptionsViewController.m in Sources */,
 				F73CC0721E813DFF006E3047 /* BKPasscodeLockScreenManager.m in Sources */,
 				F73B4F101F470D9100BBEE4B /* nsSBCharSetProber.cpp in Sources */,
+				F7381EE3218218C9000B1560 /* NCOfflineGridCell.swift in Sources */,
 				F762CB0E1EACB66200B38484 /* NSExpression+XLFormAdditions.m in Sources */,
 				F73B4F071F470D9100BBEE4B /* nsEscSM.cpp in Sources */,
 				F77B0E221D118A16002130FE /* CCManageLocation.m in Sources */,
@@ -4316,7 +4317,6 @@
 				F7ED7EDE216B85DA007AB4D9 /* NCTrashListCell.swift in Sources */,
 				F762CB101EACB66200B38484 /* NSPredicate+XLFormAdditions.m in Sources */,
 				F7622FCF2175FCC0000383FF /* ActionSheetMultiSelectToggleItem.swift in Sources */,
-				F7381ED321821281000B1560 /* NCOffline.swift in Sources */,
 				F7D4237E1F0596C6009C9782 /* ReaderDocument.m in Sources */,
 				F7659A291DC0B726004860C4 /* EAIntroView.m in Sources */,
 				F7D4237C1F0596C6009C9782 /* ReaderContentTile.m in Sources */,
@@ -4342,6 +4342,7 @@
 				F754EECC21772B6100BB1CDF /* SectionHeader.swift in Sources */,
 				F73CC0751E813DFF006E3047 /* BKPasscodeViewController.m in Sources */,
 				F750374D1DBFA91A008FB480 /* ALView+PureLayout.m in Sources */,
+				F7381EE1218218C9000B1560 /* NCOffline.swift in Sources */,
 				F7659A2E1DC0B72F004860C4 /* EARestrictedScrollView.m in Sources */,
 				F7622FCA2175FCC0000383FF /* ActionSheetCancelButton.swift in Sources */,
 				F712AC972175E56F0061158E /* CTAssetsPageView.m in Sources */,
@@ -4378,7 +4379,6 @@
 				F7622FAD2175FCC0000383FF /* ActionSheetMargin.swift in Sources */,
 				F77B0E9B1D118A16002130FE /* CCBKPasscode.m in Sources */,
 				F7659A271DC0B726004860C4 /* EAIntroPage.m in Sources */,
-				F7381ED521821281000B1560 /* NCOfflineHeaderFooterMenu.swift in Sources */,
 				F7169A1D1EE590930086BD69 /* NCSharesCell.m in Sources */,
 				F77B0EA61D118A16002130FE /* NSString+TruncateToWidth.m in Sources */,
 				F70022C21EC4C9100080073F /* OCNotifications.m in Sources */,
@@ -4442,6 +4442,7 @@
 				F77B0EC61D118A16002130FE /* CCCellMain.m in Sources */,
 				F758B3E6212C4A6C00515F55 /* PDFPage.swift in Sources */,
 				F7DC5FED1F011EB700A903C7 /* MGSwipeTableCell.m in Sources */,
+				F7381EE6218218C9000B1560 /* NCOfflineListCell.swift in Sources */,
 				F7622FB32175FCC0000383FF /* ActionSheetDangerButtonAppearance.swift in Sources */,
 				F7D4238B1F0596C6009C9782 /* ThumbsViewController.m in Sources */,
 				F7622FB52175FCC0000383FF /* ActionSheetButtonItemAppearance.swift in Sources */,
@@ -4481,7 +4482,6 @@
 				F73CC06C1E813DFF006E3047 /* BKPasscodeField.m in Sources */,
 				F77B0ED51D118A16002130FE /* PHAsset+Utility.m in Sources */,
 				F7622FD22175FCC0000383FF /* ActionSheetSelectItem.swift in Sources */,
-				F7381ED421821281000B1560 /* NCOfflineGridCell.swift in Sources */,
 				F73B4EFD1F470D9100BBEE4B /* LangHebrewModel.cpp in Sources */,
 				F70022CE1EC4C9100080073F /* OCShareUser.m in Sources */,
 				F77B0ED91D118A16002130FE /* main.m in Sources */,

+ 147 - 0
iOSClient/Offline/NCOffline.storyboard

@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="EFX-fO-Oip">
+    <device id="retina5_9" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--Offline-->
+        <scene sceneID="X4W-6b-l7s">
+            <objects>
+                <viewController storyboardIdentifier="NCOffline.storyboard" id="EFX-fO-Oip" customClass="NCOffline" customModule="Nextcloud" customModuleProvider="target" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="QEs-gO-Cmp">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="Zaz-Cl-qpZ">
+                                <rect key="frame" x="0.0" y="44" width="375" height="734"/>
+                                <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="fF1-wd-0xN">
+                                    <size key="itemSize" width="0.0" height="0.0"/>
+                                    <size key="headerReferenceSize" width="50" height="50"/>
+                                    <size key="footerReferenceSize" width="50" height="50"/>
+                                    <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
+                                </collectionViewFlowLayout>
+                                <cells/>
+                                <collectionReusableView key="sectionHeaderView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" reuseIdentifier="headerMenu" id="AQ6-rS-Wxb" customClass="NCOfflineHeaderMenu" customModule="Nextcloud" customModuleProvider="target">
+                                    <rect key="frame" x="0.0" y="0.0" width="375" height="50"/>
+                                    <autoresizingMask key="autoresizingMask"/>
+                                    <subviews>
+                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hva-qI-4Kl" userLabel="Separator">
+                                            <rect key="frame" x="0.0" y="48" width="375" height="1"/>
+                                            <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                            <color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                            <constraints>
+                                                <constraint firstAttribute="height" constant="1" id="5Wf-y6-RCg"/>
+                                            </constraints>
+                                        </view>
+                                        <button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="gBv-v2-Zec" userLabel="buttonSwitch">
+                                            <rect key="frame" x="12" y="12.666666666666664" width="25" height="25"/>
+                                            <constraints>
+                                                <constraint firstAttribute="height" constant="25" id="0mp-3J-eb3"/>
+                                                <constraint firstAttribute="width" constant="25" id="DxY-uU-Znk"/>
+                                            </constraints>
+                                            <state key="normal" image="switchList"/>
+                                            <connections>
+                                                <action selector="touchUpInsideSwitch:" destination="AQ6-rS-Wxb" eventType="touchUpInside" id="wkS-i9-OsH"/>
+                                            </connections>
+                                        </button>
+                                        <button hidden="YES" opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Qqn-cs-A3P" userLabel="buttonSwitch">
+                                            <rect key="frame" x="338" y="12.666666666666664" width="25" height="25"/>
+                                            <constraints>
+                                                <constraint firstAttribute="width" constant="25" id="2OK-Fr-IGe"/>
+                                                <constraint firstAttribute="height" constant="25" id="HAe-ET-Q3h"/>
+                                            </constraints>
+                                            <state key="normal" image="moreBig"/>
+                                            <connections>
+                                                <action selector="touchUpInsideMore:" destination="AQ6-rS-Wxb" eventType="touchUpInside" id="F2B-LW-hs5"/>
+                                            </connections>
+                                        </button>
+                                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0q4-Qd-ic4" userLabel="buttonOrder">
+                                            <rect key="frame" x="55" y="11" width="230" height="28"/>
+                                            <constraints>
+                                                <constraint firstAttribute="width" constant="230" id="n74-Xy-Qpd"/>
+                                            </constraints>
+                                            <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                                            <state key="normal" title="Sort by name (from A to Z)">
+                                                <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+                                            </state>
+                                            <connections>
+                                                <action selector="touchUpInsideOrder:" destination="AQ6-rS-Wxb" eventType="touchUpInside" id="bwn-i4-jiF"/>
+                                            </connections>
+                                        </button>
+                                    </subviews>
+                                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                    <constraints>
+                                        <constraint firstItem="0q4-Qd-ic4" firstAttribute="leading" secondItem="gBv-v2-Zec" secondAttribute="trailing" constant="18" id="86t-HS-JzM"/>
+                                        <constraint firstItem="0q4-Qd-ic4" firstAttribute="centerY" secondItem="AQ6-rS-Wxb" secondAttribute="centerY" id="APZ-gg-uLs"/>
+                                        <constraint firstItem="Qqn-cs-A3P" firstAttribute="centerY" secondItem="AQ6-rS-Wxb" secondAttribute="centerY" id="Cgb-zq-vQE"/>
+                                        <constraint firstAttribute="trailing" secondItem="Qqn-cs-A3P" secondAttribute="trailing" constant="12" id="FJp-2Z-jvg"/>
+                                        <constraint firstItem="gBv-v2-Zec" firstAttribute="leading" secondItem="AQ6-rS-Wxb" secondAttribute="leading" constant="12" id="Glf-95-Dxh"/>
+                                        <constraint firstAttribute="trailing" secondItem="hva-qI-4Kl" secondAttribute="trailing" id="Nq8-X5-7Cq"/>
+                                        <constraint firstItem="gBv-v2-Zec" firstAttribute="centerY" secondItem="AQ6-rS-Wxb" secondAttribute="centerY" id="OEU-E8-r92"/>
+                                        <constraint firstItem="hva-qI-4Kl" firstAttribute="leading" secondItem="AQ6-rS-Wxb" secondAttribute="leading" id="a0G-P5-ZTU"/>
+                                        <constraint firstAttribute="bottom" secondItem="hva-qI-4Kl" secondAttribute="bottom" constant="1" id="ixp-nm-HUt"/>
+                                    </constraints>
+                                    <connections>
+                                        <outlet property="buttonMore" destination="Qqn-cs-A3P" id="9hu-4g-sm5"/>
+                                        <outlet property="buttonOrder" destination="0q4-Qd-ic4" id="A8C-el-YQr"/>
+                                        <outlet property="buttonOrderWidthConstraint" destination="n74-Xy-Qpd" id="1yu-SR-FZN"/>
+                                        <outlet property="buttonSwitch" destination="gBv-v2-Zec" id="yBa-g0-ChU"/>
+                                        <outlet property="separator" destination="hva-qI-4Kl" id="rP4-bg-nt9"/>
+                                    </connections>
+                                </collectionReusableView>
+                                <collectionReusableView key="sectionFooterView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" reuseIdentifier="footerMenu" id="KIO-gv-emq" customClass="NCOfflineFooterMenu" customModule="Nextcloud" customModuleProvider="target">
+                                    <rect key="frame" x="0.0" y="50" width="375" height="50"/>
+                                    <autoresizingMask key="autoresizingMask"/>
+                                    <subviews>
+                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5ZS-UE-CHl" userLabel="LabelFooter">
+                                            <rect key="frame" x="10" y="17" width="355" height="16"/>
+                                            <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                                            <nil key="textColor"/>
+                                            <nil key="highlightedColor"/>
+                                        </label>
+                                    </subviews>
+                                    <constraints>
+                                        <constraint firstItem="5ZS-UE-CHl" firstAttribute="centerY" secondItem="KIO-gv-emq" secondAttribute="centerY" id="5Ip-b9-luC"/>
+                                        <constraint firstAttribute="trailing" secondItem="5ZS-UE-CHl" secondAttribute="trailing" constant="10" id="6rY-5r-1Mf"/>
+                                        <constraint firstItem="5ZS-UE-CHl" firstAttribute="leading" secondItem="KIO-gv-emq" secondAttribute="leading" constant="10" id="JLx-VS-sTx"/>
+                                    </constraints>
+                                    <connections>
+                                        <outlet property="labelFooter" destination="5ZS-UE-CHl" id="zcJ-1o-Jtw"/>
+                                    </connections>
+                                </collectionReusableView>
+                                <connections>
+                                    <outlet property="dataSource" destination="EFX-fO-Oip" id="2On-qP-zuG"/>
+                                    <outlet property="delegate" destination="EFX-fO-Oip" id="s3n-CL-8X2"/>
+                                </connections>
+                            </collectionView>
+                        </subviews>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <constraints>
+                            <constraint firstItem="Zaz-Cl-qpZ" firstAttribute="leading" secondItem="Meh-VD-wWh" secondAttribute="leading" id="1bp-sm-u0X"/>
+                            <constraint firstItem="Meh-VD-wWh" firstAttribute="trailing" secondItem="Zaz-Cl-qpZ" secondAttribute="trailing" id="aNd-UL-hmu"/>
+                            <constraint firstItem="Meh-VD-wWh" firstAttribute="bottom" secondItem="Zaz-Cl-qpZ" secondAttribute="bottom" id="aNr-tf-2AH"/>
+                            <constraint firstItem="Zaz-Cl-qpZ" firstAttribute="top" secondItem="Meh-VD-wWh" secondAttribute="top" id="tji-wt-R7s"/>
+                        </constraints>
+                        <viewLayoutGuide key="safeArea" id="Meh-VD-wWh"/>
+                    </view>
+                    <connections>
+                        <outlet property="collectionView" destination="Zaz-Cl-qpZ" id="8oA-Gx-z7T"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="JJ0-Le-6eT" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="256.80000000000001" y="228.93553223388307"/>
+        </scene>
+    </scenes>
+    <resources>
+        <image name="moreBig" width="120" height="120"/>
+        <image name="switchList" width="25" height="25"/>
+    </resources>
+</document>

+ 710 - 0
iOSClient/Offline/NCOffline.swift

@@ -0,0 +1,710 @@
+//
+//  NCOffline.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 24/10/2018.
+//  Copyright © 2018 Marino Faggiana. 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
+
+class NCOffline: UIViewController ,UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UIGestureRecognizerDelegate, NCOfflineListCellDelegate, NCOfflineGridCellDelegate, NCOfflineHeaderMenuDelegate, DropdownMenuDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate  {
+    
+    @IBOutlet fileprivate weak var collectionView: UICollectionView!
+
+    let appDelegate = UIApplication.shared.delegate as! AppDelegate
+    var serverUrl = ""
+    var titleCurrentFolder = NSLocalizedString("_manage_file_offline_", comment: "")
+    var datasource = [tableMetadata]()
+    var datasourceSorted = ""
+    var datasourceAscending = true
+    var isEditMode = false
+    var selectFileID = [String]()
+    
+    var listLayout: ListLayoutOffline!
+    var gridLayout: GridLayoutOffline!
+    
+    private let highHeader: CGFloat = 50
+    
+    private let refreshControl = UIRefreshControl()
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        
+        collectionView.register(UINib.init(nibName: "NCOfflineListCell", bundle: nil), forCellWithReuseIdentifier: "cell-list")
+        collectionView.register(UINib.init(nibName: "NCOfflineGridCell", bundle: nil), forCellWithReuseIdentifier: "cell-grid")
+        
+        collectionView.alwaysBounceVertical = true
+
+        listLayout = ListLayoutOffline()
+        gridLayout = GridLayoutOffline()
+        
+        if CCUtility.getLayoutOffline() == "list" {
+            collectionView.collectionViewLayout = listLayout
+        } else {
+            collectionView.collectionViewLayout = gridLayout
+        }
+        
+        // Add Refresh Control
+        if #available(iOS 10.0, *) {
+            collectionView.refreshControl = refreshControl
+        } else {
+            collectionView.addSubview(refreshControl)
+        }
+        
+        // Configure Refresh Control
+        refreshControl.tintColor = NCBrandColor.sharedInstance.brandText
+        refreshControl.backgroundColor = NCBrandColor.sharedInstance.brand
+        refreshControl.addTarget(self, action: #selector(loadDatasource(withSynchronized:)), for: .valueChanged)
+        
+        // empty Data Source
+        self.collectionView.emptyDataSetDelegate = self;
+        self.collectionView.emptyDataSetSource = self;        
+    }
+    
+    override func viewWillAppear(_ animated: Bool) {
+        super.viewWillAppear(animated)
+        
+        self.navigationItem.title = titleCurrentFolder
+
+        if serverUrl == "" {
+            serverUrl = CCUtility.getHomeServerUrlActiveUrl(appDelegate.activeUrl)
+        }
+        
+        datasourceSorted = CCUtility.getOrderSettings()
+        datasourceAscending = CCUtility.getAscendingSettings()
+        
+        loadDatasource(withSynchronized: false)
+    }
+    
+    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
+        super.viewWillTransition(to: size, with: coordinator)
+        
+        coordinator.animate(alongsideTransition: nil) { _ in
+            self.collectionView.collectionViewLayout.invalidateLayout()
+        }
+    }
+    
+    // MARK: DZNEmpty
+    
+    func backgroundColor(forEmptyDataSet scrollView: UIScrollView) -> UIColor? {
+        return NCBrandColor.sharedInstance.backgroundView
+    }
+    
+    func image(forEmptyDataSet scrollView: UIScrollView) -> UIImage? {
+        return CCGraphics.changeThemingColorImage(UIImage.init(named: "filesNoFiles"), multiplier: 2, color: NCBrandColor.sharedInstance.brandElement)
+    }
+    
+    func title(forEmptyDataSet scrollView: UIScrollView) -> NSAttributedString? {
+        let text = "\n"+NSLocalizedString("_files_no_files_", comment: "")
+        let attributes = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 20), NSAttributedString.Key.foregroundColor: UIColor.lightGray]
+        return NSAttributedString.init(string: text, attributes: attributes)
+    }
+    
+    /*
+    func description(forEmptyDataSet scrollView: UIScrollView) -> NSAttributedString? {
+        let text = "\n"+NSLocalizedString("_no_file_pull_down_", comment: "")
+        let attributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14), NSAttributedString.Key.foregroundColor: UIColor.lightGray]
+        return NSAttributedString.init(string: text, attributes: attributes)
+    }
+    */
+    
+    func emptyDataSetShouldAllowScroll(_ scrollView: UIScrollView) -> Bool {
+        return true
+    }
+
+    // MARK: TAP EVENT
+    
+    func tapSwitchHeaderMenu(sender: Any) {
+        
+        if collectionView.collectionViewLayout == gridLayout {
+            // list layout
+            UIView.animate(withDuration: 0.0, animations: {
+                self.collectionView.collectionViewLayout.invalidateLayout()
+                self.collectionView.setCollectionViewLayout(self.listLayout, animated: false, completion: { (_) in
+                    self.collectionView.reloadData()
+                    self.collectionView.setContentOffset(CGPoint(x:0,y:0), animated: false)
+                })
+            })
+            CCUtility.setLayoutOffline("list")
+        } else {
+            // grid layout
+            UIView.animate(withDuration: 0.0, animations: {
+                self.collectionView.collectionViewLayout.invalidateLayout()
+                self.collectionView.setCollectionViewLayout(self.gridLayout, animated: false, completion: { (_) in
+                    self.collectionView.reloadData()
+                    self.collectionView.setContentOffset(CGPoint(x:0,y:0), animated: false)
+                })
+            })
+            CCUtility.setLayoutOffline("grid")
+        }
+    }
+    
+    func tapOrderHeaderMenu(sender: Any) {
+        
+        var menuView: DropdownMenu?
+        var selectedRow = 0
+        
+        let item1 = DropdownItem(image: CCGraphics.changeThemingColorImage(UIImage.init(named: "sortFileNameAZ"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), title: NSLocalizedString("_order_by_name_a_z_", comment: ""))
+        let item2 = DropdownItem(image: CCGraphics.changeThemingColorImage(UIImage.init(named: "sortFileNameZA"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), title: NSLocalizedString("_order_by_name_z_a_", comment: ""))
+        let item3 = DropdownItem(image: CCGraphics.changeThemingColorImage(UIImage.init(named: "sortDateMoreRecent"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), title: NSLocalizedString("_order_by_date_more_recent_", comment: ""))
+        let item4 = DropdownItem(image: CCGraphics.changeThemingColorImage(UIImage.init(named: "sortDateLessRecent"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), title: NSLocalizedString("_order_by_date_less_recent_", comment: ""))
+        let item5 = DropdownItem(image: CCGraphics.changeThemingColorImage(UIImage.init(named: "sortSmallest"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), title: NSLocalizedString("_order_by_size_smallest_", comment: ""))
+        let item6 = DropdownItem(image: CCGraphics.changeThemingColorImage(UIImage.init(named: "sortLargest"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), title: NSLocalizedString("_order_by_size_largest_", comment: ""))
+        
+        switch datasourceSorted {
+        case "fileName":
+            if datasourceAscending == true { item1.style = .highlight; selectedRow = 0 }
+            if datasourceAscending == false { item2.style = .highlight; selectedRow = 1 }
+        case "date":
+            if datasourceAscending == false { item3.style = .highlight; selectedRow = 2 }
+            if datasourceAscending == true { item4.style = .highlight; selectedRow = 3 }
+        case "size":
+            if datasourceAscending == true { item5.style = .highlight; selectedRow = 4 }
+            if datasourceAscending == false { item6.style = .highlight; selectedRow = 5 }
+        default:
+            print("")
+        }
+        
+        menuView = DropdownMenu(navigationController: self.navigationController!, items: [item1, item2, item3, item4, item5, item6], selectedRow: selectedRow)
+        menuView?.token = "tapOrderHeaderMenu"
+        menuView?.delegate = self
+        menuView?.rowHeight = 50
+        menuView?.highlightColor = NCBrandColor.sharedInstance.brand
+        menuView?.tableView.alwaysBounceVertical = false
+        
+        let header = (sender as? UIButton)?.superview as! NCOfflineHeaderMenu
+        let headerRect = self.collectionView.convert(header.bounds, from: self.view)
+        let menuOffsetY =  headerRect.height - headerRect.origin.y - 2
+        menuView?.topOffsetY = CGFloat(menuOffsetY)
+        
+        menuView?.showMenu()
+    }
+    
+    func tapMoreHeaderMenu(sender: Any) {
+        
+        var menuView: DropdownMenu?
+        
+        if isEditMode {
+            
+            let item0 = DropdownItem(image: CCGraphics.changeThemingColorImage(UIImage.init(named: "checkedNo"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), title:  NSLocalizedString("_cancel_", comment: ""))
+            let item1 = DropdownItem(image: CCGraphics.changeThemingColorImage(UIImage.init(named: "restore"), multiplier: 1, color: NCBrandColor.sharedInstance.icon), title:  NSLocalizedString("_trash_restore_selected_", comment: ""))
+            let item2 = DropdownItem(image: CCGraphics.changeThemingColorImage(UIImage.init(named: "trash"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), title:  NSLocalizedString("_trash_delete_selected_", comment: ""))
+            
+            menuView = DropdownMenu(navigationController: self.navigationController!, items: [item0, item1, item2], selectedRow: -1)
+            menuView?.token = "tapMoreHeaderMenuSelect"
+            
+        } else {
+            
+            let item0 = DropdownItem(image: CCGraphics.changeThemingColorImage(UIImage.init(named: "select"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), title:  NSLocalizedString("_select_", comment: ""))
+            let item1 = DropdownItem(image: CCGraphics.changeThemingColorImage(UIImage.init(named: "restore"), multiplier: 1, color: NCBrandColor.sharedInstance.icon), title:  NSLocalizedString("_trash_restore_all_", comment: ""))
+            let item2 = DropdownItem(image: CCGraphics.changeThemingColorImage(UIImage.init(named: "trash"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), title:  NSLocalizedString("_trash_delete_all_", comment: ""))
+            
+            menuView = DropdownMenu(navigationController: self.navigationController!, items: [item0, item1, item2], selectedRow: -1)
+            menuView?.token = "tapMoreHeaderMenu"
+        }
+        
+        
+        menuView?.delegate = self
+        menuView?.rowHeight = 50
+        menuView?.tableView.alwaysBounceVertical = false
+        
+        let header = (sender as? UIButton)?.superview as! NCOfflineHeaderMenu
+        let headerRect = self.collectionView.convert(header.bounds, from: self.view)
+        let menuOffsetY =  headerRect.height - headerRect.origin.y - 2
+        menuView?.topOffsetY = CGFloat(menuOffsetY)
+        
+        menuView?.showMenu()
+    }
+    
+    func tapMoreItem(with fileID: String, sender: Any) {
+        tapMoreGridItem(with: fileID, sender: sender)
+    }
+    
+    func tapMoreGridItem(with fileID: String, sender: Any) {
+        
+        guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "fileID == %@", fileID)) else {
+            return
+        }
+        guard let serverUrl = NCManageDatabase.sharedInstance.getServerUrl(metadata.directoryID) else {
+            return
+        }
+        
+        if !isEditMode {
+            var items = [ActionSheetItem]()
+            let appearanceDelete = ActionSheetItemAppearance.init()
+            appearanceDelete.textColor = UIColor.red
+            
+            if (metadata.directory == false || serverUrl == CCUtility.getHomeServerUrlActiveUrl(appDelegate.activeUrl)) {
+                items.append(ActionSheetItem(title: NSLocalizedString("_remove_available_offline_", comment: ""), value: 0, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "offline"), multiplier: 2, color: NCBrandColor.sharedInstance.icon)))
+            }
+            items.append(ActionSheetItem(title: NSLocalizedString("_share_", comment: ""), value: 1, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "share"), multiplier: 2, color: NCBrandColor.sharedInstance.icon)))
+
+            let itemDelete = ActionSheetItem(title: NSLocalizedString("_delete_", comment: ""), value: 2, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "trash"), multiplier: 2, color: UIColor.red))
+            itemDelete.customAppearance = appearanceDelete
+            items.append(itemDelete)
+            items.append(ActionSheetCancelButton(title: NSLocalizedString("_cancel_", comment: "")))
+            
+            let actionSheet = ActionSheet(items: items) { sheet, item in
+                if item.value as? Int == 0 {
+                    if metadata.directory {
+                        let serverUrlDir = CCUtility.stringAppendServerUrl(serverUrl, addFileName: metadata.fileName)
+                        NCManageDatabase.sharedInstance.setDirectory(serverUrl: serverUrlDir!, offline: false)
+                        self.loadDatasource(withSynchronized: false)
+                    } else {
+                        NCManageDatabase.sharedInstance.setLocalFile(fileID: metadata.fileID, offline: false)
+                    }
+                }
+                if item.value as? Int == 1 { self.appDelegate.activeMain.openWindowShare(metadata) }
+                if item.value as? Int == 2 {  }
+                if item is ActionSheetCancelButton { print("Cancel buttons has the value `true`") }
+            }
+            
+            let headerView = actionSheetHeader(with: fileID)
+            actionSheet.headerView = headerView
+            actionSheet.headerView?.frame.size.height = 50
+            
+            actionSheet.present(in: self, from: sender as! UIButton)
+        } else {
+            let buttonPosition:CGPoint = (sender as! UIButton).convert(CGPoint.zero, to:collectionView)
+            let indexPath = collectionView.indexPathForItem(at: buttonPosition)
+            collectionView(self.collectionView, didSelectItemAt: indexPath!)
+        }
+    }
+    
+    // MARK: DROP-DOWN-MENU
+
+    func dropdownMenu(_ dropdownMenu: DropdownMenu, didSelectRowAt indexPath: IndexPath) {
+        
+        if dropdownMenu.token == "tapOrderHeaderMenu" {
+            
+            switch indexPath.row {
+                
+            case 0: CCUtility.setOrderSettings("fileName"); CCUtility.setAscendingSettings(true)
+            case 1: CCUtility.setOrderSettings("fileName"); CCUtility.setAscendingSettings(false)
+                
+            case 2: CCUtility.setOrderSettings("date"); CCUtility.setAscendingSettings(false)
+            case 3: CCUtility.setOrderSettings("date"); CCUtility.setAscendingSettings(true)
+                
+            case 4: CCUtility.setOrderSettings("size"); CCUtility.setAscendingSettings(true)
+            case 5: CCUtility.setOrderSettings("size"); CCUtility.setAscendingSettings(false)
+                
+            default: print("")
+            }
+            
+            datasourceSorted = CCUtility.getOrderSettings()
+            datasourceAscending = CCUtility.getAscendingSettings()
+            
+            loadDatasource(withSynchronized: false)
+        }
+        
+        if dropdownMenu.token == "tapMoreHeaderMenu" {
+        
+        }
+        
+        if dropdownMenu.token == "tapMoreHeaderMenuSelect" {
+            
+        }
+    }
+    
+    // MARK: NC API
+    
+    func downloadThumbnail(with tableMetadata: tableMetadata, indexPath: IndexPath) {
+                
+        let ocNetworking = OCnetworking.init(delegate: self, metadataNet: nil, withUser: appDelegate.activeUser, withUserID: appDelegate.activeUserID, withPassword: appDelegate.activePassword, withUrl: appDelegate.activeUrl)
+        
+        ocNetworking?.downloadPreviewTrash(withFileID: tableMetadata.fileID, fileName: tableMetadata.fileName, completion: { (message, errorCode) in
+            if errorCode == 0 && CCUtility.fileProviderStorageIconExists(tableMetadata.fileID, fileNameView: tableMetadata.fileName) {
+                self.collectionView.reloadItems(at: [indexPath])
+            }
+        })
+    }
+    
+    // MARK: DATASOURCE
+    @objc func loadDatasource(withSynchronized: Bool = false) {
+        
+        datasource.removeAll()
+        
+        let directories = NCManageDatabase.sharedInstance.getTablesDirectory(predicate: NSPredicate(format: "account == %@ AND offline == true", appDelegate.activeAccount), sorted: "serverUrl", ascending: true)
+        if directories != nil {
+            for directory: tableDirectory in directories! {
+                guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "fileID == %@", directory.fileID)) else {
+                    continue
+                }
+                datasource.append(metadata)
+            }
+        }
+        
+        let files = NCManageDatabase.sharedInstance.getTableLocalFiles(predicate: NSPredicate(format: "account == %@ AND offline == true", appDelegate.activeAccount), sorted: "fileName", ascending: true)
+        if files != nil {
+            for file: tableLocalFile in files! {
+                guard let metadata = NCManageDatabase.sharedInstance.getMetadata(predicate: NSPredicate(format: "fileID == %@", file.fileID)) else {
+                    continue
+                }
+                datasource.append(metadata)
+            }
+        }
+        
+        collectionView.reloadData()
+    }
+    
+    // MARK: COLLECTIONVIEW METHODS
+    
+    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
+        
+        if kind == UICollectionView.elementKindSectionHeader {
+            
+            let offlineHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerMenu", for: indexPath) as! NCOfflineHeaderMenu
+            
+            if collectionView.collectionViewLayout == gridLayout {
+                offlineHeader.buttonSwitch.setImage(CCGraphics.changeThemingColorImage(UIImage.init(named: "switchList"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), for: .normal)
+            } else {
+                offlineHeader.buttonSwitch.setImage(CCGraphics.changeThemingColorImage(UIImage.init(named: "switchGrid"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), for: .normal)
+            }
+            
+            offlineHeader.delegate = self
+            
+            if self.datasource.count == 0 {
+                offlineHeader.buttonSwitch.isEnabled = false
+                offlineHeader.buttonOrder.isEnabled = false
+                offlineHeader.buttonMore.isEnabled = false
+            } else {
+                offlineHeader.buttonSwitch.isEnabled = true
+                offlineHeader.buttonOrder.isEnabled = true
+                offlineHeader.buttonMore.isEnabled = true
+            }
+            
+            // Order (∨∧▽△)
+            var title = ""
+            
+            switch datasourceSorted {
+            case "fileName":
+                if datasourceAscending == true { title = NSLocalizedString("_order_by_name_a_z_", comment: "") }
+                if datasourceAscending == false { title = NSLocalizedString("_order_by_name_z_a_", comment: "") }
+            case "date":
+                if datasourceAscending == false { title = NSLocalizedString("_order_by_date_more_recent_", comment: "") }
+                if datasourceAscending == true { title = NSLocalizedString("_order_by_date_less_recent_", comment: "") }
+            case "size":
+                if datasourceAscending == true { title = NSLocalizedString("_order_by_size_smallest_", comment: "") }
+                if datasourceAscending == false { title = NSLocalizedString("_order_by_size_largest_", comment: "") }
+            default:
+                title = NSLocalizedString("_order_by_", comment: "") + " " + datasourceSorted
+            }
+            
+            title = title + "  ▽"
+            let size = title.size(withAttributes:[.font: offlineHeader.buttonOrder.titleLabel?.font as Any])
+            
+            offlineHeader.buttonOrder.setTitle(title, for: .normal)
+            offlineHeader.buttonOrderWidthConstraint.constant = size.width + 5
+            
+            return offlineHeader
+            
+        } else {
+            
+            let offlineFooter = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "footerMenu", for: indexPath) as! NCOfflineFooterMenu
+            
+            offlineFooter.labelFooter.textColor = NCBrandColor.sharedInstance.icon
+            
+            var folders: Int = 0, foldersText = ""
+            var files: Int = 0, filesText = ""
+            var size: Double = 0
+            
+            for record: tableMetadata in self.datasource {
+                if record.directory {
+                    folders += 1
+                } else {
+                    files += 1
+                    size = size + record.size
+                }
+            }
+            
+            if folders > 1 {
+                foldersText = "\(folders) " + NSLocalizedString("_folders_", comment: "")
+            } else if folders == 1 {
+                foldersText = "1 " + NSLocalizedString("_folder_", comment: "")
+            }
+            
+            if files > 1 {
+                filesText = "\(files) " + NSLocalizedString("_files_", comment: "") + " " + CCUtility.transformedSize(size)
+            } else if files == 1 {
+                filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + CCUtility.transformedSize(size)
+            }
+           
+            if foldersText == "" {
+                offlineFooter.labelFooter.text = filesText
+            } else if filesText == "" {
+                offlineFooter.labelFooter.text = foldersText
+            } else {
+                offlineFooter.labelFooter.text = foldersText + ", " + filesText
+            }
+            
+            return offlineFooter
+        }
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
+        return CGSize(width: collectionView.frame.width, height: highHeader)
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
+        return CGSize(width: collectionView.frame.width, height: highHeader)
+    }
+    
+    func numberOfSections(in collectionView: UICollectionView) -> Int {
+        return 1
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+        return datasource.count
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+        
+        let tableMetadata = datasource[indexPath.item]
+        var image: UIImage?
+        
+        if tableMetadata.iconName.count > 0 {
+            image = UIImage.init(named: tableMetadata.iconName)
+        } else {
+            image = UIImage.init(named: "file")
+        }
+        
+        if FileManager().fileExists(atPath: CCUtility.getDirectoryProviderStorageIconFileID(tableMetadata.fileID, fileNameView: tableMetadata.fileName)) {
+            image = UIImage.init(contentsOfFile: CCUtility.getDirectoryProviderStorageIconFileID(tableMetadata.fileID, fileNameView: tableMetadata.fileName))
+        } else {
+            if tableMetadata.thumbnailExists && !CCUtility.fileProviderStorageIconExists(tableMetadata.fileID, fileNameView: tableMetadata.fileName) {
+                downloadThumbnail(with: tableMetadata, indexPath: indexPath)
+            }
+        }
+        
+        if collectionView.collectionViewLayout == listLayout {
+            
+            // LIST
+            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell-list", for: indexPath) as! NCOfflineListCell
+            cell.delegate = self
+            
+            cell.fileID = tableMetadata.fileID
+            cell.indexPath = indexPath
+            cell.labelTitle.text = tableMetadata.fileNameView
+            
+            if tableMetadata.directory {
+                cell.imageItem.image = CCGraphics.changeThemingColorImage(UIImage.init(named: "folder"), multiplier: 3, color: NCBrandColor.sharedInstance.brandElement)
+                cell.labelInfo.text = CCUtility.dateDiff(tableMetadata.date as Date)
+            } else {
+                cell.imageItem.image = image
+                cell.labelInfo.text = CCUtility.dateDiff(tableMetadata.date as Date) + " " + CCUtility.transformedSize(tableMetadata.size)
+            }
+            
+            if isEditMode {
+                cell.imageItemLeftConstraint.constant = 45
+                cell.imageSelect.isHidden = false
+                
+                if selectFileID.contains(tableMetadata.fileID) {
+                    cell.imageSelect.image = CCGraphics.changeThemingColorImage(UIImage.init(named: "checkedYes"), multiplier: 2, color: NCBrandColor.sharedInstance.brand)
+                    cell.backgroundView = cellBlurEffect(with: cell.bounds)
+                } else {
+                    cell.imageSelect.image = CCGraphics.changeThemingColorImage(UIImage.init(named: "checkedNo"), multiplier: 2, color: NCBrandColor.sharedInstance.optionItem)
+                    cell.backgroundView = nil
+                }
+            } else {
+                cell.imageItemLeftConstraint.constant = 10
+                cell.imageSelect.isHidden = true
+                cell.backgroundView = nil
+            }
+            
+            return cell
+        
+        } else {
+            
+            // GRID
+            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell-grid", for: indexPath) as! NCOfflineGridCell
+            cell.delegate = self
+            
+            cell.fileID = tableMetadata.fileID
+            cell.indexPath = indexPath
+            cell.labelTitle.text = tableMetadata.fileNameView
+            
+            if tableMetadata.directory {
+                cell.imageItem.image = CCGraphics.changeThemingColorImage(UIImage.init(named: "folder"), multiplier: 3, color: NCBrandColor.sharedInstance.brandElement)
+            } else {
+                cell.imageItem.image = image
+            }
+            
+            if isEditMode {
+                cell.imageSelect.isHidden = false
+                if selectFileID.contains(tableMetadata.fileID) {
+                    cell.imageSelect.image = CCGraphics.changeThemingColorImage(UIImage.init(named: "checkedYes"), multiplier: 2, color: UIColor.white)
+                    cell.backgroundView = cellBlurEffect(with: cell.bounds)
+                } else {
+                    cell.imageSelect.isHidden = true
+                    cell.backgroundView = nil
+                }
+            } else {
+                cell.imageSelect.isHidden = true
+                cell.backgroundView = nil
+            }
+            return cell
+        }
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+        
+        let tableMetadata = datasource[indexPath.item]
+
+        if isEditMode {
+            if let index = selectFileID.index(of: tableMetadata.fileID) {
+                selectFileID.remove(at: index)
+            } else {
+                selectFileID.append(tableMetadata.fileID)
+            }
+            collectionView.reloadItems(at: [indexPath])
+            return
+        }
+        
+        if tableMetadata.directory {
+        
+            let ncOffline:NCOffline = UIStoryboard(name: "NCOffline", bundle: nil).instantiateInitialViewController() as! NCOffline
+            ncOffline.serverUrl = CCUtility.stringAppendServerUrl(serverUrl, addFileName: tableMetadata.fileName)
+            ncOffline.titleCurrentFolder = tableMetadata.fileNameView
+            self.navigationController?.pushViewController(ncOffline, animated: true)
+        }
+    }
+    
+    // MARK: UTILITY
+    
+    private func cellBlurEffect(with frame: CGRect) -> UIView {
+        
+        let blurEffect = UIBlurEffect(style: .extraLight)
+        let blurEffectView = UIVisualEffectView(effect: blurEffect)
+        
+        blurEffectView.frame = frame
+        blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+        blurEffectView.backgroundColor = NCBrandColor.sharedInstance.brand.withAlphaComponent(0.2)
+        
+        return blurEffectView
+    }
+    
+    private func actionSheetHeader(with fileID: String) -> UIView? {
+        
+        var image: UIImage?
+
+        guard let tableTrash = NCManageDatabase.sharedInstance.getTrashItem(fileID: fileID) else {
+            return nil
+        }
+        
+        // Header
+        if tableTrash.directory {
+            image = CCGraphics.changeThemingColorImage(UIImage.init(named: "folder"), multiplier: 3, color: NCBrandColor.sharedInstance.brandElement)
+        } else if tableTrash.iconName.count > 0 {
+            image = UIImage.init(named: tableTrash.iconName)
+        } else {
+            image = UIImage.init(named: "file")
+        }
+        if FileManager().fileExists(atPath: CCUtility.getDirectoryProviderStorageIconFileID(tableTrash.fileID, fileNameView: tableTrash.fileName)) {
+            image = UIImage.init(contentsOfFile: CCUtility.getDirectoryProviderStorageIconFileID(tableTrash.fileID, fileNameView: tableTrash.fileName))
+        }
+        
+        let headerView = UINib(nibName: "NCActionSheetHeaderView", bundle: nil).instantiate(withOwner: self, options: nil).first as! NCActionSheetHeaderView
+        headerView.imageItem.image = image
+        headerView.label.text = tableTrash.trashbinFileName
+        headerView.label.textColor = NCBrandColor.sharedInstance.icon
+        
+        return headerView
+    }
+}
+
+class ListLayoutOffline: UICollectionViewFlowLayout {
+    
+    let itemHeight: CGFloat = 60
+    
+    override init() {
+        super.init()
+        
+        minimumInteritemSpacing = 0
+        minimumLineSpacing = 1
+        
+        self.scrollDirection = .vertical
+        self.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
+    }
+    
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    override var itemSize: CGSize {
+        get {
+            if let collectionView = collectionView {
+                let itemWidth: CGFloat = collectionView.frame.width
+                return CGSize(width: itemWidth, height: self.itemHeight)
+            }
+            
+            // Default fallback
+            return CGSize(width: 100, height: 100)
+        }
+        set {
+            super.itemSize = newValue
+        }
+    }
+    
+    override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
+        return proposedContentOffset
+    }
+}
+
+class GridLayoutOffline: UICollectionViewFlowLayout {
+    
+    let heightLabelPlusButton: CGFloat = 45
+    let preferenceWidth: CGFloat = 110
+    let marginLeftRight: CGFloat = 5
+    
+    override init() {
+        super.init()
+        
+        minimumInteritemSpacing = 1
+        minimumLineSpacing = 1
+
+        self.scrollDirection = .vertical
+        self.sectionInset = UIEdgeInsets(top: 10, left: marginLeftRight, bottom: 10, right:  marginLeftRight)
+    }
+    
+    required init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    override var itemSize: CGSize {
+        get {
+            if let collectionView = collectionView {
+                
+                let numItems: Int = Int(collectionView.frame.width / preferenceWidth)                
+                let itemWidth: CGFloat = (collectionView.frame.width - (marginLeftRight * 2) - CGFloat(numItems)) / CGFloat(numItems)
+                let itemHeight: CGFloat = itemWidth + heightLabelPlusButton
+                return CGSize(width: itemWidth, height: itemHeight)
+            }
+            
+            // Default fallback
+            return CGSize(width: 100, height: 100)
+        }
+        set {
+            super.itemSize = newValue
+        }
+    }
+    
+    override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
+        return proposedContentOffset
+    }
+}

+ 53 - 0
iOSClient/Offline/NCOfflineGridCell.swift

@@ -0,0 +1,53 @@
+//
+//  NCOfflineGridCell.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 24/10/2018.
+//  Copyright © 2018 Marino Faggiana. 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
+import UIKit
+
+class NCOfflineGridCell: UICollectionViewCell {
+    
+    @IBOutlet weak var imageItem: UIImageView!
+    @IBOutlet weak var imageSelect: UIImageView!
+    @IBOutlet weak var labelTitle: UILabel!
+    @IBOutlet weak var imageMore: UIImageView!
+    @IBOutlet weak var buttonMoreGrid: UIButton!
+
+    var delegate: NCOfflineGridCellDelegate?
+    
+    var fileID = ""
+    var indexPath = IndexPath()
+
+    override func awakeFromNib() {
+        super.awakeFromNib()
+       
+        imageMore.image = CCGraphics.changeThemingColorImage(UIImage.init(named: "more"), multiplier: 2, color: NCBrandColor.sharedInstance.optionItem)
+    }
+    
+    @IBAction func touchUpInsideMoreGrid(_ sender: Any) {
+        delegate?.tapMoreGridItem(with: fileID, sender: sender)
+    }
+}
+
+protocol NCOfflineGridCellDelegate {
+    func tapMoreGridItem(with fileID: String, sender: Any)
+}

+ 84 - 0
iOSClient/Offline/NCOfflineGridCell.xib

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cell-grid" id="vf1-Kf-9uL" customClass="NCOfflineGridCell" customModule="Nextcloud" customModuleProvider="target">
+            <rect key="frame" x="0.0" y="0.0" width="220" height="265"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
+                <rect key="frame" x="0.0" y="0.0" width="220" height="265"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="5Ci-V1-hf5" userLabel="imageItem">
+                        <rect key="frame" x="0.0" y="0.0" width="220" height="220"/>
+                    </imageView>
+                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eU3-lY-fKr" userLabel="labelTitle">
+                        <rect key="frame" x="0.0" y="220" width="220" height="14.5"/>
+                        <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                        <nil key="textColor"/>
+                        <nil key="highlightedColor"/>
+                    </label>
+                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="EJs-Ro-nbe" userLabel="buttonMoreGrid">
+                        <rect key="frame" x="95" y="234.5" width="30" height="30"/>
+                        <constraints>
+                            <constraint firstAttribute="height" constant="30" id="4Ba-Uy-pX2"/>
+                            <constraint firstAttribute="width" constant="30" id="aRK-GA-Nba"/>
+                        </constraints>
+                        <connections>
+                            <action selector="touchUpInsideMoreGrid:" destination="vf1-Kf-9uL" eventType="touchUpInside" id="bg0-Yq-0J6"/>
+                        </connections>
+                    </button>
+                    <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="3sA-NC-kIg" userLabel="imageMore">
+                        <rect key="frame" x="100" y="239.5" width="20" height="20"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="20" id="hoH-4o-Tff"/>
+                            <constraint firstAttribute="height" constant="20" id="vGK-h7-x3M"/>
+                        </constraints>
+                    </imageView>
+                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="DHy-Up-3Bh" userLabel="imageSelect">
+                        <rect key="frame" x="192" y="192" width="25" height="25"/>
+                        <constraints>
+                            <constraint firstAttribute="height" constant="25" id="SoZ-J3-98x"/>
+                            <constraint firstAttribute="width" constant="25" id="cZG-gx-gwt"/>
+                        </constraints>
+                    </imageView>
+                </subviews>
+            </view>
+            <constraints>
+                <constraint firstItem="eU3-lY-fKr" firstAttribute="top" secondItem="5Ci-V1-hf5" secondAttribute="bottom" id="4Yq-Nh-z1l"/>
+                <constraint firstItem="DHy-Up-3Bh" firstAttribute="top" secondItem="5Ci-V1-hf5" secondAttribute="bottom" constant="-28" id="I68-jJ-Ea7"/>
+                <constraint firstItem="VXh-sQ-LeX" firstAttribute="trailing" secondItem="eU3-lY-fKr" secondAttribute="trailing" id="Lu1-AM-kPq"/>
+                <constraint firstItem="5Ci-V1-hf5" firstAttribute="top" secondItem="VXh-sQ-LeX" secondAttribute="top" id="Ouj-ZD-UFm"/>
+                <constraint firstItem="VXh-sQ-LeX" firstAttribute="trailing" secondItem="5Ci-V1-hf5" secondAttribute="trailing" id="cHT-cP-NN6"/>
+                <constraint firstItem="VXh-sQ-LeX" firstAttribute="bottom" secondItem="5Ci-V1-hf5" secondAttribute="bottom" constant="45" id="eEC-eB-alE"/>
+                <constraint firstItem="eU3-lY-fKr" firstAttribute="leading" secondItem="VXh-sQ-LeX" secondAttribute="leading" id="gZe-FC-8XQ"/>
+                <constraint firstItem="DHy-Up-3Bh" firstAttribute="leading" secondItem="5Ci-V1-hf5" secondAttribute="trailing" constant="-28" id="ib0-sc-DXe"/>
+                <constraint firstItem="5Ci-V1-hf5" firstAttribute="leading" secondItem="VXh-sQ-LeX" secondAttribute="leading" id="qT3-WD-iTV"/>
+                <constraint firstItem="3sA-NC-kIg" firstAttribute="centerY" secondItem="EJs-Ro-nbe" secondAttribute="centerY" id="r4I-Ey-m5L"/>
+                <constraint firstItem="EJs-Ro-nbe" firstAttribute="top" secondItem="eU3-lY-fKr" secondAttribute="bottom" id="uL8-ea-AWa"/>
+                <constraint firstItem="EJs-Ro-nbe" firstAttribute="centerX" secondItem="VXh-sQ-LeX" secondAttribute="centerX" id="vNm-qK-cIn"/>
+                <constraint firstItem="3sA-NC-kIg" firstAttribute="centerX" secondItem="EJs-Ro-nbe" secondAttribute="centerX" id="xIf-Ba-1CZ"/>
+            </constraints>
+            <viewLayoutGuide key="safeArea" id="VXh-sQ-LeX"/>
+            <size key="customSize" width="220" height="260"/>
+            <connections>
+                <outlet property="buttonMoreGrid" destination="EJs-Ro-nbe" id="sUc-vE-XKf"/>
+                <outlet property="imageItem" destination="5Ci-V1-hf5" id="xky-Nw-NUb"/>
+                <outlet property="imageMore" destination="3sA-NC-kIg" id="yZE-cI-zm0"/>
+                <outlet property="imageSelect" destination="DHy-Up-3Bh" id="mo9-rP-P4I"/>
+                <outlet property="labelTitle" destination="eU3-lY-fKr" id="0P7-yM-Asb"/>
+            </connections>
+            <point key="canvasLocation" x="88" y="141.67916041979012"/>
+        </collectionViewCell>
+    </objects>
+</document>

+ 77 - 0
iOSClient/Offline/NCOfflineHeaderFooterMenu.swift

@@ -0,0 +1,77 @@
+//
+//  NCOfflineHeaderFooterMenu.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 24/10/2018.
+//  Copyright © 2018 Marino Faggiana. 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
+
+class NCOfflineHeaderMenu: UICollectionReusableView {
+    
+    @IBOutlet weak var buttonMore: UIButton!
+    @IBOutlet weak var buttonSwitch: UIButton!
+    @IBOutlet weak var buttonOrder: UIButton!
+    @IBOutlet weak var buttonOrderWidthConstraint: NSLayoutConstraint!
+    @IBOutlet weak var separator: UIView!
+    
+    var delegate: NCOfflineHeaderMenuDelegate?
+
+    override func awakeFromNib() {
+        super.awakeFromNib()
+        
+        buttonSwitch.setImage(CCGraphics.changeThemingColorImage(UIImage.init(named: "switchList"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), for: .normal)
+        
+        buttonOrder.setTitle("", for: .normal)
+        buttonOrder.setTitleColor(NCBrandColor.sharedInstance.icon, for: .normal)
+        
+        buttonMore.setImage(CCGraphics.changeThemingColorImage(UIImage.init(named: "more"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), for: .normal)
+        
+        separator.backgroundColor = NCBrandColor.sharedInstance.seperator
+    }
+    
+    @IBAction func touchUpInsideMore(_ sender: Any) {
+        delegate?.tapMoreHeaderMenu(sender: sender)
+    }
+    
+    @IBAction func touchUpInsideSwitch(_ sender: Any) {
+        delegate?.tapSwitchHeaderMenu(sender: sender)
+    }
+    
+    @IBAction func touchUpInsideOrder(_ sender: Any) {
+        delegate?.tapOrderHeaderMenu(sender: sender)
+    }
+}
+
+protocol NCOfflineHeaderMenuDelegate {
+    func tapSwitchHeaderMenu(sender: Any)
+    func tapMoreHeaderMenu(sender: Any)
+    func tapOrderHeaderMenu(sender: Any)
+
+}
+
+class NCOfflineFooterMenu: UICollectionReusableView {
+    
+    @IBOutlet weak var labelFooter: UILabel!
+
+    override func awakeFromNib() {
+        super.awakeFromNib()
+        
+    }
+}

+ 61 - 0
iOSClient/Offline/NCOfflineListCell.swift

@@ -0,0 +1,61 @@
+//
+//  NCOfflineListCell.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 24/10/2018.
+//  Copyright © 2018 Marino Faggiana. 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
+import UIKit
+
+class NCOfflineListCell: UICollectionViewCell {
+    
+    @IBOutlet weak var imageItem: UIImageView!
+    @IBOutlet weak var imageItemLeftConstraint: NSLayoutConstraint!
+    @IBOutlet weak var imageSelect: UIImageView!
+
+    @IBOutlet weak var labelTitle: UILabel!
+    @IBOutlet weak var labelInfo: UILabel!
+    
+    @IBOutlet weak var imageMore: UIImageView!
+    @IBOutlet weak var buttonMore: UIButton!
+    
+    @IBOutlet weak var separator: UIView!
+
+    var delegate: NCOfflineListCellDelegate?
+    
+    var fileID = ""
+    var indexPath = IndexPath()
+
+    override func awakeFromNib() {
+        super.awakeFromNib()
+       
+        imageMore.image = CCGraphics.changeThemingColorImage(UIImage.init(named: "more"), multiplier: 2, color: NCBrandColor.sharedInstance.optionItem)
+        
+        separator.backgroundColor = NCBrandColor.sharedInstance.seperator
+    }
+    
+    @IBAction func touchUpInsideMore(_ sender: Any) {
+        delegate?.tapMoreItem(with: fileID, sender: sender)
+    }
+}
+
+protocol NCOfflineListCellDelegate {
+    func tapMoreItem(with fileID: String, sender: Any)
+}

+ 109 - 0
iOSClient/Offline/NCOfflineListCell.xib

@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cell-list" id="jxV-Pk-fPt" customClass="NCOfflineListCell" customModule="Nextcloud" customModuleProvider="target">
+            <rect key="frame" x="0.0" y="0.0" width="600" height="60"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
+                <rect key="frame" x="0.0" y="0.0" width="600" height="60"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="w2m-Vw-hpd" userLabel="ImageItem">
+                        <rect key="frame" x="45" y="10" width="40" height="40"/>
+                        <constraints>
+                            <constraint firstAttribute="height" constant="40" id="Dpd-Xj-z4U"/>
+                            <constraint firstAttribute="width" constant="40" id="v0e-MW-EeE"/>
+                        </constraints>
+                    </imageView>
+                    <label opaque="NO" userInteractionEnabled="NO" tag="101" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="UtT-L6-mgW" userLabel="labelTitle">
+                        <rect key="frame" x="95" y="13" width="455" height="18"/>
+                        <fontDescription key="fontDescription" type="system" pointSize="15"/>
+                        <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                        <nil key="highlightedColor"/>
+                    </label>
+                    <label opaque="NO" userInteractionEnabled="NO" tag="102" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AXX-71-9Q6" userLabel="labelInfo">
+                        <rect key="frame" x="95" y="31" width="455" 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="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="dgL-g5-Nkc" userLabel="imageMore">
+                        <rect key="frame" x="565" y="20" width="20" height="20"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="20" id="05P-NL-pd8"/>
+                            <constraint firstAttribute="height" constant="20" id="Jet-eo-x1M" userLabel="height = 20"/>
+                        </constraints>
+                    </imageView>
+                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yhy-xd-w5C" userLabel="buttonMore">
+                        <rect key="frame" x="560" y="0.0" width="40" height="60"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="40" id="ZgH-mI-l2k"/>
+                            <constraint firstAttribute="height" constant="60" id="woC-64-Tyc"/>
+                        </constraints>
+                        <connections>
+                            <action selector="touchUpInsideMore:" destination="jxV-Pk-fPt" eventType="touchUpInside" id="Mtu-LP-kuR"/>
+                        </connections>
+                    </button>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Egg-cb-EhZ" userLabel="separator">
+                        <rect key="frame" x="85" y="59" width="515" height="1"/>
+                        <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <color key="tintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <constraints>
+                            <constraint firstAttribute="height" constant="1" id="G5S-67-boG"/>
+                        </constraints>
+                    </view>
+                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="AyA-hP-r6w" userLabel="imageSelect">
+                        <rect key="frame" x="10" y="17.5" width="25" height="25"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="25" id="bIF-gu-6Jj"/>
+                            <constraint firstAttribute="height" constant="25" id="nJa-oj-gcQ"/>
+                        </constraints>
+                    </imageView>
+                </subviews>
+            </view>
+            <constraints>
+                <constraint firstItem="Gu8-oz-zWa" firstAttribute="bottom" secondItem="Egg-cb-EhZ" secondAttribute="bottom" id="81D-sw-EaX"/>
+                <constraint firstItem="yhy-xd-w5C" firstAttribute="leading" secondItem="dgL-g5-Nkc" secondAttribute="trailing" constant="-25" id="980-6s-ave"/>
+                <constraint firstItem="yhy-xd-w5C" firstAttribute="leading" secondItem="UtT-L6-mgW" secondAttribute="trailing" constant="10" id="Db3-6O-kdP"/>
+                <constraint firstItem="Egg-cb-EhZ" firstAttribute="leading" secondItem="w2m-Vw-hpd" secondAttribute="trailing" id="JCm-UU-Pxu"/>
+                <constraint firstItem="dgL-g5-Nkc" firstAttribute="centerY" secondItem="yhy-xd-w5C" secondAttribute="centerY" id="OMy-Cu-HAx"/>
+                <constraint firstItem="UtT-L6-mgW" firstAttribute="leading" secondItem="w2m-Vw-hpd" secondAttribute="trailing" constant="10" id="PQ8-0b-fLa"/>
+                <constraint firstItem="AXX-71-9Q6" firstAttribute="leading" secondItem="w2m-Vw-hpd" secondAttribute="trailing" constant="10" id="Qvq-r5-AX9"/>
+                <constraint firstItem="AyA-hP-r6w" firstAttribute="leading" secondItem="Gu8-oz-zWa" secondAttribute="leading" constant="10" id="RYl-cO-cCN"/>
+                <constraint firstItem="yhy-xd-w5C" firstAttribute="centerY" secondItem="Gu8-oz-zWa" secondAttribute="centerY" id="ZO7-Ny-L3I"/>
+                <constraint firstItem="Gu8-oz-zWa" firstAttribute="bottom" secondItem="AXX-71-9Q6" secondAttribute="bottom" constant="14" id="d06-sn-I3Y"/>
+                <constraint firstItem="Gu8-oz-zWa" firstAttribute="trailing" secondItem="Egg-cb-EhZ" secondAttribute="trailing" id="k8f-bU-D6I"/>
+                <constraint firstItem="w2m-Vw-hpd" firstAttribute="leading" secondItem="Gu8-oz-zWa" secondAttribute="leading" constant="45" id="mBb-ff-7HD"/>
+                <constraint firstItem="UtT-L6-mgW" firstAttribute="top" secondItem="Gu8-oz-zWa" secondAttribute="top" constant="13" id="nrY-2F-QZ2"/>
+                <constraint firstItem="w2m-Vw-hpd" firstAttribute="centerY" secondItem="Gu8-oz-zWa" secondAttribute="centerY" id="qKl-4Y-m5t"/>
+                <constraint firstItem="yhy-xd-w5C" firstAttribute="leading" secondItem="AXX-71-9Q6" secondAttribute="trailing" constant="10" id="qem-j1-9RR"/>
+                <constraint firstItem="Gu8-oz-zWa" firstAttribute="trailing" secondItem="yhy-xd-w5C" secondAttribute="trailing" id="s2S-RP-cw5"/>
+                <constraint firstItem="AyA-hP-r6w" firstAttribute="centerY" secondItem="Gu8-oz-zWa" secondAttribute="centerY" id="sJp-0x-bdC"/>
+            </constraints>
+            <viewLayoutGuide key="safeArea" id="Gu8-oz-zWa"/>
+            <size key="customSize" width="650" height="58"/>
+            <connections>
+                <outlet property="buttonMore" destination="yhy-xd-w5C" id="agm-M9-xtq"/>
+                <outlet property="imageItem" destination="w2m-Vw-hpd" id="iY5-ed-crD"/>
+                <outlet property="imageItemLeftConstraint" destination="mBb-ff-7HD" id="fsR-5N-1NC"/>
+                <outlet property="imageMore" destination="dgL-g5-Nkc" id="r7x-Ib-4nz"/>
+                <outlet property="imageSelect" destination="AyA-hP-r6w" id="c1t-yz-HBg"/>
+                <outlet property="labelInfo" destination="AXX-71-9Q6" id="krb-tZ-UQ7"/>
+                <outlet property="labelTitle" destination="UtT-L6-mgW" id="Xv6-zM-2v1"/>
+                <outlet property="separator" destination="Egg-cb-EhZ" id="uhq-Nc-z8K"/>
+            </connections>
+            <point key="canvasLocation" x="97.599999999999994" y="129.53523238380811"/>
+        </collectionViewCell>
+    </objects>
+</document>