Skip to main content

Changelog

Every improvement, automatically tracked from our commit history.

Subscribe via Atom feed
← Prev Page 12 of 22 Next →
February 19, 2026
minor UI Components

Add EmptyState control — v1.40.0

SDK 1.39.0 → 1.40.0 | c4ac63db
Details

Introduces a reusable `EmptyState` control to `PrivStack.UI.Adaptive`, eliminating

per-plugin ad-hoc "no items yet" implementations.

**What was added**

`Controls/EmptyState.cs` — a `Border` subclass following the established imperative

construction pattern (no AXAML template, no reflection bindings). All visual tokens

resolve dynamically from the active PrivStack theme via `GetResourceObservable`.

Properties exposed:

  • `IconData` (Geometry?) — Material icon path supplied by the consumer.
  • `Title` (string) — Primary heading displayed below the icon bubble.
  • `Message` (string) — Supporting copy, center-aligned, max-width 320, wrapping.
  • `ActionLabel` / `ActionCommand` — Optional primary CTA (renders as `Button.accent`,

hidden when ActionLabel is null or empty).

  • `SecondaryActionLabel` / `SecondaryActionCommand` — Optional ghost CTA (renders as

`Button.ghost`, hidden when SecondaryActionLabel is null or empty).

  • `Variant` (EmptyStateVariant enum: Default | Search | Error | Permission) — Controls

which theme brush pair is applied to the icon bubble background and icon fill.

Visual structure:

```

StackPanel (center, spacing=24)

Border (72×72, CornerRadius=20) ← icon bubble; color driven by Variant

Path (36×36, Stretch=Uniform) ← icon path

StackPanel (spacing=8)

TextBlock ← title (ThemeFontSizeHeading2, SemiBold, ThemeTextPrimaryBrush)

TextBlock ← message (ThemeFontSizeBody, ThemeTextMutedBrush, MaxWidth=320)

StackPanel (spacing=12) [hidden when no ActionLabel]

Button.accent ← primary CTA

Button.ghost ← secondary CTA [hidden when no SecondaryActionLabel]

```

Variant → brush mapping:

  • Default → ThemePrimaryMutedBrush / ThemePrimaryBrush
  • Search → ThemeInfoMutedBrush / ThemeInfoBrush
  • Error → ThemeDangerMutedBrush / ThemeDangerBrush
  • Permission → ThemeWarningMutedBrush / ThemeWarningBrush

Theme changes are handled by subscribing to `ActualThemeVariantChanged` in

`OnAttachedToVisualTree` and unsubscribing in `OnDetachedFromVisualTree`, matching

the lifecycle pattern used by `PluginToolbar`, `PluginSidebar`, and `IconLabel`.

**Version bump**

`Directory.Build.props`: `PrivStackSdkVersion` 1.39.0 → 1.40.0

This is a minor bump reflecting new additive API surface in `PrivStack.UI.Adaptive`.

No breaking changes to existing controls.

minor Desktop Shell

Visual modernization pass 2 — shell components (v1.37.0)

Desktop 1.36.0 → 1.37.0 | 44becf8e
Details

Continued modernization of the PrivStack desktop shell components

toward a Material 3 aesthetic, following the Phase 1 color and nav

overhaul (v1.36.0).

PluginCommandBar.axaml:

  • Fixed StackPanel Spacing="-2" → Spacing="2" eliminating the

negative-spacing title/subtitle overlap

  • Title downgraded from FontSizeLg/SemiBold to FontSizeMd/Medium

to reduce visual weight in the command bar

  • Subtitle font size reduced to ThemeFontSizeXsSm for better hierarchy

PluginFooter.axaml:

  • Removed the Windows XP-era 1×12px Border vertical separator between

primary and secondary stat sections

  • Replaced with a modern "·" mid-dot separator (·) consistent

with the FilesView footer pattern

PrivStackTheme.axaml:

  • Added global Button.view-toggle, Button.view-toggle:pointerover, and

Button.view-toggle.active styles so plugin views using the view-toggle

class work without needing a ViewToggleGroup wrapper

  • Active state: ThemePrimaryMutedBrush background + ThemePrimaryBrush

foreground + SemiBold weight

minor Desktop Shell

Modernize design system to material-inspired indigo palette (v1.36.0)

Desktop 1.35.0 → 1.36.0 | 4db55012
Details

Overhaul the default Dark and Light themes plus core component styles to bring the

