feat(scoreboard): the layer is available to ALL scenes (YT_ACTIVITY_TICKER)

Creator ruling: the Scoreboard layer exists in every scene rather than being added five times.
ScoreboardHealer.Ensure keeps exactly one per scene — healed on load like the Background and Brand
logo — so a scene can never end up with two, and 'off' is the ordinary per-scene eye toggle rather
than a delete.

It is appended as the TOPMOST layer on purpose: a full-width strip draws over the scene, and
inserting it above the background would break the Brand logo's documented invariant (directly above
the background). That choice is also why the layer-reorder test still passes untouched.

Also: a layer-list icon for the type, so the row is not blank.

Guard: ScoreboardHealerTests — one per scene, topmost, exact strip geometry, idempotent, and a
duplicate healed back to one.
This commit is contained in:
2026-10-30 14:50:20 -07:00
parent 96d528b3ac
commit 85a4a8a7d3
5 changed files with 125 additions and 0 deletions
+1
View File
@@ -439,6 +439,7 @@ public partial class MainViewModel
}
SeedOnAirImage();
EnsureBrandLogos();
EnsureScoreboards();
OnPropertyChanged(nameof(ShowSourcesEmptyHint));
OnPropertyChanged(nameof(LayerCount));
}
+12
View File
@@ -45,6 +45,18 @@ public partial class MainViewModel
RefreshScoreboardPreviews();
}
/// <summary>One Scoreboard layer in every scene, healed on load — "available to all scenes"
/// (creator ruling 2026-10-30). Per-scene visibility is the ordinary eye toggle.</summary>
internal void EnsureScoreboards()
{
if (ScoreboardHealer.Ensure(Scenes))
{
foreach (var scene in Scenes) _sceneGraph.InvalidateBake(scene);
RefreshScoreboardPreviews();
OnPropertyChanged(nameof(LayerCount));
}
}
private void InitScoreboard()
{
_scoreboardPresenter = new ScoreboardPresenter(_scoreboard, _scoreboardStyle)