Changelog

All notable changes to Blue Synergy are listed here. Looking for the user-friendly highlights? See Releases. The app uses automatic updates — you’ll be notified when a new version is available.

[Unreleased]

[0.7.49] - 2026-05-14

Added

Clips

  • Recent-clip cache size is now configurable in config.toml — the in-memory cache that backs the workspace table (previously hard-coded to 5000 most-recent clips + all pinned) reads from clips.recent_cache_size in config.toml. Default 5000 unchanged; valid range is 100..50000 (out-of-range values clamp to the default with a log warning). Higher = older clips also navigable in the table without a search; lower = leaner RAM footprint. Requires a restart to apply since the cache is loaded once at startup. Eliminates the previous parallel-constant footgun in the frontend — the TS store now asks the backend for whatever the cache holds instead of guessing 5000.
  • Workspace status bar surfaces cache-vs-DB ratio — when the database has more non-deleted clips than the in-memory cache can hold (typically after 5000+ captures with the default cache size), the footer now reads DB: <loaded> / <total> loaded instead of just DB: <n> total. Hover for a tooltip explaining the cache window and pointing to the Filter bar for full-DB search. Hidden when cache holds everything — no visual noise for users with <5000 clips.
  • Right-click context menu in the clip preview editor — the CodeMirror preview now has a full Blue Synergy-styled right-click menu instead of an empty/native one. Sections: Create-clip-from-selection (lifts the selection into a new clip in the same folder, title taken from the first ~40 chars of the selection); Search / Filter (Filter lines containing… / NOT containing…, Find next, Search all clips for…); Tag / Trigger (Add as tag — creates the tag if it doesn’t already exist; Use as trigger keyword / expansion — opens the trigger dialog pre-seeded); Smart-Detect runs at menu-open time on selections under 50 KB and surfaces context-aware entries — Open URL in browser when the selection is a single bare URL, Format as JSON / XML when the selection parses, Parse as CSV when the selection has a comma-rectangle (opens a table-preview modal with Copy as TSV); Transform submenu (lower / UPPER / Title case, Trim, URL-encode / -decode, Base64-encode / -decode, sort ascending / descending / reverse / dedupe — each scoped to selection or whole doc); System (Copy / Cut / Paste / Select All via document.execCommand) plus Open Find / Open Line Filter when no selection. IMG clips get a tailored menu (Copy file path / Open in default app / Show in Explorer / Copy image). Read-only contexts (archived-folder clips, locked secure clips, diff-view, DPAPI peek-mode) hide mutating actions; the format-preview modal disables Replace selection with a tooltip in those states. Diff-view distinguishes the left (original) pane from the right (edited) pane — the left side shows only Copy / Find / Search. The Locked-secure-clip path inside DPAPI peek mode gets a Lock clip again action that clears the peek override.
  • Live selection-stats footer below the clip preview — a thin status strip beneath the editor surfaces Lines / Words / Chars / Bytes for the active selection, updated on every mouseup / keyup. Hidden when nothing is selected or when the clip is IMG. Visually matches .pv-statusbar. Helps you tell at a glance how big a block you’ve picked before triggering a transform, or whether the selection straddles more lines than you expected.
  • Import a text file as a new clip — File → Import → Clip from File… — the Clips workspace gained a native file-picker entry that ingests a single text file as a new clip. The clip lands in the currently active folder (or All Clips if no folder is selected), is auto-selected and scrolled into view, and the file’s basename becomes the clip title. Known code extensions (json, xml, yaml, toml, md, py, rs, ts, …) classify the clip as CODE so syntax highlighting kicks in; anything else lands as TXT. MVP scope: single file, UTF-8 expected, 1 MB cap — binary and oversized files reject with a status message. Drag-and-drop, multi-file selection, image import, and encoding detection are tracked in the Kanban as follow-ups.
  • Mark-for-Compare — diff clips across folders without losing the marker — the existing 2-clip Compare path (Ctrl+Click two clips → Ctrl+D) only worked while both selected clips were visible in the current filter; switching folders dropped the first clip’s highlight and the diff button silently disabled. The new flow keeps the marker visible regardless of filter. Right-click any text clip → Mark for Compare pins it (visible as a ⚖ icon in a new table column, plus a ⚖ Comparing from #N cell in the bottom status bar that doubles as an unmark-click target). Navigate to any other folder / All Clips / search result, right-click a different clip → Compare with marked (#N) — the diff viewer opens with the marked clip on the left and the right-clicked clip on the right. Right-clicking the same clip again shows Unmark for Compare. Marker is session-only (resets on app restart). IMG and masked clips are skipped from the menu entries. If the marked clip is deleted or trashed while marked, the marker auto-clears so “Compare with marked” never points at a vanished clip. Implements option (a) from the 2026-05-11 brainstorm — git-stash mental model, minimal state, single visual marker rather than a sticky-multi-select hack.

Fixed

Core

  • App startup no longer races the WebView — DevTools “state not managed” cascade fixed — opening Blue Synergy on a populated database produced a chain of state not managed for field <X> on command <Y> errors in the WebView’s DevTools console (config / get_config, clipManager / get_recent_clips, tagManager / get_tag_definitions, folderManager / get_folders, groupManager / get_groups), plus visible follow-on symptoms: the diff feature stopped working and the folders tree showed up empty until the user switched to another tab and back. Root cause: in the setup callback of lib.rs, app.manage() for these five states ran AFTER run_startup_cleanup — and Tauri v2 dispatches IPC commands on a separate runtime, so any frontend call fired during the cleanup pass (which can take ~100 ms on a populated database) hit unmanaged state. The five “critical-path” states are now .manage()‘d immediately after construction, BEFORE the slow cleanup pass; subsequent code that needs them (cleanup, retention engine, window sizing, OCR auto-detect) reads through app.state::<T>() instead of the local owned values. The remaining managers (trigger engine, capture manager, retention engine, vault ring) stay where they were because they are not in the frontend’s mount-time IPC critical path.

Clips

  • Captures copies from Microsoft Word, PowerPoint and other OLE-only Office sources — these apps publish clipboard content exclusively via the OLE IDataObject interface; the classic Win32 clipboard receives only two stub markers (DataObject, Object Descriptor) with no CF_UNICODETEXT / Rich Text Format / HTML Format. The listener used to bail through correctly (no text, no DIB, no HDROP → nothing to capture), so Word copies silently produced no clip. The listener now detects the OLE-only signature (every classic format on the clipboard is a known OLE stub) and falls back to OleGetClipboard()IDataObject to extract the real payload: plain text (UTF-16), Rich Text Format, HTML Format with Office wrapper, and bitmap (CF_DIB → PNG-on-disk for the “Word table copied as image” case). The extracted data flows through the same insert / retention / DPAPI paths as classic-clipboard clips, so paste-back into Notepad gets plain text, paste-back into Word gets HTML/RTF with formatting preserved, etc. OleInitialize runs once at clipboard-listener thread startup; if it fails the classic path keeps working and only the OLE fallback is silently disabled. OleGetClipboard is retried 4× at 30 ms intervals when the source app still holds the clipboard exclusively (matches the classic-clipboard retry strategy), and the fallback gate was relaxed so formatted Word tables (which publish OLE stubs alongside classic HTML/RTF) also reach the extractor instead of falling through to a half-working classic path. RTF and HTML bytes are passed through byte-exact — the previous lossy UTF-8 decoder corrupted the HTML Format byte-offset header (StartHTML / EndHTML / StartFragment / EndFragment), which made round-trips into Excel paste as plain text.
  • Paste, 📋 Copy, group-paste sequence and trigger flows now re-publish stored rich formats — capturing from Word / Outlook / browsers stores HTML Format, Rich Text Format and similar payloads in clip_formats, but every clipboard-write path used to publish only CF_UNICODETEXT, so pasting back into Word / Excel / Outlook lost the formatting. A shared write_text_with_formats helper now opens the clipboard once, writes CF_UNICODETEXT as the baseline, then RegisterClipboardFormatW-resolves each stored format name and publishes it alongside; per-format failures are logged but non-fatal so the plain-text baseline always lands. All four flows route through it: paste_clip (workspace paste / Ctrl+V), copy_clip_to_clipboard (workspace 📋 button — copies-without-pasting for a follow-up manual Ctrl+V), paste_group_sequence (group multi-paste — per-clip format lookup, skipped when the per-group transform or append-separator has mutated the text), and the trigger system (ActionType::CLIP plus the seeded {clip:X}-only TXT triggers ;cliplast, ;clipnr, ,-1c,-5c glue — mixed templates like Pre {clip:last} post stay on the plain-paste path since rich formats wouldn’t fit the surrounding text). The CF_UNICODETEXT / CF_TEXT / CF_DIB baselines and OLE-stub markers are filtered out so we never re-publish formats the target wouldn’t read or BS uses for internal bookkeeping. paste_clip_ref (trigger CLIP-action / TXT-shortcut) also gained vault-ring decryption so secure clips inserted via {clip:N} now reach the target as plaintext instead of an empty string.
  • Group-paste sequence inter-clip delay raised from 100 ms to 300 ms — pasting a 5+ clip group into Word / Excel with rich formats used to drop some clips entirely: the clipboard was flipped to the next clip before the target app had committed the previous paste, so Ctrl+V landed on the new clip. 300 ms covers slow renderers (Word with large tables, Excel with HTML cell-range paste); a configurable per-group / global override is on the Kanban as a follow-up. Plain-text groups feel marginally slower but no clips get dropped.
  • Preview statusbar wraps cleanly when the pane is narrow — the bottom statusbar for text and image clips used a fixed 20 px height and no flex-wrap, so when the preview pane was squeezed (split view, low-DPI screen) labels like Size: 1920 x 1080 or Editor 110% would overflow horizontally and clip mid-character at the right edge. The strip now grows downward (min-height + flex-wrap) and each segment is a white-space: nowrap cluster, so labels reflow as whole units instead of breaking mid-word.

[0.7.48] - 2026-05-11

Added

Clips

  • Duplicate Clip — right-click → Duplicate, or Ctrl+Shift+D on a selected clip — folder-association in Blue Synergy is 1:1 (one folder_id per clip), so without a Duplicate action you couldn’t keep the same content in two folders. The new entry copies the clip’s content + most metadata (tags, source_app, pinned, exclude_retention, is_masked / mask_mode, plus all rich-format payloads in clip_formats), resets uses to 0 and stamps a fresh created_at, appends " (copy)" to the title, and overwrites source_title with "Duplicate of #NNNNNN" so the metadata reflects how the row came to exist (manual duplicate) rather than carrying the original capture’s window title forward, and lands the duplicate in the same folder as the source. For image clips the file path is shared with the original — BS’s image-delete dedup logic refcounts so neither side breaks when the other is deleted. Multi-select right-click → Duplicate N clips duplicates each in place. The shortcut is Ctrl+Shift+D (dedicated — Ctrl+D stays the way it was, dispatching to compare-diff or diff-to-original depending on selection state). Secure (DPAPI / AES) clips are refused for v1 — duplicating encrypted payloads needs a vault-membership design pass; a follow-up Kanban entry will cover it. Read-only folder rules are asymmetric: duplicating out of an archived folder is allowed (read-only blocks mutation of the archived row, but the duplicate is a new row landing elsewhere), duplicating into one is blocked through the existing folder_in_read_only_subtree guard.

Fixed

Clips

  • Glue concatenates clips in click order, not display order — gluing N selected clips used to join their content in the order the clips appeared in the table (sorted DESC by nr, so newest first), regardless of the order in which the user picked them. Two places were the culprit: glueSelectedNrs derived its list from Array.from(multiSelectedNrs) (a Set whose iteration order can come from display-ordered reconstruction, not click order), and ClipsTable.handleContextMenu rebuilt its selection via props.clips.filter(c => selectedNrs().has(c.nr)) (display order). Both paths now consume the orderedSelection array that the table already maintained for multi-paste — same source of truth, so glue and paste agree on order. The right-click → Glue path in ClipContextMenu also iterates props.nrs directly instead of filtering the global clip store.
  • Tree filter self-heals when its target folder or group is deleted — deleting the folder (or group) you were currently viewing left the clips list stuck on a folder:42 / group:7 filter that resolved to nothing, so the workspace looked empty even though clips existed. A small effect tracks each folder/group’s (parent, sort_order, name) while the workspace is open; when the active filter points at an id that disappears from the store, the filter jumps to the visually-above sibling (same parent, immediately before in the tree’s (sort_order, name) render order — matching the backend’s ORDER BY sort_order, name). When the deleted entry was the first of its siblings the filter falls back to the parent folder; top-level deletions without a prior sibling fall back to All Clips. Group deletions follow the same pattern within the containing folder. Matches the file-manager convention “selection lands on the entry right above the one you just deleted”.
  • Glue result inherits the active folder — gluing several clips together from inside a folder used to drop the resulting clip in All Clips with folder_id = NULL, so the user had to manually move it back. The result now lands in the same folder the user is mentally “in”: (a) when invoked from the workspace toolbar / hotkey, it follows the active tree filter (treeFilter() === "folder:N"N); (b) when invoked from the right-click context menu, it lands in the folder all source clips share, or in All Clips if they’re scattered across folders. The merge_clips Tauri command gains an optional target_folder_id parameter; after insert_clip it calls move_clip_to_folder so the move goes through the existing read-only-folder guard rails.
  • Group clip-count badges in the tree update immediately after Add / Remove / Reorder — dragging a clip onto a group in the sidebar (and the right-click → Add to group, Remove from group, group reordering paths) used to leave the count badge stale until something else forced a refresh. Group membership lives in a separate group_clips join table that doesn’t touch the clips table, so the previous re-fetch trigger (clipsState.clips.length) never noticed. Added a groupMembershipVersion signal that the count effect listens to; the three mutation entry points (addClipsToGroup, removeClipsFromGroup, reorderGroupClips) are now exported from stores/groups.store.ts as wrapped versions that bump the version after the Tauri call. All 7 call sites in the workspace, tree, preview, context menu and group-picker switched to the wrapped imports — the raw versions in lib/tauri-commands.ts are kept for the wrappers themselves but marked “do not import directly from UI”.

Triggers

  • Tags column in the triggers list is now sortable — clicking the Tags header used to be a no-op while every other column reordered the list. The column had no sortable: true flag, even though the same column in the clips list already sorted. Sort key is the tags joined alphabetically (["foo", "bar"]"foo,bar"), so the order matches what a reader would expect when scanning the visible pills left-to-right.

[0.7.47] - 2026-05-10

Changed

Clips

  • Move-to-Folder and Add-to-Group context-menu actions now open a modal picker — the previous flat-submenu approach grew unusable once you had more than ~10 folders / sub-folders: the submenu ran off-screen, deeper levels became unreachable, and there was no scroll, no search, and no way to find a specific entry without eyeballing the list. Both actions now open a 420×~70vh modal with a search field at the top, a “Recent” section showing the three most-recently-created folders / groups, and a tree-aware list below with full ancestor paths visible while searching. The picker is keyboard-first: type to filter (matches against the joined ancestor path so kunde finds Arbeit › Kunde A), Up / Down to navigate the visible list, Enter to confirm, Esc to cancel. Add-to-Group’s picker also lets you create a new group inline by typing a name that doesn’t match any existing group — replaces the legacy “+ Group selected clips…” inline form. The “current” folder / group gets a subtle badge so you don’t accidentally move a clip to where it already lives. “Remove from folder” is now the last row of the folder picker (only when at least one selected clip is in a folder) — same surface, fewer detours. The context-menu entries themselves stay as hover submenus showing the top 5 most-recently-created folders / groups for quick access; a “More …” row at the bottom opens the modal picker for everything else. Sub-folder rows in the picker use a centered SVG corner-arrow marker (replaces the raw glyph) and a blue info callout at the bottom explains the single-folder semantic and points users to the Folder column for placement at a glance.

UI

  • Sharper text rendering on Windows — the UI font now uses Segoe UI as the primary face (with IBM Plex Sans as fallback), and the monospace font used in clip previews now starts with Cascadia Mono (Microsoft’s Windows-Terminal default, ships with Windows 10 1903+/Win11) before falling back to Consolas and IBM Plex Mono. Both fonts are pixel-hinted for typical Windows scaling factors, so small UI text and ß / German umlauts in clip previews look noticeably crisper than the previous Plex-first stack. The <body> rule also gained text-rendering: geometricPrecision and font-feature-settings: "kern" 1, "liga" 1 to enable kerning and standard ligatures consistently across themes. Future enhancement: a Settings toggle to enable programming-style ligatures (e.g. Cascadia Code or Fira Code) — tracked separately on the Kanban.

Overlay

  • Default Quick Overlay shortcut is now Ctrl+Alt+Space (was Ctrl+Space). Ctrl+Space collides with the autocomplete shortcut in every major coding tool — VS Code, Cursor, JetBrains, Visual Studio, Sublime, Vim — so devs lost autocomplete the moment they installed Blue Synergy and had to rebind manually before getting any work done. Existing users keep whatever they already configured (the migration only fills in fresh installs); only fresh config.toml files pick up the new default. Web docs (Quick Start, Reference, Settings, Keyboard-Shortcuts) updated to match.

Security

  • Auto-peek for DPAPI clips is now on by default — selecting a DPAPI-secured clip in the clips list now decrypts and shows the content in the preview pane automatically (Windows handles the credential transparently — no password prompt). Previously the toggle defaulted to off, so users had to click an explicit “Click to peek” affordance even though the underlying auth required no input. This aligns the default with how DPAPI is treated everywhere else in the app — transparent auth means transparent UX. Existing users who explicitly toggled the setting off in Settings → Security keep their preference (only fresh config.toml files missing the auto_peek_dpapi field pick up the new default).

Fixed

Settings

  • Maintenance modal closes with Esc — the Settings → Maintenance modal had no keydown handler, so Esc did nothing and you had to click the X-button or outside the modal. Esc now closes it like every other dialog. Implemented as a createEffect in MainWindow.tsx that installs a window.keydown listener while the modal is open and removes it on close (same pattern as UpdateCheck.tsx).

Core

  • Autostart plugin disabled in dev builds — the autostart plugin (tauri-plugin-autostart) writes the running binary’s path into HKCU\Software\Microsoft\Windows\CurrentVersion\Run when toggled on. In tauri dev this would record the worktree’s target/debug/blue-synergy.exe path; if the worktree was later deleted or rebuilt, the next Windows login tried to launch a non-existent binary (or worse, accidentally launched a stale dev build instead of the installed release). The plugin is now gated behind #[cfg(not(debug_assertions))] so it’s only registered in release builds. The “Start with Windows” toggle in Settings → General and the Welcome-Screen onboarding nudge both detect the missing plugin (the isEnabled() call rejects), disable themselves, and show an explanatory tooltip.

Security

  • Wrong recovery password keeps the input focused — entering an incorrect master password in the unlock dialog (overlay or workspace) used to drop focus from the password field while the submit was in flight (disabled={busy()} toggled), and the field stayed focus-less even after the error rendered. Users had to click back into the input before retrying. After a failed unlock the dialog now refocuses + select-alls the password input so the next attempt is one keystroke away.

Overlay

  • DPAPI clips no longer trigger the master-password dialog from the Quick Overlay — pressing Enter or Ctrl+Enter on a DPAPI-secured clip in the overlay used to open the UnlockSecureDialog whenever the vault session was inactive (e.g. before any AES clip had been used in the current session). DPAPI doesn’t need a vault session — the Rust path decrypt_clip_content → decrypt_dpapi succeeds directly via the Windows user’s credentials. The pre-hide gate in activateItem now only requires session_active = true for AES-256 clips; DPAPI clips fall through to the normal paste/copy flow which decrypts transparently. The F3 expand path (already correctly mode-gated) and the Clips-workspace F3 / Ctrl+Enter paths (also correct) are unchanged. Note: the broader Phase D consolidation card in the Backlog ([clips] Phase D — Vault-State-Machine konsolidieren) remains valuable — this is a targeted fix for the user-reported overlay symptom; the systematic refactor of the 4-6 unlock call-sites stays open.

Core

  • Backup-reminder dialog now actually appears for new installs — the prompt’s gate required prompt_enabled = true AND a non-empty destination, but both defaulted to the disabled state. Fresh installs accumulated clipboard history for weeks without ever seeing the reminder, so a crash / disk failure / migration mishap meant total data loss. Two-prong fix: (1) Variant A — sensible defaults: prompt_enabled flips to true by default and the gate falls back to <config-dir>/backups when destination is empty (the dir is created on demand by Config::config_dir()). The Settings → Maintenance hint “Set a destination folder for the reminder to appear” is replaced with “Backups will go to the default folder until you pick a custom destination” so the UI matches the new behaviour. Existing users who explicitly disabled the prompt keep their saved value because serde reads the persisted field. (2) Variant C — force-show safety net: a new usage_started_at timestamp is anchored on first launch; after force_show_backup_after_days days (default 14) of usage with prompt_enabled = false AND prompt_last_prompted_at empty, the prompt fires once anyway. Catches users on stuck-disabled state from before the fix who never went through Settings. The dialog’s Don’t-ask-again path sets prompt_last_prompted_at and silences the safety net thereafter. Touches: src-tauri/src/core/config.rs (defaults + new fields), src-tauri/src/core/commands.rs (get_backup_prompt_status gate rewrite + effective_backup_destination helper), src-tauri/src/lib.rs (seed usage_started_at on first start), src/settings/MaintenancePage.tsx (hint text).

Triggers

  • Global trigger settings now actually propagate to new triggers — when you created a new trigger, the form pre-filled the per-trigger “Typing Mode” override with the current global default (paste from [triggers].typing_mode). The save then wrote that value into the trigger row, so later changes in Settings → Triggers were silently ignored — the trigger had a frozen copy of whatever the global was at creation time. Same bug shape in the TOML import / export path: missing typing_mode defaulted to "paste" instead of “inherit”, and on export "paste" was treated as a magic value to skip while every other value was written. Both surfaces now treat empty string as “inherit global setting” — new triggers ship with the per-trigger override unset (the dropdown shows “Default (use global setting)” out of the gate), and TOML round-trips preserve the inherit semantic instead of baking the export-time global into the file. Note: existing triggers in the database still carry their frozen values; open the trigger editor and switch the Mode dropdowns back to “Default” to make them inherit, or wait for the planned migration in a future release.
  • Keyword-erase reliable inside Citrix / Teams / RDP / VMware Horizon / Royal TS — trigger keywords like ,.üt used to leave a residue (,.übermittelter Text instead of just übermittelter Text) when fired inside virtual-desktop hosts. The host’s low-level keyboard hook drops events from a single batched SendInput call before they reach the remote session, so the Backspace × N (or Shift+Left × N + Delete) erase landed only partially. Blue Synergy now detects the foreground EXE (wfica32, Receiver, CDViewer, concentr, Teams, ms-teams, mstsc, vmware-view, Royalt) and switches the erase routine into per-keystroke mode with a 10ms delay between events. Configurable via triggers.erase_inter_key_delay_ms_remote (default 10) — set to 0 to disable, raise for slower remote pipes. Outside remote sessions the erase remains a single batched SendInput (no latency added). Covers all three call sites: keyboard-fire (typing the keyword in the target window), mouse-fire (firing from the Quick Overlay), and undo (Backspace within the undo-window to restore the keyword). Per-trigger erase_method overrides keep precedence over the auto-detect, so existing trigger configs stay honoured.

[0.7.46] - 2026-05-09

Added

Clips

  • Line filter bar in the clip preview (Ctrl+L) — slide-out filter bar at the bottom of the preview pane shows only matching lines while it’s active; the underlying clip is untouched until you Apply. Pattern input supports plain text with * wildcards (test*, *test*, *test) by default; toggle to full regex via the .* button. Aa flips case-sensitivity. The = / button inverts keep-matching (vim g! style — keep lines that do NOT match). Matches inside the kept lines are inline-highlighted (accent background) so it’s obvious at a glance which substring made the line pass; in inverted mode the highlight stays off because every visible line is non-matching by definition. Opening the bar pre-fills the pattern from the most relevant source: a non-empty editor selection wins (multi-line selections collapse to the first line); otherwise an active CM search query is handed off (so a Ctrl+F → "Error" → Ctrl+L workflow opens the filter with Error already typed, and the search panel closes); the input is select-all’d so typing immediately replaces the pre-fill — same convention as Ctrl+F in browsers and VS Code. A Presets ▾ dropdown ships six built-ins that write their regex into the input and switch mode to Regex so the expression is visible and editable: Comments (^\s*(#|//|--|;|<!--)), Bullet Points (^\s*[-•*]\s), Markdown Headings (^#{1,6}\s), Numbered Steps (^\s*(?:[-•*]\s+)?\d+[.)]\s — top-level and bullet-prefixed numbered items, e.g. - 1. nested step), TODOs (\b(TODO|FIXME|XXX|HACK)\b), and URLs (https?://\S+). The Apply split-button writes the filtered content back to the clip (Replace, recoverable via Revert to Original) or creates a fresh clip with the filtered subset (Save As New, also reachable via Shift+Apply or Shift+Enter). A live <n> / <total> count helps you sanity-check the filter before committing. Esc closes the bar from anywhere on the preview side and restores the editor cursor to where it was before the bar opened. The clip preview’s tool row also gains two new buttons: 🔍 Find (opens the editor’s search panel; equivalent to Ctrl+F) and ⌗ Filter (opens / closes the line filter bar; equivalent to Ctrl+L, with active state when the bar is showing). The bar is hidden for image and locked clips. Phase 2 (line-marker system) and Phase 3 (trigger-token filter) stay open in the Backlog card.
  • Ctrl+Shift+V — image clipboard → path shadow [TEMPORARY BRIDGE] — explicit interim solution; will be replaced by direct Ctrl+V interception once the global-hook + per-app-profile design lands (“CMD-Paste Image direkt” Backlog card). Until then: after making a screenshot press Ctrl+Shift+V from anywhere; Blue Synergy decodes the bitmap from the clipboard, saves it as PNG into the captures folder, and writes the quoted file path back to the clipboard as CF_UNICODETEXT while keeping CF_DIB available for image-aware apps. The next Ctrl+V in a console (CMD / PowerShell / Windows Terminal / Claude Code in Terminal / Cursor / Codex CLI) pastes the path; Ctrl+V in Word, browsers, Photoshop etc. still pastes the bitmap. Two keystrokes instead of three (no Quick Overlay detour). Hotkey is hardcoded for now — both binding and direct-Ctrl+V interception ship together with the App-Profiles sprint, at which point this entry should be marked deprecated.

Editor (shared)

  • Ctrl+G now opens Go-to-Line in every CodeMirror editor — was a redundant alias for “find next” via the default keymap (which fell through to opening the search panel when no query was active, duplicating Ctrl+F). The override binds Ctrl+G to CM’s gotoLine command so you can jump straight to a typed line number; F3 / Shift+F3 still navigate find-next/prev when a search is active.

Fixed

Clips

  • Diff-to-Original block-merge no longer collapses both sides — clicking the merge arrow on a hunk in Diff-to-Original mode used to write the merged content into both the live clip and the synthetic original snapshot (they share the same nr), making both diff sides identical and the diff render empty. The synthetic original is now tagged with __syntheticOriginal: true and the merge handler skips it, so only the right-side live clip absorbs the merge while the left snapshot stays put and the diff continues to render.
  • TreeView no longer jumps to the top on folder-create or folder-switch — the existing preserveScrollOnItemClick only matched .ti and .sh-icon-chip mousedowns, so clicking the header action + New folder and the late loadClips() rebuild wave both clamped scrollTop back to 0. Selector now also catches .sh-action, and a new createEffect(on(props.sections, ...)) listener replays the last saved scrollTop after every section rebuild — covers async clip-reload, tag-change, and app-list refresh too.
  • Triggers search results no longer inherit usage bias from the upstream tree filter — typing in the trigger search bar previously preserved whatever order the most-used tree filter (or any other) was producing, which floated frequently-fired triggers above more relevant fresh matches. With a non-empty query, results are now scored by match position (keyword match > description match > extra-keyword match; lower indexOf wins; alphabetical tiebreak) and the order is independent of usage count.
  • Preview pane reserves a minimum visible width for the clips list on resize — earlier the preview was capped at 70% of the workspace dimension, which was enough on a wide monitor but on a narrow window the remaining 30% was eaten by the tree sidebar and the clips list visually disappeared. Two-rule clamp now: the soft 70% cap is still there, AND the preview must leave at least 260 px for the clips list (200 px in the stacked lc layout) plus 12 px splitter margin. The smaller cap wins, so when you shrink the window the preview yields its size first and the clips list stays recognisably present. Same clamp drives the persisted-size restore on mount, every window resize, the arrow-button reopen path, the Ctrl+←/→ resize keymap, and the splitter drag handler — all five paths share computeMaxPreviewSize().
  • Console-driven image paste no longer leaks the file-path text into the next paste elsewhere — when you pasted an IMG clip into CMD / PowerShell / Windows Terminal, Blue Synergy wrote both CF_DIB (bitmap) and CF_UNICODETEXT (quoted path) so the console could pick the text. The text format stayed on the clipboard afterwards, so the next Ctrl+V in a browser chat (web Copilot, ChatGPT) or any text-leaning input surprised users by pasting the file path instead of the image. Two paths are covered now: (1) BS-driven IMG paste (paste_image_with_console_fallback — Ctrl+Enter on an IMG clip, the trigger {clip:N} expansion etc.) re-writes the clipboard with bitmap only ~300 ms after the simulated Ctrl+V so the console has consumed the text first; (2) the temporary Ctrl+Shift+V “image-to-path” hotkey watches the foreground after the dual-format write — the moment the user moves off the console the strip fires (polled every 150 ms; 5 s timeout fallback for the corner case where the foreground stays on a console). Same listener-pause guard covers both strip-writes.
  • Folders self-heal from a startup-race empty result — on first launch the folder tree was sometimes empty even though folders existed in the database; tab-switching to Triggers and back made them appear. The folders.store was caching loaded: true after a first call that returned [] because the backend FolderManager hadn’t finished its initial load yet. The store now (a) only marks loaded when the result is non-empty so subsequent calls retry until the backend is ready, and (b) coalesces concurrent calls from the four onMount sites (ClipsTree / ClipsPreview / ClipsWorkspace / ClipContextMenu) into a single backend fetch via an in-flight promise guard.

Overlay

  • Smart Filters (virtual folders) hidden from *folder= autocomplete — typing *folder= in the overlay listed every folder including Smart Filters, but selecting a Smart Filter silently returned zero clips because the overlay’s filter-resolution doesn’t evaluate the underlying query. The autocomplete now only lists static folders, so users no longer see entries that look selectable but go nowhere. The broader question of whether Smart Filters should be reachable from the overlay at all (and how — dedicated *smart= token, inline marker + query evaluation, or a separate surface) is parked as a brainstorm-needed Backlog card.

Triggers

  • Multi-select context-menu actions no longer drop the anchor row — selecting trigger A, then Ctrl+Click trigger B, then right-click → “Mark Obsolete All” used to act on {B} only and silently leave A out (the visual showed both rows highlighted, so the dropped row was invisible to the user — explained the “some don’t get selected” reports). The Ctrl+Click handler now folds the existing single-select anchor into the multi-set on the first transition, the menu’s “use multi” gate loosens from multi.size > 1 to multi.size > 0, and DataTable applies both .sel + .sel-multi when a row is both anchor and inside the range so the visual matches the action set. Same fold-anchor rule covers the Ctrl+drag path.

Removed

Editor (shared)

  • Ctrl+L is no longer bound to the lowercase text transform — Ctrl+L is now owned by the clips line filter bar (and conventionally also by browser address-bar focus). The other transform shortcuts (Ctrl+U upper, Ctrl+T title, Ctrl+J join) stay; lowercase remains reachable via the toolbar aa button.

[0.7.45] - 2026-05-07

Added

Clips

  • Image-clip paste into consoles inserts the file path — pasting an image clip (Ctrl+Enter or Enter in the Quick Overlay, or via a {clip:N} reference in a trigger) into CMD, PowerShell, Windows Terminal, or Git-Bash / mintty (Cygwin / MSYS) now inserts the on-disk PNG path as a double-quoted string instead of silently doing nothing. Detection is automatic — Blue Synergy reads the foreground window’s class name, and when it’s a console host the paste switches to text mode. Image-aware apps (Word, Notepad++, Photoshop, browsers, the captures editor) still get the actual image because all clipboard formats are written together: CF_DIB + the custom PNG format + CF_UNICODETEXT (the latter only added when the foreground is a console). The console picks the text, the image-aware app picks the image. Same behaviour applies to selecting a Capture from the overlay (Ctrl+Enter for paste, Enter for copy-only).
  • Lost-on-disk image clips self-heal on paste — if the captures folder was cleaned up by hand and an old image clip’s PNG is missing, pasting that clip now rebuilds the PNG from the bitmap data still kept in the clip’s stored formats (clip_formats.CF_DIB blob). The path the clip points to is updated in the database, so the next paste is a normal warm-path paste with no rebuild needed. Handles V4 / V5 / BI_BITFIELDS / palette DIB headers correctly via the existing dib_pixel_offset helper, so images from Word, Excel, Chromium-based apps round-trip too.

Overlay

  • *folder= filter works in the Quick Overlay (was workspace-only) — typing *folder=Prompts in the Find bar narrows results to clips inside that folder and every sub-folder beneath it. Both the canonical separator and ASCII > are accepted, so *folder="Arbeit › Kunde A" and *folder="Arbeit > Kunde A" resolve identically. The * autocomplete dropdown also lists the new fields (folder, archived, protected, exclude_retention) and serves dynamic folder paths so users can pick a sub-folder by full path instead of guessing whether two folders share a leaf name.
  • Trigger fast-path expanded — keyword and action body — typing buch now jumps not only triggers whose keyword starts with buch (existing behaviour, score 50_000) but also triggers whose action body’s first real word is buch after stripping leading symbols/emoji. So a trigger that pastes ✅ → buch ist i.o is found by the natural query buch. The keyword check itself also strips leading punctuation so ;buch matches buch without falling to the slow path.
  • Smart-Backspace, two-stage Esc, scrollable suggestion list — Backspace at the end of a complete *field="value" token removes the whole token in one keystroke (was character-by-character). Esc with text in the Find bar clears the query first and only closes the overlay on a second Esc. The * dropdown now scrolls past the visible 6-row window via mouse-wheel and arrow-keys, with the selected row scrolled into view automatically.
  • debug_overlay_search_scores Tauri command — read-only DevTools diagnostic that returns a per-clip score breakdown (content_score, title_score, uses_boost, pin_boost, prefix_bonus, curation_boost, total_score, age_days). Used to investigate ranking before/after the formula change; useful for any future ranking audit. Invoke from DevTools console: await __TAURI_INTERNALS__.invoke("debug_overlay_search_scores", { query: "…", limit: 30 }).

Core

  • Autostart: launch Blue Synergy at Windows login — new toggle in Settings → General → “Start with Windows” wires up tauri-plugin-autostart. When enabled, Windows starts Blue Synergy at sign-in with a --minimized flag; the app initializes the tray + clipboard listener + hotkeys but skips showing the main window — open it later via the tray icon, the Main Window hotkey, or the Quick Overlay. Setting state is read live from the Windows registry (HKCU\…\Run) via the plugin’s isEnabled(), not mirrored in config.toml, so external toggles (e.g. via Task Manager → Startup) never drift from what the UI shows. The single-instance handler ignores second-launches that also carry --minimized so a duplicate autostart event cannot pop the window. The Backup-prompt welcome-screen also exposes the autostart toggle as a recommendation under the existing setup-decisions (“Start Blue Synergy with Windows — recommended, starts in the tray”) so first-run users discover it without needing to dig into Settings; the toggle persists immediately so the choice sticks even if they “Skip” the backup. macOS / Linux paths are wired through the same plugin (LaunchAgent / .desktop) for forward-compatibility, but BS itself is Windows-only for v1.

Fixed

Triggers

  • {clip:N} referencing an image clip now quotes the path — a trigger that resolved to an image clip used to paste the bare on-disk path (e.g. C:\Users\me\My Captures\foo.png), which broke in shells the moment a path segment had a space. The path is now wrapped in double quotes for IMG clips so the same trigger works in CMD / Git-Bash / etc. without manual quoting. TXT and other text content types pass through unchanged.

Overlay

  • Search ranking — relevant matches no longer buried under stale frequently-pasted clips — the original symptom was a fresh --resume <uuid> clip ranking below an older happy --resume "X" that had been pasted dozens of times, even though the fresh clip’s content actually started with the query. The formula now boosts true prefix matches (after stripping leading symbols/emoji) by a fixed amount large enough to dominate the use-count multiplier, lifts user-curated clips (edited / titled / tagged / foldered / exclude-retention) over ad-hoc clipboard noise, and breaks score ties in favour of the newer clip. Net: the result you reach for is at the top.
  • *folder="A > B" no longer breaks parsing — the operator-detection in the filter parser used to scan past the field name and pick up any > or < inside a quoted value, mangling *folder="A > B" into a malformed >-operator filter. Fixed by anchoring the operator search to the end of the field name; >=, <=, >, <, = are detected only immediately after the field name.
  • *folder=Prompts Prompt was sent to the backend as r=Prompts Prompt — a backtracking quirk in the frontend regex that strips incomplete *field tokens would, on a complete *folder=value token, fail at the full field, back off one character, succeed, and strip the partial *folde from the query. The remaining r=value then fuzzy-matched any clip with r = in it (terminal commands, dev-tool snippets), pushing the actual folder content out of view. Regex re-anchored to require whitespace or end-of-string after the field name, so a complete filter is never partially matched.
  • *folder=Prompts Prompt now means folder + free textfolder_name no longer auto-absorbs continuation words, so *folder=Prompts Prompt parses as folder filter Prompts plus free-text Prompt, the natural shape for “narrow this folder by free text”. Multi-word folder names need explicit quotes (*folder="Demo Prompts"), and the autocomplete adds the quotes for you when you pick a multi-word value.
  • Suggestion dropdown stays out of the way during Backspace — rapid deletion no longer flickers the dropdown on every keystroke; suppression releases the moment you type a non-deletion character. Search itself debounces 200 ms while shrinking (vs 80 ms when typing) so the result list doesn’t churn through each intermediate query.

[0.7.44] - 2026-05-04

Added

Captures

  • OCR Selection: cursor-follow over monitors (matches Region Capture) — starting an OCR capture on one monitor and moving the cursor to another no longer left the selection overlay stranded on the original screen. start_ocr_capture now spawns the same cursor-follow polling thread that start_region_capture has used since v0.7.42 (PR #142): every 50 ms it reads GetCursorPos, and when the cursor crosses to a different monitor it re-captures that monitor, repositions the capture-selector window, and emits region-monitor-changed (the frontend already listens for that event in OCR mode). First mousedown locks via freeze_cursor_follow. Initial region_state.{monitor_name, scale} are now also populated up front so the loop’s “still on same monitor” check works on the very first poll instead of triggering a redundant re-capture. The existing region-capture path is unchanged.
  • Resize the thumbnail strip and the thumbs scale with it (both layouts) — dragging the horizontal resize-h handle in Layout A/B used to make the strip taller without growing the cells. Layout C had no resize handle at all. Both fixed: ThumbnailStrip accepts stripSize and orientation props; cell width/height are written inline from a Solid memo (after several CSS-var and aspect-ratio attempts proved unreliable in this Solid + Tauri WebView2 stack — percentage heights and CSS custom properties did not propagate cleanly, and aspect-ratio on a flex item suppressed align-items: stretch). Layout C also gets a new resize-v handle wired to a stripWidth signal. Both stripHeight and stripWidth persist via localStorage. The .cstrip height/width is also set inline because CSS height: 100% shrunk to the cells’ min-content size instead of resolving to the wrapper’s explicit height.
  • Vertical thumbnail strip uses axis-correct arrow keys — Layout C inherited the horizontal mapping (←/→ navigate, ↓ enter group, ↑ exit), which was disorienting because pressing ← / → moved the visual selection up / down and pressing ↓ jumped into a burst group instead of down to the next capture. ThumbnailStrip now takes an orientation prop and remaps: in vertical mode ↑/↓ navigate captures, → enters a burst group, ← exits. Enter still drills into a group regardless of orientation. Horizontal mode (Layout A/B) is unchanged.
  • Mouse-wheel over the thumbnail strip cycles through captures — wheeling on the strip used to scroll the cell list (often a dead-end gesture: you still had to click to actually select something). The strip now consumes wheel events and walks prev / next through captures, honouring expanded burst-group context like the arrow keys. Ctrl+Wheel is intentionally not intercepted so the app-level UI-zoom router still owns it. The selection auto-scrolls into view via the existing scroll-to-selected effect.

Changed

Captures

  • Region/OCR selector badges fade out of the way — the Drag to select… hint bar (top-center) and the OCR badge (top-left) used to sit at full opacity over whatever they covered, which was annoying when the text you wanted to capture was right under them. Both now render at 55 % opacity by default so screen content shows through, and fade fully to 0 (transition: opacity 120ms ease-out) when the cursor enters the top 60 px of the screen so they’re completely out of the way. Returns on cursor down again. pointer-events: none is preserved so the change is purely visual.

Fixed

Captures

  • Canvas Size: live preview of the new canvas extent before Apply — when the Image Size popover or ribbon is set to Canvas Size mode and W/H differ from the current image, the canvas display now extends to the bounding box of image ∪ new-canvas and a dashed accent-blue rectangle marks the new canvas extent. The image stays at its anchor-derived position, so picking anchor=top-left grows the rectangle to the right and down, anchor=bottom-right grows up and left, anchor=center grows in all directions, etc. Lets the user see exactly where the new padding will appear before committing.
  • Crop tool: explicit Reset button + Shift+C clears all preset values — no single gesture used to clear the persisted crop preset state (W, H, X/Y offset via cropRegion, anchor, aspect ratio, lock). Users had to empty each input by hand or restart the editor. Added a “Reset” button to the Image Size popover footer next to “Apply” / “Repeat last” that clears everything in one click; Shift+C does the same from the canvas (was previously only clearing W and H). The full reset returns to defaults: W=null, H=null, anchor=top-left, ratio=free, lock=off, cropRegion=null.
  • Crop tool: changing W or H resizes the placed rectangle around the active anchor — typing a new W/H in the popover or ribbon while a crop region was already on the canvas previously only updated the underlying signal — the rectangle stayed pinned at its old top-left and ignored the new size. The active anchor (top-left, center, bottom-right…) was effectively “top-left always” once a rect existed. Added a createEffect that fires on W/H/anchor changes: it pins the active anchor’s image-space position from the old rectangle, then recomputes the new top-left so the same anchor point lands on the same pixel after the resize. Result: with anchor=center, growing H from 10 to 30 expands the rectangle 10 px up and 10 px down; with anchor=bottom-right, the rectangle grows up-and-to-the-left so its bottom-right corner stays put. Clamped to image bounds. Also: a freehand drag now syncs imageSizeW/H to the dragged dimensions so the popover and ribbon inputs reflect the actual rect size — without that sync, opening the popover after a drag and editing W would jump the rect to the old (pre-drag) constraint size.
  • Crop tool: arrow-key nudge for the placed rectangle — once a crop region is committed, ←/→/↑/↓ shifts it by 1 px (Shift+Arrow = 10 px, Ctrl+Arrow = 50 px). Movement is clamped to image bounds so the rect cannot escape the canvas. Mirrors the X/Y axis fine-tune contract from Region Capture’s selector overlay (region_keys.x_axis_mode / y_axis_mode). Bypassed when the user is typing in an input or has an annotation selected, so editor Delete / arrow-resize on annotations stays unaffected.
  • Crop tool: position chip in the ribbon + Offset X/Y in the Image Size popover — once a crop region is placed, a compact X, Y chip appears next to the W×H inputs showing the rectangle’s image-space position. Clicking the chip jumps into the Image Size popover, which now has an Offset section with X/Y number inputs (read-write) under the Crop tab. The cropRegion signal was lifted from EditorCanvas-local state into image-size-store so the ribbon, the popover, and the canvas all read/write the same source without prop-drilling.
  • Crop tool: hover-preview for fixed-size mode — when the crop tool is active and a W×H constraint is set, the canvas now renders a faint dashed rectangle at the cursor position so you can see exactly where a click would drop the fixed-size rect. Updates on mousemove, hidden during an active drag, hidden once a crop region is committed. Bonus dim outside the preview so it stays readable on busy thumbnails. Solves the “type W×H, then I have no idea where the rectangle will land before clicking” gap that came up after the drag-override fix exposed the click-place flow as a real first-class option.
  • Crop tool: drag always works, even when a fixed Crop Size is set — once the user had typed values into the Crop Size W×H inputs (or applied a “Crop Size 1920×1080”-style preset), pressing C and dragging on the canvas did nothing visible. The crop tool’s onMouseDown short-circuited into a fixed-size-place branch (single-click drops a fixed-size rectangle, drag was ignored). Both clicks and drags now share the same start path; on mouseup the handler picks the mode based on user intent — drag ≥ 5 px in image space → freehand crop region from the dragged box, drag < 5 px → place the fixed-size rectangle at the click point using the active anchor. Constraint values stay set for the next action so users who want the fixed-size click-place flow get it on the next click.
  • Empty Crop Size inputs now actually clear the constraint — typing into the W or H inputs (in the ribbon and in the Image Size popover) and selecting → backspace to delete the value left the underlying signal unchanged. Root cause: parseInt("") returns NaN, the early-return in onInput / onWChange fired before setImageSizeW(null) ran, so the signal kept its previous value while the input visually showed empty. All four input handlers (ribbon W, ribbon H, popover W, popover H) now treat an empty trimmed string as “clear” → setImageSizeW(null) / setImageSizeH(null).

[0.7.43] - 2026-05-03

Added

Captures

  • Cursor-follow region overlay (multi-monitor) — start a region capture on one monitor, move the cursor to another monitor, and the selection overlay teleports to the new screen so you can capture there. The first mousedown locks the overlay to its current monitor for the rest of the selection. Works for 2, 3, or more displays, and across monitors with different DPI scales (e.g. 100% + 125%). Implemented as a 50 ms polling thread that watches GetCursorPos while no mousedown has happened; emits a region-monitor-changed event the frontend uses to resize the canvas buffer for the new monitor’s resolution. The previous-monitor’s saved region (used by SHIFT+R / R) is intentionally cleared on cross-monitor moves — saved coordinates are not meaningful on a different monitor.

Changed

Shared

  • About dialog footer shows full publisher name “Ivorinox Blue” — the credits line at the bottom of the About dialog now reads © 2026 Ivorinox Blue · Windows Productivity Tool instead of just Ivorinox, matching the official publisher name used in the installer and Investor materials.

Fixed

Clips

  • Locked-clip preview now explains how to peek instead of just showing dots — selecting a is_secure clip used to render the preview as •••••••• in the editor with no indication of how to reveal the content. Replaced with a centered notice that names the lock mode (Windows DPAPI / AES-256), tells the user F3 to peek, and — for DPAPI specifically — hints that auto-peek is off and points to Settings → Security if the user wants always-visible content while their Windows session is active. AES branch additionally surfaces “vault must be unlocked first” when the vault session is locked, removing a small dead-end where users would press F3 and see nothing happen.
  • Locking the vault now hides revealed DPAPI clips too, not just AES — when an AES-256 clip was peeked open (F3 or auto-peek) and the user locked the vault, the plaintext correctly disappeared. DPAPI peeks stayed visible because they technically do not need the vault session (DPAPI is bound to the Windows user, not to the vault key). UX-wise this contradicted the lock-icon promise — clicking “Lock vault” is a deliberate “hide what I just revealed” gesture and should apply to both modes. The vault-status listener in ClipsWorkspace.tsx now clears the entire peekOverrides map on lock instead of filtering by secure_mode === "aes256". Auto-peek-DPAPI is unchanged: re-selecting a clip after lock will re-decrypt if the user has that setting enabled, which is the deliberate opt-in.
  • KeePass passwords no longer briefly visible as plaintext in the clip list — when a Lock-DPAPI retention rule matched a freshly captured clip (e.g. a password copied from KeePass), the clipboard-monitor used to first INSERT the row with the plaintext content, then run a follow-up encrypt-and-UPDATE pass. Between the two steps the password was visible in the UI and present as plaintext in the on-disk SQLite file. PR #143 fixed the storage-format part (raw blob → hex), this closes the timing window itself: when a Lock-DPAPI rule matches at capture time, the content is encrypted before the row is written. New ClipManager::insert_clip_atomic_dpapi performs a single INSERT with is_secure=1, secure_mode='dpapi', secure_content=<hex>, content='••••••••'. The clipboard-changed event sends the already-locked clip to the frontend so the UI never displays the plaintext, and the raw OS-format blobs in clip_formats (which would otherwise duplicate the secret) are skipped on this path. AES-256 retention rules keep their existing flow because they need a vault key the capture thread may not have access to — tracked separately as a high-prio card.
  • Auto-locked DPAPI clips were unreadable after restart (KeePass / retention rule scenario) — when a retention rule auto-encrypted a freshly captured clip (e.g. KeePass password, Lock-DPAPI rule), the auto-lock path wrote secure_content as a raw byte BLOB. The read-back path expects a hex-encoded TEXT column and crashes with Invalid column type Blob at index:1, expected String, leaving the clip showing as locked but empty. The clipboard-monitor auto-lock path now matches the manual lock_clip and apply-to-existing paths and hex_encodes the encrypted bytes before writing. Existing rows that were corrupted by older builds are self-healed on startup: any is_secure=1 row whose secure_content storage type is BLOB is re-stored as lower(hex(secure_content)) so subsequent reads decrypt correctly. The heal check is idempotent — already-healed rows are skipped via SQLite’s typeof() filter.

Core

  • Backup reminder now reaches users who finished the Welcome screen — the reminder dialog was effectively unreachable until the user manually went into Settings → Maintenance and toggled “Show backup reminder” on. Root cause: complete_first_run (commands.rs) only persisted the chosen destination but left prompt_enabled at the false default, while the gate in run_startup_cleanup requires prompt_enabled && !destination.is_empty() plus an interval check before showing the dialog. On startup the app now detects the broken-state pattern (first_run_completed=true + prompt_enabled=false + prompt_last_prompted_at="") and self-heals: flips prompt_enabled on, fills destination with <config_dir>/backups if empty, and leaves prompt_last_prompted_at empty so the gate fires this same startup. Users who already dismissed the dialog have a non-empty prompt_last_prompted_at (set by dismiss_backup_prompt) and are not re-engaged — that timestamp is the discriminator between “never seen the dialog” and “actively chose to skip”.

Captures

  • “Load more” in the captures strip actually loads more — clicking the N / total · Load more chip incremented the frontend’s captureLimit from 200 → 400 and re-fetched, but get_captures() in storage.rs returned cache.iter().take(limit) from the hot-tier cache only — and that cache is hardcoded to the 200 most recent rows at startup. Asking for 400 still returned the same 200, the array got replaced with same-id-but-new-proxy items (visible as a brief EditorCanvas flicker via <Show keyed> on the meta line), counter stayed at 200 / 1976, no new thumbnails appeared. Added a slow-path branch: when limit > cache.len(), query the DB directly with the same WHERE deleted_at IS NULL ORDER BY id DESC LIMIT ? clause. The cache stays bounded by design — this is an opt-in extension at the call site, not a cache bump.
  • Captures category switching feels noticeably snappier with many captures — switching between Tree categories (All / Recent / Session / Trash) felt sluggish proportional to capture count: 153 captures in All was clearly slower than 20 in Recent, 15 in Trash was instant. Root cause in ThumbnailStrip.tsx: thumbnailToDataUrl() re-encoded every JPEG thumbnail to base64 (Array.from(uint8).map(String.fromCharCode).join('') + btoa(...)) on every render of every cell — 153 captures = 153 encodings per filter switch, plus the local function shadowed an identical export from capture-commands.ts. Added a module-level Map<id, dataUrl> cache; thumbnails are immutable once created on the backend, so capture id is a stable key. Cache is evicted in the permanent-delete handler (soft-delete keeps entries because the capture moves to trash and may need to render there). A second optimization (caching the groupedItems wrapper objects so <For> reuses DOM rows) was tried and reverted — under Solid store reconciliation it caused Load-more clicks to look like nothing happened (proxy refs survived the reload, cache returned stale wrappers, <For> skipped the diff).
  • Right-click → Delete on a thumbnail no longer freezes the app — two-part fix: (1) handleDelete now closes the menu before opening the confirm dialog, so the menu’s full-viewport backdrop (z-index 999, inset 0) no longer sits on top of the dialog and swallows clicks; (2) the editor preview meta line was reading selectedCapture()!.id from inside a plain && short-circuit, which let inner reactive scopes evaluate the bang-asserted access after the memo flipped to undefined (window between setCapturesState("captures", filter) and props.onSelect(nextFocus) in the delete path) — the resulting uncaught TypeError: Cannot read properties of undefined (reading 'id') aborted the render and the app appeared dead. Switched to <Show keyed> so the captured value is non-null inside and the whole subtree mounts/unmounts atomically.
  • Region Capture SHIFT+R repeat lines up with the saved region on 125%/150% DPI — pressing SHIFT+R inside the region selector overlay reused the previously captured rectangle but cropped a 1.5625× shifted area on 125% Windows display scaling (worse on 150%). Same root-cause family as the v0.7.42 finish_region_capture fix: RegionSelector.tsx was re-multiplying the saved physical-pixel coordinates by devicePixelRatio before applying the selection — _savedRegion* are already physical pixels (canvas-coord-system) because canvas.width = innerWidth × dpr. Removed the redundant multiplication on the SHIFT+R path, the R ghost-load path, and the ghost-rectangle render. Pre-existing — visible at any UI zoom != 100%, surfaced after testing at 125% DPI.

Triggers

  • Used Count refreshes after keystroke/keyword fire — the Used Count column in the Triggers table only updated on full app reload; firing a trigger by typing its keyword incremented the value in the backend but the table kept showing the old number. The backend now emits a triggers://uses-updated event after every fire (keystroke, manual, test), and the Triggers workspace reloads (debounced 500 ms to coalesce keystroke bursts) so the column tracks reality.

CI

  • Release workflow shaves 30-60 s per runcache: 'npm' removed from the actions/setup-node@v4 step in .github/workflows/release.yml. The Post-Setup-Node step packed ~/.npm and uploaded the tarball to GitHub Actions cache on every release run; on the BSDEV01 self-hosted runner the local npm store is faster than the cache upload, so net effect is positive.

[0.7.42] - 2026-04-29

Added

Shared

  • Editor zoom indicator in workspace status bars — when the CodeEditor zoom (Ctrl+Wheel inside an editor, or Ctrl+= / Ctrl+- / Ctrl+0) differs from 100%, an Editor N% cell appears at the right-hand edge of the relevant status bar — Triggers shows it in its own status bar, Clips shows it in the per-clip preview status bar (pv-sb-editor-zoom) for text/code previews. The cell hides at 100%. Captures and Clips image previews already display their respective zoom levels in their built-in toolbars; the levels live next to the content they apply to.
  • Double-click to reset UI zoom to 100% — the Zoom: N% indicator in the main window status bar and the transient qo-zoom-indicator pill in the overlay both respond to double-click by resetting the UI zoom to 100% — quick way out of an accidental drift without hunting for Ctrl+0. Cursor + tooltip make the affordance discoverable.

Fixed

Captures

  • Region Capture cropped the wrong rectangle on 125%/150% DPI displays — at non-100% Windows display scaling, the rectangle drawn in the region selector overlay produced a screenshot that was offset and undersized — clearly off at 125%, more so at 150%. Root cause: the RegionSelector already converts cursor coordinates to physical pixels (its canvas buffer is sized to innerWidth × devicePixelRatio), but finish_region_capture was multiplying those coordinates by the monitor scale a second time. Removed the double conversion; the crop now uses the physical-pixel coords directly. 100% scaling was unaffected (the scale=1.0 multiplication was a no-op there). Pre-existing since v0.7.27 (commit 10611ec).

Shared

  • Ctrl+Wheel zoom — reliable across all hover targets — Ctrl+Wheel routing was state-dependent: at UI zoom != 1.0 it sometimes failed to zoom the UI when hovering thumbnails, and image zoom landed off-target when the cursor sat in the gray padding around a small image in the Captures editor. The router now reads the browser-maintained :hover state instead of computing a viewport coordinate from the OS-level wheel hook, so the choice between UI zoom and image zoom matches what is visually under the cursor at any UI zoom level. Image-zoom consumers (Captures editor, Clips preview) now pivot at a tracked mousemove position, which shares the same coordinate system as getBoundingClientRect() and is therefore body-zoom-correct at every level.
  • Tree scroll no longer pulls the canvas with it — scrolling inside the left-hand tree (Clips, Triggers, Captures) used to leak wheel events to the editor canvas / preview pane via overflow chaining when the tree reached its scroll limit. Adding overscroll-behavior: contain to the tree side panel keeps scrolling contained to the tree.

[0.7.41] - 2026-04-28

Fixed

Shared

  • UI Zoom != 1.0 — cursor coordinates land where you click — at non-100% UI zoom (Settings → UI Zoom), context menus and dropdowns appeared offset from the cursor, and the Captures editor canvas drew at the wrong position relative to the mouse. The 14 menu/popup sites and 3 canvas-coord sites now divide clientX/Y by the active zoom factor (document.body.style.zoom) via a shared zoomCompensateXY helper, so placement is correct at every zoom level.

Captures

  • Right-click context menu on category items — categories in the Captures sidebar (This Session, Recent, With OCR Text) now expose the same Hide-and-Restore right-click menu that Clips already had. Hidden labels persist in localStorage; an eye-icon header action appears once anything is hidden and restores all in one click. All Captures is the un-hideable anchor.
  • Active filter falls back to All Captures when its category gets hidden — hiding the currently-active category (or starting the app with the default This Session filter while it was hidden last session) used to leave the table filtering on an invisible filter. The tree now snaps the active filter to All Captures in both cases.
  • All Captures hoisted to the top of the Categories list — matches the convention already used by All Clips in Clips and All Triggers in Triggers (un-hideable anchor first, contextual filters below).
  • Load-more chip hidden for filtered views — the N / total · Load more chip used to compare the filtered list length against the global database count, so it appeared even on an empty This Session view as 0 / 1976 · Load more and clicking it loaded older captures that still didn’t match the session filter. The chip now appears only on the All Captures view, where bumping the raw cache mathematically translates to more visible rows.

Triggers

  • Import dialog title scrub — header reads Import Triggers instead of Import Triggers from espanso YAML. The dialog has ingested both espanso and Blue Synergy YAML since the Pack System (v0.7.39); the espanso-only label was misleading.

Settings

  • Maintenance page now auto-saves edits — turning Max age or Max count no longer required a manual click on Save before the cleanup preview reflected the new values. Edits flush to the backend after a 250 ms debounce so preview_maintenance_cleanup reads current state on every recalculation.

[0.7.40] - 2026-04-26

Added

Triggers

  • Trigger Forms — interactive prompt window that pops up before a trigger fires, asking you to fill in fields. Two ways to use:
    • Inline syntax inside a TXT trigger body — {name?Label|default} renders a text field; variants: {date?Label|default|DD.MM.YYYY} (date picker), {time?Label||HH:mm} (time picker), {pick?Label||clip:latest} (dropdown sourced from clips/script/file). The first inline placeholder of each name produces one form field; subsequent uses substitute the same value.
    • YAML form_block: in the editor’s Form tab for richer schemas — multiple typed fields (text, multiline, dropdown, date, time), per-field defaults, dropdown sources (static, clip:N, clip:latest, script:, file:), per-axis window-size override.
    • Cross-field references{field:NAME} inside a default or label resolves another field’s current value (cycle-safe, chains up to 5 levels deep).
    • Token defaults — field defaults can use template tokens: default: "{clip:5}" pre-fills with clip 5’s content; {date} and {time} work too.
    • Date-type inference — fields named date, dob, *_date, *_at, *_on, date_start, date1, etc. automatically render a date picker even without explicit type: date.
    • Persistence — submitted values and the form-window size are remembered per trigger.
    • Engine integration — the form runs on a dedicated thread so the IPC pool stays responsive; on submit, the focused window is restored before paste so output lands where you started.
  • Form Fields token group in the TXT-trigger toolbar — one-click insertion of {name?…}, {date?…}, {time?…}, {pick?…} snippets.
  • YAML snippet groups in the Form tab — drop-in templates for common form-block patterns.
  • Visual form-trigger marker — triggers with a form get an amber keyword in the Trigger list and the Quick Overlay (with an opt-in left-bar accent), and a Form badge in the workflow editor.
  • TOML round-trip for form_block_yaml — form schemas survive Copy as TOML / Paste TOML in the workflow editor.

Settings

  • Forms section — toggles for the form window’s header X-close button and footer key-hint bar.

Database

  • Schema bumped to 0.7.40 — adds trigger_form_values (per-trigger persisted field values), trigger_form_size (per-trigger window size), and form_block_yaml column on triggers table. Migration 0.7.40_form_block_yaml is split from the form-store tables migration so each ALTER fails independently if a column already exists.

Fixed

Clips

  • Multi-clip Delete no longer pastes the active clip — pressing Enter to confirm a multi-clip delete dialog used to also fire the capture-phase multi-paste handler, dumping the active clip into whatever app had previously been focused. The capture handler now bails out while a confirm dialog is open.
  • Focus survives a delete — after deleting one or more clips, the cursor now lands on the next still-visible row (filtered view aware), scrolls into view, and table focus is restored. Previously the keyboard often ended up on a hidden row or lost focus entirely.
  • Active selected row stays readable on hover — hovering the active .sel row used to override its dark bg with the lighter hover bg while the text stayed locked to white, washing the text into the background. Hover is now suppressed on the selected row.
  • Row hover suppressed during keyboard navigation and multi-select — when extending a selection with Shift+Arrow (or just navigating with arrows), the row the mouse happened to be on no longer lights up and competes with the keyboard cursor. Hover comes back the moment the mouse moves.
  • Export-clips dialog now uses the branded ConfirmDialog — was the OS-native window.confirm(). Same look and keyboard behaviour as every other Blue Synergy dialog.

Triggers

  • Pack-import preview polish — pack metadata chip now spans the full dialog width and the “Source: …” strip is a full-bleed amber band under the chip (no inset card-in-card look).
  • WorkflowEditor renders again on dev reload — a missing invoke import was silently swallowing the get_config call, so the workflow form refused to mount. Restored.

Shared

  • ConfirmDialog Enter confirms — pressing Enter inside a confirm dialog now triggers the primary action (matches BS dialog convention used everywhere else); secondary/cancel buttons still receive Enter when they have focus.
  • ConfirmDialog confirm-button focus is reliable — the dialog now focuses the OK button via setTimeout(0) instead of onMount, which was a silent no-op inside <Show>. You can press Enter immediately after the dialog appears.
  • DataTable ignores keys while a confirm dialog is open — Enter / Delete pressed during a confirm dialog no longer also fires on the underlying selected row (which would have re-triggered the very action being confirmed, or pasted the row into the foreground app).
  • DataTable column minWidth enforced as initial width tootable-layout: fixed ignores min-width, so columns sized below their declared minWidth (e.g. Content) used to render too narrow on first paint.

UI

  • Global scrollbar restored to 11 px wide — a recent change had narrowed it to 7 px, which made the scroll thumb hard to grab on high-DPI displays.

[0.7.39] - 2026-04-26

Added

Clips

  • Protected-clips delete dialog — when a delete touches pinned, archived (own or inherited), or retention-shielded clips, a dialog now lists the breakdown by category, offers per-category [show] deep-links to filter the table, defaults to “Skip protected, delete the other N”, and gates a “Force-delete all anyway” opt-in behind an amber warning checkbox. Pinned and exclude-retention clips are now treated as delete-protected too, mirroring what the retention sweep already enforced.
  • Status-bar protected-clips cell🛡 N indicator (visible when count > 0) with hover-tooltip breakdown by source; click filters the table to all protected clips via *protected=true.
  • Folder column in the clips table — opt-in via the column-chooser (right-click any header). Renders the folder path (Arbeit › Kunde A) right-truncated with full path in tooltip.
  • Folder option for the Quick Overlay last column — Settings → Overlay → Last Column → Folder. Each clip row in the overlay shows its folder path on the right.
  • Search tokens for folder, archive, protection, and virtual title:
    • *folder=<name> — case-insensitive substring match against folder name; supports wildcards (*demo*, demo*) and OR-pipe (A|B).
    • *archive=true|false — clips in (or outside) the read-only-folder subtree.
    • *protected=true|false — union of pinned, exclude_retention, and archive.
    • *exclude_retention=true|false — surfaces in the workspace SQL search (was overlay-only).
    • *title=<X> — matches the displayed title only (explicit title or first non-blank line of content); masked/secure clips never match for privacy.

Triggers

  • Trigger packs from a URL — new File → Import → From URL… lets you paste any HTTPS URL pointing at a Blue Synergy YAML file and import the triggers it contains. Off by default; toggle in Settings → Security → Online Pack Imports. Conservative fetch profile (10 s timeout, 1 MB cap, content-type allow-list, max 3 redirects). When the YAML carries an optional pack: metadata header (name / description / author / author_url), the import preview shows a header chip with a clickable author link plus an amber “External, unverified — only install packs from authors you trust” source-URL strip.

Core

  • File → Import → and File → Export → submenus — Triggers, Clips, and Config (MainWindow) workspaces now share the same submenu pattern. Existing entries (Blue Synergy YAML…, Clips from Folder…, Config…) move under the appropriate parent. Triggers’ YAML entries are renamed to From File… / To File… for the new submenu shape. The previously-standalone top-level Export menu in the Clips workspace is folded under File → Export.

Shared

  • <PromptDialog> shared component — canonical single-input dialog (focus trap, ESC closes, Enter confirms, Blue Synergy theme, optional loading state). Used here for the URL-entry prompt and available for future single-input flows that today re-implement the pattern locally.

Changed

Clips

  • *folder= alias now resolves to the human-readable folder name (was the numeric folder_id — only useful to power users with the database open). Numeric ID searches keep working via *folder_id=.

Settings

  • Security → Online Pack Imports section — new opt-in toggle, positioned just above Advanced. When disabled (the default), triggers_preview_import_yaml_url refuses to fetch and the From URL… menu entry is rendered disabled with a tooltip pointing to the Settings location. Toggling the setting updates the menu state within a second — no restart needed.

Fixed

Clips

  • Archive-folder protection extended to manual delete — clips in a read-only (archived) folder, pinned clips, and exclude-retention clips can no longer disappear silently from the clips-table delete actions. The new dialog explains why and offers an opt-in bypass.
  • Chip + free-text combo no longer absorbs into the chip value — with a [folder=Geset] pill active, typing Prompt in the search now correctly searches for “Prompt” in the folder, not for a literal folder named “Geset Prompt”. Two-layer fix: backend tokenizer respects already-quoted values; frontend chip-emitter always quotes.
  • Frontend chip alias for folder and archived — pills now display the canonical field name (folder_name) matching backend. Previously the pill said folder_id and could look like the chip wasn’t added.
  • ESC clears chip pills too — works whether the search input or the table has focus, and triggers when only chip pills are active (no free text required).
  • Quick Overlay folder context — clip rows can now display the folder path as the last column (see Added above for the new option).
  • Older clips appear in the table on first launch — the in-memory cache now holds 5 000 most-recent clips (was 500). Long-time users with multi-thousand histories no longer have to copy something new before older entries become searchable.

[0.7.38] - 2026-04-24

Added

Updater

  • “Continue in background” button in the install-phase WPF window — click to dismiss the modal while the install continues silently; app still restarts when ready.

Changed

Updater

  • Rotating Blue Synergy aperture replaces the indeterminate progress bar in the install-phase window. 6-blade logo spinning at 2 s / rotation; 400×180 footprint.

Fixed

Clips

  • Content column no longer collapses to 0 after a hide/show window cycle; minimum width bumped from 160 → 280 px so previews get readable room by default.
  • Secure-clip titles surface in the Quick Overlay — F2-renamed secure clips now show their title instead of the masked ●●● placeholder.

Overlay

  • Filter tab order reacts immediately to config changes — rearranging filters in Settings no longer requires an app restart; overlay re-cycles within 1-3 s.
  • Timeline colorized badges toggle with Ctrl+Shift+B alongside the main-table and overlay views (previously only the latter two picked up the toggle).

Triggers

  • YAML-paste parse errors are visible — pasting malformed trigger YAML now surfaces the parser error in an alert instead of silently swallowing the paste.

Removed

Core

  • Redundant 0.7.21_trigger_trash migration — the ALTER TABLE triggers ADD COLUMN deleted_at statement was a duplicate of a column already added by 0.7.19_trigger_columns. Silently swallowed by the runner as a “duplicate column” error, so this is dead-code cleanup. Existing installs keep their schema_version stamp (harmless).

[0.7.37] - 2026-04-24

Changed

Updater

  • Maintenance release — validates the v0.7.36 install-phase improvements (WPF progress window + single spinner) end-to-end: the outgoing v0.7.36 relay now runs these during a real update. No user-facing code changes beyond the version stamp.

[0.7.36] - 2026-04-23

Added

Triggers

  • {time|date|datetime:in:<offset>} — natural-language time arithmetic. New token family that answers “what’s the time in 2 hours?” or “what’s the date next week?”. Units: m (minutes), h (hours), d (days), w (weeks). Negative offsets look into the past. Default for h strips minutes to :00 (so {time:in:2h} at 19:02 gives 21:00); prefix + preserves them ({time:in:+2h}21:02). Examples: {date:in:2d}, {date:in:1w}, {datetime:in:2d}.
  • {time|date|datetime:was:<offset>} — past-direction alias. Same grammar as :in: but reads naturally for the past ({time:was:2h} = “2 hours ago”). Paired with :in: in the Date/Time token menu as a separate “Was … (past)” section.
  • Custom format suffix on offset and round tokens. Append :<fmt> to any :in: / :was: / :round: token for a custom output format using the same friendly/strftime rules as {time:FMT}. Examples: {time:in:2h:HHmm}2100, {time:round:15m:up:HHmm}1430, {date:in:2d:YYYYMMDD}20260425.
  • {clip:latest} accepted as alias for {clip:last} — backend-only alias for users who muscle-memory the longer form; both resolve to the most recent clip. Not surfaced in the menu.

Triggers — Token menu

  • {cursor} in the Keys group — the cursor-placement marker is now one click away instead of something you have to type manually.
  • Date/Time menu gains “In … (future)” and “Was … (past)” sections exposing the new offset tokens directly.
  • Clipboard menu expanded{clip:last} (named) plus {clip:-1} through {clip:-5} (relative), so common multi-clip sequences are one click each.
  • Single-line token items — labels and {token} codes render side-by-side on one line (label left, code right, baseline-aligned) so more tokens fit in the same popover height.
  • Sub-section state resets on popover close — next time you open a Date/Time menu, every collapsible section starts collapsed again instead of carrying over the last session’s state.

Updater

  • Install-phase progress window — during the silent update install (the window between “app exits” and “new app launches”), a small WPF window shows a Blue Synergy–branded indeterminate progress bar with “Installing update… App will restart automatically.” It’s rendered by the PowerShell relay process and self-closes when the install completes, so there’s no zombie tray icon risk. Works under RDP/Citrix unlike Windows toast / tray balloon notifications.

Changed

Updater

  • In-app Install spinner — the “Installing update…” line in the dialog now shows one branded ApertureSpinner instead of two rotating glyphs (the Unicode was redundant next to the rotating logo).

Fixed

Triggers

  • {time:round:…} and {date:round:…} now resolve to actual times. These tokens were previously dead code: the generic time:/date: custom-format arm sat before the round arm in the template resolver, so round tokens were swallowed as format strings and rendered as literal text (round:15m:up). The round arm now comes first, and a new integration test exercises the full resolve_template() pipeline so the regression cannot reappear silently.

Updater

  • Installer save path — .exe guardget_installer_info now saves downloads to blue-synergy-setup.exe if the manifest’s download_url path does NOT end in .exe. Without this, a redirect URL whose path does not carry an .exe suffix would save the download under the redirect’s filename and Windows would open the “Select an app to open this file” dialog instead of running the installer. Saves are always .exe-suffixed now regardless of URL shape.
  • Release manifest.json — download_url — reverted to the direct GitHub release asset URL (from a server-side redirect added in 0.7.35). The redirect will be re-enabled later once the server rewrites the delivered path to end in .exe, so the client doesn’t need the 0.7.36 .exe guard to ship updates.

[0.7.35] - 2026-04-23

Added

Updater

  • RELEASE-NOTES.md — a dedicated user-facing release highlights file ships alongside CHANGELOG.md, embedded in the binary for offline display in the Updates dialog.

Changed

Updater

  • Updates dialog — “What’s New” now shows release notes — the top panel leads with warm user-friendly highlights from RELEASE-NOTES.md instead of the raw technical changelog. The full technical changelog stays visible in the Version History panel below.
  • Updates dialog — What’s New / Version History 60/40 split — the two panels now share the changelog area at a true 3:2 ratio regardless of modal size, instead of Version History hitting a fixed 220 px cap while What’s New stayed cramped. Both still shrink gracefully on tiny windows; What’s New keeps a 140 px readable floor.

[0.7.34] - 2026-04-23

Added

Clips

  • Real archive semantics for read-only folders — turning Read-only on a folder now truly protects its contents. Deleting, moving, or removing clips from the folder is blocked with a clear error; archive inherits down the folder tree (subfolders can’t bypass the lock); enabling Read-only auto-exempts the folder from retention so archived clips aren’t silently purged later.
  • Folder context menu — quick toggles — right-click a folder and flip Read-only / Accept-clips / Exclude-retention directly from the menu with live ☑/☐ checkmarks; no more round-tripping through Properties. Mutual-exclusion rules (Read-only off ↔ other toggles) are reflected inline.
  • Alt+letter category shortcuts — Alt+A (All Clips, works globally), plus Alt+T/C/U/I/P/G/E/S inside the Clips tab to jump to Text / Code / URLs / Images / Pinned / Glued / Edited / Secure.
  • Filter menu populated — the previously-empty Filter menu now lists all 10 sidebar categories with active-state checkmark and shortcut text, doubling as a discovery surface for the Alt+letter bindings.
  • Search menu populated — Focus Search Bar (Ctrl+F) + Clear Search (Esc); the latter greys out when the search is already empty.
  • Clips table — protection columns (opt-in) — three 28 px icon columns for 🛡️ excluded-from-retention / 🔒 archived-folder / 🔐 inherited-archive are available via the column chooser. Hidden by default; tooltips in the chooser explain each.
  • Tree indicators — archive state — folders show 🔒 (own archive) or 🔐 (inherited archive) next to their label, matching the clips-table column semantics.

Shared

  • PropertiesDialog — auto-focus + Enter to Save — opens with the first field focused and accepts Enter to commit (textareas still take newlines on plain Enter). Field-level disabled state + cascade patches (Read-only on → Accept-clips off + Exclude-retention on) live in the dialog instead of only on Save.

Fixed

Clips

  • Retention rule with Lock-DPAPI / Lock-AES mode no longer fails with CHECK constraint failed. The retention_rules.mode schema CHECK was never expanded when the lock_dpapi / lock_aes modes were introduced in 0.6.0; creating or saving a rule with either mode would hit the old whitelist and error out. Migration 0.7.34_retention_lock_modes.sql rebuilds the table with the two values added.
  • “Apply to Existing Clips” — Lock-DPAPI / Lock-AES support — the one-shot retention pass triggered from Settings → Security now actually encrypts when the rule’s mode is lock_dpapi or lock_aes. Previously the backend purge_existing_clips only handled delete / truncate and silently skipped lock modes, so users had to wait for the next scheduled run. Source-app matching is also case-insensitive now to mirror the live monitor.
  • ‘All Clips’ right-click no longer opens the WebView’s native menu (Inspect Element / Reload / …) — the entry now silently swallows the right-click.
  • Folder ctx-menu checkmarks update in real time after a quick-toggle, instead of needing the menu to close and reopen.

Clips — Clipboard monitor

  • Phantom clip on fast arrow-key navigation — holding ↑ / ↓ on the clips table or pressing them in rapid succession no longer sneaks a duplicate of the selected clip into the list. The auto-copy-on-select writes used to spawn overlapping 600 ms clipboard-suppression timers; the first timer would expire and re-enable the monitor before later writes’ echo notifications arrived, so those echoes were picked up as external copies. The suppression is now reference-counted and stays active until the last write’s timer drains. Much more likely to trigger under RDP / Citrix because rdpclip.exe adds echo latency.

Updater

  • No more mysterious blue “(i)” icons after an update — the PowerShell relay used a Windows Information tray icon + balloon while it waited for the NSIS installer; under RDP the balloon was silently suppressed but the icon stayed, and the window between NSIS’s post-install app relaunch and the relay’s dispose briefly showed two Blue Synergy tray icons side-by-side. The relay now runs fully silently and the in-app Install button shows an inline “Installing update — Blue Synergy will restart automatically…” spinner for ~2 s before the app exits, so the user stays informed without a stray tray icon.
  • Inner silent installer is now -WindowStyle Hidden so slow WebView2 bootstrapper runs can no longer flash an NSIS splash into the taskbar.

Shared

  • Tree scroll position stays put on item click — selecting a folder / category / tag no longer snaps the tree back to the top, even with UI zoom or Windows DPI scaling ≠ 100 %.
  • Tree arrow-key navigation survives item clicks and async reloads — after clicking a tree item, ↑/↓ keep working without needing to click back in.
  • Tree keyboard focus ring behaves like :focus-visible — shown only after keyboard navigation, hidden after a plain mouse click.
  • Menu-label underline mnemonics removed — the decorative underlines suggested Alt+letter shortcuts that were never wired up. Dropped until real mnemonic handling lands.
  • Protection icons (🛡️ 🔒 🔐) render in colour — explicit emoji-font fallback chain and a variation selector on the shield fix Windows rendering the icons as small monochrome glyphs.

Changed

Clips

  • Folder ctx menu ordering — Read-only (archive) is now the first toggle, above Accept-clips and Exclude-retention; when it’s on, the others auto-disable so leading with it is clearer.

Updater

  • Branded Aperture spinner during install — the generic CSS border-spinner is replaced with the Blue Synergy ApertureSpinner (branded variant, orange-B5 accent) plus a rotating ↻ glyph, matching the StartupOverlay loading visual the user already knows.
  • Updates dialog — “What’s New” panel sizing — on multi-bullet releases the section could collapse to a ~30 px strip when the main window was small (e.g. 800 × 500) because the Version History section claimed its 220 px first. The panel now has a viewport-clamped minimum height, What’s New has a guaranteed 140 px floor, and Version History is allowed to shrink below its cap when space is tight.

Database

  • Migration 0.7.34_retention_lock_modes.sql — expands the retention_rules.mode CHECK constraint to accept 'lock_dpapi' and 'lock_aes' modes that the Rust enum has supported since 0.6.0.

[0.7.33] - 2026-04-21

Added

Triggers — Citrix / RDP Unicode fix

  • Global Send Unicode setting (Settings → Triggers → Send Unicode ▾) with three values:
    • auto (default) — auto-detect Citrix Workspace (wfica32.exe, CDViewer.exe, SelfService.exe), Windows RDP (mstsc.exe, rdpclip.exe), or VMware Horizon (vmware-view.exe, HorizonClient.exe) in the foreground and switch the char-by-char typing path to KEYEVENTF_UNICODE.
    • always — force the UNICODE SendInput path for every char-by-char expansion.
    • never — keep the legacy VkKeyScanW + Shift path.
  • Per-trigger Send Unicode override (Trigger editor → Settings tab → Inherit / Always / Never). Stored in the new trigger.use_unicode_sendinput column (nullable, defaults to inherit). Cascade: per-trigger > global > auto-detection.
  • Surrogate-pair handling: emojis and other Supplementary-Plane characters now type correctly via UNICODE SendInput (two code units per codepoint).
  • Copy as YAML / Export YAML now emit use_unicode_sendinput: "always" (or "never") for triggers with an explicit override. inherit stays out of the output to keep YAML tight.

Fixed

Triggers — Citrix

  • Underscore _ and other Shift-requiring characters no longer drop when char-by-char typing into a Citrix-published app. Root cause: Citrix ICA channels translate VK+Shift events through the remote keyboard layout, so local-DE / remote-EN (or similar) mismatches silently mistranslate or discard the keystrokes. The UNICODE-SendInput path sends the final UTF-16 code unit directly and survives layout translation.

Clips

  • Folder import — title & error-list polishFile → Import Clips from Folder… now uses the filename without extension as the clip title (e.g. notes.mdnotes) and surfaces every failed file in a scrollable result dialog with path + reason instead of swallowing errors silently.
  • Folder import — legacy encodings — ClipMate / Notepad-pre-2019 / any Windows-ANSI export with German umlauts (ä, ö, ü) no longer fails with “stream did not contain valid UTF-8”. The importer now tries UTF-8 (with/without BOM), UTF-16 LE/BE (with BOM), and falls back to Windows-1252 — covers every real-world Windows text file without data loss.

UI / Shared

  • Clips tree — “Create subfolder” / “Create group” — folder context menu now opens the BS PropertiesDialog instead of the raw browser prompt(), matching the theming and keyboard conventions of the rest of the app (same flow as “Create virtual folder” and the tree-header “New folder” button).
  • Clips tree — scroll position — clicking a folder / category / app / tag no longer snaps the tree back to the top. Tree scrollTop is captured on mousedown and restored after Solid’s reactive re-render, even on long folder lists.

Database

  • Migration 0.7.33_unicode_mode.sql — adds use_unicode_sendinput TEXT NULL column to the triggers table.

[0.7.32] - 2026-04-20

Added

Triggers

  • Token-level chain settle — after every keystroke-producing token the engine now waits a small beat (80 ms after paste, 20 ms after a named key like {TAB} or char-by-char type) so the target application has time to process the event before the next token fires. Fixes the race where {TAB}{DELAY:N} started the N-ms wait before the TAB was processed, and Text{TAB} could race-deliver TAB ahead of the Ctrl+V paste. Settle honours abortable_sleep so ESC still cuts through.
  • {SETTLE:N} token — overrides the post-action settle delay for the rest of the step (mirrors {SPEED:N}). {SETTLE:0} disables settle entirely for max throughput; {SETTLE:200} gives laggy web forms more breathing room. Exposed in the Timing token popover under ‘Override settle’.
  • ;localip sample trigger — body ipconfig | findstr IPv4, uses the cmd executor; demonstrates the non-PowerShell executor path.
  • Shipped SCR samples now register the correct per-keyword executor on seed & reseed (;localip → cmd, other SCR → powershell) instead of NULL. The ;ip body is cleaned of its previously baked-in powershell -Command "..." wrapper so the executor template wraps the body properly.
  • File → Load Sample Triggers… now routes through the standard TriggersImportDialog: per-sample checkboxes, existing-keyword conflict detection, unified import / undo pipeline. The former “Reset Sample Triggers (overwrite)…” confirm-modal is removed — the import dialog already handles conflicts.

UI / Shared

  • Global ‘Colorize Badges’ toggle — lifted from the Clips workspace View menu to the main View menu with a Ctrl+Shift+B shortcut, accessible from any tab. Listed under the Core section of the ? help dialog.
  • Cross-window badge sync uses a dedicated badges-toggle Tauri event instead of the HTML storage event, which did not fire reliably between Tauri WebViews — toggling in one window (main or overlay) now propagates immediately to the other.

Core

  • Config-merge on app load — when a user’s config.toml is missing HashMap defaults (currently [triggers.executors] entries powershell + cmd), they are re-written to disk on startup so the user can see and edit them. Detection compares the raw parsed file, not the post-serde struct, because #[serde(default)] silently fills missing sections in memory.

Fixed

Triggers

  • Settings → Steps tab no longer requires a detour through Code: the TOML round-trip only runs when leaving Code view, so clicks on Steps are no-ops from Settings (fast + no stale-TOML parse error).
  • Duplicate-keyword save now shows a BS ConfirmDialog (Keyword "X" already exists…) and keeps the editor open instead of silently closing — previously the UNIQUE-constraint rejection from the backend was swallowed.

Clipboard listener resilience

  • Pre-read retention gate — apps with a Skip retention rule (e.g. Excel) no longer trigger Office’s lazy-render, so the Excel “The picture is too large and will be truncated” dialog never fires for skipped apps.
  • Pre-storage 10 MB image cap — oversized DIBs (Excel / CAD / Photoshop 30-80 MB screenshots) are now skipped BEFORE writing to disk. The user gets a visible toast “Skipped large image from X.EXE — Y MB > 10 MB cap”.
  • OpenClipboard retry loop — 4 attempts with 30 ms backoff recovers from the Office-copy contention race where BS used to miss the clipboard update (text captured “only sometimes”). Warn is only logged after all 4 attempts fail.
  • CF_METAFILEPICT added to the GDI-handle skip list — the documented trigger of Excel’s “picture too large” dialog (same fix Ditto and FastKeys adopted). Also closes a heap-safety gap because CF_METAFILEPICT is GDI-handle-backed, not HGLOBAL.

UI / Shared

  • GlobalMenuBar renders the ✓ checkmark for top-level items with a boolean checked field (was only implemented for submenu items) — the global View menu entry now shows its state correctly.
  • Main window’s top-level menu is now an accessor function so tracked signals re-run when they change (fixes stale checkmark after toggle).
  • ConfirmDialog Cancel button hides when cancelLabel === "" so callers can use it as an OK-only alert dialog without a separate component.

Removed

  • [clips] Duplicate ‘Show Colorized Badges’ entry from the Clips workspace View menu (replaced by the new global View menu entry).

[0.7.31] - 2026-04-19

Added

Triggers

  • YAML import — robust parse chain (handles bare-sequence + plural triggers: array correctly mapping first → keyword, rest → extra_keywords); 4 new unit tests
  • Plural - triggers: paste heuristicCtrl+V recognises both singular - trigger: and plural - triggers: list-item keys
  • Visible Import button in the Triggers toolbar (📥) + File → Import Blue Synergy YAML… menu entry — strict BS-format only with helpful error if espanso YAML is picked
  • Export to filetriggers_export_yaml opens a Save dialog with smart filenames: bs-trigger-<keyword>.yaml for single, bs-triggers-<scope>-<count>-YYYYMMDD.yaml for filter / selection / all
  • Inline edit description in the grid — F2 cycles keyword → description → exit; double-click on description cell opens edit
  • {WAIT:N} token — explicit alias for {DELAY:N} (absolute pause, no inline text variant)
  • {RDELAY:LO-HI} + {RDELAY:LO-HI,"text"} — random pause / random per-char typing speed
  • {RWAIT:LO-HI} — alias for {RDELAY:LO-HI} (paired with WAIT/DELAY naming)
  • {datetime} — full date+time (2026-04-19 17:30:45)
  • {date:FMT} / {time:FMT} / {datetime:FMT} — custom format with friendly tokens (YYYY MM DD HH mm ss) AND/OR chrono strftime (%A %d %B %Y)
  • {time:round:Nm[:up|down]} / {date:round:Nm[:up|down]} — round time to 5/10/15/30/min or 1/2/h granularity, nearest by default or up/down
  • ESC during firing aborts the in-flight workflow (chunked sleeps for ~50 ms responsiveness)
  • Token toolbar restructured as horizontal menu strip with collapsible sub-sections (Keys / Timing / Date-Time / Clipboard) — popover per group, per-step state
  • Tree-item context menu (Categories / App Profiles / Tags) — Export YAML / Delete by filter

Clips

  • Import clips from a folder of text files — File → Import Clips from Folder… and folder right-click Import clips from folder… (imports into the right-clicked folder); recognises 30+ text/code extensions
  • Tree-item context menu (Categories / By App / By Tag) — Export… / Delete all matching… with protected-clips opt-in checkbox; folder right-click also gets Delete all clips in this folder…
  • *source_title=… filter now uses substring match (LIKE %x%) — *source_title=Glue matches Glue (3 Clips) etc.

Captures

  • Crop & Image Size overhaul — unified popover with three tabs (Crop ✂ / Scale ⊡ / Canvas ⬚), 9-point anchor grid on crop selections, Shift-drag constrains crop to source aspect ratio, click-to-place when W × H is preset, select tool can move an existing crop region, and live W × H overlay while dragging.
  • Aspect-ratio presets in the Image Size popover — Original, 1:1, 3:2, 4:3, 16:9, Custom; “Use original size” button on every tab; per-operation Repeat last (Ctrl+Shift+R remembers crop, scale, and canvas separately).
  • Scale operation with Fast (nearest-neighbor) vs Smooth (bilinear) interpolation; Canvas resize with background color picker — transparent option preserves the alpha channel on PNG / GIF / 32-bit BMP output.
  • Photoshop-style foreground / background color widget in the ribbon — overlapping squares, ⇄ swap arrow (X key), reset-to-defaults button (black / white), active-slot ▾ indicator, checkerboard swatch for transparent.
  • 2 × 4 quick-palette of the eight most-used colors next to the FG / BG widget — left-click sets foreground, right-click sets background.
  • Always-visible hex input in the ribbon with native OS color picker square; tabbed full color picker popover (Palette / Hex / RGB / HSL) with live conversion between modes.
  • Rectangle and ellipse tools now accept an optional background color — foreground draws the stroke, background draws the fill; transparent background yields outline-only shapes.
  • Checkerboard pattern behind the editor canvas so transparent pixels (after a canvas resize with transparent background) read as transparent instead of grey.
  • Editor Tools single-key shortcuts: M Select · C Crop · Shift+C Crop + clear W × H · R Rectangle · O Ellipse · L Line · A Arrow · P Pencil · T Text · H Highlight · B Blur · X Swap FG / BG; Enter applies a set crop; Ctrl+Shift+R repeats the last operation.
  • Edit menu gains a Tools submenu with check marks for the active tool and shortcut columns; canvas right-click context menu matches. View menu gains Canvas Full Pane (F11).
  • DPI/physical-resolution crop — region capture preserves full pixel density at 125%/150% Windows scale; multi-monitor mixed-DPI handled correctly via per-capture scale recording
  • Disabled stub buttons in the Advanced capture group (Scrollable / Object / Multi / Freehand) marked (coming soon)

UI / Shared

  • ConfirmDialog gains a styled amber warning slot with optional opt-in checkbox; native window.confirm() calls replaced with the BS dialog where appropriate
  • Filter ID rendered as inline <code> in confirm dialogs (Filter: tag: dev)
  • Editor text zoom — Ctrl+Scroll over a CodeMirror editor enlarges editor font without affecting UI; persisted per-session
  • Cross-window zoom sync — Main ↔ Overlay share localStorage["ui-scale"] + a ui-zoom-changed Tauri event
  • Double-click the Zoom indicator resets to 100 %
  • CodeEditor supports VSCode-style Alt+Shift+↑ / Alt+Shift+↓ to move the current line (or multi-line selection) up and down.

Changed

UI / Shared

  • Edited-state indicator on type badges is now a small red corner dot (4 × 4 px, bottom-left) instead of recolouring the whole badge — type colour stays visible
  • IMG badge colour changed from orange (#c05a00) to terracotta (#a0522d) — no longer clashes with amber-edited look
  • URL badge colour tweaked to cyan (#0e7490) for clearer separation from amber/terracotta neighbours
  • Colorized-badges mode keeps badge colours on selected rows (main table + Quick Overlay) — previously selected rows always reverted to neutral

Fixed

Triggers

  • F2 inside the keyword input now cycles to description (was just committing and exiting)

Clips

  • source_app naming unified to "Blue Synergy" for all internally-generated clips; per-action verb moved to source_title (Glue (3 Clips), Split from #N, Import: foo.txt, New (blank), Captures, OCR). DB migration 0.7.31_source_app_normalize backfills existing rows.
  • Glued smart-filter repaired after the source-naming refactor (now reads source_title.startsWith("Glue"))
  • Pretty filter ID resolves folder/group/vfolder names instead of raw IDs
  • Silenced harmless Clip not found race in auto-copy debounce
  • Image-zoom shortcuts (Ctrl+0 / Ctrl+1 / Ctrl++ / Ctrl+-) restored in the preview panel via capture-phase handler — defence in depth alongside MainWindow’s __bs-img-key routing

Captures

  • Multi-undo chain now cascades correctly: Ctrl+Z unwinds annotations first, then falls through to the last image operation (crop / scale / canvas) when the annotation stack is empty.
  • Pre-crop snapshot is preserved in the annotation store, so navigating away from a cropped capture and back retains the ability to undo the crop.
  • Ctrl+0 / Ctrl+1 / Ctrl++ / Ctrl+- zoom now works even when the cursor is over the ribbon or sidebar — routing falls back to the active tab’s canvas zone.
  • Escape closes the Image Size popover reliably even when another pop-up is open; Tab / Shift+Tab is focus-trapped inside popovers so keyboard navigation no longer leaks out to the ribbon.
  • finish_region_capture scales the RegionSelector’s logical coords to physical pixels using the captured monitor’s DPI factor (recorded at start, not looked up later by name — fixes mixed-DPI multi-monitor case)

UI / Shared

  • Context menus now use the UI font with antialiasing (was rendering ‘hackig’)
  • ExportClipsDialog ESC closes / ENTER triggers OK; clean font rendering
  • Tree-item context menu captures filterId BEFORE closing the menu (was crashing silently when ctx() returned null after close)
  • Empty Test menu placeholder removed from Triggers
  • Zoom rework — kills 115 %/130 % drift on app start (body × html no longer compounds); editor / canvas / image areas zoom independently of UI; keyboard Ctrl+= / Ctrl+0 and Rust ctrl-wheel paths now share state via __bs-ui-zoom

Database

  • Migration 0.7.31_source_app_normalize.sql — normalises legacy Blue Synergy · Glue / Blue Synergy · Split / Folder Import source_app values to Blue Synergy, moves the verb into source_title. Idempotent.

[0.7.30] - 2026-04-17

Added

  • [triggers] CodeMirror 6 editor for TXT and SCR steps — syntax highlighting, token-insert toolbar ({TAB}, {ENTER}, {DELAY:N}, {date}, {clip:-N}, etc.), and inline {variable} accent highlighting.
  • [triggers] Ex-bar (Ctrl+/) — vim-style command input: /pattern highlights inline matches (fade out after 4 s), :%s/from/to/g global substitute, :g/pattern/ list-matching lines, :g!/pattern/d delete non-matching lines. Session history recalled with Up/Down.
  • [triggers] Native find/replace panel (Ctrl+F) — BS-styled two-row layout (inputs + buttons on row 1, checkboxes on row 2); custom BS-style checkboxes; Ctrl+/ swaps back to ex-bar; Tab/Shift+Tab moves focus between Find and Replace fields.
  • [triggers] F3 / Shift+F3 cycles through ex-bar search highlights (next/prev, wraps around); F3 consumed at highest priority to block Tauri native find.
  • [triggers] Right-click context menu on step editors — Find/Replace entry opens ex-bar prefilled with :%s/.

[0.7.29] - 2026-04-17

Added

  • [triggers] Triggers Trash — soft-delete triggers instead of permanent deletion; restore single or multiple triggers from trash; permanently delete from trash; Empty All Trash action.
  • [triggers] Trash tab in Triggers sidebar tree with count badge (“Deleted Triggers” node).
  • [triggers] Triggers included in global Trash window count and TrashStats badges.
  • [triggers] Expired triggers in trash are purged on startup according to the global retention_days setting.

[0.7.28] - 2026-04-16

Added

  • [triggers] Copy as YAML from right-click context menu — right-click any trigger (or multi-selection) in the Triggers table to get “Copy as YAML” directly, in addition to the existing toolbar/menu shortcut.
  • [captures] Session auto-edit — when opening the Captures workspace, if captures were taken earlier in this session, the newest one is automatically selected and the editor tab is opened.
  • [captures] Thumbnail Strip load-more — when there are more captures in the database than the 200 shown in the strip, a “N / total · Load more” button appears at the end of the strip. Clicking it loads 200 additional captures. Works in both horizontal (Layout A/B) and vertical (Layout C) strip modes.

[0.7.27] - 2026-04-16

Added

  • [captures] Right-click context menu on canvas — right-click anywhere on the editor canvas to switch tools (Select, Rectangle, Ellipse, Line, Arrow, Pencil, Text, Highlight, Blur/Redact) and access Undo, Redo, and Delete directly — no need to reach the toolbar.

[0.7.26] - 2026-04-16

Added

  • [clips] F11 full-pane preview — press F11 to expand the preview pane to fill the full Clips workspace (hides list, tree, and toolbar). F11 again or Escape restores the split view.
  • [captures] F11 full-pane canvas — press F11 in the Captures workspace to expand the editor canvas to full screen (hides thumbnail strip and sidebar). F11 again or Escape restores the layout.

[0.7.25] - 2026-04-16

Added

  • [clips] Statusbar monitor toggle — click “Monitoring” in the status bar to pause/resume clipboard monitoring; label changes to “⏸ Paused” while paused.
  • [clips] Statusbar vault toggle — click “🔒/🔓 Vault” in the status bar to lock the vault (when unlocked) or open the unlock dialog (when locked).

Fixed

  • [clips] Preview pane restores last good size on re-expand — collapsing and re-opening the preview pane now restores the last dragged width instead of opening at minimum size.

[0.7.24] - 2026-04-16

Added

  • [overlay] F3 inline preview for IMG/CAP/TRG — pressing F3 on an image clip or capture shows the image thumbnail inline; pressing F3 on a trigger shows its YAML. F3 hint now visible for all previewable types.
  • [overlay/clips] Golden SVG lock badge with D/A letter — secure clips show a blue badge with a golden padlock SVG and a letter: D (DPAPI, always open shackle) or A (AES-256, open when vault unlocked, closed when locked). Applied in overlay, clips table, timeline, and preview pane.
  • [clips] Colorized type badges — new “Show Colorized Badges” toggle in View menu; each content type (TXT/CODE/URL/IMG/CAP/TRG) renders with its own color palette. Persisted in localStorage.
  • [triggers] Created / Deleted columns — column chooser now includes “Created” (relative + absolute on hover) and “Deleted” (trash view only).
  • [triggers] Fire into Window menu items — “Fire into Last Window” (Shift+F5) and “Choose Application…” (F5) added to the Workflow menu; ▶ Test button kept.
  • [core] Open Trash moved to Tools menu — accessible from all workspaces via Tools → Open Trash….
  • [clips] New Clip in File menu — File → New Clip (Ctrl+N) mirrors Triggers pattern.
  • [triggers] trigger_get_yaml command — new Tauri command returns YAML for a single trigger (used by overlay F3 preview).

Fixed

  • [clips] TAB + Enter on delete dialog triggers pastestopPropagation added to dialog keydown handler so Enter on “Delete Permanently” no longer bubbles to the global paste handler.
  • [overlay] F3 on AES clip shows message regardless of vault state — AES clips now silently do nothing when vault is locked; content only decrypts when the vault session is already active.
  • [overlay] +N more count always inflated by trigger countoverlay_search_filtered was capping clips at max internally; triggers were then appended on top, making total_matches always wrong. Truncation now happens once in commands.rs.
  • [overlay] F3 CAP preview shows filename instead of image — CAP items now fetch the thumbnail from SQLite via get_capture_thumbnail_by_id instead of using the filename as a path.
  • [overlay] Overlay footer counter shows total matches, not visible count — footer now shows visible / total so users see how many clips are currently rendered vs. available.
  • [triggers] F5 reloads the Tauri webviewe.preventDefault() added to the F5 keydown handler in TriggersWorkspace so the browser refresh is suppressed.
  • [clips] F3 DPAPI decrypt in ClipsWorkspace — pressing F3 on a selected DPAPI-encrypted clip now toggles a decrypted peek inline; a second F3 hides it.
  • [overlay] secure_mode missing from OverlayItem — DPAPI and AES-256 clips were indistinguishable in the overlay; added secure_mode field to fix badge display and F3 routing.
  • [overlay] AES peek content stays visible after vault locks — clearing AES peekOverrides now happens immediately on vault://updated when session becomes inactive.
  • [clips] Lock badge dynamic open/closed — AES badge shackle now reflects live vault state in clips table, timeline, and preview pane; DPAPI always shows open.

[0.7.23] - 2026-04-15

Fixed

  • [triggers] Ctrl+V paste of BS-exported YAML silently ignored — “Copy as YAML” produces bs_trigger: format; the paste heuristic now recognises it.
  • [triggers] Saving trigger with Default typing mode crashestyping_mode column was NOT NULL; selecting “Default (use global setting)” sent NULL and hit the constraint. Engine now stores "" for Default and reads it back as None.

[0.7.22] - 2026-04-15

Added

  • [triggers] WorkflowEditor 3-tab layout: Steps / Settings / Code — trigger settings (app profile, immediate, typing mode, erase method) moved to a dedicated Settings tab; keyword, extra keywords, and description always visible above the tabs.
  • [triggers] Full-pane editor (F11): F11 expands the trigger editor to fill the full workspace (same pattern as Clips preview pane); F11 again restores the split view.
  • [triggers] Per-trigger typing mode — “Default (use global setting)”: typing mode dropdown now has a “Default” option matching the erase method pattern; trigger inherits the global config typing mode when set to Default.
  • [triggers] Fire into window (Shift+▶ Test): Shift+click on the ▶ Test button opens the window picker to fire the trigger into a specific application window.
  • [triggers] SCR working directory: optional start folder for the script process — set it in the script step controls; the process runs with that directory as its working dir.
  • [triggers] SCR output mode: “Paste output” (default) or “Discard output” dropdown in script step controls — discard suppresses stdout paste entirely.

Fixed

  • [triggers] Fire button behavior: plain click on ▶ Test now opens the window picker; Shift+click fires directly into the last focused window (previously reversed).
  • [triggers] BS window restored after fire-to: the Blue Synergy window is shown and focused again after firing a trigger into another window.
  • [triggers] Window picker: arrow keys skip every second item: stopPropagation fix — key events no longer fire twice by bubbling from input to outer container.
  • [triggers] Window picker: monitor icons invisible on selected items: selected items now show white monitor icons instead of using the accent colour (which was the same as the selection background).
  • [triggers] SCR step: BS template variables corrupted in scripts: {0}, {date}, {clip:last} etc. in script content are no longer processed by the BS template resolver — raw code passes through untouched.
  • [triggers] SCR step: multi-line PowerShell via -Command: multi-line PS scripts now always execute via a temp .ps1 file with -File — avoids -Command quoting edge cases and {0} format-string conflicts.
  • [triggers] SCR step: Window/Debug + PowerShell multi-line: opening a console window with a multi-line PS script no longer splits lines into separate cmd commands inside the .bat.
  • [triggers] SCR step: metadata prefixes inside script body: [window]/[debug]/[dir:]/[out:] prefixes are now stripped before applying the executor template so they don’t appear verbatim inside the PS script.
  • [triggers] SCR step: executor controls styling and layout: executor dropdown sits above the mode toggle, uses BS-standard dropdown styling; placeholder text adapts to the selected executor (PowerShell / cmd / raw hints).
  • [triggers] Trigger editor autofocus: keyword field is focused automatically when the editor opens; Ctrl+E focuses the keyword field when the editor is already open.
  • [triggers] TXT/SCR textarea cursor: cursor is placed at the start of the content on focus, not at the end.

[0.7.21] - 2026-04-15

Added

  • [triggers/F6] Triggers Trash: soft-delete triggers to trash instead of permanent delete
  • Restore trigger(s) from trash (single or multi-select)
  • Permanently delete individual trigger(s) from trash
  • Empty Triggers Trash (all trashed triggers in one action)
  • Trash view in Triggers sidebar tree (“Deleted Triggers” node with count badge)
  • Triggers count in global TrashStats (tree badges + Trash window)
  • Expired-trash purge on startup now covers triggers (same retention_days setting)
  • DB migration 0.7.21: adds deleted_at column to triggers table

[0.7.20] - 2026-04-15

Added

  • [triggers/F2] Test-Run button in WorkflowEditor: click ▶ Test to preview all steps (dry run — no paste/keystroke executed); Shift+click fires the trigger for real against a focused window.
  • [triggers/F3] Copy as YAML: toolbar button and Edit menu entry serialize selected trigger(s) to BS YAML (bs_trigger: key) and copy to clipboard; parser extended to recognize bs_trigger: on import.
  • [triggers/F4] Code Editor + Executor: SCR steps now have an Executor dropdown (raw / powershell / cmd) that wraps the script body via a configurable template ({body} placeholder); TriggersConfig.executors in TOML for custom executor definitions.
  • [triggers/F5] Per-trigger Erase Method: “Erase Method” dropdown in WorkflowEditor overrides the global setting for individual triggers; stored as erase_method on the trigger row (None = use global).

[0.7.19] - 2026-04-15

Added

  • [triggers] Inline keystroke tokens in TXT steps: {TAB}, {ENTER}, {ESC}, {UP}, {DOWN}, {LEFT}, {RIGHT}, {HOME}, {END}, {PGUP}, {PGDN}, {BACKSPACE}, {DELETE}, {INSERT}, {F1}{F12} — send the corresponding key press mid-expansion without a separate KEY step
  • [triggers] {DELAY:N} token pauses N milliseconds mid-TXT expansion
  • [triggers] {DELAY:N,"text"} slow-types quoted text at N ms per character
  • [triggers] {SPEED:N} token sets per-step typing speed (N ms/char) for all subsequent plain text in that step
  • [triggers] Per-trigger Typing Mode: Paste (clipboard Ctrl+V, fast, default) or Type (enigo char-by-char, works over RDP and in apps that block paste)
  • [triggers] triggers.typing_mode config default and triggers.typing_speed_ms global speed setting

[0.7.18] - 2026-04-15

Added

  • [overlay] Ctrl+Enter on a trigger in the overlay copies the resolved expansion text to the clipboard instead of pasting it — useful for reviewing or redirecting output.
  • [triggers] Trigger keyword inputs in the editor now explicitly pause the expansion engine on focus and resume on blur — prevents accidental trigger firing while editing keywords.
  • [clips] “Use as Trigger” dialog now includes an optional Description field so new triggers are immediately identifiable in the list.
  • [triggers] Filter bar in Triggers workspace — same filter-bar pattern as in the Clips workspace; filter by keyword, description, action type, or enabled state.
  • [triggers] Column chooser — right-click any column header to show or hide columns; visible columns are persisted.
  • [triggers] Duplicate trigger — right-click or toolbar button duplicates the selected trigger; the copy opens in the editor with a -copy keyword suffix.
  • [triggers] {clip:-N} template variable — inserts the Nth most recent clipboard clip; -1 = most recent, -2 = second most recent, etc.
  • [triggers] Multi-select improvements — Ctrl+A selects all visible triggers; bulk fire sends up to 10 with a 150 ms delay; the toolbar shows a count badge.
  • [triggers] Script step editor — the SCR action textarea is now taller (6 rows) with a script-focused placeholder and a mode toggle button (Silent / Window / Debug) that controls how the command runs.
  • [triggers] Paste YAML from clipboard — Ctrl+V in the Triggers workspace auto-detects espanso-compatible YAML and opens the import preview dialog; a single new trigger is created instantly without the dialog.
  • [triggers] espanso type: script import — espanso triggers that use a type: script variable are now imported as Blue Synergy SCR (script) steps instead of plain text.
  • [triggers] “Load Sample Triggers” re-enables disabled samples — clicking Edit > Load Sample Triggers now re-activates existing samples that were previously disabled.

Fixed

  • [overlay] Edited clips in the overlay now show an amber type badge — matching the clips workspace appearance; badge stays visible (white pill) on selected rows.
  • [overlay] Selecting an AES-256 encrypted clip in the overlay now prompts for the vault password when the vault is locked, instead of silently pasting garbled text.
  • [clips] “Use as Trigger” dialog no longer stretches to the full window height; auto-focuses the keyword field; Enter submits and Escape dismisses from anywhere inside the dialog.
  • [triggers] Sample triggers ;save and ;header are now seeded as disabled on a fresh install — both send keystrokes and should require explicit opt-in.
  • [clips] Timeline layout (T button) now appears correctly on first launch after entering a golden key — onMount could fire before startup completed, leaving isPower = false; now also re-checks on startup://done.
  • [triggers] Sample trigger ;ip (IP address lookup) was not expanding after a “Load Sample Triggers” — the command was already in the database as disabled; it is now re-enabled correctly.

[0.7.17] - 2026-04-14

Fixed

  • [core] App version in installer and About dialog was stuck at 0.7.12 — tauri.conf.json was not updated alongside Cargo.toml since 0.7.12.

[0.7.16] - 2026-04-14

Changed

  • [overlay] Empty-query browse now shows the most recent clips first, with pinned clips that fall outside the top 50 appended at the bottom as a fixed quick-access section. A pinned clip inside the recent block stays in its natural position and does not appear twice.

[0.7.15] - 2026-04-14

Fixed

  • [overlay] Most recent copy was no longer shown at the top of the overlay when no search query was active. The smart-ranking change from 0.7.11 incorrectly applied uses-sorting to the empty-query browse view — new clips with 0 uses sank below older frequently-pasted clips. Empty-query order is now: pinned first, then most recent.

[0.7.14] - 2026-04-14

Fixed

  • [clips] Timeline layout button (T) was not appearing in the layout switcher even after activating a Golden Key / Power tier license. Root cause: SolidJS <For> does not re-run item callbacks reactively when props change — replaced non-reactive if/return null guard with a <Show> wrapper.

[0.7.13] - 2026-04-14

Fixed

  • [overlay] Uncaught ReferenceError on overlay open — createRoot was missing from the import in overlay.store.ts, causing the overlay to crash at runtime for all users on 0.7.11 and 0.7.12.
  • [triggers] Overlapping immediate keywords — if two immediate triggers share a prefix (e.g. ;t and ;te), the shorter one no longer fires before the user finishes typing the longer one. Blue Synergy now waits one character to confirm whether a longer keyword is coming before expanding.

[0.7.12] - 2026-04-13

Added

  • [overlay] Content autocomplete toggle — Settings > Overlay now has a “Content Autocomplete” checkbox to enable or disable ghost-text completion in the search box.
  • [overlay] Pinned clips always visible — pinned clips appear at the top of empty-query results and are appended at the bottom of any free-text search so they are always reachable.
  • [overlay] Smart clip ranking — clips are ranked by pinned > uses > recency in empty-query results; fuzzy-search results get a uses-frequency boost and a pinned boost so frequently-used clips surface first.

Fixed

  • [overlay] Star-filter *type=TXT hello — “hello” was incorrectly absorbed into the filter value instead of being treated as free text. Multi-word absorption now only applies to *source= and *window= (app/window names).
  • [overlay] *pinned=true returned empty — old clips pinned outside the recent-500 cache window were missing from the in-memory cache. Pinning an old clip now loads it into cache immediately.
  • [overlay] *obsolete=true was leaking all clips — trigger-specific filter fields (enabled, obsolete, immediate, keyword, app_profile) now correctly exclude clips from results.
  • [overlay] Trigger search — triggers are now searchable by their expansion text (action data), not just keyword and description.
  • [overlay] Trigger keyword-prefix always surfaces — a trigger whose keyword starts with the typed query is guaranteed to appear at the top, fixing punctuation-prefix groups like ., and .-.
  • [overlay] Trigger highlight indices — matched characters are now highlighted correctly in trigger rows.
  • [overlay] Zoom indicator — no longer flashes on overlay open; only shown on explicit Ctrl+Scroll or Ctrl+=/-.
  • [overlay] F3 expand — works correctly for one-liners, multi-line clips, and triggers.
  • [overlay] Ctrl+Enter on trigger — copies the trigger keyword to clipboard instead of attempting a paste.
  • [overlay] Theme not applied on overlay open — overlay now reads and applies the configured theme on startup and syncs live when settings change.

Changed

  • [overlay] Search debounce reduced from 80ms to 40ms.

[0.7.11] - 2026-04-13

Fixed

  • [core] Ctrl+Scroll no longer blocked in other apps while Blue Synergy runs — the global mouse hook now intercepts only when a Blue Synergy window is in the foreground.
  • [core] Golden Key now correctly grants Power tier — Timeline View and other Power-only features are visible immediately after entering a Golden Key.
  • [triggers] YAML trigger import no longer crashes when the file contains duplicate keywords — duplicates are silently skipped and counted in the “skipped” summary.

[0.7.10] - 2026-04-12

Added

  • [triggers] Extra keywords — assign multiple keywords to a single trigger; all aliases appear in the table and are searchable in the overlay.
  • [triggers] Configurable erase method — choose between Select+Delete and Backspace in Settings > Triggers to control how the typed keyword is removed before expansion.
  • [triggers] F2 inline keyword rename — press F2 on any trigger row to rename the keyword without opening the editor.
  • [clips] Timeline View (Layout T) — chronological clip history with column chooser, resizable columns, day-of-week group header styling, and Date+Time column. Power tier / Golden Key users only. See [[clips-timeline-view]] for details.
  • [core] Golden Key trophy moment — activating a Golden Key shows a trophy animation confirming Power tier.
  • [core] Golden Key hint while typing — the BS-GOLD- prefix is recognized as you type, showing a confirmation hint before you finish entering the key.
  • [core] Change License Key — Settings > License now shows a “Change License Key” button when already activated, so you can enter a different or upgraded key without reinstalling. See [[core-license-activation]] for details.

[0.7.8] - 2026-04-12

Added

  • [core] Close behavior dialog — pressing Alt+F4 or clicking the X button now asks “Minimize to Tray?” or “Exit?” instead of silently hiding the window. Check “Remember my choice” to save your preference permanently. The setting can also be changed at any time in Settings > General > Close Window.
  • [core] File > Restart — new menu item restarts Blue Synergy in place. Useful after importing a config or changing settings that benefit from a fresh start.
  • [core] Single-instance guard — launching a second copy of Blue Synergy now brings the existing window to the foreground instead of opening a duplicate.
  • [clips] Delete image file from disk when clip is deleted — when an image clip is permanently deleted (or the trash is emptied), the image file on disk is also removed. The file is only deleted when no other clip or capture still references it. Can be turned off in Settings > Clips > Delete Image Files.
  • [clips] Image clips can now be renamed inline — press F2 or double-click the clip title to rename in place. The Properties panel also pre-fills the filename so you can see and edit the actual file name on disk.
  • [captures] “Add to Clips” option when closing an unsaved capture — the unsaved-changes dialog now offers a third choice to save the capture directly as an image clip before discarding.
  • [core] Backup max retention — set a limit on how many backup ZIPs to keep. After each successful backup, older ZIPs beyond the limit are automatically deleted. Configurable in Settings → Maintenance → Backup.
  • [core] Safety backup before restore — the restore dialog now has an opt-out checkbox to create a safety backup of your current data before the restore begins. Checked by default.
  • [core] Include orphaned capture files in backup — backup now sweeps for image files on disk that are no longer tracked in the database (e.g. from deleted captures) and bundles them into the archive. Configurable per-session or permanently in settings.
  • [core] Backup warns when image clips may not be fully recoverable — if the backup destination is on a different drive from the clips folder, Blue Synergy now shows a clear warning that image files are not included in the archive.
  • [core] Backup progress now moves steadily from 0% to 100% — progress is divided into named phases (database export, clip formats, images) so the bar advances continuously instead of stalling for long periods.
  • [core] Orphaned capture files visible in cleanup preview — the backup/cleanup preview now lists image files on disk that have no matching database record, giving you a clear picture of what will be removed before you confirm.

Fixed

  • [core] Files inside backup archives now show the correct last-modified date — previously all entries showed 31.12.1979 (ZIP epoch default) instead of the actual backup date.
  • [core] Startup backup now respects the configured backup interval — previously a new backup was created on every app launch. Blue Synergy now skips the startup backup if a recent backup already exists within the configured interval (e.g. 7 days), so the backup schedule matches what you set.
  • [core] Restoring a backup no longer fails with an EOCD error — backups are now written to a temporary file and renamed to .zip only after the archive is fully written, so an in-progress backup can never appear as a broken file in the restore picker.
  • [clips] Image clips no longer overwrite the clipboard while you navigate away — a short dwell delay prevents the clipboard from being written if you switch clips quickly, and navigating to a non-image clip immediately cancels the pending write.
  • [clips] Pasting an image to Word or another app no longer creates a spurious duplicate clip — clipboard deduplication now correctly ignores clipboard-change events that occur during a paste operation.
  • [clips] Images copied from Word and other Office apps now display correctly in the Clips preview — the BMP pixel offset calculation now correctly accounts for BI_BITFIELDS color masks, so 32-bit images with embedded color tables load properly.
  • [clips] Image clips captured at startup no longer show “Blue Synergy” as the source app — the startup clipboard seed now hashes only and skips creating a clip, since the foreground window at that point is always Blue Synergy itself.
  • [clips] Exporting or pasting an image clip now reads the original file from disk when available, instead of reconstructing from stored format blobs — more reliable for large or high-quality images.
  • [core] Backup progress no longer freezes at 20% during the clip formats step — clip format data is now streamed row-by-row with live progress updates instead of blocking until the entire export is assembled.
  • [core] Backup cleanup preview now accurately reflects what will actually be deleted — previously the preview could list items that the real cleanup would skip due to disabled retention rules.
  • [core] On-disk capture image files are now always included in backups — files that existed on disk without a matching database record were previously silently omitted.
  • [core] ZIP64 format used for all backup entries — prevents failures when individual capture image files exceed the 4 GB ZIP32 size limit.
  • [core] Backup reminder dialog no longer causes the main window to flash or freeze when dismissed — the prompt now updates the config without triggering a full UI reload.
  • [clips] Preview-toolbar layout fixed in all three layouts — Layout C no longer shows a narrow toolbar when the editor is collapsed; A/B layouts use the same collapse mechanic as the tree panel; toolbar icons are left-aligned instead of stretched across the full width.
  • [clips] Blank clip created via Ctrl+N now shows type “TXT” — previously showed “text/plain” (inconsistent with all other clip types).
  • [clips] Accept Edit (✓) now works correctly after editing a blank clip — the empty-string original content was treated as falsy and silently blocked the confirm dialog from opening.
  • [clips] Ctrl+N editor focus is now reliable — the new clip is fully loaded before the editor receives focus, so the cursor always lands in the right place.
  • [clips] Split and Glue separator picker overhauled — ✂+▾ and ⊕+▾ now appear as connected split-button groups in the toolbar. Separator options in the Edit menu and toolbar dropdown use a consistent column layout (checkmark · value badge · label). Custom… opens a dialog with preset chips and a textarea; separator is saved immediately when focus leaves the field so clicking the action button directly after typing works correctly. Tooltips on ✂ and ⊕ show the active separator.

[0.7.7] - 2026-04-10

Added

  • [clips] Multi-select Enter paste in click order — Ctrl+Click to select multiple clips, then Enter pastes them all to the last focused app in the exact order you selected them. Works for text and image clips.
  • [shared] File > New and Ctrl+N are now context-sensitive — creates a new blank clip (Clips tab), new trigger (Triggers tab), or fullscreen capture (Captures tab).

Fixed

  • [captures] Ctrl+Alt+L (Repeat Last) now correctly repeats region captures — previously, a leftover window title caused window-capture mode to always win over the more recent region capture.
  • [clips] Locked clips (DPAPI + AES-256) no longer leave raw format data (RTF, HTML, CF_DIB) in the database after locking — clip_formats rows are deleted as part of both lock paths.
  • [clips] LockClipDialog now focuses the Lock button on open — pressing Enter confirms the lock without touching the mouse.
  • [captures] Capture image format (PNG/JPG/BMP) change now applies immediately — no restart required.
  • [clips] Secure clip title is now shown in the clips list (🔒 + title); F2 rename works on locked clips (title is unencrypted and always editable).
  • [core] File → Export Config / Import Config now functional — opens native file dialogs.
  • [captures] Dragging a capture thumbnail into Claude or other apps now delivers the actual image file instead of a text path.
  • [clips] Dragging a single TXT clip to an external app now sets plain-text data; dragging an IMG clip delivers the image file.
  • [core] Vault status poll interval is now correctly cleared on unmount — onCleanup was registered after await in an async onMount, losing its reactive owner so the interval accumulated on every HMR reload.
  • [clips] Content column no longer collapses to near-zero width on narrow layouts.
  • [triggers] {clip:last} template variable no longer returns soft-deleted clips.

[0.7.5] - 2026-04-09

Added

  • Ctrl+Shift+S Save As in Captures — new shortcut always opens the Save dialog to choose a filename. Ctrl+S now silently overwrites the existing file when the capture was already saved to disk; it only opens the dialog for new (not-yet-saved) captures.
  • Alt+1/2/3 workspace shortcuts — Switch between Clips (Alt+1), Triggers (Alt+2), and Captures (Alt+3) from anywhere in the app without touching the mouse. Shortcut hints are shown in the button tooltips. The three buttons are now equal width.
  • Keyboard shortcuts for image zoom — While hovering over any image in Captures or Clips, use Ctrl++ / Ctrl+= to zoom in, Ctrl+- to zoom out, Ctrl+0 for actual pixel size (1:1), and Ctrl+1 to fit the image to the pane.
  • Zoom percentage in Captures editor — The current canvas zoom (e.g. “125%”) is now shown live in the properties bar below the capture canvas. Reacts to all zoom inputs: buttons, scroll wheel, fit, and 1:1.
  • UI zoom indicator reflects actual zoom — The “Zoom: X%” readout in the menu bar was always stuck at 100%. It now updates correctly when zooming with Ctrl+Scroll.

Fixed

  • Ctrl+Scroll zoom anchors to cursor in Captures and Clips — Zooming with the scroll wheel now keeps the image point under your cursor fixed in place, making it easy to zoom into a specific detail.
  • “Apply to existing” now masks clips for all masking modes — adding a retention rule with mode mask_all or mask_title_purge and checking “Apply to existing” now correctly sets is_masked = 1 on matching clips. Previously only mask_purge was handled; the other masking modes were silently skipped.
  • By App list shows all apps — the By App sidebar section no longer caps at 5 entries with a “Show more” button. All apps are listed immediately.
  • Annotations no longer bleed to other captures — Drawing on one capture then quickly switching thumbnails could cause the annotation to appear on the next capture. Reactive ordering between the load effect and sync-back is now guaranteed, making this race condition impossible.
  • Annotations preserved when switching away and back — Switching away from a capture that had unsaved annotations and then switching back no longer reloads the original screenshot, discarding your work.
  • Fullscreen and Repeat Last captures no longer include the app window — Blue Synergy occasionally appeared in its own screenshots. An extra 80 ms DWM recompose delay is now applied after hiding the window before the screenshot is taken, matching the existing region capture behavior.
  • “This Session” sidebar count includes captures with unsaved annotations — A capture modified with annotations but not yet saved now appears in the “This Session” section even if it was taken before the current session.
  • Unsaved-annotation indicator visible on thumbnails — Captures with pending annotation changes now show a yellow dot on their thumbnail strip card, replacing the subtle * prefix that was easy to miss.

[0.7.0] - 2026-04-06

Added

  • Source title for clips — Each clip now records the exact window title of the source app at capture time. Used internally for smarter app grouping and future display options.
  • Dim overlay toggle for region capture — A new option in Settings → Captures lets you disable the dark dimming overlay during region selection, keeping the screen fully visible while drawing a selection.

Fixed

  • “By App” shows all apps — The By App sidebar section previously capped at 8 entries. All apps are now listed with a “Show more” button for long lists.
  • Region selector zoom preview on secondary monitor — The zoom loupe and crosshair in the region selector now sample the correct screen position when the capture window is on a monitor with a different DPR than the primary display.
  • Region selector W/H display — Width and height in the info panel now show CSS (logical) pixels, consistent with the X/Y cursor readout. Previously on high-DPR displays (e.g. 150% scaling) the W/H values appeared proportionally larger than the actual captured area.
  • Region selector info panel position on secondary monitor — The info panel now floats at the correct position when the capture window opens on a monitor with a different DPR than the primary display.
  • “What’s New” shows correct changes — The What’s New dialog now displays only the changes introduced since the previously installed version, not the full changelog from the beginning.

[0.6.4] - 2026-04-06

Fixed

  • Clearing a clip title after F2 rename — Saving an empty title (F2, clear the field, Enter) now removes the custom title in the database and falls back to the default derived title instead of leaving the old title in place.
  • “Show more” in By App and Tags — After expanding a long list with “Show more”, choosing an app or tag no longer collapses the section back to the truncated list; expanded state is persisted across selection changes.
  • Startup hotkey conflict warning — The app now detects when any two global shortcuts use the same key combination (not only Flash vs. fullscreen), lists them, and can reset duplicates to defaults with a restart.
  • Update check after switching primary manifest URL — If the website manifest is not available yet (HTTP 404/403), the app automatically retries using the public GitHub releases manifest and changelog so update checks keep working.

Changed

  • Update check location — In-app updates now use a public URL for the manifest and remote changelog (alpha).

[0.6.3] - 2026-04-04

Added

  • Ctrl+C / Ctrl+V in CapturesCtrl+C copies the selected capture to the clipboard (uses annotated version if unsaved changes exist). Ctrl+V pastes any image from the clipboard as a new capture entry. Both shortcuts are listed in the ? help dialog.
  • --version / -V CLI flagblue-synergy.exe --version prints the installed version and exits. Useful for scripting and verifying which build is installed.
  • Right-click Trash node → Empty Trash / Restore All — Both Clips and Captures sidebar trees now show a context menu when right-clicking the Trash node: “Restore All” recovers everything in one click, “Empty Trash” (red) permanently deletes all items. Both execute immediately with a status toast — no confirmation dialog.
  • Status toasts on all trash actions — Moving clips or captures to trash, restoring, permanently deleting, or emptying trash now shows a status notification in the menu bar (e.g. “3 clips moved to trash”, “2 captures restored”, “Trash emptied”). Consistent across both modules.
  • “Reset dismissed dialogs” in General settings — Settings → General → Dialogs now includes a “Reset dismissed dialogs” button. Clicking it re-enables any “Don’t ask again”-suppressed confirmation dialogs (Move to Trash, Delete Capture permanently) so they appear again on the next action.

Fixed

  • Trash lifecycle unified across Clips and Captures — Both modules now follow the same pattern: Delete key in trash view = permanent delete (not restore); right-click in trash shows Restore and Delete Permanently as separate buttons; Empty Trash and all trash actions execute immediately with a toast (no confirmation dialogs); trash count refreshes on module open; selecting a capture in the trash strip now shows its preview (was blank).
  • Clips trash context menu: Restore and Delete Permanently are now separate actions — Right-clicking a clip in the Trash view now shows two distinct buttons: “Restore” (recovers the clip) and “Delete Permanently” (red, irreversible). Previously both actions routed through the same handler — clicking “Restore” would permanently delete the clip instead.
  • Update banner: inline download progress, correct version in title, See Changes shows changelog — “Update Now” now downloads directly within the banner (progress bar + %, Cancel, then Install) without opening the full Updates dialog. The banner title now correctly reads “Blue Synergy update is available v0.6.2” (was showing no version due to a Solid.js reactive accessor bug). “See Changes” now correctly pre-fills the changelog dialog with the new version’s entries (previously showed “You are up to date”).
  • Source app name now handles uppercase .EXE extension — Clips captured from apps that report their executable with an uppercase extension (.EXE, .Exe) now show the correct app name instead of including the extension suffix.
  • Keyboard navigation in all confirmation dialogs — Every dialog (Unsaved Changes, Move to Trash, Delete Capture, and others) now supports: Tab/Shift+Tab cycles through buttons without escaping to the main window; Esc cancels; pressing the first letter of any button activates it (underlined in the label); focus lands on the primary button as soon as the dialog opens; button order is now always primary → danger → cancel.
  • Delete Capture dialog converted to shared ConfirmDialog — The inline delete dialog in the Captures strip now uses the same shared component as all other dialogs, giving it focus trap, keyboard shortcuts (Delete files / Keep files / Cancel), and consistent styling.
  • Initial Setup and Vault Setup keyboard support — Enter confirms the primary action on both setup screens. On Initial Setup, C/S shortcuts activate Continue/Skip when not typing in a field. On Vault Setup, Esc handles the two-step skip confirmation (first press = “Skip for now”, second press = “Skip (confirm)”).
  • Space+Drag panning for zoomed images — Hold Space and drag to pan when an image clip is zoomed in (free mode). Cursor shows grab/grabbing feedback. Activates only when hovering the image area and not typing in a field.
  • Zoomed images in Clips preview now scroll instead of being clipped — Zooming into an image clip no longer hides content at the edges with no way to reach it. The image in free mode now renders at its true pixel dimensions, and the container scrolls natively. Mouse-wheel zoom and zoom buttons are unchanged; drag-to-pan is replaced by scrollbars.
  • : and / now type normally in all text editors — Both characters were intercepted by the CodeEditor’s vim-style ex command bar shortcut, making it impossible to type colons (e.g. in URLs, JSON, code) or slashes. The ex bar is now opened with Ctrl+/ instead; the bare : binding is removed entirely.
  • Unsaved-changes dialog when switching triggers in edit mode — Clicking a different trigger row while the editor is open now checks for unsaved changes. If the form is dirty, a dialog appears with Save / Discard / Cancel. If clean, the editor closes and the new trigger loads immediately.
  • Trigger step drag-to-reorder with dual-mode feedback — HTML5 drag-and-drop replaced with pointer capture (reliable in WebView2). Dragging into the top/bottom 30% of a row shows an insert line; dragging into the center highlights the row for a swap. The step moves to the exact target position — no unexpected jumping.

[0.6.1] - 2026-04-03

Added

  • Secure Clips — per-clip AES-256-GCM and DPAPI encryption — Individual clips can now be locked using Windows DPAPI (machine-bound, auto-unlocks with Windows login) or AES-256-GCM with a master vault password (portable, restorable on any machine with the recovery password). Locked clips show a 🔒 SEC badge; content is hidden until explicitly unlocked or peeked.
  • Vault status indicator in status bar — The clips workspace status bar shows a live lock/unlock indicator with a tooltip showing DPAPI session info or countdown to password session expiry.
  • Secure + Protected sidebar categories — The ClipsTree sidebar now includes a Secure category (encrypted clips only) and a Protected category (clips excluded from retention cleanup or masked).
  • Auto-peek on select (DPAPI) — Optional setting in Security → Secure Vault: selecting a DPAPI-locked clip automatically decrypts and previews its content without an extra click.
  • Vault backup/restore — Backups now include all encrypted clip data and the vault key configuration (vault_config). Restoring on a different machine shows a warning that DPAPI clips are unrecoverable cross-machine.
  • Hostname in backup manifest — The backup file now records the source machine name; the restore UI highlights when you are restoring a backup created on a different PC.
  • “Update Now” auto-starts download from banner — The update available banner now has three buttons: “Update Now” opens the Updates dialog and immediately starts downloading; “See Changes” opens the changelog without auto-download; “Dismiss” hides until a newer version appears.
  • Post-update “What’s New” toast — After installing an update and relaunching, a toast notification appears in the menu bar (“★ Updated to vX.Y.Z”) with a “What’s New” button that opens the changelog. The toast auto-hides after 6 seconds.
  • “Delete Permanently” button in delete dialog — The delete confirmation dialog now offers two actions: “Move to Trash” (primary, recoverable) and “Delete Permanently” (red, irreversible). ConfirmDialog gained a reusable secondaryLabel/onSecondaryConfirm prop for danger actions.
  • Redesigned About dialog — The About dialog now shows the branded Aperture logo, a version badge, feature pills (Clipboard · Text Expansion · Captures · OCR), beta expiry info, and a ✕ close button.

Fixed

  • Paste and copy now decrypt secure clipspaste_clip and copy_clip_to_clipboard previously wrote the •••••••• placeholder to the clipboard when a clip was encrypted. They now decrypt the content before writing.
  • Security settings warnings now align under the control column — The “No recovery password set” warning box and hint paragraphs in Security Settings were spanning full panel width; they now indent under the label column and the warning icon sits in its own column for clean alignment.
  • Image zoom no longer jumps to 125% on first click — The +/ zoom buttons in the Clips image preview now start from the actual rendered fit scale instead of multiplying from the stored zoom value. The zoom percentage label also shows the correct value in fit mode.
  • Edited clips reappear in overlay — After editing or reverting a clip, it is now reloaded in the in-memory cache instead of being evicted. Previously, edited clips disappeared from overlay search results until the next app restart.
  • CI: Clippy no longer blocks PRs on style warningscargo clippy -- -D warnings replaced with cargo clippy; remaining style warnings are visible in CI output without failing the build.
  • Overlay settings toggles now match design theme — The checkbox grid in Overlay Settings (Overlay Config) now uses the same font, colors, and spacing as all other settings panels. Checkboxes are accent-colored via accent-color: var(--ac), sized 13×13 px, with var(--ui) label font and var(--tx) text. A stale duplicate entry for star_filter_dropdown was also removed.

[0.5.3] - 2026-04-03

Added

  • Tray icon badge when update is available — When Blue Synergy detects a newer version in the background, the system tray icon now shows a small orange dot in the top-right corner. The tooltip changes to “Blue Synergy — Update available”. The badge disappears once you dismiss the update banner or install the update.
  • Input validation for retention duration fields — Duration fields in Security Settings (sweep interval, default duration, per-rule durations) now reject invalid values (e.g. asdf) before saving. Invalid fields are highlighted with a red border. A yellow warning is shown when the default duration is shorter than the sweep interval, explaining that clips may not be purged on time.
  • “Restart Now” button for sweep interval changes — Changing the sweep interval requires a restart to take effect (the background thread reads the interval once at startup). A “Restart Now” button now appears in Security Settings when the sweep interval is modified.

Fixed

  • Update Check dialog no longer leaks event listeners — Fixed a Solid.js reactive-owner warning (“cleanups created outside a createRoot”) that appeared every time the Updates dialog opened. The four download-progress event listeners are now correctly unregistered when the dialog closes.
  • Retention sweep no longer crashes the app on DB error — A panic in load_cache() (triggered by a DB error after a successful sweep purge) was silently killing the background sweep thread and the entire process. Converted load_cache() to return Result instead of panicking, and added catch_unwind() as a secondary safety net around each sweep iteration.
  • File → Open Trash no longer crashes the appshow_trash_window called run_on_main_thread directly from the Tauri sync command handler, which can deadlock when the dispatcher runs sync commands on the main thread. Wrapped in std::thread::spawn first, matching the pattern used throughout the captures module.
  • Retention MaskPurge clips are now deleted — Clips with a Mask + Purge retention rule were masked correctly but never deleted by the sweep. The sweep query had an overly broad AND is_masked = 0 guard that blocked deletion. Removed — mask-only clips are already protected by purge_at IS NULL.
  • Solid.js createRoot warnings eliminated — All 7 module-level stores and the StartupOverlay component created reactive primitives outside a reactive owner, causing “cleanups created outside a createRoot or render will never be run” in DevTools. Wrapped stores in createRoot() and converted StartupOverlay’s onMount(async) to sync with Promise chaining to preserve the reactive owner across listener registration.
  • “Installing update” notification after app closes — When the user triggers an update, the app closes and a Windows tray balloon appears: “Installing update — Blue Synergy will restart automatically.” Previously the app disappeared silently with no indication the installer was running.

[0.5.2] - 2026-03-31

Fixed

  • App relaunches automatically after installing an update — After clicking Install in the Updates dialog, Blue Synergy now restarts itself once the new version is installed. Previously the user had to relaunch manually.
  • Uninstall “Remove all data” now fully cleans up — The uninstaller now correctly deletes the app’s data folder when “Remove all data” is checked. Previously the folder was left behind.

[0.5.1] - 2026-03-31

Added

  • Update available banner — Blue Synergy checks for updates silently 10 seconds after startup and shows a banner when a newer version is found. Click “Update Now” to open the Updates dialog pre-loaded with the changelog, or “Dismiss” to hide it until the next version.
  • Update download progress — The Updates dialog now shows a real-time progress bar (percentage and MB) while downloading the installer, with a Cancel button.
  • Startup config warnings — If two shortcuts conflict at startup, a dialog appears offering to reassign the conflicting key with a one-click fix. Warnings can be snoozed for 7 days.
  • Overlay keyboard navigation — Jump ±5 rows in the overlay list with Ctrl+Down / Ctrl+Up. Load more results on demand with Ctrl+Alt+Down or the “+N more” button. Matched characters are highlighted in accent color. Maximum visible results is now configurable (default 50, previously hardcoded at 20).
  • Starts-with search filter — Type ^word or *starts=word to find clips whose content begins with that text. Quoted form ^"cd " matches the exact prefix including spaces.
  • Keyword highlight in search results — Matching words are highlighted in the clips table and in the preview editor while a search is active.
  • Search jumps to first match in editor — When switching clips during an active search, the editor scrolls to two lines above the first highlighted match.
  • Uses counter (opt-in) — Enable Track Uses in Settings → Clips to count how often a clip is pasted. Uses the window-blur heuristic (increments when you switch to another app after selecting a clip). The Uses column is hidden by default; show it via right-click on the table header.

Fixed

  • OCR auto-detects Tesseract on first run — If OCR was never explicitly configured, the app now checks for Tesseract at startup and enables or disables it automatically. A toast notification is shown when Tesseract is not found so the user knows why OCR is unavailable.
  • Export respects selection — When 2 or more clips are selected, File > Export now exports only those clips. With no multi-selection active, all clips in the current view are exported as before.
  • Virtual folder and group counts now update immediately — Counts in the sidebar (All Clips, Pinned, Glued, Edited, etc.) and group counts now refresh instantly after adding, deleting, or moving clips instead of staying stale until the next reload.
  • Clips search returned no results — A missing column in the FTS5 query caused the row mapping to fail silently, dropping every search result. Fixed.
  • Prefix search now works — Searching fla now finds clips containing flash, flashlight, etc.
  • Hyphenated search terms — Searching flash-capture now correctly finds clips containing that exact hyphenated term.
  • Ctrl+F focuses search bar — From anywhere in the Clips workspace, Ctrl+F moves focus to the search field and selects existing text.
  • ESC navigation in search — ESC from the search field returns focus to the clips table while keeping the current selection (if it is in the results). ESC on the table clears the search and reloads all clips.
  • Category switch clears search — Switching to a different folder or group now resets the search field and chip filters automatically.

[0.5.0] - 2026-03-30

Added

  • Branded app logo throughout — The aperture logo now appears in its official colors (steel blues + orange anchor blade) in the startup screen, window title bar, and system tray. The title bar and tray use a transparent-background icon that blends cleanly with the native Windows chrome; the taskbar and installer keep the full logo with its dark background.

Fixed

  • Startup screen shows brand colors immediately — The loading spinner no longer flashes teal before switching to the correct blue/orange palette.
  • Startup overlay text no longer shifts — “BLUE SYNERGY” and “Starting up…” no longer reflow during font loading.
  • Startup spinner no longer wind-ups — The blade animation continues seamlessly from the static HTML overlay into the SolidJS overlay without restarting.
  • Title bar icon is sharp — Previously the 256px icon was blurry when Windows scaled it down; the icon is now generated at 32px for pixel-accurate rendering.
  • Steel Blue is the default theme — View > Theme menu, Settings, and the first-run screen now correctly show Steel Blue as the default (was incorrectly labelled Teal). Steel Blue also appears at the top of the theme list.

[0.4.9] - 2026-03-28

Added

  • Immediate-fire triggers — Triggers can now be marked as “immediate”: they expand the moment the last keyword character is typed, with no trailing space or backspace needed. Toggle per-trigger in the editor (⚡ badge shown). A triggers.immediate_by_default config option sets the default for new triggers.
  • Ctrl+E to edit / stop editing — In the Triggers workspace, Ctrl+E opens the editor for the selected row. Pressing Ctrl+E again (or ESC or Cancel) closes the editor and returns focus to the grid.
  • Triggers grid auto-focuses on tab switch — Opening the Triggers tab (including after “Use as Trigger” from Clips) immediately focuses the trigger table for keyboard navigation.

Fixed

  • “Use as Trigger” from Clips no longer silently fails — The clip-to-trigger flow was broken after the immediate-fire branch added a new parameter to the trigger creation API.
  • Ctrl+E always edits the intended row — Pressing Ctrl+E on a selected row could open the editor for a different trigger. The trigger is now captured at keypress time and passed explicitly to the editor.
  • App icon now appears in title bar, taskbar, and system tray — The window icon was never applied at runtime (Tauri v2 requires an explicit set_icon() call). The correct icon now shows in the title bar (top left), taskbar button, and Alt+Tab thumbnail.
  • Auto-update now closes the app cleanly before installing — After clicking “Download & Install”, the app now exits properly (saves unsaved captures via the save dialog, then quits) before NSIS installs the new version. Previously the old instance kept running, which caused the new version’s window to stay hidden after install.

[0.4.8] - 2026-03-28

Added

  • Overlay Enter = copy, Ctrl+Enter = paste — In the quick overlay, pressing Enter now copies the selected clip or capture to the clipboard without pasting. Press Ctrl+Enter to also paste into the previous window (Ctrl+V simulation). Works for text clips, image clips, and captures.

  • Overlay keyboard navigation: PageUp/Down, Home/End — Navigate the overlay results list with PageUp/PageDown (jump 10 items) and Home/End (jump to first/last). The list scrolls to keep the selection visible on all navigation keys.

  • Edited clip marker — Edited clips now show an orange circle ✎ indicator in the table. Type badges on selected rows have a clean white background that stands out from the blue selection highlight.

  • 4 masking modes for retention rules — Retention rules now offer fine-grained masking: Mask Title (hides title only, content visible in preview), Mask Content & Title (hides both), plus purge variants of each. Masking is visual only — the real content is preserved and pasted normally. Intended for password managers (KeePass, 1Password, Dashlane) where copied credentials should not be visible in the clipboard history.

  • Shift+Arrow range selection — Hold Shift and press Arrow Up/Down to extend the selection range in the clips table, matching standard table keyboard behavior.

Changed

  • Masking no longer destroys content — Previously, masked clips had their content permanently replaced with bullet characters. Now masking is visual only: the clips table and overlay show MASKED + ●●●●●●●●●● but the real content stays in the database. Paste always outputs the real text. The preview panel shows real content for title-only masks, or a masked notice for content masks.

Fixed

  • Overlay Last Column setting now works — The “Last Column” setting in Settings > Overlay (Time vs Source App) was non-functional. It now correctly switches between showing relative time (2m, 1h, 3d) or the source app name in the overlay’s right column.

  • Overlay scroll follows keyboard selection — Navigating the overlay with arrow keys now scrolls the list to keep the selected item visible. Previously, the selection could move off-screen.

  • Save-on-exit dialog: Skip now works correctly — When closing the app with unsaved capture edits, pressing “Skip” on the save dialog now discards the annotation changes and moves to the next capture. Previously, Cancel accidentally deleted the entire capture from disk.

  • Consistent font across all clip types — IMG and TXT clip rows in the clips table now use the same font.

  • Right-click on Trash / By App no longer opens DevTools — Right-clicking tree items in the “By App” section or “Trash” now suppresses the browser default context menu.

  • Glue separator respected in right-click menu — Gluing clips via the right-click context menu now uses the separator configured in the toolbar instead of always using a newline.

  • Clipboard syncs immediately on edit and revert — Editing a clip or reverting to original now updates the system clipboard instantly. Works from both the preview panel and the right-click context menu.

  • F2 rename no longer flickers — Pressing F2 to rename a clip no longer causes the table to flicker or shift row height.

  • Selection moves to next row after delete — Deleting a clip now selects the next row below (or the last remaining row if the bottom row was deleted).

[0.4.7] - 2026-03-26

Added

  • Tree Section Controls — Customize the sidebar tree in all three workspaces. Hide sections you don’t need via the gear icon or right-click. Sections with many items (By App, Tags, App Profiles) show only 5 entries by default with a “Show more” link to expand. Section headers display quick-filter icons (type badges, app chips, colour dots) — click to filter directly. Reorder sections via up/down arrows in the gear popover. All preferences persist across sessions.

  • Flash Capture (Burst Mode) — Take a rapid series of screenshots with a single hotkey press (Ctrl+Alt+F). Configurable count, interval, and timeout. Keyboard controls during burst: B=pause, F=single-step, S=skip, R=reset, H=hide panel, +/- adjust speed. Captures are automatically grouped in the ThumbnailStrip as collapsible burst series. Uses a custom name or auto-generated timestamp.

  • Burst Group Column — Flash capture groups are now stored in a dedicated burst_group column instead of creating tags. Existing flash-* tags are migrated automatically. The tag list stays clean — burst grouping is internal, not a user-visible tag.

  • ThumbnailStrip Multi-Select & Delete — Ctrl+click to toggle individual captures, Shift+click for range select, Ctrl+A to select all. Delete key opens a confirmation dialog. Right-click context menu with tag management (submenu flyout, color picker, new tag inline).

  • Glue Title & Virtual Folder — Gluing clips now auto-generates a title like “Glue (3 Clips)” so glued clips are easy to identify. Default virtual folders (Pinned, Glued, Edited) are seeded on both fresh and existing installs.

  • Glued & Edited in Categories — The tree sidebar now shows Glued and Edited entries in Categories with live counts. Click to filter. Right-click any category entry to hide it; click the eye icon on the header to restore hidden entries.

Fixed

  • Tree context menus not appearing — Right-click menus in the sidebar tree (Hide Pinned, Hide section) were invisible because the sidebar container clips overflowing content. Menus now render via Portal and work reliably.

  • F2 Rename grid flicker — Pressing F2 to rename a clip no longer causes the entire table to flicker. The inline edit input now only re-renders the affected row.

  • Keyboard nav after rename — After confirming or cancelling an inline rename (Enter/Escape), arrow key navigation now works immediately without needing to click the table first.

[0.4.6] - 2026-03-26

Added

  • Diff Inline Edit — Edit text directly in the diff viewer. In side-by-side mode, click the pencil button to turn one side into an editable text area. The other side shows the live-updating diff as you type. Version diff: right side is editable. Compare diff: click either side to switch. Merge buttons still work during editing.

  • Image Zoom in Clips Preview — When viewing an image clip, a zoom toolbar appears above the image with +, -, Fit, and 1:1 buttons plus a percentage label. Scroll wheel zooms, click-and-drag pans when zoomed in. Zoom resets when switching clips.

  • Captures Zoom Controls — The View ribbon tab zoom buttons (+, -, Fit, 1:1) now work. Zoom in for precision annotation work, fit to canvas for overview, or view at actual pixel size.

Fixed

  • OCR text now saved as Clip — Running OCR on a screen region now creates a Clip entry in history (source: “Blue Synergy · OCR”). Previously the text was only copied to the clipboard and lost once you copied something else.

  • OCR “Enabled” toggle enforced — The Enabled checkbox in Settings > OCR now actually controls whether OCR works. Toggling takes effect immediately — no restart needed. When disabled, the hotkey is unregistered and the capture command is blocked.

  • Instant window hide during capture — App windows now disappear instantly when taking a screenshot, with no fade animation. Previously the Windows DWM fade-out could appear in the captured image.

[0.4.5] - 2026-03-25

Added

  • Layout Modes A/B/C for all Workspaces — All three workspaces (Clips, Triggers, Captures) now support three layout modes. Layout A shows all panels side by side, Layout B collapses the tree by default, and Layout C stacks panels vertically with a flip button to swap order. Switch via the toolbar buttons (A/B/C), View menu, or Captures ribbon View tab. All preferences (layout, flip, panel sizes) persist across sessions.

  • Triggers Multi-Select — The Triggers table now supports Ctrl+Click, Shift+Click, and Shift+Arrow for multi-selection. Delete key, toolbar button, and context menu all work with multiple triggers selected. Multi-selected rows show a teal tint highlight.

  • Triggers Context Menu Overhaul — The right-click menu now matches the Clips pattern: Tags appear in a submenu flyout with checkmarks, tag recoloring via ColorPalette, and inline new-tag creation. Delete shows a count for multi-select. Fire, Enable/Disable, and Mark Obsolete are available for single selection.

  • Captures Tree Toggle — The View ribbon tab in Captures now has a Tree group with a button to show/hide the category tree panel.

  • Triggers Editor Splitter — The splitter between the trigger list and workflow editor now has a visible drag handle with a click-to-collapse arrow, matching the Clips preview splitter pattern. Editor visibility persists across sessions.

Changed

  • Default Theme — New installations now default to the Steel Blue theme instead of Teal. Existing users keep their configured theme.

  • Triggers Menu Bar — Triggers now uses GlobalMenuBar (with dropdown submenus) instead of the flat MenuBar. Includes a View menu with Layout A/B/C switching.

Fixed

  • Layout B crushed to 22x20px — A CSS class collision between the layout button class .lb and the body class .body.lb caused Layout B to shrink to 22x20 pixels in all workspaces. The button class was renamed to .lbtn.

  • Triggers layout modes had no effect — The layout CSS targeted Clips-specific class names (.cl-list-panel, .pv) that don’t exist in the Triggers workspace. Layouts now use generic .lo-stack wrapper classes shared by all workspaces.

  • Captures had no layout switching — The Captures workspace was missing the LayoutSwitcher component entirely. Layout buttons are now in the View ribbon tab, and View > Layout menu items are available in the GlobalMenuBar.

  • Multi-select row highlight only worked in Clips — The .sel-multi CSS was defined only in clips.css. It’s now in design-system.css so multi-select highlighting works in all workspaces.

  • English OCR bundled — The installer now ships with the English Tesseract language pack (eng.traineddata). OCR works immediately after install — no download required. Additional languages (German, French, Spanish, and more) can be downloaded inside the app under Captures → OCR Settings. The installer shows this hint on every install.

  • Factory Reset — Blue Synergy can now be reset to a clean install state. Use --factory-reset from the command line to wipe everything, or --reset=config,db,captures,backups to remove only specific parts. The Windows installer and uninstaller both offer checkboxes to remove user data during reinstall or uninstall.

Fixed

  • OCR language pack download feedback — The language dropdown in the Captures ribbon now shows which packs are installed (✓ English) and which need downloading (German ↓). Selecting a not-yet-installed language shows a “Downloading…” toast and disables the dropdown until complete. Success and failure are both reported as toasts. Previously the download happened silently with no indication of progress or errors.

  • OCR result and error feedback — After drawing an OCR selection, the result is now shown as a toast in the main window: “OCR: N characters copied to clipboard” on success, or a red error toast explaining what went wrong (e.g. language pack not installed, Tesseract unavailable). Previously all OCR failures were silently swallowed.

  • App crash when copying image content — Copying bitmaps, palette data, or enhanced metafiles to the clipboard could corrupt the native heap, causing a STATUS_HEAP_CORRUPTION crash. The crash was non-deterministic and appeared unrelated (e.g. during fast scrolling or app start) because heap corruption is detected late. These clipboard format types are now correctly skipped during capture. An additional safety check logs a warning for any other unexpected non-memory handle before it can reach unsafe code.

  • OCR language packs left behind after uninstall — Downloaded language packs (e.g. deu.traineddata) were not removed when uninstalling Blue Synergy, because they are downloaded after install and not tracked in the installer manifest. The uninstaller data cleanup dialog now includes a “Remove downloaded OCR language packs” checkbox. The reinstall dialog offers the same option.

  • Installer data reset had no effect — The “Reset database / configuration / captures / backups” checkboxes in the installer and uninstaller were silently deleting the wrong folder (AppData\Local\blue-synergy) while Blue Synergy stores all user data in AppData\Roaming\blue-synergy. Checking any of these boxes left all data intact. The correct path is now used.

  • Version History rendering — Keyboard shortcuts in changelog entries (e.g. F2, Ctrl+D, Escape) now appear as styled key badges instead of plain code. Bold text, inline code, and italic are rendered correctly. The Unreleased section is no longer shown to end users.
  • Version History font size — Changelog text now uses 13px to match the sidebar headers, which also improves ClearType rendering on Windows.

[0.4.4] - 2026-03-23

Added

  • Configurable Overlay Position — The Quick Overlay can now appear at 7 different positions (Center, Top Left, Top Center, Top Right, Bottom Left, Bottom Center, Bottom Right) on any monitor. Choose “Follow cursor” to open it on whichever screen you’re working on, or pin it to a fixed monitor. Settings > Overlay > Position.

  • Beta Expiry Notice — The Update Check dialog shows an orange banner when the beta period expires (2026-06-30). Check/Download buttons are disabled after expiry. The About dialog shows the expiry date (or “EXPIRED” in red). The app itself continues to run normally.

[0.4.3] - 2026-03-23

Fixed

  • Auto-Update Public Repo — Switched the releases repo to public to avoid embedding a GitHub PAT in the binary (security risk: classic PAT with repo scope exposes all private repos). Update checks now use direct CDN downloads — no API authentication needed.

  • Download & Install — The “Check for Updates” dialog now has a Download & Install button that downloads the NSIS installer and launches it in silent mode (/S). No manual download or browser needed.

  • Changelog Embedding — Fixed include_str! path that was reading a stale duplicate CHANGELOG.md from src-tauri/ instead of the project root. All versions now appear correctly in Version History.

  • What’s New Filter — Changed from inclusive (>=) to strict (>) filter so the current version’s entries only appear in Version History, not in What’s New.

[0.4.2] - 2026-03-22

Fixed

  • About Dialog Version — The About dialog now shows the actual app version dynamically instead of a hardcoded “0.1.0”.

  • ESC to Close Dialogs — The Update Check and About dialogs can now be closed with the Escape key.

  • Auto-Update for Private Repos — The update checker now uses the GitHub API with asset streaming to download the manifest from private repos. Previously it used a browser-style URL that always returned 404 for private repos.

[0.4.1] - 2026-03-22

Added

  • Clip Edit Versioning — Editing a clip now automatically preserves the original content. An amber “edited” badge appears on the type column and in the preview status bar. Revert to the original via the preview toolbar, context menu, or discard all changes at once. Diff to Original (preview toolbar, context menu, or Ctrl+D) opens the Diff Viewer comparing original vs. edited content. Star-filter *edited=true/false lets you search for edited clips. View > Show Edited Badge toggles the orange indicator. DB migration 0.4.1.

  • Repeat Last Capture — Instantly re-capture the last used rectangular region without opening the Region Selector. Hotkey: Ctrl+Alt+L (configurable in Settings > Captures). Ribbon button “↻” in the Screenshot group. Falls back to fullscreen when no region was captured in the current session. Toast notification shows capture method and dimensions. Region memory is cleared on app startup for a fresh start each session.

Fixed

  • Diff Viewer Ignore Case — Toggling “Ignore case” in the Diff Viewer no longer displays lowercased text. The diff engine now uses preprocessed text only for comparison but shows the original content.

  • Diff Viewer Whitespace Default — Ignore-whitespace is now enabled by default to avoid false positives from line-ending differences.

  • Ctrl+D Toggle — Pressing Ctrl+D a second time now closes the diff and returns focus to the clip list.

[0.4.0] - 2026-03-22

Added

  • Trash / Papierkorb — Deleting a clip or capture now moves it to a per-module Trash instead of permanently removing it. Each module (Clips, Captures) shows a Trash node in the Tree Panel with a live count badge. Click to browse trashed items; the Delete button becomes Restore, and the context menu adapts accordingly. A global Trash window (File > Open Trash…) shows all trashed items across modules with Restore and Delete buttons per item. Edit > Empty Trash clears a module’s trash; the global window has per-tab Empty buttons. Expired items are auto-purged on startup (configurable retention: default 30 days). Settings > Maintenance > Trash lets you toggle soft-delete, set retention days, and control auto-purge. Capture image files stay on disk until permanent delete.

[0.3.1] - 2026-03-22

Added

  • Factory Reset — Blue Synergy can now be fully reset to a clean state. Use --factory-reset from the command line to wipe everything, or --reset=config,db,captures,backups to selectively delete specific data. The Windows installer and uninstaller also offer checkboxes to remove user data during reinstall or uninstall.

  • Version History in Update Check — The Help > Check for Updates dialog now shows a full Version History section below “What’s New”. When already on the latest version, the dialog no longer shows an empty section but a clear “You are up to date” message.

Fixed

  • Diff Viewer Focus — Opening Ctrl+D now auto-focuses the Diff Viewer so keyboard shortcuts (Esc, Ctrl+Z) work immediately. Closing the diff returns focus to the clip list.

  • Thumbnail Strip Arrow Keys — Navigate captures with ArrowLeft/ArrowRight in the thumbnail strip. Wraps around at the edges. Auto-scroll follows the selection.

  • Preview Pane Keyboard Resize — Ctrl+ArrowLeft grows, Ctrl+ArrowRight shrinks the preview pane by 50px per press. Works in both Clips and Triggers workspaces. Respects the same min/max limits as mouse resize.

  • F6 Pane Focus Toggle — Press F6 to jump between the clip/trigger list and the preview/editor pane. Skipped when typing in an input field or CodeMirror editor.

  • Table Scroll Behind Sticky Header — Arrow key navigation in the clip list no longer scrolls rows behind the sticky column headers. Rows stay fully visible.

  • Ctrl+A in Input Fields — Ctrl+A inside an input or textarea now selects that field’s text instead of selecting all clips in the table.

  • Changelog UI — Improved font rendering, antialiasing, and formatting in the in-app changelog viewer. Unreleased section is hidden from end users.

[0.3.0] - 2026-03-21

Added

  • Installer & Auto-Update — Blue Synergy now ships as a proper Windows installer (.exe). Pushing a version tag automatically builds and publishes the installer. Installed copies check for updates via Help > Check for Updates and show a download link when a newer version is available.

  • Clip Diff Viewer — Compare 2 text clips with word-level highlighting. Trigger via toolbar (⇔), right-click > Compare, or Ctrl+D. Side-by-side and unified views (auto-switch by pane width). Merge individual lines (→) or entire blocks (»), Ctrl reverses direction. Undo with Ctrl+Z during the diff session. Options: ignore whitespace, ignore case, ignore regex pattern. Full pane mode to maximize. Dirty flag (*) shows merge count. Confirmation on first merge per session.

  • Word Wrap Toggle — Toggle between word wrap and horizontal scrolling in the editor. Button (↩) in the Text Transform toolbar. Setting persists across restarts.

  • Show Whitespace — Make invisible characters (spaces, tabs, trailing whitespace) visible in the editor. Toggle button (·) in the Text Transform toolbar.

  • Glue Separator Flyout — Choose the separator when gluing clips together: None, Newline, Tab, Space, Divider, or Custom. Small ▾ arrow next to the Glue button opens the picker. Selection is saved.

Fixed

  • Clip Title in Table — Titles now show multiple lines as preview (separated by |) instead of just the first 120 characters. Empty leading lines are skipped. Hover shows the full title as tooltip.

  • Split & Glue Buttons — The Split button is now visible in the toolbar. Both buttons are grayed out when the action is not possible (Split: no clip selected, Glue: fewer than 2 clips).

  • Overlay: Long App Names — Source app names that are too long for the column are truncated with .... Hover shows the full name.

  • Source App Detection — Now uses the clipboard owner (the window that actually set the data) instead of the foreground window. When a window title looks like a document name (e.g. [untitled 4 *]), the process name is shown instead. Reduces false attributions from overlay tools like ZoomIT.

  • Rename Clip with F2F2 on a selected clip opens an inline text field for renaming. Double-clicking the title also works. Enter saves, Escape cancels. Also works for image clips.

  • Flexible Preview Pane — The preview splitter can now be dragged up to 70% of the window width. Dragging below the minimum size collapses the preview entirely.

  • Content Search with *content= — The star filter now supports *content=searchterm for full-text search in clip contents. Wildcards with * are supported (e.g. *content=SELECT*).

  • Fixed Table Header — Column headers stay visible when scrolling. No more flickering between rows.

  • Content Column Always Visible — The Content column can no longer be hidden via the column context menu. Clip text fills the full column width.

  • Image Clip Pasting — Image clips are now pasted as actual images (CF_DIB) instead of file path text. Enter/double-click on an IMG clip pastes the image into the active application.

  • Clean Shutdown — When quitting the app (File > Exit, Tray > Quit), all global hotkeys are properly unregistered and the database is secured via WAL checkpoint.

    </article> </div>

</div>