Fix greyed-out sidebar in client mode (concurrent command execution)
Details
CommunityToolkit's AsyncRelayCommand disables the command while it's
executing, preventing concurrent calls. In client mode, SelectTab awaits
plugin.OnNavigatedToAsync() which makes HTTP SDK calls to the server —
these are much slower than local FFI calls. While the first SelectTab
is waiting on the HTTP response, all sidebar buttons bound to the same
SelectTabCommand are disabled (greyed out) because CanExecute returns
false during execution.
Fix: AllowConcurrentExecutions = true on SelectTab, matching the
expected behavior where rapid tab switching should always work.
Also fix HttpSdkTransport stale logger (same pattern as PluginRegistry:
static readonly ForContext becomes dead after ReconfigureForWorkspace).
Split Tasks plugin: create PrivStack.Plugin.Tasks.Headless
Details
Extract Models/ (16 files) and Services/ (16 files) from the Tasks
plugin into a new PrivStack.Plugin.Tasks.Headless project. This
assembly references only PrivStack.Sdk — zero Avalonia dependency —
making it loadable by the headless server.
New files in Headless:
- TasksHeadlessPlugin.cs: HeadlessPluginBase entry point with entity
schemas, service initialization, and IApiProvider implementation
- TasksApiHandler.cs: Shared API handler extracted from
TasksPlugin.Api.cs — used by both desktop and headless plugins
The UI plugin (PrivStack.Plugin.Tasks) now references the Headless
project for shared models and services. TasksPlugin.Api.cs delegates
to the shared TasksApiHandler.
Directory.Build.props updated: HeadlessPlugin=true opt-out prevents
UI.Adaptive (and thus Avalonia) from being added as a transitive
dependency to headless plugin projects.
AXAML xmlns declarations updated with assembly qualifier for types
now in the Headless assembly.
Bump patch versions for unified toast migration
Details
Calendar 1.14.7→1.14.8, Canvas 1.0.4→1.0.5, Contacts 1.9.6→1.9.7,
Data 1.21.0→1.21.1, Email 1.28.1→1.28.2, Files 1.11.0→1.11.1,
Finance 3.24.1→3.24.2, Habits 1.2.3→1.2.4, Journal 1.15.5→1.15.6,
Notes 1.65.1→1.65.2, WebClips 1.3.4→1.3.5. Both csproj and
PluginMetadata versions updated.
Fix plugin assembly resolution for cross-project dependencies
Details
PluginLoadContext now resolves assemblies from sibling plugin directories
when the plugin's own directory and host don't have them. This fixes the
Tasks plugin failing to load in client mode with FileNotFoundException
for PrivStack.Plugin.Tasks.Headless — the Headless DLL is deployed to
its own sibling directory (plugins/PrivStack.Plugin.Tasks.Headless/)
and the Tasks plugin depends on it for shared models and services.
Also guard Emergency Kit regeneration in client mode — SetupRecovery()
requires the native runtime which isn't initialized when running as a
client. Shows a clear message directing users to the server instance.
Migrate remaining plugins to unified IToastService
Details
Migrate Journal, Finance, Habits, WebClips, Canvas, Data, and Email
from local ErrorMessage/StatusMessage patterns to the shell's unified
IToastService. Email was the most involved — removed _errorMessage
ObservableProperty, ClearStatusAfterDelay helper, and converted all
ErrorMessage/StatusMessage completion notifications across 8 partial
class files to _toast?.Show() calls. StatusMessage retained for
in-progress indicators (sync status text). Sub-ViewModels (Compose,
AccountSetup, AccountSettings) keep their own ErrorMessage for inline
form validation.
Get notified about new releases