From 02e79cc42681c6dab04b78cba5a7324b8a15658e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 15:07:48 +0530 Subject: [PATCH 1/2] Bump ajv in the npm_and_yarn group across 1 directory (#176) Bumps the npm_and_yarn group with 1 update in the / directory: [ajv](https://github.com/ajv-validator/ajv). Updates `ajv` from 6.12.6 to 6.14.0 - [Release notes](https://github.com/ajv-validator/ajv/releases) - [Commits](https://github.com/ajv-validator/ajv/compare/v6.12.6...v6.14.0) --- updated-dependencies: - dependency-name: ajv dependency-version: 6.14.0 dependency-type: indirect dependency-group: npm_and_yarn ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pnpm-lock.yaml | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6acb83b..1ee5ee1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2080,11 +2080,11 @@ packages: peerDependencies: ajv: ^8.8.2 - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@6.14.0: + resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} - ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} @@ -4958,7 +4958,7 @@ snapshots: '@eslint/eslintrc@3.3.1': dependencies: - ajv: 6.12.6 + ajv: 6.14.0 debug: 4.4.1 espree: 10.4.0 globals: 14.0.0 @@ -6272,27 +6272,27 @@ snapshots: acorn@8.15.0: {} - ajv-formats@2.1.1(ajv@8.17.1): + ajv-formats@2.1.1(ajv@8.18.0): optionalDependencies: - ajv: 8.17.1 + ajv: 8.18.0 - ajv-keywords@3.5.2(ajv@6.12.6): + ajv-keywords@3.5.2(ajv@6.14.0): dependencies: - ajv: 6.12.6 + ajv: 6.14.0 - ajv-keywords@5.1.0(ajv@8.17.1): + ajv-keywords@5.1.0(ajv@8.18.0): dependencies: - ajv: 8.17.1 + ajv: 8.18.0 fast-deep-equal: 3.1.3 - ajv@6.12.6: + ajv@6.14.0: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.17.1: + ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 fast-uri: 3.0.6 @@ -6993,7 +6993,7 @@ snapshots: '@humanwhocodes/retry': 0.4.3 '@types/estree': 1.0.8 '@types/json-schema': 7.0.15 - ajv: 6.12.6 + ajv: 6.14.0 chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.4.1 @@ -8276,15 +8276,15 @@ snapshots: schema-utils@3.3.0: dependencies: '@types/json-schema': 7.0.15 - ajv: 6.12.6 - ajv-keywords: 3.5.2(ajv@6.12.6) + ajv: 6.14.0 + ajv-keywords: 3.5.2(ajv@6.14.0) schema-utils@4.3.3: dependencies: '@types/json-schema': 7.0.15 - ajv: 8.17.1 - ajv-formats: 2.1.1(ajv@8.17.1) - ajv-keywords: 5.1.0(ajv@8.17.1) + ajv: 8.18.0 + ajv-formats: 2.1.1(ajv@8.18.0) + ajv-keywords: 5.1.0(ajv@8.18.0) semver@6.3.1: {} From 5d68275e5c7990613beee09e0339a2f083a0ecfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiberiu=20Sab=C4=83u?= Date: Sat, 28 Feb 2026 21:55:05 +0100 Subject: [PATCH 2/2] fix: zoom should be wrt the current scrubbers --- app/hooks/useTimeline.ts | 17 +++++++++++------ app/routes/home.tsx | 12 ++++++------ app/utils/llm-handler.ts | 15 +++++++++------ 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/app/hooks/useTimeline.ts b/app/hooks/useTimeline.ts index 5534791..d991f5b 100644 --- a/app/hooks/useTimeline.ts +++ b/app/hooks/useTimeline.ts @@ -82,10 +82,13 @@ export const useTimeline = () => { }, [zoomLevel]); // Zoom functions that update scrubber positions and widths accordingly - const handleZoomIn = useCallback(() => { + // Zoom is relative to the center point (ruler position) so that the timeline + // zooms towards/away from the current playhead position + const handleZoomIn = useCallback((centerPx: number = 0) => { const currentZoom = zoomLevelRef.current; const newZoom = Math.min(MAX_ZOOM, currentZoom * 1.5); const zoomRatio = newZoom / currentZoom; + const offset = centerPx * (1 - zoomRatio); zoomLevelRef.current = newZoom; setZoomLevel(newZoom); @@ -96,17 +99,18 @@ export const useTimeline = () => { ...track, scrubbers: track.scrubbers.map((scrubber) => ({ ...scrubber, - left: scrubber.left * zoomRatio, + left: scrubber.left * zoomRatio + offset, width: scrubber.width * zoomRatio, })), })), })); }, []); - const handleZoomOut = useCallback(() => { + const handleZoomOut = useCallback((centerPx: number = 0) => { const currentZoom = zoomLevelRef.current; const newZoom = Math.max(MIN_ZOOM, currentZoom / 1.5); const zoomRatio = newZoom / currentZoom; + const offset = centerPx * (1 - zoomRatio); zoomLevelRef.current = newZoom; setZoomLevel(newZoom); @@ -117,17 +121,18 @@ export const useTimeline = () => { ...track, scrubbers: track.scrubbers.map((scrubber) => ({ ...scrubber, - left: scrubber.left * zoomRatio, + left: scrubber.left * zoomRatio + offset, width: scrubber.width * zoomRatio, })), })), })); }, []); - const handleZoomReset = useCallback(() => { + const handleZoomReset = useCallback((centerPx: number = 0) => { const currentZoom = zoomLevelRef.current; const newZoom = DEFAULT_ZOOM; const zoomRatio = newZoom / currentZoom; + const offset = centerPx * (1 - zoomRatio); zoomLevelRef.current = newZoom; setZoomLevel(newZoom); @@ -138,7 +143,7 @@ export const useTimeline = () => { ...track, scrubbers: track.scrubbers.map((scrubber) => ({ ...scrubber, - left: scrubber.left * zoomRatio, + left: scrubber.left * zoomRatio + offset, width: scrubber.width * zoomRatio, })), })), diff --git a/app/routes/home.tsx b/app/routes/home.tsx index fa2c737..c9c9d25 100644 --- a/app/routes/home.tsx +++ b/app/routes/home.tsx @@ -660,9 +660,9 @@ export default function TimelineEditor() { const scrollDirection = e.deltaY > 0 ? -1 : 1; if (scrollDirection > 0) { - handleZoomIn(); + handleZoomIn(rulerPositionPx); } else { - handleZoomOut(); + handleZoomOut(rulerPositionPx); } } }; @@ -673,7 +673,7 @@ export default function TimelineEditor() { return () => { timelineContainer.removeEventListener("wheel", handleWheel); }; - }, [handleZoomIn, handleZoomOut]); + }, [handleZoomIn, handleZoomOut, rulerPositionPx]); const { user, isLoading: isAuthLoading, isSigningIn, signInWithGoogle, signOut } = useAuth(); @@ -924,7 +924,7 @@ export default function TimelineEditor() {