feature: Phase 18.6 Track A — public Settings menu + streaming-quality toggle

This commit is contained in:
daniel-c-harvey
2026-06-23 14:06:19 -04:00
parent e5366bc4ec
commit c63c7ca033
18 changed files with 382 additions and 6 deletions
+2
View File
@@ -34,11 +34,13 @@
@code {
[Inject] public required DarkModeService DarkModeService { get; set; }
[Inject] public required SettingsService SettingsService { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
DarkModeService.CheckDarkMode();
SettingsService.CheckSettings();
}
}
@@ -0,0 +1,25 @@
using DeepDrftPublic.Client.Common;
using DeepDrftPublic.Client.Services;
namespace DeepDrftPublic.Services;
/// <summary>
/// Server-side prerender reader for public-site listener settings (Phase 18 wave 18.6), the sibling of
/// <see cref="DarkModeService"/>. Reads each preference's cookie via <see cref="IHttpContextAccessor"/>
/// during prerender and seeds the scoped <see cref="PublicSiteSettings"/>, which <c>MainLayout</c> then
/// rounds through <c>PersistentComponentState</c> into WASM — so the first paint already reflects the
/// listener's choice with no wrong-default flash (the streaming-quality analogue of the wrong-theme fix).
/// Inherits the shared cookie names + parsers from <see cref="SettingsServiceBase"/> so the server read and
/// the client write agree on one wire format.
/// </summary>
public class SettingsService(PublicSiteSettings settings, IHttpContextAccessor httpAccessor) : SettingsServiceBase
{
public void CheckSettings()
{
var cookies = httpAccessor.HttpContext?.Request.Cookies;
if (cookies is null) return;
cookies.TryGetValue(StreamQualityCookieName, out var streamQuality);
settings.StreamQuality = ParseStreamQuality(streamQuality);
}
}
+5
View File
@@ -11,5 +11,10 @@ public static class Startup
builder.Services
.AddHttpContextAccessor()
.AddScoped<DarkModeService>();
// Server prerender read for public-site listener settings (Phase 18 wave 18.6), sibling to
// DarkModeService. PublicSiteSettings itself is registered in the client Startup (shared by SSR and
// WASM); this seeds it from the streamQuality cookie during prerender.
builder.Services.AddScoped<SettingsService>();
}
}
@@ -463,6 +463,46 @@ h2, h3, h4, h5, h6,
flex: 1 1 auto;
}
/* Public-site Settings menu (Phase 18 wave 18.6). The MudMenu body renders inside .mud-popover, which
already re-points --mud-palette-surface to the theme-aware --deepdrft-popover-surface (see above), so the
panel inherits the correct surface + text in both themes with no dark override. These rules are layout
only: padding, the section heading, and each settings item's label/control stacking. Scoped via the
global stylesheet (not CSS isolation) because the menu body portals out of the component's DOM scope. */
.dd-settings-panel {
padding: 0.75rem 1rem;
min-width: 240px;
max-width: 320px;
color: var(--deepdrft-page-text);
}
.dd-settings-heading {
font-family: "DM Sans", sans-serif;
font-size: 0.7rem;
font-weight: 600;
letter-spacing: 0.12em;
text-transform: uppercase;
opacity: 0.7;
margin-bottom: 0.5rem;
}
.dd-settings-item + .dd-settings-item {
margin-top: 0.75rem;
padding-top: 0.75rem;
border-top: 1px solid var(--deepdrft-popover-surface);
}
.dd-settings-item-label {
font-weight: 500;
margin-bottom: 0.25rem;
}
/* The honest capability note under the quality control (OQ2 / AC7). */
.dd-setting-note {
font-size: 0.75rem;
opacity: 0.75;
margin-top: 0.25rem;
}
.deepdrft-share-embed-field .mud-input-slot {
font-family: var(--deepdrft-font-mono) !important;
font-size: 0.75rem;