Skip to content

[FEATURE] Add an Edge Glow + Draft voice visual - #123

Merged
tornikegomareli merged 11 commits into
tornikegomareli:mainfrom
JulianPscheid:feature/waveform-with-draft
Sep 5, 2026
Merged

tornikegomareli merged 11 commits into
tornikegomareli:mainfrom
JulianPscheid:feature/waveform-with-draft

Conversation

@JulianPscheid

@JulianPscheid JulianPscheid commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Edge Glow + Draft is a new voice visual that keeps the last eight words of the live draft at 24-point type, centered in the island, with Edge Glow on the silhouette. It is a pick in Appearance, next to Waveform, Edge Glow, and Compact. There is no Chart Line ribbon. Insertion still uses the full transcript; this is display only, so you can watch the words land without giving up the glow. I used Grok and Codex while building and reviewing this.

Closes #120

JulianPscheid and others added 8 commits September 3, 2026 20:06
Keeps Compact's live draft under a slim Chart Line ribbon and wraps the
shape in Edge Glow, without a particle center or the concert waveform
styles. Refs tornikegomareli#120.
The Chart Line shares the text band instead of taking a 24-point strip of
its own, so the words start higher and keep the height that band used.
The live HUD was waiting on a 250ms spring for every recognizer update.
Volatile guesses now paint as they arrive, lighter than committed words,
and the transcriber uses Apple's progressive live preset.
String-interpolating Text views printed their debug description into
the HUD. Committed and volatile words now share one AttributedString.
A status message could keep the previous guess glued on, and Waveform +
Draft's Slide park used a size 24 points too short. Volatile words also
use regular weight so they read as the uncommitted half.

The ribbon had the same problem the volatile text did: it was drawn
whenever Waveform + Draft was picked, not only while a voice visual was
up. A status message renders with the session's settings and no visual,
over a level history that only a session start clears, so an error
arrived above a frozen squiggle of the words that had just failed to
insert, on a band 24 points taller than any other visual's message. The
gate is a static now, so a test can hold it there.

Grow Down sprang on a character count, one step per 40, but wrapping
follows rendered width — roughly 90 characters to a line — so the spring
fired where nothing had moved and the island snapped where it actually
grew, and a volatile guess crossing a boundary back and forth fired it
again for nothing. It springs on the draft itself, and a transaction
holds the glyphs out of that animation, which is what the count was
there to do.

Pausing the edge glow for a dead microphone skipped the beam rather than
pausing it: the sweep reads elapsed wall-clock time and sweepStart only
moved on a session start, so a recovered microphone resumed somewhere
else on the silhouette. It absorbs the quiet interval now. The concert
Chart Line had the older half of the same bug — its timeline never
paused at all, so the dead-mic amber kept scrolling when it is meant to
be motionless. Both Chart Lines read one silver from HUDVisualTokens.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EpgExpqh8faqvAnRiBZHb6
hide() pins isDismissing so the shape does not resize while it slides away,
and claim() cancels that order-out, so a later showMessage inherited the
retract pin. Waveform + Draft then drew the last session's audio above a
band 24 points taller than any other visual's message. showMessage now
clears the retract pin and the shaping caption; the ribbon stays for
listening, retract, and shaping, and leaves with the status line.

Grow Down is keyed on a coarse character step again. Wrapping by rendered
width is real, but keying the spring on every volatile string put new
words behind a layout transaction; glyphs still opt out of that spring.

A dead-mic Chart Line keeps the paused timeline's progress instead of
snapping a sample slot. Edge Glow subtracts an open quiet interval from
elapsed time so the first unpaused frame does not jump. The 12-point
ribbon uses most of its strip and square-root samples, because the concert
0.75-point rest lift flattened quiet speech into a shaking straight line.
Waveform + Draft keeps one 18-point line of recent tokens instead of
wrapping the full draft, and Settings can hide the Chart Line so the
live draft sits in the glow on its own. Insertion still uses the
full transcript.
Waveform + Draft now centers the recent-word line on the housing-plus-stage
island, keeps per-word identity so only new and departing tokens slide, and
clips the oldest words when the line is wider than the shape instead of
ellipsizing each one. Finalizations that merge or rewrite a token snap in
place.
@JulianPscheid

JulianPscheid commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor Author

Demo video of the PR. I've since fixed the extra ellipses showing up.
https://github.com/user-attachments/assets/d88ea1fc-978d-456e-ab0e-f22818533916

The extra Compact flag was the same predicate as the leading-draft layout,
so it never hid the indicator. The ribbon-over-words overlap is the
feel-tested Waveform + Draft look, so it is called out as kept.
@tornikegomareli tornikegomareli self-assigned this Sep 5, 2026
@tornikegomareli tornikegomareli added the enhancement New feature or request label Sep 5, 2026

@tornikegomareli tornikegomareli left a comment •

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this

Two things I want changed before it goes in

The visual is called Waveform + Draft, but what it draws is the edge glow. usesEdgeGlow returns true for it, it takes the glow palette, the status ghost picks up the glow accent, and the drop HUD strokes with it. The waveform is the part that can be switched off. If I turn the Chart Line ribbon off, the visual still stands, which tells me the waveform is not what it is made of. Please rename it to Edge Glow + Draft.

The second is the Chart Line ribbon toggle. Your own reason for not offering the waveform style picker here is that this composition is one designed Chart Line, and I agree with that. But then the ribbon should not be optional either. A designed composition does not keep its defining element behind a switch. Either it is always there and the setting goes, or the version without it is a different visual. I would drop the toggle and the waveDraftShowsRibbon key with it. That also takes Appearance from four conditional rows back to two, which is the direction I want that pane going.

The rest reads fine to me. It is current with main and merges clean, so this is just the two changes.

The silhouette is the glow, not a concert waveform. The Chart Line ribbon
and its Settings toggle are gone: this visual is the version without it.
A stored Waveform + Draft pick still loads as Edge Glow + Draft.
@JulianPscheid JulianPscheid changed the title [FEATURE] Add a Waveform + Draft voice visual [FEATURE] Add an Edge Glow + Draft voice visual Sep 5, 2026
@JulianPscheid

Copy link
Copy Markdown
Contributor Author

Renamed to Edge Glow + Draft and dropped the Chart Line. This is the version without the ribbon, so the toggle and the stored key are gone. A pick that was saved as Waveform + Draft still loads.

Unknown picks already fall back to Waveform. This visual only exists as
Edge Glow + Draft.

@tornikegomareli tornikegomareli left a comment •

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One small thing, not blocking. HUDRecentDraftWindow.committed, .volatile and .displayString are never read outside tests, the view renders visibleTokens. The split is also the one fragile part, since the boundary offsets by committed.count into the joined string and mis-splits when a volatile chunk opens with a combining mark. Your own test already asserts visibleTokens.map(.text).joined() == displayString, so displayString could be defined that way and the two stored properties could go. Happy for that to be a follow-up.

Merging. Nice work.

@tornikegomareli
tornikegomareli merged commit fe23809 into tornikegomareli:main Sep 5, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Show live draft together with the waveform and Edge Glow

2 participants