Styles & Home Page Content Cleanup

Mobile Menu System & Dark Mode Cookie
Theme Draft
This commit is contained in:
daniel-c-harvey
2025-12-09 16:46:07 -05:00
parent bb3551a248
commit bc521d5b29
26 changed files with 461 additions and 168 deletions
+10 -10
View File
@@ -2,21 +2,21 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.8" />
<PackageReference Include="Terminal.Gui" Version="1.17.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.1" />
<PackageReference Include="Terminal.Gui" Version="1.19.0" />
</ItemGroup>
<ItemGroup>
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
+2 -2
View File
@@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.6"/>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.1" />
</ItemGroup>
<ItemGroup>
+1 -1
View File
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
+12 -6
View File
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
@@ -9,11 +9,17 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="NUnit" Version="4.2.2" />
<PackageReference Include="NUnit.Analyzers" Version="4.4.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
<PackageReference Include="coverlet.collector" Version="6.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="NUnit" Version="4.4.0" />
<PackageReference Include="NUnit.Analyzers" Version="4.11.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NUnit3TestAdapter" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
+28
View File
@@ -0,0 +1,28 @@
namespace DeepDrftWeb.Client.Common;
public static class DDIcons
{
/// <summary>
/// Charleston gas lamp lantern - uses currentColor for theming
/// </summary>
/// <summary>
/// Charleston gas lamp lantern - uses currentColor for theming
/// </summary>
public const string GasLamp = """
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="currentColor" d="M11 0h2v2h-2zM5 6l7-4 7 4v2H5zM6 8h12l-1.5 10h-9zM7.7 9l1.2 8h6.2l1.2-8zM9 19h6v1H9zM10 21h4v2h-4z"/>
</svg>
""";
/// <summary>
/// Charleston gas lamp with lit flame - for dark mode
/// </summary>
public const string GasLampLit = """
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="currentColor" d="M11 0h2v2h-2zM5 6l7-4 7 4v2H5zM6 8h12l-1.5 10h-9zM7.7 9l1.2 8h6.2l1.2-8zM9 19h6v1H9zM10 21h4v2h-4z"/>
<ellipse cx="12" cy="13" rx="2.5" ry="3.5" fill="#FF9800"/>
<ellipse cx="12" cy="12.5" rx="1.5" ry="2.5" fill="#FFCA28"/>
<ellipse cx="12" cy="12" rx=".7" ry="1.5" fill="#FFF8E1"/>
</svg>
""";
}
@@ -0,0 +1,20 @@
using Microsoft.AspNetCore.Components;
namespace DeepDrftWeb.Client.Common;
public class DarkModeSettings()
{
// public EventCallback<bool> IsDarkModeChanged { get; set; }
[PersistentState]
public bool IsDarkMode
{
get;
set
{
if (value == field) return;
field = value;
// IsDarkModeChanged.InvokeAsync(value);
}
} = false;
}
@@ -8,7 +8,7 @@ namespace DeepDrftWeb.Client.Controls.AudioPlayerBar;
public partial class AudioPlayerBar : ComponentBase, IAsyncDisposable
{
[CascadingParameter] public required IStreamingPlayerService PlayerService { get; set; }
[Inject] private IBrowserViewportService BrowserViewportService { get; set; } = default!;
[Inject] public required IBrowserViewportService BrowserViewportService { get; set; }
private bool _isMinimized = true;
private bool _isSeeking = false;
+5 -4
View File
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
@@ -9,10 +9,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.*" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="9.*" />
<PackageReference Include="MudBlazor" Version="8.*" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.1" />
<PackageReference Include="MudBlazor" Version="8.15.0" />
<PackageReference Include="MudBlazor.ThemeManager" Version="3.0.0" />
</ItemGroup>
@@ -0,0 +1,118 @@
@using DeepDrftWeb.Client.Controls
@using DeepDrftWeb.Client.Services
<MudAppBar Elevation="@Elevation">
<div class="d-inline-flex align-center flex-1 justify-space-between">
@if (_isDesktop)
{
<div>
<MudStack Row AlignItems="AlignItems.Center" Spacing="6">
<MudLink Href="/" Underline="Underline.None">
<MudStack Row AlignItems="AlignItems.Center">
<MudAvatar Class="mr-2">
<MudImage Src="img/deepdrft-logo.jpg"></MudImage>
</MudAvatar>
<div>Deep DRFT</div>
</MudStack>
</MudLink>
</MudStack>
</div>
<div>
<MudStack Spacing="8" Row AlignItems="AlignItems.Center">
@foreach (PageRoute thePage in Pages.AllPages)
{
<AppNavLink Href="@thePage.Route" Icon="@thePage.Icon">@thePage.Name</AppNavLink>
}
</MudStack>
</div>
}
else
{
<div>
<MudStack Row AlignItems="AlignItems.Center">
<MudMenu RelativeWidth="DropdownWidth.Adaptive">
<ActivatorContent>
<MudStack Row AlignItems="AlignItems.Center" Spacing="4">
<MudIcon Icon="@Icons.Material.Filled.Menu"/>
<MudAvatar Class="mr-2">
<MudImage Src="img/deepdrft-logo.jpg"></MudImage>
</MudAvatar>
<div>Deep DRFT</div>
</MudStack>
</ActivatorContent>
<ChildContent>
@foreach (PageRoute route in Pages.AllPages)
{
<MudMenuItem Href="@route.Route" Class="px-6">
<MudStack Row AlignItems="AlignItems.Center">
<MudIcon Icon="@route.Icon" Color="Color.Primary"/>
<MudText Typo="Typo.button" Color="Color.Primary">
@route.Name
</MudText>
</MudStack>
</MudMenuItem>
}
</ChildContent>
</MudMenu>
</MudStack>
</div>
}
<div>
<MudIconButton Icon="@(DarkLightModeButtonIcon)" Color="Color.Inherit" OnClick="@DarkModeToggle"/>
</div>
</div>
</MudAppBar>
@code {
[Inject] public required IBrowserViewportService BrowserViewportService { get; set; }
[Inject] public required DarkModeCookieService DarkModeCookieService { get; set; }
[Parameter] public int Elevation { get; set; }
[Parameter] public required bool IsDarkMode { get; set; }
[Parameter] public required EventCallback<bool> IsDarkModeChanged { get; set; }
private bool _isDesktop = true;
private Guid _viewportSubscriptionId;
protected override async Task OnInitializedAsync()
{
IsDarkMode = DarkModeCookieService.GetDarkModeAsync();
await IsDarkModeChanged.InvokeAsync(IsDarkMode);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var breakpoint = await BrowserViewportService.GetCurrentBreakpointAsync();
_isDesktop = breakpoint >= Breakpoint.Sm;
_viewportSubscriptionId = Guid.NewGuid();
await BrowserViewportService.SubscribeAsync(
_viewportSubscriptionId,
args =>
{
_isDesktop = args.Breakpoint >= Breakpoint.Sm;
InvokeAsync(StateHasChanged);
},
new ResizeOptions { NotifyOnBreakpointOnly = true },
fireImmediately: true);
StateHasChanged();
}
}
private string DarkLightModeButtonIcon => IsDarkMode switch
{
true => DDIcons.GasLampLit,
false => DDIcons.GasLamp,
};
private async Task DarkModeToggle()
{
IsDarkMode = !IsDarkMode;
await DarkModeCookieService.SetDarkModeAsync(IsDarkMode);
await IsDarkModeChanged.InvokeAsync(IsDarkMode);
}
}
+55 -44
View File
@@ -1,6 +1,10 @@
@using DeepDrftWeb.Client.Controls
@using DeepDrftWeb.Client.Controls.AudioPlayerBar
@using DeepDrftWeb.Client.Services
@using DeepDrftWeb.Client.Common
@using Microsoft.AspNetCore.Components
@inherits LayoutComponentBase
@implements IDisposable
<MudThemeProvider Theme="@_themeManager.Theme" IsDarkMode="_isDarkMode" />
<MudPopoverProvider />
@@ -9,14 +13,7 @@
<div class="@ThemeWrapperClass">
<MudLayout Style="display: flex; flex-direction: column; min-height: 100vh">
<AudioPlayerProvider>
<MudAppBar Elevation="_themeManager.AppBarElevation">
<MudAvatar Class="mr-2">
<MudImage Src="img/deepdrft-logo.jpg"></MudImage>
</MudAvatar>
<NavMenu />
<MudSpacer/>
<MudIconButton Icon="@(DarkLightModeButtonIcon)" Color="Color.Inherit" OnClick="@DarkModeToggle"/>
</MudAppBar>
<DeepDrftMenu Elevation="_themeManager.AppBarElevation" @bind-IsDarkMode="_isDarkMode" />
<MudMainContent Class="flex-grow-1 pt-16 pb-8">
<MudContainer MaxWidth="MaxWidth.False" Class="pa-4">
@Body
@@ -35,12 +32,31 @@
</div>
@code {
private bool _drawerOpen = true;
private const string DarkModeKey = "darkMode";
private bool _isDarkMode = true;
private PersistingComponentStateSubscription _persistingSubscription;
[Inject] public required PersistentComponentState PersistentState { get; set; }
[Inject] public required DarkModeSettings DarkModeSettings { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
// Restore persisted dark mode state (from server prerender)
if (PersistentState.TryTakeFromJson<bool>(DarkModeKey, out var restored))
{
_isDarkMode = restored;
DarkModeSettings.IsDarkMode = restored;
}
else
{
_isDarkMode = DarkModeSettings.IsDarkMode;
}
// Register to persist state when prerendering completes
_persistingSubscription = PersistentState.RegisterOnPersisting(PersistDarkMode);
_themeManager = new ThemeManagerTheme
{
Theme =
@@ -59,23 +75,23 @@
},
H2 = new H2Typography()
{
FontFamily = new[] {"EB Garamond", "serif"}
FontFamily = new[] {"Cormorant", "serif"}
},
H3 = new H3Typography()
{
FontFamily = new[] {"EB Garamond", "serif"}
FontFamily = new[] {"Cormorant", "serif"}
},
H4 = new H4Typography()
{
FontFamily = new[] {"EB Garamond", "serif"}
FontFamily = new[] {"Cormorant", "serif"}
},
H5 = new H5Typography()
{
FontFamily = new[] {"EB Garamond", "serif"}
FontFamily = new[] {"Cormorant", "serif"}
},
H6 = new H6Typography()
{
FontFamily = new[] {"EB Garamond", "serif"}
FontFamily = new[] {"Cormorant", "serif"}
},
Button = new ButtonTypography()
{
@@ -87,16 +103,6 @@
StateHasChanged();
}
private void DrawerToggle()
{
_drawerOpen = !_drawerOpen;
}
private void DarkModeToggle()
{
_isDarkMode = !_isDarkMode;
}
private ThemeManagerTheme _themeManager;
public bool _themeManagerOpen = false;
@@ -113,31 +119,31 @@
}
// Charleston in the Day - Light Theme
// Inspired by Charleston's historic architecture: white stucco, black wrought iron gates, elegant accents
// Inspired by Charleston's historic architecture: wrought iron, bronze, Atlantic coast
private readonly PaletteLight _lightPalette = new()
{
Primary = "#1C1C1C", // Wrought iron black - strong, elegant
Secondary = "#B8848C", // Dusty rose - elegant accent
Tertiary = "#C9A962", // Antique gold - replaces brown
Primary = "#1A1A1A", // Wrought iron black
Secondary = "#B8623D", // Burnished copper - warm orange bronze
Tertiary = "#2A7B8C", // Atlantic turquoise
Info = "#2196F3", // MudBlazor default blue (semantic)
Success = "#4CAF50", // MudBlazor default green (semantic)
Warning = "#FF9800", // MudBlazor default amber (semantic)
Error = "#F44336", // MudBlazor default red (semantic)
Black = "#1C1C1C", // Wrought iron black
Black = "#1A1A1A", // Wrought iron black
White = "#FDFBF7", // Cream white (stucco)
Surface = "#FDFBF7", // Cream stucco surface
Background = "#F5F2EC", // Warm linen background
AppbarText = "#FDFBF7", // Cream text on dark appbar (FIX)
AppbarBackground = "#1C1C1C", // Solid wrought iron appbar
AppbarText = "#FDFBF7", // Cream text on dark appbar
AppbarBackground = "#1A1A1A", // Solid wrought iron appbar
DrawerBackground = "#F5F2EC", // Linen drawer
TextPrimary = "#1C1C1C", // Wrought iron text
TextPrimary = "#1A1A1A", // Wrought iron text
TextSecondary = "#4A4A4A", // Softer iron text
GrayLight = "rgba(28,28,28,0.08)", // Light iron tint
GrayLighter = "rgba(28,28,28,0.04)", // Very light iron tint
GrayDefault = "rgba(28,28,28,0.15)", // Medium iron tint
GrayDark = "rgba(28,28,28,0.25)", // Darker iron tint
Divider = "rgba(28,28,28,0.12)", // Subtle divider lines
TableLines = "rgba(28,28,28,0.12)", // Table borders
GrayLight = "rgba(26,26,26,0.08)", // Light iron tint
GrayLighter = "rgba(26,26,26,0.04)", // Very light iron tint
GrayDefault = "rgba(26,26,26,0.15)", // Medium iron tint
GrayDark = "rgba(26,26,26,0.25)", // Darker iron tint
Divider = "rgba(26,26,26,0.12)", // Subtle divider lines
TableLines = "rgba(26,26,26,0.12)", // Table borders
};
// Lowcountry Summer Nights - Dark Theme
@@ -178,14 +184,19 @@
OverlayDark = "rgba(255,255,255,0.08)", // Light overlay
};
public string DarkLightModeButtonIcon => _isDarkMode switch
{
true => Icons.Material.Rounded.AutoMode,
false => Icons.Material.Outlined.DarkMode,
};
// Theme wrapper class for CSS targeting
private string ThemeWrapperClass => _isDarkMode ? "deepdrft-theme-dark" : "deepdrft-theme-light";
private Task PersistDarkMode()
{
PersistentState.PersistAsJson(DarkModeKey, _isDarkMode);
return Task.CompletedTask;
}
public void Dispose()
{
_persistingSubscription.Dispose();
}
}
-2
View File
@@ -1,7 +1,5 @@
@using DeepDrftWeb.Client.Controls
<AppNavLink Href="" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Home">Home</AppNavLink>
<AppNavLink Href="/tracks" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.LibraryMusic">Track Gallery</AppNavLink>
+24
View File
@@ -0,0 +1,24 @@
using MudBlazor;
namespace DeepDrftWeb.Client.Layout;
public class PageRoute
{
public string Name { get; set; } = string.Empty;
public string Route { get; set; } = string.Empty;
public string? Icon { get; set; } = null;
}
public static class Pages
{
public static readonly List<PageRoute> MenuPages =
[
new() { Name = "Track Gallery", Route = "/tracks", Icon = Icons.Material.Filled.LibraryMusic }
];
public static readonly List<PageRoute> AllPages =
new List<PageRoute>
{
new() { Name = "Home", Route = "/", Icon = Icons.Material.Filled.Home }
}.Concat(MenuPages).ToList();
}
+28 -28
View File
@@ -1,6 +1,6 @@
@page "/"
<PageTitle>DeepDrft - Electronic Music Collective</PageTitle>
<PageTitle>Deep DRFT- Electronic Music Collective</PageTitle>
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pa-0">
@@ -11,17 +11,17 @@
<MudItem xs="12" md="8">
<MudText Typo="Typo.h1"
Class="mb-4 deepdrft-text-hero deepdrft-hero-title">
DEEPDRFT
DEEP DRFT
</MudText>
<MudText Typo="Typo.h4"
<MudText Typo="Typo.h2"
Class="mb-6 deepdrft-text-subtitle deepdrft-hero-subtitle">
ELECTRONIC MUSIC COLLECTIVE
</MudText>
<MudText Typo="Typo.h6"
<MudText Typo="Typo.h3"
Class="mb-8 deepdrft-text-description deepdrft-hero-text-container deepdrft-hero-description">
Live electronic music from Charleston, SC featuring house, techno, trance, and IDM crafted with synthesizers and grooveboxes
Live electronic music from Charleston, South Carolina
</MudText>
<MudButton Variant="Variant.Filled"
@@ -32,7 +32,8 @@
START STREAMING
</MudButton>
<MudButton Variant="Variant.Outlined"
<MudButton Href="/tracks"
Variant="Variant.Outlined"
Color="Color.Primary"
Size="Size.Large"
Class="mb-2 deepdrft-hero-button-outlined">
@@ -46,8 +47,8 @@
@* About Section *@
<MudGrid Class="mb-8" Spacing="6">
<MudItem xs="12" md="6">
<MudPaper Elevation="4" Class="pa-6 deepdrft-gradient-soft-primary deepdrft-border-left-primary deepdrft-about-card">
<MudText Typo="Typo.h4" Color="Color.Primary" Class="mb-4 deepdrft-text-bold">
<MudPaper Elevation="4" Class="pa-6 deepdrft-gradient-soft-primary deepdrft-border-left-secondary deepdrft-about-card">
<MudText Typo="Typo.h4" Color="Color.Secondary" Class="mb-4 deepdrft-text-bold">
<MudIcon Icon="@Icons.Material.Filled.Group" Class="mr-2" />
The Collective
</MudText>
@@ -65,8 +66,8 @@
</MudItem>
<MudItem xs="12" md="6">
<MudPaper Elevation="4" Class="pa-6 deepdrft-gradient-soft-secondary deepdrft-border-left-secondary deepdrft-about-card">
<MudText Typo="Typo.h4" Color="Color.Secondary" Class="mb-4 deepdrft-text-bold">
<MudPaper Elevation="4" Class="pa-6 deepdrft-gradient-soft-secondary deepdrft-border-left-tertiary deepdrft-about-card">
<MudText Typo="Typo.h4" Color="Color.Tertiary" Class="mb-4 deepdrft-text-bold">
<MudIcon Icon="@Icons.Material.Filled.MusicNote" Class="mr-2" />
Our Sound
</MudText>
@@ -96,11 +97,11 @@
<MudGrid Spacing="6">
<MudItem xs="12" sm="6" md="3">
<MudCard Elevation="8" Class="pa-4 deepdrft-feature-card deepdrft-feature-icon-container deepdrft-card-purple-tint">
<MudIcon Icon="@Icons.Material.Filled.Headphones"
Size="Size.Large"
Color="Color.Primary"
<MudIcon Icon="@Icons.Material.Filled.Headphones"
Size="Size.Large"
Color="Color.Secondary"
Class="mb-3 deepdrft-icon-large" />
<MudText Typo="Typo.h6" Color="Color.Primary" Class="mb-2 deepdrft-text-bold">
<MudText Typo="Typo.h6" Color="Color.Secondary" Class="mb-2 deepdrft-text-bold">
High-Quality Streaming
</MudText>
<MudText Typo="Typo.body2">
@@ -111,9 +112,9 @@
<MudItem xs="12" sm="6" md="3">
<MudCard Elevation="8" Class="pa-4 deepdrft-feature-card deepdrft-feature-icon-container deepdrft-card-pink-tint">
<MudIcon Icon="@Icons.Material.Filled.LiveTv"
Size="Size.Large"
Color="Color.Tertiary"
<MudIcon Icon="@Icons.Material.Filled.LiveTv"
Size="Size.Large"
Color="Color.Tertiary"
Class="mb-3 deepdrft-icon-large" />
<MudText Typo="Typo.h6" Color="Color.Tertiary" Class="mb-2 deepdrft-text-bold">
Live Sessions
@@ -126,11 +127,10 @@
<MudItem xs="12" sm="6" md="3">
<MudCard Elevation="8" Class="pa-4 deepdrft-feature-card deepdrft-feature-icon-container deepdrft-card-indigo-tint">
<MudIcon Icon="@Icons.Material.Filled.VideoLibrary"
Size="Size.Large"
Color="Color.Secondary"
Class="mb-3 deepdrft-icon-large" />
<MudText Typo="Typo.h6" Color="Color.Secondary" Class="mb-2 deepdrft-text-bold">
<MudIcon Icon="@Icons.Material.Filled.VideoLibrary"
Size="Size.Large"
Class="mb-3 deepdrft-icon-large deepdrft-text-quaternary" />
<MudText Typo="Typo.h6" Class="mb-2 deepdrft-text-bold deepdrft-text-quaternary">
Video Content
</MudText>
<MudText Typo="Typo.body2">
@@ -143,8 +143,8 @@
<MudCard Elevation="8" Class="pa-4 deepdrft-feature-card deepdrft-feature-icon-container deepdrft-card-lavender-tint">
<MudIcon Icon="@Icons.Material.Filled.Archive"
Size="Size.Large"
Class="mb-3 deepdrft-icon-large deepdrft-text-quaternary" />
<MudText Typo="Typo.h6" Class="mb-2 deepdrft-text-bold deepdrft-text-quaternary">
Class="mb-3 deepdrft-icon-large deepdrft-text-quinary" />
<MudText Typo="Typo.h6" Class="mb-2 deepdrft-text-bold deepdrft-text-quinary">
Growing Archive
</MudText>
<MudText Typo="Typo.body2">
@@ -158,8 +158,8 @@
@* Location & Connect Section *@
<MudGrid Class="mb-8" Spacing="6">
<MudItem xs="12" md="6">
<MudPaper Elevation="4" Class="pa-6 deepdrft-gradient-soft-accent deepdrft-border-top-primary">
<MudText Typo="Typo.h4" Color="Color.Primary" Class="mb-4 deepdrft-text-bold">
<MudPaper Elevation="4" Class="pa-6 deepdrft-gradient-soft-accent deepdrft-border-top-quaternary">
<MudText Typo="Typo.h4" Class="mb-4 deepdrft-text-bold deepdrft-text-quaternary">
<MudIcon Icon="@Icons.Material.Filled.LocationOn" Class="mr-2" />
Charleston, SC
</MudText>
@@ -175,8 +175,8 @@
</MudItem>
<MudItem xs="12" md="6">
<MudPaper Elevation="4" Class="pa-6 deepdrft-gradient-soft-tertiary deepdrft-border-top-secondary">
<MudText Typo="Typo.h4" Color="Color.Tertiary" Class="mb-4 deepdrft-text-bold">
<MudPaper Elevation="4" Class="pa-6 deepdrft-gradient-soft-tertiary deepdrft-border-top-senary">
<MudText Typo="Typo.h4" Class="mb-4 deepdrft-text-bold deepdrft-text-senary">
<MudIcon Icon="@Icons.Material.Filled.ConnectWithoutContact" Class="mr-2" />
Connect With Us
</MudText>
@@ -0,0 +1,25 @@
using DeepDrftWeb.Client.Common;
using Microsoft.JSInterop;
namespace DeepDrftWeb.Client.Services;
public class DarkModeCookieService(DarkModeSettings darkModeSetting, IJSRuntime js) : DarkModeServiceBase
{
private const int EXPIRY_DAYS = 365;
public bool GetDarkModeAsync()
{
return darkModeSetting.IsDarkMode;
// var value = await js.InvokeAsync<string?>("eval",
// $"document.cookie.split('; ').find(c => c.startsWith('{COOKIE_NAME}='))?.split('=')[1]");
// return value == "true";
}
public async ValueTask SetDarkModeAsync(bool isDarkMode)
{
var expires = DateTime.UtcNow.AddDays(EXPIRY_DAYS).ToString("R");
await js.InvokeVoidAsync("eval",
$"document.cookie = '{COOKIE_NAME}={isDarkMode.ToString().ToLower()}; expires={expires}; path=/; SameSite=Lax'");
darkModeSetting.IsDarkMode = isDarkMode;
}
}
@@ -0,0 +1,6 @@
namespace DeepDrftWeb.Client.Services;
public abstract class DarkModeServiceBase
{
protected const string COOKIE_NAME = "darkMode";
}
+6 -1
View File
@@ -1,6 +1,8 @@
using DeepDrftWeb.Client.Clients;
using DeepDrftWeb.Client.Common;
using DeepDrftWeb.Client.Services;
using DeepDrftWeb.Client.ViewModels;
using Microsoft.AspNetCore.Http;
namespace DeepDrftWeb.Client;
@@ -8,6 +10,10 @@ public static class Startup
{
public static void ConfigureDomainServices(IServiceCollection services)
{
// Theme Support
services.AddScoped<DarkModeSettings>();
services.AddScoped<DarkModeCookieService>();
// Track Client
services.AddScoped<TrackClient>();
services.AddScoped<TracksViewModel>();
@@ -29,6 +35,5 @@ public static class Startup
});
services.AddScoped<TrackMediaClient>();
services.AddScoped<AudioInteropService>();
// AudioPlaybackEngine removed - functionality merged into AudioPlayerService
}
}
+1
View File
@@ -9,3 +9,4 @@
@using MudBlazor
@using MudBlazor.Services
@using MudBlazor.ThemeManager
@using DeepDrftWeb.Client.Common
@@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.8">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
+19 -7
View File
@@ -1,4 +1,5 @@
<!DOCTYPE html>
@using DeepDrftWeb.Services
<!DOCTYPE html>
<html lang="en">
<head>
@@ -8,7 +9,7 @@
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Bodoni+Moda:opsz,wght@6..96,400;6..96,500;6..96,600;6..96,700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=EB+Garamond:wght@400;500;600;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Cormorant:wght@400;500;600;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
<link href="_@Assets["content/MudBlazor.ThemeManager/MudBlazorThemeManager.css"]" rel="stylesheet" />
<link href=@Assets["_content/MudBlazor/MudBlazor.min.css"] rel="stylesheet" />
@@ -20,12 +21,23 @@
</head>
<body>
<Routes @rendermode="InteractiveAuto" />
<script src="_framework/blazor.web.js"></script>
<script src=@Assets["_content/MudBlazor/MudBlazor.min.js"]></script>
<script type="module">
<Routes @rendermode="InteractiveAuto" />
<script src="_framework/blazor.web.js"></script>
<script src=@Assets["_content/MudBlazor/MudBlazor.min.js"]></script>
<script type="module">
import('./js/audio/index.js');
</script>
</body>
</html>
@code {
[Inject] public required DarkModeService DarkModeService { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
DarkModeService.CheckDarkMode();
}
}
+8 -8
View File
@@ -1,32 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.8">
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.8">
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<ProjectReference Include="..\DeepDrftModels\DeepDrftModels.csproj" />
<ProjectReference Include="..\DeepDrftWeb.Client\DeepDrftWeb.Client.csproj" />
<ProjectReference Include="..\DeepDrftWeb.Services\DeepDrftWeb.Services.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.*" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.TypeScript.MSBuild" Version="5.9.2">
<PackageReference Include="Microsoft.TypeScript.MSBuild" Version="5.9.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
+3 -4
View File
@@ -1,5 +1,4 @@
using DeepDrftWeb;
using DeepDrftWeb.Client.Services;
using MudBlazor.Services;
using DeepDrftWeb.Components;
using Microsoft.AspNetCore.HttpOverrides;
@@ -10,17 +9,17 @@ var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMudServices();
// Add AudioInteropService for both server and client rendering
builder.Services.AddScoped<AudioInteropService>();
// builder.Services.AddScoped<AudioInteropService>();
var baseUrl = builder.GetKestrelUrl();
var contentApiUrl = builder.Configuration["ApiUrls:ContentApi"] ?? throw new Exception("Content API URL is not configured");
Startup.ConfigureDomainServices(builder);
DeepDrftWeb.Client.Startup.ConfigureApiHttpClient(builder.Services, baseUrl);
DeepDrftWeb.Client.Startup.ConfigureDomainServices(builder.Services);
DeepDrftWeb.Client.Startup.ConfigureContentServices(builder.Services, contentApiUrl);
Startup.ConfigureDomainServices(builder);
builder.Services.AddControllers();
// Add services to the container.
+22
View File
@@ -0,0 +1,22 @@
using DeepDrftWeb.Client.Common;
using DeepDrftWeb.Client.Services;
namespace DeepDrftWeb.Services;
public class DarkModeService(DarkModeSettings darkModeSettings, IHttpContextAccessor httpAccessor) : DarkModeServiceBase
{
public void CheckDarkMode()
{
// get
// {
bool isDarkMode = false; // Default to light mode
var context = httpAccessor.HttpContext;
if (context?.Request.Cookies.TryGetValue(COOKIE_NAME, out var dark) == true)
{
isDarkMode = dark == "true";
}
darkModeSettings.IsDarkMode = isDarkMode;
// return isDarkMode;
// }
}
}
+10 -3
View File
@@ -1,4 +1,4 @@
using DeepDrftWeb.Services.Data;
using DeepDrftWeb.Services.Data;
using DeepDrftWeb.Services.Repositories;
using DeepDrftWeb.Services;
using Microsoft.EntityFrameworkCore;
@@ -13,9 +13,16 @@ public static class Startup
builder.Services.AddDbContext<DeepDrftContext>(options =>
options.UseSqlite(builder.Configuration.GetConnectionString("DefaultConnection")));
// Add Server Prerendering Theming Support
// DarkModeSettings is registered in DeepDrftWeb.Client.Startup.ConfigureDomainServices
builder.Services
.AddHttpContextAccessor()
.AddScoped<DarkModeService>();
// Add Track services
builder.Services.AddScoped<TrackRepository>();
builder.Services.AddScoped<TrackService>();
builder.Services
.AddScoped<TrackRepository>()
.AddScoped<TrackService>();
}
public static string GetKestrelUrl(this WebApplicationBuilder builder)
+50 -40
View File
@@ -4,16 +4,16 @@
/* Color Variables - Charleston in the Day (Light Mode Default) */
:root {
/* Charleston Theme Colors */
--deepdrft-primary: #1C1C1C; /* Wrought iron black */
--deepdrft-secondary: #B8848C; /* Dusty rose - elegant accent */
--deepdrft-tertiary: #C9A962; /* Antique gold - replaces brown */
--deepdrft-accent: #7D9B8C; /* Sage green */
/* Charleston Theme Colors - Elegant Ironwork & Lowcountry */
--deepdrft-primary: #1A1A1A; /* Wrought iron black */
--deepdrft-secondary: #B8623D; /* Burnished copper - warm orange bronze */
--deepdrft-tertiary: #2A7B8C; /* Atlantic turquoise */
--deepdrft-accent: #2A7B8C; /* Atlantic turquoise */
/* Extended Palette - Light Theme (Charleston) */
--deepdrft-quaternary: #7D9B8C; /* Sage green */
--deepdrft-quinary: #6B7D8A; /* Slate blue */
--deepdrft-senary: #C4967A; /* Warm terracotta */
--deepdrft-quaternary: #D4A556; /* Lamplight orange/yellow */
--deepdrft-quinary: #3D5A47; /* Swampy elegant green */
--deepdrft-senary: #6B4C6A; /* Sunset purple */
--deepdrft-septenary: #8A7A96; /* Soft plum */
/* Surface Colors */
@@ -32,17 +32,19 @@
--deepdrft-theme-septenary: var(--deepdrft-septenary);
/* Charleston-specific accent colors */
--charleston-iron: #1C1C1C;
--charleston-iron: #1A1A1A;
--charleston-iron-soft: #4A4A4A;
--charleston-cream: #FDFBF7;
--charleston-rose: #B8848C;
--charleston-gold: #C9A962;
--charleston-sage: #7D9B8C;
--charleston-bronze: #B8623D;
--charleston-turquoise: #2A7B8C;
--charleston-lamplight: #D4A556;
--charleston-swamp: #3D5A47;
--charleston-sunset: #6B4C6A;
/* Font Hierarchy - DRY font definitions */
/* Upscale steakhouse aesthetic - refined, modern luxury */
/* Upscale Charleston aesthetic - tall decorative ironwork elegance */
--deepdrft-font-largest-headers: "Bodoni Moda", serif; /* h1, hero text - high-fashion editorial */
--deepdrft-font-headers: "EB Garamond", serif; /* h2-h6 - elegant serif headers */
--deepdrft-font-headers: "Cormorant", serif; /* h2-h6 - elegant readable serif */
--deepdrft-font-body: "DM Sans", sans-serif; /* body, buttons, UI - clean modern */
}
@@ -111,13 +113,13 @@
.deepdrft-theme-light .deepdrft-gradient-soft-primary {
background: linear-gradient(45deg,
color-mix(in srgb, var(--charleston-iron) 4%, transparent) 0%,
color-mix(in srgb, var(--charleston-rose) 6%, transparent) 100%);
color-mix(in srgb, var(--charleston-bronze) 6%, transparent) 100%);
}
.deepdrft-theme-light .mud-paper.deepdrft-gradient-soft-secondary,
.deepdrft-theme-light .deepdrft-gradient-soft-secondary {
background: linear-gradient(45deg,
color-mix(in srgb, var(--charleston-gold) 6%, transparent) 0%,
color-mix(in srgb, var(--charleston-lamplight) 6%, transparent) 0%,
color-mix(in srgb, var(--charleston-iron) 4%, transparent) 100%);
}
@@ -125,13 +127,13 @@
.deepdrft-theme-light .deepdrft-gradient-soft-accent {
background: linear-gradient(135deg,
color-mix(in srgb, var(--charleston-iron) 3%, transparent) 0%,
color-mix(in srgb, var(--charleston-gold) 5%, transparent) 100%);
color-mix(in srgb, var(--charleston-lamplight) 5%, transparent) 100%);
}
.deepdrft-theme-light .mud-paper.deepdrft-gradient-soft-tertiary,
.deepdrft-theme-light .deepdrft-gradient-soft-tertiary {
background: linear-gradient(135deg,
color-mix(in srgb, var(--charleston-rose) 5%, transparent) 0%,
color-mix(in srgb, var(--charleston-bronze) 5%, transparent) 0%,
color-mix(in srgb, var(--charleston-iron) 3%, transparent) 100%);
}
@@ -139,7 +141,7 @@
.deepdrft-theme-light .deepdrft-gradient-features {
background: linear-gradient(to right,
color-mix(in srgb, var(--charleston-iron) 2%, transparent) 0%,
color-mix(in srgb, var(--charleston-rose) 3%, transparent) 100%);
color-mix(in srgb, var(--charleston-bronze) 3%, transparent) 100%);
}
/* Lowcountry Gradient Overrides (Dark Mode) */
@@ -204,17 +206,13 @@ h1, .deepdrft-text-hero, .deepdrft-heading-primary {
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
}
.deepdrft-text-hero {
font-size: clamp(2rem, 8vw, 4rem);
}
/* Hero Section Theme-Aware Text Colors */
/* Light mode (cream background): dark text */
.deepdrft-theme-light .deepdrft-hero-container .deepdrft-hero-title {
color: var(--charleston-iron);
}
.deepdrft-theme-light .deepdrft-hero-container .deepdrft-hero-subtitle {
color: var(--charleston-rose);
color: var(--charleston-bronze);
}
.deepdrft-theme-light .deepdrft-hero-container .deepdrft-hero-description {
color: var(--charleston-iron-soft);
@@ -351,6 +349,18 @@ body, p, span, div,
border-top: 4px solid var(--deepdrft-theme-tertiary);
}
.deepdrft-border-top-quaternary {
border-top: 4px solid var(--deepdrft-theme-quaternary);
}
.deepdrft-border-top-quinary {
border-top: 4px solid var(--deepdrft-theme-quinary);
}
.deepdrft-border-top-senary {
border-top: 4px solid var(--deepdrft-theme-senary);
}
/* Buttons */
.deepdrft-button-primary {
color: var(--deepdrft-theme-primary);
@@ -382,7 +392,7 @@ body, p, span, div,
.deepdrft-theme-light .mud-card.deepdrft-card-pink-tint,
.deepdrft-theme-light .mud-paper.deepdrft-card-pink-tint {
background: color-mix(in srgb, var(--charleston-rose) 10%, transparent);
background: color-mix(in srgb, var(--charleston-bronze) 10%, transparent);
}
.deepdrft-theme-dark .mud-card.deepdrft-card-pink-tint,
.deepdrft-theme-dark .mud-paper.deepdrft-card-pink-tint {
@@ -400,7 +410,7 @@ body, p, span, div,
.deepdrft-theme-light .mud-card.deepdrft-card-lavender-tint,
.deepdrft-theme-light .mud-paper.deepdrft-card-lavender-tint {
background: color-mix(in srgb, var(--charleston-sage) 10%, transparent);
background: color-mix(in srgb, var(--charleston-swamp) 10%, transparent);
}
.deepdrft-theme-dark .mud-card.deepdrft-card-lavender-tint,
.deepdrft-theme-dark .mud-paper.deepdrft-card-lavender-tint {
@@ -419,7 +429,7 @@ body, p, span, div,
.deepdrft-theme-light .mud-card.deepdrft-card-secondary-tint,
.deepdrft-theme-light .mud-paper.deepdrft-card-secondary-tint {
background: color-mix(in srgb, var(--charleston-rose) 8%, transparent);
background: color-mix(in srgb, var(--charleston-bronze) 8%, transparent);
}
.deepdrft-theme-dark .mud-card.deepdrft-card-secondary-tint,
.deepdrft-theme-dark .mud-paper.deepdrft-card-secondary-tint {
@@ -428,7 +438,7 @@ body, p, span, div,
.deepdrft-theme-light .mud-card.deepdrft-card-tertiary-tint,
.deepdrft-theme-light .mud-paper.deepdrft-card-tertiary-tint {
background: color-mix(in srgb, var(--charleston-gold) 8%, transparent);
background: color-mix(in srgb, var(--charleston-lamplight) 8%, transparent);
}
.deepdrft-theme-dark .mud-card.deepdrft-card-tertiary-tint,
.deepdrft-theme-dark .mud-paper.deepdrft-card-tertiary-tint {
@@ -483,7 +493,7 @@ body, p, span, div,
.deepdrft-hero-text-container {
max-width: 600px;
margin: 0 auto;
/*margin: 0 auto;*/
}
/* Feature Cards Layout */
@@ -606,27 +616,27 @@ body, p, span, div,
box-shadow: inset 0 0 20px rgba(28,28,28,0.03);
}
/* Gold Accent */
.charleston-gold-accent {
border-bottom: 2px solid var(--charleston-gold, #C9A962);
/* Lamplight Accent */
.charleston-lamplight-accent {
border-bottom: 2px solid var(--charleston-lamplight, #D4A556);
}
.charleston-gold-border {
border: 1px solid var(--charleston-gold, #C9A962);
.charleston-lamplight-border {
border: 1px solid var(--charleston-lamplight, #D4A556);
}
/* Rose Accent */
.charleston-rose-accent {
border-bottom: 2px solid var(--charleston-rose, #B8848C);
/* Bronze Accent */
.charleston-bronze-accent {
border-bottom: 2px solid var(--charleston-bronze, #B8623D);
}
.charleston-rose-border {
border: 1px solid var(--charleston-rose, #B8848C);
.charleston-bronze-border {
border: 1px solid var(--charleston-bronze, #B8623D);
}
/* Garden Card (subtle green tint) */
.charleston-garden-tint {
background: color-mix(in srgb, var(--charleston-sage) 8%, transparent);
background: color-mix(in srgb, var(--charleston-swamp) 8%, transparent);
}
/* Iron Gate Pattern Overlay */
+2 -2
View File
@@ -1,7 +1,7 @@
{
"sdk": {
"version": "10.0.100",
"version": "10.0.0",
"rollForward": "latestMajor",
"allowPrerelease": true
"allowPrerelease": false
}
}