mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-10 04:30:25 +02:00
add setting to override theme primary shade (#1791)
This commit is contained in:
@@ -724,6 +724,10 @@
|
|||||||
"accentColor": "accent color",
|
"accentColor": "accent color",
|
||||||
"useThemeAccentColor": "use theme accent color",
|
"useThemeAccentColor": "use theme accent color",
|
||||||
"useThemeAccentColor_description": "use the primary color defined in the selected theme instead of the custom accent color",
|
"useThemeAccentColor_description": "use the primary color defined in the selected theme instead of the custom accent color",
|
||||||
|
"useThemePrimaryShade": "use theme primary shade",
|
||||||
|
"useThemePrimaryShade_description": "use the primary shade defined in the selected theme for primary color variants",
|
||||||
|
"primaryShade": "primary shade",
|
||||||
|
"primaryShade_description": "override the primary shade (0–9) used for buttons, links, and other primary-colored elements",
|
||||||
"albumBackground_description": "adds a background image for album pages containing the album art",
|
"albumBackground_description": "adds a background image for album pages containing the album art",
|
||||||
"albumBackground": "album background image",
|
"albumBackground": "album background image",
|
||||||
"albumBackgroundBlur_description": "adjusts the amount of blur applied to the album background image",
|
"albumBackgroundBlur_description": "adjusts the amount of blur applied to the album background image",
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ type SettingsProperties = {
|
|||||||
'settings.themeLight': string;
|
'settings.themeLight': string;
|
||||||
'settings.tray': boolean;
|
'settings.tray': boolean;
|
||||||
'settings.useThemeAccentColor': boolean;
|
'settings.useThemeAccentColor': boolean;
|
||||||
|
'settings.useThemePrimaryShade': boolean;
|
||||||
'settings.windowBarStyle': Platform;
|
'settings.windowBarStyle': Platform;
|
||||||
'settings.zoomFactor': number;
|
'settings.zoomFactor': number;
|
||||||
};
|
};
|
||||||
@@ -192,6 +193,7 @@ const getSettingsProperties = (): SettingsProperties => {
|
|||||||
'settings.themeLight': settings.general.themeLight,
|
'settings.themeLight': settings.general.themeLight,
|
||||||
'settings.tray': ignoreWeb(settings.window.tray),
|
'settings.tray': ignoreWeb(settings.window.tray),
|
||||||
'settings.useThemeAccentColor': settings.general.useThemeAccentColor,
|
'settings.useThemeAccentColor': settings.general.useThemeAccentColor,
|
||||||
|
'settings.useThemePrimaryShade': settings.general.useThemePrimaryShade,
|
||||||
'settings.windowBarStyle': ignoreWeb(settings.window.windowBarStyle),
|
'settings.windowBarStyle': ignoreWeb(settings.window.windowBarStyle),
|
||||||
'settings.zoomFactor': ignoreWeb(settings.general.zoomFactor),
|
'settings.zoomFactor': ignoreWeb(settings.general.zoomFactor),
|
||||||
} as any;
|
} as any;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { THEME_DATA, useSetColorScheme } from '/@/renderer/themes/use-app-theme'
|
|||||||
import { ColorInput } from '/@/shared/components/color-input/color-input';
|
import { ColorInput } from '/@/shared/components/color-input/color-input';
|
||||||
import { Group } from '/@/shared/components/group/group';
|
import { Group } from '/@/shared/components/group/group';
|
||||||
import { Select } from '/@/shared/components/select/select';
|
import { Select } from '/@/shared/components/select/select';
|
||||||
|
import { Slider } from '/@/shared/components/slider/slider';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { Switch } from '/@/shared/components/switch/switch';
|
import { Switch } from '/@/shared/components/switch/switch';
|
||||||
import { getAppTheme } from '/@/shared/themes/app-theme';
|
import { getAppTheme } from '/@/shared/themes/app-theme';
|
||||||
@@ -253,6 +254,51 @@ export const ThemeSettings = memo(() => {
|
|||||||
}),
|
}),
|
||||||
title: t('setting.accentColor', { postProcess: 'sentenceCase' }),
|
title: t('setting.accentColor', { postProcess: 'sentenceCase' }),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
control: (
|
||||||
|
<Switch
|
||||||
|
checked={settings.useThemePrimaryShade}
|
||||||
|
onChange={(e) => {
|
||||||
|
setSettings({
|
||||||
|
general: {
|
||||||
|
useThemePrimaryShade: e.currentTarget.checked,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
description: t('setting.useThemePrimaryShade', {
|
||||||
|
context: 'description',
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
}),
|
||||||
|
isHidden: false,
|
||||||
|
title: t('setting.useThemePrimaryShade', { postProcess: 'sentenceCase' }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
control: (
|
||||||
|
<Slider
|
||||||
|
defaultValue={settings.primaryShade}
|
||||||
|
label={(value) => value}
|
||||||
|
max={9}
|
||||||
|
min={0}
|
||||||
|
onChangeEnd={(value) => {
|
||||||
|
setSettings({
|
||||||
|
general: {
|
||||||
|
primaryShade: value,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
step={1}
|
||||||
|
w={120}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
description: t('setting.primaryShade', {
|
||||||
|
context: 'description',
|
||||||
|
postProcess: 'sentenceCase',
|
||||||
|
}),
|
||||||
|
isHidden: settings.useThemePrimaryShade,
|
||||||
|
title: t('setting.primaryShade', { postProcess: 'sentenceCase' }),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -462,6 +462,7 @@ export const GeneralSettingsSchema = z.object({
|
|||||||
playerbarOpenDrawer: z.boolean(),
|
playerbarOpenDrawer: z.boolean(),
|
||||||
playerbarSlider: PlayerbarSliderSchema,
|
playerbarSlider: PlayerbarSliderSchema,
|
||||||
playlistTarget: PlaylistTargetSchema,
|
playlistTarget: PlaylistTargetSchema,
|
||||||
|
primaryShade: z.number().min(0).max(9),
|
||||||
resume: z.boolean(),
|
resume: z.boolean(),
|
||||||
showLyricsInSidebar: z.boolean(),
|
showLyricsInSidebar: z.boolean(),
|
||||||
showRatings: z.boolean(),
|
showRatings: z.boolean(),
|
||||||
@@ -479,6 +480,7 @@ export const GeneralSettingsSchema = z.object({
|
|||||||
themeDark: z.nativeEnum(AppTheme),
|
themeDark: z.nativeEnum(AppTheme),
|
||||||
themeLight: z.nativeEnum(AppTheme),
|
themeLight: z.nativeEnum(AppTheme),
|
||||||
useThemeAccentColor: z.boolean(),
|
useThemeAccentColor: z.boolean(),
|
||||||
|
useThemePrimaryShade: z.boolean(),
|
||||||
volumeWheelStep: z.number(),
|
volumeWheelStep: z.number(),
|
||||||
volumeWidth: z.number(),
|
volumeWidth: z.number(),
|
||||||
zoomFactor: z.number(),
|
zoomFactor: z.number(),
|
||||||
@@ -1051,6 +1053,7 @@ const initialState: SettingsState = {
|
|||||||
type: PlayerbarSliderType.SLIDER,
|
type: PlayerbarSliderType.SLIDER,
|
||||||
},
|
},
|
||||||
playlistTarget: PlaylistTarget.TRACK,
|
playlistTarget: PlaylistTarget.TRACK,
|
||||||
|
primaryShade: 6,
|
||||||
resume: true,
|
resume: true,
|
||||||
showLyricsInSidebar: true,
|
showLyricsInSidebar: true,
|
||||||
showRatings: true,
|
showRatings: true,
|
||||||
@@ -1072,6 +1075,7 @@ const initialState: SettingsState = {
|
|||||||
themeDark: AppTheme.DEFAULT_DARK,
|
themeDark: AppTheme.DEFAULT_DARK,
|
||||||
themeLight: AppTheme.DEFAULT_LIGHT,
|
themeLight: AppTheme.DEFAULT_LIGHT,
|
||||||
useThemeAccentColor: false,
|
useThemeAccentColor: false,
|
||||||
|
useThemePrimaryShade: true,
|
||||||
volumeWheelStep: 5,
|
volumeWheelStep: 5,
|
||||||
volumeWidth: 70,
|
volumeWidth: 70,
|
||||||
zoomFactor: 100,
|
zoomFactor: 100,
|
||||||
@@ -2371,10 +2375,12 @@ export const useThemeSettings = () =>
|
|||||||
useSettingsStore(
|
useSettingsStore(
|
||||||
(state) => ({
|
(state) => ({
|
||||||
followSystemTheme: state.general.followSystemTheme,
|
followSystemTheme: state.general.followSystemTheme,
|
||||||
|
primaryShade: state.general.primaryShade,
|
||||||
theme: state.general.theme,
|
theme: state.general.theme,
|
||||||
themeDark: state.general.themeDark,
|
themeDark: state.general.themeDark,
|
||||||
themeLight: state.general.themeLight,
|
themeLight: state.general.themeLight,
|
||||||
useThemeAccentColor: state.general.useThemeAccentColor,
|
useThemeAccentColor: state.general.useThemeAccentColor,
|
||||||
|
useThemePrimaryShade: state.general.useThemePrimaryShade,
|
||||||
}),
|
}),
|
||||||
shallow,
|
shallow,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export const useAppTheme = (overrideTheme?: AppTheme) => {
|
|||||||
const themeInlineStylesRef = useRef<HTMLStyleElement | null>(null);
|
const themeInlineStylesRef = useRef<HTMLStyleElement | null>(null);
|
||||||
const getCurrentTheme = () => window.matchMedia('(prefers-color-scheme: dark)').matches;
|
const getCurrentTheme = () => window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
const [isDarkTheme, setIsDarkTheme] = useState(getCurrentTheme());
|
const [isDarkTheme, setIsDarkTheme] = useState(getCurrentTheme());
|
||||||
const { followSystemTheme, theme, themeDark, themeLight, useThemeAccentColor } =
|
const { followSystemTheme, primaryShade, theme, themeDark, themeLight, useThemeAccentColor, useThemePrimaryShade } =
|
||||||
useThemeSettings();
|
useThemeSettings();
|
||||||
|
|
||||||
const mqListener = (e: any) => {
|
const mqListener = (e: any) => {
|
||||||
@@ -144,14 +144,23 @@ export const useAppTheme = (overrideTheme?: AppTheme) => {
|
|||||||
? themeProperties.colors?.primary || themeProperties.colors?.['state-info'] || accent
|
? themeProperties.colors?.primary || themeProperties.colors?.['state-info'] || accent
|
||||||
: accent;
|
: accent;
|
||||||
|
|
||||||
|
// Use theme's primary shade if useThemePrimaryShade is enabled, otherwise use slider value
|
||||||
|
const effectivePrimaryShade = useThemePrimaryShade
|
||||||
|
? themeProperties.mantineOverride?.primaryShade
|
||||||
|
: { dark: primaryShade, light: primaryShade };
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...themeProperties,
|
...themeProperties,
|
||||||
colors: {
|
colors: {
|
||||||
...themeProperties.colors,
|
...themeProperties.colors,
|
||||||
primary: primaryColor,
|
primary: primaryColor,
|
||||||
},
|
},
|
||||||
|
mantineOverride: {
|
||||||
|
...themeProperties.mantineOverride,
|
||||||
|
...(effectivePrimaryShade != null && { primaryShade: effectivePrimaryShade }),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}, [accent, selectedTheme, useThemeAccentColor]);
|
}, [accent, primaryShade, selectedTheme, useThemeAccentColor, useThemePrimaryShade]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const root = document.documentElement;
|
const root = document.documentElement;
|
||||||
@@ -241,7 +250,7 @@ export const useAppThemeColors = () => {
|
|||||||
const accent = useAccent();
|
const accent = useAccent();
|
||||||
const getCurrentTheme = () => window.matchMedia('(prefers-color-scheme: dark)').matches;
|
const getCurrentTheme = () => window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
const [isDarkTheme] = useState(getCurrentTheme());
|
const [isDarkTheme] = useState(getCurrentTheme());
|
||||||
const { followSystemTheme, theme, themeDark, themeLight, useThemeAccentColor } =
|
const { followSystemTheme, primaryShade, theme, themeDark, themeLight, useThemeAccentColor, useThemePrimaryShade } =
|
||||||
useThemeSettings();
|
useThemeSettings();
|
||||||
|
|
||||||
const getSelectedTheme = () => {
|
const getSelectedTheme = () => {
|
||||||
@@ -262,14 +271,23 @@ export const useAppThemeColors = () => {
|
|||||||
? themeProperties.colors?.primary || themeProperties.colors?.['state-info'] || accent
|
? themeProperties.colors?.primary || themeProperties.colors?.['state-info'] || accent
|
||||||
: accent;
|
: accent;
|
||||||
|
|
||||||
|
// Use theme's primary shade if useThemePrimaryShade is enabled, otherwise use slider value
|
||||||
|
const effectivePrimaryShade = useThemePrimaryShade
|
||||||
|
? themeProperties.mantineOverride?.primaryShade
|
||||||
|
: { dark: primaryShade, light: primaryShade };
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...themeProperties,
|
...themeProperties,
|
||||||
colors: {
|
colors: {
|
||||||
...themeProperties.colors,
|
...themeProperties.colors,
|
||||||
primary: primaryColor,
|
primary: primaryColor,
|
||||||
},
|
},
|
||||||
|
mantineOverride: {
|
||||||
|
...themeProperties.mantineOverride,
|
||||||
|
...(effectivePrimaryShade != null && { primaryShade: effectivePrimaryShade }),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}, [accent, selectedTheme, useThemeAccentColor]);
|
}, [accent, primaryShade, selectedTheme, useThemeAccentColor, useThemePrimaryShade]);
|
||||||
|
|
||||||
const themeVars = useMemo(() => {
|
const themeVars = useMemo(() => {
|
||||||
return Object.entries(appTheme?.app ?? {})
|
return Object.entries(appTheme?.app ?? {})
|
||||||
|
|||||||
Reference in New Issue
Block a user