Refine footer layout to match legacy look
This commit is contained in:
parent
f021bcc26c
commit
2b16b130f4
92
main.go
92
main.go
|
|
@ -106,9 +106,24 @@ func moduleColor(id string) color.Color {
|
||||||
return queueColor
|
return queueColor
|
||||||
}
|
}
|
||||||
|
|
||||||
// statusBar creates a consistent bottom status bar for modules.
|
// statusStrip renders a consistent dark status area with the shared stats bar.
|
||||||
func statusBar(color color.Color, bar *ui.ConversionStatsBar) fyne.CanvasObject {
|
func statusStrip(bar *ui.ConversionStatsBar) fyne.CanvasObject {
|
||||||
return ui.TintedBar(color, container.NewHBox(bar, layout.NewSpacer()))
|
bg := canvas.NewRectangle(color.NRGBA{R: 34, G: 34, B: 34, A: 255})
|
||||||
|
bg.SetMinSize(fyne.NewSize(0, 32))
|
||||||
|
content := container.NewPadded(container.NewHBox(bar, layout.NewSpacer()))
|
||||||
|
return container.NewMax(bg, content)
|
||||||
|
}
|
||||||
|
|
||||||
|
// moduleFooter stacks the dark status strip above a tinted action/footer area.
|
||||||
|
// Pass a content node for module-specific footer controls; use layout.NewSpacer() if empty.
|
||||||
|
func moduleFooter(tint color.Color, content fyne.CanvasObject, bar *ui.ConversionStatsBar) fyne.CanvasObject {
|
||||||
|
if content == nil {
|
||||||
|
content = layout.NewSpacer()
|
||||||
|
}
|
||||||
|
bg := canvas.NewRectangle(tint)
|
||||||
|
bg.SetMinSize(fyne.NewSize(0, 44))
|
||||||
|
tinted := container.NewMax(bg, container.NewPadded(content))
|
||||||
|
return container.NewVBox(statusStrip(bar), tinted)
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolveTargetAspect resolves an aspect ratio value or source aspect
|
// resolveTargetAspect resolves an aspect ratio value or source aspect
|
||||||
|
|
@ -414,30 +429,31 @@ type convertConfig struct {
|
||||||
AutoNameTemplate string // Template for metadata-driven naming, e.g., "<actress> - <studio> - <scene>"
|
AutoNameTemplate string // Template for metadata-driven naming, e.g., "<actress> - <studio> - <scene>"
|
||||||
|
|
||||||
// Video encoding settings
|
// Video encoding settings
|
||||||
VideoCodec string // H.264, H.265, VP9, AV1, Copy
|
VideoCodec string // H.264, H.265, VP9, AV1, Copy
|
||||||
EncoderPreset string // ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow
|
EncoderPreset string // ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow
|
||||||
CRF string // Manual CRF value (0-51, or empty to use Quality preset)
|
CRF string // Manual CRF value (0-51, or empty to use Quality preset)
|
||||||
BitrateMode string // CRF, CBR, VBR, "Target Size"
|
BitrateMode string // CRF, CBR, VBR, "Target Size"
|
||||||
BitratePreset string // Friendly bitrate presets (codec-aware recommendations)
|
BitratePreset string // Friendly bitrate presets (codec-aware recommendations)
|
||||||
VideoBitrate string // For CBR/VBR modes (e.g., "5000k")
|
VideoBitrate string // For CBR/VBR modes (e.g., "5000k")
|
||||||
TargetFileSize string // Target file size (e.g., "25MB", "100MB") - requires BitrateMode="Target Size"
|
TargetFileSize string // Target file size (e.g., "25MB", "100MB") - requires BitrateMode="Target Size"
|
||||||
TargetResolution string // Source, 720p, 1080p, 1440p, 4K, or custom
|
TargetResolution string // Source, 720p, 1080p, 1440p, 4K, or custom
|
||||||
FrameRate string // Source, 24, 30, 60, or custom
|
FrameRate string // Source, 24, 30, 60, or custom
|
||||||
PixelFormat string // yuv420p, yuv422p, yuv444p
|
UseMotionInterpolation bool // Use motion interpolation for smooth frame rate changes
|
||||||
HardwareAccel string // auto, none, nvenc, amf, vaapi, qsv, videotoolbox
|
PixelFormat string // yuv420p, yuv422p, yuv444p
|
||||||
TwoPass bool // Enable two-pass encoding for VBR
|
HardwareAccel string // auto, none, nvenc, amf, vaapi, qsv, videotoolbox
|
||||||
H264Profile string // baseline, main, high (for H.264 compatibility)
|
TwoPass bool // Enable two-pass encoding for VBR
|
||||||
H264Level string // 3.0, 3.1, 4.0, 4.1, 5.0, 5.1 (for H.264 compatibility)
|
H264Profile string // baseline, main, high (for H.264 compatibility)
|
||||||
Deinterlace string // Auto, Force, Off
|
H264Level string // 3.0, 3.1, 4.0, 4.1, 5.0, 5.1 (for H.264 compatibility)
|
||||||
DeinterlaceMethod string // yadif, bwdif (bwdif is higher quality but slower)
|
Deinterlace string // Auto, Force, Off
|
||||||
AutoCrop bool // Auto-detect and remove black bars
|
DeinterlaceMethod string // yadif, bwdif (bwdif is higher quality but slower)
|
||||||
CropWidth string // Manual crop width (empty = use auto-detect)
|
AutoCrop bool // Auto-detect and remove black bars
|
||||||
CropHeight string // Manual crop height (empty = use auto-detect)
|
CropWidth string // Manual crop width (empty = use auto-detect)
|
||||||
CropX string // Manual crop X offset (empty = use auto-detect)
|
CropHeight string // Manual crop height (empty = use auto-detect)
|
||||||
CropY string // Manual crop Y offset (empty = use auto-detect)
|
CropX string // Manual crop X offset (empty = use auto-detect)
|
||||||
FlipHorizontal bool // Flip video horizontally (mirror)
|
CropY string // Manual crop Y offset (empty = use auto-detect)
|
||||||
FlipVertical bool // Flip video vertically (upside down)
|
FlipHorizontal bool // Flip video horizontally (mirror)
|
||||||
Rotation string // 0, 90, 180, 270 (clockwise rotation in degrees)
|
FlipVertical bool // Flip video vertically (upside down)
|
||||||
|
Rotation string // 0, 90, 180, 270 (clockwise rotation in degrees)
|
||||||
|
|
||||||
// Audio encoding settings
|
// Audio encoding settings
|
||||||
AudioCodec string // AAC, Opus, MP3, FLAC, Copy
|
AudioCodec string // AAC, Opus, MP3, FLAC, Copy
|
||||||
|
|
@ -2050,7 +2066,7 @@ func (s *appState) showMergeView() {
|
||||||
s.updateQueueButtonLabel()
|
s.updateQueueButtonLabel()
|
||||||
|
|
||||||
topBar := ui.TintedBar(mergeColor, container.NewHBox(backBtn, layout.NewSpacer(), queueBtn))
|
topBar := ui.TintedBar(mergeColor, container.NewHBox(backBtn, layout.NewSpacer(), queueBtn))
|
||||||
bottomBar := statusBar(mergeColor, s.statsBar)
|
bottomBar := moduleFooter(mergeColor, layout.NewSpacer(), s.statsBar)
|
||||||
|
|
||||||
listBox := container.NewVBox()
|
listBox := container.NewVBox()
|
||||||
var addFiles func([]string)
|
var addFiles func([]string)
|
||||||
|
|
@ -3024,8 +3040,15 @@ func (s *appState) executeConvertJob(ctx context.Context, job *queue.Job, progre
|
||||||
|
|
||||||
// Frame rate
|
// Frame rate
|
||||||
frameRate, _ := cfg["frameRate"].(string)
|
frameRate, _ := cfg["frameRate"].(string)
|
||||||
|
useMotionInterp, _ := cfg["useMotionInterpolation"].(bool)
|
||||||
if frameRate != "" && frameRate != "Source" {
|
if frameRate != "" && frameRate != "Source" {
|
||||||
vf = append(vf, "fps="+frameRate)
|
if useMotionInterp {
|
||||||
|
// Use motion interpolation for smooth frame rate changes
|
||||||
|
vf = append(vf, fmt.Sprintf("minterpolate=fps=%s:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1", frameRate))
|
||||||
|
} else {
|
||||||
|
// Simple frame rate change (duplicates/drops frames)
|
||||||
|
vf = append(vf, "fps="+frameRate)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(vf) > 0 {
|
if len(vf) > 0 {
|
||||||
|
|
@ -8392,7 +8415,13 @@ func (s *appState) startConvert(status *widget.Label, btn, cancelBtn *widget.But
|
||||||
|
|
||||||
// Frame rate
|
// Frame rate
|
||||||
if cfg.FrameRate != "" && cfg.FrameRate != "Source" {
|
if cfg.FrameRate != "" && cfg.FrameRate != "Source" {
|
||||||
vf = append(vf, "fps="+cfg.FrameRate)
|
if cfg.UseMotionInterpolation {
|
||||||
|
// Use motion interpolation for smooth frame rate changes
|
||||||
|
vf = append(vf, fmt.Sprintf("minterpolate=fps=%s:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1", cfg.FrameRate))
|
||||||
|
} else {
|
||||||
|
// Simple frame rate change (duplicates/drops frames)
|
||||||
|
vf = append(vf, "fps="+cfg.FrameRate)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(vf) > 0 {
|
if len(vf) > 0 {
|
||||||
|
|
@ -9614,7 +9643,7 @@ func buildCompareView(state *appState) fyne.CanvasObject {
|
||||||
state.queueBtn = queueBtn
|
state.queueBtn = queueBtn
|
||||||
state.updateQueueButtonLabel()
|
state.updateQueueButtonLabel()
|
||||||
topBar := ui.TintedBar(compareColor, container.NewHBox(backBtn, layout.NewSpacer(), queueBtn))
|
topBar := ui.TintedBar(compareColor, container.NewHBox(backBtn, layout.NewSpacer(), queueBtn))
|
||||||
bottomBar := statusBar(compareColor, state.statsBar)
|
bottomBar := moduleFooter(compareColor, layout.NewSpacer(), state.statsBar)
|
||||||
|
|
||||||
// Instructions
|
// Instructions
|
||||||
instructions := widget.NewLabel("Load two videos to compare their metadata side by side. Drag videos here or use buttons below.")
|
instructions := widget.NewLabel("Load two videos to compare their metadata side by side. Drag videos here or use buttons below.")
|
||||||
|
|
@ -10118,6 +10147,7 @@ func buildInspectView(state *appState) fyne.CanvasObject {
|
||||||
state.queueBtn = queueBtn
|
state.queueBtn = queueBtn
|
||||||
state.updateQueueButtonLabel()
|
state.updateQueueButtonLabel()
|
||||||
topBar := ui.TintedBar(inspectColor, container.NewHBox(backBtn, layout.NewSpacer(), queueBtn))
|
topBar := ui.TintedBar(inspectColor, container.NewHBox(backBtn, layout.NewSpacer(), queueBtn))
|
||||||
|
bottomBar := moduleFooter(inspectColor, layout.NewSpacer(), state.statsBar)
|
||||||
|
|
||||||
// Instructions
|
// Instructions
|
||||||
instructions := widget.NewLabel("Load a video to inspect its properties and preview playback. Drag a video here or use the button below.")
|
instructions := widget.NewLabel("Load a video to inspect its properties and preview playback. Drag a video here or use the button below.")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user