Add unit selector for target file size

This commit is contained in:
Stu Leak 2025-12-20 13:35:39 -05:00
parent 43efc84bf6
commit 121a61d627
4 changed files with 94 additions and 13 deletions

View File

@ -767,6 +767,7 @@ This file tracks completed features, fixes, and milestones.
- ✅ Fixed aspect ratio default from 16:9 to Source (dev7)
- ✅ Ranked benchmark results by score and added cancel confirmation
- ✅ Added estimated audio bitrate fallback when metadata is missing
- ✅ Made target file size input unit-selectable with numeric-only entry
- ✅ Stabilized video seeking and embedded rendering
- ✅ Improved player window positioning
- ✅ Fixed clear video functionality

View File

@ -42,6 +42,7 @@ This file tracks upcoming features, improvements, and known issues.
- Dynamic dropdown based on codec
- Lossless + Target Size mode support
- Audio bitrate estimation when metadata is missing
- Target size unit selector and numeric entry
## Priority Features for dev20+

View File

@ -217,15 +217,18 @@ func ParseFileSize(sizeStr string) (int64, error) {
if err != nil {
return 0, fmt.Errorf("invalid size format: %s", sizeStr)
}
if unit == "" {
unit = "MB"
}
// Convert to bytes
multiplier := int64(1)
switch unit {
case "KB":
case "K", "KB":
multiplier = 1024
case "MB":
case "M", "MB":
multiplier = 1024 * 1024
case "GB":
case "G", "GB":
multiplier = 1024 * 1024 * 1024
case "B", "":
multiplier = 1

96
main.go
View File

@ -5966,7 +5966,61 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
// Target File Size with smart presets + manual entry
targetFileSizeEntry = widget.NewEntry()
targetFileSizeEntry.SetPlaceHolder("e.g., 25MB, 100MB, 8MB")
targetFileSizeEntry.SetPlaceHolder("e.g., 250")
targetFileSizeUnitSelect := widget.NewSelect([]string{"KB", "MB", "GB"}, func(value string) {})
targetFileSizeUnitSelect.SetSelected("MB")
targetSizeManualRow := container.NewBorder(nil, nil, nil, targetFileSizeUnitSelect, targetFileSizeEntry)
parseSizeParts := func(input string) (string, string, bool) {
trimmed := strings.TrimSpace(input)
if trimmed == "" {
return "", "", false
}
upper := strings.ToUpper(trimmed)
var num float64
var unit string
if _, err := fmt.Sscanf(upper, "%f%s", &num, &unit); err != nil {
return "", "", false
}
numStr := strconv.FormatFloat(num, 'f', -1, 64)
return numStr, unit, true
}
updateTargetSizeState := func() {
val := strings.TrimSpace(targetFileSizeEntry.Text)
if val == "" {
state.convert.TargetFileSize = ""
return
}
if num, unit, ok := parseSizeParts(val); ok && unit != "" {
if num != val {
targetFileSizeEntry.SetText(num)
return
}
if unit != targetFileSizeUnitSelect.Selected {
targetFileSizeUnitSelect.SetSelected(unit)
return
}
val = num
}
unit := targetFileSizeUnitSelect.Selected
if unit == "" {
unit = "MB"
targetFileSizeUnitSelect.SetSelected(unit)
}
state.convert.TargetFileSize = val + unit
logging.Debug(logging.CatUI, "target file size set to %s", state.convert.TargetFileSize)
if buildCommandPreview != nil {
buildCommandPreview()
}
}
targetFileSizeUnitSelect.OnChanged = func(value string) {
if targetFileSizeEntry.Hidden {
return
}
updateTargetSizeState()
}
updateTargetSizeOptions := func() {
if src == nil {
@ -6010,8 +6064,17 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
targetFileSizeSelect = widget.NewSelect([]string{"Manual", "25MB", "50MB", "100MB", "200MB", "500MB", "1GB"}, func(value string) {
if value == "Manual" {
targetFileSizeEntry.Show()
targetFileSizeEntry.SetText(state.convert.TargetFileSize)
targetSizeManualRow.Show()
if state.convert.TargetFileSize != "" {
if num, unit, ok := parseSizeParts(state.convert.TargetFileSize); ok {
targetFileSizeEntry.SetText(num)
if unit != "" {
targetFileSizeUnitSelect.SetSelected(unit)
}
} else {
targetFileSizeEntry.SetText(state.convert.TargetFileSize)
}
}
} else {
// Extract size from selection (handle "XMB (Y% smaller)" format)
var sizeStr string
@ -6023,19 +6086,32 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
sizeStr = value
}
state.convert.TargetFileSize = sizeStr
targetFileSizeEntry.SetText(sizeStr)
targetFileSizeEntry.Hide()
if num, unit, ok := parseSizeParts(sizeStr); ok {
targetFileSizeEntry.SetText(num)
if unit != "" {
targetFileSizeUnitSelect.SetSelected(unit)
}
} else {
targetFileSizeEntry.SetText(sizeStr)
}
targetSizeManualRow.Hide()
}
logging.Debug(logging.CatUI, "target file size set to %s", state.convert.TargetFileSize)
})
targetFileSizeSelect.SetSelected("Manual")
updateTargetSizeOptions()
targetFileSizeEntry.SetText(state.convert.TargetFileSize)
targetFileSizeEntry.OnChanged = func(val string) {
state.convert.TargetFileSize = val
if buildCommandPreview != nil {
buildCommandPreview()
updateTargetSizeState()
}
if state.convert.TargetFileSize != "" {
if num, unit, ok := parseSizeParts(state.convert.TargetFileSize); ok {
targetFileSizeEntry.SetText(num)
if unit != "" {
targetFileSizeUnitSelect.SetSelected(unit)
}
} else {
targetFileSizeEntry.SetText(state.convert.TargetFileSize)
}
}
@ -6043,7 +6119,7 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject {
targetSizeContainer = container.NewVBox(
widget.NewLabelWithStyle("Target File Size", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
targetFileSizeSelect,
targetFileSizeEntry,
targetSizeManualRow,
)
encodingHint := widget.NewLabel("")