Merge pull request #86 from ThePangel/main

Added the ability to resize the callsign.
pull/95/head
accius 1 day ago committed by GitHub
commit 94275d5ca5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -19,7 +19,7 @@ export const Header = ({
isFullscreen
}) => {
return (
<div style={{
<div style={{
gridColumn: '1 / -1',
display: 'flex',
flexWrap: 'nowrap',
@ -35,8 +35,12 @@ export const Header = ({
}}>
{/* Callsign & Settings */}
<div style={{ display: 'flex', alignItems: 'center', gap: '12px', flexShrink: 0 }}>
<span
style={{ fontSize: '22px', fontWeight: '900', color: 'var(--accent-amber)', cursor: 'pointer', fontFamily: 'Orbitron, monospace', whiteSpace: 'nowrap' }}
<span
style={{
fontSize: config.callsignSize > 0.1 && config.callsignSize <= 2
? `${22 * config.callsignSize}px`
: "22px", fontWeight: '900', color: 'var(--accent-amber)', cursor: 'pointer', fontFamily: 'Orbitron, monospace', whiteSpace: 'nowrap'
}}
onClick={onSettingsClick}
title="Click for settings"
>
@ -44,37 +48,37 @@ export const Header = ({
</span>
{config.version && <span style={{ fontSize: '11px', color: 'var(--text-muted)' }}>v{config.version}</span>}
</div>
{/* UTC Clock */}
<div style={{ display: 'flex', alignItems: 'center', gap: '6px', flexShrink: 0 }}>
<span style={{ fontSize: '13px', color: 'var(--accent-cyan)', fontWeight: '600' }}>UTC</span>
<span style={{
fontSize: '24px',
fontWeight: '700',
color: 'var(--accent-cyan)',
<span style={{
fontSize: '24px',
fontWeight: '700',
color: 'var(--accent-cyan)',
fontFamily: 'JetBrains Mono, Consolas, monospace',
whiteSpace: 'nowrap'
}}>{utcTime}</span>
<span style={{ fontSize: '12px', color: 'var(--text-muted)', whiteSpace: 'nowrap' }}>{utcDate}</span>
</div>
{/* Local Clock - Clickable to toggle 12/24 hour format */}
<div
<div
style={{ display: 'flex', alignItems: 'center', gap: '6px', cursor: 'pointer', flexShrink: 0 }}
onClick={onTimeFormatToggle}
title={`Click to switch to ${use12Hour ? '24-hour' : '12-hour'} format`}
>
<span style={{ fontSize: '13px', color: 'var(--accent-amber)', fontWeight: '600' }}>LOCAL</span>
<span style={{
fontSize: '24px',
fontWeight: '700',
color: 'var(--accent-amber)',
<span style={{
fontSize: '24px',
fontWeight: '700',
color: 'var(--accent-amber)',
fontFamily: 'JetBrains Mono, Consolas, monospace',
whiteSpace: 'nowrap'
}}>{localTime}</span>
<span style={{ fontSize: '12px', color: 'var(--text-muted)', whiteSpace: 'nowrap' }}>{localDate}</span>
</div>
{/* Weather & Solar Stats */}
<div style={{ display: 'flex', gap: '12px', fontSize: '13px', fontFamily: 'JetBrains Mono, Consolas, monospace', whiteSpace: 'nowrap', flexShrink: 0 }}>
{localWeather?.data && (() => {
@ -85,12 +89,12 @@ export const Header = ({
const tempC = Math.round(rawC);
const windLabel = localWeather.data.windUnit || 'mph';
return (
<div title={`${localWeather.data.description} • Wind: ${localWeather.data.windSpeed} ${windLabel}`}>
<span style={{ marginRight: '3px' }}>{localWeather.data.icon}</span>
<span style={{ color: 'var(--accent-cyan)', fontWeight: '600' }}>
{tempF}°F/{tempC}°C
</span>
</div>
<div title={`${localWeather.data.description} • Wind: ${localWeather.data.windSpeed} ${windLabel}`}>
<span style={{ marginRight: '3px' }}>{localWeather.data.icon}</span>
<span style={{ color: 'var(--accent-cyan)', fontWeight: '600' }}>
{tempF}°F/{tempC}°C
</span>
</div>
);
})()}
<div>
@ -108,7 +112,7 @@ export const Header = ({
<span style={{ color: 'var(--accent-cyan)', fontWeight: '700' }}>{spaceWeather?.data?.sunspotNumber || '--'}</span>
</div>
</div>
{/* Settings & Fullscreen Buttons */}
<div style={{ display: 'flex', gap: '6px', flexShrink: 0 }}>
<a
@ -116,17 +120,17 @@ export const Header = ({
target="_blank"
rel="noopener noreferrer"
style={{
background: 'linear-gradient(135deg, #ff813f 0%, #ffdd00 100%)',
background: 'linear-gradient(135deg, #ff813f 0%, #ffdd00 100%)',
border: 'none',
padding: '6px 10px',
borderRadius: '4px',
padding: '6px 10px',
borderRadius: '4px',
color: '#000',
fontSize: '12px',
fontSize: '12px',
cursor: 'pointer',
fontWeight: '600',
fontWeight: '600',
textDecoration: 'none',
display: 'flex',
alignItems: 'center',
display: 'flex',
alignItems: 'center',
gap: '3px',
whiteSpace: 'nowrap'
}}
@ -136,13 +140,13 @@ export const Header = ({
</a>
<button
onClick={onSettingsClick}
style={{
background: 'var(--bg-tertiary)',
border: '1px solid var(--border-color)',
padding: '6px 10px',
borderRadius: '4px',
color: 'var(--text-secondary)',
fontSize: '12px',
style={{
background: 'var(--bg-tertiary)',
border: '1px solid var(--border-color)',
padding: '6px 10px',
borderRadius: '4px',
color: 'var(--text-secondary)',
fontSize: '12px',
cursor: 'pointer',
whiteSpace: 'nowrap'
}}
@ -151,19 +155,19 @@ export const Header = ({
</button>
<button
onClick={onFullscreenToggle}
style={{
background: isFullscreen ? 'rgba(0, 255, 136, 0.15)' : 'var(--bg-tertiary)',
border: `1px solid ${isFullscreen ? 'var(--accent-green)' : 'var(--border-color)'}`,
padding: '6px 10px',
borderRadius: '4px',
color: isFullscreen ? 'var(--accent-green)' : 'var(--text-secondary)',
fontSize: '12px',
style={{
background: isFullscreen ? 'rgba(0, 255, 136, 0.15)' : 'var(--bg-tertiary)',
border: `1px solid ${isFullscreen ? 'var(--accent-green)' : 'var(--border-color)'}`,
padding: '6px 10px',
borderRadius: '4px',
color: isFullscreen ? 'var(--accent-green)' : 'var(--text-secondary)',
fontSize: '12px',
cursor: 'pointer',
whiteSpace: 'nowrap'
}}
title={isFullscreen ? "Exit Fullscreen (Esc)" : "Enter Fullscreen"}
>
{isFullscreen
{isFullscreen
? <><IconShrink size={12} style={{ verticalAlign: 'middle', marginRight: '4px' }} />Exit</>
: <><IconExpand size={12} style={{ verticalAlign: 'middle', marginRight: '4px' }} />Full</>
}

@ -9,6 +9,7 @@ import { LANGUAGES } from '../lang/i18n.js';
export const SettingsPanel = ({ isOpen, onClose, config, onSave }) => {
const [callsign, setCallsign] = useState(config?.callsign || '');
const [callsignSize, setCallsignSize] = useState(config?.callsignSize || 1.0);
const [gridSquare, setGridSquare] = useState('');
const [lat, setLat] = useState(config?.location?.lat || 0);
const [lon, setLon] = useState(config?.location?.lon || 0);
@ -17,7 +18,7 @@ export const SettingsPanel = ({ isOpen, onClose, config, onSave }) => {
const [timezone, setTimezone] = useState(config?.timezone || '');
const [dxClusterSource, setDxClusterSource] = useState(config?.dxClusterSource || 'dxspider-proxy');
const { t, i18n } = useTranslation();
// Layer controls
const [layers, setLayers] = useState([]);
const [activeTab, setActiveTab] = useState('station');
@ -25,6 +26,7 @@ export const SettingsPanel = ({ isOpen, onClose, config, onSave }) => {
useEffect(() => {
if (config) {
setCallsign(config.callsign || '');
setCallsignSize(config.callsignSize || 1.0)
setLat(config.location?.lat || 0);
setLon(config.location?.lon || 0);
setTheme(config.theme || 'dark');
@ -70,22 +72,22 @@ export const SettingsPanel = ({ isOpen, onClose, config, onSave }) => {
const parseGridSquare = (grid) => {
grid = grid.toUpperCase();
if (grid.length < 4) return null;
const lon1 = (grid.charCodeAt(0) - 65) * 20 - 180;
const lat1 = (grid.charCodeAt(1) - 65) * 10 - 90;
const lon2 = parseInt(grid[2]) * 2;
const lat2 = parseInt(grid[3]) * 1;
let lon = lon1 + lon2 + 1;
let lat = lat1 + lat2 + 0.5;
if (grid.length >= 6) {
const lon3 = (grid.charCodeAt(4) - 65) * (2/24);
const lat3 = (grid.charCodeAt(5) - 65) * (1/24);
lon = lon1 + lon2 + lon3 + (1/24);
lat = lat1 + lat2 + lat3 + (1/48);
}
return { lat, lon };
};
@ -116,17 +118,17 @@ export const SettingsPanel = ({ isOpen, onClose, config, onSave }) => {
if (window.hamclockLayerControls) {
const layer = layers.find(l => l.id === layerId);
const newEnabledState = !layer.enabled;
// Update the control
window.hamclockLayerControls.toggleLayer(layerId, newEnabledState);
// Force immediate UI update
setLayers(prevLayers =>
prevLayers.map(l =>
setLayers(prevLayers =>
prevLayers.map(l =>
l.id === layerId ? { ...l, enabled: newEnabledState } : l
)
);
// Refresh after a short delay to get the updated state
setTimeout(() => {
if (window.hamclockLayerControls) {
@ -147,6 +149,7 @@ export const SettingsPanel = ({ isOpen, onClose, config, onSave }) => {
onSave({
...config,
callsign: callsign.toUpperCase(),
callsignSize: callsignSize,
location: { lat: parseFloat(lat), lon: parseFloat(lon) },
theme,
layout,
@ -198,8 +201,8 @@ export const SettingsPanel = ({ isOpen, onClose, config, onSave }) => {
maxHeight: '90vh',
overflowY: 'auto'
}}>
<h2 style={{
color: 'var(--accent-cyan)',
<h2 style={{
color: 'var(--accent-cyan)',
marginTop: 0,
marginBottom: '24px',
textAlign: 'center',
@ -302,6 +305,35 @@ export const SettingsPanel = ({ isOpen, onClose, config, onSave }) => {
/>
</div>
{/* Callsign Size*/}
<div style={{ marginBottom: '20px'}}>
<div>
<label style={{ display: 'block', marginBottom: '6px', color: 'var(--text-muted)', fontSize: '11px', textTransform: 'uppercase' }}>
{t('station.settings.callsignSize')}
</label>
<input
type="number"
step="0.1"
value={isNaN(lat) ? '' : callsignSize}
onChange={(e) => {
if (e.target.value >= 0.1 && e.target.value <= 2.0) {
setCallsignSize(e.target.value)
}}}
style={{
width: '100%',
padding: '10px',
background: 'var(--bg-tertiary)',
border: '1px solid var(--border-color)',
borderRadius: '6px',
color: 'var(--text-primary)',
fontSize: '14px',
fontFamily: 'JetBrains Mono, monospace',
boxSizing: 'border-box'
}}
/>
</div>
</div>
{/* Grid Square */}
<div style={{ marginBottom: '20px' }}>
<label style={{ display: 'block', marginBottom: '6px', color: 'var(--text-muted)', fontSize: '11px', textTransform: 'uppercase', letterSpacing: '1px' }}>
@ -601,15 +633,15 @@ export const SettingsPanel = ({ isOpen, onClose, config, onSave }) => {
onClick={() => i18n.changeLanguage(lang.code)}
style={{
padding: '8px 6px',
background: i18n.language === lang.code || (i18n.language && i18n.language.startsWith(lang.code))
? 'rgba(0, 221, 255, 0.2)'
background: i18n.language === lang.code || (i18n.language && i18n.language.startsWith(lang.code))
? 'rgba(0, 221, 255, 0.2)'
: 'var(--bg-tertiary)',
border: `1px solid ${i18n.language === lang.code || (i18n.language && i18n.language.startsWith(lang.code))
? 'var(--accent-cyan)'
? 'var(--accent-cyan)'
: 'var(--border-color)'}`,
borderRadius: '6px',
color: i18n.language === lang.code || (i18n.language && i18n.language.startsWith(lang.code))
? 'var(--accent-cyan)'
? 'var(--accent-cyan)'
: 'var(--text-secondary)',
fontSize: '12px',
cursor: 'pointer',

@ -14,6 +14,7 @@
"station.settings.button.save": "Save Settings",
"station.settings.button.save.confirm": "Settings saved to your browser",
"station.settings.callsign": "Your Callsign",
"station.settings.callsignSize": "Your Callsign's size",
"station.settings.describe": "Enter your callsign and grid square to get started. Settings are saved in your browser.",
"station.settings.dx.describe": "→ Real-time DX Spider feed via our dedicated proxy service",
"station.settings.dx.option1": "⭐ DX Spider Proxy (Recommended)",

@ -14,6 +14,7 @@
"station.settings.button.save": "Guardar Configuración",
"station.settings.button.save.confirm": "La configuración se guarda en tu navegador",
"station.settings.callsign": "Tu Indicativo",
"station.settings.callsignSize": "El tamaño de tu Indicativo",
"station.settings.describe": "Ingresa tu indicativo y cuadrícula para comenzar. Tu configuración se guardará en el navegador.",
"station.settings.dx.describe": "→ Feed en tiempo real de DX Spider a través de nuestro servicio proxy dedicado",
"station.settings.dx.option1": "⭐ Proxy DX Spider (Recomendado)",

@ -10,6 +10,7 @@
export const DEFAULT_CONFIG = {
callsign: 'N0CALL',
callsignSize: 1.0, // Float multiplies base px size (0.1 to 2.0)
locator: '',
location: { lat: 40.0150, lon: -105.2705 }, // Boulder, CO (default)
defaultDX: { lat: 35.6762, lon: 139.6503 }, // Tokyo

Loading…
Cancel
Save

Powered by TurnKey Linux.