Explorar o código

Merge pull request #1722 from nextcloud/feature/activities

Combine Activities View
Marino Faggiana %!s(int64=3) %!d(string=hai) anos
pai
achega
1c350a6b6b

+ 10 - 11
Nextcloud.xcodeproj/project.pbxproj

@@ -18,6 +18,7 @@
 		371B5A2E23D0B04500FAFAE9 /* NCMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371B5A2D23D0B04500FAFAE9 /* NCMenu.swift */; };
 		3781B9B023DB2B7E006B4B1D /* AppDelegate+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */; };
 		D575039F27146F93008DC9DC /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */; };
+		D5B6AA7827200C7200D49C24 /* NCActivityTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */; };
 		F700222C1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; };
 		F700222D1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; };
 		F700510122DF63AC003A3356 /* NCShare.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F700510022DF63AC003A3356 /* NCShare.storyboard */; };
@@ -162,7 +163,6 @@
 		F755BD9B20594AC7008C5FBB /* NCService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F755BD9A20594AC7008C5FBB /* NCService.swift */; };
 		F7581D1A25EFDA61004DC699 /* NCLoginWeb+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7581D1925EFDA60004DC699 /* NCLoginWeb+Menu.swift */; };
 		F7581D2425EFDDDF004DC699 /* NCMedia+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7581D2325EFDDDF004DC699 /* NCMedia+Menu.swift */; };
-		F7581D2A25EFDF44004DC699 /* NCShareComments+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7581D2925EFDF43004DC699 /* NCShareComments+Menu.swift */; };
 		F758B45A212C564000515F55 /* Scan.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F758B457212C564000515F55 /* Scan.storyboard */; };
 		F758B45E212C569D00515F55 /* ScanCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F758B45D212C569C00515F55 /* ScanCell.swift */; };
 		F758B460212C56A400515F55 /* ScanCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F758B45F212C56A400515F55 /* ScanCollectionView.swift */; };
@@ -327,7 +327,7 @@
 		F7DFB7F0219C5B8000680748 /* NCCreateFormUploadAssets.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7EF219C5B8000680748 /* NCCreateFormUploadAssets.swift */; };
 		F7DFB7F4219C5CA800680748 /* NCCreateFormUploadScanDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7DFB7F3219C5CA800680748 /* NCCreateFormUploadScanDocument.swift */; };
 		F7E0CDCF265CE8610044854E /* NCUserStatus.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */; };
-		F7E4D9C422ED929B003675FD /* NCShareComments.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E4D9C322ED929B003675FD /* NCShareComments.swift */; };
+		F7E4D9C422ED929B003675FD /* NCShareCommentsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E4D9C322ED929B003675FD /* NCShareCommentsCell.swift */; };
 		F7ED547C25EEA65400956C55 /* QRCodeReader in Frameworks */ = {isa = PBXBuildFile; productRef = F7ED547B25EEA65400956C55 /* QRCodeReader */; };
 		F7EDE4CC262D7B6F00414FE6 /* NCEmptyDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7239870253D86B600257F49 /* NCEmptyDataSet.swift */; };
 		F7EDE4D1262D7B8400414FE6 /* NCDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7C1EEA425053A9C00866ACC /* NCDataSource.swift */; };
@@ -423,6 +423,7 @@
 		371B5A2D23D0B04500FAFAE9 /* NCMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMenu.swift; sourceTree = "<group>"; };
 		371B5A3223D0BD5500FAFAE9 /* FloatingPanel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FloatingPanel.framework; path = Carthage/Build/iOS/FloatingPanel.framework; sourceTree = "<group>"; };
 		3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Menu.swift"; sourceTree = "<group>"; };
+		D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCActivityTableViewCell.swift; sourceTree = "<group>"; };
 		F700222B1EC479840080073F /* Custom.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Custom.xcassets; sourceTree = "<group>"; };
 		F700510022DF63AC003A3356 /* NCShare.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCShare.storyboard; sourceTree = "<group>"; };
 		F700510222DF6897003A3356 /* Parchment.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Parchment.framework; path = Carthage/Build/iOS/Parchment.framework; sourceTree = "<group>"; };
@@ -573,7 +574,6 @@
 		F755BD9A20594AC7008C5FBB /* NCService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCService.swift; sourceTree = "<group>"; };
 		F7581D1925EFDA60004DC699 /* NCLoginWeb+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCLoginWeb+Menu.swift"; sourceTree = "<group>"; };
 		F7581D2325EFDDDF004DC699 /* NCMedia+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCMedia+Menu.swift"; sourceTree = "<group>"; };
-		F7581D2925EFDF43004DC699 /* NCShareComments+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCShareComments+Menu.swift"; sourceTree = "<group>"; };
 		F758B457212C564000515F55 /* Scan.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Scan.storyboard; sourceTree = "<group>"; };
 		F758B45D212C569C00515F55 /* ScanCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScanCell.swift; sourceTree = "<group>"; };
 		F758B45F212C56A400515F55 /* ScanCollectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScanCollectionView.swift; sourceTree = "<group>"; };
@@ -757,7 +757,7 @@
 		F7DFB7F3219C5CA800680748 /* NCCreateFormUploadScanDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCreateFormUploadScanDocument.swift; sourceTree = "<group>"; };
 		F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCUserStatus.storyboard; sourceTree = "<group>"; };
 		F7E45E6D21E75BF200579249 /* ja-JP */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ja-JP"; path = "ja-JP.lproj/Localizable.strings"; sourceTree = "<group>"; };
-		F7E4D9C322ED929B003675FD /* NCShareComments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareComments.swift; sourceTree = "<group>"; };
+		F7E4D9C322ED929B003675FD /* NCShareCommentsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCommentsCell.swift; sourceTree = "<group>"; };
 		F7E856182351D7BE009A3330 /* SwiftyXMLParser.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyXMLParser.framework; path = Carthage/Build/iOS/SwiftyXMLParser.framework; sourceTree = "<group>"; };
 		F7EDE508262DA9D600414FE6 /* NCSelectCommandViewSelect.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCSelectCommandViewSelect.xib; sourceTree = "<group>"; };
 		F7EDE513262DC2CD00414FE6 /* NCSelectCommandViewSelect+CreateFolder.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "NCSelectCommandViewSelect+CreateFolder.xib"; sourceTree = "<group>"; };
@@ -863,7 +863,6 @@
 				F77A697C250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift */,
 				F7581D1925EFDA60004DC699 /* NCLoginWeb+Menu.swift */,
 				F7581D2325EFDDDF004DC699 /* NCMedia+Menu.swift */,
-				F7581D2925EFDF43004DC699 /* NCShareComments+Menu.swift */,
 				F7CBC31B24F78E79004D3812 /* NCSortMenu.swift */,
 				F75D19E225EFE09000D74598 /* NCTrash+Menu.swift */,
 				F710D2012405826100A6033D /* NCViewer+Menu.swift */,
@@ -1004,7 +1003,7 @@
 			children = (
 				F700510022DF63AC003A3356 /* NCShare.storyboard */,
 				F700510422DF6A89003A3356 /* NCShare.swift */,
-				F7E4D9C322ED929B003675FD /* NCShareComments.swift */,
+				F7E4D9C322ED929B003675FD /* NCShareCommentsCell.swift */,
 				F723B3DC22FC6D1C00301EFE /* NCShareCommentsCell.xib */,
 				F769454522E9F1B0000A798A /* NCShareCommon.swift */,
 				F73CB3B122E072A000AD728E /* NCShareHeaderView.xib */,
@@ -1260,6 +1259,7 @@
 			children = (
 				F7C9555221F0C4CA0024296E /* NCActivity.storyboard */,
 				F7C9555421F0C5470024296E /* NCActivity.swift */,
+				D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */,
 			);
 			path = Activity;
 			sourceTree = "<group>";
@@ -1797,7 +1797,6 @@
 						ProvisioningStyle = Automatic;
 					};
 					F77B0DEB1D118A16002130FE = {
-						DevelopmentTeam = 6JLRKY9ZV7;
 						LastSwiftMigration = 1020;
 						ProvisioningStyle = Automatic;
 						SystemCapabilities = {
@@ -2204,7 +2203,6 @@
 				F7CA212D25F1333300826ABB /* NCAccountRequest.swift in Sources */,
 				F765F73125237E3F00391DBE /* NCRecent.swift in Sources */,
 				F76B3CCE1EAE01BD00921AC9 /* NCBrand.swift in Sources */,
-				F7581D2A25EFDF44004DC699 /* NCShareComments+Menu.swift in Sources */,
 				F769454422E9F142000A798A /* NCShareUserMenuView.swift in Sources */,
 				F7581D2425EFDDDF004DC699 /* NCMedia+Menu.swift in Sources */,
 				F77B0E981D118A16002130FE /* CCManageAccount.m in Sources */,
@@ -2231,6 +2229,7 @@
 				F70968A424212C4E00ED60E5 /* NCLivePhoto.swift in Sources */,
 				F7BC288026663F85004D46C5 /* NCViewCertificateDetails.swift in Sources */,
 				F702F2E625EE5C86008F8E80 /* NCAudioRecorderViewController.swift in Sources */,
+				D5B6AA7827200C7200D49C24 /* NCActivityTableViewCell.swift in Sources */,
 				F745B253222D88AE00346520 /* NCLoginQRCode.swift in Sources */,
 				F7CBC31C24F78E79004D3812 /* NCSortMenu.swift in Sources */,
 				F769454822E9F20D000A798A /* NCShareNetworking.swift in Sources */,
@@ -2246,7 +2245,7 @@
 				F77B0ED11D118A16002130FE /* Acknowledgements.m in Sources */,
 				F70D8D8124A4A9BF000A5756 /* NCNetworkingProcessUpload.swift in Sources */,
 				F7D96FCC246ED7E200536D73 /* NCNetworkingCheckRemoteUser.swift in Sources */,
-				F7E4D9C422ED929B003675FD /* NCShareComments.swift in Sources */,
+				F7E4D9C422ED929B003675FD /* NCShareCommentsCell.swift in Sources */,
 				F717402E24F699A5000C87D5 /* NCFavorite.swift in Sources */,
 				F74DE14325135B6800917068 /* NCTransfers.swift in Sources */,
 			);
@@ -2950,8 +2949,8 @@
 			isa = XCRemoteSwiftPackageReference;
 			repositoryURL = "https://github.com/nextcloud/ios-communication-library/";
 			requirement = {
-				kind = revision;
-				revision = 9fa3a3567f9c3092c73e3501cb055b1df40900bb;
+				branch = develop;
+				kind = branch;
 			};
 		};
 		F788ECC5263AAAF900ADC67F /* XCRemoteSwiftPackageReference "MarkdownKit" */ = {

+ 10 - 46
Nextcloud.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

@@ -10,15 +10,6 @@
           "version": "0.20200225.4"
         }
       },
-      {
-        "package": "Alamofire",
-        "repositoryURL": "https://github.com/Alamofire/Alamofire",
-        "state": {
-          "branch": null,
-          "revision": "d120af1e8638c7da36c8481fd61a66c0c08dc4fc",
-          "version": "5.4.4"
-        }
-      },
       {
         "package": "BoringSSL-GRPC",
         "repositoryURL": "https://github.com/firebase/boringssl-SwiftPM.git",
@@ -42,8 +33,8 @@
         "repositoryURL": "https://github.com/firebase/firebase-ios-sdk",
         "state": {
           "branch": null,
-          "revision": "839cc6b0cd80b0b8bf81fe9bd82b743b25dc6446",
-          "version": "8.9.1"
+          "revision": "81b568348ab4e113dd8bcef5a83c5dd431741ae4",
+          "version": "8.8.1"
         }
       },
       {
@@ -60,8 +51,8 @@
         "repositoryURL": "https://github.com/google/GoogleAppMeasurement.git",
         "state": {
           "branch": null,
-          "revision": "9b2f6aca5b4685c45f9f5481f19bee8e7982c538",
-          "version": "8.9.1"
+          "revision": "06add56b27b88ae5180e92d4ee21a1199ee888a1",
+          "version": "8.8.0"
         }
       },
       {
@@ -69,8 +60,8 @@
         "repositoryURL": "https://github.com/google/GoogleDataTransport.git",
         "state": {
           "branch": null,
-          "revision": "15ccdfd25ac55b9239b82809531ff26605e7556e",
-          "version": "9.1.2"
+          "revision": "7fb27ea49414b9c5483503cd06baa821c8654d1e",
+          "version": "9.1.1"
         }
       },
       {
@@ -78,8 +69,8 @@
         "repositoryURL": "https://github.com/google/GoogleUtilities.git",
         "state": {
           "branch": null,
-          "revision": "797005ad8a1f0614063933e2fa010a5d13cb09d0",
-          "version": "7.6.0"
+          "revision": "616fac2626b6b2d1424d79a6f786b4e2ed1cfb49",
+          "version": "7.5.2"
         }
       },
       {
@@ -100,15 +91,6 @@
           "version": "1.7.0"
         }
       },
