diff options
author | marinofaggiana <ios@nextcloud.com> | 2022-03-09 12:42:03 +0300 |
---|---|---|
committer | marinofaggiana <ios@nextcloud.com> | 2022-03-09 12:42:03 +0300 |
commit | 7a00076a655182384cf67a31d45924e210f9dacf (patch) | |
tree | b9abe33df3c0b690473a3dbe4b3d7e5ae54956a9 | |
parent | 404d101b24525a693e74bf281e545189483ddab0 (diff) | |
parent | 1dd85fe64c1f3b4beb3cad76f018a222cb330335 (diff) |
Merge branch 'develop'4.3.0
276 files changed, 2265 insertions, 2718 deletions
diff --git a/.swiftlint.yml b/.swiftlint.yml index 6dc7182d3..fd76de49a 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -11,7 +11,8 @@ empty_count: line_length: # warning: 120 - warning: 200 + warning: 250 + error: 250 type_body_length: # error: 350 @@ -117,9 +118,6 @@ excluded: - iOSClient/Shares/NCShares.swift - iOSClient/Transfers/NCTransferCell.swift - iOSClient/Transfers/NCTransfers.swift - - iOSClient/Trash/Cell/NCTrashListCell.swift - - iOSClient/Trash/NCTrash.swift - - iOSClient/Trash/Section/NCTrashSectionHeaderFooter.swift - iOSClient/UserStatus/NCUserStatus.swift - iOSClient/Utility/NCAskAuthorization.swift - iOSClient/Utility/NCContentPresenter.swift diff --git a/Cartfile.resolved b/Cartfile.resolved index c96766238..013ceec7d 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,3 +1,3 @@ github "krzyzanowskim/OpenSSL" "1.1.1300" github "marinofaggiana/KTVHTTPCache" "2.0.2" -github "marinofaggiana/TOPasscodeViewController" "7a750031bb86d9dc9f193bf34a38bbd288b3c4fd" +github "marinofaggiana/TOPasscodeViewController" "a1b9d1058b2648e636525fc368e220a0cfddb42a" diff --git a/File Provider Extension/FileProviderExtension.swift b/File Provider Extension/FileProviderExtension.swift index 16c91c36c..2e003945f 100644 --- a/File Provider Extension/FileProviderExtension.swift +++ b/File Provider Extension/FileProviderExtension.swift @@ -197,7 +197,7 @@ class FileProviderExtension: NSFileProviderExtension, NCNetworkingDelegate { } let tableLocalFile = NCManageDatabase.shared.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) - if tableLocalFile != nil && CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) && tableLocalFile?.etag == metadata.etag { + if tableLocalFile != nil && CCUtility.fileProviderStorageExists(metadata) && tableLocalFile?.etag == metadata.etag { completionHandler(nil) return } diff --git a/File Provider Extension/FileProviderItem.swift b/File Provider Extension/FileProviderItem.swift index 6b872dc2f..ea00cf1a5 100644 --- a/File Provider Extension/FileProviderItem.swift +++ b/File Provider Extension/FileProviderItem.swift @@ -103,7 +103,7 @@ class FileProviderItem: NSObject, NSFileProviderItem { if metadata.directory { return true } - if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + if CCUtility.fileProviderStorageExists(metadata) { return true } else { return false diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index 15de9501f..1e77419f6 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -27,6 +27,10 @@ AF22B218277D196700DAB0CC /* NCShareExtension+Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF22B216277D196700DAB0CC /* NCShareExtension+Files.swift */; }; AF2D7C7C2742556F00ADF566 /* NCShareLinkCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF2D7C7B2742556F00ADF566 /* NCShareLinkCell.swift */; }; AF2D7C7E2742559100ADF566 /* NCShareUserCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF2D7C7D2742559100ADF566 /* NCShareUserCell.swift */; }; + AF36077127BFA4E8001A243D /* ParallelWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF36077027BFA4E8001A243D /* ParallelWorker.swift */; }; + AF36077627BFB019001A243D /* ParallelWorkerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF36077527BFB019001A243D /* ParallelWorkerTest.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 */; }; 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 */; }; @@ -39,7 +43,10 @@ AF4BF61F27562B3F0081CEEF /* 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 */; }; + AF68326A27BE65A90010BF0B /* NCMenuAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF68326927BE65A90010BF0B /* NCMenuAction.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 */; }; AF817EF2274BC781009ED85B /* NCUserBaseUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */; }; AF817EF3274BC781009ED85B /* NCUserBaseUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */; }; @@ -125,6 +132,7 @@ F7239871253D86B600257F49 /* NCEmptyDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7239870253D86B600257F49 /* NCEmptyDataSet.swift */; }; F7239877253D86D300257F49 /* NCEmptyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F7239876253D86D300257F49 /* NCEmptyView.xib */; }; F723B3DD22FC6D1D00301EFE /* NCShareCommentsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F723B3DC22FC6D1C00301EFE /* NCShareCommentsCell.xib */; }; + F72685E727C78E490019EF5E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F72685E927C78E490019EF5E /* InfoPlist.strings */; }; F726EEEC1FED1C820030B9C8 /* NCEndToEndInitialize.swift in Sources */ = {isa = PBXBuildFile; fileRef = F726EEEB1FED1C820030B9C8 /* NCEndToEndInitialize.swift */; }; F72928A0253B0937009CA4FD /* NCMainNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F729289F253B0937009CA4FD /* NCMainNavigationController.swift */; }; F72A47EC2487B06B005AD489 /* NCOperationQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72A47EB2487B06B005AD489 /* NCOperationQueue.swift */; }; @@ -184,9 +192,9 @@ F7581D1A25EFDA61004DC699 /* NCLoginWeb+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7581D1925EFDA60004DC699 /* NCLoginWeb+Menu.swift */; }; F7581D2425EFDDDF004DC699 /* NCMedia+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7581D2325EFDDDF004DC699 /* NCMedia+Menu.swift */; }; F758A01227A7F03E0069468B /* JGProgressHUD in Frameworks */ = {isa = PBXBuildFile; productRef = F758A01127A7F03E0069468B /* JGProgressHUD */; }; - F758B45A212C564000515F55 /* Scan.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F758B457212C564000515F55 /* Scan.storyboard */; }; - F758B45E212C569D00515F55 /* ScanCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F758B45D212C569C00515F55 /* ScanCell.swift */; }; - F758B460212C56A400515F55 /* ScanCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F758B45F212C56A400515F55 /* ScanCollectionView.swift */; }; + F758B45A212C564000515F55 /* NCScan.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F758B457212C564000515F55 /* NCScan.storyboard */; }; + F758B45E212C569D00515F55 /* NCScanCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F758B45D212C569C00515F55 /* NCScanCell.swift */; }; + F758B460212C56A400515F55 /* NCScan.swift in Sources */ = {isa = PBXBuildFile; fileRef = F758B45F212C56A400515F55 /* NCScan.swift */; }; F75A9EE623796C6F0044CFCE /* NCNetworking.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75A9EE523796C6F0044CFCE /* NCNetworking.swift */; }; F75A9EE723796C6F0044CFCE /* NCNetworking.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75A9EE523796C6F0044CFCE /* NCNetworking.swift */; }; F75AC2431F1F62450073EC19 /* NCManageAutoUploadFileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = F75AC2421F1F62450073EC19 /* NCManageAutoUploadFileName.swift */; }; @@ -319,6 +327,7 @@ F7AE00F5230D5F9E007ACF8A /* NCLoginWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AE00F4230D5F9E007ACF8A /* NCLoginWeb.swift */; }; F7AE00F8230E81CB007ACF8A /* NCBrowserWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7AE00F7230E81CB007ACF8A /* NCBrowserWeb.swift */; }; F7AE00FA230E81EB007ACF8A /* NCBrowserWeb.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7AE00F9230E81EB007ACF8A /* NCBrowserWeb.storyboard */; }; + F7B6B70427C4E7FA00A7F6EB /* NCScan+CollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B6B70327C4E7FA00A7F6EB /* NCScan+CollectionView.swift */; }; F7B7504B2397D38F004E13EC /* UIImage+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */; }; F7B8B83025681C3400967775 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = F7B8B82F25681C3400967775 /* GoogleService-Info.plist */; }; F7B8CD91261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B8CD90261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift */; }; @@ -461,10 +470,16 @@ 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>"; }; AF2D7C7D2742559100ADF566 /* NCShareUserCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareUserCell.swift; sourceTree = "<group>"; }; + AF36077027BFA4E8001A243D /* ParallelWorker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParallelWorker.swift; sourceTree = "<group>"; }; + AF36077527BFB019001A243D /* ParallelWorkerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParallelWorkerTest.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>"; }; 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>"; }; + AF68326927BE65A90010BF0B /* NCMenuAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMenuAction.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>"; }; 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>"; }; @@ -582,6 +597,7 @@ F7239876253D86D300257F49 /* NCEmptyView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NCEmptyView.xib; sourceTree = "<group>"; }; F723B3DC22FC6D1C00301EFE /* NCShareCommentsCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCShareCommentsCell.xib; sourceTree = "<group>"; }; F7267A81225DFCE100D6DB7D /* AFNetworking.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AFNetworking.framework; path = Carthage/Build/iOS/AFNetworking.framework; sourceTree = "<group>"; }; + F72685E827C78E490019EF5E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; }; F726EEEB1FED1C820030B9C8 /* NCEndToEndInitialize.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCEndToEndInitialize.swift; sourceTree = "<group>"; }; F728B2BB23E83AD200E12DA0 /* Notification_Service_Extension.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Notification_Service_Extension.plist; sourceTree = "<group>"; }; F728B2BC23E83AD200E12DA0 /* Notification_Service_Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Notification_Service_Extension.entitlements; sourceTree = "<group>"; }; @@ -638,9 +654,9 @@ F755BD9A20594AC7008C5FBB /* NCService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCService.swift; sourceTree = "<group>"; }; F7581D1925EFDA60004DC699 /* NCLoginWeb+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCLoginWeb+Menu.swift"; sourceTree = "<group>"; }; F7581D2325EFDDDF004DC699 /* NCMedia+Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NCMedia+Menu.swift"; sourceTree = "<group>"; }; - F758B457212C564000515F55 /* Scan.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Scan.storyboard; sourceTree = "<group>"; }; - F758B45D212C569C00515F55 /* ScanCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScanCell.swift; sourceTree = "<group>"; }; - F758B45F212C56A400515F55 /* ScanCollectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScanCollectionView.swift; sourceTree = "<group>"; }; + F758B457212C564000515F55 /* NCScan.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCScan.storyboard; sourceTree = "<group>"; }; + F758B45D212C569C00515F55 /* NCScanCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCScanCell.swift; sourceTree = "<group>"; }; + F758B45F212C56A400515F55 /* NCScan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCScan.swift; sourceTree = "<group>"; }; F75A9EE523796C6F0044CFCE /* NCNetworking.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCNetworking.swift; sourceTree = "<group>"; }; F75AC2421F1F62450073EC19 /* NCManageAutoUploadFileName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCManageAutoUploadFileName.swift; sourceTree = "<group>"; }; F75B0ABC244C4DBB00E58DCA /* NCFunctionCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCFunctionCenter.swift; sourceTree = "<group>"; }; @@ -755,6 +771,48 @@ F7A321AC1E9E6AD50069AD1B /* CCAdvanced.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCAdvanced.m; sourceTree = "<group>"; }; F7A80BC8252624C100C7CD01 /* NCFileViewInFolder.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCFileViewInFolder.storyboard; sourceTree = "<group>"; }; F7A80BC9252624C100C7CD01 /* NCFileViewInFolder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCFileViewInFolder.swift; sourceTree = "<group>"; }; + F7AA41B827C7CF4600494705 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41B927C7CF4B00494705 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41BA27C7CF5000494705 /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41BB27C7CF5100494705 /* cs-CZ */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "cs-CZ"; path = "cs-CZ.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41BC27C7CF5300494705 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41BD27C7CF5400494705 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41BE27C7CF5600494705 /* ja-JP */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ja-JP"; path = "ja-JP.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41BF27C7CF5700494705 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41C027C7CF5800494705 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41C127C7CF5900494705 /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = gl; path = gl.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41C227C7CF5A00494705 /* ka-GE */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ka-GE"; path = "ka-GE.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41C327C7CF5B00494705 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41C427C7CF5C00494705 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41C527C7CF5D00494705 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41C627C7CF5E00494705 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41C727C7CF6000494705 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41C827C7CF6200494705 /* es-HN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-HN"; path = "es-HN.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41C927C7CF6300494705 /* es-DO */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-DO"; path = "es-DO.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41CA27C7CF6400494705 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41CB27C7CF6500494705 /* nb-NO */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "nb-NO"; path = "nb-NO.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41CC27C7CF6600494705 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41CD27C7CF6700494705 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41CE27C7CF6800494705 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41CF27C7CF6900494705 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41D027C7CF6900494705 /* sk-SK */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sk-SK"; path = "sk-SK.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41D127C7CF6A00494705 /* sr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sr; path = sr.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41D227C7CF6C00494705 /* es-CO */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CO"; path = "es-CO.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41D327C7CF6D00494705 /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41D427C7CF6E00494705 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41D527C7CF6F00494705 /* es-CR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CR"; path = "es-CR.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41D627C7CF7100494705 /* es-GT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-GT"; path = "es-GT.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41D727C7CF7200494705 /* es-SV */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-SV"; path = "es-SV.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41D827C7CF7300494705 /* es-EC */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-EC"; path = "es-EC.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41D927C7CF7500494705 /* es-PR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-PR"; path = "es-PR.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41DA27C7CF7600494705 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + F7AA41DB27C7CF7800494705 /* es-UY */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-UY"; path = "es-UY.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41DC27C7CF7900494705 /* es-PE */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-PE"; path = "es-PE.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41DD27C7CF7B00494705 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41DE27C7CF7D00494705 /* es-PA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-PA"; path = "es-PA.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41DF27C7CF7E00494705 /* es-PY */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-PY"; path = "es-PY.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41E027C7CF8000494705 /* es-NI */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-NI"; path = "es-NI.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; + F7AA41E127C7CF8100494705 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; F7ACE4291BAC0268006C0017 /* Acknowledgements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Acknowledgements.h; sourceTree = "<group>"; }; F7ACE42A1BAC0268006C0017 /* Acknowledgements.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Acknowledgements.m; sourceTree = "<group>"; }; F7ACE42B1BAC0268006C0017 /* Acknowledgements.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; path = Acknowledgements.rtf; sourceTree = "<group>"; }; @@ -770,6 +828,7 @@ F7AF7632246BEDFE00B86E3C /* TOPasscodeViewController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TOPasscodeViewController.framework; path = Carthage/Build/iOS/TOPasscodeViewController.framework; sourceTree = "<group>"; }; F7B1076C25D3CF2800E72DE2 /* BackgroundTasks.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BackgroundTasks.framework; path = System/Library/Frameworks/BackgroundTasks.framework; sourceTree = SDKROOT; }; F7B1A7761EBB3C8000BFB6D1 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; }; + F7B6B70327C4E7FA00A7F6EB /* NCScan+CollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCScan+CollectionView.swift"; sourceTree = "<group>"; }; F7B7504A2397D38E004E13EC /* UIImage+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extensions.swift"; sourceTree = "<group>"; }; F7B8B82F25681C3400967775 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "GoogleService-Info.plist"; sourceTree = SOURCE_ROOT; }; F7B8CD90261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCNetworkingChunkedUpload.swift; sourceTree = "<group>"; }; @@ -937,6 +996,7 @@ children = ( 3704EB2923D5A58400455C5B /* NCMenu.storyboard */, 371B5A2D23D0B04500FAFAE9 /* NCMenu.swift */, + AF68326927BE65A90010BF0B /* NCMenuAction.swift */, AF935066276B84E700BD078F /* NCMenu+FloatingPanel.swift */, 3781B9AF23DB2B7E006B4B1D /* AppDelegate+Menu.swift */, 8491B1CC273BBA82001C8C5B /* UIViewController+Menu.swift */, @@ -954,6 +1014,7 @@ isa = PBXGroup; children = ( AF8ED2022757822700B8DBC4 /* NCGlobalTests.swift */, + AF36077527BFB019001A243D /* ParallelWorkerTest.swift */, AF8ED1FB2757821000B8DBC4 /* NextcloudTests.swift */, ); path = NextcloudTests; @@ -1118,6 +1179,7 @@ isa = PBXGroup; children = ( F7E70DE91A24DE4100E1B66A /* Localizable.strings */, + F72685E927C78E490019EF5E /* InfoPlist.strings */, ); name = Localizations; sourceTree = "<group>"; @@ -1167,9 +1229,10 @@ F758B41E212C516300515F55 /* ScanDocument */ = { isa = PBXGroup; children = ( - F758B457212C564000515F55 /* Scan.storyboard */, - F758B45D212C569C00515F55 /* ScanCell.swift */, - F758B45F212C56A400515F55 /* ScanCollectionView.swift */, + F758B457212C564000515F55 /* NCScan.storyboard */, + F758B45D212C569C00515F55 /* NCScanCell.swift */, + F758B45F212C56A400515F55 /* NCScan.swift */, + F7B6B70327C4E7FA00A7F6EB /* NCScan+CollectionView.swift */, ); path = ScanDocument; sourceTree = "<group>"; @@ -1178,6 +1241,7 @@ isa = PBXGroup; children = ( F70D7C3525FFBF81002B9E34 /* NCCollectionViewCommon.swift */, + AF7E504F27A2D92300B5E4AF /* NCSelectableNavigationView.swift */, F78ACD3F21903CC20088454D /* NCGridCell.swift */, F78ACD4521903D010088454D /* NCGridCell.xib */, F78ACD4121903CE00088454D /* NCListCell.swift */, @@ -1267,6 +1331,7 @@ F7632FC32183667400721B71 /* Section */, F78F74332163757000C2ADAD /* NCTrash.storyboard */, F78F74352163781100C2ADAD /* NCTrash.swift */, + AF3FDCC12796ECC300710F60 /* NCTrash+CollectionView.swift */, ); path = Trash; sourceTree = "<group>"; @@ -1329,6 +1394,7 @@ F7A0D1342591FBC5008F8A13 /* String+Extensions.swift */, F70CEF5523E9C7E50007035B /* UIColor+Extensions.swift */, F79B645F26CA661600838ACA /* UIControl+Extensions.swift */, + AF7E504D27A2D8FF00B5E4AF /* UIBarButton+Extension.swift */, F713FEFE2472764000214AF6 /* UIImage+animatedGIF.h */, AFD3323F276A02C000F5AE02 /* UIApplication+Orientation.swift */, F713FEFF2472764100214AF6 /* UIImage+animatedGIF.m */, @@ -1439,6 +1505,7 @@ F70BFC7320E0FA7C00C67599 /* NCUtility.swift */, AF817EF0274BC781009ED85B /* NCUserBaseUrl.swift */, F74AF3A3247FB6AE00AC767B /* NCUtilityFileSystem.swift */, + AF36077027BFA4E8001A243D /* ParallelWorker.swift */, F702F2FC25EE5D2C008F8E80 /* NYMnemonic */, ); path = Utility; @@ -1922,7 +1989,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1310; - LastUpgradeCheck = 1250; + LastUpgradeCheck = 1320; ORGANIZATIONNAME = "Marino Faggiana"; TargetAttributes = { 2C33C47E23E2C475005F963B = { @@ -2105,13 +2172,14 @@ F77444F622281649000D5EB0 /* NCGridMediaCell.xib in Resources */, F78ACD4421903CF20088454D /* NCListCell.xib in Resources */, F78ACD4621903D010088454D /* NCGridCell.xib in Resources */, + F72685E727C78E490019EF5E /* InfoPlist.strings in Resources */, F769453C22E9CFFF000A798A /* NCShareUserCell.xib in Resources */, F7A80BCA252624C100C7CD01 /* NCFileViewInFolder.storyboard in Resources */, F76D3CF52428D0C1005DFA87 /* NCViewerPDF.storyboard in Resources */, F700222C1EC479840080073F /* Custom.xcassets in Resources */, F702F2F125EE5CDB008F8E80 /* NCLogin.storyboard in Resources */, F723985C253C95CE00257F49 /* NCViewerRichdocument.storyboard in Resources */, - F758B45A212C564000515F55 /* Scan.storyboard in Resources */, + F758B45A212C564000515F55 /* NCScan.storyboard in Resources */, F70D87CF25EE6E58008CBBBD /* NCRenameFile.storyboard in Resources */, F765F73225237E3F00391DBE /* NCRecent.storyboard in Resources */, F78F74342163757000C2ADAD /* NCTrash.storyboard in Resources */, @@ -2247,6 +2315,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + AF36077627BFB019001A243D /* ParallelWorkerTest.swift in Sources */, AF8ED1FC2757821000B8DBC4 /* NextcloudTests.swift in Sources */, AF8ED2032757822700B8DBC4 /* NCGlobalTests.swift in Sources */, ); @@ -2272,6 +2341,7 @@ AF4BF61A27562A4B0081CEEF /* NCManageDatabse+Metadata.swift in Sources */, AF4BF615275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */, F798F0E225880608000DAFFD /* UIColor+Extensions.swift in Sources */, + AF3FDCC32796F3FB00710F60 /* NCTrashListCell.swift in Sources */, AF817EF2274BC781009ED85B /* NCUserBaseUrl.swift in Sources */, F78295311F962EFA00A572F5 /* NCEndToEndEncryption.m in Sources */, F74AF3A5247FB6AE00AC767B /* NCUtilityFileSystem.swift in Sources */, @@ -2374,12 +2444,14 @@ AF4BF61927562A4B0081CEEF /* NCManageDatabse+Metadata.swift in Sources */, F78A18B623CDD07D00F681F3 /* NCViewerRichWorkspaceWebView.swift in Sources */, F716B75F26F09DF600D37EFC /* NCKTVHTTPCache.swift in Sources */, + AF36077127BFA4E8001A243D /* ParallelWorker.swift in Sources */, F75A9EE623796C6F0044CFCE /* NCNetworking.swift in Sources */, - F758B460212C56A400515F55 /* ScanCollectionView.swift in Sources */, + F758B460212C56A400515F55 /* NCScan.swift in Sources */, F78ACD52219046DC0088454D /* NCSectionHeaderFooter.swift in Sources */, F749C10C23C4A5340027D966 /* NCIntroViewController.swift in Sources */, F710D2022405826100A6033D /* NCViewer+Menu.swift in Sources */, F77A697D250A0FBC00FF1708 /* NCCollectionViewCommon+Menu.swift in Sources */, + AF7E504E27A2D8FF00B5E4AF /* UIBarButton+Extension.swift in Sources */, F72928A0253B0937009CA4FD /* NCMainNavigationController.swift in Sources */, F704B5E92430C0B800632F5F /* NCCreateFormUploadConflictCell.swift in Sources */, F72D404923D2082500A97FD0 /* NCViewerNextcloudText.swift in Sources */, @@ -2395,6 +2467,7 @@ F78ACD4A21903F850088454D /* NCTrashListCell.swift in Sources */, F7B8CD91261AF3F7007C1359 /* NCNetworkingChunkedUpload.swift in Sources */, F760329F252F0F8E0015A421 /* NCTransferCell.swift in Sources */, + AF68326A27BE65A90010BF0B /* NCMenuAction.swift in Sources */, F7682FE023C36B0500983A04 /* NCMainTabBar.swift in Sources */, F7A0D1352591FBC5008F8A13 /* String+Extensions.swift in Sources */, F77B0E5F1D118A16002130FE /* NCSettings.m in Sources */, @@ -2414,6 +2487,7 @@ 3781B9B023DB2B7E006B4B1D /* AppDelegate+Menu.swift in Sources */, F73D5E47246DE09200DF6467 /* NCElementsJSON.swift in Sources */, F710D1F52405770F00A6033D /* NCViewerPDF.swift in Sources */, + F7B6B70427C4E7FA00A7F6EB /* NCScan+CollectionView.swift in Sources */, F7501C332212E57500FB1415 /* NCMedia.swift in Sources */, F70BFC7420E0FA7D00C67599 /* NCUtility.swift in Sources */, F79EDAA526B004980007D134 /* NCPlayer.swift in Sources */, @@ -2439,6 +2513,7 @@ F79B869B265E19D40085C0E0 /* NSMutableAttributedString+Extensions.swift in Sources */, F7B7504B2397D38F004E13EC /* UIImage+Extensions.swift in Sources */, F7EFC0CD256BF8DD00461AAD /* NCUserStatus.swift in Sources */, + AF3FDCC22796ECC300710F60 /* NCTrash+CollectionView.swift in Sources */, F7DFB7F4219C5CA800680748 /* NCCreateFormUploadScanDocument.swift in Sources */, F70D7C3725FFBF82002B9E34 /* NCCollectionViewCommon.swift in Sources */, F7020FCE2233D7F700B7297D /* NCCreateFormUploadVoiceNote.swift in Sources */, @@ -2466,7 +2541,7 @@ F70CEF5623E9C7E50007035B /* UIColor+Extensions.swift in Sources */, F75AC2431F1F62450073EC19 /* NCManageAutoUploadFileName.swift in Sources */, F7C7B489245EBA4100D93E60 /* NCViewerQuickLook.swift in Sources */, - F758B45E212C569D00515F55 /* ScanCell.swift in Sources */, + F758B45E212C569D00515F55 /* NCScanCell.swift in Sources */, F7581D1A25EFDA61004DC699 /* NCLoginWeb+Menu.swift in Sources */, F77B0ED11D118A16002130FE /* Acknowledgements.m in Sources */, F70D8D8124A4A9BF000A5756 /* NCNetworkingProcessUpload.swift in Sources */, @@ -2474,6 +2549,7 @@ F7E4D9C422ED929B003675FD /* NCShareCommentsCell.swift in Sources */, F717402E24F699A5000C87D5 /* NCFavorite.swift in Sources */, AF2D7C7E2742559100ADF566 /* NCShareUserCell.swift in Sources */, + AF7E505027A2D92300B5E4AF /* NCSelectableNavigationView.swift in Sources */, F74DE14325135B6800917068 /* NCTransfers.swift in Sources */, AF4BF614275629E20081CEEF /* NCManageDatabase+Account.swift in Sources */, AF4BF61E27562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */, @@ -2506,6 +2582,57 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ + F72685E927C78E490019EF5E /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + F72685E827C78E490019EF5E /* en */, + F7AA41B827C7CF4600494705 /* ca */, + F7AA41B927C7CF4B00494705 /* zh-Hans */, + F7AA41BA27C7CF5000494705 /* zh-Hant-TW */, + F7AA41BB27C7CF5100494705 /* cs-CZ */, + F7AA41BC27C7CF5300494705 /* da */, + F7AA41BD27C7CF5400494705 /* nl */, + F7AA41BE27C7CF5600494705 /* ja-JP */, + F7AA41BF27C7CF5700494705 /* fr */, + F7AA41C027C7CF5800494705 /* en-GB */, + F7AA41C127C7CF5900494705 /* gl */, + F7AA41C227C7CF5A00494705 /* ka-GE */, + F7AA41C327C7CF5B00494705 /* de */, + F7AA41C427C7CF5C00494705 /* hu */, + F7AA41C527C7CF5D00494705 /* is */, + F7AA41C627C7CF5E00494705 /* it */, + F7AA41C727C7CF6000494705 /* tr */, + F7AA41C827C7CF6200494705 /* es-HN */, + F7AA41C927C7CF6300494705 /* es-DO */, + F7AA41CA27C7CF6400494705 /* ko */, + F7AA41CB27C7CF6500494705 /* nb-NO */, + F7AA41CC27C7CF6600494705 /* pl */, + F7AA41CD27C7CF6700494705 /* pt-BR */, + F7AA41CE27C7CF6800494705 /* pt-PT */, + F7AA41CF27C7CF6900494705 /* ru */, + F7AA41D027C7CF6900494705 /* sk-SK */, + F7AA41D127C7CF6A00494705 /* sr */, + F7AA41D227C7CF6C00494705 /* es-CO */, + F7AA41D327C7CF6D00494705 /* es-CL */, + F7AA41D427C7CF6E00494705 /* es */, + F7AA41D527C7CF6F00494705 /* es-CR */, + F7AA41D627C7CF7100494705 /* es-GT */, + F7AA41D727C7CF7200494705 /* es-SV */, + F7AA41D827C7CF7300494705 /* es-EC */, + F7AA41D927C7CF7500494705 /* es-PR */, + F7AA41DA27C7CF7600494705 /* sv */, + F7AA41DB27C7CF7800494705 /* es-UY */, + F7AA41DC27C7CF7900494705 /* es-PE */, + F7AA41DD27C7CF7B00494705 /* es-419 */, + F7AA41DE27C7CF7D00494705 /* es-PA */, + F7AA41DF27C7CF7E00494705 /* es-PY */, + F7AA41E027C7CF8000494705 /* es-NI */, + F7AA41E127C7CF8100494705 /* es-MX */, + ); + name = InfoPlist.strings; + path = "Supporting Files"; + sourceTree = "<group>"; + }; F7E70DE91A24DE4100E1B66A /* Localizable.strings */ = { isa = PBXVariantGroup; children = ( @@ -2563,102 +2690,34 @@ 2C33C48723E2C475005F963B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = NO; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; - CLANG_WARN_STRICT_PROTOTYPES = NO; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/iOSClient/Brand/Notification_Service_Extension.entitlements"; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = 6JLRKY9ZV7; - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", EXTENSION, EXTENSION_NOTIFICATION_SERVICE, ); - HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/Notification_Service_Extension.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - LIBRARY_SEARCH_PATHS = ""; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.Notification-Service-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_NOTIFICATION_SERVICE"; SWIFT_OBJC_BRIDGING_HEADER = "Notification Service Extension/Notification_Service_Extension-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 2C33C48823E2C475005F963B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = NO; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; - CLANG_WARN_STRICT_PROTOTYPES = NO; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/iOSClient/Brand/Notification_Service_Extension.entitlements"; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = 6JLRKY9ZV7; - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", EXTENSION, EXTENSION_NOTIFICATION_SERVICE, ); - HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/Notification_Service_Extension.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - LIBRARY_SEARCH_PATHS = ""; - MTL_FAST_MATH = YES; - OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.Notification-Service-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_NOTIFICATION_SERVICE"; SWIFT_OBJC_BRIDGING_HEADER = "Notification Service Extension/Notification_Service_Extension-Bridging-Header.h"; - SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; @@ -2666,38 +2725,11 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_STYLE = Automatic; - DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = 6JLRKY9ZV7; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Nextcloud.app/Nextcloud"; }; name = Debug; @@ -2706,31 +2738,11 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_STYLE = Automatic; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = 6JLRKY9ZV7; - GCC_C_LANGUAGE_STANDARD = gnu11; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; + ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.NextcloudTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_EMIT_LOC_STRINGS = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Nextcloud.app/Nextcloud"; }; name = Release; @@ -2738,301 +2750,107 @@ F7145A261D12E3B700CAFEEC /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; - CLANG_ENABLE_MODULES = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; - CLANG_WARN_STRICT_PROTOTYPES = NO; CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/Share.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = 6JLRKY9ZV7; - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", EXTENSION, EXTENSION_SHARE, ); - HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/Share.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - LIBRARY_SEARCH_PATHS = ""; - OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Share; PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_SHARE"; SWIFT_OBJC_BRIDGING_HEADER = "Share/Share-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - USE_HEADERMAP = YES; }; name = Debug; }; F7145A271D12E3B700CAFEEC /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; - CLANG_ENABLE_MODULES = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; - CLANG_WARN_STRICT_PROTOTYPES = NO; CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/Share.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = 6JLRKY9ZV7; - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", EXTENSION, EXTENSION_SHARE, ); - HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/Share.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - LIBRARY_SEARCH_PATHS = ""; - OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = it.twsweb.Nextcloud.Share; PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_SHARE"; SWIFT_OBJC_BRIDGING_HEADER = "Share/Share-Bridging-Header.h"; - SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - USE_HEADERMAP = YES; }; name = Release; }; F771E3F020E2392E00AFB62D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = NO; - CLANG_WARN_DOCUMENTATION_COMMENTS = NO; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; - CLANG_WARN_STRICT_PROTOTYPES = NO; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/iOSClient/Brand/File_Provider_Extension.entitlements"; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = 6JLRKY9ZV7; - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", EXTENSION, EXTENSION_FILE_PROVIDER_EXTENSION, ); - HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/File_Provider_Extension.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - LIBRARY_SEARCH_PATHS = ""; - OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_FILE_PROVIDER_EXTENSION"; SWIFT_OBJC_BRIDGING_HEADER = "File Provider Extension/FileProviderExtension-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; F771E3F120E2392E00AFB62D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = NO; - CLANG_WARN_DOCUMENTATION_COMMENTS = NO; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; - CLANG_WARN_STRICT_PROTOTYPES = NO; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = "$(SRCROOT)/iOSClient/Brand/File_Provider_Extension.entitlements"; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = 6JLRKY9ZV7; - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", EXTENSION, EXTENSION_FILE_PROVIDER_EXTENSION, ); - HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/File_Provider_Extension.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - LIBRARY_SEARCH_PATHS = ""; - OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.Nextcloud.File-Provider-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) EXTENSION EXTENSION_FILE_PROVIDER_EXTENSION"; SWIFT_OBJC_BRIDGING_HEADER = "File Provider Extension/FileProviderExtension-Bridging-Header.h"; - SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; F77B0F9B1D118A16002130FE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; - CLANG_ENABLE_MODULES = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; - CLANG_WARN_STRICT_PROTOTYPES = NO; CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/iOSClient.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = 6JLRKY9ZV7; - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = ""; - GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/iOSClient.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - LIBRARY_SEARCH_PATHS = ""; - OTHER_LDFLAGS = ( - "-ObjC", - "-weak_framework", - SwiftUI, - ); - OTHER_SWIFT_FLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_OBJC_BRIDGING_HEADER = "iOSClient/Nextcloud-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - USE_HEADERMAP = YES; - VERSIONING_SYSTEM = ""; }; name = Debug; }; F77B0F9C1D118A16002130FE /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; - CLANG_ENABLE_MODULES = YES; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; - CLANG_WARN_STRICT_PROTOTYPES = NO; CODE_SIGN_ENTITLEMENTS = iOSClient/Brand/iOSClient.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEVELOPMENT_TEAM = 6JLRKY9ZV7; - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = ""; - GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; - HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = "$(SRCROOT)/iOSClient/Brand/iOSClient.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@executable_path/../../Frameworks", - ); - LIBRARY_SEARCH_PATHS = ""; - OTHER_LDFLAGS = ( - "-ObjC", - "-weak_framework", - SwiftUI, - ); PRODUCT_BUNDLE_IDENTIFIER = "it.twsweb.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; SWIFT_OBJC_BRIDGING_HEADER = "iOSClient/Nextcloud-Bridging-Header.h"; - SWIFT_PRECOMPILE_BRIDGING_HEADER = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - USE_HEADERMAP = YES; - VERSIONING_SYSTEM = ""; }; name = Release; }; F7F67BC91A24D27800EE80DA /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -3040,66 +2858,58 @@ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 7; - DEFINES_MODULE = YES; + CURRENT_PROJECT_VERSION = 4; + DEVELOPMENT_TEAM = 6JLRKY9ZV7; ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", DEBUG, NC, ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.1; - MARKETING_VERSION = 4.2.2; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = ( - "-Obj-C", - "-all_load", + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", ); + MARKETING_VERSION = 4.3.0; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ""; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) NC"; - SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; F7F67BCA1A24D27800EE80DA /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; + CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; @@ -3107,45 +2917,42 @@ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = NO; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 7; - DEFINES_MODULE = YES; + CURRENT_PROJECT_VERSION = 4; + DEVELOPMENT_TEAM = 6JLRKY9ZV7; ENABLE_BITCODE = NO; - ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NC, ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 12.1; - MARKETING_VERSION = 4.2.2; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ( - "-Obj-C", - "-all_load", + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", ); + MARKETING_VERSION = 4.3.0; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = ""; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG NC"; - SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_SWIFT3_OBJC_INFERENCE = Off; - VALIDATE_PRODUCT = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; @@ -3334,7 +3141,7 @@ repositoryURL = "https://github.com/nextcloud/ios-communication-library/"; requirement = { kind = exactVersion; - version = 0.99.4; + version = 0.99.5; }; }; F788ECC5263AAAF900ADC67F /* XCRemoteSwiftPackageReference "MarkdownKit" */ = { diff --git a/Nextcloud.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Nextcloud.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index 6b94a32f7..000000000 --- a/Nextcloud.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -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": "78f7087fd5d48eb7c36e299f330b6dddccd647b2", - "version": "8.12.1" - } - }, - { - "package": "FloatingPanel", - "repositoryURL": "https://github.com/scenee/FloatingPanel", - "state": { - "branch": null, - "revision": "fe30e60235c5cc753e2ee2a3eebc8e654971634d", - "version": "2.5.2" - } - }, - { - "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": "6cc2991c11872510a5314bc112cc7558dd9d046a", - "version": "8.12.0" - } - }, - { - "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": null, - "revision": "c7aabb42f734f30c2e325dec4000c59349f33005", - "version": "0.99.4" - } - }, - { - "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": "fbd7fc73c4ee5593fde57b9d50fe53d307dcf07c", - "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 -} diff --git a/Nextcloud.xcodeproj/xcshareddata/xcschemes/File Provider Extension.xcscheme b/Nextcloud.xcodeproj/xcshareddata/xcschemes/File Provider Extension.xcscheme index 315a8ea7d..9f6feaf4e 100755 --- a/Nextcloud.xcodeproj/xcshareddata/xcschemes/File Provider Extension.xcscheme +++ b/Nextcloud.xcodeproj/xcshareddata/xcschemes/File Provider Extension.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "1250" + LastUpgradeVersion = "1320" wasCreatedForAppExtension = "YES" version = "2.0"> <BuildAction @@ -93,7 +93,6 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES" - askForAppToLaunch = "Yes" launchAutomaticallySubstyle = "2"> <BuildableProductRunnable runnableDebuggingMode = "0"> diff --git a/Nextcloud.xcodeproj/xcshareddata/xcschemes/Nextcloud.xcscheme b/Nextcloud.xcodeproj/xcshareddata/xcschemes/Nextcloud.xcscheme index 0de72cffc..3646e7016 100755 --- a/Nextcloud.xcodeproj/xcshareddata/xcschemes/Nextcloud.xcscheme +++ b/Nextcloud.xcodeproj/xcshareddata/xcschemes/Nextcloud.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "1250" + LastUpgradeVersion = "1320" version = "1.7"> <BuildAction parallelizeBuildables = "YES" diff --git a/Nextcloud.xcodeproj/xcshareddata/xcschemes/Share.xcscheme b/Nextcloud.xcodeproj/xcshareddata/xcschemes/Share.xcscheme index 279a69ad5..80e2013e6 100755 --- a/Nextcloud.xcodeproj/xcshareddata/xcschemes/Share.xcscheme +++ b/Nextcloud.xcodeproj/xcshareddata/xcschemes/Share.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - LastUpgradeVersion = "1250" + LastUpgradeVersion = "1320" wasCreatedForAppExtension = "YES" version = "2.0"> <BuildAction @@ -97,7 +97,6 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES" - askForAppToLaunch = "Yes" launchAutomaticallySubstyle = "2"> <BuildableProductRunnable runnableDebuggingMode = "0"> diff --git a/NextcloudTests/ParallelWorkerTest.swift b/NextcloudTests/ParallelWorkerTest.swift new file mode 100644 index 000000000..fdfbace63 --- /dev/null +++ b/NextcloudTests/ParallelWorkerTest.swift @@ -0,0 +1,85 @@ +// +// ParallelWorkerTest.swift +// Nextcloud +// +// Created by Henrik Storch on 18.02.22. +// Copyright © 2021 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/>. +// + +@testable import Nextcloud +import XCTest + +class ParallelWorkerTest: XCTestCase { + + func testWorkerComplete() throws { + let expectation = XCTestExpectation(description: "Worker executes all tasks") + let taskCount = 20 + var tasksComplete = 0 + let worker = ParallelWorker(n: 5, titleKey: nil, totalTasks: nil, hudView: nil) + for _ in 0..<taskCount { + worker.execute { completion in + tasksComplete += 1 + completion() + } + } + worker.completeWork { + XCTAssertEqual(tasksComplete, taskCount) + if tasksComplete == taskCount { + expectation.fulfill() + } + } + + let result = XCTWaiter.wait(for: [expectation], timeout: 5) + XCTAssertEqual(result, .completed) + } + + func testWorkerOrder() throws { + let expectation = XCTestExpectation(description: "Worker executes work in sequence for n = 1") + let sortedArray = Array(0..<20) + var array: [Int] = [] + let worker = ParallelWorker(n: 1, titleKey: nil, totalTasks: nil, hudView: nil) + for i in sortedArray { + worker.execute { completion in + DispatchQueue.main.asyncAfter(deadline: .now() + Double.random(in: 0...0.2)) { + array.append(i) + completion() + } + } + } + worker.completeWork { + XCTAssertEqual(sortedArray, array) + if sortedArray == array { + expectation.fulfill() + } + } + let result = XCTWaiter.wait(for: [expectation], timeout: 5) + XCTAssertEqual(result, .completed) + } + + func testWorkerFailsWithoutCompletion() throws { + let expectation = XCTestExpectation(description: "Worker fails if completion isn't called") + expectation.isInverted = true + let worker = ParallelWorker(n: 5, titleKey: nil, totalTasks: nil, hudView: nil) + for _ in 0..<20 { + worker.execute { _ in } + } + worker.completeWork { expectation.fulfill() } + let result = XCTWaiter.wait(for: [expectation], timeout: 5) + XCTAssertEqual(result, .completed) + } +} diff --git a/Share/NCShareExtension.swift b/Share/NCShareExtension.swift index 970700054..f45c2d342 100644 --- a/Share/NCShareExtension.swift +++ b/Share/NCShareExtension.swift @@ -104,7 +104,7 @@ class NCShareExtension: UIViewController { createFolderView.addGestureRecognizer(createFolderGesture) uploadView.layer.cornerRadius = 10 - + // uploadImage.image = NCUtility.shared.loadImage(named: "square.and.arrow.up", color: NCBrandColor.shared.label) uploadLabel.text = NSLocalizedString("_upload_", comment: "") uploadLabel.textColor = .systemBlue @@ -130,7 +130,7 @@ class NCShareExtension: UIViewController { if let indicatorView = hud.indicatorView as? JGProgressHUDRingIndicatorView { indicatorView.ringWidth = 1.5 } - + NotificationCenter.default.addObserver(self, selector: #selector(triggerProgressTask(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterProgressTask), object: nil) } @@ -188,7 +188,7 @@ class NCShareExtension: UIViewController { guard let progress = notification.userInfo?["progress"] as? Float else { return } hud.progress = progress } - + func setNavigationBar(navigationTitle: String) { navigationItem.title = navigationTitle @@ -357,7 +357,7 @@ extension NCShareExtension { hud.textLabel.text = NSLocalizedString("_upload_file_", comment: "") + " \(counterUploaded + 1) " + NSLocalizedString("_of_", comment: "") + " \(filesName.count)" hud.progress = 0 hud.show(in: self.view) - + NCNetworking.shared.upload(metadata: metadata) { } completion: { errorCode, _ in if errorCode == 0 { self.counterUploaded += 1 diff --git a/iOSClient/.tx/config b/iOSClient/.tx/config index af6f69eb1..9706c6ea1 100755 --- a/iOSClient/.tx/config +++ b/iOSClient/.tx/config @@ -7,3 +7,10 @@ source_file = Supporting Files/en.lproj/Localizable.strings source_lang = en type = STRINGS lang_map = pt_BR:pt-BR,zh_CN:zh-Hans,fi_FI:fi-FI,es_MX:es-MX,nb_NO:nb-NO,cs_CZ:cs-CZ,en_GB:en-GB,es_AR:es-AR,sk_SK:sk-SK,hu_HU:hu,ka_GE:ka-GE,zh_TW:zh-Hant-TW,es_CL:es-CL,es_CO:es-CO,es_CR:es-CR,es_DO:es-DO,es_EC:es-EC,es_GT:es-GT,es_HN:es-HN,es_NI:es-NI,es_PA:es-PA,es_PE:es-PE,es_PR:es-PR,es_PY:es-PY,es_SV:es-SV,es_UY:es-UY,es_419:es-419,pt_PT:pt-PT,ja_JP:ja-JP + +[nextcloud.ios-info] +file_filter = Supporting Files/<lang>.lproj/InfoPlist.strings +source_file = Supporting Files/en.lproj/InfoPlist.strings +source_lang = en +type = STRINGS +lang_map = pt_BR:pt-BR,zh_CN:zh-Hans,fi_FI:fi-FI,es_MX:es-MX,nb_NO:nb-NO,cs_CZ:cs-CZ,en_GB:en-GB,es_AR:es-AR,sk_SK:sk-SK,hu_HU:hu,ka_GE:ka-GE,zh_TW:zh-Hant-TW,es_CL:es-CL,es_CO:es-CO,es_CR:es-CR,es_DO:es-DO,es_EC:es-EC,es_GT:es-GT,es_HN:es-HN,es_NI:es-NI,es_PA:es-PA,es_PE:es-PE,es_PR:es-PR,es_PY:es-PY,es_SV:es-SV,es_UY:es-UY,es_419:es-419,pt_PT:pt-PT,ja_JP:ja-JP diff --git a/iOSClient/Activity/NCActivityTableViewCell.swift b/iOSClient/Activity/NCActivityTableViewCell.swift index 0136e195a..f75c88d62 100644 --- a/iOSClient/Activity/NCActivityTableViewCell.swift +++ b/iOSClient/Activity/NCActivityTableViewCell.swift @@ -111,7 +111,7 @@ extension NCActivityTableViewCell: UICollectionViewDelegate { var responder: UIResponder? = collectionView while !(responder is UIViewController) { responder = responder?.next - if nil == responder { + if responder == nil { break } } diff --git a/iOSClient/AppDelegate.swift b/iOSClient/AppDelegate.swift index a790747e3..7172cc047 100644 --- a/iOSClient/AppDelegate.swift +++ b/iOSClient/AppDelegate.swift @@ -59,7 +59,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD var disableSharesView: Bool = false var documentPickerViewController: NCDocumentPickerViewController? var networkingProcessUpload: NCNetworkingProcessUpload? - var pasteboardOcIds: [String] = [] var shares: [tableShare] = [] var timerErrorNetworking: Timer? diff --git a/iOSClient/Data/NCDataSource.swift b/iOSClient/Data/NCDataSource.swift index 8408c26bb..09c423492 100644 --- a/iOSClient/Data/NCDataSource.swift +++ b/iOSClient/Data/NCDataSource.swift @@ -114,16 +114,13 @@ class NCDataSource: NSObject { } // is Local / offline - if !metadata.directory { - let size = CCUtility.fileProviderStorageSize(metadata.ocId, fileNameView: metadata.fileNameView) - if size > 0 { - let tableLocalFile = NCManageDatabase.shared.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) - if tableLocalFile == nil && size == metadata.size { - NCManageDatabase.shared.addLocalFile(metadata: metadata) - } - if tableLocalFile?.offline ?? false { - metadataOffLine.append(metadata.ocId) - } + if !metadata.directory, CCUtility.fileProviderStorageExists(metadata) { + let tableLocalFile = NCManageDatabase.shared.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) + if tableLocalFile == nil { + NCManageDatabase.shared.addLocalFile(metadata: metadata) + } + if tableLocalFile?.offline ?? false { + metadataOffLine.append(metadata.ocId) } } @@ -183,15 +180,19 @@ class NCDataSource: NSObject { var index: Int? - if ocIdTemp != nil { - index = self.getIndexMetadata(ocId: ocIdTemp!) + if let ocIdTemp = ocIdTemp { + index = self.getIndexMetadata(ocId: ocIdTemp) } else { index = self.getIndexMetadata(ocId: ocId) } - if index != nil { - if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) { - metadatas[index!] = metadata + guard let index = index, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { return nil } + metadatas[index] = metadata + + if CCUtility.fileProviderStorageExists(metadata) { + let tableLocalFile = NCManageDatabase.shared.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) + if tableLocalFile?.offline ?? false { + metadataOffLine.append(metadata.ocId) } } diff --git a/iOSClient/Data/NCDatabase.swift b/iOSClient/Data/NCDatabase.swift index b5a6ca5eb..479e8ca92 100644 --- a/iOSClient/Data/NCDatabase.swift +++ b/iOSClient/Data/NCDatabase.swift @@ -24,6 +24,7 @@ import UIKit import RealmSwift +import NCCommunication protocol DateCompareable { var dateKey: Date { get } @@ -52,7 +53,6 @@ class tableAccount: Object, NCUserBaseUrl { @objc dynamic var businessSize: String = "" @objc dynamic var businessType = "" @objc dynamic var city = "" - @objc dynamic var company = "" @objc dynamic var country = "" @objc dynamic var displayName = "" @objc dynamic var email = "" @@ -62,6 +62,7 @@ class tableAccount: Object, NCUserBaseUrl { @objc dynamic var lastLogin: Int64 = 0 @objc dynamic var locale = "" @objc dynamic var mediaPath = "" + @objc dynamic var organisation = "" @objc dynamic var password = "" @objc dynamic var phone = "" @objc dynamic var quota: Int64 = 0 @@ -83,7 +84,7 @@ class tableAccount: Object, NCUserBaseUrl { @objc dynamic var userStatusMessageIsPredefined: Bool = false @objc dynamic var userStatusStatus: String? @objc dynamic var userStatusStatusIsUserDefined: Bool = false - @objc dynamic var webpage = "" + @objc dynamic var website = "" @objc dynamic var zip = "" // COLOR Files @@ -413,6 +414,14 @@ class tableMetadata: Object, NCUserBaseUrl { } } +extension tableMetadata { + var fileExtension: String { (fileNameView as NSString).pathExtension } + + var isPrintable: Bool { + classFile == NCCommunicationCommon.typeClassFile.image.rawValue || ["application/pdf", "com.adobe.pdf"].contains(contentType) || contentType.hasPrefix("text/") + } +} + class tablePhotoLibrary: Object { @objc dynamic var account = "" diff --git a/iOSClient/Data/NCManageDatabase+Account.swift b/iOSClient/Data/NCManageDatabase+Account.swift index 01a687274..305e37f33 100644 --- a/iOSClient/Data/NCManageDatabase+Account.swift +++ b/iOSClient/Data/NCManageDatabase+Account.swift @@ -302,6 +302,7 @@ extension NCManageDatabase { result.language = userProfile.language result.lastLogin = userProfile.lastLogin result.locale = userProfile.locale + result.organisation = userProfile.organisation result.phone = userProfile.phone result.quota = userProfile.quota result.quotaFree = userProfile.quotaFree @@ -312,7 +313,7 @@ extension NCManageDatabase { result.subadmin = userProfile.subadmin.joined(separator: ",") result.twitter = userProfile.twitter result.userId = userProfile.userId - result.webpage = userProfile.webpage + result.website = userProfile.website returnAccount = result } @@ -323,7 +324,7 @@ extension NCManageDatabase { return tableAccount.init(value: returnAccount) } - @objc func setAccountUserProfileHC(businessSize: String, businessType: String, city: String, company: String, country: String, role: String, zip: String) -> tableAccount? { + @objc func setAccountUserProfileHC(businessSize: String, businessType: String, city: String, organisation: String, country: String, role: String, zip: String) -> tableAccount? { let realm = try! Realm() @@ -343,7 +344,7 @@ extension NCManageDatabase { result.businessSize = businessSize result.businessType = businessType result.city = city - result.company = company + result.organisation = organisation result.country = country result.role = role result.zip = zip diff --git a/iOSClient/Data/NCManageDatabase.swift b/iOSClient/Data/NCManageDatabase.swift index 858d709bd..d2df51389 100644 --- a/iOSClient/Data/NCManageDatabase.swift +++ b/iOSClient/Data/NCManageDatabase.swift @@ -1131,7 +1131,7 @@ class NCManageDatabase: NSObject { do { try realm.safeWrite { - let addObject = tableLocalFile() + let addObject = getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) ?? tableLocalFile() addObject.account = metadata.account addObject.etag = metadata.etag diff --git a/iOSClient/Data/NCManageDatabse+Metadata.swift b/iOSClient/Data/NCManageDatabse+Metadata.swift index bc45836a8..684a37a1e 100644 --- a/iOSClient/Data/NCManageDatabse+Metadata.swift +++ b/iOSClient/Data/NCManageDatabse+Metadata.swift @@ -141,6 +141,8 @@ extension NCManageDatabase { let metadata = tableMetadata() let resultInternalType = NCCommunicationCommon.shared.getInternalType(fileName: fileName, mimeType: contentType, directory: false) + + let fileName = fileName.trimmingCharacters(in: .whitespacesAndNewlines) metadata.account = account metadata.chunk = false diff --git a/iOSClient/EmptyView/NCEmptyView.xib b/iOSClient/EmptyView/NCEmptyView.xib index e72820c00..7325e0e2a 100644 --- a/iOSClient/EmptyView/NCEmptyView.xib +++ b/iOSClient/EmptyView/NCEmptyView.xib @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> <device id="retina3_5" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="System colors in document resources" minToolsVersion="11.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> @@ -23,12 +23,12 @@ </constraints> </imageView> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="crs-DO-owR"> - <rect key="frame" x="0.0" y="180" width="350" height="24"/> + <rect key="frame" x="20" y="180" width="310" height="24"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="20"/> <color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <nil key="highlightedColor"/> </label> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D4p-sI-mNB"> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D4p-sI-mNB"> <rect key="frame" x="20" y="224" width="310" height="17"/> <constraints> <constraint firstAttribute="height" relation="lessThanOrEqual" constant="50" id="u7B-jW-bWI"/> @@ -41,10 +41,10 @@ <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <constraints> - <constraint firstItem="crs-DO-owR" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="CMU-Tp-bUM"/> + <constraint firstItem="crs-DO-owR" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="20" id="CMU-Tp-bUM"/> <constraint firstItem="W3d-Us-kU4" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" id="Fyb-so-iAw"/> <constraint firstItem="D4p-sI-mNB" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" constant="20" id="egV-G4-wax"/> - <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="crs-DO-owR" secondAttribute="trailing" id="hHl-iN-Gev"/> + <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="crs-DO-owR" secondAttribute="trailing" constant="20" id="hHl-iN-Gev"/> <constraint firstItem="crs-DO-owR" firstAttribute="top" secondItem="W3d-Us-kU4" secondAttribute="bottom" constant="30" id="hLN-L6-0gH"/> <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="D4p-sI-mNB" secondAttribute="trailing" constant="20" id="imv-AK-mqu"/> <constraint firstItem="W3d-Us-kU4" firstAttribute="centerX" secondItem="vUN-kp-3ea" secondAttribute="centerX" id="kma-1Q-c3Q"/> diff --git a/iOSClient/Extensions/UIBarButton+Extension.swift b/iOSClient/Extensions/UIBarButton+Extension.swift new file mode 100644 index 000000000..242c6e0e6 --- /dev/null +++ b/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() + } +} diff --git a/iOSClient/Extensions/UIImage+Extensions.swift b/iOSClient/Extensions/UIImage+Extensions.swift index 2bc191ed4..c790eb66e 100644 --- a/iOSClient/Extensions/UIImage+Extensions.swift +++ b/iOSClient/Extensions/UIImage+Extensions.swift @@ -117,27 +117,25 @@ extension UIImage { @objc func image(color: UIColor, size: CGFloat) -> UIImage { - return autoreleasepool { () -> UIImage in - let size = CGSize(width: size, height: size) + let size = CGSize(width: size, height: size) - UIGraphicsBeginImageContextWithOptions(size, false, self.scale) - color.setFill() + UIGraphicsBeginImageContextWithOptions(size, false, self.scale) + color.setFill() - let context = UIGraphicsGetCurrentContext() - context?.translateBy(x: 0, y: size.height) - context?.scaleBy(x: 1.0, y: -1.0) - context?.setBlendMode(CGBlendMode.normal) + let context = UIGraphicsGetCurrentContext() + context?.translateBy(x: 0, y: size.height) + context?.scaleBy(x: 1.0, y: -1.0) + context?.setBlendMode(CGBlendMode.normal) - let rect = CGRect(origin: .zero, size: size) - guard let cgImage = self.cgImage else { return self } - context?.clip(to: rect, mask: cgImage) - context?.fill(rect) + let rect = CGRect(origin: .zero, size: size) + guard let cgImage = self.cgImage else { return self } + context?.clip(to: rect, mask: cgImage) + context?.fill(rect) - let newImage = UIGraphicsGetImageFromCurrentImageContext() ?? self - UIGraphicsEndImageContext() + let newImage = UIGraphicsGetImageFromCurrentImageContext() ?? self + UIGraphicsEndImageContext() - return newImage - } + return newImage } func imageColor(_ color: UIColor) -> UIImage { @@ -204,4 +202,29 @@ extension UIImage { // Return the downsampled image as UIImage return UIImage(cgImage: downsampledImage) } + + // Source: + // https://stackoverflow.com/questions/27092354/rotating-uiimage-in-swift/47402811#47402811 + + func rotate(radians: Float) -> UIImage? { + var newSize = CGRect(origin: CGPoint.zero, size: self.size).applying(CGAffineTransform(rotationAngle: CGFloat(radians))).size + // Trim off the extremely small float value to prevent core graphics from rounding it up + newSize.width = floor(newSize.width) + newSize.height = floor(newSize.height) + + UIGraphicsBeginImageContextWithOptions(newSize, true, self.scale) + let context = UIGraphicsGetCurrentContext()! + + // Move origin to middle + context.translateBy(x: newSize.width / 2, y: newSize.height / 2) + // Rotate around middle + context.rotate(by: CGFloat(radians)) + // Draw the image at its center + self.draw(in: CGRect(x: -self.size.width / 2, y: -self.size.height / 2, width: self.size.width, height: self.size.height)) + + let newImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + + return newImage + } } diff --git a/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift b/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift index 487ea6c26..fd431bd06 100644 --- a/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift +++ b/iOSClient/Main/AudioRecorder/NCAudioRecorderViewController.swift @@ -37,7 +37,7 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate { open weak var delegate: NCAudioRecorderViewControllerDelegate? var recording: NCAudioRecorder! - var recordDuration: TimeInterval = 0 + var startDate: Date = Date() var fileName: String = "" @IBOutlet weak var contentContainerView: UIView! @@ -93,7 +93,7 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate { if recording.state == .record { - recordDuration = 0 + startDate = Date() recording.stop() voiceRecordHUD.update(0.0) @@ -103,7 +103,6 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate { } else { - recordDuration = 0 do { try recording.record() startStopLabel.text = NSLocalizedString("_voice_memo_stop_", comment: "") @@ -149,8 +148,11 @@ class NCAudioRecorderViewController: UIViewController, NCAudioRecorderDelegate { voiceRecordHUD.update(CGFloat(rate)) voiceRecordHUD.fillColor = UIColor.green - recordDuration += 1 - durationLabel.text = String().formatSecondsToString(recordDuration/60) + + let formatter = DateComponentsFormatter() + formatter.allowedUnits = [.second] + formatter.unitsStyle = .full + durationLabel.text = formatter.string(from: startDate, to: Date()) } } diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift index 3b58091c7..0ff8de7a5 100644 --- a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift @@ -22,9 +22,11 @@ // import UIKit +import Realm 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! @@ -448,13 +450,15 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS @objc func downloadedFile(_ notification: NSNotification) { - if let userInfo = notification.userInfo as NSDictionary?, let ocId = userInfo["ocId"] as? String, let _ = userInfo["errorCode"] as? Int, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) { - if let row = dataSource.reloadMetadata(ocId: metadata.ocId) { - let indexPath = IndexPath(row: row, section: 0) - if indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section) { - collectionView?.reloadItems(at: [indexPath]) - } - } + guard let userInfo = notification.userInfo as NSDictionary?, + let ocId = userInfo["ocId"] as? String, + let _ = userInfo["errorCode"] as? Int, + let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId), + let row = dataSource.reloadMetadata(ocId: metadata.ocId) + else { return } + let indexPath = IndexPath(row: row, section: 0) + if indexPath.section < collectionView.numberOfSections && indexPath.row < collectionView.numberOfItems(inSection: indexPath.section) { + collectionView?.reloadItems(at: [indexPath]) } } @@ -577,76 +581,63 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS // MARK: - Layout @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 { @@ -729,16 +720,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS // MARK: - TAP EVENT - @objc func tapSelect(sender: Any) { - - isEditMode = !isEditMode - - selectOcId.removeAll() - setNavigationItem() - - self.collectionView.reloadData() - } - func accountRequestChangeAccount(account: String) { NCManageDatabase.shared.setAccountActive(account) if let activeAccount = NCManageDatabase.shared.getActiveAccount() { @@ -787,11 +768,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS sortMenu.toggleMenu(viewController: self, key: layoutKey, sortButton: sender as? UIButton, serverUrl: serverUrl) } - @objc func tapSelectMenu(sender: Any) { - - toggleMenuSelect() - } - func tapMoreHeader(sender: Any) { } func tapMoreListItem(with objectId: String, namedButtonMore: String, image: UIImage?, sender: Any) { @@ -1228,7 +1204,7 @@ extension NCCollectionViewCommon: UICollectionViewDelegate { return } - if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + if CCUtility.fileProviderStorageExists(metadata) { NCViewer.shared.view(viewController: self, metadata: metadata, metadatas: [metadata], imageIcon: imageIcon) } else if NCCommunication.shared.isNetworkReachable() { NCNetworking.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorLoadFileView) { _ in } @@ -1245,12 +1221,6 @@ extension NCCollectionViewCommon: UICollectionViewDelegate { 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, *) func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { @@ -1459,7 +1429,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource { // image local if dataSource.metadataOffLine.contains(metadata.ocId) { cell.imageLocal.image = NCBrandColor.cacheImages.offlineFlag - } else if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + } else if CCUtility.fileProviderStorageExists(metadata) { cell.imageLocal.image = NCBrandColor.cacheImages.local } } @@ -1627,7 +1597,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource { // image Local if dataSource.metadataOffLine.contains(metadata.ocId) { cell.imageLocal.image = NCBrandColor.cacheImages.offlineFlag - } else if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + } else if CCUtility.fileProviderStorageExists(metadata) { cell.imageLocal.image = NCBrandColor.cacheImages.local } } diff --git a/iOSClient/Main/Collection Common/NCGridCell.swift b/iOSClient/Main/Collection Common/NCGridCell.swift index ced3d5e93..e458e3cd2 100644 --- a/iOSClient/Main/Collection Common/NCGridCell.swift +++ b/iOSClient/Main/Collection Common/NCGridCell.swift @@ -23,7 +23,8 @@ import UIKit -class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProtocol { +class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProtocol, NCTrashCell { + var labelInfo: UILabel? @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageSelect: UIImageView! @@ -35,7 +36,7 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto @IBOutlet weak var imageVisualEffect: UIVisualEffectView! @IBOutlet weak var progressView: UIProgressView! - private var objectId = "" + internal var objectId = "" private var user = "" weak var delegate: NCGridCellDelegate? diff --git a/iOSClient/Main/Collection Common/NCSelectableNavigationView.swift b/iOSClient/Main/Collection Common/NCSelectableNavigationView.swift new file mode 100644 index 000000000..86aa18c8f --- /dev/null +++ b/iOSClient/Main/Collection Common/NCSelectableNavigationView.swift @@ -0,0 +1,130 @@ +// +// 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 NCCommunication +import Realm +import UIKit + +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 } + + var selectActions: [NCMenuAction] { get } + + func reloadDataSource() + func setNavigationItem() + + func tapSelectMenu() + func tapSelect() +} + +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() { + presentMenu(with: selectActions) + } + + var selectActions: [NCMenuAction] { + var actions = [NCMenuAction]() + if selectOcId.count != selectableDataSource.count { + actions.append(.selectAllAction(action: collectionViewSelectAll)) + } + + guard !selectOcId.isEmpty else { return actions } + var selectedMetadatas: [tableMetadata] = [] + var selectedMediaMetadatas: [tableMetadata] = [] + var isAnyOffline = false + + for ocId in selectOcId { + guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { continue } + selectedMetadatas.append(metadata) + if [NCCommunicationCommon.typeClassFile.image.rawValue, NCCommunicationCommon.typeClassFile.video.rawValue].contains(metadata.classFile) { + selectedMediaMetadatas.append(metadata) + } + + guard !isAnyOffline else { continue } + if metadata.directory, + let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, metadata.serverUrl + "/" + metadata.fileName)) { + isAnyOffline = directory.offline + } else if let localFile = NCManageDatabase.shared.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) { + isAnyOffline = localFile.offline + } // else: file is not offline, continue + } + + actions.append(.openInAction(selectedMetadatas: selectedMetadatas, viewController: self, completion: tapSelect)) + + if !selectedMediaMetadatas.isEmpty { + actions.append(.saveMediaAction(selectedMediaMetadatas: selectedMediaMetadatas, completion: tapSelect)) + } + actions.append(.setAvailableOfflineAction(selectedMetadatas: selectedMetadatas, isAnyOffline: isAnyOffline, viewController: self, completion: { + self.reloadDataSource() + self.tapSelect() + })) + + actions.append(.moveOrCopyAction(selectedMetadatas: selectedMetadatas, completion: tapSelect)) + actions.append(.copyAction(selectOcId: selectOcId, hudView: self.view, completion: tapSelect)) + actions.append(.deleteAction(selectedMetadatas: selectedMetadatas, viewController: self, completion: tapSelect)) + return actions + } +} diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift index 069314edd..6d90735b9 100644 --- a/iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift +++ b/iOSClient/Main/Create cloud/NCCreateFormUploadDocuments.swift @@ -274,6 +274,9 @@ import XLForm return } else { + //Trim whitespaces after checks above + fileNameForm = (fileNameForm as! String).trimmingCharacters(in: .whitespacesAndNewlines) + let result = NCCommunicationCommon.shared.getInternalType(fileName: fileNameForm as! String, mimeType: "", directory: false) if NCUtility.shared.isDirectEditing(account: appDelegate.account, contentType: result.mimeType).count == 0 { fileNameForm = (fileNameForm as! NSString).deletingPathExtension + "." + fileNameExtension diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift b/iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift index 42954b67f..7058688f7 100644 --- a/iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift +++ b/iOSClient/Main/Create cloud/NCCreateFormUploadScanDocument.swift @@ -762,10 +762,10 @@ class NCCreateScanDocument: NSObject, VNDocumentCameraViewControllerDelegate { } controller.dismiss(animated: true) { - if self.viewController is DragDropViewController { - (self.viewController as! DragDropViewController).loadImage() + if let viewController = self.viewController as? NCScan { + viewController.loadImage() } else { - let storyboard = UIStoryboard(name: "Scan", bundle: nil) + let storyboard = UIStoryboard(name: "NCScan", bundle: nil) let controller = storyboard.instantiateInitialViewController()! controller.modalPresentationStyle = UIModalPresentationStyle.pageSheet diff --git a/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.storyboard b/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.storyboard index 8f0878f99..477b8d940 100644 --- a/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.storyboard +++ b/iOSClient/Main/Create cloud/NCCreateFormUploadVoiceNote.storyboard @@ -1,11 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="hTm-e0-ORl"> - <device id="retina4_7" orientation="portrait"> - <adaptation id="fullscreen"/> - </device> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="hTm-e0-ORl"> + <device id="retina4_7" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> @@ -19,18 +17,15 @@ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" scrollEnabled="NO" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="eeP-9N-ZRP"> - <rect key="frame" x="0.0" y="89" width="375" height="150"/> + <rect key="frame" x="0.0" y="163" width="375" height="504"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - <constraints> - <constraint firstAttribute="height" constant="150" id="kKy-VZ-d0g"/> - </constraints> <connections> <outlet property="dataSource" destination="uQo-FX-ejX" id="Y7U-AM-3WZ"/> <outlet property="delegate" destination="uQo-FX-ejX" id="gsE-cc-f9G"/> </connections> </tableView> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="s98-hk-uUP"> - <rect key="frame" x="150" y="249" width="75" height="75"/> + <rect key="frame" x="150" y="54" width="75" height="75"/> <constraints> <constraint firstAttribute="width" constant="75" id="h48-gg-iPB"/> <constraint firstAttribute="height" constant="75" id="mjB-VI-Gzf"/> @@ -41,7 +36,7 @@ </connections> </button> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00:00" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="we1-Q7-8Us"> - <rect key="frame" x="20" y="344" width="70" height="17"/> + <rect key="frame" x="20" y="132.5" width="70" height="17"/> <constraints> <constraint firstAttribute="width" constant="70" id="Su3-nN-I5z"/> </constraints> @@ -50,7 +45,7 @@ <nil key="highlightedColor"/> </label> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00:00" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zd0-7e-z9V" userLabel="Label Duration"> - <rect key="frame" x="285" y="344" width="70" height="17"/> + <rect key="frame" x="285" y="132.5" width="70" height="17"/> <constraints> <constraint firstAttribute="width" constant="70" id="JZa-Lm-wgx"/> </constraints> @@ -59,24 +54,25 @@ <nil key="highlightedColor"/> </label> <progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="6HO-NK-obf"> - <rect key="frame" x="100" y="351.5" width="175" height="2"/> + <rect key="frame" x="100" y="139" width="175" height="4"/> </progressView> </subviews> + <viewLayoutGuide key="safeArea" id="ILQ-5j-b92"/> <constraints> - <constraint firstItem="eeP-9N-ZRP" firstAttribute="top" secondItem="ILQ-5j-b92" secondAttribute="top" constant="25" id="AEH-dn-vHh"/> + <constraint firstItem="s98-hk-uUP" firstAttribute="top" secondItem="ILQ-5j-b92" secondAttribute="top" constant="10" id="5mu-uh-SqU"/> <constraint firstItem="6HO-NK-obf" firstAttribute="leading" secondItem="we1-Q7-8Us" secondAttribute="trailing" constant="10" id="C6M-oc-T1Z"/> <constraint firstItem="6HO-NK-obf" firstAttribute="centerY" secondItem="we1-Q7-8Us" secondAttribute="centerY" id="J28-Wh-Byv"/> + <constraint firstItem="6HO-NK-obf" firstAttribute="top" secondItem="s98-hk-uUP" secondAttribute="bottom" constant="10" id="RxM-5b-ZEm"/> + <constraint firstItem="zd0-7e-z9V" firstAttribute="centerY" secondItem="6HO-NK-obf" secondAttribute="centerY" id="T4r-QI-wSb"/> <constraint firstItem="ILQ-5j-b92" firstAttribute="trailing" secondItem="zd0-7e-z9V" secondAttribute="trailing" constant="20" id="Zkq-S4-Hnu"/> + <constraint firstItem="ILQ-5j-b92" firstAttribute="bottom" secondItem="eeP-9N-ZRP" secondAttribute="bottom" id="a74-Md-bui"/> <constraint firstItem="zd0-7e-z9V" firstAttribute="leading" secondItem="6HO-NK-obf" secondAttribute="trailing" constant="10" id="bKe-sM-Gvy"/> - <constraint firstItem="we1-Q7-8Us" firstAttribute="top" secondItem="s98-hk-uUP" secondAttribute="bottom" constant="20" id="ehi-c7-6om"/> - <constraint firstItem="zd0-7e-z9V" firstAttribute="top" secondItem="s98-hk-uUP" secondAttribute="bottom" constant="20" id="elb-sf-8LP"/> - <constraint firstItem="s98-hk-uUP" firstAttribute="top" secondItem="eeP-9N-ZRP" secondAttribute="bottom" constant="10" id="o8u-gE-61X"/> + <constraint firstItem="eeP-9N-ZRP" firstAttribute="top" secondItem="6HO-NK-obf" secondAttribute="bottom" constant="20" id="eqV-Ls-16q"/> <constraint firstItem="eeP-9N-ZRP" firstAttribute="leading" secondItem="ILQ-5j-b92" secondAttribute="leading" id="pNx-zH-54E"/> <constraint firstItem="we1-Q7-8Us" firstAttribute="leading" secondItem="ILQ-5j-b92" secondAttribute="leading" constant="20" id="uvM-m5-Ofp"/> <constraint firstItem="s98-hk-uUP" firstAttribute="centerX" secondItem="ILQ-5j-b92" secondAttribute="centerX" id="vLn-iu-xOz"/> <constraint firstItem="ILQ-5j-b92" firstAttribute="trailing" secondItem="eeP-9N-ZRP" secondAttribute="trailing" id="yxz-bK-MTp"/> </constraints> - <viewLayoutGuide key="safeArea" id="ILQ-5j-b92"/> </view> <navigationItem key="navigationItem" id="YB9-Lg-X9d"/> <connections> @@ -97,7 +93,7 @@ <navigationController automaticallyAdjustsScrollViewInsets="NO" id="hTm-e0-ORl" sceneMemberID="viewController"> <toolbarItems/> <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="erz-WY-qOP"> - <rect key="frame" x="0.0" y="20" width="375" height="44"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="44"/> <autoresizingMask key="autoresizingMask"/> </navigationBar> <nil name="viewControllers"/> diff --git a/iOSClient/Main/NCFunctionCenter.swift b/iOSClient/Main/NCFunctionCenter.swift index fca6d01f8..55378f930 100644 --- a/iOSClient/Main/NCFunctionCenter.swift +++ b/iOSClient/Main/NCFunctionCenter.swift @@ -25,14 +25,13 @@ import UIKit import NCCommunication import Queuer import JGProgressHUD +import SVGKit @objc class NCFunctionCenter: NSObject, UIDocumentInteractionControllerDelegate, NCSelectDelegate { @objc public static let shared: NCFunctionCenter = { let instance = NCFunctionCenter() - NotificationCenter.default.addObserver(instance, selector: #selector(downloadedFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDownloadedFile), object: nil) NotificationCenter.default.addObserver(instance, selector: #selector(uploadedFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadedFile), object: nil) - return instance }() @@ -44,126 +43,121 @@ import JGProgressHUD @objc func downloadedFile(_ notification: NSNotification) { - if let userInfo = notification.userInfo as NSDictionary? { - if let ocId = userInfo["ocId"] as? String, let selector = userInfo["selector"] as? String, let errorCode = userInfo["errorCode"] as? Int, let errorDescription = userInfo["errorDescription"] as? String, let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) { - - if metadata.account != appDelegate.account { return } - - if errorCode == 0 { - - switch selector { - case NCGlobal.shared.selectorLoadFileQuickLook: - - let fileNamePath = NSTemporaryDirectory() + metadata.fileNameView - CCUtility.copyFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView), toPath: fileNamePath) - - var editingMode = false - if #available(iOS 13.0, *) { - editingMode = true - } - - let viewerQuickLook = NCViewerQuickLook(with: URL(fileURLWithPath: fileNamePath), editingMode: editingMode, metadata: metadata) - let navigationController = UINavigationController(rootViewController: viewerQuickLook) - navigationController.modalPresentationStyle = .overFullScreen - - self.appDelegate.window?.rootViewController?.present(navigationController, animated: true) - - case NCGlobal.shared.selectorLoadFileView: - - if UIApplication.shared.applicationState == UIApplication.State.active { - - if metadata.contentType.contains("opendocument") && !NCUtility.shared.isRichDocument(metadata) { - - self.openDocumentController(metadata: metadata) - - } else if metadata.classFile == NCCommunicationCommon.typeClassFile.compress.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.unknow.rawValue { - - self.openDocumentController(metadata: metadata) - - } else { - - if let viewController = self.appDelegate.activeViewController { - let imageIcon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) - NCViewer.shared.view(viewController: viewController, metadata: metadata, metadatas: [metadata], imageIcon: imageIcon) - } - } - } - - case NCGlobal.shared.selectorOpenIn: - - if UIApplication.shared.applicationState == UIApplication.State.active { - - self.openDocumentController(metadata: metadata) - } - - case NCGlobal.shared.selectorLoadCopy: - - copyPasteboard() - - case NCGlobal.shared.selectorLoadOffline: - - NCManageDatabase.shared.setLocalFile(ocId: metadata.ocId, offline: true) - - case NCGlobal.shared.selectorPrint: - - printDocument(metadata: metadata) - - case NCGlobal.shared.selectorSaveAlbum: - - saveAlbum(metadata: metadata) - - case NCGlobal.shared.selectorSaveBackground: - - saveBackground(metadata: metadata) - - case NCGlobal.shared.selectorSaveAlbumLivePhotoIMG, NCGlobal.shared.selectorSaveAlbumLivePhotoMOV: - - var metadata = metadata - var metadataMOV = metadata - guard let metadataTMP = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) else { break } - - if selector == NCGlobal.shared.selectorSaveAlbumLivePhotoIMG { - metadataMOV = metadataTMP - } - - if selector == NCGlobal.shared.selectorSaveAlbumLivePhotoMOV { - metadata = metadataTMP - } - - if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) && CCUtility.fileProviderStorageExists(metadataMOV.ocId, fileNameView: metadataMOV.fileNameView) { - saveLivePhotoToDisk(metadata: metadata, metadataMov: metadataMOV) - } + guard let userInfo = notification.userInfo as NSDictionary?, + let ocId = userInfo["ocId"] as? String, + let selector = userInfo["selector"] as? String, + let errorCode = userInfo["errorCode"] as? Int, + let errorDescription = userInfo["errorDescription"] as? String, + let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId), + metadata.account == appDelegate.account + else { return } + + guard errorCode == 0 else { + // File do not exists on server, remove in local + if errorCode == NCGlobal.shared.errorResourceNotFound || errorCode == NCGlobal.shared.errorBadServerResponse { + do { + try FileManager.default.removeItem(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId)) + } catch { } + NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) + NCManageDatabase.shared.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) + + } else { + NCContentPresenter.shared.messageNotification("_download_file_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode, priority: .max) + } + return + } + + switch selector { + case NCGlobal.shared.selectorLoadFileQuickLook: + let fileNamePath = NSTemporaryDirectory() + metadata.fileNameView + CCUtility.copyFile(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView), toPath: fileNamePath) + + var editingMode = false + if #available(iOS 13.0, *) { + editingMode = true + } - case NCGlobal.shared.selectorSaveAsScan: + let viewerQuickLook = NCViewerQuickLook(with: URL(fileURLWithPath: fileNamePath), editingMode: editingMode, metadata: metadata) + let navigationController = UINavigationController(rootViewController: viewerQuickLook) + navigationController.modalPresentationStyle = .overFullScreen - saveAsScan(metadata: metadata) + self.appDelegate.window?.rootViewController?.present(navigationController, animated: true) - case NCGlobal.shared.selectorOpenDetail: + case NCGlobal.shared.selectorLoadFileView: + guard UIApplication.shared.applicationState == UIApplication.State.active else { break } - NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterOpenMediaDetail, userInfo: ["ocId": metadata.ocId]) + if metadata.contentType.contains("opendocument") && !NCUtility.shared.isRichDocument(metadata) { + self.openDocumentController(metadata: metadata) + } else if metadata.classFile == NCCommunicationCommon.typeClassFile.compress.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.unknow.rawValue { + self.openDocumentController(metadata: metadata) + } else { + if let viewController = self.appDelegate.activeViewController { + let imageIcon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag)) + NCViewer.shared.view(viewController: viewController, metadata: metadata, metadatas: [metadata], imageIcon: imageIcon) + } + } + + case NCGlobal.shared.selectorOpenIn: + if UIApplication.shared.applicationState == UIApplication.State.active { + self.openDocumentController(metadata: metadata) + } + + case NCGlobal.shared.selectorLoadOffline: + NCManageDatabase.shared.setLocalFile(ocId: metadata.ocId, offline: true) + + case NCGlobal.shared.selectorPrint: + printDocument(metadata: metadata) + + case NCGlobal.shared.selectorSaveAlbum: + saveAlbum(metadata: metadata) + + case NCGlobal.shared.selectorSaveBackground: + saveBackground(metadata: metadata) + + case NCGlobal.shared.selectorSaveAlbumLivePhotoIMG, NCGlobal.shared.selectorSaveAlbumLivePhotoMOV: - default: + var metadata = metadata + var metadataMOV = metadata + guard let metadataTMP = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) else { break } - break - } + if selector == NCGlobal.shared.selectorSaveAlbumLivePhotoIMG { + metadataMOV = metadataTMP + } - } else { + if selector == NCGlobal.shared.selectorSaveAlbumLivePhotoMOV { + metadata = metadataTMP + } - // File do not exists on server, remove in local - if errorCode == NCGlobal.shared.errorResourceNotFound || errorCode == NCGlobal.shared.errorBadServerResponse { + if CCUtility.fileProviderStorageExists(metadata) && CCUtility.fileProviderStorageExists(metadataMOV) { + saveLivePhotoToDisk(metadata: metadata, metadataMov: metadataMOV) + } - do { - try FileManager.default.removeItem(atPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId)) - } catch { } + case NCGlobal.shared.selectorSaveAsScan: + saveAsScan(metadata: metadata) - NCManageDatabase.shared.deleteMetadata(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) - NCManageDatabase.shared.deleteLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) + case NCGlobal.shared.selectorOpenDetail: + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterOpenMediaDetail, userInfo: ["ocId": metadata.ocId]) - } else { + default: + break + } + } - NCContentPresenter.shared.messageNotification("_download_file_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode, priority: .max) - } - } + func setMetadataAvalableOffline(_ metadata: tableMetadata, isOffline: Bool) { + let serverUrl = metadata.serverUrl + "/" + metadata.fileName + if isOffline { + if metadata.directory { + NCManageDatabase.shared.setDirectory(serverUrl: serverUrl, offline: false, account: self.appDelegate.account) + } else { + NCManageDatabase.shared.setLocalFile(ocId: metadata.ocId, offline: false) + } + } else if metadata.directory { + NCManageDatabase.shared.setDirectory(serverUrl: serverUrl, offline: true, account: self.appDelegate.account) + NCOperationQueue.shared.synchronizationMetadata(metadata, selector: NCGlobal.shared.selectorDownloadAllFile) + } else { + NCNetworking.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorLoadOffline) { _ in } + if let metadataLivePhoto = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) { + NCNetworking.shared.download(metadata: metadataLivePhoto, selector: NCGlobal.shared.selectorLoadOffline) { _ in } } } } @@ -204,7 +198,7 @@ import JGProgressHUD func openDownload(metadata: tableMetadata, selector: String) { - if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + if CCUtility.fileProviderStorageExists(metadata) { NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDownloadedFile, userInfo: ["ocId": metadata.ocId, "selector": selector, "errorCode": 0, "errorDescription": "" ]) @@ -225,47 +219,35 @@ import JGProgressHUD documentController?.presentOptionsMenu(from: mainTabBar.menuRect, in: mainTabBar, animated: true) } - func openActivityViewController(selectOcId: [String]) { - - NCUtility.shared.startActivityIndicator(backgroundView: nil, blurEffect: true) - - var error: Int = 0 - var items: [Any] = [] + func openActivityViewController(selectedMetadata: [tableMetadata]) { + let metadatas = selectedMetadata.filter({ !$0.directory }) + var items: [URL] = [] + var downloadMetadata: [(tableMetadata, URL)] = [] - for ocId in selectOcId { - if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) { - if metadata.directory { - continue - } - if !CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { - let semaphore = Semaphore() - NCNetworking.shared.download(metadata: metadata, selector: "") { errorCode in - error = errorCode - semaphore.continue() - } - semaphore.wait() - } - if error != 0 { - break - } - let fileURL = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)) - items.append(fileURL) + for metadata in metadatas { + let fileURL = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)) + if CCUtility.fileProviderStorageExists(metadata) { items.append(fileURL) } + else { downloadMetadata.append((metadata, fileURL)) } + } + + let processor = ParallelWorker(n: 5, titleKey: "_downloading_", totalTasks: downloadMetadata.count, hudView: self.appDelegate.window?.rootViewController?.view) + for (metadata, url) in downloadMetadata { + processor.execute { completion in + NCNetworking.shared.download(metadata: metadata, selector: "", completion: { _ in + if CCUtility.fileProviderStorageExists(metadata) { items.append(url) } + completion() + }) } } - if error == 0 && items.count > 0 { - - guard let mainTabBar = self.appDelegate.mainTabBar else { return } + processor.completeWork { + guard !items.isEmpty, let mainTabBar = self.appDelegate.mainTabBar else { return } let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: nil) - activityViewController.popoverPresentationController?.permittedArrowDirections = .any activityViewController.popoverPresentationController?.sourceView = mainTabBar activityViewController.popoverPresentationController?.sourceRect = mainTabBar.menuRect - self.appDelegate.window?.rootViewController?.present(activityViewController, animated: true) - } - NCUtility.shared.stopActivityIndicator() } // MARK: - Save as scan @@ -278,7 +260,7 @@ import JGProgressHUD NCUtilityFileSystem.shared.copyFile(atPath: fileNamePath, toPath: fileNamePathDestination) - let storyboard = UIStoryboard(name: "Scan", bundle: nil) + let storyboard = UIStoryboard(name: "NCScan", bundle: nil) let navigationController = storyboard.instantiateInitialViewController()! navigationController.modalPresentationStyle = UIModalPresentationStyle.pageSheet @@ -289,21 +271,37 @@ import JGProgressHUD // MARK: - Print func printDocument(metadata: tableMetadata) { - let fileNameURL = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!) + let printController = UIPrintInteractionController.shared + let printInfo = UIPrintInfo(dictionary: nil) + printInfo.jobName = fileNameURL.lastPathComponent + printInfo.outputType = metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue ? .photo : .general + printController.printInfo = printInfo + printController.showsNumberOfCopies = true + + guard !UIPrintInteractionController.canPrint(fileNameURL) else { + printController.printingItem = fileNameURL + printController.present(animated: true) + return + } - if UIPrintInteractionController.canPrint(fileNameURL) { - - let printInfo = UIPrintInfo(dictionary: nil) - printInfo.jobName = fileNameURL.lastPathComponent - printInfo.outputType = .photo + // can't print without data + guard let data = try? Data(contentsOf: fileNameURL) else { return } - let printController = UIPrintInteractionController.shared - printController.printInfo = printInfo - printController.showsNumberOfCopies = true - printController.printingItem = fileNameURL - printController.present(animated: true, completionHandler: nil) + if let svg = SVGKImage(data: data) { + printController.printingItem = svg.uiImage + printController.present(animated: true) + return } + + guard let text = String(data: data, encoding: .utf8) else { return } + let formatter = UISimpleTextPrintFormatter(text: text) + formatter.perPageContentInsets.top = 72 + formatter.perPageContentInsets.bottom = 72 + formatter.perPageContentInsets.left = 72 + formatter.perPageContentInsets.right = 72 + printController.printFormatter = formatter + printController.present(animated: true) } // MARK: - Save photo @@ -344,15 +342,15 @@ import JGProgressHUD func saveLivePhoto(metadata: tableMetadata, metadataMOV: tableMetadata) { - if !CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + if !CCUtility.fileProviderStorageExists(metadata) { NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorSaveAlbumLivePhotoIMG) } - if !CCUtility.fileProviderStorageExists(metadataMOV.ocId, fileNameView: metadataMOV.fileNameView) { + if !CCUtility.fileProviderStorageExists(metadataMOV) { NCOperationQueue.shared.download(metadata: metadataMOV, selector: NCGlobal.shared.selectorSaveAlbumLivePhotoMOV) } - if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) && CCUtility.fileProviderStorageExists(metadataMOV.ocId, fileNameView: metadataMOV.fileNameView) { + if CCUtility.fileProviderStorageExists(metadata) && CCUtility.fileProviderStorageExists(metadataMOV) { saveLivePhotoToDisk(metadata: metadata, metadataMov: metadataMOV) } } @@ -418,100 +416,74 @@ import JGProgressHUD // MARK: - Copy & Paste - func copyPasteboard() { - - var metadatas: [tableMetadata] = [] + func copyPasteboard(pasteboardOcIds: [String], hudView: UIView) { var items = [[String: Any]]() - - for ocId in appDelegate.pasteboardOcIds { - if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) { - metadatas.append(metadata) + let hud = JGProgressHUD() + hud.textLabel.text = NSLocalizedString("_wait_", comment: "") + hud.show(in: hudView) + + // getting file data can take some time and block the main queue + DispatchQueue.global(qos: .userInitiated).async { + var downloadMetadatas: [tableMetadata] = [] + for ocid in pasteboardOcIds { + guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocid) else { continue } + if let pasteboardItem = metadata.toPasteBoardItem() { items.append(pasteboardItem) } + else { downloadMetadatas.append(metadata) } } - } - for metadata in metadatas { + DispatchQueue.main.async(execute: hud.dismiss) - if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { - do { - // Get Data - let data = try Data(contentsOf: URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView))) - // Pasteboard item - if let unmanagedFileUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (metadata.fileNameView as NSString).pathExtension as CFString, nil) { - let fileUTI = unmanagedFileUTI.takeRetainedValue() as String - items.append([fileUTI: data]) - } - } catch { - print("error") + // do 5 downloads in parallel to optimize efficiency + let parallelizer = ParallelWorker(n: 5, titleKey: "_downloading_", totalTasks: downloadMetadatas.count, hudView: hudView) + + for metadata in downloadMetadatas { + parallelizer.execute { completion in + NCNetworking.shared.download(metadata: metadata, selector: "") { _ in completion() } } - } else { - NCNetworking.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorLoadCopy) { _ in } + } + parallelizer.completeWork { + items.append(contentsOf: downloadMetadatas.compactMap({ $0.toPasteBoardItem() })) + UIPasteboard.general.setItems(items, options: [:]) } } + } - UIPasteboard.general.setItems(items, options: [:]) + func upload(fileName: String, serverUrlFileName: String, fileNameLocalPath: String, serverUrl: String, completion: @escaping () -> Void) { + NCCommunication.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath) { _ in + } progressHandler: { progress in + } completionHandler: { account, ocId, etag, _, _, _, errorCode, errorDescription in + if errorCode == 0 && etag != nil && ocId != nil { + let toPath = CCUtility.getDirectoryProviderStorageOcId(ocId!, fileNameView: fileName)! + NCUtilityFileSystem.shared.moveFile(atPath: fileNameLocalPath, toPath: toPath) + NCManageDatabase.shared.addLocalFile(account: account, etag: etag!, ocId: ocId!, fileName: fileName) + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced, userInfo: ["serverUrl": serverUrl]) + } else { + NCContentPresenter.shared.showError(description: errorDescription, errorCode: errorCode) + } + completion() + } } func pastePasteboard(serverUrl: String) { + let parallelizer = ParallelWorker(n: 5, titleKey: "_uploading_", totalTasks: nil, hudView: appDelegate.window?.rootViewController?.view) - var pasteboardTypes: [String] = [] - - func upload(pasteboardType: String?, data: Data?) -> Bool { - - guard let data = data else { return false} - guard let pasteboardType = pasteboardType else { return false } - - let results = NCCommunicationCommon.shared.getFileProperties(inUTI: pasteboardType as CFString) - if results.ext == "" { return false } - - do { + for (index, items) in UIPasteboard.general.items.enumerated() { + for item in items { + let results = NCCommunicationCommon.shared.getFileProperties(inUTI: item.key as CFString) + guard !results.ext.isEmpty, + let data = UIPasteboard.general.data(forPasteboardType: item.key, inItemSet: IndexSet([index]))?.first + else { continue } let fileName = results.name + "_" + CCUtility.getIncrementalNumber() + "." + results.ext let serverUrlFileName = serverUrl + "/" + fileName let ocIdUpload = UUID().uuidString let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(ocIdUpload, fileNameView: fileName)! - try data.write(to: URL(fileURLWithPath: fileNameLocalPath)) - let hud = JGProgressHUD() - - hud.indicatorView = JGProgressHUDRingIndicatorView() - if let indicatorView = hud.indicatorView as? JGProgressHUDRingIndicatorView { - indicatorView.ringWidth = 1.5 - } - hud.show(in: (appDelegate.window?.rootViewController?.view)!) - hud.textLabel.text = fileName - - NCCommunication.shared.upload(serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath) { _ in - } progressHandler: { progress in - hud.progress = Float(progress.fractionCompleted) - } completionHandler: { account, ocId, etag, _, _, _, errorCode, errorDescription in - if errorCode == 0 && etag != nil && ocId != nil { - let toPath = CCUtility.getDirectoryProviderStorageOcId(ocId!, fileNameView: fileName)! - NCUtilityFileSystem.shared.moveFile(atPath: fileNameLocalPath, toPath: toPath) - NCManageDatabase.shared.addLocalFile(account: account, etag: etag!, ocId: ocId!, fileName: fileName) - NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterReloadDataSourceNetworkForced, userInfo: ["serverUrl": serverUrl]) - hud.indicatorView = JGProgressHUDSuccessIndicatorView() - hud.textLabel.text = NSLocalizedString("_success_", comment: "") - } else { - hud.indicatorView = JGProgressHUDErrorIndicatorView() - hud.textLabel.text = NSLocalizedString(errorDescription, comment: "") - } - hud.dismiss(afterDelay: 1) - } - } catch { - return false - } - return true - } - - for (index, items) in UIPasteboard.general.items.enumerated() { - - for item in items { pasteboardTypes.append(item.key) } - - for typeIdentifier in pasteboardTypes { - let data = UIPasteboard.general.data(forPasteboardType: typeIdentifier, inItemSet: IndexSet([index]))?.first - if upload(pasteboardType: typeIdentifier, data: data) { - continue + do { try data.write(to: URL(fileURLWithPath: fileNameLocalPath)) } catch { continue } + parallelizer.execute { completion in + self.upload(fileName: fileName, serverUrlFileName: serverUrlFileName, fileNameLocalPath: fileNameLocalPath, serverUrl: serverUrl, completion: completion) } } } + parallelizer.completeWork() } // MARK: - @@ -575,7 +547,7 @@ import JGProgressHUD } } - func openSelectView(items: [Any], viewController: UIViewController) { + func openSelectView(items: [Any]) { let navigationController = UIStoryboard(name: "NCSelect", bundle: nil).instantiateInitialViewController() as! UINavigationController let topViewController = navigationController.topViewController as! NCSelect @@ -623,7 +595,7 @@ import JGProgressHUD navigationController.setViewControllers(listViewController, animated: false) navigationController.modalPresentationStyle = .formSheet - viewController.present(navigationController, animated: true, completion: nil) + appDelegate.window?.rootViewController?.present(navigationController, animated: true, completion: nil) } // MARK: - Context Menu Configuration @@ -658,8 +630,7 @@ import JGProgressHUD let titleOffline = isOffline ? NSLocalizedString("_remove_available_offline_", comment: "") : NSLocalizedString("_set_available_offline_", comment: "") let copy = UIAction(title: NSLocalizedString("_copy_file_", comment: ""), image: UIImage(systemName: "doc.on.doc")) { _ in - self.appDelegate.pasteboardOcIds = [metadata.ocId] - self.copyPasteboard() + self.copyPasteboard(pasteboardOcIds: [metadata.ocId], hudView: viewController.view) } let copyPath = UIAction(title: NSLocalizedString("_copy_path_", comment: ""), image: UIImage(systemName: "doc.on.clipboard")) { _ in @@ -673,26 +644,9 @@ import JGProgressHUD } let offline = UIAction(title: titleOffline, image: UIImage(systemName: "tray.and.arrow.down")) { _ in - if isOffline { - if metadata.directory { - NCManageDatabase.shared.setDirectory(serverUrl: serverUrl, offline: false, account: self.appDelegate.account) - } else { - NCManageDatabase.shared.setLocalFile(ocId: metadata.ocId, offline: false) - } - } else { - if metadata.directory { - NCManageDatabase.shared.setDirectory(serverUrl: serverUrl, offline: true, account: self.appDelegate.account) - NCOperationQueue.shared.synchronizationMetadata(metadata, selector: NCGlobal.shared.selectorDownloadAllFile) - } else { - NCNetworking.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorLoadOffline) { _ in } - if let metadataLivePhoto = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) { - NCNetworking.shared.download(metadata: metadataLivePhoto, selector: NCGlobal.shared.selectorLoadOffline) { _ in } - } - } - } - - if viewController is NCCollectionViewCommon { - (viewController as! NCCollectionViewCommon).reloadDataSource() + self.setMetadataAvalableOffline(metadata, isOffline: isOffline) + if let viewController = viewController as? NCCollectionViewCommon { + viewController.reloadDataSource() } } @@ -700,7 +654,7 @@ import JGProgressHUD if metadataMOV != nil { self.saveLivePhoto(metadata: metadata, metadataMOV: metadataMOV!) } else { - if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + if CCUtility.fileProviderStorageExists(metadata) { self.saveAlbum(metadata: metadata) } else { NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorSaveAlbum) @@ -709,7 +663,7 @@ import JGProgressHUD } let saveBackground = UIAction(title: NSLocalizedString("_use_as_background_", comment: ""), image: UIImage(systemName: "text.below.photo")) { _ in - if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + if CCUtility.fileProviderStorageExists(metadata) { self.saveBackground(metadata: metadata) } else { NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorSaveBackground) @@ -739,7 +693,7 @@ import JGProgressHUD // let open = UIMenu(title: NSLocalizedString("_open_", comment: ""), image: UIImage(systemName: "square.and.arrow.up"), children: [openIn, openQuickLook]) let moveCopy = UIAction(title: NSLocalizedString("_move_or_copy_", comment: ""), image: UIImage(systemName: "arrow.up.right.square")) { _ in - self.openSelectView(items: [metadata], viewController: viewController) + self.openSelectView(items: [metadata]) } let rename = UIAction(title: NSLocalizedString("_rename_", comment: ""), image: UIImage(systemName: "pencil")) { _ in @@ -833,3 +787,17 @@ import JGProgressHUD return UIMenu(title: "", children: [detail, submenu]) } } + +fileprivate extension tableMetadata { + func toPasteBoardItem() -> [String: Any]? { + // Get Data + let fileUrl = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(ocId, fileNameView: fileNameView)) + guard CCUtility.fileProviderStorageExists(self), + let data = try? Data(contentsOf: fileUrl), + let unmanagedFileUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension as CFString, nil) + else { return nil } + // Pasteboard item + let fileUTI = unmanagedFileUTI.takeRetainedValue() as String + return [fileUTI: data] + } +} diff --git a/iOSClient/Media/NCMedia.swift b/iOSClient/Media/NCMedia.swift index 1c92ea5cf..aebb00c67 100644 --- a/iOSClient/Media/NCMedia.swift +++ b/iOSClient/Media/NCMedia.swift @@ -133,6 +133,12 @@ class NCMedia: UIViewController, NCEmptyDataSetDelegate, NCSelectDelegate { } } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + mediaCommandTitle() + } + override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) diff --git a/iOSClient/Menu/NCCollectionViewCommon+Menu.swift b/iOSClient/Menu/NCCollectionViewCommon+Menu.swift index e4cfb8b0b..2cfb5e7d3 100644 --- a/iOSClient/Menu/NCCollectionViewCommon+Menu.swift +++ b/iOSClient/Menu/NCCollectionViewCommon+Menu.swift @@ -5,9 +5,11 @@ // Created by Philippe Weidmann on 24.01.20. // Copyright © 2020 Philippe Weidmann. All rights reserved. // Copyright © 2020 Marino Faggiana All rights reserved. +// Copyright © 2022 Henrik Storch. All rights reserved. // // Author Philippe Weidmann // 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 @@ -38,34 +40,13 @@ extension NCCollectionViewCommon { let serverUrl = metadata.serverUrl + "/" + metadata.fileName let isFolderEncrypted = CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase) let serverUrlHome = NCUtilityFileSystem.shared.getHomeServer(account: appDelegate.account) - var isOffline = false + let isOffline: Bool - var titleDelete = NSLocalizedString("_delete_", comment: "") - if NCManageDatabase.shared.isMetadataShareOrMounted(metadata: metadata, metadataFolder: metadataFolder) { - titleDelete = NSLocalizedString("_leave_share_", comment: "") - } else if metadata.directory { - titleDelete = NSLocalizedString("_delete_folder_", comment: "") - } else { - titleDelete = NSLocalizedString("_delete_file_", comment: "") - } - - if let metadataFolder = metadataFolder { - let isShare = metadata.permissions.contains(NCGlobal.shared.permissionShared) && !metadataFolder.permissions.contains(NCGlobal.shared.permissionShared) - let isMounted = metadata.permissions.contains(NCGlobal.shared.permissionMounted) && !metadataFolder.permissions.contains(NCGlobal.shared.permissionMounted) - if isShare || isMounted { - titleDelete = NSLocalizedString("_leave_share_", comment: "") - } - } - - if metadata.directory { - if let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, serverUrl)) { - isOffline = directory.offline - } - } else { - if let localFile = NCManageDatabase.shared.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) { - isOffline = localFile.offline - } - } + if metadata.directory, let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", appDelegate.account, serverUrl)) { + isOffline = directory.offline + } else if let localFile = NCManageDatabase.shared.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) { + isOffline = localFile.offline + } else { isOffline = false } let editors = NCUtility.shared.isDirectEditing(account: metadata.account, contentType: metadata.contentType) let isRichDocument = NCUtility.shared.isRichDocument(metadata) @@ -126,32 +107,7 @@ extension NCCollectionViewCommon { // OFFLINE // if !isFolderEncrypted { - actions.append( - NCMenuAction( - title: isOffline ? NSLocalizedString("_remove_available_offline_", comment: "") : NSLocalizedString("_set_available_offline_", comment: ""), - icon: NCUtility.shared.loadImage(named: "tray.and.arrow.down"), - action: { _ in - if isOffline { - if metadata.directory { - NCManageDatabase.shared.setDirectory(serverUrl: serverUrl, offline: false, account: self.appDelegate.account) - } else { - NCManageDatabase.shared.setLocalFile(ocId: metadata.ocId, offline: false) - } - } else { - if metadata.directory { - NCManageDatabase.shared.setDirectory(serverUrl: serverUrl, offline: true, account: self.appDelegate.account) - NCOperationQueue.shared.synchronizationMetadata(metadata, selector: NCGlobal.shared.selectorDownloadAllFile) - } else { - NCNetworking.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorLoadOffline) { _ in } - if let metadataLivePhoto = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) { - NCNetworking.shared.download(metadata: metadataLivePhoto, selector: NCGlobal.shared.selectorLoadOffline) { _ in } - } - } - } - self.reloadDataSource() - } - ) - ) + actions.append(.setAvailableOfflineAction(selectedMetadatas: [metadata], isAnyOffline: isOffline, viewController: self, completion: self.reloadDataSource)) } // @@ -190,67 +146,21 @@ extension NCCollectionViewCommon { // OPEN IN // if !metadata.directory && !NCBrandOptions.shared.disable_openin_file { - actions.append( - NCMenuAction( - title: NSLocalizedString("_open_in_", comment: ""), - icon: NCUtility.shared.loadImage(named: "square.and.arrow.up"), - action: { menuAction in - if self is NCFileViewInFolder { - self.dismiss(animated: true) { - NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorOpenIn) - } - } else { - NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorOpenIn) - } - } - ) - ) + actions.append(.openInAction(selectedMetadatas: [metadata], viewController: self)) } // // PRINT // - if (metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && metadata.contentType != "image/svg+xml") || metadata.contentType == "application/pdf" || metadata.contentType == "com.adobe.pdf" { - actions.append( - NCMenuAction( - title: NSLocalizedString("_print_", comment: ""), - icon: NCUtility.shared.loadImage(named: "printer"), - action: { _ in - NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorPrint) - } - ) - ) + if metadata.isPrintable { + actions.append(.printAction(metadata: metadata)) } // // SAVE // if (metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && metadata.contentType != "image/svg+xml") || metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue { - var title: String = NSLocalizedString("_save_selected_files_", comment: "") - var icon = NCUtility.shared.loadImage(named: "square.and.arrow.down") - let metadataMOV = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) - if metadataMOV != nil { - title = NSLocalizedString("_livephoto_save_", comment: "") - icon = NCUtility.shared.loadImage(named: "livephoto") - } - - actions.append( - NCMenuAction( - title: title, - icon: icon, - action: { _ in - if metadataMOV != nil { - 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) - } - } - } - ) - ) + actions.append(.saveMediaAction(selectedMediaMetadatas: [metadata])) } // @@ -298,31 +208,14 @@ extension NCCollectionViewCommon { // COPY - MOVE // if !isFolderEncrypted && serverUrl != "" { - actions.append( - NCMenuAction( - title: NSLocalizedString("_move_or_copy_", comment: ""), - icon: NCUtility.shared.loadImage(named: "arrow.up.right.square"), - action: { _ in - NCFunctionCenter.shared.openSelectView(items: [metadata], viewController: self) - } - ) - ) + actions.append(.moveOrCopyAction(selectedMetadatas: [metadata])) } // // COPY // if !metadata.directory { - actions.append( - NCMenuAction( - title: NSLocalizedString("_copy_file_", comment: ""), - icon: NCUtility.shared.loadImage(named: "doc.on.doc"), - action: { _ in - self.appDelegate.pasteboardOcIds = [metadata.ocId] - NCFunctionCenter.shared.copyPasteboard() - } - ) - ) + actions.append(.copyAction(selectOcId: [metadata.ocId], hudView: self.view)) } /* @@ -374,23 +267,7 @@ extension NCCollectionViewCommon { // // DELETE // - actions.append( - NCMenuAction( - title: titleDelete, - icon: NCUtility.shared.loadImage(named: "trash"), - action: { _ in - let alertController = UIAlertController(title: "", message: metadata.fileNameView + "\n\n" + NSLocalizedString("_want_delete_", comment: ""), preferredStyle: .alert) - alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_delete_", comment: ""), style: .default) { (_: UIAlertAction) in - NCOperationQueue.shared.delete(metadata: metadata, onlyLocalCache: false) - }) - alertController.addAction(UIAlertAction(title: NSLocalizedString("_remove_local_file_", comment: ""), style: .default) { (_: UIAlertAction) in - NCOperationQueue.shared.delete(metadata: metadata, onlyLocalCache: true) - }) - alertController.addAction(UIAlertAction(title: NSLocalizedString("_no_delete_", comment: ""), style: .default) { (_: UIAlertAction) in }) - self.present(alertController, animated: true, completion: nil) - } - ) - ) + actions.append(.deleteAction(selectedMetadatas: [metadata], metadataFolder: metadataFolder, viewController: self)) // // SET FOLDER E2EE @@ -444,137 +321,4 @@ extension NCCollectionViewCommon { 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) - } } diff --git a/iOSClient/Menu/NCMedia+Menu.swift b/iOSClient/Menu/NCMedia+Menu.swift index 5b2efe67c..5454dd3eb 100644 --- a/iOSClient/Menu/NCMedia+Menu.swift +++ b/iOSClient/Menu/NCMedia+Menu.swift @@ -26,11 +26,18 @@ import FloatingPanel import NCCommunication extension NCMedia { + func tapSelect() { + self.isEditMode = false + self.selectOcId.removeAll() + self.reloadDataThenPerform { } + } func toggleMenu() { var actions: [NCMenuAction] = [] + defer { presentMenu(with: actions) } + if !isEditMode { if metadatas.count > 0 { actions.append( @@ -137,129 +144,37 @@ extension NCMedia { NCMenuAction( title: NSLocalizedString("_cancel_", comment: ""), icon: NCUtility.shared.loadImage(named: "xmark"), - action: { _ in - self.isEditMode = false - self.selectOcId.removeAll() - self.reloadDataThenPerform { } - } + action: { _ in self.tapSelect() } ) ) + guard !selectOcId.isEmpty else { return } + let selectedMetadatas = selectOcId.compactMap(NCManageDatabase.shared.getMetadataFromOcId) + // // OPEN IN // - actions.append( - NCMenuAction( - title: NSLocalizedString("_open_in_", comment: ""), - icon: NCUtility.shared.loadImage(named: "square.and.arrow.up"), - action: { _ in - self.isEditMode = false - NCFunctionCenter.shared.openActivityViewController(selectOcId: self.selectOcId) - self.selectOcId.removeAll() - self.reloadDataThenPerform { } - } - ) - ) + actions.append(.openInAction(selectedMetadatas: selectedMetadatas, viewController: self, completion: 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.isEditMode = false - 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.selectOcId.removeAll() - self.reloadDataThenPerform { } - } - ) - ) + actions.append(.saveMediaAction(selectedMediaMetadatas: selectedMetadatas, completion: 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 - self.isEditMode = false - 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.selectOcId.removeAll() - self.reloadDataThenPerform { } - } - ) - ) + actions.append(.moveOrCopyAction(selectedMetadatas: selectedMetadatas, completion: tapSelect)) // // COPY // - actions.append( - NCMenuAction( - title: NSLocalizedString("_copy_file_", comment: ""), - icon: NCUtility.shared.loadImage(named: "doc.on.doc"), - action: { _ in - self.isEditMode = false - self.appDelegate.pasteboardOcIds.removeAll() - for ocId in self.selectOcId { - self.appDelegate.pasteboardOcIds.append(ocId) - } - NCFunctionCenter.shared.copyPasteboard() - self.selectOcId.removeAll() - self.reloadDataThenPerform { } - } - ) - ) + actions.append(.copyAction(selectOcId: selectOcId, hudView: self.view, completion: tapSelect)) // // DELETE // - actions.append( - NCMenuAction( - title: NSLocalizedString("_delete_selected_files_", comment: ""), - icon: NCUtility.shared.loadImage(named: "trash"), - action: { _ in - self.isEditMode = false - for ocId in self.selectOcId { - if let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) { - NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: false) { errorCode, errorDescription in - if errorCode != 0 { - NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode) - } - } - } - } - self.selectOcId.removeAll() - self.reloadDataThenPerform { } - } - ) - ) + actions.append(.deleteAction(selectedMetadatas: selectedMetadatas, metadataFolder: nil, viewController: self, completion: tapSelect)) } - - presentMenu(with: actions) } } diff --git a/iOSClient/Menu/NCMenu.swift b/iOSClient/Menu/NCMenu.swift index a174b62d7..4c0e2a50a 100644 --- a/iOSClient/Menu/NCMenu.swift +++ b/iOSClient/Menu/NCMenu.swift @@ -115,33 +115,3 @@ extension NCMenu: FloatingPanelControllerDelegate { fpc.dismiss(animated: true, completion: nil) } } - -class NCMenuAction { - - let title: String - let icon: UIImage - let selectable: Bool - var onTitle: String? - var onIcon: UIImage? - var selected: Bool = false - var isOn: Bool = false - var action: ((_ menuAction: NCMenuAction) -> Void)? - - init(title: String, icon: UIImage, action: ((_ menuAction: NCMenuAction) -> Void)?) { - self.title = title - self.icon = icon - self.action = action - self.selectable = false - } - - init(title: String, icon: UIImage, onTitle: String? = nil, onIcon: UIImage? = nil, selected: Bool, on: Bool, action: ((_ menuAction: NCMenuAction) -> Void)?) { - self.title = title - self.icon = icon - self.onTitle = onTitle ?? title - self.onIcon = onIcon ?? icon - self.action = action - self.selected = selected - self.isOn = on - self.selectable = true - } -} diff --git a/iOSClient/Menu/NCMenuAction.swift b/iOSClient/Menu/NCMenuAction.swift new file mode 100644 index 000000000..03f17b2c1 --- /dev/null +++ b/iOSClient/Menu/NCMenuAction.swift @@ -0,0 +1,215 @@ +// +// NCMenuAction.swift +// Nextcloud +// +// Created by Henrik Storch on 17.02.22. +// Copyright © 2022 Marino Faggiana. All rights reserved. +// + +import Foundation +import UIKit + +class NCMenuAction { + let title: String + let icon: UIImage + let selectable: Bool + var onTitle: String? + var onIcon: UIImage? + var selected: Bool = false + var isOn: Bool = false + var action: ((_ menuAction: NCMenuAction) -> Void)? + + init(title: String, icon: UIImage, action: ((_ menuAction: NCMenuAction) -> Void)?) { + self.title = title + self.icon = icon + self.action = action + self.selectable = false + } + + init(title: String, icon: UIImage, onTitle: String? = nil, onIcon: UIImage? = nil, selected: Bool, on: Bool, action: ((_ menuAction: NCMenuAction) -> Void)?) { + self.title = title + self.icon = icon + self.onTitle = onTitle ?? title + self.onIcon = onIcon ?? icon + self.action = action + self.selected = selected + self.isOn = on + self.selectable = true + } +} + +// MARK: - Actions + +extension NCMenuAction { + + /// Select all items + static func selectAllAction(action: @escaping () -> Void) -> NCMenuAction { + NCMenuAction( + title: NSLocalizedString("_select_all_", comment: ""), + icon: NCUtility.shared.loadImage(named: "checkmark.circle.fill"), + action: { _ in action() } + ) + } + + /// Copy files to pasteboard + static func copyAction(selectOcId: [String], hudView: UIView, completion: (() -> Void)? = nil) -> NCMenuAction { + NCMenuAction( + title: NSLocalizedString("_copy_file_", comment: ""), + icon: NCUtility.shared.loadImage(named: "doc.on.doc"), + action: { _ in + NCFunctionCenter.shared.copyPasteboard(pasteboardOcIds: selectOcId, hudView: hudView) + completion?() + } + ) + } + + /// Delete files either from cache or from Nextcloud + static func deleteAction(selectedMetadatas: [tableMetadata], metadataFolder: tableMetadata? = nil, viewController: UIViewController, completion: (() -> Void)? = nil) -> NCMenuAction { + var titleDelete = NSLocalizedString("_delete_", comment: "") + if selectedMetadatas.count > 1 { + titleDelete = NSLocalizedString("_delete_selected_files_", comment: "") + } else if let metadata = selectedMetadatas.first { + if NCManageDatabase.shared.isMetadataShareOrMounted(metadata: metadata, metadataFolder: metadataFolder) { + titleDelete = NSLocalizedString("_leave_share_", comment: "") + } else if metadata.directory { + titleDelete = NSLocalizedString("_delete_folder_", comment: "") + } else { + titleDelete = NSLocalizedString("_delete_file_", comment: "") + } + + if let metadataFolder = metadataFolder { + let isShare = metadata.permissions.contains(NCGlobal.shared.permissionShared) && !metadataFolder.permissions.contains(NCGlobal.shared.permissionShared) + let isMounted = metadata.permissions.contains(NCGlobal.shared.permissionMounted) && !metadataFolder.permissions.contains(NCGlobal.shared.permissionMounted) + if isShare || isMounted { + titleDelete = NSLocalizedString("_leave_share_", comment: "") + } + } + } // else: no metadata selected + + var fileList = "" + for (ix, metadata) in selectedMetadatas.enumerated() { + guard ix < 3 else { fileList += "\n - ..."; break } + fileList += "\n - " + metadata.fileName + } + + return NCMenuAction( + title: titleDelete, + icon: NCUtility.shared.loadImage(named: "trash"), + action: { _ in + let alertController = UIAlertController( + title: titleDelete, + message: NSLocalizedString("_want_delete_", comment: "") + fileList, + preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_delete_", comment: ""), style: .default) { (_: UIAlertAction) in + selectedMetadatas.forEach({ NCOperationQueue.shared.delete(metadata: $0, onlyLocalCache: false) }) + completion?() + }) + + // NCMedia removes image from collection view if removed from cache + if !(viewController is NCMedia) { + alertController.addAction(UIAlertAction(title: NSLocalizedString("_remove_local_file_", comment: ""), style: .default) { (_: UIAlertAction) in + selectedMetadatas.forEach({ NCOperationQueue.shared.delete(metadata: $0, onlyLocalCache: true) }) + completion?() + }) + } + alertController.addAction(UIAlertAction(title: NSLocalizedString("_no_delete_", comment: ""), style: .default) { (_: UIAlertAction) in }) + viewController.present(alertController, animated: true, completion: nil) + } + ) + } + + /// Open "share view" (activity VC) to open files in another app + static func openInAction(selectedMetadatas: [tableMetadata], viewController: UIViewController, completion: (() -> Void)? = nil) -> NCMenuAction { + NCMenuAction( + title: NSLocalizedString("_open_in_", comment: ""), + icon: NCUtility.shared.loadImage(named: "square.and.arrow.up"), + action: { _ in + if viewController is NCFileViewInFolder { + viewController.dismiss(animated: true) { + NCFunctionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas) + } + } else { + NCFunctionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas) + } + completion?() + } + ) + } + + /// Save selected files to user's photo library + static func saveMediaAction(selectedMediaMetadatas: [tableMetadata], completion: (() -> Void)? = nil) -> NCMenuAction { + var title: String = NSLocalizedString("_save_selected_files_", comment: "") + var icon = NCUtility.shared.loadImage(named: "square.and.arrow.down") + if selectedMediaMetadatas.allSatisfy({ NCManageDatabase.shared.getMetadataLivePhoto(metadata: $0) != nil }) { + title = NSLocalizedString("_livephoto_save_", comment: "") + icon = NCUtility.shared.loadImage(named: "livephoto") + } + + return NCMenuAction( + title: title, + icon: icon, + action: { _ in + for metadata in selectedMediaMetadatas { + if let metadataMOV = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) { + NCFunctionCenter.shared.saveLivePhoto(metadata: metadata, metadataMOV: metadataMOV) + } else { + if CCUtility.fileProviderStorageExists(metadata) { + NCFunctionCenter.shared.saveAlbum(metadata: metadata) + } else { + NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorSaveAlbum) + } + } + } + completion?() + } + ) + } + + /// Set (or remove) a file as *available offline*. Downloads the file if not downloaded already + static func setAvailableOfflineAction(selectedMetadatas: [tableMetadata], isAnyOffline: Bool, viewController: UIViewController, completion: (() -> Void)? = nil) -> NCMenuAction { + NCMenuAction( + title: isAnyOffline ? NSLocalizedString("_remove_available_offline_", comment: "") : NSLocalizedString("_set_available_offline_", comment: ""), + icon: NCUtility.shared.loadImage(named: "tray.and.arrow.down"), + action: { _ in + if !isAnyOffline, selectedMetadatas.count > 3 { + let alert = UIAlertController( + title: NSLocalizedString("_set_available_offline_", comment: ""), + message: NSLocalizedString("_select_offline_warning_", comment: ""), + preferredStyle: .alert) + alert.addAction(UIAlertAction(title: NSLocalizedString("_continue_", comment: ""), style: .default, handler: { _ in + selectedMetadatas.forEach { NCFunctionCenter.shared.setMetadataAvalableOffline($0, isOffline: isAnyOffline) } + completion?() + })) + alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel)) + viewController.present(alert, animated: true) + } else { + selectedMetadatas.forEach { NCFunctionCenter.shared.setMetadataAvalableOffline($0, isOffline: isAnyOffline) } + completion?() + } + } + ) + } + + /// Open view that lets the user move or copy the files within Nextcloud + static func moveOrCopyAction(selectedMetadatas: [tableMetadata], completion: (() -> Void)? = nil) -> NCMenuAction { + NCMenuAction( + title: NSLocalizedString("_move_or_copy_selected_files_", comment: ""), + icon: NCUtility.shared.loadImage(named: "arrow.up.right.square"), + action: { _ in + NCFunctionCenter.shared.openSelectView(items: selectedMetadatas) + completion?() + } + ) + } + + /// Open AirPrint view to print a single file + static func printAction(metadata: tableMetadata) -> NCMenuAction { + NCMenuAction( + title: NSLocalizedString("_print_", comment: ""), + icon: NCUtility.shared.loadImage(named: "printer"), + action: { _ in + NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorPrint) + } + ) + } +} diff --git a/iOSClient/Menu/NCTrash+Menu.swift b/iOSClient/Menu/NCTrash+Menu.swift index 05831d9e0..e3677651d 100644 --- a/iOSClient/Menu/NCTrash+Menu.swift +++ b/iOSClient/Menu/NCTrash+Menu.swift @@ -4,8 +4,10 @@ // // Created by Marino Faggiana on 03/03/2021. // Copyright © 2021 Marino Faggiana. All rights reserved. +// 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 @@ -26,101 +28,82 @@ import FloatingPanel import NCCommunication extension NCTrash { - - func toggleMenuMoreHeader() { - - 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) - } - ) + var selectActions: [NCMenuAction] { + [ + NCMenuAction( + title: NSLocalizedString("_trash_restore_selected_", comment: ""), + icon: NCUtility.shared.loadImage(named: "restore"), + action: { _ in + self.selectOcId.forEach(self.restoreItem) + self.tapSelect() + } + ), + 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(self.deleteItem) + self.tapSelect() + })) + 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?) { + func toggleMenuMoreHeader() { 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( 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( NCMenuAction( - title: NSLocalizedString("_delete_", comment: ""), + title: NSLocalizedString("_trash_delete_all_", comment: ""), icon: NCUtility.shared.loadImage(named: "trash"), 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 { 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! if let icon = UIImage(contentsOfFile: CCUtility.getDirectoryProviderStorageIconOcId(tableTrash.fileId, etag: tableTrash.fileName)) { iconHeader = icon diff --git a/iOSClient/Menu/NCViewer+Menu.swift b/iOSClient/Menu/NCViewer+Menu.swift index 6a23fb6d9..e85354bce 100644 --- a/iOSClient/Menu/NCViewer+Menu.swift +++ b/iOSClient/Menu/NCViewer+Menu.swift @@ -29,29 +29,14 @@ extension NCViewer { func toggleMenu(viewController: UIViewController, metadata: tableMetadata, webView: Bool, imageIcon: UIImage?) { + guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(metadata.ocId) else { return } + var actions = [NCMenuAction]() - var titleFavorite = NSLocalizedString("_add_favorites_", comment: "") if metadata.favorite { titleFavorite = NSLocalizedString("_remove_favorites_", comment: "") } let localFile = NCManageDatabase.shared.getTableLocalFile(predicate: NSPredicate(format: "ocId == %@", metadata.ocId)) - - var titleOffline = "" - if localFile == nil || localFile!.offline == false { - titleOffline = NSLocalizedString("_set_available_offline_", comment: "") - } else { - titleOffline = NSLocalizedString("_remove_available_offline_", comment: "") - } - - var titleDelete = NSLocalizedString("_delete_", comment: "") - if NCManageDatabase.shared.isMetadataShareOrMounted(metadata: metadata, metadataFolder: nil) { - titleDelete = NSLocalizedString("_leave_share_", comment: "") - } else if metadata.directory { - titleDelete = NSLocalizedString("_delete_folder_", comment: "") - } else { - titleDelete = NSLocalizedString("_delete_file_", comment: "") - } - let isFolderEncrypted = CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase) + let isOffline = localFile?.offline == true // // FAVORITE @@ -89,34 +74,14 @@ extension NCViewer { // OFFLINE // if metadata.session == "" && !webView { - actions.append( - NCMenuAction( - title: titleOffline, - icon: NCUtility.shared.loadImage(named: "tray.and.arrow.down"), - action: { _ in - if (localFile == nil || !CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView)) && metadata.session == "" { - NCNetworking.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorLoadOffline) { _ in } - } else { - NCManageDatabase.shared.setLocalFile(ocId: metadata.ocId, offline: !localFile!.offline) - } - } - ) - ) + actions.append(.setAvailableOfflineAction(selectedMetadatas: [metadata], isAnyOffline: isOffline, viewController: viewController)) } // // OPEN IN // if metadata.session == "" && !webView { - actions.append( - NCMenuAction( - title: NSLocalizedString("_open_in_", comment: ""), - icon: NCUtility.shared.loadImage(named: "square.and.arrow.up"), - action: { _ in - NCFunctionCenter.shared.openDownload(metadata: metadata, selector: NCGlobal.shared.selectorOpenIn) - } - ) - ) + actions.append(.openInAction(selectedMetadatas: [metadata], viewController: viewController)) } // @@ -142,7 +107,7 @@ extension NCViewer { actions.append( NCMenuAction( - title: NSLocalizedString("_video_conversion_", comment: ""), + title: NSLocalizedString("_video_processing_", comment: ""), icon: NCUtility.shared.loadImage(named: "film"), action: { menuAction in if let ncplayer = (viewController as? NCViewerMediaPage)?.currentViewController.ncplayer { @@ -158,28 +123,7 @@ extension NCViewer { // SAVE IMAGE / VIDEO // if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue { - - var title: String = NSLocalizedString("_save_selected_files_", comment: "") - var icon = NCUtility.shared.loadImage(named: "square.and.arrow.down") - let metadataMOV = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) - if metadataMOV != nil { - title = NSLocalizedString("_livephoto_save_", comment: "") - icon = NCUtility.shared.loadImage(named: "livephoto") - } - - actions.append( - NCMenuAction( - title: title, - icon: icon, - action: { _ in - if metadataMOV != nil { - NCFunctionCenter.shared.saveLivePhoto(metadata: metadata, metadataMOV: metadataMOV!) - } else { - NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorSaveAlbum) - } - } - ) - ) + actions.append(.saveMediaAction(selectedMediaMetadatas: [metadata])) } // @@ -228,39 +172,13 @@ extension NCViewer { // COPY - MOVE // if !webView { - actions.append( - NCMenuAction( - title: NSLocalizedString("_move_or_copy_", comment: ""), - icon: NCUtility.shared.loadImage(named: "arrow.up.right.square"), - action: { _ in - - let storyboard = UIStoryboard(name: "NCSelect", bundle: nil) - let navigationController = storyboard.instantiateInitialViewController() as! UINavigationController - let viewController = navigationController.topViewController as! NCSelect - - viewController.delegate = NCViewer.shared - viewController.typeOfCommandView = .copyMove - viewController.items = [metadata] - - self.appDelegate.window?.rootViewController?.present(navigationController, animated: true, completion: nil) - } - ) - ) + actions.append(.moveOrCopyAction(selectedMetadatas: [metadata])) } // // COPY // - actions.append( - NCMenuAction( - title: NSLocalizedString("_copy_file_", comment: ""), - icon: NCUtility.shared.loadImage(named: "doc.on.doc"), - action: { _ in - self.appDelegate.pasteboardOcIds = [metadata.ocId] - NCFunctionCenter.shared.copyPasteboard() - } - ) - ) + actions.append(.copyAction(selectOcId: [metadata.ocId], hudView: viewController.view)) // // VIEW IN FOLDER @@ -281,7 +199,7 @@ extension NCViewer { // DOWNLOAD IMAGE MAX RESOLUTION // if metadata.session == "" { - if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && !CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) && metadata.session == "" { + if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && !CCUtility.fileProviderStorageExists(metadata) && metadata.session == "" { actions.append( NCMenuAction( title: NSLocalizedString("_download_image_max_", comment: ""), @@ -365,29 +283,7 @@ extension NCViewer { // DELETE // if !webView { - actions.append( - NCMenuAction( - title: titleDelete, - 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 - - NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: false) { errorCode, errorDescription in - if errorCode != 0 { - NCContentPresenter.shared.messageNotification("_error_", description: errorDescription, delay: NCGlobal.shared.dismissAfterSecond, type: NCContentPresenter.messageType.error, errorCode: errorCode) - } - } - }) - - alertController.addAction(UIAlertAction(title: NSLocalizedString("_no_delete_", comment: ""), style: .default) { (_: UIAlertAction) in }) - - viewController.present(alertController, animated: true, completion: nil) - } - ) - ) + actions.append(.deleteAction(selectedMetadatas: [metadata], metadataFolder: nil, viewController: viewController)) } viewController.presentMenu(with: actions) diff --git a/iOSClient/Menu/UIViewController+Menu.swift b/iOSClient/Menu/UIViewController+Menu.swift index 821827d24..d2463553d 100644 --- a/iOSClient/Menu/UIViewController+Menu.swift +++ b/iOSClient/Menu/UIViewController+Menu.swift @@ -35,7 +35,7 @@ extension UIViewController { url.scheme == "mailto", let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { - NCContentPresenter.shared.showGenericError(description: "_cannot_send_mail_error_") + NCContentPresenter.shared.showError(description: "_cannot_send_mail_error_") return } sendEmail(to: components.path) @@ -50,7 +50,7 @@ extension UIViewController { default: 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 } UIApplication.shared.open(url, options: [:]) @@ -94,7 +94,7 @@ extension UIViewController { func sendEmail(to email: String) { guard MFMailComposeViewController.canSendMail() else { - NCContentPresenter.shared.showGenericError(description: "_cannot_send_mail_error_") + NCContentPresenter.shared.showError(description: "_cannot_send_mail_error_") return } @@ -106,8 +106,9 @@ extension UIViewController { } func presentMenu(with actions: [NCMenuAction]) { + guard !actions.isEmpty else { return } guard let menuViewController = NCMenu.makeNCMenu(with: actions) else { - NCContentPresenter.shared.showGenericError(description: "_internal_generic_error_") + NCContentPresenter.shared.showError(description: "_internal_generic_error_") return } diff --git a/iOSClient/More/NCMore.swift b/iOSClient/More/NCMore.swift index 02e21a1bb..8f2be2f0e 100644 --- a/iOSClient/More/NCMore.swift +++ b/iOSClient/More/NCMore.swift @@ -145,7 +145,7 @@ class NCMore: UIViewController, UITableViewDelegate, UITableViewDataSource { item = NCCommunicationExternalSite() item.name = "_scanned_images_" item.icon = "doc.text.viewfinder" - item.url = "openStoryboardScan" + item.url = "openStoryboardNCScan" functionMenu.append(item) } diff --git a/iOSClient/NCGlobal.swift b/iOSClient/NCGlobal.swift index 0decbce5f..bae04f0cc 100644 --- a/iOSClient/NCGlobal.swift +++ b/iOSClient/NCGlobal.swift @@ -112,7 +112,7 @@ class NCGlobal: NSObject { // Database Realm // let databaseDefault = "nextcloud.realm" - let databaseSchemaVersion: UInt64 = 215 + let databaseSchemaVersion: UInt64 = 216 // Intro selector // @@ -272,7 +272,6 @@ class NCGlobal: NSObject { let selectorListingFavorite = "listingFavorite" let selectorLoadFileView = "loadFileView" let selectorLoadFileQuickLook = "loadFileQuickLook" - let selectorLoadCopy = "loadCopy" let selectorLoadOffline = "loadOffline" let selectorOpenIn = "openIn" let selectorPrint = "print" diff --git a/iOSClient/Networking/NCNetworking.swift b/iOSClient/Networking/NCNetworking.swift index 4ffd96360..19dccaedc 100644 --- a/iOSClient/Networking/NCNetworking.swift +++ b/iOSClient/Networking/NCNetworking.swift @@ -327,7 +327,7 @@ import Queuer } } - @objc func download(metadata: tableMetadata, selector: String, notificationCenterProgressTask: Bool = true, progressHandler: @escaping (_ progress: Progress) -> () = { _ in }, completion: @escaping (_ errorCode: Int)->()) { + @objc func download(metadata: tableMetadata, selector: String, notificationCenterProgressTask: Bool = true, progressHandler: @escaping (_ progress: Progress) -> Void = { _ in }, completion: @escaping (_ errorCode: Int) -> Void) { let serverUrlFileName = metadata.serverUrl + "/" + metadata.fileName let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileName)! @@ -363,7 +363,7 @@ import Queuer progressHandler(progress) - }) { (account, etag, date, length, allHeaderFields, error, errorCode, errorDescription) in + }) { (account, etag, date, _, allHeaderFields, error, errorCode, errorDescription) in if error?.isExplicitlyCancelledError ?? false { @@ -448,7 +448,7 @@ import Queuer let metadata = tableMetadata.init(value: metadata) - if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + if CCUtility.fileProviderStorageExists(metadata) { let fileNameLocalPath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)! let results = NCCommunicationCommon.shared.getInternalType(fileName: metadata.fileNameView, mimeType: metadata.contentType, directory: false) @@ -929,7 +929,9 @@ import Queuer @objc func createFolder(fileName: String, serverUrl: String, account: String, urlBase: String, overwrite: Bool = false, completion: @escaping (_ errorCode: Int, _ errorDescription: String) -> Void) { let isDirectoryEncrypted = CCUtility.isFolderEncrypted(serverUrl, e2eEncrypted: false, account: account, urlBase: urlBase) - + + let fileName = fileName.trimmingCharacters(in: .whitespacesAndNewlines) + if isDirectoryEncrypted { #if !EXTENSION NCNetworkingE2EE.shared.createFolder(fileName: fileName, serverUrl: serverUrl, account: account, urlBase: urlBase, completion: completion) @@ -1181,6 +1183,7 @@ import Queuer let isDirectoryEncrypted = CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase) let metadataLive = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) + let fileNameNew = fileNameNew.trimmingCharacters(in: .whitespacesAndNewlines) let fileNameNewLive = (fileNameNew as NSString).deletingPathExtension + ".mov" if isDirectoryEncrypted { @@ -1364,7 +1367,7 @@ import Queuer func getVideoUrl(metadata: tableMetadata, completition: @escaping (_ url: URL?) -> Void) { - if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + if CCUtility.fileProviderStorageExists(metadata) { completition(URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView))) diff --git a/iOSClient/Rename file/NCRenameFile.swift b/iOSClient/Rename file/NCRenameFile.swift index c96085ef0..57a661fd8 100644 --- a/iOSClient/Rename file/NCRenameFile.swift +++ b/iOSClient/Rename file/NCRenameFile.swift @@ -70,7 +70,7 @@ class NCRenameFile: UIViewController, UITextFieldDelegate { fileNameWithoutExt.delegate = self fileNameWithoutExt.becomeFirstResponder() - ext.text = (metadata.fileNameView as NSString).pathExtension + ext.text = metadata.fileExtension ext.delegate = self if disableChangeExt { ext.isEnabled = false @@ -176,7 +176,7 @@ class NCRenameFile: UIViewController, UITextFieldDelegate { } else { if ext.text == nil || ext.text?.count == 0 { - self.ext.text = (metadata.fileNameView as NSString).pathExtension + self.ext.text = metadata.fileExtension return } else { extNew = ext.text! @@ -196,7 +196,7 @@ class NCRenameFile: UIViewController, UITextFieldDelegate { title = NSLocalizedString("_keep_", comment: "") + " ." + metadata.ext alertController.addAction(UIAlertAction(title: title, style: .default, handler: { _ in - self.ext.text = (metadata.fileNameView as NSString).pathExtension + self.ext.text = metadata.fileExtension })) self.present(alertController, animated: true) diff --git a/iOSClient/ScanDocument/NCScan+CollectionView.swift b/iOSClient/ScanDocument/NCScan+CollectionView.swift new file mode 100644 index 000000000..34290e86f --- /dev/null +++ b/iOSClient/ScanDocument/NCScan+CollectionView.swift @@ -0,0 +1,226 @@ +// +// NCScan+CollectionView.swift +// Nextcloud +// +// Created by Marino Faggiana on 22/02/22. +// Copyright © 2022 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana <marino.faggiana@nextcloud.com> +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +import Foundation + +@available(iOS 13.0, *) +extension NCScan: UICollectionViewDataSource { + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + + return collectionView == collectionViewSource ? itemsSource.count : imagesDestination.count + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + + if collectionView == collectionViewSource { + + let cell = (collectionView.dequeueReusableCell(withReuseIdentifier: "cell1", for: indexPath) as? NCScanCell)! + + let fileNamePath = CCUtility.getDirectoryScan() + "/" + itemsSource[indexPath.row] + + guard let data = try? Data(contentsOf: URL(fileURLWithPath: fileNamePath)), var image = UIImage(data: data) else { return cell } + + let imageWidthInPixels = image.size.width * image.scale + let imageHeightInPixels = image.size.height * image.scale + + // 72 DPI + if imageWidthInPixels > 595 || imageHeightInPixels > 842 { + image = image.resizeImage(size: CGSize(width: 595, height: 842), isAspectRation: true) ?? image + } + + cell.customImageView?.image = image + cell.delete.action(for: .touchUpInside) { sender in + + let buttonPosition: CGPoint = (sender as? UIButton)!.convert(.zero, to: self.collectionViewSource) + if let indexPath = self.collectionViewSource.indexPathForItem(at: buttonPosition) { + + let fileNameAtPath = CCUtility.getDirectoryScan() + "/" + self.itemsSource[indexPath.row] + CCUtility.removeFile(atPath: fileNameAtPath) + self.itemsSource.remove(at: indexPath.row) + + self.collectionViewSource.deleteItems(at: [indexPath]) + } + } + + return cell + + } else { + + let cell = (collectionView.dequeueReusableCell(withReuseIdentifier: "cell2", for: indexPath) as? NCScanCell)! + cell.delegate = self + cell.index = indexPath.row + + var image = imagesDestination[indexPath.row] + + let imageWidthInPixels = image.size.width * image.scale + let imageHeightInPixels = image.size.height * image.scale + + // 72 DPI + if imageWidthInPixels > 595 || imageHeightInPixels > 842 { + image = image.resizeImage(size: CGSize(width: 595, height: 842), isAspectRation: true) ?? image + } + + cell.customImageView?.image = filter(image: image) + cell.customLabel.text = NSLocalizedString("_scan_document_pdf_page_", comment: "") + " " + "\(indexPath.row + 1)" + + return cell + } + } +} + +@available(iOS 13.0, *) +extension NCScan: UICollectionViewDragDelegate { + func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] { + + if collectionView == collectionViewSource { + let item = itemsSource[indexPath.row] + let itemProvider = NSItemProvider(object: item as NSString) + let dragItem = UIDragItem(itemProvider: itemProvider) + + dragItem.localObject = item + + return [dragItem] + + } else { + let item = imagesDestination[indexPath.row] + let itemProvider = NSItemProvider(object: item as UIImage) + let dragItem = UIDragItem(itemProvider: itemProvider) + + dragItem.localObject = item + + return [dragItem] + } + } + + func collectionView(_ collectionView: UICollectionView, itemsForAddingTo session: UIDragSession, at indexPath: IndexPath, point: CGPoint) -> [UIDragItem] { + + if collectionView == collectionViewSource { + let item = itemsSource[indexPath.row] + let itemProvider = NSItemProvider(object: item as NSString) + let dragItem = UIDragItem(itemProvider: itemProvider) + + dragItem.localObject = item + + return [dragItem] + + } else { + let item = imagesDestination[indexPath.row] + let itemProvider = NSItemProvider(object: item as UIImage) + let dragItem = UIDragItem(itemProvider: itemProvider) + + dragItem.localObject = item + + return [dragItem] + } + } + + func collectionView(_ collectionView: UICollectionView, dragPreviewParametersForItemAt indexPath: IndexPath) -> UIDragPreviewParameters? { + + let previewParameters = UIDragPreviewParameters() + if collectionView == collectionViewSource { + previewParameters.visiblePath = UIBezierPath(rect: CGRect(x: 20, y: 20, width: 100, height: 100)) + } else { + previewParameters.visiblePath = UIBezierPath(rect: CGRect(x: 20, y: 20, width: 80, height: 80)) + } + + return previewParameters + } +} + +@available(iOS 13.0, *) +extension NCScan: UICollectionViewDropDelegate { + + func collectionView(_ collectionView: UICollectionView, canHandle session: UIDropSession) -> Bool { + + return true // session.canLoadObjects(ofClass: NSString.self) + } + + func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal { + + if collectionView == collectionViewSource { + + if collectionView.hasActiveDrag { + return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath) + } else { + return UICollectionViewDropProposal(operation: .forbidden) + } + + } else { + + if collectionView.hasActiveDrag { + return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath) + } else { + return UICollectionViewDropProposal(operation: .copy, intent: .insertAtDestinationIndexPath) + } + } + } + + func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) { + + let destinationIndexPath: IndexPath + + switch coordinator.proposal.operation { + + case .move: + + if let indexPath = coordinator.destinationIndexPath { + + destinationIndexPath = indexPath + + } else { + + // Get last index path of table view. + let section = collectionView.numberOfSections - 1 + let row = collectionView.numberOfItems(inSection: section) + + destinationIndexPath = IndexPath(row: row, section: section) + } + reorderItems(coordinator: coordinator, destinationIndexPath: destinationIndexPath, collectionView: collectionView) + + case .copy: + + // Get last index path of table view. + let section = collectionView.numberOfSections - 1 + let row = collectionView.numberOfItems(inSection: section) + + destinationIndexPath = IndexPath(row: row, section: section) + copyItems(coordinator: coordinator, destinationIndexPath: destinationIndexPath, collectionView: collectionView) + + default: + return + } + } + + func collectionView(_ collectionView: UICollectionView, dropSessionDidEnd session: UIDropSession) { + + collectionViewDestination.reloadData() + + // Save button + if imagesDestination.isEmpty { + save.isEnabled = false + } else { + save.isEnabled = true + } + } +} diff --git a/iOSClient/ScanDocument/Scan.storyboard b/iOSClient/ScanDocument/NCScan.storyboard index 3395a9e9e..fafd2597a 100755 --- a/iOSClient/ScanDocument/Scan.storyboard +++ b/iOSClient/ScanDocument/NCScan.storyboard @@ -1,23 +1,23 @@ <?xml version="1.0" encoding="UTF-8"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="bdK-eL-mz4"> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="bdK-eL-mz4"> <device id="retina4_7" orientation="portrait" appearance="light"/> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> - <!--Drag Drop View Controller--> + <!--Scan--> <scene sceneID="tne-QT-ifu"> <objects> - <viewController extendedLayoutIncludesOpaqueBars="YES" id="BYZ-38-t0r" customClass="DragDropViewController" customModule="Nextcloud" customModuleProvider="target" sceneMemberID="viewController"> + <viewController extendedLayoutIncludesOpaqueBars="YES" id="BYZ-38-t0r" customClass="NCScan" customModule="Nextcloud" customModuleProvider="target" sceneMemberID="viewController"> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="jwq-kF-6Nq" userLabel="collectionViewSource"> - <rect key="frame" x="57" y="52" width="318" height="160"/> + <rect key="frame" x="57" y="44" width="318" height="160"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <constraints> <constraint firstAttribute="height" constant="160" id="0Wb-eO-Qiu"/> @@ -29,7 +29,7 @@ <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/> </collectionViewFlowLayout> <cells> - <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cell1" id="Lca-vD-NY2" customClass="ScanCell" customModule="Nextcloud" customModuleProvider="target"> + <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cell1" id="Lca-vD-NY2" customClass="NCScanCell" customModule="Nextcloud" customModuleProvider="target"> <rect key="frame" x="0.0" y="10" width="140" height="140"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO"> @@ -69,11 +69,8 @@ </connections> </collectionView> <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="fGo-qU-AYi" userLabel="collectionViewDestination"> - <rect key="frame" x="0.0" y="258" width="375" height="359"/> + <rect key="frame" x="0.0" y="239" width="375" height="378"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - <constraints> - <constraint firstAttribute="height" constant="339" id="nTl-vy-iQ8"/> - </constraints> <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="9Sn-Y3-S86"> <size key="itemSize" width="120" height="120"/> <size key="headerReferenceSize" width="0.0" height="0.0"/> @@ -81,7 +78,7 @@ <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/> </collectionViewFlowLayout> <cells> - <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cell2" id="Pph-tY-PGX" customClass="ScanCell" customModule="Nextcloud" customModuleProvider="target"> + <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cell2" id="Pph-tY-PGX" customClass="NCScanCell" customModule="Nextcloud" customModuleProvider="target"> <rect key="frame" x="0.0" y="0.0" width="120" height="120"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO"> @@ -108,6 +105,9 @@ <constraint firstAttribute="height" constant="23" id="QOj-Nj-nAA"/> </constraints> <state key="normal" image="deleteScan"/> + <connections> + <action selector="touchUpInsideDelete:" destination="Pph-tY-PGX" eventType="touchUpInside" id="KcT-WM-s1K"/> + </connections> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="XEo-o0-dSF" userLabel="Rotate"> <rect key="frame" x="98" y="0.0" width="22" height="22"/> @@ -116,6 +116,9 @@ <constraint firstAttribute="height" constant="22" id="fd5-QY-wlr"/> </constraints> <state key="normal" image="rotate"/> + <connections> + <action selector="touchUpInsideRotate:" destination="Pph-tY-PGX" eventType="touchUpInside" id="x5z-go-m4Y"/> + </connections> </button> </subviews> </view> @@ -146,7 +149,7 @@ </connections> </collectionView> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="PDF" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YHy-9G-ngy"> - <rect key="frame" x="0.0" y="220" width="375" height="30"/> + <rect key="frame" x="0.0" y="204" width="375" height="30"/> <color key="backgroundColor" white="1" alpha="0.5" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <constraints> <constraint firstAttribute="height" constant="30" id="vrg-ki-2Lk"/> @@ -156,7 +159,7 @@ <nil key="highlightedColor"/> </label> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0Gy-eG-A0f"> - <rect key="frame" x="20" y="82" width="30" height="30"/> + <rect key="frame" x="20" y="74" width="30" height="30"/> <constraints> <constraint firstAttribute="height" constant="30" id="A6e-zC-q5t"/> <constraint firstAttribute="width" constant="30" id="U2p-ow-Iad"/> @@ -181,7 +184,7 @@ </connections> </segmentedControl> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Fqr-e6-s3n" userLabel="transferDown"> - <rect key="frame" x="20" y="152" width="30" height="30"/> + <rect key="frame" x="20" y="144" width="30" height="30"/> <constraints> <constraint firstAttribute="height" constant="30" id="YPl-DJ-aNS"/> <constraint firstAttribute="width" constant="30" id="yGb-Y2-8Oj"/> @@ -199,7 +202,7 @@ <constraint firstItem="Fqr-e6-s3n" firstAttribute="top" secondItem="jwq-kF-6Nq" secondAttribute="bottom" constant="-60" id="5FJ-rD-ncI"/> <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="jwq-kF-6Nq" secondAttribute="trailing" id="6EM-YK-lEy"/> <constraint firstItem="jwq-kF-6Nq" firstAttribute="top" secondItem="0Gy-eG-A0f" secondAttribute="bottom" constant="-60" id="8D3-HY-PIM"/> - <constraint firstItem="YHy-9G-ngy" firstAttribute="top" secondItem="jwq-kF-6Nq" secondAttribute="bottom" constant="8" id="90f-NC-udY"/> + <constraint firstItem="YHy-9G-ngy" firstAttribute="top" secondItem="jwq-kF-6Nq" secondAttribute="bottom" id="90f-NC-udY"/> <constraint firstItem="0Gy-eG-A0f" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="20" id="BNZ-HM-6yi"/> <constraint firstItem="jwq-kF-6Nq" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="57" id="ELU-RG-o16"/> <constraint firstItem="fGo-qU-AYi" firstAttribute="trailing" secondItem="6Tk-OE-BBY" secondAttribute="trailing" id="Ew2-9q-DKl"/> @@ -208,11 +211,11 @@ <constraint firstAttribute="trailingMargin" secondItem="b3i-bF-ITj" secondAttribute="trailing" constant="8" id="Ogg-xT-qyc"/> <constraint firstItem="Fqr-e6-s3n" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="20" id="UJ4-nd-oV8"/> <constraint firstItem="fGo-qU-AYi" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" id="aU0-Bn-B6T"/> - <constraint firstItem="jwq-kF-6Nq" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="8" id="dyH-ym-lrb"/> + <constraint firstItem="jwq-kF-6Nq" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" id="dyH-ym-lrb"/> <constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="b3i-bF-ITj" secondAttribute="bottom" constant="11" id="iCt-vj-sDA"/> <constraint firstItem="b3i-bF-ITj" firstAttribute="top" secondItem="fGo-qU-AYi" secondAttribute="bottom" constant="12" id="kGQ-oN-ccm"/> <constraint firstItem="b3i-bF-ITj" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="p4i-a8-soi"/> - <constraint firstItem="fGo-qU-AYi" firstAttribute="top" secondItem="YHy-9G-ngy" secondAttribute="bottom" constant="8" id="x2i-aj-hzf"/> + <constraint firstItem="fGo-qU-AYi" firstAttribute="top" secondItem="YHy-9G-ngy" secondAttribute="bottom" constant="5" id="x2i-aj-hzf"/> </constraints> </view> <navigationItem key="navigationItem" id="zeb-Ex-mE8"> diff --git a/iOSClient/ScanDocument/NCScan.swift b/iOSClient/ScanDocument/NCScan.swift new file mode 100755 index 000000000..a5d395610 --- /dev/null +++ b/iOSClient/ScanDocument/NCScan.swift @@ -0,0 +1,372 @@ +// +// NCScan.swift +// Nextcloud +// +// Created by Marino Faggiana on 21/08/18. +// Copyright (c) 2018 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana <marino.faggiana@nextcloud.com> +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +import UIKit + +@available(iOS 13.0, *) +class NCScan: UIViewController, NCScanCellCellDelegate { + + @IBOutlet weak var collectionViewSource: UICollectionView! + @IBOutlet weak var collectionViewDestination: UICollectionView! + @IBOutlet weak var cancel: UIBarButtonItem! + @IBOutlet weak var save: UIBarButtonItem! + @IBOutlet weak var add: UIButton! + @IBOutlet weak var transferDown: UIButton! + @IBOutlet weak var labelTitlePDFzone: UILabel! + @IBOutlet weak var segmentControlFilter: UISegmentedControl! + + // Data Source for collectionViewSource + internal var itemsSource: [String] = [] + + // Data Source for collectionViewDestination + internal var imagesDestination: [UIImage] = [] + internal var itemsDestination: [String] = [] + + internal let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! + + enum TypeFilter { + case original + case grayScale + case bn + } + internal var filter: TypeFilter = TypeFilter.original + + // MARK: - View Life Cycle + + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + navigationItem.title = NSLocalizedString("_scanned_images_", comment: "") + + collectionViewSource.dragInteractionEnabled = true + collectionViewSource.dragDelegate = self + collectionViewSource.dropDelegate = self + collectionViewSource.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + + collectionViewDestination.dragInteractionEnabled = true + collectionViewDestination.dropDelegate = self + collectionViewDestination.dragDelegate = self + collectionViewDestination.reorderingCadence = .fast // default value - .immediate + collectionViewDestination.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground + + cancel.title = NSLocalizedString("_cancel_", comment: "") + save.title = NSLocalizedString("_save_", comment: "") + + labelTitlePDFzone.text = NSLocalizedString("_scan_label_document_zone_", comment: "") + labelTitlePDFzone.backgroundColor = NCBrandColor.shared.systemGray6 + labelTitlePDFzone.textColor = NCBrandColor.shared.label + + segmentControlFilter.setTitle(NSLocalizedString("_filter_original_", comment: ""), forSegmentAt: 0) + segmentControlFilter.setTitle(NSLocalizedString("_filter_grayscale_", comment: ""), forSegmentAt: 1) + segmentControlFilter.setTitle(NSLocalizedString("_filter_bn_", comment: ""), forSegmentAt: 2) + + add.setImage(UIImage(named: "plus")?.image(color: NCBrandColor.shared.label, size: 25), for: .normal) + transferDown.setImage(UIImage(named: "transferDown")?.image(color: NCBrandColor.shared.label, size: 25), for: .normal) + + let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressGesture(recognizer:))) + collectionViewSource.addGestureRecognizer(longPressRecognizer) + let longPressRecognizerPlus = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressGesture(recognizer:))) + add.addGestureRecognizer(longPressRecognizerPlus) + + collectionViewSource.reloadData() + collectionViewDestination.reloadData() + + loadImage() + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + add.setImage(UIImage(named: "plus")?.image(color: NCBrandColor.shared.label, size: 25), for: .normal) + transferDown.setImage(UIImage(named: "transferDown")?.image(color: NCBrandColor.shared.label, size: 25), for: .normal) + } + + override var canBecomeFirstResponder: Bool { return true } + + override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { + if action == #selector(pasteImage) { + return true + } + return false + } + + @IBAction func cancelAction(sender: UIBarButtonItem) { + self.dismiss(animated: true, completion: nil) + } + + @IBAction func saveAction(sender: UIBarButtonItem) { + + if !imagesDestination.isEmpty { + + var images: [UIImage] = [] + let serverUrl = appDelegate.activeServerUrl + + for image in imagesDestination { + images.append(filter(image: image)!) + } + + let formViewController = NCCreateFormUploadScanDocument(serverUrl: serverUrl, arrayImages: images) + self.navigationController?.pushViewController(formViewController, animated: true) + } + } + + @IBAction func add(sender: UIButton) { + + NCCreateScanDocument.shared.openScannerDocument(viewController: self) + } + + @IBAction func transferDown(sender: UIButton) { + + for fileName in itemsSource { + + if !itemsDestination.contains(fileName) { + + let fileNamePathAt = CCUtility.getDirectoryScan() + "/" + fileName + + guard let data = try? Data(contentsOf: URL(fileURLWithPath: fileNamePathAt)), let image = UIImage(data: data) else { return } + + imagesDestination.append(image) + itemsDestination.append(fileName) + } + } + + // Save button + if imagesDestination.isEmpty { + save.isEnabled = false + } else { + save.isEnabled = true + } + + collectionViewDestination.reloadData() + } + + @IBAction func indexChanged(_ sender: AnyObject) { + + switch segmentControlFilter.selectedSegmentIndex { + case 0: + filter = .original + case 1: + filter = .grayScale + case 2: + filter = .bn + default: + break + } + + collectionViewDestination.reloadData() + } + + func loadImage() { + + itemsSource.removeAll() + + do { + let atPath = CCUtility.getDirectoryScan()! + let directoryContents = try FileManager.default.contentsOfDirectory(atPath: atPath) + for fileName in directoryContents where fileName.first != "." { + itemsSource.append(fileName) + } + } catch { + print(error.localizedDescription) + } + + itemsSource = itemsSource.sorted() + + collectionViewSource.reloadData() + + // Save button + if imagesDestination.isEmpty { + save.isEnabled = false + } else { + save.isEnabled = true + } + } + + func filter(image: UIImage) -> UIImage? { + + var inputContrast: Double = 0 + + if filter == .original { + return image + } + + if filter == .grayScale { + inputContrast = 1 + } + + if filter == .bn { + inputContrast = 4 + } + + let ciImage = CIImage(image: image)! + let imageFilter = ciImage.applyingFilter("CIColorControls", parameters: ["inputSaturation": 0, "inputContrast": inputContrast]) + + let context: CIContext = CIContext(options: nil) + let cgImage: CGImage = context.createCGImage(imageFilter, from: imageFilter.extent)! + let image: UIImage = UIImage(cgImage: cgImage) + return image + } + + // destinationIndexPath: indexpath of the collection view where the user drops the element + // collectionView: collectionView in which reordering needs to be done. + + func reorderItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView) { + + let items = coordinator.items + + if items.count == 1, let item = items.first, let sourceIndexPath = item.sourceIndexPath { + + var dIndexPath = destinationIndexPath + + if dIndexPath.row >= collectionView.numberOfItems(inSection: 0) { + dIndexPath.row = collectionView.numberOfItems(inSection: 0) - 1 + } + + collectionView.performBatchUpdates({ + + if collectionView === collectionViewDestination { + + imagesDestination.remove(at: sourceIndexPath.row) + imagesDestination.insert((item.dragItem.localObject as? UIImage)!, at: dIndexPath.row) + + let fileName = itemsDestination[sourceIndexPath.row] + itemsDestination.remove(at: sourceIndexPath.row) + itemsDestination.insert(fileName, at: dIndexPath.row) + + } else { + + itemsSource.remove(at: sourceIndexPath.row) + itemsSource.insert((item.dragItem.localObject as? String)!, at: dIndexPath.row) + } + + collectionView.deleteItems(at: [sourceIndexPath]) + collectionView.insertItems(at: [dIndexPath]) + }) + + coordinator.drop(items.first!.dragItem, toItemAt: dIndexPath) + } + } + + func copyItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView) { + collectionView.performBatchUpdates({ + + var indexPaths: [IndexPath] = [] + + for (index, item) in coordinator.items.enumerated() { + + let indexPath = IndexPath(row: destinationIndexPath.row + index, section: destinationIndexPath.section) + + if collectionView === collectionViewDestination { + + let fileName = (item.dragItem.localObject as? String)! + let fileNamePathAt = CCUtility.getDirectoryScan() + "/" + fileName + + guard let data = try? Data(contentsOf: URL(fileURLWithPath: fileNamePathAt)), let image = UIImage(data: data) else { return } + + imagesDestination.insert(image, at: indexPath.row) + itemsDestination.insert(fileName, at: indexPath.row) + + } else { + + // NOT PERMITTED + return + } + + indexPaths.append(indexPath) + } + + collectionView.insertItems(at: indexPaths) + }) + } + + @objc func handleLongPressGesture(recognizer: UIGestureRecognizer) { + + if recognizer.state == UIGestureRecognizer.State.began { + + self.becomeFirstResponder() + + let pasteboard = UIPasteboard.general + + if let recognizerView = recognizer.view, let recognizerSuperView = recognizerView.superview, pasteboard.hasImages { + + UIMenuController.shared.menuItems = [UIMenuItem(title: "Paste", action: #selector(pasteImage))] + UIMenuController.shared.setTargetRect(recognizerView.frame, in: recognizerSuperView) + UIMenuController.shared.setMenuVisible(true, animated: true) + } + } + } + + @objc func pasteImage() { + + let pasteboard = UIPasteboard.general + + if pasteboard.hasImages { + + guard let image = pasteboard.image?.fixedOrientation() else { return } + + let fileName = CCUtility.createFileName("scan.png", fileDate: Date(), + fileType: PHAssetMediaType.image, + keyFileName: NCGlobal.shared.keyFileNameMask, + keyFileNameType: NCGlobal.shared.keyFileNameType, + keyFileNameOriginal: NCGlobal.shared.keyFileNameOriginal, + forcedNewFileName: true)! + let fileNamePath = CCUtility.getDirectoryScan() + "/" + fileName + + do { + try image.pngData()?.write(to: NSURL.fileURL(withPath: fileNamePath), options: .atomic) + } catch { + return + } + + loadImage() + } + } + + func delete(with imageIndex: Int, sender: Any) { + + imagesDestination.remove(at: imageIndex) + itemsDestination.remove(at: imageIndex) + + // Save button + if imagesDestination.isEmpty { + save.isEnabled = false + } else { + save.isEnabled = true + } + + collectionViewDestination.reloadData() + } + + func rotate(with imageIndex: Int, sender: Any) { + + let indexPath = IndexPath(row: imageIndex, section: 0) + if let cell = collectionViewDestination.cellForItem(at: indexPath) as? NCScanCell { + + var image = imagesDestination[imageIndex] + image = image.rotate(radians: .pi / 2)! + imagesDestination[imageIndex] = image + cell.customImageView.image = image + } + } +} diff --git a/iOSClient/ScanDocument/ScanCell.swift b/iOSClient/ScanDocument/NCScanCell.swift index 560efc8d3..d073d3e62 100755 --- a/iOSClient/ScanDocument/ScanCell.swift +++ b/iOSClient/ScanDocument/NCScanCell.swift @@ -1,5 +1,5 @@ // -// ScanCell.swift +// NCScanCell.swift // Nextcloud // // Created by Marino Faggiana on 21/08/18. @@ -23,10 +23,26 @@ import UIKit -class ScanCell: UICollectionViewCell { +class NCScanCell: UICollectionViewCell { @IBOutlet weak var customImageView: UIImageView! @IBOutlet weak var customLabel: UILabel! @IBOutlet weak var delete: UIButton! @IBOutlet weak var rotate: UIButton! + + weak var delegate: NCScanCellCellDelegate? + var index = 0 + + @IBAction func touchUpInsideDelete(_ sender: Any) { + delegate?.delete(with: index, sender: sender) + } + + @IBAction func touchUpInsideRotate(_ sender: Any) { + delegate?.rotate(with: index, sender: sender) + } +} + +protocol NCScanCellCellDelegate: AnyObject { + func delete(with index: Int, sender: Any) + func rotate(with index: Int, sender: Any) } diff --git a/iOSClient/ScanDocument/ScanCollectionView.swift b/iOSClient/ScanDocument/ScanCollectionView.swift deleted file mode 100755 index ad96a50b4..000000000 --- a/iOSClient/ScanDocument/ScanCollectionView.swift +++ /dev/null @@ -1,642 +0,0 @@ -// -// ScanCollectionView.swift -// Nextcloud -// -// Created by Marino Faggiana on 21/08/18. -// Copyright (c) 2018 Marino Faggiana. All rights reserved. -// -// Author Marino Faggiana <marino.faggiana@nextcloud.com> -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// - -import UIKit - -@available(iOS 13.0, *) -class DragDropViewController: UIViewController { - - // Data Source for collectionViewSource - private var itemsSource: [String] = [] - - // Data Source for collectionViewDestination - private var imagesDestination: [UIImage] = [] - private var itemsDestination: [String] = [] - - private let appDelegate = UIApplication.shared.delegate as! AppDelegate - - // MARK: Outlets - @IBOutlet weak var collectionViewSource: UICollectionView! - @IBOutlet weak var collectionViewDestination: UICollectionView! - @IBOutlet weak var cancel: UIBarButtonItem! - @IBOutlet weak var save: UIBarButtonItem! - @IBOutlet weak var add: UIButton! - @IBOutlet weak var transferDown: UIButton! - @IBOutlet weak var labelTitlePDFzone: UILabel! - @IBOutlet weak var segmentControlFilter: UISegmentedControl! - - // filter - enum typeFilter { - case original - case grayScale - case bn - } - private var filter: typeFilter = typeFilter.original - - override var canBecomeFirstResponder: Bool { return true } - - // MARK: - View Life Cycle - - override func viewDidLoad() { - super.viewDidLoad() - - view.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground - navigationItem.title = NSLocalizedString("_scanned_images_", comment: "") - - collectionViewSource.dragInteractionEnabled = true - collectionViewSource.dragDelegate = self - collectionViewSource.dropDelegate = self - collectionViewSource.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground - - collectionViewDestination.dragInteractionEnabled = true - collectionViewDestination.dropDelegate = self - collectionViewDestination.dragDelegate = self - collectionViewDestination.reorderingCadence = .fast // default value - .immediate - collectionViewDestination.backgroundColor = NCBrandColor.shared.secondarySystemGroupedBackground - - cancel.title = NSLocalizedString("_cancel_", comment: "") - save.title = NSLocalizedString("_save_", comment: "") - - labelTitlePDFzone.text = NSLocalizedString("_scan_label_document_zone_", comment: "") - labelTitlePDFzone.backgroundColor = NCBrandColor.shared.systemGray6 - labelTitlePDFzone.textColor = NCBrandColor.shared.label - - segmentControlFilter.setTitle(NSLocalizedString("_filter_original_", comment: ""), forSegmentAt: 0) - segmentControlFilter.setTitle(NSLocalizedString("_filter_grayscale_", comment: ""), forSegmentAt: 1) - segmentControlFilter.setTitle(NSLocalizedString("_filter_bn_", comment: ""), forSegmentAt: 2) - - add.setImage(UIImage(named: "plus")?.image(color: NCBrandColor.shared.label, size: 25), for: .normal) - transferDown.setImage(UIImage(named: "transferDown")?.image(color: NCBrandColor.shared.label, size: 25), for: .normal) - - let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressGesture(recognizer:))) - collectionViewSource.addGestureRecognizer(longPressRecognizer) - let longPressRecognizerPlus = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPressGesture(recognizer:))) - add.addGestureRecognizer(longPressRecognizerPlus) - - collectionViewSource.reloadData() - collectionViewDestination.reloadData() - - loadImage() - } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - - add.setImage(UIImage(named: "plus")?.image(color: NCBrandColor.shared.label, size: 25), for: .normal) - transferDown.setImage(UIImage(named: "transferDown")?.image(color: NCBrandColor.shared.label, size: 25), for: .normal) - } - - // MARK: Button Action - - @IBAction func cancelAction(sender: UIBarButtonItem) { - self.dismiss(animated: true, completion: nil) - } - - @IBAction func saveAction(sender: UIBarButtonItem) { - - if imagesDestination.count > 0 { - - var images: [UIImage] = [] - let serverUrl = appDelegate.activeServerUrl - - for image in imagesDestination { - images.append(filter(image: image)!) - } - -// if let directory = CCUtility.getDirectoryScanDocuments() { -// serverUrl = directory -// } - - let formViewController = NCCreateFormUploadScanDocument(serverUrl: serverUrl, arrayImages: images) - self.navigationController?.pushViewController(formViewController, animated: true) - } - } - - @IBAction func add(sender: UIButton) { - - NCCreateScanDocument.shared.openScannerDocument(viewController: self) - } - - @IBAction func transferDown(sender: UIButton) { - - for fileName in itemsSource { - - if !itemsDestination.contains(fileName) { - - let fileNamePathAt = CCUtility.getDirectoryScan() + "/" + fileName - - guard let data = try? Data(contentsOf: URL(fileURLWithPath: fileNamePathAt)) else { return } - guard let image = UIImage(data: data) else { return } - - imagesDestination.append(image) - itemsDestination.append(fileName) - } - } - - // Save button - if imagesDestination.count == 0 { - save.isEnabled = false - } else { - save.isEnabled = true - } - - collectionViewDestination.reloadData() - } - - @IBAction func indexChanged(_ sender: AnyObject) { - - switch segmentControlFilter.selectedSegmentIndex { - case 0: - filter = typeFilter.original - case 1: - filter = typeFilter.grayScale - case 2: - filter = typeFilter.bn - default: - break - } - - collectionViewDestination.reloadData() - } - - func loadImage() { - - itemsSource.removeAll() - - do { - let atPath = CCUtility.getDirectoryScan()! - let directoryContents = try FileManager.default.contentsOfDirectory(atPath: atPath) - for fileName in directoryContents { - if fileName.first != "." { - itemsSource.append(fileName) - } - } - } catch { - print(error.localizedDescription) - } - - itemsSource = itemsSource.sorted() - - collectionViewSource.reloadData() - - // Save button - if imagesDestination.count == 0 { - save.isEnabled = false - } else { - save.isEnabled = true - } - } - - // MARK: Private Methods - - func filter(image: UIImage) -> UIImage? { - - var inputContrast: Double = 0 - - if filter == typeFilter.original { - return image - } - - if filter == typeFilter.grayScale { - inputContrast = 1 - } - - if filter == typeFilter.bn { - inputContrast = 4 - } - - let ciImage = CIImage(image: image)! - let imageFilter = ciImage.applyingFilter("CIColorControls", parameters: ["inputSaturation": 0, "inputContrast": inputContrast]) - - let context: CIContext = CIContext(options: nil) - let cgImage: CGImage = context.createCGImage(imageFilter, from: imageFilter.extent)! - let image: UIImage = UIImage(cgImage: cgImage) - return image - } - - /// This method moves a cell from source indexPath to destination indexPath within the same collection view. It works for only 1 item. If multiple items selected, no reordering happens. - /// - /// - Parameters: - /// - coordinator: coordinator obtained from performDropWith: UICollectionViewDropDelegate method - /// - destinationIndexPath: indexpath of the collection view where the user drops the element - /// - collectionView: collectionView in which reordering needs to be done. - - private func reorderItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView) { - - let items = coordinator.items - - if items.count == 1, let item = items.first, let sourceIndexPath = item.sourceIndexPath { - - var dIndexPath = destinationIndexPath - - if dIndexPath.row >= collectionView.numberOfItems(inSection: 0) { - dIndexPath.row = collectionView.numberOfItems(inSection: 0) - 1 - } - - collectionView.performBatchUpdates({ - - if collectionView === collectionViewDestination { - - imagesDestination.remove(at: sourceIndexPath.row) - imagesDestination.insert(item.dragItem.localObject as! UIImage, at: dIndexPath.row) - - let fileName = itemsDestination[sourceIndexPath.row] - itemsDestination.remove(at: sourceIndexPath.row) - itemsDestination.insert(fileName, at: dIndexPath.row) - - } else { - - itemsSource.remove(at: sourceIndexPath.row) - itemsSource.insert(item.dragItem.localObject as! String, at: dIndexPath.row) - } - - collectionView.deleteItems(at: [sourceIndexPath]) - collectionView.insertItems(at: [dIndexPath]) - }) - - coordinator.drop(items.first!.dragItem, toItemAt: dIndexPath) - } - } - - /// This method copies a cell from source indexPath in 1st collection view to destination indexPath in 2nd collection view. It works for multiple items. - /// - /// - Parameters: - /// - coordinator: coordinator obtained from performDropWith: UICollectionViewDropDelegate method - /// - destinationIndexPath: indexpath of the collection view where the user drops the element - /// - collectionView: collectionView in which reordering needs to be done. - - private func copyItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView) { - collectionView.performBatchUpdates({ - - var indexPaths: [IndexPath] = [] - - for (index, item) in coordinator.items.enumerated() { - - let indexPath = IndexPath(row: destinationIndexPath.row + index, section: destinationIndexPath.section) - - if collectionView === collectionViewDestination { - - let fileName = item.dragItem.localObject as! String - let fileNamePathAt = CCUtility.getDirectoryScan() + "/" + fileName - - guard let data = try? Data(contentsOf: URL(fileURLWithPath: fileNamePathAt)) else { - return - } - guard let image = UIImage(data: data) else { - return - } - - imagesDestination.insert(image, at: indexPath.row) - itemsDestination.insert(fileName, at: indexPath.row) - - } else { - - // NOT PERMITTED - return - } - - indexPaths.append(indexPath) - } - - collectionView.insertItems(at: indexPaths) - }) - } - - // MARK: - UIGestureRecognizerv - Paste - - @objc func handleLongPressGesture(recognizer: UIGestureRecognizer) { - - if recognizer.state == UIGestureRecognizer.State.began { - - self.becomeFirstResponder() - - let pasteboard = UIPasteboard.general - - if let recognizerView = recognizer.view, let recognizerSuperView = recognizerView.superview, pasteboard.hasImages { - - UIMenuController.shared.menuItems = [UIMenuItem(title: "Paste", action: #selector(pasteImage))] - UIMenuController.shared.setTargetRect(recognizerView.frame, in: recognizerSuperView) - UIMenuController.shared.setMenuVisible(true, animated: true) - } - } - } - - override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { - if action == #selector(pasteImage) { - return true - } - return false - } - - @objc func pasteImage() { - - let pasteboard = UIPasteboard.general - - if pasteboard.hasImages { - - let fileName = CCUtility.createFileName("scan.png", fileDate: Date(), fileType: PHAssetMediaType.image, keyFileName: NCGlobal.shared.keyFileNameMask, keyFileNameType: NCGlobal.shared.keyFileNameType, keyFileNameOriginal: NCGlobal.shared.keyFileNameOriginal, forcedNewFileName: true)! - let fileNamePath = CCUtility.getDirectoryScan() + "/" + fileName - - guard let image = pasteboard.image?.fixedOrientation() else { - return - } - - do { - try image.pngData()?.write(to: NSURL.fileURL(withPath: fileNamePath), options: .atomic) - } catch { - return - } - - loadImage() - } - } -} - -// MARK: - UICollectionViewDataSource Methods - -@available(iOS 13.0, *) -extension DragDropViewController: UICollectionViewDataSource { - - func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - - return collectionView == collectionViewSource ? itemsSource.count : imagesDestination.count - } - - func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - - if collectionView == collectionViewSource { - - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell1", for: indexPath) as! ScanCell - - let fileNamePath = CCUtility.getDirectoryScan() + "/" + itemsSource[indexPath.row] - - guard let data = try? Data(contentsOf: URL(fileURLWithPath: fileNamePath)) else { - return cell - } - - guard var image = UIImage(data: data) else { - return cell - } - - let imageWidthInPixels = image.size.width * image.scale - let imageHeightInPixels = image.size.height * image.scale - - // 72 DPI - if imageWidthInPixels > 595 || imageHeightInPixels > 842 { - image = image.resizeImage(size: CGSize(width: 595, height: 842), isAspectRation: true) ?? image - } - - cell.customImageView?.image = image - cell.delete.action(for: .touchUpInside) { sender in - - let buttonPosition: CGPoint = (sender as! UIButton).convert(.zero, to: self.collectionViewSource) - if let indexPath = self.collectionViewSource.indexPathForItem(at: buttonPosition) { - - let fileNameAtPath = CCUtility.getDirectoryScan() + "/" + self.itemsSource[indexPath.row] - CCUtility.removeFile(atPath: fileNameAtPath) - self.itemsSource.remove(at: indexPath.row) - - self.collectionViewSource.reloadData() - } - } - - return cell - - } else { - - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell2", for: indexPath) as! ScanCell - - var image = imagesDestination[indexPath.row] - - let imageWidthInPixels = image.size.width * image.scale - let imageHeightInPixels = image.size.height * image.scale - - // 72 DPI - if imageWidthInPixels > 595 || imageHeightInPixels > 842 { - image = image.resizeImage(size: CGSize(width: 595, height: 842), isAspectRation: true) ?? image - } - - cell.customImageView?.image = self.filter(image: image) - cell.customLabel.text = NSLocalizedString("_scan_document_pdf_page_", comment: "") + " " + "\(indexPath.row+1)" - cell.delete.action(for: .touchUpInside) { sender in - - let buttonPosition: CGPoint = (sender as! UIButton).convert(.zero, to: self.collectionViewDestination) - if let indexPath = self.collectionViewDestination.indexPathForItem(at: buttonPosition) { - - self.imagesDestination.remove(at: indexPath.row) - self.itemsDestination.remove(at: indexPath.row) - - self.collectionViewDestination.reloadData() - - // Save button - if self.imagesDestination.count == 0 { - self.save.isEnabled = false - } else { - self.save.isEnabled = true - } - } - } - cell.rotate.action(for: .touchUpInside) { sender in - - let buttonPosition: CGPoint = (sender as! UIButton).convert(.zero, to: self.collectionViewDestination) - if let indexPath = self.collectionViewDestination.indexPathForItem(at: buttonPosition) { - - let image = self.imagesDestination[indexPath.row] - self.imagesDestination[indexPath.row] = image.rotate(radians: .pi/2)! - - self.collectionViewDestination.reloadData() - } - } - - return cell - } - } -} - -extension UIImage { - func rotate(radians: Float) -> UIImage? { - var newSize = CGRect(origin: CGPoint.zero, size: self.size).applying(CGAffineTransform(rotationAngle: CGFloat(radians))).size - // Trim off the extremely small float value to prevent core graphics from rounding it up - newSize.width = floor(newSize.width) - newSize.height = floor(newSize.height) - - UIGraphicsBeginImageContextWithOptions(newSize, true, self.scale) - let context = UIGraphicsGetCurrentContext()! - - // Move origin to middle - context.translateBy(x: newSize.width/2, y: newSize.height/2) - // Rotate around middle - context.rotate(by: CGFloat(radians)) - // Draw the image at its center - self.draw(in: CGRect(x: -self.size.width/2, y: -self.size.height/2, width: self.size.width, height: self.size.height)) - - let newImage = UIGraphicsGetImageFromCurrentImageContext() - UIGraphicsEndImageContext() - - return newImage - } -} - -// MARK: - UICollectionViewDragDelegate Methods - -@available(iOS 13.0, *) -extension DragDropViewController: UICollectionViewDragDelegate { - func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] { - - if collectionView == collectionViewSource { - let item = itemsSource[indexPath.row] - let itemProvider = NSItemProvider(object: item as NSString) - let dragItem = UIDragItem(itemProvider: itemProvider) - - dragItem.localObject = item - - return [dragItem] - - } else { - let item = imagesDestination[indexPath.row] - let itemProvider = NSItemProvider(object: item as UIImage) - let dragItem = UIDragItem(itemProvider: itemProvider) - - dragItem.localObject = item - - return [dragItem] - } - } - - func collectionView(_ collectionView: UICollectionView, itemsForAddingTo session: UIDragSession, at indexPath: IndexPath, point: CGPoint) -> [UIDragItem] { - - if collectionView == collectionViewSource { - let item = itemsSource[indexPath.row] - let itemProvider = NSItemProvider(object: item as NSString) - let dragItem = UIDragItem(itemProvider: itemProvider) - - dragItem.localObject = item - - return [dragItem] - - } else { - let item = imagesDestination[indexPath.row] - let itemProvider = NSItemProvider(object: item as UIImage) - let dragItem = UIDragItem(itemProvider: itemProvider) - - dragItem.localObject = item - - return [dragItem] - } - } - - func collectionView(_ collectionView: UICollectionView, dragPreviewParametersForItemAt indexPath: IndexPath) -> UIDragPreviewParameters? { - - let previewParameters = UIDragPreviewParameters() - if collectionView == collectionViewSource { - previewParameters.visiblePath = UIBezierPath(rect: CGRect(x: 20, y: 20, width: 100, height: 100)) - } else { - previewParameters.visiblePath = UIBezierPath(rect: CGRect(x: 20, y: 20, width: 80, height: 80)) - } - - return previewParameters - } -} - -// MARK: - UICollectionViewDropDelegate Methods - -@available(iOS 13.0, *) -extension DragDropViewController: UICollectionViewDropDelegate { - - func collectionView(_ collectionView: UICollectionView, canHandle session: UIDropSession) -> Bool { - - return true // session.canLoadObjects(ofClass: NSString.self) - } - - func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal { - - if collectionView == collectionViewSource { - - if collectionView.hasActiveDrag { - return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath) - } else { - return UICollectionViewDropProposal(operation: .forbidden) - } - - } else { - - if collectionView.hasActiveDrag { - return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath) - } else { - return UICollectionViewDropProposal(operation: .copy, intent: .insertAtDestinationIndexPath) - } - } - } - - func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) { - - let destinationIndexPath: IndexPath - - switch coordinator.proposal.operation { - - case .move: - - if let indexPath = coordinator.destinationIndexPath { - - destinationIndexPath = indexPath - - } else { - - // Get last index path of table view. - let section = collectionView.numberOfSections - 1 - let row = collectionView.numberOfItems(inSection: section) - - destinationIndexPath = IndexPath(row: row, section: section) - } - self.reorderItems(coordinator: coordinator, destinationIndexPath: destinationIndexPath, collectionView: collectionView) - - break - - case .copy: - - // Get last index path of table view. - let section = collectionView.numberOfSections - 1 - let row = collectionView.numberOfItems(inSection: section) - - destinationIndexPath = IndexPath(row: row, section: section) - self.copyItems(coordinator: coordinator, destinationIndexPath: destinationIndexPath, collectionView: collectionView) - - break - - default: - return - } - } - - func collectionView(_ collectionView: UICollectionView, dropSessionDidEnd session: UIDropSession) { - - collectionViewDestination.reloadData() - - // Save button - if imagesDestination.count == 0 { - save.isEnabled = false - } else { - save.isEnabled = true - } - } -} diff --git a/iOSClient/Security/NCEndToEndEncryption.m b/iOSClient/Security/NCEndToEndEncryption.m index 8ff38430f..d613957ce 100644 --- a/iOSClient/Security/NCEndToEndEncryption.m +++ b/iOSClient/Security/NCEndToEndEncryption.m @@ -376,7 +376,7 @@ - (NSString *)decryptPrivateKey:(NSString *)privateKeyCipher passphrase:(NSString *)passphrase publicKey:(NSString *)publicKey { NSMutableData *privateKeyData = [NSMutableData new]; - NSString *privateKey; + NSString *privateKey = @""; // Key (data) NSMutableData *keyData = [NSMutableData dataWithLength:PBKDF2_KEY_LENGTH/8]; diff --git a/iOSClient/Select/NCSelect.swift b/iOSClient/Select/NCSelect.swift index 7d083c6e2..7ab1f908e 100644 --- a/iOSClient/Select/NCSelect.swift +++ b/iOSClient/Select/NCSelect.swift @@ -520,7 +520,7 @@ extension NCSelect: UICollectionViewDataSource { // image local if dataSource.metadataOffLine.contains(metadata.ocId) { cell.imageLocal.image = NCBrandColor.cacheImages.offlineFlag - } else if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + } else if CCUtility.fileProviderStorageExists(metadata) { cell.imageLocal.image = NCBrandColor.cacheImages.local } } @@ -617,7 +617,7 @@ extension NCSelect: UICollectionViewDataSource { // image Local if dataSource.metadataOffLine.contains(metadata.ocId) { cell.imageLocal.image = NCBrandColor.cacheImages.offlineFlag - } else if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + } else if CCUtility.fileProviderStorageExists(metadata) { cell.imageLocal.image = NCBrandColor.cacheImages.local } } diff --git a/iOSClient/Settings/CCManageAccount.m b/iOSClient/Settings/CCManageAccount.m index 19b60a6e7..57ee9a4f2 100644 --- a/iOSClient/Settings/CCManageAccount.m +++ b/iOSClient/Settings/CCManageAccount.m @@ -235,14 +235,14 @@ } // Web - if ([activeAccount.webpage length] > 0) { + if ([activeAccount.website length] > 0) { row = [XLFormRowDescriptor formRowDescriptorWithTag:@"userweb" rowType:XLFormRowDescriptorTypeInfo title:NSLocalizedString(@"_user_web_", nil)]; row.cellConfigAtConfigure[@"backgroundColor"] = NCBrandColor.shared.secondarySystemGroupedBackground; [row.cellConfig setObject:[UIFont systemFontOfSize:15.0] forKey:@"textLabel.font"]; [row.cellConfig setObject:[UIFont systemFontOfSize:15.0] forKey:@"detailTextLabel.font"]; [row.cellConfig setObject:NCBrandColor.shared.label forKey:@"textLabel.textColor"]; [row.cellConfig setObject:[[UIImage imageNamed:@"network"] imageWithColor:NCBrandColor.shared.gray size:25] forKey:@"imageView.image"]; - row.value = activeAccount.webpage; + row.value = activeAccount.website; [section addFormRow:row]; } @@ -305,7 +305,7 @@ [row.cellConfig setObject:[UIFont systemFontOfSize:15.0] forKey:@"detailTextLabel.font"]; [row.cellConfig setObject:NCBrandColor.shared.label forKey:@"textLabel.textColor"]; [row.cellConfig setObject:[[UIImage imageNamed:@"company"] imageWithColor:NCBrandColor.shared.gray size:25] forKey:@"imageView.image"]; - row.value = activeAccount.company; + row.value = activeAccount.organisation; [section addFormRow:row]; if (activeAccount.hcIsTrial) { diff --git a/iOSClient/Supporting Files/af.lproj/InfoPlist.strings b/iOSClient/Supporting Files/af.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/af.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/af.lproj/Localizable.strings b/iOSClient/Supporting Files/af.lproj/Localizable.strings Binary files differindex 21e263093..8af22bc37 100644 --- a/iOSClient/Supporting Files/af.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/af.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ar.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ar.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ar.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ar.lproj/Localizable.strings b/iOSClient/Supporting Files/ar.lproj/Localizable.strings Binary files differindex df9a3d9d9..f1ac2903e 100644 --- a/iOSClient/Supporting Files/ar.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/ar.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ast.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ast.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ast.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ast.lproj/Localizable.strings b/iOSClient/Supporting Files/ast.lproj/Localizable.strings Binary files differindex 69b463bb3..09a842f36 100644 --- a/iOSClient/Supporting Files/ast.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/ast.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/az.lproj/InfoPlist.strings b/iOSClient/Supporting Files/az.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/az.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/az.lproj/Localizable.strings b/iOSClient/Supporting Files/az.lproj/Localizable.strings Binary files differindex 7468c2f81..d7647967f 100644 --- a/iOSClient/Supporting Files/az.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/az.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/be.lproj/InfoPlist.strings b/iOSClient/Supporting Files/be.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/be.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/be.lproj/Localizable.strings b/iOSClient/Supporting Files/be.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..61aa73400 --- /dev/null +++ b/iOSClient/Supporting Files/be.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/bg_BG.lproj/InfoPlist.strings b/iOSClient/Supporting Files/bg_BG.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/bg_BG.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/bg_BG.lproj/Localizable.strings b/iOSClient/Supporting Files/bg_BG.lproj/Localizable.strings Binary files differindex 5098e4369..ea077df63 100644 --- a/iOSClient/Supporting Files/bg_BG.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/bg_BG.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/bn_BD.lproj/InfoPlist.strings b/iOSClient/Supporting Files/bn_BD.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/bn_BD.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/bn_BD.lproj/Localizable.strings b/iOSClient/Supporting Files/bn_BD.lproj/Localizable.strings Binary files differindex 66318496e..25c719311 100644 --- a/iOSClient/Supporting Files/bn_BD.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/bn_BD.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/br.lproj/InfoPlist.strings b/iOSClient/Supporting Files/br.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/br.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/br.lproj/Localizable.strings b/iOSClient/Supporting Files/br.lproj/Localizable.strings Binary files differindex 4c277bd66..236b4c10a 100644 --- a/iOSClient/Supporting Files/br.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/br.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/bs.lproj/InfoPlist.strings b/iOSClient/Supporting Files/bs.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/bs.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/bs.lproj/Localizable.strings b/iOSClient/Supporting Files/bs.lproj/Localizable.strings Binary files differindex 0b70741f9..afdb00d49 100644 --- a/iOSClient/Supporting Files/bs.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/bs.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ca.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ca.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ca.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ca.lproj/Localizable.strings b/iOSClient/Supporting Files/ca.lproj/Localizable.strings Binary files differindex 7f8aea723..5bd2b1379 100644 --- a/iOSClient/Supporting Files/ca.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/ca.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/cs-CZ.lproj/InfoPlist.strings b/iOSClient/Supporting Files/cs-CZ.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..5fe77cc9c --- /dev/null +++ b/iOSClient/Supporting Files/cs-CZ.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings b/iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings Binary files differindex dbd35be77..93032bd6a 100644 --- a/iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/cs-CZ.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/cy_GB.lproj/InfoPlist.strings b/iOSClient/Supporting Files/cy_GB.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/cy_GB.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/cy_GB.lproj/Localizable.strings b/iOSClient/Supporting Files/cy_GB.lproj/Localizable.strings Binary files differindex cb306e884..c38de2e6a 100644 --- a/iOSClient/Supporting Files/cy_GB.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/cy_GB.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/da.lproj/InfoPlist.strings b/iOSClient/Supporting Files/da.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..466a99c4a --- /dev/null +++ b/iOSClient/Supporting Files/da.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/da.lproj/Localizable.strings b/iOSClient/Supporting Files/da.lproj/Localizable.strings Binary files differindex ed9f65cb9..ddce71e31 100644 --- a/iOSClient/Supporting Files/da.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/da.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/de.lproj/InfoPlist.strings b/iOSClient/Supporting Files/de.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..500c1139a --- /dev/null +++ b/iOSClient/Supporting Files/de.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/de.lproj/Localizable.strings b/iOSClient/Supporting Files/de.lproj/Localizable.strings Binary files differindex f14fb07d8..ea3634aa7 100644 --- a/iOSClient/Supporting Files/de.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/de.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/el.lproj/InfoPlist.strings b/iOSClient/Supporting Files/el.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/el.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/el.lproj/Localizable.strings b/iOSClient/Supporting Files/el.lproj/Localizable.strings Binary files differindex b75187879..5b845b08c 100644 --- a/iOSClient/Supporting Files/el.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/el.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/en-GB.lproj/InfoPlist.strings b/iOSClient/Supporting Files/en-GB.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/en-GB.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/en-GB.lproj/Localizable.strings b/iOSClient/Supporting Files/en-GB.lproj/Localizable.strings Binary files differindex 104bf8157..33332d7aa 100644 --- a/iOSClient/Supporting Files/en-GB.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/en-GB.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/en.lproj/InfoPlist.strings b/iOSClient/Supporting Files/en.lproj/InfoPlist.strings new file mode 100644 index 000000000..e163dea69 --- /dev/null +++ b/iOSClient/Supporting Files/en.lproj/InfoPlist.strings @@ -0,0 +1,7 @@ +NSCameraUsageDescription = "Camera access is required to scan documents and make photo and video."; +NSFaceIDUsageDescription = "Face ID is required to authenticate using face recognition."; +NSLocationAlwaysUsageDescription = "GPS is used to detect new photos from camera roll, continued use of GPS running in the background can dramatically decrease battery life."; +NSPhotoLibraryUsageDescription = "Photo library access is required to upload your photos and videos to your cloud."; +NSPhotoLibraryAddUsageDescription = "Photo library access is required to upload your photos and videos to your cloud."; +NSMicrophoneUsageDescription = "Microphone access is required to create voice notes."; +NSLocationWhenInUseUsageDescription = "GPS is used to detect new photos from camera roll on background, the use of GPS only when the App is in use is useless."; diff --git a/iOSClient/Supporting Files/en.lproj/Localizable.strings b/iOSClient/Supporting Files/en.lproj/Localizable.strings index e08d82840..49952614a 100644 --- a/iOSClient/Supporting Files/en.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/en.lproj/Localizable.strings @@ -21,6 +21,7 @@ // "_cancel_" = "Cancel"; +"_tap_to_cancel_" = "Tap to cancel"; "_upload_file_" = "Upload file"; "_accessibility_add_upload_" = "Add and upload"; "_download_file_" = "Download file"; @@ -333,8 +334,7 @@ "_user_employee_" = "Employee"; "_user_contractor_" = "Contractor"; "_user_editprofile_" = "Edit profile"; -"_favorite_offline_" = "Favorites available offline"; -"_favorite_offline_footer_" = "Making all favorites available offline may take a while and use a lot of memory while doing it."; +"_select_offline_warning_" = "Making multiple files and folders available offline may take a while and use a lot of memory while doing so."; "_advanced_" = "Advanced"; "_disable_files_app_" = "Disable Files App integration"; "_disable_files_app_footer_" = "Do not permit the access of files via the iOS Files application"; @@ -708,10 +708,11 @@ "_trash_view_" = "Deleted files"; "_trash_restore_all_" = "Restore all files"; "_trash_delete_all_" = "Empty trash"; +"_trash_delete_all_description_" = "Do you want to empty the trash bin?"; "_trash_no_trash_" = "No files deleted"; "_trash_no_trash_description_" = "You can restore deleted files from here"; "_trash_restore_selected_" = "Restore selected files"; -"_trash_delete_selected_" = "Deleted selected files"; +"_trash_delete_selected_" = "Delete selected files"; "_manage_file_offline_" = "Manage offline files"; "_set_available_offline_" = "Set as available offline"; "_remove_available_offline_" = "Remove as available offline"; diff --git a/iOSClient/Supporting Files/eo.lproj/InfoPlist.strings b/iOSClient/Supporting Files/eo.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/eo.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/eo.lproj/Localizable.strings b/iOSClient/Supporting Files/eo.lproj/Localizable.strings Binary files differindex a37cd5521..e752850f3 100644 --- a/iOSClient/Supporting Files/eo.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/eo.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-419.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-419.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-419.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-419.lproj/Localizable.strings b/iOSClient/Supporting Files/es-419.lproj/Localizable.strings Binary files differindex 87e431b7d..08e4b7142 100644 --- a/iOSClient/Supporting Files/es-419.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-419.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-AR.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-AR.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-AR.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-AR.lproj/Localizable.strings b/iOSClient/Supporting Files/es-AR.lproj/Localizable.strings Binary files differindex f5a0f7e59..4d2b401be 100644 --- a/iOSClient/Supporting Files/es-AR.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-AR.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-CL.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-CL.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-CL.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-CL.lproj/Localizable.strings b/iOSClient/Supporting Files/es-CL.lproj/Localizable.strings Binary files differindex 1d765f7b9..1df3a142a 100644 --- a/iOSClient/Supporting Files/es-CL.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-CL.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-CO.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-CO.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-CO.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-CO.lproj/Localizable.strings b/iOSClient/Supporting Files/es-CO.lproj/Localizable.strings Binary files differindex 1d765f7b9..1df3a142a 100644 --- a/iOSClient/Supporting Files/es-CO.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-CO.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-CR.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-CR.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-CR.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-CR.lproj/Localizable.strings b/iOSClient/Supporting Files/es-CR.lproj/Localizable.strings Binary files differindex 1d765f7b9..1df3a142a 100644 --- a/iOSClient/Supporting Files/es-CR.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-CR.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-DO.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-DO.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-DO.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-DO.lproj/Localizable.strings b/iOSClient/Supporting Files/es-DO.lproj/Localizable.strings Binary files differindex 1d765f7b9..1df3a142a 100644 --- a/iOSClient/Supporting Files/es-DO.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-DO.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-EC.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-EC.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-EC.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-EC.lproj/Localizable.strings b/iOSClient/Supporting Files/es-EC.lproj/Localizable.strings Binary files differindex 51311efc0..999010d18 100644 --- a/iOSClient/Supporting Files/es-EC.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-EC.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-GT.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-GT.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-GT.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-GT.lproj/Localizable.strings b/iOSClient/Supporting Files/es-GT.lproj/Localizable.strings Binary files differindex 1d765f7b9..1df3a142a 100644 --- a/iOSClient/Supporting Files/es-GT.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-GT.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-HN.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-HN.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-HN.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-HN.lproj/Localizable.strings b/iOSClient/Supporting Files/es-HN.lproj/Localizable.strings Binary files differindex 63e8fc6b6..682a10fc4 100644 --- a/iOSClient/Supporting Files/es-HN.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-HN.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-MX.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-MX.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-MX.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-MX.lproj/Localizable.strings b/iOSClient/Supporting Files/es-MX.lproj/Localizable.strings Binary files differindex 5af7133a6..06042e9b1 100644 --- a/iOSClient/Supporting Files/es-MX.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-MX.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-NI.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-NI.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-NI.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-NI.lproj/Localizable.strings b/iOSClient/Supporting Files/es-NI.lproj/Localizable.strings Binary files differindex 63e8fc6b6..682a10fc4 100644 --- a/iOSClient/Supporting Files/es-NI.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-NI.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-PA.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-PA.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-PA.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-PA.lproj/Localizable.strings b/iOSClient/Supporting Files/es-PA.lproj/Localizable.strings Binary files differindex 63e8fc6b6..682a10fc4 100644 --- a/iOSClient/Supporting Files/es-PA.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-PA.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-PE.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-PE.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-PE.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-PE.lproj/Localizable.strings b/iOSClient/Supporting Files/es-PE.lproj/Localizable.strings Binary files differindex 63e8fc6b6..682a10fc4 100644 --- a/iOSClient/Supporting Files/es-PE.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-PE.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-PR.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-PR.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-PR.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-PR.lproj/Localizable.strings b/iOSClient/Supporting Files/es-PR.lproj/Localizable.strings Binary files differindex 63e8fc6b6..682a10fc4 100644 --- a/iOSClient/Supporting Files/es-PR.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-PR.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-PY.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-PY.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-PY.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-PY.lproj/Localizable.strings b/iOSClient/Supporting Files/es-PY.lproj/Localizable.strings Binary files differindex 9db190576..69c760b42 100644 --- a/iOSClient/Supporting Files/es-PY.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-PY.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-SV.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-SV.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-SV.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-SV.lproj/Localizable.strings b/iOSClient/Supporting Files/es-SV.lproj/Localizable.strings Binary files differindex 1d765f7b9..1df3a142a 100644 --- a/iOSClient/Supporting Files/es-SV.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-SV.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es-UY.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es-UY.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/es-UY.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es-UY.lproj/Localizable.strings b/iOSClient/Supporting Files/es-UY.lproj/Localizable.strings Binary files differindex 63e8fc6b6..682a10fc4 100644 --- a/iOSClient/Supporting Files/es-UY.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es-UY.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/es.lproj/InfoPlist.strings b/iOSClient/Supporting Files/es.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..7b744e241 --- /dev/null +++ b/iOSClient/Supporting Files/es.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/es.lproj/Localizable.strings b/iOSClient/Supporting Files/es.lproj/Localizable.strings Binary files differindex a66685a43..d4811b624 100644 --- a/iOSClient/Supporting Files/es.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/es.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/et_EE.lproj/InfoPlist.strings b/iOSClient/Supporting Files/et_EE.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/et_EE.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/et_EE.lproj/Localizable.strings b/iOSClient/Supporting Files/et_EE.lproj/Localizable.strings Binary files differindex a75c94f67..39381572f 100644 --- a/iOSClient/Supporting Files/et_EE.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/et_EE.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/eu.lproj/InfoPlist.strings b/iOSClient/Supporting Files/eu.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/eu.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/eu.lproj/Localizable.strings b/iOSClient/Supporting Files/eu.lproj/Localizable.strings Binary files differindex 2b341dbe9..e5c3566c8 100644 --- a/iOSClient/Supporting Files/eu.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/eu.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/fa.lproj/InfoPlist.strings b/iOSClient/Supporting Files/fa.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/fa.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/fa.lproj/Localizable.strings b/iOSClient/Supporting Files/fa.lproj/Localizable.strings Binary files differindex a7e04a24e..f6f6b67b9 100644 --- a/iOSClient/Supporting Files/fa.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/fa.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/fi-FI.lproj/InfoPlist.strings b/iOSClient/Supporting Files/fi-FI.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/fi-FI.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings b/iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings Binary files differindex 264e87450..4f3846b4c 100644 --- a/iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/fi-FI.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/fo.lproj/InfoPlist.strings b/iOSClient/Supporting Files/fo.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/fo.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/fo.lproj/Localizable.strings b/iOSClient/Supporting Files/fo.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..cad2830f0 --- /dev/null +++ b/iOSClient/Supporting Files/fo.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/fr.lproj/InfoPlist.strings b/iOSClient/Supporting Files/fr.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..dabb43b5e --- /dev/null +++ b/iOSClient/Supporting Files/fr.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/fr.lproj/Localizable.strings b/iOSClient/Supporting Files/fr.lproj/Localizable.strings Binary files differindex 376e187a9..adb4b7364 100644 --- a/iOSClient/Supporting Files/fr.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/fr.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/gd.lproj/InfoPlist.strings b/iOSClient/Supporting Files/gd.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/gd.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/gd.lproj/Localizable.strings b/iOSClient/Supporting Files/gd.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..29465f2a1 --- /dev/null +++ b/iOSClient/Supporting Files/gd.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/gl.lproj/InfoPlist.strings b/iOSClient/Supporting Files/gl.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/gl.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/gl.lproj/Localizable.strings b/iOSClient/Supporting Files/gl.lproj/Localizable.strings Binary files differindex 6cd87ef3c..860cfba88 100644 --- a/iOSClient/Supporting Files/gl.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/gl.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/he.lproj/InfoPlist.strings b/iOSClient/Supporting Files/he.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/he.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/he.lproj/Localizable.strings b/iOSClient/Supporting Files/he.lproj/Localizable.strings Binary files differindex ce6a9c74f..bca57ad9e 100644 --- a/iOSClient/Supporting Files/he.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/he.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/hi_IN.lproj/InfoPlist.strings b/iOSClient/Supporting Files/hi_IN.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/hi_IN.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/hi_IN.lproj/Localizable.strings b/iOSClient/Supporting Files/hi_IN.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..29465f2a1 --- /dev/null +++ b/iOSClient/Supporting Files/hi_IN.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/hr.lproj/InfoPlist.strings b/iOSClient/Supporting Files/hr.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/hr.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/hr.lproj/Localizable.strings b/iOSClient/Supporting Files/hr.lproj/Localizable.strings Binary files differindex 93aa635c5..f9b8306b3 100644 --- a/iOSClient/Supporting Files/hr.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/hr.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/hsb.lproj/InfoPlist.strings b/iOSClient/Supporting Files/hsb.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/hsb.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/hsb.lproj/Localizable.strings b/iOSClient/Supporting Files/hsb.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..1ce567a41 --- /dev/null +++ b/iOSClient/Supporting Files/hsb.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/hu.lproj/InfoPlist.strings b/iOSClient/Supporting Files/hu.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..1a9745288 --- /dev/null +++ b/iOSClient/Supporting Files/hu.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/hu.lproj/Localizable.strings b/iOSClient/Supporting Files/hu.lproj/Localizable.strings Binary files differindex 863dfa382..b32adfb13 100644 --- a/iOSClient/Supporting Files/hu.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/hu.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/hy.lproj/InfoPlist.strings b/iOSClient/Supporting Files/hy.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/hy.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/hy.lproj/Localizable.strings b/iOSClient/Supporting Files/hy.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..688f0e548 --- /dev/null +++ b/iOSClient/Supporting Files/hy.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ia.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ia.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ia.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ia.lproj/Localizable.strings b/iOSClient/Supporting Files/ia.lproj/Localizable.strings Binary files differindex 512a9744d..50a2d5f91 100644 --- a/iOSClient/Supporting Files/ia.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/ia.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/id.lproj/InfoPlist.strings b/iOSClient/Supporting Files/id.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/id.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/id.lproj/Localizable.strings b/iOSClient/Supporting Files/id.lproj/Localizable.strings Binary files differindex e65a18559..abffe4686 100644 --- a/iOSClient/Supporting Files/id.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/id.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ig.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ig.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ig.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ig.lproj/Localizable.strings b/iOSClient/Supporting Files/ig.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..29465f2a1 --- /dev/null +++ b/iOSClient/Supporting Files/ig.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/is.lproj/InfoPlist.strings b/iOSClient/Supporting Files/is.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/is.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/is.lproj/Localizable.strings b/iOSClient/Supporting Files/is.lproj/Localizable.strings Binary files differindex 77ce1282a..1f42be7e8 100644 --- a/iOSClient/Supporting Files/is.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/is.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/it.lproj/InfoPlist.strings b/iOSClient/Supporting Files/it.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..9f957bc21 --- /dev/null +++ b/iOSClient/Supporting Files/it.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/it.lproj/Localizable.strings b/iOSClient/Supporting Files/it.lproj/Localizable.strings Binary files differindex 7e76dcf01..a35b9bf43 100644 --- a/iOSClient/Supporting Files/it.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/it.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ja-JP.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ja-JP.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ja-JP.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ja-JP.lproj/Localizable.strings b/iOSClient/Supporting Files/ja-JP.lproj/Localizable.strings Binary files differindex 547f85a4a..785646f12 100644 --- a/iOSClient/Supporting Files/ja-JP.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/ja-JP.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ka-GE.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ka-GE.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ka-GE.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ka-GE.lproj/Localizable.strings b/iOSClient/Supporting Files/ka-GE.lproj/Localizable.strings Binary files differindex 980dd2284..8711f456d 100644 --- a/iOSClient/Supporting Files/ka-GE.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/ka-GE.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ka.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ka.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ka.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ka.lproj/Localizable.strings b/iOSClient/Supporting Files/ka.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..d31ff4616 --- /dev/null +++ b/iOSClient/Supporting Files/ka.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/kab.lproj/InfoPlist.strings b/iOSClient/Supporting Files/kab.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/kab.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/kab.lproj/Localizable.strings b/iOSClient/Supporting Files/kab.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..7b125ea57 --- /dev/null +++ b/iOSClient/Supporting Files/kab.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/kk.lproj/InfoPlist.strings b/iOSClient/Supporting Files/kk.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/kk.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/kk.lproj/Localizable.strings b/iOSClient/Supporting Files/kk.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..29465f2a1 --- /dev/null +++ b/iOSClient/Supporting Files/kk.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/km.lproj/InfoPlist.strings b/iOSClient/Supporting Files/km.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/km.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/km.lproj/Localizable.strings b/iOSClient/Supporting Files/km.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..a48abd3c0 --- /dev/null +++ b/iOSClient/Supporting Files/km.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/kn.lproj/InfoPlist.strings b/iOSClient/Supporting Files/kn.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/kn.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/kn.lproj/Localizable.strings b/iOSClient/Supporting Files/kn.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..a848f6d5e --- /dev/null +++ b/iOSClient/Supporting Files/kn.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ko.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ko.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ko.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ko.lproj/Localizable.strings b/iOSClient/Supporting Files/ko.lproj/Localizable.strings Binary files differindex aafb05b37..ac7a42d2c 100644 --- a/iOSClient/Supporting Files/ko.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/ko.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/la.lproj/InfoPlist.strings b/iOSClient/Supporting Files/la.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/la.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/la.lproj/Localizable.strings b/iOSClient/Supporting Files/la.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..91c1683d2 --- /dev/null +++ b/iOSClient/Supporting Files/la.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/lb.lproj/InfoPlist.strings b/iOSClient/Supporting Files/lb.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/lb.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/lb.lproj/Localizable.strings b/iOSClient/Supporting Files/lb.lproj/Localizable.strings Binary files differindex fae4465b7..b27bbd24b 100644 --- a/iOSClient/Supporting Files/lb.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/lb.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/lo.lproj/InfoPlist.strings b/iOSClient/Supporting Files/lo.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/lo.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/lo.lproj/Localizable.strings b/iOSClient/Supporting Files/lo.lproj/Localizable.strings Binary files differindex 264f74f32..8432bea32 100644 --- a/iOSClient/Supporting Files/lo.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/lo.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/lt_LT.lproj/InfoPlist.strings b/iOSClient/Supporting Files/lt_LT.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/lt_LT.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/lt_LT.lproj/Localizable.strings b/iOSClient/Supporting Files/lt_LT.lproj/Localizable.strings Binary files differindex f88b4f87d..a347fc39b 100644 --- a/iOSClient/Supporting Files/lt_LT.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/lt_LT.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/lv.lproj/InfoPlist.strings b/iOSClient/Supporting Files/lv.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/lv.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/lv.lproj/Localizable.strings b/iOSClient/Supporting Files/lv.lproj/Localizable.strings Binary files differindex ac1da0780..3e525055c 100644 --- a/iOSClient/Supporting Files/lv.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/lv.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/mk.lproj/InfoPlist.strings b/iOSClient/Supporting Files/mk.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/mk.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/mk.lproj/Localizable.strings b/iOSClient/Supporting Files/mk.lproj/Localizable.strings Binary files differindex 9dd9b4609..6937fb8db 100644 --- a/iOSClient/Supporting Files/mk.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/mk.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/mn.lproj/InfoPlist.strings b/iOSClient/Supporting Files/mn.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/mn.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/mn.lproj/Localizable.strings b/iOSClient/Supporting Files/mn.lproj/Localizable.strings Binary files differindex fd792c77b..b389828d7 100644 --- a/iOSClient/Supporting Files/mn.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/mn.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/mr.lproj/InfoPlist.strings b/iOSClient/Supporting Files/mr.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/mr.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/mr.lproj/Localizable.strings b/iOSClient/Supporting Files/mr.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..29465f2a1 --- /dev/null +++ b/iOSClient/Supporting Files/mr.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ms_MY.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ms_MY.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ms_MY.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ms_MY.lproj/Localizable.strings b/iOSClient/Supporting Files/ms_MY.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..602303db4 --- /dev/null +++ b/iOSClient/Supporting Files/ms_MY.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/my.lproj/InfoPlist.strings b/iOSClient/Supporting Files/my.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/my.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/my.lproj/Localizable.strings b/iOSClient/Supporting Files/my.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..cb25a9ecc --- /dev/null +++ b/iOSClient/Supporting Files/my.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/nb-NO.lproj/InfoPlist.strings b/iOSClient/Supporting Files/nb-NO.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/nb-NO.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/nb-NO.lproj/Localizable.strings b/iOSClient/Supporting Files/nb-NO.lproj/Localizable.strings Binary files differindex a5e04176a..a616388f0 100644 --- a/iOSClient/Supporting Files/nb-NO.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/nb-NO.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ne.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ne.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ne.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ne.lproj/Localizable.strings b/iOSClient/Supporting Files/ne.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..0837b531d --- /dev/null +++ b/iOSClient/Supporting Files/ne.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/nl.lproj/InfoPlist.strings b/iOSClient/Supporting Files/nl.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/nl.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/nl.lproj/Localizable.strings b/iOSClient/Supporting Files/nl.lproj/Localizable.strings Binary files differindex 823702989..6587eaffb 100644 --- a/iOSClient/Supporting Files/nl.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/nl.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/nn_NO.lproj/InfoPlist.strings b/iOSClient/Supporting Files/nn_NO.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/nn_NO.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/nn_NO.lproj/Localizable.strings b/iOSClient/Supporting Files/nn_NO.lproj/Localizable.strings Binary files differindex c34e8715f..e8654611a 100644 --- a/iOSClient/Supporting Files/nn_NO.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/nn_NO.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/oc.lproj/InfoPlist.strings b/iOSClient/Supporting Files/oc.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/oc.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/oc.lproj/Localizable.strings b/iOSClient/Supporting Files/oc.lproj/Localizable.strings Binary files differindex 77ecdf6f8..ec06d8816 100644 --- a/iOSClient/Supporting Files/oc.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/oc.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/pl.lproj/InfoPlist.strings b/iOSClient/Supporting Files/pl.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b055470d7 --- /dev/null +++ b/iOSClient/Supporting Files/pl.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/pl.lproj/Localizable.strings b/iOSClient/Supporting Files/pl.lproj/Localizable.strings Binary files differindex 6dec5b026..500e7296d 100644 --- a/iOSClient/Supporting Files/pl.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/pl.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ps.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ps.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ps.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ps.lproj/Localizable.strings b/iOSClient/Supporting Files/ps.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..6ed383774 --- /dev/null +++ b/iOSClient/Supporting Files/ps.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/pt-BR.lproj/InfoPlist.strings b/iOSClient/Supporting Files/pt-BR.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..d73155d57 --- /dev/null +++ b/iOSClient/Supporting Files/pt-BR.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/pt-BR.lproj/Localizable.strings b/iOSClient/Supporting Files/pt-BR.lproj/Localizable.strings Binary files differindex 934bfad15..74336c384 100644 --- a/iOSClient/Supporting Files/pt-BR.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/pt-BR.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/pt-PT.lproj/InfoPlist.strings b/iOSClient/Supporting Files/pt-PT.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/pt-PT.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/pt-PT.lproj/Localizable.strings b/iOSClient/Supporting Files/pt-PT.lproj/Localizable.strings Binary files differindex f6e2514e1..26c2f511d 100644 --- a/iOSClient/Supporting Files/pt-PT.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/pt-PT.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ro.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ro.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ro.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ro.lproj/Localizable.strings b/iOSClient/Supporting Files/ro.lproj/Localizable.strings Binary files differindex 2ed82520d..41de44c52 100644 --- a/iOSClient/Supporting Files/ro.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/ro.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ru.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ru.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ru.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ru.lproj/Localizable.strings b/iOSClient/Supporting Files/ru.lproj/Localizable.strings Binary files differindex ca1a3f56b..2b40acab0 100644 --- a/iOSClient/Supporting Files/ru.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/ru.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/sc.lproj/InfoPlist.strings b/iOSClient/Supporting Files/sc.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/sc.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/sc.lproj/Localizable.strings b/iOSClient/Supporting Files/sc.lproj/Localizable.strings Binary files differindex 54b9c1777..04f9753f0 100644 --- a/iOSClient/Supporting Files/sc.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/sc.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/si.lproj/InfoPlist.strings b/iOSClient/Supporting Files/si.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/si.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/si.lproj/Localizable.strings b/iOSClient/Supporting Files/si.lproj/Localizable.strings Binary files differindex 21cd9ca0c..e3ef30803 100644 --- a/iOSClient/Supporting Files/si.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/si.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/sk-SK.lproj/InfoPlist.strings b/iOSClient/Supporting Files/sk-SK.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..4afaa09dc --- /dev/null +++ b/iOSClient/Supporting Files/sk-SK.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/sk-SK.lproj/Localizable.strings b/iOSClient/Supporting Files/sk-SK.lproj/Localizable.strings Binary files differindex 21b2589f1..b26ecfca3 100644 --- a/iOSClient/Supporting Files/sk-SK.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/sk-SK.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/sl.lproj/InfoPlist.strings b/iOSClient/Supporting Files/sl.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/sl.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/sl.lproj/Localizable.strings b/iOSClient/Supporting Files/sl.lproj/Localizable.strings Binary files differindex 6524d21f6..561ab7d2f 100644 --- a/iOSClient/Supporting Files/sl.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/sl.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/sq.lproj/InfoPlist.strings b/iOSClient/Supporting Files/sq.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/sq.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/sq.lproj/Localizable.strings b/iOSClient/Supporting Files/sq.lproj/Localizable.strings Binary files differindex 2d3efbb22..4db0730ea 100644 --- a/iOSClient/Supporting Files/sq.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/sq.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/sr.lproj/InfoPlist.strings b/iOSClient/Supporting Files/sr.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/sr.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/sr.lproj/Localizable.strings b/iOSClient/Supporting Files/sr.lproj/Localizable.strings Binary files differindex 1d79879fd..ce3c29b44 100644 --- a/iOSClient/Supporting Files/sr.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/sr.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/sr@latin.lproj/InfoPlist.strings b/iOSClient/Supporting Files/sr@latin.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/sr@latin.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/sr@latin.lproj/Localizable.strings b/iOSClient/Supporting Files/sr@latin.lproj/Localizable.strings Binary files differindex 7b1f593d3..551b3d8e9 100644 --- a/iOSClient/Supporting Files/sr@latin.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/sr@latin.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/sv.lproj/InfoPlist.strings b/iOSClient/Supporting Files/sv.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..1edb2895e --- /dev/null +++ b/iOSClient/Supporting Files/sv.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/sv.lproj/Localizable.strings b/iOSClient/Supporting Files/sv.lproj/Localizable.strings Binary files differindex 804e59180..2e693b521 100644 --- a/iOSClient/Supporting Files/sv.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/sv.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/sw.lproj/InfoPlist.strings b/iOSClient/Supporting Files/sw.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/sw.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/sw.lproj/Localizable.strings b/iOSClient/Supporting Files/sw.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..29465f2a1 --- /dev/null +++ b/iOSClient/Supporting Files/sw.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ta.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ta.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ta.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ta.lproj/Localizable.strings b/iOSClient/Supporting Files/ta.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..77655b07c --- /dev/null +++ b/iOSClient/Supporting Files/ta.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/th_TH.lproj/InfoPlist.strings b/iOSClient/Supporting Files/th_TH.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/th_TH.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/th_TH.lproj/Localizable.strings b/iOSClient/Supporting Files/th_TH.lproj/Localizable.strings Binary files differindex 5e11e4de5..43b01cf13 100644 --- a/iOSClient/Supporting Files/th_TH.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/th_TH.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/tk.lproj/InfoPlist.strings b/iOSClient/Supporting Files/tk.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/tk.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/tk.lproj/Localizable.strings b/iOSClient/Supporting Files/tk.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..5b1131787 --- /dev/null +++ b/iOSClient/Supporting Files/tk.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/tr.lproj/InfoPlist.strings b/iOSClient/Supporting Files/tr.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..a4424f682 --- /dev/null +++ b/iOSClient/Supporting Files/tr.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/tr.lproj/Localizable.strings b/iOSClient/Supporting Files/tr.lproj/Localizable.strings Binary files differindex 7d12c0f38..9abfe1c5d 100644 --- a/iOSClient/Supporting Files/tr.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/tr.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ug.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ug.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ug.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ug.lproj/Localizable.strings b/iOSClient/Supporting Files/ug.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..ad7e9d073 --- /dev/null +++ b/iOSClient/Supporting Files/ug.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/uk.lproj/InfoPlist.strings b/iOSClient/Supporting Files/uk.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/uk.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/uk.lproj/Localizable.strings b/iOSClient/Supporting Files/uk.lproj/Localizable.strings Binary files differindex ca5b942fe..d5c5277f1 100644 --- a/iOSClient/Supporting Files/uk.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/uk.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/ur_PK.lproj/InfoPlist.strings b/iOSClient/Supporting Files/ur_PK.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/ur_PK.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/ur_PK.lproj/Localizable.strings b/iOSClient/Supporting Files/ur_PK.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..3912758b2 --- /dev/null +++ b/iOSClient/Supporting Files/ur_PK.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/uz.lproj/InfoPlist.strings b/iOSClient/Supporting Files/uz.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/uz.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/uz.lproj/Localizable.strings b/iOSClient/Supporting Files/uz.lproj/Localizable.strings Binary files differnew file mode 100644 index 000000000..6c9045dc1 --- /dev/null +++ b/iOSClient/Supporting Files/uz.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/vi.lproj/InfoPlist.strings b/iOSClient/Supporting Files/vi.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/vi.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/vi.lproj/Localizable.strings b/iOSClient/Supporting Files/vi.lproj/Localizable.strings Binary files differindex a390b61f0..308165814 100644 --- a/iOSClient/Supporting Files/vi.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/vi.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/zh-Hans.lproj/InfoPlist.strings b/iOSClient/Supporting Files/zh-Hans.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..349e58003 --- /dev/null +++ b/iOSClient/Supporting Files/zh-Hans.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/zh-Hans.lproj/Localizable.strings b/iOSClient/Supporting Files/zh-Hans.lproj/Localizable.strings Binary files differindex 4e59a0f48..a71f2177c 100644 --- a/iOSClient/Supporting Files/zh-Hans.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/zh-Hans.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/zh-Hant-TW.lproj/InfoPlist.strings b/iOSClient/Supporting Files/zh-Hant-TW.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..b907f6e78 --- /dev/null +++ b/iOSClient/Supporting Files/zh-Hant-TW.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/zh-Hant-TW.lproj/Localizable.strings b/iOSClient/Supporting Files/zh-Hant-TW.lproj/Localizable.strings Binary files differindex 4e1076bc4..859f5f7a9 100644 --- a/iOSClient/Supporting Files/zh-Hant-TW.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/zh-Hant-TW.lproj/Localizable.strings diff --git a/iOSClient/Supporting Files/zh_HK.lproj/InfoPlist.strings b/iOSClient/Supporting Files/zh_HK.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..9788a2bfe --- /dev/null +++ b/iOSClient/Supporting Files/zh_HK.lproj/InfoPlist.strings diff --git a/iOSClient/Supporting Files/zh_HK.lproj/Localizable.strings b/iOSClient/Supporting Files/zh_HK.lproj/Localizable.strings Binary files differindex d2fe23210..95c7b93b2 100644 --- a/iOSClient/Supporting Files/zh_HK.lproj/Localizable.strings +++ b/iOSClient/Supporting Files/zh_HK.lproj/Localizable.strings diff --git a/iOSClient/Trash/Cell/NCTrashListCell.swift b/iOSClient/Trash/Cell/NCTrashListCell.swift index 13f83c183..5c953a6b8 100644 --- a/iOSClient/Trash/Cell/NCTrashListCell.swift +++ b/iOSClient/Trash/Cell/NCTrashListCell.swift @@ -4,7 +4,9 @@ // // Created by Marino Faggiana on 08/10/2018. // 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> // // This program is free software: you can redistribute it and/or modify @@ -23,14 +25,14 @@ import UIKit -class NCTrashListCell: UICollectionViewCell { +class NCTrashListCell: UICollectionViewCell, NCTrashCell { @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageItemLeftConstraint: NSLayoutConstraint! @IBOutlet weak var imageSelect: UIImageView! @IBOutlet weak var labelTitle: UILabel! - @IBOutlet weak var labelInfo: UILabel! + @IBOutlet weak var labelInfo: UILabel? @IBOutlet weak var imageRestore: UIImageView! @IBOutlet weak var imageMore: UIImageView! @@ -44,13 +46,12 @@ class NCTrashListCell: UICollectionViewCell { weak var delegate: NCTrashListCellDelegate? var objectId = "" - var indexPath = IndexPath() override func awakeFromNib() { super.awakeFromNib() imageRestore.image = NCBrandColor.cacheImages.buttonRestore - imageMore.image = NCBrandColor.cacheImages.buttonMore + imageMore.image = NCUtility.shared.loadImage(named: "trash") imageItem.layer.cornerRadius = 6 imageItem.layer.masksToBounds = true @@ -80,18 +81,26 @@ class NCTrashListCell: UICollectionViewCell { func selected(_ status: Bool) { if status { + var blurEffect: UIVisualEffect? + var blurEffectView: UIView? 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 - + separator.isHidden = true } else { imageSelect.image = NCBrandColor.cacheImages.checkedNo backgroundView = nil + separator.isHidden = false } } } @@ -100,3 +109,28 @@ protocol NCTrashListCellDelegate: AnyObject { func tapRestoreListItem(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) + } + } +} diff --git a/iOSClient/Trash/NCTrash+CollectionView.swift b/iOSClient/Trash/NCTrash+CollectionView.swift new file mode 100644 index 000000000..66c4fde96 --- /dev/null +++ b/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) + } +} diff --git a/iOSClient/Trash/NCTrash.swift b/iOSClient/Trash/NCTrash.swift index 9647dfff9..4382ec759 100644 --- a/iOSClient/Trash/NCTrash.swift +++ b/iOSClient/Trash/NCTrash.swift @@ -4,7 +4,9 @@ // // Created by Marino Faggiana on 02/10/2018. // 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> // // 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/>. // +import Realm import UIKit 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! @@ -33,22 +38,21 @@ class NCTrash: UIViewController, UIGestureRecognizerDelegate, NCTrashListCellDel var blinkFileId: String? 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 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() // MARK: - View Life Cycle override func viewDidLoad() { - super.viewDidLoad() view.backgroundColor = NCBrandColor.shared.systemBackground self.navigationController?.navigationBar.prefersLargeTitles = true @@ -82,7 +86,6 @@ class NCTrash: UIViewController, UIGestureRecognizerDelegate, NCTrashListCellDel } override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) appDelegate.activeViewController = self @@ -97,16 +100,16 @@ class NCTrash: UIViewController, UIGestureRecognizerDelegate, NCTrashListCellDel collectionView.collectionViewLayout = gridLayout } - if trashPath == "" { + if trashPath.isEmpty { 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/" } + setNavigationItem() reloadDataSource() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - loadListingTrash() } @@ -125,7 +128,6 @@ class NCTrash: UIViewController, UIGestureRecognizerDelegate, NCTrashListCellDel // MARK: - Empty func emptyDataSetView(_ view: NCEmptyView) { - view.emptyImage.image = UIImage(named: "trash")?.image(color: .gray, size: UIScreen.main.bounds.width) view.emptyTitle.text = NSLocalizedString("_trash_no_trash_", comment: "") view.emptyDescription.text = NSLocalizedString("_trash_no_trash_description_", comment: "") @@ -159,13 +161,11 @@ class NCTrash: UIViewController, UIGestureRecognizerDelegate, NCTrashListCellDel } func tapOrderHeaderMenu(sender: Any) { - let sortMenu = NCSortMenu() sortMenu.toggleMenu(viewController: self, key: NCGlobal.shared.layoutViewTrash, sortButton: sender as? UIButton, serverUrl: "", hideDirectoryOnTop: true) } func tapMoreHeaderMenu(sender: Any) { - toggleMenuMoreHeader() } @@ -173,211 +173,38 @@ class NCTrash: UIViewController, UIGestureRecognizerDelegate, NCTrashListCellDel if !isEditMode { 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) collectionView(self.collectionView, didSelectItemAt: indexPath!) - } + } // else: undefined sender } func tapMoreListItem(with objectId: String, image: UIImage?, sender: Any) { 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) collectionView(self.collectionView, didSelectItemAt: indexPath!) - } + } // else: undefined sender } func tapMoreGridItem(with objectId: String, namedButtonMore: String, image: UIImage?, sender: Any) { 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) 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() { @@ -391,28 +218,28 @@ extension NCTrash { datasource = tashItems 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() { @@ -422,7 +249,7 @@ extension NCTrash { NCManageDatabase.shared.deleteTrash(filePath: self.trashPath, account: self.appDelegate.account) NCManageDatabase.shared.addTrash(account: account, items: items) } 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 { print("[LOG] It has been changed user during networking process, error.") } @@ -448,7 +275,7 @@ extension NCTrash { NCManageDatabase.shared.deleteTrash(fileId: fileId, account: account) self.reloadDataSource() } 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 { print("[LOG] It has been changed user during networking process, error.") } @@ -463,7 +290,7 @@ extension NCTrash { if errorCode == 0 && account == self.appDelegate.account { NCManageDatabase.shared.deleteTrash(fileId: nil, account: self.appDelegate.account) } 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 { print("[LOG] It has been changed user during networking process, error.") } @@ -484,7 +311,7 @@ extension NCTrash { NCManageDatabase.shared.deleteTrash(fileId: fileId, account: account) self.reloadDataSource() } 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 { 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 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 } - } } } diff --git a/iOSClient/Trash/Section/NCTrashSectionHeaderFooter.swift b/iOSClient/Trash/Section/NCTrashSectionHeaderFooter.swift index c919e41f5..0f36a0160 100644 --- a/iOSClient/Trash/Section/NCTrashSectionHeaderFooter.swift +++ b/iOSClient/Trash/Section/NCTrashSectionHeaderFooter.swift @@ -61,7 +61,7 @@ class NCTrashSectionHeaderMenu: UICollectionReusableView { func setStatusButton(datasource: [tableTrash]) { - if datasource.count == 0 { + if datasource.isEmpty { buttonSwitch.isEnabled = false buttonOrder.isEnabled = false buttonMore.isEnabled = false @@ -128,9 +128,9 @@ class NCTrashSectionFooter: UICollectionReusableView { filesText = "1 " + NSLocalizedString("_file_", comment: "") + " " + CCUtility.transformedSize(size) } - if foldersText == "" { + if foldersText.isEmpty { labelFooter.text = filesText - } else if filesText == "" { + } else if filesText.isEmpty { labelFooter.text = foldersText } else { labelFooter.text = foldersText + ", " + filesText diff --git a/iOSClient/Utility/CCUtility.h b/iOSClient/Utility/CCUtility.h index 360056a67..e2aee0e86 100644 --- a/iOSClient/Utility/CCUtility.h +++ b/iOSClient/Utility/CCUtility.h @@ -217,7 +217,7 @@ + (NSString *)getDirectoryProviderStorageOcId:(NSString *)ocId fileNameView:(NSString *)fileNameView; + (NSString *)getDirectoryProviderStorageIconOcId:(NSString *)ocId etag:(NSString *)etag; + (NSString *)getDirectoryProviderStoragePreviewOcId:(NSString *)ocId etag:(NSString *)etag; -+ (BOOL)fileProviderStorageExists:(NSString *)ocId fileNameView:(NSString *)fileNameView; ++ (BOOL)fileProviderStorageExists:(tableMetadata *)metadata; + (int64_t)fileProviderStorageSize:(NSString *)ocId fileNameView:(NSString *)fileNameView; + (BOOL)fileProviderStoragePreviewIconExists:(NSString *)ocId etag:(NSString *)etag; diff --git a/iOSClient/Utility/CCUtility.m b/iOSClient/Utility/CCUtility.m index bc77b3c6b..e2e68dc2d 100644 --- a/iOSClient/Utility/CCUtility.m +++ b/iOSClient/Utility/CCUtility.m @@ -1135,6 +1135,8 @@ NSString *fileNamePath = [NSString stringWithFormat:@"%@/%@", [self getDirectoryProviderStorageOcId:ocId], fileNameView]; // if do not exists create file 0 length + // causes files with lenth 0 to never be downloaded, because already exist + // also makes it impossible to delete any file with length 0 (from cache) if ([[NSFileManager defaultManager] fileExistsAtPath:fileNamePath] == NO) { [[NSFileManager defaultManager] createFileAtPath:fileNamePath contents:nil attributes:nil]; } @@ -1152,14 +1154,15 @@ return [NSString stringWithFormat:@"%@/%@.preview.%@", [self getDirectoryProviderStorageOcId:ocId], etag, [NCGlobal shared].extensionPreview]; } -+ (BOOL)fileProviderStorageExists:(NSString *)ocId fileNameView:(NSString *)fileNameView ++ (BOOL)fileProviderStorageExists:(tableMetadata *)metadata { - NSString *fileNamePath = [self getDirectoryProviderStorageOcId:ocId fileNameView:fileNameView]; - + NSString *fileNamePath = [self getDirectoryProviderStorageOcId:metadata.ocId fileNameView:metadata.fileNameView]; + if (![[NSFileManager defaultManager] fileExistsAtPath:fileNamePath]) { + return false; + } + unsigned long long fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:fileNamePath error:nil] fileSize]; - - if (fileSize > 0) return true; - else return false; + return fileSize == metadata.size; } + (int64_t)fileProviderStorageSize:(NSString *)ocId fileNameView:(NSString *)fileNameView @@ -1652,9 +1655,9 @@ long fileSize = 0; int pixelY = 0; int pixelX = 0; - NSString *lensModel; + NSString *lensModel = @""; - if (![metadata.classFile isEqualToString:@"image"] || ![CCUtility fileProviderStorageExists:metadata.ocId fileNameView:metadata.fileNameView]) { + if (![metadata.classFile isEqualToString:@"image"] || ![CCUtility fileProviderStorageExists:metadata]) { completition(latitude, longitude, location, date, lensModel); return; } diff --git a/iOSClient/Utility/NCContentPresenter.swift b/iOSClient/Utility/NCContentPresenter.swift index 2607d39f6..ffe6c5396 100644 --- a/iOSClient/Utility/NCContentPresenter.swift +++ b/iOSClient/Utility/NCContentPresenter.swift @@ -62,12 +62,12 @@ class NCContentPresenter: NSObject { // MARK: - Message - @objc func showGenericError(description: String) { + @objc func showError(description: String, errorCode: Int = NCGlobal.shared.errorGeneric) { messageNotification( "_error_", description: description, delay: NCGlobal.shared.dismissAfterSecond, type: .error, - errorCode: NCGlobal.shared.errorGeneric) + errorCode: errorCode) } @objc func messageNotification(_ title: String, description: String?, delay: TimeInterval, type: messageType, errorCode: Int) { diff --git a/iOSClient/Utility/NCUtility.swift b/iOSClient/Utility/NCUtility.swift index db79e1b96..a29f0cdea 100644 --- a/iOSClient/Utility/NCUtility.swift +++ b/iOSClient/Utility/NCUtility.swift @@ -440,7 +440,7 @@ class NCUtility: NSObject { let fileNamePathIcon = CCUtility.getDirectoryProviderStorageIconOcId(ocId, etag: etag)! if FileManager().fileExists(atPath: fileNamePathPreview) && FileManager().fileExists(atPath: fileNamePathIcon) { return } - if !CCUtility.fileProviderStorageExists(ocId, fileNameView: fileName) { return } + if CCUtility.fileProviderStorageSize(ocId, fileNameView: fileName) != 0 { return } if classFile != NCCommunicationCommon.typeClassFile.image.rawValue && classFile != NCCommunicationCommon.typeClassFile.video.rawValue { return } if classFile == NCCommunicationCommon.typeClassFile.image.rawValue { diff --git a/iOSClient/Utility/ParallelWorker.swift b/iOSClient/Utility/ParallelWorker.swift new file mode 100644 index 000000000..1dfc269ed --- /dev/null +++ b/iOSClient/Utility/ParallelWorker.swift @@ -0,0 +1,100 @@ +// +// ParallelWorker.swift +// Nextcloud +// +// Created by Henrik Storch on 18.02.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 UIKit +import JGProgressHUD + +/// Object to execute multiple tasks in parallel like uploading or downloading. +/// - Can display a progress indicator with status message +/// - Can be canceled by user +class ParallelWorker { + let completionGroup = DispatchGroup() + let queue = DispatchQueue(label: "ParallelWorker") + let semaphore: DispatchSemaphore + let titleKey: String + var hud: JGProgressHUD? + var totalTasks: Int? + var completedTasks = 0 + var isCancelled = false + + /// Creates a ParallelWorker + /// - Parameters: + /// - n: Amount of tasks to be executed in parallel + /// - titleKey: Localized String key, used for the status. Default: *Please Wait...* + /// - totalTasks: Number of total tasks, if known + /// - hudView: The parent view or current view which should present the progress indicator. If `nil`, no progress indicator will be shown. + init(n: Int, titleKey: String?, totalTasks: Int?, hudView: UIView?) { + semaphore = DispatchSemaphore(value: n) + self.totalTasks = totalTasks + self.titleKey = titleKey ?? "_wait_" + guard let hudView = hudView else { return } + + DispatchQueue.main.async { + let hud = JGProgressHUD() + hud.show(in: hudView) + hud.textLabel.text = NSLocalizedString(self.titleKey, comment: "") + hud.detailTextLabel.text = NSLocalizedString("_tap_to_cancel_", comment: "") + hud.tapOnHUDViewBlock = { hud in + self.isCancelled = true + hud.dismiss() + } + self.hud = hud + } + } + + /// Execute + /// - Parameter task: The task to execute. Needs to call `completion()` when done so the next task can be executed. + func execute(task: @escaping (_ completion: @escaping () -> Void) -> Void) { + completionGroup.enter() + queue.async { + self.semaphore.wait() + guard !self.isCancelled else { return self.completionGroup.leave() } + task { + self.completedTasks += 1 + DispatchQueue.main.async { + self.hud?.textLabel.text = "\(NSLocalizedString(self.titleKey, comment: "")) \(self.completedTasks) " + if let totalTasks = self.totalTasks { + self.hud?.textLabel.text?.append("\(NSLocalizedString("_of_", comment: "")) \(totalTasks)") + } else { + self.hud?.textLabel.text?.append(NSLocalizedString("_files_", comment: "")) + } + } + self.semaphore.signal() + self.completionGroup.leave() + } + } + } + + /// Indicates that all tasks have been scheduled. Some tasks might still be in progress. + /// - Parameter completion: Will be called after all tasks have finished + func completeWork(completion: (() -> Void)? = nil) { + completionGroup.notify(queue: .main) { + guard !self.isCancelled else { return } + self.hud?.indicatorView = JGProgressHUDSuccessIndicatorView() + self.hud?.textLabel.text = NSLocalizedString("_done_", comment: "") + self.hud?.detailTextLabel.text = "" + self.hud?.dismiss(afterDelay: 1) + completion?() + } + } +} diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCKTVHTTPCache.swift b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCKTVHTTPCache.swift index 5a213bcf1..067bf0946 100644 --- a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCKTVHTTPCache.swift +++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCKTVHTTPCache.swift @@ -33,7 +33,7 @@ class NCKTVHTTPCache: NSObject { func getVideoURL(metadata: tableMetadata) -> URL? { - if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + if CCUtility.fileProviderStorageExists(metadata) { return URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)) @@ -94,7 +94,7 @@ class NCKTVHTTPCache: NSObject { func saveCache(metadata: tableMetadata) { - if !CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + if !CCUtility.fileProviderStorageExists(metadata) { guard let stringURL = (metadata.serverUrl + "/" + metadata.fileName).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { return } diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift index 05548d089..9c796b421 100644 --- a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift +++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayer.swift @@ -32,10 +32,10 @@ class NCPlayer: NSObject { internal let appDelegate = UIApplication.shared.delegate as! AppDelegate internal var url: URL internal var playerToolBar: NCPlayerToolBar? - + internal var viewController: UIViewController + private var imageVideoContainer: imageVideoContainerView private var detailView: NCViewerMediaDetailView? - private var viewController: UIViewController private var observerAVPlayerItemDidPlayToEndTime: Any? private var observerAVPlayertTime: Any? @@ -65,11 +65,17 @@ class NCPlayer: NSObject { print(error) } - // Exists the file video encoded + #if MFFFLIB if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: NCGlobal.shared.fileNameVideoEncoded) { self.url = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: NCGlobal.shared.fileNameVideoEncoded)) } - + if MFFF.shared.existsMFFFSession(url: URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView))) { + return + } else { + MFFF.shared.dismissMessage() + } + #endif + openAVPlayer() { status, error in switch status { diff --git a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift index f3a539597..b28862d4b 100644 --- a/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift +++ b/iOSClient/Viewer/NCViewerMedia/NCPlayer/NCPlayerToolBar.swift @@ -262,9 +262,9 @@ class NCPlayerToolBar: UIView { public func show(enableTimerAutoHide: Bool = false) { - guard let metadata = self.metadata, ncplayer != nil, !metadata.livePhoto, (metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue) else - { return } - + guard let metadata = self.metadata, ncplayer != nil, !metadata.livePhoto else { return } + if metadata.classFile != NCCommunicationCommon.typeClassFile.video.rawValue && metadata.classFile != NCCommunicationCommon.typeClassFile.audio.rawValue { return } + #if MFFFLIB if MFFF.shared.existsMFFFSession(url: URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView))) { self.hide() diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift b/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift index e43aca34a..f276b5e92 100644 --- a/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift +++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMedia.swift @@ -164,12 +164,9 @@ class NCViewerMedia: UIViewController { } #if MFFFLIB - MFFF.shared.delegate = self.ncplayer -// if !MFFF.shared.existsMFFFSession(url: URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView))) { -// self.playerToolBar.hideMessage() -// } + MFFF.shared.setDelegate = self.ncplayer #endif - + } else if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue { viewerMediaPage?.clearCommandCenter() @@ -244,7 +241,7 @@ class NCViewerMedia: UIViewController { let isFolderEncrypted = CCUtility.isFolderEncrypted(metadata.serverUrl, e2eEncrypted: metadata.e2eEncrypted, account: metadata.account, urlBase: metadata.urlBase) let ext = CCUtility.getExtension(metadata.fileNameView) - if (CCUtility.getAutomaticDownloadImage() || (metadata.contentType == "image/heic" && metadata.hasPreview == false) || ext == "GIF" || ext == "SVG" || isFolderEncrypted) && (metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && !CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) && metadata.session == "") { + if (CCUtility.getAutomaticDownloadImage() || (metadata.contentType == "image/heic" && metadata.hasPreview == false) || ext == "GIF" || ext == "SVG" || isFolderEncrypted) && (metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && !CCUtility.fileProviderStorageExists(metadata) && metadata.session == "") { NCNetworking.shared.download(metadata: metadata, selector: "") { _ in @@ -268,7 +265,7 @@ class NCViewerMedia: UIViewController { let fileName = (metadata.fileNameView as NSString).deletingPathExtension + ".mov" - if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameView LIKE[c] %@", metadata.account, metadata.serverUrl, fileName)), !CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameView LIKE[c] %@", metadata.account, metadata.serverUrl, fileName)), !CCUtility.fileProviderStorageExists(metadata) { NCNetworking.shared.download(metadata: metadata, selector: "") { _ in } } @@ -304,7 +301,7 @@ class NCViewerMedia: UIViewController { let ext = CCUtility.getExtension(metadata.fileNameView) var image: UIImage? - if CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) && metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue { + if CCUtility.fileProviderStorageExists(metadata) && metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue { let previewPath = CCUtility.getDirectoryProviderStoragePreviewOcId(metadata.ocId, etag: metadata.etag)! let imagePath = CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)! diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift index dc15718fc..350b795cb 100644 --- a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift +++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaDetailView.swift @@ -156,7 +156,7 @@ class NCViewerMediaDetailView: UIView { } // Message - if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && !CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) && metadata.session == "" { + if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && !CCUtility.fileProviderStorageExists(metadata) && metadata.session == "" { messageButton.setTitle(NSLocalizedString("_try_download_full_resolution_", comment: ""), for: .normal) messageButton.isHidden = false } else { diff --git a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift index afe06d96f..5a304f6ea 100644 --- a/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift +++ b/iOSClient/Viewer/NCViewerMedia/NCViewerMediaPage.swift @@ -117,7 +117,11 @@ class NCViewerMediaPage: UIViewController { metadatas.removeAll() ncplayerLivePhoto = nil - + + #if MFFFLIB + MFFF.shared.dismissMessage() + #endif + // Remove Observer NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterDeleteFile), object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterRenameFile), object: nil) @@ -579,7 +583,7 @@ extension NCViewerMediaPage: UIGestureRecognizerDelegate { currentViewController.statusLabel.isHidden = true let fileName = (currentViewController.metadata.fileNameView as NSString).deletingPathExtension + ".mov" - if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameView LIKE[c] %@", currentViewController.metadata.account, currentViewController.metadata.serverUrl, fileName)), CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + if let metadata = NCManageDatabase.shared.getMetadata(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND fileNameView LIKE[c] %@", currentViewController.metadata.account, currentViewController.metadata.serverUrl, fileName)), CCUtility.fileProviderStorageExists(metadata) { AudioServicesPlaySystemSound(1519) // peek feedback diff --git a/iOSClient/Viewer/NCViewerProviderContextMenu.swift b/iOSClient/Viewer/NCViewerProviderContextMenu.swift index 58965dd99..67a653fdc 100644 --- a/iOSClient/Viewer/NCViewerProviderContextMenu.swift +++ b/iOSClient/Viewer/NCViewerProviderContextMenu.swift @@ -80,30 +80,28 @@ class NCViewerProviderContextMenu: UIViewController { } // VIEW IMAGE - if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { - + if metadata.classFile == NCCommunicationCommon.typeClassFile.image.rawValue && CCUtility.fileProviderStorageExists(metadata) { viewImage(metadata: metadata) } // VIEW LIVE PHOTO - if metadataLivePhoto != nil && CCUtility.fileProviderStorageExists(metadataLivePhoto!.ocId, fileNameView: metadataLivePhoto!.fileNameView) { - - viewVideo(metadata: metadataLivePhoto!) + if let metadataLivePhoto = metadataLivePhoto, CCUtility.fileProviderStorageExists(metadataLivePhoto) { + viewVideo(metadata: metadataLivePhoto) } // VIEW VIDEO - if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue && CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + if metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue && CCUtility.fileProviderStorageExists(metadata) { viewVideo(metadata: metadata) } // PLAY SOUND - if metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue && CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) { + if metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue && CCUtility.fileProviderStorageExists(metadata) { playSound(metadata: metadata) } // AUTO DOWNLOAD VIDEO / AUDIO // if !CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) && (metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue || metadata.contentType == "application/pdf") { - if !CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) && (metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue) { + if !CCUtility.fileProviderStorageExists(metadata) && (metadata.classFile == NCCommunicationCommon.typeClassFile.video.rawValue || metadata.classFile == NCCommunicationCommon.typeClassFile.audio.rawValue) { var maxDownload: UInt64 = 0 @@ -119,18 +117,18 @@ class NCViewerProviderContextMenu: UIViewController { } // AUTO DOWNLOAD IMAGE GIF - if !CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) && metadata.contentType == "image/gif" { + if !CCUtility.fileProviderStorageExists(metadata) && metadata.contentType == "image/gif" { NCOperationQueue.shared.download(metadata: metadata, selector: "") } // AUTO DOWNLOAD IMAGE SVG - if !CCUtility.fileProviderStorageExists(metadata.ocId, fileNameView: metadata.fileNameView) && metadata.contentType == "image/svg+xml" { + if !CCUtility.fileProviderStorageExists(metadata) && metadata.contentType == "image/svg+xml" { NCOperationQueue.shared.download(metadata: metadata, selector: "") } // AUTO DOWNLOAD LIVE PHOTO if let metadataLivePhoto = self.metadataLivePhoto { - if !CCUtility.fileProviderStorageExists(metadataLivePhoto.ocId, fileNameView: metadataLivePhoto.fileNameView) { + if !CCUtility.fileProviderStorageExists(metadataLivePhoto) { NCOperationQueue.shared.download(metadata: metadataLivePhoto, selector: "") } } |