Stylesheet: Collect and load theme mode files

This commit is contained in:
Sukhwinder Dhillon 2021-06-11 16:53:30 +02:00 committed by Johannes Meyer
parent c64e9888a2
commit 8b24e3bffe
2 changed files with 96 additions and 8 deletions

View File

@ -55,6 +55,13 @@ class LessCompiler
*/
protected $theme;
/**
* Path of the LESS theme mode
*
* @var string
*/
protected $themeMode;
/**
* Create a new LESS compiler
*/
@ -127,6 +134,11 @@ class LessCompiler
if ($this->theme !== null) {
$lessFiles[] = $this->theme;
}
if ($this->themeMode !== null) {
$lessFiles[] = $this->themeMode;
}
return $lessFiles;
}
@ -147,6 +159,23 @@ class LessCompiler
return $this;
}
/**
* Set the path to the LESS theme mode
*
* @param string $themeMode Path to the LESS theme mode
*
* @return $this
*/
public function setThemeMode($themeMode)
{
if (is_file($themeMode) && is_readable($themeMode)) {
$this->themeMode = $themeMode;
} else {
Logger::error('Can\t load theme mode %s. Make sure that the theme mode exists and is readable', $themeMode);
}
return $this;
}
/**
* Instruct the compiler to minify CSS
*
@ -216,6 +245,10 @@ class LessCompiler
$this->source .= file_get_contents($this->theme);
}
if ($this->themeMode !== null) {
$this->source .= file_get_contents($this->themeMode);
}
return preg_replace(
'/(\.icinga-module\.module-[^\s]+) (#layout\.[^\s]+)/m',
'\2 \1',

View File

@ -21,6 +21,28 @@ class StyleSheet
*/
const DEFAULT_THEME = 'Icinga';
/**
* The name of the default theme mode
*
* @var string
*/
const DEFAULT_MODE = 'dark';
/**
* RegEx pattern for matching full css @media query of theme mode
*
* @var string
*/
const REGEX_ALL_MODE_QUERY = '/@media\s*\(\s*min-height\s*:\s*@prefer-light-color-scheme\s*\)\s*,' .
'\s*\(\s*prefers-color-scheme\s*:\s*light\s*\)\s*and\s*\(\s*min-height\s*:\s*@enable-color-preference\s*\)/';
/**
* RegEx pattern for matching css @media query of theme mode
*
* @var string
*/
const REGEX_AUTO_MODE_QUERY = '/@media.*prefers-color-scheme/';
/**
* Array of core LESS files Web 2 sends to the client
*
@ -137,18 +159,23 @@ class StyleSheet
}
}
if ($theme && $theme !== self::DEFAULT_THEME) {
if (($pos = strpos($theme, '/')) !== false) {
$moduleName = substr($theme, 0, $pos);
$theme = substr($theme, $pos + 1);
if ($mm->hasLoaded($moduleName)) {
$module = $mm->getModule($moduleName);
$this->lessCompiler->setTheme($module->getCssDir() . '/themes/' . $theme . '.less');
if ($themePath = self::getThemeFile($theme)) {
$this->lessCompiler->setTheme($themePath);
}
$mode = 'none';
if ($user = Auth::getInstance()->getUser()) {
$file = $themePath !== null ? file_get_contents($themePath) : '';
if ($file !== '' && ! preg_match(self::REGEX_ALL_MODE_QUERY, $file)) {
if (preg_match(self::REGEX_AUTO_MODE_QUERY, $file)) {
$mode = 'system';
}
} else {
$this->lessCompiler->setTheme($this->pubPath . '/css/themes/' . $theme . '.less');
$mode = $user->getPreferences()->getValue('icingaweb', 'theme_mode', self::DEFAULT_MODE);
}
}
$this->lessCompiler->setThemeMode($this->pubPath . '/css/modes/'. $mode . '.less');
}
/**
@ -236,4 +263,32 @@ class StyleSheet
return IcingaException::describe($e);
}
}
/**
* Get the path to the current LESS theme file
*
* @param $theme
*
* @return string|null Return null if self::DEFAULT_THEME is set as theme, path otherwise
*/
public static function getThemeFile($theme)
{
$app = Icinga::app();
if ($theme && $theme !== self::DEFAULT_THEME) {
if (($pos = strpos($theme, '/')) !== false) {
$moduleName = substr($theme, 0, $pos);
$theme = substr($theme, $pos + 1);
if ($app->getModuleManager()->hasLoaded($moduleName)) {
$module = $app->getModuleManager()->getModule($moduleName);
return $module->getCssDir() . '/themes/' . $theme . '.less';
}
} else {
return $app->getBaseDir('public') . '/css/themes/' . $theme . '.less';
}
}
return null;
}
}