// The part of the URL after the page — #/grid/services/ — is that page's selection: // which unit, which job, which folder. Reload keeps it and a link can carry it. import { useCallback, useEffect, useState } from 'react' const viewOf = () => location.hash.split('/')[2] ?? '' // The selection belongs to one page. A page reads it only while the URL is still pointing at // that page: moving from #/grid/services/ssh.service to #/hub/docker/stack:gitea changes the // hash in one step, and the page being left is still mounted for a moment — long enough, before // this, for Services to go and ask grid about a "service" called stack:gitea. const read = (view?: string) => { try { return view !== undefined && viewOf() !== view ? '' : decodeURIComponent(location.hash.split('/').slice(3).join('/')) } catch { return '' } } export function useHashSel(view?: string): [string, (v: string) => void] { const [sel, setSel] = useState(() => read(view)) useEffect(() => { const h = () => setSel(read(view)) window.addEventListener('popstate', h); window.addEventListener('hashchange', h) return () => { window.removeEventListener('popstate', h); window.removeEventListener('hashchange', h) } }, [view]) const set = useCallback((v: string) => { if (view !== undefined && viewOf() !== view) return // the URL has already moved on const base = location.hash.split('/').slice(0, 3).join('/') const want = v ? `${base}/${encodeURIComponent(v)}` : base if (location.hash !== want) history.replaceState(null, '', want) setSel(v) }, [view]) return [sel, set] }