浏览代码

Merge pull request #1856 from nextcloud/fix/trash-select

NCTrash select
Marino Faggiana 3 年之前
父节点
当前提交
aff63982e2

+ 2 - 4
.swiftlint.yml

@@ -11,7 +11,8 @@ empty_count:
 
 
 line_length:
 line_length:
   # warning: 120
   # warning: 120
-  warning: 200
+  warning: 250
+  error: 250
 
 
 type_body_length:
 type_body_length:
   # error: 350
   # error: 350
@@ -117,9 +118,6 @@ excluded:
   - iOSClient/Shares/NCShares.swift
   - iOSClient/Shares/NCShares.swift
   - iOSClient/Transfers/NCTransferCell.swift
   - iOSClient/Transfers/NCTransferCell.swift
   - iOSClient/Transfers/NCTransfers.swift
   - iOSClient/Transfers/NCTransfers.swift
-  - iOSClient/Trash/Cell/NCTrashListCell.swift
-  - iOSClient/Trash/NCTrash.swift
-  - iOSClient/Trash/Section/NCTrashSectionHeaderFooter.swift
   - iOSClient/UserStatus/NCUserStatus.swift
   - iOSClient/UserStatus/NCUserStatus.swift
   - iOSClient/Utility/NCAskAuthorization.swift
   - iOSClient/Utility/NCAskAuthorization.swift
   - iOSClient/Utility/NCContentPresenter.swift
   - iOSClient/Utility/NCContentPresenter.swift

+ 14 - 0
Nextcloud.xcodeproj/project.pbxproj

@@ -27,6 +27,8 @@
 		AF22B218277D196700DAB0CC /* NCShareExtension+Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF22B216277D196700DAB0CC /* NCShareExtension+Files.swift */; };
 		AF22B218277D196700DAB0CC /* NCShareExtension+Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF22B216277D196700DAB0CC /* NCShareExtension+Files.swift */; };
 		AF2D7C7C2742556F00ADF566 /* NCShareLinkCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF2D7C7B2742556F00ADF566 /* NCShareLinkCell.swift */; };
 		AF2D7C7C2742556F00ADF566 /* NCShareLinkCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF2D7C7B2742556F00ADF566 /* NCShareLinkCell.swift */; };
 		AF2D7C7E2742559100ADF566 /* NCShareUserCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF2D7C7D2742559100ADF566 /* NCShareUserCell.swift */; };
 		AF2D7C7E2742559100ADF566 /* NCShareUserCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF2D7C7D2742559100ADF566 /* NCShareUserCell.swift */; };
+		AF3FDCC22796ECC300710F60 /* NCTrash+CollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF3FDCC12796ECC300710F60 /* NCTrash+CollectionView.swift */; };
+		AF3FDCC32796F3FB00710F60 /* NCTrashListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F78ACD4821903F850088454D /* NCTrashListCell.swift */; };
 		AF4BF614275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */; };
 		AF4BF614275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */; };
 		AF4BF615275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */; };
 		AF4BF615275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */; };
 		AF4BF616275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */; };
 		AF4BF616275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */; };
@@ -40,6 +42,8 @@
 		AF4BF62027562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */; };
 		AF4BF62027562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */; };
 		AF4BF62127562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */; };
 		AF4BF62127562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */; };
 		AF730AFA27843E4C00B7520E /* NCShareExtension+NCDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF730AF927843E4C00B7520E /* NCShareExtension+NCDelegate.swift */; };
 		AF730AFA27843E4C00B7520E /* NCShareExtension+NCDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF730AF927843E4C00B7520E /* NCShareExtension+NCDelegate.swift */; };
+		AF7E504E27A2D8FF00B5E4AF /* UIBarButton+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E504D27A2D8FF00B5E4AF /* UIBarButton+Extension.swift */; };
+		AF7E505027A2D92300B5E4AF /* NCSelectableNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF7E504F27A2D92300B5E4AF /* NCSelectableNavigationView.swift */; };
 		AF817EF1274BC781009ED85B /* NCUserBaseUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */; };
 		AF817EF1274BC781009ED85B /* NCUserBaseUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */; };
 		AF817EF2274BC781009ED85B /* NCUserBaseUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */; };
 		AF817EF2274BC781009ED85B /* NCUserBaseUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */; };
 		AF817EF3274BC781009ED85B /* NCUserBaseUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */; };
 		AF817EF3274BC781009ED85B /* NCUserBaseUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */; };
@@ -461,10 +465,13 @@
 		AF22B216277D196700DAB0CC /* NCShareExtension+Files.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCShareExtension+Files.swift"; sourceTree = "<group>"; };
 		AF22B216277D196700DAB0CC /* NCShareExtension+Files.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCShareExtension+Files.swift"; sourceTree = "<group>"; };
 		AF2D7C7B2742556F00ADF566 /* NCShareLinkCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareLinkCell.swift; sourceTree = "<group>"; };
 		AF2D7C7B2742556F00ADF566 /* NCShareLinkCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareLinkCell.swift; sourceTree = "<group>"; };
 		AF2D7C7D2742559100ADF566 /* NCShareUserCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareUserCell.swift; sourceTree = "<group>"; };
 		AF2D7C7D2742559100ADF566 /* NCShareUserCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareUserCell.swift; sourceTree = "<group>"; };
+		AF3FDCC12796ECC300710F60 /* NCTrash+CollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCTrash+CollectionView.swift"; sourceTree = "<group>"; };
 		AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Account.swift"; sourceTree = "<group>"; };
 		AF4BF613275629E20081CEEF /* NCManageDatabase+Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Account.swift"; sourceTree = "<group>"; };
 		AF4BF61827562A4B0081CEEF /* NCManageDatabse+Metadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabse+Metadata.swift"; sourceTree = "<group>"; };
 		AF4BF61827562A4B0081CEEF /* NCManageDatabse+Metadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabse+Metadata.swift"; sourceTree = "<group>"; };
 		AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Activity.swift"; sourceTree = "<group>"; };
 		AF4BF61D27562B3F0081CEEF /* NCManageDatabase+Activity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Activity.swift"; sourceTree = "<group>"; };
 		AF730AF927843E4C00B7520E /* NCShareExtension+NCDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShareExtension+NCDelegate.swift"; sourceTree = "<group>"; };
 		AF730AF927843E4C00B7520E /* NCShareExtension+NCDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCShareExtension+NCDelegate.swift"; sourceTree = "<group>"; };
+		AF7E504D27A2D8FF00B5E4AF /* UIBarButton+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIBarButton+Extension.swift"; sourceTree = "<group>"; };
+		AF7E504F27A2D92300B5E4AF /* NCSelectableNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSelectableNavigationView.swift; sourceTree = "<group>"; };
 		AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUserBaseUrl.swift; sourceTree = "<group>"; };
 		AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCUserBaseUrl.swift; sourceTree = "<group>"; };
 		AF8ED1F92757821000B8DBC4 /* NextcloudTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NextcloudTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		AF8ED1F92757821000B8DBC4 /* NextcloudTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NextcloudTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		AF8ED1FB2757821000B8DBC4 /* NextcloudTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudTests.swift; sourceTree = "<group>"; };
 		AF8ED1FB2757821000B8DBC4 /* NextcloudTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NextcloudTests.swift; sourceTree = "<group>"; };
@@ -1178,6 +1185,7 @@
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
 				F70D7C3525FFBF81002B9E34 /* NCCollectionViewCommon.swift */,
 				F70D7C3525FFBF81002B9E34 /* NCCollectionViewCommon.swift */,
+				AF7E504F27A2D92300B5E4AF /* NCSelectableNavigationView.swift */,
 				F78ACD3F21903CC20088454D /* NCGridCell.swift */,
 				F78ACD3F21903CC20088454D /* NCGridCell.swift */,
 				F78ACD4521903D010088454D /* NCGridCell.xib */,
 				F78ACD4521903D010088454D /* NCGridCell.xib */,
 				F78ACD4121903CE00088454D /* NCListCell.swift */,
 				F78ACD4121903CE00088454D /* NCListCell.swift */,
@@ -1267,6 +1275,7 @@
 				F7632FC32183667400721B71 /* Section */,
 				F7632FC32183667400721B71 /* Section */,
 				F78F74332163757000C2ADAD /* NCTrash.storyboard */,
 				F78F74332163757000C2ADAD /* NCTrash.storyboard */,
 				F78F74352163781100C2ADAD /* NCTrash.swift */,
 				F78F74352163781100C2ADAD /* NCTrash.swift */,
+				AF3FDCC12796ECC300710F60 /* NCTrash+CollectionView.swift */,
 			);
 			);
 			path = Trash;
 			path = Trash;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -1329,6 +1338,7 @@
 				F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */,
 				F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */,
 				F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */,
 				F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */,
 				F79B645F26CA661600838ACA /* UIControl+Extensions.swift */,
 				F79B645F26CA661600838ACA /* UIControl+Extensions.swift */,
+				AF7E504D27A2D8FF00B5E4AF /* UIBarButton+Extension.swift */,
 				F713FEFE2472764000214AF6 /* UIImage+animatedGIF.h */,
 				F713FEFE2472764000214AF6 /* UIImage+animatedGIF.h */,
 				AFD3323F276A02C000F5AE02 /* UIApplication+Orientation.swift */,
 				AFD3323F276A02C000F5AE02 /* UIApplication+Orientation.swift */,
 				F713FEFF2472764100214AF6 /* UIImage+animatedGIF.m */,
 				F713FEFF2472764100214AF6 /* UIImage+animatedGIF.m */,
@@ -2272,6 +2282,7 @@
 				AF4BF61A27562A4B0081CEEF /* NCManageDatabse+Metadata.swift in Sources */,
 				AF4BF61A27562A4B0081CEEF /* NCManageDatabse+Metadata.swift in Sources */,
 				AF4BF615275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
 				AF4BF615275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
 				F798F0E225880608000DAFFD /* UIColor+Extensions.swift in Sources */,
 				F798F0E225880608000DAFFD /* UIColor+Extensions.swift in Sources */,
+				AF3FDCC32796F3FB00710F60 /* NCTrashListCell.swift in Sources */,
 				AF817EF2274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
 				AF817EF2274BC781009ED85B /* NCUserBaseUrl.swift in Sources */,
 				F78295311F962EFA00A572F5 /* NCEndToEndEncryption.m in Sources */,
 				F78295311F962EFA00A572F5 /* NCEndToEndEncryption.m in Sources */,
 				F74AF3A5247FB6AE00AC767B /* NCUtilityFileSystem.swift in Sources */,
 				F74AF3A5247FB6AE00AC767B /* NCUtilityFileSystem.swift in Sources */,
@@ -2380,6 +2391,7 @@
 				F749C10C23C4A5340027D966 /* NCIntroViewController.swift in Sources */,
 				F749C10C23C4A5340027D966 /* NCIntroViewController.swift in Sources */,
 				F710D2022405826100A6033D /* NCViewer+Menu.swift in Sources */,
 				F710D2022405826100A6033D /* NCViewer+Menu.swift in Sources */,
 				F77A697D250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift in Sources */,
 				F77A697D250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift in Sources */,
+				AF7E504E27A2D8FF00B5E4AF /* UIBarButton+Extension.swift in Sources */,
 				F72928A0253B0937009CA4FD /* NCMainNavigationController.swift in Sources */,
 				F72928A0253B0937009CA4FD /* NCMainNavigationController.swift in Sources */,
 				F704B5E92430C0B800632F5F /* NCCreateFormUploadConflictCell.swift in Sources */,
 				F704B5E92430C0B800632F5F /* NCCreateFormUploadConflictCell.swift in Sources */,
 				F72D404923D2082500A97FD0 /* NCViewerNextcloudText.swift in Sources */,
 				F72D404923D2082500A97FD0 /* NCViewerNextcloudText.swift in Sources */,
