/ hooks / notifs / useAutoModeUnavailableNotification.ts
useAutoModeUnavailableNotification.ts
 1  import { feature } from 'bun:bundle'
 2  import { useEffect, useRef } from 'react'
 3  import { useNotifications } from 'src/context/notifications.js'
 4  import { getIsRemoteMode } from '../../bootstrap/state.js'
 5  import { useAppState } from '../../state/AppState.js'
 6  import type { PermissionMode } from '../../utils/permissions/PermissionMode.js'
 7  import {
 8    getAutoModeUnavailableNotification,
 9    getAutoModeUnavailableReason,
10  } from '../../utils/permissions/permissionSetup.js'
11  import { hasAutoModeOptIn } from '../../utils/settings/settings.js'
12  
13  /**
14   * Shows a one-shot notification when the shift-tab carousel wraps past where
15   * auto mode would have been. Covers all reasons (settings, circuit-breaker,
16   * org-allowlist). The startup case (defaultMode: auto silently downgraded) is
17   * handled by verifyAutoModeGateAccess → checkAndDisableAutoModeIfNeeded.
18   */
19  export function useAutoModeUnavailableNotification(): void {
20    const { addNotification } = useNotifications()
21    const mode = useAppState(s => s.toolPermissionContext.mode)
22    const isAutoModeAvailable = useAppState(
23      s => s.toolPermissionContext.isAutoModeAvailable,
24    )
25    const shownRef = useRef(false)
26    const prevModeRef = useRef<PermissionMode>(mode)
27  
28    useEffect(() => {
29      const prevMode = prevModeRef.current
30      prevModeRef.current = mode
31  
32      if (!feature('TRANSCRIPT_CLASSIFIER')) return
33      if (getIsRemoteMode()) return
34      if (shownRef.current) return
35  
36      const wrappedPastAutoSlot =
37        mode === 'default' &&
38        prevMode !== 'default' &&
39        prevMode !== 'auto' &&
40        !isAutoModeAvailable &&
41        hasAutoModeOptIn()
42  
43      if (!wrappedPastAutoSlot) return
44  
45      const reason = getAutoModeUnavailableReason()
46      if (!reason) return
47  
48      shownRef.current = true
49      addNotification({
50        key: 'auto-mode-unavailable',
51        text: getAutoModeUnavailableNotification(reason),
52        color: 'warning',
53        priority: 'medium',
54      })
55    }, [mode, isAutoModeAvailable, addNotification])
56  }