fix(panels): bypass GoTrueClient lock — expose accessToken via AuthContext, gate panels on auth

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]>
This commit is contained in:
2026-05-25 15:06:51 +01:00
co-authored by Claude Sonnet 4.6
parent 5284d30f84
commit 6bd85671d2
3 changed files with 27 additions and 10 deletions
@@ -1,4 +1,5 @@
import React, { useEffect, useRef, useState } from "react";
import { useAuth } from "../../../../../contexts/AuthContext";
import { Mic as MicIcon, Stop as StopIcon, History as HistoryIcon, Settings as SettingsIcon, AutoAwesome as AutoAwesomeIcon, NotificationsActive as KeywordIcon, Close } from "@mui/icons-material";
import { useTranscriptionStore, TranscriptionSegment, TranscriptionSession, TimetablePeriod, KeywordWatch, KeywordMatch, ServerSegment } from "../../../../../stores/transcriptionStore";
import { TranscriptionService } from "../../../cc-base/cc-transcription/transcriptionService";
@@ -92,6 +93,7 @@ export const CCTranscriptionPanel: React.FC = () => {
// Modal state
const [showSettingsModal, setShowSettingsModal] = useState(false);
const { user: authUser } = useAuth();
const [showSummaryModal, setShowSummaryModal] = useState(false);
const [summaryType, setSummaryType] = useState('full_lesson');
@@ -99,11 +101,13 @@ export const CCTranscriptionPanel: React.FC = () => {
const [newKeyword, setNewKeyword] = useState('');
const [isAddingKeyword, setIsAddingKeyword] = useState(false);
// Load sessions and keyword watches on mount
// Load sessions when auth is confirmed (avoids GoTrueClient lock on mount)
useEffect(() => {
loadSessions().then(setSessions);
loadKeywordWatches();
}, []);
if (authUser?.id) {
loadSessions().then(setSessions);
loadKeywordWatches();
}
}, [authUser?.id]);
// Auto-detect timetable context on mount
useEffect(() => {