@@ -2439,6 +2451,7 @@
 				F79B869B265E19D40085C0E0 /* NSMutableAttributedString+Extensions.swift in Sources */,
 				F79B869B265E19D40085C0E0 /* NSMutableAttributedString+Extensions.swift in Sources */,
 				F7B7504B2397D38F004E13EC /* UIImage+Extensions.swift in Sources */,
 				F7B7504B2397D38F004E13EC /* UIImage+Extensions.swift in Sources */,
 				F7EFC0CD256BF8DD00461AAD /* NCUserStatus.swift in Sources */,
 				F7EFC0CD256BF8DD00461AAD /* NCUserStatus.swift in Sources */,
+				AF3FDCC22796ECC300710F60 /* NCTrash+CollectionView.swift in Sources */,
 				F7DFB7F4219C5CA800680748 /* NCCreateFormUploadScanDocument.swift in Sources */,
 				F7DFB7F4219C5CA800680748 /* NCCreateFormUploadScanDocument.swift in Sources */,
 				F70D7C3725FFBF82002B9E34 /* NCCollectionViewCommon.swift in Sources */,
 				F70D7C3725FFBF82002B9E34 /* NCCollectionViewCommon.swift in Sources */,
 				F7020FCE2233D7F700B7297D /* NCCreateFormUploadVoiceNote.swift in Sources */,
 				F7020FCE2233D7F700B7297D /* NCCreateFormUploadVoiceNote.swift in Sources */,
@@ -2474,6 +2487,7 @@
 				F7E4D9C422ED929B003675FD /* NCShareCommentsCell.swift in Sources */,
 				F7E4D9C422ED929B003675FD /* NCShareCommentsCell.swift in Sources */,
 				F717402E24F699A5000C87D5 /* NCFavorite.swift in Sources */,
 				F717402E24F699A5000C87D5 /* NCFavorite.swift in Sources */,
 				AF2D7C7E2742559100ADF566 /* NCShareUserCell.swift in Sources */,
 				AF2D7C7E2742559100ADF566 /* NCShareUserCell.swift in Sources */,
+				AF7E505027A2D92300B5E4AF /* NCSelectableNavigationView.swift in Sources */,
 				F74DE14325135B6800917068 /* NCTransfers.swift in Sources */,
 				F74DE14325135B6800917068 /* NCTransfers.swift in Sources */,
 				AF4BF614275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
 				AF4BF614275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */,
 				AF4BF61E27562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */,
 				AF4BF61E27562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */,

+ 0 - 340
Nextcloud.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

@@ -1,340 +0,0 @@
-{
-  "object": {
-    "pins": [
-      {
-        "package": "abseil",
-        "repositoryURL": "https://github.com/firebase/abseil-cpp-SwiftPM.git",
-        "state": {
-          "branch": null,
-          "revision": "fffc3c2729be5747390ad02d5100291a0d9ad26a",
-          "version": "0.20200225.4"
-        }
-      },
-      {
-        "package": "Alamofire",
-        "repositoryURL": "https://github.com/Alamofire/Alamofire",
-        "state": {
-          "branch": null,
-          "revision": "f82c23a8a7ef8dc1a49a8bfc6a96883e79121864",
-          "version": "5.5.0"
-        }
-      },
-      {
-        "package": "BoringSSL-GRPC",
-        "repositoryURL": "https://github.com/firebase/boringssl-SwiftPM.git",
-        "state": {
-          "branch": null,
-          "revision": "734a8247442fde37df4364c21f6a0085b6a36728",
-          "version": "0.7.2"
-        }
-      },
-      {
-        "package": "ChromaColorPicker",
-        "repositoryURL": "https://github.com/marinofaggiana/ChromaColorPicker",
-        "state": {
-          "branch": "master",
-          "revision": "b1b2c58c3c5617c73863a073cb6393c79195932e",
-          "version": null
-        }
-      },
-      {
-        "package": "CocoaLumberjack",
-        "repositoryURL": "https://github.com/CocoaLumberjack/CocoaLumberjack.git",
-        "state": {
-          "branch": null,
-          "revision": "80ada1f753b0d53d9b57c465936a7c4169375002",
-          "version": "3.7.4"
-        }
-      },
-      {
-        "package": "DropDown",
-        "repositoryURL": "https://github.com/AssistoLab/DropDown",
-        "state": {
-          "branch": "master",
-          "revision": "2ab6f6ce19f0117d1a76ea043ef8f57722c65d16",
-          "version": null
-        }
-      },
-      {
-        "package": "Firebase",
-        "repositoryURL": "https://github.com/firebase/firebase-ios-sdk",
-        "state": {
-          "branch": null,
-          "revision": "5344857522053b5d4403ec8173ec0d23200a97ea",
-          "version": "8.11.0"
-        }
-      },
-      {
-        "package": "FloatingPanel",
-        "repositoryURL": "https://github.com/scenee/FloatingPanel",
-        "state": {
-          "branch": null,
-          "revision": "0fbbbc8d99b4dfe58bb1dd704d14b45f35b46584",
-          "version": "2.5.1"
-        }
-      },
-      {
-        "package": "FSCalendar",
-        "repositoryURL": "https://github.com/WenchaoD/FSCalendar",
-        "state": {
-          "branch": null,
-          "revision": "afaf247581eb1f8aea847f2e6c99c665ae900494",
-          "version": "2.8.3"
-        }
-      },
-      {
-        "package": "GoogleAppMeasurement",
-        "repositoryURL": "https://github.com/google/GoogleAppMeasurement.git",
-        "state": {
-          "branch": null,
-          "revision": "9b2f6aca5b4685c45f9f5481f19bee8e7982c538",
-          "version": "8.9.1"
-        }
-      },
-      {
-        "package": "GoogleDataTransport",
-        "repositoryURL": "https://github.com/google/GoogleDataTransport.git",
-        "state": {
-          "branch": null,
-          "revision": "15ccdfd25ac55b9239b82809531ff26605e7556e",
-          "version": "9.1.2"
-        }
-      },
-      {
-        "package": "GoogleUtilities",
-        "repositoryURL": "https://github.com/google/GoogleUtilities.git",
-        "state": {
-          "branch": null,
-          "revision": "b3bb0c5551fb3f80ca939829639ab5b093edd14f",
-          "version": "7.7.0"
-        }
-      },
-      {
-        "package": "gRPC",
-        "repositoryURL": "https://github.com/firebase/grpc-SwiftPM.git",
-        "state": {
-          "branch": null,
-          "revision": "fb405dd2c7901485f7e158b24e3a0a47e4efd8b5",
-          "version": "1.28.4"
-        }
-      },
-      {
-        "package": "GTMSessionFetcher",
-        "repositoryURL": "https://github.com/google/gtm-session-fetcher.git",
-        "state": {
-          "branch": null,
-          "revision": "bc6a19702ac76ac4e488b68148710eb815f9bc56",
-          "version": "1.7.0"
-        }
-      },
-      {
-        "package": "NCCommunication",
-        "repositoryURL": "https://github.com/nextcloud/ios-communication-library/",
-        "state": {
-          "branch": "develop",
-          "revision": "8afdc5016ccaeb648fcd3baa4091a01b088506a8",
-          "version": null
-        }
-      },
-      {
-        "package": "JGProgressHUD",
-        "repositoryURL": "https://github.com/JonasGessner/JGProgressHUD.git",
-        "state": {
-          "branch": null,
-          "revision": "78d7cd35f1d90ff74fd82e486f2cbe4b24be8cf9",
-          "version": "2.2.0"
-        }
-      },
-      {
-        "package": "leveldb",
-        "repositoryURL": "https://github.com/firebase/leveldb.git",
-        "state": {
-          "branch": null,
-          "revision": "0706abcc6b0bd9cedfbb015ba840e4a780b5159b",
-          "version": "1.22.2"
-        }
-      },
-      {
-        "package": "MarkdownKit",
-        "repositoryURL": "https://github.com/bmoliveira/MarkdownKit",
-        "state": {
-          "branch": null,
-          "revision": "5056f3305d3499f44d8815530d560b87082e0cf5",
-          "version": "1.7.1"
-        }
-      },
-      {
-        "package": "MarqueeLabel",
-        "repositoryURL": "https://github.com/cbpowell/MarqueeLabel",
-        "state": {
-          "branch": null,
-          "revision": "f2c72a5f8568579dade6350dc26a482076d3d346",
-          "version": "4.3.0"
-        }
-      },
-      {
-        "package": "nanopb",
-        "repositoryURL": "https://github.com/firebase/nanopb.git",
-        "state": {
-          "branch": null,
-          "revision": "7ee9ef9f627d85cbe1b8c4f49a3ed26eed216c77",
-          "version": "2.30908.0"
-        }
-      },
-      {
-        "package": "Parchment",
-        "repositoryURL": "https://github.com/rechsteiner/Parchment",
-        "state": {
-          "branch": "main",
-          "revision": "cad6924f8a292eecaedc1bdefb57006f7979b9eb",
-          "version": null
-        }
-      },
-      {
-        "package": "Promises",
-        "repositoryURL": "https://github.com/google/promises.git",
-        "state": {
-          "branch": null,
-          "revision": "611337c330350c9c1823ad6d671e7f936af5ee13",
-          "version": "2.0.0"
-        }
-      },
-      {
-        "package": "QRCodeReader",
-        "repositoryURL": "https://github.com/yannickl/QRCodeReader.swift",
-        "state": {
-          "branch": null,
-          "revision": "5020b5a47199d8ba80c83a4b4fafd70e9dc9dc7f",
-          "version": "10.1.1"
-        }
-      },
-      {
-        "package": "Queuer",
-        "repositoryURL": "https://github.com/FabrizioBrancati/Queuer",
-        "state": {
-          "branch": null,
-          "revision": "52515108d0ac4616d9e15ffcc7ad986e300d31ff",
-          "version": "2.1.1"
-        }
-      },
-      {
-        "package": "QuickLayout",
-        "repositoryURL": "https://github.com/huri000/QuickLayout",
-        "state": {
-          "branch": null,
-          "revision": "6be62decbe508d8fc8f9dbafc349d05bab03c38b",
-          "version": "3.0.1"
-        }
-      },
-      {
-        "package": "RealmDatabase",
-        "repositoryURL": "https://github.com/realm/realm-core",
-        "state": {
-          "branch": null,
-          "revision": "6b81f1a7a2d421f9e0b9e7f04e76bcf736a54409",
-          "version": "11.9.0"
-        }
-      },
-      {
-        "package": "Realm",
-        "repositoryURL": "https://github.com/realm/realm-swift",
-        "state": {
-          "branch": null,
-          "revision": "9dff9f2862240d521ad6ad599541269177ddb993",
-          "version": "10.22.0"
-        }
-      },
-      {
-        "package": "SVGKit",
-        "repositoryURL": "https://github.com/SVGKit/SVGKit.git",
-        "state": {
-          "branch": "3.x",
-          "revision": "e9bc636845fb4d6d5d8e25a9bd08e75c5cf92de9",
-          "version": null
-        }
-      },
-      {
-        "package": "swift-log",
-        "repositoryURL": "https://github.com/apple/swift-log.git",
-        "state": {
-          "branch": null,
-          "revision": "5d66f7ba25daf4f94100e7022febf3c75e37a6c7",
-          "version": "1.4.2"
-        }
-      },
-      {
-        "package": "SwiftProtobuf",
-        "repositoryURL": "https://github.com/apple/swift-protobuf.git",
-        "state": {
-          "branch": null,
-          "revision": "7e2c5f3cbbeea68e004915e3a8961e20bd11d824",
-          "version": "1.18.0"
-        }
-      },
-      {
-        "package": "SwiftEntryKit",
-        "repositoryURL": "https://github.com/huri000/SwiftEntryKit",
-        "state": {
-          "branch": null,
-          "revision": "c2d42574e4fe4e1f9719843f35add7922942a16b",
-          "version": "1.2.7"
-        }
-      },
-      {
-        "package": "SwiftRichString",
-        "repositoryURL": "https://github.com/malcommac/SwiftRichString",
-        "state": {
-          "branch": null,
-          "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": "d7a1d23f04c86c1cd2e8f19247dd15d74e0ea8be",
-          "version": "5.6.0"
-        }
-      },
-      {
-        "package": "TLPhotoPicker",
-        "repositoryURL": "https://github.com/tilltue/TLPhotoPicker",
-        "state": {
-          "branch": null,
-          "revision": "0d0cbbd2d20ed5fd36e5f4052209f5e2d9aaa8b7",
-          "version": "2.1.9"
-        }
-      },
-      {
-        "package": "UICKeyChainStore",
-        "repositoryURL": "https://github.com/kishikawakatsumi/UICKeyChainStore",
-        "state": {
-          "branch": "master",
-          "revision": "db869212bc69b6198a62efe03e2f5fc8e19c6b65",
-          "version": null
-        }
-      },
-      {
-        "package": "XLForm",
-        "repositoryURL": "https://github.com/xmartlabs/XLForm",
-        "state": {
-          "branch": null,
-          "revision": "870afc56602fd518e33d0b271371a2d5acd410ea",
-          "version": "4.3.0"
-        }
-      }
-    ]
-  },
-  "version": 1
-}

