Marino Faggiana 6 жил өмнө
parent
commit
e0f4339d6d

+ 36 - 0
Nextcloud.xcodeproj/project.pbxproj

@@ -163,6 +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 */; };
+		F73747F8218059CA00908896 /* NCOnDevice.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F73747F1218059CA00908896 /* NCOnDevice.storyboard */; };
+		F73747F9218059CA00908896 /* NCOnDeviceListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73747F2218059CA00908896 /* NCOnDeviceListCell.swift */; };
+		F73747FA218059CA00908896 /* NCOnDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73747F3218059CA00908896 /* NCOnDevice.swift */; };
+		F73747FB218059CA00908896 /* NCOnDeviceGridCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73747F4218059CA00908896 /* NCOnDeviceGridCell.swift */; };
+		F73747FC218059CA00908896 /* NCOnDeviceGridCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F73747F5218059CA00908896 /* NCOnDeviceGridCell.xib */; };
+		F73747FD218059CA00908896 /* NCOnDeviceListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F73747F6218059CA00908896 /* NCOnDeviceListCell.xib */; };
+		F73747FE218059CA00908896 /* NCOnDeviceHeaderFooterMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73747F7218059CA00908896 /* NCOnDeviceHeaderFooterMenu.swift */; };
 		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 */; };
