feat(scoreboard): scroll speed is a property (20-400 px/s, persisted)

The marquee now has the dial it needs. `ScoreboardPresenter.PixelsPerSecond` is the single owner of
the range (20-400, default 120), the layer's properties expose it with a live px/s readout, and the
value is persisted as Scoreboard.ScrollSpeed because it is a READABILITY choice — re-dialling it
every launch would be a tax on the creator who needs the strip to be readable.

Advance() still takes an optional override so tests can drive exact distances.

Guard: the presenter test proves speed is real (same elapsed time, twice the speed, different
window) — not a value that is stored and ignored — and the panel test pins the control, its range
and the persistence key.
This commit is contained in:
2026-10-30 15:19:28 -07:00
parent 460b36204d
commit 28525c90aa
7 changed files with 61 additions and 3 deletions
+10
View File
@@ -479,6 +479,16 @@
ItemsSource="{Binding ScoreboardEdgeOptions}"
SelectedItem="{Binding ScoreboardEdge, Mode=TwoWay}"/>
<DockPanel Margin="10,0,0,6">
<TextBlock DockPanel.Dock="Left" Text="Scroll speed" Foreground="{StaticResource Brush.OnSurfaceVariant}"
FontSize="11" Width="76" VerticalAlignment="Center"/>
<TextBlock DockPanel.Dock="Right" Width="56" TextAlignment="Right" FontSize="11"
Foreground="{StaticResource Brush.OnSurfaceVariant}" VerticalAlignment="Center"
Text="{Binding ScoreboardScrollSpeed, StringFormat={}{0:0} px/s}"/>
<Slider Minimum="20" Maximum="400" SmallChange="10" LargeChange="40"
Value="{Binding ScoreboardScrollSpeed, Mode=TwoWay}" VerticalAlignment="Center"/>
</DockPanel>
<TextBlock Text="Facts" Foreground="{StaticResource Brush.OnSurfaceVariant}" FontSize="11" FontWeight="SemiBold" Margin="0,0,0,4"/>
<WrapPanel Margin="10,0,0,0">
<CheckBox Style="{StaticResource YtCheckBox}" Content="Subscribers" Margin="0,0,10,4"