+ 1 - 1
iOSClient/Activity/NCActivityTableViewCell.swift

@@ -111,7 +111,7 @@ extension NCActivityTableViewCell: UICollectionViewDelegate {
             var responder: UIResponder? = collectionView
             var responder: UIResponder? = collectionView
             while !(responder is UIViewController) {
             while !(responder is UIViewController) {
                 responder = responder?.next
                 responder = responder?.next
-                if nil == responder {
+                if responder == nil {
                     break
                     break
                 }
                 }
             }
             }

+ 55 - 0
iOSClient/Extensions/UIBarButton+Extension.swift

@@ -0,0 +1,55 @@
+//
+//  UIBarButton+Extension.swift
+//  Nextcloud
+//
+//  Created by Henrik Storch on 27.01.22.
+//  Copyright © 2022 Henrik Storch. 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
+//  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
+
+private var actionKey: Void?
+
+extension UIBarButtonItem {
+    // https://stackoverflow.com/a/36983811/9506784
+    private var _action: () -> Void {
+        get {
+            return objc_getAssociatedObject(self, &actionKey) as? () -> Void ?? { }
+        }
+        set {
+            objc_setAssociatedObject(self, &actionKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+
+    convenience init(title: String?, style: UIBarButtonItem.Style, action: @escaping () -> Void) {
+        self.init(title: title, style: style, target: nil, action: #selector(pressed))
+        self.target = self
+        self._action = action
+    }
+
+    convenience init(image: UIImage?, style: UIBarButtonItem.Style, action: @escaping () -> Void) {
+        self.init(image: image, style: style, target: nil, action: #selector(pressed))
+        self.target = self
+        self._action = action
+    }
+
+    @objc private func pressed(sender: UIBarButtonItem) {
+        _action()
+    }
+}

+ 57 - 89
iOSClient/Main/Collection Common/NCCollectionViewCommon.swift

@@ -22,9 +22,11 @@
 //
 //
 
 
 import UIKit
 import UIKit
+import Realm
 import NCCommunication
 import NCCommunication
 
 
-class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate, NCListCellDelegate, NCGridCellDelegate, NCSectionHeaderMenuDelegate, UIAdaptivePresentationControllerDelegate, NCEmptyDataSetDelegate, UIContextMenuInteractionDelegate, NCAccountRequestDelegate, NCBackgroundImageColorDelegate {
+class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate, NCListCellDelegate, NCGridCellDelegate, NCSectionHeaderMenuDelegate, UIAdaptivePresentationControllerDelegate, NCEmptyDataSetDelegate, UIContextMenuInteractionDelegate, NCAccountRequestDelegate, NCBackgroundImageColorDelegate, NCSelectableNavigationView {
+    var selectableDataSource: [RealmSwiftObject] { dataSource.metadatas }
 
 
     @IBOutlet weak var collectionView: UICollectionView!
     @IBOutlet weak var collectionView: UICollectionView!
 
 
@@ -577,76 +579,63 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
     // MARK: - Layout
     // MARK: - Layout
 
 
     @objc func setNavigationItem() {
     @objc func setNavigationItem() {
-
-        if isEditMode {
-
-            navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "navigationMore"), style: .plain, target: self, action: #selector(tapSelectMenu(sender:)))
-            navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: .plain, target: self, action: #selector(tapSelect(sender:)))
-            navigationItem.title = NSLocalizedString("_selected_", comment: "") + " : \(selectOcId.count)" + " / \(dataSource.metadatas.count)"
-
-        } else {
-
-            navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_select_", comment: ""), style: UIBarButtonItem.Style.plain, target: self, action: #selector(tapSelect(sender:)))
-            navigationItem.leftBarButtonItem = nil
-            navigationItem.title = titleCurrentFolder
-
-            // PROFILE BUTTON
-
-            if layoutKey == NCGlobal.shared.layoutViewFiles {
-                let activeAccount = NCManageDatabase.shared.getActiveAccount()
-
-                let image = NCUtility.shared.loadUserImage(
-                    for: appDelegate.user,
-                       displayName: activeAccount?.displayName,
-                       userBaseUrl: appDelegate)
-
-                let button = UIButton(type: .custom)
-                button.setImage(image, for: .normal)
-
-                if serverUrl == NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account) {
-
-                    var titleButton = "  "
-
-                    if getNavigationTitle() == activeAccount?.alias {
-                        titleButton = ""
-                    } else {
-                        titleButton += activeAccount?.displayName ?? ""
-                    }
-
-                    button.setTitle(titleButton, for: .normal)
-                    button.setTitleColor(.systemBlue, for: .normal)
-                }
-
-                button.semanticContentAttribute = .forceLeftToRight
-                button.sizeToFit()
-                button.action(for: .touchUpInside) { _ in
-
-                    let accounts = NCManageDatabase.shared.getAllAccountOrderAlias()
-                    if accounts.count > 0 {
-
-                        if let vcAccountRequest = UIStoryboard(name: "NCAccountRequest", bundle: nil).instantiateInitialViewController() as? NCAccountRequest {
-
-                            vcAccountRequest.activeAccount = NCManageDatabase.shared.getActiveAccount()
-                            vcAccountRequest.accounts = accounts
-                            vcAccountRequest.enableTimerProgress = false
-                            vcAccountRequest.enableAddAccount = true
-                            vcAccountRequest.delegate = self
-                            vcAccountRequest.dismissDidEnterBackground = true
-
-                            let screenHeighMax = UIScreen.main.bounds.height - (UIScreen.main.bounds.height/5)
-                            let numberCell = accounts.count + 1
-                            let height = min(CGFloat(numberCell * Int(vcAccountRequest.heightCell) + 45), screenHeighMax)
-
-                            let popup = NCPopupViewController(contentController: vcAccountRequest, popupWidth: 300, popupHeight: height)
-
-                            UIApplication.shared.keyWindow?.rootViewController?.present(popup, animated: true)
-                        }
-                    }
+        self.setNavigationHeader()
+        guard !isEditMode, layoutKey == NCGlobal.shared.layoutViewFiles else { return }
+        
+        // PROFILE BUTTON
+        
+        let activeAccount = NCManageDatabase.shared.getActiveAccount()
+        
+        let image = NCUtility.shared.loadUserImage(
+            for: appDelegate.user,
+               displayName: activeAccount?.displayName,
+               userBaseUrl: appDelegate)
+        
+        let button = UIButton(type: .custom)
+        button.setImage(image, for: .normal)
+        
+        if serverUrl == NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account) {
+            
+            var titleButton = "  "
+            
+            if getNavigationTitle() == activeAccount?.alias {
+                titleButton = ""
+            } else {
+                titleButton += activeAccount?.displayName ?? ""
+            }
+            
+            button.setTitle(titleButton, for: .normal)
+            button.setTitleColor(.systemBlue, for: .normal)
+        }
+        
+        button.semanticContentAttribute = .forceLeftToRight
+        button.sizeToFit()
+        button.action(for: .touchUpInside) { _ in
+            
+            let accounts = NCManageDatabase.shared.getAllAccountOrderAlias()
+            if accounts.count > 0 {
+                
+                if let vcAccountRequest = UIStoryboard(name: "NCAccountRequest", bundle: nil).instantiateInitialViewController() as? NCAccountRequest {
+                    
+                    vcAccountRequest.activeAccount = NCManageDatabase.shared.getActiveAccount()
+                    vcAccountRequest.accounts = accounts
+                    vcAccountRequest.enableTimerProgress = false
+                    vcAccountRequest.enableAddAccount = true
+                    vcAccountRequest.delegate = self
+                    vcAccountRequest.dismissDidEnterBackground = true
+                    
+                    let screenHeighMax = UIScreen.main.bounds.height - (UIScreen.main.bounds.height/5)
+                    let numberCell = accounts.count + 1
+                    let height = min(CGFloat(numberCell * Int(vcAccountRequest.heightCell) + 45), screenHeighMax)
+                    
+                    let popup = NCPopupViewController(contentController: vcAccountRequest, popupWidth: 300, popupHeight: height)
+                    
+                    UIApplication.shared.keyWindow?.rootViewController?.present(popup, animated: true)
                 }
                 }
-                navigationItem.setLeftBarButton(UIBarButtonItem(customView: button), animated: true)
-                navigationItem.leftItemsSupplementBackButton = true
             }
             }
         }
         }
+        navigationItem.setLeftBarButton(UIBarButtonItem(customView: button), animated: true)
+        navigationItem.leftItemsSupplementBackButton = true
     }
     }
 
 
     func getNavigationTitle() -> String {
     func getNavigationTitle() -> String {
@@ -729,16 +718,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
 
 
     // MARK: - TAP EVENT
     // MARK: - TAP EVENT
 
 
-    @objc func tapSelect(sender: Any) {
-
-        isEditMode = !isEditMode
-
-        selectOcId.removeAll()
-        setNavigationItem()
-
-        self.collectionView.reloadData()
-    }
-
     func accountRequestChangeAccount(account: String) {
     func accountRequestChangeAccount(account: String) {
         NCManageDatabase.shared.setAccountActive(account)
         NCManageDatabase.shared.setAccountActive(account)
         if let activeAccount = NCManageDatabase.shared.getActiveAccount() {
         if let activeAccount = NCManageDatabase.shared.getActiveAccount() {
@@ -787,11 +766,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS
         sortMenu.toggleMenu(viewController: self, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl)
         sortMenu.toggleMenu(viewController: self, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl)
     }
     }
 
 
-    @objc func tapSelectMenu(sender: Any) {
-
-        toggleMenuSelect()
-    }
-
     func tapMoreHeader(sender: Any) { }
     func tapMoreHeader(sender: Any) { }
 
 
     func tapMoreListItem(with objectId: String, namedButtonMore: String, image: UIImage?, sender: Any) {
     func tapMoreListItem(with objectId: String, namedButtonMore: String, image: UIImage?, sender: Any) {
@@ -1245,12 +1219,6 @@ extension NCCollectionViewCommon: UICollectionViewDelegate {
         navigationController?.pushViewController(viewController, animated: true)
         navigationController?.pushViewController(viewController, animated: true)
     }
     }
 
 
-    func collectionViewSelectAll() {
-        selectOcId = dataSource.metadatas.map({ $0.ocId })
-        navigationItem.title = NSLocalizedString("_selected_", comment: "") + " : \(selectOcId.count)" + " / \(dataSource.metadatas.count)"
-        collectionView.reloadData()
-    }
-
     @available(iOS 13.0, *)
     @available(iOS 13.0, *)
     func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
     func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
 
 

+ 3 - 2
iOSClient/Main/Collection Common/NCGridCell.swift

@@ -23,7 +23,8 @@
 
 
 import UIKit
 import UIKit
 
 
-class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProtocol {
+class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProtocol, NCTrashCell {
+    var labelInfo: UILabel?
 
 
     @IBOutlet weak var imageItem: UIImageView!
     @IBOutlet weak var imageItem: UIImageView!
     @IBOutlet weak var imageSelect: UIImageView!
     @IBOutlet weak var imageSelect: UIImageView!
@@ -35,7 +36,7 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto
     @IBOutlet weak var imageVisualEffect: UIVisualEffectView!
     @IBOutlet weak var imageVisualEffect: UIVisualEffectView!
     @IBOutlet weak var progressView: UIProgressView!
     @IBOutlet weak var progressView: UIProgressView!
 
 
-    private var objectId = ""
+    internal var objectId = ""
     private var user = ""
     private var user = ""
 
 
     weak var delegate: NCGridCellDelegate?
     weak var delegate: NCGridCellDelegate?

+ 226 - 0
iOSClient/Main/Collection Common/NCSelectableNavigationView.swift

@@ -0,0 +1,226 @@
+//
+//  NCSelectableNavigationView.swift
+//  Nextcloud
+//
+//  Created by Henrik Storch on 27.01.22.
+//  Copyright © 2022 Henrik Storch. 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
+//  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
+import Realm
+
+extension RealmSwiftObject {
+    var primaryKeyValue: String? {
+        guard let primaryKeyName = self.objectSchema.primaryKeyProperty?.name else { return nil }
+        return value(forKey: primaryKeyName) as? String
+    }
+}
+
+protocol NCSelectableNavigationView: AnyObject {
+    var appDelegate: AppDelegate { get }
+    var selectableDataSource: [RealmSwiftObject] { get }
+    var collectionView: UICollectionView! { get set }
+    var isEditMode: Bool { get set }
+    var selectOcId: [String] { get set }
+    var titleCurrentFolder: String { get }
+    var navigationItem: UINavigationItem { get }
+
+    func tapSelectMenu()
+    func tapSelect()
+    func setNavigationItem()
+}
+
+extension NCSelectableNavigationView {
+    func setNavigationItem() { setNavigationHeader() }
+
+    func setNavigationHeader() {
+        if isEditMode {
+            navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "navigationMore"), style: .plain, action: tapSelectMenu)
+            navigationItem.leftBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: .plain, action: tapSelect)
+            navigationItem.title = NSLocalizedString("_selected_", comment: "") + " : \(selectOcId.count)" + " / \(selectableDataSource.count)"
+        } else {
+            navigationItem.rightBarButtonItem = UIBarButtonItem(title: NSLocalizedString("_select_", comment: ""), style: UIBarButtonItem.Style.plain, action: tapSelect)
+            navigationItem.leftBarButtonItem = nil
+            navigationItem.title = titleCurrentFolder
+        }
+    }
+
+    func tapSelect() {
+        isEditMode = !isEditMode
+        selectOcId.removeAll()
+        self.setNavigationItem()
+        self.collectionView.reloadData()
+    }
+
+    func collectionViewSelectAll() {
+        selectOcId = selectableDataSource.compactMap({ $0.primaryKeyValue })
+        navigationItem.title = NSLocalizedString("_selected_", comment: "") + " : \(selectOcId.count)" + " / \(selectableDataSource.count)"
+        collectionView.reloadData()
+    }
+}
+
+extension NCSelectableNavigationView where Self: UIViewController {
+    func tapSelectMenu() {
+
+        var actions = [NCMenuAction]()
+
+        //
+        // SELECT ALL
+        //
+        actions.append(
+            NCMenuAction(
+                title: NSLocalizedString("_select_all_", comment: ""),
+                icon: NCUtility.shared.loadImage(named: "checkmark.circle.fill"),
+                action: { _ in
+                    self.collectionViewSelectAll()
+                }
+            )
+        )
+
+        if let trash = self as? NCTrash {
+            actions.append(
+                NCMenuAction(
+                    title: NSLocalizedString("_trash_restore_selected_", comment: ""),
+                    icon: NCUtility.shared.loadImage(named: "restore"),
+                    action: { _ in
+                        self.selectOcId.forEach(trash.restoreItem)
+                        self.tapSelect()
+                    }
+                )
+            )
+            actions.append(
+                NCMenuAction(
+                    title: NSLocalizedString("_trash_delete_selected_", comment: ""),
+                    icon: NCUtility.shared.loadImage(named: "trash"),
+                    action: { _ in
+                        let alert = UIAlertController(title: NSLocalizedString("_trash_delete_selected_", comment: ""), message: "", preferredStyle: .alert)
+                        alert.addAction(UIAlertAction(title: NSLocalizedString("_delete_", comment: ""), style: .destructive, handler: { _ in
+                            self.selectOcId.forEach(trash.deleteItem)
+                            self.tapSelect()
+                        }))
+                        alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: { _ in }))
+                        self.present(alert, animated: true, completion: nil)
+                    }
+                )
+            )
+            return presentMenu(with: actions)
+        }
+
+        //
+        // OPEN IN
+        //
+        actions.append(
+            NCMenuAction(
+                title: NSLocalizedString("_open_in_", comment: ""),
+                icon: NCUtility.shared.loadImage(named: "square.and.arrow.up"),
+                action: { _ in
+                    NCFunctionCenter.shared.openActivityViewController(selectOcId: self.selectOcId)
+                    self.tapSelect()
+                }
+            )
+        )
+
+        //
+        // SAVE TO PHOTO GALLERY
+        //
+        actions.append(
+            NCMenuAction(
+                title: NSLocalizedString("_save_selected_files_", comment: ""),
+                icon: NCUtility.shared.loadImage(named: "square.and.arrow.down"),
+                action: { _ in
+                    self.selectOcId
+                        .compactMap(NCManageDatabase.shared.getMetadataFromOcId)
+                        .filter({ $0.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || $0.classFile == NCCommunicationCommon.typeClassFile.video.rawValue })
+                        .forEach { metadata in
+                            if let metadataMOV = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) {
+                                NCFunctionCenter.shared.saveLivePhoto(metadata: metadata, metadataMOV: metadataMOV)
+                            } else {
+                                if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) {
+                                    NCFunctionCenter.shared.saveAlbum(metadata: metadata)
+                                } else {
+                                    NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorSaveAlbum)
+                                }
+                            }
+                        }
+                    self.tapSelect()
+                }
+            )
+        )
+
+        //
+        // COPY - MOVE
+        //
+        actions.append(
+            NCMenuAction(
+                title: NSLocalizedString("_move_or_copy_selected_files_", comment: ""),
+                icon: NCUtility.shared.loadImage(named: "arrow.up.right.square"),
+                action: { _ in
+                    let meradatasSelect = self.selectOcId.compactMap(NCManageDatabase.shared.getMetadataFromOcId)
+                    if !meradatasSelect.isEmpty {
+                        NCFunctionCenter.shared.openSelectView(items: meradatasSelect, viewController: self)
+                    }
+                    self.tapSelect()
+                }
+            )
+        )
+
+        //
+        // COPY
+        //
+        actions.append(
+            NCMenuAction(
+                title: NSLocalizedString("_copy_file_", comment: ""),
+                icon: NCUtility.shared.loadImage(named: "doc.on.doc"),
+                action: { _ in
+                    self.appDelegate.pasteboardOcIds = self.selectOcId
+                    NCFunctionCenter.shared.copyPasteboard()
+                    self.tapSelect()
+                }
+            )
+        )
+
+        //
+        // DELETE
+        //
+        actions.append(
+            NCMenuAction(
+                title: NSLocalizedString("_delete_selected_files_", comment: ""),
+                icon: NCUtility.shared.loadImage(named: "trash"),
+                action: { _ in
+                    let meradatasSelect = self.selectOcId.compactMap(NCManageDatabase.shared.getMetadataFromOcId)
+
+                    let alertController = UIAlertController(title: "", message: NSLocalizedString("_want_delete_", comment: ""), preferredStyle: .alert)
+                    alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_delete_", comment: ""), style: .default) { (_: UIAlertAction) in
+                        meradatasSelect.forEach({ NCOperationQueue.shared.delete(metadata: $0, onlyLocalCache: false) })
+                        self.tapSelect()
+                    })
+                    alertController.addAction(UIAlertAction(title: NSLocalizedString("_remove_local_file_", comment: ""), style: .default) { (_: UIAlertAction) in
+                        meradatasSelect.forEach({ NCOperationQueue.shared.delete(metadata: $0, onlyLocalCache: true) })
+                        self.tapSelect()
+                    })
+                    alertController.addAction(UIAlertAction(title: NSLocalizedString("_no_delete_", comment: ""), style: .default) { (_: UIAlertAction) in })
+                    self.present(alertController, animated: true, completion: nil)
+                }
+            )
+        )
+
+        presentMenu(with: actions)
+    }
+}

+ 2 - 133
iOSClient/Menu/NCCollectionViewCommon+Menu.swift

@@ -5,9 +5,11 @@
 //  Created by Philippe Weidmann on 24.01.20.
 //  Created by Philippe Weidmann on 24.01.20.
 //  Copyright © 2020 Philippe Weidmann. All rights reserved.
 //  Copyright © 2020 Philippe Weidmann. All rights reserved.
 //  Copyright © 2020 Marino Faggiana All rights reserved.
 //  Copyright © 2020 Marino Faggiana All rights reserved.
+//  Copyright © 2022 Henrik Storch. All rights reserved.
 //
 //
 //  Author Philippe Weidmann
 //  Author Philippe Weidmann
 //  Author Marino Faggiana <marino.faggiana@nextcloud.com>
 //  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
 //  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
 //  it under the terms of the GNU General Public License as published by
@@ -444,137 +446,4 @@ extension NCCollectionViewCommon {
 
 
         presentMenu(with: actions)
         presentMenu(with: actions)
     }
     }
-
-    func toggleMenuSelect() {
-
-        var actions = [NCMenuAction]()
-
-        //
-        // SELECT ALL
-        //
-        actions.append(
-            NCMenuAction(
-                title: NSLocalizedString("_select_all_", comment: ""),
-                icon: NCUtility.shared.loadImage(named: "checkmark.circle.fill"),
-                action: { _ in
-                    self.collectionViewSelectAll()
-                }
-            )
-        )
-
-        //
-        // OPEN IN
-        //
-        actions.append(
-            NCMenuAction(
-                title: NSLocalizedString("_open_in_", comment: ""),
-                icon: NCUtility.shared.loadImage(named: "square.and.arrow.up"),
-                action: { _ in
-                    NCFunctionCenter.shared.openActivityViewController(selectOcId: self.selectOcId)
-                    self.tapSelect(sender: self)
-                }
-            )
-        )
-
-        //
-        // SAVE TO PHOTO GALLERY
-        //
-        actions.append(
-            NCMenuAction(
-                title: NSLocalizedString("_save_selected_files_", comment: ""),
-                icon: NCUtility.shared.loadImage(named: "square.and.arrow.down"),
-                action: { _ in
-                    for ocId in self.selectOcId {
-                        if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
-                            if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue {
-                                if let metadataMOV = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) {
-                                    NCFunctionCenter.shared.saveLivePhoto(metadata: metadata, metadataMOV: metadataMOV)
-                                } else {
-                                    if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) {
-                                        NCFunctionCenter.shared.saveAlbum(metadata: metadata)
-                                    } else {
-                                        NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorSaveAlbum)
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    self.tapSelect(sender: self)
-                }
-            )
-        )
-
-        //
-        // COPY - MOVE
-        //
-        actions.append(
-            NCMenuAction(
-                title: NSLocalizedString("_move_or_copy_selected_files_", comment: ""),
-                icon: NCUtility.shared.loadImage(named: "arrow.up.right.square"),
-                action: { _ in
-                    var meradatasSelect = [tableMetadata]()
-                    for ocId in self.selectOcId {
-                        if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
-                            meradatasSelect.append(metadata)
-                        }
-                    }
-                    if meradatasSelect.count > 0 {
-                        NCFunctionCenter.shared.openSelectView(items: meradatasSelect, viewController: self)
-                    }
-                    self.tapSelect(sender: self)
-                }
-            )
-        )
-
-        //
-        // COPY
-        //
-        actions.append(
-            NCMenuAction(
-                title: NSLocalizedString("_copy_file_", comment: ""),
-                icon: NCUtility.shared.loadImage(named: "doc.on.doc"),
-                action: { _ in
-                    self.appDelegate.pasteboardOcIds.removeAll()
-                    for ocId in self.selectOcId {
-                        self.appDelegate.pasteboardOcIds.append(ocId)
-                    }
-                    NCFunctionCenter.shared.copyPasteboard()
-                    self.tapSelect(sender: self)
-                }
-            )
-        )
-
-        //
-        // DELETE
-        //
-        actions.append(
-            NCMenuAction(
-                title: NSLocalizedString("_delete_selected_files_", comment: ""),
-                icon: NCUtility.shared.loadImage(named: "trash"),
-                action: { _ in
-                    let alertController = UIAlertController(title: "", message: NSLocalizedString("_want_delete_", comment: ""), preferredStyle: .alert)
-                    alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_delete_", comment: ""), style: .default) { (_: UIAlertAction) in
-                        for ocId in self.selectOcId {
-                            if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
-                                NCOperationQueue.shared.delete(metadata: metadata, onlyLocalCache: false)
-                            }
-                        }
-                        self.tapSelect(sender: self)
-                    })
-                    alertController.addAction(UIAlertAction(title: NSLocalizedString("_remove_local_file_", comment: ""), style: .default) { (_: UIAlertAction) in
-                        for ocId in self.selectOcId {
-                            if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) {
-                                NCOperationQueue.shared.delete(metadata: metadata, onlyLocalCache: true)
-                            }
-                        }
-                        self.tapSelect(sender: self)
-                    })
-                    alertController.addAction(UIAlertAction(title: NSLocalizedString("_no_delete_", comment: ""), style: .default) { (_: UIAlertAction) in })
-                    self.present(alertController, animated: true, completion: nil)
-                }
-            )
-        )
-
-        presentMenu(with: actions)
-    }
 }
 }

