From 3fde7fcfe6165ebacf302011c7a2821239128548 Mon Sep 17 00:00:00 2001 From: gramps Date: Thu, 5 Nov 2026 12:13:45 -0800 Subject: [PATCH] =?UTF-8?q?refactor(ui):=20alert=20rows=20are=20two=20line?= =?UTF-8?q?s=20of=20text=20=E2=80=94=20the=20heading=20line=20was=20redund?= =?UTF-8?q?ant?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Creator: system messages are limited to two lines; the label above the message ('STEAM ID NOT PRESENT', 'STREAM') was repeating what the row already said and pushing the stack past its budget. AttentionAlert loses Label; rows render Text only. The licence row is now exactly: Steam ID Limit: 30fps Click for More Info (60fps with a close control once owned). Rows are identified by Id internally, so nothing in the UI depends on the removed text. Tests updated to assert position/text rather than the heading. --- Controls/LeftPanel.xaml | 9 +++------ Models/AttentionAlert.cs | 3 ++- ViewModels/MainViewModel.Alerts.cs | 11 ++++------- ViewModels/MainViewModel.Recovery.cs | 1 - docs/ai/ui-surface.md | 6 ++++-- ytLive.Tests/AboutHubTests.cs | 2 +- ytLive.Tests/AttentionAlertStackTests.cs | 20 +++++++++++--------- 7 files changed, 25 insertions(+), 27 deletions(-) diff --git a/Controls/LeftPanel.xaml b/Controls/LeftPanel.xaml index c8f4c73..f384da6 100644 --- a/Controls/LeftPanel.xaml +++ b/Controls/LeftPanel.xaml @@ -81,12 +81,9 @@ Width="14" Height="14" Stretch="Uniform" VerticalAlignment="Top" Margin="6,2,2,0" ToolTip="Standing indicator" Visibility="{Binding ShowsPin, Converter={StaticResource BoolToVis}}"/> - - - - + diff --git a/Models/AttentionAlert.cs b/Models/AttentionAlert.cs index 1b3a2af..9313663 100644 --- a/Models/AttentionAlert.cs +++ b/Models/AttentionAlert.cs @@ -8,10 +8,11 @@ namespace ytLive.Models; /// becomes dismissible — and its dismissal permanent — once ownership is verified). /// Clicking a row runs its action: the licence indicator opens About; an event alert opens the /// Logs tab with that event's lines highlighted. +/// Rows are text only — a heading line above the message was redundant and pushed the stack past +/// its two-line budget (creator, 2026-11-05). /// public sealed record AttentionAlert( string Id, - string Label, string Text, bool IsPinned, AttentionAlertAction Action, diff --git a/ViewModels/MainViewModel.Alerts.cs b/ViewModels/MainViewModel.Alerts.cs index fceb2fd..8ee5ad7 100644 --- a/ViewModels/MainViewModel.Alerts.cs +++ b/ViewModels/MainViewModel.Alerts.cs @@ -46,8 +46,6 @@ public partial class MainViewModel return $"Steam ID Limit: {entitled}fps\nClick for More Info"; } - private string SteamLicenceLabel() => IsAppOwned ? "STEAM ID PRESENT" : "STEAM ID NOT PRESENT"; - /// Recomputes row 1 in place. Called at startup and whenever ownership changes. private void RefreshSteamLicenceAlert() { @@ -63,7 +61,6 @@ public partial class MainViewModel var alert = new AttentionAlert( SteamLicenceAlertId, - SteamLicenceLabel(), SteamLicenceText(), IsPinned: !IsAppOwned, AttentionAlertAction.About); @@ -76,9 +73,9 @@ public partial class MainViewModel /// Pushes an event alert. Newest sits directly under the licence indicator; older ones /// stack beneath, so the newest is the one nearest the eye. - private AttentionAlert? PushAttentionAlert(string id, string label, string text, long logFrom, long logTo) + private AttentionAlert? PushAttentionAlert(string id, string text, long logFrom, long logTo) { - var alert = new AttentionAlert(id, label, text, IsPinned: false, AttentionAlertAction.Logs, logFrom, logTo); + var alert = new AttentionAlert(id, text, IsPinned: false, AttentionAlertAction.Logs, logFrom, logTo); var insertAt = _attentionAlerts.Count(alert => alert.Id == SteamLicenceAlertId); var existing = _attentionAlerts.FirstOrDefault(candidate => candidate.Id == id); if (existing != null) @@ -95,8 +92,8 @@ public partial class MainViewModel } /// Test seam: pushes an event row without a stream session behind it. - internal AttentionAlert? PushAttentionAlertForTest(string id, string label, string text, long logFrom, long logTo) - => PushAttentionAlert(id, label, text, logFrom, logTo); + internal AttentionAlert? PushAttentionAlertForTest(string id, string text, long logFrom, long logTo) + => PushAttentionAlert(id, text, logFrom, logTo); private void RemoveAttentionAlert(string id) { diff --git a/ViewModels/MainViewModel.Recovery.cs b/ViewModels/MainViewModel.Recovery.cs index 876eb2f..22b5b09 100644 --- a/ViewModels/MainViewModel.Recovery.cs +++ b/ViewModels/MainViewModel.Recovery.cs @@ -87,7 +87,6 @@ public partial class MainViewModel : logFrom; PushAttentionAlert( "stream-recovery", - "STREAM", text, logFrom, Math.Max(logFrom, to)); diff --git a/docs/ai/ui-surface.md b/docs/ai/ui-surface.md index 568c545..d84da1b 100644 --- a/docs/ai/ui-surface.md +++ b/docs/ai/ui-surface.md @@ -4,9 +4,11 @@ A stack of red rows at the top of the left panel, **above both mode grids** (so and while live) and pushing the panel's content down. Only red rows belong there — it is the surface for "something needs you", never chatter. +- **Rows are text only, two lines at most** — no heading line above the message (creator, 2026-11-05: + the heading was redundant and pushed the stack past its budget). - **Row 1 is always the Steam licence indicator** and nothing displaces it. It reads as status, not a - warning: `Entitlement 30 fps · Maximum 60 fps`, both numbers derived from `QualityOptions` and - `HasProOutput`. It shows a **pin** (standing indicator, no close control) while higher tiers are + warning: `Steam ID Limit: 30fps` / `Click for More Info` (60fps once owned), both numbers derived from + `QualityOptions` and `HasProOutput`. It shows a **pin** (standing indicator, no close control) while higher tiers are unavailable, and a **close control once ownership is verified** — that close is persisted (`Steam.LicenceIndicatorDismissed`) and permanent *while ownership holds*; losing ownership restores the row as pinned, because that is a change of state rather than a preference. Click → About. diff --git a/ytLive.Tests/AboutHubTests.cs b/ytLive.Tests/AboutHubTests.cs index f635a2c..e344f86 100644 --- a/ytLive.Tests/AboutHubTests.cs +++ b/ytLive.Tests/AboutHubTests.cs @@ -99,7 +99,7 @@ public sealed class AboutHubTests // The old red panel under the quality picker is gone (2026-11-05): the licence state // lives in the left panel's alert stack now, as a pinned status indicator. Assert.Null(window.FindName("EntitlementErrorPanel")); - var licenceRow = vm.AttentionAlerts.Single(alert => alert.Label == "STEAM ID NOT PRESENT"); + var licenceRow = vm.AttentionAlerts.Single(alert => alert.Id == "steam-licence"); Assert.True(licenceRow.IsPinned); Assert.Contains("Steam ID Limit: 30fps", licenceRow.Text); Assert.Contains("Click for More Info", licenceRow.Text); diff --git a/ytLive.Tests/AttentionAlertStackTests.cs b/ytLive.Tests/AttentionAlertStackTests.cs index c1ee44d..4ac8a85 100644 --- a/ytLive.Tests/AttentionAlertStackTests.cs +++ b/ytLive.Tests/AttentionAlertStackTests.cs @@ -32,11 +32,13 @@ public sealed class AttentionAlertStackTests vm.EntitlementOverride = new FakeEntitlement(false, "Steam licensing is not configured in this build."); var row = Assert.Single(vm.AttentionAlerts); - Assert.Equal("STEAM ID NOT PRESENT", row.Label); + Assert.Equal("steam-licence", row.Id); Assert.True(row.IsPinned); Assert.True(row.ShowsPin); Assert.False(row.CanDismiss); Assert.Equal(AttentionAlertAction.About, row.Action); + // Two lines at most: the heading above the message was redundant. + Assert.DoesNotContain("\n\n", row.Text); // Creator wording: the limit this build runs at, and where to find out why. Assert.Contains("Steam ID Limit: 30fps", row.Text); @@ -63,11 +65,11 @@ public sealed class AttentionAlertStackTests // Permanent: a fresh view-model on the same profile must not bring it back… var reloaded = new MainViewModel(); - Assert.DoesNotContain(reloaded.AttentionAlerts, alert => alert.Label.StartsWith("STEAM ID")); + Assert.DoesNotContain(reloaded.AttentionAlerts, alert => alert.Id == "steam-licence"); // …but losing ownership restores it as a pinned indicator: a change of state, not a preference. reloaded.EntitlementOverride = new FakeEntitlement(false, "Steam licensing is not configured in this build."); - var restored = reloaded.AttentionAlerts.First(alert => alert.Label == "STEAM ID NOT PRESENT"); + var restored = reloaded.AttentionAlerts.First(alert => alert.Id == "steam-licence"); Assert.True(restored.IsPinned); }); } @@ -90,22 +92,22 @@ public sealed class AttentionAlertStackTests WithVm(vm => { vm.EntitlementOverride = new FakeEntitlement(false, "Steam licensing is not configured in this build."); - vm.PushAttentionAlertForTest("drop-1", "STREAM", "Stream dropped — reconnecting (attempt 1 of 4)", 10, 12); - vm.PushAttentionAlertForTest("drop-2", "STREAM", "Stream dropped — reconnecting (attempt 2 of 4)", 13, 15); + vm.PushAttentionAlertForTest("drop-1", "Stream dropped — reconnecting (attempt 1 of 4)", 10, 12); + vm.PushAttentionAlertForTest("drop-2", "Stream dropped — reconnecting (attempt 2 of 4)", 13, 15); - Assert.Equal(new[] { "STEAM ID NOT PRESENT", "STREAM", "STREAM" }, vm.AttentionAlerts.Select(a => a.Label)); + Assert.Equal(new[] { "steam-licence", "drop-2", "drop-1" }, vm.AttentionAlerts.Select(a => a.Id)); // Newest event sits directly under the indicator. Assert.Contains("attempt 2", vm.AttentionAlerts[1].Text); Assert.Contains("attempt 1", vm.AttentionAlerts[2].Text); // The same event advancing updates its row instead of adding another. - vm.PushAttentionAlertForTest("drop-2", "STREAM", "Stream recovered after 1.4 s", 13, 16); + vm.PushAttentionAlertForTest("drop-2", "Stream recovered after 1.4 s", 13, 16); Assert.Equal(3, vm.AttentionAlerts.Count); Assert.Contains("recovered", vm.AttentionAlerts[1].Text); vm.DismissAlertCommand.Execute(vm.AttentionAlerts[1]); Assert.Equal(2, vm.AttentionAlerts.Count); - Assert.Equal("STEAM ID NOT PRESENT", vm.AttentionAlerts[0].Label); + Assert.Equal("steam-licence", vm.AttentionAlerts[0].Id); }); } @@ -114,7 +116,7 @@ public sealed class AttentionAlertStackTests { WithVm(vm => { - vm.PushAttentionAlertForTest("drop-1", "STREAM", "Stream dropped", 41, 47); + vm.PushAttentionAlertForTest("drop-1", "Stream dropped", 41, 47); vm.ActivateAlertCommand.Execute(vm.AttentionAlerts[1]);