source dump of claude code
at main 59 lines 2.5 kB view raw
1import { useEffect, useRef } from 'react' 2import { 3 type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 4 logEvent, 5} from '../services/analytics/index.js' 6import { useOptionalKeybindingContext } from './KeybindingContext.js' 7import type { KeybindingContextName } from './types.js' 8 9// TODO(keybindings-migration): Remove fallback parameter after migration is complete 10// and we've confirmed no 'keybinding_fallback_used' events are being logged. 11// The fallback exists as a safety net during migration - if bindings fail to load 12// or an action isn't found, we fall back to hardcoded values. Once stable, callers 13// should be able to trust that getBindingDisplayText always returns a value for 14// known actions, and we can remove this defensive pattern. 15 16/** 17 * Hook to get the display text for a configured shortcut. 18 * Returns the configured binding or a fallback if unavailable. 19 * 20 * @param action - The action name (e.g., 'app:toggleTranscript') 21 * @param context - The keybinding context (e.g., 'Global') 22 * @param fallback - Fallback text if keybinding context unavailable 23 * @returns The configured shortcut display text 24 * 25 * @example 26 * const expandShortcut = useShortcutDisplay('app:toggleTranscript', 'Global', 'ctrl+o') 27 * // Returns the user's configured binding, or 'ctrl+o' as default 28 */ 29export function useShortcutDisplay( 30 action: string, 31 context: KeybindingContextName, 32 fallback: string, 33): string { 34 const keybindingContext = useOptionalKeybindingContext() 35 const resolved = keybindingContext?.getDisplayText(action, context) 36 const isFallback = resolved === undefined 37 const reason = keybindingContext ? 'action_not_found' : 'no_context' 38 39 // Log fallback usage once per mount (not on every render) to avoid 40 // flooding analytics with events from frequent re-renders. 41 const hasLoggedRef = useRef(false) 42 useEffect(() => { 43 if (isFallback && !hasLoggedRef.current) { 44 hasLoggedRef.current = true 45 logEvent('tengu_keybinding_fallback_used', { 46 action: 47 action as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 48 context: 49 context as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 50 fallback: 51 fallback as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 52 reason: 53 reason as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 54 }) 55 } 56 }, [isFallback, action, context, fallback, reason]) 57 58 return isFallback ? fallback : resolved 59}