feat: Ctrl+Up/Down hops spot-to-spot on the Main-view band map
Add a keyNav prop to BandMap: when set (only the docked Main-view map, not the multi-band Band Map tab), Ctrl+ArrowUp / Ctrl+ArrowDown selects the next in-band spot above / below the rig frequency and tunes to it via the existing spot-click handler. Higher freq is up on the map (freqToY), so Up = next higher spot. Ignored while typing in an input. Changelog 0.21.1.
This commit is contained in:
@@ -5320,6 +5320,7 @@ export default function App() {
|
||||
currentFreqHz={band && freqMhz ? Math.round(parseFloat(freqMhz) * 1_000_000) : 0}
|
||||
onSpotClick={handleSpotClick}
|
||||
onClose={() => setBandMapShown(false)}
|
||||
keyNav
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -41,6 +41,10 @@ interface Props {
|
||||
// globally from the band-map tab toolbar.
|
||||
hideDigital?: boolean;
|
||||
fitToBand?: boolean;
|
||||
// keyNav enables Ctrl+↑ / Ctrl+↓ to hop to the next spot above / below the rig
|
||||
// frequency (and tune to it). Only the docked Main-view band map sets this, so
|
||||
// the multi-band Band Map tab (several maps) doesn't fight over the shortcut.
|
||||
keyNav?: boolean;
|
||||
}
|
||||
|
||||
const BAND_RANGES: Record<string, [number, number]> = {
|
||||
@@ -153,7 +157,7 @@ const BOT_PAD = 14; // the top-most freq label isn't clipped at y=0
|
||||
// last; ties broken by closeness to the rig freq).
|
||||
const MAX_VISIBLE_SPOTS = 30;
|
||||
|
||||
export function BandMap({ band, spots, spotStatus, currentFreqHz, onSpotClick, onClose, side = 'right', onToggleSide, hideDigital = false, fitToBand = false }: Props) {
|
||||
export function BandMap({ band, spots, spotStatus, currentFreqHz, onSpotClick, onClose, side = 'right', onToggleSide, hideDigital = false, fitToBand = false, keyNav = false }: Props) {
|
||||
const { t } = useI18n();
|
||||
const range = BAND_RANGES[band];
|
||||
const segments = SEGMENT_COLORS[band] ?? [];
|
||||
@@ -362,6 +366,38 @@ export function BandMap({ band, spots, spotStatus, currentFreqHz, onSpotClick, o
|
||||
scrollerRef.current.scrollTop = Math.max(0, y - containerH / 2);
|
||||
}
|
||||
|
||||
// Ctrl+↑ / Ctrl+↓ hop to the next spot above / below the rig frequency and tune
|
||||
// to it. Higher freq is UP on the map (see freqToY), so ↑ = next higher spot.
|
||||
// Only active on the docked Main-view map (keyNav) and ignored while typing.
|
||||
useEffect(() => {
|
||||
if (!keyNav) return;
|
||||
const onKey = (e: KeyboardEvent) => {
|
||||
if (!e.ctrlKey || e.altKey || e.metaKey) return;
|
||||
if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return;
|
||||
const ae = document.activeElement as HTMLElement | null;
|
||||
const tag = (ae?.tagName || '').toLowerCase();
|
||||
if (tag === 'input' || tag === 'textarea' || tag === 'select' || ae?.isContentEditable) return;
|
||||
const list = spots
|
||||
.filter((s) => (s.band ?? '') === band && s.freq_hz > 0)
|
||||
.slice()
|
||||
.sort((a, b) => a.freq_hz - b.freq_hz);
|
||||
if (!list.length) return;
|
||||
const cur = currentFreqHz || (lo + hi) * 500; // mid-band kHz→Hz when no rig freq
|
||||
const EPS = 50; // Hz, so we don't re-pick the spot we're already sitting on
|
||||
let target: Spot | undefined;
|
||||
if (e.key === 'ArrowUp') {
|
||||
target = list.find((s) => s.freq_hz > cur + EPS);
|
||||
} else {
|
||||
for (let i = list.length - 1; i >= 0; i--) { if (list[i].freq_hz < cur - EPS) { target = list[i]; break; } }
|
||||
}
|
||||
if (!target) return;
|
||||
e.preventDefault();
|
||||
onSpotClick(target);
|
||||
};
|
||||
window.addEventListener('keydown', onKey);
|
||||
return () => window.removeEventListener('keydown', onKey);
|
||||
}, [keyNav, spots, band, currentFreqHz, lo, hi, onSpotClick]);
|
||||
|
||||
const currentKHz = currentFreqHz ? currentFreqHz / 1000 : 0;
|
||||
const showRigPointer = currentKHz >= lo && currentKHz <= hi;
|
||||
const rigY = freqToY(currentKHz);
|
||||
|
||||
Reference in New Issue
Block a user