forked from Leak_Technologies/VideoTools
Drag-and-Drop on Main Menu: - Implemented position-based drop detection on main menu module tiles - Added detectModuleTileAtPosition() to calculate which tile receives the drop - Modified window drop handler to pass position and route to appropriate module - Bypasses Fyne's drop event hierarchy limitation where window-level handlers intercept drops before widgets can receive them - Only enabled tiles (currently Convert) respond to drops - Loads video and switches to module automatically Cover Art Embedding Fixes: - Fixed FFmpeg exit code 234 error when embedding cover art - Added explicit PNG codec specification for cover art streams - Snippet generation: Added `-c✌️1 png` after mapping cover art stream - Full conversion: Added `-c✌️1 png` for proper MP4 thumbnail encoding - MP4 containers require attached pictures to be PNG or MJPEG encoded Embedded Cover Art Extraction: - Added EmbeddedCoverArt field to videoSource struct - Extended ffprobe parsing to detect attached_pic disposition - Automatically extracts embedded thumbnails when loading videos - Extracted cover art displays in metadata section (168x168) - Enables round-trip workflow: generate snippet with thumbnail, load snippet and see the embedded thumbnail displayed Technical Details: - Modified handleDrop to accept position parameter - Added Index and Disposition fields to ffprobe stream parsing - Cover art streams now excluded from main video stream detection - Grid layout: 3 columns, ~302px per column, ~122px per row, starts at y=100 - Embedded thumbnails extracted to /tmp/videotools-embedded-cover-*.png 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
85 lines
2.3 KiB
Go
85 lines
2.3 KiB
Go
package ui
|
|
|
|
import (
|
|
"fmt"
|
|
"image/color"
|
|
|
|
"fyne.io/fyne/v2"
|
|
"fyne.io/fyne/v2/canvas"
|
|
"fyne.io/fyne/v2/container"
|
|
"fyne.io/fyne/v2/layout"
|
|
"git.leaktechnologies.dev/stu/VideoTools/internal/logging"
|
|
)
|
|
|
|
// ModuleInfo contains information about a module for display
|
|
type ModuleInfo struct {
|
|
ID string
|
|
Label string
|
|
Color color.Color
|
|
Enabled bool
|
|
}
|
|
|
|
// BuildMainMenu creates the main menu view with module tiles
|
|
func BuildMainMenu(modules []ModuleInfo, onModuleClick func(string), onModuleDrop func(string, []fyne.URI), titleColor, queueColor, textColor color.Color) fyne.CanvasObject {
|
|
title := canvas.NewText("VIDEOTOOLS", titleColor)
|
|
title.TextStyle = fyne.TextStyle{Monospace: true, Bold: true}
|
|
title.TextSize = 28
|
|
|
|
queueTile := buildQueueTile(0, 0, queueColor, textColor)
|
|
|
|
header := container.New(layout.NewHBoxLayout(),
|
|
title,
|
|
layout.NewSpacer(),
|
|
queueTile,
|
|
)
|
|
|
|
var tileObjects []fyne.CanvasObject
|
|
for _, mod := range modules {
|
|
modID := mod.ID // Capture for closure
|
|
var tapFunc func()
|
|
var dropFunc func([]fyne.URI)
|
|
if mod.Enabled {
|
|
tapFunc = func() {
|
|
onModuleClick(modID)
|
|
}
|
|
dropFunc = func(items []fyne.URI) {
|
|
onModuleDrop(modID, items)
|
|
}
|
|
}
|
|
tileObjects = append(tileObjects, buildModuleTile(mod, tapFunc, dropFunc))
|
|
}
|
|
|
|
grid := container.NewGridWithColumns(3, tileObjects...)
|
|
|
|
padding := canvas.NewRectangle(color.Transparent)
|
|
padding.SetMinSize(fyne.NewSize(0, 14))
|
|
|
|
body := container.New(layout.NewVBoxLayout(),
|
|
header,
|
|
padding,
|
|
grid,
|
|
)
|
|
|
|
return body
|
|
}
|
|
|
|
// buildModuleTile creates a single module tile
|
|
func buildModuleTile(mod ModuleInfo, tapped func(), dropped func([]fyne.URI)) fyne.CanvasObject {
|
|
logging.Debug(logging.CatUI, "building tile %s color=%v enabled=%v", mod.ID, mod.Color, mod.Enabled)
|
|
return container.NewPadded(NewModuleTile(mod.Label, mod.Color, mod.Enabled, tapped, dropped))
|
|
}
|
|
|
|
// buildQueueTile creates the queue status tile
|
|
func buildQueueTile(done, total int, queueColor, textColor color.Color) fyne.CanvasObject {
|
|
rect := canvas.NewRectangle(queueColor)
|
|
rect.CornerRadius = 8
|
|
rect.SetMinSize(fyne.NewSize(160, 60))
|
|
|
|
text := canvas.NewText(fmt.Sprintf("QUEUE: %d/%d", done, total), textColor)
|
|
text.Alignment = fyne.TextAlignCenter
|
|
text.TextStyle = fyne.TextStyle{Monospace: true, Bold: true}
|
|
text.TextSize = 18
|
|
|
|
return container.NewMax(rect, container.NewCenter(text))
|
|
}
|