diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json
index 318d17925..b18cf90d4 100644
--- a/src/i18n/locales/en.json
+++ b/src/i18n/locales/en.json
@@ -657,6 +657,8 @@
"autoDJ_timing_description": "the number of songs remaining in the queue before auto DJ is triggered",
"accentColor_description": "sets the accent color for the application",
"accentColor": "accent color",
+ "useThemeAccentColor": "use theme accent color",
+ "useThemeAccentColor_description": "use the primary color defined in the selected theme instead of the custom accent color",
"albumBackground_description": "adds a background image for album pages containing the album art",
"albumBackground": "album background image",
"albumBackgroundBlur_description": "adjusts the amount of blur applied to the album background image",
diff --git a/src/renderer/components/item-list/item-table-list/item-table-list.module.css b/src/renderer/components/item-list/item-table-list/item-table-list.module.css
index d530baa69..5e323aa33 100644
--- a/src/renderer/components/item-list/item-table-list/item-table-list.module.css
+++ b/src/renderer/components/item-list/item-table-list/item-table-list.module.css
@@ -187,19 +187,10 @@
pointer-events: none;
background: linear-gradient(
to bottom,
- rgb(0 0 0 / 50%) 0%,
- rgb(0 0 0 / 5%) 50%,
+ darken(var(--theme-colors-background), 10%) 0%,
+ darken(var(--theme-colors-background), 5%) 50%,
transparent 100%
);
-
- @mixin light {
- background: linear-gradient(
- to bottom,
- var(--theme-colors-background) 0%,
- alpha(var(--theme-colors-background), 0.05) 50%,
- transparent 100%
- );
- }
}
.item-table-left-scroll-shadow {
@@ -210,18 +201,21 @@
z-index: 1;
width: 8px;
pointer-events: none;
- background: linear-gradient(
- to right,
- rgb(0 0 0 / 50%) 0%,
- rgb(0 0 0 / 5%) 50%,
- transparent 100%
- );
+
+ @mixin dark {
+ background: linear-gradient(
+ to right,
+ darken(var(--theme-colors-background), 10%) 0%,
+ darken(var(--theme-colors-background), 5%) 50%,
+ transparent 100%
+ );
+ }
@mixin light {
background: linear-gradient(
to right,
- var(--theme-colors-background) 0%,
- alpha(var(--theme-colors-background), 0.05) 50%,
+ darken(var(--theme-colors-background), 5%) 0%,
+ darken(var(--theme-colors-background), 3%) 50%,
transparent 100%
);
}
@@ -235,18 +229,21 @@
z-index: 1;
width: 8px;
pointer-events: none;
- background: linear-gradient(
- to left,
- rgb(0 0 0 / 50%) 0%,
- rgb(0 0 0 / 5%) 50%,
- transparent 100%
- );
+
+ @mixin dark {
+ background: linear-gradient(
+ to left,
+ darken(var(--theme-colors-background), 10%) 0%,
+ darken(var(--theme-colors-background), 5%) 50%,
+ transparent 100%
+ );
+ }
@mixin light {
background: linear-gradient(
to left,
- var(--theme-colors-background) 0%,
- alpha(var(--theme-colors-background), 0.05) 50%,
+ darken(var(--theme-colors-background), 5%) 0%,
+ darken(var(--theme-colors-background), 3%) 50%,
transparent 100%
);
}
@@ -260,18 +257,21 @@
z-index: 1;
height: 8px;
pointer-events: none;
- background: linear-gradient(
- to bottom,
- rgb(0 0 0 / 50%) 0%,
- rgb(0 0 0 / 5%) 50%,
- transparent 100%
- );
+
+ @mixin dark {
+ background: linear-gradient(
+ to bottom,
+ darken(var(--theme-colors-background), 10%) 0%,
+ darken(var(--theme-colors-background), 5%) 50%,
+ transparent 100%
+ );
+ }
@mixin light {
background: linear-gradient(
to bottom,
- var(--theme-colors-background) 0%,
- alpha(var(--theme-colors-background), 0.05) 50%,
+ darken(var(--theme-colors-background), 5%) 0%,
+ darken(var(--theme-colors-background), 3%) 50%,
transparent 100%
);
}
diff --git a/src/renderer/features/player/components/playerbar-waveform.tsx b/src/renderer/features/player/components/playerbar-waveform.tsx
index 56eb4d507..572cd0932 100644
--- a/src/renderer/features/player/components/playerbar-waveform.tsx
+++ b/src/renderer/features/player/components/playerbar-waveform.tsx
@@ -14,9 +14,8 @@ import {
usePlaybackSettings,
usePlayerSong,
usePlayerTimestamp,
- usePrimaryColor,
} from '/@/renderer/store';
-import { useColorScheme } from '/@/renderer/themes/use-app-theme';
+import { useAppThemeColors, useColorScheme } from '/@/renderer/themes/use-app-theme';
import { Spinner } from '/@/shared/components/spinner/spinner';
import { Text } from '/@/shared/components/text/text';
@@ -39,7 +38,8 @@ export const PlayerbarWaveform = () => {
const streamUrl = useSongUrl(currentSong, true, transcode);
- const primaryColor = usePrimaryColor();
+ const { color } = useAppThemeColors();
+ const primaryColor = (color['--theme-colors-primary'] as string) || 'rgb(53, 116, 252)';
const colorScheme = useColorScheme();
diff --git a/src/renderer/features/settings/components/advanced/styles-settings.tsx b/src/renderer/features/settings/components/advanced/styles-settings.tsx
index 2ab627167..b4b543a8e 100644
--- a/src/renderer/features/settings/components/advanced/styles-settings.tsx
+++ b/src/renderer/features/settings/components/advanced/styles-settings.tsx
@@ -1,4 +1,3 @@
-import { closeAllModals, openModal } from '@mantine/modals';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
@@ -7,7 +6,6 @@ import { useCssSettings, useSettingsStoreActions } from '/@/renderer/store';
import { sanitizeCss } from '/@/renderer/utils/sanitize';
import { Button } from '/@/shared/components/button/button';
import { Code } from '/@/shared/components/code/code';
-import { ConfirmModal } from '/@/shared/components/modal/modal';
import { Switch } from '/@/shared/components/switch/switch';
import { Text } from '/@/shared/components/text/text';
import { Textarea } from '/@/shared/components/textarea/textarea';
@@ -30,16 +28,6 @@ export const StylesSettings = () => {
});
};
- const handleResetToDefault = () => {
- setSettings({
- css: {
- content,
- enabled: true,
- },
- });
- closeAllModals();
- };
-
useEffect(() => {
if (content !== css) {
setCss(content);
@@ -47,19 +35,6 @@ export const StylesSettings = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps -- Reason: This is to only fire if an external source updates the stores css.content
}, [content]);
- const openConfirmModal = () => {
- openModal({
- children: (
-
-
- {t('setting.customCssNotice', { postProcess: 'sentenceCase' })}
-
-
- ),
- title: t('setting.customCssEnable', { postProcess: 'sentenceCase' }),
- });
- };
-
return (
<>
{
{
- if (!e.currentTarget.checked) {
- setSettings({
- css: {
- content,
- enabled: false,
- },
- });
- } else {
- openConfirmModal();
- }
+ setSettings({
+ css: {
+ content,
+ enabled: e.currentTarget.checked,
+ },
+ });
}}
/>
}
@@ -84,6 +55,7 @@ export const StylesSettings = () => {
context: 'description',
postProcess: 'sentenceCase',
})}
+ note={t('setting.customCssNotice', { postProcess: 'sentenceCase' })}
title={t('setting.customCssEnable', { postProcess: 'sentenceCase' })}
/>
{enabled && (
diff --git a/src/renderer/features/settings/components/general/theme-settings.tsx b/src/renderer/features/settings/components/general/theme-settings.tsx
index 4df0978c2..c71ad467e 100644
--- a/src/renderer/features/settings/components/general/theme-settings.tsx
+++ b/src/renderer/features/settings/components/general/theme-settings.tsx
@@ -1,6 +1,8 @@
import isElectron from 'is-electron';
+import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
+import i18n from '/@/i18n/i18n';
import { StylesSettings } from '/@/renderer/features/settings/components/advanced/styles-settings';
import {
SettingOption,
@@ -9,19 +11,83 @@ import {
import { useGeneralSettings, useSettingsStoreActions } from '/@/renderer/store/settings.store';
import { THEME_DATA, useSetColorScheme } from '/@/renderer/themes/use-app-theme';
import { ColorInput } from '/@/shared/components/color-input/color-input';
+import { Group } from '/@/shared/components/group/group';
import { Select } from '/@/shared/components/select/select';
import { Stack } from '/@/shared/components/stack/stack';
import { Switch } from '/@/shared/components/switch/switch';
+import { getAppTheme } from '/@/shared/themes/app-theme';
import { AppTheme } from '/@/shared/themes/app-theme-types';
const localSettings = isElectron() ? window.api.localSettings : null;
+const getThemeSwatchColors = (theme: AppTheme) => {
+ const themeConfig = getAppTheme(theme);
+ return {
+ background: themeConfig.colors?.background || 'rgb(0, 0, 0)',
+ foreground: themeConfig.colors?.foreground || 'rgb(255, 255, 255)',
+ surface: themeConfig.colors?.surface || themeConfig.colors?.background || 'rgb(0, 0, 0)',
+ };
+};
+
+const getGroupedThemeData = () => {
+ const darkThemes = THEME_DATA.filter((theme) => theme.type === 'dark').sort((a, b) =>
+ a.label.localeCompare(b.label),
+ );
+ const lightThemes = THEME_DATA.filter((theme) => theme.type === 'light').sort((a, b) =>
+ a.label.localeCompare(b.label),
+ );
+
+ return [
+ {
+ group: i18n.t('setting.themeDark', { postProcess: 'sentenceCase' }),
+ items: darkThemes,
+ },
+ {
+ group: i18n.t('setting.themeLight', { postProcess: 'sentenceCase' }),
+ items: lightThemes,
+ },
+ ];
+};
+
+const ColorSwatch = ({ color }: { color: string }) => {
+ return (
+
+ );
+};
+
+const renderThemeOption = ({ option }: { option: { label: string; value: string } }) => {
+ const themeValue = option.value as AppTheme;
+ const colors = getThemeSwatchColors(themeValue);
+
+ return (
+
+
+
+
+
+
+ {option.label}
+
+ );
+};
+
export const ThemeSettings = () => {
const { t } = useTranslation();
const settings = useGeneralSettings();
const { setSettings } = useSettingsStoreActions();
const { setColorScheme } = useSetColorScheme();
+ const groupedThemeData = useMemo(() => getGroupedThemeData(), []);
+
const themeOptions: SettingOption[] = [
{
control: (
@@ -57,7 +123,7 @@ export const ThemeSettings = () => {
{
control: (