Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions app/hooks/useTimeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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,
})),
})),
Expand Down
12 changes: 6 additions & 6 deletions app/routes/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
};
Expand All @@ -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();

Expand Down Expand Up @@ -924,22 +924,22 @@ export default function TimelineEditor() {
<Button
variant="ghost"
size="sm"
onClick={handleZoomOut}
onClick={() => handleZoomOut(rulerPositionPx)}
className="h-6 w-6 p-0 text-xs"
title="Zoom Out">
<Minus className="h-3 w-3" />
</Button>
<Badge
variant="secondary"
className="text-xs h-4 px-1.5 font-mono cursor-pointer hover:bg-secondary/80 transition-colors"
onClick={handleZoomReset}
onClick={() => handleZoomReset(rulerPositionPx)}
title="Click to reset zoom to 100%">
{Math.round(zoomLevel * 100)}%
</Badge>
<Button
variant="ghost"
size="sm"
onClick={handleZoomIn}
onClick={() => handleZoomIn(rulerPositionPx)}
className="h-6 w-6 p-0 text-xs"
title="Zoom In">
<Plus className="h-3 w-3" />
Expand Down
15 changes: 9 additions & 6 deletions app/utils/llm-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,21 +156,24 @@ export function llmDeleteTrackByNumber(
// ============================

export function llmZoomIn(
handleZoomIn: () => void
handleZoomIn: (centerPx?: number) => void,
centerPx?: number
) {
handleZoomIn();
handleZoomIn(centerPx);
}

export function llmZoomOut(
handleZoomOut: () => void
handleZoomOut: (centerPx?: number) => void,
centerPx?: number
) {
handleZoomOut();
handleZoomOut(centerPx);
}

export function llmZoomReset(
handleZoomReset: () => void
handleZoomReset: (centerPx?: number) => void,
centerPx?: number
) {
handleZoomReset();
handleZoomReset(centerPx);
}

export function llmSetTimelinePosition(
Expand Down
38 changes: 19 additions & 19 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading