refactor: change theme handling to support element-ui scss variables

This commit is contained in:
pa
2025-07-27 21:39:10 +09:00
committed by Natsumi
parent 96dfe2fcef
commit def96c1a4d
6 changed files with 91 additions and 98 deletions

View File

@@ -8,12 +8,14 @@
// For a copy, see <https://opensource.org/licenses/MIT>.
//
@use "./assets/scss/flags.scss";
@use "./assets/scss/animated-emoji.scss";
$--font-path: '~element-ui/lib/theme-chalk/fonts';
@use './assets/scss/flags.scss';
@use './assets/scss/animated-emoji.scss';
@import '~animate.css/animate.min.css';
@import '~noty/lib/noty.css';
@import '~element-ui/lib/theme-chalk/index.css';
@import '~element-ui/packages/theme-chalk/src/index';
.color-palettes {
background: #409eff;

View File

@@ -9,3 +9,4 @@ export * from './user';
export * from './instance';
export * from './world';
export * from './moderation';
export * from './themes';

View File

@@ -0,0 +1,39 @@
export const THEME_CONFIG = {
system: {
cssFile: '',
requiresDarkBase: false,
isDark: 'system',
name: 'System'
},
light: {
cssFile: '',
requiresDarkBase: false,
isDark: false,
name: 'Light'
},
dark: { cssFile: '', requiresDarkBase: true, isDark: true, name: 'Dark' },
darkvanillaold: {
cssFile: 'theme.darkvanillaold.css',
requiresDarkBase: true,
isDark: true,
name: 'Dark Vanilla Old'
},
darkvanilla: {
cssFile: 'theme.darkvanilla.css',
requiresDarkBase: true,
isDark: true,
name: 'Dark Vanilla'
},
pink: {
cssFile: 'theme.pink.css',
requiresDarkBase: true,
isDark: true,
name: 'Pink'
},
material3: {
cssFile: 'theme.material3.css',
requiresDarkBase: true,
isDark: true,
name: 'Material 3'
}
};

View File

@@ -1,5 +1,6 @@
import { storeToRefs } from 'pinia';
import { useAppearanceSettingsStore } from '../../../stores';
import { THEME_CONFIG } from '../../constants';
/**
*
@@ -21,43 +22,10 @@ function changeAppDarkStyle(isDark) {
}
}
/**
*
* @param {string} themeMode
* @returns
*/
function changeAppThemeStyle(themeMode) {
const themeStyle = {};
switch (themeMode) {
case 'light':
themeStyle.href = '';
break;
case 'dark':
themeStyle.href = '';
break;
case 'darkvanillaold':
themeStyle.href = 'theme.darkvanillaold.css';
break;
case 'darkvanilla':
themeStyle.href = 'theme.darkvanilla.css';
break;
case 'pink':
themeStyle.href = 'theme.pink.css';
break;
case 'material3':
themeStyle.href = 'theme.material3.css';
break;
case 'system':
themeStyle.href = '';
break;
}
const themeConfig = THEME_CONFIG[themeMode];
if (!themeConfig) return;
/**
* prevents flickering
* giving absolute paths does prevent flickering
* when switching from another dark theme to 'dark' theme
* <del>works on my machine</del>
*/
let filePathPrefix = 'file://vrcx/';
if (LINUX) {
filePathPrefix = './';
@@ -70,38 +38,35 @@ function changeAppThemeStyle(themeMode) {
$appThemeStyle.rel = 'stylesheet';
document.head.appendChild($appThemeStyle);
}
$appThemeStyle.href = themeStyle.href
? `${filePathPrefix}${themeStyle.href}`
$appThemeStyle.href = themeConfig.cssFile
? `${filePathPrefix}${themeConfig.cssFile}`
: '';
let $appThemeDarkStyle = document.getElementById('app-theme-dark-style');
const darkThemeCssPath = `${filePathPrefix}theme.dark.css`;
const shouldApplyDarkBase =
themeConfig.requiresDarkBase ||
(themeMode === 'system' && systemIsDarkMode());
if (!$appThemeDarkStyle && themeMode !== 'light') {
if (themeMode === 'system' && !systemIsDarkMode()) {
return;
if (shouldApplyDarkBase) {
if (!$appThemeDarkStyle) {
$appThemeDarkStyle = document.createElement('link');
$appThemeDarkStyle.setAttribute('id', 'app-theme-dark-style');
$appThemeDarkStyle.rel = 'stylesheet';
$appThemeDarkStyle.href = darkThemeCssPath;
document.head.insertBefore($appThemeDarkStyle, $appThemeStyle);
} else if ($appThemeDarkStyle.href !== darkThemeCssPath) {
$appThemeDarkStyle.href = darkThemeCssPath;
}
$appThemeDarkStyle = document.createElement('link');
$appThemeDarkStyle.setAttribute('id', 'app-theme-dark-style');
$appThemeDarkStyle.rel = 'stylesheet';
$appThemeDarkStyle.href = darkThemeCssPath;
document.head.insertBefore($appThemeDarkStyle, $appThemeStyle);
} else {
if (themeMode === 'system' && systemIsDarkMode()) {
if ($appThemeDarkStyle.href === darkThemeCssPath) {
return;
}
$appThemeDarkStyle.href = darkThemeCssPath;
} else if (themeMode !== 'light' && themeMode !== 'system') {
if ($appThemeDarkStyle.href === darkThemeCssPath) {
return;
}
$appThemeDarkStyle.href = darkThemeCssPath;
} else {
$appThemeDarkStyle && $appThemeDarkStyle.remove();
}
$appThemeDarkStyle && $appThemeDarkStyle.remove();
}
let isDarkForExternalApp = themeConfig.isDark;
if (isDarkForExternalApp === 'system') {
isDarkForExternalApp = systemIsDarkMode();
}
changeAppDarkStyle(isDarkForExternalApp);
}
/**

View File

@@ -340,40 +340,12 @@
</el-button>
<el-dropdown-menu>
<el-dropdown-item
@click.native="saveThemeMode('system')"
v-text="
t('view.settings.appearance.appearance.theme_mode_system')
"></el-dropdown-item>
<el-dropdown-item
@click.native="saveThemeMode('light')"
v-text="
t('view.settings.appearance.appearance.theme_mode_light')
"></el-dropdown-item>
<el-dropdown-item
@click.native="saveThemeMode('dark')"
v-text="
t('view.settings.appearance.appearance.theme_mode_dark')
"></el-dropdown-item>
<el-dropdown-item
@click.native="saveThemeMode('darkvanilla')"
v-text="
t('view.settings.appearance.appearance.theme_mode_darkvanilla')
"></el-dropdown-item>
<el-dropdown-item
@click.native="saveThemeMode('darkvanillaold')"
v-text="
t('view.settings.appearance.appearance.theme_mode_darkvanillaold')
"></el-dropdown-item>
<el-dropdown-item
@click.native="saveThemeMode('pink')"
v-text="
t('view.settings.appearance.appearance.theme_mode_pink')
"></el-dropdown-item>
<el-dropdown-item
@click.native="saveThemeMode('material3')"
v-text="
t('view.settings.appearance.appearance.theme_mode_material3')
"></el-dropdown-item>
v-for="(config, themeKey) in THEME_CONFIG"
:key="themeKey"
@click.native="saveThemeMode(themeKey)"
:class="{ 'is-active': themeMode === themeKey }">
{{ t(`view.settings.appearance.appearance.theme_mode_${themeKey}`) }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
@@ -1885,6 +1857,7 @@
import FeedFiltersDialog from './dialogs/FeedFiltersDialog.vue';
import AvatarProviderDialog from './dialogs/AvatarProviderDialog.vue';
import { openExternalLink } from '../../shared/utils';
import { THEME_CONFIG } from '../../shared/constants';
const { messages, t } = useI18n();
const { $message } = getCurrentInstance().proxy;

View File

@@ -64,7 +64,14 @@ module.exports = (env, argv) => {
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader'
{
loader: 'sass-loader',
options: {
sassOptions: {
quietDeps: true
}
}
}
]
},
{
@@ -77,7 +84,13 @@ module.exports = (env, argv) => {
]
},
devServer: {
port: 9000
port: 9000,
client: {
overlay: {
warnings: false,
errors: true
}
}
},
resolve: {
extensions: ['.js', '.vue', '.css', '.scss'],