-      {
-        "package": "NCCommunication",
-        "repositoryURL": "https://github.com/nextcloud/ios-communication-library/",
-        "state": {
-          "branch": null,
-          "revision": "9fa3a3567f9c3092c73e3501cb055b1df40900bb",
-          "version": null
-        }
-      },
       {
         "package": "leveldb",
         "repositoryURL": "https://github.com/firebase/leveldb.git",
@@ -186,8 +168,8 @@
         "repositoryURL": "https://github.com/realm/realm-cocoa",
         "state": {
           "branch": null,
-          "revision": "9f43d0da902c55b493d6c8bb63203764caa8acbe",
-          "version": "10.18.0"
+          "revision": "7ca0ce1dd58553d5be1ec9cc7283b068c256979d",
+          "version": "10.17.0"
         }
       },
       {
@@ -243,24 +225,6 @@
           "revision": "9bf4b5af6bb4386865636fc504d6c588c2b65040",
           "version": "3.7.2"
         }
-      },
-      {
-        "package": "SwiftyJSON",
-        "repositoryURL": "https://github.com/SwiftyJSON/SwiftyJSON",
-        "state": {
-          "branch": null,
-          "revision": "b3dcd7dbd0d488e1a7077cb33b00f2083e382f07",
-          "version": "5.0.1"
-        }
-      },
-      {
-        "package": "SwiftyXMLParser",
-        "repositoryURL": "https://github.com/yahoojapan/SwiftyXMLParser",
-        "state": {
-          "branch": null,
-          "revision": "ad5eeeaf7797f69e26943aaa53c81c6a9fdaa516",
-          "version": "5.5.0"
-        }
       }
     ]
   },

+ 61 - 14
iOSClient/Activity/NCActivity.storyboard

@@ -1,9 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="nhT-TJ-YvX">
-    <device id="retina5_9" orientation="portrait" appearance="light"/>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19162" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="nhT-TJ-YvX">
     <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19144"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
@@ -13,22 +11,22 @@
             <objects>
                 <viewController storyboardIdentifier="NCActivity.storyboard" extendedLayoutIncludesOpaqueBars="YES" id="nhT-TJ-YvX" customClass="NCActivity" customModule="Nextcloud" customModuleProvider="target" sceneMemberID="viewController">
                     <view key="view" contentMode="scaleToFill" id="vOO-VC-ekK">
-                        <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
+                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                         <subviews>
                             <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="20" sectionFooterHeight="1" translatesAutoresizingMaskIntoConstraints="NO" id="X49-xg-JXO">
-                                <rect key="frame" x="0.0" y="0.0" width="375" height="778"/>
+                                <rect key="frame" x="0.0" y="100" width="600" height="500"/>
                                 <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                 <prototypes>
-                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="tableCell" rowHeight="120" id="ggj-aE-fnh" customClass="activityTableViewCell" customModule="Nextcloud" customModuleProvider="target">
-                                        <rect key="frame" x="0.0" y="24.333333969116211" width="375" height="120"/>
+                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="tableCell" rowHeight="120" id="ggj-aE-fnh" customClass="NCActivityTableViewCell" customModule="Nextcloud" customModuleProvider="target">
+                                        <rect key="frame" x="0.0" y="44.5" width="600" height="120"/>
                                         <autoresizingMask key="autoresizingMask"/>
                                         <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="ggj-aE-fnh" id="i35-U4-bEk">
-                                            <rect key="frame" x="0.0" y="0.0" width="375" height="120"/>
+                                            <rect key="frame" x="0.0" y="0.0" width="600" height="120"/>
                                             <autoresizingMask key="autoresizingMask"/>
                                             <subviews>
                                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fcO-YL-MuT">
-                                                    <rect key="frame" x="88" y="5" width="277" height="25"/>
+                                                    <rect key="frame" x="88" y="5" width="502" height="25"/>
                                                     <fontDescription key="fontDescription" name=".AppleSystemUIFont" family=".AppleSystemUIFont" pointSize="15"/>
                                                     <nil key="textColor"/>
                                                     <nil key="highlightedColor"/>
@@ -48,7 +46,7 @@
                                                     </constraints>
                                                 </imageView>
                                                 <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="KpO-no-BMl">
-                                                    <rect key="frame" x="50" y="40" width="325" height="60"/>
+                                                    <rect key="frame" x="50" y="40" width="550" height="60"/>
                                                     <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                                     <constraints>
                                                         <constraint firstAttribute="height" constant="60" id="deQ-wc-jNT" userLabel="height = 60"/>
@@ -60,7 +58,7 @@
                                                         <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
                                                     </collectionViewFlowLayout>
                                                     <cells>
-                                                        <collectionViewCell clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="collectionCell" id="uIN-z5-7vk" customClass="activityCollectionViewCell" customModule="Nextcloud" customModuleProvider="target">
+                                                        <collectionViewCell clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="collectionCell" id="uIN-z5-7vk" customClass="NCActivityCollectionViewCell" customModule="Nextcloud" customModuleProvider="target">
                                                             <rect key="frame" x="0.0" y="5" width="50" height="50"/>
                                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                                                             <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
@@ -113,17 +111,66 @@
                                     <outlet property="prefetchDataSource" destination="nhT-TJ-YvX" id="317-AD-uQe"/>
                                 </connections>
                             </tableView>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sG1-7f-3rF">
+                                <rect key="frame" x="0.0" y="0.0" width="600" height="100"/>
+                                <subviews>
+                                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="hVn-Fn-7td">
+                                        <rect key="frame" x="10" y="10" width="40" height="40"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="40" id="eRU-q6-wZT"/>
+                                            <constraint firstAttribute="width" constant="40" id="nee-e2-atl"/>
+                                        </constraints>
+                                    </imageView>
+                                    <textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="249" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" clearButtonMode="always" translatesAutoresizingMaskIntoConstraints="NO" id="Wz7-gw-foA">
+                                        <rect key="frame" x="60" y="60" width="530" height="30"/>
+                                        <constraints>
+                                            <constraint firstAttribute="height" constant="30" id="4ni-Qx-ber"/>
+                                        </constraints>
+                                        <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                        <textInputTraits key="textInputTraits"/>
+                                        <connections>
+                                            <action selector="newCommentFieldDidEndOnExitWithTextField:" destination="nhT-TJ-YvX" eventType="editingDidEndOnExit" id="vPB-Eu-qkb"/>
+                                        </connections>
+                                    </textField>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="user" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YRy-AS-CMk">
+                                        <rect key="frame" x="60" y="21.5" width="530" height="17"/>
+                                        <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                        <color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <constraints>
+                                    <constraint firstItem="YRy-AS-CMk" firstAttribute="centerY" secondItem="hVn-Fn-7td" secondAttribute="centerY" id="CBB-vi-6Z1"/>
+                                    <constraint firstAttribute="trailing" secondItem="Wz7-gw-foA" secondAttribute="trailing" constant="10" id="CuV-5o-sFz"/>
+                                    <constraint firstItem="hVn-Fn-7td" firstAttribute="leading" secondItem="sG1-7f-3rF" secondAttribute="leading" constant="10" id="NWH-NK-FjI"/>
+                                    <constraint firstAttribute="height" constant="100" id="SfP-Sr-vbR"/>
+                                    <constraint firstItem="Wz7-gw-foA" firstAttribute="leading" secondItem="hVn-Fn-7td" secondAttribute="trailing" constant="10" id="baP-t5-Kut"/>
+                                    <constraint firstItem="Wz7-gw-foA" firstAttribute="top" secondItem="hVn-Fn-7td" secondAttribute="bottom" constant="10" id="bsh-yh-NR2"/>
+                                    <constraint firstItem="YRy-AS-CMk" firstAttribute="leading" secondItem="hVn-Fn-7td" secondAttribute="trailing" constant="10" id="chn-JO-eYr"/>
+                                    <constraint firstAttribute="bottom" secondItem="Wz7-gw-foA" secondAttribute="bottom" constant="10" id="e8b-hy-WHK"/>
+                                    <constraint firstAttribute="trailing" secondItem="YRy-AS-CMk" secondAttribute="trailing" constant="10" id="uaN-5Y-k6V"/>
+                                    <constraint firstItem="hVn-Fn-7td" firstAttribute="top" secondItem="sG1-7f-3rF" secondAttribute="top" constant="10" id="yLz-68-e22"/>
+                                </constraints>
+                            </view>
                         </subviews>
                         <viewLayoutGuide key="safeArea" id="USa-eR-a1s"/>
                         <constraints>
-                            <constraint firstItem="USa-eR-a1s" firstAttribute="trailing" secondItem="X49-xg-JXO" secondAttribute="trailing" id="5we-Fh-GVu"/>
-                            <constraint firstItem="X49-xg-JXO" firstAttribute="top" secondItem="vOO-VC-ekK" secondAttribute="top" id="SfR-9z-HeQ"/>
+                            <constraint firstItem="sG1-7f-3rF" firstAttribute="top" secondItem="vOO-VC-ekK" secondAttribute="top" id="0Wu-9f-jFf"/>
+                            <constraint firstItem="X49-xg-JXO" firstAttribute="trailing" secondItem="USa-eR-a1s" secondAttribute="trailing" id="5we-Fh-GVu"/>
                             <constraint firstItem="USa-eR-a1s" firstAttribute="bottom" secondItem="X49-xg-JXO" secondAttribute="bottom" id="aHq-g4-dUG"/>
+                            <constraint firstItem="X49-xg-JXO" firstAttribute="top" secondItem="sG1-7f-3rF" secondAttribute="bottom" id="eeu-9y-t1U"/>
+                            <constraint firstItem="sG1-7f-3rF" firstAttribute="trailing" secondItem="vOO-VC-ekK" secondAttribute="trailing" id="htz-S1-01v"/>
+                            <constraint firstItem="sG1-7f-3rF" firstAttribute="leading" secondItem="vOO-VC-ekK" secondAttribute="leading" id="lLm-NY-aXQ"/>
                             <constraint firstItem="X49-xg-JXO" firstAttribute="leading" secondItem="USa-eR-a1s" secondAttribute="leading" id="pfF-ag-f7x"/>
                         </constraints>
                     </view>
                     <connections>
+                        <outlet property="commentView" destination="sG1-7f-3rF" id="Nip-au-Ilu"/>
+                        <outlet property="imageItem" destination="hVn-Fn-7td" id="tqx-nV-WfA"/>
+                        <outlet property="labelUser" destination="YRy-AS-CMk" id="ijz-je-fBV"/>
+                        <outlet property="newCommentField" destination="Wz7-gw-foA" id="PDr-8b-iQY"/>
                         <outlet property="tableView" destination="X49-xg-JXO" id="GUb-8b-mIS"/>
+                        <outlet property="viewContainerConstraint" destination="0Wu-9f-jFf" id="TGF-fh-T7Y"/>
                     </connections>
                 </viewController>
                 <placeholder placeholderIdentifier="IBFirstResponder" id="UOE-pW-DRy" userLabel="First Responder" sceneMemberID="firstResponder"/>

+ 308 - 421
iOSClient/Activity/NCActivity.swift

@@ -6,6 +6,7 @@
 //  Copyright © 2019 Marino Faggiana. All rights reserved.
 //
 //  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//  Author Henrik Storch <henrik.storch@nextcloud.com>
 //
 //  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
@@ -24,21 +25,29 @@
 import UIKit
 import SwiftRichString
 import NCCommunication
