From 727bbd9097792bfa4cfa991df537bdead3f7691d Mon Sep 17 00:00:00 2001 From: Stu Leak Date: Tue, 16 Dec 2025 23:23:43 -0500 Subject: [PATCH] Fix drag-and-drop workflow: load videos to memory instead of auto-queuing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes multi-video drag-and-drop behavior to load videos into memory instead of automatically adding them to conversion queue. This allows users to: - Adjust conversion settings before queuing - Generate snippets instead of converting - Navigate through videos before deciding to convert Creates new loadMultipleVideos() function that loads all videos into loadedVideos array and shows informative dialog. Users can now use Convert or Snippet buttons to manually process videos as needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- main.go | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 5be5e4a..c790249 100644 --- a/main.go +++ b/main.go @@ -6995,10 +6995,11 @@ func (s *appState) handleDrop(pos fyne.Position, items []fyne.URI) { return } - // If multiple videos, add all to queue + // Load all videos into memory (don't auto-queue) + // This allows users to adjust settings or generate snippets before manually queuing if len(videoPaths) > 1 { - logging.Debug(logging.CatUI, "multiple videos dropped in convert module; adding all to queue") - go s.batchAddToQueue(videoPaths) + logging.Debug(logging.CatUI, "multiple videos dropped in convert module; loading all into memory") + go s.loadMultipleVideos(videoPaths) } else { // Single video: load it logging.Debug(logging.CatUI, "single video dropped in convert module; loading: %s", videoPaths[0]) @@ -7402,6 +7403,65 @@ func (s *appState) loadVideo(path string) { }, false) } +// loadMultipleVideos loads multiple videos into memory without auto-queuing +func (s *appState) loadMultipleVideos(paths []string) { + logging.Debug(logging.CatModule, "loading %d videos into memory", len(paths)) + + var validVideos []*videoSource + var failedFiles []string + + for _, path := range paths { + src, err := probeVideo(path) + if err != nil { + logging.Debug(logging.CatFFMPEG, "ffprobe failed for %s: %v", path, err) + failedFiles = append(failedFiles, filepath.Base(path)) + continue + } + validVideos = append(validVideos, src) + } + + if len(validVideos) == 0 { + fyne.CurrentApp().Driver().DoFromGoroutine(func() { + msg := fmt.Sprintf("Failed to analyze %d file(s):\n%s", len(failedFiles), strings.Join(failedFiles, ", ")) + s.showErrorWithCopy("Load Failed", fmt.Errorf("%s", msg)) + }, false) + return + } + + // Load all videos into loadedVideos array + s.loadedVideos = validVideos + s.currentIndex = 0 + + // Load the first video to display + firstVideo := validVideos[0] + if frames, err := capturePreviewFrames(firstVideo.Path, firstVideo.Duration); err == nil { + firstVideo.PreviewFrames = frames + if len(frames) > 0 { + s.currentFrame = frames[0] + } + } + + s.applyInverseDefaults(firstVideo) + s.convert.OutputBase = s.resolveOutputBase(firstVideo, false) + if firstVideo.EmbeddedCoverArt != "" { + s.convert.CoverArtPath = firstVideo.EmbeddedCoverArt + } else { + s.convert.CoverArtPath = "" + } + s.convert.AspectHandling = "Auto" + + fyne.CurrentApp().Driver().DoFromGoroutine(func() { + msg := fmt.Sprintf("Loaded %d video(s) into memory.\nUse arrow buttons or Convert/Snippet buttons to process.", len(validVideos)) + if len(failedFiles) > 0 { + msg += fmt.Sprintf("\n\n%d file(s) failed to analyze:\n%s", len(failedFiles), strings.Join(failedFiles, ", ")) + } + dialog.ShowInformation("Videos Loaded", msg, s.window) + s.showConvertView(firstVideo) + }, false) + + logging.Debug(logging.CatModule, "loaded %d videos into memory", len(validVideos)) +} + func (s *appState) clearVideo() { logging.Debug(logging.CatModule, "clearing loaded video") s.stopPlayer()