From 1938cd790db74ba0d6a341f0f394f2b7f564e5b2 Mon Sep 17 00:00:00 2001 From: David Enete Date: Tue, 10 Mar 2026 10:28:55 -0400 Subject: [PATCH 1/3] [feature-693] updated theme buttons to use a select element, added a preview panel to let users see theme as selected, changed to hex only to avoid bug with rgba selector and custom theme storage, included theme attribute removal in application of custom theme --- src/components/SettingsPanel.jsx | 6 +- src/components/ThemeSelector.jsx | 199 +++++++++++++++++++++++++++++-- src/styles/themes.css | 4 - src/theme/themeConfig.js | 2 +- src/theme/themeUtils.js | 1 + 5 files changed, 195 insertions(+), 17 deletions(-) diff --git a/src/components/SettingsPanel.jsx b/src/components/SettingsPanel.jsx index c2c15725..b1ee3873 100644 --- a/src/components/SettingsPanel.jsx +++ b/src/components/SettingsPanel.jsx @@ -2290,10 +2290,10 @@ export const SettingsPanel = ({ > {t('station.settings.theme')} - -
+ + {/*
{t('station.settings.theme.' + theme + '.describe')} -
+
*/} {theme === 'custom' && customTheme && ( { setActiveThemeButton(theme); }, []); return ( - <> -
- {Object.entries(AVAILABLE_THEMES).map(([key, t]) => ( - - ))} +
+
+ +
+ {t('station.settings.theme.' + theme + '.describe')} +
- +
+

+ Theme: {AVAILABLE_THEMES[theme].label} +

+
+

Secondary Text Over Secondary Background

+
+

Primary Text Over Panel Background

+

+ Muted Text Sample. +

+ + +
+

Muted text over secondary background.

+
+
    +
  • + Amber Accent +
  • +
  • + Amber Accent (dim) +
  • +
  • + Green Accent +
  • +
  • + Green Accent (dim) +
  • +
  • + Red Accent +
  • +
  • + Blue Accent +
  • +
  • + Cyan Accent +
  • +
  • + Purple Accent +
  • +
+
+
+
+
); } diff --git a/src/styles/themes.css b/src/styles/themes.css index 9b7d3c59..4fb67412 100644 --- a/src/styles/themes.css +++ b/src/styles/themes.css @@ -20,7 +20,6 @@ --accent-cyan: #00ddff; --accent-purple: #aa66ff; --map-ocean: #0a0e14; - /* --scanline-opacity: 0.02; */ } /* ============================================ @@ -44,7 +43,6 @@ --accent-cyan: #0099bb; --accent-purple: #7744cc; --map-ocean: #f0f4f8; - /* --scanline-opacity: 0; */ } /* ============================================ @@ -68,7 +66,6 @@ --accent-cyan: #00ffff; --accent-purple: #ff00ff; --map-ocean: #000008; - /* --scanline-opacity: 0.05; */ } /* ============================================ @@ -96,5 +93,4 @@ --title-bar: linear-gradient(90deg, #000080, #1084d0); --title-bar-text: #ffffff; --map-ocean: #000080; - /* --scanline-opacity: 0; */ } diff --git a/src/theme/themeConfig.js b/src/theme/themeConfig.js index aed2b508..5a909100 100644 --- a/src/theme/themeConfig.js +++ b/src/theme/themeConfig.js @@ -3,7 +3,7 @@ export const THEME_COLOR_CONFIG = { '--bg-secondary': { alpha: false, hueRestrict: null }, '--bg-tertiary': { alpha: false, hueRestrict: null }, '--bg-panel': { alpha: false, hueRestrict: null }, - '--border-color': { alpha: true, hueRestrict: null }, + '--border-color': { alpha: false, hueRestrict: null }, '--text-primary': { alpha: false, hueRestrict: null }, '--text-secondary': { alpha: false, hueRestrict: null }, '--text-muted': { alpha: false, hueRestrict: null }, diff --git a/src/theme/themeUtils.js b/src/theme/themeUtils.js index 21dd7eff..d321bd3e 100644 --- a/src/theme/themeUtils.js +++ b/src/theme/themeUtils.js @@ -21,6 +21,7 @@ export function readCssVariables() { /* Apply a theme object to :root */ export function applyCustomTheme(themeVars) { + document.documentElement.removeAttribute('data-theme'); Object.entries(themeVars).forEach(([key, value]) => { document.documentElement.style.setProperty(key, value); }); From 2dae44f257b09485ca08efe758465f293033e60c Mon Sep 17 00:00:00 2001 From: David Enete Date: Tue, 10 Mar 2026 17:18:45 -0400 Subject: [PATCH 2/3] [feature-693] addressed issue with rgba color picker being set incorrectly with a string instead of an object, moved excessive styles from style preview to main.css, added reset for custom theme, added translations for theme reset, removed unused functions from the button theme selectors --- src/components/CustomThemeEditor.jsx | 59 +++++++---- src/components/SettingsPanel.jsx | 6 +- src/components/ThemeSelector.jsx | 135 +++---------------------- src/lang/ca.json | 56 ++++------- src/lang/de.json | 2 + src/lang/en.json | 2 + src/lang/es.json | 2 + src/lang/fr.json | 2 + src/lang/it.json | 2 + src/lang/ja.json | 2 + src/lang/ka.json | 2 + src/lang/ko.json | 2 + src/lang/ms.json | 2 + src/lang/nl.json | 2 + src/lang/pt.json | 2 + src/lang/ru.json | 2 + src/lang/sl.json | 2 + src/lang/zh.json | 21 ++++ src/styles/main.css | 142 +++++++++++++++++++++++---- src/theme/colorUtils.js | 25 +++++ src/theme/themeConfig.js | 46 ++++----- src/theme/themeUtils.js | 28 +++--- src/theme/useTheme.js | 27 +++-- 23 files changed, 335 insertions(+), 236 deletions(-) create mode 100644 src/theme/colorUtils.js diff --git a/src/components/CustomThemeEditor.jsx b/src/components/CustomThemeEditor.jsx index 07805be9..e58b4d0b 100644 --- a/src/components/CustomThemeEditor.jsx +++ b/src/components/CustomThemeEditor.jsx @@ -1,27 +1,52 @@ import { HexColorPicker, RgbaColorPicker } from 'react-colorful'; import { THEME_COLOR_CONFIG } from '../theme/themeConfig'; import { useTranslation } from 'react-i18next'; +import { rgbaStringToObject, rgbaObjectToString } from '../theme/colorUtils'; -export default function CustomThemeEditor({ id, customTheme, updateCustomVar }) { +export default function CustomThemeEditor({ id, customTheme, updateCustomVar, resetCustomToDefault }) { const { t } = useTranslation(); return ( -
- {Object.entries(THEME_COLOR_CONFIG).map(([key, cfg]) => { - const Picker = cfg.alpha ? RgbaColorPicker : HexColorPicker; + <> + - return ( -
- - { - updateCustomVar(key, color); - }} - /> -
- ); - })} -
+
+ {Object.entries(THEME_COLOR_CONFIG).map(([key, cfg]) => { + const value = customTheme[key]; + + return ( +
+ + + {cfg.alpha ? ( + { + const rgbaString = rgbaObjectToString(colorObj); + updateCustomVar(key, rgbaString); + }} + /> + ) : ( + { + updateCustomVar(key, hex); + }} + /> + )} +
+ ); + })} +
+ ); } diff --git a/src/components/SettingsPanel.jsx b/src/components/SettingsPanel.jsx index b1ee3873..0190d5f0 100644 --- a/src/components/SettingsPanel.jsx +++ b/src/components/SettingsPanel.jsx @@ -37,7 +37,7 @@ export const SettingsPanel = ({ onToggleDXNews, wakeLockStatus, }) => { - const { theme, setTheme, customTheme, updateCustomVar } = useTheme(); + const { theme, setTheme, customTheme, updateCustomVar, resetCustomToDefault } = useTheme(); const [callsign, setCallsign] = useState(config?.callsign || ''); const [headerSize, setheaderSize] = useState(config?.headerSize || 1.0); @@ -2291,13 +2291,11 @@ export const SettingsPanel = ({ {t('station.settings.theme')} - {/*
- {t('station.settings.theme.' + theme + '.describe')} -
*/} {theme === 'custom' && customTheme && ( )} diff --git a/src/components/ThemeSelector.jsx b/src/components/ThemeSelector.jsx index 2d768ae2..c6199fd0 100644 --- a/src/components/ThemeSelector.jsx +++ b/src/components/ThemeSelector.jsx @@ -1,5 +1,4 @@ import { useEffect } from 'react'; -import { setActiveThemeButton } from '../theme/themeUtils'; import { AVAILABLE_THEMES } from '../theme/themeConfig'; export default function ThemeSelector({ @@ -10,129 +9,34 @@ export default function ThemeSelector({ selectedTheme, t, }) { - useEffect(() => { - setActiveThemeButton(theme); - }, []); - return ( -
-
- setTheme(e.target.value)}> {Object.entries(AVAILABLE_THEMES).map(([key, t]) => ( ))} -
- {t('station.settings.theme.' + theme + '.describe')} -
+
{t('station.settings.theme.' + theme + '.describe')}
-
-

- Theme: {AVAILABLE_THEMES[theme].label} -

-
-

Secondary Text Over Secondary Background

-
-

Primary Text Over Panel Background

-

- Muted Text Sample. -

- - +
+

Theme: {AVAILABLE_THEMES[theme].label}

+
+

Secondary Text Over Secondary Background

+
+

Primary Text Over Panel Background

+

Muted Text over panel background.

+ +
-

Muted text over secondary background.

-
-
    +

    Muted text over secondary background.

    +
    +
    • Amber Accent @@ -140,7 +44,6 @@ export default function ThemeSelector({
    • Amber Accent (dim) @@ -148,7 +51,6 @@ export default function ThemeSelector({
    • Green Accent @@ -156,7 +58,6 @@ export default function ThemeSelector({
    • Green Accent (dim) @@ -164,7 +65,6 @@ export default function ThemeSelector({
    • Red Accent @@ -172,7 +72,6 @@ export default function ThemeSelector({
    • Blue Accent @@ -180,7 +79,6 @@ export default function ThemeSelector({
    • Cyan Accent @@ -188,7 +86,6 @@ export default function ThemeSelector({
    • Purple Accent diff --git a/src/lang/ca.json b/src/lang/ca.json index 5a1d95cb..76e80170 100644 --- a/src/lang/ca.json +++ b/src/lang/ca.json @@ -77,7 +77,6 @@ "contest.panel.time.live.minutes": "{{minutes}}m restants", "contest.panel.time.startsIn": "Comença en {{hours}}h", "contest.panel.title": "⊛ CONCURSOS", - "dxClusterPanel.filterTooltip": "Filtrar spots DX per banda, mode o continent", "dxClusterPanel.filtersButton": "Filtres", "dxClusterPanel.live": "EN VIU", @@ -91,24 +90,19 @@ "dxClusterPanel.relativeTime": "fa {{minutes}}m ({{time}})", "dxClusterPanel.spotter": "de {{spotter}}", "dxClusterPanel.title": "CLÚSTER DX", - "plugins.layers.aurora.description": "Predicció de probabilitat d’aurores NOAA OVATION (30 min)", "plugins.layers.aurora.name": "Predicció d’aurores", - "plugins.layers.earthquakes.description": "Dades sísmiques en viu de l’USGS (M2.5+ de les últimes 24 hores)", "plugins.layers.earthquakes.name": "Terratrèmols", "plugins.layers.earthquakes.viewDetails": "Veure detalls →", - "plugins.layers.floods.description": "Inundacions i tempestes severes actives arreu del món via NASA EONET", "plugins.layers.floods.name": "Inundacions i Tempestes", - "plugins.layers.grayline.description": "Terminador dia/nit amb zones de crepuscle", "plugins.layers.grayline.enhancedDx": "Zona DX millorada", "plugins.layers.grayline.name": "Línia Grisa", "plugins.layers.grayline.showTwilight": "Mostrar zones de crepuscle", "plugins.layers.grayline.title": "Línia Grisa", "plugins.layers.grayline.utcTime": "HORA UTC", - "plugins.layers.lightning.avgIntensity": "Intensitat mitjana:", "plugins.layers.lightning.description": "Llamps en temps real arreu del món (30 min)", "plugins.layers.lightning.fresh": "Recent (<1 min):", @@ -119,7 +113,6 @@ "plugins.layers.lightning.title": "Activitat elèctrica", "plugins.layers.lightning.total": "Total (30 min):", "plugins.layers.lightning.updates": "Actualitzat cada 30s", - "plugins.layers.rbn.allBands": "Totes les bandes", "plugins.layers.rbn.avgSnr": "SNR mitjà", "plugins.layers.rbn.band": "Banda:", @@ -134,7 +127,6 @@ "plugins.layers.rbn.title": "RBN", "plugins.layers.wildfires.description": "Incendis forestals actius arreu del món via detecció satel·lital NASA EONET", "plugins.layers.wildfires.name": "Incendis forestals", - "plugins.layers.wspr.allBands": "Totes les bandes", "plugins.layers.wspr.animation": "Animació", "plugins.layers.wspr.band": "Banda:", @@ -166,11 +158,9 @@ "plugins.layers.wspr.txStations": "Estacions TX:", "plugins.layers.wspr.veryWeak": "Molt dèbil (< -20 dB)", "plugins.layers.wspr.weak": "Dèbil (-20 a -10 dB)", - "plugins.layers.wxradar.attribution": "Dades meteorològiques © Iowa State University Mesonet", "plugins.layers.wxradar.description": "Superposició del radar meteorològic NEXRAD per a Amèrica del Nord", "plugins.layers.wxradar.name": "Radar meteorològic", - "propagation.day": "Dia", "propagation.estimated": "estimat", "propagation.geomag": "Geomag", @@ -189,10 +179,8 @@ "propagation.view.toggle": "clica per canviar", "pskReporterPanel.map.hide": "Amagar spots al mapa", "pskReporterPanel.map.show": "Mostrar spots al mapa", - "pskReporterPanel.mode.pskTooltip": "Informes de recepció per Internet via PSKReporter.info", "pskReporterPanel.mode.wsjtxTooltip": "Decodificacions WSJT-X locals via relé UDP", - "pskReporterPanel.psk.connecting": "Connectant...", "pskReporterPanel.psk.connectionFailed": "Connexió fallida, cal refrescar?", "pskReporterPanel.psk.filterTooltip": "Filtrar spots per banda, mode o quadrícula", @@ -201,16 +189,13 @@ "pskReporterPanel.psk.refreshTooltip": "Reconnectar a PSKReporter", "pskReporterPanel.psk.setCallsign": "Configura el teu indicatiu a Configuració per veure informes", "pskReporterPanel.psk.waitingForSpots": "Esperant spots... (TX per veure informes)", - "pskReporterPanel.tabs.heard": "Escoltat ({{count}})", "pskReporterPanel.tabs.heardTooltip": "▲ Estacions que escolten el teu senyal", "pskReporterPanel.tabs.hearing": "Escoltant ({{count}})", "pskReporterPanel.tabs.hearingTooltip": "▼ Estacions que escoltes", - "pskReporterPanel.time.hours": "{{hours}}h", "pskReporterPanel.time.minutes": "{{minutes}}m", "pskReporterPanel.time.now": "ara", - "pskReporterPanel.wsjtx.decodes": "Decodificacions ({{count}})", "pskReporterPanel.wsjtx.decodingTooltip": "Decodificacions WSJT-X en viu", "pskReporterPanel.wsjtx.downloadRelay": "Descarrega l’agent relé per al teu PC:", @@ -219,18 +204,14 @@ "pskReporterPanel.wsjtx.listening": "Escoltant...", "pskReporterPanel.wsjtx.noDecodesFiltered": "Cap decodificació coincideix amb el filtre", "pskReporterPanel.wsjtx.noQsos": "Encara no hi ha QSOs registrats", - "pskReporterPanel.wsjtx.platformLinux": "🐧 Linux", "pskReporterPanel.wsjtx.platformMac": "🍎 Mac", "pskReporterPanel.wsjtx.platformWindows": "🪟 Windows", - "pskReporterPanel.wsjtx.qsos": "QSOs ({{count}})", "pskReporterPanel.wsjtx.qsosTooltip": "QSOs registrats des de WSJT-X", - "pskReporterPanel.wsjtx.relayConnected": "Relé connectat", "pskReporterPanel.wsjtx.relayHint": "Les decodificacions WSJT-X apareixeran aquí quan l’estació estigui activa", "pskReporterPanel.wsjtx.requiresNode": "Requereix Node.js 🟢 Executa l’script i després inicia WSJT-X", - "pskReporterPanel.wsjtx.udpAddress": "Adreça: 127.0.0.1 🟢 Port: {{port}}", "pskReporterPanel.wsjtx.udpPath": "A WSJT-X: Settings → Reporting → UDP Server", "pskReporterPanel.wsjtx.waiting": "Esperant WSJT-X...", @@ -255,9 +236,7 @@ "station.settings.dx.option3": "DXWatch", "station.settings.dx.option4": "Auto (provar totes les fonts)", "station.settings.dx.title": "Font del Clúster DX", - "station.settings.headerSize": "Mida del teu indicatiu", - "station.settings.language": "Idioma", "station.settings.language.de": "Deutsch", "station.settings.language.en": "English", @@ -273,16 +252,13 @@ "station.settings.language.ru": "Русский", "station.settings.language.ka": "ქართული", "station.settings.language.ms": "Melayu", - "station.settings.latitude": "Latitud", "station.settings.longitude": "Longitud", "station.settings.locator": "Quadrícula (o introdueix Lat/Lon a sota)", "station.settings.locator.placeholder": "FN20nc", - "station.settings.layers.noLayers": "No hi ha capes de mapa disponibles", "station.settings.layers.opacity": "Opacitat", "station.settings.layers.title": "Capes del mapa", - "station.settings.layout": "Disseny", "station.settings.layout.classic": "Clàssic", "station.settings.layout.classic.describe": "→ Disseny estil HamClock original", @@ -296,13 +272,10 @@ "station.settings.layout.reset.confirm": "Restablir el disseny dels panells al predeterminat?", "station.settings.layout.tablet": "Tauleta", "station.settings.layout.tablet.describe": "→ Optimitzat per a pantalles amples de 7–10\" (16:9)", - "station.settings.mouseZoom": "Sensibilitat de la roda del ratolí", "station.settings.mouseZoom.describeMax": "Més", "station.settings.mouseZoom.describeMin": "Menys", - "station.settings.power": "Potència (W)", - "station.settings.rigControl.autoMode": "Mode automàtic", "station.settings.rigControl.autoMode.hint": "Canvia a CW/SSB/Dades segons el pla de banda en sintonitzar", "station.settings.rigControl.enabled": "Habilitar integració Hamlib", @@ -311,18 +284,15 @@ "station.settings.rigControl.title": "📻 Control de ràdio", "station.settings.rigControl.tuneEnabled": "Clica per sintonitzar", "station.settings.rigControl.tuneEnabled.hint": "Fer clic als spots sintonitza la ràdio", - "station.settings.satellites.belowHorizon": "✗ Sota l’horitzó", "station.settings.satellites.clear": "Netejar", "station.settings.satellites.selectAll": "Seleccionar-ho tot", "station.settings.satellites.selectedCount": "{{count}} satèl·lit(s) seleccionat(s)", "station.settings.satellites.showAll": "Mostrant tots els satèl·lits (sense filtre)", "station.settings.satellites.visible": "✓ Visible", - "station.settings.tab1.title": "⌇ Estació", "station.settings.tab2.title": "⊞ Capes del mapa", "station.settings.tab3.title": "⛊ Satèl·lits", - "station.settings.theme": "TEMA", "station.settings.theme.dark": "Fosc", "station.settings.theme.dark.describe": "→ Tema fosc modern (predeterminat)", @@ -332,26 +302,43 @@ "station.settings.theme.light.describe": "→ Tema clar per a ús diürn", "station.settings.theme.retro": "Retro", "station.settings.theme.retro.describe": "→ Estil retro Windows anys 90", - + "station.settings.theme.custom": "Personalitzat", + "station.settings.theme.custom.describe": "→ Un tema configurable", + "station.settings.theme.custom.--bg-primary": "Fons principal", + "station.settings.theme.custom.--bg-secondary": "Fons secundari", + "station.settings.theme.custom.--bg-tertiary": "Fons terciari", + "station.settings.theme.custom.--bg-panel": "Fons del panell", + "station.settings.theme.custom.--border-color": "Color de la vora", + "station.settings.theme.custom.--text-primary": "Text principal", + "station.settings.theme.custom.--text-secondary": "Text secundari", + "station.settings.theme.custom.--text-muted": "Text apagat", + "station.settings.theme.custom.--map-ocean": "Mapa de l'oceà", + "station.settings.theme.custom.--accent-amber": "Accent ambre", + "station.settings.theme.custom.--accent-amber-dim": "Accent ambre (atenuat)", + "station.settings.theme.custom.--accent-green": "Accent verd", + "station.settings.theme.custom.--accent-green-dim": "Accent verd (atenuat)", + "station.settings.theme.custom.--accent-red": "Accent vermell", + "station.settings.theme.custom.--accent-blue": "Accent blau", + "station.settings.theme.custom.--accent-cyan": "Accent cian", + "station.settings.theme.custom.--accent-purple": "Accent morat", + "station.settings.theme.reset": "Restableix el tema personalitzat als colors predeterminats", + "station.settings.theme.reset.confirm": "Vols restablir el tema personalitzat als valors predeterminats? Això substituirà els teus colors personalitzats actuals. Aquesta acció no es pot desfer.", "station.settings.timezone": "Zona horària", "station.settings.timezone.auto": "Auto (predeterminat del navegador)", "station.settings.timezone.currentDefault": " S’està usant el predeterminat del navegador.", "station.settings.timezone.describe": "Ajusta-ho si l’hora local es mostra incorrectament (p. ex. igual que UTC). Navegadors de privacitat com Librewolf poden falsejar la zona horària.", - "station.settings.timezone.group.africa": "Àfrica", "station.settings.timezone.group.asiaPacific": "Àsia i Pacífic", "station.settings.timezone.group.europe": "Europa", "station.settings.timezone.group.northAmerica": "Amèrica del Nord", "station.settings.timezone.group.other": "Altres", "station.settings.timezone.group.southAmerica": "Amèrica del Sud", - "station.settings.tip.env": "💡 Consell: Per a una configuració permanent, copia .env.example a .env i configura CALLSIGN i LOCATOR", "station.settings.title": "⚙ Configuració de l’estació", "station.settings.useLocation": "📍 Usar la meva ubicació actual", "station.settings.useLocation.error1": "No s’ha pogut obtenir la ubicació. Introdueix-la manualment.", "station.settings.useLocation.error2": "La geolocalització no és compatible amb el teu navegador.", "station.settings.welcome": "👋 Benvingut/da a OpenHamClock!", - "weather.clouds": "☁️ Núvols", "weather.condition.0": "Serè", "weather.condition.1": "Majoritàriament serè", @@ -381,7 +368,6 @@ "weather.condition.95": "Tempesta", "weather.condition.96": "Tempesta amb calamarsa lleu", "weather.condition.99": "Tempesta amb calamarsa intensa", - "weather.dewPoint": "🌡️ Punt de rosada", "weather.error.busy": "Servei meteorològic ocupat", "weather.error.loading": "Carregant el temps...", diff --git a/src/lang/de.json b/src/lang/de.json index 90b89f8d..26864ecd 100644 --- a/src/lang/de.json +++ b/src/lang/de.json @@ -342,6 +342,8 @@ "station.settings.theme.custom.--accent-blue": "Blauer Akzent", "station.settings.theme.custom.--accent-cyan": "Cyanfarbener Akzent", "station.settings.theme.custom.--accent-purple": "Lila Akzent", + "station.settings.theme.reset": "Benutzerdefiniertes Design auf Standardfarben zurücksetzen", + "station.settings.theme.reset.confirm": "Benutzerdefiniertes Design auf Standardfarben zurücksetzen? Dadurch werden Ihre aktuellen benutzerdefinierten Farben überschrieben. Dieser Vorgang kann nicht rückgängig gemacht werden.", "station.settings.timezone": "Zeitzone", "station.settings.timezone.auto": "Auto (Browser-Standard)", "station.settings.timezone.currentDefault": " Browser-Standard wird verwendet.", diff --git a/src/lang/en.json b/src/lang/en.json index bcfd6316..78600ce1 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -98,6 +98,8 @@ "station.settings.theme.custom.--accent-blue": "Blue Accent", "station.settings.theme.custom.--accent-cyan": "Cyan Accent", "station.settings.theme.custom.--accent-purple": "Purple Accent", + "station.settings.theme.reset": "Reset Custom Theme to Default Colors", + "station.settings.theme.reset.confirm": "Reset custom theme to defaults? This will replace your current custom colors. This cannot be undone.", "station.settings.timezone": "🕐 Timezone", "station.settings.timezone.describe": "Set this if your local time shows incorrectly (e.g. same as UTC). Privacy browsers like Librewolf may spoof your timezone.", "station.settings.title": "Station Settings", diff --git a/src/lang/es.json b/src/lang/es.json index c800fbdd..68a984ab 100644 --- a/src/lang/es.json +++ b/src/lang/es.json @@ -337,6 +337,8 @@ "station.settings.theme.custom.--accent-blue": "Acento azul", "station.settings.theme.custom.--accent-cyan": "Acento cian", "station.settings.theme.custom.--accent-purple": "Acento morado", + "station.settings.theme.reset": "Restablecer el tema personalizado a los colores predeterminados", + "station.settings.theme.reset.confirm": "¿Restablecer el tema personalizado a los valores predeterminados? Esto reemplazará tus colores personalizados actuales. Esta acción no se puede deshacer.", "station.settings.timezone": "Zona horaria", "station.settings.timezone.auto": "Auto (predeterminado del navegador)", "station.settings.timezone.currentDefault": " Usando el predeterminado del navegador.", diff --git a/src/lang/fr.json b/src/lang/fr.json index ce2afadd..8d348d85 100644 --- a/src/lang/fr.json +++ b/src/lang/fr.json @@ -337,6 +337,8 @@ "station.settings.theme.custom.--accent-blue": "Bleu", "station.settings.theme.custom.--accent-cyan": "Cyan", "station.settings.theme.custom.--accent-purple": "Violet", + "station.settings.theme.reset": "Réinitialiser le thème personnalisé aux couleurs par défaut", + "station.settings.theme.reset.confirm": "Réinitialiser le thème personnalisé aux couleurs par défaut ? Cette action remplacera vos couleurs personnalisées actuelles. Elle est irréversible.", "station.settings.timezone": "🕐 Fuseau horaire", "station.settings.timezone.auto": "Auto (par défaut navigateur)", "station.settings.timezone.currentDefault": " Utilisation du réglage navigateur.", diff --git a/src/lang/it.json b/src/lang/it.json index 567faa3b..035d59eb 100644 --- a/src/lang/it.json +++ b/src/lang/it.json @@ -337,6 +337,8 @@ "station.settings.theme.custom.--accent-blue": "Accento blu", "station.settings.theme.custom.--accent-cyan": "Accento ciano", "station.settings.theme.custom.--accent-purple": "Accento viola", + "station.settings.theme.reset": "Ripristina i colori predefiniti del tema personalizzato", + "station.settings.theme.reset.confirm": "Ripristinare i colori predefiniti del tema personalizzato? Questa operazione sostituirà i colori personalizzati correnti. Questa operazione non può essere annullata.", "station.settings.timezone": "Fuso orario", "station.settings.timezone.auto": "Auto (predefinito browser)", "station.settings.timezone.currentDefault": " Attualmente uso il predefinito del browser.", diff --git a/src/lang/ja.json b/src/lang/ja.json index ac8151e0..73dbb866 100644 --- a/src/lang/ja.json +++ b/src/lang/ja.json @@ -337,6 +337,8 @@ "station.settings.theme.custom.--accent-blue": "ブルーアクセント", "station.settings.theme.custom.--accent-cyan": "シアンアクセント", "station.settings.theme.custom.--accent-purple": "パープルアクセント", + "station.settings.theme.reset": "カスタムテーマをデフォルトカラーにリセット", + "station.settings.theme.reset.confirm": "カスタムテーマをデフォルトにリセットしますか?これにより、現在のカスタムカラーが置き換えられます。この操作は元に戻せません。", "station.settings.timezone": "🕐 タイムゾーン", "station.settings.timezone.auto": "自動 (ブラウザのデフォルト)", "station.settings.timezone.currentDefault": " 現在ブラウザのデフォルトを使用中。", diff --git a/src/lang/ka.json b/src/lang/ka.json index 096abf70..1cd1ac25 100644 --- a/src/lang/ka.json +++ b/src/lang/ka.json @@ -87,6 +87,8 @@ "station.settings.theme.custom.--accent-blue": "ლურჯი აქცენტი", "station.settings.theme.custom.--accent-cyan": "ცისფერი აქცენტი", "station.settings.theme.custom.--accent-purple": "იისფერი აქცენტი", + "station.settings.theme.reset": "მორგებული თემის ნაგულისხმევ ფერებზე დაბრუნება", + "station.settings.theme.reset.confirm": "გსურთ მორგებული თემის ნაგულისხმევ ფერებზე დაბრუნება? ეს ჩაანაცვლებს თქვენს მიმდინარე მორგებულ ფერებს. ამ მოქმედების გაუქმება შეუძლებელია.", "station.settings.timezone": "🕐 დროის სარტყელი", "station.settings.timezone.describe": "დააყენეთ, თუ ადგილობრივი დრო არასწორად ჩანს (მაგ. UTC-ს ემთხვევა). კონფიდენციალურობის ბრაუზერები შეიძლება ცვლიდნენ დროის სარტყელს.", "station.settings.title": "სადგურის პარამეტრები", diff --git a/src/lang/ko.json b/src/lang/ko.json index d1535e27..e8be20b6 100644 --- a/src/lang/ko.json +++ b/src/lang/ko.json @@ -337,6 +337,8 @@ "station.settings.theme.custom.--accent-blue": "파란색 강조 색상", "station.settings.theme.custom.--accent-cyan": "청록색 강조 색상", "station.settings.theme.custom.--accent-purple": "보라색 강조 색상", + "station.settings.theme.reset": "사용자 지정 테마를 기본 색상으로 초기화하시겠습니까?", + "station.settings.theme.reset.confirm": "사용자 지정 테마를 기본 색상으로 초기화하면 현재 사용자 지정 색상이 변경됩니다. 이 작업은 되돌릴 수 없습니다.", "station.settings.timezone": "🕐 시간대", "station.settings.timezone.auto": "자동 (브라우저 기본값)", "station.settings.timezone.currentDefault": " 현재 브라우저 기본값 사용 중.", diff --git a/src/lang/ms.json b/src/lang/ms.json index 97dbbbe4..e193225d 100644 --- a/src/lang/ms.json +++ b/src/lang/ms.json @@ -337,6 +337,8 @@ "station.settings.theme.custom.--accent-blue": "Aksen Biru", "station.settings.theme.custom.--accent-cyan": "Aksen Sian", "station.settings.theme.custom.--accent-purple": "Aksen Ungu", + "station.settings.theme.reset": "Tetapkan Semula Tema Tersuai kepada Warna Lalai", + "station.settings.theme.reset.confirm": "Tetapkan semula tema tersuai kepada lalai? Ini akan menggantikan warna tersuai semasa anda. Ini tidak boleh dibuat asal.", "station.settings.timezone": "🕐 Zon Waktu", "station.settings.timezone.auto": "Auto (lalai pelayar)", "station.settings.timezone.currentDefault": " Sedang menggunakan lalai pelayar.", diff --git a/src/lang/nl.json b/src/lang/nl.json index 6aa15e62..e8f05bc5 100644 --- a/src/lang/nl.json +++ b/src/lang/nl.json @@ -337,6 +337,8 @@ "station.settings.theme.custom.--accent-blue": "Blauw accent", "station.settings.theme.custom.--accent-cyan": "Cyaan accent", "station.settings.theme.custom.--accent-purple": "Paars accent", + "station.settings.theme.reset": "Aangepast thema terugzetten naar standaardkleuren", + "station.settings.theme.reset.confirm": "Aangepast thema terugzetten naar standaardinstellingen? Hiermee worden uw huidige aangepaste kleuren vervangen. Deze actie kan niet ongedaan worden gemaakt.", "station.settings.timezone": "Tijdzone", "station.settings.timezone.auto": "Auto (browserstandaard)", "station.settings.timezone.currentDefault": " Browserstandaard wordt gebruikt.", diff --git a/src/lang/pt.json b/src/lang/pt.json index 5aaff644..7de0c8ef 100644 --- a/src/lang/pt.json +++ b/src/lang/pt.json @@ -337,6 +337,8 @@ "station.settings.theme.custom.--accent-blue": "Destaque Azul", "station.settings.theme.custom.--accent-cyan": "Destaque Ciano", "station.settings.theme.custom.--accent-purple": "Destaque Roxo", + "station.settings.theme.reset": "Redefinir tema personalizado para as cores padrão", + "station.settings.theme.reset.confirm": "Redefinir tema personalizado para as cores padrão? Isso substituirá suas cores personalizadas atuais. Essa ação não pode ser desfeita.", "station.settings.timezone": "Fuso horário", "station.settings.timezone.auto": "Auto (padr?o do navegador)", "station.settings.timezone.currentDefault": " Usando o padr?o do navegador.", diff --git a/src/lang/ru.json b/src/lang/ru.json index 484b1669..5e875795 100644 --- a/src/lang/ru.json +++ b/src/lang/ru.json @@ -87,6 +87,8 @@ "station.settings.theme.custom.--accent-blue": "Синий акцент", "station.settings.theme.custom.--accent-cyan": "Бирюзовый акцент", "station.settings.theme.custom.--accent-purple": "Фиолетовый акцент", + "station.settings.theme.reset": "Сбросить пользовательскую тему до цветов по умолчанию", + "station.settings.theme.reset.confirm": "Сбросить пользовательскую тему до цветов по умолчанию? Это заменит ваши текущие пользовательские цвета. Это действие необратимо.", "station.settings.timezone": "🕐 Часовой пояс", "station.settings.timezone.describe": "Установите, если местное время отображается неправильно (например, совпадает с UTC). Браузеры конфиденциальности могут подменять часовой пояс.", "station.settings.title": "Настройки станции", diff --git a/src/lang/sl.json b/src/lang/sl.json index 87bde91d..9aba4fcf 100644 --- a/src/lang/sl.json +++ b/src/lang/sl.json @@ -337,6 +337,8 @@ "station.settings.theme.custom.--accent-blue": "Moder poudarek", "station.settings.theme.custom.--accent-cyan": "Cianov poudarek", "station.settings.theme.custom.--accent-purple": "Vijoličen poudarek", + "station.settings.theme.reset": "Ponastavitev teme po meri na privzete barve", + "station.settings.theme.reset.confirm": "Želite ponastaviti temo po meri na privzete nastavitve? To bo nadomestilo vaše trenutne barve po meri. Tega ni mogoče razveljaviti.", "station.settings.timezone": "Časovni pas", "station.settings.timezone.auto": "Samodejno (privzeto v brskalniku)", "station.settings.timezone.currentDefault": " Uporablja se privzeta nastavitev brskalnika.", diff --git a/src/lang/zh.json b/src/lang/zh.json index 9e9787a0..50c610b7 100644 --- a/src/lang/zh.json +++ b/src/lang/zh.json @@ -69,6 +69,27 @@ "station.settings.theme.light.describe": "→ 适用于日间使用的浅色主题", "station.settings.theme.retro": "怀旧", "station.settings.theme.retro.describe": "→ 90年代 Windows 风格", + "station.settings.theme.custom": "自定义", + "station.settings.theme.custom.describe": "→ 可配置主题", + "station.settings.theme.custom.--bg-primary": "主背景", + "station.settings.theme.custom.--bg-secondary": "次背景", + "station.settings.theme.custom.--bg-tertiary": "三级背景", + "station.settings.theme.custom.--bg-panel": "面板背景", + "station.settings.theme.custom.--border-color": "边框颜色", + "station.settings.theme.custom.--text-primary": "主文本", + "station.settings.theme.custom.--text-secondary": "次文本", + "station.settings.theme.custom.--text-muted": "低亮度文本", + "station.settings.theme.custom.--map-ocean": "海洋地图", + "station.settings.theme.custom.--accent-amber": "琥珀色点缀", + "station.settings.theme.custom.--accent-amber-dim": "琥珀色点缀(暗)", + "station.settings.theme.custom.--accent-green": "绿色点缀", + "station.settings.theme.custom.--accent-green-dim": "绿色点缀(暗)", + "station.settings.theme.custom.--accent-red": "红色点缀", + "station.settings.theme.custom.--accent-blue": "蓝色点缀", + "station.settings.theme.custom.--accent-cyan": "青色点缀", + "station.settings.theme.custom.--accent-purple": "紫色点缀", + "station.settings.theme.reset": "将自定义主题重置为默认颜色", + "station.settings.theme.reset.confirm": "将自定义主题重置为默认设置?这将替换您当前的自定义颜色。此操作无法撤销。", "station.settings.timezone": "🕐 时区", "station.settings.timezone.describe": "如果您的本地时间显示错误请手动设置。某些隐私浏览器可能会伪造时区。", "station.settings.title": "电台设置", diff --git a/src/styles/main.css b/src/styles/main.css index eb012b85..1341486f 100644 --- a/src/styles/main.css +++ b/src/styles/main.css @@ -625,24 +625,31 @@ body::before { .text-amber { color: var(--accent-amber); } + .text-green { color: var(--accent-green); } + .text-red { color: var(--accent-red); } + .text-blue { color: var(--accent-blue); } + .text-cyan { color: var(--accent-cyan); } + .text-muted { color: var(--text-muted); } + .text-primary { color: var(--text-primary); } + .text-secondary { color: var(--text-secondary); } @@ -650,6 +657,7 @@ body::before { .font-mono { font-family: 'JetBrains Mono', monospace; } + .font-display { font-family: 'Orbitron', monospace; } @@ -657,43 +665,144 @@ body::before { .bg-panel { background: var(--bg-panel); } + .bg-primary { background: var(--bg-primary); } + .bg-secondary { background: var(--bg-secondary); } + .bg-tertiary { background: var(--bg-tertiary); } /* Theme controls */ -#theme-selector-component .theme-select-button { +.theme-selector-component { + display: flex; + grid-column: 1 / -1; + display: flex; + flex-wrap: wrap; + gap: 1em; +} + +#custom-theme-editor-component { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 8px; +} + +.theme-selector-control { + flex: 1; + flex-basis: 350px; + box-sizing: border-box; +} + +.theme-selector-control select { + width: 100%; padding: 10px; background: var(--bg-tertiary); + color: var(--text-primary); border: 1px solid var(--border-color); border-radius: 6px; + font-family: 'JetBrains Mono', monospace; + cursor: pointer; +} + +.theme-selector-control .theme-description { + font-size: 11px; + color: var(--text-muted); + margin-top: 6px; +} + +.theme-selector-preview { + flex: 1; + flex-basis: 350px; + box-sizing: border-box; + background: var(--bg-primary); + border: 1px solid var(--border-color); + border-radius: 6px; + padding: 1em 2em 2em 2em; +} + +.theme-selector-preview h2 { + color: var(--text-primary); + text-transform: capitalize; + margin-bottom: 0.5em; +} + +.theme-selector-preview .preview-element { + background: var(--bg-secondary); + border: 1px solid var(--border-color); + padding: 1em; + border-radius: 6px; + margin: 0; +} + +.theme-selector-preview h4 { color: var(--text-secondary); - font-size: 12px; +} + +.theme-selector-preview .preview-panel { + background: var(--bg-panel); + border: 1px solid var(--border-color); + padding: 1em; + margin: 1em 0; + border-radius: 6px; +} + +.theme-selector-preview .preview-panel:last-child { + margin-bottom: 0; +} + +.theme-selector-preview .preview-panel ul { + margin: 0 1em; +} + +.theme-selector-preview .preview-panel ul li { + margin: 0 0.25em; +} + +.theme-selector-preview h4 { + color: var(--text-primary); +} + +.theme-selector-preview button { + display: inline-block; + padding: 1em; + border: 1px solid var(--border-color); + border-radius: 6px; cursor: pointer; - font-weight: 400; } -#theme-selector-component .theme-select-button span.icon { - text-shadow: 0 0 5px #000; +.theme-selector-preview button.btn-primary { + margin-right: 1em; + background: var(--accent-amber); + color: var(--text-primary); } -#theme-selector-component .theme-select-button.active { - border-color: var(--accent-amber); - background-color: var(--accent-amber); - color: #000; - font-weight: 600; +.theme-selector-preview button.btn-secondary { + background: var(--bg-tertiary); + color: var(--text-secondary); } -#custom-theme-editor-component { - display: grid; - grid-template-columns: repeat(4, 1fr); - gap: 8px; +.theme-selector-preview p.muted-text { + color: var(--text-muted); + margin: 1em 0; +} + +.reset-theme-button { + min-width: 100%; + margin: 2em 0; + padding: 10px; + background: var(--bg-tertiary); + border: 1px solid var(--border-color); + border-radius: 6px; + color: var(--text-secondary); + font-size: 12px; + cursor: pointer; + font-weight: 400; } @media screen and (max-width: 768px) { @@ -726,11 +835,6 @@ body::before { display: block; } -/* Hide the hue slider for variables that have color names */ -#custom-theme-editor-component .hue-locked .react-colorful__hue { - display: none; -} - /* ============================================ WSPR PLUGIN ANIMATIONS (v1.3.0) ============================================ */ diff --git a/src/theme/colorUtils.js b/src/theme/colorUtils.js new file mode 100644 index 00000000..6f5b27c1 --- /dev/null +++ b/src/theme/colorUtils.js @@ -0,0 +1,25 @@ +export function rgbaStringToObject(str) { + if (!str) return { r: 0, g: 0, b: 0, a: 1 }; + + const match = str.match(/rgba?\(([^)]+)\)/); + if (!match) return { r: 0, g: 0, b: 0, a: 1 }; + + const parts = match[1].split(',').map((p) => p.trim()); + + return { + r: parseInt(parts[0], 10), + g: parseInt(parts[1], 10), + b: parseInt(parts[2], 10), + a: parts[3] !== undefined ? parseFloat(parts[3]) : 1, + }; +} + +export function rgbaObjectToString({ r, g, b, a }) { + /* in case we get a malformed object, adjust it to be valid */ + r = Math.max(0, Math.min(255, r)); + g = Math.max(0, Math.min(255, g)); + b = Math.max(0, Math.min(255, b)); + a = Math.max(0, Math.min(1, a ?? 1)); + + return `rgba(${r}, ${g}, ${b}, ${a})`; +} diff --git a/src/theme/themeConfig.js b/src/theme/themeConfig.js index 5a909100..83e714f5 100644 --- a/src/theme/themeConfig.js +++ b/src/theme/themeConfig.js @@ -1,29 +1,31 @@ export const THEME_COLOR_CONFIG = { - '--bg-primary': { alpha: false, hueRestrict: null }, - '--bg-secondary': { alpha: false, hueRestrict: null }, - '--bg-tertiary': { alpha: false, hueRestrict: null }, - '--bg-panel': { alpha: false, hueRestrict: null }, - '--border-color': { alpha: false, hueRestrict: null }, - '--text-primary': { alpha: false, hueRestrict: null }, - '--text-secondary': { alpha: false, hueRestrict: null }, - '--text-muted': { alpha: false, hueRestrict: null }, - '--map-ocean': { alpha: false, hueRestrict: null }, - '--accent-amber': { alpha: false, hueRestrict: 45 }, - '--accent-amber-dim': { alpha: false, hueRestrict: 45 }, - '--accent-green': { alpha: false, hueRestrict: 120 }, - '--accent-green-dim': { alpha: false, hueRestrict: 120 }, - '--accent-red': { alpha: false, hueRestrict: 0 }, - '--accent-blue': { alpha: false, hueRestrict: 240 }, - '--accent-cyan': { alpha: false, hueRestrict: 180 }, - '--accent-purple': { alpha: false, hueRestrict: 277 }, + '--bg-primary': { alpha: false }, + '--bg-secondary': { alpha: false }, + '--bg-tertiary': { alpha: false }, + '--bg-panel': { alpha: true }, + '--border-color': { alpha: true }, + '--text-primary': { alpha: false }, + '--text-secondary': { alpha: false }, + '--text-muted': { alpha: true }, + '--map-ocean': { alpha: false }, + '--accent-amber': { alpha: false }, + '--accent-amber-dim': { alpha: true }, + '--accent-green': { alpha: false }, + '--accent-green-dim': { alpha: true }, + '--accent-red': { alpha: false }, + '--accent-blue': { alpha: false }, + '--accent-cyan': { alpha: false }, + '--accent-purple': { alpha: false }, }; export const THEME_VARS = Object.keys(THEME_COLOR_CONFIG); export const AVAILABLE_THEMES = { - dark: { label: 'Dark', icon: '🌙' }, - light: { label: 'Light', icon: '☀️' }, - legacy: { label: 'Legacy', icon: '💻' }, - retro: { label: 'Retro', icon: '🪟' }, - custom: { label: 'Custom', icon: '🎨' }, + dark: { label: 'Dark' }, + light: { label: 'Light' }, + legacy: { label: 'Legacy' }, + retro: { label: 'Retro' }, + custom: { label: 'Custom' }, }; + +export const DEFAULT_THEME = 'dark'; diff --git a/src/theme/themeUtils.js b/src/theme/themeUtils.js index d321bd3e..62381837 100644 --- a/src/theme/themeUtils.js +++ b/src/theme/themeUtils.js @@ -1,18 +1,4 @@ import { THEME_VARS } from './themeConfig'; - -/* Add "active" class to theme button that is selected */ -export function setActiveThemeButton(selectorString) { - const allThemeButtons = document.querySelectorAll('.theme-select-button'); - allThemeButtons.forEach((element) => { - element.classList.remove('active'); - }); - - const activeButton = document.querySelector('.' + selectorString + '-theme-select-button'); - if (activeButton) { - activeButton.classList.add('active'); - } -} - /* Read CSS variables from the active theme */ export function readCssVariables() { const styles = getComputedStyle(document.documentElement); @@ -32,3 +18,17 @@ export function applyPrebuiltTheme(themeName) { document.documentElement.removeAttribute('style'); // clears custom overrides document.documentElement.setAttribute('data-theme', themeName); } + +/* get a theme's styles */ +export function getThemeStyles(themeName) { + document.documentElement.removeAttribute('style'); + document.documentElement.setAttribute('data-theme', themeName); + + const styles = getComputedStyle(document.documentElement); + return Array.from(styles) + .filter((name) => name.startsWith('--')) + .reduce((acc, name) => { + acc[name] = styles.getPropertyValue(name).trim(); + return acc; + }, {}); +} diff --git a/src/theme/useTheme.js b/src/theme/useTheme.js index b38d1878..f2746e41 100644 --- a/src/theme/useTheme.js +++ b/src/theme/useTheme.js @@ -1,18 +1,19 @@ import { useEffect, useState } from 'react'; import { loadConfig, saveConfig } from './themeStorage'; -import { setActiveThemeButton, readCssVariables, applyCustomTheme, applyPrebuiltTheme } from './themeUtils'; +import { DEFAULT_THEME } from '../theme/themeConfig'; +import { getThemeStyles, readCssVariables, applyCustomTheme, applyPrebuiltTheme } from './themeUtils'; export function useTheme() { const config = loadConfig(); - const [theme, setTheme] = useState(config.theme || 'dark'); + const [theme, setTheme] = useState(config.theme || DEFAULT_THEME); const [customTheme, setCustomTheme] = useState(config.customTheme || null); /* Initial load */ useEffect(() => { if (!config.customTheme) { - const defaults = readCssVariables(); // from dark theme - saveConfig({ theme: 'dark', customTheme: defaults }); + const defaults = readCssVariables(); // from default theme + saveConfig({ theme: DEFAULT_THEME, customTheme: defaults }); setCustomTheme(defaults); } @@ -23,6 +24,21 @@ export function useTheme() { } }, []); + /* Custom Theme reset */ + function resetCustomToDefault() { + const defaultStyles = getThemeStyles(DEFAULT_THEME); + + setCustomTheme(defaultStyles); + applyCustomTheme(defaultStyles); + + saveConfig({ + theme: 'custom', + customTheme: defaultStyles, + }); + + setTheme('custom'); + } + /* Theme switching */ useEffect(() => { if (theme === 'custom') { @@ -31,8 +47,6 @@ export function useTheme() { applyPrebuiltTheme(theme); } saveConfig({ theme }); - - setActiveThemeButton(theme); }, [theme]); /* Custom edits */ @@ -48,5 +62,6 @@ export function useTheme() { setTheme, customTheme, updateCustomVar, + resetCustomToDefault, }; } From 31c0eb386f9cb1d866aa76bc14d50331f479af91 Mon Sep 17 00:00:00 2001 From: David Enete Date: Tue, 10 Mar 2026 17:58:10 -0400 Subject: [PATCH 3/3] [feature-693] removed loading of translation engine where it could be passed by props from a parent, added translations for sample button text --- src/components/CustomThemeEditor.jsx | 11 +++++--- src/components/SettingsPanel.jsx | 1 + src/components/ThemeSelector.jsx | 41 +++++++++++++++++----------- src/lang/ca.json | 1 + src/lang/de.json | 1 + src/lang/en.json | 1 + src/lang/es.json | 1 + src/lang/fr.json | 1 + src/lang/it.json | 1 + src/lang/ja.json | 1 + src/lang/ka.json | 1 + src/lang/ko.json | 1 + src/lang/ms.json | 1 + src/lang/nl.json | 1 + src/lang/pt.json | 1 + src/lang/ru.json | 1 + src/lang/sl.json | 1 + src/lang/zh.json | 1 + 18 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/components/CustomThemeEditor.jsx b/src/components/CustomThemeEditor.jsx index e58b4d0b..5f26e384 100644 --- a/src/components/CustomThemeEditor.jsx +++ b/src/components/CustomThemeEditor.jsx @@ -1,11 +1,14 @@ import { HexColorPicker, RgbaColorPicker } from 'react-colorful'; import { THEME_COLOR_CONFIG } from '../theme/themeConfig'; -import { useTranslation } from 'react-i18next'; import { rgbaStringToObject, rgbaObjectToString } from '../theme/colorUtils'; -export default function CustomThemeEditor({ id, customTheme, updateCustomVar, resetCustomToDefault }) { - const { t } = useTranslation(); - +export default function CustomThemeEditor({ + id = 'custom-theme-editor-component', + customTheme, + updateCustomVar, + resetCustomToDefault, + t, +}) { return ( <>
    diff --git a/src/components/ThemeSelector.jsx b/src/components/ThemeSelector.jsx index c6199fd0..4802eb53 100644 --- a/src/components/ThemeSelector.jsx +++ b/src/components/ThemeSelector.jsx @@ -1,4 +1,3 @@ -import { useEffect } from 'react'; import { AVAILABLE_THEMES } from '../theme/themeConfig'; export default function ThemeSelector({ @@ -22,16 +21,26 @@ export default function ThemeSelector({
    {t('station.settings.theme.' + theme + '.describe')}
-

Theme: {AVAILABLE_THEMES[theme].label}

+

+ {t('station.settings.theme')}: {AVAILABLE_THEMES[theme].label} +

-

Secondary Text Over Secondary Background

+

+ {t('station.settings.theme.custom.--text-secondary')} / {t('station.settings.theme.custom.--bg-secondary')} +

-

Primary Text Over Panel Background

-

Muted Text over panel background.

- - +

+ {t('station.settings.theme.custom.--text-primary')} / {t('station.settings.theme.custom.--bg-panel')} +

+

+ {t('station.settings.theme.custom.--text-muted')} / {t('station.settings.theme.custom.--bg-panel')} +

+ +
-

Muted text over secondary background.

+

+ {t('station.settings.theme.custom.--text-muted')} / {t('station.settings.theme.custom.--bg-secondary')} +

  • - Amber Accent + {t('station.settings.theme.custom.--accent-amber')}
  • - Amber Accent (dim) + {t('station.settings.theme.custom.--accent-amber-dim')}
  • - Green Accent + {t('station.settings.theme.custom.--accent-green')}
  • - Green Accent (dim) + {t('station.settings.theme.custom.--accent-green-dim')}
  • - Red Accent + {t('station.settings.theme.custom.--accent-red')}
  • - Blue Accent + {t('station.settings.theme.custom.--accent-blue')}
  • - Cyan Accent + {t('station.settings.theme.custom.--accent-cyan')}
  • - Purple Accent + {t('station.settings.theme.custom.--accent-purple')}
diff --git a/src/lang/ca.json b/src/lang/ca.json index 76e80170..5c441f22 100644 --- a/src/lang/ca.json +++ b/src/lang/ca.json @@ -323,6 +323,7 @@ "station.settings.theme.custom.--accent-purple": "Accent morat", "station.settings.theme.reset": "Restableix el tema personalitzat als colors predeterminats", "station.settings.theme.reset.confirm": "Vols restablir el tema personalitzat als valors predeterminats? Això substituirà els teus colors personalitzats actuals. Aquesta acció no es pot desfer.", + "station.settings.theme.sampleButtonText": "Botó", "station.settings.timezone": "Zona horària", "station.settings.timezone.auto": "Auto (predeterminat del navegador)", "station.settings.timezone.currentDefault": " S’està usant el predeterminat del navegador.", diff --git a/src/lang/de.json b/src/lang/de.json index 26864ecd..241524b6 100644 --- a/src/lang/de.json +++ b/src/lang/de.json @@ -344,6 +344,7 @@ "station.settings.theme.custom.--accent-purple": "Lila Akzent", "station.settings.theme.reset": "Benutzerdefiniertes Design auf Standardfarben zurücksetzen", "station.settings.theme.reset.confirm": "Benutzerdefiniertes Design auf Standardfarben zurücksetzen? Dadurch werden Ihre aktuellen benutzerdefinierten Farben überschrieben. Dieser Vorgang kann nicht rückgängig gemacht werden.", + "station.settings.theme.sampleButtonText": "Taste", "station.settings.timezone": "Zeitzone", "station.settings.timezone.auto": "Auto (Browser-Standard)", "station.settings.timezone.currentDefault": " Browser-Standard wird verwendet.", diff --git a/src/lang/en.json b/src/lang/en.json index 78600ce1..2084e8e0 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -100,6 +100,7 @@ "station.settings.theme.custom.--accent-purple": "Purple Accent", "station.settings.theme.reset": "Reset Custom Theme to Default Colors", "station.settings.theme.reset.confirm": "Reset custom theme to defaults? This will replace your current custom colors. This cannot be undone.", + "station.settings.theme.sampleButtonText": "Button", "station.settings.timezone": "🕐 Timezone", "station.settings.timezone.describe": "Set this if your local time shows incorrectly (e.g. same as UTC). Privacy browsers like Librewolf may spoof your timezone.", "station.settings.title": "Station Settings", diff --git a/src/lang/es.json b/src/lang/es.json index 68a984ab..c3b73c23 100644 --- a/src/lang/es.json +++ b/src/lang/es.json @@ -339,6 +339,7 @@ "station.settings.theme.custom.--accent-purple": "Acento morado", "station.settings.theme.reset": "Restablecer el tema personalizado a los colores predeterminados", "station.settings.theme.reset.confirm": "¿Restablecer el tema personalizado a los valores predeterminados? Esto reemplazará tus colores personalizados actuales. Esta acción no se puede deshacer.", + "station.settings.theme.sampleButtonText": "Botón", "station.settings.timezone": "Zona horaria", "station.settings.timezone.auto": "Auto (predeterminado del navegador)", "station.settings.timezone.currentDefault": " Usando el predeterminado del navegador.", diff --git a/src/lang/fr.json b/src/lang/fr.json index 8d348d85..69e20358 100644 --- a/src/lang/fr.json +++ b/src/lang/fr.json @@ -339,6 +339,7 @@ "station.settings.theme.custom.--accent-purple": "Violet", "station.settings.theme.reset": "Réinitialiser le thème personnalisé aux couleurs par défaut", "station.settings.theme.reset.confirm": "Réinitialiser le thème personnalisé aux couleurs par défaut ? Cette action remplacera vos couleurs personnalisées actuelles. Elle est irréversible.", + "station.settings.theme.sampleButtonText": "Bouton", "station.settings.timezone": "🕐 Fuseau horaire", "station.settings.timezone.auto": "Auto (par défaut navigateur)", "station.settings.timezone.currentDefault": " Utilisation du réglage navigateur.", diff --git a/src/lang/it.json b/src/lang/it.json index 035d59eb..c25c6b10 100644 --- a/src/lang/it.json +++ b/src/lang/it.json @@ -339,6 +339,7 @@ "station.settings.theme.custom.--accent-purple": "Accento viola", "station.settings.theme.reset": "Ripristina i colori predefiniti del tema personalizzato", "station.settings.theme.reset.confirm": "Ripristinare i colori predefiniti del tema personalizzato? Questa operazione sostituirà i colori personalizzati correnti. Questa operazione non può essere annullata.", + "station.settings.theme.sampleButtonText": "Pulsante", "station.settings.timezone": "Fuso orario", "station.settings.timezone.auto": "Auto (predefinito browser)", "station.settings.timezone.currentDefault": " Attualmente uso il predefinito del browser.", diff --git a/src/lang/ja.json b/src/lang/ja.json index 73dbb866..54cfa176 100644 --- a/src/lang/ja.json +++ b/src/lang/ja.json @@ -339,6 +339,7 @@ "station.settings.theme.custom.--accent-purple": "パープルアクセント", "station.settings.theme.reset": "カスタムテーマをデフォルトカラーにリセット", "station.settings.theme.reset.confirm": "カスタムテーマをデフォルトにリセットしますか?これにより、現在のカスタムカラーが置き換えられます。この操作は元に戻せません。", + "station.settings.theme.sampleButtonText": "ボタン", "station.settings.timezone": "🕐 タイムゾーン", "station.settings.timezone.auto": "自動 (ブラウザのデフォルト)", "station.settings.timezone.currentDefault": " 現在ブラウザのデフォルトを使用中。", diff --git a/src/lang/ka.json b/src/lang/ka.json index 1cd1ac25..9b476612 100644 --- a/src/lang/ka.json +++ b/src/lang/ka.json @@ -89,6 +89,7 @@ "station.settings.theme.custom.--accent-purple": "იისფერი აქცენტი", "station.settings.theme.reset": "მორგებული თემის ნაგულისხმევ ფერებზე დაბრუნება", "station.settings.theme.reset.confirm": "გსურთ მორგებული თემის ნაგულისხმევ ფერებზე დაბრუნება? ეს ჩაანაცვლებს თქვენს მიმდინარე მორგებულ ფერებს. ამ მოქმედების გაუქმება შეუძლებელია.", + "station.settings.theme.sampleButtonText": "ღილაკი", "station.settings.timezone": "🕐 დროის სარტყელი", "station.settings.timezone.describe": "დააყენეთ, თუ ადგილობრივი დრო არასწორად ჩანს (მაგ. UTC-ს ემთხვევა). კონფიდენციალურობის ბრაუზერები შეიძლება ცვლიდნენ დროის სარტყელს.", "station.settings.title": "სადგურის პარამეტრები", diff --git a/src/lang/ko.json b/src/lang/ko.json index e8be20b6..43c88779 100644 --- a/src/lang/ko.json +++ b/src/lang/ko.json @@ -339,6 +339,7 @@ "station.settings.theme.custom.--accent-purple": "보라색 강조 색상", "station.settings.theme.reset": "사용자 지정 테마를 기본 색상으로 초기화하시겠습니까?", "station.settings.theme.reset.confirm": "사용자 지정 테마를 기본 색상으로 초기화하면 현재 사용자 지정 색상이 변경됩니다. 이 작업은 되돌릴 수 없습니다.", + "station.settings.theme.sampleButtonText": "단추", "station.settings.timezone": "🕐 시간대", "station.settings.timezone.auto": "자동 (브라우저 기본값)", "station.settings.timezone.currentDefault": " 현재 브라우저 기본값 사용 중.", diff --git a/src/lang/ms.json b/src/lang/ms.json index e193225d..7ffcf704 100644 --- a/src/lang/ms.json +++ b/src/lang/ms.json @@ -339,6 +339,7 @@ "station.settings.theme.custom.--accent-purple": "Aksen Ungu", "station.settings.theme.reset": "Tetapkan Semula Tema Tersuai kepada Warna Lalai", "station.settings.theme.reset.confirm": "Tetapkan semula tema tersuai kepada lalai? Ini akan menggantikan warna tersuai semasa anda. Ini tidak boleh dibuat asal.", + "station.settings.theme.sampleButtonText": "Butang", "station.settings.timezone": "🕐 Zon Waktu", "station.settings.timezone.auto": "Auto (lalai pelayar)", "station.settings.timezone.currentDefault": " Sedang menggunakan lalai pelayar.", diff --git a/src/lang/nl.json b/src/lang/nl.json index e8f05bc5..b8e5af58 100644 --- a/src/lang/nl.json +++ b/src/lang/nl.json @@ -339,6 +339,7 @@ "station.settings.theme.custom.--accent-purple": "Paars accent", "station.settings.theme.reset": "Aangepast thema terugzetten naar standaardkleuren", "station.settings.theme.reset.confirm": "Aangepast thema terugzetten naar standaardinstellingen? Hiermee worden uw huidige aangepaste kleuren vervangen. Deze actie kan niet ongedaan worden gemaakt.", + "station.settings.theme.sampleButtonText": "Knop", "station.settings.timezone": "Tijdzone", "station.settings.timezone.auto": "Auto (browserstandaard)", "station.settings.timezone.currentDefault": " Browserstandaard wordt gebruikt.", diff --git a/src/lang/pt.json b/src/lang/pt.json index 7de0c8ef..dd7e9859 100644 --- a/src/lang/pt.json +++ b/src/lang/pt.json @@ -339,6 +339,7 @@ "station.settings.theme.custom.--accent-purple": "Destaque Roxo", "station.settings.theme.reset": "Redefinir tema personalizado para as cores padrão", "station.settings.theme.reset.confirm": "Redefinir tema personalizado para as cores padrão? Isso substituirá suas cores personalizadas atuais. Essa ação não pode ser desfeita.", + "station.settings.theme.sampleButtonText": "Botão", "station.settings.timezone": "Fuso horário", "station.settings.timezone.auto": "Auto (padr?o do navegador)", "station.settings.timezone.currentDefault": " Usando o padr?o do navegador.", diff --git a/src/lang/ru.json b/src/lang/ru.json index 5e875795..77b8d8a5 100644 --- a/src/lang/ru.json +++ b/src/lang/ru.json @@ -89,6 +89,7 @@ "station.settings.theme.custom.--accent-purple": "Фиолетовый акцент", "station.settings.theme.reset": "Сбросить пользовательскую тему до цветов по умолчанию", "station.settings.theme.reset.confirm": "Сбросить пользовательскую тему до цветов по умолчанию? Это заменит ваши текущие пользовательские цвета. Это действие необратимо.", + "station.settings.theme.sampleButtonText": "Кнопка", "station.settings.timezone": "🕐 Часовой пояс", "station.settings.timezone.describe": "Установите, если местное время отображается неправильно (например, совпадает с UTC). Браузеры конфиденциальности могут подменять часовой пояс.", "station.settings.title": "Настройки станции", diff --git a/src/lang/sl.json b/src/lang/sl.json index 9aba4fcf..1deb5929 100644 --- a/src/lang/sl.json +++ b/src/lang/sl.json @@ -339,6 +339,7 @@ "station.settings.theme.custom.--accent-purple": "Vijoličen poudarek", "station.settings.theme.reset": "Ponastavitev teme po meri na privzete barve", "station.settings.theme.reset.confirm": "Želite ponastaviti temo po meri na privzete nastavitve? To bo nadomestilo vaše trenutne barve po meri. Tega ni mogoče razveljaviti.", + "station.settings.theme.sampleButtonText": "Gumb", "station.settings.timezone": "Časovni pas", "station.settings.timezone.auto": "Samodejno (privzeto v brskalniku)", "station.settings.timezone.currentDefault": " Uporablja se privzeta nastavitev brskalnika.", diff --git a/src/lang/zh.json b/src/lang/zh.json index 50c610b7..3676958b 100644 --- a/src/lang/zh.json +++ b/src/lang/zh.json @@ -90,6 +90,7 @@ "station.settings.theme.custom.--accent-purple": "紫色点缀", "station.settings.theme.reset": "将自定义主题重置为默认颜色", "station.settings.theme.reset.confirm": "将自定义主题重置为默认设置?这将替换您当前的自定义颜色。此操作无法撤销。", + "station.settings.theme.sampleButtonText": "按钮", "station.settings.timezone": "🕐 时区", "station.settings.timezone.describe": "如果您的本地时间显示错误请手动设置。某些隐私浏览器可能会伪造时区。", "station.settings.title": "电台设置",