Add Sign In button to update modal for expired sessions
Details
When the update download fails due to an expired token and refresh also
fails, the modal now shows a "Sign In" button that triggers the OAuth
PKCE flow directly from the update dialog. On successful auth, tokens
are persisted and the user can immediately retry the download without
navigating to Settings.
- Added SignInCommand to UpdateViewModel with full OAuth PKCE flow
- Updated UpdateModal.axaml auth notice: replaced "go to Settings" text
with an inline Sign In button + "Waiting for browser..." state
- Added IsAuthenticating property for button state management
Add client-side token refresh fallback for update downloads
Details
When the access token is rejected during update download, the client now
silently attempts to refresh it via /api/auth/refresh using the stored
refresh token. On success, new tokens are persisted and the download
retries. On failure, the access token is cleared and the UI shows
"Session expired — please sign in again" instead of a generic error.
New: PrivStackApiClient.RefreshAccessTokenAsync() + RefreshTokenResponse DTO.
Fix info panel hover zone blocking plugin content clicks
Details
The info-tab-hover-zone Border used a 36px-wide transparent background
with IsHitTestVisible=True at ZIndex=10, creating an invisible click
barrier across the entire right edge of the content area. This blocked
clicks on plugin UI elements positioned near the right edge (e.g., the
settings cog in Tasks).
Fix: Remove the wide transparent hit area. The tab button is now always
slightly visible (opacity 0.15) and becomes fully visible on hover of
the button itself. The parent border no longer has a background or
forced hit-test, so pointer events pass through to the plugin content
below.
Catch NotSupportedException in SDK deserialization and fix PluginLoadContext
Details
SdkHost only caught JsonException but .NET 9's System.Text.Json throws
NotSupportedException for polymorphic type errors (missing discriminator,
unsupported interface types). Added catch for NotSupportedException so
these errors return graceful SdkResponse.Fail instead of crashing callers.
PluginLoadContext: changed from Default.LoadFromAssemblyPath (which could
conflict with runtime-managed assemblies) to returning null to let the
runtime's standard probing handle host-provided assemblies.
Fix PluginLoadContext: delegate to runtime probing instead of Default.LoadFromAssemblyPath
Details
The previous approach used Default.LoadFromAssemblyPath() to explicitly
load host-provided assemblies into the Default context. This could
conflict with runtime-managed assemblies and cause JSON polymorphic
deserialization failures (NotSupportedException for types with
JsonPolymorphic attributes).
Changed to return null when the host resolver can provide the assembly,
letting the runtime's standard default-context probing handle it. The
runtime finds the DLL in the app's output directory and loads it into
Default naturally, avoiding conflicts with already-loaded assemblies.
Get notified about new releases