Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add deleteCalendar() function #278

Merged
merged 4 commits into from
Mar 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class CalendarDelegate : PluginRegistry.RequestPermissionsResultListener {
private val CREATE_OR_UPDATE_EVENT_REQUEST_CODE = RETRIEVE_CALENDAR_REQUEST_CODE + 1
private val DELETE_EVENT_REQUEST_CODE = CREATE_OR_UPDATE_EVENT_REQUEST_CODE + 1
private val REQUEST_PERMISSIONS_REQUEST_CODE = DELETE_EVENT_REQUEST_CODE + 1
private val DELETE_CALENDAR_REQUEST_CODE = REQUEST_PERMISSIONS_REQUEST_CODE + 1
private val PART_TEMPLATE = ";%s="
private val BYMONTHDAY_PART = "BYMONTHDAY"
private val BYMONTH_PART = "BYMONTH"
Expand Down Expand Up @@ -141,6 +142,9 @@ class CalendarDelegate : PluginRegistry.RequestPermissionsResultListener {
REQUEST_PERMISSIONS_REQUEST_CODE -> {
finishWithSuccess(permissionGranted, cachedValues.pendingChannelResult)
}
DELETE_CALENDAR_REQUEST_CODE -> {
deleteCalendar(cachedValues.calendarId,cachedValues.pendingChannelResult)
}
}

return true
Expand Down Expand Up @@ -236,6 +240,39 @@ class CalendarDelegate : PluginRegistry.RequestPermissionsResultListener {
return null
}

fun deleteCalendar(calendarId: String, pendingChannelResult: MethodChannel.Result, isInternalCall: Boolean = false): Calendar? {
if (isInternalCall || arePermissionsGranted()) {
val calendarIdNumber = calendarId.toLongOrNull()
if (calendarIdNumber == null) {
if (!isInternalCall) {
finishWithError(INVALID_ARGUMENT, CALENDAR_ID_INVALID_ARGUMENT_NOT_A_NUMBER_MESSAGE, pendingChannelResult)
}
return null
}

val contentResolver: ContentResolver? = _context?.contentResolver

val calendar = retrieveCalendar(calendarId,pendingChannelResult,true);
if(calendar != null) {
val calenderUriWithId = ContentUris.withAppendedId(CalendarContract.Calendars.CONTENT_URI, calendarIdNumber)
val deleteSucceeded = contentResolver?.delete(calenderUriWithId, null, null) ?: 0
finishWithSuccess(deleteSucceeded > 0, pendingChannelResult)
}else {
if (!isInternalCall) {
finishWithError(NOT_FOUND, "The calendar with the ID $calendarId could not be found", pendingChannelResult)
}
}
} else {
val parameters = CalendarMethodsParametersCacheModel(
pendingChannelResult = pendingChannelResult,
calendarDelegateMethodCode = DELETE_CALENDAR_REQUEST_CODE,
calendarId = calendarId)
requestPermissions(parameters)
}

return null
}

fun createCalendar(calendarName: String, calendarColor: String?, localAccountName: String, pendingChannelResult: MethodChannel.Result) {
val contentResolver: ContentResolver? = _context?.contentResolver

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class DeviceCalendarPlugin() : MethodCallHandler {
private val DELETE_EVENT_INSTANCE_METHOD = "deleteEventInstance"
private val CREATE_OR_UPDATE_EVENT_METHOD = "createOrUpdateEvent"
private val CREATE_CALENDAR_METHOD = "createCalendar"
private val DELETE_CALENDAR_METHOD = "deleteCalendar"

// Method arguments
private val CALENDAR_ID_ARGUMENT = "calendarId"
Expand Down Expand Up @@ -130,6 +131,10 @@ class DeviceCalendarPlugin() : MethodCallHandler {

_calendarDelegate.createCalendar(calendarName!!, calendarColor, localAccountName!!, result)
}
DELETE_CALENDAR_METHOD -> {
val calendarId = call.argument<String>(CALENDAR_ID_ARGUMENT)
_calendarDelegate.deleteCalendar(calendarId!!,result)
}
else -> {
result.notImplemented()
}
Expand Down
1 change: 1 addition & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ stages:
displayName: 'Flutter build - Android'
inputs:
target: 'aab'
buildNumber: $(Build.BuildID)
projectDirectory: 'example'

- task: FlutterBuild@0
Expand Down
2 changes: 1 addition & 1 deletion example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
compileSdkVersion 29
ndkVersion '21.3.6528147'
ndkVersion '22.0.7026061'

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
Expand Down
50 changes: 49 additions & 1 deletion example/lib/presentation/pages/calendar_events.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ class _CalendarEventsPageState extends State<CalendarEventsPage> {
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldstate,
appBar: AppBar(title: Text('${_calendar.name} events')),
appBar: AppBar(title: Text('${_calendar.name} events'),actions: [
_getDeleteButton()
],),
body: ((_calendarEvents?.isNotEmpty ?? false) || _isLoading)
? Stack(
children: [
Expand Down Expand Up @@ -137,4 +139,50 @@ class _CalendarEventsPageState extends State<CalendarEventsPage> {
_isLoading = false;
});
}

Widget _getDeleteButton() {
return IconButton(
icon: Icon(Icons.delete),
onPressed: () async {
_showDeleteDialog();
});
}

Future<void> _showDeleteDialog() async {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Warning'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('This will delete this calendar'),
Text('Are you sure?'),
],
),
),
actions: <Widget>[
TextButton(
child: Text('Delete!'),
onPressed: () async {
var returnValue = await _deviceCalendarPlugin.deleteCalendar(_calendar.id);
print("returnValue: ${returnValue.data}, ${returnValue.errors}");
Navigator.of(context).pop();
Navigator.of(context).pop();
},
),
TextButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
}


11 changes: 11 additions & 0 deletions example/lib/presentation/pages/calendars.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ class _CalendarsPageState extends State<CalendarsPage> {
return Scaffold(
appBar: AppBar(
title: Text('Calendars'),
actions: [
_getRefreshButton()
],
),
body: Column(
children: [
Expand Down Expand Up @@ -136,4 +139,12 @@ class _CalendarsPageState extends State<CalendarsPage> {
print(e);
}
}

Widget _getRefreshButton() {
return IconButton(
icon: Icon(Icons.refresh),
onPressed: () async {
_retrieveCalendars();
});
}
}
29 changes: 29 additions & 0 deletions ios/Classes/SwiftDeviceCalendarPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public class SwiftDeviceCalendarPlugin: NSObject, FlutterPlugin {
let retrieveSourcesMethod = "retrieveSources"
let createOrUpdateEventMethod = "createOrUpdateEvent"
let createCalendarMethod = "createCalendar"
let deleteCalendarMethod = "deleteCalendar"
let deleteEventMethod = "deleteEvent"
let deleteEventInstanceMethod = "deleteEventInstance"
let calendarIdArgument = "calendarId"
Expand Down Expand Up @@ -146,6 +147,8 @@ public class SwiftDeviceCalendarPlugin: NSObject, FlutterPlugin {
deleteEvent(call, result)
case createCalendarMethod:
createCalendar(call, result)
case deleteCalendarMethod:
deleteCalendar(call, result)
default:
result(FlutterMethodNotImplemented)
}
Expand Down Expand Up @@ -209,6 +212,32 @@ public class SwiftDeviceCalendarPlugin: NSObject, FlutterPlugin {
}, result: result)
}

private func deleteCalendar(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
checkPermissionsThenExecute(permissionsGrantedAction: {
let arguments = call.arguments as! Dictionary<String, AnyObject>
let calendarId = arguments[calendarIdArgument] as! String

let ekCalendar = self.eventStore.calendar(withIdentifier: calendarId)
if ekCalendar == nil {
self.finishWithCalendarNotFoundError(result: result, calendarId: calendarId)
return
}

if !(ekCalendar!.allowsContentModifications) {
self.finishWithCalendarReadOnlyError(result: result, calendarId: calendarId)
return
}

do {
try self.eventStore.removeCalendar(ekCalendar!, commit: true)
result(true)
} catch {
self.eventStore.reset()
result(FlutterError(code: self.genericError, message: error.localizedDescription, details: nil))
}
}, result: result)
}

private func getAccountType(_ sourceType: EKSourceType) -> String {
switch (sourceType) {
case .local:
Expand Down
1 change: 1 addition & 0 deletions lib/src/common/channel_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class ChannelConstants {
static const String methodNameDeleteEventInstance = 'deleteEventInstance';
static const String methodNameCreateOrUpdateEvent = 'createOrUpdateEvent';
static const String methodNameCreateCalendar = 'createCalendar';
static const String methodNameDeleteCalendar = 'deleteCalendar';

static const String parameterNameCalendarId = 'calendarId';
static const String parameterNameStartDate = 'startDate';
Expand Down
20 changes: 20 additions & 0 deletions lib/src/device_calendar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,26 @@ class DeviceCalendarPlugin {
);
}

/// Deletes a calendar.
/// The `calendarId` parameter is the id of the calendar that plugin will try to delete the event from\///
/// Returns a [Result] indicating if the instance of the calendar has (true) or has not (false) been deleted
Future<Result<bool>> deleteCalendar(
String calendarId,
) async {
return _invokeChannelMethod(
ChannelConstants.methodNameDeleteCalendar,
assertParameters: (result) {
_validateCalendarIdParameter(
result,
calendarId,
);
},
arguments: () => <String, Object>{
ChannelConstants.parameterNameCalendarId: calendarId,
},
);
}

Future<Result<T>> _invokeChannelMethod<T>(
String channelMethodName, {
Function(Result<T>) assertParameters,
Expand Down