diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index bcc774ebe4..cfd4cf4059 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -161,6 +161,8 @@ 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 */; }; @@ -214,7 +216,6 @@ F72944F52A8424F800246839 /* NCEndToEndMetadataV1.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72944F42A8424F800246839 /* NCEndToEndMetadataV1.swift */; }; F72944F62A8424F800246839 /* NCEndToEndMetadataV1.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72944F42A8424F800246839 /* NCEndToEndMetadataV1.swift */; }; F72A17D828B221E300F3F159 /* DashboardWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72A17D728B221E300F3F159 /* DashboardWidgetView.swift */; }; - F72A47EC2487B06B005AD489 /* NCOperationQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = F72A47EB2487B06B005AD489 /* NCOperationQueue.swift */; }; F72AD70D28C24B93006CB92D /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = F72AD70C28C24B93006CB92D /* NextcloudKit */; }; F72AD70F28C24BA1006CB92D /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = F72AD70E28C24BA1006CB92D /* NextcloudKit */; }; F72AD71128C24BBB006CB92D /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = F72AD71028C24BBB006CB92D /* NextcloudKit */; }; @@ -549,6 +550,10 @@ F7A321AD1E9E6AD50069AD1B /* CCAdvanced.m in Sources */ = {isa = PBXBuildFile; fileRef = F7A321AC1E9E6AD50069AD1B /* CCAdvanced.m */; }; F7A48413297022E000BD1B49 /* ViewerQuickLook.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A48412297022E000BD1B49 /* ViewerQuickLook.swift */; }; F7A48415297028FC00BD1B49 /* Nextcloud Hub.png in Resources */ = {isa = PBXBuildFile; fileRef = F7A48414297028FC00BD1B49 /* Nextcloud Hub.png */; }; + F7A560422AE1593700BE8FD6 /* NCOperationSaveLivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A560412AE1593700BE8FD6 /* NCOperationSaveLivePhoto.swift */; }; + F7A560442AE15D2900BE8FD6 /* Queuer in Frameworks */ = {isa = PBXBuildFile; productRef = F7A560432AE15D2900BE8FD6 /* Queuer */; }; + F7A560462AE15D3D00BE8FD6 /* Queuer in Frameworks */ = {isa = PBXBuildFile; productRef = F7A560452AE15D3D00BE8FD6 /* Queuer */; }; + F7A560482AE15D5000BE8FD6 /* Queuer in Frameworks */ = {isa = PBXBuildFile; productRef = F7A560472AE15D5000BE8FD6 /* Queuer */; }; F7A60F86292D215000FCE1F2 /* NCShareAccounts.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7A60F84292D215000FCE1F2 /* NCShareAccounts.swift */; }; F7A60F87292D215000FCE1F2 /* NCShareAccounts.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F7A60F85292D215000FCE1F2 /* NCShareAccounts.storyboard */; }; F7A76DC8256A71CD00119AB3 /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B7504A2397D38E004E13EC /* UIImage+Extension.swift */; }; @@ -971,7 +976,6 @@ F72944F12A84246400246839 /* NCEndToEndMetadataV20.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCEndToEndMetadataV20.swift; sourceTree = ""; }; F72944F42A8424F800246839 /* NCEndToEndMetadataV1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCEndToEndMetadataV1.swift; sourceTree = ""; }; F72A17D728B221E300F3F159 /* DashboardWidgetView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashboardWidgetView.swift; sourceTree = ""; }; - F72A47EB2487B06B005AD489 /* NCOperationQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCOperationQueue.swift; sourceTree = ""; }; F72CD63925C19EBF00F46F9A /* NCAutoUpload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCAutoUpload.swift; sourceTree = ""; }; F72D1005210B6882009C96B7 /* NCPushNotificationEncryption.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NCPushNotificationEncryption.m; sourceTree = ""; }; F72D1006210B6882009C96B7 /* NCPushNotificationEncryption.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NCPushNotificationEncryption.h; sourceTree = ""; }; @@ -1171,6 +1175,7 @@ F7A321AC1E9E6AD50069AD1B /* CCAdvanced.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCAdvanced.m; sourceTree = ""; }; F7A48412297022E000BD1B49 /* ViewerQuickLook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewerQuickLook.swift; sourceTree = ""; }; F7A48414297028FC00BD1B49 /* Nextcloud Hub.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Nextcloud Hub.png"; sourceTree = SOURCE_ROOT; }; + F7A560412AE1593700BE8FD6 /* NCOperationSaveLivePhoto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCOperationSaveLivePhoto.swift; sourceTree = ""; }; F7A60F84292D215000FCE1F2 /* NCShareAccounts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NCShareAccounts.swift; sourceTree = ""; }; F7A60F85292D215000FCE1F2 /* NCShareAccounts.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = NCShareAccounts.storyboard; sourceTree = ""; }; F7A7FA6229265CF4000603EF /* NCManageE2EE.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCManageE2EE.swift; sourceTree = ""; }; @@ -1444,6 +1449,7 @@ F72CD01227A7E92400E59476 /* JGProgressHUD in Frameworks */, F77CB6A92AA08053000C3CA4 /* OpenSSL in Frameworks */, F73ADD2126554F8E0069EA0D /* SwiftEntryKit in Frameworks */, + F7A560482AE15D5000BE8FD6 /* Queuer in Frameworks */, F7EBCDCF277B81FF00A4EF67 /* UICKeyChainStore in Frameworks */, F70821D829E59E6D001CA2D7 /* TagListView in Frameworks */, F7F623B72A5EFA0C0022D3D4 /* Gzip in Frameworks */, @@ -1460,6 +1466,7 @@ F783034428B5142B00B84583 /* NextcloudKit in Frameworks */, F7346E1328B0EF5B006CE2D2 /* SwiftUI.framework in Frameworks */, F7346E2928B0FFF2006CE2D2 /* RealmSwift in Frameworks */, + F7A560462AE15D3D00BE8FD6 /* Queuer in Frameworks */, F783030D28B4C59A00B84583 /* SwiftEntryKit in Frameworks */, F7346E1228B0EF5B006CE2D2 /* WidgetKit.framework in Frameworks */, ); @@ -1469,6 +1476,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + F7A560442AE15D2900BE8FD6 /* Queuer in Frameworks */, F7EBCDD1277B820D00A4EF67 /* UICKeyChainStore in Frameworks */, F73ADD2426554FE20069EA0D /* SwiftEntryKit in Frameworks */, F710FC84277B7D3500AA9FBF /* RealmSwift in Frameworks */, @@ -1552,6 +1560,7 @@ AF93471127E2341B002537EE /* NCShare+Menu.swift */, F710D2012405826100A6033D /* NCViewer+Menu.swift */, F78C6FDD296D677300C952C3 /* NCContextMenu.swift */, + F7A560412AE1593700BE8FD6 /* NCOperationSaveLivePhoto.swift */, ); path = Menu; sourceTree = ""; @@ -1882,7 +1891,6 @@ F75A9EE523796C6F0044CFCE /* NCNetworking.swift */, F7D96FCB246ED7E100536D73 /* NCNetworkingCheckRemoteUser.swift */, F70D8D8024A4A9BF000A5756 /* NCNetworkingProcessUpload.swift */, - F72A47EB2487B06B005AD489 /* NCOperationQueue.swift */, F755BD9A20594AC7008C5FBB /* NCService.swift */, F77BC3EC293E528A005F2B08 /* NCConfigServer.swift */, ); @@ -2793,6 +2801,7 @@ F70821D729E59E6D001CA2D7 /* TagListView */, F7F623B62A5EFA0C0022D3D4 /* Gzip */, F77CB6A82AA08053000C3CA4 /* OpenSSL */, + F7A560472AE15D5000BE8FD6 /* Queuer */, ); productName = "Share Ext"; productReference = F7CE8AFB1DC1F8D8009CAE48 /* Share.appex */; @@ -2817,6 +2826,7 @@ F783030C28B4C59A00B84583 /* SwiftEntryKit */, F783034328B5142B00B84583 /* NextcloudKit */, F787AC0A298BCB540001BB00 /* SVGKitSwift */, + F7A560452AE15D3D00BE8FD6 /* Queuer */, ); productName = DashboardWidgetExtension; productReference = F7346E1028B0EF5B006CE2D2 /* Widget.appex */; @@ -2840,6 +2850,7 @@ F710FC83277B7D3500AA9FBF /* RealmSwift */, F7EBCDD0277B820D00A4EF67 /* UICKeyChainStore */, F72AD71228C24BCC006CB92D /* NextcloudKit */, + F7A560432AE15D2900BE8FD6 /* Queuer */, ); productName = "File Provider Extension"; productReference = F771E3D020E2392D00AFB62D /* File Provider Extension.appex */; @@ -3537,6 +3548,7 @@ F72EA95A28B7BD0D00C88F0C /* FilesWidgetView.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 */, @@ -3619,6 +3631,7 @@ 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 */, ); @@ -3661,7 +3674,6 @@ F79EDAA326B004980007D134 /* NCPlayerToolBar.swift in Sources */, F77444F8222816D5000D5EB0 /* NCPickerViewController.swift in Sources */, F77BB74A2899857B0090FC19 /* UINavigationController+Extension.swift in Sources */, - F72A47EC2487B06B005AD489 /* NCOperationQueue.swift in Sources */, F769454622E9F1B0000A798A /* NCShareCommon.swift in Sources */, F70753F12542A9A200972D44 /* NCViewerMedia.swift in Sources */, F76B649C2ADFFAED00014640 /* NCMediaCache.swift in Sources */, @@ -3776,6 +3788,7 @@ F70CAE3A1F8CF31A008125FD /* NCEndToEndEncryption.m in Sources */, AF93471B27E2361E002537EE /* NCShareAdvancePermission.swift in Sources */, F77BC3ED293E528A005F2B08 /* NCConfigServer.swift in Sources */, + F7A560422AE1593700BE8FD6 /* NCOperationSaveLivePhoto.swift in Sources */, F70753EB2542A99800972D44 /* NCViewerMediaPage.swift in Sources */, F7817CF829801A3500FFBC65 /* Data+Extension.swift in Sources */, F749B651297B0F2400087535 /* NCManageDatabase+Avatar.swift in Sources */, @@ -5427,6 +5440,21 @@ package = F7A1050C29E587AF00FFD92B /* XCRemoteSwiftPackageReference "TagListView" */; productName = TagListView; }; + F7A560432AE15D2900BE8FD6 /* Queuer */ = { + isa = XCSwiftPackageProductDependency; + package = F76DA961277B760E0082465B /* XCRemoteSwiftPackageReference "Queuer" */; + productName = Queuer; + }; + F7A560452AE15D3D00BE8FD6 /* Queuer */ = { + isa = XCSwiftPackageProductDependency; + package = F76DA961277B760E0082465B /* XCRemoteSwiftPackageReference "Queuer" */; + productName = Queuer; + }; + F7A560472AE15D5000BE8FD6 /* Queuer */ = { + isa = XCSwiftPackageProductDependency; + package = F76DA961277B760E0082465B /* XCRemoteSwiftPackageReference "Queuer" */; + productName = Queuer; + }; F7A8D72328F1771B008BBE1C /* NextcloudKit */ = { isa = XCSwiftPackageProductDependency; package = F783034028B511D200B84583 /* XCRemoteSwiftPackageReference "NextcloudKit" */; diff --git a/iOSClient/Activity/NCActivity.swift b/iOSClient/Activity/NCActivity.swift index 22b85b8fe5..97bea2299c 100644 --- a/iOSClient/Activity/NCActivity.swift +++ b/iOSClient/Activity/NCActivity.swift @@ -212,7 +212,7 @@ extension NCActivity: UITableViewDataSource { // Image let fileName = appDelegate.userBaseUrl + "-" + comment.actorId + ".png" - NCOperationQueue.shared.downloadAvatar(user: comment.actorId, dispalyName: comment.actorDisplayName, fileName: fileName, cell: cell, view: tableView, cellImageView: cell.fileAvatarImageView) + NCNetworking.shared.downloadAvatar(user: comment.actorId, dispalyName: comment.actorDisplayName, fileName: fileName, cell: cell, view: tableView, cellImageView: cell.fileAvatarImageView) // Username cell.labelUser.text = comment.actorDisplayName cell.labelUser.textColor = .label @@ -279,7 +279,7 @@ extension NCActivity: UITableViewDataSource { let fileName = appDelegate.userBaseUrl + "-" + activity.user + ".png" - NCOperationQueue.shared.downloadAvatar(user: activity.user, dispalyName: nil, fileName: fileName, cell: cell, view: tableView, cellImageView: cell.fileAvatarImageView) + NCNetworking.shared.downloadAvatar(user: activity.user, dispalyName: nil, fileName: fileName, cell: cell, view: tableView, cellImageView: cell.fileAvatarImageView) } // subject diff --git a/iOSClient/Activity/NCActivityTableViewCell.swift b/iOSClient/Activity/NCActivityTableViewCell.swift index f835ef1b5a..410870aa35 100644 --- a/iOSClient/Activity/NCActivityTableViewCell.swift +++ b/iOSClient/Activity/NCActivityTableViewCell.swift @@ -25,6 +25,7 @@ import Foundation import NextcloudKit import FloatingPanel import JGProgressHUD +import Queuer class NCActivityCollectionViewCell: UICollectionViewCell { @@ -194,7 +195,13 @@ extension NCActivityTableViewCell: UICollectionViewDataSource { if FileManager.default.fileExists(atPath: fileNamePath), let image = UIImage(contentsOfFile: fileNamePath) { cell.imageView.image = image } else { - NCOperationQueue.shared.downloadThumbnailActivity(fileNamePathOrFileId: activityPreview.source, fileNamePreviewLocalPath: fileNamePath, fileId: fileId, cell: cell, collectionView: collectionView) + cell.imageView?.image = UIImage(named: "file_photo") + cell.fileId = fileId + if !FileManager.default.fileExists(atPath: fileNamePath) { + if appDelegate.downloadThumbnailActivityQueue.operations.filter({ ($0 as? NCOperationDownloadThumbnailActivity)?.fileId == fileId }).isEmpty { + appDelegate.downloadThumbnailActivityQueue.addOperation(NCOperationDownloadThumbnailActivity(fileNamePathOrFileId: activityPreview.source, fileNamePreviewLocalPath: fileNamePath, fileId: fileId, cell: cell, collectionView: collectionView)) + } + } } } } @@ -219,3 +226,49 @@ extension NCActivityTableViewCell: UICollectionViewDelegateFlowLayout { return UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0) } } + +class NCOperationDownloadThumbnailActivity: ConcurrentOperation { + + var cell: NCActivityCollectionViewCell? + var collectionView: UICollectionView? + var fileNamePathOrFileId: String + var fileNamePreviewLocalPath: String + var fileId: String + + init(fileNamePathOrFileId: String, fileNamePreviewLocalPath: String, fileId: String, cell: NCActivityCollectionViewCell?, collectionView: UICollectionView?) { + self.fileNamePathOrFileId = fileNamePathOrFileId + self.fileNamePreviewLocalPath = fileNamePreviewLocalPath + self.fileId = fileId + self.cell = cell + self.collectionView = collectionView + } + + override func start() { + + guard !isCancelled else { return self.finish() } + + NextcloudKit.shared.downloadPreview(fileNamePathOrFileId: fileNamePathOrFileId, + fileNamePreviewLocalPath: fileNamePreviewLocalPath, + widthPreview: 0, + heightPreview: 0, + etag: nil, + useInternalEndpoint: false, + options: NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)) { _, imagePreview, _, _, _, error in + + if error == .success, let imagePreview = imagePreview { + DispatchQueue.main.async { + if self.fileId == self.cell?.fileId, let imageView = self.cell?.imageView { + UIView.transition(with: imageView, + duration: 0.75, + options: .transitionCrossDissolve, + animations: { imageView.image = imagePreview }, + completion: nil) + } else { + self.collectionView?.reloadData() + } + } + } + self.finish() + } + } +} diff --git a/iOSClient/Files/NCFiles.swift b/iOSClient/Files/NCFiles.swift index 5005d5e888..4469b0ec0a 100644 --- a/iOSClient/Files/NCFiles.swift +++ b/iOSClient/Files/NCFiles.swift @@ -165,7 +165,9 @@ class NCFiles: NCCollectionViewCommon { networkReadFolder(isForced: isForced) { tableDirectory, metadatas, metadatasUpdate, metadatasDelete, error in if error == .success { for metadata in metadatas ?? [] where !metadata.directory && NCManageDatabase.shared.isDownloadMetadata(metadata, download: false) { - NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile) + if self.appDelegate.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty { + self.appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile)) + } } } diff --git a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift index df69d96e3b..8d1ccf700a 100644 --- a/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift +++ b/iOSClient/Main/Collection Common/NCCollectionViewCommon.swift @@ -941,7 +941,7 @@ class NCCollectionViewCommon: UIViewController, UIGestureRecognizerDelegate, UIS searchResults: self.searchResults) } update: { _, _, searchResult, metadatas in guard let metadatas, !metadatas.isEmpty, self.isSearchingMode, let searchResult else { return } - NCOperationQueue.shared.unifiedSearchAddSection(collectionViewCommon: self, metadatas: metadatas, searchResult: searchResult) + self.appDelegate.unifiedSearchQueue.addOperation(NCOperationUnifiedSearch(collectionViewCommon: self, metadatas: metadatas, searchResult: searchResult)) } completion: { _, _ in self.refreshControl.endRefreshing() self.isReloadDataSourceNetworkInProgress = false @@ -1238,7 +1238,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource { if !metadata.iconUrl.isEmpty { if let ownerId = NCUtility.shared.getAvatarFromIconUrl(metadata: metadata), let cell = cell as? NCCellProtocol { let fileName = metadata.userBaseUrl + "-" + ownerId + ".png" - NCOperationQueue.shared.downloadAvatar(user: ownerId, dispalyName: nil, fileName: fileName, cell: cell, view: collectionView, cellImageView: cell.filePreviewImageView) + NCNetworking.shared.downloadAvatar(user: ownerId, dispalyName: nil, fileName: fileName, cell: cell, view: collectionView, cellImageView: cell.filePreviewImageView) } } } @@ -1250,7 +1250,7 @@ extension NCCollectionViewCommon: UICollectionViewDataSource { appDelegate.account == metadata.account, let cell = cell as? NCCellProtocol { let fileName = metadata.userBaseUrl + "-" + metadata.ownerId + ".png" - NCOperationQueue.shared.downloadAvatar(user: metadata.ownerId, dispalyName: metadata.ownerDisplayName, fileName: fileName, cell: cell, view: collectionView, cellImageView: cell.fileAvatarImageView) + NCNetworking.shared.downloadAvatar(user: metadata.ownerId, dispalyName: metadata.ownerDisplayName, fileName: fileName, cell: cell, view: collectionView, cellImageView: cell.fileAvatarImageView) } } @@ -1706,6 +1706,41 @@ extension NCCollectionViewCommon: EasyTipViewDelegate { } } +// 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 diff --git a/iOSClient/Menu/NCContextMenu.swift b/iOSClient/Menu/NCContextMenu.swift index 16c1c66116..9775bde74c 100644 --- a/iOSClient/Menu/NCContextMenu.swift +++ b/iOSClient/Menu/NCContextMenu.swift @@ -98,7 +98,9 @@ class NCContextMenu: NSObject { let save = UIAction(title: titleSave, image: UIImage(systemName: "square.and.arrow.down")) { _ in if let metadataMOV = metadataMOV { - NCOperationQueue.shared.saveLivePhoto(metadata: metadata, metadataMOV: metadataMOV) + if let appDelegate = (UIApplication.shared.delegate as? AppDelegate) { + appDelegate.saveLivePhotoQueue.addOperation(NCOperationSaveLivePhoto(metadata: metadata, metadataMOV: metadataMOV)) + } } else { if CCUtility.fileProviderStorageExists(metadata) { NCActionCenter.shared.saveAlbum(metadata: metadata) diff --git a/iOSClient/Menu/NCMenuAction.swift b/iOSClient/Menu/NCMenuAction.swift index 240faf9026..7d4dc88400 100644 --- a/iOSClient/Menu/NCMenuAction.swift +++ b/iOSClient/Menu/NCMenuAction.swift @@ -222,12 +222,16 @@ extension NCMenuAction { action: { _ in for metadata in selectedMediaMetadatas { if let metadataMOV = NCManageDatabase.shared.getMetadataLivePhoto(metadata: metadata) { - NCOperationQueue.shared.saveLivePhoto(metadata: metadata, metadataMOV: metadataMOV) + if let appDelegate = (UIApplication.shared.delegate as? AppDelegate) { + appDelegate.saveLivePhotoQueue.addOperation(NCOperationSaveLivePhoto(metadata: metadata, metadataMOV: metadataMOV)) + } } else { if CCUtility.fileProviderStorageExists(metadata) { NCActionCenter.shared.saveAlbum(metadata: metadata) } else { - NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorSaveAlbum) + if let appDelegate = (UIApplication.shared.delegate as? AppDelegate), appDelegate.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty { + appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: NCGlobal.shared.selectorSaveAlbum)) + } } } } diff --git a/iOSClient/Menu/NCOperationSaveLivePhoto.swift b/iOSClient/Menu/NCOperationSaveLivePhoto.swift new file mode 100644 index 0000000000..d7eb485480 --- /dev/null +++ b/iOSClient/Menu/NCOperationSaveLivePhoto.swift @@ -0,0 +1,124 @@ +// +// NCooo.swift +// Nextcloud +// +// Created by Marino Faggiana on 19/10/23. +// Copyright © 2023 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 +import Queuer +import JGProgressHUD + +class NCOperationSaveLivePhoto: ConcurrentOperation { + + var metadata: tableMetadata + var metadataMOV: tableMetadata + let hud = JGProgressHUD() + let appDelegate = UIApplication.shared.delegate as? AppDelegate + + init(metadata: tableMetadata, metadataMOV: tableMetadata) { + self.metadata = tableMetadata.init(value: metadata) + self.metadataMOV = tableMetadata.init(value: metadataMOV) + } + + override func start() { + guard !isCancelled else { return self.finish() } + + DispatchQueue.main.async { + self.hud.indicatorView = JGProgressHUDRingIndicatorView() + if let indicatorView = self.hud.indicatorView as? JGProgressHUDRingIndicatorView { + indicatorView.ringWidth = 1.5 + } + self.hud.textLabel.text = NSLocalizedString("_download_image_", comment: "") + self.hud.detailTextLabel.text = self.metadata.fileName + self.hud.show(in: (self.appDelegate?.window?.rootViewController?.view)!) + } + + NCNetworking.shared.download(metadata: metadata, selector: "", notificationCenterProgressTask: false, checkfileProviderStorageExists: true) { _ in + } progressHandler: { progress in + self.hud.progress = Float(progress.fractionCompleted) + } completion: { _, error in + guard error == .success else { + DispatchQueue.main.async { + self.hud.indicatorView = JGProgressHUDErrorIndicatorView() + self.hud.textLabel.text = NSLocalizedString("_livephoto_save_error_", comment: "") + self.hud.dismiss() + } + return self.finish() + } + NCNetworking.shared.download(metadata: self.metadataMOV, selector: "", notificationCenterProgressTask: false, checkfileProviderStorageExists: true) { _ in + DispatchQueue.main.async { + self.hud.textLabel.text = NSLocalizedString("_download_video_", comment: "") + self.hud.detailTextLabel.text = self.metadataMOV.fileName + } + } progressHandler: { progress in + self.hud.progress = Float(progress.fractionCompleted) + } completion: { _, error in + guard error == .success else { + DispatchQueue.main.async { + self.hud.indicatorView = JGProgressHUDErrorIndicatorView() + self.hud.textLabel.text = NSLocalizedString("_livephoto_save_error_", comment: "") + self.hud.dismiss() + } + return self.finish() + } + self.saveLivePhotoToDisk(metadata: self.metadata, metadataMov: self.metadataMOV) + } + } + } + + func saveLivePhotoToDisk(metadata: tableMetadata, metadataMov: tableMetadata) { + + let fileNameImage = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!) + let fileNameMov = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadataMov.ocId, fileNameView: metadataMov.fileNameView)!) + + DispatchQueue.main.async { + self.hud.textLabel.text = NSLocalizedString("_livephoto_save_", comment: "") + self.hud.detailTextLabel.text = "" + } + + NCLivePhoto.generate(from: fileNameImage, videoURL: fileNameMov, progress: { progress in + self.hud.progress = Float(progress) + }, completion: { _, resources in + if resources != nil { + NCLivePhoto.saveToLibrary(resources!) { result in + DispatchQueue.main.async { + if !result { + self.hud.indicatorView = JGProgressHUDErrorIndicatorView() + self.hud.textLabel.text = NSLocalizedString("_livephoto_save_error_", comment: "") + } else { + self.hud.indicatorView = JGProgressHUDSuccessIndicatorView() + self.hud.textLabel.text = NSLocalizedString("_success_", comment: "") + } + self.hud.dismiss() + } + return self.finish() + } + } else { + DispatchQueue.main.async { + self.hud.indicatorView = JGProgressHUDErrorIndicatorView() + self.hud.textLabel.text = NSLocalizedString("_livephoto_save_error_", comment: "") + self.hud.dismiss() + } + return self.finish() + } + }) + } +} diff --git a/iOSClient/Networking/NCNetworking.swift b/iOSClient/Networking/NCNetworking.swift index 4096a8f180..0a7e3ea45d 100644 --- a/iOSClient/Networking/NCNetworking.swift +++ b/iOSClient/Networking/NCNetworking.swift @@ -26,6 +26,7 @@ import OpenSSL import NextcloudKit import Alamofire import Photos +import Queuer @objc public protocol NCNetworkingDelegate { @objc optional func downloadProgress(_ progress: Float, totalBytes: Int64, totalBytesExpected: Int64, fileName: String, serverUrl: String, session: URLSession, task: URLSessionTask) @@ -353,6 +354,26 @@ class NCNetworking: NSObject, NKCommonDelegate { } } +#if !EXTENSION + func downloadAvatar(user: String, dispalyName: String?, fileName: String, cell: NCCellProtocol, view: UIView?, cellImageView: UIImageView?) { + guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return } + let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName + + if let image = NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) { + cellImageView?.image = image + cell.fileAvatarImageView?.image = image + return + } + + if let account = NCManageDatabase.shared.getActiveAccount() { + cellImageView?.image = NCUtility.shared.loadUserImage(for: user, displayName: dispalyName, userBaseUrl: account) + } + + for case let operation as NCOperationDownloadAvatar in appDelegate.downloadAvatarQueue.operations where operation.fileName == fileName { return } + appDelegate.downloadAvatarQueue.addOperation(NCOperationDownloadAvatar(user: user, fileName: fileName, fileNameLocalPath: fileNameLocalPath, cell: cell, view: view, cellImageView: cellImageView)) + } +#endif + // MARK: - Upload func upload(metadata: tableMetadata, @@ -958,8 +979,11 @@ class NCNetworking: NSObject, NKCommonDelegate { if metadata.directory { let serverUrl = metadata.serverUrl + "/" + metadata.fileName NCManageDatabase.shared.addDirectory(encrypted: metadata.e2eEncrypted, favorite: metadata.favorite, ocId: metadata.ocId, fileId: metadata.fileId, etag: metadata.etag, permissions: metadata.permissions, serverUrl: serverUrl, account: metadata.account) - } else if selector == NCGlobal.shared.selectorSynchronizationOffline, NCManageDatabase.shared.isDownloadMetadata(metadata, download: true) { - NCOperationQueue.shared.download(metadata: metadata, selector: selector) + } else if selector == NCGlobal.shared.selectorSynchronizationOffline, + NCManageDatabase.shared.isDownloadMetadata(metadata, download: true), + let appDelegate = (UIApplication.shared.delegate as? AppDelegate), + appDelegate.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty { + appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: selector)) } } } @@ -1646,3 +1670,81 @@ extension Array where Element == URLQueryItem { first(where: { $0.name == name }) } } + +// MARK: - + +class NCOperationDownload: ConcurrentOperation { + + var metadata: tableMetadata + var selector: String + + init(metadata: tableMetadata, selector: String) { + self.metadata = tableMetadata.init(value: metadata) + self.selector = selector + } + + override func start() { + + guard !isCancelled else { return self.finish() } + + NCNetworking.shared.download(metadata: metadata, selector: self.selector) { _, _ in + self.finish() + } + } +} + +class NCOperationDownloadAvatar: ConcurrentOperation { + + var user: String + var fileName: String + var etag: String? + var fileNameLocalPath: String + var cell: NCCellProtocol! + var view: UIView? + var cellImageView: UIImageView? + + init(user: String, fileName: String, fileNameLocalPath: String, cell: NCCellProtocol, view: UIView?, cellImageView: UIImageView?) { + self.user = user + self.fileName = fileName + self.fileNameLocalPath = fileNameLocalPath + self.cell = cell + self.view = view + self.etag = NCManageDatabase.shared.getTableAvatar(fileName: fileName)?.etag + self.cellImageView = cellImageView + } + + override func start() { + + guard !isCancelled else { return self.finish() } + + NextcloudKit.shared.downloadAvatar(user: user, + fileNameLocalPath: fileNameLocalPath, + sizeImage: NCGlobal.shared.avatarSize, + avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, + etag: self.etag, + options: NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)) { _, imageAvatar, _, etag, error in + + if error == .success, let imageAvatar = imageAvatar, let etag = etag { + NCManageDatabase.shared.addAvatar(fileName: self.fileName, etag: etag) + DispatchQueue.main.async { + if self.user == self.cell.fileUser, let avatarImageView = self.cellImageView { + UIView.transition(with: avatarImageView, + duration: 0.75, + options: .transitionCrossDissolve, + animations: { avatarImageView.image = imageAvatar }, + completion: nil) + } else { + if self.view is UICollectionView { + (self.view as? UICollectionView)?.reloadData() + } else if self.view is UITableView { + (self.view as? UITableView)?.reloadData() + } + } + } + } else if error.errorCode == NCGlobal.shared.errorNotModified { + NCManageDatabase.shared.setAvatarLoaded(fileName: self.fileName) + } + self.finish() + } + } +} diff --git a/iOSClient/Networking/NCOperationQueue.swift b/iOSClient/Networking/NCOperationQueue.swift deleted file mode 100644 index 523e0f1ea6..0000000000 --- a/iOSClient/Networking/NCOperationQueue.swift +++ /dev/null @@ -1,358 +0,0 @@ -// -// NCOperationQueue.swift -// Nextcloud -// -// Created by Marino Faggiana on 03/06/2020. -// Copyright © 2020 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 -import Queuer -import NextcloudKit -import JGProgressHUD - -@objc class NCOperationQueue: NSObject { - @objc public static let shared: NCOperationQueue = { - let instance = NCOperationQueue() - return instance - }() - - let appDelegate = (UIApplication.shared.delegate as? AppDelegate)! - - // MARK: - Download file - - func download(metadata: tableMetadata, selector: String) { - - for case let operation as NCOperationDownload in appDelegate.downloadQueue.operations where operation.metadata.ocId == metadata.ocId { return } - appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: selector)) - } - - // MARK: - Download Thumbnail Activity - - func downloadThumbnailActivity(fileNamePathOrFileId: String, fileNamePreviewLocalPath: String, fileId: String, cell: NCActivityCollectionViewCell, collectionView: UICollectionView?) { - - cell.imageView?.image = UIImage(named: "file_photo") - cell.fileId = fileId - - if !FileManager.default.fileExists(atPath: fileNamePreviewLocalPath) { - for case let operation as NCOperationDownloadThumbnailActivity in appDelegate.downloadThumbnailActivityQueue.operations where operation.fileId == fileId { - return - } - appDelegate.downloadThumbnailActivityQueue.addOperation(NCOperationDownloadThumbnailActivity(fileNamePathOrFileId: fileNamePathOrFileId, fileNamePreviewLocalPath: fileNamePreviewLocalPath, fileId: fileId, cell: cell, collectionView: collectionView)) - } - } - - // MARK: - Download Avatar - - func downloadAvatar(user: String, dispalyName: String?, fileName: String, cell: NCCellProtocol, view: UIView?, cellImageView: UIImageView?) { - - let fileNameLocalPath = String(CCUtility.getDirectoryUserData()) + "/" + fileName - - if let image = NCManageDatabase.shared.getImageAvatarLoaded(fileName: fileName) { - cellImageView?.image = image - cell.fileAvatarImageView?.image = image - return - } - - if let account = NCManageDatabase.shared.getActiveAccount() { - cellImageView?.image = NCUtility.shared.loadUserImage( - for: user, - displayName: dispalyName, - userBaseUrl: account) - } - - for case let operation as NCOperationDownloadAvatar in appDelegate.downloadAvatarQueue.operations where operation.fileName == fileName { return } - appDelegate.downloadAvatarQueue.addOperation(NCOperationDownloadAvatar(user: user, fileName: fileName, fileNameLocalPath: fileNameLocalPath, cell: cell, view: view, cellImageView: cellImageView)) - } - - // MARK: - Unified Search - - func unifiedSearchAddSection(collectionViewCommon: NCCollectionViewCommon, metadatas: [tableMetadata], searchResult: NKSearchResult) { - appDelegate.unifiedSearchQueue.addOperation(NCOperationUnifiedSearch(collectionViewCommon: collectionViewCommon, metadatas: metadatas, searchResult: searchResult)) - } - - // MARK: - Save Live Photo - - func saveLivePhoto(metadata: tableMetadata, metadataMOV: tableMetadata) { - - for case let operation as NCOperationSaveLivePhoto in appDelegate.saveLivePhotoQueue.operations where operation.metadata.fileName == metadata.fileName { return } - appDelegate.saveLivePhotoQueue.addOperation(NCOperationSaveLivePhoto(metadata: metadata, metadataMOV: metadataMOV)) - } -} - -// MARK: - - -class NCOperationDownload: ConcurrentOperation { - - var metadata: tableMetadata - var selector: String - - init(metadata: tableMetadata, selector: String) { - self.metadata = tableMetadata.init(value: metadata) - self.selector = selector - } - - override func start() { - - guard !isCancelled else { return self.finish() } - - NCNetworking.shared.download(metadata: metadata, selector: self.selector) { _, _ in - self.finish() - } - } -} - -// MARK: - - -class NCOperationDownloadThumbnailActivity: ConcurrentOperation { - - var cell: NCActivityCollectionViewCell? - var collectionView: UICollectionView? - var fileNamePathOrFileId: String - var fileNamePreviewLocalPath: String - var fileId: String - - init(fileNamePathOrFileId: String, fileNamePreviewLocalPath: String, fileId: String, cell: NCActivityCollectionViewCell?, collectionView: UICollectionView?) { - self.fileNamePathOrFileId = fileNamePathOrFileId - self.fileNamePreviewLocalPath = fileNamePreviewLocalPath - self.fileId = fileId - self.cell = cell - self.collectionView = collectionView - } - - override func start() { - - guard !isCancelled else { return self.finish() } - - NextcloudKit.shared.downloadPreview(fileNamePathOrFileId: fileNamePathOrFileId, - fileNamePreviewLocalPath: fileNamePreviewLocalPath, - widthPreview: 0, - heightPreview: 0, - etag: nil, - useInternalEndpoint: false, - options: NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)) { _, imagePreview, _, _, _, error in - - if error == .success, let imagePreview = imagePreview { - DispatchQueue.main.async { - if self.fileId == self.cell?.fileId, let imageView = self.cell?.imageView { - UIView.transition(with: imageView, - duration: 0.75, - options: .transitionCrossDissolve, - animations: { imageView.image = imagePreview }, - completion: nil) - } else { - self.collectionView?.reloadData() - } - } - } - self.finish() - } - } -} - -// MARK: - - -class NCOperationDownloadAvatar: ConcurrentOperation { - - var user: String - var fileName: String - var etag: String? - var fileNameLocalPath: String - var cell: NCCellProtocol! - var view: UIView? - var cellImageView: UIImageView? - - init(user: String, fileName: String, fileNameLocalPath: String, cell: NCCellProtocol, view: UIView?, cellImageView: UIImageView?) { - self.user = user - self.fileName = fileName - self.fileNameLocalPath = fileNameLocalPath - self.cell = cell - self.view = view - self.etag = NCManageDatabase.shared.getTableAvatar(fileName: fileName)?.etag - self.cellImageView = cellImageView - } - - override func start() { - - guard !isCancelled else { return self.finish() } - - NextcloudKit.shared.downloadAvatar(user: user, - fileNameLocalPath: fileNameLocalPath, - sizeImage: NCGlobal.shared.avatarSize, - avatarSizeRounded: NCGlobal.shared.avatarSizeRounded, - etag: self.etag, - options: NKRequestOptions(queue: NextcloudKit.shared.nkCommonInstance.backgroundQueue)) { _, imageAvatar, _, etag, error in - - if error == .success, let imageAvatar = imageAvatar, let etag = etag { - NCManageDatabase.shared.addAvatar(fileName: self.fileName, etag: etag) - DispatchQueue.main.async { - if self.user == self.cell.fileUser, let avatarImageView = self.cellImageView { - UIView.transition(with: avatarImageView, - duration: 0.75, - options: .transitionCrossDissolve, - animations: { avatarImageView.image = imageAvatar }, - completion: nil) - } else { - if self.view is UICollectionView { - (self.view as? UICollectionView)?.reloadData() - } else if self.view is UITableView { - (self.view as? UITableView)?.reloadData() - } - } - } - } else if error.errorCode == NCGlobal.shared.errorNotModified { - NCManageDatabase.shared.setAvatarLoaded(fileName: self.fileName) - } - self.finish() - } - } -} - -// 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() - } - } -} - -// MARK: - - -class NCOperationSaveLivePhoto: ConcurrentOperation { - - var metadata: tableMetadata - var metadataMOV: tableMetadata - let hud = JGProgressHUD() - let appDelegate = UIApplication.shared.delegate as? AppDelegate - - init(metadata: tableMetadata, metadataMOV: tableMetadata) { - self.metadata = tableMetadata.init(value: metadata) - self.metadataMOV = tableMetadata.init(value: metadataMOV) - } - - override func start() { - guard !isCancelled else { return self.finish() } - - DispatchQueue.main.async { - self.hud.indicatorView = JGProgressHUDRingIndicatorView() - if let indicatorView = self.hud.indicatorView as? JGProgressHUDRingIndicatorView { - indicatorView.ringWidth = 1.5 - } - self.hud.textLabel.text = NSLocalizedString("_download_image_", comment: "") - self.hud.detailTextLabel.text = self.metadata.fileName - self.hud.show(in: (self.appDelegate?.window?.rootViewController?.view)!) - } - - NCNetworking.shared.download(metadata: metadata, selector: "", notificationCenterProgressTask: false, checkfileProviderStorageExists: true) { _ in - } progressHandler: { progress in - self.hud.progress = Float(progress.fractionCompleted) - } completion: { _, error in - guard error == .success else { - DispatchQueue.main.async { - self.hud.indicatorView = JGProgressHUDErrorIndicatorView() - self.hud.textLabel.text = NSLocalizedString("_livephoto_save_error_", comment: "") - self.hud.dismiss() - } - return self.finish() - } - NCNetworking.shared.download(metadata: self.metadataMOV, selector: "", notificationCenterProgressTask: false, checkfileProviderStorageExists: true) { _ in - DispatchQueue.main.async { - self.hud.textLabel.text = NSLocalizedString("_download_video_", comment: "") - self.hud.detailTextLabel.text = self.metadataMOV.fileName - } - } progressHandler: { progress in - self.hud.progress = Float(progress.fractionCompleted) - } completion: { _, error in - guard error == .success else { - DispatchQueue.main.async { - self.hud.indicatorView = JGProgressHUDErrorIndicatorView() - self.hud.textLabel.text = NSLocalizedString("_livephoto_save_error_", comment: "") - self.hud.dismiss() - } - return self.finish() - } - self.saveLivePhotoToDisk(metadata: self.metadata, metadataMov: self.metadataMOV) - } - } - } - - func saveLivePhotoToDisk(metadata: tableMetadata, metadataMov: tableMetadata) { - - let fileNameImage = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadata.ocId, fileNameView: metadata.fileNameView)!) - let fileNameMov = URL(fileURLWithPath: CCUtility.getDirectoryProviderStorageOcId(metadataMov.ocId, fileNameView: metadataMov.fileNameView)!) - - DispatchQueue.main.async { - self.hud.textLabel.text = NSLocalizedString("_livephoto_save_", comment: "") - self.hud.detailTextLabel.text = "" - } - - NCLivePhoto.generate(from: fileNameImage, videoURL: fileNameMov, progress: { progress in - self.hud.progress = Float(progress) - }, completion: { _, resources in - if resources != nil { - NCLivePhoto.saveToLibrary(resources!) { result in - DispatchQueue.main.async { - if !result { - self.hud.indicatorView = JGProgressHUDErrorIndicatorView() - self.hud.textLabel.text = NSLocalizedString("_livephoto_save_error_", comment: "") - } else { - self.hud.indicatorView = JGProgressHUDSuccessIndicatorView() - self.hud.textLabel.text = NSLocalizedString("_success_", comment: "") - } - self.hud.dismiss() - } - return self.finish() - } - } else { - DispatchQueue.main.async { - self.hud.indicatorView = JGProgressHUDErrorIndicatorView() - self.hud.textLabel.text = NSLocalizedString("_livephoto_save_error_", comment: "") - self.hud.dismiss() - } - return self.finish() - } - }) - } -} diff --git a/iOSClient/Networking/NCService.swift b/iOSClient/Networking/NCService.swift index 677dab0b56..8dccd34e03 100644 --- a/iOSClient/Networking/NCService.swift +++ b/iOSClient/Networking/NCService.swift @@ -309,8 +309,9 @@ class NCService: NSObject { let files = NCManageDatabase.shared.getTableLocalFiles(predicate: NSPredicate(format: "account == %@ AND offline == true", account), sorted: "fileName", ascending: true) for file: tableLocalFile in files { guard let metadata = NCManageDatabase.shared.getMetadataFromOcId(file.ocId) else { continue } - if NCManageDatabase.shared.isDownloadMetadata(metadata, download: true) { - NCOperationQueue.shared.download(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile) + if NCManageDatabase.shared.isDownloadMetadata(metadata, download: true), + appDelegate.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty { + appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: NCGlobal.shared.selectorDownloadFile)) } } NextcloudKit.shared.nkCommonInstance.writeLog("[INFO] end synchronize offline") diff --git a/iOSClient/Notification/NCNotification.swift b/iOSClient/Notification/NCNotification.swift index 8ce907017b..ce8c306d57 100644 --- a/iOSClient/Notification/NCNotification.swift +++ b/iOSClient/Notification/NCNotification.swift @@ -154,7 +154,7 @@ class NCNotification: UITableViewController, NCNotificationCellDelegate, NCEmpty cell.avatar.image = image } else if !FileManager.default.fileExists(atPath: fileNameLocalPath) { cell.fileUser = user - NCOperationQueue.shared.downloadAvatar(user: user, dispalyName: json["user"]?["name"].string, fileName: fileName, cell: cell, view: tableView, cellImageView: cell.fileAvatarImageView) + NCNetworking.shared.downloadAvatar(user: user, dispalyName: json["user"]?["name"].string, fileName: fileName, cell: cell, view: tableView, cellImageView: cell.fileAvatarImageView) } } diff --git a/iOSClient/Select/NCSelect.swift b/iOSClient/Select/NCSelect.swift index 43c4a7989d..861790e533 100644 --- a/iOSClient/Select/NCSelect.swift +++ b/iOSClient/Select/NCSelect.swift @@ -319,7 +319,7 @@ extension NCSelect: UICollectionViewDataSource { activeAccount.account == metadata.account, let cell = cell as? NCCellProtocol { let fileName = metadata.userBaseUrl + "-" + metadata.ownerId + ".png" - NCOperationQueue.shared.downloadAvatar(user: metadata.ownerId, dispalyName: metadata.ownerDisplayName, fileName: fileName, cell: cell, view: collectionView, cellImageView: cell.fileAvatarImageView) + NCNetworking.shared.downloadAvatar(user: metadata.ownerId, dispalyName: metadata.ownerDisplayName, fileName: fileName, cell: cell, view: collectionView, cellImageView: cell.fileAvatarImageView) } } diff --git a/iOSClient/Share/NCShare.swift b/iOSClient/Share/NCShare.swift index 9127f3867c..88ac281538 100644 --- a/iOSClient/Share/NCShare.swift +++ b/iOSClient/Share/NCShare.swift @@ -371,7 +371,7 @@ extension NCShare: UITableViewDataSource { cell.delegate = self cell.setupCellUI(userId: appDelegate.userId) let fileName = appDelegate.userBaseUrl + "-" + tableShare.shareWith + ".png" - NCOperationQueue.shared.downloadAvatar(user: tableShare.shareWith, dispalyName: tableShare.shareWithDisplayname, fileName: fileName, cell: cell, view: tableView, cellImageView: cell.fileAvatarImageView) + NCNetworking.shared.downloadAvatar(user: tableShare.shareWith, dispalyName: tableShare.shareWithDisplayname, fileName: fileName, cell: cell, view: tableView, cellImageView: cell.fileAvatarImageView) return cell } } diff --git a/iOSClient/Viewer/NCViewerProviderContextMenu.swift b/iOSClient/Viewer/NCViewerProviderContextMenu.swift index 8dfa7fdd18..b2b3bd2187 100644 --- a/iOSClient/Viewer/NCViewerProviderContextMenu.swift +++ b/iOSClient/Viewer/NCViewerProviderContextMenu.swift @@ -116,28 +116,38 @@ class NCViewerProviderContextMenu: UIViewController { maxDownload = NCGlobal.shared.maxAutoDownload } - if metadata.size <= maxDownload { - NCOperationQueue.shared.download(metadata: metadata, selector: "") + if metadata.size <= maxDownload, + let appDelegate = (UIApplication.shared.delegate as? AppDelegate), + appDelegate.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty { + appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: "")) } } } // AUTO DOWNLOAD IMAGE GIF - if !CCUtility.fileProviderStorageExists(metadata) && metadata.contentType == "image/gif" { - NCOperationQueue.shared.download(metadata: metadata, selector: "") + if !CCUtility.fileProviderStorageExists(metadata), + metadata.contentType == "image/gif", + let appDelegate = (UIApplication.shared.delegate as? AppDelegate), + appDelegate.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty { + appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: "")) } // AUTO DOWNLOAD IMAGE SVG - if !CCUtility.fileProviderStorageExists(metadata) && metadata.contentType == "image/svg+xml" { - NCOperationQueue.shared.download(metadata: metadata, selector: "") + if !CCUtility.fileProviderStorageExists(metadata), + metadata.contentType == "image/svg+xml", + let appDelegate = (UIApplication.shared.delegate as? AppDelegate), + appDelegate.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty { + appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadata, selector: "")) } // AUTO DOWNLOAD LIVE PHOTO - if let metadataLivePhoto = self.metadataLivePhoto { - if !CCUtility.fileProviderStorageExists(metadataLivePhoto) { - NCOperationQueue.shared.download(metadata: metadataLivePhoto, selector: "") - } + if let metadataLivePhoto = self.metadataLivePhoto, + !CCUtility.fileProviderStorageExists(metadataLivePhoto), + let appDelegate = (UIApplication.shared.delegate as? AppDelegate), + appDelegate.downloadQueue.operations.filter({ ($0 as? NCOperationDownload)?.metadata.ocId == metadata.ocId }).isEmpty { + appDelegate.downloadQueue.addOperation(NCOperationDownload(metadata: metadataLivePhoto, selector: "")) } + } }