From 0519bf86b3b8ac9a1ed1bbfbec7b48e404e692c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 29 Dec 2025 23:13:32 +0100 Subject: [PATCH] I dont know some improvements on reacting calendar changes. --- .../CalendarPageViewModel.cs | 58 ++++++++----------- .../Interfaces/ICalendarService.cs | 1 + Wino.Core.ViewModels/CalendarBaseViewModel.cs | 17 +++++- .../Processors/OutlookChangeProcessor.cs | 26 ++++++--- .../Calendar/CustomCalendarFlipView.cs | 2 - .../Controls/Calendar/WinoCalendarControl.cs | 4 +- Wino.Services/CalendarService.cs | 54 +++++++++++++---- 7 files changed, 101 insertions(+), 61 deletions(-) diff --git a/Wino.Calendar.ViewModels/CalendarPageViewModel.cs b/Wino.Calendar.ViewModels/CalendarPageViewModel.cs index 8eeed6eb..2a0a8d95 100644 --- a/Wino.Calendar.ViewModels/CalendarPageViewModel.cs +++ b/Wino.Calendar.ViewModels/CalendarPageViewModel.cs @@ -166,7 +166,6 @@ public partial class CalendarPageViewModel : CalendarBaseViewModel, base.RegisterRecipients(); Messenger.Register(this); - Messenger.Register(this); Messenger.Register(this); Messenger.Register(this); Messenger.Register(this); @@ -177,7 +176,6 @@ public partial class CalendarPageViewModel : CalendarBaseViewModel, base.UnregisterRecipients(); Messenger.Unregister(this); - Messenger.Unregister(this); Messenger.Unregister(this); Messenger.Unregister(this); Messenger.Unregister(this); @@ -613,30 +611,7 @@ public partial class CalendarPageViewModel : CalendarBaseViewModel, } } - protected override async void OnCalendarItemAdded(CalendarItem calendarItem) - { - base.OnCalendarItemAdded(calendarItem); - // Check if event falls into the current date range. - - - if (DayRanges.DisplayRange == null) return; - - // Check whether this event falls into any of the loaded date ranges. - var allDaysForEvent = DayRanges.SelectMany(a => a.CalendarDays).Where(a => a.Period.OverlapsWith(calendarItem.Period)); - - foreach (var calendarDay in allDaysForEvent) - { - var calendarItemViewModel = new CalendarItemViewModel(calendarItem); - - await ExecuteUIThread(() => - { - calendarDay.EventsCollection.AddCalendarItem(calendarItemViewModel); - }); - } - - FilterActiveCalendars(DayRanges); - } private async Task InitializeCalendarEventsForDayRangeAsync(DayRangeRenderModel dayRangeRenderModel) { @@ -871,23 +846,36 @@ public partial class CalendarPageViewModel : CalendarBaseViewModel, public void Receive(CalendarItemDoubleTappedMessage message) => NavigateEvent(message.CalendarItemViewModel, CalendarEventTargetType.Single); - public void Receive(CalendarItemRightTappedMessage message) - { + public void Receive(CalendarItemRightTappedMessage message) { } + protected override void OnCalendarItemDeleted(CalendarItem calendarItem) + { + base.OnCalendarItemDeleted(calendarItem); + + Debug.WriteLine($"Calendar item deleted: {calendarItem.Id}"); } - public async void Receive(CalendarItemDeleted message) + protected override async void OnCalendarItemAdded(CalendarItem calendarItem) { - // Each deleted recurrence will report for it's own. + base.OnCalendarItemAdded(calendarItem); + Debug.WriteLine($"Calendar item added: {calendarItem.Id}"); - await ExecuteUIThread(() => + // Check if event falls into the current date range. + if (DayRanges.DisplayRange == null) return; + + // Check whether this event falls into any of the loaded date ranges. + var allDaysForEvent = DayRanges.SelectMany(a => a.CalendarDays).Where(a => a.Period.OverlapsWith(calendarItem.Period)); + + foreach (var calendarDay in allDaysForEvent) { - var deletedItem = message.CalendarItem; + var calendarItemViewModel = new CalendarItemViewModel(calendarItem); - // Event might be spreaded into multiple days. - // Remove from all. + await ExecuteUIThread(() => + { + calendarDay.EventsCollection.AddCalendarItem(calendarItemViewModel); + }); + } - // var calendarItems = GetCalendarItems(deletedItem.Id); - }); + FilterActiveCalendars(DayRanges); } } diff --git a/Wino.Core.Domain/Interfaces/ICalendarService.cs b/Wino.Core.Domain/Interfaces/ICalendarService.cs index e598048b..b43c2ccd 100644 --- a/Wino.Core.Domain/Interfaces/ICalendarService.cs +++ b/Wino.Core.Domain/Interfaces/ICalendarService.cs @@ -37,4 +37,5 @@ public interface ICalendarService Task GetCalendarItemAsync(Guid id); Task> GetAttendeesAsync(Guid calendarEventTrackingId); Task> ManageEventAttendeesAsync(Guid calendarItemId, List allAttendees); + Task UpdateCalendarItemAsync(CalendarItem calendarItem, List attendees); } diff --git a/Wino.Core.ViewModels/CalendarBaseViewModel.cs b/Wino.Core.ViewModels/CalendarBaseViewModel.cs index 8b609872..e58e179b 100644 --- a/Wino.Core.ViewModels/CalendarBaseViewModel.cs +++ b/Wino.Core.ViewModels/CalendarBaseViewModel.cs @@ -4,23 +4,34 @@ using Wino.Messaging.Client.Calendar; namespace Wino.Core.ViewModels; -public class CalendarBaseViewModel : CoreBaseViewModel, IRecipient +public class CalendarBaseViewModel : CoreBaseViewModel, + IRecipient, + IRecipient, + IRecipient { public void Receive(CalendarItemAdded message) => OnCalendarItemAdded(message.CalendarItem); + public void Receive(CalendarItemUpdated message) => OnCalendarItemUpdated(message.CalendarItem); + public void Receive(CalendarItemDeleted message) => OnCalendarItemDeleted(message.CalendarItem); protected virtual void OnCalendarItemAdded(CalendarItem calendarItem) { } + protected virtual void OnCalendarItemUpdated(CalendarItem calendarItem) { } + protected virtual void OnCalendarItemDeleted(CalendarItem calendarItem) { } protected override void RegisterRecipients() { base.RegisterRecipients(); - + Messenger.Register(this); + Messenger.Register(this); + Messenger.Register(this); } protected override void UnregisterRecipients() { base.UnregisterRecipients(); - + Messenger.Unregister(this); + Messenger.Unregister(this); + Messenger.Unregister(this); } } diff --git a/Wino.Core/Integration/Processors/OutlookChangeProcessor.cs b/Wino.Core/Integration/Processors/OutlookChangeProcessor.cs index 6123d14c..473fbb89 100644 --- a/Wino.Core/Integration/Processors/OutlookChangeProcessor.cs +++ b/Wino.Core/Integration/Processors/OutlookChangeProcessor.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Graph.Models; @@ -49,6 +50,7 @@ public class OutlookChangeProcessor(IDatabaseService databaseService, var savingItem = await CalendarService.GetCalendarItemAsync(assignedCalendar.Id, calendarEvent.Id); Guid savingItemId = Guid.Empty; + bool isNewItem = savingItem == null; if (savingItem != null) savingItemId = savingItem.Id; @@ -111,7 +113,7 @@ public class OutlookChangeProcessor(IDatabaseService databaseService, // Set timestamps if (calendarEvent.CreatedDateTime.HasValue) savingItem.CreatedAt = calendarEvent.CreatedDateTime.Value; - + if (calendarEvent.LastModifiedDateTime.HasValue) savingItem.UpdatedAt = calendarEvent.LastModifiedDateTime.Value; @@ -164,15 +166,23 @@ public class OutlookChangeProcessor(IDatabaseService databaseService, savingItem.Status = CalendarItemStatus.Confirmed; } - // Upsert the event. - await Connection.InsertOrReplaceAsync(savingItem, typeof(CalendarItem)); - - // Manage attendees. + // Prepare attendees list + List attendees = null; if (calendarEvent.Attendees != null) { - // Clear all attendees for this event. - var attendees = calendarEvent.Attendees.Select(a => a.CreateAttendee(savingItemId)).ToList(); - await CalendarService.ManageEventAttendeesAsync(savingItemId, attendees).ConfigureAwait(false); + attendees = calendarEvent.Attendees.Select(a => a.CreateAttendee(savingItemId)).ToList(); + } + + // Use CalendarService to create or update the event + if (isNewItem) + { + // New item - use CreateNewCalendarItemAsync + await CalendarService.CreateNewCalendarItemAsync(savingItem, attendees).ConfigureAwait(false); + } + else + { + // Existing item - use UpdateCalendarItemAsync + await CalendarService.UpdateCalendarItemAsync(savingItem, attendees).ConfigureAwait(false); } } } diff --git a/Wino.Mail.WinUI/Controls/Calendar/CustomCalendarFlipView.cs b/Wino.Mail.WinUI/Controls/Calendar/CustomCalendarFlipView.cs index 3cc32ec7..d52dd761 100644 --- a/Wino.Mail.WinUI/Controls/Calendar/CustomCalendarFlipView.cs +++ b/Wino.Mail.WinUI/Controls/Calendar/CustomCalendarFlipView.cs @@ -24,8 +24,6 @@ public partial class CustomCalendarFlipView : FlipView // Hide navigation buttons PreviousButton.Opacity = NextButton.Opacity = 0; PreviousButton.IsHitTestVisible = NextButton.IsHitTestVisible = false; - - var t = FindName("ScrollingHost"); } public void GoPreviousFlip() diff --git a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarControl.cs b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarControl.cs index 6de17e97..0889205b 100644 --- a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarControl.cs +++ b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarControl.cs @@ -133,7 +133,6 @@ public partial class WinoCalendarControl : Control } } - private static void OnActiveVerticalScrollViewerChanged(DependencyObject calendar, DependencyPropertyChangedEventArgs e) { if (calendar is WinoCalendarControl calendarControl) @@ -152,7 +151,6 @@ public partial class WinoCalendarControl : Control } } - private static void OnActiveCanvasChanged(DependencyObject calendar, DependencyPropertyChangedEventArgs e) { if (calendar is WinoCalendarControl calendarControl) @@ -189,6 +187,8 @@ public partial class WinoCalendarControl : Control canvas.SelectedDateTime = null; canvas.TimelineCellSelected -= ActiveTimelineCellSelected; canvas.TimelineCellUnselected -= ActiveTimelineCellUnselected; + + canvas.Dispose(); } private void RegisterCanvas(WinoDayTimelineCanvas canvas) diff --git a/Wino.Services/CalendarService.cs b/Wino.Services/CalendarService.cs index 4508cd61..b2dbff90 100644 --- a/Wino.Services/CalendarService.cs +++ b/Wino.Services/CalendarService.cs @@ -8,13 +8,13 @@ using CommunityToolkit.Mvvm.Messaging; using Ical.Net.CalendarComponents; using Ical.Net.DataTypes; using Itenso.TimePeriod; +using Serilog; using Wino.Core.Domain; using Wino.Core.Domain.Entities.Calendar; using Wino.Core.Domain.Enums; using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Models.Calendar; using Wino.Messaging.Client.Calendar; -using Wino.Services.Extensions; namespace Wino.Services; @@ -78,17 +78,49 @@ public class CalendarService : BaseDatabaseService, ICalendarService public async Task CreateNewCalendarItemAsync(CalendarItem calendarItem, List attendees) { - await Connection.RunInTransactionAsync((conn) => - { - conn.Insert(calendarItem, typeof(CalendarItem)); + try + { + await Connection.RunInTransactionAsync((conn) => + { + conn.Insert(calendarItem, typeof(CalendarItem)); - if (attendees != null) - { - conn.InsertAll(attendees, typeof(CalendarEventAttendee)); - } - }); + if (attendees != null) + { + conn.InsertAll(attendees, typeof(CalendarEventAttendee)); + } + }); - WeakReferenceMessenger.Default.Send(new CalendarItemAdded(calendarItem)); + WeakReferenceMessenger.Default.Send(new CalendarItemAdded(calendarItem)); + } + catch (Exception ex) + { + Log.Error(ex, "Error creating new calendar item"); + } + } + + public async Task UpdateCalendarItemAsync(CalendarItem calendarItem, List attendees) + { + try + { + await Connection.RunInTransactionAsync((conn) => + { + conn.Update(calendarItem, typeof(CalendarItem)); + + // Clear existing attendees and add new ones + conn.Table().Delete(a => a.CalendarItemId == calendarItem.Id); + + if (attendees != null) + { + conn.InsertAll(attendees, typeof(CalendarEventAttendee)); + } + }); + + WeakReferenceMessenger.Default.Send(new CalendarItemUpdated(calendarItem)); + } + catch (Exception ex) + { + Log.Error(ex, "Error updating calendar item"); + } } /// @@ -180,7 +212,7 @@ public class CalendarService : BaseDatabaseService, ICalendarService // Compare by checking if an exception instance overlaps with this occurrence's time window. var occurrenceStart = occurrence.Period.StartTime.Value; var occurrenceEnd = occurrence.Period.EndTime?.Value ?? occurrenceStart.Add(occurrence.Period.Duration); - + var exceptionInstance = exceptionInstances.FirstOrDefault(a => a.StartDate <= occurrenceEnd && a.EndDate >= occurrenceStart);