From 97d9d6692fd23aaabbc7ca6a1af6b02c98ba813d Mon Sep 17 00:00:00 2001 From: Piotr Korzuszek Date: Wed, 6 May 2026 10:50:55 +0200 Subject: [PATCH] Show keyboard shortcuts in button tooltips --- src/renderer/src/BottomBar.tsx | 36 +++--- src/renderer/src/SegmentList.tsx | 16 +-- src/renderer/src/TopMenu.tsx | 8 +- .../src/components/CaptureFormatButton.tsx | 4 +- src/renderer/src/components/Kbd.tsx | 104 +----------------- src/renderer/src/components/VolumeControl.tsx | 5 +- src/renderer/src/hooks/useActionTitle.ts | 27 +++++ src/renderer/src/util.ts | 102 +++++++++++++++++ 8 files changed, 172 insertions(+), 130 deletions(-) create mode 100644 src/renderer/src/hooks/useActionTitle.ts diff --git a/src/renderer/src/BottomBar.tsx b/src/renderer/src/BottomBar.tsx index 127544ec..9ae55dd7 100644 --- a/src/renderer/src/BottomBar.tsx +++ b/src/renderer/src/BottomBar.tsx @@ -24,6 +24,7 @@ import { getSegColor as getSegColorRaw } from './util/colors'; import { useSegColors } from './contexts'; import { isExactDurationMatch } from './util/duration'; import useUserSettings from './hooks/useUserSettings'; +import useActionTitle from './hooks/useActionTitle'; import { askForPlaybackRate, checkAppPath } from './dialogs'; import type { FormatTimecode, ParseTimecode, PlaybackMode, SegmentColorIndex, SegmentToExport, StateSegment } from './types'; import type { WaveformMode } from '../../common/types'; @@ -358,6 +359,7 @@ function BottomBar({ }), [currentFrame]); const { invertCutSegments, setInvertCutSegments, simpleMode, toggleSimpleMode, exportConfirmEnabled } = useUserSettings(); + const actionTitle = useActionTitle(); const rotationStr = `${rotation}°`; @@ -414,7 +416,7 @@ function BottomBar({ toggleWaveformMode()} /> )} @@ -423,14 +425,14 @@ function BottomBar({ @@ -446,18 +448,18 @@ function BottomBar({ {renderJumpCutpointButton(-1)} - + )} - + {!simpleMode && } @@ -465,7 +467,7 @@ function BottomBar({ seekClosestKeyframe(-1)} /> @@ -476,7 +478,7 @@ function BottomBar({ style={{ flexShrink: 0, marginLeft: -6, marginRight: -4 }} size={28} role="button" - title={t('One frame back')} + title={actionTitle(t('One frame back'), 'seekPreviousFrame')} onClick={() => shortStep(-1)} /> )} @@ -490,7 +492,7 @@ function BottomBar({ style={{ flexShrink: 0, marginRight: -6, marginLeft: -4 }} size={28} role="button" - title={t('One frame forward')} + title={actionTitle(t('One frame forward'), 'seekNextFrame')} onClick={() => shortStep(1)} /> )} @@ -500,25 +502,25 @@ function BottomBar({ style={{ flexShrink: 0, marginLeft: 2, ...keyframeStyle }} size={25} role="button" - title={t('Seek next keyframe')} + title={actionTitle(t('Seek next keyframe'), 'seekForwardsKeyframe')} onClick={() => seekClosestKeyframe(1)} /> )} {!simpleMode && } - + {!simpleMode && ( <> - + {renderJumpCutpointButton(1)} @@ -571,7 +573,7 @@ function BottomBar({
{isRotationSet && rotationStr}
@@ -581,7 +583,7 @@ function BottomBar({ {!simpleMode && isFileOpened && ( @@ -602,7 +604,7 @@ function BottomBar({ )} {isFileOpened && ( -
+
)} diff --git a/src/renderer/src/SegmentList.tsx b/src/renderer/src/SegmentList.tsx index df7999cf..016ea7ea 100644 --- a/src/renderer/src/SegmentList.tsx +++ b/src/renderer/src/SegmentList.tsx @@ -15,6 +15,7 @@ import prettyBytes from 'pretty-bytes'; import useContextMenu from './hooks/useContextMenu'; import useUserSettings from './hooks/useUserSettings'; +import useActionTitle from './hooks/useActionTitle'; import { saveColor, controlsBackground, primaryTextColor, darkModeTransition } from './colors'; import { useSegColors } from './contexts'; import { getSegmentTags } from './segments'; @@ -382,6 +383,7 @@ function SegmentList({ const [draggingId, setDraggingId] = useState(); const { invertCutSegments, simpleMode, darkMode, springAnimation } = useUserSettings(); + const actionTitle = useActionTitle(); const getButtonColor = useCallback((seg: SegmentColorIndex | undefined, next?: boolean) => getSegColor(seg ? { segColorIndex: next ? seg.segColorIndex + 1 : seg.segColorIndex } : undefined).desaturate(0.3).lightness(darkMode ? 45 : 55).string(), [darkMode, getSegColor]); const currentSegColor = useMemo(() => getButtonColor(currentCutSeg), [currentCutSeg, getButtonColor]); @@ -438,7 +440,7 @@ function SegmentList({ size={24} style={{ ...buttonBaseStyle, background: nextSegmentColor }} role="button" - title={t('Add segment')} + title={actionTitle(t('Add segment'), 'addSegment')} onClick={addSegment} /> @@ -446,7 +448,7 @@ function SegmentList({ size={24} style={{ ...buttonBaseStyle, ...(cutSegments.length > 0 ? { backgroundColor: currentSegColor } : disabledButtonStyle) }} role="button" - title={t('Remove cutpoint from segment {{segmentNumber}}', { segmentNumber: currentSegIndex + 1 })} + title={actionTitle(t('Remove cutpoint from segment {{segmentNumber}}', { segmentNumber: currentSegIndex + 1 }), 'removeCurrentCutpoint')} onClick={() => removeSegment(currentSegIndex)} /> @@ -454,7 +456,7 @@ function SegmentList({ <> = 2 ? { backgroundColor: currentSegColor } : disabledButtonStyle) }} onClick={() => onReorderSegs(currentSegIndex)} @@ -462,7 +464,7 @@ function SegmentList({ 0 ? { backgroundColor: currentSegColor } : disabledButtonStyle) }} onClick={() => onLabelSegment(currentSegIndex)} @@ -472,7 +474,7 @@ function SegmentList({ 0 ? { backgroundColor: neutralButtonColor } : disabledButtonStyle) }} onClick={onInvertSelectedSegments} @@ -639,7 +641,7 @@ function SegmentList({ {getHeader()} (null); const DarkMode = darkMode ? FaSun : FaMoon; @@ -99,7 +101,7 @@ function TopMenu({ {enabledStreamsFilter != null && ( )} -
diff --git a/src/renderer/src/components/CaptureFormatButton.tsx b/src/renderer/src/components/CaptureFormatButton.tsx index dd6c383e..56fd0acb 100644 --- a/src/renderer/src/components/CaptureFormatButton.tsx +++ b/src/renderer/src/components/CaptureFormatButton.tsx @@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next'; import { FaImage } from 'react-icons/fa'; import useUserSettings from '../hooks/useUserSettings'; +import useActionTitle from '../hooks/useActionTitle'; import { withBlur } from '../util'; import Button from './Button'; @@ -10,9 +11,10 @@ import Button from './Button'; function CaptureFormatButton({ showIcon = false, ...props }: { showIcon?: boolean } & Parameters[0]) { const { t } = useTranslation(); const { captureFormat, toggleCaptureFormat } = useUserSettings(); + const actionTitle = useActionTitle(); return (