Repository navigation
Conversation
…ervices Port of the Omarchy Quickshell build to Windows as an Electron app: - plugin/core runs unchanged (ranker, frecency, calculator, root search, schema, migrate, rpc); Paths gains resolveWindows, Schema the Windows config keys (hotkey, fontFamily, agentCommand, gapsOut, cornerRadius) - ui/: px-for-px DOM port of plugin/ui (LauncherWindow state machine, ResultRow, ActionPanel, InfoPanel, Alert, KeyHint, PointerMoveGate) - src/theme/: port of omarchy-theme-color/-set-templates and the Color/Style/Border singletons; Tokyo Night bundled through the real shell.toml.tpl, omarchy.ttf + JetBrainsMono Nerd Font for exact glyphs - src/: JsonStore, CalculatorData (ECB rates + Intl zones), Start Menu app library, backend RPC surface, host adapters - main.js: overlay window on the cursor's monitor, Alt+Space hotkey, named-pipe CLI, paste via keybd_event, toast HUDs - bin/oma-cast.ps1: toggle/show/hide/run/call/doctor/install - tests: theme golden values, store migrations, backend round-trips
The bash/Omarchy-tooling preflight tests have nothing to exercise on a Windows runner (the port's hand-off is covered by electron's backend tests). TEST_RUNNER lets forks without the WarpBuild app use ubuntu-latest.
Windows keeps foreground activation locked: a freshly shown frameless window is often painted without keyboard focus, so keystrokes stayed in the previous app. Now show() grabs focus in three steps: moveTop+focus, a retry after Windows answers, and — if still refused — the documented foreground-lock break (dummy ALT keybd_event + SetForegroundWindow with the real HWND) via PowerShell. The renderer double-checks with document.hasFocus() and requests the steal itself if needed. Also: everything now logs to %LOCALAPPDATA%\oma-cast\logs\main.log (main + renderer console, hotkey registration state, focus transitions), so a misbehaving install can be diagnosed from one file.
Icons: Chromium memory-maps fonts and mmap cannot pass through the
asar patch, so every bundled Nerd Font glyph rendered as tofu in the
packaged exe. electron-builder asarUnpack now puts assets/ on disk as
real files (app.asar.unpacked) while the file:// URLs keep resolving;
the CI layout check asserts both.
- File search (SPEC §8.6 slice): FileSearch.js (name-then-path-then-
recency matching, shared), file-index.js (chunked home walk, 100k
cap, excludes, hidden opt-in, disk cache, 10-min re-walk), a Files
section after Results, Open / Reveal in Explorer / Copy Path
- unduck.link as the third web fallback + quicklink (q={query})
- Settings view (SettingsView.js): every window/hotkey/search/calc
setting as a cycling row; hotkey writes config.json and
re-registers immediately — the Phase-2 stub closed here [D]
- Kill Process: PowerShell snapshot sorted by working set, destructive
confirm, synchronous taskkill /F, Reveal + Copy PID
- placeholders, copy shortcuts (Ctrl+Shift+C covers path/pid), loading
empty state; docs updated
…e and publishes it with curated notes
The Windows equivalents of Omarchy's system actions: shutdown/restart go through the same destructive confirmation alert, then schedule shutdown.exe /s|/r /t 15 — the success toast carries a Cancel action (system.cancelPowerShutdown → shutdown /a) for the whole 15 seconds. Sleep confirms nothing, closes the launcher first, and suspends via rundll32 SetSuspendState 400 ms after the unmap (hibernates instead if hibernation is enabled — Windows quirk, documented). Power actions skip frecency so they never crowd Suggestions. All three glyphs verified in the bundled Nerd Font.
The publish step wrote a fixed body, so v0.1.1 shipped with v0.1.0's 'first release' text and never mentioned Shut Down / Restart / Sleep. Now the notes append the commit subjects since the previous tag (full checkout for history), an existing release's notes are refreshed on a re-run, and the stale v0.1.0 default on workflow_dispatch is gone.
A pushed "Windows Settings" view (electron/src/windows-settings.js): 71 Settings-app deep links grouped by category (System … Windows Update), filtered by title/category/URI/keywords, ↵ opens the page through shell.openExternal with a HUD line. It also leads the in-app Settings view, so "settings" reaches themes, display and Windows Update without leaving the launcher. Rows carry the standard Open action and a Setting/Category/URI about panel. Built-ins now carry platform: "windows"; plugin/Backend.qml skips them on the shell side, which also drops Kill Process from a build where nothing implements its view. backend.VERSION now reads electron/package.json, so doctor/system.info cannot drift from the installer (it still said 0.1.0). Tests: page-table invariants (no duplicates, sections cover every page), the builtin glyph/push, the Settings-view lead row, filtering, open dispatch and the about panel.
Caret: style.css ports LauncherWindow.qml's SequentialAnimation on the caret's opacity — 530 ms solid, 530 ms hidden, step-end, on #caret and the argument pills. The README promised this blink; the port never had the animation. Icons: powershell.exe joins everything after -Command into one command string, so the trailing linkPath/png arguments were appended to the last statement of the extraction script, $args never bound and every Start Menu icon silently failed — rows showed an empty icon column. The paths are now interpolated into the script (PowerShell-quoted), a .lnk resolves to its target before ExtractAssociatedIcon, URLs are encoded, and a row with nothing extracted falls back to U+F2D0 instead of a blank box. Themes: the place for themes is %APPDATA%\oma-cast\themes\<name>\ colors.toml (electron/src/themes.js — bundled first, then the user's, a directory with a colors.toml is a theme, optional per-theme shell.toml override). config.json gains "theme"; the Theme row in the Settings view lists what is on disk and cycles it, and the change goes out as settings.configChanged so the renderer rebuilds the theme and repaints in place. themes.list / themes.resolve RPCs for the CLI.
ui/app.js built the backend with paths/apps/host only, so `processes` and `fileIndex` were null in the shipped app: the Kill Process view filtered an empty array (no listing, no search) and the Files section never appeared. The unit tests inject both services, which is why every suite stayed green off-Windows. The window now creates them and hands them over: a file index rooted at fileSearchScopes (or home) with its cache under the cache dir, and a process snapshot that excludes this pid plus anything running from process.execPath — main, GPU and renderer all share the exe, so the launcher can no longer list itself and be killed from its own view. Also: host.onVisibility never called backend.visibility(), so a show never refreshed exchange rates, re-scanned the Start Menu or re-walked files when stale — it does now. Both PowerShell snapshot scripts force [Console]::OutputEncoding to UTF-8 before emitting JSON, otherwise non-ASCII names arrive in the OEM codepage.
The left-ellipsis CSS trick (direction: rtl + text-align: left) on #query, .pill span and .panel-search span flips the paragraph direction, so the bidi algorithm reorders anything whose first strong character is not LTR: typing "1 rem to px" displayed "rem to px 1". Text.ElideLeft is now a JS helper (electron/src/text.js): the cut happens on the logical string — the front goes, the tail stays, "…" marks the cut — and the elements stay LTR. Applied to the query, the argument pills and the action-panel filter, so the elide matches Qt instead of approximating it with CSS. Same pass: the pill caret measured pill.clientWidth on a detached element (always 0) and parked itself left of the text; it uses the width it just set now. Tests: elide order/room/mark/edge cases plus a guard that no direction:rtl survives in the UI stylesheet.
The Omarchy token model (live QML singletons, the Windows theme engine, colors.toml / shell.toml schemas, layout scaling, contrast) lives in docs/THEME_SPEC.md; SPEC 10.4 keeps the pointer and the deltas that matter for the plan, and the 15-field Raycast theme model stays as a superseded reference.
…pps, switch to an open window (1) Open at Login: a Settings row over config.json's openAtLogin; main turns it into the real HKCU Run entry (app.setLoginItemSettings) at launch and on every config change — the backend's config watch notifies main too, so an edit by hand or by the CLI also lands. oma-cast.ps1 install now writes that key instead of planting a Startup shortcut, and both drop the legacy .lnk so two entries can never race at login and toggle the window open on the desktop. (2) Focus hand-back: show maps with showInactive so a resident PowerShell helper (ping / getfg / focus, ~10 ms warm instead of a 300 ms spawn) can sample the window that had the foreground; hide hands it back with SetForegroundWindow — only while we still hold focus, since on blur the clicked window already won — and the paste path waits for the hand-back so Ctrl+V lands there. A cold helper means no wait and stock Windows behaviour: focus never waits on the capture. (3) Missing apps (Notion): the scan covers both Desktops and Store/MSIX apps (Get-StartApps, falling back to shell:AppsFolder — they ship no .lnk anywhere); uwp: rows launch through explorer shell:AppsFolder\<AppID> and show the generic window glyph. system.info.applications + the doctor's applications line print the count so a short list is visible. (4) Take me there: Enter on an app that already has a window switches to it instead of spawning a second instance — exe name from the shortcut target → Get-Process → MainWindowHandle → SW_RESTORE → SetForegroundWindow through the helper's new app command. Main drops the hand-back target on receipt, so the close that follows leaves the app with focus, and the renderer's 2.5 s settle timer guarantees the launch fallback can never be swallowed. 8 new tests; suites green (154 port / 104 core). CLAUDE.md status updated — and carries the theme-spec table row from the docs commit.
actions/checkout on windows-latest checks out with core.autocrlf=true, so main.js has CRLF there and /prevFh = null\n…/ matched nothing, while the same suite passed on Linux. The pattern accepts \r?\n now — the rule for file-content asserts: never anchor a bare \n across a line ending.
…real exe names Live report: Enter still opens a second instance on the machine. Between us and the answer were three blind spots plus two lookup holes: - nothing was logged: main now logs every request and the helper's answer (app switch: X -> ok 1 / none / no answer) and the backend logs which exe it derived, asked or launched — both land in main.log. - the handler whitelisted [A-Za-z0-9 ._+-]; any other character silently answered "launch". It sanitises line breaks and length instead. - the helper had 1500 ms — a cold PowerShell spawn could blow the budget and time out into a duplicate; 2000 ms still settles inside the renderer's 2.5 s fallback. - Store/MSIX rows never asked: the package family prefix is now the guess at the process name (Notion_…!App -> Notion); a wrong guess answers none and launches exactly as before. - wrapper shortcuts (explorer/cmd/… targets, the real app lives in the arguments we do not parse) never ask — they would "find" the desktop. Tests: the family-prefix branch both ways, the wrapper guard, the log line.
…y app switch answered err Root-caused live on the Windows box (0.2.1; the log at %LOCALAPPDATA%\State\oma-cast\logs\main.log): "app switch: Obsidian -> err", "app switch: vivaldi -> err", then a launch. The lookup was fine; the helper's type wasn't there. A C# attribute covers only the NEXT declaration, so [DllImport] applied to GetForegroundWindow() alone and Add-Type — warnings as errors — refused the whole class. [Win32.Input] never existed: getfg/focus/app all threw into the catch and printed err, and err reads as "not running", so every Enter launched a duplicate. The same root cause had killed the close hand-back (getfg always failed, prevFh was never captured — zero "foreground before show" lines in the log) and the one-shot foreground steal, which was doubly broken: it also passed its HWND as a trailing -Command argument, which powershell.exe joins into the script text instead of binding to $args — the apps.js lesson again. - every extern carries its own [DllImport] (helper: six, steal: two) - focusScript(hwnd) interpolates a validated integer handle; an unusable one logs and bails - regression test: DllImport count == static extern count over main.js code (comments stripped) and no $args in code - docs: logs live at %LOCALAPPDATA%\State\oma-cast\logs\main.log, cache at %LOCALAPPDATA%\Temp\oma-cast (resolveWindows mirrors XDG state/cache) — the paths in README and the release notes never existed, which is why the log took a find to locate Proven on the box through the real helper, no desktop disruption: ping/getfg/focus <fg>/app Obsidian -> pong / fg 330594 / ok 1 / ok 1, an unknown name -> none, focusScript executed clean.
…-known apps gain aliases
The launcher was a fullscreen transparent overlay, which paints the whole monitor opaque black wherever compositing fails (VMs, RDP, some drivers). It is now a card-sized window centered on the monitor under the cursor: the renderer reports its card size after every layout and main resizes to fit, so the desktop stays visible around the card.
Walk the Start Menu roots (not just Programs) and append the App Paths registry (HKLM + HKCU) as a safety net, skipping rows whose exe a shortcut already covers. Every scan logs its entry count next to the doctor line.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.