Browse Source

add light mode (#2223)

pull/2225/head
Jason Dove 1 year ago committed by GitHub
parent
commit
e0175fc4e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      CHANGELOG.md
  2. 1
      ErsatzTV.Core/Domain/ConfigElementKey.cs
  3. 6
      ErsatzTV/Pages/Artist.razor
  4. 6
      ErsatzTV/Pages/Movie.razor
  5. 6
      ErsatzTV/Pages/TelevisionEpisodeList.razor
  6. 6
      ErsatzTV/Pages/TelevisionSeasonList.razor
  7. 2
      ErsatzTV/Pages/_Host.cshtml
  8. 50
      ErsatzTV/Shared/MainLayout.razor
  9. 31
      ErsatzTV/wwwroot/css/site.css

1
CHANGELOG.md

@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Sidecar text subtitles (e.g. `srt` files) - Sidecar text subtitles (e.g. `srt` files)
- Embedded image subtitles - Embedded image subtitles
- Embedded text subtitles that have already been extracted by ETV - Embedded text subtitles that have already been extracted by ETV
- Add light mode and light/dark mode toggle to app bar
### Fixed ### Fixed
- Fix app startup with MySql/MariaDB - Fix app startup with MySql/MariaDB

1
ErsatzTV.Core/Domain/ConfigElementKey.cs

@ -28,6 +28,7 @@ public class ConfigElementKey
public static ConfigElementKey SearchIndexVersion => new("search_index.version"); public static ConfigElementKey SearchIndexVersion => new("search_index.version");
public static ConfigElementKey HDHRTunerCount => new("hdhr.tuner_count"); public static ConfigElementKey HDHRTunerCount => new("hdhr.tuner_count");
public static ConfigElementKey HDHRUUID => new("hdhr.uuid"); public static ConfigElementKey HDHRUUID => new("hdhr.uuid");
public static ConfigElementKey PagesIsDarkMode => new("pages.is_dark_mode");
public static ConfigElementKey ChannelsPageSize => new("pages.channels.page_size"); public static ConfigElementKey ChannelsPageSize => new("pages.channels.page_size");
public static ConfigElementKey CollectionsPageSize => new("pages.collections.page_size"); public static ConfigElementKey CollectionsPageSize => new("pages.collections.page_size");
public static ConfigElementKey MultiCollectionsPageSize => new("pages.multi_collections.page_size"); public static ConfigElementKey MultiCollectionsPageSize => new("pages.multi_collections.page_size");

6
ErsatzTV/Pages/Artist.razor

@ -19,13 +19,13 @@
<img src="@($"artwork/fanart/{_artist.FanArt}")" alt="fan art"/> <img src="@($"artwork/fanart/{_artist.FanArt}")" alt="fan art"/>
} }
</MudContainer> </MudContainer>
<MudContainer MaxWidth="MaxWidth.Large" Style="margin-top: 100px"> <MudContainer MaxWidth="MaxWidth.Large" Style="margin-top: 100px" Class="z-10">
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Spacing="6"> <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Spacing="6">
@if (!string.IsNullOrWhiteSpace(_artist.Thumbnail)) @if (!string.IsNullOrWhiteSpace(_artist.Thumbnail))
{ {
<MudImage Elevation="2" Src="@($"artwork/thumbnails/{_artist.Thumbnail}")" Class="rounded-lg" Style="height: 220px; width: 220px; margin-left: auto; margin-right: auto;" /> <MudImage Elevation="2" Src="@($"artwork/thumbnails/{_artist.Thumbnail}")" Class="rounded-lg z-10" Style="height: 220px; width: 220px; margin-left: auto; margin-right: auto;" />
} }
<div style="display: flex; flex-direction: column; height: 100%"> <div style="display: flex; flex-direction: column; height: 100%" class="z-10">
<MudStack Row="false"> <MudStack Row="false">
<MudHidden Invert="true" Breakpoint="Breakpoint.SmAndDown"> <MudHidden Invert="true" Breakpoint="Breakpoint.SmAndDown">
<MudText Typo="Typo.h4" Class="media-item-title">@_artist?.Name</MudText> <MudText Typo="Typo.h4" Class="media-item-title">@_artist?.Name</MudText>

