From 09dd9a16d9d2ce3ce91783acae5815e8ac376bac Mon Sep 17 00:00:00 2001 From: Marino Faggiana Date: Mon, 18 Mar 2024 11:08:20 +0100 Subject: [PATCH] Version 5.2.2 (#2852) --- .github/workflows/{xcode.yml => xcode.xxx} | 0 Brand/Database.swift | 2 +- Nextcloud.xcodeproj/project.pbxproj | 67 ++- Share/NCShareExtension+DataSource.swift | 2 +- iOSClient/AppDelegate.swift | 47 +- .../Data/NCManageDatabase+Metadata.swift | 26 +- .../UIAlertController+Extension.swift | 45 ++ iOSClient/Extensions/UIColor+Extension.swift | 7 +- iOSClient/Extensions/UIView+Extension.swift | 6 + iOSClient/Files/NCFiles.swift | 27 +- .../Image.imageset/Contents.json | 9 + .../Image.imageset/folder_link.svg | 10 + .../Contents.json | 38 ++ .../folder.imageset/Contents.json | 13 +- .../folder.imageset/folder.pdf | Bin 911 -> 0 bytes .../folder.imageset/folder.svg | 10 + .../Contents.json | 13 +- .../folderAutomaticUpload.pdf | Bin 1266 -> 0 bytes .../folder_photo.svg | 10 + .../folderEncrypted.imageset/Contents.json | 13 +- .../folderEncrypted.pdf | Bin 1085 -> 0 bytes .../folder_encrypted.svg | 10 + .../folderStarred.imageset/Contents.json | 15 - .../folderStarred.imageset/folderStarred.pdf | Bin 969 -> 0 bytes .../folder_external.imageset/Contents.json | 13 +- .../folder_external.pdf | Bin 1128 -> 0 bytes .../folder_external.svg | 10 + .../folder_group.imageset/Contents.json | 13 +- .../folder_group.imageset/Untitled.pdf | Bin 2229 -> 0 bytes .../folder_group.imageset/folder_group.svg | 10 + .../folder_public.imageset/Contents.json | 13 +- .../folder_public.imageset/folder_link.svg | 10 + .../folder_public.imageset/folder_public.pdf | Bin 1463 -> 0 bytes .../Contents.json | 13 +- .../folder_shared_with_me.pdf | Bin 2420 -> 0 bytes .../folder_shared_with_me.svg | 10 + ...ctionViewCommon+SelectTabBarDelegate.swift | 313 ++++++++++++++ ...mmon+SwipeCollectionViewCellDelegate.swift | 94 ++++ .../NCCollectionViewCommon.swift | 408 +----------------- .../NCCollectionViewCommonSelectTabBar.swift | 15 + .../NCCollectionViewDownloadThumbnail.swift | 88 ++++ .../NCCollectionViewUnifiedSearch.swift | 60 +++ .../Main/Collection Common/NCGridCell.swift | 17 +- .../Main/Collection Common/NCGridCell.xib | 30 +- .../Main/Collection Common/NCListCell.swift | 39 +- .../Main/Collection Common/NCListCell.xib | 39 +- .../NCSelectableNavigationView.swift | 5 +- iOSClient/Main/NCCellProtocol.swift | 4 +- iOSClient/Media/NCMediaDataSource.swift | 4 +- .../Menu/NCCollectionViewCommon+Menu.swift | 4 +- iOSClient/Menu/NCMenuAction.swift | 49 +-- iOSClient/Menu/NCViewer+Menu.swift | 4 +- iOSClient/More/Cells/NCMoreUserCell.swift | 6 + iOSClient/Networking/NCAutoUpload.swift | 8 + .../NCNetworking+Synchronization.swift | 2 +- .../Networking/NCNetworking+Upload.swift | 5 - .../Networking/NCNetworking+WebDAV.swift | 8 +- .../Networking/NCNetworkingProcess.swift | 343 ++++++--------- iOSClient/Networking/NCService.swift | 2 +- iOSClient/Select/NCSelect.swift | 2 +- iOSClient/Settings/Acknowledgements.rtf | 93 +++- iOSClient/Settings/NCKeychain.swift | 14 + .../af.lproj/Localizable.strings | Bin 124378 -> 124666 bytes .../an.lproj/Localizable.strings | Bin 123744 -> 124012 bytes .../ar.lproj/Localizable.strings | Bin 122938 -> 123186 bytes .../ast.lproj/Localizable.strings | Bin 123768 -> 124036 bytes .../az.lproj/Localizable.strings | Bin 124068 -> 124338 bytes .../be.lproj/Localizable.strings | Bin 123824 -> 124092 bytes .../bg_BG.lproj/Localizable.strings | Bin 131258 -> 131520 bytes .../bn_BD.lproj/Localizable.strings | Bin 123994 -> 124264 bytes .../br.lproj/Localizable.strings | Bin 127988 -> 128248 bytes .../bs.lproj/Localizable.strings | Bin 124056 -> 124326 bytes .../ca.lproj/Localizable.strings | Bin 130986 -> 131258 bytes .../cs-CZ.lproj/Localizable.strings | Bin 127638 -> 127882 bytes .../cy_GB.lproj/Localizable.strings | Bin 124018 -> 124288 bytes .../da.lproj/Localizable.strings | Bin 124740 -> 124994 bytes .../de.lproj/Localizable.strings | Bin 135400 -> 135662 bytes .../el.lproj/Localizable.strings | Bin 134552 -> 134838 bytes .../en-GB.lproj/Localizable.strings | Bin 123844 -> 124112 bytes .../en.lproj/Localizable.strings | 6 +- .../eo.lproj/Localizable.strings | Bin 124486 -> 124752 bytes .../es-419.lproj/Localizable.strings | Bin 127908 -> 128184 bytes .../es-AR.lproj/Localizable.strings | Bin 126934 -> 127214 bytes .../es-CL.lproj/Localizable.strings | Bin 128630 -> 128906 bytes .../es-CO.lproj/Localizable.strings | Bin 128276 -> 128552 bytes .../es-CR.lproj/Localizable.strings | Bin 128278 -> 128554 bytes .../es-DO.lproj/Localizable.strings | Bin 128274 -> 128550 bytes .../es-EC.lproj/Localizable.strings | Bin 133612 -> 133888 bytes .../es-GT.lproj/Localizable.strings | Bin 128278 -> 128554 bytes .../es-HN.lproj/Localizable.strings | Bin 127892 -> 128168 bytes .../es-MX.lproj/Localizable.strings | Bin 128592 -> 128868 bytes .../es-NI.lproj/Localizable.strings | Bin 127882 -> 128158 bytes .../es-PA.lproj/Localizable.strings | Bin 127890 -> 128166 bytes .../es-PE.lproj/Localizable.strings | Bin 127880 -> 128156 bytes .../es-PR.lproj/Localizable.strings | Bin 127892 -> 128168 bytes .../es-PY.lproj/Localizable.strings | Bin 127908 -> 128184 bytes .../es-SV.lproj/Localizable.strings | Bin 128266 -> 128542 bytes .../es-UY.lproj/Localizable.strings | Bin 127906 -> 128182 bytes .../es.lproj/Localizable.strings | Bin 133204 -> 133446 bytes .../et_EE.lproj/Localizable.strings | Bin 124292 -> 124560 bytes .../eu.lproj/Localizable.strings | Bin 131084 -> 131376 bytes .../fa.lproj/Localizable.strings | Bin 124570 -> 124848 bytes .../fi-FI.lproj/Localizable.strings | Bin 126786 -> 127060 bytes .../fo.lproj/Localizable.strings | Bin 123754 -> 124022 bytes .../fr.lproj/Localizable.strings | Bin 137878 -> 138132 bytes .../gd.lproj/Localizable.strings | Bin 125254 -> 125522 bytes .../gl.lproj/Localizable.strings | Bin 132816 -> 133084 bytes .../he.lproj/Localizable.strings | Bin 121868 -> 122128 bytes .../hi_IN.lproj/Localizable.strings | Bin 123728 -> 123996 bytes .../hr.lproj/Localizable.strings | Bin 128552 -> 128826 bytes .../hsb.lproj/Localizable.strings | Bin 123734 -> 124002 bytes .../hu.lproj/Localizable.strings | Bin 130038 -> 130328 bytes .../hy.lproj/Localizable.strings | Bin 124010 -> 124278 bytes .../ia.lproj/Localizable.strings | Bin 124512 -> 124782 bytes .../id.lproj/Localizable.strings | Bin 124642 -> 124912 bytes .../ig.lproj/Localizable.strings | Bin 123704 -> 123972 bytes .../is.lproj/Localizable.strings | Bin 125998 -> 126260 bytes .../it.lproj/Localizable.strings | Bin 132428 -> 132706 bytes .../ja-JP.lproj/Localizable.strings | Bin 106634 -> 106934 bytes .../ka-GE.lproj/Localizable.strings | Bin 126458 -> 126738 bytes .../ka.lproj/Localizable.strings | Bin 123732 -> 124000 bytes .../kab.lproj/Localizable.strings | Bin 123788 -> 124060 bytes .../km.lproj/Localizable.strings | Bin 123986 -> 124254 bytes .../kn.lproj/Localizable.strings | Bin 124218 -> 124478 bytes .../ko.lproj/Localizable.strings | Bin 100876 -> 101176 bytes .../la.lproj/Localizable.strings | Bin 123718 -> 123986 bytes .../lb.lproj/Localizable.strings | Bin 124142 -> 124412 bytes .../lo.lproj/Localizable.strings | Bin 122398 -> 122676 bytes .../lt_LT.lproj/Localizable.strings | Bin 126414 -> 126688 bytes .../lv.lproj/Localizable.strings | Bin 124844 -> 125112 bytes .../mk.lproj/Localizable.strings | Bin 125040 -> 125308 bytes .../mn.lproj/Localizable.strings | Bin 124514 -> 124786 bytes .../mr.lproj/Localizable.strings | Bin 123696 -> 123964 bytes .../ms_MY.lproj/Localizable.strings | Bin 123846 -> 124114 bytes .../my.lproj/Localizable.strings | Bin 123914 -> 124182 bytes .../nb-NO.lproj/Localizable.strings | Bin 126320 -> 126582 bytes .../ne.lproj/Localizable.strings | Bin 123748 -> 124016 bytes .../nl.lproj/Localizable.strings | Bin 129272 -> 129550 bytes .../nn_NO.lproj/Localizable.strings | Bin 123872 -> 124140 bytes .../oc.lproj/Localizable.strings | Bin 124870 -> 125140 bytes .../pl.lproj/Localizable.strings | Bin 128656 -> 128930 bytes .../ps.lproj/Localizable.strings | Bin 123746 -> 124010 bytes .../pt-BR.lproj/Localizable.strings | Bin 130520 -> 130804 bytes .../pt-PT.lproj/Localizable.strings | Bin 127616 -> 127888 bytes .../ro.lproj/Localizable.strings | Bin 126870 -> 127144 bytes .../ru.lproj/Localizable.strings | Bin 130676 -> 130958 bytes .../sc.lproj/Localizable.strings | Bin 132808 -> 133082 bytes .../si.lproj/Localizable.strings | Bin 124686 -> 124954 bytes .../sk-SK.lproj/Localizable.strings | Bin 128548 -> 128832 bytes .../sl.lproj/Localizable.strings | Bin 129626 -> 129912 bytes .../sq.lproj/Localizable.strings | Bin 125526 -> 125798 bytes .../sr.lproj/Localizable.strings | Bin 127860 -> 128068 bytes .../sr@latin.lproj/Localizable.strings | Bin 124032 -> 124300 bytes .../sv.lproj/Localizable.strings | Bin 126038 -> 126308 bytes .../sw.lproj/Localizable.strings | Bin 123728 -> 123996 bytes .../ta.lproj/Localizable.strings | Bin 124062 -> 124326 bytes .../th_TH.lproj/Localizable.strings | Bin 123626 -> 123894 bytes .../tk.lproj/Localizable.strings | Bin 124428 -> 124698 bytes .../tr.lproj/Localizable.strings | Bin 128718 -> 128978 bytes .../ug.lproj/Localizable.strings | Bin 123902 -> 124174 bytes .../uk.lproj/Localizable.strings | Bin 126108 -> 126484 bytes .../ur_PK.lproj/Localizable.strings | Bin 123776 -> 124044 bytes .../uz.lproj/Localizable.strings | Bin 123728 -> 123996 bytes .../vi.lproj/Localizable.strings | Bin 125124 -> 125392 bytes .../zh-Hans.lproj/Localizable.strings | Bin 91776 -> 92008 bytes .../zh-Hant-TW.lproj/Localizable.strings | Bin 102772 -> 103090 bytes .../zh_HK.lproj/Localizable.strings | Bin 92414 -> 92600 bytes .../zu_ZA.lproj/Localizable.strings | Bin 123728 -> 123996 bytes iOSClient/Transfers/NCTransfers.swift | 6 + iOSClient/Trash/NCTrash+CollectionView.swift | 2 +- iOSClient/Trash/NCTrash.swift | 2 +- iOSClient/Utility/NCCameraRoll.swift | 8 + iOSClient/Utility/NCUtility.swift | 2 +- iOSClient/Viewer/NCViewer.swift | 1 + .../NCViewerMedia/NCViewerMediaPage.swift | 3 + 175 files changed, 1327 insertions(+), 821 deletions(-) rename .github/workflows/{xcode.yml => xcode.xxx} (100%) create mode 100644 iOSClient/Images.xcassets/Image.imageset/Contents.json create mode 100644 iOSClient/Images.xcassets/Image.imageset/folder_link.svg create mode 100644 iOSClient/Images.xcassets/SystemBackgroundInverted.colorset/Contents.json delete mode 100644 iOSClient/Images.xcassets/folder.imageset/folder.pdf create mode 100644 iOSClient/Images.xcassets/folder.imageset/folder.svg delete mode 100644 iOSClient/Images.xcassets/folderAutomaticUpload.imageset/folderAutomaticUpload.pdf create mode 100644 iOSClient/Images.xcassets/folderAutomaticUpload.imageset/folder_photo.svg delete mode 100644 iOSClient/Images.xcassets/folderEncrypted.imageset/folderEncrypted.pdf create mode 100644 iOSClient/Images.xcassets/folderEncrypted.imageset/folder_encrypted.svg delete mode 100644 iOSClient/Images.xcassets/folderStarred.imageset/Contents.json delete mode 100644 iOSClient/Images.xcassets/folderStarred.imageset/folderStarred.pdf delete mode 100644 iOSClient/Images.xcassets/folder_external.imageset/folder_external.pdf create mode 100644 iOSClient/Images.xcassets/folder_external.imageset/folder_external.svg delete mode 100644 iOSClient/Images.xcassets/folder_group.imageset/Untitled.pdf create mode 100644 iOSClient/Images.xcassets/folder_group.imageset/folder_group.svg create mode 100644 iOSClient/Images.xcassets/folder_public.imageset/folder_link.svg delete mode 100644 iOSClient/Images.xcassets/folder_public.imageset/folder_public.pdf delete mode 100644 iOSClient/Images.xcassets/folder_shared_with_me.imageset/folder_shared_with_me.pdf create mode 100644 iOSClient/Images.xcassets/folder_shared_with_me.imageset/folder_shared_with_me.svg create mode 100644 iOSClient/Main/Collection Common/NCCollectionViewCommon+SelectTabBarDelegate.swift create mode 100644 iOSClient/Main/Collection Common/NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift create mode 100644 iOSClient/Main/Collection Common/NCCollectionViewDownloadThumbnail.swift create mode 100644 iOSClient/Main/Collection Common/NCCollectionViewUnifiedSearch.swift diff --git a/.github/workflows/xcode.yml b/.github/workflows/xcode.xxx similarity index 100% rename from .github/workflows/xcode.yml rename to .github/workflows/xcode.xxx diff --git a/Brand/Database.swift b/Brand/Database.swift index 0b227895fb..c1f05fc6f1 100644 --- a/Brand/Database.swift +++ b/Brand/Database.swift @@ -26,4 +26,4 @@ import Foundation // Database Realm // let databaseName = "nextcloud.realm" -let databaseSchemaVersion: UInt64 = 345 +let databaseSchemaVersion: UInt64 = 346 diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index 36f653118f..e7da10d9ae 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -85,6 +85,8 @@ F31F69612A2F907800162F76 /* __Snapshots__ in Resources */ = {isa = PBXBuildFile; fileRef = F31F69602A2F907800162F76 /* __Snapshots__ */; }; F31F69642A2F929600162F76 /* PreviewSnapshots in Frameworks */ = {isa = PBXBuildFile; productRef = F31F69632A2F929600162F76 /* PreviewSnapshots */; }; F321DA8A2B71205A00DDA0E6 /* NCTrashSelectTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = F321DA892B71205A00DDA0E6 /* NCTrashSelectTabBar.swift */; }; + F327FA432B8CC0B900E5B743 /* SwipeCellKit in Frameworks */ = {isa = PBXBuildFile; productRef = F327FA422B8CC0B900E5B743 /* SwipeCellKit */; }; + F327FA452B8CC36900E5B743 /* SwipeCellKit in Frameworks */ = {isa = PBXBuildFile; productRef = F327FA442B8CC36900E5B743 /* SwipeCellKit */; }; F32ED5062A2F254400EABA81 /* EnvVars.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A96302A27AEBF00D7BCFE /* EnvVars.generated.swift */; }; F33AAF9A2A60394C006ECCBD /* NCMoreUserCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F33AAF992A60394C006ECCBD /* NCMoreUserCell.xib */; }; F343A4B32A1E01FF00DDA874 /* PHAsset+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F343A4B22A1E01FF00DDA874 /* PHAsset+Extension.swift */; }; @@ -108,6 +110,13 @@ F359D86B2A7D03420023F405 /* NCUtility+Exif.swift in Sources */ = {isa = PBXBuildFile; fileRef = F359D8662A7D03420023F405 /* NCUtility+Exif.swift */; }; F359D86C2A7D03420023F405 /* NCUtility+Exif.swift in Sources */ = {isa = PBXBuildFile; fileRef = F359D8662A7D03420023F405 /* NCUtility+Exif.swift */; }; F359D86D2A7D03420023F405 /* NCUtility+Exif.swift in Sources */ = {isa = PBXBuildFile; fileRef = F359D8662A7D03420023F405 /* NCUtility+Exif.swift */; }; + F36E64F72B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift */; }; + F36E64F92B92459B0085ABB5 /* NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36E64F82B92459B0085ABB5 /* NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift */; }; + F36E64FA2B96236C0085ABB5 /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E41315294A19B300839300 /* UIView+Extension.swift */; }; + F36E64FB2B9733F10085ABB5 /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E41315294A19B300839300 /* UIView+Extension.swift */; }; + F36E64FC2B9733F20085ABB5 /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E41315294A19B300839300 /* UIView+Extension.swift */; }; + F36E64FD2B9735900085ABB5 /* NCCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370D26AE248A3D7A00121797 /* NCCellProtocol.swift */; }; + F36E64FE2B9735920085ABB5 /* NCCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370D26AE248A3D7A00121797 /* NCCellProtocol.swift */; }; F38F71252B6BBDC300473CDC /* NCCollectionViewCommonSelectTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = F38F71242B6BBDC300473CDC /* NCCollectionViewCommonSelectTabBar.swift */; }; F39298972A3B12CB00509762 /* BaseNCMoreCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F39298962A3B12CB00509762 /* BaseNCMoreCell.swift */; }; F3953BD72A6E87E000EE03F9 /* BaseIntegrationXCTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3953BD62A6E87E000EE03F9 /* BaseIntegrationXCTestCase.swift */; }; @@ -144,8 +153,6 @@ F70753EB2542A99800972D44 /* NCViewerMediaPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70753EA2542A99800972D44 /* NCViewerMediaPage.swift */; }; F70753F12542A9A200972D44 /* NCViewerMedia.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70753F02542A9A200972D44 /* NCViewerMedia.swift */; }; F70753F72542A9C000972D44 /* NCViewerMediaPage.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F70753F62542A9C000972D44 /* NCViewerMediaPage.storyboard */; }; - F7075B672AE15F6200512300 /* NCCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370D26AE248A3D7A00121797 /* NCCellProtocol.swift */; }; - F7075B682AE15F8100512300 /* NCCellProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370D26AE248A3D7A00121797 /* NCCellProtocol.swift */; }; F707C26521A2DC5200F6181E /* NCStoreReview.swift in Sources */ = {isa = PBXBuildFile; fileRef = F707C26421A2DC5200F6181E /* NCStoreReview.swift */; }; F70821D829E59E6D001CA2D7 /* TagListView in Frameworks */ = {isa = PBXBuildFile; productRef = F70821D729E59E6D001CA2D7 /* TagListView */; }; F70968A424212C4E00ED60E5 /* NCLivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F70968A324212C4E00ED60E5 /* NCLivePhoto.swift */; }; @@ -763,6 +770,8 @@ F7E0CDCF265CE8610044854E /* NCUserStatus.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7E0CDCE265CE8610044854E /* NCUserStatus.storyboard */; }; F7E41316294A19B300839300 /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E41315294A19B300839300 /* UIView+Extension.swift */; }; F7E4D9C422ED929B003675FD /* NCShareCommentsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E4D9C322ED929B003675FD /* NCShareCommentsCell.swift */; }; + F7E7AEA52BA32C6500512E52 /* NCCollectionViewDownloadThumbnail.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E7AEA42BA32C6500512E52 /* NCCollectionViewDownloadThumbnail.swift */; }; + F7E7AEA72BA32D0000512E52 /* NCCollectionViewUnifiedSearch.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E7AEA62BA32D0000512E52 /* NCCollectionViewUnifiedSearch.swift */; }; F7E8A391295DC5E0006CB2D0 /* View+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E8A390295DC5E0006CB2D0 /* View+Extension.swift */; }; F7E98C1627E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */; }; F7E98C1727E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */; }; @@ -973,6 +982,8 @@ F343A4B22A1E01FF00DDA874 /* PHAsset+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PHAsset+Extension.swift"; sourceTree = ""; }; F343A4BA2A1E734600DDA874 /* Optional+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optional+Extension.swift"; sourceTree = ""; }; F359D8662A7D03420023F405 /* NCUtility+Exif.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCUtility+Exif.swift"; sourceTree = ""; }; + F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+SelectTabBarDelegate.swift"; sourceTree = ""; }; + F36E64F82B92459B0085ABB5 /* NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift"; sourceTree = ""; }; F38F71242B6BBDC300473CDC /* NCCollectionViewCommonSelectTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCollectionViewCommonSelectTabBar.swift; sourceTree = ""; }; F39298962A3B12CB00509762 /* BaseNCMoreCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseNCMoreCell.swift; sourceTree = ""; }; F3953BD62A6E87E000EE03F9 /* BaseIntegrationXCTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseIntegrationXCTestCase.swift; sourceTree = ""; }; @@ -1483,6 +1494,8 @@ F7E41315294A19B300839300 /* UIView+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Extension.swift"; sourceTree = ""; }; F7E45E6D21E75BF200579249 /* ja-JP */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ja-JP"; path = "ja-JP.lproj/Localizable.strings"; sourceTree = ""; }; F7E4D9C322ED929B003675FD /* NCShareCommentsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCShareCommentsCell.swift; sourceTree = ""; }; + F7E7AEA42BA32C6500512E52 /* NCCollectionViewDownloadThumbnail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCollectionViewDownloadThumbnail.swift; sourceTree = ""; }; + F7E7AEA62BA32D0000512E52 /* NCCollectionViewUnifiedSearch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCCollectionViewUnifiedSearch.swift; sourceTree = ""; }; F7E856182351D7BE009A3330 /* SwiftyXMLParser.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyXMLParser.framework; path = Carthage/Build/iOS/SwiftyXMLParser.framework; sourceTree = ""; }; F7E8A390295DC5E0006CB2D0 /* View+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Extension.swift"; sourceTree = ""; }; F7E98C1527E0D0FC001F9F19 /* NCManageDatabase+Video.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NCManageDatabase+Video.swift"; sourceTree = ""; }; @@ -1578,6 +1591,7 @@ F72AD70F28C24BA1006CB92D /* NextcloudKit in Frameworks */, F737DA992B7B864E0063BAFC /* TOPasscodeViewController.xcframework in Frameworks */, F72CD01227A7E92400E59476 /* JGProgressHUD in Frameworks */, + F327FA452B8CC36900E5B743 /* SwipeCellKit in Frameworks */, F77CB6A92AA08053000C3CA4 /* OpenSSL in Frameworks */, F760DE092AE66ED00027D78A /* KeychainAccess in Frameworks */, F73ADD2126554F8E0069EA0D /* SwiftEntryKit in Frameworks */, @@ -1641,6 +1655,7 @@ F70B86752642CE3B00ED5349 /* FirebaseCrashlytics in Frameworks */, F7A1050E29E587AF00FFD92B /* TagListView in Frameworks */, F76DA969277B77EA0082465B /* DropDown in Frameworks */, + F327FA432B8CC0B900E5B743 /* SwipeCellKit in Frameworks */, F7F623B52A5EF4D30022D3D4 /* Gzip in Frameworks */, F75EAED826D2552E00F4320E /* MarqueeLabel in Frameworks */, F710FC7A277B7D0000AA9FBF /* Realm in Frameworks */, @@ -2059,12 +2074,16 @@ isa = PBXGroup; children = ( F70D7C3525FFBF81002B9E34 /* NCCollectionViewCommon.swift */, - AF7E504F27A2D92300B5E4AF /* NCSelectableNavigationView.swift */, + F36E64F62B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift */, + F36E64F82B92459B0085ABB5 /* NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift */, + F38F71242B6BBDC300473CDC /* NCCollectionViewCommonSelectTabBar.swift */, + F7E7AEA42BA32C6500512E52 /* NCCollectionViewDownloadThumbnail.swift */, + F7E7AEA62BA32D0000512E52 /* NCCollectionViewUnifiedSearch.swift */, F78ACD3F21903CC20088454D /* NCGridCell.swift */, F78ACD4521903D010088454D /* NCGridCell.xib */, F78ACD4121903CE00088454D /* NCListCell.swift */, F78ACD4321903CF20088454D /* NCListCell.xib */, - F38F71242B6BBDC300473CDC /* NCCollectionViewCommonSelectTabBar.swift */, + AF7E504F27A2D92300B5E4AF /* NCSelectableNavigationView.swift */, ); path = "Collection Common"; sourceTree = ""; @@ -2947,6 +2966,7 @@ F760DE082AE66ED00027D78A /* KeychainAccess */, F74C863C2AEFBFD9009A1D4A /* LRUCache */, F711A4EE2AF932B900095DD8 /* SVGKitSwift */, + F327FA442B8CC36900E5B743 /* SwipeCellKit */, ); productName = "Share Ext"; productReference = F7CE8AFB1DC1F8D8009CAE48 /* Share.appex */; @@ -3053,6 +3073,7 @@ F7F623B42A5EF4D30022D3D4 /* Gzip */, F76B649D2ADFFDEC00014640 /* LRUCache */, F760DE022AE66EA80027D78A /* KeychainAccess */, + F327FA422B8CC0B900E5B743 /* SwipeCellKit */, ); productName = "Crypto Cloud"; productReference = F7CE8AFA1DC1F8D8009CAE48 /* Nextcloud.app */; @@ -3229,6 +3250,7 @@ F7F623B32A5EF4D30022D3D4 /* XCRemoteSwiftPackageReference "GzipSwift" */, F76B649A2ADFFAD200014640 /* XCRemoteSwiftPackageReference "LRUCache" */, F760DE012AE66E860027D78A /* XCRemoteSwiftPackageReference "KeychainAccess" */, + F327FA412B8CC0B900E5B743 /* XCRemoteSwiftPackageReference "SwipeCellKit" */, ); productRefGroup = F7F67B9F1A24D27800EE80DA; projectDirPath = ""; @@ -3685,6 +3707,7 @@ F73EF7BA2B0224AB0087E6E9 /* NCManageDatabase+ExternalSites.swift in Sources */, F711A4EB2AF9327D00095DD8 /* UIImage+animatedGIF.m in Sources */, F71459D21D12E3B700CAFEEC /* CCUtility.m in Sources */, + F36E64FA2B96236C0085ABB5 /* UIView+Extension.swift in Sources */, F75A9EE723796C6F0044CFCE /* NCNetworking.swift in Sources */, AF730AFA27843E4C00B7520E /* NCShareExtension+NCDelegate.swift in Sources */, F7183BD62AEBDCD7000CD020 /* NCKeychain.swift in Sources */, @@ -3749,7 +3772,6 @@ F71F6D082B6A6A5E00F1EB15 /* ThreadSafeArray.swift in Sources */, F78302FE28B4C44700B84583 /* NCBrand.swift in Sources */, F749B64B297B0CBB00087535 /* NCManageDatabase+Share.swift in Sources */, - F7075B682AE15F8100512300 /* NCCellProtocol.swift in Sources */, F7817CF929801A3500FFBC65 /* Data+Extension.swift in Sources */, F7864ACD2A78FE73004870E0 /* NCManageDatabase+LocalFile.swift in Sources */, F343A4B42A1E084100DDA874 /* PHAsset+Extension.swift in Sources */, @@ -3775,6 +3797,7 @@ F783030628B4C51E00B84583 /* String+Extension.swift in Sources */, F763D29E2A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */, F711A4DD2AF92CAE00095DD8 /* NCUtility+Date.swift in Sources */, + F36E64FB2B9733F10085ABB5 /* UIView+Extension.swift in Sources */, F77ED59328C9CEA000E24ED0 /* ToolbarWidgetProvider.swift in Sources */, F72A17D828B221E300F3F159 /* DashboardWidgetView.swift in Sources */, F72429382AFE39A80040AEF3 /* NCLivePhoto.swift in Sources */, @@ -3799,6 +3822,7 @@ F73EF7D82B0226080087E6E9 /* NCManageDatabase+Tip.swift in Sources */, F7C9B91E2B582F550064EA91 /* NCManageDatabase+SecurityGuard.swift in Sources */, F72FD3B6297ED49A00075D28 /* NCManageDatabase+E2EE.swift in Sources */, + F36E64FD2B9735900085ABB5 /* NCCellProtocol.swift in Sources */, F783030128B4C49700B84583 /* UIImage+Extension.swift in Sources */, F72EA95428B7BABA00C88F0C /* FilesWidgetProvider.swift in Sources */, ); @@ -3808,6 +3832,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F36E64FC2B9733F20085ABB5 /* UIView+Extension.swift in Sources */, F771E3F720E239B500AFB62D /* FileProviderExtension+Actions.swift in Sources */, F7245926289BB59300474787 /* ThreadSafeDictionary.swift in Sources */, F76673F022C90434007ED366 /* FileProviderUtility.swift in Sources */, @@ -3843,6 +3868,7 @@ AF4BF61B27562A4B0081CEEF /* NCManageDatabase+Metadata.swift in Sources */, F70460542499095400BB98A7 /* NotificationCenter+MainThread.swift in Sources */, F78A10C329322E8A008499B8 /* NCManageDatabase+Directory.swift in Sources */, + F36E64FE2B9735920085ABB5 /* NCCellProtocol.swift in Sources */, F7BF9D862934CA21009EE9A6 /* NCManageDatabase+LayoutForView.swift in Sources */, F7E98C1827E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */, F785EEA42461A4A600B3F945 /* NCUtility.swift in Sources */, @@ -3870,7 +3896,6 @@ F343A4BF2A1E734600DDA874 /* Optional+Extension.swift in Sources */, AF4BF62027562B3F0081CEEF /* NCManageDatabase+Activity.swift in Sources */, F785EEA62461A4FB00B3F945 /* CCUtility.m in Sources */, - F7075B672AE15F6200512300 /* NCCellProtocol.swift in Sources */, F73ADD2226554FD10069EA0D /* NCContentPresenter.swift in Sources */, F72FD3B9297ED49A00075D28 /* NCManageDatabase+E2EE.swift in Sources */, ); @@ -3883,6 +3908,7 @@ F30A96312A27AEBF00D7BCFE /* EnvVars.generated.swift in Sources */, F77444F522281649000D5EB0 /* NCGridMediaCell.swift in Sources */, F78C6FDE296D677300C952C3 /* NCContextMenu.swift in Sources */, + F7E7AEA72BA32D0000512E52 /* NCCollectionViewUnifiedSearch.swift in Sources */, F769CA172965AB7C00039397 /* NCUploadAssets.swift in Sources */, F73EF7A72B0223900087E6E9 /* NCManageDatabase+Comments.swift in Sources */, F7AE00F8230E81CB007ACF8A /* NCBrowserWeb.swift in Sources */, @@ -3965,6 +3991,7 @@ F7A0D1352591FBC5008F8A13 /* String+Extension.swift in Sources */, F77B0E5F1D118A16002130FE /* NCSettings.m in Sources */, F7F9D1BB25397CE000D9BFF5 /* NCViewer.swift in Sources */, + F7E7AEA52BA32C6500512E52 /* NCCollectionViewDownloadThumbnail.swift in Sources */, AF730AF827834B1400B7520E /* NCShare+NCCellDelegate.swift in Sources */, F70460522499061800BB98A7 /* NotificationCenter+MainThread.swift in Sources */, F78F74362163781100C2ADAD /* NCTrash.swift in Sources */, @@ -4021,6 +4048,7 @@ F7C30DFD291BD0B80017149B /* NCNetworkingE2EEDelete.swift in Sources */, F72FD3B5297ED49A00075D28 /* NCManageDatabase+E2EE.swift in Sources */, F73EF7CF2B0225BA0087E6E9 /* NCManageDatabase+Tag.swift in Sources */, + F36E64F92B92459B0085ABB5 /* NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift in Sources */, AF93471227E2341B002537EE /* NCShare+Menu.swift in Sources */, F7EFA47825ADBA500083159A /* NCViewerProviderContextMenu.swift in Sources */, F755BD9B20594AC7008C5FBB /* NCService.swift in Sources */, @@ -4032,6 +4060,7 @@ F70D7C3725FFBF82002B9E34 /* NCCollectionViewCommon.swift in Sources */, F76D364628A4F8BF00214537 /* NCActivityIndicator.swift in Sources */, F7134186259747BA00768D21 /* NCPushNotification.m in Sources */, + F36E64F72B9245210085ABB5 /* NCCollectionViewCommon+SelectTabBarDelegate.swift in Sources */, F3BB464F2A39EBE500461F6E /* NCMoreUserCell.swift in Sources */, F726EEEC1FED1C820030B9C8 /* NCEndToEndInitialize.swift in Sources */, F79A65C62191D95E00FF6DCC /* NCSelect.swift in Sources */, @@ -4991,7 +5020,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0; + CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = NKUJUXUJ3B; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -5017,7 +5046,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 5.2.1; + MARKETING_VERSION = 5.2.2; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ""; SDKROOT = iphoneos; @@ -5056,7 +5085,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 0; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = NKUJUXUJ3B; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -5079,7 +5108,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 5.2.1; + MARKETING_VERSION = 5.2.2; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ""; SDKROOT = iphoneos; @@ -5230,6 +5259,14 @@ version = 1.4.0; }; }; + F327FA412B8CC0B900E5B743 /* XCRemoteSwiftPackageReference "SwipeCellKit" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/SwipeCellKit/SwipeCellKit"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.7.1; + }; + }; F70B86732642CE3B00ED5349 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/firebase/firebase-ios-sdk"; @@ -5455,6 +5492,16 @@ package = F31F69622A2F929600162F76 /* XCRemoteSwiftPackageReference "swiftui-preview-snapshots" */; productName = PreviewSnapshots; }; + F327FA422B8CC0B900E5B743 /* SwipeCellKit */ = { + isa = XCSwiftPackageProductDependency; + package = F327FA412B8CC0B900E5B743 /* XCRemoteSwiftPackageReference "SwipeCellKit" */; + productName = SwipeCellKit; + }; + F327FA442B8CC36900E5B743 /* SwipeCellKit */ = { + isa = XCSwiftPackageProductDependency; + package = F327FA412B8CC0B900E5B743 /* XCRemoteSwiftPackageReference "SwipeCellKit" */; + productName = SwipeCellKit; + }; F3C6D0962B0F9BA40078DD25 /* XLForm */ = { isa = XCSwiftPackageProductDependency; package = F74E771E277A2EF40013B958 /* XCRemoteSwiftPackageReference "XLForm" */; diff --git a/Share/NCShareExtension+DataSource.swift b/Share/NCShareExtension+DataSource.swift index 466a60609d..6931b1181c 100644 --- a/Share/NCShareExtension+DataSource.swift +++ b/Share/NCShareExtension+DataSource.swift @@ -59,7 +59,7 @@ extension NCShareExtension: UICollectionViewDataSource { return UICollectionViewCell() } - cell.delegate = self + cell.listCellDelegate = self cell.fileObjectId = metadata.ocId cell.indexPath = indexPath diff --git a/iOSClient/AppDelegate.swift b/iOSClient/AppDelegate.swift index d82b1cb27e..71497052ab 100644 --- a/iOSClient/AppDelegate.swift +++ b/iOSClient/AppDelegate.swift @@ -187,8 +187,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD NCSettingsBundleHelper.setVersionAndBuildNumber() NCSettingsBundleHelper.checkAndExecuteSettings(delay: 0.5) - // START OBSERVE/TIMER UPLOAD PROCESS - NCNetworkingProcess.shared.observeTableMetadata() + // START TIMER UPLOAD PROCESS NCNetworkingProcess.shared.startTimer() if !NCAskAuthorization().isRequesting { @@ -211,8 +210,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD guard !account.isEmpty else { return } - // STOP OBSERVE/TIMER UPLOAD PROCESS - NCNetworkingProcess.shared.invalidateObserveTableMetadata() + // STOP TIMER UPLOAD PROCESS NCNetworkingProcess.shared.stopTimer() if NCKeychain().privacyScreenEnabled { @@ -359,33 +357,28 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD } func handleAppRefreshProcessingTask(taskText: String, completion: @escaping () -> Void = {}) { - let semaphore = DispatchSemaphore(value: 0) - - NCAutoUpload.shared.initAutoUpload(viewController: nil) { items in + Task { + NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] \(taskText) start handle") + let items = await NCAutoUpload.shared.initAutoUpload() NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] \(taskText) auto upload with \(items) uploads") - - NCNetworkingProcess.shared.start { counterDownload, counterUpload in - NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] \(taskText) networking process with download: \(counterDownload) upload: \(counterUpload)") - - if taskText == "ProcessingTask", - items == 0, counterDownload == 0, counterUpload == 0, - let directories = NCManageDatabase.shared.getTablesDirectory(predicate: NSPredicate(format: "account == %@ AND offline == true", self.account), sorted: "offlineDate", ascending: true) { - - for directory: tableDirectory in directories { - // only 3 time for day - if let offlineDate = directory.offlineDate, offlineDate.addingTimeInterval(28800) > Date() { - NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] \(taskText) skip synchronization for \(directory.serverUrl) in date \(offlineDate)") - continue - } - NCNetworking.shared.synchronization(account: self.account, serverUrl: directory.serverUrl, add: false) { errorCode, items in - NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] \(taskText) end synchronization for \(directory.serverUrl), errorCode: \(errorCode), item: \(items)") - semaphore.signal() - } - semaphore.wait() + let results = await NCNetworkingProcess.shared.start() + NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] \(taskText) networking process with download: \(results.counterDownload) upload: \(results.counterUpload)") + + if taskText == "ProcessingTask", + items == 0, results.counterDownload == 0, results.counterUpload == 0, + let directories = NCManageDatabase.shared.getTablesDirectory(predicate: NSPredicate(format: "account == %@ AND offline == true", self.account), sorted: "offlineDate", ascending: true) { + for directory: tableDirectory in directories { + // only 3 time for day + if let offlineDate = directory.offlineDate, offlineDate.addingTimeInterval(28800) > Date() { + NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] \(taskText) skip synchronization for \(directory.serverUrl) in date \(offlineDate)") + continue } + let results = await NCNetworking.shared.synchronization(account: self.account, serverUrl: directory.serverUrl, add: false) + NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] \(taskText) end synchronization for \(directory.serverUrl), errorCode: \(results.errorCode), item: \(results.items)") } - completion() } + NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] \(taskText) completion handle") + completion() } } diff --git a/iOSClient/Data/NCManageDatabase+Metadata.swift b/iOSClient/Data/NCManageDatabase+Metadata.swift index ba1d8b6f1b..a2dd2f59a9 100644 --- a/iOSClient/Data/NCManageDatabase+Metadata.swift +++ b/iOSClient/Data/NCManageDatabase+Metadata.swift @@ -62,7 +62,6 @@ class tableMetadata: Object, NCUserBaseUrl { @objc dynamic var dataFingerprint = "" @objc dynamic var date = NSDate() @objc dynamic var directory: Bool = false - @objc dynamic var deleteAssetLocalIdentifier: Bool = false @objc dynamic var downloadURL = "" @objc dynamic var e2eEncrypted: Bool = false @objc dynamic var edited: Bool = false @@ -215,7 +214,7 @@ extension tableMetadata { return session.isEmpty && !isDocumentViewableOnly && !isDirectoryE2EE && !e2eEncrypted } - var canOpenIn: Bool { + var canShare: Bool { return session.isEmpty && !isDocumentViewableOnly && !directory && !NCBrandOptions.shared.disable_openin_file } @@ -979,7 +978,7 @@ extension NCManageDatabase { do { let realm = try Realm() - let results = realm.objects(tableMetadata.self).filter("account == %@ AND assetLocalIdentifier != '' AND deleteAssetLocalIdentifier == true", account) + let results = realm.objects(tableMetadata.self).filter("account == %@ AND assetLocalIdentifier != ''", account) for result in results { assetLocalIdentifiers.append(result.assetLocalIdentifier) } @@ -998,7 +997,6 @@ extension NCManageDatabase { let results = realm.objects(tableMetadata.self).filter("account == %@ AND assetLocalIdentifier IN %@", account, assetLocalIdentifiers) for result in results { result.assetLocalIdentifier = "" - result.deleteAssetLocalIdentifier = false } } } catch let error { @@ -1123,24 +1121,24 @@ extension NCManageDatabase { } @discardableResult - func updateMetadatas(_ metadatas: [tableMetadata], predicate: NSPredicate) -> (metadatasChangedCount: Int, metadatasChanged: Bool) { + func updateMetadatas(_ metadatas: [tableMetadata], predicate: NSPredicate) -> (metadatasDifferentCount: Int, metadatasModified: Int) { - var metadatasChangedCount: Int = 0 - var metadatasChanged: Bool = false + var metadatasDifferentCount: Int = 0 + var metadatasModified: Int = 0 do { let realm = try Realm() try realm.write { let results = realm.objects(tableMetadata.self).filter(predicate) - metadatasChangedCount = metadatas.count - results.count + metadatasDifferentCount = metadatas.count - results.count for metadata in metadatas { - if let result = results.first(where: { $0.ocId == metadata.ocId }), - metadata.isEqual(result) { } else { - metadatasChanged = true - break + if let result = results.first(where: { $0.ocId == metadata.ocId }) { + // before realm.add copy the value not available from server + metadata.assetLocalIdentifier = result.assetLocalIdentifier + if !metadata.isEqual(result) { metadatasModified += 1 } } } - if metadatasChangedCount != 0 || metadatasChanged { + if metadatasDifferentCount != 0 || metadatasModified > 0 { realm.delete(results) for metadata in metadatas { realm.add(tableMetadata(value: metadata), update: .all) @@ -1151,7 +1149,7 @@ extension NCManageDatabase { NextcloudKit.shared.nkCommonInstance.writeLog("Could not write to database: \(error)") } - return (metadatasChangedCount, metadatasChanged) + return (metadatasDifferentCount, metadatasModified) } func replaceMetadata(_ metadatas: [tableMetadata], predicate: NSPredicate) { diff --git a/iOSClient/Extensions/UIAlertController+Extension.swift b/iOSClient/Extensions/UIAlertController+Extension.swift index d662fc699f..4b97d1c621 100644 --- a/iOSClient/Extensions/UIAlertController+Extension.swift +++ b/iOSClient/Extensions/UIAlertController+Extension.swift @@ -101,6 +101,51 @@ extension UIAlertController { textField.isSecureTextEntry = true textField.placeholder = NSLocalizedString("_password_", comment: "") }, completion: completion) + } + + static func deleteFileOrFolder(titleString: String, message: String?, canDeleteServer: Bool, selectedMetadatas: [tableMetadata], indexPaths: [IndexPath], completion: @escaping (_ cancelled: Bool) -> Void) -> UIAlertController { + let alertController = UIAlertController( + title: titleString, + message: message, + preferredStyle: .alert) + if canDeleteServer { + alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_", comment: ""), style: .destructive) { (_: UIAlertAction) in + Task { + var error = NKError() + var ocId: [String] = [] + for metadata in selectedMetadatas where error == .success { + error = await NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: false) + if error == .success { + ocId.append(metadata.ocId) + } + } + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": ocId, "indexPath": indexPaths, "onlyLocalCache": false, "error": error]) + } + completion(false) + }) + } + alertController.addAction(UIAlertAction(title: NSLocalizedString("_remove_local_file_", comment: ""), style: .default) { (_: UIAlertAction) in + Task { + var error = NKError() + var ocId: [String] = [] + for metadata in selectedMetadatas where error == .success { + error = await NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: true) + if error == .success { + ocId.append(metadata.ocId) + } + } + if error != .success { + NCContentPresenter().showError(error: error) + } + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": ocId, "indexPath": indexPaths, "onlyLocalCache": true, "error": error]) + } + completion(false) + }) + + alertController.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel) { (_: UIAlertAction) in + completion(true) + }) + return alertController } } diff --git a/iOSClient/Extensions/UIColor+Extension.swift b/iOSClient/Extensions/UIColor+Extension.swift index ca4e8a4281..bfd8f49539 100644 --- a/iOSClient/Extensions/UIColor+Extension.swift +++ b/iOSClient/Extensions/UIColor+Extension.swift @@ -25,7 +25,12 @@ import Foundation import UIKit extension UIColor { - + var inverted: UIColor { + var r: CGFloat = 0.0, g: CGFloat = 0.0, b: CGFloat = 0.0, a: CGFloat = 0.0 + self.getRed(&r, green: &g, blue: &b, alpha: &a) + return UIColor(red: (1 - r), green: (1 - g), blue: (1 - b), alpha: a) // Assuming you want the same alpha value. + } + var hexString: String { let cgColorInRGB = cgColor.converted(to: CGColorSpace(name: CGColorSpace.sRGB)!, intent: .defaultIntent, options: nil)! diff --git a/iOSClient/Extensions/UIView+Extension.swift b/iOSClient/Extensions/UIView+Extension.swift index a65805591d..a57cde15fc 100644 --- a/iOSClient/Extensions/UIView+Extension.swift +++ b/iOSClient/Extensions/UIView+Extension.swift @@ -54,4 +54,10 @@ extension UIView { blurredEffectView.isUserInteractionEnabled = false self.addSubview(blurredEffectView) } + + func makeCircularBackground(withColor backgroundColor: UIColor) { + self.backgroundColor = backgroundColor + self.layer.cornerRadius = self.frame.size.width / 2 + self.layer.masksToBounds = true + } } diff --git a/iOSClient/Files/NCFiles.swift b/iOSClient/Files/NCFiles.swift index b03d2f8709..1f48b8f699 100644 --- a/iOSClient/Files/NCFiles.swift +++ b/iOSClient/Files/NCFiles.swift @@ -59,7 +59,7 @@ class NCFiles: NCCollectionViewCommon { self.isSearchingMode = false self.isEditMode = false self.selectOcId.removeAll() - self.selectIndexPath.removeAll() + self.selectIndexPaths.removeAll() self.layoutForView = NCManageDatabase.shared.getLayoutForView(account: self.appDelegate.account, key: self.layoutKey, serverUrl: self.serverUrl) self.gridLayout.itemForLine = CGFloat(self.layoutForView?.itemForLine ?? 3) @@ -104,7 +104,12 @@ class NCFiles: NCCollectionViewCommon { override func queryDB() { super.queryDB() - let metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl)) + var metadatas: [tableMetadata] = [] + if NCKeychain().getPersonalFilesOnly(account: self.appDelegate.account) { + metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND (ownerId == %@ || ownerId == '') AND mountType == ''", self.appDelegate.account, self.serverUrl, self.appDelegate.userId)) + } else { + metadatas = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl)) + } let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@", self.appDelegate.account, self.serverUrl)) if self.metadataFolder == nil { self.metadataFolder = NCManageDatabase.shared.getMetadataFolder(account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId, serverUrl: self.serverUrl) @@ -156,7 +161,7 @@ class NCFiles: NCCollectionViewCommon { super.reloadDataSourceNetwork() - networkReadFolder { tableDirectory, metadatas, metadatasChangedCount, metadatasChanged, error in + networkReadFolder { tableDirectory, metadatas, metadatasDifferentCount, metadatasModified, error in if error == .success { for metadata in metadatas ?? [] where !metadata.directory && downloadMetadata(metadata) { if NCNetworking.shared.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty { @@ -165,7 +170,7 @@ class NCFiles: NCCollectionViewCommon { } self.richWorkspaceText = tableDirectory?.richWorkspace - if metadatasChangedCount != 0 || metadatasChanged { + if metadatasDifferentCount != 0 || metadatasModified != 0 { self.reloadDataSource() } else { self.reloadDataSource(withQueryDB: false) @@ -176,7 +181,7 @@ class NCFiles: NCCollectionViewCommon { } } - private func networkReadFolder(completion: @escaping(_ tableDirectory: tableDirectory?, _ metadatas: [tableMetadata]?, _ metadatasChangedCount: Int, _ metadatasChanged: Bool, _ error: NKError) -> Void) { + private func networkReadFolder(completion: @escaping(_ tableDirectory: tableDirectory?, _ metadatas: [tableMetadata]?, _ metadatasDifferentCount: Int, _ metadatasModified: Int, _ error: NKError) -> Void) { var tableDirectory: tableDirectory? @@ -185,7 +190,7 @@ class NCFiles: NCCollectionViewCommon { self.collectionView.reloadData() } completion: { account, metadataFolder, error in guard error == .success, let metadataFolder else { - return completion(nil, nil, 0, false, error) + return completion(nil, nil, 0, 0, error) } tableDirectory = NCManageDatabase.shared.setDirectory(serverUrl: self.serverUrl, richWorkspace: metadataFolder.richWorkspace, account: account) // swiftlint:disable empty_string @@ -198,9 +203,9 @@ class NCFiles: NCCollectionViewCommon { forceReplaceMetadatas: forceReplaceMetadatas) { task in self.dataSourceTask = task self.collectionView.reloadData() - } completion: { _, metadataFolder, metadatas, metadatasChangedCount, metadatasChanged, error in + } completion: { _, metadataFolder, metadatas, metadatasDifferentCount, metadatasModified, error in guard error == .success else { - return completion(tableDirectory, nil, 0, false, error) + return completion(tableDirectory, nil, 0, 0, error) } self.metadataFolder = metadataFolder // E2EE @@ -245,14 +250,14 @@ class NCFiles: NCCollectionViewCommon { } else { NCContentPresenter().showError(error: NKError(errorCode: NCGlobal.shared.errorE2EEKeyDecodeMetadata, errorDescription: "_e2e_error_")) } - completion(tableDirectory, metadatas, metadatasChangedCount, metadatasChanged, error) + completion(tableDirectory, metadatas, metadatasDifferentCount, metadatasModified, error) } } else { - completion(tableDirectory, metadatas, metadatasChangedCount, metadatasChanged, error) + completion(tableDirectory, metadatas, metadatasDifferentCount, metadatasModified, error) } } } else { - completion(tableDirectory, nil, 0, false, NKError()) + completion(tableDirectory, nil, 0, 0, NKError()) } } } diff --git a/iOSClient/Images.xcassets/Image.imageset/Contents.json b/iOSClient/Images.xcassets/Image.imageset/Contents.json new file mode 100644 index 0000000000..3dcbc3dd3b --- /dev/null +++ b/iOSClient/Images.xcassets/Image.imageset/Contents.json @@ -0,0 +1,9 @@ +{ + "images" : [ + + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/Image.imageset/folder_link.svg b/iOSClient/Images.xcassets/Image.imageset/folder_link.svg new file mode 100644 index 0000000000..8966f9a61a --- /dev/null +++ b/iOSClient/Images.xcassets/Image.imageset/folder_link.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/iOSClient/Images.xcassets/SystemBackgroundInverted.colorset/Contents.json b/iOSClient/Images.xcassets/SystemBackgroundInverted.colorset/Contents.json new file mode 100644 index 0000000000..d890719186 --- /dev/null +++ b/iOSClient/Images.xcassets/SystemBackgroundInverted.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.000", + "green" : "0.000", + "red" : "0.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOSClient/Images.xcassets/folder.imageset/Contents.json b/iOSClient/Images.xcassets/folder.imageset/Contents.json index 6093e445ee..68fa26d8d7 100644 --- a/iOSClient/Images.xcassets/folder.imageset/Contents.json +++ b/iOSClient/Images.xcassets/folder.imageset/Contents.json @@ -1,15 +1,16 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "folder.pdf" + "filename" : "folder.svg", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { - "preserves-vector-representation" : true + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/folder.imageset/folder.pdf b/iOSClient/Images.xcassets/folder.imageset/folder.pdf deleted file mode 100644 index 2bab530b5243e3eb558a28724e255779624a0951..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 911 zcmaJ=TS!zv7_Jb+A%ut?d=N%#$&j2mo{O%@VtX^GHQAL2OzN~duBUd-#MxQge6)HA zlq?@4jH1xD9wI2PjItzOq+kgG?V<#E2|?(khc5rDn+q#6oWn5R{NMcFHy`8b@COem zbsBPI*H#vhf+^EuB~IvgHLM;U;T3zkWMi<5={8@XbO z+kR6pT;p%5r;3}ZRIjI+sx{P7dH_DC3-Q?hOFSOL?3k2LUyu^C5(1i%U;>W!vnY=- zM2<5%E_$(IXdVwv2~e9vnX%B2Qa(+02m0P^UH(nbbs>piD($vP&Ps{x;vJ*F6-3|S!zNrqN>Fa7;_3z2_M0R%c^Zp}y z9-bO3A6WhpP=;HYE>FIE_o#C3)zPsJ6J_gXXI@+PSAV>})iNKQ8y|VrH+Op2NR|H4 zf3BC!%~q-l51ve|KJOhb{kW3Y*m`8RuDO6#ZtISm#pprO|G}m5DBvsPdia)1DQj<(Fha3&SgtF zSw>*emIN8z{OrrmZQY0jGNLsiWaPkYrP$aM3Oz}P#VpgyGq{TasM6dI6d$(*v!R2G zH!K}Guq?JH56Wwen$nUtgh@Mhl4hb{DC4jmL~#S6TLT-quIji4Z($19mIK>cn4-fC z7GY{*<2Fo#lZxv!H`poS8U}dzhY82D63megC}Q<9P)EX?3oJ7RyKQz4$MTWMJX6AS PM9zibb|aT7a3c5@!y_GM diff --git a/iOSClient/Images.xcassets/folder.imageset/folder.svg b/iOSClient/Images.xcassets/folder.imageset/folder.svg new file mode 100644 index 0000000000..b3bf667783 --- /dev/null +++ b/iOSClient/Images.xcassets/folder.imageset/folder.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/Contents.json b/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/Contents.json index 43e311862b..51ff0d5d02 100644 --- a/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/Contents.json +++ b/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/Contents.json @@ -1,15 +1,16 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "folderAutomaticUpload.pdf" + "filename" : "folder_photo.svg", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { - "preserves-vector-representation" : true + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/folderAutomaticUpload.pdf b/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/folderAutomaticUpload.pdf deleted file mode 100644 index ac2b5e4174cd93d36dfb04ed3041c1e76aa06798..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1266 zcmY!laBpkQ!zW}-e&uR^Yw8BhYOI5R)bC9xz`LBqw$$iUFjz}Udd(A3n#*i75NKplvH z>U{H4@GG&i<4Vm-0Xe}4;S{&boD!g=`ffQu<6Tmd^HWl}^nFtE(n~TFObspU>=cSi zfUeEus+f}-;@EfFfM?HdQ7dr`Z?7dTdlSyTUCPgK>#d^Zg}473WrK>$7|q<0s?JFA zd0Gca91lO}pR70i_Q&@RY6b6ak3W81|EYdJq13dS@`9IkPVij#Fs^RTl=juzuRp%c zJ^lLs_6bv?@+_`%EV;t*DCKF9$HcY=yP7Ua%Buuk?T}b8E#Ls>$z6-GUB1VtL`*vS ze9pf0L3g_JK5{Ht)mE;nDbf|^wD$1zQt7>N^?Zx9f~*!gY2EAd+v+`ydrK;d+*!R7 zGmd5yS>!pW7p|9Nf7N+F=aSo|=V{!Nxz%Micx>a2@JM6N;#}+~F?q6Gw(l{f;LHGF z&-v38qHkquFRts5I(_ns<+UXNr`)x?d*_8S)f|lxX0(6S()r;M*NoKd3tk-Xv$z>> zb$L+U%Ju&H7Od$1H}idy+VeT-ZoDDubNf$jay#?8()osp;rhS)udZFb@>b%=t+J_k z+0HkX_J$N*GJ6-HKY7aa3jK|Rx7QkOwJR2w;O(U6x-Bkb-*&a#B@(mlo;U2UymGu* zY2IO$2^+Z1+rDzJO}=q?mab#=jj{`8Pp6-KCzzAw{j^iiV&-qNTRBf^Z5D0&Rlsw7 zviyvtX*)ia9Ln6mIJ2(r%$-GyTlcLsyubU>mrDm^mt4KJgz4Je{W}*6Tq!<(J8Q~S zU;dJu%k%!TUfdOSUd`lw-}zg6AH4lrTXXy)AKQlyd7u;oO%TwuWQ<5lA(aKG3i{58 zC5but>A)17n4Vg!U;>m6LL@y97n%zo%E79DsXV_luSCI+OW!*)rC1@_6r?K_p$){x z(8i@7lv`QY%Un^gVNd&TxX#&QRJjmP_BYqQpJ8 z1eB?Odfg2a%peX0+NtlGnv$95lwY9`Z2%NBHUMLw7U%rDlGHq)4WJAZ1oB}Kkc;j` zkU>zlCMSZt>J zp(!u~(ZtM6fbKyTv#`VvvoOKXYiM8ybS_M9Nl{{EPHGXThzicEN(H)3KPW%HL;)1X iK<|3yrR6JtiZM`p7MCOzm4JO=Xkcp0rK;-c?*;(iC(gtG diff --git a/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/folder_photo.svg b/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/folder_photo.svg new file mode 100644 index 0000000000..f46eb94656 --- /dev/null +++ b/iOSClient/Images.xcassets/folderAutomaticUpload.imageset/folder_photo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/iOSClient/Images.xcassets/folderEncrypted.imageset/Contents.json b/iOSClient/Images.xcassets/folderEncrypted.imageset/Contents.json index cfa30bf519..d5a0abaa2c 100644 --- a/iOSClient/Images.xcassets/folderEncrypted.imageset/Contents.json +++ b/iOSClient/Images.xcassets/folderEncrypted.imageset/Contents.json @@ -1,15 +1,16 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "folderEncrypted.pdf" + "filename" : "folder_encrypted.svg", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { - "preserves-vector-representation" : true + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/folderEncrypted.imageset/folderEncrypted.pdf b/iOSClient/Images.xcassets/folderEncrypted.imageset/folderEncrypted.pdf deleted file mode 100644 index f259942a2ed815522f0bb8ab914089898935606e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1085 zcmY!laBpkQ!zW}-e&uR^Yw8BhYOI5R)bC9xz`LBqw$$iUFjz}Udl$k4#V$WYtBKplvH z>U{H4@GG&i<4Vm-0Xe}4;S{&boD!g=`ffQu<6Tmd^HWl}^nFtE(n~TFjEybq>=cSi zfUeEus+f~I(Kqji0#EDrIfq_P^vXTdZ+URdZC`$Yt(RSw1ug$RJ&T!9$aj+GpM3|< zn+Ytqqpz}_Rq)#GpQblj{>jaM_L#}usWX==^=n6pWfL!pnc?BzqH14v%)G9B=bo)Cvm3U#{?Gx~?*H$2ygW-WNyPT3xGdtn#r;J1fjxk|j7LZKr_bGAm(G_4~DI z`!wITP41R|81m7feD|Zh#rjWUKg*t(s6B6!s;VpZQl4P{-Zg4lx1_qy=9CTWyb`-S z<>um&q~Fu>p4~QJ(aw%Ae&441SxE4%%Vu87(}x9~o=CFVl(KirGRf7FQ*@u|_+Oe- zG0o*u@9*?~#%0@|ZwZM$x8;jywzA=*Hn4Vg!U;>m6LPR5o3r$fF8P037j%CAs}HUJ758-OuTi*tTn zNopR@22f%Q0{O5A$VK-e$RMa&lM_K+a`IKs_scKJP0T@fsG=w}jmtp6oXY?X6wFLb zjZGEO6yRcpKyQP9LLOYq&=eSgXkw;jK=+`DnHgAOikV^RwJ-)c7pAwQC^0i9wFs2m vgEOmAfv(dJ%Fi!R0L3xTyPkPz`3j&S0TiFbC5c5PU|(368*>5EufH1r7tnD1 diff --git a/iOSClient/Images.xcassets/folderEncrypted.imageset/folder_encrypted.svg b/iOSClient/Images.xcassets/folderEncrypted.imageset/folder_encrypted.svg new file mode 100644 index 0000000000..4f9e6b487e --- /dev/null +++ b/iOSClient/Images.xcassets/folderEncrypted.imageset/folder_encrypted.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/iOSClient/Images.xcassets/folderStarred.imageset/Contents.json b/iOSClient/Images.xcassets/folderStarred.imageset/Contents.json deleted file mode 100644 index 6b9892fdd7..0000000000 --- a/iOSClient/Images.xcassets/folderStarred.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "filename" : "folderStarred.pdf", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "preserves-vector-representation" : true - } -} diff --git a/iOSClient/Images.xcassets/folderStarred.imageset/folderStarred.pdf b/iOSClient/Images.xcassets/folderStarred.imageset/folderStarred.pdf deleted file mode 100644 index 80c4b65d5ed410e43db7e4bfe4552eea3e895f06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 969 zcmY!laBpkQ!zW}-e&uR^Yw8BhYOI5R)bC9xz`LBqw$$iUFjz}Udl$iURV$Vl73KplvH z>U{H4@GG&i<4Vm-0Xe}4;S{&boD!g=`ffQu<6Tmd^HWl}^nFtE(n~TFjEs!z>=cSi zfUeEus+i;3@0fSkfQRLM&Cz+>Qxru{PK%pRT>O%`$;|Qu!-GbJ%^WWyY}iDZ-ryrLy}?`EU$o;l{$mvR7x)AeGEk2~!^jvBMj@32sS5hei6x0S z`RTxzN=#2JRxkm|2O)wK#D&H#L^)U$F!u6G^GXy9x%9m=Q;HR$O+mV15!yg}3~gNc zL8-<0rA5g=Yk;W*m@<-sQ%iul!Kp$&B(PWcrI(FQ<4V*@Y-YH`lbD@n}*+5k!zK_DL%0lDa21Q`T% zYjPsUOHRHD`hNLExrsRl4^-2;2^Gg&!aSZgX eXI@&q0w{Ze;3v*L*E>%@me>VV2JT~h9 diff --git a/iOSClient/Images.xcassets/folder_external.imageset/Contents.json b/iOSClient/Images.xcassets/folder_external.imageset/Contents.json index 83fbf53d0b..741bbee824 100644 --- a/iOSClient/Images.xcassets/folder_external.imageset/Contents.json +++ b/iOSClient/Images.xcassets/folder_external.imageset/Contents.json @@ -1,15 +1,16 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "folder_external.pdf" + "filename" : "folder_external.svg", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { - "preserves-vector-representation" : true + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/folder_external.imageset/folder_external.pdf b/iOSClient/Images.xcassets/folder_external.imageset/folder_external.pdf deleted file mode 100644 index 7e6ea31577dc7d33d97787e9462666a673cd75ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1128 zcmY!laBpkQ!zW}-e&uR^Yw8BhYOI5R)bC9xz`LBqw$$iUFjz}Udl$k4#t&{*5RKplvH z>U{H4@GG&i<4Vm-0Xe}4;S{&boD!g=`ffQu<6Tmd^HWl}^nFtE(n~TFj4cf9>=cSi zfUeEus+dzc$=mO+15excVy^YtiO-%^&RLLsqo9G~l#(mcJN=KhJ!g4_3Yl)Tzq$YI zN0v_&^O@{UR?k}Z?)J~C7w@0nU2T0)JR>9K=%RA&hw~zs3Uhno&YM)&i+`{AR`Rp7 zvH0V!l&+Fi>BDDvMIPRY*E6x4(W!cQPsCPp7B#27{#ngEKFta?DyhDl)24oxQLyYd zq1DH;kZ0nBj~UZ;8S1R_40v=;`i@)ouXq0Ic<;U8IyR%<`P{q9q3^av9cS8`BG$$) zpdFTe{BwtO`>MZPN#{L{Rs=yvuaY)4xvX@VoSOXoC(=+yf-VE z`zqg}muL8IUo~u5s?C4FBPjR4>T8$f_)D&AsM3}dl?yyGZ}PlYYrjA8`>hw~$ywYC zTv1{9sCsJSb)K0GY&O%?b_H-v{A)B_RAe{5xmo0Oshe!8HXkYScjYyZ)Ruj4ZQ825 z2>*=TQW zNM%8)g1&QNNn%cZIxrz6rl%Gwm;mL25HSwoLK7cEIan1iapjlhl_(f;>3e6U6e~oV zf^@|qw1M~-+PL(CQj7CTi;{uX024DX;U)*CmH>5w6RmzoYDI~HzGp7b8BS2z8A^M` za_PHPl(+|%fYLHhue*VQ8N{JLJN122Q!*2s@+%ag4S<5i24D=-;+&sXl9~s!0hDfo zKt3!2a?!mAG6?F{ + + + + + + + + + diff --git a/iOSClient/Images.xcassets/folder_group.imageset/Contents.json b/iOSClient/Images.xcassets/folder_group.imageset/Contents.json index a3f76c948d..2c54bdc970 100644 --- a/iOSClient/Images.xcassets/folder_group.imageset/Contents.json +++ b/iOSClient/Images.xcassets/folder_group.imageset/Contents.json @@ -1,15 +1,16 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "Untitled.pdf" + "filename" : "folder_group.svg", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { - "preserves-vector-representation" : true + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/folder_group.imageset/Untitled.pdf b/iOSClient/Images.xcassets/folder_group.imageset/Untitled.pdf deleted file mode 100644 index 819728c8f7800adedc343119612c743984e397e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2229 zcmaJ@4K$S58y5}RAY$7j^d1>0WxkA=@t+yYj45QAeB?yhrkQs%)6BfgjPD3Zq!g_} zv!$A0p26Ab#V=~AchiSUNGyAn;9oO&w6o+os)TSBQ<9%W^Q`) z7wU)E5919)^4(7}15e6sCtIw^@i23;2-a(Sky|J+mzNUy-^CEmkA1G%!+jzCHyr$& z%sd`gy%2_r+wR-yFB_~4r5UEU^^Ts$OPiVwi=g2{`LBYe&mOO|5WUoNxw^RHuc@9| z#;sC2-A)L@hW6=JuA|qODivB>i^yZacP1AZ2rooMAtDOXF}TFb;WcOQC&LDkw%%C6 zhRO`RO%Wr~B?&{x_Dc*05hkQ%X-maAzL&-xU-mSoZHzNk8VzNpWq-FxKDwKkjtboV zb9f@fcqic0nvp(GRAGj`0!qU(4g%W&V&pX5WxPZB)R5Gich_wxaK9ne#WsT%=bUBo zoEbdT3XGUgl5Ju3D~k(M9n z`a2JuTycbTt-UUJ)}BIl&@<|Hnb^TfV5Iu+x^$L#ob8&ftNn2&{Ul@948(QKz9b#q zSL*q_)p~8VGUbK8rIm=xFATZV z*l=@NOP2JrZLF#BjvZQK+^l!6wZWKCK#C7v(i=4T(UZT zb~icRS*t)xnY-)THC&+uWO&2CVR@UzQsa;?-S>34v!|S0gc#kXr#U)6Ev>q}C1$kr zMjO6YEWTPivqf3ox4kQi)ZuQHpPAP(u*O)seJBm5zld{t4dc)KkJx#^Q6I8=E0apg{-p08bl!aaJqHo`_?@UzG(H7$hQ=8xpS|yY7Q(9PkQ4`$ZDV=Ui3tN6?I+J7m?iS@r38-*5-+4|gWz=FA&X4Y1P{Ubx+~8!JUe@a z*864bDujsliWYzJ;>XD=%a!4h3RB&`uK8-J_5@Os+>*W8Yr)BP_}H+?Ai>jN&AR;O zs||rp`Ol**Wd1+yS|FmHp$Z$cvvJvfJ8eiMU|Jn~rCXyHY6f&+*49e863~yl+2xo`(f*=K; it~X5AO)7u@^-DxuTe*TOQ+#FtzbPD$D3t3~*8c$uBc3Aw diff --git a/iOSClient/Images.xcassets/folder_group.imageset/folder_group.svg b/iOSClient/Images.xcassets/folder_group.imageset/folder_group.svg new file mode 100644 index 0000000000..960ab84ec1 --- /dev/null +++ b/iOSClient/Images.xcassets/folder_group.imageset/folder_group.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/iOSClient/Images.xcassets/folder_public.imageset/Contents.json b/iOSClient/Images.xcassets/folder_public.imageset/Contents.json index b49530ec58..ce84569fca 100644 --- a/iOSClient/Images.xcassets/folder_public.imageset/Contents.json +++ b/iOSClient/Images.xcassets/folder_public.imageset/Contents.json @@ -1,15 +1,16 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "folder_public.pdf" + "filename" : "folder_link.svg", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { - "preserves-vector-representation" : true + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/folder_public.imageset/folder_link.svg b/iOSClient/Images.xcassets/folder_public.imageset/folder_link.svg new file mode 100644 index 0000000000..8966f9a61a --- /dev/null +++ b/iOSClient/Images.xcassets/folder_public.imageset/folder_link.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/iOSClient/Images.xcassets/folder_public.imageset/folder_public.pdf b/iOSClient/Images.xcassets/folder_public.imageset/folder_public.pdf deleted file mode 100644 index 5aed5f65bc9be688bfd4604f234a890da20315e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1463 zcmY!laBpkQ!zW}-e&uR^Yw8BhYOI5R)bC9xz`LBqw$$iUFjz}Udl$k4#T&{EsLKplvH z>U{H4@GG&i<4Vm-0Xe}4;S{&boD!g=`ffQu<6Tmd^HWl}^nFtE(n~TF%neQL>=cSi zfUeEus+f}+;++?5$a80Za7OHcRdy<_^Aui}U1pZZ-BrM4ve$ls=9lYbzN}dDdruoUP;=EeXuH>$jrUv*5*+CK=;iy zrM?z#&cw~kO}V-?bzL~4M`wZj>82SC%a2%{e)T2f zfY!a<{>=w?V{+Xix0m{Jg{8W!61|#IuJBAm_(n{EX!CLF^TB#23^k5dTzJ40l5%Tb zlc%@HjU3M_isd@DT9<3?30P(Na8c*1Cpx`79_ubz?$L^zy*ad@L3;Aqtj~h;z9>lj z{N-S8^6|s>rbQ(zu4YlCh1;6XF|eA~;Tkm9MR_i-R7yV&=zIE3ZSCQAnUPY?6zKSID*eWKx zjJxN*@LrjX+0QA4&#u^VAMI_M|2F?!T411*V&d#OdLnbref9o($nDL~{qx^fTi2%E z40tz3_?n6B^t2i885w*klXn~Ne(`7IljSKo@X}%aOY4NWn+j*_I<&JSD+3b7tm968oiw!6nKvOj|Ll`46L`Y>ps)D|AVo737 zemXE)CZ?wrE0_S~gAn-##D!*Mh;pzhU{=j9%_~tb zA&4esX>5rpW&v~tsyagh6JSA#CT3&^j6j%JNl{{EPHGXToDI&bN(H)3KPW%HL;)1X iK<|3yrR6Jt%3@G_7MCOzm4JO=Xk==@rK;-c?*;(T5-NxQ diff --git a/iOSClient/Images.xcassets/folder_shared_with_me.imageset/Contents.json b/iOSClient/Images.xcassets/folder_shared_with_me.imageset/Contents.json index aa2ce13145..8b5e688724 100644 --- a/iOSClient/Images.xcassets/folder_shared_with_me.imageset/Contents.json +++ b/iOSClient/Images.xcassets/folder_shared_with_me.imageset/Contents.json @@ -1,15 +1,16 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "folder_shared_with_me.pdf" + "filename" : "folder_shared_with_me.svg", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { - "preserves-vector-representation" : true + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" } -} \ No newline at end of file +} diff --git a/iOSClient/Images.xcassets/folder_shared_with_me.imageset/folder_shared_with_me.pdf b/iOSClient/Images.xcassets/folder_shared_with_me.imageset/folder_shared_with_me.pdf deleted file mode 100644 index 7216a75412ae564055f89e09e7b474651d67b707..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2420 zcmaJ@c{r47A6Ay>Ogf~<-fOFHG7B@7kWjLfE!i0i1~bEW=NL=bcO_J$=?HDIL>NRW zT2A&Yd?H1YWe_34@V(RV)%EpV*Y{rUdp*~4Kfn9=-S_+aaX$(ch9?fARMg-KJ*>$O za1?+9$nL&yZEb`B1&;&C6yT774~0x5P>G6ggaw7{N%g=(ptTM5sQTuz84e7 zBtsmC2M!r(p^+#}q$(1FMxoHENM$7QAoN0Y=48+RU!toE$CErc63{=ToFMpvP*cPS ze`tF{ya(A64@a2cN#39jfWoSybajCs5RyxT)984+V;S-o{`zI*DKnlpyeVTTTBj)v zX7-eltq{%J-0f+i68r|e2RZBS$hc+W;GzjXA0e{-;0h%?JdC}d#Nysu+jzxV&b{~~ zs#!bX#q{!yo|eEI$?@!km6?{nwM90Im4#rgtbR5gH&?0OMxrghEP(y($H!($9s%i(QhJXl=ZKgbDBgS7G5acpd>bm zB%DciBOBZnlB8lyi%9OZ;UZV;Yl9vPw@P@ocNLipP7j-qO*+q1osBjy`HX2)@J`n< z5g2gO7nF)jy!>@rfXIezbbxRBK*U#-?!&th7pk{?z3=`;v)WgJ*lC|z5W16_sx@kr zc3wo)uWUb`gMm+KSufU0jGn?AyrdLKvfkd4Z|xlUM#h;a#Wi0PAMmweva>6+6|<~+ zM6VLjUR(EJWA|GIcPx5j}N1W5vpwVwJ+Vfs7ZCj`G|1xCeEn#%$1Bj&V`S2Hd>H ze9woJv$*zglS1};r*)0C<#2(AAEguM9@n1i7I?2^f(}jxf!L5~i5uJEV`fgR2WrKj z!o+Kmd63-dp8}N+Mk+tA?&hxP-pyBv=A~b&JA+1T7;5JC);|BxJZEKe{)iT1v7%#i zxJjd7$}LB(+r@GjtfeLPzDnU2b^6mxav*iW`=(2gT7KU-hP2bXX2Kqc08u7)QA_+; z)mh8?qDn{F^65JW%0#h=xCB_=6{ibhen>FZR7GRoZDI(ri9K3?o%g6!LS@MgQtSw5 zxlC03XjPY^lZWDBhxDq^JM0I9fx^$Zg4vCAet?7~@gCiRhXPM$W{t8?6P z^j$-d`^tR59~47(n>E}R5Z`+j*^N%b5r}p2DWU?K3L!FV#S5Z*sE>IU42@G~)6`C) z$MTy_IhcD*)VIi4qMM{wcc{gmMPfsIRp_BvCvTP;lLZ|5v@;lYPi_~0E#_qyPELo5 z7`1hpg-po@zAR@sA4)=hdi}-u76z@h4l9)3I9kF#r?erSX&d}7gpyk>My;lnlZkZk z8S?$UHvWi;M+=~}bTbjxp8 z@T27nnmDX9(Znwk#Jnve6_%DFv@Enb=C-qvx~SM?Y&&GXt+D! zeAQ*a1x9}y@~Kmhw?*&`)}7;V%80sp;m)Tx)yycy^=^%k7kY2m%AfCe-h3?KY|EW5 zbvmI)@jzmGg3TIjl5{hq>5J@MZJW|l*ZV7JyjfIr=DoDvRtsNF6-B_3J*FlSyb4?k zd_t4cOVy9rB)AUsu*2Qj7Soc-ea#$csSa^TQzemXp#&nvvv!Ri}3y()0GZf7#L^ylXHA`>IN^#QiK%x%IL zq4qhAO<#s(eOq6SD-EDlwoAOblvdm?JCHaa81vi-zaPKvp!>sFphIAW>3&BKZR9YJ4N=brjoIT*Std{Q#v|`!v~<=^Urvm{b*k{}PmiIpw6|-yo8oihth4JIupMh>0ZxW(CDK-!ss2ne zn~(rJfH1&;IDfJ?l&Lsxd=Q`pty}#JKhAV3hyN-6UIpbWnMwiy6dYkn@C*VRF&vij zPa0?bKQuVP3LiwKQaqqGP_9E6?qQ7wA@=wDM%dtKAb>C?LNfHXMuV-<*cpyEP6Lgs zK~AhgTq7ia{YNO&6Jd_`B;fSPG{6xFfvU*wA4D-AlR!KP>cEL`D~>}7H2u{gXQM5x z9ypFAeRBYDicBHm{C^svQSe@HB%lsQ{&)Z^2BV4rynr7V3bM_40MZW(g@OLye`6>O zO{nEBn5G(ZFu!7&8oy#_lsaVbKXo7lNASl}IF}@ALMR?mhp-}(L4b3{kX>Vv7a8DO Zq&Vjp1mY;*cNb_hQXQ_KaQyU%e*;VR4}<^! diff --git a/iOSClient/Images.xcassets/folder_shared_with_me.imageset/folder_shared_with_me.svg b/iOSClient/Images.xcassets/folder_shared_with_me.imageset/folder_shared_with_me.svg new file mode 100644 index 0000000000..d115211941 --- /dev/null +++ b/iOSClient/Images.xcassets/folder_shared_with_me.imageset/folder_shared_with_me.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon+SelectTabBarDelegate.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon+SelectTabBarDelegate.swift new file mode 100644 index 0000000000..cf1ea50da0 --- /dev/null +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon+SelectTabBarDelegate.swift @@ -0,0 +1,313 @@ +// +// NCCollectionViewCommon+SelectTabBarDelegate.swift +// Nextcloud +// +// Created by Milen on 01.03.24. +// Copyright © 2024 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// 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 . +// + +import Foundation +import NextcloudKit + +extension NCCollectionViewCommon: NCSelectableNavigationView, NCCollectionViewCommonSelectTabBarDelegate { + func setNavigationRightItems(enableMenu: Bool = false) { + if layoutKey == NCGlobal.shared.layoutViewTransfers { return } + + var selectedMetadatas: [tableMetadata] = [] + var isAnyOffline = false + var isAnyDirectory = false + var isAllDirectory = true + var isAnyLocked = false + var canUnlock = true + var canSetAsOffline = true + let isTabBarHidden = self.tabBarController?.tabBar.isHidden + + for ocId in selectOcId { + guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { continue } + selectedMetadatas.append(metadata) + + if metadata.directory { + isAnyDirectory = true + } else { + isAllDirectory = false + } + + if !metadata.canSetAsAvailableOffline { + canSetAsOffline = false + } + + if metadata.lock { + isAnyLocked = true + if metadata.lockOwner != appDelegate.userId { + canUnlock = false + } + } + + 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 + } + + guard let tabBarSelect = tabBarSelect as? NCCollectionViewCommonSelectTabBar else { return } + + tabBarSelect.isAnyOffline = isAnyOffline + tabBarSelect.canSetAsOffline = canSetAsOffline + tabBarSelect.isAnyDirectory = isAnyDirectory + tabBarSelect.isAllDirectory = isAllDirectory + tabBarSelect.isAnyLocked = isAnyLocked + tabBarSelect.canUnlock = canUnlock + tabBarSelect.enableLock = !isAnyDirectory && canUnlock && !NCGlobal.shared.capabilityFilesLockVersion.isEmpty + tabBarSelect.isSelectedEmpty = selectOcId.isEmpty + tabBarSelect.selectedMetadatas = selectedMetadatas + + if isEditMode { + tabBarSelect.show() + let select = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: .done) { self.toggleSelect() } + navigationItem.rightBarButtonItems = [select] + } else { + tabBarSelect.hide() + if navigationItem.rightBarButtonItems == nil || enableMenu { + let menuButton = UIBarButtonItem(image: .init(systemName: "ellipsis.circle"), menu: UIMenu(children: createMenuActions())) + if layoutKey == NCGlobal.shared.layoutViewFiles { + let notification = UIBarButtonItem(image: .init(systemName: "bell"), style: .plain, action: tapNotification) + navigationItem.rightBarButtonItems = [menuButton, notification] + } else { + navigationItem.rightBarButtonItems = [menuButton] + } + } else { + navigationItem.rightBarButtonItems?.first?.menu = navigationItem.rightBarButtonItems?.first?.menu?.replacingChildren(createMenuActions()) + } + } + // fix, if the tabbar was hidden before the update, set hidden + if let isTabBarHidden, isTabBarHidden { + self.tabBarController?.tabBar.isHidden = true + } + } + + func onListSelected() { + if layoutForView?.layout == NCGlobal.shared.layoutGrid { + layoutForView?.layout = NCGlobal.shared.layoutList + NCManageDatabase.shared.setLayoutForView(account: appDelegate.account, key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout) + self.groupByField = "name" + if self.dataSource.groupByField != self.groupByField { + self.dataSource.changeGroupByField(self.groupByField) + } + + self.collectionView.reloadData() + self.collectionView.collectionViewLayout.invalidateLayout() + self.collectionView.setCollectionViewLayout(self.listLayout, animated: true) {_ in self.isTransitioning = false } + } + } + + func onGridSelected() { + if layoutForView?.layout == NCGlobal.shared.layoutList { + layoutForView?.layout = NCGlobal.shared.layoutGrid + NCManageDatabase.shared.setLayoutForView(account: appDelegate.account, key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout) + if isSearchingMode { + self.groupByField = "name" + } else { + self.groupByField = "classFile" + } + if self.dataSource.groupByField != self.groupByField { + self.dataSource.changeGroupByField(self.groupByField) + } + + self.collectionView.reloadData() + self.collectionView.collectionViewLayout.invalidateLayout() + self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true) {_ in self.isTransitioning = false } + } + } + + func selectAll() { + collectionViewSelectAll() + } + + func delete(selectedMetadatas: [tableMetadata]) { + let alertController = UIAlertController( + title: NSLocalizedString("_confirm_delete_selected_", comment: ""), + message: nil, + preferredStyle: .alert) + + let canDeleteServer = selectedMetadatas.allSatisfy { !$0.lock } + + if canDeleteServer { + let copyMetadatas = selectedMetadatas + + alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_", comment: ""), style: .destructive) { _ in + Task { + var error = NKError() + var ocId: [String] = [] + for metadata in copyMetadatas where error == .success { + error = await NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: false) + if error == .success { + ocId.append(metadata.ocId) + } + } + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": ocId, "indexPath": self.selectIndexPaths, "onlyLocalCache": false, "error": error]) + } + + self.toggleSelect() + }) + } + + alertController.addAction(UIAlertAction(title: NSLocalizedString("_remove_local_file_", comment: ""), style: .default) { (_: UIAlertAction) in + let copyMetadatas = selectedMetadatas + + Task { + var error = NKError() + var ocId: [String] = [] + for metadata in copyMetadatas where error == .success { + error = await NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: true) + if error == .success { + ocId.append(metadata.ocId) + } + } + if error != .success { + NCContentPresenter().showError(error: error) + } + NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": ocId, "indexPath": self.selectIndexPaths, "onlyLocalCache": true, "error": error]) + self.toggleSelect() + } + }) + + alertController.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel) { (_: UIAlertAction) in }) + self.viewController.present(alertController, animated: true, completion: nil) + } + + func move(selectedMetadatas: [tableMetadata]) { + NCActionCenter.shared.openSelectView(items: selectedMetadatas, indexPath: self.selectIndexPaths) + self.toggleSelect() + } + + func share(selectedMetadatas: [tableMetadata]) { + NCActionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas) + self.toggleSelect() + } + + func saveAsAvailableOffline(selectedMetadatas: [tableMetadata], isAnyOffline: Bool) { + 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 { NCActionCenter.shared.setMetadataAvalableOffline($0, isOffline: isAnyOffline) } + self.toggleSelect() + })) + alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel)) + self.viewController.present(alert, animated: true) + } else { + selectedMetadatas.forEach { NCActionCenter.shared.setMetadataAvalableOffline($0, isOffline: isAnyOffline) } + self.toggleSelect() + } + } + + func lock(selectedMetadatas: [tableMetadata], isAnyLocked: Bool) { + for metadata in selectedMetadatas where metadata.lock == isAnyLocked { + NCNetworking.shared.lockUnlockFile(metadata, shoulLock: !isAnyLocked) + } + + self.toggleSelect() + } + + func createMenuActions() -> [UIMenuElement] { + guard let layoutForView = NCManageDatabase.shared.getLayoutForView(account: appDelegate.account, key: layoutKey, serverUrl: serverUrl) else { return [] } + + let select = UIAction(title: NSLocalizedString("_select_", comment: ""), image: .init(systemName: "checkmark.circle"), attributes: selectableDataSource.isEmpty ? .disabled : []) { _ in self.toggleSelect() } + + let list = UIAction(title: NSLocalizedString("_list_", comment: ""), image: .init(systemName: "list.bullet"), state: layoutForView.layout == NCGlobal.shared.layoutList ? .on : .off) { _ in + self.onListSelected() + self.setNavigationRightItems() + } + + let grid = UIAction(title: NSLocalizedString("_icons_", comment: ""), image: .init(systemName: "square.grid.2x2"), state: layoutForView.layout == NCGlobal.shared.layoutGrid ? .on : .off) { _ in + self.onGridSelected() + self.setNavigationRightItems() + } + + let viewStyleSubmenu = UIMenu(title: "", options: .displayInline, children: [list, grid]) + + let ascending = layoutForView.ascending + let ascendingChevronImage = UIImage(systemName: ascending ? "chevron.up" : "chevron.down") + let isName = layoutForView.sort == "fileName" + let isDate = layoutForView.sort == "date" + let isSize = layoutForView.sort == "size" + + let byName = UIAction(title: NSLocalizedString("_name_", comment: ""), image: isName ? ascendingChevronImage : nil, state: isName ? .on : .off) { _ in + if isName { // repeated press + layoutForView.ascending = !layoutForView.ascending + } + layoutForView.sort = "fileName" + self.saveLayout(layoutForView) + } + + let byNewest = UIAction(title: NSLocalizedString("_date_", comment: ""), image: isDate ? ascendingChevronImage : nil, state: isDate ? .on : .off) { _ in + if isDate { // repeated press + layoutForView.ascending = !layoutForView.ascending + } + layoutForView.sort = "date" + self.saveLayout(layoutForView) + } + + let byLargest = UIAction(title: NSLocalizedString("_size_", comment: ""), image: isSize ? ascendingChevronImage : nil, state: isSize ? .on : .off) { _ in + if isSize { // repeated press + layoutForView.ascending = !layoutForView.ascending + } + layoutForView.sort = "size" + self.saveLayout(layoutForView) + } + + let sortSubmenu = UIMenu(title: NSLocalizedString("_order_by_", comment: ""), options: .displayInline, children: [byName, byNewest, byLargest]) + + let foldersOnTop = UIAction(title: NSLocalizedString("_directory_on_top_no_", comment: ""), image: UIImage(systemName: "folder"), state: layoutForView.directoryOnTop ? .on : .off) { _ in + layoutForView.directoryOnTop = !layoutForView.directoryOnTop + self.saveLayout(layoutForView) + } + + let personalFilesOnly = NCKeychain().getPersonalFilesOnly(account: appDelegate.account) + let personalFilesOnlyAction = UIAction(title: NSLocalizedString("_personal_files_only_", comment: ""), image: UIImage(systemName: "folder.badge.person.crop"), state: personalFilesOnly ? .on : .off) { _ in + NCKeychain().setPersonalFilesOnly(account: self.appDelegate.account, value: !personalFilesOnly) + self.reloadDataSource() + } + + let showDescriptionKeychain = NCKeychain().showDescription + let showDescription = UIAction(title: NSLocalizedString("_show_description_", comment: ""), image: UIImage(systemName: "list.dash.header.rectangle"), attributes: richWorkspaceText == nil ? .disabled : [], state: showDescriptionKeychain && richWorkspaceText != nil ? .on : .off) { _ in + NCKeychain().showDescription = !showDescriptionKeychain + self.collectionView.reloadData() + self.setNavigationRightItems() + } + showDescription.subtitle = richWorkspaceText == nil ? NSLocalizedString("_no_description_available_", comment: "") : "" + + if layoutKey == NCGlobal.shared.layoutViewRecent { + return [select] + } else { + var additionalSubmenu = UIMenu() + if layoutKey == NCGlobal.shared.layoutViewFiles { + additionalSubmenu = UIMenu(title: "", options: .displayInline, children: [foldersOnTop, personalFilesOnlyAction, showDescription]) + } else { + additionalSubmenu = UIMenu(title: "", options: .displayInline, children: [foldersOnTop, showDescription]) + } + return [select, viewStyleSubmenu, sortSubmenu, additionalSubmenu] + } + } +} diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift new file mode 100644 index 0000000000..a9b5b77b97 --- /dev/null +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift @@ -0,0 +1,94 @@ +// +// NCCollectionViewCommon+SwipeCollectionViewCellDelegate.swift +// Nextcloud +// +// Created by Milen on 01.03.24. +// Copyright © 2024 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// 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 . +// + +import Foundation +import SwipeCellKit + +extension NCCollectionViewCommon: SwipeCollectionViewCellDelegate { + func collectionView(_ collectionView: UICollectionView, editActionsForItemAt indexPath: IndexPath, for orientation: SwipeCellKit.SwipeActionsOrientation) -> [SwipeCellKit.SwipeAction]? { + guard orientation == .right, let metadata = self.dataSource.cellForItemAt(indexPath: indexPath) else { return nil } + + let scaleTransition = ScaleTransition(duration: 0.3, initialScale: 0.8, threshold: 0.8) + + // wait a fix for truncate the text .. ? .. + let favoriteAction = SwipeAction(style: .default, title: NSLocalizedString(metadata.favorite ? "_favorite_short_" : "_favorite_short_", comment: "") ) { _, _ in + NCNetworking.shared.favoriteMetadata(metadata) { error in + if error != .success { + NCContentPresenter().showError(error: error) + } + } + } + favoriteAction.backgroundColor = NCBrandColor.shared.yellowFavorite + favoriteAction.image = .init(systemName: metadata.favorite ? "star.slash.fill" : "star.fill") + favoriteAction.transitionDelegate = scaleTransition + favoriteAction.hidesWhenSelected = true + + var actions = [favoriteAction] + + let shareAction = SwipeAction(style: .default, title: NSLocalizedString("_share_", comment: "")) { _, _ in + NCActionCenter.shared.openActivityViewController(selectedMetadata: [metadata]) + } + shareAction.backgroundColor = .blue + shareAction.image = .init(systemName: "square.and.arrow.up") + shareAction.transitionDelegate = scaleTransition + shareAction.hidesWhenSelected = true + + let deleteAction = SwipeAction(style: .destructive, title: NSLocalizedString("_delete_", comment: "")) { _, _ in + let titleDelete: String + + if metadata.directory { + titleDelete = NSLocalizedString("_delete_folder_", comment: "") + } else { + titleDelete = NSLocalizedString("_delete_file_", comment: "") + } + + let message = NSLocalizedString("_want_delete_", comment: "") + "\n - " + metadata.fileNameView + + let alertController = UIAlertController.deleteFileOrFolder(titleString: titleDelete + "?", message: message, canDeleteServer: !metadata.lock, selectedMetadatas: [metadata], indexPaths: self.selectIndexPaths) { _ in } + + self.viewController.present(alertController, animated: true, completion: nil) + } + deleteAction.image = .init(systemName: "trash") + deleteAction.style = .destructive + deleteAction.transitionDelegate = scaleTransition + deleteAction.hidesWhenSelected = true + + if !NCManageDatabase.shared.isMetadataShareOrMounted(metadata: metadata, metadataFolder: metadataFolder) { + actions.insert(deleteAction, at: 0) + } + + if metadata.canShare { + actions.append(shareAction) + } + + return actions + } + + func collectionView(_ collectionView: UICollectionView, editActionsOptionsForItemAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> SwipeOptions { + var options = SwipeOptions() + options.expansionStyle = .selection + options.transitionStyle = .border + options.backgroundColor = .clear + return options + } +} diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift index dee3298696..833f8f2d2f 100644 --- a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift @@ -26,7 +26,6 @@ import Realm import NextcloudKit import EasyTipView import JGProgressHUD -import Queuer class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate, NCListCellDelegate, NCGridCellDelegate, NCSectionHeaderMenuDelegate, NCSectionFooterDelegate, UIAdaptivePresentationControllerDelegate, NCEmptyDataSetDelegate, UIContextMenuInteractionDelegate, NCAccountRequestDelegate { @@ -37,7 +36,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS private var pushed: Bool = false private var tipView: EasyTipView? - private var isTransitioning: Bool = false + var isTransitioning: Bool = false let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! let utilityFileSystem = NCUtilityFileSystem() @@ -49,7 +48,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS var serverUrl: String = "" var isEditMode = false var selectOcId: [String] = [] - var selectIndexPath: [IndexPath] = [] + var selectIndexPaths: [IndexPath] = [] var metadataFolder: tableMetadata? var dataSource = NCDataSource() var richWorkspaceText: String? @@ -91,10 +90,6 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS // MARK: - View Life Cycle - required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } - override func viewDidLoad() { super.viewDidLoad() @@ -544,8 +539,8 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS let chunk: Int = userInfo["chunk"] as? Int ?? 0 let e2eEncrypted: Bool = userInfo["e2eEncrypted"] as? Bool ?? false - if self.headerMenuTransferView && (chunk > 0 || e2eEncrypted) { - DispatchQueue.main.async { + DispatchQueue.main.async { + if self.headerMenuTransferView && (chunk > 0 || e2eEncrypted) { if NCNetworking.shared.transferInForegorund?.ocId == ocId { NCNetworking.shared.transferInForegorund?.progress = progressNumber.floatValue } else { @@ -553,12 +548,9 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS self.collectionView.reloadData() } self.headerMenu?.progressTransfer.progress = progressNumber.floatValue - } - } else { - guard let indexPath = self.dataSource.getIndexPathMetadata(ocId: ocId).indexPath else { return } - let status = userInfo["status"] as? Int ?? NCGlobal.shared.metadataStatusNormal - DispatchQueue.main.async { - guard let cell = self.collectionView?.cellForItem(at: indexPath), + } else { + guard let indexPath = self.dataSource.getIndexPathMetadata(ocId: ocId).indexPath, + let cell = self.collectionView?.cellForItem(at: indexPath), let cell = cell as? NCCellProtocol else { return } if progressNumber.floatValue == 1 && !(cell is NCTransferCell) { cell.fileProgressView?.isHidden = true @@ -574,6 +566,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS cell.fileProgressView?.isHidden = false cell.fileProgressView?.progress = progressNumber.floatValue cell.setButtonMore(named: NCGlobal.shared.buttonMoreStop, image: NCImageCache.images.buttonStop) + let status = userInfo["status"] as? Int ?? NCGlobal.shared.metadataStatusNormal if status == NCGlobal.shared.metadataStatusDownloading { cell.fileInfoLabel?.text = self.utilityFileSystem.transformedSize(totalBytesExpected) cell.fileSubinfoLabel?.text = self.infoLabelsSeparator + "↓ " + self.utilityFileSystem.transformedSize(totalBytes) @@ -943,7 +936,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS searchResults: self.searchResults) } update: { _, _, searchResult, metadatas in guard let metadatas, !metadatas.isEmpty, self.isSearchingMode, let searchResult else { return } - NCNetworking.shared.unifiedSearchQueue.addOperation(NCOperationUnifiedSearch(collectionViewCommon: self, metadatas: metadatas, searchResult: searchResult)) + NCNetworking.shared.unifiedSearchQueue.addOperation(NCCollectionViewUnifiedSearch(collectionViewCommon: self, metadatas: metadatas, searchResult: searchResult)) } completion: { _, _ in self.refreshControl.endRefreshing() self.collectionView.reloadData() @@ -1042,10 +1035,10 @@ extension NCCollectionViewCommon: UICollectionViewDelegate { if isEditMode { if let index = selectOcId.firstIndex(of: metadata.ocId) { selectOcId.remove(at: index) - selectIndexPath.removeAll(where: { $0 == indexPath }) + selectIndexPaths.removeAll(where: { $0 == indexPath }) } else { selectOcId.append(metadata.ocId) - selectIndexPath.append(indexPath) + selectIndexPaths.append(indexPath) } collectionView.reloadItems(at: [indexPath]) @@ -1246,12 +1239,13 @@ extension NCCollectionViewCommon: UICollectionViewDataSource { // LAYOUT LIST if layoutForView?.layout == NCGlobal.shared.layoutList { guard let listCell = collectionView.dequeueReusableCell(withReuseIdentifier: "listCell", for: indexPath) as? NCListCell else { return NCListCell() } - listCell.delegate = self + listCell.listCellDelegate = self + // listCell.delegate = self cell = listCell } else { // LAYOUT GRID guard let gridCell = collectionView.dequeueReusableCell(withReuseIdentifier: "gridCell", for: indexPath) as? NCGridCell else { return NCGridCell() } - gridCell.delegate = self + gridCell.gridCellDelegate = self cell = gridCell } @@ -1362,7 +1356,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource { // image Favorite if metadata.favorite { cell.fileFavoriteImage?.image = NCImageCache.images.favorite - a11yValues.append(NSLocalizedString("_favorite_", comment: "")) + a11yValues.append(NSLocalizedString("_favorite_short_", comment: "")) } // Share image @@ -1476,6 +1470,8 @@ extension NCCollectionViewCommon: UICollectionViewDataSource { cell.hideButtonMore(true) } + cell.setIconOutlines() + return cell } @@ -1658,282 +1654,6 @@ extension NCCollectionViewCommon: EasyTipViewDelegate { } } -extension NCCollectionViewCommon: NCSelectableNavigationView, NCCollectionViewCommonSelectTabBarDelegate { - func setNavigationRightItems(enableMenu: Bool = false) { - var selectedMetadatas: [tableMetadata] = [] - var isAnyOffline = false - var isAnyDirectory = false - var isAllDirectory = true - var isAnyLocked = false - var canUnlock = true - var canSetAsOffline = true - - for ocId in selectOcId { - guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(ocId) else { continue } - selectedMetadatas.append(metadata) - - if metadata.directory { - isAnyDirectory = true - } else { - isAllDirectory = false - } - - if !metadata.canSetAsAvailableOffline { - canSetAsOffline = false - } - - if metadata.lock { - isAnyLocked = true - if metadata.lockOwner != appDelegate.userId { - canUnlock = false - } - } - - 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 - } - - guard let tabBarSelect = tabBarSelect as? NCCollectionViewCommonSelectTabBar else { return } - - tabBarSelect.isAnyOffline = isAnyOffline - tabBarSelect.canSetAsOffline = canSetAsOffline - tabBarSelect.isAnyDirectory = isAnyDirectory - tabBarSelect.isAllDirectory = isAllDirectory - tabBarSelect.isAnyLocked = isAnyLocked - tabBarSelect.canUnlock = canUnlock - tabBarSelect.enableLock = !isAnyDirectory && canUnlock && !NCGlobal.shared.capabilityFilesLockVersion.isEmpty - tabBarSelect.isSelectedEmpty = selectOcId.isEmpty - tabBarSelect.selectedMetadatas = selectedMetadatas - - if isEditMode { - tabBarSelect.show() - let select = UIBarButtonItem(title: NSLocalizedString("_cancel_", comment: ""), style: .done) { self.toggleSelect() } - navigationItem.rightBarButtonItems = [select] - } else { - tabBarSelect.hide() - if navigationItem.rightBarButtonItems == nil || enableMenu { - let menuButton = UIBarButtonItem(image: .init(systemName: "ellipsis.circle"), menu: UIMenu(children: createMenuActions())) - if layoutKey == NCGlobal.shared.layoutViewFiles { - let notification = UIBarButtonItem(image: .init(systemName: "bell"), style: .plain, action: tapNotification) - navigationItem.rightBarButtonItems = [menuButton, notification] - } else { - navigationItem.rightBarButtonItems = [menuButton] - } - } else { - navigationItem.rightBarButtonItems?.first?.menu = navigationItem.rightBarButtonItems?.first?.menu?.replacingChildren(createMenuActions()) - } - } - } - - func onListSelected() { - if layoutForView?.layout == NCGlobal.shared.layoutGrid { - layoutForView?.layout = NCGlobal.shared.layoutList - NCManageDatabase.shared.setLayoutForView(account: appDelegate.account, key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout) - self.groupByField = "name" - if self.dataSource.groupByField != self.groupByField { - self.dataSource.changeGroupByField(self.groupByField) - } - - self.collectionView.reloadData() - self.collectionView.collectionViewLayout.invalidateLayout() - self.collectionView.setCollectionViewLayout(self.listLayout, animated: true) {_ in self.isTransitioning = false } - } - } - - func onGridSelected() { - if layoutForView?.layout == NCGlobal.shared.layoutList { - layoutForView?.layout = NCGlobal.shared.layoutGrid - NCManageDatabase.shared.setLayoutForView(account: appDelegate.account, key: layoutKey, serverUrl: serverUrl, layout: layoutForView?.layout) - if isSearchingMode { - self.groupByField = "name" - } else { - self.groupByField = "classFile" - } - if self.dataSource.groupByField != self.groupByField { - self.dataSource.changeGroupByField(self.groupByField) - } - - self.collectionView.reloadData() - self.collectionView.collectionViewLayout.invalidateLayout() - self.collectionView.setCollectionViewLayout(self.gridLayout, animated: true) {_ in self.isTransitioning = false } - } - } - - func selectAll() { - collectionViewSelectAll() - } - - func delete(selectedMetadatas: [tableMetadata]) { - let alertController = UIAlertController( - title: NSLocalizedString("_confirm_delete_selected_", comment: ""), - message: nil, - preferredStyle: .alert) - - let canDeleteServer = selectedMetadatas.allSatisfy { !$0.lock } - - if canDeleteServer { - let copyMetadatas = selectedMetadatas - - alertController.addAction(UIAlertAction(title: NSLocalizedString("_yes_", comment: ""), style: .destructive) { _ in - Task { - var error = NKError() - var ocId: [String] = [] - for metadata in copyMetadatas where error == .success { - error = await NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: false) - if error == .success { - ocId.append(metadata.ocId) - } - } - NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": ocId, "indexPath": self.selectIndexPath, "onlyLocalCache": false, "error": error]) - } - - self.toggleSelect() - }) - } - - alertController.addAction(UIAlertAction(title: NSLocalizedString("_remove_local_file_", comment: ""), style: .default) { (_: UIAlertAction) in - let copyMetadatas = selectedMetadatas - - Task { - var error = NKError() - var ocId: [String] = [] - for metadata in copyMetadatas where error == .success { - error = await NCNetworking.shared.deleteMetadata(metadata, onlyLocalCache: true) - if error == .success { - ocId.append(metadata.ocId) - } - } - if error != .success { - NCContentPresenter().showError(error: error) - } - NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": ocId, "indexPath": self.selectIndexPath, "onlyLocalCache": true, "error": error]) - self.toggleSelect() - } - }) - - alertController.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel) { (_: UIAlertAction) in }) - self.viewController.present(alertController, animated: true, completion: nil) - } - - func move(selectedMetadatas: [tableMetadata]) { - NCActionCenter.shared.openSelectView(items: selectedMetadatas, indexPath: self.selectIndexPath) - self.toggleSelect() - } - - func share(selectedMetadatas: [tableMetadata]) { - NCActionCenter.shared.openActivityViewController(selectedMetadata: selectedMetadatas) - self.toggleSelect() - } - - func saveAsAvailableOffline(selectedMetadatas: [tableMetadata], isAnyOffline: Bool) { - 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 { NCActionCenter.shared.setMetadataAvalableOffline($0, isOffline: isAnyOffline) } - self.toggleSelect() - })) - alert.addAction(UIAlertAction(title: NSLocalizedString("_cancel_", comment: ""), style: .cancel)) - self.viewController.present(alert, animated: true) - } else { - selectedMetadatas.forEach { NCActionCenter.shared.setMetadataAvalableOffline($0, isOffline: isAnyOffline) } - self.toggleSelect() - } - } - - func lock(selectedMetadatas: [tableMetadata], isAnyLocked: Bool) { - for metadata in selectedMetadatas where metadata.lock == isAnyLocked { - NCNetworking.shared.lockUnlockFile(metadata, shoulLock: !isAnyLocked) - } - - self.toggleSelect() - } - - func createMenuActions() -> [UIMenuElement] { - guard let layoutForView = NCManageDatabase.shared.getLayoutForView(account: appDelegate.account, key: layoutKey, serverUrl: serverUrl) else { return [] } - - let select = UIAction(title: NSLocalizedString("_select_", comment: ""), image: .init(systemName: "checkmark.circle"), attributes: selectableDataSource.isEmpty ? .disabled : []) { _ in self.toggleSelect() } - - let list = UIAction(title: NSLocalizedString("_list_", comment: ""), image: .init(systemName: "list.bullet"), state: layoutForView.layout == NCGlobal.shared.layoutList ? .on : .off) { _ in - self.onListSelected() - self.setNavigationRightItems() - } - - let grid = UIAction(title: NSLocalizedString("_icons_", comment: ""), image: .init(systemName: "square.grid.2x2"), state: layoutForView.layout == NCGlobal.shared.layoutGrid ? .on : .off) { _ in - self.onGridSelected() - self.setNavigationRightItems() - } - - let viewStyleSubmenu = UIMenu(title: "", options: .displayInline, children: [list, grid]) - - let ascending = layoutForView.ascending - let ascendingChevronImage = UIImage(systemName: ascending ? "chevron.up" : "chevron.down") - let isName = layoutForView.sort == "fileName" - let isDate = layoutForView.sort == "date" - let isSize = layoutForView.sort == "size" - - let byName = UIAction(title: NSLocalizedString("_name_", comment: ""), image: isName ? ascendingChevronImage : nil, state: isName ? .on : .off) { _ in - if isName { // repeated press - layoutForView.ascending = !layoutForView.ascending - } - - layoutForView.sort = "fileName" - self.saveLayout(layoutForView) - } - - let byNewest = UIAction(title: NSLocalizedString("_date_", comment: ""), image: isDate ? ascendingChevronImage : nil, state: isDate ? .on : .off) { _ in - if isDate { // repeated press - layoutForView.ascending = !layoutForView.ascending - } - - layoutForView.sort = "date" - self.saveLayout(layoutForView) - } - - let byLargest = UIAction(title: NSLocalizedString("_size_", comment: ""), image: isSize ? ascendingChevronImage : nil, state: isSize ? .on : .off) { _ in - if isSize { // repeated press - layoutForView.ascending = !layoutForView.ascending - } - - layoutForView.sort = "size" - self.saveLayout(layoutForView) - } - - let sortSubmenu = UIMenu(title: NSLocalizedString("_order_by_", comment: ""), options: .displayInline, children: [byName, byNewest, byLargest]) - - let foldersOnTop = UIAction(title: NSLocalizedString("_directory_on_top_no_", comment: ""), image: UIImage(systemName: "folder"), state: layoutForView.directoryOnTop ? .on : .off) { _ in - layoutForView.directoryOnTop = !layoutForView.directoryOnTop - self.saveLayout(layoutForView) - } - - let showDescriptionKeychain = NCKeychain().showDescription - - let showDescription = UIAction(title: NSLocalizedString("_show_description_", comment: ""), image: UIImage(systemName: "list.dash.header.rectangle"), attributes: richWorkspaceText == nil ? .disabled : [], state: showDescriptionKeychain && richWorkspaceText != nil ? .on : .off) { _ in - NCKeychain().showDescription = !showDescriptionKeychain - self.collectionView.reloadData() - self.setNavigationRightItems() - } - - showDescription.subtitle = richWorkspaceText == nil ? NSLocalizedString("_no_description_available_", comment: "") : "" - - let additionalSubmenu = UIMenu(title: "", options: .displayInline, children: [foldersOnTop, showDescription]) - - if layoutKey == NCGlobal.shared.layoutViewRecent { - return [select] - } else { - return [select, viewStyleSubmenu, sortSubmenu, additionalSubmenu] - } - } -} - extension NCCollectionViewCommon { func getAvatarFromIconUrl(metadata: tableMetadata) -> String? { @@ -2047,100 +1767,6 @@ extension NCCollectionViewCommon { // MARK: - -class NCOperationUnifiedSearch: ConcurrentOperation { - - var collectionViewCommon: NCCollectionViewCommon - var metadatas: [tableMetadata] - var searchResult: NKSearchResult - - init(collectionViewCommon: NCCollectionViewCommon, metadatas: [tableMetadata], searchResult: NKSearchResult) { - self.collectionViewCommon = collectionViewCommon - self.metadatas = metadatas - self.searchResult = searchResult - } - - func reloadDataThenPerform(_ closure: @escaping (() -> Void)) { - DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { - CATransaction.begin() - CATransaction.setCompletionBlock(closure) - self.collectionViewCommon.collectionView.reloadData() - CATransaction.commit() - } - } - - override func start() { - - guard !isCancelled else { return self.finish() } - - self.collectionViewCommon.dataSource.addSection(metadatas: metadatas, searchResult: searchResult) - self.collectionViewCommon.searchResults?.append(self.searchResult) - reloadDataThenPerform { - self.finish() - } - } -} - -class NCCollectionViewDownloadThumbnail: ConcurrentOperation { - - var metadata: tableMetadata - var cell: NCCellProtocol? - var collectionView: UICollectionView? - var fileNamePath: String - var fileNamePreviewLocalPath: String - var fileNameIconLocalPath: String - let utilityFileSystem = NCUtilityFileSystem() - - init(metadata: tableMetadata, cell: NCCellProtocol?, collectionView: UICollectionView?) { - self.metadata = tableMetadata.init(value: metadata) - self.cell = cell - self.collectionView = collectionView - self.fileNamePath = utilityFileSystem.getFileNamePath(metadata.fileName, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, userId: metadata.userId) - self.fileNamePreviewLocalPath = utilityFileSystem.getDirectoryProviderStoragePreviewOcId(metadata.ocId, etag: metadata.etag) - self.fileNameIconLocalPath = utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag) - } - - override func start() { - guard !isCancelled else { return self.finish() } - - var etagResource: String? - let sizePreview = NCUtility().getSizePreview(width: metadata.width, height: metadata.height) - - if FileManager.default.fileExists(atPath: fileNameIconLocalPath) && FileManager.default.fileExists(atPath: fileNamePreviewLocalPath) { - etagResource = metadata.etagResource - } - - NextcloudKit.shared.downloadPreview(fileNamePathOrFileId: fileNamePath, - fileNamePreviewLocalPath: fileNamePreviewLocalPath, - widthPreview: Int(sizePreview.width), - heightPreview: Int(sizePreview.height), - fileNameIconLocalPath: fileNameIconLocalPath, - sizeIcon: NCGlobal.shared.sizeIcon, - etag: etagResource, - options: NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)) { _, _, imageIcon, _, etag, error in - - if error == .success, let image = imageIcon { - NCManageDatabase.shared.setMetadataEtagResource(ocId: self.metadata.ocId, etagResource: etag) - DispatchQueue.main.async { - if self.metadata.ocId == self.cell?.fileObjectId, let filePreviewImageView = self.cell?.filePreviewImageView { - if self.metadata.hasPreviewBorder { - self.cell?.filePreviewImageView?.layer.borderWidth = 0.2 - self.cell?.filePreviewImageView?.layer.borderColor = UIColor.systemGray3.cgColor - } - UIView.transition(with: filePreviewImageView, - duration: 0.75, - options: .transitionCrossDissolve, - animations: { filePreviewImageView.image = image }, - completion: nil) - } else { - self.collectionView?.reloadData() - } - } - } - self.finish() - } - } -} - private class AccountSwitcherButton: UIButton { var onMenuOpened: (() -> Void)? diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommonSelectTabBar.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommonSelectTabBar.swift index b0f2b6bc1c..b369db4bda 100644 --- a/iOSClient/Main/Collection Common/NCCollectionViewCommonSelectTabBar.swift +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommonSelectTabBar.swift @@ -5,6 +5,21 @@ // Created by Milen on 01.02.24. // Copyright © 2024 Marino Faggiana. All rights reserved. // +// Author Marino Faggiana +// +// 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 . +// import Foundation import SwiftUI diff --git a/iOSClient/Main/Collection Common/NCCollectionViewDownloadThumbnail.swift b/iOSClient/Main/Collection Common/NCCollectionViewDownloadThumbnail.swift new file mode 100644 index 0000000000..c3be24bb0b --- /dev/null +++ b/iOSClient/Main/Collection Common/NCCollectionViewDownloadThumbnail.swift @@ -0,0 +1,88 @@ +// +// NCCollectionViewDownloadThumbnail.swift +// Nextcloud +// +// Created by Marino Faggiana on 14/03/24. +// Copyright © 2024 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// 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 . +// + +import Foundation +import Queuer +import NextcloudKit +import Realm + +class NCCollectionViewDownloadThumbnail: ConcurrentOperation { + + var metadata: tableMetadata + var cell: NCCellProtocol? + var collectionView: UICollectionView? + var fileNamePath: String + var fileNamePreviewLocalPath: String + var fileNameIconLocalPath: String + let utilityFileSystem = NCUtilityFileSystem() + + init(metadata: tableMetadata, cell: NCCellProtocol?, collectionView: UICollectionView?) { + self.metadata = tableMetadata.init(value: metadata) + self.cell = cell + self.collectionView = collectionView + self.fileNamePath = utilityFileSystem.getFileNamePath(metadata.fileName, serverUrl: metadata.serverUrl, urlBase: metadata.urlBase, userId: metadata.userId) + self.fileNamePreviewLocalPath = utilityFileSystem.getDirectoryProviderStoragePreviewOcId(metadata.ocId, etag: metadata.etag) + self.fileNameIconLocalPath = utilityFileSystem.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag) + } + + override func start() { + guard !isCancelled else { return self.finish() } + + var etagResource: String? + let sizePreview = NCUtility().getSizePreview(width: metadata.width, height: metadata.height) + + if FileManager.default.fileExists(atPath: fileNameIconLocalPath) && FileManager.default.fileExists(atPath: fileNamePreviewLocalPath) { + etagResource = metadata.etagResource + } + + NextcloudKit.shared.downloadPreview(fileNamePathOrFileId: fileNamePath, + fileNamePreviewLocalPath: fileNamePreviewLocalPath, + widthPreview: Int(sizePreview.width), + heightPreview: Int(sizePreview.height), + fileNameIconLocalPath: fileNameIconLocalPath, + sizeIcon: NCGlobal.shared.sizeIcon, + etag: etagResource, + options: NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)) { _, _, imageIcon, _, etag, error in + + if error == .success, let image = imageIcon { + NCManageDatabase.shared.setMetadataEtagResource(ocId: self.metadata.ocId, etagResource: etag) + DispatchQueue.main.async { + if self.metadata.ocId == self.cell?.fileObjectId, let filePreviewImageView = self.cell?.filePreviewImageView { + if self.metadata.hasPreviewBorder { + self.cell?.filePreviewImageView?.layer.borderWidth = 0.2 + self.cell?.filePreviewImageView?.layer.borderColor = UIColor.systemGray3.cgColor + } + UIView.transition(with: filePreviewImageView, + duration: 0.75, + options: .transitionCrossDissolve, + animations: { filePreviewImageView.image = image }, + completion: nil) + } else { + self.collectionView?.reloadData() + } + } + } + self.finish() + } + } +} diff --git a/iOSClient/Main/Collection Common/NCCollectionViewUnifiedSearch.swift b/iOSClient/Main/Collection Common/NCCollectionViewUnifiedSearch.swift new file mode 100644 index 0000000000..7083ed754f --- /dev/null +++ b/iOSClient/Main/Collection Common/NCCollectionViewUnifiedSearch.swift @@ -0,0 +1,60 @@ +// +// NCCollectionViewUnifiedSearch.swift +// Nextcloud +// +// Created by Marino Faggiana on 14/03/24. +// Copyright © 2024 Marino Faggiana. All rights reserved. +// +// Author Marino Faggiana +// +// 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 . +// + +import Foundation +import Queuer +import NextcloudKit +import Realm + +class NCCollectionViewUnifiedSearch: ConcurrentOperation { + + var collectionViewCommon: NCCollectionViewCommon + var metadatas: [tableMetadata] + var searchResult: NKSearchResult + + init(collectionViewCommon: NCCollectionViewCommon, metadatas: [tableMetadata], searchResult: NKSearchResult) { + self.collectionViewCommon = collectionViewCommon + self.metadatas = metadatas + self.searchResult = searchResult + } + + func reloadDataThenPerform(_ closure: @escaping (() -> Void)) { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + CATransaction.begin() + CATransaction.setCompletionBlock(closure) + self.collectionViewCommon.collectionView.reloadData() + CATransaction.commit() + } + } + + override func start() { + + guard !isCancelled else { return self.finish() } + + self.collectionViewCommon.dataSource.addSection(metadatas: metadatas, searchResult: searchResult) + self.collectionViewCommon.searchResults?.append(self.searchResult) + reloadDataThenPerform { + self.finish() + } + } +} diff --git a/iOSClient/Main/Collection Common/NCGridCell.swift b/iOSClient/Main/Collection Common/NCGridCell.swift index e7a17a0dd0..f0c05c14fc 100644 --- a/iOSClient/Main/Collection Common/NCGridCell.swift +++ b/iOSClient/Main/Collection Common/NCGridCell.swift @@ -40,7 +40,7 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto var indexPath = IndexPath() private var user = "" - weak var delegate: NCGridCellDelegate? + weak var gridCellDelegate: NCGridCellDelegate? var namedButtonMore = "" var fileObjectId: String? { @@ -114,6 +114,7 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto labelTitle.text = "" labelInfo.text = "" + labelSubinfo.text = "" } override func prepareForReuse() { @@ -129,15 +130,15 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto } @IBAction func touchUpInsideMore(_ sender: Any) { - delegate?.tapMoreGridItem(with: objectId, namedButtonMore: namedButtonMore, image: imageItem.image, indexPath: indexPath, sender: sender) + gridCellDelegate?.tapMoreGridItem(with: objectId, namedButtonMore: namedButtonMore, image: imageItem.image, indexPath: indexPath, sender: sender) } @objc func longPressInsideMore(gestureRecognizer: UILongPressGestureRecognizer) { - delegate?.longPressMoreGridItem(with: objectId, namedButtonMore: namedButtonMore, indexPath: indexPath, gestureRecognizer: gestureRecognizer) + gridCellDelegate?.longPressMoreGridItem(with: objectId, namedButtonMore: namedButtonMore, indexPath: indexPath, gestureRecognizer: gestureRecognizer) } @objc func longPress(gestureRecognizer: UILongPressGestureRecognizer) { - delegate?.longPressGridItem(with: objectId, indexPath: indexPath, gestureRecognizer: gestureRecognizer) + gridCellDelegate?.longPressGridItem(with: objectId, indexPath: indexPath, gestureRecognizer: gestureRecognizer) } fileprivate func setA11yActions() { @@ -211,6 +212,14 @@ class NCGridCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto accessibilityLabel = label accessibilityValue = value } + + func setIconOutlines() { + if imageStatus.image != nil { + imageStatus.makeCircularBackground(withColor: .systemBackground) + } else { + imageStatus.backgroundColor = .clear + } + } } protocol NCGridCellDelegate: AnyObject { diff --git a/iOSClient/Main/Collection Common/NCGridCell.xib b/iOSClient/Main/Collection Common/NCGridCell.xib index 01f8eca397..4d3847f19a 100644 --- a/iOSClient/Main/Collection Common/NCGridCell.xib +++ b/iOSClient/Main/Collection Common/NCGridCell.xib @@ -1,6 +1,6 @@ - + @@ -47,8 +47,17 @@ - - + + + + + + + + + + + @@ -100,6 +109,7 @@ + @@ -123,12 +133,19 @@ + + + + + + + @@ -146,11 +163,18 @@ + + + + + + + diff --git a/iOSClient/Main/Collection Common/NCListCell.swift b/iOSClient/Main/Collection Common/NCListCell.swift index 3b54aeee95..d83525e6f6 100755 --- a/iOSClient/Main/Collection Common/NCListCell.swift +++ b/iOSClient/Main/Collection Common/NCListCell.swift @@ -22,13 +22,15 @@ // import UIKit +import SwipeCellKit -class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProtocol { +class NCListCell: SwipeCollectionViewCell, UIGestureRecognizerDelegate, NCCellProtocol { @IBOutlet weak var imageItem: UIImageView! @IBOutlet weak var imageSelect: UIImageView! @IBOutlet weak var imageStatus: UIImageView! @IBOutlet weak var imageFavorite: UIImageView! + @IBOutlet weak var imageFavoriteBackground: UIImageView! @IBOutlet weak var imageLocal: UIImageView! @IBOutlet weak var labelTitle: UILabel! @IBOutlet weak var labelInfo: UILabel! @@ -51,7 +53,7 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto private var user = "" var indexPath = IndexPath() - weak var delegate: NCListCellDelegate? + weak var listCellDelegate: NCListCellDelegate? var namedButtonMore = "" var fileAvatarImageView: UIImageView? { @@ -147,14 +149,23 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto labelTitle.text = "" labelInfo.text = "" + labelSubinfo.text = "" labelTitle.textColor = .label labelInfo.textColor = .systemGray labelSubinfo.textColor = .systemGray + + imageFavoriteBackground.isHidden = true } override func prepareForReuse() { super.prepareForReuse() imageItem.backgroundColor = nil + if fileFavoriteImage?.image != nil { + imageFavoriteBackground.isHidden = false + } else { + imageFavoriteBackground.isHidden = true + } + accessibilityHint = nil accessibilityLabel = nil accessibilityValue = nil @@ -165,19 +176,19 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto } @IBAction func touchUpInsideShare(_ sender: Any) { - delegate?.tapShareListItem(with: objectId, indexPath: indexPath, sender: sender) + listCellDelegate?.tapShareListItem(with: objectId, indexPath: indexPath, sender: sender) } @IBAction func touchUpInsideMore(_ sender: Any) { - delegate?.tapMoreListItem(with: objectId, namedButtonMore: namedButtonMore, image: imageItem.image, indexPath: indexPath, sender: sender) + listCellDelegate?.tapMoreListItem(with: objectId, namedButtonMore: namedButtonMore, image: imageItem.image, indexPath: indexPath, sender: sender) } @objc func longPressInsideMore(gestureRecognizer: UILongPressGestureRecognizer) { - delegate?.longPressMoreListItem(with: objectId, namedButtonMore: namedButtonMore, indexPath: indexPath, gestureRecognizer: gestureRecognizer) + listCellDelegate?.longPressMoreListItem(with: objectId, namedButtonMore: namedButtonMore, indexPath: indexPath, gestureRecognizer: gestureRecognizer) } @objc func longPress(gestureRecognizer: UILongPressGestureRecognizer) { - delegate?.longPressListItem(with: objectId, indexPath: indexPath, gestureRecognizer: gestureRecognizer) + listCellDelegate?.longPressListItem(with: objectId, indexPath: indexPath, gestureRecognizer: gestureRecognizer) } fileprivate func setA11yActions() { @@ -307,6 +318,22 @@ class NCListCell: UICollectionViewCell, UIGestureRecognizerDelegate, NCCellProto } } } + + func setIconOutlines() { + imageFavoriteBackground.isHidden = fileFavoriteImage?.image == nil + + if imageStatus.image != nil { + imageStatus.makeCircularBackground(withColor: .systemBackground) + } else { + imageStatus.backgroundColor = .clear + } + + if imageLocal.image != nil { + imageLocal.makeCircularBackground(withColor: .systemBackground) + } else { + imageLocal.backgroundColor = .clear + } + } } protocol NCListCellDelegate: AnyObject { diff --git a/iOSClient/Main/Collection Common/NCListCell.xib b/iOSClient/Main/Collection Common/NCListCell.xib index 367c7a13e3..f80e36009a 100755 --- a/iOSClient/Main/Collection Common/NCListCell.xib +++ b/iOSClient/Main/Collection Common/NCListCell.xib @@ -32,8 +32,16 @@ - - + + + @@ -65,6 +73,12 @@ +