Social bar position is a click-toggle, not a drag — the drag-snap misbehaved for shaky hands (snapped up but wouldn't come back down; jitter around the deadzone). Clicking the bar now flips it top/bottom via ToggleSocialBarPosition; SocialBarSnap and its units removed — 153 tests passing, 0 warnings

This commit is contained in:
2026-08-13 11:04:32 -07:00
parent ac60a26d82
commit ea250c02a6
8 changed files with 58 additions and 141 deletions
+18 -13
View File
@@ -477,12 +477,17 @@ exception is contained (logged + `Failed` + pump stops) rather than crashing.
#### Ship step 5.5 — Social bar bug fixes + the bar on the live output (2026-08-13)
**Bug 1 — drag doesn't snap (root cause found):** `SocialBar_PreviewMouseMove` set `Canvas.SetTop(bar, …)`
with a local value, which permanently overrides the `Canvas.Top="{Binding SocialBarTop}"` binding — the
release-time `SetSocialBarPosition` → `PropertyChanged(SocialBarTop)` could never beat it, so the bar stayed
wherever it was dropped. Fixed by direction-snapping **during** the drag (`SocialBarSnap.Decide` — deadzone
±6px, once the direction commits the bar rides the edge it's dragged toward, never mid-screen) and on release
`bar.ClearValue(Canvas.TopProperty)` re-engages the binding before `SetSocialBarPosition`.
**Bug 1 — bar wouldn't reliably change position (root cause found, then simplified):** the original
drag set `Canvas.SetTop(bar, …)` with a local value, which permanently overrides the
`Canvas.Top="{Binding SocialBarTop}"` binding — the release-time `SetSocialBarPosition` →
`PropertyChanged(SocialBarTop)` could never beat it. First fix added direction-snapping during the drag
(`SocialBarSnap.Decide`, ±6px deadzone) + `bar.ClearValue(Canvas.TopProperty)` on release — but that
still misbehaved for shaky hands (jitter around the deadzone: it snapped up reliably, then refused to
come back down and snapped back to top). **Superseded by a click-toggle (KISS, user decision):** clicking
the bar in the preview flips it top ⇄ bottom (`MainViewModel.ToggleSocialBarPosition` → the existing
`SetSocialBarPosition`), the bar rides `{Binding SocialBarTop}` alone (no local values, no deadzone, no
jitter sensitivity), and `SocialBarSnap` was removed. The `ClearValue` lesson stands: never set a local
value on a property the binding owns.
**Bug 2 — Mastodon showed the generic 7-star honeycomb (root cause found):** the DB row
`@gramps@llamachile.tube` had `Software = NULL` — nodeinfo was only ever resolved against the identity domain
@@ -505,13 +510,13 @@ BGRA strip (1920-wide, 40px content + 24px glow pad, green `#2ecc71` glow baked
`SourceRectHeight bar height`. `MainViewModel` owns the frame (`RenderSocialBarFrame`, re-rendered on
load/save/notify) and feeds the seam.
**Tests (+8 → 155 passing, 0 warnings):** `SocialBarSnap.Decide` units (direction + deadzone + custom
deadzone), settable `FediverseSoftware` updates `LogoData`, subdomain-probe unit + null-when-silent unit,
the branch's **one integration test** `Socials_HealMissingFediverseSoftware_RoundTripsThroughDb`
(temp-DB roundtrip: NULL software → healed via the validator → persisted), compositor bar overlay
(top/bottom + above-flash), `FramePump` bar pass-through (Top then flipped to Bottom mid-run — the seam is
re-read each frame), and both `ISocialValidator` fakes (`FakeValidator`/`BlockingValidator`) gained
`ResolveFediverseSoftwareAsync`.
**Tests (+6 → 153 passing, 0 warnings):** settable `FediverseSoftware` updates `LogoData`,
subdomain-probe unit + null-when-silent unit, the branch's **one integration test**
`Socials_HealMissingFediverseSoftware_RoundTripsThroughDb` (temp-DB roundtrip: NULL software → healed via
the validator → persisted), compositor bar overlay (top/bottom + above-flash), `FramePump` bar pass-through
(Top then flipped to Bottom mid-run — the seam is re-read each frame), and both `ISocialValidator` fakes
(`FakeValidator`/`BlockingValidator`) gained `ResolveFediverseSoftwareAsync`. The drag-snap units
(`SocialBarSnap`) were removed with the click-toggle supersession.
**Not included (say the word):** rewriting the healed entry's `ProfileUrl` to `https://mastodon.llamachile.tube/@gramps`.