+import RealmSwift
+
+class NCActivity: UIViewController {
 
-class NCActivity: UIViewController, NCEmptyDataSetDelegate {
-    
     @IBOutlet weak var tableView: UITableView!
 
+    @IBOutlet weak var commentView: UIView!
+    @IBOutlet weak var imageItem: UIImageView!
+    @IBOutlet weak var labelUser: UILabel!
+    @IBOutlet weak var newCommentField: UITextField!
+
+    @IBOutlet weak var viewContainerConstraint: NSLayoutConstraint!
+    var height: CGFloat = 0
+
+    var metadata: tableMetadata?
+
     private let appDelegate = UIApplication.shared.delegate as! AppDelegate
 
-    var emptyDataSet: NCEmptyDataSet?
-    var allActivities: [tableActivity] = []
-    var filterActivities: [tableActivity] = []
+    var allItems: [DateCompareable] = []
+    var sectionDates: [Date] = []
 
-    var sectionDate: [Date] = []
     var insets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
     var didSelectItemEnable: Bool = true
-    var filterFileId: String?
     var objectType: String?
     
     var canFetchActivity = true
@@ -53,9 +62,6 @@ class NCActivity: UIViewController, NCEmptyDataSetDelegate {
         view.backgroundColor = NCBrandColor.shared.systemBackground
         self.title = NSLocalizedString("_activity_", comment: "")
 
-        // Empty
-        emptyDataSet = NCEmptyDataSet.init(view: tableView, offset: 0, delegate: self)
-        
         tableView.allowsSelection = false
         tableView.separatorColor = UIColor.clear
         tableView.tableFooterView = UIView()
@@ -65,14 +71,44 @@ class NCActivity: UIViewController, NCEmptyDataSetDelegate {
         NotificationCenter.default.addObserver(self, selector: #selector(self.changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
         
         changeTheming()
+        
+        setupComments()
+    }
+    
+    func setupComments() {
+        tableView.register(UINib.init(nibName: "NCShareCommentsCell", bundle: nil), forCellReuseIdentifier: "cell")
+
+
+        newCommentField.placeholder = NSLocalizedString("_new_comment_", comment: "")
+        viewContainerConstraint.constant = height
+
+        // Display Name & Quota
+        guard let activeAccount = NCManageDatabase.shared.getActiveAccount(), height > 0 else {
+            commentView.isHidden = true
+            return
+        }
+        
+        let fileName = String(CCUtility.getUserUrlBase(appDelegate.user, urlBase: appDelegate.urlBase)) + "-" + appDelegate.user + ".png"
+        let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
+        if let image = UIImage(contentsOfFile: fileNameLocalPath) {
+            imageItem.image = image
+        } else {
+            imageItem.image = UIImage(named: "avatar")
+        }
+        
+        if activeAccount.displayName.isEmpty {
+            labelUser.text = activeAccount.user
+        } else {
+            labelUser.text = activeAccount.displayName
+        }
+        labelUser.textColor = NCBrandColor.shared.label
     }
     
     override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
         
         appDelegate.activeViewController = self
-        
-        //
+
         NotificationCenter.default.addObserver(self, selector: #selector(initialize), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterInitialize), object: nil)
     }
     
@@ -99,65 +135,22 @@ class NCActivity: UIViewController, NCEmptyDataSetDelegate {
         tableView.reloadData()
     }
     
-    // MARK: - Empty
-    
-    func emptyDataSetView(_ view: NCEmptyView) {
-        
-        view.emptyImage.image = UIImage.init(named: "bolt")?.image(color: .gray, size: UIScreen.main.bounds.width)
-        view.emptyTitle.text = NSLocalizedString("_no_activity_", comment: "")
-        view.emptyDescription.text = ""
-    }
-}
-
-class activityTableViewCell: UITableViewCell, NCCellProtocol {
-    
-    private let appDelegate = UIApplication.shared.delegate as! AppDelegate
-
-    @IBOutlet weak var collectionView: UICollectionView!
-    @IBOutlet weak var icon: UIImageView!
-    @IBOutlet weak var avatar: UIImageView!
-    @IBOutlet weak var subject: UILabel!
-    @IBOutlet weak var subjectTrailingConstraint: NSLayoutConstraint!
-    @IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint!
-
-    private var user: String = ""
+    @IBAction func newCommentFieldDidEndOnExit(textField: UITextField) {
+        guard
+            let message = textField.text,
+            !message.isEmpty,
+            let metadata = self.metadata
+        else { return }
 
-    var idActivity: Int = 0
-    var account: String = ""
-    var activityPreviews: [tableActivityPreview] = []
-    var didSelectItemEnable: Bool = true
-    var viewController: UIViewController? = nil
-    
-    var fileAvatarImageView: UIImageView? {
-        get {
-            return avatar
-        }
-    }
-    var fileObjectId: String? {
-        get {
-            return nil
-        }
-    }
-    var filePreviewImageView: UIImageView? {
-        get {
-            return nil
-        }
-    }
-    var fileUser: String? {
-        get {
-            return user
-        }
-        set {
-            user = newValue ?? ""
+        NCCommunication.shared.putComments(fileId: metadata.fileId, message: message) { (account, errorCode, errorDescription) in
+            if errorCode == 0 {
+                self.newCommentField.text = ""
+                self.loadDataSource()
+            } else {
+                NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+            }
         }
     }
-    
-    override func awakeFromNib() {
-        super.awakeFromNib()
-        
-        collectionView.delegate = self
-        collectionView.dataSource = self
-    }
 }
 
 // MARK: - Table View
@@ -184,7 +177,7 @@ extension NCActivity: UITableViewDelegate {
         let label = UILabel()
         label.font = UIFont.boldSystemFont(ofSize: 13)
         label.textColor = NCBrandColor.shared.label
-        label.text = CCUtility.getTitleSectionDate(sectionDate[section])
+        label.text = CCUtility.getTitleSectionDate(sectionDates[section])
         label.textAlignment = .center
         label.layer.cornerRadius = 11
         label.layer.masksToBounds = true
@@ -201,396 +194,207 @@ extension NCActivity: UITableViewDelegate {
 extension NCActivity: UITableViewDataSource {
     
     func numberOfSections(in tableView: UITableView) -> Int {
-        return sectionDate.count
+        return sectionDates.count
     }
     
     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        let numberItems = getTableActivitiesFromSection(section).count
-        emptyDataSet?.numberOfItemsInSection(numberItems, section: section)
-        return numberItems
+        let date = sectionDates[section]
+        return allItems.filter({ Calendar.current.isDate($0.dateKey, inSameDayAs: date) }).count
     }
     
     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        
-        if let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as? activityTableViewCell {
-            
-            let results = getTableActivitiesFromSection(indexPath.section)
-            let activity = results[indexPath.row]
-            var orderKeysId: [String] = []
-            
-            cell.idActivity = activity.idActivity
-            cell.account = activity.account
-            cell.avatar.image = nil
-            cell.avatar.isHidden = true
-            cell.subjectTrailingConstraint.constant = 10
-            cell.didSelectItemEnable = self.didSelectItemEnable
-            cell.subject.textColor = NCBrandColor.shared.label
-            cell.viewController = self
-            
-            // icon
-            if activity.icon.count > 0 {
-                
-                let fileNameIcon = (activity.icon as NSString).lastPathComponent
-                let fileNameLocalPath = CCUtility.getDirectoryUserData() + "/" + fileNameIcon
-                
-                if FileManager.default.fileExists(atPath: fileNameLocalPath) {
-                    if let image = UIImage(contentsOfFile: fileNameLocalPath) { cell.icon.image = image }
-                } else {
-                    NCCommunication.shared.downloadContent(serverUrl: activity.icon) { (account, data, errorCode, errorMessage) in
-                        if errorCode == 0 {
-                            do {
-                                try data!.write(to: NSURL(fileURLWithPath: fileNameLocalPath) as URL, options: .atomic)
-                                tableView.reloadData()
-                            } catch { return }
-                        }
-                    }
-                }
-            }
-            
-            // avatar
-            if activity.user.count > 0 && activity.user != appDelegate.userId {
-                
-                cell.subjectTrailingConstraint.constant = 50
-                cell.avatar.isHidden = false
-                cell.fileUser = activity.user
-                
-                let fileName = String(CCUtility.getUserUrlBase(appDelegate.user, urlBase: appDelegate.urlBase)) + "-" + activity.user + ".png"
+        let date = sectionDates[indexPath.section]
+        let sectionItems = allItems
+            .filter({ Calendar.current.isDate($0.dateKey, inSameDayAs: date) })
+        let cellData = sectionItems[indexPath.row]
 
-                NCOperationQueue.shared.downloadAvatar(user: activity.user, fileName: fileName, placeholder: UIImage(named: "avatar"), cell: cell, view: tableView)
-            }
-            
-            // subject
-            if activity.subjectRich.count > 0 {
-                
-                var subject = activity.subjectRich
-                var keys: [String] = []
-                
-                if let regex = try? NSRegularExpression(pattern: "\\{[a-z0-9]+\\}", options: .caseInsensitive) {
-                    let string = subject as NSString
-                    keys = regex.matches(in: subject, options: [], range: NSRange(location: 0, length: string.length)).map {
-                        string.substring(with: $0.range).replacingOccurrences(of: "[\\{\\}]", with: "", options: .regularExpression)
-                    }
-                }
-                
-                for key in keys {
-                    if let result = NCManageDatabase.shared.getActivitySubjectRich(account: appDelegate.account, idActivity: activity.idActivity, key: key) {
-                        orderKeysId.append(result.id)
-                        subject = subject.replacingOccurrences(of: "{\(key)}", with: "<bold>" + result.name + "</bold>")
-                    }
-                }
-                
-                let normal = Style {
-                    $0.font = UIFont.systemFont(ofSize: cell.subject.font.pointSize)
-                    $0.lineSpacing = 1.5
-                }
-                let bold = Style { $0.font = UIFont.systemFont(ofSize: cell.subject.font.pointSize, weight: .bold) }
-                let date = Style { $0.font = UIFont.systemFont(ofSize: cell.subject.font.pointSize - 3)
-                    $0.color = UIColor.lightGray
-                }
-                
-                subject = subject + "\n" + "<date>" + CCUtility.dateDiff(activity.date as Date) + "</date>"
-                cell.subject.attributedText = subject.set(style: StyleGroup(base: normal, ["bold": bold, "date": date]))
-            }
-            
-            // CollectionView
-            cell.activityPreviews = NCManageDatabase.shared.getActivityPreview(account: activity.account, idActivity: activity.idActivity, orderKeysId: orderKeysId)
-            if cell.activityPreviews.count == 0 {
-                cell.collectionViewHeightConstraint.constant = 0
-            } else {
-                cell.collectionViewHeightConstraint.constant = 60
-            }
-            cell.collectionView.reloadData()
-            
-            return cell
+        if let activityData = cellData as? tableActivity {
+            return makeActivityCell(activityData, for: indexPath)
+        } else if let commentData = cellData as? tableComments {
+            return makeCommentCell(commentData, for: indexPath)
+        } else {
+            return UITableViewCell()
         }
-        
-        return UITableViewCell()
     }
-}
-
-/*
-extension NCActivity: UITableViewDataSourcePrefetching {
     
-    func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
-        
-        let section = indexPaths.last?.section ?? 0
-        let row = indexPaths.last?.row ?? 0
-        
-        let lastSection = self.sectionDate.count - 1
-        let lastRow = getTableActivitiesFromSection(section).count - 1
-        
-        if section == lastSection && row > lastRow - 1 {
-            //loadActivity(idActivity: allActivities.last!.idActivity)
+    func makeCommentCell(_ comment: tableComments, for indexPath: IndexPath) -> UITableViewCell {
+        guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? NCShareCommentsCell else {
+            return UITableViewCell()
         }
-    }
-    
-    func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) {
-        //print("cancelPrefetchingForRowsAt \(indexPaths)")
-    }
-}
-*/
-
-// MARK: - ScrollView
-
-extension NCActivity: UIScrollViewDelegate {
-    
-    func scrollViewDidScroll(_ scrollView: UIScrollView) {
-        if scrollView.contentSize.height - scrollView.contentOffset.y - scrollView.frame.height < 100 {
-            if let activities = allActivities.last {
-                loadActivity(idActivity: activities.idActivity)
-            }
+        
+        cell.tableComments = comment
+        cell.delegate = self
+        cell.sizeToFit()
+        
+        // Image
+        let fileName = String(CCUtility.getUserUrlBase(appDelegate.user, urlBase: appDelegate.urlBase)) + "-" + comment.actorId + ".png"
+        NCOperationQueue.shared.downloadAvatar(user: comment.actorId, fileName: fileName, placeholder: UIImage(named: "avatar"), cell: cell, view: tableView)
+        // Username
+        cell.labelUser.text = comment.actorDisplayName
+        cell.labelUser.textColor = NCBrandColor.shared.label
+        // Date
+        cell.labelDate.text = CCUtility.dateDiff(comment.creationDateTime as Date)
+        cell.labelDate.textColor = NCBrandColor.shared.systemGray4
+        // Message
+        cell.labelMessage.text = comment.message
+        cell.labelMessage.textColor = NCBrandColor.shared.label
+        // Button Menu
+        if comment.actorId == appDelegate.userId {
+            cell.buttonMenu.isHidden = false
+        } else {
+            cell.buttonMenu.isHidden = true
         }
+        
+        return cell
     }
-}
-
-// MARK: - Collection View
-
-extension activityTableViewCell: UICollectionViewDelegate {
     
-    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        
-        // Select not permitted
-        if !didSelectItemEnable {
-            return
+    func makeActivityCell(_ activity: tableActivity, for indexPath: IndexPath) -> UITableViewCell {
+        guard let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as? NCActivityTableViewCell else {
+            return UITableViewCell()
         }
         
-        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as? activityCollectionViewCell
+        var orderKeysId: [String] = []
         
-        let activityPreview = activityPreviews[indexPath.row]
+        cell.idActivity = activity.idActivity
+        cell.account = activity.account
+        cell.avatar.image = nil
+        cell.avatar.isHidden = true
+        cell.subjectTrailingConstraint.constant = 10
+        cell.didSelectItemEnable = self.didSelectItemEnable
+        cell.subject.textColor = NCBrandColor.shared.label
+        cell.viewController = self
         
-        if activityPreview.view == "trashbin" {
+        // icon
+        if activity.icon.count > 0 {
             
-            var responder: UIResponder? = collectionView
-            while !(responder is UIViewController) {
-                responder = responder?.next
-                if nil == responder {
-                    break
-                }
-            }
-            if (responder as? UIViewController)!.navigationController != nil {
-                if let viewController = UIStoryboard.init(name: "NCTrash", bundle: nil).instantiateInitialViewController() as? NCTrash {
-                    if let result = NCManageDatabase.shared.getTrashItem(fileId: String(activityPreview.fileId), account: activityPreview.account) {
-                        viewController.blinkFileId = result.fileId
-                        viewController.trashPath = result.filePath
-                        (responder as? UIViewController)!.navigationController?.pushViewController(viewController, animated: true)
-                    } else {
-                        NCContentPresenter.shared.messageNotification("_error_", description: "_trash_file_not_found_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError)
+            let fileNameIcon = (activity.icon as NSString).lastPathComponent
+            let fileNameLocalPath = CCUtility.getDirectoryUserData() + "/" + fileNameIcon
+            
+            if FileManager.default.fileExists(atPath: fileNameLocalPath) {
+                if let image = UIImage(contentsOfFile: fileNameLocalPath) { cell.icon.image = image }
+            } else {
+                NCCommunication.shared.downloadContent(serverUrl: activity.icon) { (account, data, errorCode, errorMessage) in
+                    if errorCode == 0 {
+                        do {
+                            try data!.write(to: NSURL(fileURLWithPath: fileNameLocalPath) as URL, options: .atomic)
+                            self.tableView.reloadData()
+                        } catch { return }
                     }
                 }
             }
-            
-            return
         }
         
-        if activityPreview.view == "files" && activityPreview.mimeType != "dir" {
-            
-            guard let activitySubjectRich = NCManageDatabase.shared.getActivitySubjectRich(account: activityPreview.account, idActivity: activityPreview.idActivity, id: String(activityPreview.fileId)) else {
-                return
-            }
-            
-            if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "fileId == %@", activitySubjectRich.id)) {
-                if let filePath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView) {
-                    do {
-                        let attr = try FileManager.default.attributesOfItem(atPath: filePath)
-                        let fileSize = attr[FileAttributeKey.size] as! UInt64
-                        if fileSize > 0 {
-                            if let viewController = self.viewController {
-                                NCViewer.shared.view(viewController: viewController, metadata: metadata, metadatas: [metadata], imageIcon: cell?.imageView.image)
-                            }
-                            return
-                        }
-                    } catch {
-                        print("Error: \(error)")
-                    }
-                }
-            }
-            
-            var pathComponents = activityPreview.link.components(separatedBy: "?")
-            pathComponents = pathComponents[1].components(separatedBy: "&")
-            var serverUrlFileName = pathComponents[0].replacingOccurrences(of: "dir=", with: "").removingPercentEncoding!
-            serverUrlFileName = appDelegate.urlBase + "/" + NCUtilityFileSystem.shared.getWebDAV(account: activityPreview.account) + serverUrlFileName + "/" + activitySubjectRich.name
+        // avatar
+        if activity.user.count > 0 && activity.user != appDelegate.userId {
             
-            let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(activitySubjectRich.id, fileNameView: activitySubjectRich.name)!
+            cell.subjectTrailingConstraint.constant = 50
+            cell.avatar.isHidden = false
+            cell.fileUser = activity.user
             
-            NCUtility.shared.startActivityIndicator(backgroundView: (appDelegate.window?.rootViewController?.view)!, blurEffect: true)
+            let fileName = String(CCUtility.getUserUrlBase(appDelegate.user, urlBase: appDelegate.urlBase)) + "-" + activity.user + ".png"
             
-            NCCommunication.shared.download(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, requestHandler: { (_) in
-                
-            }, taskHandler: { (_) in
-                
-            }, progressHandler: { (_) in
-                
-            }) { (account, etag, date, lenght, allHeaderFields, error, errorCode, errorDescription) in
-                
-                if account == self.appDelegate.account && errorCode == 0 {
-                    
-                    let serverUrl = (serverUrlFileName as NSString).deletingLastPathComponent
-                    let fileName = (serverUrlFileName as NSString).lastPathComponent
-                    let serverUrlFileName = serverUrl + "/" + fileName
-                    
-                    NCNetworking.shared.readFile(serverUrlFileName: serverUrlFileName, account: activityPreview.account) { (account, metadata, errorCode, errorDescription) in
-                        
-                        NCUtility.shared.stopActivityIndicator()
-                        
-                        if account == self.appDelegate.account && errorCode == 0  {
-                            
-                            // move from id to oc:id + instanceid (ocId)
-                            let atPath = CCUtility.getDirectoryProviderStorage()! + "/" + activitySubjectRich.id
-                            let toPath = CCUtility.getDirectoryProviderStorage()! + "/" + metadata!.ocId
-                                                       
-                            CCUtility.moveFile(atPath: atPath, toPath: toPath)
-                                                       
-                            NCManageDatabase.shared.addMetadata(metadata!)
-                            if let viewController = self.viewController {
-                                NCViewer.shared.view(viewController: viewController, metadata: metadata!, metadatas: [metadata!], imageIcon: cell?.imageView.image)
-                            }
-                        }
-                    }
-                    
-                } else {
-                    
-                    NCUtility.shared.stopActivityIndicator()
-                }
-            }
+            NCOperationQueue.shared.downloadAvatar(user: activity.user, fileName: fileName, placeholder: UIImage(named: "avatar"), cell: cell, view: tableView)
         }
-    }
-}
-
-extension activityTableViewCell: UICollectionViewDataSource {
-    
-    func numberOfSections(in collectionView: UICollectionView) -> Int {
-        return 1
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        return activityPreviews.count
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
         
-        let cell: activityCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! activityCollectionViewCell
+        // subject
+        if activity.subjectRich.count > 0 {
             
-        cell.imageView.image = nil
-        
-        let activityPreview = activityPreviews[indexPath.row]
-        let fileId = String(activityPreview.fileId)
-        
-        // Trashbin
-        if activityPreview.view == "trashbin" {
-            
-            let source = activityPreview.source
+            var subject = activity.subjectRich
+            var keys: [String] = []
             
-            NCUtility.shared.convertSVGtoPNGWriteToUserData(svgUrlString: source, fileName: nil, width: 100, rewrite: false, account: appDelegate.account) { (imageNamePath) in
-                if imageNamePath != nil {
-                    if let image = UIImage(contentsOfFile: imageNamePath!) {
-                        cell.imageView.image = image
-                    }
-                } else {
-                     cell.imageView.image = UIImage.init(named: "file")
+            if let regex = try? NSRegularExpression(pattern: "\\{[a-z0-9]+\\}", options: .caseInsensitive) {
+                let string = subject as NSString
+                keys = regex.matches(in: subject, options: [], range: NSRange(location: 0, length: string.length)).map {
+                    string.substring(with: $0.range).replacingOccurrences(of: "[\\{\\}]", with: "", options: .regularExpression)
                 }
             }
             
-        } else {
-            
-            if activityPreview.isMimeTypeIcon {
-                
-                let source = activityPreview.source
-                
-                NCUtility.shared.convertSVGtoPNGWriteToUserData(svgUrlString: source, fileName: nil, width: 100, rewrite: false, account: appDelegate.account) { (imageNamePath) in
-                    if imageNamePath != nil {
-                        if let image = UIImage(contentsOfFile: imageNamePath!) {
-                            cell.imageView.image = image
-                        }
-                    } else {
-                        cell.imageView.image = UIImage.init(named: "file")
-                    }
-                }
-                
-            } else {
-                
-                if let activitySubjectRich = NCManageDatabase.shared.getActivitySubjectRich(account: account, idActivity: idActivity, id: fileId) {
-                    
-                    let fileNamePath = CCUtility.getDirectoryUserData() + "/" + activitySubjectRich.name
-                    
-                    if FileManager.default.fileExists(atPath: fileNamePath) {
-                        
-                        if let image = UIImage(contentsOfFile: fileNamePath) {
-                            cell.imageView.image = image
-                        }
-                        
-                    } else {
-                        
-                        NCCommunication.shared.downloadPreview(fileNamePathOrFileId: activityPreview.source, fileNamePreviewLocalPath: fileNamePath, widthPreview: 0, heightPreview: 0, etag: nil, useInternalEndpoint: false) { (account, imagePreview, imageIcon, imageOriginal, etag, errorCode, errorDescription) in
-                            if errorCode == 0 && imagePreview != nil {
-                                self.collectionView.reloadData()
-                            }
-                        }
-                    }
+            for key in keys {
+                if let result = NCManageDatabase.shared.getActivitySubjectRich(account: appDelegate.account, idActivity: activity.idActivity, key: key) {
+                    orderKeysId.append(result.id)
+                    subject = subject.replacingOccurrences(of: "{\(key)}", with: "<bold>" + result.name + "</bold>")
                 }
             }
-        }
             
+            let normal = Style {
+                $0.font = UIFont.systemFont(ofSize: cell.subject.font.pointSize)
+                $0.lineSpacing = 1.5
+            }
+            let bold = Style { $0.font = UIFont.systemFont(ofSize: cell.subject.font.pointSize, weight: .bold) }
+            let date = Style { $0.font = UIFont.systemFont(ofSize: cell.subject.font.pointSize - 3)
+                $0.color = UIColor.lightGray
+            }
+            
+            subject = subject + "\n" + "<date>" + CCUtility.dateDiff(activity.date as Date) + "</date>"
+            cell.subject.attributedText = subject.set(style: StyleGroup(base: normal, ["bold": bold, "date": date]))
+        }
+        
+        // CollectionView
+        cell.activityPreviews = NCManageDatabase.shared.getActivityPreview(account: activity.account, idActivity: activity.idActivity, orderKeysId: orderKeysId)
+        if cell.activityPreviews.count == 0 {
+            cell.collectionViewHeightConstraint.constant = 0
+        } else {
+            cell.collectionViewHeightConstraint.constant = 60
+        }
+        cell.collectionView.reloadData()
+        
         return cell
     }
-    
 }
 
-class activityCollectionViewCell: UICollectionViewCell {
-    
-    @IBOutlet weak var imageView: UIImageView!
-    
-    override func awakeFromNib() {
-        super.awakeFromNib()
-    }
-}
+// MARK: - ScrollView
 
-extension activityTableViewCell: UICollectionViewDelegateFlowLayout {
-    
-    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
-        return CGSize(width: 50, height: 50)
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
-        return 20
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
-        return UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
+extension NCActivity: UIScrollViewDelegate {
+    func scrollViewDidScroll(_ scrollView: UIScrollView) {
+        if scrollView.contentSize.height - scrollView.contentOffset.y - scrollView.frame.height < 100 {
+            // comments are always loaded in full, only partially load more acitvities
+            if let activity = allItems.compactMap({ $0 as? tableActivity }).last {
+                loadActivity(idActivity: activity.objectId)
+            }
+        }
     }
 }
 
 // MARK: - NC API & Algorithm
 
 extension NCActivity {
-    
+
     func loadDataSource() {
         
-        sectionDate.removeAll()
-        
-        let activities = NCManageDatabase.shared.getActivity(predicate: NSPredicate(format: "account == %@", appDelegate.account), filterFileId: filterFileId)
-        allActivities = activities.all
-        filterActivities = activities.filter
-        for tableActivity in filterActivities {
-            guard let date = Calendar.current.date(from: Calendar.current.dateComponents([.year, .month, .day], from: tableActivity.date as Date)) else {
-                continue
-            }
-            if !sectionDate.contains(date) {
-                sectionDate.append(date)
+        guard let metadata = self.metadata else { return }
+        NCUtility.shared.startActivityIndicator(backgroundView: tableView, blurEffect: false)
+        let reloadDispatch = DispatchGroup()
+        self.allItems = []
+        reloadDispatch.enter()
+        reloadDispatch.enter()
+
+        NCCommunication.shared.getComments(fileId: metadata.fileId) { (account, comments, errorCode, errorDescription) in
+            if errorCode == 0 && comments != nil {
+                NCManageDatabase.shared.addComments(comments!, account: metadata.account, objectId: metadata.fileId)
+                self.allItems += NCManageDatabase.shared.getComments(account: metadata.account, objectId: metadata.fileId)
+                reloadDispatch.leave()
+            } else {
+                if errorCode != NCGlobal.shared.errorResourceNotFound {
+                    NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                }
             }
         }
         
-        tableView.reloadData()
-    }
-    
-    func getTableActivitiesFromSection(_ section: Int) -> [tableActivity] {
-        let startDate = sectionDate[section]
-        let endDate: Date = {
-            let components = DateComponents(day: 1, second: -1)
-            return Calendar.current.date(byAdding: components, to: startDate)!
-        }()
-        
-        let activities = NCManageDatabase.shared.getActivity(predicate: NSPredicate(format: "account == %@ && date BETWEEN %@", appDelegate.account, [startDate, endDate]), filterFileId: filterFileId)
-        return activities.filter
+        let activities = NCManageDatabase.shared.getActivity(
+            predicate: NSPredicate(format: "account == %@", appDelegate.account),
+            filterFileId: metadata.fileId)
+        self.allItems += activities.filter
+        reloadDispatch.leave()
+        
+        reloadDispatch.notify(qos: .userInitiated, flags: .enforceQoS, queue: .main) {
+            self.allItems.sort(by: { $0.dateKey > $1.dateKey })
+            self.sectionDates = self.allItems.reduce(into: Set<Date>()) { partialResult, next in
+                   let newDay = Calendar.current.startOfDay(for: next.dateKey)
+                   partialResult.insert(newDay)
+            }.sorted(by: >)
+            self.tableView.reloadData()
+            NCUtility.shared.stopActivityIndicator()
+        }
     }
     
     @objc func loadActivity(idActivity: Int) {
@@ -604,21 +408,104 @@ extension NCActivity {
             NCUtility.shared.startActivityIndicator(backgroundView: self.view, blurEffect: false, bottom: height + 50, style: .gray)
         }
         
-        NCCommunication.shared.getActivity(since: idActivity, limit: 200, objectId: filterFileId, objectType: objectType, previews: true) { (account, activities, errorCode, errorDescription) in
-            
-           if errorCode == 0 && account == self.appDelegate.account {
-                NCManageDatabase.shared.addActivity(activities , account: account)
-            }
-            
-            NCUtility.shared.stopActivityIndicator()
-            
-            if errorCode == NCGlobal.shared.errorNotModified {
-                self.canFetchActivity = false
-            } else {
-                self.canFetchActivity = true
+        NCCommunication.shared.getActivity(
+            since: idActivity,
+            limit: 200,
+            objectId: metadata?.fileId,
+            objectType: objectType,
+            previews: true) { (account, activities, errorCode, errorDescription) in
+                
+                if errorCode == 0 && account == self.appDelegate.account {
+                    NCManageDatabase.shared.addActivity(activities, account: account)
+                }
+                
+                NCUtility.shared.stopActivityIndicator()
+                
+                if errorCode == NCGlobal.shared.errorNotModified {
+                    self.canFetchActivity = false
+                } else {
+                    self.canFetchActivity = true
+                }
+                
+                self.loadDataSource()
             }
-            
-            self.loadDataSource()
-        }
     }
 }
+
+extension NCActivity: NCShareCommentsCellDelegate {
+    func tapMenu(with tableComments: tableComments?, sender: Any) {
+        toggleMenu(with: tableComments)
+    }
+    
+    func toggleMenu(with tableComments: tableComments?) {
+        
+        let menuViewController = UIStoryboard.init(name: "NCMenu", bundle: nil).instantiateInitialViewController() as! NCMenu
+        var actions = [NCMenuAction]()
+
+        actions.append(
+            NCMenuAction(
+                title: NSLocalizedString("_edit_comment_", comment: ""),
+                icon: UIImage(named: "edit")!.image(color: NCBrandColor.shared.gray, size: 50),
+                action: { menuAction in
+                    guard let metadata = self.metadata, let tableComments = tableComments else { return }
+                    
+                    let alert = UIAlertController(title: NSLocalizedString("_edit_comment_", comment: ""), message: nil, preferredStyle: .alert)
+                    alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: nil))
+                    
+                    alert.addTextField(configurationHandler: { textField in
+                        textField.placeholder = NSLocalizedString("_new_comment_", comment: "")
+                    })
+                    
+                    alert.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { action in
+                        guard let message = alert.textFields?.first?.text, message != "" else { return }
+
+                        NCCommunication.shared.updateComments(fileId: metadata.fileId, messageId: tableComments.messageId, message: message) { (account, errorCode, errorDescription) in
+                            if errorCode == 0 {
+                                self.loadDataSource()
+                            } else {
+                                NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                            }
+                        }
+                    }))
+
+                    self.present(alert, animated: true)
+                }
+            )
+        )
+        
+        actions.append(
+            NCMenuAction(
+                title: NSLocalizedString("_delete_comment_", comment: ""),
+                icon: NCUtility.shared.loadImage(named: "trash"),
+                action: { menuAction in
+                    guard let metadata = self.metadata, let tableComments = tableComments else { return }
+
+                    NCCommunication.shared.deleteComments(fileId: metadata.fileId, messageId: tableComments.messageId) { (account, errorCode, errorDescription) in
+                        if errorCode == 0 {
+                            self.loadDataSource()
+                        } else {
+                            NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                        }
+                    }
+                }
+            )
+        )
+        
+        actions.append(
+            NCMenuAction(
+                title: NSLocalizedString("_cancel_", comment: ""),
+                icon: UIImage(named: "cancel")!.image(color: NCBrandColor.shared.gray, size: 50),
+                action: nil)
+        )
+        
+        menuViewController.actions = actions
+
+        let menuPanelController = NCMenuPanelController()
+        menuPanelController.parentPresenter = self
+        menuPanelController.delegate = menuViewController
+        menuPanelController.set(contentViewController: menuViewController)
+        menuPanelController.track(scrollView: menuViewController.tableView)
+        self.present(menuPanelController, animated: true, completion: nil)
+    }
+}
+

+ 292 - 0
iOSClient/Activity/NCActivityTableViewCell.swift

@@ -0,0 +1,292 @@
+//
+//  NCActivityCollectionViewCell.swift
+//  Nextcloud
+//
+//  Created by Henrik Storch on 17/01/2019.
+//  Copyright © 2021. All rights reserved.
+//
+//  Author Henrik Storch <henrik.storch@nextcloud.com>
+//
+//  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 NCCommunication
+
+class NCActivityCollectionViewCell: UICollectionViewCell {
+    
+    @IBOutlet weak var imageView: UIImageView!
+    
+    override func awakeFromNib() {
+        super.awakeFromNib()
+    }
+}
+
+class NCActivityTableViewCell: UITableViewCell, NCCellProtocol {
+    
+    private let appDelegate = UIApplication.shared.delegate as! AppDelegate
+
+    @IBOutlet weak var collectionView: UICollectionView!
+    @IBOutlet weak var icon: UIImageView!
+    @IBOutlet weak var avatar: UIImageView!
+    @IBOutlet weak var subject: UILabel!
+    @IBOutlet weak var subjectTrailingConstraint: NSLayoutConstraint!
+    @IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint!
+
+    private var user: String = ""
+
+    var idActivity: Int = 0
+    var account: String = ""
+    var activityPreviews: [tableActivityPreview] = []
+    var didSelectItemEnable: Bool = true
+    var viewController: UIViewController? = nil
+    
+    var fileAvatarImageView: UIImageView? {
+        get {
+            return avatar
+        }
+    }
+    var fileObjectId: String? {
+        get {
+            return nil
+        }
+    }
+    var filePreviewImageView: UIImageView? {
+        get {
+            return nil
+        }
+    }
+    var fileUser: String? {
+        get {
+            return user
+        }
+        set {
+            user = newValue ?? ""
+        }
+    }
+    
+    override func awakeFromNib() {
+        super.awakeFromNib()
+        
+        collectionView.delegate = self
+        collectionView.dataSource = self
+    }
+}
+
+// MARK: - Collection View
+
+extension NCActivityTableViewCell: UICollectionViewDelegate {
+    
+    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+        
+        // Select not permitted
+        if !didSelectItemEnable {
+            return
+        }
+        
+        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as? NCActivityCollectionViewCell
+        
+        let activityPreview = activityPreviews[indexPath.row]
+        
+        if activityPreview.view == "trashbin" {
+            
+            var responder: UIResponder? = collectionView
+            while !(responder is UIViewController) {
+                responder = responder?.next
+                if nil == responder {
+                    break
+                }
+            }
+            if (responder as? UIViewController)!.navigationController != nil {
+                if let viewController = UIStoryboard.init(name: "NCTrash", bundle: nil).instantiateInitialViewController() as? NCTrash {
+                    if let result = NCManageDatabase.shared.getTrashItem(fileId: String(activityPreview.fileId), account: activityPreview.account) {
+                        viewController.blinkFileId = result.fileId
+                        viewController.trashPath = result.filePath
+                        (responder as? UIViewController)!.navigationController?.pushViewController(viewController, animated: true)
+                    } else {
+                        NCContentPresenter.shared.messageNotification("_error_", description: "_trash_file_not_found_", delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.info, errorCode: NCGlobal.shared.errorInternalError)
+                    }
+                }
+            }
+            
+            return
+        }
+        
+        if activityPreview.view == "files" && activityPreview.mimeType != "dir" {
+            
+            guard let activitySubjectRich = NCManageDatabase.shared.getActivitySubjectRich(account: activityPreview.account, idActivity: activityPreview.idActivity, id: String(activityPreview.fileId)) else {
+                return
+            }
+            
+            if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "fileId == %@", activitySubjectRich.id)) {
+                if let filePath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView) {
+                    do {
+                        let attr = try FileManager.default.attributesOfItem(atPath: filePath)
+                        let fileSize = attr[FileAttributeKey.size] as! UInt64
+                        if fileSize > 0 {
+                            if let viewController = self.viewController {
+                                NCViewer.shared.view(viewController: viewController, metadata: metadata, metadatas: [metadata], imageIcon: cell?.imageView.image)
+                            }
+                            return
+                        }
+                    } catch {
+                        print("Error: \(error)")
+                    }
+                }
+            }
+            
+            var pathComponents = activityPreview.link.components(separatedBy: "?")
+            pathComponents = pathComponents[1].components(separatedBy: "&")
+            var serverUrlFileName = pathComponents[0].replacingOccurrences(of: "dir=", with: "").removingPercentEncoding!
+            serverUrlFileName = appDelegate.urlBase + "/" + NCUtilityFileSystem.shared.getWebDAV(account: activityPreview.account) + serverUrlFileName + "/" + activitySubjectRich.name
+            
+            let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(activitySubjectRich.id, fileNameView: activitySubjectRich.name)!
+            
+            NCUtility.shared.startActivityIndicator(backgroundView: (appDelegate.window?.rootViewController?.view)!, blurEffect: true)
+            
+            NCCommunication.shared.download(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, requestHandler: { (_) in
+                
+            }, taskHandler: { (_) in
+                
+            }, progressHandler: { (_) in
+                
+            }) { (account, etag, date, lenght, allHeaderFields, error, errorCode, errorDescription) in
+                
+                if account == self.appDelegate.account && errorCode == 0 {
+                    
+                    let serverUrl = (serverUrlFileName as NSString).deletingLastPathComponent
+                    let fileName = (serverUrlFileName as NSString).lastPathComponent
+                    let serverUrlFileName = serverUrl + "/" + fileName
+                    
+                    NCNetworking.shared.readFile(serverUrlFileName: serverUrlFileName, account: activityPreview.account) { (account, metadata, errorCode, errorDescription) in
+                        
+                        NCUtility.shared.stopActivityIndicator()
+                        
+                        if account == self.appDelegate.account && errorCode == 0  {
+                            
+                            // move from id to oc:id + instanceid (ocId)
+                            let atPath = CCUtility.getDirectoryProviderStorage()! + "/" + activitySubjectRich.id
+                            let toPath = CCUtility.getDirectoryProviderStorage()! + "/" + metadata!.ocId
+                                                       
+                            CCUtility.moveFile(atPath: atPath, toPath: toPath)
+                                                       
+                            NCManageDatabase.shared.addMetadata(metadata!)
+                            if let viewController = self.viewController {
+                                NCViewer.shared.view(viewController: viewController, metadata: metadata!, metadatas: [metadata!], imageIcon: cell?.imageView.image)
+                            }
+                        }
+                    }
+                    
+                } else {
+                    
+                    NCUtility.shared.stopActivityIndicator()
+                }
+            }
+        }
+    }
+}
+
+extension NCActivityTableViewCell: UICollectionViewDataSource {
+    
+    func numberOfSections(in collectionView: UICollectionView) -> Int {
+        return 1
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+        return activityPreviews.count
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+        
+        let cell: NCActivityCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! NCActivityCollectionViewCell
+            
+        cell.imageView.image = nil
+        
+        let activityPreview = activityPreviews[indexPath.row]
+        let fileId = String(activityPreview.fileId)
+        
+        // Trashbin
+        if activityPreview.view == "trashbin" {
+            
+            let source = activityPreview.source
+            
+            NCUtility.shared.convertSVGtoPNGWriteToUserData(svgUrlString: source, fileName: nil, width: 100, rewrite: false, account: appDelegate.account) { (imageNamePath) in
+                if imageNamePath != nil {
+                    if let image = UIImage(contentsOfFile: imageNamePath!) {
+                        cell.imageView.image = image
+                    }
+                } else {
+                     cell.imageView.image = UIImage.init(named: "file")
+                }
+            }
+            
+        } else {
+            
+            if activityPreview.isMimeTypeIcon {
+                
+                let source = activityPreview.source
+                
+                NCUtility.shared.convertSVGtoPNGWriteToUserData(svgUrlString: source, fileName: nil, width: 100, rewrite: false, account: appDelegate.account) { (imageNamePath) in
+                    if imageNamePath != nil {
+                        if let image = UIImage(contentsOfFile: imageNamePath!) {
+                            cell.imageView.image = image
+                        }
+                    } else {
+                        cell.imageView.image = UIImage.init(named: "file")
+                    }
+                }
+                
+            } else {
+                
+                if let activitySubjectRich = NCManageDatabase.shared.getActivitySubjectRich(account: account, idActivity: idActivity, id: fileId) {
+                    
+                    let fileNamePath = CCUtility.getDirectoryUserData() + "/" + activitySubjectRich.name
+                    
+                    if FileManager.default.fileExists(atPath: fileNamePath) {
+                        
+                        if let image = UIImage(contentsOfFile: fileNamePath) {
+                            cell.imageView.image = image
+                        }
+                        
+                    } else {
+                        
+                        NCCommunication.shared.downloadPreview(fileNamePathOrFileId: activityPreview.source, fileNamePreviewLocalPath: fileNamePath, widthPreview: 0, heightPreview: 0, etag: nil, useInternalEndpoint: false) { (account, imagePreview, imageIcon, imageOriginal, etag, errorCode, errorDescription) in
+                            if errorCode == 0 && imagePreview != nil {
+                                self.collectionView.reloadData()
+                            }
+                        }
+                    }
+                }
+            }
+        }
+            
+        return cell
+    }
+    
+}
+
+extension NCActivityTableViewCell: UICollectionViewDelegateFlowLayout {
+    
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
+        return CGSize(width: 50, height: 50)
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
+        return 20
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
+        return UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
+    }
+}

+ 10 - 3
iOSClient/Data/NCDatabase.swift

@@ -24,6 +24,10 @@
 import UIKit
 import RealmSwift
 
+protocol DateCompareable {
+    var dateKey: Date { get }
+}
+
 class tableAccount: Object {
 
     @objc dynamic var account = ""
@@ -103,8 +107,9 @@ class tableAccount: Object {
     }
 }
 
-class tableActivity: Object {
-    
+class tableActivity: Object, DateCompareable {
+    var dateKey: Date { date as Date }
+
     @objc dynamic var account = ""
     @objc dynamic var idPrimaryKey = ""
     @objc dynamic var action = "Activity"
@@ -202,7 +207,9 @@ class tableChunk: Object {
     }
 }
 
-class tableComments: Object {
+class tableComments: Object, DateCompareable {
+    var dateKey: Date { creationDateTime as Date }
+    
     
     @objc dynamic var account = ""
     @objc dynamic var actorDisplayName = ""

+ 66 - 57
iOSClient/Data/NCManageDatabase.swift

@@ -775,56 +775,61 @@ class NCManageDatabase: NSObject {
                     addObjectActivity.user = activity.user
                     addObjectActivity.subject = activity.subject
                     
-                    if let subject_rich = activity.subject_rich {
-                        if let json = JSON(subject_rich).array {
-                            addObjectActivity.subjectRich = json[0].stringValue
-                            if json.count > 1 {
-                                if let dict = json[1].dictionary {
-                                    for (key, value) in dict {
-                                        let addObjectActivitySubjectRich = tableActivitySubjectRich()
-                                        let dict = value as JSON
-                                        addObjectActivitySubjectRich.account = account
-                                        if dict["id"].intValue > 0 {
-                                            addObjectActivitySubjectRich.id = String(dict["id"].intValue)
-                                        } else {
-                                            addObjectActivitySubjectRich.id = dict["id"].stringValue
-                                        }
-                                        addObjectActivitySubjectRich.name = dict["name"].stringValue
-                                        addObjectActivitySubjectRich.idPrimaryKey = account + String(activity.idActivity) + addObjectActivitySubjectRich.id + addObjectActivitySubjectRich.name
-                                        addObjectActivitySubjectRich.key = key
-                                        addObjectActivitySubjectRich.idActivity = activity.idActivity
-                                        addObjectActivitySubjectRich.link = dict["link"].stringValue
-                                        addObjectActivitySubjectRich.path = dict["path"].stringValue
-                                        addObjectActivitySubjectRich.type = dict["type"].stringValue
-
-                                        realm.add(addObjectActivitySubjectRich, update: .all)
-                                    }
+                    if let subject_rich = activity.subject_rich,
+                       let json = JSON(subject_rich).array {
+                        
+                        addObjectActivity.subjectRich = json[0].stringValue
+                        if json.count > 1,
+                           let dict = json[1].dictionary {
+                            
+                            for (key, value) in dict {
+                                let addObjectActivitySubjectRich = tableActivitySubjectRich()
+                                let dict = value as JSON
+                                addObjectActivitySubjectRich.account = account
+                                
+                                if dict["id"].intValue > 0 {
+                                    addObjectActivitySubjectRich.id = String(dict["id"].intValue)
+                                } else {
+                                    addObjectActivitySubjectRich.id = dict["id"].stringValue
                                 }
-                            }
-                        }
-                    }
-                    
-                    if let previews = activity.previews {
-                        if let json = JSON(previews).array {
-                            for preview in json {
-                                let addObjectActivityPreview = tableActivityPreview()
                                 
-                                addObjectActivityPreview.account = account
-                                addObjectActivityPreview.idActivity = activity.idActivity
-                                addObjectActivityPreview.fileId = preview["fileId"].intValue
-                                addObjectActivityPreview.filename = preview["filename"].stringValue
-                                addObjectActivityPreview.idPrimaryKey = account + String(activity.idActivity) + String(addObjectActivityPreview.fileId)
-                                addObjectActivityPreview.source = preview["source"].stringValue
-                                addObjectActivityPreview.link = preview["link"].stringValue
-                                addObjectActivityPreview.mimeType = preview["mimeType"].stringValue
-                                addObjectActivityPreview.view = preview["view"].stringValue
-                                addObjectActivityPreview.isMimeTypeIcon = preview["isMimeTypeIcon"].boolValue
+                                addObjectActivitySubjectRich.name = dict["name"].stringValue
+                                addObjectActivitySubjectRich.idPrimaryKey = account
+                                + String(activity.idActivity)
+                                + addObjectActivitySubjectRich.id
+                                + addObjectActivitySubjectRich.name
+                                
+                                addObjectActivitySubjectRich.key = key
+                                addObjectActivitySubjectRich.idActivity = activity.idActivity
+                                addObjectActivitySubjectRich.link = dict["link"].stringValue
+                                addObjectActivitySubjectRich.path = dict["path"].stringValue
+                                addObjectActivitySubjectRich.type = dict["type"].stringValue
                                 
-                                realm.add(addObjectActivityPreview, update: .all)
+                                realm.add(addObjectActivitySubjectRich, update: .all)
                             }
                         }
                     }
                     
+                    if let previews = activity.previews,
+                       let json = JSON(previews).array {
+                        for preview in json {
+                            let addObjectActivityPreview = tableActivityPreview()
+                            
+                            addObjectActivityPreview.account = account
+                            addObjectActivityPreview.idActivity = activity.idActivity
+                            addObjectActivityPreview.fileId = preview["fileId"].intValue
+                            addObjectActivityPreview.filename = preview["filename"].stringValue
+                            addObjectActivityPreview.idPrimaryKey = account + String(activity.idActivity) + String(addObjectActivityPreview.fileId)
+                            addObjectActivityPreview.source = preview["source"].stringValue
+                            addObjectActivityPreview.link = preview["link"].stringValue
+                            addObjectActivityPreview.mimeType = preview["mimeType"].stringValue
+                            addObjectActivityPreview.view = preview["view"].stringValue
+                            addObjectActivityPreview.isMimeTypeIcon = preview["isMimeTypeIcon"].boolValue
+
+                            realm.add(addObjectActivityPreview, update: .all)
+                        }
+                    }
+
                     addObjectActivity.icon = activity.icon
                     addObjectActivity.link = activity.link
                     addObjectActivity.message = activity.message
@@ -845,22 +850,26 @@ class NCManageDatabase: NSObject {
         let realm = try! Realm()
         
         let results = realm.objects(tableActivity.self).filter(predicate).sorted(byKeyPath: "idActivity", ascending: false)
-        let allActivity = Array(results.map { tableActivity.init(value:$0) })
-        if filterFileId != nil {
-            var resultsFilter: [tableActivity] = []
-            for result in results {
-                let resultsActivitySubjectRich = realm.objects(tableActivitySubjectRich.self).filter("account == %@ && idActivity == %d", result.account, result.idActivity)
-                for resultActivitySubjectRich in resultsActivitySubjectRich {
-                    if filterFileId!.contains(resultActivitySubjectRich.id) && resultActivitySubjectRich.key == "file" {
-                        resultsFilter.append(result)
-                        break
-                    }
+        let allActivity = Array(results.map(tableActivity.init))
+        guard let filterFileId = filterFileId else {
+            return (all: allActivity, filter: allActivity)
+        }
+        // comments are loaded seperately
+        let filtered = allActivity.filter({ String($0.objectId) == filterFileId && $0.type != "comments" })
+        return (all: allActivity, filter: filtered)
+        
+        //HELP: What is this? What is it used for? Why not just use `.filter()` on the array
+        var resultsFilter: [tableActivity] = []
+        for result in results {
+            let resultsActivitySubjectRich = realm.objects(tableActivitySubjectRich.self).filter("account == %@ && idActivity == %d", result.account, result.idActivity)
+            for resultActivitySubjectRich in resultsActivitySubjectRich {
+                if filterFileId.contains(resultActivitySubjectRich.id) && resultActivitySubjectRich.key == "file" {
+                    resultsFilter.append(result)
+                    break
                 }
             }
-            return(all: allActivity, filter: Array(resultsFilter.map { tableActivity.init(value:$0) }))
-        } else {
-            return(all: allActivity, filter: allActivity)
         }
+        return(all: allActivity, filter: Array(resultsFilter.map(tableActivity.init)))
     }
     
     @objc func getActivitySubjectRich(account: String, idActivity: Int, key: String) -> tableActivitySubjectRich? {
@@ -1252,7 +1261,7 @@ class NCManageDatabase: NSObject {
         
         let results = realm.objects(tableComments.self).filter("account == %@ AND objectId == %@", account, objectId).sorted(byKeyPath: "creationDateTime", ascending: false)
         
-        return Array(results.map { tableComments.init(value:$0) })
+        return Array(results.map(tableComments.init))
     }
     
     //MARK: -

+ 1 - 1
iOSClient/Main/Collection Common/NCCollectionViewCommon.swift

@@ -817,7 +817,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
         if isEditMode { return }
         guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(objectId) else { return }
         
-        NCFunctionCenter.shared.openShare(ViewController: self, metadata: metadata, indexPage: 2)
+        NCFunctionCenter.shared.openShare(ViewController: self, metadata: metadata, indexPage: .sharing)
     }
         
     func tapMoreGridItem(with objectId: String, namedButtonMore: String, image: UIImage?, sender: Any) {

+ 2 - 2
iOSClient/Main/NCFunctionCenter.swift

@@ -187,7 +187,7 @@ import Queuer
     
     // MARK: -
 
-    func openShare(ViewController: UIViewController, metadata: tableMetadata, indexPage: Int) {
+    func openShare(ViewController: UIViewController, metadata: tableMetadata, indexPage: NCGlobal.NCSharePagingIndex) {
         
         let shareNavigationController = UIStoryboard(name: "NCShare", bundle: nil).instantiateInitialViewController() as! UINavigationController
         let shareViewController = shareNavigationController.topViewController as! NCSharePaging
@@ -643,7 +643,7 @@ import Queuer
         }
         
         let detail = UIAction(title: NSLocalizedString("_details_", comment: ""), image: UIImage(systemName: "info")) { action in
-            self.openShare(ViewController: viewController, metadata: metadata, indexPage: 0)
+            self.openShare(ViewController: viewController, metadata: metadata, indexPage: .activity)
         }
         
         let offline = UIAction(title: titleOffline, image: UIImage(systemName: "tray.and.arrow.down")) { action in

+ 1 - 1
iOSClient/Menu/NCCollectionViewCommon+Menu.swift

@@ -117,7 +117,7 @@ extension NCCollectionViewCommon {
                     title: NSLocalizedString("_details_", comment: ""),
                     icon: NCUtility.shared.loadImage(named: "info"),
                     action: { menuAction in
-                        NCFunctionCenter.shared.openShare(ViewController: self, metadata: metadata, indexPage: 0)
+                        NCFunctionCenter.shared.openShare(ViewController: self, metadata: metadata, indexPage: .activity)
                     }
                 )
             )

+ 0 - 107
iOSClient/Menu/NCShareComments+Menu.swift

@@ -1,107 +0,0 @@
-//
-//  NCShareComments+Menu.swift
-//  Nextcloud
-//
-//  Created by Marino Faggiana on 03/03/2021.
-//  Copyright © 2021 Marino Faggiana. All rights reserved.
-//
-//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
-//
-//  This program is free software: you can redistribute it and/or modify
-//  it under the terms of the GNU General Public License as published by
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-import UIKit
-import FloatingPanel
-import NCCommunication
-
-extension NCShareComments {
-
-    func toggleMenu(with tableComments: tableComments?) {
-        
-        let menuViewController = UIStoryboard.init(name: "NCMenu", bundle: nil).instantiateInitialViewController() as! NCMenu
-        var actions = [NCMenuAction]()
-
-        actions.append(
-            NCMenuAction(
-                title: NSLocalizedString("_edit_comment_", comment: ""),
-                icon: UIImage(named: "edit")!.image(color: NCBrandColor.shared.gray, size: 50),
-                action: { menuAction in
-                    guard let metadata = self.metadata else { return }
-                    guard let tableComments = tableComments else { return }
-                    
-                    let alert = UIAlertController(title: NSLocalizedString("_edit_comment_", comment: ""), message: nil, preferredStyle: .alert)
-                    alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: nil))
-                    
-                    alert.addTextField(configurationHandler: { textField in
-                        textField.placeholder = NSLocalizedString("_new_comment_", comment: "")
-                    })
-                    
-                    alert.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { action in
-                        if let message = alert.textFields?.first?.text {
-                            if message != "" {
-                                NCCommunication.shared.updateComments(fileId: metadata.fileId, messageId: tableComments.messageId, message: message) { (account, errorCode, errorDescription) in
-                                    if errorCode == 0 {
-                                        self.reloadData()
-                                    } else {
-                                        NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
-                                    }
-                                }
-                            }
-                        }
-                    }))
-                    
-                    self.present(alert, animated: true)
-                }
-            )
-        )
-        
-        actions.append(
-            NCMenuAction(
-                title: NSLocalizedString("_delete_comment_", comment: ""),
-                icon: NCUtility.shared.loadImage(named: "trash"),
-                action: { menuAction in
-                    guard let metadata = self.metadata else { return }
-                    guard let tableComments = tableComments else { return }
-
-                    NCCommunication.shared.deleteComments(fileId: metadata.fileId, messageId: tableComments.messageId) { (account, errorCode, errorDescription) in
-                        if errorCode == 0 {
-                            self.reloadData()
-                        } else {
-                            NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
-                        }
-                    }
-                }
-            )
-        )
-        
-        actions.append(
-            NCMenuAction(
-                title: NSLocalizedString("_cancel_", comment: ""),
-                icon: UIImage(named: "cancel")!.image(color: NCBrandColor.shared.gray, size: 50),
-                action: { menuAction in
-                }
-            )
-        )
-        
-        menuViewController.actions = actions
-
-        let menuPanelController = NCMenuPanelController()
-        menuPanelController.parentPresenter = self
-        menuPanelController.delegate = menuViewController
-        menuPanelController.set(contentViewController: menuViewController)
-        menuPanelController.track(scrollView: menuViewController.tableView)
-        self.present(menuPanelController, animated: true, completion: nil)
-    }
-}
-

+ 1 - 1
iOSClient/Menu/NCViewer+Menu.swift

@@ -80,7 +80,7 @@ extension NCViewer {
                     title: NSLocalizedString("_details_", comment: ""),
                     icon: NCUtility.shared.loadImage(named: "info"),
                     action: { menuAction in
-                        NCFunctionCenter.shared.openShare(ViewController: viewController, metadata: metadata, indexPage: 0)
+                        NCFunctionCenter.shared.openShare(ViewController: viewController, metadata: metadata, indexPage: .activity)
                     }
                 )
             )

+ 4 - 4
iOSClient/NCGlobal.swift

@@ -141,10 +141,10 @@ class NCGlobal: NSObject {
     
     // NCSharePaging
     //
-    let indexPageActivity: Int                      = 0
-    let indexPageComments: Int                      = 1
-    let indexPageSharing: Int                       = 2
-    
+    enum NCSharePagingIndex: Int, CaseIterable {
+        case activity, sharing
+    }
+
     // NCViewerProviderContextMenu
     //
     let maxAutoDownload: UInt64                     = 50000000      // 50MB

+ 1 - 1
iOSClient/RichWorkspace/NCViewerRichWorkspaceWebView.swift

@@ -85,7 +85,7 @@ class NCViewerRichWorkspaceWebView: UIViewController, WKNavigationDelegate, WKSc
             
             if message.body as? String == "share" {
                 if (metadata != nil) {
-                    NCFunctionCenter.shared.openShare(ViewController: self, metadata: metadata!, indexPage: 2)
+                    NCFunctionCenter.shared.openShare(ViewController: self, metadata: metadata!, indexPage: .sharing)
                 }
             }
             

+ 2 - 80
iOSClient/Share/NCShare.storyboard

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Ts3-RO-A9l">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19162" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Ts3-RO-A9l">
     <device id="retina5_5" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19144"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
@@ -42,84 +42,6 @@
             </objects>
             <point key="canvasLocation" x="334.78260869565219" y="-167.41071428571428"/>
         </scene>
-        <!--Share Comments-->
-        <scene sceneID="R3f-Og-D1Y">
-            <objects>
-                <viewController storyboardIdentifier="comments" id="GMr-2Y-4vs" customClass="NCShareComments" customModule="Nextcloud" customModuleProvider="target" sceneMemberID="viewController">
-                    <view key="view" contentMode="scaleToFill" id="5MM-pX-rNX">
-                        <rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <subviews>
-                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jzJ-Ra-l4b" userLabel="View container">
-                                <rect key="frame" x="0.0" y="0.0" width="409" height="736"/>
-                                <subviews>
-                                    <textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="249" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" clearButtonMode="always" translatesAutoresizingMaskIntoConstraints="NO" id="j5C-gO-XF8">
-                                        <rect key="frame" x="55" y="60" width="344" height="30"/>
-                                        <constraints>
-                                            <constraint firstAttribute="height" constant="30" id="Cia-Ws-3fQ"/>
-                                        </constraints>
-                                        <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                                        <textInputTraits key="textInputTraits"/>
-                                        <connections>
-                                            <action selector="newCommentFieldDidEndOnExitWithTextField:" destination="GMr-2Y-4vs" eventType="editingDidEndOnExit" id="Vvc-xW-hjc"/>
-                                        </connections>
-                                    </textField>
-                                    <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="DFs-4t-iWX">
-                                        <rect key="frame" x="5" y="100" width="404" height="626"/>
-                                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                                        <color key="separatorColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                                    </tableView>
-                                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Oca-tA-DgS">
-                                        <rect key="frame" x="10" y="10" width="40" height="40"/>
-                                        <constraints>
-                                            <constraint firstAttribute="width" constant="40" id="COd-nn-6gK"/>
-                                            <constraint firstAttribute="height" constant="40" id="cp1-OV-zK5"/>
-                                        </constraints>
-                                    </imageView>
-                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="user" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9sc-sV-YF1">
-                                        <rect key="frame" x="60" y="21.666666666666668" width="337" height="17.000000000000004"/>
-                                        <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                                        <color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                                        <nil key="highlightedColor"/>
-                                    </label>
-                                </subviews>
-                                <constraints>
-                                    <constraint firstItem="DFs-4t-iWX" firstAttribute="top" secondItem="j5C-gO-XF8" secondAttribute="bottom" constant="10" id="2W4-MV-Q3t"/>
-                                    <constraint firstItem="9sc-sV-YF1" firstAttribute="centerY" secondItem="Oca-tA-DgS" secondAttribute="centerY" id="IAl-P4-FDb"/>
-                                    <constraint firstItem="9sc-sV-YF1" firstAttribute="leading" secondItem="Oca-tA-DgS" secondAttribute="trailing" constant="10" id="JLb-OL-NAh"/>
-                                    <constraint firstItem="DFs-4t-iWX" firstAttribute="leading" secondItem="jzJ-Ra-l4b" secondAttribute="leading" constant="5" id="JN4-2m-lYt"/>
-                                    <constraint firstItem="Oca-tA-DgS" firstAttribute="top" secondItem="jzJ-Ra-l4b" secondAttribute="top" constant="10" id="Nix-3m-Pph"/>
-                                    <constraint firstItem="j5C-gO-XF8" firstAttribute="leading" secondItem="jzJ-Ra-l4b" secondAttribute="leading" constant="55" id="TyF-h2-Kf2"/>
-                                    <constraint firstItem="Oca-tA-DgS" firstAttribute="leading" secondItem="jzJ-Ra-l4b" secondAttribute="leading" constant="10" id="UkL-iB-zOb"/>
-                                    <constraint firstItem="j5C-gO-XF8" firstAttribute="top" secondItem="Oca-tA-DgS" secondAttribute="bottom" constant="10" id="Xe1-ck-SGj"/>
-                                    <constraint firstAttribute="trailing" secondItem="DFs-4t-iWX" secondAttribute="trailing" id="ZcL-Ph-LOK"/>
-                                    <constraint firstAttribute="trailing" secondItem="j5C-gO-XF8" secondAttribute="trailing" constant="10" id="baS-fH-yjJ"/>
-                                    <constraint firstAttribute="trailing" secondItem="9sc-sV-YF1" secondAttribute="trailing" constant="12" id="ds7-kh-lTP"/>
-                                    <constraint firstAttribute="bottom" secondItem="DFs-4t-iWX" secondAttribute="bottom" constant="10" id="ghq-O1-zbF"/>
-                                </constraints>
-                            </view>
-                        </subviews>
-                        <viewLayoutGuide key="safeArea" id="j3W-IW-lzW"/>
-                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                        <constraints>
-                            <constraint firstItem="jzJ-Ra-l4b" firstAttribute="leading" secondItem="j3W-IW-lzW" secondAttribute="leading" id="B4V-GC-zYM"/>
-                            <constraint firstItem="j3W-IW-lzW" firstAttribute="trailing" secondItem="jzJ-Ra-l4b" secondAttribute="trailing" constant="5" id="WPr-LS-NPk"/>
-                            <constraint firstItem="j3W-IW-lzW" firstAttribute="bottom" secondItem="jzJ-Ra-l4b" secondAttribute="bottom" id="qNg-QS-tUI"/>
-                            <constraint firstItem="jzJ-Ra-l4b" firstAttribute="top" secondItem="5MM-pX-rNX" secondAttribute="top" id="vgD-mh-dz8"/>
-                        </constraints>
-                    </view>
-                    <connections>
-                        <outlet property="imageItem" destination="Oca-tA-DgS" id="4s1-hB-7aX"/>
-                        <outlet property="labelUser" destination="9sc-sV-YF1" id="JDY-BT-xob"/>
-                        <outlet property="newCommentField" destination="j5C-gO-XF8" id="bYE-r4-F6m"/>
-                        <outlet property="tableView" destination="DFs-4t-iWX" id="oU5-M6-jh0"/>
-                        <outlet property="viewContainerConstraint" destination="vgD-mh-dz8" id="CC9-oG-uiP"/>
-                    </connections>
-                </viewController>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="l4G-HZ-s1x" userLabel="First Responder" sceneMemberID="firstResponder"/>
-            </objects>
-            <point key="canvasLocation" x="2047.826086956522" y="-167.41071428571428"/>
-        </scene>
         <!--Share-->
         <scene sceneID="Iqh-6B-MEV">
             <objects>

+ 0 - 255
iOSClient/Share/NCShareComments.swift

@@ -1,255 +0,0 @@
-//
-//  NCShareComments.swift
-//  Nextcloud
-//
-//  Created by Marino Faggiana on 28/07/2019.
-//  Copyright © 2019 Marino Faggiana. All rights reserved.
-//
-//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
-//
-//  This program is free software: you can redistribute it and/or modify
-//  it under the terms of the GNU General Public License as published by
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-//  GNU General Public License for more details.
-//
-//  You should have received a copy of the GNU General Public License
-//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-//
-
-import UIKit
-import NCCommunication
-
-class NCShareComments: UIViewController, NCShareCommentsCellDelegate {
-   
-    @IBOutlet weak var viewContainerConstraint: NSLayoutConstraint!
-    @IBOutlet weak var tableView: UITableView!
-    @IBOutlet weak var imageItem: UIImageView!
-    @IBOutlet weak var labelUser: UILabel!
-    @IBOutlet weak var newCommentField: UITextField!
-
-    private let appDelegate = UIApplication.shared.delegate as! AppDelegate
-
-    var metadata: tableMetadata?
-    public var height: CGFloat = 0
-
-    // MARK: - View Life Cycle
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        
-        view.backgroundColor = NCBrandColor.shared.systemBackground
-        viewContainerConstraint.constant = height
-        
-        tableView.dataSource = self
-        tableView.delegate = self
-        tableView.tableFooterView = UIView()
-        tableView.rowHeight = UITableView.automaticDimension
-        tableView.estimatedRowHeight = tableView.bounds.height
-        tableView.allowsSelection = false
-        tableView.backgroundColor = NCBrandColor.shared.systemBackground
-        tableView.separatorColor = NCBrandColor.shared.separator
-        
-        tableView.register(UINib.init(nibName: "NCShareCommentsCell", bundle: nil), forCellReuseIdentifier: "cell")
-
-        newCommentField.placeholder = NSLocalizedString("_new_comment_", comment: "")
-        
-        // Display Name user & Quota
-        guard let activeAccount = NCManageDatabase.shared.getActiveAccount() else {
-            return
-        }
-        
-        if activeAccount.displayName.isEmpty {
-            labelUser.text = activeAccount.user
-        }
-        else{
-            labelUser.text = activeAccount.displayName
-        }
-        labelUser.textColor = NCBrandColor.shared.label
-        
-        let fileName = String(CCUtility.getUserUrlBase(appDelegate.user, urlBase: appDelegate.urlBase)) + "-" + appDelegate.user + ".png"
-        let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName
-        if let image = UIImage(contentsOfFile: fileNameLocalPath) {
-            imageItem.image = image
-        } else {
-            imageItem.image = UIImage(named: "avatar")
-        }
-        
-        // Mark comment ad read
-        if metadata != nil && metadata!.commentsUnread {
-            NCCommunication.shared.markAsReadComments(fileId: metadata!.fileId) { (account, errorCode, errorDescription) in
-                if errorCode == 0 {
-                    NCManageDatabase.shared.readMarkerMetadata(account: account, fileId: self.metadata!.fileId)
-                }
-            }
-        }
-        
-        // changeTheming
-        NotificationCenter.default.addObserver(self, selector: #selector(changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
-        
-        changeTheming()
-    }
-    
-    override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        
-        reloadData()
-    }
-    
-    @objc func changeTheming() {
-        tableView.reloadData()
-    }
-    
-    @objc func reloadData() {
-        
-        guard let metadata = self.metadata else { return }
-
-        NCCommunication.shared.getComments(fileId: metadata.fileId) { (account, comments, errorCode, errorDescription) in
-            if errorCode == 0 && comments != nil {
-                NCManageDatabase.shared.addComments(comments!, account: metadata.account, objectId: metadata.fileId)
-                self.tableView.reloadData()
-            } else {
-                if errorCode != NCGlobal.shared.errorResourceNotFound {
-                    NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
-                }
-            }
-        }
-        
-        tableView.reloadData()
-    }
-    
-    // MARK: - IBAction & Tap
-    
-    @IBAction func newCommentFieldDidEndOnExit(textField: UITextField) {
-        
-        guard let message = textField.text else { return }
-        guard let metadata = self.metadata else { return }
-        if message.count == 0 { return }
-
-        NCCommunication.shared.putComments(fileId: metadata.fileId, message: message) { (account, errorCode, errorDescription) in
-            if errorCode == 0 {
-                self.newCommentField.text = ""
-                self.reloadData()
-            } else {
-                NCContentPresenter.shared.messageNotification("_share_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
-            }
-        }
-    }
-    
-    func tapMenu(with tableComments: tableComments?, sender: Any) {
-       toggleMenu(with: tableComments)
-    }
-}
-
-// MARK: - UITableViewDelegate
-
-extension NCShareComments: UITableViewDelegate {
-    
-    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
-        return UITableView.automaticDimension
-    }
-}
-
-// MARK: - UITableViewDataSource
-
-extension NCShareComments: UITableViewDataSource {
-    
-    func numberOfSections(in tableView: UITableView) -> Int {
-        return 1
-    }
-    
-    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        
-        let comments = NCManageDatabase.shared.getComments(account: metadata!.account, objectId: metadata!.fileId)
-        return comments.count
-    }
-    
-    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        
-        let comments = NCManageDatabase.shared.getComments(account: metadata!.account, objectId: metadata!.fileId)
-        let tableComments = comments[indexPath.row]
-        
-        if let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? NCShareCommentsCell {
-            
-            cell.tableComments = tableComments
-            cell.delegate = self
-            cell.sizeToFit()
-            
-            // Image
-            let fileName = String(CCUtility.getUserUrlBase(appDelegate.user, urlBase: appDelegate.urlBase)) + "-" + tableComments.actorId + ".png"
-            NCOperationQueue.shared.downloadAvatar(user: tableComments.actorId, fileName: fileName, placeholder: UIImage(named: "avatar"), cell: cell, view: tableView)
-            // Username
-            cell.labelUser.text = tableComments.actorDisplayName
-            cell.labelUser.textColor = NCBrandColor.shared.label
-            // Date
-            cell.labelDate.text = CCUtility.dateDiff(tableComments.creationDateTime as Date)
-            cell.labelDate.textColor = NCBrandColor.shared.systemGray4
-            // Message
-            cell.labelMessage.text = tableComments.message
-            cell.labelMessage.textColor = NCBrandColor.shared.label
-            // Button Menu
-            if tableComments.actorId == appDelegate.userId {
-                cell.buttonMenu.isHidden = false
-            } else {
-                cell.buttonMenu.isHidden = true
-            }
-            
-            return cell
-        }
-        
-        return UITableViewCell()
-    }
-}
-
-// MARK: - NCShareCommentsCell
-
-class NCShareCommentsCell: UITableViewCell, NCCellProtocol {
-    
-    @IBOutlet weak var imageItem: UIImageView!
-    @IBOutlet weak var labelUser: UILabel!
-    @IBOutlet weak var buttonMenu: UIButton!
-    @IBOutlet weak var labelDate: UILabel!
-    @IBOutlet weak var labelMessage: UILabel!
-    
-    var tableComments: tableComments?
-    var delegate: NCShareCommentsCellDelegate?
-    
-    var filePreviewImageView : UIImageView? {
-        get{
-            return nil
-        }
-    }
-    var fileAvatarImageView: UIImageView? {
-        get{
-            return imageItem
-        }
-    }
-    var fileObjectId: String? {
-        get {
-            return nil
-        }
-    }
-    var fileUser: String? {
-        get{
-            return tableComments?.actorId
-        }
-    }
-    
-    override func awakeFromNib() {
-        super.awakeFromNib()
-        
-        buttonMenu.setImage(UIImage.init(named: "shareMenu")!.image(color: .lightGray, size: 50), for: .normal)
-    }
-    
-    @IBAction func touchUpInsideMenu(_ sender: Any) {
-        delegate?.tapMenu(with: tableComments, sender: sender)
-    }
-}
-
-protocol NCShareCommentsCellDelegate {
-    func tapMenu(with tableComments: tableComments?, sender: Any)
-}

+ 74 - 0
iOSClient/Share/NCShareCommentsCell.swift

@@ -0,0 +1,74 @@
+//
+//  NCShareComments.swift
+//  Nextcloud
+//
+//  Created by Marino Faggiana on 28/07/2019.
+//  Copyright © 2019 Marino Faggiana. All rights reserved.
+//
+//  Author Marino Faggiana <marino.faggiana@nextcloud.com>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+//
+
+import UIKit
+import NCCommunication
+
+// MARK: - NCShareCommentsCell
+
+class NCShareCommentsCell: UITableViewCell, NCCellProtocol {
+    
+    @IBOutlet weak var imageItem: UIImageView!
+    @IBOutlet weak var labelUser: UILabel!
+    @IBOutlet weak var buttonMenu: UIButton!
+    @IBOutlet weak var labelDate: UILabel!
+    @IBOutlet weak var labelMessage: UILabel!
+    
+    var tableComments: tableComments?
+    var delegate: NCShareCommentsCellDelegate?
+    
+    var filePreviewImageView : UIImageView? {
+        get{
+            return nil
+        }
+    }
+    var fileAvatarImageView: UIImageView? {
+        get{
+            return imageItem
+        }
+    }
+    var fileObjectId: String? {
+        get {
+            return nil
+        }
+    }
+    var fileUser: String? {
+        get{
+            return tableComments?.actorId
+        }
+    }
+    
+    override func awakeFromNib() {
+        super.awakeFromNib()
+        
+        buttonMenu.setImage(UIImage.init(named: "shareMenu")!.image(color: .lightGray, size: 50), for: .normal)
+    }
+    
+    @IBAction func touchUpInsideMenu(_ sender: Any) {
+        delegate?.tapMenu(with: tableComments, sender: sender)
+    }
+}
+
+protocol NCShareCommentsCellDelegate {
+    func tapMenu(with tableComments: tableComments?, sender: Any)
+}

+ 28 - 44
iOSClient/Share/NCSharePaging.swift

@@ -37,7 +37,7 @@ class NCSharePaging: UIViewController {
     private var sharingEnabled = true
     
     @objc var metadata = tableMetadata()
-    @objc var indexPage: Int = 0
+    var indexPage = NCGlobal.NCSharePagingIndex.activity
         
     // MARK: - View Life Cycle
 
@@ -62,18 +62,11 @@ class NCSharePaging: UIViewController {
         if activity == nil {
             activityEnabled = false
         }
-        if indexPage == NCGlobal.shared.indexPageComments && !commentsEnabled {
-            indexPage = NCGlobal.shared.indexPageActivity
+        if indexPage == .sharing && !sharingEnabled {
+            indexPage = .activity
         }
-        if indexPage == NCGlobal.shared.indexPageSharing && !sharingEnabled {
-            indexPage = NCGlobal.shared.indexPageActivity
-        }
-        if indexPage == NCGlobal.shared.indexPageActivity && !activityEnabled {
-            if sharingEnabled {
-                indexPage = NCGlobal.shared.indexPageSharing
-            } else if commentsEnabled {
-                indexPage = NCGlobal.shared.indexPageComments
-            }
+        if indexPage == .activity && !activityEnabled && sharingEnabled {
+            indexPage = .sharing
         }
         
         // *** MUST BE THE FIRST ONE ***
@@ -112,8 +105,8 @@ class NCSharePaging: UIViewController {
         
         pagingViewController.dataSource = self
         pagingViewController.delegate = self
-        pagingViewController.select(index: indexPage)
-        let pagingIndexItem = self.pagingViewController(pagingViewController, pagingItemAt: indexPage) as! PagingIndexItem
+        pagingViewController.select(index: indexPage.rawValue)
+        let pagingIndexItem = self.pagingViewController(pagingViewController, pagingItemAt: indexPage.rawValue) as! PagingIndexItem
         self.title = pagingIndexItem.title
         
         NotificationCenter.default.addObserver(self, selector: #selector(self.changeTheming), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeTheming), object: nil)
@@ -127,7 +120,9 @@ class NCSharePaging: UIViewController {
             self.dismiss(animated: false, completion: nil)
         }
         
-        pagingViewController.menuItemSize = .fixed(width: self.view.bounds.width/3, height: 40)
+        pagingViewController.menuItemSize = .fixed(
+            width: self.view.bounds.width / CGFloat(NCGlobal.NCSharePagingIndex.allCases.count),
+            height: 40)
     }
     
     override func viewWillDisappear(_ animated: Bool) {
@@ -155,13 +150,14 @@ extension NCSharePaging: PagingViewControllerDelegate {
     
     func pagingViewController(_ pagingViewController: PagingViewController, willScrollToItem pagingItem: PagingItem, startingViewController: UIViewController, destinationViewController: UIViewController) {
         
-        guard let item = pagingItem as? PagingIndexItem else { return }
+        guard
+            let item = pagingItem as? PagingIndexItem,
+            let itemIndex = NCGlobal.NCSharePagingIndex(rawValue: item.index)
+        else { return }
          
-        if item.index == NCGlobal.shared.indexPageActivity && !activityEnabled {
+        if itemIndex == .activity && !activityEnabled {
             pagingViewController.contentInteraction = .none
-        } else if item.index == NCGlobal.shared.indexPageComments && !commentsEnabled {
-            pagingViewController.contentInteraction = .none
-        } else if item.index == NCGlobal.shared.indexPageSharing && !sharingEnabled {
+        } else if itemIndex == .sharing && !sharingEnabled {
             pagingViewController.contentInteraction = .none
         } else {
             self.title = item.title
@@ -176,22 +172,16 @@ extension NCSharePaging: PagingViewControllerDataSource {
     func pagingViewController(_: PagingViewController, viewControllerAt index: Int) -> UIViewController {
     
         let height = pagingViewController.options.menuHeight + NCSharePagingView.HeaderHeight
-        let topSafeArea = UIApplication.shared.keyWindow?.safeAreaInsets.top ?? 0
-        
-        switch index {
-        case NCGlobal.shared.indexPageActivity:
+
+        switch NCGlobal.NCSharePagingIndex(rawValue: index) {
+        case .activity:
             let viewController = UIStoryboard(name: "NCActivity", bundle: nil).instantiateInitialViewController() as! NCActivity
-            viewController.insets = UIEdgeInsets(top: height - topSafeArea, left: 0, bottom: 0, right: 0)
+            viewController.height = height
             viewController.didSelectItemEnable = false
-            viewController.filterFileId = metadata.fileId
-            viewController.objectType = "files"
-            return viewController
-        case NCGlobal.shared.indexPageComments:
-            let viewController = UIStoryboard(name: "NCShare", bundle: nil).instantiateViewController(withIdentifier: "comments") as! NCShareComments
             viewController.metadata = metadata
-            viewController.height = height
+            viewController.objectType = "files"
             return viewController
-        case NCGlobal.shared.indexPageSharing:
+        case .sharing:
             let viewController = UIStoryboard(name: "NCShare", bundle: nil).instantiateViewController(withIdentifier: "sharing") as! NCShare
             viewController.sharingEnabled = sharingEnabled
             viewController.metadata = metadata
@@ -204,12 +194,10 @@ extension NCSharePaging: PagingViewControllerDataSource {
     
     func pagingViewController(_: PagingViewController, pagingItemAt index: Int) -> PagingItem {
         
-        switch index {
-        case NCGlobal.shared.indexPageActivity:
+        switch NCGlobal.NCSharePagingIndex(rawValue: index) {
+        case .activity:
             return PagingIndexItem(index: index, title: NSLocalizedString("_activity_", comment: ""))
-        case NCGlobal.shared.indexPageComments:
-            return PagingIndexItem(index: index, title: NSLocalizedString("_comments_", comment: ""))
-        case NCGlobal.shared.indexPageSharing:
+        case .sharing:
             return PagingIndexItem(index: index, title: NSLocalizedString("_sharing_", comment: ""))
         default:
             return PagingIndexItem(index: index, title: "")
@@ -217,7 +205,7 @@ extension NCSharePaging: PagingViewControllerDataSource {
     }
    
     func numberOfViewControllers(in pagingViewController: PagingViewController) -> Int {
-        return 3
+        return 2
     }
 }
 
@@ -242,13 +230,9 @@ class NCShareHeaderViewController: PagingViewController {
     }
     
     override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        if indexPath.item == NCGlobal.shared.indexPageActivity && !activityEnabled {
+        if NCGlobal.NCSharePagingIndex(rawValue: indexPath.item) == .activity && !activityEnabled {
             return
-        }
-        if indexPath.item == NCGlobal.shared.indexPageComments && !commentsEnabled {
-            return
-        }
-        if indexPath.item == NCGlobal.shared.indexPageSharing && !sharingEnabled {
+        } else if NCGlobal.NCSharePagingIndex(rawValue: indexPath.item) == .sharing && !sharingEnabled {
             return
         }
         super.collectionView(collectionView, didSelectItemAt: indexPath)

+ 1 - 1
iOSClient/Viewer/NCViewerNextcloudText/NCViewerNextcloudText.swift

@@ -159,7 +159,7 @@ class NCViewerNextcloudText: UIViewController, WKNavigationDelegate, WKScriptMes
             }
             
             if message.body as? String == "share" {
-                NCFunctionCenter.shared.openShare(ViewController: self, metadata: metadata, indexPage: 2)
+                NCFunctionCenter.shared.openShare(ViewController: self, metadata: metadata, indexPage: .sharing)
             }
             
             if message.body as? String == "loading" {

+ 1 - 1
iOSClient/Viewer/NCViewerRichdocument/NCViewerRichdocument.swift

@@ -181,7 +181,7 @@ class NCViewerRichdocument: UIViewController, WKNavigationDelegate, WKScriptMess
             }
             
             if message.body as? String == "share" {
-                NCFunctionCenter.shared.openShare(ViewController: self, metadata: metadata, indexPage: 2)
+                NCFunctionCenter.shared.openShare(ViewController: self, metadata: metadata, indexPage: .sharing)
             }
             
             if let param = message.body as? Dictionary<AnyHashable,Any> {