feat(gui): enhance application UI with new status segments and improved layout
Tests / Go and GTK tests (push) Failing after 2m14s
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:
+64
-5
@@ -6,9 +6,11 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/diamondburned/gotk4/pkg/gdk/v4"
|
||||
"github.com/diamondburned/gotk4/pkg/gtk/v4"
|
||||
"tea.chunkbyte.com/kato/captioneer/src/diagnostics"
|
||||
"tea.chunkbyte.com/kato/captioneer/src/output/history"
|
||||
)
|
||||
|
||||
@@ -35,6 +37,8 @@ func (a *Application) buildCaptionsPage() *gtk.Box {
|
||||
page.Append(toolbar)
|
||||
|
||||
a.captionBuffer = gtk.NewTextBuffer(nil)
|
||||
a.captionMetaTag = bufferTag(a.captionBuffer, "meta", "#8A9384")
|
||||
a.captionHintTag = bufferTag(a.captionBuffer, "hint", "#6E7763")
|
||||
a.captionView = gtk.NewTextViewWithBuffer(a.captionBuffer)
|
||||
a.captionView.SetEditable(false)
|
||||
a.captionView.SetCursorVisible(true)
|
||||
@@ -54,8 +58,9 @@ func (a *Application) buildCaptionsPage() *gtk.Box {
|
||||
|
||||
provisional := gtk.NewBox(gtk.OrientationHorizontal, 8)
|
||||
provisional.AddCSSClass("provisional-row")
|
||||
caption := labelWithClass("LIVE", "section-title")
|
||||
caption := labelWithClass("LIVE", "live-tag")
|
||||
caption.SetVAlign(gtk.AlignStart)
|
||||
caption.SetMarginTop(2)
|
||||
provisional.Append(caption)
|
||||
a.provisionalLabel = gtk.NewLabel("Waiting for speech…")
|
||||
a.provisionalLabel.SetXAlign(0)
|
||||
@@ -93,6 +98,9 @@ func (a *Application) buildConsolePage() *gtk.Box {
|
||||
page.Append(toolbar)
|
||||
|
||||
a.consoleBuffer = gtk.NewTextBuffer(nil)
|
||||
a.consoleMetaTag = bufferTag(a.consoleBuffer, "meta", "#79826F")
|
||||
a.consoleWarnTag = bufferTag(a.consoleBuffer, "warn", "#C79C4E")
|
||||
a.consoleErrorTag = bufferTag(a.consoleBuffer, "error", "#CF826D")
|
||||
a.consoleView = gtk.NewTextViewWithBuffer(a.consoleBuffer)
|
||||
a.consoleView.SetEditable(false)
|
||||
a.consoleView.SetCursorVisible(true)
|
||||
@@ -113,18 +121,44 @@ func (a *Application) buildConsolePage() *gtk.Box {
|
||||
return page
|
||||
}
|
||||
|
||||
// tagSpan marks a character range of freshly rendered buffer text so a
|
||||
// TextTag can be applied after SetText replaces the whole buffer.
|
||||
type tagSpan struct {
|
||||
tag *gtk.TextTag
|
||||
start, end int
|
||||
}
|
||||
|
||||
func applyTagSpans(buffer *gtk.TextBuffer, spans []tagSpan) {
|
||||
for _, span := range spans {
|
||||
buffer.ApplyTag(span.tag, buffer.IterAtOffset(span.start), buffer.IterAtOffset(span.end))
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Application) renderHistory(snapshot history.Snapshot) {
|
||||
follow := isAtBottom(a.captionScroll)
|
||||
var text strings.Builder
|
||||
var spans []tagSpan
|
||||
offset := 0
|
||||
if len(snapshot.Finals) == 0 {
|
||||
hint := "No captions yet. Press START to begin listening."
|
||||
text.WriteString(hint)
|
||||
spans = append(spans, tagSpan{a.captionHintTag, 0, utf8.RuneCountInString(hint)})
|
||||
}
|
||||
for _, entry := range snapshot.Finals {
|
||||
fmt.Fprintf(&text, "%s [%s–%s] %s\n",
|
||||
meta := fmt.Sprintf("%s [%s–%s] ",
|
||||
entry.CreatedAt.Format("15:04:05"),
|
||||
formatCaptionTime(entry.StartedAt),
|
||||
formatCaptionTime(entry.EndedAt),
|
||||
entry.Text,
|
||||
)
|
||||
text.WriteString(meta)
|
||||
spans = append(spans, tagSpan{a.captionMetaTag, offset, offset + utf8.RuneCountInString(meta)})
|
||||
offset += utf8.RuneCountInString(meta)
|
||||
line := entry.Text + "\n"
|
||||
text.WriteString(line)
|
||||
offset += utf8.RuneCountInString(line)
|
||||
}
|
||||
a.captionBuffer.SetText(text.String())
|
||||
applyTagSpans(a.captionBuffer, spans)
|
||||
if snapshot.Provisional == nil || strings.TrimSpace(snapshot.Provisional.Text) == "" {
|
||||
a.provisionalLabel.SetText("Waiting for speech…")
|
||||
} else {
|
||||
@@ -138,15 +172,33 @@ func (a *Application) renderHistory(snapshot history.Snapshot) {
|
||||
func (a *Application) renderConsole() {
|
||||
follow := isAtBottom(a.consoleScroll)
|
||||
var text strings.Builder
|
||||
var spans []tagSpan
|
||||
offset := 0
|
||||
for _, entry := range a.log.Entries() {
|
||||
fmt.Fprintf(&text, "%s %-7s %-14s %s\n",
|
||||
var severityTag *gtk.TextTag
|
||||
switch entry.Severity {
|
||||
case diagnostics.Warning:
|
||||
severityTag = a.consoleWarnTag
|
||||
case diagnostics.Error:
|
||||
severityTag = a.consoleErrorTag
|
||||
}
|
||||
meta := fmt.Sprintf("%s %-7s %-14s ",
|
||||
entry.At.Format("15:04:05.000"),
|
||||
strings.ToUpper(string(entry.Severity)),
|
||||
"["+entry.Category+"]",
|
||||
entry.Message,
|
||||
)
|
||||
text.WriteString(meta)
|
||||
spans = append(spans, tagSpan{a.consoleMetaTag, offset, offset + utf8.RuneCountInString(meta)})
|
||||
offset += utf8.RuneCountInString(meta)
|
||||
line := entry.Message + "\n"
|
||||
text.WriteString(line)
|
||||
if severityTag != nil {
|
||||
spans = append(spans, tagSpan{severityTag, offset, offset + utf8.RuneCountInString(entry.Message)})
|
||||
}
|
||||
offset += utf8.RuneCountInString(line)
|
||||
}
|
||||
a.consoleBuffer.SetText(text.String())
|
||||
applyTagSpans(a.consoleBuffer, spans)
|
||||
if follow {
|
||||
scrollTextViewToEnd(a.consoleView, a.consoleScroll)
|
||||
}
|
||||
@@ -193,6 +245,13 @@ func copyBuffer(buffer *gtk.TextBuffer) {
|
||||
gdk.DisplayGetDefault().Clipboard().SetText(buffer.Text(start, end, true))
|
||||
}
|
||||
|
||||
func bufferTag(buffer *gtk.TextBuffer, name, foreground string) *gtk.TextTag {
|
||||
tag := gtk.NewTextTag(name)
|
||||
tag.SetObjectProperty("foreground", foreground)
|
||||
buffer.TagTable().Add(tag)
|
||||
return tag
|
||||
}
|
||||
|
||||
func labelWithClass(text, class string) *gtk.Label {
|
||||
label := gtk.NewLabel(text)
|
||||
label.AddCSSClass(class)
|
||||
|
||||
Reference in New Issue
Block a user