feat(gui): enhance application UI with new status segments and improved layout
Tests / Go and GTK tests (push) Failing after 2m14s

- Refactor status bar to include separate labels for source, speech, and outputs.
- Update buildWindow method to adjust layout and styling of status elements.
- Introduce new text tags for console and caption buffers to improve text rendering.
- Modify settings controls to use CheckButton instead of Switch for better clarity.
- Revise CSS styles for improved visual consistency and responsiveness across UI elements.
This commit is contained in:
2026-07-17 15:34:50 +03:00
parent 54fb100d3c
commit 04ad4eb3d9
5 changed files with 604 additions and 186 deletions
+38 -19
View File
@@ -61,14 +61,21 @@ type Application struct {
statusLabel *gtk.Label
statusDot *gtk.Label
startStopButton *gtk.Button
statusbarLabel *gtk.Label
statusSource *gtk.Label
statusSpeech *gtk.Label
statusOutputs *gtk.Label
captionBuffer *gtk.TextBuffer
captionView *gtk.TextView
captionScroll *gtk.ScrolledWindow
captionMetaTag *gtk.TextTag
captionHintTag *gtk.TextTag
provisionalLabel *gtk.Label
consoleBuffer *gtk.TextBuffer
consoleView *gtk.TextView
consoleScroll *gtk.ScrolledWindow
consoleMetaTag *gtk.TextTag
consoleWarnTag *gtk.TextTag
consoleErrorTag *gtk.TextTag
settings settingsControls
settingsError *gtk.Label
applyButton *gtk.Button
@@ -177,7 +184,7 @@ func (a *Application) buildWindow() {
brand := gtk.NewBox(gtk.OrientationHorizontal, 7)
if iconPath := findIconPath(); iconPath != "" {
icon := gtk.NewImageFromFile(iconPath)
icon.SetPixelSize(27)
icon.SetPixelSize(20)
brand.Append(icon)
}
title := gtk.NewLabel("CAPTIONEER")
@@ -187,6 +194,7 @@ func (a *Application) buildWindow() {
statusBox := gtk.NewBox(gtk.OrientationHorizontal, 6)
statusBox.SetHAlign(gtk.AlignCenter)
statusBox.AddCSSClass("status-cell")
a.statusDot = gtk.NewLabel("●")
a.statusDot.AddCSSClass("status-dot")
a.statusLabel = gtk.NewLabel("STOPPED · VAD")
@@ -211,21 +219,28 @@ func (a *Application) buildWindow() {
tabs := gtk.NewStackSwitcher()
tabs.SetStack(a.stack)
tabs.AddCSSClass("captioneer-tabs")
tabs.SetHAlign(gtk.AlignFill)
root.Append(tabs)
tabs.SetHAlign(gtk.AlignStart)
tabStrip := gtk.NewBox(gtk.OrientationHorizontal, 0)
tabStrip.AddCSSClass("captioneer-tabs")
tabStrip.Append(tabs)
root.Append(tabStrip)
a.stack.AddTitled(a.buildCaptionsPage(), "captions", "CAPTIONS")
a.stack.AddTitled(a.buildConsolePage(), "console", "CONSOLE")
a.stack.AddTitled(a.buildSettingsPage(), "settings", "SETTINGS")
root.Append(a.stack)
statusbar := gtk.NewBox(gtk.OrientationHorizontal, 8)
statusbar := gtk.NewBox(gtk.OrientationHorizontal, 4)
statusbar.AddCSSClass("statusbar")
a.statusbarLabel = gtk.NewLabel("Source: not connected · Speech: quiet · Outputs: preparing")
a.statusbarLabel.SetXAlign(0)
a.statusbarLabel.SetEllipsize(3)
statusbar.Append(a.statusbarLabel)
a.statusSource = statusSegment("Source: not connected")
a.statusSource.SetHExpand(true)
a.statusSource.SetXAlign(0)
a.statusSource.SetEllipsize(3)
a.statusSpeech = statusSegment("Speech: quiet")
a.statusOutputs = statusSegment("Outputs: preparing")
statusbar.Append(a.statusSource)
statusbar.Append(a.statusSpeech)
statusbar.Append(a.statusOutputs)
root.Append(statusbar)
a.window.SetChild(root)
}
@@ -479,17 +494,15 @@ func (a *Application) renderStatus(status app.Status) {
if source == "" {
source = "not connected"
}
overload := ""
if overloaded {
overload = " · OVERLOADED"
speech += " · OVERLOADED"
a.statusSpeech.AddCSSClass("warning-text")
} else {
a.statusSpeech.RemoveCSSClass("warning-text")
}
a.statusbarLabel.SetText(fmt.Sprintf(
"Source: %s · Speech: %s · Outputs: %s%s",
source,
speech,
a.outputSummary(),
overload,
))
a.statusSource.SetText("Source: " + source)
a.statusSpeech.SetText("Speech: " + speech)
a.statusOutputs.SetText("Outputs: " + a.outputSummary())
if status.LastError != "" && status.State == app.StateError && status.LastError != a.lastShownError {
a.log.Add(diagnostics.Error, "engine", status.LastError)
a.lastShownError = status.LastError
@@ -573,6 +586,12 @@ func (a *Application) shutdown() {
}()
}
func statusSegment(text string) *gtk.Label {
label := gtk.NewLabel(text)
label.AddCSSClass("status-segment")
return label
}
func joinError(current, next error) error {
if current == nil {
return next