fix: globe clickable after tab switch — deferred init with ResizeObserver
Globe.gl needs non-zero container dimensions for initialization and click handling. With the tab persistence fix (display:none for hidden tabs), the globe container starts at 0×0 when radio isn't the first tab. Added a separate ResizeObserver that detects when the container becomes visible and triggers globe initialization via containerVisible state dependency. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
056024d753
commit
7786d02f86
2 changed files with 52 additions and 7 deletions
|
|
@ -89,6 +89,7 @@ export default function RadioTab({ data }: { data: any }) {
|
|||
const [volume, setVolume] = useState(0.5);
|
||||
const [voiceStats, setVoiceStats] = useState<VoiceStats | null>(null);
|
||||
const [showConnModal, setShowConnModal] = useState(false);
|
||||
const [containerVisible, setContainerVisible] = useState(false);
|
||||
const searchTimeout = useRef<ReturnType<typeof setTimeout>>(undefined);
|
||||
const volumeTimeout = useRef<ReturnType<typeof setTimeout>>(undefined);
|
||||
const selectedGuildRef = useRef(selectedGuild);
|
||||
|
|
@ -211,15 +212,47 @@ export default function RadioTab({ data }: { data: any }) {
|
|||
.catch(() => setStationsLoading(false));
|
||||
};
|
||||
|
||||
// ── Watch container visibility (detects tab becoming active) ──
|
||||
useEffect(() => {
|
||||
const el = containerRef.current;
|
||||
if (!el) return;
|
||||
|
||||
// Check immediately
|
||||
if (el.clientWidth > 0 && el.clientHeight > 0) {
|
||||
setContainerVisible(true);
|
||||
}
|
||||
|
||||
const observer = new ResizeObserver((entries) => {
|
||||
for (const entry of entries) {
|
||||
const { width, height } = entry.contentRect;
|
||||
if (width > 0 && height > 0) {
|
||||
setContainerVisible(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
observer.observe(el);
|
||||
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
|
||||
// ── Initialize globe ──
|
||||
useEffect(() => {
|
||||
if (!containerRef.current || places.length === 0) return;
|
||||
|
||||
// If container is hidden (display:none), wait for it to become visible
|
||||
const cw = containerRef.current.clientWidth;
|
||||
const ch = containerRef.current.clientHeight;
|
||||
|
||||
if (globeRef.current) {
|
||||
globeRef.current.pointsData(places);
|
||||
// Re-apply dimensions in case we were hidden during init
|
||||
if (cw > 0 && ch > 0) globeRef.current.width(cw).height(ch);
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't initialize globe with zero dimensions — containerVisible will re-trigger
|
||||
if (cw === 0 || ch === 0) return;
|
||||
|
||||
// Read accent color from theme
|
||||
const initStyle = getComputedStyle(containerRef.current.parentElement!);
|
||||
const initRgb = initStyle.getPropertyValue('--accent-rgb').trim() || '230, 126, 34';
|
||||
|
|
@ -286,21 +319,28 @@ export default function RadioTab({ data }: { data: any }) {
|
|||
|
||||
const onResize = () => {
|
||||
if (containerRef.current && globeRef.current) {
|
||||
globeRef.current
|
||||
.width(containerRef.current.clientWidth)
|
||||
.height(containerRef.current.clientHeight);
|
||||
const w = containerRef.current.clientWidth;
|
||||
const h = containerRef.current.clientHeight;
|
||||
if (w > 0 && h > 0) {
|
||||
globeRef.current.width(w).height(h);
|
||||
}
|
||||
}
|
||||
};
|
||||
window.addEventListener('resize', onResize);
|
||||
|
||||
// ResizeObserver: detects when tab becomes visible (0×0 → real size)
|
||||
const resizeObserver = new ResizeObserver(() => onResize());
|
||||
resizeObserver.observe(el);
|
||||
|
||||
return () => {
|
||||
controls.removeEventListener('change', onControlsChange);
|
||||
el.removeEventListener('mousedown', onInteract);
|
||||
el.removeEventListener('touchstart', onInteract);
|
||||
el.removeEventListener('wheel', onInteract);
|
||||
window.removeEventListener('resize', onResize);
|
||||
resizeObserver.disconnect();
|
||||
};
|
||||
}, [places, pauseRotation]);
|
||||
}, [places, pauseRotation, containerVisible]);
|
||||
|
||||
// ── Play handler ──
|
||||
const handlePlay = useCallback(async (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue