This document describes the newly implemented features in the Desktop Calendar Widget application, including Always on Top, Reminder Notifications, and Recurring Events support.
Keep the Desktop Calendar Widget visible above all other windows, ensuring you never miss important events or tasks.
- Click the βοΈ Settings button in the top-right corner
- Check/Uncheck π Always on Top
- The window will immediately stay on top of other windows when enabled
- Implementation:
MainViewModel.IsAlwaysOnTopproperty bound toWindow.Topmost - Files Modified:
MainViewModel.cs: AddedIsAlwaysOnTopproperty andToggleAlwaysOnTopCommandMainWindow.xaml: AddedTopmost="{Binding IsAlwaysOnTop}"MainWindow.xaml.cs: Added menu item in settings
// MainViewModel.cs
public bool IsAlwaysOnTop
{
get => _isAlwaysOnTop;
set => SetProperty(ref _isAlwaysOnTop, value);
}Get desktop notifications for upcoming events at your preferred time before the event starts.
- Customizable Timing: Choose from 5 minutes to 1 day before event
- Notification Options:
- 5 minutes before
- 15 minutes before
- 30 minutes before (default)
- 1 hour before
- 2 hours before
- 1 day before
- Smart Notifications: Shows event title, time, and location
- Auto-dismiss: Notifications automatically close after 30 seconds
- Background Monitoring: Checks for upcoming events every minute
- Click β Add to create a new event
- Fill in event details
- Check Set Reminder
- Select desired reminder time from dropdown
- Click Save
- Click the βοΈ (edit) icon next to an event
- Check Set Reminder
- Select desired reminder time
- Click Save
- Events with reminders show a π icon in the calendar view
// CalendarEventModel.cs
public bool HasReminder { get; set; }
public int ReminderMinutes { get; set; } = 30;- Location:
Core/Services/NotificationService.cs - Functionality:
- Timer-based checking every 60 seconds
- Tracks notified events to avoid duplicates
- Creates WPF windows for notifications
- Auto-dismisses after 30 seconds
// App.xaml.cs
private NotificationService? _notificationService;
protected override void OnStartup(StartupEventArgs e)
{
// Initialize notification service
_notificationService = new NotificationService(calendarService);
_notificationService.Start();
}// GoogleCalendarService.cs
if (eventModel.HasReminder)
{
googleEvent.Reminders = new Event.RemindersData
{
UseDefault = false,
Overrides = new List<EventReminder>
{
new EventReminder
{
Method = "popup",
Minutes = eventModel.ReminderMinutes
}
}
};
}Create events that repeat on a schedule - daily, weekly, monthly, or yearly - with full Google Calendar synchronization.
- Frequency Options:
- Daily
- Weekly
- Monthly
- Yearly
- End Date: Specify when the recurring series should end
- RRULE Compliant: Uses standard iCalendar RRULE format
- Google Sync: Fully synchronized with Google Calendar recurrence patterns
- Visual Indicator: Recurring events show a π icon
- Click β Add to create a new event
- Fill in event details
- Check Repeat Event
- Select frequency from dropdown (Day/Week/Month/Year)
- Set Ends on date (optional)
- Click Save
- Click the βοΈ (edit) icon next to a recurring event
- Modify recurrence settings as needed
- Click Save
- Changes sync to all instances in Google Calendar
- Recurring events show a π icon in the calendar view
// CalendarEventModel.cs
public bool IsRecurring { get; set; }
public string RecurrenceFrequency { get; set; } = "DAILY";
public int RecurrenceInterval { get; set; } = 1;
public DateTime? RecurrenceEndDate { get; set; }
public int? RecurrenceCount { get; set; }
public string? RecurrenceRule { get; set; }// GoogleCalendarService.cs
if (eventModel.IsRecurring && eventModel.StartTime.HasValue)
{
var rrule = $"RRULE:FREQ={eventModel.RecurrenceFrequency};INTERVAL={eventModel.RecurrenceInterval}";
if (eventModel.RecurrenceEndDate.HasValue)
{
rrule += $";UNTIL={eventModel.RecurrenceEndDate.Value:yyyyMMdd}T000000Z";
}
googleEvent.Recurrence = new List<string> { rrule };
}- Daily:
RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20261231T000000Z - Weekly:
RRULE:FREQ=WEEKLY;INTERVAL=1;UNTIL=20261231T000000Z - Monthly:
RRULE:FREQ=MONTHLY;INTERVAL=1;UNTIL=20261231T000000Z - Yearly:
RRULE:FREQ=YEARLY;INTERVAL=1;UNTIL=20261231T000000Z
- New Size: 700x500 (up from 650x450)
- Min Constraints: 500x400 minimum size
- Better Layout: More breathing room for content
- π Icon: Indicates event has reminder set
- π Icon: Indicates recurring event
- Icons appear inline with event title for easy identification
- EventDialog: Now 500x500 with min constraints
- Better spacing for new reminder and recurrence sections
- Collapsible sections for recurrence options
<TextBlock Grid.Row="0" Grid.Column="0" FontWeight="SemiBold" FontSize="14" TextWrapping="Wrap">
<Run Text="{Binding Summary, Mode=OneWay}"/>
<Run Text=" π" Visibility="{Binding HasReminder, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<Run Text=" π" Visibility="{Binding IsRecurring, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</TextBlock>| Feature | Before | After |
|---|---|---|
| Always on Top | β Not available | β Toggle in settings |
| Event Reminders | β Not available | β 6 timing options |
| Recurring Events | β Not available | β 4 frequency types |
| Visual Indicators | β None | β π and π icons |
| Window Size | 650x450 | 700x500 |
| Notification System | β None | β Desktop notifications |
App.xaml.cs
βββ GoogleAuthService
βββ GoogleCalendarService (enhanced)
β βββ Reminder support
β βββ Recurrence support
βββ GoogleTaskService
βββ NotificationService (new)
β βββ Timer-based checking
β βββ Notification windows
βββ SyncService
User Action β ViewModel β Service β Google API
β
NotificationService
β
Desktop Notification
Core/Services/NotificationService.cs- Reminder notification service
-
Core/Models/CalendarEventModel.cs- Added reminder properties
- Added recurrence properties
-
Core/Services/GoogleCalendarService.cs- Enhanced with reminder mapping
- Enhanced with RRULE support
-
ViewModels/MainViewModel.cs- Added Always on Top property and command
-
Views/EventDialog.xaml&.xaml.cs- Added reminder UI
- Added recurrence UI
-
Views/CalendarView.xaml- Added visual indicators
-
MainWindow.xaml&.xaml.cs- Added Topmost binding
- Added Always on Top menu item
-
App.xaml.cs- Integrated NotificationService
- Create event: "Team Standup"
- Set time: 10:00 AM daily
- Enable reminder: 15 minutes before
- Set recurrence: Daily, ends in 1 month
- Result: Get notified at 9:45 AM every day
- Create event: "Project Deadline"
- Set date: Next Friday
- Enable reminder: 1 day before
- Result: Get notification on Thursday
- Create event: "Weekly Review"
- Set time: Friday 3:00 PM
- Enable reminder: 1 hour before
- Set recurrence: Weekly
- Result: Notified every Friday at 2:00 PM
-
Notification Service:
- Checks every minute (configurable)
- Does not support system tray notifications
- Requires app to be running
-
Recurring Events:
- Does not support complex recurrence patterns (e.g., "every 2nd Tuesday")
- Limited to basic RRULE patterns
- End date is preferred over count
-
Always on Top:
- Setting is not persisted across app restarts
- Global setting (cannot be per-window if multiple instances)
Potential improvements for future versions:
-
Enhanced Notifications:
- System tray integration
- Sound notifications
- Snooze functionality
-
Advanced Recurrence:
- Complex patterns (e.g., "last Friday of month")
- Exception dates
- Edit single occurrence
-
Persistent Settings:
- Save Always on Top preference
- Save default reminder time
- Remember window position
-
Multiple Reminders:
- Support multiple reminders per event
- Different notification types (popup, email, SMS)
Last Updated: January 2026
Version: 1.1.0
Author: Desktop Calendar Widget Team