Skip to main content

Changelog

Every improvement, automatically tracked from our commit history.

Subscribe via Atom feed
← Prev Page 9 of 95 Next →
February 28, 2026
patch Calendar

Add Google Calendar CalDAV sync via OAuth

Details

Wire the Calendar plugin into the existing shell-level Google OAuth

connection to support CalDAV sync with Google Calendar. Previously

the CalDavClient only supported HTTP Basic auth, which Google has

deprecated.

Changes:

  • CalDavProviderType: add Google enum value
  • CalDavCredentials: add BearerToken property (takes precedence

over Username/Password when set)

  • CalDavClient: rename SetBasicAuth → SetAuth, support Bearer

authorization header for OAuth providers

  • CalendarSubscription: add GoogleConnectionId field to persist

which Google OAuth account is linked to the subscription

  • CalendarPlugin: implement IConnectionConsumer declaring Google

with calendar scope, pass IConnectionService through to sync

service and ViewModel

  • AddSubscriptionViewModel: when provider is Google, load connected

Google accounts, skip username/password fields, use bearer token

for calendar discovery. Store GoogleConnectionId on subscription

  • CalendarSyncService: add ResolveCalDavCredentialsAsync that

fetches OAuth bearer tokens from IConnectionService for Google

subscriptions, vault credentials for others

Google CalDAV endpoint: apidata.googleusercontent.com/caldav/v2

Setup: enable CalDAV API and Google Calendar API in Google Cloud

Console, then connect Google account in Settings → Connections.

patch Calendar

Fix CalDAV bidirectional sync: delete propagation, metadata preservation, ICS fidelity

Details

Critical fixes:

  • Delete propagation: CalDAV events now marked pending_delete instead of being

immediately removed from the store. The sync service handles the server DELETE

and local cleanup on the next cycle.

  • Occurrence changes: Deleting or editing a single occurrence of a recurring

CalDAV event now marks the parent as pending_push so ExcludedDates propagate

to the server.

  • Editor metadata: Editing a CalDAV event preserves SourceUid, CalDavEtag,

CalDavHref, and ExcludedDates from the original event, preventing silent

metadata wipe and broken ETag concurrency.

  • Sync token initialization: After a full-fetch fallback (no token or expired

token), GetSyncTokenAsync PROPFIND acquires the current sync-token so

subsequent syncs use incremental sync-collection instead of full fetch.

  • Multi-VEVENT resources: CalDAV resources containing multiple VEVENTs (parent

+ exception overrides) are now all processed, not just the first.

ICS parser/exporter improvements:

  • EXDATE: Parse and export excluded dates for recurring events.
  • VALARM: Parse TRIGGER durations from VALARM sub-components into

ReminderMinutes. Export reminders as VALARM blocks with proper duration

formatting (e.g., -P1D, -PT1H, -PT30M).

  • Week duration: P#W format now correctly parsed as days (P1W = 7 days).
  • UNTIL date-only: 8-char UNTIL values (e.g., UNTIL=20250301) now route

through the VALUE=DATE parser branch instead of floating-time.

  • RECURRENCE-ID: Parsed into OriginalStart for CalDAV exception events.

Tests: 15 new test cases covering EXDATE, VALARM, week duration, UNTIL

date-only, RECURRENCE-ID, multi-VEVENT, and GetSyncTokenAsync.

patch Notes

Add "Publish to Gist" to Notes plugin

Details

One-click publishing of Notes pages as GitHub Gists. Converts the page to

markdown using the existing export infrastructure, creates a secret gist via

the GitHub API, and copies the gist URL to the clipboard.

Accessible from:

  • Export dropdown in page toolbar (Export → GitHub Gist)
  • Right-click context menu on page tree (Publish to Gist)

Uses the existing GitHub connection (Notes already implements IConnectionConsumer

with repo scope). No new dependencies or schema changes needed.

New files:

  • GistPublishService.cs: lightweight HTTP client for POST /gists only
patch Snippets

Fix gist push to handle title/filename renames

Details

PushSnippetAsync now detects when the snippet title has changed (producing a

different filename via BuildFilename) and sends a rename payload to the GitHub

API: deletes the old filename (null) and creates the new filename with content.

UpdateGistAsync gains a rawFiles parameter (Dictionary<string, object?>) to

support null values for file deletion, which is how the GitHub API expresses

file renames.

patch Snippets

Auto-push to gist on save when bidirectional sync is enabled

Details

When a snippet is linked to a gist source with sync_direction="bidirectional",

saving the snippet now automatically pushes the changes to GitHub. If the push

fails, the local save still succeeds and the user is notified of the push failure.

← Prev Page 9 of 95 Next →

Get notified about new releases