feat: WSPR v1.5.0 - Add minimize/maximize toggle to all panels

 New Feature - Panel Minimization:
- All 4 control panels can now be minimized/maximized
- Click panel header or toggle button (▼/▶) to collapse/expand
- Minimized panels show only header with ▶ icon
- Expanded panels show full content with ▼ icon
- State persisted to localStorage per panel

🎯 Panels with Minimize:
1. Filter Panel (top-right) - Most useful! Reduces large panel to header
2. Statistics Panel (top-left) - Clean up activity display
3. Legend Panel (bottom-right) - Hide when not needed
4. Band Activity Chart (bottom-left) - Minimize chart view

🎨 UI/UX Improvements:
- Minimize button in header (right-aligned)
- Visual feedback: button opacity changes on hover
- Click header anywhere to toggle (except on controls)
- Click ▼/▶ button to toggle
- Header cursor changes to pointer when minimized
- Smooth transitions
- Icons: ▼ = expanded, ▶ = minimized

🔧 Technical Implementation:
- New addMinimizeToggle() function
- Wraps panel content in .wspr-panel-content div
- Toggle button appended to header
- Persists state to localStorage with '-minimized' suffix
- Loads saved state on panel creation
- CTRL+drag still works when minimized
- Panel positions preserved

💾 State Persistence:
- wspr-filter-position-minimized
- wspr-stats-position-minimized
- wspr-legend-position-minimized
- wspr-chart-position-minimized

🎉 User Benefits:
- Minimize large Filter panel to reduce screen clutter
- Temporarily hide panels without disabling plugin
- Quick access - just click header to restore
- Positions and minimize states both saved
- Clean, unobstructed map view when needed

Version: 1.4.3 → 1.5.0
pull/82/head
trancen 1 day ago
parent 215145dcf1
commit 2a818bd2d0

@ -1,7 +1,7 @@
import { useState, useEffect, useRef } from 'react';
/**
* WSPR Propagation Heatmap Plugin v1.4.3
* WSPR Propagation Heatmap Plugin v1.5.0
*
* Advanced Features:
* - Great circle curved path lines between transmitters and receivers
@ -20,6 +20,7 @@ import { useState, useEffect, useRef } from 'react';
* - Fixed duplicate control creation (v1.4.2)
* - Performance optimizations (v1.4.2)
* - Separate opacity controls for paths and heatmap (v1.4.3)
* - Minimize/maximize toggle for all panels (v1.5.0)
* - Statistics display (total stations, spots)
* - Signal strength legend
*
@ -35,7 +36,7 @@ export const metadata = {
category: 'propagation',
defaultEnabled: false,
defaultOpacity: 0.7,
version: '1.4.3'
version: '1.5.0'
};
// Convert grid square to lat/lon
@ -252,6 +253,95 @@ function makeDraggable(element, storageKey) {
});
}
// Add minimize/maximize functionality to control panels
function addMinimizeToggle(element, storageKey) {
if (!element) return;
const minimizeKey = storageKey + '-minimized';
// Create minimize button
const header = element.querySelector('div:first-child');
if (!header) return;
// Wrap content (everything except header)
const content = Array.from(element.children).slice(1);
const contentWrapper = document.createElement('div');
contentWrapper.className = 'wspr-panel-content';
content.forEach(child => contentWrapper.appendChild(child));
element.appendChild(contentWrapper);
// Add minimize button to header
const minimizeBtn = document.createElement('span');
minimizeBtn.className = 'wspr-minimize-btn';
minimizeBtn.innerHTML = '▼';
minimizeBtn.style.cssText = `
float: right;
cursor: pointer;
user-select: none;
padding: 0 4px;
margin: -2px -4px 0 0;
font-size: 10px;
opacity: 0.7;
transition: opacity 0.2s;
`;
minimizeBtn.title = 'Minimize/Maximize';
minimizeBtn.addEventListener('mouseenter', () => {
minimizeBtn.style.opacity = '1';
});
minimizeBtn.addEventListener('mouseleave', () => {
minimizeBtn.style.opacity = '0.7';
});
header.style.display = 'flex';
header.style.justifyContent = 'space-between';
header.style.alignItems = 'center';
header.appendChild(minimizeBtn);
// Load saved state
const isMinimized = localStorage.getItem(minimizeKey) === 'true';
if (isMinimized) {
contentWrapper.style.display = 'none';
minimizeBtn.innerHTML = '▶';
element.style.cursor = 'pointer';
}
// Toggle function
const toggle = (e) => {
// Don't toggle if CTRL is held (for dragging)
if (e && e.ctrlKey) return;
const isCurrentlyMinimized = contentWrapper.style.display === 'none';
if (isCurrentlyMinimized) {
// Expand
contentWrapper.style.display = 'block';
minimizeBtn.innerHTML = '▼';
element.style.cursor = 'default';
localStorage.setItem(minimizeKey, 'false');
} else {
// Minimize
contentWrapper.style.display = 'none';
minimizeBtn.innerHTML = '▶';
element.style.cursor = 'pointer';
localStorage.setItem(minimizeKey, 'true');
}
};
// Click header to toggle (except on button itself)
header.addEventListener('click', (e) => {
if (e.target === header || e.target.tagName === 'DIV') {
toggle(e);
}
});
// Click button to toggle
minimizeBtn.addEventListener('click', (e) => {
e.stopPropagation();
toggle(e);
});
}
export function useLayer({ enabled = false, opacity = 0.7, map = null }) {
const [pathLayers, setPathLayers] = useState([]);
const [markerLayers, setMarkerLayers] = useState([]);
@ -408,6 +498,7 @@ export function useLayer({ enabled = false, opacity = 0.7, map = null }) {
const container = document.querySelector('.wspr-filter-control');
if (container) {
makeDraggable(container, 'wspr-filter-position');
addMinimizeToggle(container, 'wspr-filter-position');
}
}, 150);
@ -490,7 +581,10 @@ export function useLayer({ enabled = false, opacity = 0.7, map = null }) {
setTimeout(() => {
const container = document.querySelector('.wspr-stats');
if (container) makeDraggable(container, 'wspr-stats-position');
if (container) {
makeDraggable(container, 'wspr-stats-position');
addMinimizeToggle(container, 'wspr-stats-position');
}
}, 150);
// Create legend control
@ -528,7 +622,10 @@ export function useLayer({ enabled = false, opacity = 0.7, map = null }) {
setTimeout(() => {
const container = document.querySelector('.wspr-legend');
if (container) makeDraggable(container, 'wspr-legend-position');
if (container) {
makeDraggable(container, 'wspr-legend-position');
addMinimizeToggle(container, 'wspr-legend-position');
}
}, 150);
// Create band chart control
@ -558,7 +655,10 @@ export function useLayer({ enabled = false, opacity = 0.7, map = null }) {
setTimeout(() => {
const container = document.querySelector('.wspr-chart');
if (container) makeDraggable(container, 'wspr-chart-position');
if (container) {
makeDraggable(container, 'wspr-chart-position');
addMinimizeToggle(container, 'wspr-chart-position');
}
}, 150);
console.log('[WSPR] All controls created once');

Loading…
Cancel
Save

Powered by TurnKey Linux.