Skip to content

Commit

Permalink
Merge pull request #1 from sjregan/Support-for-iOS-17
Browse files Browse the repository at this point in the history
Support for i os 17
  • Loading branch information
plabes-digistorm authored Feb 14, 2024
2 parents 2b309a9 + 1052bec commit 3181ad3
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 15 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ This plugin allows you to add events to the Calendar of the mobile device.
```
cordova plugin add cordova-plugin-calendar --variable CALENDAR_USAGE_DESCRIPTION="This app uses your calendar"
```
* On iOS 16 and below, all permission requests are identical. They all request full access.
* On iOS 17+, the `requestReadPermission()` and `requestReadWritePermission()` both request full access. `requestWritePermission()` only requests write permission.
* Note: calling requestWritePermission() after calling requestReadWritePermission() may mean you lose permission to read events. You may need to call requestReadWritePermission() again.
* On iOS 17+ you need to add `NSCalendarsFullAccessUsageDescription` and `NSCalendarsWriteOnlyAccessUsageDescription` usage strings to the `.plist` files.


### Android specifics
* Supported methods on Android 4: `find`, `create` (silent and interactive), `delete`, ..
Expand Down
3 changes: 2 additions & 1 deletion src/ios/Calendar.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
@property (nonatomic, retain) EKEventStore* eventStore;
@property (nonatomic, copy) NSString *interactiveCallbackId;

- (void)initEventStoreWithCalendarCapabilities;
- (void)initEventStoreWithFullCalendarCapabilities;
- (void)initEventStoreWithWriteCalendarCapabilities;

-(NSArray*)findEKEventsWithTitle: (NSString *)title
location: (NSString *)location
Expand Down
109 changes: 95 additions & 14 deletions src/ios/Calendar.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,102 @@ @implementation Calendar
#pragma mark Initialization functions

- (void) pluginInitialize {
[self initEventStoreWithCalendarCapabilities];
}

- (void) initEventStoreWithCalendarCapabilities {
/**
* Init event store with read and write capabilities.
*
* Note: This will overwrite the existing event store.
*/
- (void) initEventStoreWithFullCalendarCapabilities {
NSLog(@"Initialising calendar event store with full access.");

EKEventStore* eventStoreCandidate = [[EKEventStore alloc] init];
__block BOOL accessGranted = NO;

dispatch_semaphore_t sema = dispatch_semaphore_create(0);
if (@available(iOS 17.0, *)) {
[eventStoreCandidate requestFullAccessToEventsWithCompletion:^(BOOL granted, NSError *error) {
accessGranted = granted;

if (!accessGranted) {
NSLog(@"Full access to the event store not granted. Error: %@", error.localizedDescription);
}

dispatch_semaphore_signal(sema);
}];
} else {
// iOS 16 or lower
if([eventStoreCandidate respondsToSelector:@selector(requestAccessToEntityType:completion:)]) {
[eventStoreCandidate requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
accessGranted = granted;

if (!accessGranted) {
NSLog(@"Full access to the event store not granted. Error: %@", error.localizedDescription);
}

dispatch_semaphore_signal(sema);
}];
} else {
// iOS 5 or lower
accessGranted = YES;
dispatch_semaphore_signal(sema);
}
}
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

if (accessGranted) {
self.eventStore = eventStoreCandidate;
NSLog(@"Full access to the event store granted and eventStore initialized.");
}
}

/**
* Init event store with write capabilities only.
*
* Note: This will overwrite the existing event store, so you may not be able to read events after requesting write
* only permission, even if you have previously requested read and write permission.
*/
- (void) initEventStoreWithWriteCalendarCapabilities {
NSLog(@"Initialising calendar event store with write access.");

EKEventStore* eventStoreCandidate = [[EKEventStore alloc] init];
if([eventStoreCandidate respondsToSelector:@selector(requestAccessToEntityType:completion:)]) {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[eventStoreCandidate requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
__block BOOL accessGranted = NO;

dispatch_semaphore_t sema = dispatch_semaphore_create(0);
if (@available(iOS 17.0, *)) {
[eventStoreCandidate requestWriteOnlyAccessToEventsWithCompletion:^(BOOL granted, NSError *error) {
accessGranted = granted;

if (!accessGranted) {
NSLog(@"Write access to the event store not granted. Error: %@", error.localizedDescription);
}

dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
} else { // we're on iOS 5 or older
accessGranted = YES;
} else {
// iOS 16 or lower
if([eventStoreCandidate respondsToSelector:@selector(requestAccessToEntityType:completion:)]) {
[eventStoreCandidate requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
accessGranted = granted;

if (!accessGranted) {
NSLog(@"Write access to the event store not granted after requesting full access for iOS <= 16. Error: %@", error.localizedDescription);
}

dispatch_semaphore_signal(sema);
}];
} else {
// iOS 5 or lower
accessGranted = YES;
dispatch_semaphore_signal(sema);
}
}
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

if (accessGranted) {
self.eventStore = eventStoreCandidate;
NSLog(@"Write access to the event store granted and eventStore initialized.");
}
}

Expand Down Expand Up @@ -1043,7 +1120,7 @@ - (void)hasReadPermission:(CDVInvokedUrlCommand*)command {
}

- (void)requestReadPermission:(CDVInvokedUrlCommand*)command {
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:[self requestCalendarAccess]];
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:[self requestFullCalendarAccess]];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}

Expand All @@ -1053,7 +1130,7 @@ - (void)hasWritePermission:(CDVInvokedUrlCommand*)command {
}

- (void)requestWritePermission:(CDVInvokedUrlCommand*)command {
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:[self requestCalendarAccess]];
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:[self requestWriteCalendarAccess]];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}

Expand All @@ -1063,14 +1140,18 @@ - (void)hasReadWritePermission:(CDVInvokedUrlCommand*)command {
}

- (void)requestReadWritePermission:(CDVInvokedUrlCommand*)command {
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:[self requestCalendarAccess]];
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:[self requestFullCalendarAccess]];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}

-(CDVCommandStatus)requestCalendarAccess{
[self initEventStoreWithCalendarCapabilities];
return (self.eventStore != nil) ? CDVCommandStatus_OK : CDVCommandStatus_ERROR;
-(CDVCommandStatus)requestFullCalendarAccess{
[self initEventStoreWithFullCalendarCapabilities];
return (self.eventStore != nil) ? CDVCommandStatus_OK : CDVCommandStatus_ERROR;
}

-(CDVCommandStatus)requestWriteCalendarAccess{
[self initEventStoreWithWriteCalendarCapabilities];
return (self.eventStore != nil) ? CDVCommandStatus_OK : CDVCommandStatus_ERROR;
}

@end

0 comments on commit 3181ad3

Please sign in to comment.