Files
noteflow/.rag/08-typescript-hooks-contexts.md

7.1 KiB

NoteFlow TypeScript Hooks & Contexts

Location

client/src/hooks/ and client/src/contexts/

React Contexts

Connection Context (connection-context.tsx)

gRPC connection state and mode detection.

interface ConnectionHelpers {
  state: ConnectionState;
  mode: ConnectionMode;           // connected | disconnected | cached | mock | reconnecting
  isConnected: boolean;
  isReadOnly: boolean;            // cached | disconnected | mock | reconnecting
  isReconnecting: boolean;
  isSimulating: boolean;          // Simulation mode from preferences
}

// Usage
const { isConnected, isReadOnly, mode } = useConnection();

Workspace Context (workspace-context.tsx)

User and workspace state.

interface WorkspaceContextValue {
  currentWorkspace: Workspace | null;
  workspaces: Workspace[];
  currentUser: GetCurrentUserResponse | null;
  switchWorkspace: (workspaceId: string) => Promise<void>;
  isLoading: boolean;
  error: string | null;
}

// Usage
const { currentWorkspace, currentUser, switchWorkspace } = useWorkspace();

Project Context (project-context.tsx)

Active project and project list.

interface ProjectContextValue {
  projects: Project[];
  activeProject: Project | null;
  switchProject: (projectId: string) => Promise<void>;
  isLoading: boolean;
  error: string | null;
}

// Usage
const { activeProject, projects, switchProject } = useProject();

Storage Context (storage.ts)

Persistent storage utilities.

Hook Organization (Domain Folders)

Audio Hooks (hooks/audio/)

Hook Purpose
use-audio-devices.ts Audio device enumeration and selection
use-audio-devices.helpers.ts Device helper functions
use-audio-devices.types.ts Device type definitions
use-asr-config.ts ASR configuration management
use-streaming-config.ts Streaming configuration
use-audio-testing.ts Audio testing utilities
// use-audio-devices.ts
interface AudioDevice {
  id: string;
  name: string;
  kind: 'input' | 'output';
}

function useAudioDevices(options: UseAudioDevicesOptions): {
  devices: AudioDevice[];
  selectedInput: AudioDevice | null;
  selectedOutput: AudioDevice | null;
  setSelectedInput: (id: string) => void;
  setSelectedOutput: (id: string) => void;
  isLoading: boolean;
}

Auth Hooks (hooks/auth/)

Hook Purpose
use-cloud-consent.ts Cloud AI consent management
use-oauth-flow.ts OAuth authentication flow
use-auth-flow.ts General auth flow
use-oidc-providers.ts OIDC provider management
use-huggingface-token.ts HuggingFace token management
use-secure-integration-secrets.ts Secure secret storage
// use-cloud-consent.ts
function useCloudConsent(): {
  hasConsent: boolean;
  grantConsent: () => Promise<void>;
  revokeConsent: () => Promise<void>;
  isLoading: boolean;
}

Data Hooks (hooks/data/)

Hook Purpose
use-async-data.ts Generic async data loading with retry
use-guarded-mutation.ts Mutation with offline/permissions guard
use-project.ts Project access from context
use-project-members.ts Project membership queries
// use-async-data.ts
const { data, isLoading, error, retry } = useAsyncData(
  () => getAPI().getMeeting({ meeting_id: meetingId }),
  {
    onError: (e) => toast.error(e.message),
    deps: [meetingId],
  }
);

Processing Hooks (hooks/processing/)

Hook Purpose
use-diarization.ts Diarization job lifecycle with polling
use-entity-extraction.ts NER extraction & updates
use-post-processing.ts Post-recording processing state
use-assistant.ts AI assistant interactions
state.ts Processing state management
events.ts Processing event handling
// use-diarization.ts
interface UseDiarizationOptions {
  onComplete?: (status: DiarizationJobStatus) => void;
  onError?: (error: string) => void;
  pollInterval?: number;
  maxRetries?: number;
  showToasts?: boolean;
  autoRecover?: boolean;
}

interface DiarizationState {
  jobId: string | null;
  status: JobStatus | null;
  progress: number;  // 0-100
  error: string | null;
  speakerIds: string[];
  segmentsUpdated: number;
  isActive: boolean;
}

function useDiarization(options?: UseDiarizationOptions): {
  state: DiarizationState;
  start: (meetingId: string, numSpeakers?: number) => Promise<void>;
  cancel: () => Promise<void>;
  reset: () => void;
  recover: () => Promise<DiarizationJobStatus | null>;
}

Recording Hooks (hooks/recording/)

Hook Purpose
use-recording-session.ts Recording session management
use-recording-app-policy.ts App recording policy detection

Sync Hooks (hooks/sync/)

Hook Purpose
use-webhooks.ts Webhook CRUD
use-calendar-sync.ts Calendar integration sync
use-integration-sync.ts Integration sync state polling
use-integration-validation.ts Integration config validation
use-preferences-sync.ts Preferences synchronization
use-meeting-reminders.ts Meeting reminder notifications
sync-notifications.ts Sync notification handling

UI Hooks (hooks/ui/)

Hook Purpose
use-toast.ts Toast notifications (shadcn/ui)
use-panel-preferences.ts Panel layout preferences
use-recording-panels.ts Recording panel state
use-animated-words.ts Word animation for transcription

Hook Patterns

Polling with Backoff (Diarization)

const { state, start, cancel, recover } = useDiarization({
  pollInterval: 2000,
  maxRetries: 10,
  autoRecover: true,
  onComplete: (status) => {
    toast.success(`Diarization complete: ${status.segmentsUpdated} segments updated`);
  },
});

// Start job
await start(meetingId, 2);  // 2 speakers

// Monitor progress
useEffect(() => {
  console.log(`Progress: ${state.progress}%`);
}, [state.progress]);

Connection-Aware Components

function MyComponent() {
  const { isConnected, isReadOnly } = useConnection();
  const { activeProject } = useProject();

  if (isReadOnly) {
    return <OfflineBanner />;
  }

  return <ConnectedUI project={activeProject} />;
}

Guarded Mutations

const { mutate, isLoading } = useGuardedMutation(
  async () => {
    await getAPI().deleteMeeting(meetingId);
  },
  {
    requiresConnection: true,
    onError: (e) => toast.error(e.message),
  }
);

Context Provider Pattern

// Root app setup
function App() {
  return (
    <ConnectionProvider>
      <WorkspaceProvider>
        <ProjectProvider>
          <Routes />
        </ProjectProvider>
      </WorkspaceProvider>
    </ConnectionProvider>
  );
}

Hook Re-exports (index.ts)

All hooks are re-exported from domain-specific index files:

// hooks/index.ts
export * from './audio';
export * from './auth';
export * from './data';
export * from './processing';
export * from './recording';
export * from './sync';
export * from './ui';