win2d -> skia, some improvements on rendering.
This commit is contained in:
@@ -45,6 +45,7 @@
|
||||
<PackageVersion Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.ApplicationInsights" Version="4.0.0" />
|
||||
<PackageVersion Include="SkiaSharp" Version="3.119.1" />
|
||||
<PackageVersion Include="SkiaSharp.Views.WinUI" Version="3.119.1" />
|
||||
<PackageVersion Include="sqlite-net-pcl" Version="1.10.196-beta" />
|
||||
<PackageVersion Include="System.Drawing.Common" Version="10.0.1" />
|
||||
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
|
||||
|
||||
@@ -150,7 +150,7 @@ public partial class CalendarAppShellViewModel : CalendarBaseViewModel,
|
||||
|
||||
private async Task InitializeAccountCalendarsAsync()
|
||||
{
|
||||
await Dispatcher.ExecuteOnUIThread(() => AccountCalendarStateService.ClearGroupedAccountCalendar());
|
||||
await Dispatcher.ExecuteOnUIThread(() => AccountCalendarStateService.ClearGroupedAccountCalendars());
|
||||
|
||||
var accounts = await _accountService.GetAccountsAsync().ConfigureAwait(false);
|
||||
|
||||
|
||||
@@ -611,8 +611,6 @@ public partial class CalendarPageViewModel : CalendarBaseViewModel,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async Task InitializeCalendarEventsForDayRangeAsync(DayRangeRenderModel dayRangeRenderModel)
|
||||
{
|
||||
// Clear all events first for all days.
|
||||
@@ -626,9 +624,8 @@ public partial class CalendarPageViewModel : CalendarBaseViewModel,
|
||||
|
||||
// Initialization is done for all calendars, regardless whether they are actively selected or not.
|
||||
// This is because the filtering is cached internally of the calendar items in CalendarEventCollection.
|
||||
var allCalendars = AccountCalendarStateService.GroupedAccountCalendars.SelectMany(a => a.AccountCalendars);
|
||||
|
||||
foreach (var calendarViewModel in allCalendars)
|
||||
foreach (var calendarViewModel in AccountCalendarStateService.AllCalendars)
|
||||
{
|
||||
// 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.
|
||||
|
||||
@@ -69,10 +69,10 @@ public partial class GroupedAccountCalendarViewModel : ObservableObject
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isExpanded = true;
|
||||
public partial bool IsExpanded { get; set; } = true;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool? isCheckedState = true;
|
||||
public partial bool? IsCheckedState { get; set; } = true;
|
||||
|
||||
private bool _isExternalPropChangeBlocked = false;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ public interface IAccountCalendarStateService : INotifyPropertyChanged
|
||||
|
||||
public void AddGroupedAccountCalendar(GroupedAccountCalendarViewModel groupedAccountCalendar);
|
||||
public void RemoveGroupedAccountCalendar(GroupedAccountCalendarViewModel groupedAccountCalendar);
|
||||
public void ClearGroupedAccountCalendar();
|
||||
public void ClearGroupedAccountCalendars();
|
||||
|
||||
public void AddAccountCalendar(AccountCalendarViewModel accountCalendar);
|
||||
public void RemoveAccountCalendar(AccountCalendarViewModel accountCalendar);
|
||||
@@ -24,5 +24,5 @@ public interface IAccountCalendarStateService : INotifyPropertyChanged
|
||||
/// Enumeration of currently selected calendars.
|
||||
/// </summary>
|
||||
IEnumerable<AccountCalendarViewModel> ActiveCalendars { get; }
|
||||
// IEnumerable<IGrouping<MailAccount, AccountCalendarViewModel>> GroupedAccountCalendarsEnumerable { get; }
|
||||
IEnumerable<AccountCalendarViewModel> AllCalendars { get; }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using Microsoft.UI.Xaml.Automation.Peers;
|
||||
using System.Linq;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Automation.Peers;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Mail.WinUI.Controls.CalendarFlipView;
|
||||
|
||||
namespace Wino.Calendar.Controls;
|
||||
|
||||
@@ -11,21 +14,37 @@ public partial class CustomCalendarFlipView : FlipView
|
||||
private const string PART_PreviousButton = "PreviousButtonHorizontal";
|
||||
private const string PART_NextButton = "NextButtonHorizontal";
|
||||
|
||||
private Button PreviousButton;
|
||||
private Button NextButton;
|
||||
private Button? PreviousButton;
|
||||
private Button? NextButton;
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
PreviousButton = GetTemplateChild(PART_PreviousButton) as Button;
|
||||
NextButton = GetTemplateChild(PART_NextButton) as Button;
|
||||
PreviousButton = (Button)GetTemplateChild(PART_PreviousButton);
|
||||
NextButton = (Button)GetTemplateChild(PART_NextButton);
|
||||
|
||||
// Hide navigation buttons
|
||||
PreviousButton.Opacity = NextButton.Opacity = 0;
|
||||
PreviousButton.IsHitTestVisible = NextButton.IsHitTestVisible = false;
|
||||
|
||||
this.SelectionChanged += FlipViewSelectionChanged;
|
||||
}
|
||||
|
||||
private void FlipViewSelectionChanged(object sender, SelectionChangedEventArgs e) => OnSelectedItemChanged(e.RemovedItems.FirstOrDefault(), e.AddedItems.FirstOrDefault());
|
||||
|
||||
protected virtual void OnSelectedItemChanged(object oldValue, object newValue) { }
|
||||
|
||||
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
|
||||
{
|
||||
base.PrepareContainerForItemOverride(element, item);
|
||||
OnContainerPrepared(element, item);
|
||||
}
|
||||
|
||||
protected virtual void OnContainerPrepared(DependencyObject element, object item) { }
|
||||
|
||||
protected override DependencyObject GetContainerForItemOverride() => new WinoCalendarFlyoutItem();
|
||||
|
||||
public void GoPreviousFlip()
|
||||
{
|
||||
var backPeer = new ButtonAutomationPeer(PreviousButton);
|
||||
|
||||
@@ -187,8 +187,6 @@ public partial class WinoCalendarControl : Control
|
||||
canvas.SelectedDateTime = null;
|
||||
canvas.TimelineCellSelected -= ActiveTimelineCellSelected;
|
||||
canvas.TimelineCellUnselected -= ActiveTimelineCellUnselected;
|
||||
|
||||
canvas.Dispose();
|
||||
}
|
||||
|
||||
private void RegisterCanvas(WinoDayTimelineCanvas canvas)
|
||||
|
||||
@@ -20,9 +20,9 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView
|
||||
/// Gets or sets the active canvas that is currently displayed in the flip view.
|
||||
/// Each day-range of flip view item has a canvas that displays the day timeline.
|
||||
/// </summary>
|
||||
public WinoDayTimelineCanvas ActiveCanvas
|
||||
public WinoDayTimelineCanvas? ActiveCanvas
|
||||
{
|
||||
get { return (WinoDayTimelineCanvas)GetValue(ActiveCanvasProperty); }
|
||||
get { return (WinoDayTimelineCanvas?)GetValue(ActiveCanvasProperty); }
|
||||
set { SetValue(ActiveCanvasProperty, value); }
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView
|
||||
/// It's the vertical scroll that scrolls the timeline only, not the header part that belongs
|
||||
/// to parent FlipView control.
|
||||
/// </summary>
|
||||
public ScrollViewer ActiveVerticalScrollViewer
|
||||
public ScrollViewer? ActiveVerticalScrollViewer
|
||||
{
|
||||
get { return (ScrollViewer)GetValue(ActiveVerticalScrollViewerProperty); }
|
||||
get { return (ScrollViewer?)GetValue(ActiveVerticalScrollViewerProperty); }
|
||||
set { SetValue(ActiveVerticalScrollViewerProperty, value); }
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView
|
||||
|
||||
public WinoCalendarFlipView()
|
||||
{
|
||||
RegisterPropertyChangedCallback(SelectedIndexProperty, new DependencyPropertyChangedCallback(OnSelectedIndexUpdated));
|
||||
RegisterPropertyChangedCallback(ItemsSourceProperty, new DependencyPropertyChangedCallback(OnItemsSourceChanged));
|
||||
}
|
||||
|
||||
@@ -57,15 +56,6 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnSelectedIndexUpdated(DependencyObject d, DependencyProperty e)
|
||||
{
|
||||
if (d is WinoCalendarFlipView flipView)
|
||||
{
|
||||
flipView.UpdateActiveCanvas();
|
||||
flipView.UpdateActiveScrollViewer();
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterItemsSourceChange()
|
||||
{
|
||||
if (GetItemsSource() is INotifyCollectionChanged notifyCollectionChanged)
|
||||
@@ -74,61 +64,51 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnSelectedItemChanged(object oldValue, object newValue)
|
||||
{
|
||||
base.OnSelectedItemChanged(oldValue, newValue);
|
||||
|
||||
UpdateActiveElements();
|
||||
}
|
||||
|
||||
protected override void OnContainerPrepared(DependencyObject element, object item)
|
||||
{
|
||||
base.OnContainerPrepared(element, item);
|
||||
|
||||
// Check if this is the currently selected item's container
|
||||
var index = IndexFromContainer(element);
|
||||
if (index >= 0 && index == SelectedIndex)
|
||||
{
|
||||
// Container for selected item is now ready, update active elements
|
||||
UpdateActiveElements();
|
||||
}
|
||||
}
|
||||
|
||||
private void ItemsSourceUpdated(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
IsIdle = e.Action == NotifyCollectionChangedAction.Reset || e.Action == NotifyCollectionChangedAction.Replace;
|
||||
}
|
||||
|
||||
private async Task<FlipViewItem> GetCurrentFlipViewItem()
|
||||
{
|
||||
// TODO: Refactor this mechanism by listening to PrepareContainerForItemOverride and Loaded events together.
|
||||
while (ContainerFromIndex(SelectedIndex) == null)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
return ContainerFromIndex(SelectedIndex) as FlipViewItem;
|
||||
}
|
||||
|
||||
private void UpdateActiveScrollViewer()
|
||||
private void UpdateActiveElements()
|
||||
{
|
||||
if (SelectedIndex < 0)
|
||||
ActiveVerticalScrollViewer = null;
|
||||
else
|
||||
{
|
||||
GetCurrentFlipViewItem().ContinueWith(task =>
|
||||
{
|
||||
if (task.IsCompletedSuccessfully)
|
||||
{
|
||||
var flipViewItem = task.Result;
|
||||
|
||||
_ = DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
ActiveVerticalScrollViewer = flipViewItem.FindDescendant<ScrollViewer>();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateActiveCanvas()
|
||||
{
|
||||
if (SelectedIndex < 0)
|
||||
ActiveCanvas = null;
|
||||
ActiveVerticalScrollViewer = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Get container from index - respects virtualization
|
||||
if (ContainerFromIndex(SelectedIndex) is FlipViewItem container)
|
||||
{
|
||||
ActiveCanvas = container.FindDescendant<WinoDayTimelineCanvas>();
|
||||
ActiveVerticalScrollViewer = container.FindDescendant<ScrollViewer>();
|
||||
}
|
||||
else
|
||||
{
|
||||
GetCurrentFlipViewItem().ContinueWith(task =>
|
||||
{
|
||||
if (task.IsCompletedSuccessfully)
|
||||
{
|
||||
var flipViewItem = task.Result;
|
||||
|
||||
_ = DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
ActiveCanvas = flipViewItem.FindDescendant<WinoDayTimelineCanvas>();
|
||||
});
|
||||
}
|
||||
});
|
||||
// Container not ready yet - will be updated when OnContainerPrepared is called
|
||||
ActiveCanvas = null;
|
||||
ActiveVerticalScrollViewer = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.WinUI;
|
||||
using Microsoft.Graphics.Canvas.Geometry;
|
||||
using Microsoft.Graphics.Canvas.UI.Xaml;
|
||||
using Microsoft.UI.Input;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.Views.Windows;
|
||||
using Windows.Foundation;
|
||||
using Wino.Calendar.Args;
|
||||
using Wino.Core.Domain.Models.Calendar;
|
||||
@@ -21,7 +21,7 @@ public partial class WinoDayTimelineCanvas : Control, IDisposable
|
||||
public event EventHandler<TimelineCellUnselectedArgs> TimelineCellUnselected;
|
||||
|
||||
private const string PART_InternalCanvas = nameof(PART_InternalCanvas);
|
||||
private CanvasControl Canvas;
|
||||
private SKXamlCanvas Canvas;
|
||||
|
||||
public static readonly DependencyProperty RenderOptionsProperty = DependencyProperty.Register(nameof(RenderOptions), typeof(CalendarRenderOptions), typeof(WinoDayTimelineCanvas), new PropertyMetadata(null, new PropertyChangedCallback(OnRenderingPropertiesChanged)));
|
||||
public static readonly DependencyProperty SeperatorColorProperty = DependencyProperty.Register(nameof(SeperatorColor), typeof(SolidColorBrush), typeof(WinoDayTimelineCanvas), new PropertyMetadata(null, new PropertyChangedCallback(OnRenderingPropertiesChanged)));
|
||||
@@ -77,11 +77,13 @@ public partial class WinoDayTimelineCanvas : Control, IDisposable
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
Canvas = GetTemplateChild(PART_InternalCanvas) as CanvasControl;
|
||||
Canvas = GetTemplateChild(PART_InternalCanvas) as SKXamlCanvas;
|
||||
|
||||
// TODO: These will leak. Dispose them properly when needed.
|
||||
Canvas.Draw += OnCanvasDraw;
|
||||
Canvas.PointerPressed += OnCanvasPointerPressed;
|
||||
if (Canvas != null)
|
||||
{
|
||||
Canvas.PaintSurface += OnCanvasPaintSurface;
|
||||
Canvas.PointerPressed += OnCanvasPointerPressed;
|
||||
}
|
||||
|
||||
ForceDraw();
|
||||
}
|
||||
@@ -179,21 +181,23 @@ public partial class WinoDayTimelineCanvas : Control, IDisposable
|
||||
{
|
||||
return RenderOptions != null
|
||||
&& Canvas != null
|
||||
&& Canvas.ReadyToDraw
|
||||
&& WorkingHourCellBackgroundColor != null
|
||||
&& SeperatorColor != null
|
||||
&& HalfHourSeperatorColor != null
|
||||
&& SelectedCellBackgroundBrush != null;
|
||||
}
|
||||
|
||||
private void OnCanvasDraw(CanvasControl sender, CanvasDrawEventArgs args)
|
||||
private void OnCanvasPaintSurface(object sender, SKPaintSurfaceEventArgs e)
|
||||
{
|
||||
if (!CanDrawTimeline()) return;
|
||||
|
||||
var canvas = e.Surface.Canvas;
|
||||
canvas.Clear(SKColors.Transparent);
|
||||
|
||||
int hours = 24;
|
||||
|
||||
double canvasWidth = Canvas.ActualWidth;
|
||||
double canvasHeight = Canvas.ActualHeight;
|
||||
double canvasWidth = e.Info.Width;
|
||||
double canvasHeight = e.Info.Height;
|
||||
|
||||
if (canvasWidth == 0 || canvasHeight == 0) return;
|
||||
|
||||
@@ -205,9 +209,33 @@ public partial class WinoDayTimelineCanvas : Control, IDisposable
|
||||
double rectHeight = RenderOptions.CalendarSettings.HourHeight;
|
||||
|
||||
// Define stroke and fill colors
|
||||
var strokeColor = SeperatorColor.Color;
|
||||
var strokeColor = ToSKColor(SeperatorColor.Color);
|
||||
float strokeThickness = 0.5f;
|
||||
|
||||
// Create paints for drawing
|
||||
using var strokePaint = new SKPaint
|
||||
{
|
||||
Color = strokeColor,
|
||||
StrokeWidth = strokeThickness,
|
||||
Style = SKPaintStyle.Stroke,
|
||||
IsAntialias = true
|
||||
};
|
||||
|
||||
using var fillPaint = new SKPaint
|
||||
{
|
||||
Style = SKPaintStyle.Fill,
|
||||
IsAntialias = true
|
||||
};
|
||||
|
||||
using var dashedPaint = new SKPaint
|
||||
{
|
||||
Color = ToSKColor(HalfHourSeperatorColor.Color),
|
||||
StrokeWidth = strokeThickness,
|
||||
Style = SKPaintStyle.Stroke,
|
||||
PathEffect = SKPathEffect.CreateDash([2f, 2f], 0),
|
||||
IsAntialias = true
|
||||
};
|
||||
|
||||
for (int day = 0; day < RenderOptions.TotalDayCount; day++)
|
||||
{
|
||||
var currentDay = RenderOptions.DateRange.StartDate.AddDays(day);
|
||||
@@ -222,32 +250,31 @@ public partial class WinoDayTimelineCanvas : Control, IDisposable
|
||||
var representingDateTime = currentDay.AddHours(hour);
|
||||
|
||||
// Calculate the position and size of the rectangle
|
||||
double x = day * rectWidth;
|
||||
double y = hour * rectHeight;
|
||||
float x = (float)(day * rectWidth);
|
||||
float y = (float)(hour * rectHeight);
|
||||
float width = (float)rectWidth;
|
||||
float height = (float)rectHeight;
|
||||
|
||||
var rectangle = new Rect(x, y, rectWidth, rectHeight);
|
||||
var rectangle = new SKRect(x, y, x + width, y + height);
|
||||
|
||||
// Draw the rectangle border.
|
||||
// This is the main rectangle.
|
||||
args.DrawingSession.DrawRectangle(rectangle, strokeColor, strokeThickness);
|
||||
canvas.DrawRect(rectangle, strokePaint);
|
||||
|
||||
// Fill another rectangle with the working hour background color
|
||||
// This rectangle must be placed with -1 margin to prevent invisible borders of the main rectangle.
|
||||
if (isWorkingDay && renderTime >= RenderOptions.CalendarSettings.WorkingHourStart && renderTime <= RenderOptions.CalendarSettings.WorkingHourEnd)
|
||||
{
|
||||
var backgroundRectangle = new Rect(x + 1, y + 1, rectWidth - 1, rectHeight - 1);
|
||||
var backgroundRectangle = new SKRect(x + 1, y + 1, x + width - 1, y + height - 1);
|
||||
|
||||
args.DrawingSession.DrawRectangle(backgroundRectangle, strokeColor, strokeThickness);
|
||||
args.DrawingSession.FillRectangle(backgroundRectangle, WorkingHourCellBackgroundColor.Color);
|
||||
canvas.DrawRect(backgroundRectangle, strokePaint);
|
||||
fillPaint.Color = ToSKColor(WorkingHourCellBackgroundColor.Color);
|
||||
canvas.DrawRect(backgroundRectangle, fillPaint);
|
||||
}
|
||||
|
||||
// Draw a line in the center of the rectangle for representing half hours.
|
||||
double lineY = y + rectHeight / 2;
|
||||
|
||||
args.DrawingSession.DrawLine((float)x, (float)lineY, (float)(x + rectWidth), (float)lineY, HalfHourSeperatorColor.Color, strokeThickness, new CanvasStrokeStyle()
|
||||
{
|
||||
DashStyle = CanvasDashStyle.Dot
|
||||
});
|
||||
float lineY = y + height / 2;
|
||||
canvas.DrawLine(x, lineY, x + width, lineY, dashedPaint);
|
||||
}
|
||||
|
||||
// Draw selected item background color for the date if possible.
|
||||
@@ -265,20 +292,30 @@ public partial class WinoDayTimelineCanvas : Control, IDisposable
|
||||
selectedY += rectHeight / 2;
|
||||
}
|
||||
|
||||
var selectedRectangle = new Rect(day * rectWidth, selectedY, rectWidth, selectionRectHeight);
|
||||
args.DrawingSession.FillRectangle(selectedRectangle, SelectedCellBackgroundBrush.Color);
|
||||
var selectedRectangle = new SKRect(
|
||||
(float)(day * rectWidth),
|
||||
(float)selectedY,
|
||||
(float)(day * rectWidth + rectWidth),
|
||||
(float)(selectedY + selectionRectHeight));
|
||||
|
||||
fillPaint.Color = ToSKColor(SelectedCellBackgroundBrush.Color);
|
||||
canvas.DrawRect(selectedRectangle, fillPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static SKColor ToSKColor(Windows.UI.Color color)
|
||||
{
|
||||
return new SKColor(color.R, color.G, color.B, color.A);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Canvas == null) return;
|
||||
|
||||
Canvas.Draw -= OnCanvasDraw;
|
||||
Canvas.PaintSurface -= OnCanvasPaintSurface;
|
||||
Canvas.PointerPressed -= OnCanvasPointerPressed;
|
||||
Canvas.RemoveFromVisualTree();
|
||||
|
||||
Canvas = null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Wino.Mail.WinUI.Controls.CalendarFlipView;
|
||||
|
||||
public partial class WinoCalendarFlyoutItem : FlipViewItem
|
||||
{
|
||||
public WinoCalendarFlyoutItem()
|
||||
{
|
||||
DefaultStyleKey = typeof(WinoCalendarFlyoutItem);
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ public partial class WinoMailItemViewModelListViewItem : ListViewItem
|
||||
|
||||
partial void OnItemPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
// TODO: This slows down. Optimize later.
|
||||
Debug.WriteLine("WinoMailItemViewModelListViewItem item changed");
|
||||
|
||||
if (e.OldValue is MailItemViewModel oldMailItemViewModel) UnregisterPropertyChanged(oldMailItemViewModel);
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Linq;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Calendar.ViewModels.Data;
|
||||
using Wino.Calendar.ViewModels.Interfaces;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
|
||||
namespace Wino.Mail.WinUI.Services;
|
||||
|
||||
@@ -14,44 +15,43 @@ namespace Wino.Mail.WinUI.Services;
|
||||
/// </summary>
|
||||
public partial class AccountCalendarStateService : ObservableObject, IAccountCalendarStateService
|
||||
{
|
||||
public event EventHandler<GroupedAccountCalendarViewModel> CollectiveAccountGroupSelectionStateChanged;
|
||||
public event EventHandler<AccountCalendarViewModel> AccountCalendarSelectionStateChanged;
|
||||
public event EventHandler<GroupedAccountCalendarViewModel>? CollectiveAccountGroupSelectionStateChanged;
|
||||
public event EventHandler<AccountCalendarViewModel>? AccountCalendarSelectionStateChanged;
|
||||
|
||||
private readonly ObservableCollection<GroupedAccountCalendarViewModel> _internalGroupedAccountCalendars;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial ReadOnlyObservableCollection<GroupedAccountCalendarViewModel> GroupedAccountCalendars { get; set; }
|
||||
|
||||
private ObservableCollection<GroupedAccountCalendarViewModel> _internalGroupedAccountCalendars = new ObservableCollection<GroupedAccountCalendarViewModel>();
|
||||
|
||||
public IEnumerable<AccountCalendarViewModel> ActiveCalendars
|
||||
{
|
||||
get
|
||||
{
|
||||
return GroupedAccountCalendars
|
||||
.SelectMany(a => a.AccountCalendars)
|
||||
.Where(b => b.IsChecked);
|
||||
return _internalGroupedAccountCalendars
|
||||
.SelectMany(a => a.AccountCalendars)
|
||||
.Where(b => b.IsChecked);
|
||||
}
|
||||
}
|
||||
|
||||
//public IEnumerable<IGrouping<MailAccount, AccountCalendarViewModel>> GroupedAccountCalendarsEnumerable
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// return GroupedAccountCalendars
|
||||
// .Select(a => a.AccountCalendars)
|
||||
// .SelectMany(b => b)
|
||||
// .GroupBy(c => c.Account);
|
||||
// }
|
||||
//}
|
||||
public IEnumerable<AccountCalendarViewModel> AllCalendars
|
||||
{
|
||||
get
|
||||
{
|
||||
return _internalGroupedAccountCalendars
|
||||
.SelectMany(a => a.AccountCalendars);
|
||||
}
|
||||
}
|
||||
|
||||
public AccountCalendarStateService()
|
||||
{
|
||||
_internalGroupedAccountCalendars = new ObservableCollection<GroupedAccountCalendarViewModel>();
|
||||
GroupedAccountCalendars = new ReadOnlyObservableCollection<GroupedAccountCalendarViewModel>(_internalGroupedAccountCalendars);
|
||||
}
|
||||
|
||||
private void SingleGroupCalendarCollectiveStateChanged(object sender, EventArgs e)
|
||||
=> CollectiveAccountGroupSelectionStateChanged?.Invoke(this, sender as GroupedAccountCalendarViewModel);
|
||||
private void SingleGroupCalendarCollectiveStateChanged(object? sender, EventArgs e)
|
||||
=> CollectiveAccountGroupSelectionStateChanged?.Invoke(this, sender as GroupedAccountCalendarViewModel ?? throw new InvalidOperationException("Sender must be GroupedAccountCalendarViewModel"));
|
||||
|
||||
private void SingleCalendarSelectionStateChanged(object sender, AccountCalendarViewModel e)
|
||||
private void SingleCalendarSelectionStateChanged(object? sender, AccountCalendarViewModel e)
|
||||
=> AccountCalendarSelectionStateChanged?.Invoke(this, e);
|
||||
|
||||
public void AddGroupedAccountCalendar(GroupedAccountCalendarViewModel groupedAccountCalendar)
|
||||
@@ -70,7 +70,7 @@ public partial class AccountCalendarStateService : ObservableObject, IAccountCal
|
||||
_internalGroupedAccountCalendars.Remove(groupedAccountCalendar);
|
||||
}
|
||||
|
||||
public void ClearGroupedAccountCalendar()
|
||||
public void ClearGroupedAccountCalendars()
|
||||
{
|
||||
while (_internalGroupedAccountCalendars.Any())
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
|
||||
xmlns:controls="using:Wino.Calendar.Controls">
|
||||
xmlns:controls="using:Wino.Calendar.Controls"
|
||||
xmlns:skia="using:SkiaSharp.Views.Windows">
|
||||
|
||||
<!-- Background Timeline Canvas -->
|
||||
<Style TargetType="controls:WinoDayTimelineCanvas">
|
||||
@@ -10,7 +10,7 @@
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="controls:WinoDayTimelineCanvas">
|
||||
<canvas:CanvasControl x:Name="PART_InternalCanvas" />
|
||||
<skia:SKXamlCanvas x:Name="PART_InternalCanvas" />
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
|
||||
@@ -150,11 +150,11 @@
|
||||
<ListView.GroupStyle>
|
||||
<GroupStyle>
|
||||
<GroupStyle.HeaderTemplate>
|
||||
<DataTemplate>
|
||||
<DataTemplate x:DataType="data:GroupedAccountCalendarViewModel">
|
||||
<TextBlock
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding Key.Name}" />
|
||||
Text="{x:Bind Account.Name}" />
|
||||
</DataTemplate>
|
||||
</GroupStyle.HeaderTemplate>
|
||||
</GroupStyle>
|
||||
|
||||
@@ -144,6 +144,7 @@
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock" />
|
||||
|
||||
<PackageReference Include="Microsoft.Graphics.Win2D" />
|
||||
<PackageReference Include="SkiaSharp.Views.WinUI" />
|
||||
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" />
|
||||
|
||||
Reference in New Issue
Block a user