-
-
Notifications
You must be signed in to change notification settings - Fork 213
feat(timeline): icon-only mode toggles and selection-aware region #133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -105,6 +105,7 @@ import { | |||||||||||||||||||||
| type ZoomFocus, | ||||||||||||||||||||||
| type ZoomRegion, | ||||||||||||||||||||||
| type ZoomTransitionEasing, | ||||||||||||||||||||||
| type TimeSelection, | ||||||||||||||||||||||
| } from "./types"; | ||||||||||||||||||||||
| import VideoPlayback, { VideoPlaybackRef } from "./VideoPlayback"; | ||||||||||||||||||||||
| import { | ||||||||||||||||||||||
|
|
@@ -418,6 +419,8 @@ export default function VideoEditor() { | |||||||||||||||||||||
| const [previewVersion, setPreviewVersion] = useState(0); | ||||||||||||||||||||||
| const [isPreviewReady, setIsPreviewReady] = useState(false); | ||||||||||||||||||||||
| const [autoSuggestZoomsTrigger, setAutoSuggestZoomsTrigger] = useState(0); | ||||||||||||||||||||||
| const [timelineMode, setTimelineMode] = useState<'move' | 'select'>('move'); | ||||||||||||||||||||||
| const [timeSelection, setTimeSelection] = useState<TimeSelection | null>(null); | ||||||||||||||||||||||
| const headerLeftControlsPaddingClass = appPlatform === "darwin" ? "pl-[76px]" : ""; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| const videoPlaybackRef = useRef<VideoPlaybackRef>(null); | ||||||||||||||||||||||
|
|
@@ -1879,6 +1882,14 @@ export default function VideoEditor() { | |||||||||||||||||||||
| if (!video.paused && !video.ended) { | ||||||||||||||||||||||
| playback.pause(); | ||||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| // Selection awareness: if playing with a selection active, jump to start if out of bounds | ||||||||||||||||||||||
| if (timeSelection) { | ||||||||||||||||||||||
| const currentTimeMs = Math.round(currentTime * 1000); | ||||||||||||||||||||||
| const bufferMs = 50; // Small buffer for end boundary | ||||||||||||||||||||||
| if (currentTimeMs < timeSelection.startMs || currentTimeMs >= timeSelection.endMs - bufferMs) { | ||||||||||||||||||||||
| handleSeek(timeSelection.startMs / 1000); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| playback.play().catch((err) => console.error("Video play failed:", err)); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
@@ -2315,14 +2326,13 @@ export default function VideoEditor() { | |||||||||||||||||||||
| return; | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| e.preventDefault(); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| const playback = videoPlaybackRef.current; | ||||||||||||||||||||||
| if (playback?.video) { | ||||||||||||||||||||||
| if (playback.video.paused) { | ||||||||||||||||||||||
| playback.play().catch(console.error); | ||||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| playback.pause(); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| togglePlayPause(); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| if (!isEditableTarget) { | ||||||||||||||||||||||
| if (key === "v" || matchesShortcut(e, shortcuts.moveMode, isMac)) { | ||||||||||||||||||||||
| setTimelineMode("move"); | ||||||||||||||||||||||
| } else if (key === "e" || matchesShortcut(e, shortcuts.selectMode, isMac)) { | ||||||||||||||||||||||
| setTimelineMode("select"); | ||||||||||||||||||||||
|
Comment on lines
+2331
to
+2335
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use only the configured mode bindings here.
Suggested change- if (key === "v" || matchesShortcut(e, shortcuts.moveMode, isMac)) {
+ if (matchesShortcut(e, shortcuts.moveMode, isMac)) {
setTimelineMode("move");
- } else if (key === "e" || matchesShortcut(e, shortcuts.selectMode, isMac)) {
+ } else if (matchesShortcut(e, shortcuts.selectMode, isMac)) {
setTimelineMode("select");
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| }; | ||||||||||||||||||||||
|
|
@@ -3300,6 +3310,7 @@ export default function VideoEditor() { | |||||||||||||||||||||
| cursorClickBounce={cursorClickBounce} | ||||||||||||||||||||||
| cursorClickBounceDuration={cursorClickBounceDuration} | ||||||||||||||||||||||
| cursorSway={cursorSway} | ||||||||||||||||||||||
| timeSelection={timeSelection} | ||||||||||||||||||||||
| volume={previewVolume} | ||||||||||||||||||||||
| /> | ||||||||||||||||||||||
| </div> | ||||||||||||||||||||||
|
|
@@ -3341,6 +3352,10 @@ export default function VideoEditor() { | |||||||||||||||||||||
| videoDuration={duration} | ||||||||||||||||||||||
| currentTime={currentTime} | ||||||||||||||||||||||
| onSeek={handleSeek} | ||||||||||||||||||||||
| timelineMode={timelineMode} | ||||||||||||||||||||||
| onTimelineModeChange={setTimelineMode} | ||||||||||||||||||||||
| timeSelection={timeSelection} | ||||||||||||||||||||||
| onTimeSelectionChange={setTimeSelection} | ||||||||||||||||||||||
| cursorTelemetry={normalizedCursorTelemetry} | ||||||||||||||||||||||
| autoSuggestZoomsTrigger={autoSuggestZoomsTrigger} | ||||||||||||||||||||||
| zoomRegions={effectiveZoomRegions} | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reset
timeSelectionwhen loading a different asset.This new editor-wide state survives the project/video load paths below, so a selection from the previous asset can still drive playback and region placement on the next one. If the new video is shorter, the stale range can even sit past
totalMsand make add-region actions fail immediately.Possible fix
🤖 Prompt for AI Agents