6
ErsatzTV/Pages/Movie.razor

@ -27,11 +27,11 @@
} }
} }
</MudContainer> </MudContainer>
<MudContainer MaxWidth="MaxWidth.Large" Style="margin-top: 100px"> <MudContainer MaxWidth="MaxWidth.Large" Style="margin-top: 100px" Class="z-10">
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Spacing="6"> <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Spacing="6">
@if (!string.IsNullOrWhiteSpace(_movie?.Poster)) @if (!string.IsNullOrWhiteSpace(_movie?.Poster))
{ {
<div style="display: flex; flex-direction: column; max-height: 325px; position: relative"> <div style="display: flex; flex-direction: column; max-height: 325px; position: relative" class="z-10">
<MudImage Src="@GetPosterUrl(_movie.Poster)" Elevation="2" Class="rounded-lg" Style="max-height: 325px; margin-left: auto; margin-right: auto" /> <MudImage Src="@GetPosterUrl(_movie.Poster)" Elevation="2" Class="rounded-lg" Style="max-height: 325px; margin-left: auto; margin-right: auto" />
@if (_movie.MediaItemState == MediaItemState.FileNotFound) @if (_movie.MediaItemState == MediaItemState.FileNotFound)
{ {
@ -47,7 +47,7 @@
} }
</div> </div>
} }
<div style="display: flex; flex-direction: column; height: 100%"> <div style="display: flex; flex-direction: column; height: 100%" class="z-10">
<MudStack Row="false"> <MudStack Row="false">
<MudHidden Invert="true" Breakpoint="Breakpoint.SmAndDown"> <MudHidden Invert="true" Breakpoint="Breakpoint.SmAndDown">
<MudText Typo="Typo.h4" Class="media-item-title">@_movie?.Title</MudText> <MudText Typo="Typo.h4" Class="media-item-title">@_movie?.Title</MudText>

6
ErsatzTV/Pages/TelevisionEpisodeList.razor

@ -27,13 +27,13 @@
} }
} }
</MudContainer> </MudContainer>
<MudContainer MaxWidth="MaxWidth.Large" Style="margin-top: 100px"> <MudContainer MaxWidth="MaxWidth.Large" Style="margin-top: 100px" Class="z-10">
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Spacing="6"> <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Spacing="6">
@if (!string.IsNullOrWhiteSpace(_season?.Poster)) @if (!string.IsNullOrWhiteSpace(_season?.Poster))
{ {
<MudImage Src="@GetPosterUrl(_season.Poster)" Elevation="2" Class="rounded-lg" Style="max-height: 325px; margin-left: auto; margin-right: auto"/> <MudImage Src="@GetPosterUrl(_season.Poster)" Elevation="2" Class="rounded-lg z-10" Style="max-height: 325px; margin-left: auto; margin-right: auto"/>
} }
<MudStack Row="false" Style="flex: 1"> <MudStack Row="false" Style="flex: 1" Class="z-10">
<MudStack Row="false"> <MudStack Row="false">
<MudLink Href="@($"media/tv/shows/{_season?.ShowId}")"> <MudLink Href="@($"media/tv/shows/{_season?.ShowId}")">
<MudHidden Invert="true" Breakpoint="Breakpoint.SmAndDown"> <MudHidden Invert="true" Breakpoint="Breakpoint.SmAndDown">

6
ErsatzTV/Pages/TelevisionSeasonList.razor

