| 1 | import { useLayoutEffect, useState } from "react"; |
| 2 | import { |
| 3 | createFileNavigationOwner, |
| 4 | currentFileNavigationOwner, |
| 5 | setFileNavigationOwner, |
| 6 | } from "../lib/fileNavigationCommands"; |
| 7 | import type { FileNavigationOwner } from "../lib/fileNavigationOwner"; |
| 8 | |
| 9 | type Runtime = { owner: FileNavigationOwner; attachment: number }; |
| 10 | |
| 11 | /** |
| 12 | * The navigation owner of this running app instance. The instance is created |
| 13 | * once and registered so the compatibility entry points reach the same records; |
| 14 | * it is disposed when the runtime goes away, which cancels every record, every |
| 15 | * pending open command and every one-shot operation it still held. |
| 16 | */ |
| 17 | export function useFileNavigationRuntime(): FileNavigationOwner { |
| 18 | const [runtime] = useState<Runtime>(() => ({ owner: createFileNavigationOwner(), attachment: 0 })); |
| 19 | useLayoutEffect(() => { |
| 20 | const attachment = ++runtime.attachment; |
| 21 | setFileNavigationOwner(runtime.owner); |
| 22 | // StrictMode reconnects effects synchronously without ending the runtime, |
| 23 | // so only the last attachment may unregister and dispose. |
| 24 | return () => queueMicrotask(() => { |
| 25 | if (runtime.attachment !== attachment) return; |
| 26 | if (currentFileNavigationOwner() === runtime.owner) setFileNavigationOwner(null); |
| 27 | runtime.owner.dispose(); |
| 28 | }); |
| 29 | }, [runtime]); |
| 30 | return runtime.owner; |
| 31 | } |
| 32 |