mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
feat: add timeline navigation return to start functionality
- Add Enter key shortcut for seeking to timeline start (00:00:00) - Add return to start button in timeline toolbar with skip-back icon - Both methods complement existing Home key shortcut - Update keyboard shortcuts help to display Enter key properly - Maintain consistent UI styling with existing playback controls Resolves #415
This commit is contained in:
@@ -72,6 +72,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/typography": "^0.5.16",
|
"@tailwindcss/typography": "^0.5.16",
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
|
"@types/node": "^24.1.0",
|
||||||
"@types/pg": "^8.15.4",
|
"@types/pg": "^8.15.4",
|
||||||
"@types/react": "^18.2.48",
|
"@types/react": "^18.2.48",
|
||||||
"@types/react-dom": "^18.2.18",
|
"@types/react-dom": "^18.2.18",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
SplitSquareHorizontal,
|
SplitSquareHorizontal,
|
||||||
Pause,
|
Pause,
|
||||||
Play,
|
Play,
|
||||||
|
SkipBack,
|
||||||
Video,
|
Video,
|
||||||
Music,
|
Music,
|
||||||
TypeIcon,
|
TypeIcon,
|
||||||
@@ -508,7 +509,7 @@ export function Timeline() {
|
|||||||
onMouseEnter={() => setIsInTimeline(true)}
|
onMouseEnter={() => setIsInTimeline(true)}
|
||||||
onMouseLeave={() => setIsInTimeline(false)}
|
onMouseLeave={() => setIsInTimeline(false)}
|
||||||
>
|
>
|
||||||
<TimelineToolbar zoomLevel={zoomLevel} setZoomLevel={setZoomLevel} />
|
<TimelineToolbar zoomLevel={zoomLevel} setZoomLevel={setZoomLevel} seek={seek} />
|
||||||
|
|
||||||
{/* Timeline Container */}
|
{/* Timeline Container */}
|
||||||
<div
|
<div
|
||||||
@@ -806,9 +807,11 @@ function TrackIcon({ track }: { track: TimelineTrack }) {
|
|||||||
function TimelineToolbar({
|
function TimelineToolbar({
|
||||||
zoomLevel,
|
zoomLevel,
|
||||||
setZoomLevel,
|
setZoomLevel,
|
||||||
|
seek,
|
||||||
}: {
|
}: {
|
||||||
zoomLevel: number;
|
zoomLevel: number;
|
||||||
setZoomLevel: (zoom: number) => void;
|
setZoomLevel: (zoom: number) => void;
|
||||||
|
seek: (time: number) => void;
|
||||||
}) {
|
}) {
|
||||||
const {
|
const {
|
||||||
tracks,
|
tracks,
|
||||||
@@ -981,6 +984,21 @@ function TimelineToolbar({
|
|||||||
{isPlaying ? "Pause (Space)" : "Play (Space)"}
|
{isPlaying ? "Pause (Space)" : "Play (Space)"}
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="text"
|
||||||
|
size="icon"
|
||||||
|
onClick={() => seek(0)}
|
||||||
|
className="mr-2"
|
||||||
|
>
|
||||||
|
<SkipBack className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
Return to Start (Home / Enter)
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
<div className="w-px h-6 bg-border mx-1" />
|
<div className="w-px h-6 bg-border mx-1" />
|
||||||
{/* Time Display */}
|
{/* Time Display */}
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ const formatKey = (key: string): string => {
|
|||||||
.replace("down", "↓")
|
.replace("down", "↓")
|
||||||
.replace("space", "Space")
|
.replace("space", "Space")
|
||||||
.replace("home", "Home")
|
.replace("home", "Home")
|
||||||
|
.replace("enter", "Enter")
|
||||||
.replace("end", "End")
|
.replace("end", "End")
|
||||||
.replace("delete", "Delete")
|
.replace("delete", "Delete")
|
||||||
.replace("backspace", "Backspace")
|
.replace("backspace", "Backspace")
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export const defaultKeybindings: KeybindingConfig = {
|
|||||||
"shift+left": "jump-backward",
|
"shift+left": "jump-backward",
|
||||||
"shift+right": "jump-forward",
|
"shift+right": "jump-forward",
|
||||||
home: "goto-start",
|
home: "goto-start",
|
||||||
|
enter: "goto-start",
|
||||||
end: "goto-end",
|
end: "goto-end",
|
||||||
s: "split-element",
|
s: "split-element",
|
||||||
n: "toggle-snapping",
|
n: "toggle-snapping",
|
||||||
|
|||||||
@@ -75,6 +75,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/typography": "^0.5.16",
|
"@tailwindcss/typography": "^0.5.16",
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
|
"@types/node": "^24.1.0",
|
||||||
"@types/pg": "^8.15.4",
|
"@types/pg": "^8.15.4",
|
||||||
"@types/react": "^18.2.48",
|
"@types/react": "^18.2.48",
|
||||||
"@types/react-dom": "^18.2.18",
|
"@types/react-dom": "^18.2.18",
|
||||||
@@ -1314,6 +1315,8 @@
|
|||||||
|
|
||||||
"next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
|
"next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
|
||||||
|
|
||||||
|
"opencut/@types/node": ["@types/node@24.1.0", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w=="],
|
||||||
|
|
||||||
"opencut/next": ["next@15.4.5", "", { "dependencies": { "@next/env": "15.4.5", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.4.5", "@next/swc-darwin-x64": "15.4.5", "@next/swc-linux-arm64-gnu": "15.4.5", "@next/swc-linux-arm64-musl": "15.4.5", "@next/swc-linux-x64-gnu": "15.4.5", "@next/swc-linux-x64-musl": "15.4.5", "@next/swc-win32-arm64-msvc": "15.4.5", "@next/swc-win32-x64-msvc": "15.4.5", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-nJ4v+IO9CPmbmcvsPebIoX3Q+S7f6Fu08/dEWu0Ttfa+wVwQRh9epcmsyCPjmL2b8MxC+CkBR97jgDhUUztI3g=="],
|
"opencut/next": ["next@15.4.5", "", { "dependencies": { "@next/env": "15.4.5", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.4.5", "@next/swc-darwin-x64": "15.4.5", "@next/swc-linux-arm64-gnu": "15.4.5", "@next/swc-linux-arm64-musl": "15.4.5", "@next/swc-linux-x64-gnu": "15.4.5", "@next/swc-linux-x64-musl": "15.4.5", "@next/swc-win32-arm64-msvc": "15.4.5", "@next/swc-win32-x64-msvc": "15.4.5", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-nJ4v+IO9CPmbmcvsPebIoX3Q+S7f6Fu08/dEWu0Ttfa+wVwQRh9epcmsyCPjmL2b8MxC+CkBR97jgDhUUztI3g=="],
|
||||||
|
|
||||||
"opencut/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
"opencut/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
||||||
@@ -1392,6 +1395,8 @@
|
|||||||
|
|
||||||
"motion/framer-motion/motion-utils": ["motion-utils@12.23.6", "", {}, "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ=="],
|
"motion/framer-motion/motion-utils": ["motion-utils@12.23.6", "", {}, "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ=="],
|
||||||
|
|
||||||
|
"opencut/@types/node/undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
|
||||||
|
|
||||||
"opencut/next/@next/env": ["@next/env@15.4.5", "", {}, "sha512-ruM+q2SCOVCepUiERoxOmZY9ZVoecR3gcXNwCYZRvQQWRjhOiPJGmQ2fAiLR6YKWXcSAh7G79KEFxN3rwhs4LQ=="],
|
"opencut/next/@next/env": ["@next/env@15.4.5", "", {}, "sha512-ruM+q2SCOVCepUiERoxOmZY9ZVoecR3gcXNwCYZRvQQWRjhOiPJGmQ2fAiLR6YKWXcSAh7G79KEFxN3rwhs4LQ=="],
|
||||||
|
|
||||||
"opencut/next/@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.4.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-84dAN4fkfdC7nX6udDLz9GzQlMUwEMKD7zsseXrl7FTeIItF8vpk1lhLEnsotiiDt+QFu3O1FVWnqwcRD2U3KA=="],
|
"opencut/next/@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.4.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-84dAN4fkfdC7nX6udDLz9GzQlMUwEMKD7zsseXrl7FTeIItF8vpk1lhLEnsotiiDt+QFu3O1FVWnqwcRD2U3KA=="],
|
||||||
|
|||||||
Reference in New Issue
Block a user