visual language in line with modern 2024-era desktop UI conventions (Linear, Craft,

Arc, Material 3). The previous design used a neon cyan primary (#00D4FF) and sharp

nav-item indicators that read as 2018-era SaaS. This commit replaces them

systematically across every touch point that the token system covers.

Color system (Dark theme):

  • Primary accent: cyan #00D4FF → indigo #6366F1. The new hue is softer, premium,

and works equally well on dark and light surfaces without the "tech-startup neon"

connotation.

  • Background surfaces shifted: #0A0A10 → #0F0F14, surface #141420 → #16161E,

elevated #1E1E2C → #21212C. The steps are now perceptibly distinct, giving the

depth hierarchy real visual weight instead of near-identical near-blacks.

  • Navigation sidebar given its own explicit dark token set (#0E0E16 bg) rather than

aliasing the standard surface color, creating a clear light/dark split between

sidebar and content even in dark mode.

  • Secondary accent: #8B5CF6 → #A78BFA (lighter, better contrast on the new surfaces).
  • Semantic colors refreshed: success → #34D399 (vibrant emerald), warning →

#FBB32F (amber), info → #60A5FA (sky), danger → #F87171 (rose). All softer

and more readable than the previous Tailwind 500-level values on dark bg.

  • Hover/selected/pressed states carry a subtle indigo tint (#1D1D2C / #201E3A)

instead of the cyan-tinted #1A2A35 that was previously selected state.

  • Text primary: pure white → #EBEBF0 (slightly warm, reduces harshness on dark).

Color system (Light theme):

  • Primary: #0099CC → #4F46E5. Consistent indigo family, darker shade for

sufficient contrast on white/near-white backgrounds.

  • Surfaces and borders carry a subtle violet tint (#F0F0F6 bg, #E8E8F2 border-subtle)

that ties the light theme to the same design language as dark.

  • Hover/selected states: #E0E2E8 / #D0E8F0 → #E2E2F0 / #D4D0F8 (indigo-tinted

instead of the previous cyan-tinted selection blue).

  • Nav (both themes): unified to #111118 / #636380 / #1A1A2A for hover — consistent

dark sidebar regardless of light/dark content theme.

Component styles (PrivStackTheme.axaml):

  • Button.accent, Button.danger, Button.success: corner radius ThemeRadiusSm (6px) →

ThemeRadiusLg (12px). On a 32px tall button this produces a clearly rounded shape

without being a full pill — exactly what MD3 specifies for filled buttons.

  • Foreground on accent/danger/success buttons changed to ThemeTextOnAccentBrush

(#FFFFFF) rather than ThemeBackgroundBrush. This is semantically correct: the

background token can be near-black on dark themes, but text-on-accent should always

be white for legibility.

  • Border.badge CornerRadius: hardcoded 10 → ThemeRadiusFull. Tags and badges are

now true pills, consistent with every modern design system.

  • ProgressBar MinHeight: 4 → 6px; CornerRadius 2 → 3. The extra 2px makes the

bar visually present without being heavy, and matches typical Material 3 density.

Navigation sidebar (NavigationSidebar.axaml):

  • Active item indicator: removed the 3px left border + asymmetric CornerRadius hack

(0,6,6,0) + offset padding (9,10,12,10). Replaced with a filled background pill

using ThemePrimaryMutedBrush (20% alpha indigo). The icon continues to render in

ThemePrimaryBrush (solid indigo) and text stays ThemeNavTextHoverBrush (white/near-

white), giving a clear active indication without the visual noise of a left stripe.

  • Same change applied to Button.nav-item-collapsed.active for the collapsed sidebar

state, so the icon-only view is consistent.

  • The pill treatment matches the Linear / Arc / Craft navigation pattern that

users associate with modern, well-designed desktop software.

Version: 1.35.0 → 1.36.0 (minor — new visual feature, no API/data changes)

February 18, 2026
minor Desktop Shell

Redesign setup wizard — auth first, cloud workspace selection (v1.35.0)

Desktop 1.34.2 → 1.35.0 | 888ecb5f
Details

Reorder the first-run setup wizard so authentication (License step)

happens before workspace creation. This enables users who already have

a cloud workspace from another device (e.g., Android) to connect to it

during initial setup instead of always creating a new empty workspace.

New flow: Welcome → License → Workspace → DataDirectory → [CloudWorkspaces] → Password → EmergencyKit → Complete

Key changes:

SetupStep enum reordered: License now comes after Welcome (position 2)

instead of after DataDirectory (position 4). CloudWorkspaces is a new

conditional step shown when the user selects PrivStack Cloud and has

existing cloud workspaces.

TrialResponse DTO extended with access_token, refresh_token, user_id,

and cloud_config fields to receive auth tokens from the server's trial

verification endpoint.

ListCloudWorkspacesAsync added to PrivStackApiClient — a direct HTTP

GET /api/cloud/workspaces call that works before FFI initialization,

needing only an access token.

Both auth flows (OAuth sign-in and trial verification) now capture

cloud sync tokens (CloudSyncAccessToken, CloudSyncRefreshToken,

CloudSyncConfigJson, CloudSyncUserId) and set IsCloudSyncAvailable

when cloud_config is present.

DataDirectory step gains a PrivStack Cloud option (visible when

authenticated). When selected, the wizard fetches cloud workspaces

via the API client and either shows the CloudWorkspaces picker step

(if existing workspaces are found) or falls through to create a new

cloud workspace automatically.

InitializeServiceAndContinue updated: after runtime initialization,

if PrivStack Cloud is selected, it calls Configure + AuthenticateWithTokens

on the ICloudSyncService, then either connects to the selected existing

cloud workspace or registers a new one, and persists the CloudWorkspaceId

+ SyncTier on the workspace record.

ICloudSyncService injected into the SetupWizardViewModel constructor.

AXAML rewritten to match the new step order with the License step

content block before Workspace, a new PrivStack Cloud card in the

DataDirectory options, and a new CloudWorkspaces step with workspace

list + "Create New Workspace" option.

minor CoreDesktop ShellSDK

Add alter_column_type mutation across Rust, FFI, and SDK (v1.12.0, SDK v1.39.0)

SDK 1.38.3 → 1.39.0 | Core 1.11.1 → 1.12.0 | 0df6ebe6
Details

Add ALTER COLUMN SET DATA TYPE support for datasets. The Rust store validates

the target type against a whitelist of known DuckDB types, executes the DDL,

and refreshes column metadata. The FFI layer exposes the operation as

privstack_dataset_alter_column_type returning PrivStackError. The SDK adds

AlterColumnTypeAsync to IDatasetService, with P/Invoke binding and service

implementation following the existing DropColumn/RenameColumn pattern. This

enables the Data plugin to let users change column types after import via

a confirmation overlay.

← Prev Page 12 of 22 Next →

Get notified about new releases