+ 29 - 71
iOSClient/Menu/NCTrash+Menu.swift

@@ -4,8 +4,10 @@
 //
 //
 //  Created by Marino Faggiana on 03/03/2021.
 //  Created by Marino Faggiana on 03/03/2021.
 //  Copyright © 2021 Marino Faggiana. All rights reserved.
 //  Copyright © 2021 Marino Faggiana. All rights reserved.
+//  Copyright © 2022 Henrik Storch. All rights reserved.
 //
 //
 //  Author Marino Faggiana <marino.faggiana@nextcloud.com>
 //  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
 //  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
 //  it under the terms of the GNU General Public License as published by
@@ -31,96 +33,52 @@ extension NCTrash {
 
 
         var actions: [NCMenuAction] = []
         var actions: [NCMenuAction] = []
 
 
-        if isEditMode {
-            actions.append(
-                NCMenuAction(
-                    title: NSLocalizedString("_trash_delete_selected_", comment: ""),
-                    icon: NCUtility.shared.loadImage(named: "trash"),
-                    action: { _ in
-                        let alert = UIAlertController(title: NSLocalizedString("_trash_delete_selected_", comment: ""), message: "", preferredStyle: .alert)
-                        alert.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .destructive, handler: { _ in
-                            for ocId in self.selectOcId {
-                                self.deleteItem(with: ocId)
-                            }
-                            self.isEditMode = false
-                            self.selectOcId.removeAll()
-                            self.collectionView.reloadData()
-                        }))
-                        alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: { _ in
-                        }))
-                        self.present(alert, animated: true, completion: nil)
-                    }
-                )
-            )
-        } else {
-            actions.append(
-                NCMenuAction(
-                    title: NSLocalizedString("_trash_delete_all_", comment: ""),
-                    icon: NCUtility.shared.loadImage(named: "trash"),
-                    action: { _ in
-                        let alert = UIAlertController(title: NSLocalizedString("_trash_delete_all_", comment: ""), message: "", preferredStyle: .alert)
-                        alert.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .destructive, handler: { _ in
-                            self.emptyTrash()
-                        }))
-                        alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel, handler: { _ in
-                        }))
-                        self.present(alert, animated: true, completion: nil)
-                    }
-                )
-            )
-        }
-
-        presentMenu(with: actions)
-    }
-
-    func toggleMenuMoreList(with objectId: String, image: UIImage?) {
-
-        var actions: [NCMenuAction] = []
-
-        guard let tableTrash = NCManageDatabase.shared.getTrashItem(fileId: objectId, account: appDelegate.account) else {
-            return
-        }
-
-        var iconHeader: UIImage!
-        if let icon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(tableTrash.fileId, etag: tableTrash.fileName)) {
-            iconHeader = icon
-        } else {
-            if tableTrash.directory {
-                iconHeader = UIImage(named: "folder")!.image(color: NCBrandColor.shared.gray, size: 50)
-            } else {
-                iconHeader = UIImage(named: tableTrash.iconName)
-            }
-        }
-
         actions.append(
         actions.append(
             NCMenuAction(
             NCMenuAction(
-                title: tableTrash.trashbinFileName,
-                icon: iconHeader,
-                action: nil
+                title: NSLocalizedString("_trash_restore_all_", comment: ""),
+                icon: NCUtility.shared.loadImage(named: "restore"),
+                action: { _ in
+                    self.datasource.forEach({ self.restoreItem(with: $0.fileId) })
+                }
             )
             )
         )
         )
 
 
         actions.append(
         actions.append(
             NCMenuAction(
             NCMenuAction(
-                title: NSLocalizedString("_delete_", comment: ""),
+                title: NSLocalizedString("_trash_delete_all_", comment: ""),
                 icon: NCUtility.shared.loadImage(named: "trash"),
                 icon: NCUtility.shared.loadImage(named: "trash"),
                 action: { _ in
                 action: { _ in
-                    self.deleteItem(with: objectId)
+                    let alert = UIAlertController(title: NSLocalizedString("_trash_delete_all_description_", comment: ""), message: "", preferredStyle: .alert)
+                    alert.addAction(UIAlertAction(title: NSLocalizedString("_trash_delete_all_", comment: ""), style: .destructive, handler: { _ in
+                        self.emptyTrash()
+                    }))
+                    alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel))
+                    self.present(alert, animated: true, completion: nil)
                 }
                 }
             )
             )
         )
         )
