From f94629e55e7dc9ed3e88cbbbb69909f15279bfc6 Mon Sep 17 00:00:00 2001 From: Stu Leak Date: Wed, 10 Dec 2025 15:46:18 -0500 Subject: [PATCH] Add in-module cancel for running jobs --- internal/queue/queue.go | 13 +++++++++++++ main.go | 32 +++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/internal/queue/queue.go b/internal/queue/queue.go index f9a26c0..f6db560 100644 --- a/internal/queue/queue.go +++ b/internal/queue/queue.go @@ -186,6 +186,19 @@ func (q *Queue) Stats() (pending, running, completed, failed int) { return } +// CurrentRunning returns the currently running job, if any. +func (q *Queue) CurrentRunning() *Job { + q.mu.RLock() + defer q.mu.RUnlock() + for _, job := range q.jobs { + if job.Status == JobStatusRunning { + clone := *job + return &clone + } + } + return nil +} + // Pause pauses a running job func (q *Queue) Pause(id string) error { q.mu.Lock() diff --git a/main.go b/main.go index d887fa7..c234620 100644 --- a/main.go +++ b/main.go @@ -4465,12 +4465,32 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject { } var convertBtn *widget.Button var cancelBtn *widget.Button + var cancelQueueBtn *widget.Button cancelBtn = widget.NewButton("Cancel", func() { state.cancelConvert(cancelBtn, convertBtn, activity, statusLabel) }) cancelBtn.Importance = widget.DangerImportance cancelBtn.Disable() + cancelQueueBtn = widget.NewButton("Cancel Active Job", func() { + if state.jobQueue == nil { + dialog.ShowInformation("Cancel", "Queue not initialized.", state.window) + return + } + job := state.jobQueue.CurrentRunning() + if job == nil { + dialog.ShowInformation("Cancel", "No running job to cancel.", state.window) + return + } + if err := state.jobQueue.Cancel(job.ID); err != nil { + dialog.ShowError(fmt.Errorf("failed to cancel job: %w", err), state.window) + return + } + dialog.ShowInformation("Cancelled", fmt.Sprintf("Cancelled job: %s", job.Title), state.window) + }) + cancelQueueBtn.Importance = widget.DangerImportance + cancelQueueBtn.Disable() + // Add to Queue button addQueueBtn := widget.NewButton("Add to Queue", func() { state.persistConvertConfig() @@ -4594,7 +4614,7 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject { leftControls := container.NewHBox(resetBtn, loadCfgBtn, saveCfgBtn, autoCompareCheck) centerStatus := container.NewHBox(activity, statusLabel) - rightControls := container.NewHBox(cancelBtn, viewLogBtn, addQueueBtn, convertBtn) + rightControls := container.NewHBox(cancelBtn, cancelQueueBtn, viewLogBtn, addQueueBtn, convertBtn) actionInner := container.NewBorder(nil, nil, leftControls, rightControls, centerStatus) actionBar := ui.TintedBar(convertColor, actionInner) @@ -4626,6 +4646,11 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject { if isBusy { convertBtn.Disable() cancelBtn.Enable() + if state.jobQueue != nil && state.jobQueue.CurrentRunning() != nil { + cancelQueueBtn.Enable() + } else { + cancelQueueBtn.Disable() + } activity.Show() if !activity.Running() { activity.Start() @@ -4637,6 +4662,11 @@ func buildConvertView(state *appState, src *videoSource) fyne.CanvasObject { convertBtn.Disable() } cancelBtn.Disable() + if state.jobQueue != nil && state.jobQueue.CurrentRunning() != nil { + cancelQueueBtn.Enable() + } else { + cancelQueueBtn.Disable() + } activity.Stop() activity.Hide() }