From 8871a531ea50143e598cfd5fe76a9ff6110ce4a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Dec 2025 04:25:23 +0000 Subject: [PATCH 1/3] Initial plan From f644e6c886dfd03bf52e1abb405b6cd8dee07a14 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Dec 2025 04:33:54 +0000 Subject: [PATCH 2/3] Replace fmt error logging with slog.Error Co-authored-by: wham <448809+wham@users.noreply.github.com> --- main.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 61e6f97..6b3f73d 100644 --- a/main.go +++ b/main.go @@ -4257,7 +4257,7 @@ func main() { } if err := RunLogin(homeDir); err != nil { - fmt.Fprintf(os.Stderr, "Login failed: %v\n", err) + slog.Error("Login failed", "error", err) os.Exit(1) } @@ -4617,7 +4617,7 @@ func main() { } default: - fmt.Fprintf(os.Stderr, "Unknown command: %s\n", cmd) + slog.Error("Unknown command", "command", cmd) fmt.Printf("Use %s -h for help\n", os.Args[0]) os.Exit(1) } @@ -4676,7 +4676,7 @@ func (p *UIProgress) InitItems(config *Config) { // Start the program in a goroutine go func() { if _, err := p.program.Run(); err != nil { - fmt.Fprintf(os.Stderr, "Error running Bubble Tea program: %v\n", err) + slog.Error("Error running Bubble Tea program", "error", err) } }() From 70fda9bd6b0e6ec9d78d2381e1d3931ba3752a46 Mon Sep 17 00:00:00 2001 From: Tomas Vesely <448809+wham@users.noreply.github.com> Date: Fri, 19 Dec 2025 21:21:06 -0800 Subject: [PATCH 3/3] Refactor login and pull command box styles to use standard lipgloss borders and render titles as bold text --- main.go | 71 ++++++++++++++++++++------------------------------------- main.md | 29 +++++++++++++++-------- 2 files changed, 44 insertions(+), 56 deletions(-) diff --git a/main.go b/main.go index 6b3f73d..c716027 100644 --- a/main.go +++ b/main.go @@ -5090,42 +5090,27 @@ func (m model) View() string { contentLines[i] = line + strings.Repeat(" ", padding) } } + + // Add title as first line of content + titleStyle := lipgloss.NewStyle().Bold(true) + titleLine := titleStyle.Render("GitHub 🧠 pull") + // Pad title line to match content width + titlePadding := maxContentWidth - visibleLength(titleLine) + if titlePadding > 0 { + titleLine = titleLine + strings.Repeat(" ", titlePadding) + } + contentLines = append([]string{titleLine}, contentLines...) content = strings.Join(contentLines, "\n") - // Create box without automatic width adjustment (we've done it ourselves) + // Create box with standard lipgloss borders boxStyle := lipgloss.NewStyle(). Border(lipgloss.RoundedBorder()). BorderForeground(borderColor). - Padding(0, 1). // 1 space padding on left and right + Padding(0, 1). Align(lipgloss.Left) box := boxStyle.Render(content) - // Add title to the top border while maintaining color - titleText := "GitHub 🧠 pull" - titleStyle := lipgloss.NewStyle().Bold(true).Foreground(borderColor) - borderStyle := lipgloss.NewStyle().Foreground(borderColor) - - boxLines := strings.Split(box, "\n") - if len(boxLines) > 0 { - // Calculate the plain title width - titlePlainWidth := visibleLength(titleText) - // Get the full width of the first line - firstLineWidth := lipgloss.Width(boxLines[0]) - // Calculate dashes needed: total width - "╭─ " (3) - title - " " (1) - "╮" (1) - dashesNeeded := firstLineWidth - 3 - titlePlainWidth - 1 - 1 - if dashesNeeded < 0 { - dashesNeeded = 0 - } - - // Build the title line with proper coloring - boxLines[0] = borderStyle.Render("╭─ ") + - titleStyle.Render(titleText) + - borderStyle.Render(" " + strings.Repeat("─", dashesNeeded) + "╮") - - box = strings.Join(boxLines, "\n") - } - return box + "\n" } @@ -5403,32 +5388,18 @@ func (m loginModel) View() string { maxContentWidth = 64 } - // Create border style + // Create border style with title borderStyle := lipgloss.NewStyle(). Border(lipgloss.RoundedBorder()). BorderForeground(borderColor). + BorderTop(true). + BorderLeft(true). + BorderRight(true). + BorderBottom(true). Padding(0, 1). Width(maxContentWidth) - // Title - title := " GitHub 🧠 Login " - titleStyle := lipgloss.NewStyle().Bold(true) - box := borderStyle.Render(content) - - // Replace top border with title - lines := strings.Split(box, "\n") - if len(lines) > 0 { - topBorder := lines[0] - titlePos := 2 - if titlePos+len(title) < len(topBorder) { - runes := []rune(topBorder) - titleRunes := []rune(titleStyle.Render(title)) - copy(runes[titlePos:], titleRunes) - lines[0] = string(runes) - } - box = strings.Join(lines, "\n") - } return box } @@ -5436,6 +5407,8 @@ func (m loginModel) View() string { func (m loginModel) renderWaitingView() string { var b strings.Builder + titleStyle := lipgloss.NewStyle().Bold(true) + b.WriteString(titleStyle.Render(" GitHub 🧠 Login") + "\n") b.WriteString("\n") b.WriteString(" 🔐 GitHub Authentication\n") b.WriteString("\n") @@ -5471,8 +5444,10 @@ func (m loginModel) renderWaitingView() string { func (m loginModel) renderOrgInputView() string { var b strings.Builder + titleStyle := lipgloss.NewStyle().Bold(true) successStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("10")) + b.WriteString(titleStyle.Render(" GitHub 🧠 Login") + "\n") b.WriteString("\n") b.WriteString(" " + successStyle.Render(fmt.Sprintf("✅ Successfully authenticated as @%s", m.username)) + "\n") b.WriteString("\n") @@ -5488,8 +5463,10 @@ func (m loginModel) renderOrgInputView() string { func (m loginModel) renderSuccessView() string { var b strings.Builder + titleStyle := lipgloss.NewStyle().Bold(true) successStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("10")) + b.WriteString(titleStyle.Render(" GitHub 🧠 Login") + "\n") b.WriteString("\n") b.WriteString(" " + successStyle.Render("✅ Setup complete!") + "\n") b.WriteString("\n") @@ -5509,8 +5486,10 @@ func (m loginModel) renderSuccessView() string { func (m loginModel) renderErrorView() string { var b strings.Builder + titleStyle := lipgloss.NewStyle().Bold(true) errorStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("9")) + b.WriteString(titleStyle.Render(" GitHub 🧠 Login") + "\n") b.WriteString("\n") b.WriteString(" " + errorStyle.Render("❌ Authentication failed") + "\n") b.WriteString("\n") diff --git a/main.md b/main.md index d5c8ff7..89eb995 100644 --- a/main.md +++ b/main.md @@ -79,7 +79,8 @@ The app uses a registered OAuth App for authentication: 3. Display the code and open browser: ``` - ╭─ GitHub 🧠 Login ─────────────────────────────────────────────╮ + ╭────────────────────────────────────────────────────────────────╮ + │ GitHub 🧠 Login │ │ │ │ 🔐 GitHub Authentication │ │ │ @@ -116,7 +117,8 @@ The app uses a registered OAuth App for authentication: 6. On success, prompt for organization: ``` - ╭─ GitHub 🧠 Login ─────────────────────────────────────────────╮ + ╭────────────────────────────────────────────────────────────────╮ + │ GitHub 🧠 Login │ │ │ │ ✅ Successfully authenticated as @wham │ │ │ @@ -130,7 +132,8 @@ The app uses a registered OAuth App for authentication: 7. Save tokens (and organization if provided) to `.env` file: ``` - ╭─ GitHub 🧠 Login ─────────────────────────────────────────────╮ + ╭────────────────────────────────────────────────────────────────╮ + │ GitHub 🧠 Login │ │ │ │ ✅ Setup complete! │ │ │ @@ -202,7 +205,8 @@ Bubble Tea handles all rendering automatically: Console at the beginning of the `pull` command - all items selected: ``` -╭─ GitHub 🧠 pull ─────────────────────────────────────────────╮ +╭────────────────────────────────────────────────────────────────╮ +│ GitHub 🧠 pull │ │ │ │ 📋 Repositories │ │ 📋 Discussions │ @@ -225,7 +229,8 @@ Console at the beginning of the `pull` command - all items selected: Console at the beginning of the `pull` command - `-i repositories`: ``` -╭─ GitHub 🧠 pull ─────────────────────────────────────────────╮ +╭────────────────────────────────────────────────────────────────╮ +│ GitHub 🧠 pull │ │ │ │ 📋 Repositories │ │ 🔕 Discussions │ @@ -248,7 +253,8 @@ Console at the beginning of the `pull` command - `-i repositories`: Console during first item pull: ``` -╭─ GitHub 🧠 pull ─────────────────────────────────────────────╮ +╭────────────────────────────────────────────────────────────────╮ +│ GitHub 🧠 pull │ │ │ │ ⠋ Repositories: 1,247 │ │ 📋 Discussions │ @@ -271,7 +277,8 @@ Console during first item pull: Console when first item completes: ``` -╭─ GitHub 🧠 pull ─────────────────────────────────────────────╮ +╭────────────────────────────────────────────────────────────────╮ +│ GitHub 🧠 pull │ │ │ │ ✅ Repositories: 2,847 │ │ ⠙ Discussions: 156 │ @@ -294,7 +301,8 @@ Console when first item completes: Console when an error occurs: ``` -╭─ GitHub 🧠 pull ─────────────────────────────────────────────╮ +╭────────────────────────────────────────────────────────────────╮ +│ GitHub 🧠 pull │ │ │ │ ✅ Repositories: 2,847 │ │ ❌ Discussions: 156 (errors) │ @@ -344,8 +352,9 @@ Console when an error occurs: **Box Drawing:** -- Use lipgloss to build bordered layouts with `lipgloss.JoinVertical` -- Rounded borders (╭╮╰╯) styled with adaptive colors +- Use standard lipgloss borders - no custom border painting or string manipulation +- Rounded borders (╭╮╰╯) styled with `lipgloss.RoundedBorder()` +- Title rendered as bold text inside the box, not embedded in border - Border colors animated via `tickMsg` sent every second - Responsive width: `max(64, terminalWidth - 4)`