- SchoolOnboardingWizard.tsx: new 3-step wizard (GAIS search → confirm →
calendar setup) triggered from the nav panel school section when no school
is linked. Calls GET /school/search for live school lookup and
POST /school/register to create the institute record.
- CCGraphNavPanel.tsx: add showOnboard button for no_school state,
onOnboardSchool context action, wire up SchoolOnboardingWizard state.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
navigationStore: rewritten off Neo4j db names — Supabase whiteboard_rooms table,
setAuthInfo(token, userId) pattern, auto-creates default room per context on first use
snapshotService: rewritten to Supabase Storage REST (/storage/v1/object/authenticated/cc.users/…),
setAccessToken() instance method, static methods take accessToken not dbName
AuthContext/NeoUserContext: auth injected into nav store, no Neo4j db names required
singlePlayerPage: loadNodeData no longer calls Neo4j; snapshot wired via accessToken
navigation types: NeoGraphNode updated for Supabase-backed tree structure
transcriptionStore/Service: getSession() removed, accessToken via AuthContext
LLMConfigModal: auth context wiring fixes
GraphNavigator/GraphSidebar: updated nav components
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Same GoTrueClient lock contention fix as CCFilesPanel:
- transcriptionStore: add _accessToken/_userId state + setAuthInfo() action;
replace all 6 getSession() calls (startSession, flushCanvasEvents, loadSessions,
loadKeywordWatches, addKeywordWatch, deleteKeywordWatch, checkSegmentForKeywords)
with stored values — zero getSession() calls remain in the store
- CCTranscriptionPanel: destructure accessToken from useAuth; sync both values into
store via setAuthInfo() on every auth change; gate loadSessions on authUser.id
- CCCabinetsPanel: same pattern as CCFilesPanel — useAuth for token, useCallback on
apiFetch/loadCabinets, gate effect on authUser.id
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Root cause: apiFetch called supabase.auth.getSession() on every API request, acquiring
the GoTrueClient internal lock. On refresh, concurrent mount of panels caused lock
contention — the loadCabinets/loadSessions fetch awaits hung, loading spinner never
cleared.
- AuthContext: add accessToken state, set/clear it alongside user on all auth events
- CCFilesPanel: apiFetch reads accessToken from AuthContext (no lock), loadCabinets
effect gated on authUser.id (fires only after SIGNED_IN, session guaranteed valid)
- CCTranscriptionPanel: loadSessions effect gated on authUser.id for same reason
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- transcriptionStore: replace all supabase.auth.getUser() with getSession() so session
restoration on page refresh does not race against GoTrue network validation
- CCFilesPanel: remove selectedCabinet from loadCabinets useCallback deps; use
initialSelectionDone ref to prevent double-call on first mount
- CCTranscriptionPanel: replace hardcoded LAN IP with VITE_API_URL env var
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- transcriptionService: track finalizedSegmentCount so only newly-final
segments are emitted per WS message (was re-processing full array each
time, causing the live segment to freeze in the completed list)
- transcriptionStore: saveSegment isFinal branch now appends the passed
text directly instead of currentSegment (currentSegment was stale
relative to the incoming final)
- CCTranscriptionPanel: record button colour changed from var(--color-text)
to explicit #2563eb so it is visible in dark mode; completed segment
backgrounds changed from hardcoded #fff to var(--color-muted) so text
is readable in both themes; keyword Add button gets same blue fix
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
BasePanel reads PANEL_DIMENSIONS[currentPanelType] to get the panel
dimensions (topOffset, bottomOffset, width). The transcription panel
type was added to the panel list and render switch during CIS Phase 3C
but was never added to PANEL_DIMENSIONS. This caused a crash whenever
the BasePanel rendered with the transcription tab active:
PANEL_DIMENSIONS["transcription"] === undefined
undefined.topOffset → TypeError: Cannot read properties of undefined
This crash appeared as a topOffset error anywhere a Tldraw canvas was
rendered (singlePlayerPage, multiplayerUser, etc.).
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- KeywordWatch and KeywordMatch interfaces in transcriptionStore
- loadKeywordWatches, addKeywordWatch, deleteKeywordWatch actions via API with JWT auth
- checkSegmentForKeywords: client-side detection on each final segment, logs events to backend
- clearKeywordMatches: resets session-scoped match list
- Keywords tab in CCTranscriptionPanel: add/delete watches, match log with timestamp
- Match count badge on Keywords tab when hits exist during recording
- Also fixes missing Close import that was present in summary modal
- Connect transcriptionStore to Supabase (start/stop session, save segments)
- Add CanvasEventLogger for silent TLDraw activity tracking
- Add Sessions tab to CCTranscriptionPanel with past sessions list
- Auto-detect timetable context on panel mount
- Flush canvas events to API every 5 seconds during recording
- Add CCTranscriptionPanel component with Live tab
- Add Zustand transcriptionStore for session state management
- Wire panel into BasePanel sidebar system
- Fix merged switch cases in getIconForPanel, getDescriptionForPanel, renderCurrentPanel
- Add VITE_WHISPERLIVE_URL to .env