From dad5d34d34bb0d7b59a11b16fc72c3ad5d1980df Mon Sep 17 00:00:00 2001 From: Stu Leak Date: Thu, 18 Dec 2025 18:02:03 -0500 Subject: [PATCH] Add 'In Progress' tab to history sidebar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Features: - New "In Progress" tab shows running/pending jobs - Displays active jobs without opening full queue - Tab positioned first for quick visibility - Shows "Running..." or "Pending" status - No delete button on active jobs (only completed/failed) Implementation: - Updated BuildHistorySidebar to accept activeJobs parameter - Converts queue.Job to ui.HistoryEntry for display - Filters running/pending jobs from queue - Conditional delete button (nil check) - Dynamic status text based on job state UX Improvements: - Quick glance at current activity without queue view - Three-tab layout: In Progress → Completed → Failed - Consistent styling with existing history entries - Tappable entries to view full job details This allows users to monitor active conversions directly from the history sidebar, reducing the need to constantly check the full job queue view. --- internal/ui/mainmenu.go | 42 ++++++++++++++++++++++++++++++----------- main.go | 25 ++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 11 deletions(-) diff --git a/internal/ui/mainmenu.go b/internal/ui/mainmenu.go index 221f5f3..0a68a17 100644 --- a/internal/ui/mainmenu.go +++ b/internal/ui/mainmenu.go @@ -153,6 +153,7 @@ func sortedKeys(m map[string][]fyne.CanvasObject) []string { // BuildHistorySidebar creates the history sidebar with tabs func BuildHistorySidebar( entries []HistoryEntry, + activeJobs []HistoryEntry, onEntryClick func(HistoryEntry), onEntryDelete func(HistoryEntry), titleColor, bgColor, textColor color.Color, @@ -168,11 +169,13 @@ func BuildHistorySidebar( } // Build lists + inProgressList := buildHistoryList(activeJobs, onEntryClick, nil, bgColor, textColor) // No delete for active jobs completedList := buildHistoryList(completedEntries, onEntryClick, onEntryDelete, bgColor, textColor) failedList := buildHistoryList(failedEntries, onEntryClick, onEntryDelete, bgColor, textColor) - // Tabs + // Tabs - In Progress first for quick visibility tabs := container.NewAppTabs( + container.NewTabItem("In Progress", container.NewVScroll(inProgressList)), container.NewTabItem("Completed", container.NewVScroll(completedList)), container.NewTabItem("Failed", container.NewVScroll(failedList)), ) @@ -220,20 +223,37 @@ func buildHistoryItem( // Capture entry for closures capturedEntry := entry - // Delete button - small "×" button - deleteBtn := widget.NewButton("×", func() { - onEntryDelete(capturedEntry) - }) - deleteBtn.Importance = widget.LowImportance + // Build header row with badge and optional delete button + headerItems := []fyne.CanvasObject{badge, layout.NewSpacer()} + if onEntryDelete != nil { + // Delete button - small "×" button (only for completed/failed) + deleteBtn := widget.NewButton("×", func() { + onEntryDelete(capturedEntry) + }) + deleteBtn.Importance = widget.LowImportance + headerItems = append(headerItems, deleteBtn) + } // Title titleLabel := widget.NewLabel(utils.ShortenMiddle(entry.Title, 25)) titleLabel.TextStyle = fyne.TextStyle{Bold: true} - // Timestamp - timeStr := "Unknown" - if entry.CompletedAt != nil { - timeStr = entry.CompletedAt.Format("Jan 2, 15:04") + // Timestamp or status info + var timeStr string + if entry.Status == queue.JobStatusRunning || entry.Status == queue.JobStatusPending { + // For in-progress jobs, show status + if entry.Status == queue.JobStatusRunning { + timeStr = "Running..." + } else { + timeStr = "Pending" + } + } else { + // For completed/failed jobs, show timestamp + if entry.CompletedAt != nil { + timeStr = entry.CompletedAt.Format("Jan 2, 15:04") + } else { + timeStr = "Unknown" + } } timeLabel := widget.NewLabel(timeStr) timeLabel.TextStyle = fyne.TextStyle{Monospace: true} @@ -246,7 +266,7 @@ func buildHistoryItem( content := container.NewBorder( nil, nil, statusRect, nil, container.NewVBox( - container.NewHBox(badge, layout.NewSpacer(), deleteBtn), + container.NewHBox(headerItems...), titleLabel, timeLabel, ), diff --git a/main.go b/main.go index 43fe038..a1e2d21 100644 --- a/main.go +++ b/main.go @@ -1372,8 +1372,33 @@ func (s *appState) showMainMenu() { // Build sidebar if visible var sidebar fyne.CanvasObject if s.sidebarVisible { + // Get active jobs from queue (running/pending) + var activeJobs []ui.HistoryEntry + if s.jobQueue != nil { + for _, job := range s.jobQueue.List() { + if job.Status == queue.JobStatusRunning || job.Status == queue.JobStatusPending { + // Convert queue.Job to ui.HistoryEntry + entry := ui.HistoryEntry{ + ID: job.ID, + Type: job.Type, + Status: job.Status, + Title: job.Title, + InputFile: job.InputFile, + OutputFile: job.OutputFile, + LogPath: job.LogPath, + Config: job.Config, + CreatedAt: job.CreatedAt, + StartedAt: job.StartedAt, + Error: job.Error, + } + activeJobs = append(activeJobs, entry) + } + } + } + sidebar = ui.BuildHistorySidebar( s.historyEntries, + activeJobs, s.showHistoryDetails, s.deleteHistoryEntry, titleColor,