ui: wire automata background, add clock + session specifier + form card

- Automata.Frame() rendered as base layer, form card overlaid via ANSI
  cursor positioning with dark background for readability
- Clock widget showing datetime (Mon Jan 02 15:04:05) in top bar
- Session type label (x11/wayland) shown above switcher selection
This commit is contained in:
2026-07-19 01:54:40 +05:30
parent a911adf284
commit d7c9951d6b

View File

@@ -438,6 +438,9 @@ var (
infoCol = lipgloss.Color("3") // yellow infoCol = lipgloss.Color("3") // yellow
greenCol = lipgloss.Color("2") // green greenCol = lipgloss.Color("2") // green
cardBg = lipgloss.Color("0") // black card background
cardPad = 2
avatarStyle = lipgloss.NewStyle().Foreground(accent) avatarStyle = lipgloss.NewStyle().Foreground(accent)
fieldBox = lipgloss.NewStyle(). fieldBox = lipgloss.NewStyle().
@@ -481,6 +484,14 @@ func (m *Model) View() string {
content := m.renderLayout() content := m.renderLayout()
if m.width > 0 && m.height > 0 { if m.width > 0 && m.height > 0 {
if m.automata != nil {
bg := m.automata.Frame()
var sb strings.Builder
sb.WriteString(bg)
sb.WriteString("\x1b[H") // cursor home before overlaying
sb.WriteString(overlayCenter(m.width, m.height, content))
return sb.String()
}
return lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center, return lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center,
content, content,
) )
@@ -488,17 +499,49 @@ func (m *Model) View() string {
return content return content
} }
func overlayCenter(w, h int, content string) string {
lines := strings.Split(content, "\n")
cw := 0
for _, l := range lines {
if lw := lipgloss.Width(l); lw > cw {
cw = lw
}
}
cx := (w - cw) / 2
cy := (h - len(lines)) / 2
if cx < 0 {
cx = 0
}
if cy < 0 {
cy = 0
}
var sb strings.Builder
for i, line := range lines {
sb.WriteString(fmt.Sprintf("\x1b[%d;%dH", cy+i+1, cx+1))
sb.WriteString(line)
}
return sb.String()
}
func (m *Model) renderLayout() string { func (m *Model) renderLayout() string {
// top bar: power hints clock := m.renderClock()
top := m.renderPowerHints()
// top bar: power hints on left, clock on right
var topParts []string
topParts = append(topParts, m.renderPowerHints())
if clock != "" {
topParts = append(topParts, clock)
}
top := strings.Join(topParts, " ")
// avatar + form side by side // avatar + form side by side
avatar := m.renderAvatar() avatar := m.renderAvatar()
form := m.renderForm() form := m.renderForm()
mid := lipgloss.JoinHorizontal(lipgloss.Top, avatar, " ", form) mid := lipgloss.JoinHorizontal(lipgloss.Top, avatar, " ", form)
// DE switcher below // DE switcher with specifier label
sw := m.renderSwitcherDots() sw := m.renderSwitcher()
// caps lock // caps lock
caps := m.renderCapsLock() caps := m.renderCapsLock()
@@ -536,7 +579,10 @@ func (m *Model) renderLayout() string {
joined = pad + joined joined = pad + joined
} }
} }
return joined return lipgloss.NewStyle().
Background(cardBg).
Padding(cardPad, cardPad+2).
Render(joined)
} }
func (m *Model) renderPowerHints() string { func (m *Model) renderPowerHints() string {
@@ -594,7 +640,12 @@ func (m *Model) renderForm() string {
return lipgloss.JoinVertical(lipgloss.Left, userField, "", passField) return lipgloss.JoinVertical(lipgloss.Left, userField, "", passField)
} }
func (m *Model) renderSwitcherDots() string { func (m *Model) renderClock() string {
now := time.Now()
return powerHint.Render(now.Format("Mon Jan 02 15:04:05"))
}
func (m *Model) renderSwitcher() string {
if len(m.envs) == 0 { if len(m.envs) == 0 {
return swNeighbour.Align(lipgloss.Center).Render("no desktop environments found") return swNeighbour.Align(lipgloss.Center).Render("no desktop environments found")
} }
@@ -604,6 +655,9 @@ func (m *Model) renderSwitcherDots() string {
var parts []string var parts []string
// session specifier (like "x11", "wayland")
spec := swDot.Render(m.envs[m.selIdx].Kind + " ")
if cfg.ShowMovers && m.selIdx > 0 { if cfg.ShowMovers && m.selIdx > 0 {
parts = append(parts, swMover.Render(cfg.LeftMover+" ")) parts = append(parts, swMover.Render(cfg.LeftMover+" "))
} }
@@ -636,7 +690,7 @@ func (m *Model) renderSwitcherDots() string {
} }
dotLine := strings.Join(dots, " ") dotLine := strings.Join(dots, " ")
return lipgloss.JoinVertical(lipgloss.Center, swLine, dotLine) return lipgloss.JoinVertical(lipgloss.Center, spec, swLine, dotLine)
} }
func (m *Model) renderCapsLock() string { func (m *Model) renderCapsLock() string {