-
-        self.presentMenu(with: actions)
+        presentMenu(with: actions)
     }
     }
 
 
-    func toggleMenuMoreGrid(with objectId: String, namedButtonMore: String, image: UIImage?) {
-
-        var actions: [NCMenuAction] = []
+    func toggleMenuMore(with objectId: String, image: UIImage?, isGridCell: Bool) {
 
 
         guard let tableTrash = NCManageDatabase.shared.getTrashItem(fileId: objectId, account: appDelegate.account) else {
         guard let tableTrash = NCManageDatabase.shared.getTrashItem(fileId: objectId, account: appDelegate.account) else {
             return
             return
         }
         }
 
 
+        guard isGridCell else {
+            let alert = UIAlertController(title: NSLocalizedString("_want_delete_", comment: ""), message: tableTrash.trashbinFileName, preferredStyle: .alert)
+            alert.addAction(UIAlertAction(title: NSLocalizedString("_delete_", comment: ""), style: .destructive, handler: { _ in
+                self.deleteItem(with: objectId)
+            }))
+            alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel))
+            self.present(alert, animated: true, completion: nil)
+
+            return
+        }
+
+        var actions: [NCMenuAction] = []
+
         var iconHeader: UIImage!
         var iconHeader: UIImage!
         if let icon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(tableTrash.fileId, etag: tableTrash.fileName)) {
         if let icon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(tableTrash.fileId, etag: tableTrash.fileName)) {
             iconHeader = icon
             iconHeader = icon

+ 4 - 4
iOSClient/Menu/UIViewController+Menu.swift

@@ -35,7 +35,7 @@ extension UIViewController {
                 url.scheme == "mailto",
                 url.scheme == "mailto",
                 let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
                 let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
             else {
             else {
-                NCContentPresenter.shared.showGenericError(description: "_cannot_send_mail_error_")
+                NCContentPresenter.shared.showError(description: "_cannot_send_mail_error_")
                 return
                 return
             }
             }
             sendEmail(to: components.path)
             sendEmail(to: components.path)
@@ -50,7 +50,7 @@ extension UIViewController {
 
 
         default:
         default:
             guard let url = action.hyperlinkUrl, UIApplication.shared.canOpenURL(url) else {
             guard let url = action.hyperlinkUrl, UIApplication.shared.canOpenURL(url) else {
-                NCContentPresenter.shared.showGenericError(description: "_open_url_error_")
+                NCContentPresenter.shared.showError(description: "_open_url_error_")
                 return
                 return
             }
             }
             UIApplication.shared.open(url, options: [:])
             UIApplication.shared.open(url, options: [:])
@@ -94,7 +94,7 @@ extension UIViewController {
 
 
     func sendEmail(to email: String) {
     func sendEmail(to email: String) {
         guard MFMailComposeViewController.canSendMail() else {
         guard MFMailComposeViewController.canSendMail() else {
-            NCContentPresenter.shared.showGenericError(description: "_cannot_send_mail_error_")
+            NCContentPresenter.shared.showError(description: "_cannot_send_mail_error_")
             return
             return
         }
         }
 
 
@@ -107,7 +107,7 @@ extension UIViewController {
 
 
     func presentMenu(with actions: [NCMenuAction]) {
     func presentMenu(with actions: [NCMenuAction]) {
         guard let menuViewController = NCMenu.makeNCMenu(with: actions) else {
         guard let menuViewController = NCMenu.makeNCMenu(with: actions) else {
-            NCContentPresenter.shared.showGenericError(description: "_internal_generic_error_")
+            NCContentPresenter.shared.showError(description: "_internal_generic_error_")
             return
             return
         }
         }
 
 

+ 2 - 1
iOSClient/Supporting Files/en.lproj/Localizable.strings

@@ -708,10 +708,11 @@
 "_trash_view_"                      = "Deleted files";
 "_trash_view_"                      = "Deleted files";
 "_trash_restore_all_"               = "Restore all files";
 "_trash_restore_all_"               = "Restore all files";
 "_trash_delete_all_"                = "Empty trash";
 "_trash_delete_all_"                = "Empty trash";
+"_trash_delete_all_description_"    = "Do you want to empty the trash?";
 "_trash_no_trash_"                  = "No files deleted";
 "_trash_no_trash_"                  = "No files deleted";
 "_trash_no_trash_description_"      = "You can restore deleted files from here";
 "_trash_no_trash_description_"      = "You can restore deleted files from here";
 "_trash_restore_selected_"          = "Restore selected files";
 "_trash_restore_selected_"          = "Restore selected files";
-"_trash_delete_selected_"           = "Deleted selected files";
+"_trash_delete_selected_"           = "Delete selected files";
 "_manage_file_offline_"             = "Manage offline files";
 "_manage_file_offline_"             = "Manage offline files";
 "_set_available_offline_"           = "Set as available offline";
 "_set_available_offline_"           = "Set as available offline";
 "_remove_available_offline_"        = "Remove as available offline";
 "_remove_available_offline_"        = "Remove as available offline";

+ 45 - 11
iOSClient/Trash/Cell/NCTrashListCell.swift

@@ -4,7 +4,9 @@
 //
 //
 //  Created by Marino Faggiana on 08/10/2018.
 //  Created by Marino Faggiana on 08/10/2018.
 //  Copyright © 2018 Marino Faggiana. All rights reserved.
 //  Copyright © 2018 Marino Faggiana. All rights reserved.
+//  Copyright © 2022 Henrik Storch. All rights reserved.
 //
 //
+//  Author Henrik Storch <henrik.storch@nextcloud.com>
 //  Author Marino Faggiana <marino.faggiana@nextcloud.com>
 //  Author Marino Faggiana <marino.faggiana@nextcloud.com>
 //
 //
 //  This program is free software: you can redistribute it and/or modify
 //  This program is free software: you can redistribute it and/or modify
@@ -23,14 +25,14 @@
 
 
 import UIKit
 import UIKit
 
 
-class NCTrashListCell: UICollectionViewCell {
+class NCTrashListCell: UICollectionViewCell, NCTrashCell {
 
 
     @IBOutlet weak var imageItem: UIImageView!
     @IBOutlet weak var imageItem: UIImageView!
     @IBOutlet weak var imageItemLeftConstraint: NSLayoutConstraint!
     @IBOutlet weak var imageItemLeftConstraint: NSLayoutConstraint!
     @IBOutlet weak var imageSelect: UIImageView!
     @IBOutlet weak var imageSelect: UIImageView!
 
 
     @IBOutlet weak var labelTitle: UILabel!
     @IBOutlet weak var labelTitle: UILabel!
-    @IBOutlet weak var labelInfo: UILabel!
+    @IBOutlet weak var labelInfo: UILabel?
 
 
     @IBOutlet weak var imageRestore: UIImageView!
     @IBOutlet weak var imageRestore: UIImageView!
     @IBOutlet weak var imageMore: UIImageView!
     @IBOutlet weak var imageMore: UIImageView!
@@ -44,13 +46,12 @@ class NCTrashListCell: UICollectionViewCell {
     weak var delegate: NCTrashListCellDelegate?
     weak var delegate: NCTrashListCellDelegate?
 
 
     var objectId = ""
     var objectId = ""
-    var indexPath = IndexPath()
 
 
     override func awakeFromNib() {
     override func awakeFromNib() {
         super.awakeFromNib()
         super.awakeFromNib()
 
 
         imageRestore.image = NCBrandColor.cacheImages.buttonRestore
         imageRestore.image = NCBrandColor.cacheImages.buttonRestore
-        imageMore.image = NCBrandColor.cacheImages.buttonMore
+        imageMore.image = NCUtility.shared.loadImage(named: "trash")
 
 
         imageItem.layer.cornerRadius = 6
         imageItem.layer.cornerRadius = 6
         imageItem.layer.masksToBounds = true
         imageItem.layer.masksToBounds = true
@@ -80,18 +81,26 @@ class NCTrashListCell: UICollectionViewCell {
 
 
     func selected(_ status: Bool) {
     func selected(_ status: Bool) {
         if status {
         if status {
+            var blurEffect: UIVisualEffect?
+            var blurEffectView: UIView?
             imageSelect.image = NCBrandColor.cacheImages.checkedYes
             imageSelect.image = NCBrandColor.cacheImages.checkedYes
-
-            let blurEffect = UIBlurEffect(style: .extraLight)
-            let blurEffectView = UIVisualEffectView(effect: blurEffect)
-            blurEffectView.frame = self.bounds
-            blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
-            blurEffectView.backgroundColor = NCBrandColor.shared.brandElement.withAlphaComponent(0.2)
+            if traitCollection.userInterfaceStyle == .dark {
+                blurEffect = UIBlurEffect(style: .dark)
+                blurEffectView = UIVisualEffectView(effect: blurEffect)
+                blurEffectView?.backgroundColor = .black
+            } else {
+                blurEffect = UIBlurEffect(style: .extraLight)
+                blurEffectView = UIVisualEffectView(effect: blurEffect)
+                blurEffectView?.backgroundColor = .lightGray
+            }
+            blurEffectView?.frame = self.bounds
+            blurEffectView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
             backgroundView = blurEffectView
             backgroundView = blurEffectView
-
+            separator.isHidden = true
         } else {
         } else {
             imageSelect.image = NCBrandColor.cacheImages.checkedNo
             imageSelect.image = NCBrandColor.cacheImages.checkedNo
             backgroundView = nil
             backgroundView = nil
+            separator.isHidden = false
         }
         }
     }
     }
 }
 }
@@ -100,3 +109,28 @@ protocol NCTrashListCellDelegate: AnyObject {
     func tapRestoreListItem(with objectId: String, image: UIImage?, sender: Any)
     func tapRestoreListItem(with objectId: String, image: UIImage?, sender: Any)
     func tapMoreListItem(with objectId: String, image: UIImage?, sender: Any)
     func tapMoreListItem(with objectId: String, image: UIImage?, sender: Any)
 }
 }
+
+protocol NCTrashCell {
+    var objectId: String { get set }
+    var labelTitle: UILabel! { get set }
+    var labelInfo: UILabel? { get set }
+    var imageItem: UIImageView! { get set }
+
+    func selectMode(_ status: Bool)
+    func selected(_ status: Bool)
+}
+extension NCTrashCell {
+    mutating func setupCellUI(tableTrash: tableTrash, image: UIImage?) {
+        self.objectId = tableTrash.fileId
+        self.labelTitle.text = tableTrash.trashbinFileName
+        self.labelTitle.textColor = NCBrandColor.shared.label
+
+        if tableTrash.directory {
+            self.imageItem.image = NCBrandColor.cacheImages.folder
+            self.labelInfo?.text = CCUtility.dateDiff(tableTrash.date as Date)
+        } else {
+            self.imageItem.image = image
+            self.labelInfo?.text = CCUtility.dateDiff(tableTrash.date as Date) + ", " + CCUtility.transformedSize(tableTrash.size)
+        }
+    }
+}

+ 143 - 0
iOSClient/Trash/NCTrash+CollectionView.swift

@@ -0,0 +1,143 @@
+//
+//  NCTrash+CollectionView.swift
+//  Nextcloud
+//
+//  Created by Henrik Storch on 18.01.22.
+//  Copyright © 2022 Henrik Storch. 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
+
+// MARK: UICollectionViewDelegate
+extension NCTrash: UICollectionViewDelegate {
+
+    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+
+        let tableTrash = datasource[indexPath.item]
+
+        guard !isEditMode else {
+            if let index = selectOcId.firstIndex(of: tableTrash.fileId) {
+                selectOcId.remove(at: index)
+            } else {
+                selectOcId.append(tableTrash.fileId)
+            }
+            collectionView.reloadItems(at: [indexPath])
+            self.navigationItem.title = NSLocalizedString("_selected_", comment: "") + " : \(selectOcId.count)" + " / \(datasource.count)"
+            return
+        }
+
+        if tableTrash.directory,
+           let ncTrash: NCTrash = UIStoryboard(name: "NCTrash", bundle: nil).instantiateInitialViewController() as? NCTrash {
+            ncTrash.trashPath = tableTrash.filePath + tableTrash.fileName
+            ncTrash.titleCurrentFolder = tableTrash.trashbinFileName
+            self.navigationController?.pushViewController(ncTrash, animated: true)
+        }
+    }
+}
+
+// MARK: UICollectionViewDataSource
+extension NCTrash: UICollectionViewDataSource {
+
+    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
+
+        if kind == UICollectionView.elementKindSectionHeader {
+
+            guard let trashHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeaderMenu", for: indexPath) as? NCTrashSectionHeaderMenu
+            else { return UICollectionReusableView() }
+
+            if collectionView.collectionViewLayout == gridLayout {
+                trashHeader.buttonSwitch.setImage(UIImage(named: "switchList")?.image(color: NCBrandColor.shared.gray, size: 25), for: .normal)
+            } else {
+                trashHeader.buttonSwitch.setImage(UIImage(named: "switchGrid")?.image(color: NCBrandColor.shared.gray, size: 25), for: .normal)
+            }
+
+            trashHeader.delegate = self
+            trashHeader.backgroundColor = NCBrandColor.shared.systemBackground
+            trashHeader.separator.backgroundColor = NCBrandColor.shared.separator
+            trashHeader.setStatusButton(datasource: datasource)
+            trashHeader.setTitleSorted(datasourceTitleButton: layoutForView?.titleButtonHeader ?? "")
+
+            return trashHeader
+
+        } else {
+            guard let trashFooter = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as? NCTrashSectionFooter
+            else { return UICollectionReusableView() }
+            trashFooter.setTitleLabelFooter(datasource: datasource)
+            return trashFooter
+        }
+    }
+
+    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+        emptyDataSet?.numberOfItemsInSection(datasource.count, section: section)
+        return datasource.count
+    }
+
+    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+
+        let tableTrash = datasource[indexPath.item]
+        var image: UIImage?
+
+        if tableTrash.iconName.isEmpty {
+            image = UIImage(named: "file")
+        } else {
+            image = UIImage(named: tableTrash.iconName)
+        }
+
+        if FileManager().fileExists(atPath: CCUtility.getDirectoryProviderStorageIconOcId(tableTrash.fileId, etag: tableTrash.fileName)) {
+            image = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(tableTrash.fileId, etag: tableTrash.fileName))
+        } else {
+            if tableTrash.hasPreview && !CCUtility.fileProviderStoragePreviewIconExists(tableTrash.fileId, etag: tableTrash.fileName) {
+                downloadThumbnail(with: tableTrash, indexPath: indexPath)
+            }
+        }
+
+        var cell: NCTrashCell & UICollectionViewCell
+
+        if collectionView.collectionViewLayout == listLayout {
+            guard let listCell = collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as? NCTrashListCell else { return UICollectionViewCell() }
+            listCell.delegate = self
+            cell = listCell
+        } else {
+            // GRID
+            guard let gridCell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCGridCell else { return UICollectionViewCell() }
+            gridCell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCBrandColor.cacheImages.buttonMore)
+            gridCell.delegate = self
+            cell = gridCell
+        }
+
+        cell.setupCellUI(tableTrash: tableTrash, image: image)
+        cell.selectMode(isEditMode)
+        if isEditMode {
+            cell.selected(selectOcId.contains(tableTrash.fileId))
+        }
+
+        return cell
+    }
+}
+
+// MARK: UICollectionViewDelegateFlowLayout
+extension NCTrash: UICollectionViewDelegateFlowLayout {
+
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
+        return CGSize(width: collectionView.frame.width, height: highHeader)
+    }
+
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
+        return CGSize(width: collectionView.frame.width, height: highHeader)
+    }
+}

+ 64 - 232
iOSClient/Trash/NCTrash.swift

@@ -4,7 +4,9 @@
 //
 //
 //  Created by Marino Faggiana on 02/10/2018.
 //  Created by Marino Faggiana on 02/10/2018.
 //  Copyright © 2018 Marino Faggiana. All rights reserved.
 //  Copyright © 2018 Marino Faggiana. All rights reserved.
+//  Copyright © 2022 Henrik Storch. All rights reserved.
 //
 //
+//  Author Henrik Storch <henrik.storch@nextcloud.com>
 //  Author Marino Faggiana <marino.faggiana@nextcloud.com>
 //  Author Marino Faggiana <marino.faggiana@nextcloud.com>
 //
 //
 //  This program is free software: you can redistribute it and/or modify
 //  This program is free software: you can redistribute it and/or modify
@@ -21,10 +23,13 @@
 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //
 //
 
 
+import Realm
 import UIKit
 import UIKit
 import NCCommunication
 import NCCommunication
 
 
-class NCTrash: UIViewController, UIGestureRecognizerDelegate, NCTrashListCellDelegate, NCGridCellDelegate, NCTrashSectionHeaderMenuDelegate, NCEmptyDataSetDelegate {
+class NCTrash: UIViewController, NCSelectableNavigationView, NCTrashListCellDelegate, NCTrashSectionHeaderMenuDelegate, NCEmptyDataSetDelegate, NCGridCellDelegate {
+
+    var selectableDataSource: [RealmSwiftObject] { datasource }
 
 
     @IBOutlet weak var collectionView: UICollectionView!
     @IBOutlet weak var collectionView: UICollectionView!
 
 
@@ -33,22 +38,21 @@ class NCTrash: UIViewController, UIGestureRecognizerDelegate, NCTrashListCellDel
     var blinkFileId: String?
     var blinkFileId: String?
     var emptyDataSet: NCEmptyDataSet?
     var emptyDataSet: NCEmptyDataSet?
 
 
-    internal let appDelegate = UIApplication.shared.delegate as! AppDelegate
+    internal let appDelegate = (UIApplication.shared.delegate as? AppDelegate)!
 
 
     internal var isEditMode = false
     internal var isEditMode = false
     internal var selectOcId: [String] = []
     internal var selectOcId: [String] = []
 
 
-    private var datasource: [tableTrash] = []
-    private var layoutForView: NCGlobal.layoutForViewType?
-    private var listLayout: NCListLayout!
-    private var gridLayout: NCGridLayout!
-    private let highHeader: CGFloat = 50
+    var datasource: [tableTrash] = []
+    var layoutForView: NCGlobal.layoutForViewType?
+    var listLayout: NCListLayout!
+    var gridLayout: NCGridLayout!
+    let highHeader: CGFloat = 50
     private let refreshControl = UIRefreshControl()
     private let refreshControl = UIRefreshControl()
 
 
     // MARK: - View Life Cycle
     // MARK: - View Life Cycle
 
 
     override func viewDidLoad() {
     override func viewDidLoad() {
-        super.viewDidLoad()
 
 
         view.backgroundColor = NCBrandColor.shared.systemBackground
         view.backgroundColor = NCBrandColor.shared.systemBackground
         self.navigationController?.navigationBar.prefersLargeTitles = true
         self.navigationController?.navigationBar.prefersLargeTitles = true
@@ -82,7 +86,6 @@ class NCTrash: UIViewController, UIGestureRecognizerDelegate, NCTrashListCellDel
     }
     }
 
 
     override func viewWillAppear(_ animated: Bool) {
     override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
 
 
         appDelegate.activeViewController = self
         appDelegate.activeViewController = self
 
 
@@ -97,16 +100,16 @@ class NCTrash: UIViewController, UIGestureRecognizerDelegate, NCTrashListCellDel
             collectionView.collectionViewLayout = gridLayout
             collectionView.collectionViewLayout = gridLayout
         }
         }
 
 
-        if trashPath == "" {
+        if trashPath.isEmpty {
             guard let userId = (appDelegate.userId as NSString).addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlFragmentAllowed) else { return }
             guard let userId = (appDelegate.userId as NSString).addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlFragmentAllowed) else { return }
             trashPath = appDelegate.urlBase + "/" + NCUtilityFileSystem.shared.getWebDAV(account: appDelegate.account) + "/trashbin/" + userId + "/trash/"
             trashPath = appDelegate.urlBase + "/" + NCUtilityFileSystem.shared.getWebDAV(account: appDelegate.account) + "/trashbin/" + userId + "/trash/"
         }
         }
+        setNavigationItem()
         reloadDataSource()
         reloadDataSource()
     }
     }
 
 
     override func viewDidAppear(_ animated: Bool) {
     override func viewDidAppear(_ animated: Bool) {
         super.viewDidAppear(animated)
         super.viewDidAppear(animated)
-
         loadListingTrash()
         loadListingTrash()
     }
     }
 
 
@@ -125,7 +128,6 @@ class NCTrash: UIViewController, UIGestureRecognizerDelegate, NCTrashListCellDel
     // MARK: - Empty
     // MARK: - Empty
 
 
     func emptyDataSetView(_ view: NCEmptyView) {
     func emptyDataSetView(_ view: NCEmptyView) {
-
         view.emptyImage.image = UIImage(named: "trash")?.image(color: .gray, size: UIScreen.main.bounds.width)
         view.emptyImage.image = UIImage(named: "trash")?.image(color: .gray, size: UIScreen.main.bounds.width)
         view.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "")
         view.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "")
         view.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "")
         view.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "")
