diff --git a/.gitignore b/.gitignore
index 2f72fc4..3fb8294 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,8 @@ build/
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
+*.lock.json
+
*_i.c
*_p.c
*.ilk
diff --git a/Calendars.sln b/Calendars.sln
index 5c63dde..65e44ee 100644
--- a/Calendars.sln
+++ b/Calendars.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
-VisualStudioVersion = 14.0.23107.0
+VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calendars.Plugin", "Calendars\Calendars.Plugin\Calendars.Plugin.csproj", "{A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}"
EndProject
@@ -104,6 +104,7 @@ Global
{A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|ARM.ActiveCfg = Debug|Any CPU
{A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|iPhone.Build.0 = Debug|Any CPU
{A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{A6FCEF44-D2BA-42C7-B3CB-13667BCD7B54}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -148,6 +149,7 @@ Global
{6EDB0588-FFC5-4EF5-8A99-9E241D0F878D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6EDB0588-FFC5-4EF5-8A99-9E241D0F878D}.Debug|ARM.ActiveCfg = Debug|Any CPU
{6EDB0588-FFC5-4EF5-8A99-9E241D0F878D}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {6EDB0588-FFC5-4EF5-8A99-9E241D0F878D}.Debug|iPhone.Build.0 = Debug|Any CPU
{6EDB0588-FFC5-4EF5-8A99-9E241D0F878D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{6EDB0588-FFC5-4EF5-8A99-9E241D0F878D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{6EDB0588-FFC5-4EF5-8A99-9E241D0F878D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -191,6 +193,7 @@ Global
{D7F3AA16-8EF1-4924-9E0A-DAD4AB46B2EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D7F3AA16-8EF1-4924-9E0A-DAD4AB46B2EB}.Debug|ARM.ActiveCfg = Debug|Any CPU
{D7F3AA16-8EF1-4924-9E0A-DAD4AB46B2EB}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {D7F3AA16-8EF1-4924-9E0A-DAD4AB46B2EB}.Debug|iPhone.Build.0 = Debug|Any CPU
{D7F3AA16-8EF1-4924-9E0A-DAD4AB46B2EB}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{D7F3AA16-8EF1-4924-9E0A-DAD4AB46B2EB}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{D7F3AA16-8EF1-4924-9E0A-DAD4AB46B2EB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -233,6 +236,7 @@ Global
{2882AEEB-D4CD-4EB9-8A6C-6653B33681F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2882AEEB-D4CD-4EB9-8A6C-6653B33681F0}.Debug|ARM.ActiveCfg = Debug|Any CPU
{2882AEEB-D4CD-4EB9-8A6C-6653B33681F0}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {2882AEEB-D4CD-4EB9-8A6C-6653B33681F0}.Debug|iPhone.Build.0 = Debug|Any CPU
{2882AEEB-D4CD-4EB9-8A6C-6653B33681F0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{2882AEEB-D4CD-4EB9-8A6C-6653B33681F0}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{2882AEEB-D4CD-4EB9-8A6C-6653B33681F0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -273,6 +277,7 @@ Global
{56A56F17-7DE1-4CA1-9617-BF32E971AC84}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{56A56F17-7DE1-4CA1-9617-BF32E971AC84}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{56A56F17-7DE1-4CA1-9617-BF32E971AC84}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {56A56F17-7DE1-4CA1-9617-BF32E971AC84}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{56A56F17-7DE1-4CA1-9617-BF32E971AC84}.Debug|x64.ActiveCfg = Debug|Any CPU
{56A56F17-7DE1-4CA1-9617-BF32E971AC84}.Debug|x86.ActiveCfg = Debug|Any CPU
{56A56F17-7DE1-4CA1-9617-BF32E971AC84}.Release|Android.ActiveCfg = Release|Any CPU
@@ -717,6 +722,8 @@ Global
{E6284EB0-BDB0-4D38-AFC4-ECDC7BFF6D6E}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{E6284EB0-BDB0-4D38-AFC4-ECDC7BFF6D6E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{E6284EB0-BDB0-4D38-AFC4-ECDC7BFF6D6E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {E6284EB0-BDB0-4D38-AFC4-ECDC7BFF6D6E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {E6284EB0-BDB0-4D38-AFC4-ECDC7BFF6D6E}.Debug|Mixed Platforms.Deploy.0 = Debug|Any CPU
{E6284EB0-BDB0-4D38-AFC4-ECDC7BFF6D6E}.Debug|x64.ActiveCfg = Debug|Any CPU
{E6284EB0-BDB0-4D38-AFC4-ECDC7BFF6D6E}.Debug|x86.ActiveCfg = Debug|Any CPU
{E6284EB0-BDB0-4D38-AFC4-ECDC7BFF6D6E}.Release|Android.ActiveCfg = Release|Any CPU
diff --git a/Calendars/Calendars.Plugin.Abstractions/CalendarEvent.cs b/Calendars/Calendars.Plugin.Abstractions/CalendarEvent.cs
index 0271f17..f7549c7 100644
--- a/Calendars/Calendars.Plugin.Abstractions/CalendarEvent.cs
+++ b/Calendars/Calendars.Plugin.Abstractions/CalendarEvent.cs
@@ -26,6 +26,11 @@ public class CalendarEvent
///
public DateTime End { get; set; }
+ ///
+ /// Gets or sets the location of the event
+ ///
+ public string Location { get; set; }
+
///
/// Whether or not this is an "all-day" event.
///
@@ -42,6 +47,7 @@ public class CalendarEvent
///
/// This ID will be the same for each instance of a recurring event.
public string ExternalID { get; set; }
+
///
/// Simple ToString helper, to assist with debugging.
@@ -49,7 +55,7 @@ public class CalendarEvent
///
public override string ToString()
{
- return "Name=" + Name + ", AllDay=" + AllDay + ", Start=" + Start + ", End=" + End;
+ return "Name=" + Name + ", AllDay=" + AllDay + ", Start=" + Start + ", End=" + End + ", Location=" + Location;
}
}
}
diff --git a/Calendars/Calendars.Plugin.Abstractions/CalendarEventReminder.cs b/Calendars/Calendars.Plugin.Abstractions/CalendarEventReminder.cs
new file mode 100644
index 0000000..890e12e
--- /dev/null
+++ b/Calendars/Calendars.Plugin.Abstractions/CalendarEventReminder.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Calendars.Plugin.Abstractions
+{
+ ///
+ /// Calendar reminder that happens before the event such as an alert
+ ///
+ public class CalendarEventReminder
+ {
+
+ ///
+ /// Amount of time to set the reminder before the start of an event.
+ /// Default is 15 minutes
+ ///
+ public TimeSpan TimeBefore { get; set; } = TimeSpan.FromMinutes(15);
+ ///
+ /// Type of reminder to display
+ ///
+ public CalendarReminderMethod Method { get; set; } = CalendarReminderMethod.Default;
+
+ }
+
+ ///
+ /// Types of methods of the reminder
+ ///
+ public enum CalendarReminderMethod
+ {
+ ///
+ /// Use system default
+ ///
+ Default,
+ ///
+ /// Pop up alert
+ ///
+ Alert,
+ ///
+ /// Send an email
+ ///
+ Email,
+ ///
+ /// Send an sms
+ ///
+ Sms
+ }
+}
diff --git a/Calendars/Calendars.Plugin.Abstractions/Calendars.Plugin.Abstractions.csproj b/Calendars/Calendars.Plugin.Abstractions/Calendars.Plugin.Abstractions.csproj
index 469518f..75bc3e0 100644
--- a/Calendars/Calendars.Plugin.Abstractions/Calendars.Plugin.Abstractions.csproj
+++ b/Calendars/Calendars.Plugin.Abstractions/Calendars.Plugin.Abstractions.csproj
@@ -40,6 +40,7 @@
+
diff --git a/Calendars/Calendars.Plugin.Abstractions/ICalendars.cs b/Calendars/Calendars.Plugin.Abstractions/ICalendars.cs
index faf68b5..94d38bf 100644
--- a/Calendars/Calendars.Plugin.Abstractions/ICalendars.cs
+++ b/Calendars/Calendars.Plugin.Abstractions/ICalendars.cs
@@ -88,5 +88,15 @@ public interface ICalendars
/// Calendar access denied
/// Unexpected platform-specific error
Task DeleteEventAsync(Calendar calendar, CalendarEvent calendarEvent);
+
+ ///
+ /// Adds a reminder to the specified calendar event
+ ///
+ /// Event to add
+ /// Reminder to add
+ /// If successful
+ /// If calendar event is not created or not valid
+ /// Unexpected platform-specific error
+ Task AddEventReminderAsync(CalendarEvent calendarEvent, CalendarEventReminder reminder);
}
}
diff --git a/Calendars/Calendars.Plugin.Android/CalendarsImplementation.cs b/Calendars/Calendars.Plugin.Android/CalendarsImplementation.cs
index a3b70b3..ff4d996 100644
--- a/Calendars/Calendars.Plugin.Android/CalendarsImplementation.cs
+++ b/Calendars/Calendars.Plugin.Android/CalendarsImplementation.cs
@@ -177,6 +177,7 @@ public async Task> GetEventsAsync(Calendar calendar, DateTi
CalendarContract.Events.InterfaceConsts.Dtstart,
CalendarContract.Events.InterfaceConsts.Dtend,
CalendarContract.Events.InterfaceConsts.AllDay,
+ CalendarContract.Events.InterfaceConsts.EventLocation,
CalendarContract.Instances.EventId
};
@@ -204,6 +205,7 @@ await Task.Run(() =>
Description = cursor.GetString(CalendarContract.Events.InterfaceConsts.Description),
Start = cursor.GetDateTime(CalendarContract.Events.InterfaceConsts.Dtstart),
End = cursor.GetDateTime(CalendarContract.Events.InterfaceConsts.Dtend),
+ Location = cursor.GetString(CalendarContract.Events.InterfaceConsts.EventLocation),
AllDay = cursor.GetBoolean(CalendarContract.Events.InterfaceConsts.AllDay)
});
} while (cursor.MoveToNext());
@@ -241,6 +243,7 @@ public Task GetEventByIdAsync(string externalId)
CalendarContract.Events.InterfaceConsts.Description,
CalendarContract.Events.InterfaceConsts.Dtstart,
CalendarContract.Events.InterfaceConsts.Dtend,
+ CalendarContract.Events.InterfaceConsts.EventLocation,
CalendarContract.Events.InterfaceConsts.AllDay
};
@@ -262,6 +265,7 @@ public Task GetEventByIdAsync(string externalId)
Description = cursor.GetString(CalendarContract.Events.InterfaceConsts.Description),
Start = cursor.GetDateTime(CalendarContract.Events.InterfaceConsts.Dtstart),
End = cursor.GetDateTime(CalendarContract.Events.InterfaceConsts.Dtend),
+ Location = cursor.GetString(CalendarContract.Events.InterfaceConsts.EventLocation),
AllDay = cursor.GetBoolean(CalendarContract.Events.InterfaceConsts.AllDay)
};
}
@@ -333,6 +337,7 @@ public async Task AddOrUpdateCalendarAsync(Calendar calendar)
values.Put(CalendarContract.Calendars.InterfaceConsts.AccountName, AccountName);
values.Put(CalendarContract.Calendars.InterfaceConsts.OwnerAccount, OwnerAccount);
values.Put(CalendarContract.Calendars.InterfaceConsts.Visible, true);
+ values.Put(CalendarContract.Calendars.InterfaceConsts.SyncEvents, true);
values.Put(CalendarContract.Calendars.InterfaceConsts.AccountType, CalendarContract.AccountTypeLocal);
}
@@ -421,6 +426,8 @@ await Task.Run(() =>
DateConversions.GetDateAsAndroidMS(calendarEvent.End));
eventValues.Put(CalendarContract.Events.InterfaceConsts.AllDay,
calendarEvent.AllDay);
+ eventValues.Put(CalendarContract.Events.InterfaceConsts.EventLocation,
+ calendarEvent.Location ?? string.Empty);
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone,
Java.Util.TimeZone.Default.ID);
@@ -435,7 +442,60 @@ await Task.Run(() =>
}
});
}
+
+ ///
+ /// Adds an event reminder to specified calendar event
+ ///
+ /// Event to add the reminder to
+ /// The reminder
+ /// Success or failure
+ /// If calendar event is not created or not valid
+ /// Unexpected platform-specific error
+ public async Task AddEventReminderAsync(CalendarEvent calendarEvent, CalendarEventReminder reminder)
+ {
+ if (string.IsNullOrEmpty(calendarEvent.ExternalID))
+ {
+ throw new ArgumentException("Missing calendar event identifier", "calendarEvent");
+ }
+ // Verify calendar event exists
+ var existingAppt = await GetEventByIdAsync(calendarEvent.ExternalID).ConfigureAwait(false);
+
+ if (existingAppt == null)
+ {
+ throw new ArgumentException("Specified calendar event not found on device");
+ }
+ return await Task.Run(() =>
+ {
+ var reminderValues = new ContentValues();
+ reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.Minutes, reminder?.TimeBefore.TotalMinutes ?? 15);
+ reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.EventId, calendarEvent.ExternalID);
+ switch(reminder.Method)
+ {
+ case CalendarReminderMethod.Alert:
+ reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.Method, (int)RemindersMethod.Alert);
+ break;
+ case CalendarReminderMethod.Default:
+ reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.Method, (int)RemindersMethod.Default);
+ break;
+ case CalendarReminderMethod.Email:
+ reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.Method, (int)RemindersMethod.Email);
+ break;
+ case CalendarReminderMethod.Sms:
+ reminderValues.Put(CalendarContract.Reminders.InterfaceConsts.Method, (int)RemindersMethod.Sms);
+ break;
+
+ }
+ var uri = CalendarContract.Reminders.ContentUri;
+ Insert(uri, reminderValues);
+
+
+ return true;
+ });
+
+ }
+
+
///
/// Removes a calendar and all its events from the system.
///
@@ -638,4 +698,4 @@ private static Exception TranslateException(Java.Lang.Exception ex)
#endregion
}
-}
\ No newline at end of file
+}
diff --git a/Calendars/Calendars.Plugin.WindowsPhoneSL81/AppointmentExtensions.cs b/Calendars/Calendars.Plugin.WindowsPhoneSL81/AppointmentExtensions.cs
index dd66bee..c670d1e 100644
--- a/Calendars/Calendars.Plugin.WindowsPhoneSL81/AppointmentExtensions.cs
+++ b/Calendars/Calendars.Plugin.WindowsPhoneSL81/AppointmentExtensions.cs
@@ -27,6 +27,7 @@ public static CalendarEvent ToCalendarEvent(this Appointment appt)
Start = appt.StartTime.LocalDateTime,
End = appt.StartTime.Add(appt.Duration).LocalDateTime,
AllDay = appt.AllDay,
+ Location = appt.Location,
ExternalID = appt.LocalId
};
}
diff --git a/Calendars/Calendars.Plugin.WindowsPhoneSL81/CalendarsImplementation.cs b/Calendars/Calendars.Plugin.WindowsPhoneSL81/CalendarsImplementation.cs
index afa8e00..848793b 100644
--- a/Calendars/Calendars.Plugin.WindowsPhoneSL81/CalendarsImplementation.cs
+++ b/Calendars/Calendars.Plugin.WindowsPhoneSL81/CalendarsImplementation.cs
@@ -111,6 +111,7 @@ public async Task> GetEventsAsync(Calendar calendar, DateTi
options.FetchProperties.Add(AppointmentProperties.StartTime);
options.FetchProperties.Add(AppointmentProperties.Duration);
options.FetchProperties.Add(AppointmentProperties.AllDay);
+ options.FetchProperties.Add(AppointmentProperties.Location);
var appointments = await deviceCalendar.FindAppointmentsAsync(start, end - start, options).ConfigureAwait(false);
var events = appointments.Select(a => a.ToCalendarEvent()).ToList();
@@ -227,12 +228,52 @@ public async Task AddOrUpdateEventAsync(Calendar calendar, CalendarEvent calenda
appt.StartTime = calendarEvent.Start;
appt.Duration = calendarEvent.End - calendarEvent.Start;
appt.AllDay = calendarEvent.AllDay;
+ appt.Location = calendarEvent.Location ?? string.Empty;
await appCalendar.SaveAppointmentAsync(appt);
calendarEvent.ExternalID = appt.LocalId;
}
+ ///
+ /// Adds an event reminder to specified calendar event
+ ///
+ /// Event to add the reminder to
+ /// The reminder
+ /// Success or failure
+ /// If calendar event is not created or not valid
+ /// Unexpected platform-specific error
+ public async Task AddEventReminderAsync(CalendarEvent calendarEvent, CalendarEventReminder reminder)
+ {
+ if (string.IsNullOrEmpty(calendarEvent.ExternalID))
+ {
+ throw new ArgumentException("Missing calendar event identifier", "calendarEvent");
+ }
+
+
+ var existingAppt = await _localApptStore.GetAppointmentAsync(calendarEvent.ExternalID);
+
+
+ if (existingAppt == null)
+ {
+ throw new ArgumentException("Specified calendar event not found on device");
+ }
+
+
+ var appCalendar = await _localApptStore.GetAppointmentCalendarAsync(existingAppt.CalendarId);
+
+ if(appCalendar == null)
+ {
+ throw new ArgumentException("Event does not have a valid calendar.");
+ }
+
+ existingAppt.Reminder = reminder?.TimeBefore ?? TimeSpan.FromMinutes(15);
+
+ await appCalendar.SaveAppointmentAsync(existingAppt);
+
+ return true;
+ }
+
///
/// Removes a calendar and all its events from the system.
///
@@ -335,9 +376,9 @@ public async Task DeleteEventAsync(Calendar calendar, CalendarEvent calend
return deleted;
}
- #endregion
+#endregion
- #region Private Methods
+#region Private Methods
private async Task EnsureInitializedAsync()
{
@@ -422,4 +463,4 @@ private async Task GetLocalCalendarAsync(string id)
#endregion
}
-}
\ No newline at end of file
+}
diff --git a/Calendars/Calendars.Plugin.WindowsStore/CalendarsImplementation.cs b/Calendars/Calendars.Plugin.WindowsStore/CalendarsImplementation.cs
index af80a0c..0091acb 100644
--- a/Calendars/Calendars.Plugin.WindowsStore/CalendarsImplementation.cs
+++ b/Calendars/Calendars.Plugin.WindowsStore/CalendarsImplementation.cs
@@ -72,7 +72,15 @@ public Task AddOrUpdateEventAsync(Calendar calendar, CalendarEvent calendarEvent
///
/// Not supported for Windows Store apps
///
- public Task DeleteCalendarAsync(Calendar calendar)
+ public Task AddEventReminderAsync(CalendarEvent calendarEvent, CalendarEventReminder reminder)
+ {
+ throw new NotSupportedException();
+ }
+
+ ///
+ /// Not supported for Windows Store apps
+ ///
+ public Task DeleteCalendarAsync(Calendar calendar)
{
throw new NotSupportedException();
}
diff --git a/Calendars/Calendars.Plugin.iOSUnified/CalendarsImplementation.cs b/Calendars/Calendars.Plugin.iOSUnified/CalendarsImplementation.cs
index b6ec551..6961904 100644
--- a/Calendars/Calendars.Plugin.iOSUnified/CalendarsImplementation.cs
+++ b/Calendars/Calendars.Plugin.iOSUnified/CalendarsImplementation.cs
@@ -34,6 +34,7 @@ public class CalendarsImplementation : ICalendars
private EKEventStore _eventStore;
private bool? _hasCalendarAccess;
+ private double defaultTimeBefore;
#endregion
@@ -45,6 +46,8 @@ public class CalendarsImplementation : ICalendars
public CalendarsImplementation()
{
_eventStore = new EKEventStore();
+ //iOS stores in negative seconds before the event
+ defaultTimeBefore = -TimeSpan.FromMinutes(15).TotalSeconds;
}
#endregion
@@ -168,7 +171,8 @@ public async Task AddOrUpdateCalendarAsync(Calendar calendar)
calendar.ExternalID = deviceCalendar.CalendarIdentifier;
// Update color in case iOS assigned one
- calendar.Color = ColorConversion.ToHexColor(deviceCalendar.CGColor);
+ if(deviceCalendar?.CGColor != null)
+ calendar.Color = ColorConversion.ToHexColor(deviceCalendar.CGColor);
}
else
{
@@ -253,6 +257,7 @@ public async Task AddOrUpdateEventAsync(Calendar calendar, CalendarEvent calenda
iosEvent.Title = calendarEvent.Name;
iosEvent.Notes = calendarEvent.Description;
iosEvent.AllDay = calendarEvent.AllDay;
+ iosEvent.Location = calendarEvent.Location ?? string.Empty;
iosEvent.StartDate = calendarEvent.Start.ToNSDate();
// If set to AllDay and given an EndDate of 12am the next day, EventKit
@@ -289,6 +294,52 @@ public async Task AddOrUpdateEventAsync(Calendar calendar, CalendarEvent calenda
calendarEvent.ExternalID = iosEvent.EventIdentifier;
}
+ ///
+ /// Adds an event reminder to specified calendar event
+ ///
+ /// Event to add the reminder to
+ /// The reminder
+ /// Success or failure
+ /// If calendar event is not created or not valid
+ /// Unexpected platform-specific error
+ public Task AddEventReminderAsync(CalendarEvent calendarEvent, CalendarEventReminder reminder)
+ {
+ if (string.IsNullOrEmpty(calendarEvent.ExternalID))
+ {
+ throw new ArgumentException("Missing calendar event identifier", "calendarEvent");
+ }
+
+ //Grab current event
+ var existingEvent = _eventStore.EventFromIdentifier(calendarEvent.ExternalID);
+
+ if (existingEvent == null)
+ {
+ throw new ArgumentException("Specified calendar event not found on device");
+ }
+
+ //
+ var seconds = -reminder?.TimeBefore.TotalSeconds ?? defaultTimeBefore;
+ var alarm = EKAlarm.FromTimeInterval(seconds);
+
+ existingEvent.AddAlarm(alarm);
+ NSError error = null;
+ if (!_eventStore.SaveEvent(existingEvent, EKSpan.ThisEvent, out error))
+ {
+ // Without this, the eventStore will continue to return the "updated"
+ // event even though the save failed!
+ // (this obviously also resets any other changes, but since we own the eventStore
+ // we can be pretty confident that won't be an issue)
+ //
+ _eventStore.Reset();
+
+
+ throw new ArgumentException(error.LocalizedDescription, "reminder", new NSErrorException(error));
+ }
+
+
+ return Task.FromResult(true);
+ }
+
///
/// Removes a calendar and all its events from the system.
///
@@ -410,32 +461,76 @@ private async Task RequestCalendarAccess()
return _hasCalendarAccess.Value;
}
- private EKCalendar CreateEKCalendar(string calendarName, string color = null)
+
+ EKCalendar SaveEKCalendar(EKSource source, string calendarName, string color = null)
{
var calendar = EKCalendar.Create(EKEntityType.Event, _eventStore);
- calendar.Source = _eventStore.Sources.First(source => source.SourceType == EKSourceType.Local);
+
+ //Setup calendar to be inserted
calendar.Title = calendarName;
+ NSError error = null;
if (!string.IsNullOrEmpty(color))
{
calendar.CGColor = ColorConversion.ToCGColor(color);
}
+ calendar.Source = source;
+
+ if (_eventStore.SaveCalendar(calendar, true, out error))
+ {
+ return calendar;
+ }
+
+ _eventStore.Reset();
+
+ return null;
+
+ }
+
+ private EKCalendar CreateEKCalendar(string calendarName, string color = null)
+ {
+
NSError error = null;
- if (!_eventStore.SaveCalendar(calendar, true, out error))
+ //first attempt to find any and all iCloud sources
+ var iCloudSources = _eventStore.Sources.Where(s => s.SourceType == EKSourceType.CalDav && s.Title.Equals("icloud", StringComparison.InvariantCultureIgnoreCase));
+ foreach (var source in iCloudSources)
{
- // Without this, the eventStore may return the new calendar even though the save failed.
- // (this obviously also resets any other changes, but since we own the eventStore
- // we can be pretty confident that won't be an issue)
- //
- _eventStore.Reset();
+
+ //Ensure that the calendar is enabled
+ if (source.GetCalendars(EKEntityType.Event).Count > 0)
+ {
+ var cal = SaveEKCalendar(source, calendarName, color);
+ if (cal != null)
+ return cal;
+ }
+ }
- throw new PlatformException(error.LocalizedDescription, new NSErrorException(error));
+ //other sources that we didn't try before that are caldav
+ var otherSources = _eventStore.Sources.Where(s => s.SourceType == EKSourceType.CalDav && !s.Title.Equals("icloud", StringComparison.InvariantCultureIgnoreCase));
+ foreach (var source in otherSources)
+ {
+ var cal = SaveEKCalendar(source, calendarName, color);
+ if (cal != null)
+ return cal;
+ }
+
+
+ //finally attempt just local sources
+ var localSources = _eventStore.Sources.Where(s => s.SourceType == EKSourceType.Local);
+ foreach (var source in localSources)
+ {
+ var cal = SaveEKCalendar(source, calendarName, color);
+ if (cal != null)
+ return cal;
}
+
+
- return calendar;
+ throw new ArgumentException("No active calendar sources available to create calendar on.");
}
+
#endregion
}
-}
\ No newline at end of file
+}
diff --git a/Calendars/Calendars.Plugin.iOSUnified/EKEventExtensions.cs b/Calendars/Calendars.Plugin.iOSUnified/EKEventExtensions.cs
index 03d873f..d4e9f95 100644
--- a/Calendars/Calendars.Plugin.iOSUnified/EKEventExtensions.cs
+++ b/Calendars/Calendars.Plugin.iOSUnified/EKEventExtensions.cs
@@ -31,6 +31,7 @@ public static CalendarEvent ToCalendarEvent(this EKEvent ekEvent)
//
End = ekEvent.EndDate.ToDateTime().AddSeconds(ekEvent.AllDay ? 1 : 0),
AllDay = ekEvent.AllDay,
+ Location = ekEvent.Location,
ExternalID = ekEvent.EventIdentifier
};
}