diff --git a/appkit/Cargo.toml b/appkit/Cargo.toml index bdd13a0..1be29b4 100644 --- a/appkit/Cargo.toml +++ b/appkit/Cargo.toml @@ -19,5 +19,6 @@ uuid = { version = "0.8", features = ["v4"] } url = "2.1.1" [features] +cloudkit = [] user-notifications = [] enable-webview-downloading = [] diff --git a/appkit/build.rs b/appkit/build.rs index 0fc90dd..3d85dcb 100644 --- a/appkit/build.rs +++ b/appkit/build.rs @@ -7,6 +7,9 @@ fn main() { if std::env::var("TARGET").unwrap().contains("-apple") { println!("cargo:rustc-link-lib=framework=Security"); println!("cargo:rustc-link-lib=framework=WebKit"); + + #[cfg(feature = "cloudkit")] + println!("cargo:rustc-link-lib=framework=CloudKit"); #[cfg(feature = "user-notifications")] println!("cargo:rustc-link-lib=framework=UserNotifications"); diff --git a/appkit/src/app/class.rs b/appkit/src/app/class.rs index e4872da..f073d65 100644 --- a/appkit/src/app/class.rs +++ b/appkit/src/app/class.rs @@ -24,6 +24,9 @@ use crate::printing::PrintSettings; use crate::user_activity::UserActivity; use crate::utils::{map_nsarray, str_from}; +#[cfg(feature = "cloudkit")] +use crate::cloudkit::share::CKShareMetaData; + /// A handy method for grabbing our `AppController` from the pointer. This is different from our /// standard `utils` version as this doesn't require `RefCell` backing. fn app(this: &Object) -> &T { @@ -196,8 +199,10 @@ extern fn did_receive_remote_notification(_this: &Object, _: S /// Fires when the application receives a `application:userDidAcceptCloudKitShareWithMetadata:` /// message. -extern fn accepted_cloudkit_share(_this: &Object, _: Sel, _: id, _: id) { - +#[cfg(feature = "cloudkit")] +extern fn accepted_cloudkit_share(_this: &Object, _: Sel, _: id, metadata: id) { + let share = CKShareMetaData::with_inner(metadata); + app::(this).user_accepted_cloudkit_share(share); } /// Fires when the application receives an `application:openURLs` message. @@ -349,6 +354,7 @@ pub(crate) fn register_app_controller_class() -> *const Class decl.add_method(sel!(application:didReceiveRemoteNotification:), did_receive_remote_notification:: as extern fn(&Object, _, _, id)); // CloudKit + #[cfg(feature = "cloudkit")] decl.add_method(sel!(application:userDidAcceptCloudKitShareWithMetadata:), accepted_cloudkit_share:: as extern fn(&Object, _, _, id)); // Opening Files diff --git a/appkit/src/app/traits.rs b/appkit/src/app/traits.rs index b69bb5d..87a3ddb 100644 --- a/appkit/src/app/traits.rs +++ b/appkit/src/app/traits.rs @@ -9,7 +9,8 @@ use crate::menu::Menu; use crate::printing::settings::PrintSettings; use crate::user_activity::UserActivity; -pub struct CKShareMetaData; +#[cfg(feature = "user-notifications")] +use crate::cloudkit::share::CKShareMetaData; /// Controllers interested in processing messages can implement this to respond to messages as /// they're dispatched. All messages come in on the main thread. @@ -122,6 +123,7 @@ pub trait AppController { /// Fires after the user accepted a CloudKit sharing invitation associated with your /// application. + #[cfg(feature = "cloudkit")] fn user_accepted_cloudkit_share(&self, _share_metadata: CKShareMetaData) {} /// Fired when you have a list of `Url`'s to open. This is best explained by quoting the Apple diff --git a/appkit/src/cloudkit/mod.rs b/appkit/src/cloudkit/mod.rs new file mode 100644 index 0000000..a3b1688 --- /dev/null +++ b/appkit/src/cloudkit/mod.rs @@ -0,0 +1,6 @@ +//! This module wraps a portion of the CloudKit API. This is a fairly extensive API, and is not +//! easy to wrap - if you use this and need something that's not implemented, please consider +//! helping out with an implementation and pull request. + +pub mod share; +pub use share::CKShareMetaData; diff --git a/appkit/src/cloudkit/share.rs b/appkit/src/cloudkit/share.rs new file mode 100644 index 0000000..cee42be --- /dev/null +++ b/appkit/src/cloudkit/share.rs @@ -0,0 +1,21 @@ +//! This module includes wrappers for `CKShare` and `CKShareMetaData`. + +use cocoa::base::id; +use objc::runtime::Object; +use objc_id::ShareId; + +/// A wrapper for `CKShareMetaData`, which describes details about a `CKShare`. You might use this +/// to, say, handle accepting an invite for a share. +#[derive(Clone, Debug)] +pub struct CKShareMetaData { + pub inner: ShareId +} + +impl CKShareMetaData { + /// Internal method for wrapping a system-provided `CKShareMetaData` object. + pub(crate) fn with_inner(object: id) -> Self { + CKShareMetaData { + inner: unsafe { ShareId::from_ptr(object) } + } + } +} diff --git a/appkit/src/lib.rs b/appkit/src/lib.rs index cf73859..4d67db0 100644 --- a/appkit/src/lib.rs +++ b/appkit/src/lib.rs @@ -23,6 +23,10 @@ pub use cocoa::base::id; pub mod alert; pub mod app; pub mod button; + +#[cfg(feature = "user-notifications")] +pub mod cloudkit; + pub mod color; pub mod collection_view; pub mod constants;