@@ -159,13 +161,11 @@ class NCTrash: UIViewController, UIGestureRecognizerDelegate, NCTrashListCellDel
     }
     }
 
 
     func tapOrderHeaderMenu(sender: Any) {
     func tapOrderHeaderMenu(sender: Any) {
-
         let sortMenu = NCSortMenu()
         let sortMenu = NCSortMenu()
         sortMenu.toggleMenu(viewController: self, key: NCGlobal.shared.layoutViewTrash, sortButton: sender as? UIButton, serverUrl: "", hideDirectoryOnTop: true)
         sortMenu.toggleMenu(viewController: self, key: NCGlobal.shared.layoutViewTrash, sortButton: sender as? UIButton, serverUrl: "", hideDirectoryOnTop: true)
     }
     }
 
 
     func tapMoreHeaderMenu(sender: Any) {
     func tapMoreHeaderMenu(sender: Any) {
-
         toggleMenuMoreHeader()
         toggleMenuMoreHeader()
     }
     }
 
 
@@ -173,211 +173,38 @@ class NCTrash: UIViewController, UIGestureRecognizerDelegate, NCTrashListCellDel
 
 
         if !isEditMode {
         if !isEditMode {
             restoreItem(with: ocId)
             restoreItem(with: ocId)
-        } else {
-            let buttonPosition: CGPoint = (sender as! UIButton).convert(CGPoint.zero, to: collectionView)
+        } else if let button = sender as? UIView {
+            let buttonPosition = button.convert(CGPoint.zero, to: collectionView)
             let indexPath = collectionView.indexPathForItem(at: buttonPosition)
             let indexPath = collectionView.indexPathForItem(at: buttonPosition)
             collectionView(self.collectionView, didSelectItemAt: indexPath!)
             collectionView(self.collectionView, didSelectItemAt: indexPath!)
-        }
+        } // else: undefined sender
     }
     }
 
 
     func tapMoreListItem(with objectId: String, image: UIImage?, sender: Any) {
     func tapMoreListItem(with objectId: String, image: UIImage?, sender: Any) {
 
 
         if !isEditMode {
         if !isEditMode {
-            toggleMenuMoreList(with: objectId, image: image)
-        } else {
-            let buttonPosition: CGPoint = (sender as! UIButton).convert(CGPoint.zero, to: collectionView)
+            toggleMenuMore(with: objectId, image: image, isGridCell: false)
+        } else if let button = sender as? UIView {
+            let buttonPosition = button.convert(CGPoint.zero, to: collectionView)
             let indexPath = collectionView.indexPathForItem(at: buttonPosition)
             let indexPath = collectionView.indexPathForItem(at: buttonPosition)
             collectionView(self.collectionView, didSelectItemAt: indexPath!)
             collectionView(self.collectionView, didSelectItemAt: indexPath!)
-        }
+        } // else: undefined sender
     }
     }
 
 
     func tapMoreGridItem(with objectId: String, namedButtonMore: String, image: UIImage?, sender: Any) {
     func tapMoreGridItem(with objectId: String, namedButtonMore: String, image: UIImage?, sender: Any) {
 
 
         if !isEditMode {
         if !isEditMode {
-            toggleMenuMoreGrid(with: objectId, namedButtonMore: namedButtonMore, image: image)
-        } else {
-            let buttonPosition: CGPoint = (sender as! UIButton).convert(CGPoint.zero, to: collectionView)
+            toggleMenuMore(with: objectId, image: image, isGridCell: true)
+        } else if let button = sender as? UIView {
+            let buttonPosition = button.convert(CGPoint.zero, to: collectionView)
             let indexPath = collectionView.indexPathForItem(at: buttonPosition)
             let indexPath = collectionView.indexPathForItem(at: buttonPosition)
             collectionView(self.collectionView, didSelectItemAt: indexPath!)
             collectionView(self.collectionView, didSelectItemAt: indexPath!)
-        }
-    }
-
-    func longPressGridItem(with objectId: String, gestureRecognizer: UILongPressGestureRecognizer) {
-    }
-
-    func longPressMoreGridItem(with objectId: String, namedButtonMore: String, gestureRecognizer: UILongPressGestureRecognizer) {
-    }
-}
-
-// MARK: - Collection View
-
-extension NCTrash: UICollectionViewDelegate {
-
-    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-
-        let tableTrash = datasource[indexPath.item]
-
-        if isEditMode {
-            if let index = selectOcId.firstIndex(of: tableTrash.fileId) {
-                selectOcId.remove(at: index)
-            } else {
-                selectOcId.append(tableTrash.fileId)
-            }
-            collectionView.reloadItems(at: [indexPath])
-            return
-        }
-
-        if tableTrash.directory {
-
-            let ncTrash: NCTrash = UIStoryboard(name: "NCTrash", bundle: nil).instantiateInitialViewController() as! NCTrash
-
-            ncTrash.trashPath = tableTrash.filePath + tableTrash.fileName
-            ncTrash.titleCurrentFolder = tableTrash.trashbinFileName
-
-            self.navigationController?.pushViewController(ncTrash, animated: true)
-        }
-    }
-}
-
-extension NCTrash: UICollectionViewDataSource {
-
-    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
-
-        if kind == UICollectionView.elementKindSectionHeader {
-
-            let trashHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionHeaderMenu", for: indexPath) as! NCTrashSectionHeaderMenu
-
-            if collectionView.collectionViewLayout == gridLayout {
-                trashHeader.buttonSwitch.setImage(UIImage(named: "switchList")?.image(color: NCBrandColor.shared.gray, size: 25), for: .normal)
-            } else {
-                trashHeader.buttonSwitch.setImage(UIImage(named: "switchGrid")?.image(color: NCBrandColor.shared.gray, size: 25), for: .normal)
-            }
-
-            trashHeader.delegate = self
-            trashHeader.backgroundColor = NCBrandColor.shared.systemBackground
-            trashHeader.separator.backgroundColor = NCBrandColor.shared.separator
-            trashHeader.setStatusButton(datasource: datasource)
-            trashHeader.setTitleSorted(datasourceTitleButton: layoutForView?.titleButtonHeader ?? "")
-
-            return trashHeader
-
-        } else {
-
-            let trashFooter = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "sectionFooter", for: indexPath) as! NCTrashSectionFooter
-
-            trashFooter.setTitleLabelFooter(datasource: datasource)
-
-            return trashFooter
-        }
-    }
-
-    func numberOfSections(in collectionView: UICollectionView) -> Int {
-        return 1
-    }
-
-    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        emptyDataSet?.numberOfItemsInSection(datasource.count, section: section)
-        return datasource.count
+        } // else: undefined sender
     }
     }
 
 
