/ src / hooks / useVoiceEnabled.ts
useVoiceEnabled.ts
 1  import { useMemo } from 'react'
 2  import { useAppState } from '../state/AppState.js'
 3  import {
 4    hasVoiceAuth,
 5    isVoiceGrowthBookEnabled,
 6  } from '../voice/voiceModeEnabled.js'
 7  
 8  /**
 9   * Combines user intent (settings.voiceEnabled) with auth + GB kill-switch.
10   * Only the auth half is memoized on authVersion — it's the expensive one
11   * (cold getClaudeAIOAuthTokens memoize → sync `security` spawn, ~60ms/call,
12   * ~180ms total in profile v5 when token refresh cleared the cache mid-session).
13   * GB is a cheap cached-map lookup and stays outside the memo so a mid-session
14   * kill-switch flip still takes effect on the next render.
15   *
16   * authVersion bumps on /login only. Background token refresh leaves it alone
17   * (user is still authed), so the auth memo stays correct without re-eval.
18   */
19  export function useVoiceEnabled(): boolean {
20    const userIntent = useAppState(s => s.settings.voiceEnabled === true)
21    const authVersion = useAppState(s => s.authVersion)
22    // eslint-disable-next-line react-hooks/exhaustive-deps
23    const authed = useMemo(hasVoiceAuth, [authVersion])
24    return userIntent && authed && isVoiceGrowthBookEnabled()
25  }