feat(watchlist): dockable in the Main tab; sticky filters; Needed-only hides worked lines
The watchlist joins the Main-tab pane list (Settings → Main view), rendered in a card like the other docked panels. The three filters persist across tab switches — the component unmounts on every switch, and filters that reset each time are filters nobody trusts. Needed-only now hides the worked SPOT LINES as well as the all-worked cards, which is DXHunter's own Not-Worked behaviour and the reported complaint: a filter that says needed and still lists five green Worked rows answers a different question than the one asked. The add-row checkbox is relabelled 'as contest' — it marks the entry being ADDED, and read as a filter beside the All/DX/Contest buttons it looked redundant.
This commit is contained in:
@@ -2018,7 +2018,7 @@ export default function App() {
|
||||
// so it's loaded async on mount and re-read on profile:changed below.
|
||||
// 'none' is only ever stored for the third and fourth panes: the first two are
|
||||
// the Main view, and a layout with no panes at all is not a layout.
|
||||
type MainPaneKind = 'map1' | 'map2' | 'cluster' | 'worked' | 'flex' | 'recent' | 'icom' | 'yaesu' | 'elecraft' | 'tci' | 'netcontrol' | 'decodes' | 'none';
|
||||
type MainPaneKind = 'map1' | 'map2' | 'cluster' | 'worked' | 'flex' | 'recent' | 'icom' | 'yaesu' | 'elecraft' | 'tci' | 'netcontrol' | 'decodes' | 'watchlist' | 'none';
|
||||
const [mapZoomSignal, setMapZoomSignal] = useState(0); // bump → world map auto-zooms now
|
||||
const [mainPaneLeft, setMainPaneLeft] = useState<MainPaneKind>('map1');
|
||||
const [mainPaneRight, setMainPaneRight] = useState<MainPaneKind>('map2');
|
||||
@@ -2029,7 +2029,7 @@ export default function App() {
|
||||
// quarter-width map is unreadable.
|
||||
const [mainLayout4, setMainLayout4] = useState<'cols' | 'quad'>('quad');
|
||||
const loadMainPanes = useCallback(async () => {
|
||||
const valid = (v: string): v is MainPaneKind => v === 'map1' || v === 'map2' || v === 'cluster' || v === 'worked' || v === 'flex' || v === 'recent' || v === 'icom' || v === 'yaesu' || v === 'elecraft' || v === 'tci' || v === 'netcontrol' || v === 'decodes';
|
||||
const valid = (v: string): v is MainPaneKind => v === 'map1' || v === 'map2' || v === 'cluster' || v === 'worked' || v === 'flex' || v === 'recent' || v === 'icom' || v === 'yaesu' || v === 'elecraft' || v === 'tci' || v === 'netcontrol' || v === 'decodes' || v === 'watchlist';
|
||||
const [l, r, p3, p4, lay] = await Promise.all([
|
||||
GetUIPref('mainPaneLeft').catch(() => ''),
|
||||
GetUIPref('mainPaneRight').catch(() => ''),
|
||||
@@ -6339,6 +6339,13 @@ export default function App() {
|
||||
<IcomPanel isNetwork={catBackend === 'icom-net'} onReportRST={(r) => { setRstSent(r); rstUserEditedRef.current = true; }} />
|
||||
</div>
|
||||
);
|
||||
case 'watchlist':
|
||||
return (
|
||||
<div className="h-full w-full min-h-0 flex flex-col bg-card border border-border rounded-lg overflow-hidden">
|
||||
<WatchlistTab spots={spots} spotStatus={spotStatus}
|
||||
onSpotSelect={handleSpotSelect} onSpotClick={handleSpotClick} />
|
||||
</div>
|
||||
);
|
||||
case 'netcontrol':
|
||||
return (
|
||||
<div className="h-full w-full min-h-0 flex flex-col rounded-lg overflow-hidden border border-border">
|
||||
|
||||
Reference in New Issue
Block a user