From fd7129c1775aef84e88f37a0a148eceef2e0ca48 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Wed, 6 Mar 2024 10:29:30 +0100 Subject: [PATCH] feat: use new calendar and reminders access APIs --- index.js | 10 ++++++- permissions.mm | 72 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 58 insertions(+), 24 deletions(-) diff --git a/index.js b/index.js index 9f04a2f..a86c525 100644 --- a/index.js +++ b/index.js @@ -36,6 +36,14 @@ function askForFoldersAccess(folder) { return permissions.askForFoldersAccess.call(this, folder) } +function askForCalendarAccess(type) { + if (!['write-only', 'full'].includes(type)) { + throw new TypeError(`${type} must be one of either 'write-only' or 'full'`) + } + + return permissions.askForCalendarAccess.call(this, type) +} + function askForScreenCaptureAccess(openPreferences = false) { if (typeof openPreferences !== 'boolean') { throw new TypeError('openPreferences must be a boolean') @@ -62,7 +70,7 @@ function askForInputMonitoringAccess(accessLevel = 'listen') { module.exports = { askForAccessibilityAccess: permissions.askForAccessibilityAccess, - askForCalendarAccess: permissions.askForCalendarAccess, + askForCalendarAccess: askForCalendarAccess, askForCameraAccess: permissions.askForCameraAccess, askForContactsAccess: permissions.askForContactsAccess, askForFoldersAccess, diff --git a/permissions.mm b/permissions.mm index 4453236..080f579 100644 --- a/permissions.mm +++ b/permissions.mm @@ -510,17 +510,38 @@ bool HasOpenSystemPreferencesDialog() { env, Napi::Function::New(env, NoOp), "calendarCallback", 0, 1); __block Napi::ThreadSafeFunction tsfn = ts_fn; - [[EKEventStore new] - requestAccessToEntityType:EKEntityTypeEvent - completion:^(BOOL granted, NSError *error) { - auto callback = [=](Napi::Env env, Napi::Function js_cb, - const char *granted) { - deferred.Resolve(Napi::String::New(env, granted)); - }; - tsfn.BlockingCall(granted ? "authorized" : "denied", - callback); - tsfn.Release(); - }]; + if (@available(macOS 14.0, *)) { + const std::string type = info[0].As().Utf8Value(); + + EKEventStoreRequestAccessCompletionHandler handler = + ^(BOOL granted, NSError *error) { + auto callback = [=](Napi::Env env, Napi::Function js_cb, + const char *granted) { + deferred.Resolve(Napi::String::New(env, granted)); + }; + tsfn.BlockingCall(granted ? "authorized" : "denied", callback); + tsfn.Release(); + }; + + if (type == "full") { + [[EKEventStore new] requestFullAccessToEventsWithCompletion:handler]; + } else { + [[EKEventStore new] requestWriteOnlyAccessToEventsWithCompletion:handler]; + } + } else { + [[EKEventStore new] + requestAccessToEntityType:EKEntityTypeEvent + completion:^(BOOL granted, NSError *error) { + auto callback = [=](Napi::Env env, + Napi::Function js_cb, + const char *granted) { + deferred.Resolve(Napi::String::New(env, granted)); + }; + tsfn.BlockingCall(granted ? "authorized" : "denied", + callback); + tsfn.Release(); + }]; + } return deferred.Promise(); } @@ -533,18 +554,23 @@ bool HasOpenSystemPreferencesDialog() { env, Napi::Function::New(env, NoOp), "remindersCallback", 0, 1); __block Napi::ThreadSafeFunction tsfn = ts_fn; - [[EKEventStore new] - requestAccessToEntityType:EKEntityTypeReminder - completion:^(BOOL granted, NSError *error) { - auto callback = [=](Napi::Env env, - Napi::Function prom_cb, - const char *granted) { - deferred.Resolve(Napi::String::New(env, granted)); - }; - tsfn.BlockingCall(granted ? "authorized" : "denied", - callback); - tsfn.Release(); - }]; + + EKEventStoreRequestAccessCompletionHandler handler = + ^(BOOL granted, NSError *error) { + auto callback = [=](Napi::Env env, Napi::Function prom_cb, + const char *granted) { + deferred.Resolve(Napi::String::New(env, granted)); + }; + tsfn.BlockingCall(granted ? "authorized" : "denied", callback); + tsfn.Release(); + }; + + if (@available(macOS 14.0, *)) { + [[EKEventStore new] requestFullAccessToRemindersWithCompletion:handler]; + } else { + [[EKEventStore new] requestAccessToEntityType:EKEntityTypeReminder + completion:handler]; + } return deferred.Promise(); }