@@ -940,6 +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>"; };
+		F73747F1218059CA00908896 /* NCOnDevice.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCOnDevice.storyboard; sourceTree = "<group>"; };
+		F73747F2218059CA00908896 /* NCOnDeviceListCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOnDeviceListCell.swift; sourceTree = "<group>"; };
+		F73747F3218059CA00908896 /* NCOnDevice.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOnDevice.swift; sourceTree = "<group>"; };
+		F73747F4218059CA00908896 /* NCOnDeviceGridCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOnDeviceGridCell.swift; sourceTree = "<group>"; };
+		F73747F5218059CA00908896 /* NCOnDeviceGridCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCOnDeviceGridCell.xib; sourceTree = "<group>"; };
+		F73747F6218059CA00908896 /* NCOnDeviceListCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCOnDeviceListCell.xib; sourceTree = "<group>"; };
+		F73747F7218059CA00908896 /* NCOnDeviceHeaderFooterMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCOnDeviceHeaderFooterMenu.swift; 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>"; };
@@ -2118,6 +2132,20 @@
 			path = "Notification Service Extension";
 			sourceTree = "<group>";
 		};
+		F73747F0218059CA00908896 /* OnDevice */ = {
+			isa = PBXGroup;
+			children = (
+				F73747F1218059CA00908896 /* NCOnDevice.storyboard */,
+				F73747F3218059CA00908896 /* NCOnDevice.swift */,
+				F73747F4218059CA00908896 /* NCOnDeviceGridCell.swift */,
+				F73747F5218059CA00908896 /* NCOnDeviceGridCell.xib */,
+				F73747F7218059CA00908896 /* NCOnDeviceHeaderFooterMenu.swift */,
+				F73747F2218059CA00908896 /* NCOnDeviceListCell.swift */,
+				F73747F6218059CA00908896 /* NCOnDeviceListCell.xib */,
+			);
+			path = OnDevice;
+			sourceTree = "<group>";
+		};
 		F73B4EAC1F470D9100BBEE4B /* src */ = {
 			isa = PBXGroup;
 			children = (
@@ -3438,6 +3466,7 @@
 				F7F9E3451BC26B19004B9223 /* Move */,
 				F74D3DB81BAC1941000BAE4B /* Networking */,
 				F7C5259A1E3B441D00FFE02C /* Notification */,
+				F73747F0218059CA00908896 /* OnDevice */,
 				F7FCFFD51D70798C000E6E29 /* PeekPop */,
 				F7BE6E2A1D2D5C3B00106933 /* QuickActions */,
 				F7FE125B1BAC03FB0041924B /* Security */,
@@ -3817,6 +3846,7 @@
 				F7226EDC1EE4089300EBECB1 /* Main.storyboard in Resources */,
 				F7ED7EDC216B83D5007AB4D9 /* NCTrashListCell.xib in Resources */,
 				F7D423471F0596AC009C9782 /* Reader-Mark-Y.png in Resources */,
+				F73747FD218059CA00908896 /* NCOnDeviceListCell.xib in Resources */,
 				F7D423431F0596AC009C9782 /* Reader-Export@3x.png in Resources */,
 				F7D4233C1F0596AC009C9782 /* Reader-Button-N@2x.png in Resources */,
 				F729B92B217A2E4E00FE2150 /* NCActionSheetHeaderView.xib in Resources */,
@@ -3825,6 +3855,7 @@
 				F7417DB5216CFE8E007D05F5 /* NCTrashGridCell.xib in Resources */,
 				F7D4233E1F0596AC009C9782 /* Reader-Email.png in Resources */,
 				F762CB981EACB84400B38484 /* icon-info@2x.png in Resources */,
+				F73747FC218059CA00908896 /* NCOnDeviceGridCell.xib in Resources */,
 				F7D423361F0596AC009C9782 /* AppIcon-167.png in Resources */,
 				F7F54CF71E5B14C700E19C62 /* PlayButtonOverlayLargeTap.png in Resources */,
 				F710E8111EF95C9C00DC2427 /* ImagesIntro.xcassets in Resources */,
@@ -3880,6 +3911,7 @@
 				F7D423481F0596AC009C9782 /* Reader-Mark-Y@2x.png in Resources */,
 				F7D4233F1F0596AC009C9782 /* Reader-Email@2x.png in Resources */,
 				F73B4EF11F470D9100BBEE4B /* EUCKRFreq.tab in Resources */,
+				F73747F8218059CA00908896 /* NCOnDevice.storyboard in Resources */,
 				F774DF111FCC26BE002AF9FC /* iTunesArtwork@3x.png in Resources */,
 				F762CB961EACB84400B38484 /* icon-error@2x.png in Resources */,
 				F7D4234A1F0596AC009C9782 /* Reader-Print.png in Resources */,
@@ -4160,6 +4192,7 @@
 				F7B1FBC61E72E3D1001781FE /* SwiftModalWebVC.swift in Sources */,
 				F7622FD02175FCC0000383FF /* ActionSheetCustomItem.swift in Sources */,
 				F7A5541F204EF8AF008468EC /* TOScrollBar.m in Sources */,
+				F73747FE218059CA00908896 /* NCOnDeviceHeaderFooterMenu.swift in Sources */,
 				F7A321651E9E37960069AD1B /* CCActivity.m in Sources */,
 				F7FB1D3E215E191D00D669EA /* NCViewerDocumentWeb.swift in Sources */,
 				F712AC902175E56F0061158E /* CTAssetSelectionLabel.m in Sources */,
@@ -4251,14 +4284,17 @@
 				F77B0E4F1D118A16002130FE /* CCManageAutoUpload.m in Sources */,
 				F712ACAC2175E56F0061158E /* UICollectionView+CTAssetsPickerController.m in Sources */,
 				F7FCFFE01D707B83000E6E29 /* CCPeekPop.m in Sources */,
+				F73747FB218059CA00908896 /* NCOnDeviceGridCell.swift in Sources */,
 				F7BAADC81ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */,
 				F7622FD32175FCC0000383FF /* ActionSheetLinkItem.swift in Sources */,
+				F73747FA218059CA00908896 /* NCOnDevice.swift in Sources */,
 				F712AC922175E56F0061158E /* CTAssetItemViewController.m in Sources */,
 				F77B0E541D118A16002130FE /* CCMove.m in Sources */,
 				F7622FC42175FCC0000383FF /* ActionSheetPopoverPresenter.swift in Sources */,
 				F712ACA72175E56F0061158E /* CTAssetCollectionViewCell.m in Sources */,
 				F7A5541E204EF8AF008468EC /* TOScrollBarGestureRecognizer.m in Sources */,
 				F7622FCB2175FCC0000383FF /* ActionSheetDangerButton.swift in Sources */,
+				F73747F9218059CA00908896 /* NCOnDeviceListCell.swift in Sources */,
 				F758B452212C516300515F55 /* Quadrilateral.swift in Sources */,
 				F712AC952175E56F0061158E /* CTAssetScrollView.m in Sources */,
 				F70022E61EC4C9100080073F /* OCXMLServerErrorsParser.m in Sources */,

+ 147 - 0
iOSClient/OnDevice/NCOnDevice.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>
+        <!--On Device-->
+        <scene sceneID="X4W-6b-l7s">
+            <objects>
+                <viewController storyboardIdentifier="NCOnDevice.storyboard" id="EFX-fO-Oip" customClass="NCOnDevice" 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="NCOnDeviceHeaderMenu" 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="NCOnDeviceFooterMenu" 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>

+ 853 - 0
iOSClient/OnDevice/NCOnDevice.swift

@@ -0,0 +1,853 @@
+//
+//  NCOnDevice.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 NCOnDevice: UIViewController ,UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UIGestureRecognizerDelegate, NCOnDeviceListCellDelegate, NCOnDeviceGridCellDelegate, NCOnDeviceHeaderMenuDelegate, DropdownMenuDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate  {
+    
+    @IBOutlet fileprivate weak var collectionView: UICollectionView!
+
+    let appDelegate = UIApplication.shared.delegate as! AppDelegate
+    var path = ""
+    var titleCurrentFolder = NSLocalizedString("_trash_view_", comment: "")
+    var datasource = [tableTrash]()
+    var datasourceSorted = ""
+    var datasourceAscending = true
+    var isEditMode = false
+    var selectFileID = [String]()
+    
+    var listLayout: ListLayoutOnDevice!
+    var gridLayout: GridLayoutOnDevice!
+    
+    private let highHeader: CGFloat = 50
+    
+    private let refreshControl = UIRefreshControl()
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        
+        collectionView.register(UINib.init(nibName: "NCOnDeviceListCell", bundle: nil), forCellWithReuseIdentifier: "cell-list")
+        collectionView.register(UINib.init(nibName: "NCOnDeviceGridCell", bundle: nil), forCellWithReuseIdentifier: "cell-grid")
+        
+        collectionView.alwaysBounceVertical = true
+
+        listLayout = ListLayoutOnDevice()
+        gridLayout = GridLayoutOnDevice()
+        
+        if CCUtility.getLayoutTrash() == "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(loadListingTrash), 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 path == "" {
+            let userID = (appDelegate.activeUserID as NSString).addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlFragmentAllowed)
+            path = k_dav + "/trashbin/" + userID! + "/trash/"
+        }
+        
+        datasourceSorted = CCUtility.getOrderSettings()
+        datasourceAscending = CCUtility.getAscendingSettings()
+        
+        guard let datasource = NCManageDatabase.sharedInstance.getTrash(filePath: path, sorted: datasourceSorted, ascending: datasourceAscending) else {
+            return
+        }
+        
+        self.datasource = datasource
+        collectionView.reloadData()
+        
+        loadListingTrash()
+    }
+    
+    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: "trashNoFiles"), multiplier: 2, color: NCBrandColor.sharedInstance.graySoft)
+    }
+    
+    func title(forEmptyDataSet scrollView: UIScrollView) -> NSAttributedString? {
+        let text = "\n"+NSLocalizedString("_trash_no_trash_", comment: "")
+        let attributes = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 20), 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.setLayoutTrash("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.setLayoutTrash("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! NCOnDeviceHeaderMenu
+        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! NCOnDeviceHeaderMenu
+        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 tapRestoreItem(with fileID: String, sender: Any) {
+        
+        if !isEditMode {
+            restoreItem(with: fileID)
+        } else {
+            let buttonPosition:CGPoint = (sender as! UIButton).convert(CGPoint.zero, to:collectionView)
+            let indexPath = collectionView.indexPathForItem(at: buttonPosition)
+            collectionView(self.collectionView, didSelectItemAt: indexPath!)
+        }
+    }
+    
+    func tapMoreItem(with fileID: String, sender: Any) {
+
+        if !isEditMode {
+            var items = [ActionSheetItem]()
+            
+            items.append(ActionSheetDangerButton(title: NSLocalizedString("_delete_", comment: "")))
+            items.append(ActionSheetCancelButton(title: NSLocalizedString("_cancel_", comment: "")))
+            
+            let actionSheet = ActionSheet(items: items) { sheet, item in
+                if item is ActionSheetDangerButton { self.deleteItem(with: fileID) }
+                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!)
+        }
+    }
+    
+    func tapMoreGridItem(with fileID: String, sender: Any) {
+        
+        if !isEditMode {
+            var items = [ActionSheetItem]()
+            let appearanceDelete = ActionSheetItemAppearance.init()
+            appearanceDelete.textColor = UIColor.red
+            
+            items.append(ActionSheetItem(title: NSLocalizedString("_restore_", comment: ""), value: 0, image: CCGraphics.changeThemingColorImage(UIImage.init(named: "restore"), multiplier: 1, color: NCBrandColor.sharedInstance.icon)))
+            let itemDelete = ActionSheetItem(title: NSLocalizedString("_delete_", comment: ""), value: 1, 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 { self.restoreItem(with: fileID) }
+                if item.value as? Int == 1 { self.deleteItem(with: fileID) }
+                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()
+            
+            guard let datasource = NCManageDatabase.sharedInstance.getTrash(filePath: path, sorted: datasourceSorted, ascending: datasourceAscending) else {
+                return
+            }
+            
+            self.datasource = datasource
+            collectionView.reloadData()
+        }
+        
+        if dropdownMenu.token == "tapMoreHeaderMenu" {
+        
+            // Select
+            if indexPath.row == 0 {
+                isEditMode = true
+                collectionView.reloadData()
+            }
+            
+            // Restore ALL
+            if indexPath.row == 1 {
+                for record: tableTrash in self.datasource {
+                    restoreItem(with: record.fileID)
+                }
+            }
+            
+            // Delete ALL
+            if indexPath.row == 2 {
+                
+                var items = [ActionSheetItem]()
+                
+                items.append(ActionSheetTitle(title: NSLocalizedString("_trash_delete_all_", comment: "")))
+                items.append(ActionSheetDangerButton(title: NSLocalizedString("_delete_", comment: "")))
+                items.append(ActionSheetCancelButton(title: NSLocalizedString("_cancel_", comment: "")))
+                
+                let actionSheet = ActionSheet(items: items) { sheet, item in
+                    if item is ActionSheetDangerButton {
+                        for record: tableTrash in self.datasource {
+                            self.deleteItem(with: record.fileID)
+                        }
+                    }
+                    if item is ActionSheetCancelButton { return }
+                }
+                
+                actionSheet.present(in: self, from: self.view)
+            }
+        }
+        
+        if dropdownMenu.token == "tapMoreHeaderMenuSelect" {
+            
+            // Cancel
+            if indexPath.row == 0 {
+                isEditMode = false
+                selectFileID.removeAll()
+                collectionView.reloadData()
+            }
+            
+            // Restore selected files
+            if indexPath.row == 1 {
+                for fileID in selectFileID {
+                    restoreItem(with: fileID)
+                }
+                isEditMode = false
+                selectFileID.removeAll()
+                collectionView.reloadData()
+            }
+            
+            // Delete selected files
+            if indexPath.row == 2 {
+                
+                var items = [ActionSheetItem]()
+                
+                items.append(ActionSheetTitle(title: NSLocalizedString("_trash_delete_selected_", comment: "")))
+                items.append(ActionSheetDangerButton(title: NSLocalizedString("_delete_", comment: "")))
+                items.append(ActionSheetCancelButton(title: NSLocalizedString("_cancel_", comment: "")))
+                
+                let actionSheet = ActionSheet(items: items) { sheet, item in
+                    if item is ActionSheetDangerButton {
+                        for fileID in self.selectFileID {
+                            self.deleteItem(with: fileID)
+                        }
+                        self.isEditMode = false
+                        self.selectFileID.removeAll()
+                        self.collectionView.reloadData()
+                    }
+                    if item is ActionSheetCancelButton { return }
+                }
+                
+                actionSheet.present(in: self, from: self.view)
+            }
+            
+        }
+    }
+    
+    // MARK: NC API
+    
+    @objc func loadListingTrash() {
+        
+        let ocNetworking = OCnetworking.init(delegate: self, metadataNet: nil, withUser: appDelegate.activeUser, withUserID: appDelegate.activeUserID, withPassword: appDelegate.activePassword, withUrl: appDelegate.activeUrl)
+        
+        ocNetworking?.listingTrash(appDelegate.activeUrl, path:path, account: appDelegate.activeAccount, success: { (item) in
+            
+            self.refreshControl.endRefreshing()
+
+            NCManageDatabase.sharedInstance.deleteTrash(filePath: self.path)
+            NCManageDatabase.sharedInstance.addTrashs(item as! [tableTrash])
+            
+            let results = NCManageDatabase.sharedInstance.getTrash(filePath: self.path, sorted: self.datasourceSorted, ascending: self.datasourceAscending)
+            if (results != nil) {
+                self.datasource = results!
+                DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
+                    self.collectionView.reloadData()
+                }
+            }
+            
+        }, failure: { (message, errorCode) in
+            
+            self.refreshControl.endRefreshing()
+            print("error " + message!)
+        })
+    }
+    
+    func restoreItem(with fileID: String) {
+        
+        guard let tableTrash = NCManageDatabase.sharedInstance.getTrashItem(fileID: fileID) else {
+            return
+        }
+        
+        let ocNetworking = OCnetworking.init(delegate: self, metadataNet: nil, withUser: appDelegate.activeUser, withUserID: appDelegate.activeUserID, withPassword: appDelegate.activePassword, withUrl: appDelegate.activeUrl)
+                
+        let fileName = appDelegate.activeUrl + tableTrash.filePath + tableTrash.fileName
+        let fileNameTo = appDelegate.activeUrl + k_dav + "/trashbin/" + appDelegate.activeUserID + "/restore/" + tableTrash.fileName
+        
+        ocNetworking?.moveFileOrFolder(fileName, fileNameTo: fileNameTo, success: {
+            
+            NCManageDatabase.sharedInstance.deleteTrash(fileID: fileID)
+            guard let datasource = NCManageDatabase.sharedInstance.getTrash(filePath: self.path, sorted: self.datasourceSorted, ascending: self.datasourceAscending) else {
+                return
+            }
+            self.datasource = datasource
+            self.collectionView.reloadData()
+            
+        }, failure: { (message, errorCode) in
+            
+            self.appDelegate.messageNotification("_error_", description: message, visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
+        })
+    }
+    
+    func deleteItem(with fileID: String) {
+        
+        guard let tableTrash = NCManageDatabase.sharedInstance.getTrashItem(fileID: fileID) else {
+            return
+        }
+        
+        let ocNetworking = OCnetworking.init(delegate: self, metadataNet: nil, withUser: appDelegate.activeUser, withUserID: appDelegate.activeUserID, withPassword: appDelegate.activePassword, withUrl: appDelegate.activeUrl)
+        
+        let path = appDelegate.activeUrl + tableTrash.filePath + tableTrash.fileName
+
+        ocNetworking?.deleteFileOrFolder(path, completion: { (message, errorCode) in
+            
+            if errorCode == 0 {
+                
+                NCManageDatabase.sharedInstance.deleteTrash(fileID: fileID)
+                guard let datasource = NCManageDatabase.sharedInstance.getTrash(filePath: self.path, sorted: self.datasourceSorted, ascending: self.datasourceAscending) else {
+                    return
+                }
+                self.datasource = datasource
+                self.collectionView.reloadData()
+                
+            } else {
+                
+                self.appDelegate.messageNotification("_error_", description: message, visible: true, delay: TimeInterval(k_dismissAfterSecond), type: TWMessageBarMessageType.error, errorCode: errorCode)
+            }
+        })
+    }
+    
+    func downloadThumbnail(with tableTrash: tableTrash, 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: tableTrash.fileID, fileName: tableTrash.fileName, completion: { (message, errorCode) in
+            if errorCode == 0 && CCUtility.fileProviderStorageIconExists(tableTrash.fileID, fileNameView: tableTrash.fileName) {
+                self.collectionView.reloadItems(at: [indexPath])
+            }
+        })
+    }
+    
+    // MARK: COLLECTIONVIEW METHODS
+    
+    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
+        
+        if kind == UICollectionView.elementKindSectionHeader {
+            
+            let onDeviceHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerMenu", for: indexPath) as! NCOnDeviceHeaderMenu
+            
+            if collectionView.collectionViewLayout == gridLayout {
+                onDeviceHeader.buttonSwitch.setImage(CCGraphics.changeThemingColorImage(UIImage.init(named: "switchList"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), for: .normal)
+            } else {
+                onDeviceHeader.buttonSwitch.setImage(CCGraphics.changeThemingColorImage(UIImage.init(named: "switchGrid"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), for: .normal)
+            }
+            
+            onDeviceHeader.delegate = self
+            
+            if self.datasource.count == 0 {
+                onDeviceHeader.buttonSwitch.isEnabled = false
+                onDeviceHeader.buttonOrder.isEnabled = false
+                onDeviceHeader.buttonMore.isEnabled = false
+            } else {
+                onDeviceHeader.buttonSwitch.isEnabled = true
+                onDeviceHeader.buttonOrder.isEnabled = true
+                onDeviceHeader.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: onDeviceHeader.buttonOrder.titleLabel?.font as Any])
+            
+            onDeviceHeader.buttonOrder.setTitle(title, for: .normal)
+            onDeviceHeader.buttonOrderWidthConstraint.constant = size.width + 5
+            
+            return onDeviceHeader
+            
+        } else {
+            
+            let onDeviceFooter = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "footerMenu", for: indexPath) as! NCOnDeviceFooterMenu
+            
+            onDeviceFooter.labelFooter.textColor = NCBrandColor.sharedInstance.icon
+            
+            var folders: Int = 0, foldersText = ""
+            var files: Int = 0, filesText = ""
+            var size: Double = 0
+            
+            for record: tableTrash 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 == "" {
+                onDeviceFooter.labelFooter.text = filesText
+            } else if filesText == "" {
+                onDeviceFooter.labelFooter.text = foldersText
+            } else {
+                onDeviceFooter.labelFooter.text = foldersText + ", " + filesText
+            }
+            
+            return onDeviceFooter
+        }
+    }
+    
+    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 tableTrash = datasource[indexPath.item]
+        var image: UIImage?
+        
+        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))
+        } else {
+            if tableTrash.thumbnailExists && !CCUtility.fileProviderStorageIconExists(tableTrash.fileID, fileNameView: tableTrash.fileName) {
+                downloadThumbnail(with: tableTrash, indexPath: indexPath)
+            }
+        }
+        
+        if collectionView.collectionViewLayout == listLayout {
+            
+            // LIST
+            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell-list", for: indexPath) as! NCOnDeviceListCell
+            cell.delegate = self
+            
+            cell.fileID = tableTrash.fileID
+            cell.indexPath = indexPath
+            cell.labelTitle.text = tableTrash.trashbinFileName
+            
+            if tableTrash.directory {
+                cell.imageItem.image = CCGraphics.changeThemingColorImage(UIImage.init(named: "folder"), multiplier: 3, color: NCBrandColor.sharedInstance.brandElement)
+                cell.labelInfo.text = CCUtility.dateDiff(tableTrash.date as Date)
+            } else {
+                cell.imageItem.image = image
+                cell.labelInfo.text = CCUtility.dateDiff(tableTrash.date as Date) + " " + CCUtility.transformedSize(tableTrash.size)
+            }
+            
+            if isEditMode {
+                cell.imageItemLeftConstraint.constant = 45
+                cell.imageSelect.isHidden = false
+                
+                if selectFileID.contains(tableTrash.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! NCOnDeviceGridCell
+            cell.delegate = self
+            
+            cell.fileID = tableTrash.fileID
+            cell.indexPath = indexPath
+            cell.labelTitle.text = tableTrash.trashbinFileName
+            
+            if tableTrash.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(tableTrash.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 tableTrash = datasource[indexPath.item]
+
+        if isEditMode {
+            if let index = selectFileID.index(of: tableTrash.fileID) {
+                selectFileID.remove(at: index)
+            } else {
+                selectFileID.append(tableTrash.fileID)
+            }
+            collectionView.reloadItems(at: [indexPath])
+            return
+        }
+        
+        if tableTrash.directory {
+        
+            let ncTrash:NCTrash = UIStoryboard(name: "NCOnDevice", bundle: nil).instantiateInitialViewController() as! NCTrash
+            ncTrash.path = tableTrash.filePath + tableTrash.fileName
+            ncTrash.titleCurrentFolder = tableTrash.trashbinFileName
+            self.navigationController?.pushViewController(ncTrash, 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 ListLayoutOnDevice: 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 GridLayoutOnDevice: 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/OnDevice/NCOnDeviceGridCell.swift

@@ -0,0 +1,53 @@
+//
+//  NCOnDeviceGridCell.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 NCOnDeviceGridCell: 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: NCOnDeviceGridCellDelegate?
+    
+    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 NCOnDeviceGridCellDelegate {
+    func tapMoreGridItem(with fileID: String, sender: Any)
+}

+ 84 - 0
iOSClient/OnDevice/NCOnDeviceGridCell.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="NCOnDeviceGridCell" 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 userInteractionEnabled="NO" contentMode="scaleAspectFit" 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/OnDevice/NCOnDeviceHeaderFooterMenu.swift

@@ -0,0 +1,77 @@
+//
+//  NCOnDeviceHeaderFooterMenu.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 NCOnDeviceHeaderMenu: 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: NCOnDeviceHeaderMenuDelegate?
+
+    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 NCOnDeviceHeaderMenuDelegate {
+    func tapSwitchHeaderMenu(sender: Any)
+    func tapMoreHeaderMenu(sender: Any)
+    func tapOrderHeaderMenu(sender: Any)
+
+}
+
+class NCOnDeviceFooterMenu: UICollectionReusableView {
+    
+    @IBOutlet weak var labelFooter: UILabel!
+
+    override func awakeFromNib() {
+        super.awakeFromNib()
+        
+    }
+}

+ 70 - 0
iOSClient/OnDevice/NCOnDeviceListCell.swift

@@ -0,0 +1,70 @@
+//
+//  NCOnDeviceListCell.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 NCOnDeviceListCell: 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 imageRestore: UIImageView!
+    @IBOutlet weak var imageMore: UIImageView!
+
+    @IBOutlet weak var buttonMore: UIButton!
+    @IBOutlet weak var buttonRestore: UIButton!
+    
+    @IBOutlet weak var separator: UIView!
+
+    var delegate: NCOnDeviceListCellDelegate?
+    
+    var fileID = ""
+    var indexPath = IndexPath()
+
+    override func awakeFromNib() {
+        super.awakeFromNib()
+       
+        imageRestore.image = CCGraphics.changeThemingColorImage(UIImage.init(named: "restore"), multiplier: 2, color: NCBrandColor.sharedInstance.optionItem)
+        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)
+    }
+    
+    @IBAction func touchUpInsideRestore(_ sender: Any) {
+        delegate?.tapRestoreItem(with: fileID, sender: sender)
+    }
+}
+
+protocol NCOnDeviceListCellDelegate {
+    func tapRestoreItem(with fileID: String, sender: Any)
+    func tapMoreItem(with fileID: String, sender: Any)
+}

+ 132 - 0
iOSClient/OnDevice/NCOnDeviceListCell.xib

@@ -0,0 +1,132 @@
+<?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="NCOnDeviceListCell" 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="scaleAspectFit" 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="420" 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="420" 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>
+                    <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="mrd-cC-VV8"/>
+                        </connections>
+                    </button>
+                    <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>
+                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="nwZ-pi-Igj" userLabel="imageRestore">
+                        <rect key="frame" x="530" y="20" width="20" height="20"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="20" id="5Zc-h7-ZRJ"/>
+                            <constraint firstAttribute="height" constant="20" id="xvo-pN-hfE"/>
+                        </constraints>
+                    </imageView>
+                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="3mk-e2-iDg" userLabel="buttonRestore">
+                        <rect key="frame" x="520" y="0.0" width="40" height="60"/>
+                        <constraints>
+                            <constraint firstAttribute="height" constant="60" id="c3w-wJ-nqd"/>
+                            <constraint firstAttribute="width" constant="40" id="eC4-Ee-c7B"/>
+                        </constraints>
+                        <connections>
+                            <action selector="touchUpInsideRestore:" destination="jxV-Pk-fPt" eventType="touchUpInside" id="xMV-fb-0ta"/>
+                        </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="nwZ-pi-Igj" firstAttribute="centerY" secondItem="3mk-e2-iDg" secondAttribute="centerY" id="A31-Yy-Gyn"/>
+                <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="yhy-xd-w5C" firstAttribute="leading" secondItem="3mk-e2-iDg" secondAttribute="trailing" id="PxA-lT-Gll"/>
+                <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="3mk-e2-iDg" firstAttribute="leading" secondItem="AXX-71-9Q6" secondAttribute="trailing" constant="5" id="UtX-Ca-aBN"/>
+                <constraint firstItem="yhy-xd-w5C" firstAttribute="centerY" secondItem="Gu8-oz-zWa" secondAttribute="centerY" id="ZO7-Ny-L3I"/>
+                <constraint firstItem="3mk-e2-iDg" firstAttribute="leading" secondItem="UtT-L6-mgW" secondAttribute="trailing" constant="5" id="cEw-b3-odo"/>
+                <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="nwZ-pi-Igj" firstAttribute="centerY" secondItem="Gu8-oz-zWa" secondAttribute="centerY" id="ldm-kv-P98"/>
+                <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="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"/>
+                <constraint firstItem="nwZ-pi-Igj" firstAttribute="centerX" secondItem="3mk-e2-iDg" secondAttribute="centerX" id="vYW-cL-DlK"/>
+            </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="buttonRestore" destination="3mk-e2-iDg" id="rGX-0C-OHo"/>
+                <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="imageRestore" destination="nwZ-pi-Igj" id="d9Y-zK-8dx"/>
+                <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>

+ 7 - 7
iOSClient/Trash/NCTrash.swift

@@ -23,7 +23,7 @@
 
 import Foundation
 
-class NCTrash: UIViewController ,UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UIGestureRecognizerDelegate, NCTrashListDelegate, NCTrashGridDelegate, NCTrashHeaderMenuDelegate, DropdownMenuDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate  {
+class NCTrash: UIViewController ,UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UIGestureRecognizerDelegate, NCTrashListCellDelegate, NCTrashGridCellDelegate, NCTrashHeaderMenuDelegate, DropdownMenuDelegate, DZNEmptyDataSetSource, DZNEmptyDataSetDelegate  {
     
     @IBOutlet fileprivate weak var collectionView: UICollectionView!
 
@@ -36,8 +36,8 @@ class NCTrash: UIViewController ,UICollectionViewDataSource, UICollectionViewDel
     var isEditMode = false
     var selectFileID = [String]()
     
-    var listLayout: ListLayout!
-    var gridLayout: GridLayout!
+    var listLayout: ListLayoutTrash!
+    var gridLayout: GridLayoutTrash!
     
     private let highHeader: CGFloat = 50
     
@@ -51,8 +51,8 @@ class NCTrash: UIViewController ,UICollectionViewDataSource, UICollectionViewDel
         
         collectionView.alwaysBounceVertical = true
 
-        listLayout = ListLayout()
-        gridLayout = GridLayout()
+        listLayout = ListLayoutTrash()
+        gridLayout = GridLayoutTrash()
         
         if CCUtility.getLayoutTrash() == "list" {
             collectionView.collectionViewLayout = listLayout
@@ -790,7 +790,7 @@ class NCTrash: UIViewController ,UICollectionViewDataSource, UICollectionViewDel
     }
 }
 
-class ListLayout: UICollectionViewFlowLayout {
+class ListLayoutTrash: UICollectionViewFlowLayout {
     
     let itemHeight: CGFloat = 60
     
@@ -828,7 +828,7 @@ class ListLayout: UICollectionViewFlowLayout {
     }
 }
 
-class GridLayout: UICollectionViewFlowLayout {
+class GridLayoutTrash: UICollectionViewFlowLayout {
     
     let heightLabelPlusButton: CGFloat = 45
     let preferenceWidth: CGFloat = 110

+ 2 - 2
iOSClient/Trash/NCTrashGridCell.swift

@@ -32,7 +32,7 @@ class NCTrashGridCell: UICollectionViewCell {
     @IBOutlet weak var imageMore: UIImageView!
     @IBOutlet weak var buttonMoreGrid: UIButton!
 
-    var delegate: NCTrashGridDelegate?
+    var delegate: NCTrashGridCellDelegate?
     
     var fileID = ""
     var indexPath = IndexPath()
@@ -48,6 +48,6 @@ class NCTrashGridCell: UICollectionViewCell {
     }
 }
 
-protocol NCTrashGridDelegate {
+protocol NCTrashGridCellDelegate {
     func tapMoreGridItem(with fileID: String, sender: Any)
 }

+ 2 - 2
iOSClient/Trash/NCTrashListCell.swift

@@ -41,7 +41,7 @@ class NCTrashListCell: UICollectionViewCell {
     
     @IBOutlet weak var separator: UIView!
 
-    var delegate: NCTrashListDelegate?
+    var delegate: NCTrashListCellDelegate?
     
     var fileID = ""
     var indexPath = IndexPath()
@@ -64,7 +64,7 @@ class NCTrashListCell: UICollectionViewCell {
     }
 }
 
-protocol NCTrashListDelegate {
+protocol NCTrashListCellDelegate {
     func tapRestoreItem(with fileID: String, sender: Any)
     func tapMoreItem(with fileID: String, sender: Any)
 }