TASK 4 ship step 5.5: social bar bug fixes + bar on the live output — direction-snap drag (SocialBarSnap.Decide + ClearValue, local Canvas.Top was overriding the binding), fediverse nodeinfo subdomain probing + load-time heal (settable FediverseSoftware), SocialBarRenderer strip blitted above the flash via a re-read FramePump socialBar seam — 155 tests passing, 0 warnings

This commit is contained in:
2026-08-13 09:29:58 -07:00
parent e72ba71165
commit ac60a26d82
16 changed files with 666 additions and 52 deletions
+28 -1
View File
@@ -407,11 +407,19 @@ seam:** `Func<Scene?>`, `Func<SceneElement, VideoFrame?>` resolver, `Func<Compos
background → `StaticPixelCache.Get(AssetId)`. `BuildCompositorOptions` rounds the VM's `OutputRect*`
doubles to ints — the vertical 607.5 half-pixel crop rounds to a perfectly-centered **608** (`Math.Round`,
ToEven); `BuildEncoderOptions` fills W×H/FPS/bitrate from the tier once the URL provider yields one.
- **Social bar on the output (bar bug-fix branch):** the `FramePump` takes an optional
`socialBar: Func<(VideoFrame? Frame, SocialBarPosition Position)>?` seam, re-read **every frame** (so a
mid-stream position flip applies immediately). The strip is pre-rasterized by `Compositor/SocialBarRenderer.cs`
(WPF glue — WPF glue here is fine because the strip is rendered once per config change on the UI thread,
the resulting immutable frame is then composited pure-CPU by `SceneCompositor`), and `SceneCompositor.Render`
blits it **last — above the branding flash** at `socialBarTop` (0 = top, `SourceRectHeight barHeight` =
bottom) in master space. `MainViewModel` owns the frame (`_socialBarFrame`, rebuilt by `RenderSocialBarFrame`
on load/save/`NotifySocialsChanged`).
- Known consideration: the pump reads the active scene on a background thread while the UI can still edit
it; a concurrent-mutation exception is contained (logged + `Failed` + the pump stops) rather than
crashing. The background thread + video pipeline is the new reality since this step.
### Social bar (TASK 14 — shipped 2026-08-12, plan in TASKS.md)
### Social bar (TASK 14 — shipped 2026-08-12, plan in TASKS.md; bar bug-fix branch 2026-08-13)
A **global bar layer** (never a Source, no sources-list row) that sits over the bottom or top of the
output and carries the creator's social links — content-sized, centered, GREEN glow when ON, top/bottom
@@ -437,6 +445,25 @@ honeycomb fallback — Simple Icons CC0 path data, initials badges gone); nodein
`CancellationToken` (dialog VM owns a CTS; Cancel/X/Save abort in-flight lookups, canceled continuations
never touch slot state).
**Bar bug-fix branch (2026-08-13) — three changes:**
1. **Drag now direction-snaps** — a local `Canvas.SetTop` value permanently overrides the
`{Binding SocialBarTop}` (a binding can never win over a local value), so the old drag left the bar
wherever it was dropped. Now `SocialBarSnap.Decide` (pure, in `Models/Socials.cs`) commits a direction
once the drag passes the ±6px deadzone and rides the edge it's dragged toward; on release
`bar.ClearValue(Canvas.TopProperty)` re-engages the binding before `SetSocialBarPosition`.
2. **Fediverse software self-heal** — the DB row `@gramps@llamachile.tube` had `Software = NULL` because
nodeinfo was only ever asked of the identity domain (a landing page; the real instance is
`mastodon.llamachile.tube`). `HttpSocialValidator.ResolveFediverseSoftwareAsync` now **probes
well-known subdomains** (`mastodon.` → `social.` → … `FediverseSubdomainCandidates`) when the identity
domain and its redirect both come up empty, under a ~15s linked-CTS budget. `MainViewModel` runs the
static `HealFediverseSoftwareAsync` off the UI thread on layout load, applies matches via the dispatcher,
and saves; `SocialEntry.FediverseSoftware` is settable and raises `LogoData`, so the icon updates in place.
3. **The bar renders on the live output** — `Compositor/SocialBarRenderer.cs` rasterizes the entries into a
transparent straight-alpha BGRA strip (1920-wide, 40px content + 24px glow pad, the green glow baked in,
Pbgra32→straight-alpha unpremultiply) and the compositor blits it above the flash (see "Live frame
pipeline").
### Licensing — do not violate (GA = paid product; see `THIRD-PARTY-NOTICES.txt`)
This product is closed-source and paid. Every third-party component must stay inside the LGPL/BSD/MIT