/// <summary>
        /// Tries to create a new calendar with the specified source/name/color.
        /// May fail depending on source.
        /// </summary>
        /// <remarks>
        /// This is only intended as a helper method for CreateEKCalendar,
        /// not to be called independently.
        /// </remarks>
        /// <returns>The created native calendar, or null on failure</returns>
        /// <param name="source">Calendar source (e.g. iCloud vs local vs gmail)</param>
        /// <param name="calendarName">Calendar name.</param>
        /// <param name="color">Calendar color.</param>
        private static EKCalendar SaveEKCalendar(EKSource source, string calendarName, string color = null)
        {
            var calendar = EKCalendar.Create(EKEntityType.Event, _eventStore);

            // Setup calendar to be inserted
            //
            calendar.Title = calendarName;

            if (!string.IsNullOrEmpty(color))
            {
                calendar.CGColor = ColorConversion.ToCGColor(color);
            }

            calendar.Source = source;

            if (_eventStore.SaveCalendar(calendar, true, out NSError error))
            {
                xLog.Debug($"Successfully saved calendar with source {source.Title}");

                // TODO: Should we try calling GetCalendars to make sure that
                //       the calendar isn't hidden??
                //
                return(calendar);
            }
            else
            {
                xLog.Debug($"Tried and failed to save calendar with source {source.Title}");
            }

            _eventStore.Reset();

            return(null);
        }
Beispiel #2
0
        /// <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));
                    }
                }
            }
        }
Beispiel #4
0
        /// <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
            });
        }