Skip to content

Commit

Permalink
#87 [iOS, UWP]: Ability to add reminders
Browse files Browse the repository at this point in the history
  • Loading branch information
ScottBTR committed Jan 31, 2020
1 parent ca626cd commit c33644e
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 58 deletions.
4 changes: 2 additions & 2 deletions DeviceTests/DeviceTests.Shared/Calendar_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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 = "[email protected]", Name = "Fake Email", Type = AttendeeType.Resource };

Expand Down
2 changes: 1 addition & 1 deletion Samples/Samples/Converters/ReminderTextConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
46 changes: 23 additions & 23 deletions Samples/Samples/View/CalendarEventPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -131,30 +131,30 @@
<Grid Grid.Row="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Text="Reminders: "/>
<StackLayout Grid.Row="0"
Grid.Column="1"
BindableLayout.ItemsSource="{Binding Reminders}">
<BindableLayout.ItemTemplate>
<DataTemplate x:DataType="essentials:CalendarEventReminder">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding MinutesPriorToEventStart, Converter={StaticResource ReminderTextConverter}}"/>
<Button Grid.Column="1"
Margin="0,0,15,0"
BackgroundColor="Red"
Text=" - "
Clicked="OnRemoveReminderFromEventButtonClicked"/>
</Grid>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</Grid>
<Label Text="Reminder: "
Grid.Column="0"/>
<Entry x:Name="Reminder"
Placeholder="X Minutes..."
Text="{Binding Reminder.MinutesPriorToEventStart}"
Grid.Column="1"
IsVisible="{Binding HasReminder, Converter={StaticResource NegativeConverter}}"/>
<Button Text="Add"
Grid.Column="2"
Clicked="OnAddReminderFromEventButtonClicked"
IsVisible="{Binding HasReminder, Converter={StaticResource NegativeConverter}}"/>
<Label Text="{Binding Reminder.MinutesPriorToEventStart, Converter={StaticResource ReminderTextConverter}}"
Grid.Column="1"
IsVisible="{Binding HasReminder}"/>
<Button Grid.Column="2"
Margin="0,0,15,0"
BackgroundColor="Red"
Text=" - "
Clicked="OnRemoveReminderFromEventButtonClicked"
IsVisible="{Binding HasReminder}"/>
</Grid>
<ScrollView Grid.Row="6">
<Grid>
<Grid.ColumnDefinitions>
Expand Down
55 changes: 38 additions & 17 deletions Samples/Samples/View/CalendarEventPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Samples.ViewModel;
using Xamarin.Essentials;
Expand Down Expand Up @@ -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)
Expand All @@ -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
};
}
}
12 changes: 8 additions & 4 deletions Xamarin.Essentials/Calendars/Calendars.android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ static async Task<CalendarEvent> 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;
}
Expand Down Expand Up @@ -276,7 +276,7 @@ static async Task<CalendarEvent> 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}");
Expand Down Expand Up @@ -310,7 +310,7 @@ static IEnumerable<CalendarEventAttendee> GetAttendeesForEvent(string eventId, s
return attendees.OrderByDescending(x => x.IsOrganizer);
}

static IEnumerable<CalendarEventReminder> GetRemindersForEvent(string eventId)
static CalendarEventReminder GetRemindersForEvent(string eventId)
{
var remindersUri = CalendarContract.Reminders.ContentUri;
var remindersProjection = new List<string>
Expand All @@ -330,7 +330,7 @@ static IEnumerable<CalendarEventReminder> GetRemindersForEvent(string eventId)
});
}
}
return reminders;
return reminders.First();
}

static async Task<string> PlatformCreateCalendar(Calendar newCalendar)
Expand Down Expand Up @@ -749,5 +749,9 @@ static string ToDayString(this List<DayOfTheWeek> dayList)
}
return toReturn.Substring(0, toReturn.Length - 1);
}

static Task<bool> PlatformAddReminderToEvent(CalendarEventReminder calendarEventReminder, string eventId) => throw ExceptionUtils.NotSupportedOrImplementedException;

static Task<bool> PlatformReminderFromEvent(string eventId) => throw ExceptionUtils.NotSupportedOrImplementedException;
}
}
56 changes: 52 additions & 4 deletions Xamarin.Essentials/Calendars/Calendars.ios.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,7 @@ static async Task<CalendarEvent> 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}");
}
Expand Down Expand Up @@ -126,7 +125,7 @@ static async Task<CalendarEvent> PlatformGetEventByIdAsync(string eventId)
EndDate = !calendarEvent.AllDay ? (DateTimeOffset?)calendarEvent.EndDate.ToDateTimeOffsetWithTimeZone(calendarEvent.TimeZone) : null,
Attendees = attendees,
RecurrancePattern = recurrenceRule,
Reminders = alarms
Reminder = alarms.First()
};
}

Expand Down Expand Up @@ -186,7 +185,7 @@ static async Task<CalendarEvent> PlatformGetEventInstanceByIdAsync(string eventI
EndDate = !calendarEvent.AllDay ? (DateTimeOffset?)calendarEvent.EndDate.ToDateTimeOffsetWithTimeZone(calendarEvent.TimeZone) : null,
Attendees = attendees,
RecurrancePattern = recurrenceRule,
Reminders = alarms
Reminder = alarms.First()
};
}

Expand Down Expand Up @@ -505,5 +504,54 @@ static async Task<bool> PlatformRemoveAttendeeFromEvent(CalendarEventAttendee ne
}
throw new Exception(error.DebugDescription);
}

static async Task<bool> PlatformAddReminderToEvent(CalendarEventReminder calendarEventReminder, string eventId)
{
await Permissions.RequestAsync<Permissions.CalendarWrite>();

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<bool> PlatformReminderFromEvent(string eventId)
{
await Permissions.RequestAsync<Permissions.CalendarWrite>();

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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,9 @@ public static partial class Calendars
static Task<bool> PlatformAddAttendeeToEvent(CalendarEventAttendee newAttendee, string eventId) => throw ExceptionUtils.NotSupportedOrImplementedException;

static Task<bool> PlatformRemoveAttendeeFromEvent(CalendarEventAttendee newAttendee, string eventId) => throw ExceptionUtils.NotSupportedOrImplementedException;

static Task<bool> PlatformReminderFromEvent(string eventId) => throw ExceptionUtils.NotSupportedOrImplementedException;

static Task<bool> PlatformAddReminderToEvent(CalendarEventReminder calendarEventReminder, string eventId) => throw ExceptionUtils.NotSupportedOrImplementedException;
}
}
4 changes: 4 additions & 0 deletions Xamarin.Essentials/Calendars/Calendars.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,9 @@ public static partial class Calendars
public static Task<bool> AddAttendeeToEvent(CalendarEventAttendee newAttendee, string eventId) => PlatformAddAttendeeToEvent(newAttendee, eventId);

public static Task<bool> RemoveAttendeeFromEvent(CalendarEventAttendee newAttendee, string eventId) => PlatformRemoveAttendeeFromEvent(newAttendee, eventId);

public static Task<bool> AddReminderToEvent(CalendarEventReminder newReminder, string eventId) => PlatformAddReminderToEvent(newReminder, eventId);

public static Task<bool> RemoveReminderFromEvent(string eventId) => PlatformReminderFromEvent(eventId);
}
}
Loading

0 comments on commit c33644e

Please sign in to comment.