Make the default theme automatically determined by the browser (if possible).

This commit is contained in:
Buster "Silver Eagle" Neece 2021-04-29 07:01:41 -05:00
parent e94f90ceb6
commit e5eeb2b631
No known key found for this signature in database
GPG Key ID: 6D9E12FF03411F4E
13 changed files with 56 additions and 48 deletions

View File

@ -5,7 +5,10 @@ release channel, you can take advantage of these new features and fixes.
## New Features/Changes
There have been no changes since the last stable release.
- **Automatic Theme Selection:** If you haven't set a default theme for either your user account or the AzuraCast public
pages, the theme will automatically be determined by the user's browser based on their OS's theme preference (dark or
light). You can override this by selecting a default theme in the "Branding" settings, or reset to using browser
preference by selecting the "Prefer System Default" option.
## Code Quality/Technical Changes

View File

@ -16,8 +16,9 @@ return [
'Select a theme to use as a base for station public pages and the login page.'
),
'choices' => [
'light' => __('Light') . ' (' . __('Default') . ')',
'dark' => __('Dark'),
App\Customization::THEME_BROWSER => __('Prefer System Default'),
App\Customization::THEME_LIGHT => __('Light'),
App\Customization::THEME_DARK => __('Dark'),
],
'default' => App\Customization::DEFAULT_THEME,
'form_group_class' => 'col-md-6',

View File

@ -93,8 +93,9 @@ return [
[
'label' => __('Site Theme'),
'choices' => [
'light' => __('Light') . ' (' . __('Default') . ')',
'dark' => __('Dark'),
App\Customization::THEME_BROWSER => __('Prefer System Default'),
App\Customization::THEME_LIGHT => __('Light'),
App\Customization::THEME_DARK => __('Dark'),
],
'default' => App\Customization::DEFAULT_THEME,
'form_group_class' => 'col-md-6',

View File

@ -1,3 +1,3 @@
&.embed-social {
body.embed-social {
background: $card-bg !important;
}

View File

@ -1,4 +1,4 @@
&.page-minimal {
body.page-minimal {
background: $body-bg url($public-page-bg);
background-size: cover;
background-attachment: fixed;

View File

@ -1,4 +1,4 @@
& {
body {
background-color: $body-bg;
color: $body-color;
}

View File

@ -3,12 +3,12 @@
@import 'common';
}
body.theme-light {
@at-root {
$theme: 'light';
@import 'common-colors';
}
body.theme-dark {
[data-theme="dark"] {
$theme: 'dark';
@import 'common-colors';
}

View File

@ -2,9 +2,10 @@
namespace App\Controller\Frontend\Profile;
use App\Form\UserProfileForm;
use App\Customization;
use App\Http\Response;
use App\Http\ServerRequest;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Http\Message\ResponseInterface;
class ThemeAction
@ -12,9 +13,23 @@ class ThemeAction
public function __invoke(
ServerRequest $request,
Response $response,
UserProfileForm $userProfileForm
EntityManagerInterface $em
): ResponseInterface {
$userProfileForm->switchTheme($request);
$user = $request->getUser();
$currentTheme = $user->getTheme();
if (empty($currentTheme)) {
$currentTheme = Customization::DEFAULT_THEME;
}
$user->setTheme(
(Customization::THEME_LIGHT === $currentTheme)
? Customization::THEME_DARK
: Customization::THEME_LIGHT
);
$em->persist($user);
$em->flush();
$referrer = $request->getHeaderLine('Referer');
return $response->withRedirect(

View File

@ -9,8 +9,9 @@ use Psr\Http\Message\ServerRequestInterface;
class Customization
{
public const DEFAULT_THEME = 'light';
public const DEFAULT_THEME = 'browser';
public const THEME_BROWSER = 'browser';
public const THEME_LIGHT = 'light';
public const THEME_DARK = 'dark';

View File

@ -278,7 +278,7 @@ class Settings
* @ORM\Column(name="public_theme", type="string", length=50, nullable=true)
*
* @OA\Property(example="light")
* @Assert\Choice({Customization::THEME_LIGHT, Customization::THEME_DARK})
* @Assert\Choice({Customization::THEME_BROWSER, Customization::THEME_LIGHT, Customization::THEME_DARK})
* @var string|null Base Theme for Public Pages
*/
protected $public_theme = Customization::DEFAULT_THEME;

View File

@ -58,31 +58,6 @@ class UserProfileForm extends EntityForm
return parent::process($request, $user);
}
public function switchTheme(ServerRequest $request): void
{
$user = $request->getUser();
$themeField = $this->getField('theme');
$themeFieldOptions = $themeField->getOptions();
$themeOptions = array_keys($themeFieldOptions['choices']);
$currentTheme = $user->getTheme();
if (empty($currentTheme)) {
$currentTheme = $themeField->getValue();
}
foreach ($themeOptions as $theme) {
if ($theme !== $currentTheme) {
$user->setTheme($theme);
break;
}
}
$this->em->persist($user);
$this->em->flush();
}
public function getView(ServerRequest $request): string
{
$user = $request->getUser();

View File

@ -12,11 +12,9 @@
* @var App\Environment $environment
*/
$page_class ??= '';
$page_class .= ' theme-' . $customization->getTheme();
?>
<!DOCTYPE html>
<html>
<html data-theme="<?=$customization->getTheme()?>">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
@ -37,7 +35,7 @@ $page_class .= ' theme-' . $customization->getTheme();
echo $assets->js();
?>
</head>
<body class="page-full <?=$page_class?> <?php
<body class="page-full <?=$page_class ?? ''?> <?php
if (!empty($sidebar)): ?>has-sidebar<?php
endif; ?>">
<?=$assets->inlineJs()?>
@ -207,5 +205,13 @@ if (null !== $flash && $flash->hasMessages()): ?>
</script>
<?php
endif; ?>
<script type="text/javascript" nonce="<?=$assets->getCspNonce()?>">
let currentTheme = document.documentElement.getAttribute('data-theme');
if (currentTheme === 'browser') {
currentTheme = (window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', currentTheme);
}
</script>
</body>
</html>

View File

@ -13,10 +13,8 @@
* @var App\Environment $environment
*/
$page_class ??= '';
$page_class .= ' theme-' . $customization->getPublicTheme();
?>
<html>
<html data-theme="<?=$customization->getPublicTheme()?>">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
@ -39,7 +37,7 @@ $page_class .= ' theme-' . $customization->getPublicTheme();
?>
</head>
<body class="page-minimal <?=$page_class?>">
<body class="page-minimal <?=$page_class ?? ''?>">
<?=$assets->inlineJs()?>
<?=$this->section('content')?>
@ -67,5 +65,13 @@ if (null !== $flash && $flash->hasMessages()): ?>
</script>
<?php
endif; ?>
<script type="text/javascript" nonce="<?=$assets->getCspNonce()?>">
let currentTheme = document.documentElement.getAttribute('data-theme');
if (currentTheme === 'browser') {
currentTheme = (window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', currentTheme);
}
</script>
</body>
</html>