@ -26,10 +26,10 @@
} }
} }
</MudContainer> </MudContainer>
<MudContainer MaxWidth="MaxWidth.Large" Style="margin-top: 100px"> <MudContainer MaxWidth="MaxWidth.Large" Style="margin-top: 100px" Class="z-10">
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Spacing="6"> <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Spacing="6">
<MudImage Src="@GetPosterUrl(_show.Poster)" Elevation="2" Class="rounded-lg" Style="max-height: 325px; margin-left: auto; margin-right: auto" /> <MudImage Src="@GetPosterUrl(_show.Poster)" Elevation="2" Class="rounded-lg z-10" Style="max-height: 325px; margin-left: auto; margin-right: auto" />
<MudStack Row="false" Style="flex: 1"> <MudStack Row="false" Style="flex: 1" Class="z-10">
<MudStack Row="false"> <MudStack Row="false">
<MudHidden Invert="true" Breakpoint="Breakpoint.SmAndDown"> <MudHidden Invert="true" Breakpoint="Breakpoint.SmAndDown">
<MudText Typo="Typo.h4" Class="media-item-title">@_show?.Title</MudText> <MudText Typo="Typo.h4" Class="media-item-title">@_show?.Title</MudText>

2
ErsatzTV/Pages/_Host.cshtml

@ -19,7 +19,7 @@
<link href="_content/MudBlazor/MudBlazor.min.css?v=@(Assembly.GetAssembly(typeof(AbstractLocalizationInterceptor))?.GetName().Version?.ToString())" rel="stylesheet"/> <link href="_content/MudBlazor/MudBlazor.min.css?v=@(Assembly.GetAssembly(typeof(AbstractLocalizationInterceptor))?.GetName().Version?.ToString())" rel="stylesheet"/>
<link href="css/site.css" asp-append-version="true" rel="stylesheet"/> <link href="css/site.css" asp-append-version="true" rel="stylesheet"/>
<link href="ErsatzTV.styles.css" asp-append-version="true" rel="stylesheet"/> <link href="ErsatzTV.styles.css" asp-append-version="true" rel="stylesheet"/>
<link href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"> <link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script> <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/npm/media-chrome@1/+esm"></script> <script type="module" src="https://cdn.jsdelivr.net/npm/media-chrome@1/+esm"></script>

50
ErsatzTV/Shared/MainLayout.razor

