refactor(flex): single shared MeterBar so Flex/amp/tuner meters are identical
The FlexRadio panel, AmpCard and TunerCard each carried their own copy of the MeterBar (LED-bar) component. Even small drift between the copies made the tuner meters look slightly off in height/LED size vs the others. Extracted one shared components/MeterBar.tsx (segments, bar height, padding) and imported it in all three, so every meter renders at exactly the same size. No behaviour change.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { Gauge, Radio, ChevronDown } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { MeterBar } from '@/components/MeterBar';
|
||||
import type { TGStatus, TGChannel } from '@/components/TunerGeniusPanel';
|
||||
import { TunerGeniusAutotune, TunerGeniusSetBypass, TunerGeniusSetOperate, TunerGeniusActivate } from '../../wailsjs/go/main/App';
|
||||
|
||||
@@ -9,43 +10,8 @@ import { TunerGeniusAutotune, TunerGeniusSetBypass, TunerGeniusSetOperate, Tuner
|
||||
// mirrors the native app's two channels (A / B) with their source, frequency and
|
||||
// antenna, a live PWR / SWR pair, and the Tune / Bypass / Operate actions. It
|
||||
// drives the backend directly (no local state) — the caller's ~1.5s poll
|
||||
// reconciles the display, just like AmpCard.
|
||||
|
||||
const METER_SEGMENTS = 26;
|
||||
|
||||
function MeterBar({ label, value, unit, lo, hi, accent = '#16a34a', display, segColor }: {
|
||||
label: string; value: number; unit?: string; lo: number; hi: number; accent?: string; display?: string;
|
||||
segColor?: (frac: number) => string;
|
||||
}) {
|
||||
const span = hi - lo;
|
||||
const pct = span > 0 ? Math.max(0, Math.min(100, ((value - lo) / span) * 100)) : 0;
|
||||
const lit = Math.round((pct / 100) * METER_SEGMENTS);
|
||||
return (
|
||||
<div className="rounded-lg border border-border/70 bg-gradient-to-b from-card to-muted/40 shadow-sm min-w-0 px-2.5 py-2">
|
||||
<div className="flex items-baseline justify-between gap-1 mb-1.5">
|
||||
<span className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground truncate">{label}</span>
|
||||
<span className="font-mono font-bold tabular-nums whitespace-nowrap text-foreground/90 text-sm">
|
||||
{display !== undefined ? display : (
|
||||
<>{Math.abs(value) >= 100 ? value.toFixed(0) : value.toFixed(1)}<span className="text-muted-foreground text-[10px] ml-0.5">{unit}</span></>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex gap-[2px] items-stretch rounded-[3px] bg-black/10 p-[2px] h-3">
|
||||
{Array.from({ length: METER_SEGMENTS }).map((_, i) => {
|
||||
const on = i < lit;
|
||||
const frac = i / METER_SEGMENTS;
|
||||
const col = segColor ? segColor(frac) : (frac > 0.82 ? '#dc2626' : accent);
|
||||
return (
|
||||
<div key={i} className="flex-1 rounded-[2px] transition-colors duration-100"
|
||||
style={on
|
||||
? { background: `linear-gradient(to bottom, ${col}, ${col}cc)`, boxShadow: `0 0 4px ${col}88` }
|
||||
: { background: '#cfc6ad', opacity: 0.35 }} />
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// reconciles the display, just like AmpCard. Meters come from the shared MeterBar
|
||||
// so they're the exact same size as the Flex/amp meters.
|
||||
|
||||
function Card({ icon: Icon, title, accent, children, ckey }: { icon: any; title: string; accent?: string; children: React.ReactNode; ckey?: string }) {
|
||||
// Collapsible with persisted state — same behaviour as the FlexRadio panel's Card.
|
||||
|
||||
Reference in New Issue
Block a user