diff --git a/ios/Classes/IcloudStorageSyncPlugin.swift b/ios/Classes/IcloudStorageSyncPlugin.swift index 8edbbfb..6e49076 100644 --- a/ios/Classes/IcloudStorageSyncPlugin.swift +++ b/ios/Classes/IcloudStorageSyncPlugin.swift @@ -27,6 +27,15 @@ public class IcloudStorageSyncPlugin: NSObject, FlutterPlugin { } else { result(FlutterError(code: "INVALID_ARGUMENT", message: "containerId not provided", details: nil)) } + case "getICloudContainerUrl": + if let args = call.arguments as? [String: Any], + let containerId = args["containerId"] as? String { + getICloudContainerUrl(containerId: containerId, result: result) + } else { + result(FlutterError(code: "INVALID_ARGUMENT", message: "containerId not provided", details: nil)) + } + case "isICloudAvailable": + isICloudAvailable(result) case "upload": upload(call, result) case "delete": @@ -157,6 +166,20 @@ public class IcloudStorageSyncPlugin: NSObject, FlutterPlugin { } } + private func getICloudContainerUrl(containerId: String, result: @escaping FlutterResult) { + guard let containerURL = FileManager.default.url(forUbiquityContainerIdentifier: containerId) else { + result(containerError) + return + } + DebugHelper.log("containerURL: \(containerURL.path)") + result(containerURL.path) + } + + private func isICloudAvailable(_ result: @escaping FlutterResult) { + let isAvailable = FileManager.default.ubiquityIdentityToken != nil + result(isAvailable) + } + private func upload(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { guard let args = call.arguments as? Dictionary, diff --git a/lib/icloud_storage_sync.dart b/lib/icloud_storage_sync.dart index 43f4ed6..e236cce 100644 --- a/lib/icloud_storage_sync.dart +++ b/lib/icloud_storage_sync.dart @@ -13,6 +13,22 @@ class IcloudStorageSync { return IcloudStorageSyncPlatform.instance.getPlatformVersion(); } + /// Returns the absolute path of the iCloud container directory for [containerId]. + Future getContainerUrl({required String containerId}) { + return IcloudStorageSyncPlatform.instance.getContainerUrl( + containerId: containerId, + ); + } + + /// Indicates whether iCloud is available on this device for iCloud Drive Documents. + /// + /// This checks if the system exposes a ubiquity identity token, which is + /// present only when the user is signed into iCloud and the feature is + /// enabled. + Future isICloudAvailable() { + return IcloudStorageSyncPlatform.instance.isICloudAvailable(); + } + /// Gathers metadata for all files in the specified iCloud container. /// /// [containerId] The ID of the iCloud container to query. diff --git a/lib/icloud_storage_sync_method_channel.dart b/lib/icloud_storage_sync_method_channel.dart index c34dc37..b5b5085 100644 --- a/lib/icloud_storage_sync_method_channel.dart +++ b/lib/icloud_storage_sync_method_channel.dart @@ -19,6 +19,21 @@ class MethodChannelIcloudStorageSync extends IcloudStorageSyncPlatform { return version; } + @override + Future getContainerUrl({required String containerId}) async { + return await methodChannel.invokeMethod('getICloudContainerUrl', { + 'containerId': containerId, + }); + } + + @override + Future isICloudAvailable() async { + final available = await methodChannel.invokeMethod( + 'isICloudAvailable', + ); + return available ?? false; + } + /// Gathers iCloud files and their metadata. /// /// [containerId] is the iCloud container identifier. diff --git a/lib/icloud_storage_sync_platform_interface.dart b/lib/icloud_storage_sync_platform_interface.dart index 03b526e..c20cee6 100644 --- a/lib/icloud_storage_sync_platform_interface.dart +++ b/lib/icloud_storage_sync_platform_interface.dart @@ -35,6 +35,18 @@ abstract class IcloudStorageSyncPlatform extends PlatformInterface { throw UnimplementedError('platformVersion() has not been implemented.'); } + /// Returns the absolute path of the iCloud container URL. + Future getContainerUrl({required String containerId}) async { + throw UnimplementedError('getContainerUrl() has not been implemented.'); + } + + /// Determines whether iCloud is available for iCloud Drive Documents by checking the ubiquity identity token. + /// + /// Returns `true` when a token is present otherwise returns `false`. + Future isICloudAvailable() async { + throw UnimplementedError('isICloudAvailable() has not been implemented.'); + } + /// Gathers all the files' metadata from the iCloud container. /// /// [containerId] is the iCloud Container Id. diff --git a/macos/Classes/IcloudStorageSyncPlugin.swift b/macos/Classes/IcloudStorageSyncPlugin.swift index 6bb12f0..9c81601 100644 --- a/macos/Classes/IcloudStorageSyncPlugin.swift +++ b/macos/Classes/IcloudStorageSyncPlugin.swift @@ -25,6 +25,15 @@ public class IcloudStorageSyncPlugin: NSObject, FlutterPlugin { } else { result(FlutterError(code: "INVALID_ARGUMENT", message: "containerId not provided", details: nil)) } + case "getICloudContainerUrl": + if let args = call.arguments as? [String: Any], + let containerId = args["containerId"] as? String { + getICloudContainerUrl(containerId: containerId, result: result) + } else { + result(FlutterError(code: "INVALID_ARGUMENT", message: "containerId not provided", details: nil)) + } + case "isICloudAvailable": + isICloudAvailable(result) case "upload": upload(call, result) case "download": @@ -205,8 +214,20 @@ public class IcloudStorageSyncPlugin: NSObject, FlutterPlugin { result(nil) } - + private func getICloudContainerUrl(containerId: String, result: @escaping FlutterResult) { + guard let containerURL = FileManager.default.url(forUbiquityContainerIdentifier: containerId) else { + result(containerError) + return + } + DebugHelper.log("containerURL: \(containerURL.path)") + result(containerURL.path) + } + + private func isICloudAvailable(_ result: @escaping FlutterResult) { + let isAvailable = FileManager.default.ubiquityIdentityToken != nil + result(isAvailable) + } private func addUploadObservers(query: NSMetadataQuery, eventChannelName: String) { NotificationCenter.default.addObserver(forName: NSNotification.Name.NSMetadataQueryDidFinishGathering, object: query, queue: query.operationQueue) { [self] (notification) in diff --git a/test/icloud_storage_sync_test.dart b/test/icloud_storage_sync_test.dart index fc0e642..82fe549 100644 --- a/test/icloud_storage_sync_test.dart +++ b/test/icloud_storage_sync_test.dart @@ -11,6 +11,10 @@ class MockIcloudStorageSyncPlatform @override Future getPlatformVersion() => Future.value('42'); + @override + Future getContainerUrl({required String containerId}) => + throw UnimplementedError(); + @override Future delete( {required String containerId, required String relativePath}) { @@ -54,6 +58,11 @@ class MockIcloudStorageSyncPlatform StreamHandler? onProgress}) { throw UnimplementedError(); } + + @override + Future isICloudAvailable() { + throw UnimplementedError(); + } } void main() {