From 6fffa5705180fcd301fa98a6fd3b3bb0c7933dcd Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Mon, 29 Apr 2024 10:11:47 +0200 Subject: [PATCH 01/23] - update SDK --- ios-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-sdk b/ios-sdk index 7229c2019..8c5befbe6 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 7229c2019a8012c385cb4c151def94a2c5ea7964 +Subproject commit 8c5befbe694d59ea0af7ff2908454d1e82711d39 From ffbb8f25f281994a46921c9fbf4e66342612b6a7 Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Thu, 13 Jun 2024 14:46:39 +0200 Subject: [PATCH 02/23] - update SDK and adapt to API changes --- ios-sdk | 2 +- ownCloud File Provider/FileProviderExtension.m | 2 +- .../OCItem+UniversalItemListCellContentProvider.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ios-sdk b/ios-sdk index 8c5befbe6..97dbb7c57 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 8c5befbe694d59ea0af7ff2908454d1e82711d39 +Subproject commit 97dbb7c578bbb42ee415e9849e3bf04c5b78a3e7 diff --git a/ownCloud File Provider/FileProviderExtension.m b/ownCloud File Provider/FileProviderExtension.m index 527588bfa..d5270dfb0 100644 --- a/ownCloud File Provider/FileProviderExtension.m +++ b/ownCloud File Provider/FileProviderExtension.m @@ -487,7 +487,7 @@ - (void)stopProvidingItemAtURL:(NSURL *)url // Cancel download if the item is currently downloading if (item.isDownloading) { - if ((downloadProgress = [self.core progressForItem:(OCItem *)item matchingEventType:OCEventTypeDownload]) != nil) + if ((downloadProgress = [self.core progressForItemWithLocalID:((OCItem *)item).localID matchingEventType:OCEventTypeDownload]) != nil) { [downloadProgress makeObjectsPerformSelector:@selector(cancel)]; } diff --git a/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell Content Providers/OCItem+UniversalItemListCellContentProvider.swift b/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell Content Providers/OCItem+UniversalItemListCellContentProvider.swift index 71f9b541a..13b4848c6 100644 --- a/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell Content Providers/OCItem+UniversalItemListCellContentProvider.swift +++ b/ownCloudAppShared/Client/Collection Views/Cells/UniversalItemListCell Content Providers/OCItem+UniversalItemListCellContentProvider.swift @@ -238,7 +238,7 @@ extension OCItem: UniversalItemListCellContentProvider { var progress : Progress? if syncActivity.rawValue & (OCItemSyncActivity.downloading.rawValue | OCItemSyncActivity.uploading.rawValue) != 0, !hasMessageForItem { - progress = context?.core?.progress(for: self, matching: .none)?.first + progress = context?.core?.progressForItem(withLocalID: self.localID, matching: .none)?.first if progress == nil { progress = Progress.indeterminate() From cd17388088291c423ce5df6dcf16b6e65694d5d5 Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Thu, 13 Jun 2024 20:38:53 +0200 Subject: [PATCH 03/23] - update SDK to improve TUS upload reliability / error/termination recovery --- ios-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-sdk b/ios-sdk index 97dbb7c57..edd6ba932 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 97dbb7c578bbb42ee415e9849e3bf04c5b78a3e7 +Subproject commit edd6ba932a9061275c05dcc59f4b424ed4e68b18 From be3782d38c33b50a974408b2e5dff1db6cc5182f Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Thu, 27 Jun 2024 12:39:11 +0200 Subject: [PATCH 04/23] - update SDK to include TUS progress reporting and fix "UNKNOWN TASK" errors in HTTP layer --- ios-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-sdk b/ios-sdk index edd6ba932..d52f394ae 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit edd6ba932a9061275c05dcc59f4b424ed4e68b18 +Subproject commit d52f394aefeb327ec8123f38f282807c9a0b5156 From 5077254e5d28ef515c974c061470992d561cf701 Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Thu, 27 Jun 2024 12:42:19 +0200 Subject: [PATCH 05/23] - update SDK reference after rebase --- ios-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-sdk b/ios-sdk index d52f394ae..72b62a23d 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit d52f394aefeb327ec8123f38f282807c9a0b5156 +Subproject commit 72b62a23d097e7984f30bd63564babd6a6491f4c From b606c65a86a1c2bda313076969008ae80071bbbe Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Fri, 5 Jul 2024 22:56:36 +0200 Subject: [PATCH 06/23] - update SDK to auto-restart stuck Sync Actions --- ios-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-sdk b/ios-sdk index 72b62a23d..2f7039514 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 72b62a23d097e7984f30bd63564babd6a6491f4c +Subproject commit 2f7039514c22189066c3b5768d5b10d59fc51cb2 From 57b5ae83aea2f327d11a8eeadac5f088eabc3ba4 Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Tue, 16 Jul 2024 12:39:43 +0200 Subject: [PATCH 07/23] - ios-sdk: update SDK to include the latest fixes - ProgressView: add minimum + touch friendly sizes to avoid display as zero-sized views (which prevented cancelling by tapping because the touch never reached the view) --- ios-sdk | 2 +- .../User Interface/Progress/ProgressView.swift | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/ios-sdk b/ios-sdk index 2f7039514..04a208a19 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 2f7039514c22189066c3b5768d5b10d59fc51cb2 +Subproject commit 04a208a193e1f801cde8dbc11b21d5c91bdc361e diff --git a/ownCloudAppShared/User Interface/Progress/ProgressView.swift b/ownCloudAppShared/User Interface/Progress/ProgressView.swift index 2c2d333da..7a6167727 100644 --- a/ownCloudAppShared/User Interface/Progress/ProgressView.swift +++ b/ownCloudAppShared/User Interface/Progress/ProgressView.swift @@ -25,7 +25,8 @@ public class ProgressView: UIView, Themeable, CAAnimationDelegate, ThemeCSSAutoS var foregroundCircleLayer : CAShapeLayer = CAShapeLayer() var stopButtonLayer : CAShapeLayer = CAShapeLayer() - private let dimensions : CGSize = CGSize(width: 30, height: 30) + private let dimensions = CGSize(width: 30, height: 30) + private let minimumViewSize = CGSize(width: 50, height: 50) private let circleLineWidth : CGFloat = 3 private var _observerRegistered : Bool = false @@ -133,6 +134,16 @@ public class ProgressView: UIView, Themeable, CAAnimationDelegate, ThemeCSSAutoS self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.cancel))) + self.addConstraints([ + // Enforce minimum size of .dimensions + widthAnchor.constraint(greaterThanOrEqualToConstant: dimensions.width), + heightAnchor.constraint(greaterThanOrEqualToConstant: dimensions.height), + + // Nudge Auto Layout towards using .minimumViewSize (.dimensions + extra space to make a better touch target) while allowing individual "overrides" + widthAnchor.constraint(equalToConstant: minimumViewSize.width).with(priority: .defaultHigh), + heightAnchor.constraint(equalToConstant: minimumViewSize.height).with(priority: .defaultHigh) + ]) + NotificationCenter.default.addObserver(self, selector: #selector(self.appDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil) } From 808fb98d2064d03bdc032d35b287d296ec117bf6 Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Thu, 25 Jul 2024 22:47:04 +0200 Subject: [PATCH 08/23] - update SDK to gain flow control for Item Policy Processors - AvailableOfflineAction: fix bug where a folder selected for Available Offline could not be removed form Available Offline by action (due to Swift != comparison apparently not using -isEqual:) --- ios-sdk | 2 +- .../Actions/Actions+Extensions/AvailableOfflineAction.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-sdk b/ios-sdk index 04a208a19..35f930938 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 04a208a193e1f801cde8dbc11b21d5c91bdc361e +Subproject commit 35f930938f147e5166a71954b81d88d47051b4ef diff --git a/ownCloud/Client/Actions/Actions+Extensions/AvailableOfflineAction.swift b/ownCloud/Client/Actions/Actions+Extensions/AvailableOfflineAction.swift index aac9bf06a..3ff5d1499 100644 --- a/ownCloud/Client/Actions/Actions+Extensions/AvailableOfflineAction.swift +++ b/ownCloud/Client/Actions/Actions+Extensions/AvailableOfflineAction.swift @@ -38,7 +38,7 @@ class AvailableOfflineAction: Action { if let itemLocation = item.location, let policies = core.retrieveAvailableOfflinePoliciesCovering(item, completionHandler: nil) { for policy in policies { // Only show if item is not already available offline via parent item - if let policyLocation = policy.location, itemLocation.isLocated(in: policyLocation) && itemLocation != policyLocation { + if let policyLocation = policy.location, itemLocation.isLocated(in: policyLocation) && !itemLocation.isEqual(policyLocation) { return .none } } From 1bfec595590813f2f1fd4c2f0b69b3bbb85b8d47 Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Tue, 30 Jul 2024 14:43:01 +0200 Subject: [PATCH 09/23] - update SDK reference to include latest feature/policy-upgrades --- ios-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-sdk b/ios-sdk index 35f930938..e63df770e 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 35f930938f147e5166a71954b81d88d47051b4ef +Subproject commit e63df770e195cbfc9b20a01e0f1ded287f519ce8 From 7837e1bcae1a2664bfcb9e0c827a761f1f3d28a2 Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Tue, 30 Jul 2024 16:09:04 +0200 Subject: [PATCH 10/23] - update SDK commit reference --- ios-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-sdk b/ios-sdk index e63df770e..50c56a552 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit e63df770e195cbfc9b20a01e0f1ded287f519ce8 +Subproject commit 50c56a5522e367155d31df8d9b599c11a78b1569 From 291ae6785ddd27dd1922a9551d5519300e97f16b Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Tue, 13 Aug 2024 17:34:13 +0200 Subject: [PATCH 11/23] - fix Xcode 16 build error by upgrading OpenSSL from 3.1.5001 to 3.1.5006 (via https://github.com/krzyzanowskim/OpenSSL/issues/213) --- ios-sdk | 2 +- ownCloud.xcodeproj/project.pbxproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ios-sdk b/ios-sdk index 50c56a552..2a646a1e0 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 50c56a5522e367155d31df8d9b599c11a78b1569 +Subproject commit 2a646a1e056b6a4ae69ff564abe7711c7636b5d2 diff --git a/ownCloud.xcodeproj/project.pbxproj b/ownCloud.xcodeproj/project.pbxproj index 604f337b3..958f8fe81 100644 --- a/ownCloud.xcodeproj/project.pbxproj +++ b/ownCloud.xcodeproj/project.pbxproj @@ -6387,7 +6387,7 @@ repositoryURL = "https://github.com/krzyzanowskim/OpenSSL.git"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 3.1.5001; + minimumVersion = 3.1.5006; }; }; DCEAF08B28084B3800980B6D /* XCRemoteSwiftPackageReference "Down" */ = { From d5e0c3dbea619947ea2c26eb5b2ccfc6dcc2ede2 Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Wed, 14 Aug 2024 11:25:56 +0200 Subject: [PATCH 12/23] - update LastUpgradeCheck from Xcode 14.2 to Xcode 16 - fix protocol warnings new in Xcode 16 - adopt newer #unavailable syntax instead of if #available { /* Nothing */ } else { /* Code*/ } --- ios-sdk | 2 +- .../ShareExtensionViewController.swift | 2 +- ownCloud.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/MakeTVG.xcscheme | 2 +- .../xcschemes/ownCloud File Provider.xcscheme | 2 +- .../xcschemes/ownCloud File ProviderUI.xcscheme | 2 +- .../xcshareddata/xcschemes/ownCloud Intents.xcscheme | 2 +- .../xcschemes/ownCloud Share Extension.xcscheme | 2 +- .../xcshareddata/xcschemes/ownCloud.xcscheme | 2 +- .../xcshareddata/xcschemes/ownCloudApp.xcscheme | 2 +- .../xcschemes/ownCloudScreenshotsTests.xcscheme | 2 +- .../xcshareddata/xcschemes/ownCloudTests.xcscheme | 2 +- .../App Controllers/AccountController+ExtraItems.swift | 2 +- .../App Controllers/AccountController+ItemActions.swift | 8 ++++---- ownCloud/AppDelegate.swift | 2 +- ownCloud/SceneDelegate.swift | 6 +++--- ownCloud/Tools/VendorServices+App.swift | 2 +- ownCloudAppShared/Branding/Branding+App.swift | 2 +- ownCloudAppShared/Intent/OCLicenseManager+Setup.swift | 2 +- ownCloudAppShared/Tools/Log.swift | 2 +- ownCloudAppShared/UIKit Extension/UIView+OCDataItem.swift | 2 +- .../View Providers/OCResourceText+ViewProvider.swift | 2 +- 22 files changed, 27 insertions(+), 27 deletions(-) diff --git a/ios-sdk b/ios-sdk index 2a646a1e0..386dc6583 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 2a646a1e056b6a4ae69ff564abe7711c7636b5d2 +Subproject commit 386dc65836c695363d93187d791d7e65517fd0c0 diff --git a/ownCloud Share Extension/ShareExtensionViewController.swift b/ownCloud Share Extension/ShareExtensionViewController.swift index 9d640ea65..8de5a3b55 100644 --- a/ownCloud Share Extension/ShareExtensionViewController.swift +++ b/ownCloud Share Extension/ShareExtensionViewController.swift @@ -460,7 +460,7 @@ class ShareExtensionViewController: EmbeddingViewController, Themeable { } } -extension UserInterfaceContext : UserInterfaceContextProvider { +extension UserInterfaceContext : ownCloudAppShared.UserInterfaceContextProvider { public func provideRootView() -> UIView? { return ShareExtensionViewController.shared?.view } diff --git a/ownCloud.xcodeproj/project.pbxproj b/ownCloud.xcodeproj/project.pbxproj index 958f8fe81..52abe3abd 100644 --- a/ownCloud.xcodeproj/project.pbxproj +++ b/ownCloud.xcodeproj/project.pbxproj @@ -4171,7 +4171,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1500; - LastUpgradeCheck = 1420; + LastUpgradeCheck = 1600; ORGANIZATIONNAME = "ownCloud GmbH"; TargetAttributes = { 233BDE9B204FEFE500C06732 = { diff --git a/ownCloud.xcodeproj/xcshareddata/xcschemes/MakeTVG.xcscheme b/ownCloud.xcodeproj/xcshareddata/xcschemes/MakeTVG.xcscheme index 6aa2916ba..8496fa8c5 100644 --- a/ownCloud.xcodeproj/xcshareddata/xcschemes/MakeTVG.xcscheme +++ b/ownCloud.xcodeproj/xcshareddata/xcschemes/MakeTVG.xcscheme @@ -1,6 +1,6 @@ UISwipeActionsConfiguration? { if let hostViewController = context?.originatingViewController ?? context?.rootViewController { let deleteRowAction = UIContextualAction(style: .destructive, title: localizedDeleteTitle, handler: { [weak self, weak hostViewController] (_, _, completionHandler) in @@ -96,7 +96,7 @@ extension AccountController { } } -extension AccountController: DataItemContextMenuInteraction { +extension AccountController: ownCloudAppShared.DataItemContextMenuInteraction { public func composeContextMenuItems(in viewController: UIViewController?, location: OCExtensionLocationIdentifier, with context: ClientContext?) -> [UIMenuElement]? { if let hostViewController = context?.originatingViewController ?? context?.rootViewController { var menuItems: [UIMenuElement] = [] @@ -166,7 +166,7 @@ extension AccountController: DataItemContextMenuInteraction { } } -extension AccountController: DataItemDragInteraction { +extension AccountController: ownCloudAppShared.DataItemDragInteraction { public func provideDragItems(with context: ClientContext?) -> [UIDragItem]? { if let bookmark, let userActivity = openInNewWindowUserActivity(with: clientContext) { let itemProvider = NSItemProvider(item: bookmark, typeIdentifier: "com.owncloud.ios-app.ocbookmark") @@ -182,7 +182,7 @@ extension AccountController: DataItemDragInteraction { } } -extension AccountController: DataItemDropInteraction { +extension AccountController: ownCloudAppShared.DataItemDropInteraction { public func allowDropOperation(for session: UIDropSession, with context: ClientContext?) -> UICollectionViewDropProposal? { if session.localDragSession == nil { return nil diff --git a/ownCloud/AppDelegate.swift b/ownCloud/AppDelegate.swift index c359ecd1b..7e3175427 100644 --- a/ownCloud/AppDelegate.swift +++ b/ownCloud/AppDelegate.swift @@ -308,7 +308,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } } -extension UserInterfaceContext : UserInterfaceContextProvider { +extension UserInterfaceContext : ownCloudAppShared.UserInterfaceContextProvider { public func provideRootView() -> UIView? { return provideCurrentWindow() } diff --git a/ownCloud/SceneDelegate.swift b/ownCloud/SceneDelegate.swift index 408875bc0..b28419d2b 100644 --- a/ownCloud/SceneDelegate.swift +++ b/ownCloud/SceneDelegate.swift @@ -51,9 +51,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { window = ThemeWindow(windowScene: windowScene) window?.rootViewController = appRootViewController - if #available(iOS 16, *) { + if #unavailable(iOS 16) { + // Only needed prior to iOS 16 // From the console: "Manually adding the rootViewController's view to the view hierarchy is no longer supported. Please allow UIWindow to add the rootViewController's view to the view hierarchy itself." - } else { window?.addSubview(appRootViewController.view) } window?.makeKeyAndVisible() @@ -167,7 +167,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } } -extension ClientContext: ClientContextProvider { +extension ClientContext: ownCloudAppShared.ClientContextProvider { public func provideClientContext(for bookmarkUUID: UUID, completion: (Error?, ownCloudAppShared.ClientContext?) -> Void) { if let sceneDelegate = scene?.delegate as? SceneDelegate, let sections = sceneDelegate.appRootViewController.sidebarViewController?.allSections { diff --git a/ownCloud/Tools/VendorServices+App.swift b/ownCloud/Tools/VendorServices+App.swift index 00ca0f28f..7760a54de 100644 --- a/ownCloud/Tools/VendorServices+App.swift +++ b/ownCloud/Tools/VendorServices+App.swift @@ -112,7 +112,7 @@ extension VendorServices { } } -extension VendorServices: MFMailComposeViewControllerDelegate { +extension VendorServices: MessageUI.MFMailComposeViewControllerDelegate { public func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) { controller.dismiss(animated: true) } diff --git a/ownCloudAppShared/Branding/Branding+App.swift b/ownCloudAppShared/Branding/Branding+App.swift index f3753479a..31c674cc9 100644 --- a/ownCloudAppShared/Branding/Branding+App.swift +++ b/ownCloudAppShared/Branding/Branding+App.swift @@ -65,7 +65,7 @@ enum BrandingColorAlias: String, CaseIterable { case fileIconColor = "file-icon-color" } -extension Branding : BrandingInitialization { +extension Branding : ownCloudApp.BrandingInitialization { public static func initializeBranding() { self.registerOCClassSettingsDefaults([ .documentationURL : "https://doc.owncloud.com/ios-app/latest/", diff --git a/ownCloudAppShared/Intent/OCLicenseManager+Setup.swift b/ownCloudAppShared/Intent/OCLicenseManager+Setup.swift index 32ab62730..5b549d152 100644 --- a/ownCloudAppShared/Intent/OCLicenseManager+Setup.swift +++ b/ownCloudAppShared/Intent/OCLicenseManager+Setup.swift @@ -107,7 +107,7 @@ public extension OCClassSettingsKey { static var disableEnterpriseLicensing : OCClassSettingsKey { return OCClassSettingsKey(rawValue: "disable-enterprise-licensing") } } -extension OCLicenseManager : OCClassSettingsSupport { +extension OCLicenseManager : ownCloudSDK.OCClassSettingsSupport { public static var classSettingsIdentifier: OCClassSettingsIdentifier { return .licensing } diff --git a/ownCloudAppShared/Tools/Log.swift b/ownCloudAppShared/Tools/Log.swift index 0420204ae..d91a277f1 100644 --- a/ownCloudAppShared/Tools/Log.swift +++ b/ownCloudAppShared/Tools/Log.swift @@ -99,7 +99,7 @@ public class Log { } } -extension OCLogger : OCLogIntroFormat { +extension OCLogger : ownCloudSDK.OCLogIntroFormat { public func logIntroFormat() -> String { return "{{stdIntro}}; Log options: \(Log.logOptionStatus)" } diff --git a/ownCloudAppShared/UIKit Extension/UIView+OCDataItem.swift b/ownCloudAppShared/UIKit Extension/UIView+OCDataItem.swift index 697ad3dc2..c6d4b9279 100644 --- a/ownCloudAppShared/UIKit Extension/UIView+OCDataItem.swift +++ b/ownCloudAppShared/UIKit Extension/UIView+OCDataItem.swift @@ -19,7 +19,7 @@ import UIKit import ownCloudSDK -extension UIView : OCDataItem, OCDataItemVersioning { +extension UIView : ownCloudSDK.OCDataItem, ownCloudSDK.OCDataItemVersioning { private static let associatedKeyViewUUID = malloc(1)! public var dataItemType: OCDataItemType { diff --git a/ownCloudAppShared/User Interface/View Providers/OCResourceText+ViewProvider.swift b/ownCloudAppShared/User Interface/View Providers/OCResourceText+ViewProvider.swift index 963905eff..7b845ffaf 100644 --- a/ownCloudAppShared/User Interface/View Providers/OCResourceText+ViewProvider.swift +++ b/ownCloudAppShared/User Interface/View Providers/OCResourceText+ViewProvider.swift @@ -45,7 +45,7 @@ class ThemeableTextView : UITextView, Themeable { } } -extension OCResourceText : OCViewProvider { +extension OCResourceText : ownCloudSDK.OCViewProvider { public func provideView(for size: CGSize, in context: OCViewProviderContext?, completion completionHandler: @escaping (UIView?) -> Void) { var attributedText : NSAttributedString? From 3c055f69584932650dece2afd285b1bc1df8ae53 Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Tue, 20 Aug 2024 09:10:13 +0200 Subject: [PATCH 13/23] - Reduce memory footprint of File Provider by removing ownCloudApp.framework as a dependency - and thereby its dependencies, especially OpenSSL.framework, which adds to the memory footprint. The dependency on ownCloudApp is removed by adding the few parts relevant to the FileProvider to the FileProvider target and directly including the respective header files. - MediaUploadOperation: no longer use File Provider for imports from the photo library due to stability issues --- ios-sdk | 2 +- .../FileProviderContentEnumerator.m | 6 +- .../FileProviderExtension.h | 1 - .../FileProviderExtension.m | 17 +++++- .../FileProviderServiceSource.m | 7 ++- ownCloud.xcodeproj/project.pbxproj | 60 +++++++++++++------ .../Media Uploads/MediaUploadOperation.swift | 8 ++- 7 files changed, 74 insertions(+), 27 deletions(-) diff --git a/ios-sdk b/ios-sdk index 386dc6583..3622a2344 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 386dc65836c695363d93187d791d7e65517fd0c0 +Subproject commit 3622a2344b5ee76c01dfdea21b51c7c07c22eb26 diff --git a/ownCloud File Provider/FileProviderContentEnumerator.m b/ownCloud File Provider/FileProviderContentEnumerator.m index 9578b211b..883cd4ff2 100644 --- a/ownCloud File Provider/FileProviderContentEnumerator.m +++ b/ownCloud File Provider/FileProviderContentEnumerator.m @@ -16,7 +16,11 @@ * */ -#import +#import + +// BEGIN: Shared with ownCloudApp.framework +#import "DisplaySettings.h" +// END: shared with ownCloudApp.framework #import "FileProviderContentEnumerator.h" #import "FileProviderEnumeratorObserver.h" diff --git a/ownCloud File Provider/FileProviderExtension.h b/ownCloud File Provider/FileProviderExtension.h index dc271abc8..8f13e2be4 100644 --- a/ownCloud File Provider/FileProviderExtension.h +++ b/ownCloud File Provider/FileProviderExtension.h @@ -33,7 +33,6 @@ extern OCClaimExplicitIdentifier OCClaimExplicitIdentifierFileProvider; -extern OCClassSettingsIdentifier OCClassSettingsIdentifierFileProvider; extern OCClassSettingsKey OCClassSettingsKeyFileProviderSkipLocalErrorChecks; #define FPLogCmdBegin(command, format,...) \ diff --git a/ownCloud File Provider/FileProviderExtension.m b/ownCloud File Provider/FileProviderExtension.m index d5270dfb0..19f618932 100644 --- a/ownCloud File Provider/FileProviderExtension.m +++ b/ownCloud File Provider/FileProviderExtension.m @@ -17,7 +17,21 @@ */ #import -#import + +// BEGIN: Shared with ownCloudApp.framework +#import "Branding.h" +#import "BrandingClassSettingsSource.h" +#import "NotificationManager.h" +#import "NotificationMessagePresenter.h" +#import "NotificationAuthErrorForwarder.h" +#import "OCBookmark+AppExtensions.h" +#import "OCBookmark+FPServices.h" +#import "OCCore+BundleImport.h" +#import "OCFileProviderSettings.h" +#import "VFSManager.h" +#import "AppLockSettings.h" +#import "ZIPArchive.h" +// END: shared with ownCloudApp.framework #import "FileProviderExtension.h" #import "OCItem+FileProviderItem.h" @@ -1382,7 +1396,6 @@ - (BOOL)skipLocalErrorChecks @end OCClaimExplicitIdentifier OCClaimExplicitIdentifierFileProvider = @"fileProvider"; -OCClassSettingsIdentifier OCClassSettingsIdentifierFileProvider = @"file-provider"; OCClassSettingsKey OCClassSettingsKeyFileProviderSkipLocalErrorChecks = @"skip-local-error-checks"; /* diff --git a/ownCloud File Provider/FileProviderServiceSource.m b/ownCloud File Provider/FileProviderServiceSource.m index 0f20d6616..9ebd89f73 100644 --- a/ownCloud File Provider/FileProviderServiceSource.m +++ b/ownCloud File Provider/FileProviderServiceSource.m @@ -17,7 +17,12 @@ */ #import "FileProviderServiceSource.h" -#import + +// BEGIN: Shared with ownCloudApp.framework +#import "OCFileProviderService.h" +#import "OCCore+BundleImport.h" +// END: Shared with ownCloudApp.framework + #import @interface OCCore (setNeedsToProcessSyncRecords) diff --git a/ownCloud.xcodeproj/project.pbxproj b/ownCloud.xcodeproj/project.pbxproj index 52abe3abd..094215eef 100644 --- a/ownCloud.xcodeproj/project.pbxproj +++ b/ownCloud.xcodeproj/project.pbxproj @@ -217,6 +217,21 @@ DC0A35A124C1091400FB58FC /* UserInterfaceContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC0A35A024C1091400FB58FC /* UserInterfaceContext.swift */; }; DC0A5C432550C70800E6674B /* class-settings-sdk in Resources */ = {isa = PBXBuildFile; fileRef = DC0A5C422550C70800E6674B /* class-settings-sdk */; }; DC0CE19D28C89CD9009ABDFB /* CreateDocumentAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC0CE19C28C89CD9009ABDFB /* CreateDocumentAction.swift */; }; + DC1251DF2C746F450040FBC6 /* DisplaySettings.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC0857D2293F2D7008CC05C /* DisplaySettings.m */; }; + DC1251E02C746F8D0040FBC6 /* NotificationMessagePresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC832E7242CB18700153F8C /* NotificationMessagePresenter.m */; }; + DC1251E12C746FA60040FBC6 /* NotificationAuthErrorForwarder.m in Sources */ = {isa = PBXBuildFile; fileRef = DCDBB60325252FDA00FAD707 /* NotificationAuthErrorForwarder.m */; }; + DC1251E22C746FFF0040FBC6 /* VFSManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DCEA7F40282D3B110050A3C0 /* VFSManager.m */; }; + DC1251E32C7470080040FBC6 /* OCVault+VFSManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DC49B55828365C5F00DAF13B /* OCVault+VFSManager.m */; }; + DC1251E42C7470180040FBC6 /* OCFileProviderSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6179E628E0578400C7C4E0 /* OCFileProviderSettings.m */; }; + DC1251E52C74703F0040FBC6 /* OCBookmark+FPServices.m in Sources */ = {isa = PBXBuildFile; fileRef = DCF2DA8024C836240026D790 /* OCBookmark+FPServices.m */; }; + DC1251E62C7470820040FBC6 /* Branding.m in Sources */ = {isa = PBXBuildFile; fileRef = DC24B27225B9DF31005783E2 /* Branding.m */; }; + DC1251E72C74708B0040FBC6 /* BrandingClassSettingsSource.m in Sources */ = {isa = PBXBuildFile; fileRef = DCB2C05E250C1F9E001083CA /* BrandingClassSettingsSource.m */; }; + DC1251E82C7470C30040FBC6 /* OCBookmark+AppExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = DC7C100F24B5F81E00227085 /* OCBookmark+AppExtensions.m */; }; + DC1251E92C7470F80040FBC6 /* AppLockSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = DC6A0E5326EA9E740076B533 /* AppLockSettings.m */; }; + DC1251EA2C7471620040FBC6 /* OCCore+BundleImport.m in Sources */ = {isa = PBXBuildFile; fileRef = DC774E6222F44E6D000B11A1 /* OCCore+BundleImport.m */; }; + DC1251EB2C74716A0040FBC6 /* ZIPArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = DC774E5D22F44E4A000B11A1 /* ZIPArchive.m */; }; + DC1251EC2C74718B0040FBC6 /* libzip.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCE93FF321FCA434000E14F2 /* libzip.framework */; }; + DC1251F42C7474910040FBC6 /* NotificationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC832EA242CB4D600153F8C /* NotificationManager.m */; }; DC1621352B8FE26200EB17F8 /* OCVault+SidebarItems.h in Headers */ = {isa = PBXBuildFile; fileRef = DC1621332B8FE26200EB17F8 /* OCVault+SidebarItems.h */; settings = {ATTRIBUTES = (Public, ); }; }; DC1621362B8FE26200EB17F8 /* OCVault+SidebarItems.m in Sources */ = {isa = PBXBuildFile; fileRef = DC1621342B8FE26200EB17F8 /* OCVault+SidebarItems.m */; }; DC1621382B8FE9BF00EB17F8 /* AddToSidebarAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC1621372B8FE9BF00EB17F8 /* AddToSidebarAction.swift */; }; @@ -505,7 +520,6 @@ DCC0857B2293F29F008CC05C /* ownCloudSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 239369782076110900BCE21A /* ownCloudSDK.framework */; }; DCC0857F2293F48D008CC05C /* DisplaySettings.m in Sources */ = {isa = PBXBuildFile; fileRef = DCC0857D2293F2D7008CC05C /* DisplaySettings.m */; }; DCC085802293F490008CC05C /* DisplaySettings.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC0857C2293F2D7008CC05C /* DisplaySettings.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DCC085812293F66D008CC05C /* ownCloudApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC0855C2293F1FD008CC05C /* ownCloudApp.framework */; }; DCC3700724D466D2008B0DEB /* DiagnosticManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC3700624D466D2008B0DEB /* DiagnosticManager.swift */; }; DCC3701624D4D365008B0DEB /* OCScanJobActivity+DiagnosticGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC3701524D4D365008B0DEB /* OCScanJobActivity+DiagnosticGenerator.swift */; }; DCC5E4472326564F002E5B84 /* NSObject+AnnotatedProperties.h in Headers */ = {isa = PBXBuildFile; fileRef = DCC5E444232654DE002E5B84 /* NSObject+AnnotatedProperties.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -900,13 +914,6 @@ remoteGlobalIDString = DCC8F9AA202852A200EB6701; remoteInfo = ownCloudSDK; }; - DCC085822293F671008CC05C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 233BDE94204FEFE500C06732 /* Project object */; - proxyType = 1; - remoteGlobalIDString = DCC0855B2293F1FD008CC05C; - remoteInfo = ownCloudApp; - }; DCC6566320C9B7E400110A97 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 233BDE94204FEFE500C06732 /* Project object */; @@ -1283,6 +1290,9 @@ DC0B37962051681600189B9A /* ThemeButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeButton.swift; sourceTree = ""; }; DC0CE19128C7DBE3009ABDFB /* OpenInWebAppAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenInWebAppAction.swift; sourceTree = ""; }; DC0CE19C28C89CD9009ABDFB /* CreateDocumentAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateDocumentAction.swift; sourceTree = ""; }; + DC1251ED2C7474100040FBC6 /* FileProvider.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FileProvider.framework; path = System/Library/Frameworks/FileProvider.framework; sourceTree = SDKROOT; }; + DC1251F02C74743E0040FBC6 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + DC1251F22C7474500040FBC6 /* LocalAuthentication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LocalAuthentication.framework; path = System/Library/Frameworks/LocalAuthentication.framework; sourceTree = SDKROOT; }; DC136581208223F000FC0F60 /* OCBookmark+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OCBookmark+Extension.swift"; sourceTree = ""; }; DC1621332B8FE26200EB17F8 /* OCVault+SidebarItems.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OCVault+SidebarItems.h"; sourceTree = ""; }; DC1621342B8FE26200EB17F8 /* OCVault+SidebarItems.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OCVault+SidebarItems.m"; sourceTree = ""; }; @@ -1840,11 +1850,11 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - DCC085812293F66D008CC05C /* ownCloudApp.framework in Frameworks */, + DC27A18F20CAA0BA008ACB6C /* ownCloudSDK.framework in Frameworks */, + DC1251EC2C74718B0040FBC6 /* libzip.framework in Frameworks */, 02AE32E424D2FA8B00A19476 /* CrashReporter in Frameworks */, DC2565EE225F5A1900828AA5 /* UserNotifications.framework in Frameworks */, DC973BBE24A28ED0001DEEC4 /* CoreServices.framework in Frameworks */, - DC27A18F20CAA0BA008ACB6C /* ownCloudSDK.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2908,6 +2918,9 @@ DC85573220513CC700189B9A /* Frameworks */ = { isa = PBXGroup; children = ( + DC1251F22C7474500040FBC6 /* LocalAuthentication.framework */, + DC1251F02C74743E0040FBC6 /* UIKit.framework */, + DC1251ED2C7474100040FBC6 /* FileProvider.framework */, DCEC3DE3242F665D0076B43C /* CoreServices.framework */, DC080CF0238C8D850044C5D2 /* StoreKit.framework */, DC2565E8225F5A1900828AA5 /* UserNotifications.framework */, @@ -4134,7 +4147,6 @@ ); dependencies = ( DC27A19320CAA0C6008ACB6C /* PBXTargetDependency */, - DCC085832293F671008CC05C /* PBXTargetDependency */, ); name = "ownCloud File Provider"; packageProductDependencies = ( @@ -5123,17 +5135,31 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DC1251E22C746FFF0040FBC6 /* VFSManager.m in Sources */, + DC1251E42C7470180040FBC6 /* OCFileProviderSettings.m in Sources */, + DC1251E12C746FA60040FBC6 /* NotificationAuthErrorForwarder.m in Sources */, + DC1251E32C7470080040FBC6 /* OCVault+VFSManager.m in Sources */, + DC1251F42C7474910040FBC6 /* NotificationManager.m in Sources */, + DC1251EB2C74716A0040FBC6 /* ZIPArchive.m in Sources */, DC2218C62822C5B900808BCE /* OCVFSNode+FileProviderItem.m in Sources */, + DC1251E72C74708B0040FBC6 /* BrandingClassSettingsSource.m in Sources */, DC98BBD420FF824600F4ED3E /* FileProviderEnumeratorObserver.m in Sources */, + DC1251E62C7470820040FBC6 /* Branding.m in Sources */, DC2218CC2823329100808BCE /* FileProviderContentEnumerator.m in Sources */, DC27A1E920CC56B0008ACB6C /* FileProviderExtensionThumbnailRequest.m in Sources */, DCF2DA7A24C82E480026D790 /* FileProviderServiceSource.m in Sources */, DC625141225C904700736874 /* NSError+MessageResolution.m in Sources */, DC27A1A820CC095C008ACB6C /* OCCore+FileProviderTools.m in Sources */, + DC1251E82C7470C30040FBC6 /* OCBookmark+AppExtensions.m in Sources */, + DC1251E52C74703F0040FBC6 /* OCBookmark+FPServices.m in Sources */, + DC1251E92C7470F80040FBC6 /* AppLockSettings.m in Sources */, + DC1251DF2C746F450040FBC6 /* DisplaySettings.m in Sources */, DCC6564A20C9B7E400110A97 /* FileProviderExtension.m in Sources */, DC27A1A520CBEF85008ACB6C /* OCBookmark+FileProvider.m in Sources */, DC27A18E20CA9F66008ACB6C /* OCItem+FileProviderItem.m in Sources */, + DC1251EA2C7471620040FBC6 /* OCCore+BundleImport.m in Sources */, DC98BBCB20FF815C00F4ED3E /* NSNumber+OCSyncAnchorData.m in Sources */, + DC1251E02C746F8D0040FBC6 /* NotificationMessagePresenter.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5314,11 +5340,6 @@ name = ownCloudSDK; targetProxy = DCC085792293F296008CC05C /* PBXContainerItemProxy */; }; - DCC085832293F671008CC05C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = DCC0855B2293F1FD008CC05C /* ownCloudApp */; - targetProxy = DCC085822293F671008CC05C /* PBXContainerItemProxy */; - }; DCC6566420C9B7E400110A97 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = DCC6564520C9B7E300110A97 /* ownCloud File Provider */; @@ -5793,9 +5814,10 @@ CODE_SIGN_ENTITLEMENTS = "ownCloud Action Extension/ownCloud Action Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = "$(APP_VERSION)"; - DEVELOPMENT_TEAM = 4AP2STM4H5; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 4AP2STM4H5; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; GENERATE_INFOPLIST_FILE = YES; @@ -5813,6 +5835,8 @@ MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.owncloud.ios-app.ownCloud-Action-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.owncloud.ios-app.ownCloud-Action-Extension"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; diff --git a/ownCloud/Media Uploads/MediaUploadOperation.swift b/ownCloud/Media Uploads/MediaUploadOperation.swift index 75b6a83c6..37aaec9b2 100644 --- a/ownCloud/Media Uploads/MediaUploadOperation.swift +++ b/ownCloud/Media Uploads/MediaUploadOperation.swift @@ -37,9 +37,11 @@ class MediaUploadOperation : Operation { self.core = core self.mediaUploadJob = mediaUploadJob self.assetId = assetId - if let vault = self.core?.vault { - self.fpSession = OCFileProviderServiceSession(vault: vault) - } + + // Disable FileProvider usage due to XPC / stability issues + // if let vault = self.core?.vault { + // self.fpSession = OCFileProviderServiceSession(vault: vault) + // } } override func main() { From 4e109a5cf4d123949488203253481643a493e39b Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Tue, 27 Aug 2024 22:13:10 +0200 Subject: [PATCH 14/23] =?UTF-8?q?-=20update=20ios-sdk=20-=20ProgressSummar?= =?UTF-8?q?izer:=20add=20method=20to=20reset=20priority=20summaries=20-=20?= =?UTF-8?q?AccountConnection:=20clear=20priority=20summaries=20after=20dis?= =?UTF-8?q?connect=20to=20return=20them=20to=20a=20defined=20state=20(fixe?= =?UTF-8?q?s=20"Connecting=E2=80=A6"=20being=20shown=20forever=20after=20a?= =?UTF-8?q?=20re-login)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios-sdk | 2 +- .../Client/Account/Connection/AccountConnection.swift | 4 +++- .../User Interface/Progress/ProgressSummarizer.swift | 9 +++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/ios-sdk b/ios-sdk index 3622a2344..3190d092d 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 3622a2344b5ee76c01dfdea21b51c7c07c22eb26 +Subproject commit 3190d092d49ee122dfeda40043c0ffe7188fc4da diff --git a/ownCloudAppShared/Client/Account/Connection/AccountConnection.swift b/ownCloudAppShared/Client/Account/Connection/AccountConnection.swift index 68e620d1d..8e60dc852 100644 --- a/ownCloudAppShared/Client/Account/Connection/AccountConnection.swift +++ b/ownCloudAppShared/Client/Account/Connection/AccountConnection.swift @@ -295,11 +295,13 @@ open class AccountConnection: NSObject { connection.fpServiceStandby?.stop() // Return core - OCCoreManager.shared.returnCore(for: self.bookmark, completionHandler: { + OCCoreManager.shared.returnCore(for: self.bookmark, completionHandler: { [weak self] in connection.richStatus = nil connection.core = nil connection.status = .noCore + self?.progressSummarizer.resetPrioritySummaries() + OnMainThread { completion?(nil) } diff --git a/ownCloudAppShared/User Interface/Progress/ProgressSummarizer.swift b/ownCloudAppShared/User Interface/Progress/ProgressSummarizer.swift index 4712cbf08..7048c60ae 100644 --- a/ownCloudAppShared/User Interface/Progress/ProgressSummarizer.swift +++ b/ownCloudAppShared/User Interface/Progress/ProgressSummarizer.swift @@ -330,6 +330,15 @@ public class ProgressSummarizer: NSObject { } } + public func resetPrioritySummaries() { + OCSynchronized(self) { + Log.debug("Reset priority summaries") + + prioritySummaries.removeAll() + self.prioritySummary = nil + } + } + // MARK: - Change notifications private var observers : [ProgressSummaryNotificationObserver] = [] public func addObserver(_ observer: AnyObject, notificationBlock: @escaping ProgressSummarizerNotificationBlock) { From ed38ee01c0bb5245ef7fc6581a0fe6f57f30df39 Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Tue, 27 Aug 2024 23:09:24 +0200 Subject: [PATCH 15/23] - update SDK to incorporate fix --- ios-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-sdk b/ios-sdk index 3190d092d..170d3f098 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 3190d092d49ee122dfeda40043c0ffe7188fc4da +Subproject commit 170d3f098a780db637162dd8fff87118dd2bceda From 2ba3eeec65ee23aad09e3bfbb3643b1188d8f788 Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Tue, 27 Aug 2024 23:37:29 +0200 Subject: [PATCH 16/23] - SDK update to reduce memory footprint further --- ios-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-sdk b/ios-sdk index 170d3f098..1bc138a9e 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 170d3f098a780db637162dd8fff87118dd2bceda +Subproject commit 1bc138a9e1610930d645bc047ecffd5f15787f40 From ec44666f128ae0247ed767b20d2b7147569eca42 Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Wed, 28 Aug 2024 11:12:25 +0200 Subject: [PATCH 17/23] - SDK update (with fixes) - FileProviderExtension: fix spurious "invalid parameter" error on import --- ios-sdk | 2 +- ownCloud File Provider/FileProviderExtension.m | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ios-sdk b/ios-sdk index 1bc138a9e..8f32ea5cf 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 1bc138a9e1610930d645bc047ecffd5f15787f40 +Subproject commit 8f32ea5cf9dad763557fd9d0711174e96f40ee8e diff --git a/ownCloud File Provider/FileProviderExtension.m b/ownCloud File Provider/FileProviderExtension.m index 19f618932..d1fa79307 100644 --- a/ownCloud File Provider/FileProviderExtension.m +++ b/ownCloud File Provider/FileProviderExtension.m @@ -800,6 +800,7 @@ - (void)importDocumentAtURL:(NSURL *)fileURL toParentItemIdentifier:(NSFileProvi OCCoreOptionImportByCopying : @(importByCopying) } placeholderCompletionHandler:^(NSError *error, OCItem *item) { FPLogCmd(@"Completed with placeholderItem=%@, error=%@", item, error); + item.bookmarkUUID = self.core.bookmark.uuid.UUIDString; // ensure bookmarkUUID is present so that vfsItemID / itemIdentifier succeed completionHandler(item, [error translatedError]); } resultHandler:^(NSError *error, OCCore *core, OCItem *item, id parameter) { if ([error.domain isEqual:OCHTTPStatusErrorDomain] && (error.code == OCHTTPStatusCodePRECONDITION_FAILED)) From 74be5b5528d74597d1202ef035929ff253437ca8 Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Mon, 2 Sep 2024 22:02:09 +0200 Subject: [PATCH 18/23] - File Provider Extension: add code that handles iOS 18 requests for downloading folder items --- ownCloud File Provider/FileProviderExtension.m | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ownCloud File Provider/FileProviderExtension.m b/ownCloud File Provider/FileProviderExtension.m index d1fa79307..c60a2cbd3 100644 --- a/ownCloud File Provider/FileProviderExtension.m +++ b/ownCloud File Provider/FileProviderExtension.m @@ -376,6 +376,12 @@ - (void)startProvidingItemAtURL:(NSURL *)provideAtURL completionHandler:(void (^ { FPLogCmdBegin(@"StartProviding", @"Downloading %@", item); + if (((OCItem *)item).type == OCItemTypeCollection) { + // Can't download folders + completionHandler([NSError errorWithDomain:NSCocoaErrorDomain code:NSFeatureUnsupportedError userInfo:@{}]); + return; + } + [self.core downloadItem:(OCItem *)item options:@{ OCCoreOptionAddFileClaim : [OCClaim claimForLifetimeOfCore:core explicitIdentifier:OCClaimExplicitIdentifierFileProvider withLockType:OCClaimLockTypeRead] From 919eef40226c6b86b6e32e2de43ca5afeab7ad6a Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Thu, 5 Sep 2024 18:41:44 +0200 Subject: [PATCH 19/23] - ShareExtensionViewController: - rewrite/refactor to upload files directly from the extension rather than through the File Provider - automatically try to avoid name collisions on upload - ProgressIndicatorViewController: - fix lack of themeing by adding the modal CSS selector to the view controller - update the displayed progress from the Progress instance set on the .progress property --- ios-sdk | 2 +- .../ShareExtensionViewController.swift | 264 +++++++++++------- .../ProgressIndicatorViewController.swift | 3 + 3 files changed, 172 insertions(+), 97 deletions(-) diff --git a/ios-sdk b/ios-sdk index 8f32ea5cf..8c0fddb15 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 8f32ea5cf9dad763557fd9d0711174e96f40ee8e +Subproject commit 8c0fddb15240b70463f33a17279c8a63ef328585 diff --git a/ownCloud Share Extension/ShareExtensionViewController.swift b/ownCloud Share Extension/ShareExtensionViewController.swift index 8de5a3b55..2ccf0659e 100644 --- a/ownCloud Share Extension/ShareExtensionViewController.swift +++ b/ownCloud Share Extension/ShareExtensionViewController.swift @@ -26,6 +26,9 @@ extension NSErrorDomain { static let ShareErrorDomain = "ShareErrorDomain" } +private let unitCountForImport: Int64 = 50 +private let unitCountForUpload: Int64 = 100 + @objc(ShareExtensionViewController) class ShareExtensionViewController: EmbeddingViewController, Themeable { // MARK: - Initialization @@ -93,62 +96,104 @@ class ShareExtensionViewController: EmbeddingViewController, Themeable { var fpServiceSession : OCFileProviderServiceSession? var asyncQueue : OCAsyncSequentialQueue = OCAsyncSequentialQueue() + var progressViewController: ProgressIndicatorViewController? + var uploadCoreProgress: Progress? + func importTo(selectedFolder: OCItem?, location: OCLocation?) { - if let targetFolder = selectedFolder, let bookmarkUUID = targetFolder.bookmarkUUID { + if let targetFolder = selectedFolder, let bookmarkUUID = targetFolder.bookmarkUUID ?? location?.bookmarkUUID?.uuidString { if let bookmark = OCBookmarkManager.shared.bookmark(forUUIDString: bookmarkUUID) { - let vault = OCVault(bookmark: bookmark) - self.fpServiceSession = OCFileProviderServiceSession(vault: vault) - OnMainThread { - let progressViewController = ProgressIndicatorViewController(initialProgressLabel: "Preparing…".localized, progress: nil, cancelHandler: {}) - - self.contentViewController = progressViewController + self.progressViewController = ProgressIndicatorViewController(initialProgressLabel: "Preparing…".localized, progress: nil, cancelHandler: { [weak self] in + self?.uploadCoreProgress?.cancel() // Cancel transfers (!) via Progress instances provided by upload methods + self?.cancel() + }) + self.contentViewController = self.progressViewController + + let importCompletionHandler : ((_ error: Error?) -> Void) = { [weak self] (error) in + self?.finish(with: error) + } - AccountConnectionPool.shared.disconnectAll { - OnMainThread { - if let fpServiceSession = self.fpServiceSession { - self.importFiles(to: targetFolder, serviceSession: fpServiceSession, progressViewController: progressViewController, completion: { [weak self] (error) in - OnMainThread { - if let error = error { - self?.extensionContext?.cancelRequest(withError: error) - } else { - self?.extensionContext?.completeRequest(returningItems: []) - } - } - }) + if let accountConnection = AccountConnectionPool.shared.connection(for: bookmark) { + // Account found - connect (just in case it's not) + accountConnection.connect { error in + if let error { + // Error connecting + Log.error("Share Extension could not connect: \(String(describing: error))") + self.finish(with: error) + } else if let core = accountConnection.core { + // Import files + OnMainThread { + self.importFiles(to: targetFolder, core: core, completion: importCompletionHandler) + } + } else { + // Error retrieving core for connection after connect (should never happen) + Log.error("Share Extension could not retrieve core for connection") + self.finish(with: NSError(ocError: .internal)) } } + } else { + // Account not found - this should not be possible + self.finish(with: NSError(ocError: .internal)) } } } } } - func importFiles(to targetDirectory : OCItem, serviceSession: OCFileProviderServiceSession, progressViewController: ProgressIndicatorViewController?, completion: @escaping (_ error: Error?) -> Void) { + func importFiles(to targetDirectory : OCItem, core: OCCore, completion: @escaping (_ error: Error?) -> Void) { if let inputItems : [NSExtensionItem] = self.extensionContext?.inputItems as? [NSExtensionItem] { - var totalItems : Int = 0 - var importedItems : Int = 0 - var importError : Error? + var totalItems : Int64 = 0 + var importedItems : Int64 = 0 + var uploadedItems : Int64 = 0 + var importProgress: Progress + var uploadProgress: Progress + var totalProgress: Progress + var uploadError: Error? + let uploadWaitGroup: DispatchGroup = DispatchGroup() for item : NSExtensionItem in inputItems { if let attachments = item.attachments { - totalItems += attachments.count + totalItems += Int64(attachments.count) } } - let incrementImportedFile : () -> Void = { [weak progressViewController] in + importProgress = Progress(totalUnitCount: totalItems) + uploadProgress = Progress(totalUnitCount: totalItems) + totalProgress = Progress(totalUnitCount: (unitCountForImport + unitCountForUpload) * totalItems) + totalProgress.addChild(importProgress, withPendingUnitCount: unitCountForImport * totalItems) + totalProgress.addChild(uploadProgress, withPendingUnitCount: unitCountForUpload * totalItems) + self.progressViewController?.progress = totalProgress + + uploadCoreProgress = Progress(totalUnitCount: totalItems) + + let incrementImportCounter = { + // Increment progress importedItems += 1 OnMainThread { - progressViewController?.update(progress: Float(importedItems)/Float(totalItems), text: NSString(format: "Importing item %ld of %ld".localized as NSString, importedItems, totalItems) as String) + importProgress.completedUnitCount = importedItems + totalProgress.localizedDescription = NSString(format: "Importing item %ld of %ld".localized as NSString, importedItems, totalItems) as String + // self.progressViewController?.update(text: NSString(format: "Importing item %ld of %ld".localized as NSString, importedItems, totalItems) as String) } } - // Keep session open - serviceSession.acquireFileProviderServicesHost(completionHandler: { (_, _, doneHandler) in - serviceSession.incrementSessionUsage() - doneHandler?() - }, errorHandler: { (_) in }) + let updateUploadMessage = { + OnMainThread { + if importedItems == totalItems { + totalProgress.localizedDescription = "Uploading {{remainingFileCount}} files…".localized(["remainingFileCount" : "\(totalItems - uploadedItems)"]) + } + } + } + + let handleUploadResult: (_ error: Error?) -> Void = { (error) in + if let error { + uploadError = error + } + uploadProgress.completedUnitCount += 1 + uploadedItems += 1 + updateUploadMessage() + uploadWaitGroup.leave() + } for item : NSExtensionItem in inputItems { if let attachments = item.attachments { @@ -160,15 +205,20 @@ class ShareExtensionViewController: EmbeddingViewController, Themeable { if var type = attachment.registeredTypeIdentifiers.first, attachment.hasItemConformingToTypeIdentifier(UTType.item.identifier) { if type == "public.plain-text" || type == "public.url" || attachment.registeredTypeIdentifiers.contains("public.file-url") { asyncQueue.async({ (jobDone) in - if progressViewController?.cancelled == true { + if self.progressViewController?.cancelled == true { jobDone() return } + + incrementImportCounter() + // Workaround for saving attachements from Mail.app. Attachments from Mail.app contains two types e.g. "com.adobe.pdf" AND "public.file-url". For loading the file the type "public.file-url" is needed. Otherwise the resource could not be accessed (NSItemProviderSandboxedResource) if attachment.registeredTypeIdentifiers.contains("public.file-url") { type = "public.file-url" } + let suggestedTextFileName = attachment.suggestedName ?? "Text".localized + attachment.loadItem(forTypeIdentifier: type, options: nil, completionHandler: { (item, error) -> Void in if error == nil { var data : Data? @@ -177,12 +227,12 @@ class ShareExtensionViewController: EmbeddingViewController, Themeable { if let text = item as? String { // Save plain text content let ext = UTType(type)?.preferredFilenameExtension - tempFilePath = NSTemporaryDirectory() + (attachment.suggestedName ?? "Text".localized) + "." + (ext ?? type) + tempFilePath = NSTemporaryDirectory() + suggestedTextFileName + "." + (ext ?? type) data = Data(text.utf8) } else if let url = item as? URL { // Download URL content if url.isFileURL { tempFileURL = URL(fileURLWithPath: NSTemporaryDirectory() + url.lastPathComponent) - if let tempFileURL = tempFileURL { + if let tempFileURL { try? FileManager.default.copyItem(at: url, to: tempFileURL) } } else { @@ -195,84 +245,58 @@ class ShareExtensionViewController: EmbeddingViewController, Themeable { } } - if tempFileURL == nil, let data = data, let tempFilePath = tempFilePath { + if tempFileURL == nil, let data = data, let tempFilePath { FileManager.default.createFile(atPath: tempFilePath, contents:data, attributes:nil) tempFileURL = URL(fileURLWithPath: tempFilePath) } - if let tempFileURL = tempFileURL { - serviceSession.importThroughFileProvider(url: tempFileURL, to: targetDirectory, completion: { (error, _) in - try? FileManager.default.removeItem(at: tempFileURL) - - if let error = error { - Log.error("Error importing item at \(tempFileURL) through file provider: \(String(describing: error))") - - self.showAlert(title: NSString(format: "Error importing %@".localized as NSString, tempFileURL.lastPathComponent) as String, error: error, decisionHandler: { (doContinue) in - if !doContinue { - importError = error - progressViewController?.cancel() - } - - jobDone() - }) - } else { - incrementImportedFile() + if let tempFileURL { + uploadWaitGroup.enter() - jobDone() - } - }) + if let coreProgress = self.uploadFile(from: tempFileURL, removeAfterImport: true, to: targetDirectory, via: core, schedulingDoneBlock: jobDone, completionHandler: handleUploadResult) { + self.uploadCoreProgress?.addChild(coreProgress, withPendingUnitCount: 1) + } } else { jobDone() } - } else { + } else if let error { Log.error("Error loading item: \(String(describing: error))") - self.showAlert(title: "Error loading item".localized, error: error, decisionHandler: { (doContinue) in + self.showAlert(title: "Error loading item".localized, error: error, decisionHandler: { [weak self] (doContinue) in if !doContinue { - importError = error - progressViewController?.cancel() + self?.cancel() } jobDone() }) + } else { + jobDone() } }) }) } else { // Handle local files asyncQueue.async({ (jobDone) in - if progressViewController?.cancelled == true { + if self.progressViewController?.cancelled == true { jobDone() return } - attachment.loadFileRepresentation(forTypeIdentifier: type) { (url, error) in - if error == nil, let url = url { - serviceSession.importThroughFileProvider(url: url, to: targetDirectory, completion: { (error, _) in - if let error = error { - Log.error("Error importing item at \(url.absoluteString) through file provider: \(String(describing: error))") - - self.showAlert(title: NSString(format: "Error importing %@", url.lastPathComponent) as String, error: error, decisionHandler: { (doContinue) in - if !doContinue { - importError = error - progressViewController?.cancel() - } + incrementImportCounter() - jobDone() - }) - } else { - incrementImportedFile() + attachment.loadFileRepresentation(forTypeIdentifier: type) { (url, error) in + if error == nil, let url { + uploadWaitGroup.enter() - jobDone() - } - }) - } else if let error = error { + if let coreProgress = self.uploadFile(from: url, removeAfterImport: false, to: targetDirectory, via: core, schedulingDoneBlock: jobDone, completionHandler: handleUploadResult) { + self.uploadCoreProgress?.addChild(coreProgress, withPendingUnitCount: 1) + } + } else if let error { Log.error("Error loading item: \(String(describing: error))") - self.showAlert(title: "Error loading item".localized, error: error, decisionHandler: { (doContinue) in + self.showAlert(title: "Error loading item".localized, error: error, decisionHandler: { [weak self] (doContinue) in if !doContinue { - importError = error - progressViewController?.cancel() + self?.cancel() } jobDone() @@ -289,17 +313,49 @@ class ShareExtensionViewController: EmbeddingViewController, Themeable { } asyncQueue.async({ (jobDone) in - // Balance previous retainSession() call and allow session to close - serviceSession.decrementSessionUsage() - OnMainThread { - completion(importError ?? ((progressViewController?.cancelled ?? false) ? NSError(ocError: .cancelled) : nil)) - jobDone() + updateUploadMessage() } + + uploadWaitGroup.notify(queue: .main, execute: { + self.finish(with: ((self.progressViewController?.cancelled ?? false) ? NSError(ocError: .cancelled) : uploadError)) + jobDone() + }) }) } } + func uploadFile(from sourceURL: URL, removeAfterImport: Bool, to targetItem: OCItem, via core: OCCore, schedulingDoneBlock: @escaping os_block_t, completionHandler: @escaping (Error?) -> Void) -> Progress? { + let progress = core.importItemNamed(sourceURL.lastPathComponent, at: targetItem, from: sourceURL, isSecurityScoped: false, options: [ + .importByCopying : true, + .automaticConflictResolutionNameStyle : OCCoreDuplicateNameStyle.bracketed.rawValue + ], placeholderCompletionHandler: { [weak self] error, placeholderItem in + if removeAfterImport { + try? FileManager.default.removeItem(at: sourceURL) + } + + if let error { + Log.error("Error importing item at \(sourceURL) through share extension: \(String(describing: error))") + + self?.showAlert(title: NSString(format: "Error importing %@".localized as NSString, sourceURL.lastPathComponent) as String, error: error, decisionHandler: { [weak self] (doContinue) in + if !doContinue { + completionHandler(error) + self?.progressViewController?.cancel() + } + + schedulingDoneBlock() + }) + } else { + schedulingDoneBlock() + } + }, resultHandler: { error, core, item, parameter in + completionHandler(error) + schedulingDoneBlock() + }) + + return progress + } + // MARK: - Events var willAppearDidInitialRun: Bool = false private var _registered = false @@ -413,19 +469,35 @@ class ShareExtensionViewController: EmbeddingViewController, Themeable { } // MARK: - Actions - func completed() { - AppLockManager.shared.appDidEnterBackground() + func cancel() { + finish(with: NSError(domain: NSErrorDomain.ShareErrorDomain, code: 0, userInfo: [NSLocalizedDescriptionKey: "Canceled by user"])) + } - AccountConnectionPool.shared.disconnectAll { - self.extensionContext?.completeRequest(returningItems: nil, completionHandler: nil) + private var _isFinished: Bool = false + func finish(with error: Error?) { + var alreadyFinished: Bool = false + + OCSynchronized(self) { + alreadyFinished = _isFinished + _isFinished = true } - } - func cancel() { - AppLockManager.shared.appDidEnterBackground() + if alreadyFinished { + // Already finished + Log.error("Share Extension already finished. Attempt to finish again with \(String(describing: error))") + return + } - AccountConnectionPool.shared.disconnectAll { - self.extensionContext?.cancelRequest(withError: NSError(domain: NSErrorDomain.ShareErrorDomain, code: 0, userInfo: [NSLocalizedDescriptionKey: "Canceled by user"])) + OnMainThread { + AppLockManager.shared.appDidEnterBackground() + + AccountConnectionPool.shared.disconnectAll { [weak self] in + if let error = error { + self?.extensionContext?.cancelRequest(withError: error) + } else { + self?.extensionContext?.completeRequest(returningItems: []) + } + } } } diff --git a/ownCloudAppShared/User Interface/Progress/ProgressIndicatorViewController.swift b/ownCloudAppShared/User Interface/Progress/ProgressIndicatorViewController.swift index 7c76dc9e1..85824ed30 100644 --- a/ownCloudAppShared/User Interface/Progress/ProgressIndicatorViewController.swift +++ b/ownCloudAppShared/User Interface/Progress/ProgressIndicatorViewController.swift @@ -57,6 +57,8 @@ open class ProgressIndicatorViewController: UIViewController, Themeable { self?.activityIndicator.stopAnimating() self?.activityIndicator.isHidden = true self?.progressView.isHidden = false + + self?.progressView.progress = Float(progress.fractionCompleted) } } }) @@ -78,6 +80,7 @@ open class ProgressIndicatorViewController: UIViewController, Themeable { super.init(nibName: nil, bundle: nil) self.progress = progress + self.cssSelectors = [ .modal ] if let initialTitleLabel = initialTitleLabel { titleLabel = UILabel() From 5fcd9b8c4b4d04ce2cab4b67b28ca088c54191ce Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Mon, 9 Sep 2024 12:13:05 +0200 Subject: [PATCH 20/23] - SaveFileIntentHandler: no longer use File Provider for uploading - Intents.intentdefinition: remove File Provider upload option for SaveIntentHandler --- .../Base.lproj/Intents.intentdefinition | 56 +------------ ownCloud Intents/SaveFileIntentHandler.swift | 82 +++++-------------- 2 files changed, 24 insertions(+), 114 deletions(-) diff --git a/ownCloud Intents/Base.lproj/Intents.intentdefinition b/ownCloud Intents/Base.lproj/Intents.intentdefinition index 89d555c95..13ab71918 100644 --- a/ownCloud Intents/Base.lproj/Intents.intentdefinition +++ b/ownCloud Intents/Base.lproj/Intents.intentdefinition @@ -126,11 +126,11 @@ INIntentDefinitionNamespace K5U8aR INIntentDefinitionSystemVersion - 21E230 + 23G93 INIntentDefinitionToolsBuildVersion - 13E113 + 16A5230g INIntentDefinitionToolsVersion - 13.3 + 16.0 INIntents @@ -943,7 +943,7 @@ 13 INIntentManagedParameterCombinations - path,file,account,filename,fileextension,shouldOverwrite,waitForCompletion + path,file,account,filename,fileextension,shouldOverwrite INIntentParameterCombinationSupportsBackgroundExecution @@ -1219,54 +1219,6 @@ INIntentParameterType Boolean - - INIntentParameterConfigurable - - INIntentParameterDisplayName - Wait for upload to complete - INIntentParameterDisplayNameID - X18VvP - INIntentParameterDisplayPriority - 7 - INIntentParameterMetadata - - INIntentParameterMetadataFalseDisplayName - false - INIntentParameterMetadataFalseDisplayNameID - 7Zv2I0 - INIntentParameterMetadataTrueDisplayName - true - INIntentParameterMetadataTrueDisplayNameID - w1TCyX - - INIntentParameterName - waitForCompletion - INIntentParameterPromptDialogs - - - INIntentParameterPromptDialogCustom - - INIntentParameterPromptDialogType - Configuration - - - INIntentParameterPromptDialogCustom - - INIntentParameterPromptDialogFormatString - Wait for upload to complete before continuing - INIntentParameterPromptDialogFormatStringID - Wt9Wgt - INIntentParameterPromptDialogType - Primary - - - INIntentParameterSupportsResolution - - INIntentParameterTag - 13 - INIntentParameterType - Boolean - INIntentResponse diff --git a/ownCloud Intents/SaveFileIntentHandler.swift b/ownCloud Intents/SaveFileIntentHandler.swift index 8dd584f48..b2e373e18 100644 --- a/ownCloud Intents/SaveFileIntentHandler.swift +++ b/ownCloud Intents/SaveFileIntentHandler.swift @@ -102,7 +102,6 @@ public class SaveFileIntentHandler: NSObject, SaveFileIntentHandling, OCCoreDele } } let filePath = path + newFilename - let waitForCompletion = (intent.waitForCompletion as? Bool) ?? false let shouldOverwrite = (intent.shouldOverwrite as? Bool) ?? false let completeWithCode = { (code: SaveFileIntentResponseCode) in @@ -132,7 +131,7 @@ public class SaveFileIntentHandler: NSObject, SaveFileIntentHandling, OCCoreDele if error == nil, let targetItem = item { // Check if file already exists OCItemTracker(for: bookmark, at: .legacyRootPath(filePath), waitOnlineTimeout: 5) { (error, core, fileItem) in - if let core = core { + if core != nil { if error == nil, let fileItem = fileItem { // File already exists if !shouldOverwrite { @@ -147,26 +146,10 @@ public class SaveFileIntentHandler: NSObject, SaveFileIntentHandling, OCCoreDele OnBackgroundQueue { if let parentItem = fileItem.parentItem(from: core) { - if waitForCompletion { - // Wait for completion: report local modification from extension - core.reportLocalModification(of: fileItem, parentItem: parentItem, withContentsOfFileAt: fileURL, isSecurityScoped: true, options: [OCCoreOption.importByCopying : true], placeholderCompletionHandler: nil, resultHandler: { (error, _, item, _) in - completeWithResult(error, item?.path) - }) - } else { - // Delegate local modification report to File Provider - let fpServiceSession = OCFileProviderServiceSession(vault: core.vault) - self.fpServiceSession = fpServiceSession - - let didStartSecurityScopedResource = fileURL.startAccessingSecurityScopedResource() - - fpServiceSession.reportModificationThroughFileProvider(url: fileURL, as: fileItem.name, for: fileItem, to: parentItem, lastModifiedDate: nil, completion: { (error) in - completeWithResult(error, fileItem.path) - - if didStartSecurityScopedResource { - fileURL.stopAccessingSecurityScopedResource() - } - }) - } + // Wait for completion: report local modification from extension + core.reportLocalModification(of: fileItem, parentItem: parentItem, withContentsOfFileAt: fileURL, isSecurityScoped: true, options: [OCCoreOption.importByCopying : true], placeholderCompletionHandler: nil, resultHandler: { (error, _, item, _) in + completeWithResult(error, item?.path) + }) } else { completeWithCode(.pathFailure) } @@ -178,39 +161,22 @@ public class SaveFileIntentHandler: NSObject, SaveFileIntentHandling, OCCoreDele } } else { // File does NOT exist => import file - if waitForCompletion { - // Wait for completion: import from extension - OCCoreManager.shared.requestCore(for: bookmark, setup: { (core, error) in - core?.delegate = self - }, completionHandler: { (core, error) in - if let core = core { - self.core = core - - OnBackgroundQueue { - core.importFileNamed(newFilename, at: targetItem, from: fileURL, isSecurityScoped: true, options: [OCCoreOption.importByCopying : true], placeholderCompletionHandler: nil, resultHandler: { (error, _, item, _) in - completeWithResult(error, item?.path) - }) - } - } else { - completeWithResult(error, nil) + // Wait for completion: import from extension + OCCoreManager.shared.requestCore(for: bookmark, setup: { (core, error) in + core?.delegate = self + }, completionHandler: { (core, error) in + if let core = core { + self.core = core + + OnBackgroundQueue { + core.importFileNamed(newFilename, at: targetItem, from: fileURL, isSecurityScoped: true, options: [OCCoreOption.importByCopying : true], placeholderCompletionHandler: nil, resultHandler: { (error, _, item, _) in + completeWithResult(error, item?.path) + }) } - }) - } else { - // Delegate import to File Provider - let fpServiceSession = OCFileProviderServiceSession(vault: core.vault) - self.fpServiceSession = fpServiceSession - - let didStartSecurityScopedResource = fileURL.startAccessingSecurityScopedResource() - - fpServiceSession.importThroughFileProvider(url: fileURL, as: newFilename, to: targetItem, completion: { (error, _) in - let itemPath = (targetItem.path as NSString? ?? path as NSString?)?.appendingPathComponent(newFilename) - completeWithResult(error, itemPath) - - if didStartSecurityScopedResource { - fileURL.stopAccessingSecurityScopedResource() - } - }) - } + } else { + completeWithResult(error, nil) + } + }) } } else { failWithError(error) @@ -276,14 +242,6 @@ public class SaveFileIntentHandler: NSObject, SaveFileIntentHandling, OCCoreDele } completion(INBooleanResolutionResult.success(with: shouldOverwrite)) } - - func resolveWaitForCompletion(for intent: SaveFileIntent, with completion: @escaping (INBooleanResolutionResult) -> Void) { - var waitForCompletion = false - if let doWait = intent.waitForCompletion?.boolValue { - waitForCompletion = doWait - } - completion(INBooleanResolutionResult.success(with: waitForCompletion)) - } } @available(iOS 13.0, *) From f5de6109c922dcd641693e91ebb4244590a9799d Mon Sep 17 00:00:00 2001 From: Felix Schwarz Date: Mon, 9 Sep 2024 12:20:26 +0200 Subject: [PATCH 21/23] - update SDK --- ios-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-sdk b/ios-sdk index 8c0fddb15..74b603927 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 8c0fddb15240b70463f33a17279c8a63ef328585 +Subproject commit 74b603927821cc745612cdceb11f24748e0f4366 From 618dc8f0897688da6ef82829797df4c8e178ff7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Hu=CC=88hne?= Date: Wed, 11 Sep 2024 09:28:55 +0200 Subject: [PATCH 22/23] updated to merged SDK commit --- ios-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-sdk b/ios-sdk index 74b603927..c1f7adcc4 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 74b603927821cc745612cdceb11f24748e0f4366 +Subproject commit c1f7adcc4e72a008c128db40bd13651abdc955ed From 6f7ba0ca0d429449b1497a6312ac9e6d361d29ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Hu=CC=88hne?= Date: Wed, 11 Sep 2024 15:11:17 +0200 Subject: [PATCH 23/23] updated to latest SDK master commit --- ios-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios-sdk b/ios-sdk index c1f7adcc4..f0c6f8f78 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit c1f7adcc4e72a008c128db40bd13651abdc955ed +Subproject commit f0c6f8f788fd33148bfe2b8ab345d5465dcc6e96