From 0f57a4dfd78340c4f8c24e3e9eac6f4cd35b781d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 6 Jan 2025 21:56:33 +0100 Subject: [PATCH] Monthly calendar basics. --- .../AccountDetailsPageViewModel.cs | 48 +++ Wino.Calendar.ViewModels/AppShellViewModel.cs | 7 +- .../CalendarPageViewModel.cs | 20 +- Wino.Calendar/App.xaml.cs | 1 + .../Controls/CalendarItemControl.xaml.cs | 5 +- Wino.Calendar/Controls/DayColumnControl.cs | 9 +- Wino.Calendar/Controls/WinoCalendarControl.cs | 51 ++- .../WinoCalendarItemTemplateSelector.cs | 34 ++ Wino.Calendar/Services/NavigationService.cs | 24 +- .../Styles/WinoCalendarResources.xaml | 402 ++++++++++++------ .../Abstract/AccountDetailsPageAbstract.cs | 7 + .../Views/Account/AccountManagementPage.xaml | 1 + .../Account/AccountManagementPage.xaml.cs | 2 +- Wino.Calendar/Views/AppShell.xaml | 32 +- Wino.Calendar/Views/AppShell.xaml.cs | 2 +- Wino.Calendar/Views/CalendarPage.xaml | 1 + Wino.Calendar/Views/CalendarPage.xaml.cs | 2 - .../Views/Settings/AccountDetailsPage.xaml | 125 ++++++ .../Views/Settings/AccountDetailsPage.xaml.cs | 12 + Wino.Calendar/Wino.Calendar.csproj | 9 + .../Entities/Shared/MailAccount.cs | 7 + Wino.Core.Domain/Enums/WinoPage.cs | 1 + .../Extensions/DateTimeExtensions.cs | 14 +- .../Interfaces/IDialogServiceBase.cs | 2 + .../Interfaces/IMailDialogService.cs | 1 - .../MonthCalendarDrawingStrategy.cs | 36 ++ .../Translations/en_US/resources.json | 2 + Wino.Core.UWP/Controls/EqualGridPanel.cs | 87 ++++ Wino.Core.UWP/CoreUWPContainerSetup.cs | 2 +- Wino.Core.UWP/Helpers/XamlHelpers.cs | 3 + Wino.Core.UWP/Services/DialogServiceBase.cs | 13 + Wino.Core.UWP/Styles/DataTemplates.xaml | 2 - .../Abstract/ManageAccountsPageAbstract.cs | 8 + .../Views/ManageAccountsPage.xaml | 8 +- .../Views/ManageAccountsPage.xaml.cs | 32 +- Wino.Core.UWP/Wino.Core.UWP.csproj | 9 + .../NewAccountManagementPageViewModel.cs | 7 +- .../Synchronizers/OutlookSynchronizer.cs | 138 +++--- Wino.Mail/Services/NavigationService.cs | 65 +-- .../NewAccountManagementPageAbstract.cs | 9 - .../Views/Account/AccountDetailsPage.xaml | 1 - Wino.Mail/Wino.Mail.csproj | 8 - Wino.Services/CalendarService.cs | 2 +- 43 files changed, 915 insertions(+), 336 deletions(-) create mode 100644 Wino.Calendar.ViewModels/AccountDetailsPageViewModel.cs create mode 100644 Wino.Calendar/Selectors/WinoCalendarItemTemplateSelector.cs create mode 100644 Wino.Calendar/Views/Abstract/AccountDetailsPageAbstract.cs create mode 100644 Wino.Calendar/Views/Settings/AccountDetailsPage.xaml create mode 100644 Wino.Calendar/Views/Settings/AccountDetailsPage.xaml.cs rename {Wino.Core => Wino.Core.Domain}/Extensions/DateTimeExtensions.cs (63%) create mode 100644 Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/MonthCalendarDrawingStrategy.cs create mode 100644 Wino.Core.UWP/Controls/EqualGridPanel.cs create mode 100644 Wino.Core.UWP/Views/Abstract/ManageAccountsPageAbstract.cs rename Wino.Mail/Views/NewAccountManagementPage.xaml => Wino.Core.UWP/Views/ManageAccountsPage.xaml (92%) rename Wino.Mail/Views/NewAccountManagementPage.xaml.cs => Wino.Core.UWP/Views/ManageAccountsPage.xaml.cs (75%) delete mode 100644 Wino.Mail/Views/Abstract/NewAccountManagementPageAbstract.cs diff --git a/Wino.Calendar.ViewModels/AccountDetailsPageViewModel.cs b/Wino.Calendar.ViewModels/AccountDetailsPageViewModel.cs new file mode 100644 index 00000000..9137759f --- /dev/null +++ b/Wino.Calendar.ViewModels/AccountDetailsPageViewModel.cs @@ -0,0 +1,48 @@ +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.Input; +using Wino.Calendar.ViewModels.Interfaces; +using Wino.Core.Domain.Interfaces; +using Wino.Core.Domain.Models.Navigation; +using Wino.Core.ViewModels; +using Wino.Mail.ViewModels.Data; +using Wino.Messaging.UI; + +namespace Wino.Calendar.ViewModels +{ + public partial class AccountDetailsPageViewModel : CalendarBaseViewModel + { + private readonly IAccountService _accountService; + + public AccountProviderDetailViewModel Account { get; private set; } + public ICalendarDialogService CalendarDialogService { get; } + public IAccountCalendarStateService AccountCalendarStateService { get; } + + public AccountDetailsPageViewModel(ICalendarDialogService calendarDialogService, IAccountService accountService, IAccountCalendarStateService accountCalendarStateService) + { + CalendarDialogService = calendarDialogService; + _accountService = accountService; + AccountCalendarStateService = accountCalendarStateService; + } + + [RelayCommand] + private async Task RenameAccount() + { + if (Account == null) + return; + + var updatedAccount = await CalendarDialogService.ShowEditAccountDialogAsync(Account.Account); + + if (updatedAccount != null) + { + await _accountService.UpdateAccountAsync(updatedAccount); + + ReportUIChange(new AccountUpdatedMessage(updatedAccount)); + } + } + + public override void OnNavigatedTo(NavigationMode mode, object parameters) + { + base.OnNavigatedTo(mode, parameters); + } + } +} diff --git a/Wino.Calendar.ViewModels/AppShellViewModel.cs b/Wino.Calendar.ViewModels/AppShellViewModel.cs index 55bf8c62..7d984fab 100644 --- a/Wino.Calendar.ViewModels/AppShellViewModel.cs +++ b/Wino.Calendar.ViewModels/AppShellViewModel.cs @@ -11,11 +11,11 @@ using Wino.Calendar.ViewModels.Data; using Wino.Calendar.ViewModels.Interfaces; using Wino.Core.Domain.Collections; using Wino.Core.Domain.Enums; +using Wino.Core.Domain.Extensions; using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Models.Calendar; using Wino.Core.Domain.Models.Navigation; using Wino.Core.Domain.Models.Synchronization; -using Wino.Core.Extensions; using Wino.Core.ViewModels; using Wino.Messaging.Client.Calendar; using Wino.Messaging.Client.Navigation; @@ -67,9 +67,6 @@ namespace Wino.Calendar.ViewModels [ObservableProperty] private int _selectedDateNavigationHeaderIndex; - - - public bool IsVerticalCalendar => StatePersistenceService.CalendarDisplayType == CalendarDisplayType.Month; // For updating account calendars asynchronously. @@ -209,7 +206,7 @@ namespace Wino.Calendar.ViewModels ForceNavigateCalendarDate(); break; case 0: - NavigationService.Navigate(WinoPage.AccountManagementPage); + NavigationService.Navigate(WinoPage.ManageAccountsPage); break; case 1: NavigationService.Navigate(WinoPage.SettingsPage); diff --git a/Wino.Calendar.ViewModels/CalendarPageViewModel.cs b/Wino.Calendar.ViewModels/CalendarPageViewModel.cs index b4235cef..4a9d7fdf 100644 --- a/Wino.Calendar.ViewModels/CalendarPageViewModel.cs +++ b/Wino.Calendar.ViewModels/CalendarPageViewModel.cs @@ -31,7 +31,9 @@ namespace Wino.Calendar.ViewModels IRecipient, IRecipient, IRecipient, - IRecipient + IRecipient, + IRecipient + { #region Quick Event Creation @@ -92,6 +94,8 @@ namespace Wino.Calendar.ViewModels #region Data Initialization + public bool IsVerticalCalendar => StatePersistanceService.CalendarDisplayType == CalendarDisplayType.Month; + [ObservableProperty] private DayRangeCollection _dayRanges = []; @@ -161,13 +165,16 @@ namespace Wino.Calendar.ViewModels private void UpdateAccountCalendarRequested(object sender, AccountCalendarViewModel e) => FilterActiveCalendars(DayRanges); - private void FilterActiveCalendars(IEnumerable dayRangeRenderModels) + private async void FilterActiveCalendars(IEnumerable dayRangeRenderModels) { - var days = dayRangeRenderModels.SelectMany(a => a.CalendarDays); + await ExecuteUIThread(() => + { + var days = dayRangeRenderModels.SelectMany(a => a.CalendarDays); - days.ForEach(a => a.EventsCollection.FilterByCalendars(AccountCalendarStateService.ActiveCalendars.Select(a => a.Id))); + days.ForEach(a => a.EventsCollection.FilterByCalendars(AccountCalendarStateService.ActiveCalendars.Select(a => a.Id))); - DisplayDetailsCalendarItemViewModel = null; + DisplayDetailsCalendarItemViewModel = null; + }); } // TODO: Replace when calendar settings are updated. @@ -178,6 +185,7 @@ namespace Wino.Calendar.ViewModels { CalendarDisplayType.Day => new DayCalendarDrawingStrategy(CurrentSettings), CalendarDisplayType.Week => new WeekCalendarDrawingStrategy(CurrentSettings), + CalendarDisplayType.Month => new MonthCalendarDrawingStrategy(CurrentSettings), _ => throw new NotImplementedException(), }; } @@ -831,5 +839,7 @@ namespace Wino.Calendar.ViewModels // var calendarItems = GetCalendarItems(deletedItem.Id); }); } + + public void Receive(CalendarDisplayTypeChangedMessage message) => OnPropertyChanged(nameof(IsVerticalCalendar)); } } diff --git a/Wino.Calendar/App.xaml.cs b/Wino.Calendar/App.xaml.cs index e7ca3f84..3e68a391 100644 --- a/Wino.Calendar/App.xaml.cs +++ b/Wino.Calendar/App.xaml.cs @@ -82,6 +82,7 @@ namespace Wino.Calendar services.AddTransient(typeof(CalendarSettingsPageViewModel)); services.AddTransient(typeof(AccountManagementViewModel)); services.AddTransient(typeof(PersonalizationPageViewModel)); + services.AddTransient(typeof(AccountDetailsPageViewModel)); } #endregion diff --git a/Wino.Calendar/Controls/CalendarItemControl.xaml.cs b/Wino.Calendar/Controls/CalendarItemControl.xaml.cs index 1d20e356..5d127613 100644 --- a/Wino.Calendar/Controls/CalendarItemControl.xaml.cs +++ b/Wino.Calendar/Controls/CalendarItemControl.xaml.cs @@ -1,5 +1,4 @@ -using System.Diagnostics; -using System.Threading.Tasks; +using System.Threading.Tasks; using CommunityToolkit.Mvvm.Messaging; using Itenso.TimePeriod; using Windows.UI.Xaml; @@ -126,7 +125,7 @@ namespace Wino.Calendar.Controls CalendarItemTitle = CalendarItem.Title; } - Debug.WriteLine($"{CalendarItem.Title} Period relation with {DisplayingDate.Period.ToString()}: {periodRelation}"); + // Debug.WriteLine($"{CalendarItem.Title} Period relation with {DisplayingDate.Period.ToString()}: {periodRelation}"); } else { diff --git a/Wino.Calendar/Controls/DayColumnControl.cs b/Wino.Calendar/Controls/DayColumnControl.cs index ea7b34ee..9250b49e 100644 --- a/Wino.Calendar/Controls/DayColumnControl.cs +++ b/Wino.Calendar/Controls/DayColumnControl.cs @@ -56,10 +56,15 @@ namespace Wino.Calendar.Controls private void UpdateValues() { - if (HeaderDateDayText == null || ColumnHeaderText == null || IsTodayBorder == null || DayModel == null) return; + if (HeaderDateDayText == null || IsTodayBorder == null || DayModel == null) return; HeaderDateDayText.Text = DayModel.RepresentingDate.Day.ToString(); - ColumnHeaderText.Text = DayModel.RepresentingDate.ToString("dddd", DayModel.CalendarRenderOptions.CalendarSettings.CultureInfo); + + // Monthly template does not use it. + if (ColumnHeaderText != null) + { + ColumnHeaderText.Text = DayModel.RepresentingDate.ToString("dddd", DayModel.CalendarRenderOptions.CalendarSettings.CultureInfo); + } AllDayItemsControl.ItemsSource = DayModel.EventsCollection.AllDayEvents; diff --git a/Wino.Calendar/Controls/WinoCalendarControl.cs b/Wino.Calendar/Controls/WinoCalendarControl.cs index 868fe9ea..d7d79758 100644 --- a/Wino.Calendar/Controls/WinoCalendarControl.cs +++ b/Wino.Calendar/Controls/WinoCalendarControl.cs @@ -6,6 +6,7 @@ using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Wino.Calendar.Args; using Wino.Calendar.ViewModels.Data; +using Wino.Core.Domain.Enums; using Wino.Core.Domain.Models.Calendar; using Wino.Helpers; @@ -30,6 +31,28 @@ namespace Wino.Calendar.Controls public static readonly DependencyProperty IsFlipIdleProperty = DependencyProperty.Register(nameof(IsFlipIdle), typeof(bool), typeof(WinoCalendarControl), new PropertyMetadata(true, new PropertyChangedCallback(OnIdleStateChanged))); public static readonly DependencyProperty ActiveScrollViewerProperty = DependencyProperty.Register(nameof(ActiveScrollViewer), typeof(ScrollViewer), typeof(WinoCalendarControl), new PropertyMetadata(null, new PropertyChangedCallback(OnActiveVerticalScrollViewerChanged))); + public static readonly DependencyProperty VerticalItemsPanelTemplateProperty = DependencyProperty.Register(nameof(VerticalItemsPanelTemplate), typeof(ItemsPanelTemplate), typeof(WinoCalendarControl), new PropertyMetadata(null, new PropertyChangedCallback(OnIsVerticalCalendarChanged))); + public static readonly DependencyProperty HorizontalItemsPanelTemplateProperty = DependencyProperty.Register(nameof(HorizontalItemsPanelTemplate), typeof(ItemsPanelTemplate), typeof(WinoCalendarControl), new PropertyMetadata(null, new PropertyChangedCallback(OnIsVerticalCalendarChanged))); + public static readonly DependencyProperty DisplayTypeProperty = DependencyProperty.Register(nameof(DisplayType), typeof(CalendarDisplayType), typeof(WinoCalendarControl), new PropertyMetadata(CalendarDisplayType.Day, new PropertyChangedCallback(OnIsVerticalCalendarChanged))); + + public CalendarDisplayType DisplayType + { + get { return (CalendarDisplayType)GetValue(DisplayTypeProperty); } + set { SetValue(DisplayTypeProperty, value); } + } + + public ItemsPanelTemplate VerticalItemsPanelTemplate + { + get { return (ItemsPanelTemplate)GetValue(VerticalItemsPanelTemplateProperty); } + set { SetValue(VerticalItemsPanelTemplateProperty, value); } + } + + public ItemsPanelTemplate HorizontalItemsPanelTemplate + { + get { return (ItemsPanelTemplate)GetValue(HorizontalItemsPanelTemplateProperty); } + set { SetValue(HorizontalItemsPanelTemplateProperty, value); } + } + public DayRangeRenderModel SelectedFlipViewDayRange { get { return (DayRangeRenderModel)GetValue(SelectedFlipViewDayRangeProperty); } @@ -81,6 +104,14 @@ namespace Wino.Calendar.Controls SizeChanged += CalendarSizeChanged; } + private static void OnIsVerticalCalendarChanged(DependencyObject calendar, DependencyPropertyChangedEventArgs e) + { + if (calendar is WinoCalendarControl control) + { + control.ManageCalendarOrientation(); + } + } + private static void OnIdleStateChanged(DependencyObject calendar, DependencyPropertyChangedEventArgs e) { if (calendar is WinoCalendarControl calendarControl) @@ -89,6 +120,7 @@ namespace Wino.Calendar.Controls } } + private static void OnActiveVerticalScrollViewerChanged(DependencyObject calendar, DependencyPropertyChangedEventArgs e) { if (calendar is WinoCalendarControl calendarControl) @@ -124,6 +156,22 @@ namespace Wino.Calendar.Controls } } + private void ManageCalendarOrientation() + { + if (InternalFlipView == null || HorizontalItemsPanelTemplate == null || VerticalItemsPanelTemplate == null) return; + + bool isHorizontalCalendar = DisplayType == CalendarDisplayType.Day || DisplayType == CalendarDisplayType.Week || DisplayType == CalendarDisplayType.WorkWeek; + + if (isHorizontalCalendar) + { + InternalFlipView.ItemsPanel = HorizontalItemsPanelTemplate; + } + else + { + InternalFlipView.ItemsPanel = VerticalItemsPanelTemplate; + } + } + private void ManageHighlightedDateRange() { if (ActiveCanvas == null) @@ -186,6 +234,7 @@ namespace Wino.Calendar.Controls IdleGrid = GetTemplateChild(PART_IdleGrid) as Grid; UpdateIdleState(); + ManageCalendarOrientation(); } private void UpdateIdleState() @@ -248,8 +297,6 @@ namespace Wino.Calendar.Controls public CalendarItemControl GetCalendarItemControl(CalendarItemViewModel calendarItemViewModel) { - if (ActiveCanvas == null) return null; - return this.FindDescendants().FirstOrDefault(a => a.CalendarItem == calendarItemViewModel); } } diff --git a/Wino.Calendar/Selectors/WinoCalendarItemTemplateSelector.cs b/Wino.Calendar/Selectors/WinoCalendarItemTemplateSelector.cs new file mode 100644 index 00000000..974559af --- /dev/null +++ b/Wino.Calendar/Selectors/WinoCalendarItemTemplateSelector.cs @@ -0,0 +1,34 @@ +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Wino.Core.Domain.Enums; + +namespace Wino.Calendar.Selectors +{ + public class WinoCalendarItemTemplateSelector : DataTemplateSelector + { + public CalendarDisplayType DisplayType { get; set; } + + public DataTemplate DayWeekWorkWeekTemplate { get; set; } + public DataTemplate MonthlyTemplate { get; set; } + + + protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) + { + switch (DisplayType) + { + case CalendarDisplayType.Day: + case CalendarDisplayType.Week: + case CalendarDisplayType.WorkWeek: + return DayWeekWorkWeekTemplate; + case CalendarDisplayType.Month: + return MonthlyTemplate; + case CalendarDisplayType.Year: + break; + default: + break; + } + + return base.SelectTemplateCore(item, container); + } + } +} diff --git a/Wino.Calendar/Services/NavigationService.cs b/Wino.Calendar/Services/NavigationService.cs index 1e0fc5bb..e8d0edb6 100644 --- a/Wino.Calendar/Services/NavigationService.cs +++ b/Wino.Calendar/Services/NavigationService.cs @@ -16,21 +16,17 @@ namespace Wino.Calendar.Services { public Type GetPageType(WinoPage winoPage) { - switch (winoPage) + return winoPage switch { - case WinoPage.CalendarPage: - return typeof(CalendarPage); - case WinoPage.SettingsPage: - return typeof(SettingsPage); - case WinoPage.CalendarSettingsPage: - return typeof(CalendarSettingsPage); - case WinoPage.AccountManagementPage: - return typeof(AccountManagementPage); - case WinoPage.PersonalizationPage: - return typeof(PersonalizationPage); - default: - throw new Exception("Page is not implemented yet."); - } + WinoPage.CalendarPage => typeof(CalendarPage), + WinoPage.SettingsPage => typeof(SettingsPage), + WinoPage.CalendarSettingsPage => typeof(CalendarSettingsPage), + WinoPage.AccountManagementPage => typeof(AccountManagementPage), + WinoPage.ManageAccountsPage => typeof(ManageAccountsPage), + WinoPage.PersonalizationPage => typeof(PersonalizationPage), + WinoPage.AccountDetailsPage => typeof(AccountDetailsPage), + _ => throw new Exception("Page is not implemented yet."), + }; } public bool Navigate(WinoPage page, object parameter = null, NavigationReferenceFrame frame = NavigationReferenceFrame.ShellFrame, NavigationTransitionType transition = NavigationTransitionType.None) diff --git a/Wino.Calendar/Styles/WinoCalendarResources.xaml b/Wino.Calendar/Styles/WinoCalendarResources.xaml index c7f6f591..ebeb0298 100644 --- a/Wino.Calendar/Styles/WinoCalendarResources.xaml +++ b/Wino.Calendar/Styles/WinoCalendarResources.xaml @@ -3,6 +3,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="using:Wino.Calendar.Controls" + xmlns:controls1="using:Wino.Core.UWP.Controls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:data="using:Wino.Calendar.ViewModels.Data" xmlns:helpers="using:Wino.Helpers" @@ -12,8 +13,6 @@ xmlns:selectors="using:Wino.Calendar.Selectors" xmlns:toolkitControls="using:CommunityToolkit.WinUI.Controls"> - - @@ -50,6 +49,8 @@ + + - + - + @@ -125,9 +123,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Wino.Calendar/Views/Abstract/AccountDetailsPageAbstract.cs b/Wino.Calendar/Views/Abstract/AccountDetailsPageAbstract.cs new file mode 100644 index 00000000..ab7aa247 --- /dev/null +++ b/Wino.Calendar/Views/Abstract/AccountDetailsPageAbstract.cs @@ -0,0 +1,7 @@ +using Wino.Calendar.ViewModels; +using Wino.Core.UWP; + +namespace Wino.Calendar.Views.Abstract +{ + public abstract class AccountDetailsPageAbstract : BasePage { } +} diff --git a/Wino.Calendar/Views/Account/AccountManagementPage.xaml b/Wino.Calendar/Views/Account/AccountManagementPage.xaml index 8c6997a6..636a25df 100644 --- a/Wino.Calendar/Views/Account/AccountManagementPage.xaml +++ b/Wino.Calendar/Views/Account/AccountManagementPage.xaml @@ -9,6 +9,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:muxc="using:Microsoft.UI.Xaml.Controls" xmlns:winuiControls="using:CommunityToolkit.WinUI.Controls" + x:Name="root" mc:Ignorable="d"> diff --git a/Wino.Calendar/Views/Account/AccountManagementPage.xaml.cs b/Wino.Calendar/Views/Account/AccountManagementPage.xaml.cs index 813889b1..97344170 100644 --- a/Wino.Calendar/Views/Account/AccountManagementPage.xaml.cs +++ b/Wino.Calendar/Views/Account/AccountManagementPage.xaml.cs @@ -6,7 +6,7 @@ namespace Wino.Calendar.Views.Account { public AccountManagementPage() { - this.InitializeComponent(); + InitializeComponent(); } } } diff --git a/Wino.Calendar/Views/AppShell.xaml b/Wino.Calendar/Views/AppShell.xaml index 6fcc4083..9893763e 100644 --- a/Wino.Calendar/Views/AppShell.xaml +++ b/Wino.Calendar/Views/AppShell.xaml @@ -231,19 +231,33 @@ HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" IsChecked="{x:Bind IsChecked, Mode=TwoWay}"> - + + + + + + + + + + @@ -360,8 +374,8 @@ - - + + diff --git a/Wino.Calendar/Views/AppShell.xaml.cs b/Wino.Calendar/Views/AppShell.xaml.cs index 1bc4ce64..32875518 100644 --- a/Wino.Calendar/Views/AppShell.xaml.cs +++ b/Wino.Calendar/Views/AppShell.xaml.cs @@ -18,9 +18,9 @@ namespace Wino.Calendar.Views InitializeComponent(); Window.Current.SetTitleBar(DragArea); + ManageCalendarDisplayType(); } - private void ManageCalendarDisplayType() { // Go to different states based on the display type. diff --git a/Wino.Calendar/Views/CalendarPage.xaml b/Wino.Calendar/Views/CalendarPage.xaml index 30cfc716..18101fe6 100644 --- a/Wino.Calendar/Views/CalendarPage.xaml +++ b/Wino.Calendar/Views/CalendarPage.xaml @@ -33,6 +33,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Wino.Calendar/Views/Settings/AccountDetailsPage.xaml.cs b/Wino.Calendar/Views/Settings/AccountDetailsPage.xaml.cs new file mode 100644 index 00000000..ae135ef2 --- /dev/null +++ b/Wino.Calendar/Views/Settings/AccountDetailsPage.xaml.cs @@ -0,0 +1,12 @@ +using Wino.Calendar.Views.Abstract; + +namespace Wino.Calendar.Views.Settings +{ + public sealed partial class AccountDetailsPage : AccountDetailsPageAbstract + { + public AccountDetailsPage() + { + this.InitializeComponent(); + } + } +} diff --git a/Wino.Calendar/Wino.Calendar.csproj b/Wino.Calendar/Wino.Calendar.csproj index 63cc491b..9adfe5c5 100644 --- a/Wino.Calendar/Wino.Calendar.csproj +++ b/Wino.Calendar/Wino.Calendar.csproj @@ -156,6 +156,7 @@ + @@ -163,6 +164,7 @@ + @@ -177,6 +179,9 @@ CalendarPage.xaml + + AccountDetailsPage.xaml + CalendarSettingsPage.xaml @@ -293,6 +298,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/Wino.Core.Domain/Entities/Shared/MailAccount.cs b/Wino.Core.Domain/Entities/Shared/MailAccount.cs index 12ae15a6..3f65e2c7 100644 --- a/Wino.Core.Domain/Entities/Shared/MailAccount.cs +++ b/Wino.Core.Domain/Entities/Shared/MailAccount.cs @@ -40,6 +40,13 @@ namespace Wino.Core.Domain.Entities.Shared /// public string SynchronizationDeltaIdentifier { get; set; } + /// + /// For tracking calendar change delta. + /// Gmail: It's per-calendar, so unused. + /// Outlook: deltaLink + /// + public string CalendarSynchronizationDeltaIdentifier { get; set; } + /// /// TODO: Gets or sets the custom account identifier color in hex. /// diff --git a/Wino.Core.Domain/Enums/WinoPage.cs b/Wino.Core.Domain/Enums/WinoPage.cs index e3623c03..0ea37b84 100644 --- a/Wino.Core.Domain/Enums/WinoPage.cs +++ b/Wino.Core.Domain/Enums/WinoPage.cs @@ -13,6 +13,7 @@ WelcomePage, AccountDetailsPage, MergedAccountDetailsPage, + ManageAccountsPage, AccountManagementPage, SignatureManagementPage, AboutPage, diff --git a/Wino.Core/Extensions/DateTimeExtensions.cs b/Wino.Core.Domain/Extensions/DateTimeExtensions.cs similarity index 63% rename from Wino.Core/Extensions/DateTimeExtensions.cs rename to Wino.Core.Domain/Extensions/DateTimeExtensions.cs index db3ceb45..69c1b571 100644 --- a/Wino.Core/Extensions/DateTimeExtensions.cs +++ b/Wino.Core.Domain/Extensions/DateTimeExtensions.cs @@ -1,7 +1,7 @@ using System; using Wino.Core.Domain.Models.Calendar; -namespace Wino.Core.Extensions +namespace Wino.Core.Domain.Extensions { public static class DateTimeExtensions { @@ -11,16 +11,14 @@ namespace Wino.Core.Extensions /// Date to get range for. public static DateRange GetMonthDateRangeStartingWeekday(this DateTime date, DayOfWeek WeekStartDay) { - var firstDayOfMonth = new DateTime(date.Year, date.Month, 1); + DateTime firstDayOfMonth = new DateTime(date.Year, date.Month, 1); - int daysToWeekDay = (int)firstDayOfMonth.DayOfWeek - (int)WeekStartDay; - if (daysToWeekDay < 0) daysToWeekDay += 7; + int daysToSubtract = (7 + (firstDayOfMonth.DayOfWeek - WeekStartDay)) % 7; + DateTime rangeStart = firstDayOfMonth.AddDays(-daysToSubtract); - firstDayOfMonth = firstDayOfMonth.AddDays(-daysToWeekDay); + DateTime rangeEnd = rangeStart.AddDays(34); - var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1); - - return new DateRange(firstDayOfMonth, lastDayOfMonth); + return new DateRange(rangeStart, rangeEnd); } public static DateTime GetWeekStartDateForDate(this DateTime date, DayOfWeek firstDayOfWeek) diff --git a/Wino.Core.Domain/Interfaces/IDialogServiceBase.cs b/Wino.Core.Domain/Interfaces/IDialogServiceBase.cs index 901582b9..cb86603e 100644 --- a/Wino.Core.Domain/Interfaces/IDialogServiceBase.cs +++ b/Wino.Core.Domain/Interfaces/IDialogServiceBase.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Wino.Core.Domain.Entities.Shared; using Wino.Core.Domain.Enums; using Wino.Core.Domain.Models.Accounts; using Wino.Core.Domain.Models.Common; @@ -16,6 +17,7 @@ namespace Wino.Core.Domain.Interfaces void InfoBarMessage(string title, string message, InfoBarMessageType messageType); void InfoBarMessage(string title, string message, InfoBarMessageType messageType, string actionButtonText, Action action); void ShowNotSupportedMessage(); + Task ShowEditAccountDialogAsync(MailAccount account); Task ShowTextInputDialogAsync(string currentInput, string dialogTitle, string dialogDescription, string primaryButtonText); Task ShowWinoCustomMessageDialogAsync(string title, string description, diff --git a/Wino.Core.Domain/Interfaces/IMailDialogService.cs b/Wino.Core.Domain/Interfaces/IMailDialogService.cs index 4f7c8350..a6509151 100644 --- a/Wino.Core.Domain/Interfaces/IMailDialogService.cs +++ b/Wino.Core.Domain/Interfaces/IMailDialogService.cs @@ -16,7 +16,6 @@ namespace Wino.Core.Domain.Interfaces // Custom dialogs Task ShowMoveMailFolderDialogAsync(List availableFolders); - Task ShowEditAccountDialogAsync(MailAccount account); Task ShowAccountPickerDialogAsync(List availableAccounts); /// diff --git a/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/MonthCalendarDrawingStrategy.cs b/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/MonthCalendarDrawingStrategy.cs new file mode 100644 index 00000000..7f20788f --- /dev/null +++ b/Wino.Core.Domain/Models/Calendar/CalendarTypeStrategies/MonthCalendarDrawingStrategy.cs @@ -0,0 +1,36 @@ +using System; +using Wino.Core.Domain.Enums; +using Wino.Core.Domain.Extensions; + +namespace Wino.Core.Domain.Models.Calendar.CalendarTypeStrategies +{ + public class MonthCalendarDrawingStrategy : BaseCalendarTypeDrawingStrategy + { + public MonthCalendarDrawingStrategy(CalendarSettings settings) + : base(settings, CalendarDisplayType.Month) + { + } + + public override DateRange GetNextDateRange(DateRange CurrentDateRange, int DayDisplayCount) + { + return DateTimeExtensions.GetMonthDateRangeStartingWeekday(CurrentDateRange.EndDate, Settings.FirstDayOfWeek); + } + + public override DateRange GetPreviousDateRange(DateRange CurrentDateRange, int DayDisplayCount) + { + return DateTimeExtensions.GetMonthDateRangeStartingWeekday(CurrentDateRange.StartDate, Settings.FirstDayOfWeek); + } + + public override DateRange GetRenderDateRange(DateTime DisplayDate, int DayDisplayCount) + { + // Load 2 months at first. + var initialRange = DateTimeExtensions.GetMonthDateRangeStartingWeekday(DisplayDate.Date, Settings.FirstDayOfWeek); + + var nextRange = GetNextDateRange(initialRange, DayDisplayCount); + + return new DateRange(initialRange.StartDate, nextRange.EndDate); + } + + public override int GetRenderDayCount(DateTime DisplayDate, int DayDisplayCount) => 35; + } +} diff --git a/Wino.Core.Domain/Translations/en_US/resources.json b/Wino.Core.Domain/Translations/en_US/resources.json index fd9806c1..110318f5 100644 --- a/Wino.Core.Domain/Translations/en_US/resources.json +++ b/Wino.Core.Domain/Translations/en_US/resources.json @@ -135,6 +135,8 @@ "CalendarItem_DetailsPopup_JoinOnline": "Join online", "CalendarItem_DetailsPopup_ViewEventButton": "View event", "CalendarItem_DetailsPopup_ViewSeriesButton": "View series", + "CalendarDisplayOptions_Expand": "Expand", + "CalendarDisplayOptions_Color": "Color", "CreateAccountAliasDialog_Title": "Create Account Alias", "CreateAccountAliasDialog_Description": "Make sure your outgoing server allows sending mails from this alias.", "CreateAccountAliasDialog_AliasAddress": "Address", diff --git a/Wino.Core.UWP/Controls/EqualGridPanel.cs b/Wino.Core.UWP/Controls/EqualGridPanel.cs new file mode 100644 index 00000000..d784bd7e --- /dev/null +++ b/Wino.Core.UWP/Controls/EqualGridPanel.cs @@ -0,0 +1,87 @@ +using Windows.Foundation; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace Wino.Core.UWP.Controls +{ + public class EqualGridPanel : Panel + { + public int Rows + { + get { return (int)GetValue(RowsProperty); } + set { SetValue(RowsProperty, value); } + } + + public static readonly DependencyProperty RowsProperty = + DependencyProperty.Register( + nameof(Rows), + typeof(int), + typeof(EqualGridPanel), + new PropertyMetadata(1, OnLayoutPropertyChanged)); + + public int Columns + { + get { return (int)GetValue(ColumnsProperty); } + set { SetValue(ColumnsProperty, value); } + } + + public static readonly DependencyProperty ColumnsProperty = + DependencyProperty.Register( + nameof(Columns), + typeof(int), + typeof(EqualGridPanel), + new PropertyMetadata(1, OnLayoutPropertyChanged)); + + private static void OnLayoutPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is EqualGridPanel panel) + { + panel.InvalidateMeasure(); + panel.InvalidateArrange(); + } + } + + protected override Size MeasureOverride(Size availableSize) + { + if (Rows <= 0 || Columns <= 0) + { + return new Size(0, 0); + } + + double cellWidth = availableSize.Width / Columns; + double cellHeight = availableSize.Height / Rows; + + foreach (UIElement child in Children) + { + child.Measure(new Size(cellWidth, cellHeight)); + } + + return availableSize; + } + + protected override Size ArrangeOverride(Size finalSize) + { + if (Rows <= 0 || Columns <= 0) + { + return new Size(0, 0); + } + + double cellWidth = finalSize.Width / Columns; + double cellHeight = finalSize.Height / Rows; + + for (int i = 0; i < Children.Count; i++) + { + int row = i / Columns; + int column = i % Columns; + + double x = column * cellWidth; + double y = row * cellHeight; + + Rect rect = new Rect(x, y, cellWidth, cellHeight); + Children[i].Arrange(rect); + } + + return finalSize; + } + } +} diff --git a/Wino.Core.UWP/CoreUWPContainerSetup.cs b/Wino.Core.UWP/CoreUWPContainerSetup.cs index 619b575d..9d775080 100644 --- a/Wino.Core.UWP/CoreUWPContainerSetup.cs +++ b/Wino.Core.UWP/CoreUWPContainerSetup.cs @@ -45,7 +45,7 @@ namespace Wino.Core.UWP services.AddTransient(typeof(SettingOptionsPageViewModel)); services.AddTransient(typeof(AboutPageViewModel)); services.AddTransient(typeof(SettingsPageViewModel)); - services.AddTransient(typeof(NewAccountManagementPageViewModel)); + services.AddTransient(typeof(ManageAccountsPagePageViewModel)); } } } diff --git a/Wino.Core.UWP/Helpers/XamlHelpers.cs b/Wino.Core.UWP/Helpers/XamlHelpers.cs index fce7f013..0896189a 100644 --- a/Wino.Core.UWP/Helpers/XamlHelpers.cs +++ b/Wino.Core.UWP/Helpers/XamlHelpers.cs @@ -101,6 +101,9 @@ namespace Wino.Helpers }; } + public static string GetColorFromHex(Color color) => color.ToHex(); + public static Color GetWindowsColorFromHex(string hex) => hex.ToColor(); + public static SolidColorBrush GetSolidColorBrushFromHex(string colorHex) => string.IsNullOrEmpty(colorHex) ? new SolidColorBrush(Colors.Transparent) : new SolidColorBrush(colorHex.ToColor()); public static Visibility IsSelectionModeMultiple(ListViewSelectionMode mode) => mode == ListViewSelectionMode.Multiple ? Visibility.Visible : Visibility.Collapsed; public static FontWeight GetFontWeightBySyncState(bool isSyncing) => isSyncing ? FontWeights.SemiBold : FontWeights.Normal; diff --git a/Wino.Core.UWP/Services/DialogServiceBase.cs b/Wino.Core.UWP/Services/DialogServiceBase.cs index f81fae1d..bec6852d 100644 --- a/Wino.Core.UWP/Services/DialogServiceBase.cs +++ b/Wino.Core.UWP/Services/DialogServiceBase.cs @@ -11,6 +11,7 @@ using Windows.Storage.Pickers; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Wino.Core.Domain; +using Wino.Core.Domain.Entities.Shared; using Wino.Core.Domain.Enums; using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Models.Accounts; @@ -38,6 +39,18 @@ namespace Wino.Core.UWP.Services ApplicationResourceManager = applicationResourceManager; } + public async Task ShowEditAccountDialogAsync(MailAccount account) + { + var editAccountDialog = new AccountEditDialog(account) + { + RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme() + }; + + await HandleDialogPresentationAsync(editAccountDialog); + + return editAccountDialog.IsSaved ? editAccountDialog.Account : null; + } + public async Task PickFilePathAsync(string saveFileName) { var picker = new FolderPicker() diff --git a/Wino.Core.UWP/Styles/DataTemplates.xaml b/Wino.Core.UWP/Styles/DataTemplates.xaml index cb06a724..d429016f 100644 --- a/Wino.Core.UWP/Styles/DataTemplates.xaml +++ b/Wino.Core.UWP/Styles/DataTemplates.xaml @@ -34,8 +34,6 @@ - - diff --git a/Wino.Core.UWP/Views/Abstract/ManageAccountsPageAbstract.cs b/Wino.Core.UWP/Views/Abstract/ManageAccountsPageAbstract.cs new file mode 100644 index 00000000..4c9743ba --- /dev/null +++ b/Wino.Core.UWP/Views/Abstract/ManageAccountsPageAbstract.cs @@ -0,0 +1,8 @@ +using Wino.Core.ViewModels; + +namespace Wino.Core.UWP.Views.Abstract +{ + public abstract class ManageAccountsPageAbstract : BasePage + { + } +} diff --git a/Wino.Mail/Views/NewAccountManagementPage.xaml b/Wino.Core.UWP/Views/ManageAccountsPage.xaml similarity index 92% rename from Wino.Mail/Views/NewAccountManagementPage.xaml rename to Wino.Core.UWP/Views/ManageAccountsPage.xaml index 0f1f2ac9..8b414196 100644 --- a/Wino.Mail/Views/NewAccountManagementPage.xaml +++ b/Wino.Core.UWP/Views/ManageAccountsPage.xaml @@ -1,8 +1,8 @@ - - + diff --git a/Wino.Mail/Views/NewAccountManagementPage.xaml.cs b/Wino.Core.UWP/Views/ManageAccountsPage.xaml.cs similarity index 75% rename from Wino.Mail/Views/NewAccountManagementPage.xaml.cs rename to Wino.Core.UWP/Views/ManageAccountsPage.xaml.cs index 5653d4e0..d02b16b8 100644 --- a/Wino.Mail/Views/NewAccountManagementPage.xaml.cs +++ b/Wino.Core.UWP/Views/ManageAccountsPage.xaml.cs @@ -1,28 +1,27 @@ -using System; -using System.Collections.ObjectModel; +using System.Collections.ObjectModel; using System.Linq; using CommunityToolkit.Mvvm.Messaging; using MoreLinq; using Windows.UI.Xaml.Media.Animation; using Windows.UI.Xaml.Navigation; +using Wino.Core.Domain; using Wino.Core.Domain.Enums; +using Wino.Core.UWP.Views.Abstract; using Wino.Mail.ViewModels.Data; using Wino.Messaging.Client.Navigation; using Wino.Messaging.UI; -using Wino.Views.Abstract; -using Wino.Views.Account; -using Wino.Views.Settings; namespace Wino.Views { - public sealed partial class NewAccountManagementPage : NewAccountManagementPageAbstract, + public sealed partial class ManageAccountsPage : ManageAccountsPageAbstract, IRecipient, IRecipient, IRecipient { public ObservableCollection PageHistory { get; set; } = new ObservableCollection(); - public NewAccountManagementPage() + + public ManageAccountsPage() { InitializeComponent(); } @@ -31,27 +30,18 @@ namespace Wino.Views { base.OnNavigatedTo(e); - var initialRequest = new BreadcrumbNavigationRequested("Manage Accounts", Core.Domain.Enums.WinoPage.AccountManagementPage); + var initialRequest = new BreadcrumbNavigationRequested(Translator.MenuManageAccounts, WinoPage.AccountManagementPage); PageHistory.Add(new BreadcrumbNavigationItemViewModel(initialRequest, true)); - AccountPagesFrame.Navigate(typeof(AccountManagementPage), null, new SuppressNavigationTransitionInfo()); + var accountManagementPageType = ViewModel.NavigationService.GetPageType(WinoPage.AccountManagementPage); + + AccountPagesFrame.Navigate(accountManagementPageType, null, new SuppressNavigationTransitionInfo()); } - private Type GetPageNavigationType(WinoPage page) - { - return page switch - { - WinoPage.SignatureManagementPage => typeof(SignatureManagementPage), - WinoPage.AccountDetailsPage => typeof(AccountDetailsPage), - WinoPage.MergedAccountDetailsPage => typeof(MergedAccountDetailsPage), - WinoPage.AliasManagementPage => typeof(AliasManagementPage), - _ => null, - }; - } void IRecipient.Receive(BreadcrumbNavigationRequested message) { - var pageType = GetPageNavigationType(message.PageType); + var pageType = ViewModel.NavigationService.GetPageType(message.PageType); if (pageType == null) return; diff --git a/Wino.Core.UWP/Wino.Core.UWP.csproj b/Wino.Core.UWP/Wino.Core.UWP.csproj index 921959aa..68e93778 100644 --- a/Wino.Core.UWP/Wino.Core.UWP.csproj +++ b/Wino.Core.UWP/Wino.Core.UWP.csproj @@ -86,6 +86,7 @@ + WinoAppTitleBar.xaml @@ -166,9 +167,13 @@ DataTemplates.xaml + + + ManageAccountsPage.xaml + SettingOptionsPage.xaml @@ -400,6 +405,10 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + MSBuild:Compile Designer diff --git a/Wino.Core.ViewModels/NewAccountManagementPageViewModel.cs b/Wino.Core.ViewModels/NewAccountManagementPageViewModel.cs index 06c8abf4..e5655863 100644 --- a/Wino.Core.ViewModels/NewAccountManagementPageViewModel.cs +++ b/Wino.Core.ViewModels/NewAccountManagementPageViewModel.cs @@ -2,10 +2,13 @@ namespace Wino.Core.ViewModels { - public class NewAccountManagementPageViewModel : CoreBaseViewModel + public class ManageAccountsPagePageViewModel : CoreBaseViewModel { - public NewAccountManagementPageViewModel(IMailDialogService dialogService) + public ManageAccountsPagePageViewModel(INavigationService navigationService) { + NavigationService = navigationService; } + + public INavigationService NavigationService { get; } } } diff --git a/Wino.Core/Synchronizers/OutlookSynchronizer.cs b/Wino.Core/Synchronizers/OutlookSynchronizer.cs index e4bb6140..97bc17d5 100644 --- a/Wino.Core/Synchronizers/OutlookSynchronizer.cs +++ b/Wino.Core/Synchronizers/OutlookSynchronizer.cs @@ -966,85 +966,83 @@ namespace Wino.Core.Synchronizers.Mail // await SynchronizeCalendarsAsync(cancellationToken).ConfigureAwait(false); + bool isInitialSync = string.IsNullOrEmpty(Account.CalendarSynchronizationDeltaIdentifier); + var localCalendars = await _outlookChangeProcessor.GetAccountCalendarsAsync(Account.Id).ConfigureAwait(false); - foreach (var calendar in localCalendars) + Microsoft.Graph.Me.CalendarView.Delta.DeltaGetResponse eventsDeltaResponse = null; + + if (isInitialSync) { - bool isInitialSync = string.IsNullOrEmpty(calendar.SynchronizationDeltaToken); + _logger.Debug("No calendar sync identifier for account {Name}. Performing initial sync.", Account.Name); - Microsoft.Graph.Me.CalendarView.Delta.DeltaGetResponse eventsDeltaResponse = null; + var startDate = DateTime.UtcNow.AddYears(-2).ToString("u"); + var endDate = DateTime.UtcNow.ToString("u"); - if (isInitialSync) + // No delta link. Performing initial sync. + eventsDeltaResponse = await _graphClient.Me.CalendarView.Delta.GetAsDeltaGetResponseAsync((requestConfiguration) => { - _logger.Debug("No sync identifier for Calendar {FolderName}. Performing initial sync.", calendar.Name); + requestConfiguration.QueryParameters.StartDateTime = startDate; + requestConfiguration.QueryParameters.EndDateTime = endDate; - var startDate = DateTime.UtcNow.AddYears(-2).ToString("u"); - var endDate = DateTime.UtcNow.ToString("u"); + // TODO: Expand does not work. + // https://github.com/microsoftgraph/msgraph-sdk-dotnet/issues/2358 - // No delta link. Performing initial sync. - eventsDeltaResponse = await _graphClient.Me.CalendarView.Delta.GetAsDeltaGetResponseAsync((requestConfiguration) => - { - requestConfiguration.QueryParameters.StartDateTime = startDate; - requestConfiguration.QueryParameters.EndDateTime = endDate; - requestConfiguration.QueryParameters.Expand = ["calendar"]; - }, cancellationToken: cancellationToken); - } - else - { - var currentDeltaToken = calendar.SynchronizationDeltaToken; - - var requestInformation = _graphClient.Me.Calendars[calendar.RemoteCalendarId].Events.Delta.ToGetRequestInformation((config) => - { - config.QueryParameters.Top = (int)InitialMessageDownloadCountPerFolder; - config.QueryParameters.Select = outlookMessageSelectParameters; - config.QueryParameters.Orderby = ["receivedDateTime desc"]; - }); - - requestInformation.UrlTemplate = requestInformation.UrlTemplate.Insert(requestInformation.UrlTemplate.Length - 1, ",%24deltatoken"); - requestInformation.QueryParameters.Add("%24deltatoken", currentDeltaToken); - - // eventsDeltaResponse = await _graphClient.RequestAdapter.SendAsync(requestInformation, Microsoft.Graph.Me.Calendars.Item.Events.Delta.DeltaGetResponse.CreateFromDiscriminatorValue); - } - - List events = new(); - - // We must first save the parent recurring events to not lose exceptions. - // Therefore, order the existing items by their type and save the parent recurring events first. - - var messageIteratorAsync = PageIterator.CreatePageIterator(_graphClient, eventsDeltaResponse, (item) => - { - events.Add(item); - - return true; - }); - - await messageIteratorAsync - .IterateAsync(cancellationToken) - .ConfigureAwait(false); - - // Desc-order will move parent recurring events to the top. - events = events.OrderByDescending(a => a.Type).ToList(); - - foreach (var item in events) - { - try - { - await _handleItemRetrievalSemaphore.WaitAsync(); - - await _outlookChangeProcessor.ManageCalendarEventAsync(item, calendar, Account).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.Error(ex, "Error occurred while handling item {Id} for calendar {Name}", item.Id, calendar.Name); - } - finally - { - _handleItemRetrievalSemaphore.Release(); - } - } - - // latestDeltaLink = messageIteratorAsync.Deltalink; + requestConfiguration.QueryParameters.Expand = new string[] { "calendar($select=name,id)" }; // Expand the calendar and select name and id. Customize as needed. + }, cancellationToken: cancellationToken); } + else + { + //var requestInformation = _graphClient.Me.Calendars[calendar.RemoteCalendarId].Events.Delta.ToGetRequestInformation((config) => + //{ + // config.QueryParameters.Top = (int)InitialMessageDownloadCountPerFolder; + // config.QueryParameters.Select = outlookMessageSelectParameters; + // config.QueryParameters.Orderby = ["receivedDateTime desc"]; + //}); + + //requestInformation.UrlTemplate = requestInformation.UrlTemplate.Insert(requestInformation.UrlTemplate.Length - 1, ",%24deltatoken"); + //requestInformation.QueryParameters.Add("%24deltatoken", currentDeltaToken); + + // eventsDeltaResponse = await _graphClient.RequestAdapter.SendAsync(requestInformation, Microsoft.Graph.Me.Calendars.Item.Events.Delta.DeltaGetResponse.CreateFromDiscriminatorValue); + } + + List events = new(); + + // We must first save the parent recurring events to not lose exceptions. + // Therefore, order the existing items by their type and save the parent recurring events first. + + var messageIteratorAsync = PageIterator.CreatePageIterator(_graphClient, eventsDeltaResponse, (item) => + { + events.Add(item); + + return true; + }); + + await messageIteratorAsync + .IterateAsync(cancellationToken) + .ConfigureAwait(false); + + // Desc-order will move parent recurring events to the top. + events = events.OrderByDescending(a => a.Type).ToList(); + + foreach (var item in events) + { + try + { + await _handleItemRetrievalSemaphore.WaitAsync(); + //await _outlookChangeProcessor.ManageCalendarEventAsync(item, calendar, Account).ConfigureAwait(false); + } + catch (Exception ex) + { + // _logger.Error(ex, "Error occurred while handling item {Id} for calendar {Name}", item.Id, calendar.Name); + } + finally + { + _handleItemRetrievalSemaphore.Release(); + } + } + + // latestDeltaLink = messageIteratorAsync.Deltalink; return default; } diff --git a/Wino.Mail/Services/NavigationService.cs b/Wino.Mail/Services/NavigationService.cs index 38303748..1c02328e 100644 --- a/Wino.Mail/Services/NavigationService.cs +++ b/Wino.Mail/Services/NavigationService.cs @@ -34,49 +34,30 @@ namespace Wino.Services public Type GetPageType(WinoPage winoPage) { - switch (winoPage) + return winoPage switch { - case WinoPage.None: - return null; - case WinoPage.IdlePage: - return typeof(IdlePage); - case WinoPage.AccountDetailsPage: - return typeof(AccountDetailsPage); - case WinoPage.MergedAccountDetailsPage: - return typeof(MergedAccountDetailsPage); - case WinoPage.AccountManagementPage: - return typeof(NewAccountManagementPage); - case WinoPage.SignatureManagementPage: - return typeof(SignatureManagementPage); - case WinoPage.AboutPage: - return typeof(AboutPage); - case WinoPage.PersonalizationPage: - return typeof(PersonalizationPage); - case WinoPage.MessageListPage: - return typeof(MessageListPage); - case WinoPage.ReadComposePanePage: - return typeof(ReadComposePanePage); - case WinoPage.MailRenderingPage: - return typeof(MailRenderingPage); - case WinoPage.ComposePage: - return typeof(ComposePage); - case WinoPage.MailListPage: - return typeof(MailListPage); - case WinoPage.SettingsPage: - return typeof(SettingsPage); - case WinoPage.WelcomePage: - return typeof(WelcomePage); - case WinoPage.SettingOptionsPage: - return typeof(SettingOptionsPage); - case WinoPage.AppPreferencesPage: - return typeof(AppPreferencesPage); - case WinoPage.AliasManagementPage: - return typeof(AliasManagementPage); - case WinoPage.LanguageTimePage: - return typeof(LanguageTimePage); - default: - return null; - } + WinoPage.None => null, + WinoPage.IdlePage => typeof(IdlePage), + WinoPage.AccountDetailsPage => typeof(AccountDetailsPage), + WinoPage.MergedAccountDetailsPage => typeof(MergedAccountDetailsPage), + WinoPage.AccountManagementPage => typeof(AccountManagementPage), + WinoPage.ManageAccountsPage => typeof(ManageAccountsPage), + WinoPage.SignatureManagementPage => typeof(SignatureManagementPage), + WinoPage.AboutPage => typeof(AboutPage), + WinoPage.PersonalizationPage => typeof(PersonalizationPage), + WinoPage.MessageListPage => typeof(MessageListPage), + WinoPage.ReadComposePanePage => typeof(ReadComposePanePage), + WinoPage.MailRenderingPage => typeof(MailRenderingPage), + WinoPage.ComposePage => typeof(ComposePage), + WinoPage.MailListPage => typeof(MailListPage), + WinoPage.SettingsPage => typeof(SettingsPage), + WinoPage.WelcomePage => typeof(WelcomePage), + WinoPage.SettingOptionsPage => typeof(SettingOptionsPage), + WinoPage.AppPreferencesPage => typeof(AppPreferencesPage), + WinoPage.AliasManagementPage => typeof(AliasManagementPage), + WinoPage.LanguageTimePage => typeof(LanguageTimePage), + _ => null, + }; } public Frame GetCoreFrame(NavigationReferenceFrame frameType) diff --git a/Wino.Mail/Views/Abstract/NewAccountManagementPageAbstract.cs b/Wino.Mail/Views/Abstract/NewAccountManagementPageAbstract.cs deleted file mode 100644 index eb376a91..00000000 --- a/Wino.Mail/Views/Abstract/NewAccountManagementPageAbstract.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Wino.Core.UWP; -using Wino.Core.ViewModels; - -namespace Wino.Views.Abstract -{ - public abstract class NewAccountManagementPageAbstract : BasePage - { - } -} diff --git a/Wino.Mail/Views/Account/AccountDetailsPage.xaml b/Wino.Mail/Views/Account/AccountDetailsPage.xaml index 05715a4b..a0c3ecf4 100644 --- a/Wino.Mail/Views/Account/AccountDetailsPage.xaml +++ b/Wino.Mail/Views/Account/AccountDetailsPage.xaml @@ -8,7 +8,6 @@ xmlns:coreControls="using:Wino.Core.UWP.Controls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:domain="using:Wino.Core.Domain" - xmlns:entites="using:Wino.Core.Domain.Entities" xmlns:folders="using:Wino.Core.Domain.Models.Folders" xmlns:helpers="using:Wino.Helpers" xmlns:interactionsCore="using:Microsoft.Xaml.Interactions.Core" diff --git a/Wino.Mail/Wino.Mail.csproj b/Wino.Mail/Wino.Mail.csproj index c4fe73a3..8e8f1b17 100644 --- a/Wino.Mail/Wino.Mail.csproj +++ b/Wino.Mail/Wino.Mail.csproj @@ -281,7 +281,6 @@ - @@ -322,9 +321,6 @@ MailRenderingPage.xaml - - NewAccountManagementPage.xaml - PersonalizationPage.xaml @@ -452,10 +448,6 @@ Designer MSBuild:Compile - - Designer - MSBuild:Compile - MSBuild:Compile Designer diff --git a/Wino.Services/CalendarService.cs b/Wino.Services/CalendarService.cs index 99490862..65ba5d58 100644 --- a/Wino.Services/CalendarService.cs +++ b/Wino.Services/CalendarService.cs @@ -23,7 +23,7 @@ namespace Wino.Services } public Task> GetAccountCalendarsAsync(Guid accountId) - => Connection.Table().Where(x => x.AccountId == accountId).ToListAsync(); + => Connection.Table().Where(x => x.AccountId == accountId).OrderByDescending(a => a.IsPrimary).ToListAsync(); public async Task InsertAccountCalendarAsync(AccountCalendar accountCalendar) {