({
version,
buildTime,
initialRepoUrl,
onConnectServer,
}: AppProps)
| 51 | } |
| 52 | |
| 53 | function AppInner({ |
| 54 | version, |
| 55 | buildTime, |
| 56 | initialRepoUrl, |
| 57 | onConnectServer, |
| 58 | }: AppProps) { |
| 59 | const { store } = useStore(); |
| 60 | const { loadGraph } = useGraph(); |
| 61 | const jobService = useJobService(); |
| 62 | const { |
| 63 | state: jobState, |
| 64 | start: startJob, |
| 65 | attach: attachJob, |
| 66 | cancel: cancelJob, |
| 67 | minimize: minimizeJob, |
| 68 | reset: resetJob, |
| 69 | } = useJobStream(jobService); |
| 70 | |
| 71 | // Fix #14 — after a page reload, if the agent is still running an |
| 72 | // index job, attach to it so the user sees the progress indicator |
| 73 | // resume instead of landing on the empty "Add Repository" state. |
| 74 | // Server-mode only; ladybug-backed sessions don't have an agent. |
| 75 | useEffect(() => { |
| 76 | if (!(store instanceof ServerGraphStore)) return; |
| 77 | let cancelled = false; |
| 78 | (async () => { |
| 79 | try { |
| 80 | const active = await store.getActiveIndexJob(); |
| 81 | if (cancelled || !active || active.done) return; |
| 82 | attachJob(active.jobId); |
| 83 | } catch (err) { |
| 84 | console.warn('[App] failed to probe for active index job', err); |
| 85 | } |
| 86 | })(); |
| 87 | return () => { |
| 88 | cancelled = true; |
| 89 | }; |
| 90 | // Only run on mount; attachJob/store identities are stable for a |
| 91 | // mounted session. |
| 92 | // eslint-disable-next-line react-hooks/exhaustive-deps |
| 93 | }, []); |
| 94 | |
| 95 | const graphViewerRef = useRef<GraphViewerHandle>(null); |
| 96 | const [chatHighlightNodes, setChatHighlightNodes] = useState<Set<string>>( |
| 97 | () => new Set(), |
| 98 | ); |
| 99 | const hasRepoParam = useRef( |
| 100 | new URLSearchParams(window.location.search).has('repo'), |
| 101 | ); |
| 102 | |
| 103 | const isNewUser = !localStorage.getItem('ot:hasVisited'); |
| 104 | const [showChat, setShowChat] = useState(!isNewUser); |
| 105 | const [chatWidth, setChatWidth] = useState(480); |
| 106 | const [showSettings, setShowSettings] = useState(false); |
| 107 | const [showHelp, setShowHelp] = useState(isNewUser); |
| 108 | const helpWidth = 380; |
| 109 | const [animationSettings, setAnimationSettings] = useState<AnimationSettings>( |
| 110 | loadAnimationSettings, |
nothing calls this directly
no test coverage detected