init claude-code
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import {
|
||||
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
logEvent,
|
||||
} from '../services/analytics/index.js'
|
||||
import { useOptionalKeybindingContext } from './KeybindingContext.js'
|
||||
import type { KeybindingContextName } from './types.js'
|
||||
|
||||
// TODO(keybindings-migration): Remove fallback parameter after migration is complete
|
||||
// and we've confirmed no 'keybinding_fallback_used' events are being logged.
|
||||
// The fallback exists as a safety net during migration - if bindings fail to load
|
||||
// or an action isn't found, we fall back to hardcoded values. Once stable, callers
|
||||
// should be able to trust that getBindingDisplayText always returns a value for
|
||||
// known actions, and we can remove this defensive pattern.
|
||||
|
||||
/**
|
||||
* Hook to get the display text for a configured shortcut.
|
||||
* Returns the configured binding or a fallback if unavailable.
|
||||
*
|
||||
* @param action - The action name (e.g., 'app:toggleTranscript')
|
||||
* @param context - The keybinding context (e.g., 'Global')
|
||||
* @param fallback - Fallback text if keybinding context unavailable
|
||||
* @returns The configured shortcut display text
|
||||
*
|
||||
* @example
|
||||
* const expandShortcut = useShortcutDisplay('app:toggleTranscript', 'Global', 'ctrl+o')
|
||||
* // Returns the user's configured binding, or 'ctrl+o' as default
|
||||
*/
|
||||
export function useShortcutDisplay(
|
||||
action: string,
|
||||
context: KeybindingContextName,
|
||||
fallback: string,
|
||||
): string {
|
||||
const keybindingContext = useOptionalKeybindingContext()
|
||||
const resolved = keybindingContext?.getDisplayText(action, context)
|
||||
const isFallback = resolved === undefined
|
||||
const reason = keybindingContext ? 'action_not_found' : 'no_context'
|
||||
|
||||
// Log fallback usage once per mount (not on every render) to avoid
|
||||
// flooding analytics with events from frequent re-renders.
|
||||
const hasLoggedRef = useRef(false)
|
||||
useEffect(() => {
|
||||
if (isFallback && !hasLoggedRef.current) {
|
||||
hasLoggedRef.current = true
|
||||
logEvent('tengu_keybinding_fallback_used', {
|
||||
action:
|
||||
action as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
context:
|
||||
context as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
fallback:
|
||||
fallback as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
reason:
|
||||
reason as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
})
|
||||
}
|
||||
}, [isFallback, action, context, fallback, reason])
|
||||
|
||||
return isFallback ? fallback : resolved
|
||||
}
|
||||
Reference in New Issue
Block a user