chore: release 0.10.2 with condensed panels and settings spacing fix

Bump version to 0.10.2 and document the UI density/resizing work in the
changelog. Also restructure the settings form into sections so separators
and the editable Storage fields keep normal spacing (dividers no longer
crowd the row above, entry boxes stay visibly separated) while the
label-only sections remain condensed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
mixeme
2026-06-25 01:41:02 +03:00
parent 21d78ea010
commit 8b81180c92
3 changed files with 75 additions and 24 deletions
+29
View File
@@ -2,6 +2,35 @@
All notable GoSentry changes are recorded in this file. All notable GoSentry changes are recorded in this file.
## 0.10.2 - 2026-06-25
**Condensed details/settings panels and a window that shrinks to 720p.**
**Jobs details panel:**
- Job metadata is laid out in two columns (Folder/Schedule, Command/Arguments,
Run mode/Overlap policy, Last run/Next run, State/Statistics), roughly halving
the block height.
- Metadata rows are stacked with a tight, negative-gap layout so the interval
between rows is no longer oversized.
- The command-output area's minimum height was reduced so the details pane can
get shorter; long output still scrolls.
- The "Selected job activity" panel is now sized to exactly fit
`maxJobActivityRows`, derived from `widget.List`'s own row metrics, so all
three rows are visible without a scrollbar regardless of theme or DPI.
**Settings tab:**
- The form is wrapped in a vertical scroll so it no longer dictates the window's
minimum height (tab containers size to the tallest tab); it scrolls on short
screens instead.
- Label-only sections (Application, Queue, About) are condensed, while
separators and the editable Storage fields keep normal spacing so dividers
have breathing room and entry boxes stay visibly separated.
**Window sizing:**
- Together these changes drop the minimum window height from ~891px to ~570px,
so the window can be resized noticeably shorter and fits comfortably on 720p
screens.
## 0.10.1 - 2026-06-24 ## 0.10.1 - 2026-06-24
**Refactoring:** **Refactoring:**
+1 -1
View File
@@ -3,4 +3,4 @@ package app
// Version is the application version shown in the GUI and used by build // Version is the application version shown in the GUI and used by build
// scripts in artifact names. It is a var rather than a const so release builds // scripts in artifact names. It is a var rather than a const so release builds
// can override it with Go ldflags when CI tags a build. // can override it with Go ldflags when CI tags a build.
var Version = "0.10.1" var Version = "0.10.2"
+45 -23
View File
@@ -123,37 +123,59 @@ func settingsView(w fyne.Window, svc *app.Service) fyne.CanvasObject {
settingsStatus.SetText("Saved") settingsStatus.SetText("Saved")
}) })
// The settings form is a tall fixed-height column. Wrapping it in a vertical // The form is grouped into sections in an outer VBox. The outer box keeps the
// scroll keeps its minimum height small so it does not dictate the whole // theme's normal padding, so the separators and the editable Storage fields
// window's minimum height (AppTabs sizes to the tallest tab); on short 720p // get proper breathing room; only the label-only sections are condensed with
// screens the window can shrink and the form scrolls instead. // the tight settingsSection spacing. Wrapping the whole thing in a vertical
return container.NewVScroll(container.NewPadded(container.New(compactVBoxLayout{spacing: settingsRowSpacing}, // scroll keeps its minimum height small so it does not dictate the window's
widget.NewLabelWithStyle("Application", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}), // minimum height (AppTabs sizes to the tallest tab) and it scrolls on short
settingsRowWithStatus("Autostart", startOnLogin, autostartStatus), // 720p screens.
settingsRow("Tray", container.New(minWidthLayout{width: settingsControlWidth}, minimizeToTray)), return container.NewVScroll(container.NewPadded(container.NewVBox(
settingsRow("Notifications", container.New(minWidthLayout{width: settingsControlWidth}, notifications)), settingsSection("Application",
settingsRowWithStatus("Autostart", startOnLogin, autostartStatus),
settingsRow("Tray", container.New(minWidthLayout{width: settingsControlWidth}, minimizeToTray)),
settingsRow("Notifications", container.New(minWidthLayout{width: settingsControlWidth}, notifications)),
),
widget.NewSeparator(), widget.NewSeparator(),
widget.NewLabelWithStyle("Queue", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}), settingsSection("Queue",
settingsRow("Execution mode", container.New(minWidthLayout{width: settingsControlWidth}, executionModeSelect)), settingsRow("Execution mode", container.New(minWidthLayout{width: settingsControlWidth}, executionModeSelect)),
settingsRow("Default overlap policy", container.New(minWidthLayout{width: settingsControlWidth}, overlapPolicySelect)), settingsRow("Default overlap policy", container.New(minWidthLayout{width: settingsControlWidth}, overlapPolicySelect)),
),
widget.NewSeparator(), widget.NewSeparator(),
widget.NewLabelWithStyle("Storage", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}), // Storage holds editable entry fields. It uses the default VBox spacing
settingsRow("Config YAML", widget.NewLabel(store.Paths.ConfigPath)), // (not the condensed section layout) so the entry boxes keep a visible
settingsRow("Jobs directory", container.NewBorder(nil, nil, nil, jobsDirBrowse, jobsDir)), // gap between them instead of merging into one block.
settingsRow("Logs directory", container.NewBorder(nil, nil, nil, logsDirBrowse, logsDir)), container.NewVBox(
settingsRow("Max log files", maxLogFiles), widget.NewLabelWithStyle("Storage", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
settingsRow("Max log age days", maxLogAgeDays), settingsRow("Config YAML", widget.NewLabel(store.Paths.ConfigPath)),
settingsRow("Jobs directory", container.NewBorder(nil, nil, nil, jobsDirBrowse, jobsDir)),
settingsRow("Logs directory", container.NewBorder(nil, nil, nil, logsDirBrowse, logsDir)),
settingsRow("Max log files", maxLogFiles),
settingsRow("Max log age days", maxLogAgeDays),
),
saveSettings, saveSettings,
settingsStatus, settingsStatus,
widget.NewSeparator(), widget.NewSeparator(),
widget.NewLabelWithStyle("About", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}), settingsSection("About",
settingsRow("GoSentry", widget.NewLabel(app.Version)), settingsRow("GoSentry", widget.NewLabel(app.Version)),
settingsRow("Go", widget.NewLabel(runtime.Version())), settingsRow("Go", widget.NewLabel(runtime.Version())),
settingsRow("Fyne", widget.NewLabel(fyneVersion())), settingsRow("Fyne", widget.NewLabel(fyneVersion())),
settingsRow("Repository", widget.NewHyperlink(projectRepositoryURL, mustParseURL(projectRepositoryURL))), settingsRow("Repository", widget.NewHyperlink(projectRepositoryURL, mustParseURL(projectRepositoryURL))),
),
))) )))
} }
// settingsSection groups a bold header above its rows using the tight
// settingsRowSpacing so a block of label rows reads as one compact unit. The
// caller keeps separators and entry-heavy sections in the surrounding VBox so
// they retain the theme's normal spacing.
func settingsSection(title string, rows ...fyne.CanvasObject) fyne.CanvasObject {
children := make([]fyne.CanvasObject, 0, len(rows)+1)
children = append(children, widget.NewLabelWithStyle(title, fyne.TextAlignLeading, fyne.TextStyle{Bold: true}))
children = append(children, rows...)
return container.New(compactVBoxLayout{spacing: settingsRowSpacing}, children...)
}
func fyneVersion() string { func fyneVersion() string {
info, ok := debug.ReadBuildInfo() info, ok := debug.ReadBuildInfo()
if !ok { if !ok {