feat(expo-router): add Expo Router support for Screens and navigations and introduce Steps API

Introduce Expo Router integration with a new Screens view and API to surface screens and transitions, plus a new Steps API and UI to depict typed steps from anchors or symbols. Extend codegraph’s extraction and resolution to handle namespace objects (export default NAME, two-statement forms, and default bindings) and React hook bindings for handlers, improving accuracy of flows across JS ↔ native boundaries. Add Swift/React Native bridge receiver evidence (RCT_EXTERN_MODULE, RCT_EXTERN_METHOD) and related resolution logic, with tests covering namespace-object resolution, useCallback-driven handlers, and inline RN event listeners. Update UI to include a Steps tab and associated components (StepsView, StepNode, ScreenEdge) and wire navigation to expose steps-based exploration via /api/steps and UI routes. Documentation and changelog reflect the new Expo Router integration and steps surface capabilities.
This commit is contained in:
Colby McHenry
2026-08-28 09:46:50 -05:00
parent f0eafe31f9
commit 873f133c96
36 changed files with 3711 additions and 73 deletions
+12
View File
@@ -14,6 +14,18 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
### New Features
- **A Steps tab in `codegraph ui` — what happens from here.** Pick a screen (or search any symbol and choose *What happens from here*) and the viewer draws everything it sets in motion as typed steps: the handlers wired to its taps and listeners, the calls that cross into native code, the native events that come back, the store actions it writes, and the calls that leave the app into the network, storage, the device or telemetry — one box per step, an arrow for every way one leads to the next, and on each arrow the condition under which it happens. The plumbing between two steps (hooks, helpers, the components in between) is folded into the arrow and listed in the side panel, exactly as the Screens tab folds a tap's chain into one transition. Any step is the next anchor, any link opens as a Flow strip, a cap the walk hit is announced on the step it hit it at, and the picture travels in the URL. React Native + Expo apps get the full picture today; any project gets handlers, stores and calls that leave the index.
- **React Native apps: Swift native modules and their events connect end to end.** A JS call like `captureView.finalizeCaptureSession()` — where `captureView` is bound to `NativeModules.CaptureView` and the module is a Swift class exposed through an `RCT_EXTERN_MODULE` shim — now resolves to the Swift method itself instead of stopping at the constant, so `codegraph_explore`, the Flow strip and the Steps view follow the code into native. Native → JS events now also land on listeners written inline (`addListener('onZipComplete', (data) => { … })`), attributed to the component that registers them. Re-index after upgrading to pick the new edges up.
### Fixes
- **React handlers written with `useCallback` are now symbols.** `const handleSubmit = useCallback(() => {…}, [])` — the way nearly every handler in a React or React Native component is written — is extracted as a function named by its binding (also `React.useCallback`, `useEffectEvent`), so `onPress={handleSubmit}` and `addListener('x', handleSubmit)` resolve to it, its calls are its own rather than the component's, and a tap's handler shows up in `codegraph_explore`, the Screens tab and the Steps tab. A JSX attribute value (`onPress={handleSubmit}`, `renderItem={renderRow}`) and a handler a hook hands back in an object (`return { handleSubmit, handleRetake }`) are now function-as-value references from the component or hook, so the graph knows which functions are wired as handlers.
- **Stores exported on a later line are read like any other.** `const useStore = create((set, get) => ({ … }))` followed by `export default useStore` (or `export { useStore }`) now has its actions extracted as functions, the same as an `export const` store — previously the two-statement form, common in React Native apps, left every action invisible.
- **API objects exported as a default namespace resolve through to their functions.** `import Api from './api'` + `Api.upload()` where the module ends in `const Api = { upload, createFolder }; export default Api` now links the call to `upload` itself (through the object's own imports), and a default import of any const named by an `export default NAME` statement finds that const rather than guessing the file's first exported function.
- **A Screens tab in `codegraph ui` — the app the way its user meets it.** One box per screen, an arrow for every way of getting from one to another, and on each arrow the condition under which it happens. Click a screen and each of its transitions is labelled beside the screen at the other end of the line with the last condition checked before it happens — `→ isCollected` above `/object-detail` — laid out so that no two labels overlap and none sits under a line; hover a label, a line, or its row in the side panel for the whole condition and the chain the tap travels through (`HomeSearchResults → ItemCard → openObjectDetail`), with a link to each navigation call. A screen that returns to where it came from is drawn around the boxes rather than through them, shared chrome (a top bar rendered on ten screens) is one node a row above what it opens rather than the same arrows from every box, a screen that opens many others is wide enough to follow each line back to it and its lines take separate paths through the gap so they fan out instead of stacking, hovering picks the line nearest the pointer, and a helper that chooses the destination after login shows its fork. Projects whose graph holds screen navigation land on this tab. Expo Router apps today.
- **The Map covers a multi-root project.** A React Native app's `ios/` beside its `src/` — or any second root holding a fifth of the code — is now on the picture, one level deeper, instead of the map silently drawing only the larger root.