diff --git a/src/components/BandConditionsPanel.jsx b/src/components/BandConditionsPanel.jsx index 732964d..92613bf 100644 --- a/src/components/BandConditionsPanel.jsx +++ b/src/components/BandConditionsPanel.jsx @@ -20,7 +20,7 @@ export const BandConditionsPanel = ({ data, loading }) => { return (
-
πŸ“‘ BAND CONDITIONS
+
βŒ‡ BAND CONDITIONS
{loading ? (
diff --git a/src/components/ContestPanel.jsx b/src/components/ContestPanel.jsx index 100e207..7b9a399 100644 --- a/src/components/ContestPanel.jsx +++ b/src/components/ContestPanel.jsx @@ -102,7 +102,7 @@ export const ContestPanel = ({ data, loading }) => { color: 'var(--accent-primary)', fontWeight: '700' }}> - πŸ† CONTESTS + βŠ› CONTESTS {liveCount > 0 && ( - 🌐 DX CLUSTER ● LIVE + DX CLUSTER ● LIVE
{spots.length}/{totalSpots || spots.length}
diff --git a/src/components/DXFilterManager.jsx b/src/components/DXFilterManager.jsx index bd3f218..377da25 100644 --- a/src/components/DXFilterManager.jsx +++ b/src/components/DXFilterManager.jsx @@ -416,7 +416,7 @@ export const DXFilterManager = ({ filters, onFilterChange, isOpen, onClose }) => }}>
- πŸ” DX Cluster Filters + ⊘ DX Cluster Filters
{getActiveFilterCount()} filters active @@ -462,7 +462,7 @@ export const DXFilterManager = ({ filters, onFilterChange, isOpen, onClose }) => - +
{/* Tab Content */} diff --git a/src/components/DXpeditionPanel.jsx b/src/components/DXpeditionPanel.jsx index a8806a9..f7060e6 100644 --- a/src/components/DXpeditionPanel.jsx +++ b/src/components/DXpeditionPanel.jsx @@ -24,7 +24,7 @@ export const DXpeditionPanel = ({ data, loading }) => { marginBottom: '6px', fontSize: '11px' }}> - 🌍 DXPEDITIONS + βŠ• DXPEDITIONS {data && ( {data.active > 0 && {data.active} active} diff --git a/src/components/Header.jsx b/src/components/Header.jsx index db8df60..72db51e 100644 --- a/src/components/Header.jsx +++ b/src/components/Header.jsx @@ -3,7 +3,7 @@ * Top bar with callsign, clocks, weather, and controls */ import React from 'react'; - +import { IconGear, IconExpand, IconShrink } from './Icons.jsx'; export const Header = ({ config, utcTime, @@ -146,7 +146,7 @@ export const Header = ({ whiteSpace: 'nowrap' }} > - βš™ Settings + Settings
diff --git a/src/components/Icons.jsx b/src/components/Icons.jsx new file mode 100644 index 0000000..00f3fb7 --- /dev/null +++ b/src/components/Icons.jsx @@ -0,0 +1,170 @@ +/** + * SVG Icons for OpenHamClock + * + * Cross-platform icons that render identically on all browsers and operating systems. + * Replaces emoji which render as tofu/boxes on Linux Chromium without emoji fonts. + * + * All icons accept: size (default 14), color (default 'currentColor'), style, className + */ +import React from 'react'; + +const defaults = { size: 14, color: 'currentColor' }; + +// Magnifying glass / Search / Filter +export const IconSearch = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + +); + +// Refresh / Reload +export const IconRefresh = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + + + +); + +// Map +export const IconMap = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + + +); + +// Gear / Settings +export const IconGear = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + +); + +// Globe / World +export const IconGlobe = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + + +); + +// Satellite +export const IconSatellite = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + + + +); + +// Antenna / Radio +export const IconAntenna = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + + + + +); + +// Sun +export const IconSun = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + + + + + + + + +); + +// Moon +export const IconMoon = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + +); + +// Trophy / Contest +export const IconTrophy = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + + + + + +); + +// Tent / POTA / Camping +export const IconTent = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + + +); + +// Earth / DXpedition +export const IconEarth = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + + +); + +// Pin / Location +export const IconPin = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + +); + +// Tag / Label +export const IconTag = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + +); + +// Fullscreen expand +export const IconExpand = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + + + +); + +// Fullscreen shrink +export const IconShrink = ({ size = defaults.size, color = defaults.color, ...props }) => ( + + + + + + +); + +export default { + IconSearch, IconRefresh, IconMap, IconGear, IconGlobe, IconSatellite, + IconAntenna, IconSun, IconMoon, IconTrophy, IconTent, IconEarth, + IconPin, IconTag, IconExpand, IconShrink, +}; diff --git a/src/components/LocationPanel.jsx b/src/components/LocationPanel.jsx index 26c2a5f..3dba44d 100644 --- a/src/components/LocationPanel.jsx +++ b/src/components/LocationPanel.jsx @@ -21,7 +21,7 @@ export const LocationPanel = ({ return (
-
πŸ“ LOCATIONS
+
β—Ž LOCATIONS
{/* DE Location */}
diff --git a/src/components/POTAPanel.jsx b/src/components/POTAPanel.jsx index 8e466bc..56ce3e6 100644 --- a/src/components/POTAPanel.jsx +++ b/src/components/POTAPanel.jsx @@ -14,9 +14,10 @@ export const POTAPanel = ({ data, loading, showOnMap, onToggleMap }) => { marginBottom: '6px', fontSize: '11px' }}> - πŸ•οΈ POTA ACTIVATORS + β–³ POTA ACTIVATORS
diff --git a/src/components/PSKFilterManager.jsx b/src/components/PSKFilterManager.jsx index ab5172a..e31a0b0 100644 --- a/src/components/PSKFilterManager.jsx +++ b/src/components/PSKFilterManager.jsx @@ -310,7 +310,7 @@ export const PSKFilterManager = ({ filters, onFilterChange, isOpen, onClose }) = }}>

- πŸ“‘ PSKReporter Filters + βŒ‡ PSKReporter Filters

{getActiveFilterCount()} filter{getActiveFilterCount() !== 1 ? 's' : ''} active diff --git a/src/components/PSKReporterPanel.jsx b/src/components/PSKReporterPanel.jsx index b73d7e4..bf18575 100644 --- a/src/components/PSKReporterPanel.jsx +++ b/src/components/PSKReporterPanel.jsx @@ -10,6 +10,7 @@ import React, { useState, useMemo } from 'react'; import { usePSKReporter } from '../hooks/usePSKReporter.js'; import { getBandColor } from '../utils/callsign.js'; +import { IconSearch, IconRefresh, IconMap } from './Icons.jsx'; const PSKReporterPanel = ({ callsign, @@ -182,10 +183,10 @@ const PSKReporterPanel = ({ }}> {/* Mode toggle */}
- -
@@ -198,14 +199,14 @@ const PSKReporterPanel = ({ {statusDot && ( {statusDot.char} )} - + }} title="Reconnect to PSKReporter"> )} @@ -241,8 +242,8 @@ const PSKReporterPanel = ({ {/* Map toggle (always visible) */} {handleMapToggle && ( - )}
@@ -252,19 +253,19 @@ const PSKReporterPanel = ({
{panelMode === 'psk' ? ( <> - - ) : ( <> - - @@ -283,7 +284,7 @@ const PSKReporterPanel = ({
) : error && !connected ? (
- Connection failed β€” tap πŸ”„ + Connection failed β€” tap refresh ↻
) : loading && filteredReports.length === 0 && pskFilterCount === 0 ? (
diff --git a/src/components/PropagationPanel.jsx b/src/components/PropagationPanel.jsx index 71e6396..c6bb226 100644 --- a/src/components/PropagationPanel.jsx +++ b/src/components/PropagationPanel.jsx @@ -34,7 +34,7 @@ export const PropagationPanel = ({ propagation, loading, bandConditions }) => { if (loading || !propagation) { return (
-
πŸ“‘ VOACAP
+
βŒ‡ VOACAP
Loading predictions...
@@ -81,7 +81,7 @@ export const PropagationPanel = ({ propagation, loading, bandConditions }) => {
- {viewMode === 'bands' ? 'πŸ“Š BAND CONDITIONS' : 'πŸ“‘ VOACAP'} + {viewMode === 'bands' ? 'β—« BAND CONDITIONS' : 'βŒ‡ VOACAP'} {hasRealData && viewMode !== 'bands' && ●} @@ -143,7 +143,7 @@ export const PropagationPanel = ({ propagation, loading, bandConditions }) => {
{hasRealData - ? `πŸ“‘ ${ionospheric?.source || 'ionosonde'}${ionospheric?.distance ? ` (${ionospheric.distance}km)` : ''}` + ? `βŒ‡ ${ionospheric?.source || 'ionosonde'}${ionospheric?.distance ? ` (${ionospheric.distance}km)` : ''}` : '⚑ estimated' } diff --git a/src/components/SettingsPanel.jsx b/src/components/SettingsPanel.jsx index b0795bf..58f7109 100644 --- a/src/components/SettingsPanel.jsx +++ b/src/components/SettingsPanel.jsx @@ -232,7 +232,7 @@ export const SettingsPanel = ({ isOpen, onClose, config, onSave }) => { fontFamily: 'JetBrains Mono, monospace' }} > - πŸ“‘ Station + βŒ‡ Station
@@ -592,7 +592,7 @@ export const SettingsPanel = ({ isOpen, onClose, config, onSave }) => { {/* Language */}
{LANGUAGES.map((lang) => ( diff --git a/src/components/SolarPanel.jsx b/src/components/SolarPanel.jsx index 6930d06..43c938e 100644 --- a/src/components/SolarPanel.jsx +++ b/src/components/SolarPanel.jsx @@ -7,7 +7,7 @@ import { getMoonPhase } from '../utils/geo.js'; const MODES = ['image', 'indices', 'xray', 'lunar']; const MODE_LABELS = { image: 'SOLAR', indices: 'SOLAR INDICES', xray: 'X-RAY FLUX', lunar: 'LUNAR' }; -const MODE_ICONS = { image: 'πŸ“Š', indices: 'πŸ“ˆ', xray: 'πŸŒ™', lunar: 'β˜€οΈ' }; +const MODE_ICONS = { image: 'β—«', indices: '⊞', xray: '☽', lunar: '☼' }; const MODE_TITLES = { image: 'Show solar indices', indices: 'Show X-ray flux', xray: 'Show lunar phase', lunar: 'Show solar image' }; // Flare class from flux value (W/mΒ²) @@ -389,13 +389,13 @@ export const SolarPanel = ({ solarIndices }) => {
-
πŸŒ‘ New
+
● New
{nextNew}
-
πŸŒ• Full
+
β—‹ Full
{nextFull}
diff --git a/src/components/SpaceWeatherPanel.jsx b/src/components/SpaceWeatherPanel.jsx index 7fa71fd..d0aaca1 100644 --- a/src/components/SpaceWeatherPanel.jsx +++ b/src/components/SpaceWeatherPanel.jsx @@ -15,7 +15,7 @@ export const SpaceWeatherPanel = ({ data, loading }) => { return (
-
β˜€οΈ SPACE WEATHER
+
☼ SPACE WEATHER
{loading ? (
diff --git a/src/components/WorldMap.jsx b/src/components/WorldMap.jsx index 4347b98..848e9d7 100644 --- a/src/components/WorldMap.jsx +++ b/src/components/WorldMap.jsx @@ -13,6 +13,7 @@ import { import { filterDXPaths, getBandColor } from '../utils/callsign.js'; import { getAllLayers } from '../plugins/layerRegistry.js'; +import { IconSatellite, IconTag, IconSun, IconMoon } from './Icons.jsx'; import PluginLayer from './PluginLayer.jsx'; import { DXNewsTicker } from './DXNewsTicker.jsx'; @@ -299,24 +300,24 @@ export const WorldMap = ({ const sunPos = getSunPosition(new Date()); const sunIcon = L.divIcon({ className: 'custom-marker sun-marker', - html: 'β˜€', + html: '☼', iconSize: [24, 24], iconAnchor: [12, 12] }); sunMarkerRef.current = L.marker([sunPos.lat, sunPos.lon], { icon: sunIcon }) - .bindPopup(`β˜€ Subsolar Point
${sunPos.lat.toFixed(2)}°, ${sunPos.lon.toFixed(2)}°`) + .bindPopup(`☼ Subsolar Point
${sunPos.lat.toFixed(2)}Β°, ${sunPos.lon.toFixed(2)}Β°`) .addTo(map); // Moon marker const moonPos = getMoonPosition(new Date()); const moonIcon = L.divIcon({ className: 'custom-marker moon-marker', - html: 'πŸŒ™', + html: '☽', iconSize: [24, 24], iconAnchor: [12, 12] }); moonMarkerRef.current = L.marker([moonPos.lat, moonPos.lon], { icon: moonIcon }) - .bindPopup(`πŸŒ™ Sublunar Point
${moonPos.lat.toFixed(2)}°, ${moonPos.lon.toFixed(2)}°`) + .bindPopup(`☽ Sublunar Point
${moonPos.lat.toFixed(2)}Β°, ${moonPos.lon.toFixed(2)}Β°`) .addTo(map); }, [deLocation, dxLocation]); @@ -480,14 +481,14 @@ export const WorldMap = ({ // Add satellite marker icon const icon = L.divIcon({ className: '', - html: `πŸ›° ${sat.name}`, + html: `β›Š ${sat.name}`, iconSize: null, iconAnchor: [0, 0] }); const marker = L.marker([sat.lat, sat.lon], { icon }) .bindPopup(` - πŸ›° ${sat.name}
+ β›Š ${sat.name}
@@ -777,6 +778,7 @@ export const WorldMap = ({ {onToggleSatellites && ( )} @@ -800,6 +802,7 @@ export const WorldMap = ({ {onToggleDXLabels && showDXPaths && ( )} @@ -865,8 +868,8 @@ export const WorldMap = ({ )}
- β˜€ Sun - πŸŒ™ Moon + ☼ Sun + ☽ Moon
Mode:${sat.mode || 'Unknown'}
Alt:${sat.alt} km