Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 28 additions & 49 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
}()

Expand Down Expand Up @@ -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"
}

Expand Down Expand Up @@ -5403,39 +5388,27 @@ 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
}

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")
Expand Down Expand Up @@ -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")
Expand All @@ -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")
Expand All @@ -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")
Expand Down
29 changes: 19 additions & 10 deletions main.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 │
│ │
Expand Down Expand Up @@ -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 │
│ │
Expand All @@ -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! │
│ │
Expand Down Expand Up @@ -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 │
Expand All @@ -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 │
Expand All @@ -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 │
Expand All @@ -271,7 +277,8 @@ Console during first item pull:
Console when first item completes:

```
╭─ GitHub 🧠 pull ─────────────────────────────────────────────╮
╭────────────────────────────────────────────────────────────────╮
│ GitHub 🧠 pull │
│ │
│ ✅ Repositories: 2,847 │
│ ⠙ Discussions: 156 │
Expand All @@ -294,7 +301,8 @@ Console when first item completes:
Console when an error occurs:

```
╭─ GitHub 🧠 pull ─────────────────────────────────────────────╮
╭────────────────────────────────────────────────────────────────╮
│ GitHub 🧠 pull │
│ │
│ ✅ Repositories: 2,847 │
│ ❌ Discussions: 156 (errors) │
Expand Down Expand Up @@ -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)`

Expand Down