Encapsulation of grouped account selection events and collective events.
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Serilog;
|
||||
using Wino.Calendar.ViewModels.Data;
|
||||
using Wino.Calendar.ViewModels.Interfaces;
|
||||
using Wino.Core.Domain.Collections;
|
||||
@@ -65,6 +67,9 @@ namespace Wino.Calendar.ViewModels
|
||||
|
||||
public bool IsVerticalCalendar => StatePersistenceService.CalendarDisplayType == CalendarDisplayType.Month;
|
||||
|
||||
// For updating account calendars asynchronously.
|
||||
private SemaphoreSlim _accountCalendarUpdateSemaphoreSlim = new(1);
|
||||
|
||||
public AppShellViewModel(IPreferencesService preferencesService,
|
||||
IStatePersistanceService statePersistanceService,
|
||||
IAccountService accountService,
|
||||
@@ -77,6 +82,9 @@ namespace Wino.Calendar.ViewModels
|
||||
_calendarService = calendarService;
|
||||
|
||||
AccountCalendarStateService = accountCalendarStateService;
|
||||
AccountCalendarStateService.AccountCalendarSelectionStateChanged += UpdateAccountCalendarRequested;
|
||||
AccountCalendarStateService.CollectiveAccountGroupSelectionStateChanged += AccountCalendarStateCollectivelyChanged;
|
||||
|
||||
NavigationService = navigationService;
|
||||
ServerConnectionManager = serverConnectionManager;
|
||||
PreferencesService = preferencesService;
|
||||
@@ -104,16 +112,33 @@ namespace Wino.Calendar.ViewModels
|
||||
UpdateDateNavigationHeaderItems();
|
||||
|
||||
await InitializeAccountCalendarsAsync();
|
||||
|
||||
TodayClicked();
|
||||
}
|
||||
|
||||
private void AddGroupedAccountCalendarViewModel(GroupedAccountCalendarViewModel groupedAccountCalendarViewModel)
|
||||
private async void AccountCalendarStateCollectivelyChanged(object sender, GroupedAccountCalendarViewModel e)
|
||||
{
|
||||
foreach (var calendarViewModel in groupedAccountCalendarViewModel.AccountCalendars)
|
||||
{
|
||||
calendarViewModel.CalendarSelectionStateChanged += UpdateAccountCalendarRequested;
|
||||
}
|
||||
// When using three-state checkbox, multiple accounts will be selected/unselected at the same time.
|
||||
// Reporting all these changes one by one to the UI is not efficient and may cause problems in the future.
|
||||
|
||||
AccountCalendarStateService.GroupedAccountCalendars.Add(groupedAccountCalendarViewModel);
|
||||
// Update all calendar states at once.
|
||||
try
|
||||
{
|
||||
await _accountCalendarUpdateSemaphoreSlim.WaitAsync();
|
||||
|
||||
foreach (var calendar in e.AccountCalendars)
|
||||
{
|
||||
await _calendarService.UpdateAccountCalendarAsync(calendar.AccountCalendar).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Error while waiting for account calendar update semaphore.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_accountCalendarUpdateSemaphoreSlim.Release();
|
||||
}
|
||||
}
|
||||
|
||||
private async void UpdateAccountCalendarRequested(object sender, AccountCalendarViewModel e)
|
||||
@@ -121,7 +146,7 @@ namespace Wino.Calendar.ViewModels
|
||||
|
||||
private async Task InitializeAccountCalendarsAsync()
|
||||
{
|
||||
await Dispatcher.ExecuteOnUIThread(() => AccountCalendarStateService.GroupedAccountCalendars.Clear());
|
||||
await Dispatcher.ExecuteOnUIThread(() => AccountCalendarStateService.ClearGroupedAccountCalendar());
|
||||
|
||||
var accounts = await _accountService.GetAccountsAsync().ConfigureAwait(false);
|
||||
|
||||
@@ -141,7 +166,7 @@ namespace Wino.Calendar.ViewModels
|
||||
|
||||
await Dispatcher.ExecuteOnUIThread(() =>
|
||||
{
|
||||
AddGroupedAccountCalendarViewModel(groupedAccountCalendarViewModel);
|
||||
AccountCalendarStateService.AddGroupedAccountCalendar(groupedAccountCalendarViewModel);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -233,12 +258,12 @@ namespace Wino.Calendar.ViewModels
|
||||
private readonly IAccountService _accountService;
|
||||
private readonly ICalendarService _calendarService;
|
||||
|
||||
public override void OnPageLoaded()
|
||||
{
|
||||
base.OnPageLoaded();
|
||||
//public override void OnPageLoaded()
|
||||
//{
|
||||
// base.OnPageLoaded();
|
||||
|
||||
TodayClicked();
|
||||
}
|
||||
// TodayClicked();
|
||||
//}
|
||||
|
||||
#region Commands
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||
using CommunityToolkit.Diagnostics;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Wino.Calendar.ViewModels.Data;
|
||||
using Wino.Calendar.ViewModels.Interfaces;
|
||||
using Wino.Core.Domain.Collections;
|
||||
using Wino.Core.Domain.Enums;
|
||||
@@ -211,8 +212,6 @@ namespace Wino.Calendar.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Create day ranges for each flip item until we reach the total days to load.
|
||||
int totalFlipItemCount = (int)Math.Ceiling((double)flipLoadRange.TotalDays / eachFlipItemCount);
|
||||
|
||||
@@ -233,15 +232,7 @@ namespace Wino.Calendar.ViewModels
|
||||
|
||||
foreach (var renderModel in renderModels)
|
||||
{
|
||||
foreach (var day in renderModel.CalendarDays)
|
||||
{
|
||||
var events = await _calendarService.GetCalendarEventsAsync(Guid.Parse("9ead7613-dacb-4163-8d33-2e32e65008a1"), day.Period.Start, day.Period.End).ConfigureAwait(false);
|
||||
|
||||
foreach (var calendarItem in events)
|
||||
{
|
||||
day.EventsCollection.Add(calendarItem);
|
||||
}
|
||||
}
|
||||
await InitializeCalendarEventsAsync(renderModel).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
CalendarLoadDirection animationDirection = calendarLoadDirection;
|
||||
@@ -326,6 +317,42 @@ namespace Wino.Calendar.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InitializeCalendarEventsAsync(DayRangeRenderModel dayRangeRenderModel)
|
||||
{
|
||||
// Load for each selected calendar from the state.
|
||||
var checkedCalendarViewModels = _accountCalendarStateService.GroupedAccountCalendars
|
||||
.SelectMany(a => a.AccountCalendars)
|
||||
.Where(b => b.IsChecked);
|
||||
|
||||
foreach (var calendarViewModel in checkedCalendarViewModels)
|
||||
{
|
||||
// Check all the events for the given date range and calendar.
|
||||
// Then find the day representation for all the events returned, and add to the collection.
|
||||
|
||||
var events = await _calendarService.GetCalendarEventsAsync(calendarViewModel,
|
||||
dayRangeRenderModel.Period.Start,
|
||||
dayRangeRenderModel.Period.End)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
foreach (var calendarItem in events)
|
||||
{
|
||||
var calendarDayModel = dayRangeRenderModel.CalendarDays.FirstOrDefault(a => a.RepresentingDate.Date == calendarItem.StartTime.Date);
|
||||
|
||||
if (calendarDayModel == null) continue;
|
||||
|
||||
var calendarItemViewModel = new CalendarItemViewModel(calendarItem);
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
// TODO: EventsCollection should not take CalendarItem, but CalendarItemViewModel.
|
||||
// Enforce it later on.
|
||||
|
||||
calendarDayModel.EventsCollection.Add(calendarItemViewModel);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task TryConsolidateItemsAsync()
|
||||
{
|
||||
// Check if trimming is necessary
|
||||
|
||||
@@ -8,8 +8,6 @@ namespace Wino.Calendar.ViewModels.Data
|
||||
{
|
||||
public partial class AccountCalendarViewModel : ObservableObject, IAccountCalendar
|
||||
{
|
||||
public event EventHandler<AccountCalendarViewModel> CalendarSelectionStateChanged;
|
||||
|
||||
public MailAccount Account { get; }
|
||||
public AccountCalendar AccountCalendar { get; }
|
||||
|
||||
@@ -24,11 +22,7 @@ namespace Wino.Calendar.ViewModels.Data
|
||||
[ObservableProperty]
|
||||
private bool _isChecked;
|
||||
|
||||
partial void OnIsCheckedChanged(bool value)
|
||||
{
|
||||
IsExtended = value;
|
||||
CalendarSelectionStateChanged?.Invoke(this, this);
|
||||
}
|
||||
partial void OnIsCheckedChanged(bool value) => IsExtended = value;
|
||||
|
||||
public string Name
|
||||
{
|
||||
@@ -71,5 +65,6 @@ namespace Wino.Calendar.ViewModels.Data
|
||||
get => AccountCalendar.RemoteCalendarId;
|
||||
set => SetProperty(AccountCalendar.RemoteCalendarId, value, AccountCalendar, (u, r) => u.RemoteCalendarId = r);
|
||||
}
|
||||
public Guid Id { get => ((IAccountCalendar)AccountCalendar).Id; set => ((IAccountCalendar)AccountCalendar).Id = value; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
using System;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Itenso.TimePeriod;
|
||||
using Wino.Core.Domain.Entities.Calendar;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Calendar.ViewModels.Data
|
||||
{
|
||||
public partial class CalendarItemViewModel : ObservableObject, ICalendarItem
|
||||
public partial class CalendarItemViewModel : ObservableObject, ICalendarItem, ICalendarItemViewModel
|
||||
{
|
||||
public ICalendarItem CalendarItem { get; }
|
||||
public CalendarItem CalendarItem { get; }
|
||||
|
||||
public string Title => CalendarItem.Title;
|
||||
|
||||
@@ -19,7 +20,9 @@ namespace Wino.Calendar.ViewModels.Data
|
||||
|
||||
public TimeRange Period => CalendarItem.Period;
|
||||
|
||||
public CalendarItemViewModel(ICalendarItem calendarItem)
|
||||
public IAccountCalendar AssignedCalendar => ((ICalendarItem)CalendarItem).AssignedCalendar;
|
||||
|
||||
public CalendarItemViewModel(CalendarItem calendarItem)
|
||||
{
|
||||
CalendarItem = calendarItem;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
@@ -9,6 +10,9 @@ namespace Wino.Calendar.ViewModels.Data
|
||||
{
|
||||
public partial class GroupedAccountCalendarViewModel : ObservableObject
|
||||
{
|
||||
public event EventHandler CollectiveSelectionStateChanged;
|
||||
public event EventHandler<AccountCalendarViewModel> CalendarSelectionStateChanged;
|
||||
|
||||
public MailAccount Account { get; }
|
||||
public ObservableCollection<AccountCalendarViewModel> AccountCalendars { get; }
|
||||
|
||||
@@ -59,6 +63,7 @@ namespace Wino.Calendar.ViewModels.Data
|
||||
if (e.PropertyName == nameof(AccountCalendarViewModel.IsChecked))
|
||||
{
|
||||
ManageIsCheckedState();
|
||||
UpdateCalendarCheckedState(viewModel, viewModel.IsChecked, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,6 +78,8 @@ namespace Wino.Calendar.ViewModels.Data
|
||||
|
||||
private void ManageIsCheckedState()
|
||||
{
|
||||
if (_isExternalPropChangeBlocked) return;
|
||||
|
||||
_isExternalPropChangeBlocked = true;
|
||||
|
||||
if (AccountCalendars.All(c => c.IsChecked))
|
||||
@@ -95,22 +102,45 @@ namespace Wino.Calendar.ViewModels.Data
|
||||
{
|
||||
if (_isExternalPropChangeBlocked) return;
|
||||
|
||||
// Update is triggered by user on the three-state checkbox.
|
||||
// We should not report all changes one by one.
|
||||
|
||||
_isExternalPropChangeBlocked = true;
|
||||
|
||||
if (newValue == null)
|
||||
{
|
||||
// Only primary calendars must be checked.
|
||||
|
||||
foreach (var calendar in AccountCalendars)
|
||||
{
|
||||
calendar.IsChecked = calendar.IsPrimary;
|
||||
UpdateCalendarCheckedState(calendar, calendar.IsPrimary);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var calendar in AccountCalendars)
|
||||
{
|
||||
calendar.IsChecked = newValue.GetValueOrDefault();
|
||||
UpdateCalendarCheckedState(calendar, newValue.GetValueOrDefault());
|
||||
}
|
||||
}
|
||||
|
||||
_isExternalPropChangeBlocked = false;
|
||||
|
||||
CollectiveSelectionStateChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void UpdateCalendarCheckedState(AccountCalendarViewModel accountCalendarViewModel, bool newValue, bool ignoreValueCheck = false)
|
||||
{
|
||||
var currentValue = accountCalendarViewModel.IsChecked;
|
||||
|
||||
if (currentValue == newValue && !ignoreValueCheck) return;
|
||||
|
||||
accountCalendarViewModel.IsChecked = newValue;
|
||||
|
||||
// No need to report.
|
||||
if (_isExternalPropChangeBlocked == true) return;
|
||||
|
||||
CalendarSelectionStateChanged?.Invoke(this, accountCalendarViewModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using Wino.Calendar.ViewModels.Data;
|
||||
|
||||
namespace Wino.Calendar.ViewModels.Interfaces
|
||||
{
|
||||
public interface IAccountCalendarStateService
|
||||
{
|
||||
ObservableCollection<GroupedAccountCalendarViewModel> GroupedAccountCalendars { get; }
|
||||
ReadOnlyObservableCollection<GroupedAccountCalendarViewModel> GroupedAccountCalendars { get; }
|
||||
|
||||
event EventHandler<GroupedAccountCalendarViewModel> CollectiveAccountGroupSelectionStateChanged;
|
||||
event EventHandler<AccountCalendarViewModel> AccountCalendarSelectionStateChanged;
|
||||
|
||||
public void AddGroupedAccountCalendar(GroupedAccountCalendarViewModel groupedAccountCalendar);
|
||||
public void RemoveGroupedAccountCalendar(GroupedAccountCalendarViewModel groupedAccountCalendar);
|
||||
public void ClearGroupedAccountCalendar();
|
||||
|
||||
public void AddAccountCalendar(AccountCalendarViewModel accountCalendar);
|
||||
public void RemoveAccountCalendar(AccountCalendarViewModel accountCalendar);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,91 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Calendar.ViewModels.Data;
|
||||
using Wino.Calendar.ViewModels.Interfaces;
|
||||
|
||||
namespace Wino.Calendar.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Encapsulated state manager for collectively managing the state of account calendars.
|
||||
/// Callers must react to the events to update their state only from this service.
|
||||
/// </summary>
|
||||
public partial class AccountCalendarStateService : ObservableObject, IAccountCalendarStateService
|
||||
{
|
||||
public event EventHandler<GroupedAccountCalendarViewModel> CollectiveAccountGroupSelectionStateChanged;
|
||||
public event EventHandler<AccountCalendarViewModel> AccountCalendarSelectionStateChanged;
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<GroupedAccountCalendarViewModel> _groupedAccountCalendars = new ObservableCollection<GroupedAccountCalendarViewModel>();
|
||||
private ReadOnlyObservableCollection<GroupedAccountCalendarViewModel> groupedAccountCalendars;
|
||||
|
||||
private ObservableCollection<GroupedAccountCalendarViewModel> _internalGroupedAccountCalendars = new ObservableCollection<GroupedAccountCalendarViewModel>();
|
||||
|
||||
public AccountCalendarStateService()
|
||||
{
|
||||
GroupedAccountCalendars = new ReadOnlyObservableCollection<GroupedAccountCalendarViewModel>(_internalGroupedAccountCalendars);
|
||||
}
|
||||
|
||||
private void SingleGroupCalendarCollectiveStateChanged(object sender, EventArgs e)
|
||||
=> CollectiveAccountGroupSelectionStateChanged?.Invoke(this, sender as GroupedAccountCalendarViewModel);
|
||||
|
||||
private void SingleCalendarSelectionStateChanged(object sender, AccountCalendarViewModel e)
|
||||
=> AccountCalendarSelectionStateChanged?.Invoke(this, e);
|
||||
|
||||
public void AddGroupedAccountCalendar(GroupedAccountCalendarViewModel groupedAccountCalendar)
|
||||
{
|
||||
groupedAccountCalendar.CalendarSelectionStateChanged += SingleCalendarSelectionStateChanged;
|
||||
groupedAccountCalendar.CollectiveSelectionStateChanged += SingleGroupCalendarCollectiveStateChanged;
|
||||
|
||||
_internalGroupedAccountCalendars.Add(groupedAccountCalendar);
|
||||
}
|
||||
|
||||
public void RemoveGroupedAccountCalendar(GroupedAccountCalendarViewModel groupedAccountCalendar)
|
||||
{
|
||||
groupedAccountCalendar.CalendarSelectionStateChanged -= SingleCalendarSelectionStateChanged;
|
||||
groupedAccountCalendar.CollectiveSelectionStateChanged -= SingleGroupCalendarCollectiveStateChanged;
|
||||
|
||||
_internalGroupedAccountCalendars.Remove(groupedAccountCalendar);
|
||||
}
|
||||
|
||||
public void ClearGroupedAccountCalendar()
|
||||
{
|
||||
foreach (var groupedAccountCalendar in _internalGroupedAccountCalendars)
|
||||
{
|
||||
RemoveGroupedAccountCalendar(groupedAccountCalendar);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddAccountCalendar(AccountCalendarViewModel accountCalendar)
|
||||
{
|
||||
// Find the group that this calendar belongs to.
|
||||
var group = _internalGroupedAccountCalendars.FirstOrDefault(g => g.Account.Id == accountCalendar.Account.Id);
|
||||
|
||||
if (group == null)
|
||||
{
|
||||
// If the group doesn't exist, create it.
|
||||
group = new GroupedAccountCalendarViewModel(accountCalendar.Account, new[] { accountCalendar });
|
||||
AddGroupedAccountCalendar(group);
|
||||
}
|
||||
else
|
||||
{
|
||||
group.AccountCalendars.Add(accountCalendar);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveAccountCalendar(AccountCalendarViewModel accountCalendar)
|
||||
{
|
||||
var group = _internalGroupedAccountCalendars.FirstOrDefault(g => g.Account.Id == accountCalendar.Account.Id);
|
||||
|
||||
// We don't expect but just in case.
|
||||
if (group == null) return;
|
||||
|
||||
group.AccountCalendars.Remove(accountCalendar);
|
||||
|
||||
if (group.AccountCalendars.Count == 0)
|
||||
{
|
||||
RemoveGroupedAccountCalendar(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Core.Domain.Collections
|
||||
{
|
||||
// TODO: Could be read-only collection in the MVVM package.
|
||||
public class CalendarEventCollection : ObservableRangeCollection<ICalendarItem>
|
||||
{
|
||||
public ObservableCollection<ICalendarItem> AllDayEvents { get; } = new ObservableCollection<ICalendarItem>();
|
||||
public new void Add(ICalendarItem calendarItem)
|
||||
{
|
||||
if (calendarItem is not ICalendarItemViewModel)
|
||||
throw new ArgumentException("CalendarItem must be of type ICalendarItemViewModel", nameof(calendarItem));
|
||||
|
||||
base.Add(calendarItem);
|
||||
|
||||
if (calendarItem.Period.Duration.TotalMinutes == 1440)
|
||||
@@ -18,6 +23,9 @@ namespace Wino.Core.Domain.Collections
|
||||
|
||||
public new void Remove(ICalendarItem calendarItem)
|
||||
{
|
||||
if (calendarItem is not ICalendarItemViewModel)
|
||||
throw new ArgumentException("CalendarItem must be of type ICalendarItemViewModel", nameof(calendarItem));
|
||||
|
||||
base.Remove(calendarItem);
|
||||
|
||||
if (calendarItem.Period.Duration.TotalMinutes == 1440)
|
||||
|
||||
@@ -24,5 +24,8 @@ namespace Wino.Core.Domain.Entities.Calendar
|
||||
|
||||
[Ignore]
|
||||
public TimeRange Period => new TimeRange(StartTime.Date, StartTime.Date.AddMinutes(DurationInMinutes));
|
||||
|
||||
[Ignore]
|
||||
public IAccountCalendar AssignedCalendar { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,5 +11,6 @@ namespace Wino.Core.Domain.Interfaces
|
||||
Guid AccountId { get; set; }
|
||||
string RemoteCalendarId { get; set; }
|
||||
bool IsExtended { get; set; }
|
||||
Guid Id { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,5 +10,6 @@ namespace Wino.Core.Domain.Interfaces
|
||||
DateTimeOffset StartTime { get; }
|
||||
int DurationInMinutes { get; }
|
||||
TimeRange Period { get; }
|
||||
IAccountCalendar AssignedCalendar { get; }
|
||||
}
|
||||
}
|
||||
|
||||
7
Wino.Core.Domain/Interfaces/ICalendarItemViewModel.cs
Normal file
7
Wino.Core.Domain/Interfaces/ICalendarItemViewModel.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Wino.Core.Domain.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Temporarily to enforce CalendarItemViewModel. Used in CalendarEventCollection.
|
||||
/// </summary>
|
||||
public interface ICalendarItemViewModel { }
|
||||
}
|
||||
@@ -14,6 +14,6 @@ namespace Wino.Core.Domain.Interfaces
|
||||
Task InsertAccountCalendarAsync(AccountCalendar accountCalendar);
|
||||
Task UpdateAccountCalendarAsync(AccountCalendar accountCalendar);
|
||||
Task CreateNewCalendarItemAsync(CalendarItem calendarItem, List<CalendarEventAttendee> attendees);
|
||||
Task<List<ICalendarItem>> GetCalendarEventsAsync(Guid calendarId, DateTime rangeStart, DateTime rangeEnd);
|
||||
Task<List<CalendarItem>> GetCalendarEventsAsync(IAccountCalendar calendar, DateTime rangeStart, DateTime rangeEnd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Wino.Core.Domain.Models.Calendar
|
||||
{
|
||||
public TimeRange Period { get; }
|
||||
public CalendarEventCollection EventsCollection { get; } = new CalendarEventCollection();
|
||||
|
||||
public CalendarDayModel(DateTime representingDate, CalendarRenderOptions calendarRenderOptions)
|
||||
{
|
||||
RepresentingDate = representingDate;
|
||||
|
||||
@@ -71,16 +71,18 @@ namespace Wino.Services
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<List<ICalendarItem>> GetCalendarEventsAsync(Guid calendarId, DateTime rangeStart, DateTime rangeEnd)
|
||||
public async Task<List<CalendarItem>> GetCalendarEventsAsync(IAccountCalendar calendar, DateTime rangeStart, DateTime rangeEnd)
|
||||
{
|
||||
// TODO: We might need to implement caching here.
|
||||
// I don't know how much of the events we'll have in total, but this logic scans all events every time.
|
||||
|
||||
var accountEvents = await Connection.Table<CalendarItem>().Where(x => x.CalendarId == calendarId).ToListAsync();
|
||||
var result = new List<ICalendarItem>();
|
||||
var accountEvents = await Connection.Table<CalendarItem>().Where(x => x.CalendarId == calendar.Id).ToListAsync();
|
||||
var result = new List<CalendarItem>();
|
||||
|
||||
foreach (var ev in accountEvents)
|
||||
{
|
||||
ev.AssignedCalendar = calendar;
|
||||
|
||||
// Parse recurrence rules
|
||||
var calendarEvent = new Ical.Net.CalendarComponents.CalendarEvent
|
||||
{
|
||||
|
||||
@@ -41,16 +41,17 @@ namespace Wino.Core.SourceGeneration.Translator
|
||||
predicate: static (node, _) => node is ClassDeclarationSyntax,
|
||||
transform: static (context, _) => (ClassDeclarationSyntax)context.TargetNode);
|
||||
|
||||
// Get the JSON schema
|
||||
// Get the JSON schema and track changes
|
||||
var jsonSchema = context.AdditionalTextsProvider
|
||||
.Where(static file => file.Path.EndsWith("en_US\\resources.json"))
|
||||
.Select((text, _) => (text, text.GetText()))
|
||||
.Collect();
|
||||
.Collect()
|
||||
.WithTrackingName("JsonSchema");
|
||||
|
||||
// Combine the JSON schema with the marked classes
|
||||
var combined = classDeclarations.Combine(jsonSchema);
|
||||
|
||||
// Generate the source
|
||||
// Generate the source only when the JSON schema changes
|
||||
context.RegisterSourceOutput(combined,
|
||||
static (spc, source) => Execute(source.Left, source.Right, spc));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user