-    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+    func longPressGridItem(with objectId: String, gestureRecognizer: UILongPressGestureRecognizer) { }
 
 
-        let tableTrash = datasource[indexPath.item]
-        var image: UIImage?
-
-        if tableTrash.iconName.count > 0 {
-            image = UIImage(named: tableTrash.iconName)
-        } else {
-            image = UIImage(named: "file")
-        }
-
-        if FileManager().fileExists(atPath: CCUtility.getDirectoryProviderStorageIconOcId(tableTrash.fileId, etag: tableTrash.fileName)) {
-            image = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(tableTrash.fileId, etag: tableTrash.fileName))
-        } else {
-            if tableTrash.hasPreview && !CCUtility.fileProviderStoragePreviewIconExists(tableTrash.fileId, etag: tableTrash.fileName) {
-                downloadThumbnail(with: tableTrash, indexPath: indexPath)
-            }
-        }
-
-        if collectionView.collectionViewLayout == listLayout {
-
-            // LIST
-            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as! NCTrashListCell
-            cell.delegate = self
-
-            cell.objectId = tableTrash.fileId
-            cell.indexPath = indexPath
-            cell.labelTitle.text = tableTrash.trashbinFileName
-            cell.labelTitle.textColor = NCBrandColor.shared.label
-
-            if tableTrash.directory {
-                cell.imageItem.image = NCBrandColor.cacheImages.folder
-                cell.labelInfo.text = CCUtility.dateDiff(tableTrash.date as Date)
-            } else {
-                cell.imageItem.image = image
-                cell.labelInfo.text = CCUtility.dateDiff(tableTrash.date as Date) + ", " + CCUtility.transformedSize(tableTrash.size)
-            }
-
-            if isEditMode {
-                cell.selectMode(true)
-                if selectOcId.contains(tableTrash.fileId) {
-                    cell.selected(true)
-                } else {
-                    cell.selected(false)
-                }
-            } else {
-                cell.selectMode(false)
-            }
-
-            return cell
-
-        } else {
-
-            // GRID
-            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as! NCGridCell
-            cell.delegate = self
-
-            cell.fileObjectId = tableTrash.fileId
-            cell.labelTitle.text = tableTrash.trashbinFileName
-            cell.labelTitle.textColor = NCBrandColor.shared.label
-            cell.setButtonMore(named: NCGlobal.shared.buttonMoreMore, image: NCBrandColor.cacheImages.buttonMore)
-
-            if tableTrash.directory {
-                cell.imageItem.image = NCBrandColor.cacheImages.folder
-            } else {
-                cell.imageItem.image = image
-            }
-
-            if isEditMode {
-                cell.imageSelect.isHidden = false
-                if selectOcId.contains(tableTrash.fileId) {
-                    cell.selected(true)
-                } else {
-                    cell.selected(false)
-                }
-            } else {
-                cell.imageSelect.isHidden = true
-                cell.backgroundView = nil
-            }
-            return cell
-        }
-    }
-}
-
-extension NCTrash: UICollectionViewDelegateFlowLayout {
-
-    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
-        return CGSize(width: collectionView.frame.width, height: highHeader)
-    }
-
-    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
-        return CGSize(width: collectionView.frame.width, height: highHeader)
-    }
-}
-
-// MARK: - NC API & Algorithm
-
-extension NCTrash {
+    func longPressMoreGridItem(with objectId: String, namedButtonMore: String, gestureRecognizer: UILongPressGestureRecognizer) { }
 
 
     @objc func reloadDataSource() {
     @objc func reloadDataSource() {
 
 
@@ -391,28 +218,28 @@ extension NCTrash {
 
 
         datasource = tashItems
         datasource = tashItems
         collectionView.reloadData()
         collectionView.reloadData()
-
-        if self.blinkFileId != nil {
-            for item in 0...self.datasource.count-1 {
-                if self.datasource[item].fileId.contains(self.blinkFileId!) {
-                    let indexPath = IndexPath(item: item, section: 0)
-                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
-                        UIView.animate(withDuration: 0.3) {
-                            self.collectionView.scrollToItem(at: indexPath, at: .centeredVertically, animated: false)
-                        } completion: { _ in
-                            if let cell = self.collectionView.cellForItem(at: indexPath) {
-                                cell.backgroundColor = .darkGray
-                                UIView.animate(withDuration: 2) {
-                                    cell.backgroundColor = .clear
-                                    self.blinkFileId = nil
-                                }
-                            }
-                        }
+        guard let blinkFileId = blinkFileId else { return }
+        for itemIx in 0..<self.datasource.count where self.datasource[itemIx].fileId.contains(blinkFileId) {
+            let indexPath = IndexPath(item: itemIx, section: 0)
+            DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
+                UIView.animate(withDuration: 0.3) {
+                    self.collectionView.scrollToItem(at: indexPath, at: .centeredVertically, animated: false)
+                } completion: { _ in
+                    guard let cell = self.collectionView.cellForItem(at: indexPath) else { return }
+                    cell.backgroundColor = .darkGray
+                    UIView.animate(withDuration: 2) {
+                        cell.backgroundColor = .clear
+                        self.blinkFileId = nil
                     }
                     }
                 }
                 }
             }
             }
         }
         }
     }
     }
