From fcbbb8ab748bd7a2428ca7f9e71564ad8a318bb9 Mon Sep 17 00:00:00 2001 From: Milen Pivchev Date: Fri, 20 Oct 2023 13:09:05 +0200 Subject: [PATCH] Squashed commit of the following: commit 28c5001295091e46b6f40644a8ea404887994c66 Author: Milen Pivchev Date: Fri Oct 20 13:08:44 2023 +0200 WIP Signed-off-by: Milen Pivchev commit a67c7a0a22fbfafbfd9d8fa8ae145ca687133f2e Merge: b42a1c8d0 510bdb453 Author: Milen Pivchev Date: Fri Oct 20 13:05:10 2023 +0200 Merge branch 'develop' of https://github.com/nextcloud/ios into media-view-performance-optimizations Signed-off-by: Milen Pivchev # Conflicts: # iOSClient/Media/NCMediaCache.swift commit 510bdb453b4c40b9666b78e2643808beaa995a0c Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Fri Oct 20 12:17:49 2023 +0200 lint Signed-off-by: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> commit 6a560e3d8080181ab32ea00c29c085b2402c994e Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Fri Oct 20 12:17:11 2023 +0200 improvements Signed-off-by: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> commit a232a022bbd75207a7346fa901560e44abd164d9 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Fri Oct 20 12:04:24 2023 +0200 lint Signed-off-by: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> commit 74d530298a5a9e7fb41d726f0bc4b31decc03897 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Fri Oct 20 12:01:26 2023 +0200 lint Signed-off-by: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> commit 3de2089f3ed24a48296c6b31fa1535b070d21386 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Fri Oct 20 11:41:07 2023 +0200 lint Signed-off-by: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> commit 01b701418354d945c3fd5c1d8e2371fcadd8628f Author: Nextcloud bot Date: Fri Oct 20 02:42:09 2023 +0000 Fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot commit b42a1c8d081ab03dcb99d3f8e13b824fccd136a7 Author: Milen Pivchev Date: Thu Oct 19 18:49:44 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 073c390d002f4d01d019a503e9b4f430e90dac1a Merge: 2475daa25 928a08897 Author: Milen Pivchev Date: Thu Oct 19 18:18:43 2023 +0200 Merge branch '2399-aspect-ratio-in-media-view' into media-view-performance-optimizations Signed-off-by: Milen Pivchev # Conflicts: # Nextcloud.xcodeproj/project.pbxproj commit 472b560882eb6c39d78a6b24cbccd5288df997be Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Thu Oct 19 17:43:49 2023 +0200 update NextcloudNit Signed-off-by: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> commit 2475daa25923764c724f108d063c8db1aef13c3d Merge: 6012f3b90 4ca1fbe75 Author: Milen Pivchev Date: Thu Oct 19 14:33:34 2023 +0200 Merge branch '2399-aspect-ratio-in-media-view' of https://github.com/nextcloud/ios into media-view-performance-optimizations commit 6012f3b9086f204a1a98f08e0c30127e2d3c14be Merge: f55c8fbf4 9747ad824 Author: Milen Pivchev Date: Thu Oct 19 12:28:17 2023 +0200 Merge branch '2399-aspect-ratio-in-media-view' of https://github.com/nextcloud/ios into media-view-performance-optimizations commit f55c8fbf4b3cb95b472ac500ae28eaf0717668a4 Author: Milen Pivchev Date: Thu Oct 19 12:24:03 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 236c98b1a5ed166d5248d5637d0dd3b1971aad51 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 16:42:52 2023 +0200 verify etag commit 7b2eab2a707d36a262b3200fd50b2908f83518ab Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 12:28:22 2023 +0200 Update NCMediaManager.swift commit 1cbe26b803e682f72ccc50ac50d4f1b58427a918 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 12:23:01 2023 +0200 optimized commit 626726672ac97b7001db5a703f42e652bad2d5da Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 11:24:59 2023 +0200 Update NCMediaManager.swift commit 7ecc1b4d73ae8a6c5d42eee1490ab7bca35ca478 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 11:22:34 2023 +0200 Update AppDelegate.swift commit 062c224c61668d014b0341d11fc06fcdbdd107b3 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 11:15:32 2023 +0200 Update NCMediaManager.swift commit 7357d6a6f1aeaab66a434858b5db27dd15c31f7a Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 11:12:24 2023 +0200 Update NCMediaManager.swift commit 2a866d6430e48f5b34728fa391d622e0de4da9d3 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 11:10:43 2023 +0200 Update NCMediaManager.swift commit 3212e92ecdc4875deeed6ae86f61892287fae07e Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 11:09:07 2023 +0200 Update NCMediaManager.swift commit d493847d29cb02fd4709d382444162c9cf095f63 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 11:03:36 2023 +0200 Update NCMediaManager.swift commit e9a5d97e78172b3301ad9fb9b4a3f62cbb0c1185 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 11:02:11 2023 +0200 Update NCMediaManager.swift commit e73c0af8e17be76741217db720f8927baf5c9781 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 10:58:25 2023 +0200 Update AppDelegate.swift commit eee1b89c088f42dd8347ad246532ee2a0e9e3700 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 10:55:28 2023 +0200 Update NCMediaManager.swift commit 753841fdc78618359a662519767f83837f665776 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 10:52:25 2023 +0200 Update NCMediaManager.swift commit 7b94537e55ff660699a5202269fbba60a1963983 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Tue Oct 17 10:50:13 2023 +0200 coding commit b7bb1fef870050aad8bc379a63fa4fb1ff0fd9a6 Author: Marino Faggiana <8616947+marinofaggiana@users.noreply.github.com> Date: Mon Oct 16 18:13:11 2023 +0200 test test commit 873df2df54966af42a6c6439c202aa1b5ebce7a3 Author: Milen Pivchev Date: Fri Oct 13 19:30:38 2023 +0200 More optimizations Signed-off-by: Milen Pivchev commit fcf9f5af04ed7112c4bcfd3aa2829d6b4a421c8c Author: Milen Pivchev Date: Fri Oct 13 18:56:48 2023 +0200 Replace LazyVStack with List Signed-off-by: Milen Pivchev commit 449641c79ad38dca0e5981c2bd0491972fa298e2 Author: Milen Pivchev Date: Fri Oct 13 18:21:29 2023 +0200 Fix some rows not updating on rotate/zoom Signed-off-by: Milen Pivchev commit 7091d2ea1c3a1f60764f5edec5e9a61813b0e160 Author: Milen Pivchev Date: Fri Oct 13 18:14:39 2023 +0200 WIP Signed-off-by: Milen Pivchev commit bc571bcb5149936c64fa521474d5b42330416fc4 Author: Milen Pivchev Date: Fri Oct 13 12:12:04 2023 +0200 Refactor Signed-off-by: Milen Pivchev commit 7172b43e7b4b512ece66b9363711341aa099a65d Author: Milen Pivchev Date: Fri Oct 13 10:48:32 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 3f97177cb466aa2ffe321458e4c99eee937a821e Author: Milen Pivchev Date: Fri Oct 13 10:46:13 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 6cd03fc82ccf9fbfb47598a96e8a108e9823c7a4 Author: Milen Pivchev Date: Thu Oct 12 18:57:26 2023 +0200 Fix scroll offset bug Signed-off-by: Milen Pivchev commit adc56705c50132ba322d31e78dbc2c270e433bd0 Author: Milen Pivchev Date: Thu Oct 12 17:43:13 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 15ed95540dd405842f2c6696f79a14c14d60ad66 Author: Milen Pivchev Date: Wed Oct 11 18:04:33 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 11062244235c301c4c714120a478b4e5218f700f Author: Milen Pivchev Date: Wed Oct 11 14:43:38 2023 +0200 Fix compile Signed-off-by: Milen Pivchev commit f668bdb8d132a2ee3510f842e53d557edd527b29 Merge: 5ac583b90 ae6b88442 Author: Milen Pivchev Date: Wed Oct 11 12:36:11 2023 +0200 Merge branch '2399-aspect-ratio-in-media-view' of https://github.com/nextcloud/ios into media-view-performance-optimizations commit 5ac583b90f532000b189d652f15b7a8c30313487 Author: Milen Pivchev Date: Wed Oct 11 12:10:37 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 01051100783a0d71b40312059842d0a7bd9f2c2e Author: Milen Pivchev Date: Wed Oct 11 12:08:14 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 40011dfc8f29c2d7579e527a50a14c2bac9e0c0e Author: Milen Pivchev Date: Wed Oct 11 12:06:54 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 7f948e13fd6621deed19ea3e917766b4e1723b35 Merge: 2d8cfb7d9 b8b08f4ea Author: Milen Pivchev Date: Wed Oct 11 11:34:47 2023 +0200 Merge branch 'media-view-performance-optimizations' of https://github.com/nextcloud/ios into media-view-performance-optimizations commit 2d8cfb7d9a070e771986f0044fe96806d10c904a Author: Milen Pivchev Date: Wed Oct 11 11:34:33 2023 +0200 WIP Signed-off-by: Milen Pivchev commit b8b08f4ea8b6f4199ec6cdda1f67e15b53cd00a6 Merge: 60de2d96d 01f2c315f Author: Marino Faggiana Date: Wed Oct 11 10:36:43 2023 +0200 Merge branch 'media-view-performance-optimizations' of https://github.com/nextcloud/ios into media-view-performance-optimizations commit 01f2c315f0d7ef3ae56035df3d0540f6fdb32f69 Author: Milen Pivchev Date: Tue Oct 10 18:55:22 2023 +0200 WIP Signed-off-by: Milen Pivchev commit b0f4b4622d585c37aecd07b5218eaa6dc1e6cf24 Author: Milen Pivchev Date: Tue Oct 10 18:52:34 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 134c91e1bb9bf5c92bf0dc2e452508849025d4e9 Author: Milen Pivchev Date: Tue Oct 10 18:05:08 2023 +0200 WIP Signed-off-by: Milen Pivchev commit fce442356af52cbabfda9e63e6e832099a5bbd69 Author: Milen Pivchev Date: Tue Oct 10 17:31:32 2023 +0200 WIP Signed-off-by: Milen Pivchev commit bdb5f4f590f80f06f09adb73469093c63e001911 Author: Milen Pivchev Date: Tue Oct 10 16:56:04 2023 +0200 WIP Signed-off-by: Milen Pivchev commit ffa930a62fb93c04150c2f45ff835b91417a44ed Author: Milen Pivchev Date: Tue Oct 10 14:15:50 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 60de2d96dd07391018f1fdd345cf0b2d8306298d Author: Marino Faggiana Date: Tue Oct 10 11:13:54 2023 +0200 test Signed-off-by: Marino Faggiana commit 179993a0ccb9b0d61bd3dda65eea1196749e22e1 Author: Milen Pivchev Date: Mon Oct 9 19:37:35 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 662040650cb00c016b4c219b73827e10ab5853ba Author: Milen Pivchev Date: Mon Oct 9 17:08:56 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 221a24806e6b6e41d07f1eb161dde08d3dc58e70 Author: Milen Pivchev Date: Mon Oct 9 15:53:01 2023 +0200 Add thread-safe LRU Cache Signed-off-by: Milen Pivchev commit d895e511e2462816ee6bd2e70f614ba83e824bf8 Author: Milen Pivchev Date: Mon Oct 9 15:00:59 2023 +0200 WIP Signed-off-by: Milen Pivchev commit d46aee27804ad4d574d21ca555678494a2cc15e0 Author: Milen Pivchev Date: Fri Oct 6 13:21:25 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 14b29c45c28430989d249671ca2fff1c4d29c261 Author: Milen Pivchev Date: Fri Oct 6 13:17:16 2023 +0200 WIP Signed-off-by: Milen Pivchev commit fb65918d9906d45dc992f34004e4db0f179080f4 Author: Milen Pivchev Date: Fri Oct 6 11:08:31 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 7c7762012651c1fe64b74a45d536f07c9acf0f8b Author: Milen Pivchev Date: Thu Oct 5 19:29:33 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 689f4416893109c0c148e9ce5742a317a7934d8d Author: Milen Pivchev Date: Thu Oct 5 17:04:18 2023 +0200 WIP Signed-off-by: Milen Pivchev commit fb7b1c636307f41a05789d5f28e11ac5315052e3 Author: Milen Pivchev Date: Thu Oct 5 15:11:05 2023 +0200 WIP Signed-off-by: Milen Pivchev commit 9d4a71ce19e4f50f072a4e5addca74aa5ea9248e Author: Milen Pivchev Date: Thu Oct 5 13:36:20 2023 +0200 Change LRU cache Signed-off-by: Milen Pivchev commit 28d5092b5fe05aa025baffc9dc85b4b390960020 Author: Milen Pivchev Date: Wed Oct 4 17:52:35 2023 +0200 WIP Signed-off-by: Milen Pivchev Signed-off-by: Milen Pivchev --- Nextcloud.xcodeproj/project.pbxproj | 143 +++++++- .../Extensions/SwiftUIView+Extensions.swift | 22 ++ .../NCCollectionViewCommon.swift | 2 +- iOSClient/Media/Cell/NCMediaCell.swift | 32 +- iOSClient/Media/NCMediaCache.swift | 40 ++- iOSClient/Media/NCMediaNew.swift | 320 +++++++++--------- iOSClient/Media/NCMediaRow.swift | 29 +- iOSClient/Media/NCMediaRowViewModel.swift | 109 +++--- iOSClient/Media/NCMediaScrollView.swift | 120 +++++++ iOSClient/Media/NCMediaViewModel.swift | 33 +- .../Networking/E2EE/NCNetworkingE2EE.swift | 18 +- .../E2EE/NCNetworkingE2EECreateFolder.swift | 2 +- .../E2EE/NCNetworkingE2EEMarkFolder.swift | 2 +- iOSClient/Settings/CCAdvanced.m | 2 - .../hu.lproj/InfoPlist.strings | Bin 1428 -> 1456 bytes .../hu.lproj/Localizable.strings | Bin 126632 -> 126638 bytes iOSClient/Utility/PreferenceKeys.swift | 6 + 17 files changed, 591 insertions(+), 289 deletions(-) create mode 100644 iOSClient/Media/NCMediaScrollView.swift diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index cfd4cf4059..a7ccbc39f3 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -76,6 +76,20 @@ C04E2F232A17BB4D001BAD85 /* FilesIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C04E2F222A17BB4D001BAD85 /* FilesIntegrationTests.swift */; }; D575039F27146F93008DC9DC /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A0D1342591FBC5008F8A13 /* String+Extension.swift */; }; D5B6AA7827200C7200D49C24 /* NCActivityTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */; }; + F306DBC22AE18E7900F0AE27 /* Shimmer in Frameworks */ = {isa = PBXBuildFile; productRef = F3EFBF5E2AB2100E00B5724C /* Shimmer */; }; + F306DBC32AE18E7900F0AE27 /* SwiftUIIntrospect in Frameworks */ = {isa = PBXBuildFile; productRef = F3077B7B2ABDA06A0013BA13 /* SwiftUIIntrospect */; }; + F306DBCE2AE18F1D00F0AE27 /* NCMediaCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F306DBC62AE18F1C00F0AE27 /* NCMediaCell.swift */; }; + F306DBCF2AE18F1D00F0AE27 /* NCGridMediaCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F306DBC72AE18F1C00F0AE27 /* NCGridMediaCell.swift */; }; + F306DBD02AE18F1D00F0AE27 /* NCGridMediaCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F306DBC82AE18F1C00F0AE27 /* NCGridMediaCell.xib */; }; + F306DBD12AE18F1D00F0AE27 /* NCMediaRowViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F306DBC92AE18F1C00F0AE27 /* NCMediaRowViewModel.swift */; }; + F306DBD22AE18F1D00F0AE27 /* NCMediaRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F306DBCA2AE18F1D00F0AE27 /* NCMediaRow.swift */; }; + F306DBD32AE18F1D00F0AE27 /* NCMediaUIKitWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F306DBCC2AE18F1D00F0AE27 /* NCMediaUIKitWrapper.swift */; }; + F306DBD42AE18F1D00F0AE27 /* NCMediaViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F306DBCD2AE18F1D00F0AE27 /* NCMediaViewModel.swift */; }; + F306DBD62AE18F4B00F0AE27 /* NCMediaNew.swift in Sources */ = {isa = PBXBuildFile; fileRef = F306DBD52AE18F4B00F0AE27 /* NCMediaNew.swift */; }; + F306DBDD2AE18F5800F0AE27 /* NCMediaCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F306DBD82AE18F5800F0AE27 /* NCMediaCell.swift */; }; + F306DBDE2AE18F5800F0AE27 /* NCGridMediaCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F306DBD92AE18F5800F0AE27 /* NCGridMediaCell.swift */; }; + F306DBDF2AE18F5800F0AE27 /* NCGridMediaCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F306DBDA2AE18F5800F0AE27 /* NCGridMediaCell.xib */; }; + F306DBE22AE1932800F0AE27 /* PreferenceKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = F306DBE12AE1932800F0AE27 /* PreferenceKeys.swift */; }; F30A962F2A27ADF900D7BCFE /* EnvVars.stencil in Resources */ = {isa = PBXBuildFile; fileRef = F30A962E2A27ADF900D7BCFE /* EnvVars.stencil */; }; F30A96312A27AEBF00D7BCFE /* EnvVars.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A96302A27AEBF00D7BCFE /* EnvVars.generated.swift */; }; F30A96322A27AEDD00D7BCFE /* EnvVars.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = F30A96302A27AEBF00D7BCFE /* EnvVars.generated.swift */; }; @@ -100,6 +114,7 @@ F31F69642A2F929600162F76 /* PreviewSnapshots in Frameworks */ = {isa = PBXBuildFile; productRef = F31F69632A2F929600162F76 /* PreviewSnapshots */; }; F31F69662A2F929600162F76 /* PreviewSnapshotsTesting in Frameworks */ = {isa = PBXBuildFile; productRef = F31F69652A2F929600162F76 /* PreviewSnapshotsTesting */; }; F31F69692A2F92F000162F76 /* SnapshotTestingHEIC in Frameworks */ = {isa = PBXBuildFile; productRef = F31F69682A2F92F000162F76 /* SnapshotTestingHEIC */; }; + F3271B8D2AD43AAE009993C3 /* LRUCache in Frameworks */ = {isa = PBXBuildFile; productRef = F3271B8C2AD43AAE009993C3 /* LRUCache */; }; 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 */; }; @@ -130,6 +145,7 @@ F3BB464F2A39EBE500461F6E /* NCMoreUserCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB464E2A39EBE500461F6E /* NCMoreUserCell.swift */; }; F3BB46522A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB46512A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift */; }; F3BB46542A3A1E9D00461F6E /* CCCellMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3BB46532A3A1E9D00461F6E /* CCCellMore.swift */; }; + F3DE93E92AD93CA000F44D31 /* NCMediaScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3DE93E82AD93CA000F44D31 /* NCMediaScrollView.swift */; }; F700222C1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; }; F700222D1EC479840080073F /* Custom.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F700222B1EC479840080073F /* Custom.xcassets */; }; F700510122DF63AC003A3356 /* NCShare.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F700510022DF63AC003A3356 /* NCShare.storyboard */; }; @@ -418,8 +434,6 @@ F7725A61251F33BB00D125E0 /* NCFiles.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7725A5F251F33BB00D125E0 /* NCFiles.storyboard */; }; F77333882927A72100466E35 /* OpenSSL in Frameworks */ = {isa = PBXBuildFile; productRef = F77333872927A72100466E35 /* OpenSSL */; }; F774264A22EB4D0000B23912 /* NCSearchUserDropDownCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F774264822EB4D0000B23912 /* NCSearchUserDropDownCell.xib */; }; - F77444F522281649000D5EB0 /* NCGridMediaCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77444F322281649000D5EB0 /* NCGridMediaCell.swift */; }; - F77444F622281649000D5EB0 /* NCGridMediaCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F77444F422281649000D5EB0 /* NCGridMediaCell.xib */; }; F77444F8222816D5000D5EB0 /* NCPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77444F7222816D5000D5EB0 /* NCPickerViewController.swift */; }; F77910A525DD517B00CEDB9E /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = F77910A425DD517B00CEDB9E /* Settings.bundle */; }; F77910AB25DD53C700CEDB9E /* NCSettingsBundleHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F77910AA25DD53C700CEDB9E /* NCSettingsBundleHelper.swift */; }; @@ -839,6 +853,18 @@ C04E2F202A17BB4D001BAD85 /* NextcloudIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NextcloudIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; C04E2F222A17BB4D001BAD85 /* FilesIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesIntegrationTests.swift; sourceTree = ""; }; D5B6AA7727200C7200D49C24 /* NCActivityTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCActivityTableViewCell.swift; sourceTree = ""; }; + F306DBC62AE18F1C00F0AE27 /* NCMediaCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCMediaCell.swift; sourceTree = ""; }; + F306DBC72AE18F1C00F0AE27 /* NCGridMediaCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCGridMediaCell.swift; sourceTree = ""; }; + F306DBC82AE18F1C00F0AE27 /* NCGridMediaCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCGridMediaCell.xib; sourceTree = ""; }; + F306DBC92AE18F1C00F0AE27 /* NCMediaRowViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCMediaRowViewModel.swift; sourceTree = ""; }; + F306DBCA2AE18F1D00F0AE27 /* NCMediaRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCMediaRow.swift; sourceTree = ""; }; + F306DBCC2AE18F1D00F0AE27 /* NCMediaUIKitWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCMediaUIKitWrapper.swift; sourceTree = ""; }; + F306DBCD2AE18F1D00F0AE27 /* NCMediaViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCMediaViewModel.swift; sourceTree = ""; }; + F306DBD52AE18F4B00F0AE27 /* NCMediaNew.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCMediaNew.swift; sourceTree = ""; }; + F306DBD82AE18F5800F0AE27 /* NCMediaCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCMediaCell.swift; sourceTree = ""; }; + F306DBD92AE18F5800F0AE27 /* NCGridMediaCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCGridMediaCell.swift; sourceTree = ""; }; + F306DBDA2AE18F5800F0AE27 /* NCGridMediaCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCGridMediaCell.xib; sourceTree = ""; }; + F306DBE12AE1932800F0AE27 /* PreferenceKeys.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreferenceKeys.swift; sourceTree = ""; }; F30A96042A27299D00D7BCFE /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; F30A962E2A27ADF900D7BCFE /* EnvVars.stencil */ = {isa = PBXFileReference; lastKnownFileType = text; path = EnvVars.stencil; sourceTree = ""; }; F30A96302A27AEBF00D7BCFE /* EnvVars.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = EnvVars.generated.swift; path = Sourcery/EnvVars.generated.swift; sourceTree = ""; }; @@ -857,6 +883,7 @@ F3BB464E2A39EBE500461F6E /* NCMoreUserCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMoreUserCell.swift; sourceTree = ""; }; F3BB46512A39EC4900461F6E /* NCMoreAppSuggestionsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMoreAppSuggestionsCell.swift; sourceTree = ""; }; F3BB46532A3A1E9D00461F6E /* CCCellMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CCCellMore.swift; sourceTree = ""; }; + F3DE93E82AD93CA000F44D31 /* NCMediaScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCMediaScrollView.swift; sourceTree = ""; }; F700222B1EC479840080073F /* Custom.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Custom.xcassets; sourceTree = ""; }; F700510022DF63AC003A3356 /* NCShare.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = NCShare.storyboard; sourceTree = ""; }; F700510222DF6897003A3356 /* Parchment.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Parchment.framework; path = Carthage/Build/iOS/Parchment.framework; sourceTree = ""; }; @@ -1113,8 +1140,6 @@ F77439541FCD6D6100662C46 /* es-PY */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-PY"; path = "es-PY.lproj/Localizable.strings"; sourceTree = ""; }; F774395B1FCD6D8200662C46 /* es-SV */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-SV"; path = "es-SV.lproj/Localizable.strings"; sourceTree = ""; }; F77439621FCD6D9C00662C46 /* es-UY */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-UY"; path = "es-UY.lproj/Localizable.strings"; sourceTree = ""; }; - F77444F322281649000D5EB0 /* NCGridMediaCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCGridMediaCell.swift; sourceTree = ""; }; - F77444F422281649000D5EB0 /* NCGridMediaCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NCGridMediaCell.xib; sourceTree = ""; }; F77444F7222816D5000D5EB0 /* NCPickerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCPickerViewController.swift; sourceTree = ""; }; F77910A425DD517B00CEDB9E /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; F77910AA25DD53C700CEDB9E /* NCSettingsBundleHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCSettingsBundleHelper.swift; sourceTree = ""; }; @@ -1488,6 +1513,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + F306DBC32AE18E7900F0AE27 /* SwiftUIIntrospect in Frameworks */, + F306DBC22AE18E7900F0AE27 /* Shimmer in Frameworks */, F7D56B1A2972405500FA46C4 /* Mantis in Frameworks */, F7ED547C25EEA65400956C55 /* QRCodeReader in Frameworks */, F788ECC7263AAAFA00ADC67F /* MarkdownKit in Frameworks */, @@ -1507,6 +1534,7 @@ F72AD70D28C24B93006CB92D /* NextcloudKit in Frameworks */, F70B86752642CE3B00ED5349 /* FirebaseCrashlytics in Frameworks */, F7A1050E29E587AF00FFD92B /* TagListView in Frameworks */, + F3271B8D2AD43AAE009993C3 /* LRUCache in Frameworks */, F76DA969277B77EA0082465B /* DropDown in Frameworks */, F7F623B52A5EF4D30022D3D4 /* Gzip in Frameworks */, F75EAED826D2552E00F4320E /* MarqueeLabel in Frameworks */, @@ -1605,6 +1633,34 @@ path = NextcloudIntegrationTests; sourceTree = ""; }; + F306DBC52AE18F1C00F0AE27 /* Cell */ = { + isa = PBXGroup; + children = ( + F306DBC62AE18F1C00F0AE27 /* NCMediaCell.swift */, + F306DBC72AE18F1C00F0AE27 /* NCGridMediaCell.swift */, + F306DBC82AE18F1C00F0AE27 /* NCGridMediaCell.xib */, + ); + path = Cell; + sourceTree = ""; + }; + F306DBCB2AE18F1D00F0AE27 /* UIWrapper */ = { + isa = PBXGroup; + children = ( + F306DBCC2AE18F1D00F0AE27 /* NCMediaUIKitWrapper.swift */, + ); + path = UIWrapper; + sourceTree = ""; + }; + F306DBD72AE18F5800F0AE27 /* Cell */ = { + isa = PBXGroup; + children = ( + F306DBD82AE18F5800F0AE27 /* NCMediaCell.swift */, + F306DBD92AE18F5800F0AE27 /* NCGridMediaCell.swift */, + F306DBDA2AE18F5800F0AE27 /* NCGridMediaCell.xib */, + ); + path = Cell; + sourceTree = ""; + }; F30A962A2A27A9C800D7BCFE /* Tests */ = { isa = PBXGroup; children = ( @@ -1754,15 +1810,6 @@ path = Shares; sourceTree = ""; }; - F720B5B72507B9A5008C94E5 /* Cell */ = { - isa = PBXGroup; - children = ( - F77444F322281649000D5EB0 /* NCGridMediaCell.swift */, - F77444F422281649000D5EB0 /* NCGridMediaCell.xib */, - ); - path = Cell; - sourceTree = ""; - }; F7239861253C95D500257F49 /* NCViewerRichdocument */ = { isa = PBXGroup; children = ( @@ -2240,6 +2287,7 @@ F7BFFA991A24D7BB0044ED85 /* Utility */ = { isa = PBXGroup; children = ( + F306DBE12AE1932800F0AE27 /* PreferenceKeys.swift */, F7053E3C1C639DF500741EA5 /* CCUtility.h */, F7053E3D1C639DF500741EA5 /* CCUtility.m */, F76D364528A4F8BF00214537 /* NCActivityIndicator.swift */, @@ -2385,11 +2433,18 @@ F7EC9CB921185F2000F1C5CE /* Media */ = { isa = PBXGroup; children = ( - F720B5B72507B9A5008C94E5 /* Cell */, + F306DBD72AE18F5800F0AE27 /* Cell */, + F306DBD52AE18F4B00F0AE27 /* NCMediaNew.swift */, + F306DBC52AE18F1C00F0AE27 /* Cell */, + F306DBCA2AE18F1D00F0AE27 /* NCMediaRow.swift */, + F306DBC92AE18F1C00F0AE27 /* NCMediaRowViewModel.swift */, + F306DBCD2AE18F1D00F0AE27 /* NCMediaViewModel.swift */, + F306DBCB2AE18F1D00F0AE27 /* UIWrapper */, F7501C302212E57400FB1415 /* NCMedia.storyboard */, - F7501C312212E57400FB1415 /* NCMedia.swift */, F76B649B2ADFFAED00014640 /* NCMediaCache.swift */, F7F1E54B2492369A00E42386 /* NCMediaCommandView.xib */, + F7501C312212E57400FB1415 /* NCMedia.swift */, + F3DE93E82AD93CA000F44D31 /* NCMediaScrollView.swift */, ); path = Media; sourceTree = ""; @@ -2905,6 +2960,8 @@ F7A1050D29E587AF00FFD92B /* TagListView */, F31F69632A2F929600162F76 /* PreviewSnapshots */, F7F623B42A5EF4D30022D3D4 /* Gzip */, + F3EFBF5E2AB2100E00B5724C /* Shimmer */, + F3077B7B2ABDA06A0013BA13 /* SwiftUIIntrospect */, F76B649D2ADFFDEC00014640 /* LRUCache */, ); productName = "Crypto Cloud"; @@ -3081,6 +3138,8 @@ F31F69622A2F929600162F76 /* XCRemoteSwiftPackageReference "swiftui-preview-snapshots" */, F31F69672A2F92F000162F76 /* XCRemoteSwiftPackageReference "SnapshotTestingHEIC" */, F7F623B32A5EF4D30022D3D4 /* XCRemoteSwiftPackageReference "GzipSwift" */, + F3EFBF5D2AB20B9100B5724C /* XCRemoteSwiftPackageReference "SwiftUI-Shimmer" */, + F3718CC02ABD9A76009BC4C2 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */, F76B649A2ADFFAD200014640 /* XCRemoteSwiftPackageReference "LRUCache" */, ); productRefGroup = F7F67B9F1A24D27800EE80DA; @@ -3194,7 +3253,6 @@ buildActionMask = 2147483647; files = ( F7362A1F220C853A005101B5 /* LaunchScreen.storyboard in Resources */, - F77444F622281649000D5EB0 /* NCGridMediaCell.xib in Resources */, F78ACD4421903CF20088454D /* NCListCell.xib in Resources */, F3BB464D2A39ADCC00461F6E /* NCMoreAppSuggestionsCell.xib in Resources */, F7F4F10727ECDBDB008676F9 /* Inconsolata-Black.ttf in Resources */, @@ -3232,6 +3290,7 @@ F7B8B83025681C3400967775 /* GoogleService-Info.plist in Resources */, F7381EE5218218C9000B1560 /* NCOffline.storyboard in Resources */, F7E0CDCF265CE8610044854E /* NCUserStatus.storyboard in Resources */, + F306DBDF2AE18F5800F0AE27 /* NCGridMediaCell.xib in Resources */, F76D3CF32428B94E005DFA87 /* NCViewerPDFSearchCell.xib in Resources */, F7CA212E25F1333300826ABB /* NCAccountRequest.storyboard in Resources */, F717402D24F699A5000C87D5 /* NCFavorite.storyboard in Resources */, @@ -3264,6 +3323,7 @@ F73B422B2476764F00A30FD3 /* NCNotification.storyboard in Resources */, F7FF2CB12842159500EBB7A1 /* NCSectionHeader.xib in Resources */, F7D1612023CF19E30039EBBF /* NCViewerRichWorkspace.storyboard in Resources */, + F306DBD02AE18F1D00F0AE27 /* NCGridMediaCell.xib in Resources */, F77B0F631D118A16002130FE /* Localizable.strings in Resources */, F774264A22EB4D0000B23912 /* NCSearchUserDropDownCell.xib in Resources */, F7CB689A2541676B0050EC94 /* NCMore.storyboard in Resources */, @@ -3642,7 +3702,6 @@ buildActionMask = 2147483647; files = ( F30A96312A27AEBF00D7BCFE /* EnvVars.generated.swift in Sources */, - F77444F522281649000D5EB0 /* NCGridMediaCell.swift in Sources */, F78C6FDE296D677300C952C3 /* NCContextMenu.swift in Sources */, F769CA172965AB7C00039397 /* NCUploadAssets.swift in Sources */, F7AE00F8230E81CB007ACF8A /* NCBrowserWeb.swift in Sources */, @@ -3664,8 +3723,10 @@ F76D3CF12428B40E005DFA87 /* NCViewerPDFSearch.swift in Sources */, F7245924289BB50C00474787 /* ThreadSafeDictionary.swift in Sources */, F73F537F1E929C8500F8678D /* NCMore.swift in Sources */, + F306DBE22AE1932800F0AE27 /* PreferenceKeys.swift in Sources */, F702F2CF25EE5B5C008F8E80 /* NCGlobal.swift in Sources */, F72CD63A25C19EBF00F46F9A /* NCAutoUpload.swift in Sources */, + F306DBD22AE18F1D00F0AE27 /* NCMediaRow.swift in Sources */, AF93471D27E2361E002537EE /* NCShareAdvancePermissionFooter.swift in Sources */, AF1A9B6427D0CA1E00F17A9E /* UIAlertController+Extension.swift in Sources */, F73B422C2476764F00A30FD3 /* NCNotification.swift in Sources */, @@ -3703,6 +3764,7 @@ F72D1007210B6882009C96B7 /* NCPushNotificationEncryption.m in Sources */, F785EE9D246196DF00B3F945 /* NCNetworkingE2EE.swift in Sources */, F76673ED22C901F6007ED366 /* FileProviderDomain.swift in Sources */, + F306DBD42AE18F1D00F0AE27 /* NCMediaViewModel.swift in Sources */, F7A321AD1E9E6AD50069AD1B /* CCAdvanced.m in Sources */, F77B0E4F1D118A16002130FE /* CCManageAutoUpload.m in Sources */, F7BAADC81ED5A87C00B7EAD4 /* NCDatabase.swift in Sources */, @@ -3732,6 +3794,7 @@ 8491B1CD273BBA82001C8C5B /* UIViewController+Menu.swift in Sources */, F761856C29E98543006EB3B0 /* NCIntroCollectionViewCell.swift in Sources */, F75DD765290ABB25002EB562 /* Intent.intentdefinition in Sources */, + F306DBDD2AE18F5800F0AE27 /* NCMediaCell.swift in Sources */, F74B6D952A7E239A00F03C5F /* NCManageDatabase+Chunk.swift in Sources */, F702F2F725EE5CED008F8E80 /* NCLogin.swift in Sources */, F7E98C1627E0D0FC001F9F19 /* NCManageDatabase+Video.swift in Sources */, @@ -3759,11 +3822,13 @@ F765F73125237E3F00391DBE /* NCRecent.swift in Sources */, F76B3CCE1EAE01BD00921AC9 /* NCBrand.swift in Sources */, F359D8672A7D03420023F405 /* NCUtility+Exif.swift in Sources */, + F3DE93E92AD93CA000F44D31 /* NCMediaScrollView.swift in Sources */, F7581D2425EFDDDF004DC699 /* NCMedia+Menu.swift in Sources */, F738D4902756740100CD1D38 /* NCLoginNavigationController.swift in Sources */, F77B0E981D118A16002130FE /* CCManageAccount.m in Sources */, F769CA192966EA3C00039397 /* ComponentView.swift in Sources */, AF93474C27E34120002537EE /* NCUtility+Image.swift in Sources */, + F306DBD32AE18F1D00F0AE27 /* NCMediaUIKitWrapper.swift in Sources */, F702F30125EE5D2C008F8E80 /* NYMnemonic.m in Sources */, AF93474E27E3F212002537EE /* NCShareNewUserAddComment.swift in Sources */, F7C30DFD291BD0B80017149B /* NCNetworkingE2EEDelete.swift in Sources */, @@ -3775,6 +3840,7 @@ F79B869B265E19D40085C0E0 /* NSMutableAttributedString+Extension.swift in Sources */, F7B7504B2397D38F004E13EC /* UIImage+Extension.swift in Sources */, F7EFC0CD256BF8DD00461AAD /* NCUserStatus.swift in Sources */, + F306DBD62AE18F4B00F0AE27 /* NCMediaNew.swift in Sources */, AF3FDCC22796ECC300710F60 /* NCTrash+CollectionView.swift in Sources */, F70D7C3725FFBF82002B9E34 /* NCCollectionViewCommon.swift in Sources */, F76D364628A4F8BF00214537 /* NCActivityIndicator.swift in Sources */, @@ -3782,6 +3848,7 @@ F7134186259747BA00768D21 /* NCPushNotification.m in Sources */, F3BB464F2A39EBE500461F6E /* NCMoreUserCell.swift in Sources */, F726EEEC1FED1C820030B9C8 /* NCEndToEndInitialize.swift in Sources */, + F306DBCE2AE18F1D00F0AE27 /* NCMediaCell.swift in Sources */, F79A65C62191D95E00FF6DCC /* NCSelect.swift in Sources */, F75D19E325EFE09000D74598 /* NCTrash+Menu.swift in Sources */, F7FC5EE12A1768D700D921F5 /* NCCapabilitiesView.swift in Sources */, @@ -3790,6 +3857,7 @@ F77BC3ED293E528A005F2B08 /* NCConfigServer.swift in Sources */, F7A560422AE1593700BE8FD6 /* NCOperationSaveLivePhoto.swift in Sources */, F70753EB2542A99800972D44 /* NCViewerMediaPage.swift in Sources */, + F306DBDE2AE18F5800F0AE27 /* NCGridMediaCell.swift in Sources */, F7817CF829801A3500FFBC65 /* Data+Extension.swift in Sources */, F749B651297B0F2400087535 /* NCManageDatabase+Avatar.swift in Sources */, F7FAFD3A28BFA948000777FE /* NCNotification+Menu.swift in Sources */, @@ -3799,6 +3867,7 @@ F707C26521A2DC5200F6181E /* NCStoreReview.swift in Sources */, F7BAADCB1ED5A87C00B7EAD4 /* NCManageDatabase.swift in Sources */, F77C97392953131000FDDD09 /* NCCameraRoll.swift in Sources */, + F306DBD12AE18F1D00F0AE27 /* NCMediaRowViewModel.swift in Sources */, F343A4B32A1E01FF00DDA874 /* PHAsset+Extension.swift in Sources */, F70968A424212C4E00ED60E5 /* NCLivePhoto.swift in Sources */, F7C30DFA291BCF790017149B /* NCNetworkingE2EECreateFolder.swift in Sources */, @@ -3820,6 +3889,7 @@ F70CEF5623E9C7E50007035B /* UIColor+Extension.swift in Sources */, F75CA1472962F13700B01130 /* HUDView.swift in Sources */, F7A48413297022E000BD1B49 /* ViewerQuickLook.swift in Sources */, + F306DBCF2AE18F1D00F0AE27 /* NCGridMediaCell.swift in Sources */, F77BB748289985270090FC19 /* UITabBarController+Extension.swift in Sources */, F763D29D2A249C4500A3C901 /* NCManageDatabase+Capabilities.swift in Sources */, F75AC2431F1F62450073EC19 /* NCManageAutoUploadFileName.swift in Sources */, @@ -4930,6 +5000,30 @@ version = 1.4.0; }; }; + F3271B8B2AD43AAE009993C3 /* XCRemoteSwiftPackageReference "LRUCache" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/nicklockwood/LRUCache.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.0.4; + }; + }; + F3718CC02ABD9A76009BC4C2 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/siteline/SwiftUI-Introspect"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.0.0; + }; + }; + F3EFBF5D2AB20B9100B5724C /* XCRemoteSwiftPackageReference "SwiftUI-Shimmer" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/markiv/SwiftUI-Shimmer.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.4.0; + }; + }; F70B86732642CE3B00ED5349 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/firebase/firebase-ios-sdk"; @@ -5145,6 +5239,11 @@ package = F76DA964277B76F10082465B /* XCRemoteSwiftPackageReference "UICKeyChainStore" */; productName = UICKeyChainStore; }; + F3077B7B2ABDA06A0013BA13 /* SwiftUIIntrospect */ = { + isa = XCSwiftPackageProductDependency; + package = F3718CC02ABD9A76009BC4C2 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */; + productName = SwiftUIIntrospect; + }; F30A96332A2DFCD000D7BCFE /* Realm */ = { isa = XCSwiftPackageProductDependency; package = F710FC78277B7CFF00AA9FBF /* XCRemoteSwiftPackageReference "realm-swift" */; @@ -5230,6 +5329,16 @@ package = F31F69672A2F92F000162F76 /* XCRemoteSwiftPackageReference "SnapshotTestingHEIC" */; productName = SnapshotTestingHEIC; }; + F3271B8C2AD43AAE009993C3 /* LRUCache */ = { + isa = XCSwiftPackageProductDependency; + package = F3271B8B2AD43AAE009993C3 /* XCRemoteSwiftPackageReference "LRUCache" */; + productName = LRUCache; + }; + F3EFBF5E2AB2100E00B5724C /* Shimmer */ = { + isa = XCSwiftPackageProductDependency; + package = F3EFBF5D2AB20B9100B5724C /* XCRemoteSwiftPackageReference "SwiftUI-Shimmer" */; + productName = Shimmer; + }; F70716F829881CFA00E72C1D /* UICKeyChainStore */ = { isa = XCSwiftPackageProductDependency; package = F76DA964277B76F10082465B /* XCRemoteSwiftPackageReference "UICKeyChainStore" */; diff --git a/Tests/NextcloudSnapshotTests/Extensions/SwiftUIView+Extensions.swift b/Tests/NextcloudSnapshotTests/Extensions/SwiftUIView+Extensions.swift index b6319a3e4f..32dda872fa 100644 --- a/Tests/NextcloudSnapshotTests/Extensions/SwiftUIView+Extensions.swift +++ b/Tests/NextcloudSnapshotTests/Extensions/SwiftUIView+Extensions.swift @@ -37,6 +37,24 @@ struct DeviceOrientationViewModifier: ViewModifier { } } +struct ViewDidFirstAppearModifier: ViewModifier { + @State private var didLoad = false + private let action: (() -> Void)? + + init(perform action: (() -> Void)? = nil) { + self.action = action + } + + func body(content: Content) -> some View { + content.onAppear { + if didLoad == false { + didLoad = true + action?() + } + } + } +} + extension SwiftUI.View { func toVC() -> UIViewController { let vc = UIHostingController (rootView: self) @@ -47,4 +65,8 @@ extension SwiftUI.View { func onRotate(perform action: @escaping (UIDeviceOrientation) -> Void) -> some View { self.modifier(DeviceOrientationViewModifier(action: action)) } + + func onFirstAppear(perform action: (() -> Void)? = nil) -> some View { + modifier(ViewDidFirstAppearModifier(perform: action)) + } } diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift index 8d1ccf700a..1657a774b8 100644 --- a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift @@ -1019,7 +1019,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS CCUtility.isEnd(toEndEnabled: self.appDelegate.account), !NCNetworkingE2EE.shared.isInUpload(account: self.appDelegate.account, serverUrl: self.serverUrl) { let lock = NCManageDatabase.shared.getE2ETokenLock(account: self.appDelegate.account, serverUrl: self.serverUrl) - NextcloudKit.shared.getE2EEMetadata(fileId: metadataFolder.ocId, e2eToken: lock?.e2eToken, route: NCNetworkingE2EE.shared.getRoute()) { _, e2eMetadata, signature, _, error in + NextcloudKit.shared.getE2EEMetadata(fileId: metadataFolder.ocId, e2eToken: lock?.e2eToken) { _, e2eMetadata, signature, _, error in if error == .success, let e2eMetadata = e2eMetadata { let error = NCEndToEndMetadata().decodeMetadata(e2eMetadata, signature: signature, serverUrl: self.serverUrl, account: self.appDelegate.account, urlBase: self.appDelegate.urlBase, userId: self.appDelegate.userId) if error == .success { diff --git a/iOSClient/Media/Cell/NCMediaCell.swift b/iOSClient/Media/Cell/NCMediaCell.swift index a54da587b3..1bce39099b 100644 --- a/iOSClient/Media/Cell/NCMediaCell.swift +++ b/iOSClient/Media/Cell/NCMediaCell.swift @@ -7,7 +7,6 @@ // import SwiftUI -import VisibilityTrackingScrollView import Shimmer import NextcloudKit @@ -30,7 +29,6 @@ struct NCMediaCell: View { var body: some View { let image = Image(uiImage: thumbnail.image) .resizable() - .trackVisibility(id: CCUtility.getTitleSectionDate(thumbnail.metadata.date as Date) ?? "") ZStack(alignment: .center) { if thumbnail.isPlaceholderImage { @@ -136,7 +134,7 @@ struct NCMediaCell: View { struct NCMediaLoadingCell: View { let itemsInRow: Int let metadata: tableMetadata - let geometryProxy: GeometryProxy + let rowSize: CGFloat let spacing: CGFloat let gradient = Gradient(colors: [ @@ -146,14 +144,24 @@ struct NCMediaLoadingCell: View { ]) var body: some View { - ZStack { - Image(uiImage: UIImage()) - .resizable() - .trackVisibility(id: CCUtility.getTitleSectionDate(metadata.date as Date) ?? "")// TODO: Fix spacing - .aspectRatio(1.5, contentMode: .fit) - .frame(width: (geometryProxy.size.width - spacing) / CGFloat(itemsInRow)) - .redacted(reason: .placeholder) - .shimmering(gradient: gradient, bandSize: 0.7) - } +// let _ = Self._printChanges() + + Image(uiImage: UIImage()) + .resizable() +// .background(Color.random) + .aspectRatio(1.5, contentMode: .fit) + .frame(width: (UIScreen.main.bounds.width - spacing) / CGFloat(itemsInRow)) + .redacted(reason: .placeholder) + .shimmering(gradient: gradient, bandSize: 0.7) + } +} + +extension Color { + static var random: Color { + return Color( + red: .random(in: 0...1), + green: .random(in: 0...1), + blue: .random(in: 0...1) + ) } } diff --git a/iOSClient/Media/NCMediaCache.swift b/iOSClient/Media/NCMediaCache.swift index 4557ec201f..861c246d69 100644 --- a/iOSClient/Media/NCMediaCache.swift +++ b/iOSClient/Media/NCMediaCache.swift @@ -2,8 +2,23 @@ // NCMediaCache.swift // Nextcloud // -// Created by Milen on 10.10.23. -// Copyright © 2023 Marino Faggiana. All rights reserved. +// Created by Marino Faggiana on 18/10/23. +// Copyright © 2021 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 UIKit @@ -17,10 +32,13 @@ import NextcloudKit return instance }() + let limit: Int = 2000 private typealias ThumbnailLRUCache = LRUCache - private let cache: ThumbnailLRUCache = ThumbnailLRUCache(countLimit: 2000) + private lazy var cache: ThumbnailLRUCache = { + return ThumbnailLRUCache(countLimit: limit) + }() - @objc func createCache(account: String) { + func createCache(account: String) { let resultsMedia = NCManageDatabase.shared.getMediaOcIdEtag(account: account) guard !resultsMedia.isEmpty, @@ -35,11 +53,8 @@ import NextcloudKit var date: Date } var files: [FileInfo] = [] - let startDate = Date() - NextcloudKit.shared.nkCommonInstance.writeLog("--------- start ThumbnailLRUCache image process ---------") - // Get files only image / video if let enumerator = manager.enumerator(at: URL(fileURLWithPath: directory), includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles]) { for case let fileURL as URL in enumerator where fileURL.lastPathComponent.hasSuffix(ext) { let fileName = fileURL.lastPathComponent @@ -54,16 +69,17 @@ import NextcloudKit } } - // Sort for most recent files.sort(by: { $0.date > $1.date }) if let firstDate = files.first?.date, let lastDate = files.last?.date { print("First date: \(firstDate)") print("Last date: \(lastDate)") } - // Insert in cache cache.removeAllValues() + var counter: Int = 0 for file in files { + counter += 1 + if counter > limit { break } autoreleasepool { if let image = UIImage(contentsOfFile: file.path.path) { cache.setValue(image, forKey: file.ocId) @@ -73,23 +89,21 @@ import NextcloudKit let endDate = Date() let diffDate = endDate.timeIntervalSinceReferenceDate - startDate.timeIntervalSinceReferenceDate + NextcloudKit.shared.nkCommonInstance.writeLog("--------- ThumbnailLRUCache image process ---------") NextcloudKit.shared.nkCommonInstance.writeLog("Counter process: \(cache.count)") NextcloudKit.shared.nkCommonInstance.writeLog("Time process: \(diffDate)") - NextcloudKit.shared.nkCommonInstance.writeLog("--------- stop ThumbnailLRUCache image process ---------") + NextcloudKit.shared.nkCommonInstance.writeLog("--------- ThumbnailLRUCache image process ---------") } func getImage(ocId: String) -> UIImage? { - return cache.value(forKey: ocId) } func setImage(ocId: String, image: UIImage) { - cache.setValue(image, forKey: ocId) } @objc func clearCache() { - cache.removeAllValues() } } diff --git a/iOSClient/Media/NCMediaNew.swift b/iOSClient/Media/NCMediaNew.swift index 888c0c2737..1edf5c1c20 100644 --- a/iOSClient/Media/NCMediaNew.swift +++ b/iOSClient/Media/NCMediaNew.swift @@ -9,19 +9,47 @@ import SwiftUI import PreviewSnapshots import NextcloudKit -import VisibilityTrackingScrollView +import Combine @_spi(Advanced) import SwiftUIIntrospect +//struct Test: View { +// var metadatas: [[tableMetadata]] +// @EnvironmentObject var vm: NCMediaViewModel +// @EnvironmentObject var parent: NCMediaUIKitWrapper +// @State var isInSelectMode = true +// @Binding var columnCountStages: [Int] +// @Binding var columnCountStagesIndex: Int +// @State var title: String = "" +// internal let cache = UIImageLRUCache(countLimit: 1000) +// +// var body: some View { +// let _ = Self._printChanges() +// +// ScrollView { +// LazyVStack(alignment: .leading, spacing: 2) { +// ForEach(metadatas, id: \.self) { rowMetadatas in +// Color.random.frame(width: 100, height: 100) +// } +// .background(GeometryReader { geometry in +// Color.clear +// .preference(key: ScrollOffsetPreferenceKey.self, value: geometry.frame(in: .named("scroll")).origin) +// }) +// } +// } +// .coordinateSpace(name: "scroll") +// } +//} + struct NCMediaNew: View { @StateObject private var vm = NCMediaViewModel() - @EnvironmentObject var parent: NCMediaUIKitWrapper + @EnvironmentObject private var parent: NCMediaUIKitWrapper @State private var title = "Media" @State private var isScrolledToTop = true @State private var tappedMetadata = tableMetadata() - @State var titleColor = Color.primary - @State var toolbarItemsColor = Color.blue - @State var toolbarColors = [Color.clear] + @State private var titleColor = Color.primary + @State private var toolbarItemsColor = Color.blue + @State private var toolbarColors = [Color.clear] @State private var showDeleteConfirmation = false @State private var showPlayFromURLAlert = false @@ -31,174 +59,127 @@ struct NCMediaNew: View { @State private var columnCountStagesIndex = 0 @State private var columnCountChanged = false - var body: some View { - GeometryReader { outerProxy in - ZStack(alignment: .top) { - VisibilityTrackingScrollView(action: cellVisibilityDidChange) { - LazyVStack(alignment: .leading, spacing: 2) { - ForEach(vm.metadatas.chunked(into: columnCountStages[columnCountStagesIndex]), id: \.self) { rowMetadatas in - NCMediaRow(metadatas: rowMetadatas, geometryProxy: outerProxy, isInSelectMode: $vm.isInSelectMode) { tappedThumbnail, isSelected in - - //TODO: Put in VM - if vm.isInSelectMode, isSelected { - vm.selectedMetadatas.append(tappedThumbnail.metadata) - } else { - vm.selectedMetadatas.removeAll(where: { $0.ocId == tappedThumbnail.metadata.ocId }) - } + @State private var selectedMetadatas: [tableMetadata] = [] + @State private var isInSelectMode = false - if !vm.isInSelectMode { - let selectedMetadata = tappedThumbnail.metadata - vm.onCellTapped(metadata: selectedMetadata) - NCViewer.shared.view(viewController: parent, metadata: selectedMetadata, metadatas: vm.metadatas, imageIcon: tappedThumbnail.image) - } - } onCellContextMenuItemSelected: { thumbnail, selection in - let selectedMetadata = thumbnail.metadata - - switch selection { - case .addToFavorites: - vm.addToFavorites(metadata: selectedMetadata) - case .details: - NCActionCenter.shared.openShare(viewController: parent, metadata: selectedMetadata, page: .activity) - case .openIn: - vm.openIn(metadata: selectedMetadata) - case .saveToPhotos: - vm.saveToPhotos(metadata: selectedMetadata) - case .viewInFolder: - vm.viewInFolder(metadata: selectedMetadata) - case .modify: - vm.modify(metadata: selectedMetadata) - case .delete: - vm.delete(metadatas: selectedMetadata) - } - } - - if vm.needsLoadingMoreItems { - ProgressView() - .frame(maxWidth: .infinity) - .onAppear { vm.loadMoreItems() } - .padding(.top, 10) - } - } - } - .padding(.top, 70) - .padding(.bottom, 40) - .background(GeometryReader { geometry in - Color.clear - .preference(key: ScrollOffsetPreferenceKey.self, value: geometry.frame(in: .named("scroll")).origin) - }) - .onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in - let isScrolledToTop = value.y >= -10 + @State var offsetPublisherSubscription: AnyCancellable? - withAnimation(.default) { - titleColor = isScrolledToTop ? Color.primary : .white - toolbarItemsColor = isScrolledToTop ? .blue : .white - toolbarColors = isScrolledToTop ? [.clear] : [.black.opacity(0.8), .black.opacity(0.0)] - } - } - } - .refreshable { - await vm.onPullToRefresh() - } - // Not possible to move the refresh control view via SwiftUI, so we have to introspect the internal UIKit views to move it. - // TODO: Maybe .contespontMargins() will resolve this but it's iOS 17+ + var body: some View { + ZStack(alignment: .top) { + NCMediaScrollView(metadatas: vm.metadatas.chunked(into: columnCountStages[columnCountStagesIndex]), isInSelectMode: $isInSelectMode, selectedMetadatas: $selectedMetadatas, columnCountStages: $columnCountStages, columnCountStagesIndex: $columnCountStagesIndex, title: $title) + .equatable() + .ignoresSafeArea(.all, edges: .horizontal) + // MediaScrollView(metadatas: vm.metadatas.chunked(into: columnCountStages[columnCountStagesIndex]), proxy: geometry, vm: $columnCountStages, parent: $columnCountStagesIndex, isInSelectMode: $isScrolledToTop, selectedMetadatas: $selectedMetadatas, isInSelectMode: $isInSelectMode) + // Test(metadatas: vm.metadatas.chunked(into: columnCountStages[columnCountStagesIndex]), columnCountStages: $columnCountStages, columnCountStagesIndex: $columnCountStagesIndex) + .environmentObject(vm) + // .environmentObject(parent) + // .onPreferenceChange(TitlePreferenceKey.self) { value in + // title = value + // } .introspect(.scrollView, on: .iOS(.v15...)) { scrollView in scrollView.refreshControl?.translatesAutoresizingMaskIntoConstraints = false scrollView.refreshControl?.topAnchor.constraint(equalTo: scrollView.superview!.topAnchor, constant: 120).isActive = true scrollView.refreshControl?.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true + + if offsetPublisherSubscription == nil { + offsetPublisherSubscription = scrollView.publisher(for: \.contentOffset) + .sink { offset in + isScrolledToTop = offset.y <= 0 + } + } } - .coordinateSpace(name: "scroll") - - // Toolbar - - HStack(content: { - HStack { - Text(title) - .font(.system(size: 20, weight: .bold)) - .foregroundStyle(titleColor) - - Spacer() - - Button(action: { - vm.isInSelectMode.toggle() - }, label: { - Text(NSLocalizedString(vm.isInSelectMode ? "_cancel_" : "_select_", comment: "")).font(.system(size: 14)) - .foregroundStyle(toolbarItemsColor) - }) - .padding(.horizontal, 6) - .padding(.vertical, 3) - .background(.ultraThinMaterial) - .cornerRadius(.infinity) - - if vm.isInSelectMode, !vm.selectedMetadatas.isEmpty { - ToolbarCircularButton(imageSystemName: "trash.fill", color: .red) - .onTapGesture { - showDeleteConfirmation = true - } - .confirmationDialog("", isPresented: $showDeleteConfirmation) { - Button(NSLocalizedString("_delete_selected_media_", comment: ""), role: .destructive) { - vm.deleteSelectedMetadata() - } + + HStack(content: { + HStack { + Text(title) + .font(.system(size: 20, weight: .bold)) + .foregroundStyle(titleColor) + + Spacer() + + Button(action: { + isInSelectMode.toggle() + }, label: { + Text(NSLocalizedString(isInSelectMode ? "_cancel_" : "_select_", comment: "")).font(.system(size: 14)) + .foregroundStyle(toolbarItemsColor) + }) + .padding(.horizontal, 6) + .padding(.vertical, 3) + .background(.ultraThinMaterial) + .cornerRadius(.infinity) + + if isInSelectMode, !selectedMetadatas.isEmpty { + ToolbarCircularButton(imageSystemName: "trash.fill", color: .red) + .onTapGesture { + showDeleteConfirmation = true + } + .confirmationDialog("", isPresented: $showDeleteConfirmation) { + Button(NSLocalizedString("_delete_selected_media_", comment: ""), role: .destructive) { + vm.deleteMetadata(metadatas: selectedMetadatas) + cancelSelection() } - } + } + } - Menu { - if vm.isInSelectMode, !vm.selectedMetadatas.isEmpty { - Section { - Button { - vm.copyOrMoveSelectedMetadataInApp() - } label: { - Label(NSLocalizedString("_move_selected_files_", comment: ""), systemImage: "arrow.up.right.square") - } + Menu { + if isInSelectMode, !selectedMetadatas.isEmpty { + Section { + Button { + vm.copyOrMoveMetadataInApp(metadatas: selectedMetadatas) + cancelSelection() + } label: { + Label(NSLocalizedString("_move_selected_files_", comment: ""), systemImage: "arrow.up.right.square") + } - Button { - vm.copySelectedMetadata() - } label: { - Label(NSLocalizedString("_copy_file_", comment: ""), systemImage: "doc.on.doc") - } + Button { + vm.copyMetadata(metadatas: selectedMetadatas) + cancelSelection() + } label: { + Label(NSLocalizedString("_copy_file_", comment: ""), systemImage: "doc.on.doc") } - } else { - Section { - Picker(NSLocalizedString("_media_view_options_", comment: ""), selection: $vm.filter) { - Label(NSLocalizedString("_media_viewimage_show_", comment: ""), systemImage: "photo.fill").tag(Filter.onlyPhotos) + } + } else { + Section { + Picker(NSLocalizedString("_media_view_options_", comment: ""), selection: $vm.filter) { + Label(NSLocalizedString("_media_viewimage_show_", comment: ""), systemImage: "photo.fill").tag(Filter.onlyPhotos) - Label(NSLocalizedString("_media_viewvideo_show_", comment: ""), systemImage: "video.fill").tag(Filter.onlyVideos) + Label(NSLocalizedString("_media_viewvideo_show_", comment: ""), systemImage: "video.fill").tag(Filter.onlyVideos) - Text(NSLocalizedString("_media_show_all_", comment: "")).tag(Filter.all) - }.pickerStyle(.menu) + Text(NSLocalizedString("_media_show_all_", comment: "")).tag(Filter.all) + }.pickerStyle(.menu) - Button { - selectMediaFolder() - } label: { - Label(NSLocalizedString("_select_media_folder_", comment: ""), systemImage: "folder") - } + Button { + selectMediaFolder() + } label: { + Label(NSLocalizedString("_select_media_folder_", comment: ""), systemImage: "folder") } + } - Section { - Button(action: { - if let tabBarController = vm.appDelegate?.window?.rootViewController as? UITabBarController { - NCDocumentPickerViewController(tabBarController: tabBarController, isViewerMedia: true, allowsMultipleSelection: false, viewController: parent) - } - }, label: { - Label(NSLocalizedString("_play_from_files_", comment: ""), systemImage: "play.circle") - }) - - Button(action: { - showPlayFromURLAlert = true - }, label: { - Label(NSLocalizedString("_play_from_url_", comment: ""), systemImage: "link") - }) - } + Section { + Button(action: { + if let tabBarController = vm.appDelegate?.window?.rootViewController as? UITabBarController { + NCDocumentPickerViewController(tabBarController: tabBarController, isViewerMedia: true, allowsMultipleSelection: false, viewController: parent) + } + }, label: { + Label(NSLocalizedString("_play_from_files_", comment: ""), systemImage: "play.circle") + }) + + Button(action: { + showPlayFromURLAlert = true + }, label: { + Label(NSLocalizedString("_play_from_url_", comment: ""), systemImage: "link") + }) } - } label: { - ToolbarCircularButton(imageSystemName: "ellipsis", color: $toolbarItemsColor) } + } label: { + ToolbarCircularButton(imageSystemName: "ellipsis", color: $toolbarItemsColor) } - }) - .frame(maxWidth: .infinity) - .padding([.horizontal, .top], 10) - .padding(.bottom, 20) - .background(LinearGradient(gradient: Gradient(colors: toolbarColors), startPoint: .top, endPoint: .bottom).edgesIgnoringSafeArea(.top)) - } + } + }) + .frame(maxWidth: .infinity) + .padding([.horizontal, .top], 10) + .padding(.bottom, 20) + .background(LinearGradient(gradient: Gradient(colors: toolbarColors), startPoint: .top, endPoint: .bottom).ignoresSafeArea(.all, edges: [.top, .horizontal])) } .onRotate { orientation in if orientation.isLandscapeHardCheck { @@ -207,13 +188,24 @@ struct NCMediaNew: View { columnCountStages = [2, 3, 4] } } + // TODO: 1. Here we load from DB first .onAppear { vm.loadMediaFromDB() } - .onChange(of: vm.isInSelectMode) { newValue in - if newValue == false { vm.selectedMetadatas.removeAll() } + .onChange(of: isInSelectMode) { newValue in + if newValue == false { selectedMetadatas.removeAll() } + } + .onChange(of: vm.filter) { _ in + cancelSelection() } .onChange(of: columnCountStagesIndex) { _ in columnCountChanged = true } + .onChange(of: isScrolledToTop) { value in + withAnimation(.default) { + titleColor = value ? Color.primary : .white + toolbarItemsColor = value ? .blue : .white + toolbarColors = value ? [.clear] : [.black.opacity(0.8), .black.opacity(0.0)] + } + } .alert("", isPresented: $showPlayFromURLAlert) { TextField("https://...", text: $playFromUrlString) .keyboardType(.URL) @@ -229,7 +221,6 @@ struct NCMediaNew: View { .gesture( MagnificationGesture(minimumScaleDelta: 0) .onChanged { scale in - print(scale) if !columnCountChanged { let newZoom = Double(columnCountStages[columnCountStagesIndex]) * 1 / scale let newZoomIndex = findClosestZoomIndex(value: newZoom) @@ -242,15 +233,7 @@ struct NCMediaNew: View { ) } - private func cellVisibilityDidChange(_ id: String, change: VisibilityChange, tracker: VisibilityTracker) { - DispatchQueue.main.async { - if let date = tracker.topVisibleView, !date.isEmpty { - title = date - } - } - } - - func findClosestZoomIndex(value: Double) -> Int { + private func findClosestZoomIndex(value: Double) -> Int { let distanceArray = columnCountStages.map { abs(Double($0) - value) } // absolute difference between zoom stages and actual pinch zoom return distanceArray.indices.min(by: {distanceArray[$0] < distanceArray[$1]}) ?? 0 // return index of element that is "closest" } @@ -271,6 +254,11 @@ struct NCMediaNew: View { guard let metadata = vm.getMetadataFromUrl(playFromUrlString) else { return } NCViewer.shared.view(viewController: parent, metadata: metadata, metadatas: [metadata], imageIcon: nil) } + + private func cancelSelection() { + isInSelectMode = false + selectedMetadatas.removeAll() + } } struct ToolbarCircularButton: View { diff --git a/iOSClient/Media/NCMediaRow.swift b/iOSClient/Media/NCMediaRow.swift index 9372747ff1..14454d256b 100644 --- a/iOSClient/Media/NCMediaRow.swift +++ b/iOSClient/Media/NCMediaRow.swift @@ -8,11 +8,15 @@ import SwiftUI import PreviewSnapshots -import VisibilityTrackingScrollView +import Queuer + +struct NCMediaRow: View, Equatable { + static func == (lhs: NCMediaRow, rhs: NCMediaRow) -> Bool { + return lhs.metadatas == rhs.metadatas + } -struct NCMediaRow: View { let metadatas: [tableMetadata] - let geometryProxy: GeometryProxy + @Binding var isInSelectMode: Bool let onCellSelected: (ScaledThumbnail, Bool) -> Void let onCellContextMenuItemSelected: (ScaledThumbnail, ContextMenuSelection) -> Void @@ -20,20 +24,29 @@ struct NCMediaRow: View { private let spacing: CGFloat = 2 var body: some View { + let _ = Self._printChanges() + HStack(spacing: spacing) { if vm.rowData.scaledThumbnails.isEmpty { - ForEach(metadatas, id: \.self) { metadata in - NCMediaLoadingCell(itemsInRow: metadatas.count, metadata: metadata, geometryProxy: geometryProxy, spacing: spacing) + ForEach(metadatas, id: \.ocId) { metadata in + NCMediaLoadingCell(itemsInRow: metadatas.count, metadata: metadata, rowSize: UIScreen.main.bounds.width, spacing: spacing) } } else { - ForEach(vm.rowData.scaledThumbnails, id: \.self) { thumbnail in + ForEach(vm.rowData.scaledThumbnails, id: \.metadata.ocId) { thumbnail in NCMediaCell(thumbnail: thumbnail, shrinkRatio: vm.rowData.shrinkRatio, isInSelectMode: $isInSelectMode, onSelected: onCellSelected, onContextMenuItemSelected: onCellContextMenuItemSelected, isFavorite: thumbnail.metadata.favorite) } } } - .onAppear { + .onFirstAppear { + vm.configure(metadatas: metadatas) + vm.downloadThumbnails(rowWidth: UIScreen.main.bounds.width, spacing: spacing) + } + .onDisappear { + vm.cancelDownloadingThumbnails() + } + .onRotate { _ in vm.configure(metadatas: metadatas) - vm.downloadThumbnails(rowWidth: geometryProxy.size.width, spacing: spacing) + vm.downloadThumbnails(rowWidth: UIScreen.main.bounds.width, spacing: spacing) } } } diff --git a/iOSClient/Media/NCMediaRowViewModel.swift b/iOSClient/Media/NCMediaRowViewModel.swift index d604d1da63..ee8671a1bc 100644 --- a/iOSClient/Media/NCMediaRowViewModel.swift +++ b/iOSClient/Media/NCMediaRowViewModel.swift @@ -8,6 +8,7 @@ import Foundation import NextcloudKit +import Queuer struct RowData { var scaledThumbnails: [ScaledThumbnail] = [] @@ -21,7 +22,7 @@ struct ScaledThumbnail: Hashable { let metadata: tableMetadata func hash(into hasher: inout Hasher) { - hasher.combine(image) + hasher.combine(metadata.ocId) } } @@ -30,6 +31,13 @@ struct ScaledThumbnail: Hashable { private var metadatas: [tableMetadata] = [] + internal let cache = NCMediaCache.shared + +// internal lazy var cache = manager.cache +// internal lazy var thumbnailsQueue = manager.queuer + + var operations: [ConcurrentOperation] = [] + func configure(metadatas: [tableMetadata]) { self.metadatas = metadatas } @@ -37,23 +45,24 @@ struct ScaledThumbnail: Hashable { func downloadThumbnails(rowWidth: CGFloat, spacing: CGFloat) { var thumbnails: [ScaledThumbnail] = [] - metadatas.enumerated().forEach { index, metadata in - let thumbnailPath = CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag) + metadatas.forEach { metadata in + if let cachedImage = cache.getImage(ocId: metadata.ocId) { + let thumbnail = ScaledThumbnail(image: cachedImage, metadata: metadata) + thumbnails.append(thumbnail) - if let thumbnailPath, FileManager.default.fileExists(atPath: thumbnailPath) { + DispatchQueue.main.async { + self.calculateShrinkRatio(thumbnails: &thumbnails, rowWidth: rowWidth, spacing: spacing) + } + } else if let thumbnailPath = CCUtility.getDirectoryProviderStorageIconOcId(metadata.ocId, etag: metadata.etag), FileManager.default.fileExists(atPath: thumbnailPath) { // Load thumbnail from file if let image = UIImage(contentsOfFile: thumbnailPath) { - thumbnails.append(ScaledThumbnail(image: image, metadata: metadata)) - - if thumbnails.count == self.metadatas.count { - thumbnails.enumerated().forEach { index, thumbnail in - thumbnails[index].scaledSize = getScaledThumbnailSize(of: thumbnail, thumbnailsInRow: thumbnails) - } - - let shrinkRatio = getShrinkRatio(thumbnailsInRow: thumbnails, fullWidth: rowWidth, spacing: spacing) + let thumbnail = ScaledThumbnail(image: image, metadata: metadata) + cache.setImage(ocId: metadata.ocId, image: image) +// cache.setValue(thumbnail, forKey: metadata.ocId) + thumbnails.append(thumbnail) - rowData.scaledThumbnails = thumbnails - rowData.shrinkRatio = shrinkRatio + DispatchQueue.main.async { + self.calculateShrinkRatio(thumbnails: &thumbnails, rowWidth: rowWidth, spacing: spacing) } } } else { @@ -67,41 +76,61 @@ struct ScaledThumbnail: Hashable { } let options = NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue) - NextcloudKit.shared.downloadPreview( - fileNamePathOrFileId: fileNamePath, - fileNamePreviewLocalPath: fileNamePreviewLocalPath, - widthPreview: Int(UIScreen.main.bounds.width) / 2, - heightPreview: Int(UIScreen.main.bounds.height) / 2, - fileNameIconLocalPath: fileNameIconLocalPath, - sizeIcon: NCGlobal.shared.sizeIcon, - etag: etagResource, - options: options) { _, _, imageIcon, _, etag, error in - print(metadata.isVideo.description + " " + metadata.fileName) - if error == .success, let image = imageIcon { +// let concurrentOperation = ConcurrentOperation { _ in + NextcloudKit.shared.downloadPreview( + fileNamePathOrFileId: fileNamePath, + fileNamePreviewLocalPath: fileNamePreviewLocalPath, + widthPreview: Int(UIScreen.main.bounds.width) / 2, + heightPreview: Int(UIScreen.main.bounds.height) / 2, + fileNameIconLocalPath: fileNameIconLocalPath, + sizeIcon: NCGlobal.shared.sizeIcon, + etag: etagResource, + options: options) { _, _, imageIcon, _, etag, error in NCManageDatabase.shared.setMetadataEtagResource(ocId: metadata.ocId, etagResource: etag) - thumbnails.append(ScaledThumbnail(image: image, metadata: metadata)) - } else { - thumbnails.append(ScaledThumbnail(image: UIImage(systemName: metadata.isVideo ? "video.fill" : "photo.fill")!.withRenderingMode(.alwaysTemplate), isPlaceholderImage: true, metadata: metadata)) - } - DispatchQueue.main.async { - if thumbnails.count == self.metadatas.count { - thumbnails.enumerated().forEach { index, thumbnail in - thumbnails[index].scaledSize = self.getScaledThumbnailSize(of: thumbnail, thumbnailsInRow: thumbnails) - } + let thumbnail: ScaledThumbnail + + if error == .success, let image = imageIcon { + thumbnail = ScaledThumbnail(image: image, metadata: metadata) + self.cache.setImage(ocId: metadata.ocId, image: image) + } else { + thumbnail = ScaledThumbnail(image: UIImage(systemName: metadata.isVideo ? "video.fill" : "photo.fill")!.withRenderingMode(.alwaysTemplate), isPlaceholderImage: true, metadata: metadata) + } - let shrinkRatio = self.getShrinkRatio(thumbnailsInRow: thumbnails, fullWidth: rowWidth, spacing: spacing) + thumbnails.append(thumbnail) +// self.cache.setValue(thumbnail, forKey: metadata.ocId) - self.rowData.scaledThumbnails = thumbnails - self.rowData.shrinkRatio = shrinkRatio + DispatchQueue.main.async { + self.calculateShrinkRatio(thumbnails: &thumbnails, rowWidth: rowWidth, spacing: spacing) } } - } +// } + +// operations.append(concurrentOperation) +// thumbnailsQueue.addOperation(concurrentOperation) + } + } + } + + private func calculateShrinkRatio(thumbnails: inout [ScaledThumbnail], rowWidth: CGFloat, spacing: CGFloat) { + if thumbnails.count == self.metadatas.count { + thumbnails.enumerated().forEach { index, thumbnail in + thumbnails[index].scaledSize = self.getScaledThumbnailSize(of: thumbnail, thumbnailsInRow: thumbnails) + } + + let shrinkRatio = self.getShrinkRatio(thumbnailsInRow: thumbnails, fullWidth: rowWidth, spacing: spacing) + + self.rowData.scaledThumbnails = thumbnails + self.rowData.shrinkRatio = shrinkRatio } } + + func cancelDownloadingThumbnails() { + operations.forEach {( $0.cancel() )} + operations.removeAll() } - func getScaledThumbnailSize(of thumbnail: ScaledThumbnail, thumbnailsInRow thumbnails: [ScaledThumbnail]) -> CGSize { + private func getScaledThumbnailSize(of thumbnail: ScaledThumbnail, thumbnailsInRow thumbnails: [ScaledThumbnail]) -> CGSize { let maxHeight = thumbnails.compactMap { CGFloat($0.image.size.height) }.max() ?? 0 let height = thumbnail.image.size.height @@ -114,7 +143,7 @@ struct ScaledThumbnail: Hashable { return .init(width: newWidth, height: newHeight) } - func getShrinkRatio(thumbnailsInRow thumbnails: [ScaledThumbnail], fullWidth: CGFloat, spacing: CGFloat) -> CGFloat { + private func getShrinkRatio(thumbnailsInRow thumbnails: [ScaledThumbnail], fullWidth: CGFloat, spacing: CGFloat) -> CGFloat { var newSummedWidth: CGFloat = 0 for thumbnail in thumbnails { diff --git a/iOSClient/Media/NCMediaScrollView.swift b/iOSClient/Media/NCMediaScrollView.swift new file mode 100644 index 0000000000..ace9946cbc --- /dev/null +++ b/iOSClient/Media/NCMediaScrollView.swift @@ -0,0 +1,120 @@ +// +// NCMediaScrollView.swift +// Nextcloud +// +// Created by Milen on 13.10.23. +// Copyright © 2023 Marino Faggiana. All rights reserved. +// + +import SwiftUI + +struct NCMediaScrollView: View, Equatable { + static func == (lhs: NCMediaScrollView, rhs: NCMediaScrollView) -> Bool { + return lhs.metadatas == rhs.metadatas + } + + var metadatas: [[tableMetadata]] + @EnvironmentObject var vm: NCMediaViewModel + @EnvironmentObject var parent: NCMediaUIKitWrapper + @Binding var isInSelectMode: Bool + @Binding var selectedMetadatas: [tableMetadata] + @Binding var columnCountStages: [Int] + @Binding var columnCountStagesIndex: Int + @Binding var title: String + + var body: some View { + let _ = Self._printChanges() + + List { + Spacer(minLength: 50).listRowSeparator(.hidden) + + // LazyVStack(alignment: .leading, spacing: 2) { + ForEach(metadatas, id: \.self) { rowMetadatas in + NCMediaRow(metadatas: rowMetadatas, isInSelectMode: $isInSelectMode) { tappedThumbnail, isSelected in + if isInSelectMode, isSelected { + selectedMetadatas.append(tappedThumbnail.metadata) + } else { + selectedMetadatas.removeAll(where: { $0.ocId == tappedThumbnail.metadata.ocId }) + } + + if !isInSelectMode { + let selectedMetadata = tappedThumbnail.metadata + vm.onCellTapped(metadata: selectedMetadata) + NCViewer.shared.view(viewController: parent, metadata: selectedMetadata, metadatas: vm.metadatas, imageIcon: tappedThumbnail.image) + } + } onCellContextMenuItemSelected: { thumbnail, selection in + let selectedMetadata = thumbnail.metadata + + switch selection { + case .addToFavorites: + vm.addToFavorites(metadata: selectedMetadata) + case .details: + NCActionCenter.shared.openShare(viewController: parent, metadata: selectedMetadata, page: .activity) + case .openIn: + vm.openIn(metadata: selectedMetadata) + case .saveToPhotos: + vm.saveToPhotos(metadata: selectedMetadata) + case .viewInFolder: + vm.viewInFolder(metadata: selectedMetadata) + case .modify: + vm.modify(metadata: selectedMetadata) + case .delete: + vm.delete(metadatas: selectedMetadata) + } + } + .equatable() + .onAppear { + // title = CCUtility.getTitleSectionDate(rowMetadatas.first?.date as? Date) ?? "" + } + .listRowSeparator(.hidden) + .listRowSpacing(0) + .listRowInsets(.init(top: 2, leading: 0, bottom: 0, trailing: 0)) + } + + // TODO: 3. Here we load old media (happens immediately since progress view appears in the beginning, should fix) + if vm.needsLoadingMoreItems { + ProgressView() + .frame(maxWidth: .infinity) + .onAppear { vm.loadMoreItems() } + .padding(.top, 10) + } + + Spacer(minLength: 40).listRowSeparator(.hidden) + }.background(GeometryReader { geometry in + Color.clear + .preference(key: ScrollOffsetPreferenceKey.self, value: geometry.frame(in: .named("scroll")).origin) + }) + .listStyle(.plain) + // .padding(.top, 70) + // .padding(.bottom, 40) + // } + .coordinateSpace(name: "scroll") + .refreshable { + await vm.onPullToRefresh() + } + // .onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in + // isScrolledToTop = value.y >= 40 + // } + // Not possible to move the refresh control view via SwiftUI, so we have to introspect the internal UIKit views to move it. + // TODO: Maybe .contentMargins() will resolve this but it's iOS 17+ + // .introspect(.scrollView, on: .iOS(.v15...)) { scrollView in + // scrollView.refreshControl?.translatesAutoresizingMaskIntoConstraints = false + // scrollView.refreshControl?.topAnchor.constraint(equalTo: scrollView.superview!.topAnchor, constant: 120).isActive = true + // scrollView.refreshControl?.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true + // + // if offsetPublisherSubscription == nil { + // offsetPublisherSubscription = scrollView.publisher(for: \.contentOffset) + // .sink { offset in + // isScrolledToTop = offset.y <= 10 + // + //// withAnimation(.easeInOut) { + //// titleColor = isScrolledToTop ? Color.primary : .white + //// toolbarItemsColor = isScrolledToTop ? .blue : .white + //// toolbarColors = isScrolledToTop ? [.clear] : [.black.opacity(0.8), .black.opacity(0.0)] + //// } + // } + // } + // } + // .preference(key: TitlePreferenceKey.self, value: title) + } +} diff --git a/iOSClient/Media/NCMediaViewModel.swift b/iOSClient/Media/NCMediaViewModel.swift index 149fd3f8d8..ce641e81f4 100644 --- a/iOSClient/Media/NCMediaViewModel.swift +++ b/iOSClient/Media/NCMediaViewModel.swift @@ -8,11 +8,10 @@ import NextcloudKit import Combine +import LRUCache @MainActor class NCMediaViewModel: ObservableObject { - @Published private(set) var metadatas: [tableMetadata] = [] - @Published internal var selectedMetadatas: [tableMetadata] = [] - @Published internal var isInSelectMode = false + @Published private(set) internal var metadatas: [tableMetadata] = [] private var account: String = "" private var lastContentOffsetY: CGFloat = 0 @@ -35,6 +34,8 @@ import Combine NotificationCenter.default.addObserver(self, selector: #selector(uploadedFile(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterUploadedFile), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(userChanged(_:)), name: NSNotification.Name(rawValue: NCGlobal.shared.notificationCenterChangeUser), object: nil) + // TODO: 2. Here we load from New media + Task { await loadNewMedia() } @@ -117,22 +118,22 @@ import Combine appDelegate?.activeServerUrl = metadata.serverUrl } - func deleteSelectedMetadata() { - let notLocked = selectedMetadatas.allSatisfy { !$0.lock } + func deleteMetadata(metadatas: [tableMetadata]) { + let notLocked = metadatas.allSatisfy { !$0.lock } if notLocked { - delete(metadatas: selectedMetadatas) + delete(metadatas: metadatas) } } - func copyOrMoveSelectedMetadataInApp() { - NCActionCenter.shared.openSelectView(items: selectedMetadatas, indexPath: []) - cancelSelection() + func copyOrMoveMetadataInApp(metadatas: [tableMetadata]) { + NCActionCenter.shared.openSelectView(items: metadatas, indexPath: []) +// cancelSelection() } - func copySelectedMetadata() { - copy(metadatas: selectedMetadatas) - cancelSelection() + func copyMetadata(metadatas: [tableMetadata]) { + copy(metadatas: metadatas) +// cancelSelection() } func addToFavorites(metadata: tableMetadata) { @@ -168,7 +169,7 @@ import Combine func saveToPhotos(metadata: tableMetadata) { if let livePhoto = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) { - NCActionCenter.shared.saveLivePhoto(metadata: metadata, metadataMOV: livePhoto) +// NCOperationQueue.shared.saveLivePhoto(metadata: metadata, metadataMOV: livePhoto) // TODO: Find where to call this } else if CCUtility.fileProviderStorageExists(metadata) { NCActionCenter.shared.saveAlbum(metadata: metadata) } else { @@ -240,7 +241,7 @@ import Combine } NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterDeleteFile, userInfo: ["ocId": ocId, "onlyLocalCache": false, "error": error]) - isInSelectMode = false +// isInSelectMode = false } } @@ -253,8 +254,8 @@ import Combine } private func cancelSelection() { - self.isInSelectMode = false - self.selectedMetadatas.removeAll() +// self.isInSelectMode = false +// self.selectedMetadatas.removeAll() } } diff --git a/iOSClient/Networking/E2EE/NCNetworkingE2EE.swift b/iOSClient/Networking/E2EE/NCNetworkingE2EE.swift index a16fab32f7..d5b724b3af 100644 --- a/iOSClient/Networking/E2EE/NCNetworkingE2EE.swift +++ b/iOSClient/Networking/E2EE/NCNetworkingE2EE.swift @@ -28,12 +28,6 @@ class NCNetworkingE2EE: NSObject { return instance }() - func getRoute() -> String { - let e2eeRouteV1 = "v1" - let e2eeRouteV2 = "v2" - return (NCGlobal.shared.capabilityE2EEApiVersion == NCGlobal.shared.e2eeVersionV20) ? e2eeRouteV1 : e2eeRouteV1 - } - func isInUpload(account: String, serverUrl: String) -> Bool { let counter = NCManageDatabase.shared.getMetadatas(predicate: NSPredicate(format: "account == %@ AND serverUrl == %@ AND (status == %d OR status == %d OR status == %d)", account, serverUrl, NCGlobal.shared.metadataStatusWaitUpload, NCGlobal.shared.metadataStatusInUpload, NCGlobal.shared.metadataStatusUploading)).count @@ -74,7 +68,7 @@ class NCNetworkingE2EE: NSObject { // METHOD // - let resultsGetE2EEMetadata = await NextcloudKit.shared.getE2EEMetadata(fileId: fileId, e2eToken: e2eToken, route: getRoute()) + let resultsGetE2EEMetadata = await NextcloudKit.shared.getE2EEMetadata(fileId: fileId, e2eToken: e2eToken) if resultsGetE2EEMetadata.error == .success { method = "PUT" } else if resultsGetE2EEMetadata.error.errorCode != NCGlobal.shared.errorResourceNotFound { @@ -112,7 +106,7 @@ class NCNetworkingE2EE: NSObject { fileId: String, e2eToken: String) async -> NKError { - let resultsGetE2EEMetadata = await NextcloudKit.shared.getE2EEMetadata(fileId: fileId, e2eToken: e2eToken, route: getRoute()) + let resultsGetE2EEMetadata = await NextcloudKit.shared.getE2EEMetadata(fileId: fileId, e2eToken: e2eToken) guard resultsGetE2EEMetadata.error == .success, let e2eMetadata = resultsGetE2EEMetadata.e2eMetadata else { return resultsGetE2EEMetadata.error } @@ -141,7 +135,7 @@ class NCNetworkingE2EE: NSObject { return resultsEncodeMetadata.error } - let putE2EEMetadataResults = await NextcloudKit.shared.putE2EEMetadata(fileId: fileId, e2eToken: e2eToken, e2eMetadata: e2eMetadata, signature: resultsEncodeMetadata.signature, method: method, route: getRoute()) + let putE2EEMetadataResults = await NextcloudKit.shared.putE2EEMetadata(fileId: fileId, e2eToken: e2eToken, e2eMetadata: e2eMetadata, signature: resultsEncodeMetadata.signature, method: method) guard putE2EEMetadataResults.error == .success else { return putE2EEMetadataResults.error } @@ -173,7 +167,7 @@ class NCNetworkingE2EE: NSObject { e2eCounter = "\(counter)" } - let resultsLockE2EEFolder = await NextcloudKit.shared.lockE2EEFolder(fileId: directory.fileId, e2eToken: e2eToken, e2eCounter: e2eCounter, method: "POST", route: getRoute()) + let resultsLockE2EEFolder = await NextcloudKit.shared.lockE2EEFolder(fileId: directory.fileId, e2eToken: e2eToken, e2eCounter: e2eCounter, method: "POST") if resultsLockE2EEFolder.error == .success, let e2eToken = resultsLockE2EEFolder.e2eToken { NCManageDatabase.shared.setE2ETokenLock(account: account, serverUrl: serverUrl, fileId: directory.fileId, e2eToken: e2eToken) } @@ -187,7 +181,7 @@ class NCNetworkingE2EE: NSObject { return } - let resultsLockE2EEFolder = await NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, e2eCounter: nil, method: "DELETE", route: getRoute()) + let resultsLockE2EEFolder = await NextcloudKit.shared.lockE2EEFolder(fileId: tableLock.fileId, e2eToken: tableLock.e2eToken, e2eCounter: nil, method: "DELETE") if resultsLockE2EEFolder.error == .success { NCManageDatabase.shared.deleteE2ETokenLock(account: account, serverUrl: serverUrl) } @@ -201,7 +195,7 @@ class NCNetworkingE2EE: NSObject { Task { for result in NCManageDatabase.shared.getE2EAllTokenLock(account: account) { - let resultsLockE2EEFolder = await NextcloudKit.shared.lockE2EEFolder(fileId: result.fileId, e2eToken: result.e2eToken, e2eCounter: nil, method: "DELETE", route: getRoute()) + let resultsLockE2EEFolder = await NextcloudKit.shared.lockE2EEFolder(fileId: result.fileId, e2eToken: result.e2eToken, e2eCounter: nil, method: "DELETE") if resultsLockE2EEFolder.error == .success { NCManageDatabase.shared.deleteE2ETokenLock(account: account, serverUrl: result.serverUrl) } diff --git a/iOSClient/Networking/E2EE/NCNetworkingE2EECreateFolder.swift b/iOSClient/Networking/E2EE/NCNetworkingE2EECreateFolder.swift index 339975f3a0..a417f24998 100644 --- a/iOSClient/Networking/E2EE/NCNetworkingE2EECreateFolder.swift +++ b/iOSClient/Networking/E2EE/NCNetworkingE2EECreateFolder.swift @@ -124,7 +124,7 @@ class NCNetworkingE2EECreateFolder: NSObject { // SET FOLDER AS E2EE // - let resultsMarkE2EEFolder = await NextcloudKit.shared.markE2EEFolder(fileId: fileId, delete: false, route: NCNetworkingE2EE.shared.getRoute()) + let resultsMarkE2EEFolder = await NextcloudKit.shared.markE2EEFolder(fileId: fileId, delete: false) guard resultsMarkE2EEFolder.error == .success else { await NCNetworkingE2EE.shared.unlock(account: account, serverUrl: serverUrl) return resultsMarkE2EEFolder.error diff --git a/iOSClient/Networking/E2EE/NCNetworkingE2EEMarkFolder.swift b/iOSClient/Networking/E2EE/NCNetworkingE2EEMarkFolder.swift index fddef4cb5e..40b7840060 100644 --- a/iOSClient/Networking/E2EE/NCNetworkingE2EEMarkFolder.swift +++ b/iOSClient/Networking/E2EE/NCNetworkingE2EEMarkFolder.swift @@ -31,7 +31,7 @@ class NCNetworkingE2EEMarkFolder: NSObject { let resultsReadFileOrFolder = await NextcloudKit.shared.readFileOrFolder(serverUrlFileName: serverUrlFileName, depth: "0") guard resultsReadFileOrFolder.error == .success, let file = resultsReadFileOrFolder.files.first else { return resultsReadFileOrFolder.error } - let resultsMarkE2EEFolder = await NextcloudKit.shared.markE2EEFolder(fileId: file.fileId, delete: false, route: NCNetworkingE2EE.shared.getRoute()) + let resultsMarkE2EEFolder = await NextcloudKit.shared.markE2EEFolder(fileId: file.fileId, delete: false) guard resultsMarkE2EEFolder.error == .success else { return resultsMarkE2EEFolder.error } file.e2eEncrypted = true diff --git a/iOSClient/Settings/CCAdvanced.m b/iOSClient/Settings/CCAdvanced.m index cb2ced5ede..f2aabfe1b8 100755 --- a/iOSClient/Settings/CCAdvanced.m +++ b/iOSClient/Settings/CCAdvanced.m @@ -161,8 +161,6 @@ - (void)initializeForm } else { [[[NextcloudKit shared] nkCommonInstance] writeLog:[NSString stringWithFormat:@"[INFO] Clear log with level %lu %@", (unsigned long)logLevel, versionNextcloudiOS]]; } - - [[NCMediaCache shared] createCacheWithAccount:appDelegate.account]; }; [section addFormRow:row]; diff --git a/iOSClient/Supporting Files/hu.lproj/InfoPlist.strings b/iOSClient/Supporting Files/hu.lproj/InfoPlist.strings index 1b50bf7e41e923825218619807df3f500dd10716..975fa87a5a0ffdc3254c1a480ff06477946ca1a1 100644 GIT binary patch delta 209 zcmbQjy@7kfJH}W?hAIXHhD3%OhHNmI3nZ%;9x@aIMROTa8Pb7dDMJZRw1goGNP^TV yFk}E_au_OsDpP^tFM${$4q_JpO?t^t0F=qwY|HeYDUGI9Fz7KTF<3KjF#rIl{4MVQ delta 185 zcmdnMJ%xM2J4XKyh75*O1_g#hh5{f|U?^wEWXJ(R1%_gvOg@mWz)%UKOBsrQtQ;UK s8K|}ds4AZ!4=4g56M?K;kQtL5nN>FzFx_H`pt8XXdJIYo)(l(>04b{^F#rGn diff --git a/iOSClient/Supporting Files/hu.lproj/Localizable.strings b/iOSClient/Supporting Files/hu.lproj/Localizable.strings index c5267a86b4c99cc49817fa766ee22e325ee66672..bfea7e6e6cb46f415a85cc7771ffefd03b3fb05e 100644 GIT binary patch delta 97 zcmZ2+mwnw`_J%Et0q3W0FlQ8+{6$m1HisdVAsvYG7*ZGl85J0c8LAi(8IpiFg+YNK t11OWjPzhuu0&yC{LxwCMUx6W;;SZ2bnJ)N{QFwBSzrgl0=Na$F0RU`;8-4%) delta 124 zcmZ2?mwm-u_J%Et0q4^^8A=!w7>XHEfiM?HD**W!Kz0!jD==h&Me-Q(!KzXjK&(=R tbf5~5o&ttMhGek15}-K5lstwMxETrzX+RTlfGQ@(`HOA8be{2!8~{U{9N_=} diff --git a/iOSClient/Utility/PreferenceKeys.swift b/iOSClient/Utility/PreferenceKeys.swift index 5ddb42b507..433a567ee8 100644 --- a/iOSClient/Utility/PreferenceKeys.swift +++ b/iOSClient/Utility/PreferenceKeys.swift @@ -14,3 +14,9 @@ struct ScrollOffsetPreferenceKey: PreferenceKey { static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) {} } + +struct TitlePreferenceKey: PreferenceKey { + static var defaultValue: String = "" + + static func reduce(value: inout String, nextValue: () -> String) {} +}