@ -1,5 +1,6 @@
@inherits LayoutComponentBase @inherits LayoutComponentBase
@using System.Reflection @using System.Reflection
@using ErsatzTV.Application.Configuration
@using ErsatzTV.Application.Search @using ErsatzTV.Application.Search
@using ErsatzTV.Core.Health @using ErsatzTV.Core.Health
@using ErsatzTV.Core.Interfaces.Search @using ErsatzTV.Core.Interfaces.Search
@ -13,12 +14,12 @@
@inject ICourier Courier @inject ICourier Courier
@inject IHealthCheckService HealthCheckService; @inject IHealthCheckService HealthCheckService;
<MudThemeProvider Theme="ErsatzTvTheme"/> <MudThemeProvider Theme="ErsatzTvTheme" IsDarkMode="_isDarkMode"/>
<MudDialogProvider BackdropClick="false"/> <MudDialogProvider BackdropClick="false"/>
<MudSnackbarProvider/> <MudSnackbarProvider/>
<MudPopoverProvider/> <MudPopoverProvider/>
<MudLayout @onclick="@(() => _isOpen = false)" Class="d-flex d-flex-column" Style="height: 100vh"> <MudLayout @onclick="@(() => _isOpen = false)" Class="@(_isDarkMode ? "d-flex d-flex-column ersatztv-dark" : "d-flex d-flex-column ersatztv-light")" Style="height: 100vh">
<MudAppBar Elevation="1" Class="app-bar"> <MudAppBar Elevation="1" Class="app-bar">
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@ToggleDrawer"/> <MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@ToggleDrawer"/>
<div style="min-width: 240px" class="ml-3 d-none d-md-flex"> <div style="min-width: 240px" class="ml-3 d-none d-md-flex">
@ -92,6 +93,7 @@
<MudTooltip Text="GitHub"> <MudTooltip Text="GitHub">
<MudIconButton Icon="@Icons.Custom.Brands.GitHub" Color="Color.Primary" Href="https://github.com/ErsatzTV/ErsatzTV" Target="_blank"/> <MudIconButton Icon="@Icons.Custom.Brands.GitHub" Color="Color.Primary" Href="https://github.com/ErsatzTV/ErsatzTV" Target="_blank"/>
</MudTooltip> </MudTooltip>
<MudIconButton Icon="@(DarkLightModeButtonIcon)" Color="Color.Primary" OnClick="@DarkModeToggle" />
<AuthorizeView> <AuthorizeView>
<form action="/account/logout" method="post"> <form action="/account/logout" method="post">
<MudTooltip Text="Logout"> <MudTooltip Text="Logout">
@ -225,6 +227,7 @@
private List<SearchTargetViewModel> _searchTargets; private List<SearchTargetViewModel> _searchTargets;
private int _errors; private int _errors;
private int _warnings; private int _warnings;
private bool _isDarkMode = true;
protected override void OnInitialized() protected override void OnInitialized()
{ {
@ -242,6 +245,18 @@
await HandleHealthCheckSummary(HealthCheckService.GetHealthCheckSummary(), CancellationToken.None); await HandleHealthCheckSummary(HealthCheckService.GetHealthCheckSummary(), CancellationToken.None);
} }
private async Task DarkModeToggle()
{
_isDarkMode = !_isDarkMode;
await Mediator.Send(new SaveConfigElementByKey(ConfigElementKey.PagesIsDarkMode, _isDarkMode.ToString()));
}
public string DarkLightModeButtonIcon => _isDarkMode switch
{
true => Icons.Material.Rounded.DarkMode,
false => Icons.Material.Outlined.LightMode,
};
public void Dispose() public void Dispose()
{ {
SystemStartup.OnDatabaseReady -= OnStartupProgress; SystemStartup.OnDatabaseReady -= OnStartupProgress;
@ -257,7 +272,7 @@
private static MudTheme ErsatzTvTheme => new() private static MudTheme ErsatzTvTheme => new()
{ {
PaletteLight = new PaletteLight PaletteDark = new PaletteDark
{ {
ActionDefault = "rgba(255,255,255, 0.80)", ActionDefault = "rgba(255,255,255, 0.80)",
Primary = "#009000", Primary = "#009000",
@ -269,7 +284,8 @@
DrawerText = "rgba(255,255,255, 0.80)", DrawerText = "rgba(255,255,255, 0.80)",
Divider = "rgba(255,255,255, 0.40)", Divider = "rgba(255,255,255, 0.40)",
Background = "#272727", Background = "#272727",
TextPrimary = "rgba(255,255,255, 0.80)", BackgroundGray = "#272727",
TextPrimary = "rgba(255,255,255, 0.90)",
TextSecondary = "rgba(255,255,255, 0.80)", TextSecondary = "rgba(255,255,255, 0.80)",
TextDisabled = "rgba(255,255,255, 0.40)", TextDisabled = "rgba(255,255,255, 0.40)",
ActionDisabled = "rgba(255,255,255, 0.40)", ActionDisabled = "rgba(255,255,255, 0.40)",
@ -278,6 +294,28 @@
Info = "#00c0c0", Info = "#00c0c0",
Tertiary = "#00c000", Tertiary = "#00c000",
White = Colors.Shades.White White = Colors.Shades.White
},
PaletteLight = new PaletteLight
{
ActionDefault = "#546E7A",
Primary = "#546E7A",
Secondary = "#EC407A",
AppbarBackground = "#ECEFF1",
AppbarText = "#424242",
DrawerBackground = "#FFFFFF",
DrawerText = "#424242",
Surface = "#FFFFFF",
Background = "#F5F5F5",
TextPrimary = "#212121",
TextSecondary = "rgba(0,0,0, 0.7)",
TextDisabled = "rgba(0,0,0, 0.5)",
ActionDisabled = "rgba(0,0,0, 0.3)",
Divider = "rgba(0,0,0, 0.12)",
TableHover = "rgba(0,0,0, 0.02)",
TableLines = "rgba(0,0,0,0.08)",
Info = "#00c0c0",
Tertiary = "#00c000"
} }
}; };
@ -318,6 +356,10 @@
{ {
_searchTargets = await Mediator.Send(new QuerySearchTargets(), _cts.Token); _searchTargets = await Mediator.Send(new QuerySearchTargets(), _cts.Token);
} }
_isDarkMode = await Mediator.Send(new GetConfigElementByKey(ConfigElementKey.PagesIsDarkMode), _cts.Token)
.MapT(result => !bool.TryParse(result.Value, out bool value) || value)
.IfNoneAsync(true);
} }
protected async void OnSearchTargetsChanged(object sender, EventArgs e) => _searchTargets = await Mediator.Send(new QuerySearchTargets(), _cts.Token); protected async void OnSearchTargetsChanged(object sender, EventArgs e) => _searchTargets = await Mediator.Send(new QuerySearchTargets(), _cts.Token);

