diff --git a/DeviceTests/DeviceTests.Shared/Calendar_Tests.cs b/DeviceTests/DeviceTests.Shared/Calendar_Tests.cs
index f697f58c7..9c40af8c1 100644
--- a/DeviceTests/DeviceTests.Shared/Calendar_Tests.cs
+++ b/DeviceTests/DeviceTests.Shared/Calendar_Tests.cs
@@ -154,7 +154,7 @@ public Task Full_Calendar_Edit_Test()
Assert.Equal(newEvent.Duration, createdEvent.Duration);
Assert.Equal(newEvent.EndDate, createdEvent.EndDate);
Assert.Equal(newEvent.Attendees, createdEvent.Attendees);
- Assert.Equal(newEvent.Reminders, createdEvent.Reminders);
+ Assert.Equal(newEvent.Reminder, createdEvent.Reminder);
Assert.Equal(newEvent.RecurrancePattern, createdEvent.RecurrancePattern);
createdEvent.RecurrancePattern = new RecurrenceRule()
@@ -182,7 +182,7 @@ public Task Full_Calendar_Edit_Test()
Assert.Equal(createdEvent.AllDay, updatedEvent.AllDay);
Assert.NotEqual(createdEvent.StartDate, updatedEvent.StartDate);
Assert.Equal(createdEvent.Attendees, updatedEvent.Attendees);
- Assert.Equal(createdEvent.Reminders, updatedEvent.Reminders);
+ Assert.Equal(createdEvent.Reminder, updatedEvent.Reminder);
var attendeeToAddAndRemove = new CalendarEventAttendee() { Email = "fake@email.com", Name = "Fake Email", Type = AttendeeType.Resource };
diff --git a/Samples/Samples/Converters/ReminderTextConverter.cs b/Samples/Samples/Converters/ReminderTextConverter.cs
index 57b7cb0c5..11c43c81a 100644
--- a/Samples/Samples/Converters/ReminderTextConverter.cs
+++ b/Samples/Samples/Converters/ReminderTextConverter.cs
@@ -11,7 +11,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn
if (value == null || !(value is int minutes))
return null;
- return minutes > 0 ? $"{minutes} minutes prior" : "No Reminders";
+ return minutes > 0 ? $"{minutes} minutes prior" : "No Reminder";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException();
diff --git a/Samples/Samples/View/CalendarEventPage.xaml b/Samples/Samples/View/CalendarEventPage.xaml
index 939bc97c0..c4f7c07de 100644
--- a/Samples/Samples/View/CalendarEventPage.xaml
+++ b/Samples/Samples/View/CalendarEventPage.xaml
@@ -131,30 +131,30 @@
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/Samples/Samples/View/CalendarEventPage.xaml.cs b/Samples/Samples/View/CalendarEventPage.xaml.cs
index 282b65545..109067afe 100644
--- a/Samples/Samples/View/CalendarEventPage.xaml.cs
+++ b/Samples/Samples/View/CalendarEventPage.xaml.cs
@@ -1,6 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
using System.Linq;
using Samples.ViewModel;
using Xamarin.Essentials;
@@ -86,29 +84,22 @@ async void OnRemoveAttendeeFromEventButtonClicked(object sender, EventArgs e)
{
lst.Remove(attendeeToRemove);
}
- BindingContext = new CalendarEvent()
- {
- AllDay = ViewModel.AllDay,
- Attendees = lst,
- CalendarId = ViewModel.CalendarId,
- Description = ViewModel.Description,
- Duration = ViewModel.Duration,
- EndDate = ViewModel.EndDate,
- Id = ViewModel.Id,
- Location = ViewModel.Location,
- StartDate = ViewModel.StartDate,
- Title = ViewModel.Title
- };
+ ViewModel.Attendees = lst;
+ RefreshValues(ViewModel);
}
}
}
- void OnRemoveReminderFromEventButtonClicked(object sender, EventArgs e)
+ async void OnRemoveReminderFromEventButtonClicked(object sender, EventArgs e)
{
if (!(sender is Button btn) || !(EventId.Text is string eventId) || string.IsNullOrEmpty(eventId))
return;
- var attendee = btn?.BindingContext as CalendarEventReminder;
+ if (await Calendars.RemoveReminderFromEvent(eventId))
+ {
+ ViewModel.Reminder = null;
+ RefreshValues(ViewModel);
+ }
}
async void OnEditEventButtonClicked(object sender, EventArgs e)
@@ -120,5 +111,35 @@ async void OnEditEventButtonClicked(object sender, EventArgs e)
modal.BindingContext = new CalendarEventAddViewModel(ViewModel.CalendarId, calendarName, ViewModel);
await Navigation.PushAsync(modal);
}
+
+ async void OnAddReminderFromEventButtonClicked(object sender, EventArgs e)
+ {
+ if (!(EventId.Text is string eventId) || string.IsNullOrEmpty(eventId) || !(Reminder.Text is string reminderMinutesString) || !int.TryParse(reminderMinutesString, out var reminderMinutes))
+ return;
+
+ if (await Calendars.AddReminderToEvent(new CalendarEventReminder() { MinutesPriorToEventStart = reminderMinutes }, eventId))
+ {
+ ViewModel.Reminder = new CalendarEventReminder() { MinutesPriorToEventStart = reminderMinutes };
+ RefreshValues(ViewModel);
+ }
+ }
+
+ void RefreshValues(CalendarEvent eventRefresh) =>
+ BindingContext = new CalendarEvent()
+ {
+ AllDay = eventRefresh.AllDay,
+ Attendees = eventRefresh.Attendees,
+ CalendarId = eventRefresh.CalendarId,
+ Description = eventRefresh.Description,
+ Duration = eventRefresh.Duration,
+ EndDate = eventRefresh.EndDate,
+ RecurrancePattern = eventRefresh.RecurrancePattern,
+ Id = eventRefresh.Id,
+ Location = eventRefresh.Location,
+ StartDate = eventRefresh.StartDate,
+ Title = eventRefresh.Title,
+ Reminder = eventRefresh.Reminder,
+ Url = eventRefresh.Url
+ };
}
}
diff --git a/Xamarin.Essentials/Calendars/Calendars.android.cs b/Xamarin.Essentials/Calendars/Calendars.android.cs
index 7dff83827..bf9fb0ae1 100644
--- a/Xamarin.Essentials/Calendars/Calendars.android.cs
+++ b/Xamarin.Essentials/Calendars/Calendars.android.cs
@@ -218,7 +218,7 @@ static async Task PlatformGetEventByIdAsync(string eventId)
EndDate = eventEndDate,
Attendees = GetAttendeesForEvent(eventId, currentContextContentResolver.GetString(eventsProjection.IndexOf(CalendarContract.Events.InterfaceConsts.Organizer))),
RecurrancePattern = !string.IsNullOrEmpty(currentContextContentResolver.GetString(eventsProjection.IndexOf(CalendarContract.Events.InterfaceConsts.Rrule))) ? GetRecurranceRuleForEvent(currentContextContentResolver.GetString(eventsProjection.IndexOf(CalendarContract.Events.InterfaceConsts.Rrule))) : null,
- Reminders = GetRemindersForEvent(eventId)
+ Reminder = GetRemindersForEvent(eventId)
};
return eventResult;
}
@@ -276,7 +276,7 @@ static async Task PlatformGetEventInstanceByIdAsync(string eventI
EndDate = eventEndDate,
Attendees = GetAttendeesForEvent(eventId, currentContextContentResolver.GetString(eventsProjection.IndexOf(CalendarContract.Events.InterfaceConsts.Organizer))),
RecurrancePattern = !string.IsNullOrEmpty(currentContextContentResolver.GetString(eventsProjection.IndexOf(CalendarContract.Events.InterfaceConsts.Rrule))) ? GetRecurranceRuleForEvent(currentContextContentResolver.GetString(eventsProjection.IndexOf(CalendarContract.Events.InterfaceConsts.Rrule))) : null,
- Reminders = GetRemindersForEvent(eventId)
+ Reminder = GetRemindersForEvent(eventId)
};
}
throw new ArgumentOutOfRangeException($"[Android]: No Event found for event Id {eventId}");
@@ -310,7 +310,7 @@ static IEnumerable GetAttendeesForEvent(string eventId, s
return attendees.OrderByDescending(x => x.IsOrganizer);
}
- static IEnumerable GetRemindersForEvent(string eventId)
+ static CalendarEventReminder GetRemindersForEvent(string eventId)
{
var remindersUri = CalendarContract.Reminders.ContentUri;
var remindersProjection = new List
@@ -330,7 +330,7 @@ static IEnumerable GetRemindersForEvent(string eventId)
});
}
}
- return reminders;
+ return reminders.First();
}
static async Task PlatformCreateCalendar(Calendar newCalendar)
@@ -749,5 +749,9 @@ static string ToDayString(this List dayList)
}
return toReturn.Substring(0, toReturn.Length - 1);
}
+
+ static Task PlatformAddReminderToEvent(CalendarEventReminder calendarEventReminder, string eventId) => throw ExceptionUtils.NotSupportedOrImplementedException;
+
+ static Task PlatformReminderFromEvent(string eventId) => throw ExceptionUtils.NotSupportedOrImplementedException;
}
}
diff --git a/Xamarin.Essentials/Calendars/Calendars.ios.cs b/Xamarin.Essentials/Calendars/Calendars.ios.cs
index b2ad0e62d..3e2d673af 100644
--- a/Xamarin.Essentials/Calendars/Calendars.ios.cs
+++ b/Xamarin.Essentials/Calendars/Calendars.ios.cs
@@ -83,8 +83,7 @@ static async Task PlatformGetEventByIdAsync(string eventId)
throw new ArgumentException($"[iOS]: No Event found for event Id {eventId}");
}
- var calendarEvent = CalendarRequest.Instance.GetCalendarItem(eventId) as EKEvent;
- if (calendarEvent == null)
+ if (!(CalendarRequest.Instance.GetCalendarItem(eventId) is EKEvent calendarEvent))
{
throw new ArgumentOutOfRangeException($"[iOS]: No Event found for event Id {eventId}");
}
@@ -126,7 +125,7 @@ static async Task PlatformGetEventByIdAsync(string eventId)
EndDate = !calendarEvent.AllDay ? (DateTimeOffset?)calendarEvent.EndDate.ToDateTimeOffsetWithTimeZone(calendarEvent.TimeZone) : null,
Attendees = attendees,
RecurrancePattern = recurrenceRule,
- Reminders = alarms
+ Reminder = alarms.First()
};
}
@@ -186,7 +185,7 @@ static async Task PlatformGetEventInstanceByIdAsync(string eventI
EndDate = !calendarEvent.AllDay ? (DateTimeOffset?)calendarEvent.EndDate.ToDateTimeOffsetWithTimeZone(calendarEvent.TimeZone) : null,
Attendees = attendees,
RecurrancePattern = recurrenceRule,
- Reminders = alarms
+ Reminder = alarms.First()
};
}
@@ -505,5 +504,54 @@ static async Task PlatformRemoveAttendeeFromEvent(CalendarEventAttendee ne
}
throw new Exception(error.DebugDescription);
}
+
+ static async Task PlatformAddReminderToEvent(CalendarEventReminder calendarEventReminder, string eventId)
+ {
+ await Permissions.RequestAsync();
+
+ if (string.IsNullOrWhiteSpace(eventId))
+ {
+ throw new ArgumentException($"[iOS]: No Event found for event Id {eventId}");
+ }
+
+ if (!(CalendarRequest.Instance.GetCalendarItem(eventId) is EKEvent calendarEvent))
+ {
+ throw new ArgumentOutOfRangeException($"[iOS]: No Event found for event Id {eventId}");
+ }
+
+ calendarEvent.Alarms = new EKAlarm[1]
+ {
+ EKAlarm.FromTimeInterval((double)calendarEventReminder.MinutesPriorToEventStart * 60)
+ };
+
+ if (CalendarRequest.Instance.SaveEvent(calendarEvent, EKSpan.FutureEvents, true, out var error))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ static async Task PlatformReminderFromEvent(string eventId)
+ {
+ await Permissions.RequestAsync();
+
+ if (string.IsNullOrWhiteSpace(eventId))
+ {
+ throw new ArgumentException($"[iOS]: No Event found for event Id {eventId}");
+ }
+
+ if (!(CalendarRequest.Instance.GetCalendarItem(eventId) is EKEvent calendarEvent))
+ {
+ throw new ArgumentOutOfRangeException($"[iOS]: No Event found for event Id {eventId}");
+ }
+
+ calendarEvent.Alarms = null;
+
+ if (CalendarRequest.Instance.SaveEvent(calendarEvent, EKSpan.FutureEvents, true, out var error))
+ {
+ return true;
+ }
+ return false;
+ }
}
}
diff --git a/Xamarin.Essentials/Calendars/Calendars.netstandard.tvos.watchos.tizen.cs b/Xamarin.Essentials/Calendars/Calendars.netstandard.tvos.watchos.tizen.cs
index 741d5da15..adb12f014 100644
--- a/Xamarin.Essentials/Calendars/Calendars.netstandard.tvos.watchos.tizen.cs
+++ b/Xamarin.Essentials/Calendars/Calendars.netstandard.tvos.watchos.tizen.cs
@@ -27,5 +27,9 @@ public static partial class Calendars
static Task PlatformAddAttendeeToEvent(CalendarEventAttendee newAttendee, string eventId) => throw ExceptionUtils.NotSupportedOrImplementedException;
static Task PlatformRemoveAttendeeFromEvent(CalendarEventAttendee newAttendee, string eventId) => throw ExceptionUtils.NotSupportedOrImplementedException;
+
+ static Task PlatformReminderFromEvent(string eventId) => throw ExceptionUtils.NotSupportedOrImplementedException;
+
+ static Task PlatformAddReminderToEvent(CalendarEventReminder calendarEventReminder, string eventId) => throw ExceptionUtils.NotSupportedOrImplementedException;
}
}
diff --git a/Xamarin.Essentials/Calendars/Calendars.shared.cs b/Xamarin.Essentials/Calendars/Calendars.shared.cs
index 462c7bc8f..a3308e917 100644
--- a/Xamarin.Essentials/Calendars/Calendars.shared.cs
+++ b/Xamarin.Essentials/Calendars/Calendars.shared.cs
@@ -31,5 +31,9 @@ public static partial class Calendars
public static Task AddAttendeeToEvent(CalendarEventAttendee newAttendee, string eventId) => PlatformAddAttendeeToEvent(newAttendee, eventId);
public static Task RemoveAttendeeFromEvent(CalendarEventAttendee newAttendee, string eventId) => PlatformRemoveAttendeeFromEvent(newAttendee, eventId);
+
+ public static Task AddReminderToEvent(CalendarEventReminder newReminder, string eventId) => PlatformAddReminderToEvent(newReminder, eventId);
+
+ public static Task RemoveReminderFromEvent(string eventId) => PlatformReminderFromEvent(eventId);
}
}
diff --git a/Xamarin.Essentials/Calendars/Calendars.uwp.cs b/Xamarin.Essentials/Calendars/Calendars.uwp.cs
index ad1563f6e..14484f6a8 100644
--- a/Xamarin.Essentials/Calendars/Calendars.uwp.cs
+++ b/Xamarin.Essentials/Calendars/Calendars.uwp.cs
@@ -44,7 +44,7 @@ static async Task> PlatformGetEventsAsync(string cale
if (eDate < sDate)
eDate = sDate;
- var instance = await CalendarRequest.GetInstanceAsync(AppointmentStoreAccessType.AllCalendarsReadOnly);
+ var instance = await CalendarRequest.GetInstanceAsync();
var events = await instance.FindAppointmentsAsync(sDate, eDate.Subtract(sDate), options);
var eventList = (from e in events
@@ -70,7 +70,7 @@ static async Task> PlatformGetEventsAsync(string cale
static async Task GetCalendarById(string calendarId)
{
- var instance = await CalendarRequest.GetInstanceAsync(AppointmentStoreAccessType.AllCalendarsReadOnly);
+ var instance = await CalendarRequest.GetInstanceAsync();
var uwpCalendarList = await instance.FindAppointmentCalendarsAsync(FindAppointmentCalendarsOptions.IncludeHidden);
var result = (from calendar in uwpCalendarList
@@ -92,7 +92,7 @@ static async Task PlatformGetEventByIdAsync(string eventId)
{
await Permissions.RequestAsync();
- var instance = await CalendarRequest.GetInstanceAsync(AppointmentStoreAccessType.AllCalendarsReadOnly);
+ var instance = await CalendarRequest.GetInstanceAsync();
Appointment uwpAppointment;
try
@@ -155,7 +155,7 @@ static async Task PlatformGetEventByIdAsync(string eventId)
EndDate = !uwpAppointment.AllDay ? (DateTimeOffset?)uwpAppointment.StartTime.Add(uwpAppointment.Duration) : null,
Attendees = GetAttendeesForEvent(uwpAppointment.Invitees, uwpAppointment.Organizer),
RecurrancePattern = rules,
- Reminders = uwpAppointment.Reminder.HasValue ? new List() { new CalendarEventReminder() { MinutesPriorToEventStart = uwpAppointment.Reminder.Value.Minutes } } : null
+ Reminder = uwpAppointment.Reminder.HasValue ? new CalendarEventReminder() { MinutesPriorToEventStart = uwpAppointment.Reminder.Value.Minutes } : null
};
}
@@ -163,7 +163,7 @@ static async Task PlatformGetEventInstanceByIdAsync(string eventI
{
await Permissions.RequestAsync();
- var instance = await CalendarRequest.GetInstanceAsync(AppointmentStoreAccessType.AllCalendarsReadOnly);
+ var instance = await CalendarRequest.GetInstanceAsync();
Appointment uwpAppointment;
try
@@ -227,7 +227,7 @@ static async Task PlatformGetEventInstanceByIdAsync(string eventI
EndDate = !uwpAppointment.AllDay ? (DateTimeOffset?)uwpAppointment.StartTime.Add(uwpAppointment.Duration) : null,
Attendees = GetAttendeesForEvent(uwpAppointment.Invitees, uwpAppointment.Organizer),
RecurrancePattern = rules,
- Reminders = uwpAppointment.Reminder.HasValue ? new List() { new CalendarEventReminder() { MinutesPriorToEventStart = uwpAppointment.Reminder.Value.Minutes } } : null
+ Reminder = uwpAppointment.Reminder.HasValue ? new CalendarEventReminder() { MinutesPriorToEventStart = uwpAppointment.Reminder.Value.Minutes } : null
};
}
@@ -522,5 +522,67 @@ static async Task PlatformRemoveAttendeeFromEvent(CalendarEventAttendee ne
return attendeeToRemove != null;
}
+
+ static async Task PlatformAddReminderToEvent(CalendarEventReminder calendarEventReminder, string eventId)
+ {
+ await Permissions.RequestAsync();
+
+ var instance = await CalendarRequest.GetInstanceAsync();
+
+ Appointment uwpAppointment;
+ try
+ {
+ uwpAppointment = await instance.GetAppointmentAsync(eventId);
+ }
+ catch (ArgumentException)
+ {
+ if (string.IsNullOrWhiteSpace(eventId))
+ {
+ throw new ArgumentException($"[UWP]: No Event found for event Id {eventId}");
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException($"[UWP]: No Event found for event Id {eventId}");
+ }
+ }
+
+ uwpAppointment.Reminder = TimeSpan.FromMinutes(calendarEventReminder.MinutesPriorToEventStart);
+ var calendar = await instance.GetAppointmentCalendarAsync(uwpAppointment.CalendarId);
+ await calendar.SaveAppointmentAsync(uwpAppointment);
+ uwpAppointment = await instance.GetAppointmentAsync(eventId);
+
+ return uwpAppointment.Reminder != null;
+ }
+
+ static async Task PlatformReminderFromEvent(string eventId)
+ {
+ await Permissions.RequestAsync();
+
+ var instance = await CalendarRequest.GetInstanceAsync();
+
+ Appointment uwpAppointment;
+ try
+ {
+ uwpAppointment = await instance.GetAppointmentAsync(eventId);
+ }
+ catch (ArgumentException)
+ {
+ if (string.IsNullOrWhiteSpace(eventId))
+ {
+ throw new ArgumentException($"[UWP]: No Event found for event Id {eventId}");
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException($"[UWP]: No Event found for event Id {eventId}");
+ }
+ }
+
+ uwpAppointment.Reminder = null;
+ var calendar = await instance.GetAppointmentCalendarAsync(uwpAppointment.CalendarId);
+ await calendar.SaveAppointmentAsync(uwpAppointment);
+ uwpAppointment = await instance.GetAppointmentAsync(eventId);
+
+ return uwpAppointment.Reminder == null;
+ }
}
}
diff --git a/Xamarin.Essentials/Types/Calendar.shared.cs b/Xamarin.Essentials/Types/Calendar.shared.cs
index 5f2e8ad30..d5db5183d 100644
--- a/Xamarin.Essentials/Types/Calendar.shared.cs
+++ b/Xamarin.Essentials/Types/Calendar.shared.cs
@@ -46,7 +46,9 @@ public TimeSpan? Duration
public IEnumerable Attendees { get; set; }
- public IEnumerable Reminders { get; set; }
+ public bool HasReminder => Reminder != null;
+
+ public CalendarEventReminder Reminder { get; set; }
public RecurrenceRule RecurrancePattern { get; set; }
}