Single isntances and some updates shit.
This commit is contained in:
@@ -13,6 +13,7 @@ public class CalendarEventCollection
|
||||
{
|
||||
public event EventHandler<ICalendarItem> CalendarItemAdded;
|
||||
public event EventHandler<ICalendarItem> CalendarItemRemoved;
|
||||
public event EventHandler<ICalendarItem> CalendarItemUpdated;
|
||||
|
||||
public event EventHandler CalendarItemsCleared;
|
||||
|
||||
@@ -116,9 +117,13 @@ public class CalendarEventCollection
|
||||
|
||||
private void AddCalendarItemInternal(ObservableRangeCollection<ICalendarItem> collection, ICalendarItem calendarItem, bool create = true)
|
||||
{
|
||||
if (calendarItem is not ICalendarItemViewModel)
|
||||
if (calendarItem is not ICalendarItemViewModel viewModel)
|
||||
throw new ArgumentException("CalendarItem must be of type ICalendarItemViewModel", nameof(calendarItem));
|
||||
|
||||
// Set the displaying context for proper title calculation
|
||||
viewModel.DisplayingPeriod = Period;
|
||||
viewModel.CalendarSettings = Settings;
|
||||
|
||||
collection.Add(calendarItem);
|
||||
|
||||
if (create)
|
||||
@@ -144,6 +149,53 @@ public class CalendarEventCollection
|
||||
CalendarItemRemoved?.Invoke(this, calendarItem);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing calendar item in-place. If the item's type changed (all-day vs regular),
|
||||
/// it will be moved to the appropriate collection.
|
||||
/// </summary>
|
||||
/// <param name="calendarItem">The updated calendar item data.</param>
|
||||
/// <returns>True if the item was found and updated; false otherwise.</returns>
|
||||
public bool UpdateCalendarItem(CalendarItem calendarItem)
|
||||
{
|
||||
var existingItem = _allItems.FirstOrDefault(x => x.Id == calendarItem.Id);
|
||||
if (existingItem == null)
|
||||
return false;
|
||||
|
||||
// Get the collections this item is currently in (before update)
|
||||
var oldCollections = GetProperCollectionsForCalendarItem(existingItem).ToList();
|
||||
|
||||
// Update the underlying data
|
||||
if (existingItem is ICalendarItemViewModel viewModel)
|
||||
{
|
||||
viewModel.UpdateFrom(calendarItem);
|
||||
}
|
||||
|
||||
// Get the collections this item should be in (after update)
|
||||
var newCollections = GetProperCollectionsForCalendarItem(existingItem).ToList();
|
||||
|
||||
// Check if the collections changed
|
||||
var collectionsToRemoveFrom = oldCollections.Except(newCollections).ToList();
|
||||
var collectionsToAddTo = newCollections.Except(oldCollections).ToList();
|
||||
|
||||
// Remove from old collections that are no longer applicable
|
||||
foreach (var collection in collectionsToRemoveFrom)
|
||||
{
|
||||
collection.Remove(existingItem);
|
||||
}
|
||||
|
||||
// Add to new collections that are now applicable
|
||||
foreach (var collection in collectionsToAddTo)
|
||||
{
|
||||
if (!collection.Contains(existingItem))
|
||||
{
|
||||
collection.Add(existingItem);
|
||||
}
|
||||
}
|
||||
|
||||
CalendarItemUpdated?.Invoke(this, existingItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_internalAllDayEvents.Clear();
|
||||
|
||||
@@ -4,6 +4,7 @@ using Itenso.TimePeriod;
|
||||
using SQLite;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Calendar;
|
||||
|
||||
namespace Wino.Core.Domain.Entities.Calendar;
|
||||
|
||||
@@ -72,9 +73,7 @@ public class CalendarItem : ICalendarItem
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Events that are either an exceptional instance of a recurring event or occurrences.
|
||||
/// IsOccurrence is used to display occurrence instances of parent recurring events.
|
||||
/// IsOccurrence == false && IsRecurringChild == true => exceptional single instance.
|
||||
/// Events that are child instances of a recurring event (occurrences or exceptions).
|
||||
/// </summary>
|
||||
public bool IsRecurringChild
|
||||
{
|
||||
@@ -85,7 +84,7 @@ public class CalendarItem : ICalendarItem
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Events that are either an exceptional instance of a recurring event or occurrences.
|
||||
/// Events that are part of a recurring series (either as parent or child).
|
||||
/// </summary>
|
||||
public bool IsRecurringEvent => IsRecurringChild || IsRecurringParent;
|
||||
|
||||
@@ -140,12 +139,12 @@ public class CalendarItem : ICalendarItem
|
||||
public string HtmlLink { get; set; }
|
||||
public CalendarItemStatus Status { get; set; }
|
||||
public CalendarItemVisibility Visibility { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Indicates how the event should be shown in the calendar (Free, Busy, Tentative, etc.).
|
||||
/// </summary>
|
||||
public CalendarItemShowAs ShowAs { get; set; } = CalendarItemShowAs.Busy;
|
||||
|
||||
|
||||
public DateTimeOffset CreatedAt { get; set; }
|
||||
public DateTimeOffset UpdatedAt { get; set; }
|
||||
public Guid CalendarId { get; set; }
|
||||
@@ -154,51 +153,11 @@ public class CalendarItem : ICalendarItem
|
||||
public IAccountCalendar AssignedCalendar { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether this item does not really exist in the database or not.
|
||||
/// These are used to display occurrence instances of parent recurring events.
|
||||
/// Id to load information related to this event (attendees, reminders, etc.).
|
||||
/// For child events, if they have their own data, use their own Id.
|
||||
/// For events that share data with their parent, return parent's Id.
|
||||
/// </summary>
|
||||
[Ignore]
|
||||
public bool IsOccurrence { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id to load information related to this event.
|
||||
/// Occurrences tracked by the parent recurring event if they are not exceptional instances.
|
||||
/// Recurring children here are exceptional instances. They have their own info in the database including Id.
|
||||
/// </summary>
|
||||
public Guid EventTrackingId => IsOccurrence ? RecurringCalendarItemId.Value : Id;
|
||||
|
||||
public CalendarItem CreateRecurrence(DateTime startDate, double durationInSeconds)
|
||||
{
|
||||
// Create a copy with the new start date and duration
|
||||
|
||||
return new CalendarItem
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Title = Title,
|
||||
Description = Description,
|
||||
Location = Location,
|
||||
StartDate = startDate,
|
||||
DurationInSeconds = durationInSeconds,
|
||||
Recurrence = Recurrence,
|
||||
OrganizerDisplayName = OrganizerDisplayName,
|
||||
OrganizerEmail = OrganizerEmail,
|
||||
RecurringCalendarItemId = Id,
|
||||
AssignedCalendar = AssignedCalendar,
|
||||
CalendarId = CalendarId,
|
||||
CreatedAt = CreatedAt,
|
||||
UpdatedAt = UpdatedAt,
|
||||
Visibility = Visibility,
|
||||
Status = Status,
|
||||
CustomEventColorHex = CustomEventColorHex,
|
||||
HtmlLink = HtmlLink,
|
||||
StartTimeZone = StartTimeZone,
|
||||
EndTimeZone = EndTimeZone,
|
||||
RemoteEventId = RemoteEventId,
|
||||
IsHidden = IsHidden,
|
||||
IsLocked = IsLocked,
|
||||
IsOccurrence = true
|
||||
};
|
||||
}
|
||||
public Guid EventTrackingId => Id;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the start date converted to user's local timezone for display.
|
||||
@@ -219,10 +178,10 @@ public class CalendarItem : ICalendarItem
|
||||
{
|
||||
var sourceTimeZone = TimeZoneInfo.FindSystemTimeZoneById(StartTimeZone);
|
||||
var localTimeZone = TimeZoneInfo.Local;
|
||||
|
||||
|
||||
// Ensure DateTime is Unspecified kind before conversion
|
||||
var unspecifiedDateTime = DateTime.SpecifyKind(StartDate, DateTimeKind.Unspecified);
|
||||
|
||||
|
||||
// Convert from source timezone to local timezone
|
||||
return TimeZoneInfo.ConvertTime(unspecifiedDateTime, sourceTimeZone, localTimeZone);
|
||||
}
|
||||
@@ -253,10 +212,10 @@ public class CalendarItem : ICalendarItem
|
||||
{
|
||||
var sourceTimeZone = TimeZoneInfo.FindSystemTimeZoneById(EndTimeZone);
|
||||
var localTimeZone = TimeZoneInfo.Local;
|
||||
|
||||
|
||||
// Ensure DateTime is Unspecified kind before conversion
|
||||
var unspecifiedDateTime = DateTime.SpecifyKind(EndDate, DateTimeKind.Unspecified);
|
||||
|
||||
|
||||
// Convert from source timezone to local timezone
|
||||
return TimeZoneInfo.ConvertTime(unspecifiedDateTime, sourceTimeZone, localTimeZone);
|
||||
}
|
||||
@@ -267,4 +226,6 @@ public class CalendarItem : ICalendarItem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string GetDisplayTitle(ITimePeriod displayingPeriod, CalendarSettings calendarSettings) => Period.ToString();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using Itenso.TimePeriod;
|
||||
using Wino.Core.Domain.Models.Calendar;
|
||||
|
||||
namespace Wino.Core.Domain.Interfaces;
|
||||
|
||||
@@ -19,4 +20,13 @@ public interface ICalendarItem
|
||||
bool IsRecurringChild { get; }
|
||||
bool IsRecurringParent { get; }
|
||||
bool IsRecurringEvent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the display title for this calendar item when rendered in a specific day.
|
||||
/// For multi-day events, includes start/end time indicators.
|
||||
/// </summary>
|
||||
/// <param name="displayingPeriod">The period of the day where this item is being rendered.</param>
|
||||
/// <param name="calendarSettings">Calendar settings for time formatting.</param>
|
||||
/// <returns>The formatted title string.</returns>
|
||||
string GetDisplayTitle(ITimePeriod displayingPeriod, CalendarSettings calendarSettings);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
namespace Wino.Core.Domain.Interfaces;
|
||||
using Itenso.TimePeriod;
|
||||
using Wino.Core.Domain.Entities.Calendar;
|
||||
using Wino.Core.Domain.Models.Calendar;
|
||||
|
||||
namespace Wino.Core.Domain.Interfaces;
|
||||
|
||||
/// <summary>
|
||||
/// Temporarily to enforce CalendarItemViewModel. Used in CalendarEventCollection.
|
||||
@@ -6,4 +10,21 @@
|
||||
public interface ICalendarItemViewModel
|
||||
{
|
||||
bool IsSelected { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The period of the day where this item is currently being displayed.
|
||||
/// </summary>
|
||||
ITimePeriod DisplayingPeriod { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Calendar settings for time formatting.
|
||||
/// </summary>
|
||||
CalendarSettings CalendarSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Updates the view model's underlying CalendarItem from new data.
|
||||
/// This allows in-place updates without removing and re-adding items.
|
||||
/// </summary>
|
||||
/// <param name="calendarItem">The updated calendar item data.</param>
|
||||
void UpdateFrom(CalendarItem calendarItem);
|
||||
}
|
||||
|
||||
@@ -24,16 +24,8 @@ public interface ICalendarService
|
||||
/// </summary>
|
||||
/// <param name="calendar">The calendar to retrieve events from.</param>
|
||||
/// <param name="period">The time period to query events for.</param>
|
||||
/// <returns>List of calendar items including regular events and recurring event occurrences.</returns>
|
||||
/// <returns>List of calendar items that fall within the requested period.</returns>
|
||||
Task<List<CalendarItem>> GetCalendarEventsAsync(IAccountCalendar calendar, ITimePeriod period);
|
||||
|
||||
/// <summary>
|
||||
/// Expands a recurring calendar item to check if any of its occurrences fall within the given periods.
|
||||
/// </summary>
|
||||
/// <param name="calendarItem">The calendar item to expand (can be recurring or non-recurring).</param>
|
||||
/// <param name="periods">The list of periods to check against.</param>
|
||||
/// <returns>List of calendar items (either the original item or expanded recurrence instances) that fall within the periods.</returns>
|
||||
Task<List<CalendarItem>> GetExpandedRecurringEventsForPeriodsAsync(CalendarItem calendarItem, IEnumerable<ITimePeriod> periods);
|
||||
|
||||
Task<CalendarItem> GetCalendarItemAsync(Guid accountCalendarId, string remoteEventId);
|
||||
Task UpdateCalendarDeltaSynchronizationToken(Guid calendarId, string deltaToken);
|
||||
|
||||
Reference in New Issue
Block a user