Commit Graph
5 Commits
Author SHA1 Message Date
gramps 279eb08dea feat(preview): right-click is the menu, zoom is the single-handed gesture
Creator ruling 2026-11-01, and the reason is live-stream ergonomics: no two-handed
chords while a broadcast or recording is running.

- Edit mode: left selects / drags / resizes, right opens the context menu, Ctrl+right
  toggles the zoom box. Chords are acceptable here because editing is a stopped activity.
- Preview mode: left toggles the zoom box, right opens the context menu, and Ctrl+right
  is swallowed outright — handled rather than left to fall through, so Ctrl+right cannot
  open a menu by accident while one hand is on the mouse.

This also removes the old live behaviour where right-click activated the magnifier at the
cursor point (and dismissed it). Zoom in preview is now a plain toggle; if point-zoom is
wanted back it needs a one-button gesture, not a chord.

Build: Release 0 warnings. Debug is currently blocked by the running app holding the exe
(PID 47252) — close it and the Debug build copies normally.
2026-11-01 08:10:04 -08:00
gramps fdb27f0758 feat(ui): gear to the rail, EDIT on the panel edge, preview undo/redo
Three creator directives (2026-11-01), done ahead of the surge.

**Gear moved to the preview rail** — first tab, orange (Brush.Attention), gear icon
only. Left-click opens the same app menu the top bar gear owned (Settings / Bug /
Feature / About), right-click goes straight to App Settings; both behaviours moved
with it, so nothing lost an entry point. TopBar keeps the wordmark and EDIT.

**EDIT right edge aligned to the layers panel.** The work area is margin 8 + a 360px
column, the top bar is padding 16, so the shared edge is 352 inside the bar. TopBar
column 0 is now a fixed 352 grid with EDIT right-aligned in it — alignment by
arithmetic instead of by eye.

**Preview undo/redo: Ctrl+Z / Ctrl+Shift+Z.** Models/PreviewHistory snapshots element
REFERENCES plus geometry, visibility, order and membership — a deep clone would mirror
every property of a dozen element subclasses and quietly miss the next one added.
One snapshot per gesture (pushed at drag/resize start, never in the move loop), bounded
at 50, redo survives multiple undos, cleared on layout load. Gated on EditingActive:
undo while the preview shows program output would rewrite a scene nobody is looking at.

Honest scope, in the type's doc comment: layout edits only. Colour/opacity/border/font
edits are not captured yet, so Ctrl+Z after one of those restores the last layout change.

6 tests in PreviewHistoryTests; 19 pass across it and the neighbouring UI classes; Debug
and Release both build at 0 warnings.
2026-11-01 07:46:10 -08:00
gramps 27fc6fb507 feat(profile): the free budget is pixels and fps, enforced once — with a dev-only release hatch
The paid delta is output quality, so the rule needs to be measurable rather than a word:
921,600 pixels and 30 fps, fail-closed. Models/OutputProfile.cs is that rule as pure
policy — a permitted tier passes through untouched (Pro, or the free tier's own 720p30),
a disallowed one resolves to the best tier the budget allows and carries ITS bitrate, so
a capped user is never offered an 8 Mbps budget for a 720p frame.

Applied once, in BuildEncoderOptions. That is genuinely one place: the stream and the
local recording are two output blocks of ONE ffmpeg process fed by one EncoderOptions,
so there is no second encoder to forget. (commercial.md claimed "both encoders — never
two checks"; the code is stronger than the doc, and the doc is corrected.)

Developer override, as asked: a "Developer mode — all resolutions" checkbox in App
Settings, bound to MainViewModel.DeveloperMode, which feeds HasProOutput. It is not
hidden in a release build — Controls/DeveloperPanel's Page and Compile items are removed
when Configuration != Debug, and OverlayHost adds it at runtime inside #if DEBUG, so a
shipped exe has no BAML for it at all. The setter also refuses the value when
DevBuild.IsDevelopment is false, which is now the single source for that question (the
scoreboard partial had its own duplicate const).

Two traps worth their lines: a `const bool` dev flag makes `if (!Flag) return;` an
unreachable-code warning in one configuration or the other (CS0162), so DevBuild uses
static readonly; and a Condition on an ItemGroup is invisible to a test reading
item.Attribute("Condition") — read the parent.

Tests: 14 pass across OutputProfileTests, AssemblyIdentityTests and StorePackagingTests.
The invariant test is the one that matters: iterate every shipped tier under a free
entitlement and assert none emits more than the budget, so a future 4K tier fails here
instead of shipping to everyone. App builds Debug and Release at 0 warnings.
2026-11-01 07:11:49 -08:00
gramps 565b8dbd6f docs(design): DESIGN.md becomes the visual standard (tokens merged, controls rejected)
Merges the 2026-10-29 Stitch export into the existing 2026-10-26 token sheet and promotes the
file from "redesign exploration" to the normative standard:

- type scale (32→10px), spacing, radii and elevation levels — the three scales the old
  DESIGN.md listed as missing
- meter thresholds: cyan ≤ -12 dB, amber -12..-3, red > -3
- interaction rules: focus ring, hover step, 150ms/90ms easing, no springs

Four export tokens rejected as Material-3 warm-seed artifacts (recorded with reasons):
tertiary #4cd7f6 (kept #38bdf8), outline #ab8986, outline-variant #5b403e,
on-surface-variant #e4beba (kept slate #94a3b8).

Product rulings recorded: #e94560 retired as the app's general accent (blue takes every
interactive role, red is live/record only, wordmark artwork untouched); error gets its own
surface (#93000a) so it cannot be mistaken for on-air red.

The export's dock, four bays, page-nav sidebar, CPU/GPU/NVENC readouts and acrylic blur are
explicitly marked exploratory, not spec — the design principle is a simpler surface, not
hardware cosplay. On-stream output styling stays outside this theme.

Falsified facts fixed in the same commit: product.md brand section now points at DESIGN.md for UI
tokens (MARCOM.md stays the marketing palette), and ui-surface.md no longer calls DESIGN.md an
unreconciled exploration.

Docs-only unit: scope-check run, no build.
2026-10-30 07:41:43 -07:00
gramps a311c8feb1 docs(ai): partition ai.md into five subsystem files (verbatim moves)
ai.md 1,308 → 228 lines. No prose rewritten: every block was moved as-is so
nothing could be lost in translation, then replaced by a pointer.

New files:
- docs/ai/environment.md — LAN/SSH + Gitea push recipe, Windows dotnet
  build/run, test-suite map, hermetic real-MainWindow test rule
- docs/ai/product.md — brand/naming, AI transparency, GPL licensing
  prohibitions, free-forever monetization, auth/account assumptions,
  packaging & distribution
- docs/ai/youtube-api.md — go-live ordering, the broadcast-binding fix, the
  private-only lock, health parsing, end-stream pre-flight, Test mode,
  chat insert shape
- docs/ai/overlays.md — social bar, native alert box (animations, clip,
  ticker), chat box conventions
- docs/ai/ui-surface.md — control surface, scene strip, preview rail,
  hotkeys, broadcast drawer, toasts, transitions, brand logo, launch
  geometry, theme/properties conventions

ai.md keeps the response/derivation rules, the architecture table, the four
existing invariant stubs, and one pointer per moved subsystem.
docs/ai/index.md routes every file with a "read when" column.

References falsified by the move were fixed in the same commit: AGENTS.md
build note → environment.md → Run, and the "Related" footers in
frame-pipeline.md / output.md / capture.md now point at the owning files.

Docs-only unit: scope-check run, no build (no source touched).
2026-10-29 11:05:53 -07:00