feat(ui): content-measured History columns, shared caption widths, settings_view split

Stage 5: generalize logColumnWidth into textColumnWidth so History's
Trigger/Job/State/Detail/Log columns size from measured text instead of
pixel constants that clipped at larger text sizes (F6, F14).

Stage 6: captionColumnWidth replaces detailCaptionWidth and
settingsLabelWidth with one theme-derived helper; jobs_view_details.go
now builds its metadata rows and their width from a single
metadataRows() list instead of two hand-kept ones (F10); the Settings
button row drops its transparent-rectangle spacers for a
CustomPaddedLayout (F8); the remaining eight fyne.TextTruncate call
sites move to the non-deprecated Truncation field (N1).

Stage 7: settings_view.go split into settings_view.go (field
construction/save/load/validate), settings_view_layout.go (the
two-column layout and settingsSection/settingsRow), and
settings_view_helpers.go (fyneVersion, dialogs, path helpers),
mirroring the jobs_view.go split. Along the way, Queue/Storage's inline
VBox and Application/About's settingsSection collapse into one
settingsSection(title, spacing, rows...) constructor, and
chooseFile/chooseJSONFile merge into one function with a filter
argument.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
mixeme
2026-07-27 16:26:13 +03:00
parent 57e6fe410e
commit cebd41a5ac
12 changed files with 621 additions and 269 deletions
+25 -2
View File
@@ -35,8 +35,8 @@ func TestFolderOptionsAlwaysIncludesSentinels(t *testing.T) {
func TestFolderOptionsAppendsUniqueFolders(t *testing.T) {
jobs := []domain.Job{
{Folder: "Maintenance"},
{Folder: ""}, // no folder → not a named folder
{Folder: " Backups "}, // trimmed to "Backups"
{Folder: ""}, // no folder → not a named folder
{Folder: " Backups "}, // trimmed to "Backups"
{Folder: "Maintenance"}, // duplicate → not added again
}
opts := folderOptions(jobs)
@@ -412,6 +412,29 @@ func TestToolbarButtonRedrawsRowAndDetails(t *testing.T) {
}
}
// TestDetailCaptionWidthCoversEveryCaption is the guard that makes the single
// metadataRows list self-enforcing (F10): every caption it returns must
// measure no wider than captionColumnWidth's result for that same list, or a
// row added to metadataRows without updating the width measurement would
// silently truncate.
func TestDetailCaptionWidthCoversEveryCaption(t *testing.T) {
testApp := test.NewApp()
defer testApp.Quit()
d := newDetailsPanel(job{}, &domain.JobRuntime{}, domain.OverlapPolicySkip, 0)
specs := d.metadataRows()
captions := make([]string, len(specs))
for i, spec := range specs {
captions[i] = spec.caption
}
capW := captionColumnWidth(captions...)
for _, c := range captions {
if w := widget.NewLabelWithStyle(c, fyne.TextAlignLeading, fyne.TextStyle{Bold: true}).MinSize().Width; w > capW {
t.Errorf("caption %q measures %v, wider than captionColumnWidth's %v", c, w, capW)
}
}
}
func TestViewToggleTextNamesTheAction(t *testing.T) {
cases := []struct {
current domain.JobListView