Skip to content

feat: Large Type — show the query across the screen (Ctrl+L) - #39

Open
AfonsoNeto wants to merge 3 commits into
typecraft-dev:mainfrom
AfonsoNeto:feat/large-type
Open

AfonsoNeto wants to merge 3 commits into
typecraft-dev:mainfrom
AfonsoNeto:feat/large-type

Conversation

@AfonsoNeto

@AfonsoNeto AfonsoNeto commented Oct 25, 2026 •

Copy link
Copy Markdown

What

Refreshed onto the restructured omacast tree (flattened layout + the flea-search backend) after the Nov 2 merges — same feature, rebased and re-verified.

Type a message in the launcher, press Ctrl+L, and it appears in very large characters across the whole screen — Alfred's Large Type, which Raycast only covers through a third-party extension. Esc, a click, or Ctrl+L again returns to the launcher with the query and focus intact, ready to edit.

Large Type overlay

The full interaction loop (type → Ctrl+L → Esc → edit continues → Ctrl+L again):

Large Type demo

A second entry point: a "Show in Large Type" row under the existing "Use "" with…" fallbacks (the same query-level mechanism as Search Google / Search DuckDuckGo). Happy to drop that row if you'd rather keep the root list untouched and shortcut-only.

How

  • core/LargeType.js (new): the testable policy — displayText() (blank/whitespace input becomes a no-op; content preserved exactly, markup included) and fitRange() (clamped pixel-size bounds so fitting can never run away).
  • ui/LargeTypeOverlay.qml (new): an opaque, theme-following surface inside the existing launcher window — no second layer surface, so dismissal can't orphan anything. Text uses Qt's bounded Text.Fit between the core bounds, Text.PlainText (user input is never markup), wrapping with WrapAtWordBoundaryOrAnywhere so long unbroken strings degrade gracefully.
  • ui/LauncherWindow.qml: the Ctrl+L binding (verified unused — no plugin binding, and no Hyprland bind on L in Omarchy defaults), a largeType outcome handler for the fallback row, and state reset in closePopups() so hide/show cycles never leave the overlay stale.
  • core/RootSearch.js / Backend.qml: the fallback row and its { largeType: query } outcome; getActions/getItemInfo work through the existing fallback paths.

Blank or whitespace-only queries are a no-op — never a blank takeover.

Testing

  • node --test tests/*.test.js: 146 pass, 0 fail on the new tree (3 skips are the Rust-helper integration tests, identical without a built omacast-search); new tests/largetype.test.js covers the display policy and fit bounds, and the root-search tests cover the row's placement, actions, and absence on the empty root and in submenus.
  • CI parity: bash -n on all four scripts, manifest JSON check; also bin/build-search + the search-integration suite locally.
  • Live on Omarchy (1920×1080, wtype + grim screenshots, re-verified on this tree): short text, accented Portuguese, literal <b>Hello</b>, a 300-character unbroken string (renders wrapped within margins, no crash), blank/whitespace no-ops, Esc restoring query + focus, Ctrl+L toggling, hyprctl layers showing exactly one omacast surface while shown and zero when hidden. Overlay follows the live theme.
  • Security pass on the diff: the overlay renders PlainText only, performs no exec/network/eval, and Escape stays reachable in every state.

Notes

  • No new dependencies; QML + plain JS per the ground rules.
  • Follow-ups deliberately out of scope: clipboard/selected-text sources, calculator result, configurable styling.
  • Pre-existing observation, not from this change: queries over FleaSearch.MAX_QUERY_LENGTH (256) bypass the native matcher and re-run the full synchronous JS search on every keystroke, so very long queries queue seconds of work. Measured live; worth a debounce discussion in a separate issue.

@AfonsoNeto

Copy link
Copy Markdown
Author

Hi — just a friendly follow-up on this one. I saw the big refactor that landed this week (the omacast rename, flattened layout, and the flea-search backend). This PR predates all of that and won't apply cleanly to the new tree anymore.

The feature itself still ports cleanly — the fallback mechanism in core/RootSearch.js survived the restructure, so it's a straightforward move onto the new layout (~250 lines, 3 commits). Happy to rebase and push a refreshed branch if you'd still like the feature; equally fine to close this if Large Type isn't a fit for omacast's direction. Thanks!

Port onto the restructured omacast tree (flattened layout, flea-search
backend). Add fallback:large-type to the root-search fallbacks and answer
its open action with a { largeType: query } outcome for the window.
core/LargeType.js holds the testable policy: displayText (blank input
becomes a no-op, content kept exactly) and fitRange (bounded pixel sizes
for the overlay's Text.Fit). No new dependencies.
Port onto the restructured omacast tree. Ctrl+L shows the current query
across the screen, as Alfred's Large Type does: the card hides and
LargeTypeOverlay paints an opaque themed surface with the text fitted by
Text.Fit between the core bounds. Esc, a click or Ctrl+L again restores
the card with the query and focus intact. The mode resets in closePopups
so hide/show cycles never leave it stale, and blank or whitespace-only
queries are a no-op.
Port onto the restructured omacast tree. Document Ctrl+L and the fallback
row in the README keyboard table and a short section with a screenshot,
and record the feature in the CLAUDE.md status.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant