Fix queue buttons, log viewer hang, and Windows console flashing

Queue UI:
- Fix pending job button labels - now shows "Remove" instead of "Cancel"
- Running/paused jobs still correctly show "Cancel" button

Log Viewer:
- Fix app hanging when viewing large conversion logs
- Make file reads asynchronous to prevent blocking UI thread
- Show "Loading log file..." message while reading
- Auto-scroll to bottom when log opens

Windows Console Flashing:
- Add ApplyNoWindow to all missing exec.Command calls
- Fixes command prompt windows flashing during module operations
- Applied to: hwaccel detection, encoder checks, Python backend detection
- Prevents console windows from appearing during upscale module usage

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Stu Leak 2025-12-21 15:59:30 -05:00
parent 6835b6d69d
commit 93ec8c7b15
2 changed files with 43 additions and 25 deletions

View File

@ -277,7 +277,7 @@ func buildJobItem(
case queue.JobStatusPending:
buttons = append(buttons,
widget.NewButton("Copy Command", func() { onCopyCommand(job.ID) }),
widget.NewButton("Cancel", func() { onCancel(job.ID) }),
widget.NewButton("Remove", func() { onRemove(job.ID) }),
)
case queue.JobStatusCompleted, queue.JobStatusFailed, queue.JobStatusCancelled:
if job.Status == queue.JobStatusFailed && strings.TrimSpace(job.Error) != "" && onCopyError != nil {

66
main.go
View File

@ -248,6 +248,7 @@ func hwAccelAvailable(accel string) bool {
hwAccelProbeOnce.Do(func() {
supported := make(map[string]bool)
cmd := exec.Command("ffmpeg", "-hide_banner", "-v", "error", "-hwaccels")
utils.ApplyNoWindow(cmd)
output, err := cmd.Output()
if err != nil {
hwAccelSupported.Store(supported)
@ -313,14 +314,10 @@ func (s *appState) openLogViewer(title, path string, live bool) {
dialog.ShowInformation("No Log", "No log available.", s.window)
return
}
data, err := os.ReadFile(path)
if err != nil {
dialog.ShowError(fmt.Errorf("failed to read log: %w", err), s.window)
return
}
// Create UI elements first
text := widget.NewMultiLineEntry()
text.SetText(string(data))
text.SetText("Loading log file...")
text.Wrapping = fyne.TextWrapWord
text.TextStyle = fyne.TextStyle{Monospace: true}
text.Disable()
@ -330,8 +327,39 @@ func (s *appState) openLogViewer(title, path string, live bool) {
scroll.SetMinSize(fyne.NewSize(600, 350))
stop := make(chan struct{})
if live {
go func() {
var d dialog.Dialog
closeBtn := widget.NewButton("Close", func() {
if d != nil {
d.Hide()
}
})
copyBtn := widget.NewButton("Copy All", func() {
s.window.Clipboard().SetContent(text.Text)
})
buttons := container.NewHBox(copyBtn, layout.NewSpacer(), closeBtn)
content := container.NewBorder(nil, buttons, nil, nil, scroll)
d = dialog.NewCustom(title, "Close", content, s.window)
d.SetOnClosed(func() { close(stop) })
d.Show()
// Read file asynchronously to avoid blocking UI
go func() {
data, err := os.ReadFile(path)
if err != nil {
fyne.CurrentApp().Driver().DoFromGoroutine(func() {
text.SetText(fmt.Sprintf("Failed to read log: %v", err))
}, false)
return
}
fyne.CurrentApp().Driver().DoFromGoroutine(func() {
text.SetText(string(data))
// Auto-scroll to bottom
scroll.ScrollToBottom()
}, false)
// Start live updates if requested
if live {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
@ -349,23 +377,8 @@ func (s *appState) openLogViewer(title, path string, live bool) {
}, false)
}
}
}()
}
var d dialog.Dialog
closeBtn := widget.NewButton("Close", func() {
if d != nil {
d.Hide()
}
})
copyBtn := widget.NewButton("Copy All", func() {
s.window.Clipboard().SetContent(text.Text)
})
buttons := container.NewHBox(copyBtn, layout.NewSpacer(), closeBtn)
content := container.NewBorder(nil, buttons, nil, nil, scroll)
d = dialog.NewCustom(title, "Close", content, s.window)
d.SetOnClosed(func() { close(stop) })
d.Show()
}()
}
// openFolder tries to open a folder in the OS file browser.
@ -1976,6 +1989,7 @@ func (s *appState) detectHardwareEncoders() []string {
for _, encoder := range encodersToCheck {
cmd := exec.Command(platformConfig.FFmpegPath, "-hide_banner", "-encoders")
utils.ApplyNoWindow(cmd)
output, err := cmd.CombinedOutput()
if err == nil && strings.Contains(string(output), encoder) {
available = append(available, encoder)
@ -13765,11 +13779,13 @@ func detectAIUpscaleBackend() string {
}
cmd := exec.Command("python3", "-c", "import realesrgan")
utils.ApplyNoWindow(cmd)
if err := cmd.Run(); err == nil {
return "python"
}
cmd = exec.Command("python", "-c", "import realesrgan")
utils.ApplyNoWindow(cmd)
if err := cmd.Run(); err == nil {
return "python"
}
@ -13783,10 +13799,12 @@ func checkAIFaceEnhanceAvailable(backend string) bool {
return false
}
cmd := exec.Command("python3", "-c", "import realesrgan, gfpgan")
utils.ApplyNoWindow(cmd)
if err := cmd.Run(); err == nil {
return true
}
cmd = exec.Command("python", "-c", "import realesrgan, gfpgan")
utils.ApplyNoWindow(cmd)
return cmd.Run() == nil
}