Fix PATCH endpoint wiping unspecified fields on task/project update
Details
The HandleUpdateTaskAsync and HandleUpdateProjectAsync handlers were
passing the partial PATCH body directly as the SdkAction.Update payload.
Since the SDK treats Update as a full replacement, sending e.g.
{"status":"done"} would wipe title, description, and all other fields.
Added MergeWithExistingAsync helper that reads the current entity,
overlays the PATCH fields on top, and sends the merged result. This
gives proper partial-update (PATCH) semantics to both /tasks/{id} and
/projects/{id} endpoints.
Fix custom fields: delete, edit visibility, and detail panel display
Details
- Settings overlay: add delete button (x) to each custom field row
- Settings overlay: replace static List/Card badges with interactive
ToggleButtons that persist ShowInList/ShowInCard via UpdateAsync
- Detail panel: add Custom Fields section between Notes and Linked Items,
showing name-value pairs bound to SelectedTaskCustomFields
- ViewModel: parameterize DeleteFieldCommand to accept field directly,
add ToggleFieldVisibilityCommand with "list:{id}" / "card:{id}" format
Fix settings cog button in Tasks plugin (BUG #30)
Details
The TasksSettingsOverlay was missing the StyleInclude for the local
ModalOverlayTheme.axaml. Without this ControlTheme, the ModalOverlay
TemplatedControl had no visual template — clicking the settings cog
set IsOpen=true and made the UserControl visible, but the overlay
rendered as an empty box with no backdrop, card, or content.
The GitHubIssueSourcesOverlay had the correct StyleInclude but it
was never added to TasksSettingsOverlay when it was created.
Note: Build may fail at this commit due to concurrent in-progress
work by another session (CS0136 variable shadowing in
TasksViewModel.cs:2421) — will be resolved in a subsequent commit.
Add confirmation dialogs before destructive delete operations
Details
Notes: TrashPageAsync, TrashPageFromTreeAsync, DeletePagePermanentlyAsync,
and EmptyTrashAsync now prompt for user confirmation before proceeding.
Tasks: DeleteTaskByItem, DeleteTask, and BulkDelete converted from void
to async Task and now prompt for confirmation. DialogService wired in
TasksPlugin.CreateViewModelCore.
Calendar: DeleteEventByIdAsync now prompts for confirmation on the
non-recurring path (recurring events already have their own dialog).
Fixes polish audit bugs #22, #23, #49, #69.
Make ICS/CalDAV sync fully non-blocking with incremental UI refresh
Details
All sync operations now run on background threads so the UI stays
responsive. Events populate incrementally as each subscription
completes rather than blocking until everything finishes.
CalendarSyncService:
- SyncAllAsync runs subscriptions concurrently (bounded by
MaxConcurrency=8) instead of sequentially. Each subscription
fires SyncCompleted on completion for incremental UI refresh.
- Background timer loop (RunAsync) uses the same concurrent pattern
instead of sequential foreach.
CalendarViewModel:
- SyncAllCalendars fires sync on Task.Run and returns immediately.
SyncCompleted event (already wired via Dispatcher.UIThread.Post
in CalendarPlugin) handles the refresh.
AddSubscriptionViewModel:
- ICS and CalDAV subscription creation closes the dialog immediately
after persisting the subscription. Initial sync fires in background
via Task.Run — no more blocking the UI while the first fetch runs.
Get notified about new releases