7.1 KiB
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';