31
ErsatzTV/wwwroot/css/site.css

@ -1,4 +1,18 @@
.media-card-grid { div.ersatztv-dark {
--fanart-background-rgb: 39, 39, 39;
--search-bar-background: rgba(255, 255, 255, .15);
--search-bar-text-color: #fafafa;
--selected-row-color: #009000;
}
div.ersatztv-light {
--fanart-background-rgb: 245, 245, 245;
--search-bar-background: #fff;
--search-bar-text-color: #424242;
--selected-row-color: #546E7A77;
}
.media-card-grid {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
flex-wrap: wrap; flex-wrap: wrap;
@ -52,13 +66,13 @@
.search-bar .mud-input { height: 42px; } .search-bar .mud-input { height: 42px; }
.search-bar { .search-bar {
background-color: rgba(255, 255, 255, .15); background-color: var(--search-bar-background);
border-radius: 4px; border-radius: 4px;
height: 42px; height: 42px;
margin-bottom: 5px; margin-bottom: 5px;
} }
.search-bar div .mud-input-root { color: #fafafa; } .search-bar div .mud-input-root { color: var(--search-bar-text-color); }
.search-bar .mud-input.mud-input-outlined .mud-input-outlined-border { .search-bar .mud-input.mud-input-outlined .mud-input-outlined-border {
border: none; border: none;
@ -70,7 +84,7 @@
.fanart-container { .fanart-container {
position: relative; position: relative;
width: 100%; width: 100%;
z-index: -1; z-index: 0;
} }
.fanart-container img { .fanart-container img {
@ -83,7 +97,7 @@
} }
.fanart-container > .fanart-tint { .fanart-container > .fanart-tint {
background: linear-gradient(rgba(39, 39, 39, 0.47) 0%, rgb(39, 39, 39) 100%); background: linear-gradient(rgba(var(--fanart-background-rgb), 0.47) 0%, rgb(var(--fanart-background-rgb)) 100%);
height: 400px; height: 400px;
position: absolute; position: absolute;
width: 100%; width: 100%;
@ -148,11 +162,6 @@
font-weight: unset; font-weight: unset;
} }
.form-field-stack .mud-typography,
.mud-form .mud-typography-h5 {
color: rgba(255, 255, 255, 0.90);
}
.form-field-stack > div.d-flex { .form-field-stack > div.d-flex {
width: 300px; width: 300px;
justify-content: flex-start; justify-content: flex-start;
@ -168,5 +177,5 @@
} }
.selected { .selected {
background-color: #009000 !important; background-color: var(--selected-row-color) !important;
} }

Loading…
Cancel
Save