+}
+
+// MARK: - NC API & Algorithm
+
+extension NCTrash {
 
 
     @objc func loadListingTrash() {
     @objc func loadListingTrash() {
 
 
@@ -422,7 +249,7 @@ extension NCTrash {
                 NCManageDatabase.shared.deleteTrash(filePath: self.trashPath, account: self.appDelegate.account)
                 NCManageDatabase.shared.deleteTrash(filePath: self.trashPath, account: self.appDelegate.account)
                 NCManageDatabase.shared.addTrash(account: account, items: items)
                 NCManageDatabase.shared.addTrash(account: account, items: items)
             } else if errorCode != 0 {
             } else if errorCode != 0 {
-                NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                NCContentPresenter.shared.showError(description: errorDescription, errorCode: errorCode)
             } else {
             } else {
                 print("[LOG] It has been changed user during networking process, error.")
                 print("[LOG] It has been changed user during networking process, error.")
             }
             }
@@ -448,7 +275,7 @@ extension NCTrash {
                 NCManageDatabase.shared.deleteTrash(fileId: fileId, account: account)
                 NCManageDatabase.shared.deleteTrash(fileId: fileId, account: account)
                 self.reloadDataSource()
                 self.reloadDataSource()
             } else if errorCode != 0 {
             } else if errorCode != 0 {
-                NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                NCContentPresenter.shared.showError(description: errorDescription, errorCode: errorCode)
             } else {
             } else {
                 print("[LOG] It has been changed user during networking process, error.")
                 print("[LOG] It has been changed user during networking process, error.")
             }
             }
@@ -463,7 +290,7 @@ extension NCTrash {
             if errorCode == 0 && account == self.appDelegate.account {
             if errorCode == 0 && account == self.appDelegate.account {
                 NCManageDatabase.shared.deleteTrash(fileId: nil, account: self.appDelegate.account)
                 NCManageDatabase.shared.deleteTrash(fileId: nil, account: self.appDelegate.account)
             } else if errorCode != 0 {
             } else if errorCode != 0 {
-                NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                NCContentPresenter.shared.showError(description: errorDescription, errorCode: errorCode)
             } else {
             } else {
                 print("[LOG] It has been changed user during networking process, error.")
                 print("[LOG] It has been changed user during networking process, error.")
             }
             }
@@ -484,7 +311,7 @@ extension NCTrash {
                 NCManageDatabase.shared.deleteTrash(fileId: fileId, account: account)
                 NCManageDatabase.shared.deleteTrash(fileId: fileId, account: account)
                 self.reloadDataSource()
                 self.reloadDataSource()
             } else if errorCode != 0 {
             } else if errorCode != 0 {
-                NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode)
+                NCContentPresenter.shared.showError(description: errorDescription, errorCode: errorCode)
             } else {
             } else {
                 print("[LOG] It has been changed user during networking process, error.")
                 print("[LOG] It has been changed user during networking process, error.")
             }
             }
@@ -496,17 +323,22 @@ extension NCTrash {
         let fileNamePreviewLocalPath = CCUtility.getDirectoryProviderStoragePreviewOcId(tableTrash.fileId, etag: tableTrash.fileName)!
         let fileNamePreviewLocalPath = CCUtility.getDirectoryProviderStoragePreviewOcId(tableTrash.fileId, etag: tableTrash.fileName)!
         let fileNameIconLocalPath = CCUtility.getDirectoryProviderStorageIconOcId(tableTrash.fileId, etag: tableTrash.fileName)!
         let fileNameIconLocalPath = CCUtility.getDirectoryProviderStorageIconOcId(tableTrash.fileId, etag: tableTrash.fileName)!
 
 
-        NCCommunication.shared.downloadPreview(fileNamePathOrFileId: tableTrash.fileId, fileNamePreviewLocalPath: fileNamePreviewLocalPath, widthPreview: NCGlobal.shared.sizePreview, heightPreview: NCGlobal.shared.sizePreview, fileNameIconLocalPath: fileNameIconLocalPath, sizeIcon: NCGlobal.shared.sizeIcon, etag: nil, endpointTrashbin: true) { account, _, imageIcon, _, _, errorCode, _ in
-
-            if errorCode == 0 && imageIcon != nil && account == self.appDelegate.account {
-                if let cell = self.collectionView.cellForItem(at: indexPath) {
-                    if cell is NCTrashListCell {
-                        (cell as! NCTrashListCell).imageItem.image = imageIcon
-                    } else if cell is NCGridCell {
-                        (cell as! NCGridCell).imageItem.image = imageIcon
-                    }
-                }
+        NCCommunication.shared.downloadPreview(
+            fileNamePathOrFileId: tableTrash.fileId,
+            fileNamePreviewLocalPath: fileNamePreviewLocalPath,
+            widthPreview: NCGlobal.shared.sizePreview,
+            heightPreview: NCGlobal.shared.sizePreview,
+            fileNameIconLocalPath: fileNameIconLocalPath,
+            sizeIcon: NCGlobal.shared.sizeIcon,
+            etag: nil,
+            endpointTrashbin: true) { account, _, imageIcon, _, _, errorCode, _ in
+                guard errorCode == 0, let imageIcon = imageIcon, account == self.appDelegate.account,
+                      let cell = self.collectionView.cellForItem(at: indexPath) else { return }
+                if let cell = cell as? NCTrashListCell {
+                    cell.imageItem.image = imageIcon
+                } else if let cell = cell as? NCGridCell {
+                    cell.imageItem.image = imageIcon
+                } // else: undefined cell
             }
             }
-        }
     }
     }
 }
 }

+ 3 - 3
iOSClient/Trash/Section/NCTrashSectionHeaderFooter.swift

@@ -61,7 +61,7 @@ class NCTrashSectionHeaderMenu: UICollectionReusableView {
 
 
     func setStatusButton(datasource: [tableTrash]) {
     func setStatusButton(datasource: [tableTrash]) {
 
 
-        if datasource.count == 0 {
+        if datasource.isEmpty {
             buttonSwitch.isEnabled = false
             buttonSwitch.isEnabled = false
             buttonOrder.isEnabled = false
             buttonOrder.isEnabled = false
             buttonMore.isEnabled = false
             buttonMore.isEnabled = false
@@ -128,9 +128,9 @@ class NCTrashSectionFooter: UICollectionReusableView {
             filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + CCUtility.transformedSize(size)
             filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + CCUtility.transformedSize(size)
         }
         }
 
 
-        if foldersText == "" {
+        if foldersText.isEmpty {
             labelFooter.text = filesText
             labelFooter.text = filesText
-        } else if filesText == "" {
+        } else if filesText.isEmpty {
             labelFooter.text = foldersText
             labelFooter.text = foldersText
         } else {
         } else {
             labelFooter.text = foldersText + ", " + filesText
             labelFooter.text = foldersText + ", " + filesText

+ 2 - 2
iOSClient/Utility/NCContentPresenter.swift

@@ -62,12 +62,12 @@ class NCContentPresenter: NSObject {
 
 
     // MARK: - Message
     // MARK: - Message
 
 
-    @objc func showGenericError(description: String) {
+    @objc func showError(description: String, errorCode: Int = NCGlobal.shared.errorGeneric) {
         messageNotification(
         messageNotification(
             "_error_", description: description,
             "_error_", description: description,
             delay: NCGlobal.shared.dismissAfterSecond,
             delay: NCGlobal.shared.dismissAfterSecond,
             type: .error,
             type: .error,
-            errorCode: NCGlobal.shared.errorGeneric)
+            errorCode: errorCode)
     }
     }
 
 
     @objc func messageNotification(_ title: String, description: String?, delay: TimeInterval, type: messageType, errorCode: Int) {
     @objc func messageNotification(_ title: String, description: String?, delay: TimeInterval, type: messageType, errorCode: Int) {