/// <summary> /// Creates a new Calendars.Plugin.Abstractions.CalendarEvent from an EKEvent /// </summary> /// <param name="ekEvent">Source EKEvent</param> /// <returns>Corresponding Calendars.Plugin.Abstraction.CalendarEvent</returns> public static CalendarEvent ToCalendarEvent(this EKEvent ekEvent) { string cClr = ColorConversion.ToHexColor(ekEvent.Calendar.CGColor); return(new CalendarEvent { Title = ekEvent.Title, Description = ekEvent.Notes, Start = ekEvent.StartDate.ToDateTime(), EventColorString = cClr, CalendarColorString = cClr, DisplayColorString = cClr, // EventKit treats a one-day AllDay event as starting/ending on the same day, // but WinPhone/Android (and thus Calendars.Plugin) define it as ending on the following day. // End = ekEvent.EndDate.ToDateTime().AddSeconds(ekEvent.AllDay ? 1 : 0), AllDay = ekEvent.AllDay, Location = ekEvent.Location, ExternalID = ekEvent.EventIdentifier, Reminders = ekEvent.Alarms?.Select(alarm => alarm.ToCalendarEventReminder()).ToList() }); }
/// <summary> /// Creates a new calendar or updates the name and color of an existing one. /// If a new calendar was created, the ExternalID property will be set on the Calendar object, /// to support future queries/updates. /// </summary> /// <param name="calendar">The calendar to create/update</param> /// <exception cref="System.ArgumentException">Calendar does not exist on device or is read-only</exception> /// <exception cref="System.UnauthorizedAccessException">Calendar access denied</exception> /// <exception cref="System.InvalidOperationException">No active calendar sources available to create calendar on.</exception> /// <exception cref="Plugin.Calendars.Abstractions.PlatformException">Unexpected platform-specific error</exception> public static async Task AddOrUpdateCalendarAsync(Calendar calendar) { await RequestCalendarAccess().ConfigureAwait(false); EKCalendar deviceCalendar = null; if (!string.IsNullOrEmpty(calendar.ExternalID)) { deviceCalendar = _eventStore.GetCalendar(calendar.ExternalID); if (deviceCalendar == null) { throw new ArgumentException("Specified calendar does not exist on device", nameof(calendar)); } } if (deviceCalendar == null) { deviceCalendar = CreateEKCalendar(calendar.Name, calendar.Color); calendar.ExternalID = deviceCalendar.CalendarIdentifier; // Update color in case iOS assigned one if (deviceCalendar?.CGColor != null) { calendar.Color = ColorConversion.ToHexColor(deviceCalendar.CGColor); } } else { deviceCalendar.Title = calendar.Name; if (!string.IsNullOrEmpty(calendar.Color)) { deviceCalendar.CGColor = ColorConversion.ToCGColor(calendar.Color); } if (!_eventStore.SaveCalendar(deviceCalendar, true, out NSError error)) { // Without this, the eventStore will continue to return the "updated" // 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(); if (error.Domain == _ekErrorDomain && error.Code == (int)EKErrorCode.CalendarIsImmutable) { throw new ArgumentException(error.LocalizedDescription, new NSErrorException(error)); } else { throw new PlatformException(error.LocalizedDescription, new NSErrorException(error)); } } } }
/// <summary> /// Creates a new Calendars.Plugin.Abstractions.Calendar from an EKCalendar /// </summary> /// <param name="ekCalendar">Source EKCalendar</param> /// <returns>Corresponding Calendars.Plugin.Abstractions.Calendar</returns> public static Calendar ToCalendar(this EKCalendar ekCalendar) { xLog.Debug($"Calendar: {ekCalendar.Title}, Source: {ekCalendar.Source.Title}, {ekCalendar.Source.SourceType}"); return(new Calendar { Name = ekCalendar.Title, ExternalID = ekCalendar.CalendarIdentifier, CanEditCalendar = !ekCalendar.Immutable, CanEditEvents = ekCalendar.AllowsContentModifications, Color = ColorConversion.ToHexColor(ekCalendar.CGColor), AccountName = ekCalendar.Source.Title }); }