9817bab0cbe55266f409f433538fcea5bf6d1353

Author
Toby Padilla <toby@charm.sh>
Committer
Toby Padilla <toby@charm.sh>
Date

Message

Selection box, list repos, tab activate main boxes

Diff

  1diff --git a/tui/bubble.go b/tui/bubble.go
  2index 538fc1ac1c4448a462012f3a65c61f67662d5bd2..abdc6ef9910b3a832e3fdabb2536c746da58c1bd 100644
  3--- a/tui/bubble.go
  4+++ b/tui/bubble.go
  5@@ -3,10 +3,10 @@ package tui
  6 import (
  7 	"fmt"
  8 	"smoothie/git"
  9-	"smoothie/tui/bubbles/commits"
 10 	"time"
 11 
 12 	tea "github.com/charmbracelet/bubbletea"
 13+	"github.com/charmbracelet/lipgloss"
 14 	"github.com/gliderlabs/ssh"
 15 )
 16 
 17@@ -21,14 +21,16 @@ const (
 18 )
 19 
 20 type Model struct {
 21-	state          sessionState
 22-	error          string
 23-	info           string
 24-	width          int
 25-	height         int
 26-	windowChanges  <-chan ssh.Window
 27-	repoSource     *git.RepoSource
 28-	commitTimeline *commits.Bubble
 29+	state         sessionState
 30+	error         string
 31+	info          string
 32+	width         int
 33+	height        int
 34+	windowChanges <-chan ssh.Window
 35+	repoSource    *git.RepoSource
 36+	repos         []*git.Repo
 37+	activeBubble  int
 38+	bubbles       []tea.Model
 39 }
 40 
 41 func NewModel(width int, height int, windowChanges <-chan ssh.Window, repoSource *git.RepoSource) *Model {
 42@@ -37,6 +39,7 @@ func NewModel(width int, height int, windowChanges <-chan ssh.Window, repoSource
 43 		height:        height,
 44 		windowChanges: windowChanges,
 45 		repoSource:    repoSource,
 46+		bubbles:       make([]tea.Model, 2),
 47 	}
 48 	m.state = startState
 49 	return m
 50@@ -56,9 +59,8 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 51 		switch msg.String() {
 52 		case "q", "ctrl+c":
 53 			return m, tea.Quit
 54-		case "j", "k", "up", "down":
 55-			_, cmd := m.commitTimeline.Update(msg)
 56-			cmds = append(cmds, cmd)
 57+		case "tab":
 58+			m.activeBubble = (m.activeBubble + 1) % 2
 59 		}
 60 	case errMsg:
 61 		m.error = msg.Error()
 62@@ -71,11 +73,27 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 63 	case tea.WindowSizeMsg:
 64 		m.width = msg.Width
 65 		m.height = msg.Height
 66-		m.commitTimeline.Height = msg.Height
 67+	}
 68+	if m.state == loadedState {
 69+		b, cmd := m.bubbles[m.activeBubble].Update(msg)
 70+		m.bubbles[m.activeBubble] = b
 71+		if cmd != nil {
 72+			cmds = append(cmds, cmd)
 73+		}
 74 	}
 75 	return m, tea.Batch(cmds...)
 76 }
 77 
 78+func (m *Model) viewForBubble(i int, width int) string {
 79+	var ls lipgloss.Style
 80+	if i == m.activeBubble {
 81+		ls = activeBoxStyle.Width(width)
 82+	} else {
 83+		ls = inactiveBoxStyle.Width(width)
 84+	}
 85+	return ls.Render(m.bubbles[i].View())
 86+}
 87+
 88 func (m *Model) View() string {
 89 	pad := 6
 90 	h := headerStyle.Width(m.width - pad).Render("Charm Beta")
 91@@ -84,7 +102,9 @@ func (m *Model) View() string {
 92 	content := ""
 93 	switch m.state {
 94 	case loadedState:
 95-		s += m.commitTimeline.View()
 96+		lb := m.viewForBubble(0, 25)
 97+		rb := m.viewForBubble(1, 84)
 98+		s += lipgloss.JoinHorizontal(lipgloss.Top, lb, rb)
 99 	case errorState:
100 		s += errorStyle.Render(fmt.Sprintf("Bummer: %s", m.error))
101 	default:
102diff --git a/tui/bubbles/commits/bubble.go b/tui/bubbles/commits/bubble.go
103index 25aed72d2362919adcc5ffc8fe1d37cd81191abc..1e7ed7ca596d50f1b686172d6422c1e67f64bedc 100644
104--- a/tui/bubbles/commits/bubble.go
105+++ b/tui/bubbles/commits/bubble.go
106@@ -62,7 +62,7 @@ func (b *Bubble) renderCommit(rc git.RepoCommit) string {
107 	s += " "
108 	s += commitAuthorEmailStyle.Render(rc.Commit.Author.Email)
109 	s += " "
110-	return commitBoxStyle.Width(b.viewport.Height).Render(s)
111+	return commitBoxStyle.Width(b.viewport.Width).Render(s)
112 }
113 
114 func (b *Bubble) View() string {
115diff --git a/tui/bubbles/selection/bubble.go b/tui/bubbles/selection/bubble.go
116new file mode 100644
117index 0000000000000000000000000000000000000000..b957872e07b5d28a266b29fb9c280f182db0f8f7
118--- /dev/null
119+++ b/tui/bubbles/selection/bubble.go
120@@ -0,0 +1,70 @@
121+package selection
122+
123+import (
124+	tea "github.com/charmbracelet/bubbletea"
125+	"github.com/charmbracelet/lipgloss"
126+)
127+
128+type SelectedMsg struct {
129+	Name  string
130+	Index int
131+}
132+
133+type Bubble struct {
134+	NormalStyle   lipgloss.Style
135+	SelectedStyle lipgloss.Style
136+	Items         []string
137+	selectedItem  int
138+}
139+
140+func NewBubble(items []string) *Bubble {
141+	return &Bubble{
142+		NormalStyle:   normalStyle,
143+		SelectedStyle: selectedStyle,
144+		Items:         items,
145+		selectedItem:  -1,
146+	}
147+}
148+
149+func (b *Bubble) Init() tea.Cmd {
150+	return nil
151+}
152+
153+func (b *Bubble) View() string {
154+	s := ""
155+	for i, item := range b.Items {
156+		if i == b.selectedItem {
157+			s += b.SelectedStyle.Render(item) + "\n"
158+		} else {
159+			s += b.NormalStyle.Render(item) + "\n"
160+		}
161+	}
162+	return s
163+}
164+
165+func (b *Bubble) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
166+	cmds := make([]tea.Cmd, 0)
167+	switch msg := msg.(type) {
168+	case tea.KeyMsg:
169+		switch msg.String() {
170+		case "k", "up":
171+			if b.selectedItem > 0 {
172+				b.selectedItem--
173+			}
174+		case "j", "down":
175+			if b.selectedItem < len(b.Items)-1 {
176+				b.selectedItem++
177+			}
178+		case "enter":
179+			cmds = append(cmds, b.sendMessage)
180+		}
181+	}
182+	return b, tea.Batch(cmds...)
183+}
184+
185+func (b *Bubble) sendMessage() tea.Msg {
186+	return SelectedMsg{
187+		Name:  b.Items[b.selectedItem],
188+		Index: b.selectedItem,
189+	}
190+}
191diff --git a/tui/bubbles/selection/style.go b/tui/bubbles/selection/style.go
192new file mode 100644
193index 0000000000000000000000000000000000000000..8aeeb002b267f9eb4c99208be42b95c92bac6ebc
194--- /dev/null
195+++ b/tui/bubbles/selection/style.go
196@@ -0,0 +1,11 @@
197+package selection
198+
199+import (
200+	"github.com/charmbracelet/lipgloss"
201+)
202+
203+var normalStyle = lipgloss.NewStyle().
204+	Foreground(lipgloss.Color("#FFFFFF"))
205+
206+var selectedStyle = lipgloss.NewStyle().
207+	Foreground(lipgloss.Color("#714C7B"))
208diff --git a/tui/commands.go b/tui/commands.go
209index e26b9564acd3f358abdb8553210811b13543d572..3317d36520e72424c303aeb13c385fca80e3766e 100644
210--- a/tui/commands.go
211+++ b/tui/commands.go
212@@ -2,6 +2,7 @@ package tui
213 
214 import (
215 	"smoothie/tui/bubbles/commits"
216+	"smoothie/tui/bubbles/selection"
217 
218 	tea "github.com/charmbracelet/bubbletea"
219 )
220@@ -23,7 +24,13 @@ func (m *Model) windowChangesCmd() tea.Msg {
221 }
222 
223 func (m *Model) loadGitCmd() tea.Msg {
224-	m.commitTimeline = commits.NewBubble(m.height, 2, 80, m.repoSource.GetCommits(200))
225+	rs := make([]string, 0)
226+	for _, r := range m.repoSource.AllRepos() {
227+		rs = append(rs, r.Name)
228+	}
229+	m.bubbles[0] = selection.NewBubble(rs)
230+	m.bubbles[1] = commits.NewBubble(m.height, 7, 80, m.repoSource.GetCommits(200))
231+	m.activeBubble = 0
232 	m.state = loadedState
233 	return nil
234 }
235diff --git a/tui/style.go b/tui/style.go
236index dc0d2f4bd0efad5142f31dd2b30af385049aaf27..2cd8e6c0cf17853ecf082fbdfc63b7fc39005dae 100644
237--- a/tui/style.go
238+++ b/tui/style.go
239@@ -9,6 +9,18 @@ var appBoxStyle = lipgloss.NewStyle().
240 	PaddingRight(2).
241 	MarginBottom(1)
242 
243+var inactiveBoxStyle = lipgloss.NewStyle().
244+	Foreground(lipgloss.Color("#606060")).
245+	BorderStyle(lipgloss.RoundedBorder()).
246+	BorderForeground(lipgloss.Color("#303030")).
247+	Padding(1)
248+
249+var activeBoxStyle = lipgloss.NewStyle().
250+	Foreground(lipgloss.Color("#FFFFFF")).
251+	BorderStyle(lipgloss.RoundedBorder()).
252+	BorderForeground(lipgloss.Color("#714C7B")).
253+	Padding(1)
254+
255 var headerStyle = lipgloss.NewStyle().
256 	Foreground(lipgloss.Color("#670083")).
257 	Align(lipgloss.Right).