From 9817bab0cbe55266f409f433538fcea5bf6d1353 Mon Sep 17 00:00:00 2001 From: Toby Padilla Date: Wed, 4 Aug 2021 15:50:29 -0500 Subject: [PATCH] Selection box, list repos, tab activate main boxes --- tui/bubble.go | 48 +++++++++++++++------- tui/bubbles/commits/bubble.go | 2 +- tui/bubbles/selection/bubble.go | 70 +++++++++++++++++++++++++++++++++ tui/bubbles/selection/style.go | 11 ++++++ tui/commands.go | 9 ++++- tui/style.go | 12 ++++++ 6 files changed, 136 insertions(+), 16 deletions(-) create mode 100644 tui/bubbles/selection/bubble.go create mode 100644 tui/bubbles/selection/style.go diff --git a/tui/bubble.go b/tui/bubble.go index 538fc1ac1c4448a462012f3a65c61f67662d5bd2..abdc6ef9910b3a832e3fdabb2536c746da58c1bd 100644 --- a/tui/bubble.go +++ b/tui/bubble.go @@ -3,10 +3,10 @@ package tui import ( "fmt" "smoothie/git" - "smoothie/tui/bubbles/commits" "time" tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" "github.com/gliderlabs/ssh" ) @@ -21,14 +21,16 @@ const ( ) type Model struct { - state sessionState - error string - info string - width int - height int - windowChanges <-chan ssh.Window - repoSource *git.RepoSource - commitTimeline *commits.Bubble + state sessionState + error string + info string + width int + height int + windowChanges <-chan ssh.Window + repoSource *git.RepoSource + repos []*git.Repo + activeBubble int + bubbles []tea.Model } func NewModel(width int, height int, windowChanges <-chan ssh.Window, repoSource *git.RepoSource) *Model { @@ -37,6 +39,7 @@ func NewModel(width int, height int, windowChanges <-chan ssh.Window, repoSource height: height, windowChanges: windowChanges, repoSource: repoSource, + bubbles: make([]tea.Model, 2), } m.state = startState return m @@ -56,9 +59,8 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg.String() { case "q", "ctrl+c": return m, tea.Quit - case "j", "k", "up", "down": - _, cmd := m.commitTimeline.Update(msg) - cmds = append(cmds, cmd) + case "tab": + m.activeBubble = (m.activeBubble + 1) % 2 } case errMsg: m.error = msg.Error() @@ -71,11 +73,27 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.WindowSizeMsg: m.width = msg.Width m.height = msg.Height - m.commitTimeline.Height = msg.Height + } + if m.state == loadedState { + b, cmd := m.bubbles[m.activeBubble].Update(msg) + m.bubbles[m.activeBubble] = b + if cmd != nil { + cmds = append(cmds, cmd) + } } return m, tea.Batch(cmds...) } +func (m *Model) viewForBubble(i int, width int) string { + var ls lipgloss.Style + if i == m.activeBubble { + ls = activeBoxStyle.Width(width) + } else { + ls = inactiveBoxStyle.Width(width) + } + return ls.Render(m.bubbles[i].View()) +} + func (m *Model) View() string { pad := 6 h := headerStyle.Width(m.width - pad).Render("Charm Beta") @@ -84,7 +102,9 @@ func (m *Model) View() string { content := "" switch m.state { case loadedState: - s += m.commitTimeline.View() + lb := m.viewForBubble(0, 25) + rb := m.viewForBubble(1, 84) + s += lipgloss.JoinHorizontal(lipgloss.Top, lb, rb) case errorState: s += errorStyle.Render(fmt.Sprintf("Bummer: %s", m.error)) default: diff --git a/tui/bubbles/commits/bubble.go b/tui/bubbles/commits/bubble.go index 25aed72d2362919adcc5ffc8fe1d37cd81191abc..1e7ed7ca596d50f1b686172d6422c1e67f64bedc 100644 --- a/tui/bubbles/commits/bubble.go +++ b/tui/bubbles/commits/bubble.go @@ -62,7 +62,7 @@ func (b *Bubble) renderCommit(rc git.RepoCommit) string { s += " " s += commitAuthorEmailStyle.Render(rc.Commit.Author.Email) s += " " - return commitBoxStyle.Width(b.viewport.Height).Render(s) + return commitBoxStyle.Width(b.viewport.Width).Render(s) } func (b *Bubble) View() string { diff --git a/tui/bubbles/selection/bubble.go b/tui/bubbles/selection/bubble.go new file mode 100644 index 0000000000000000000000000000000000000000..b957872e07b5d28a266b29fb9c280f182db0f8f7 --- /dev/null +++ b/tui/bubbles/selection/bubble.go @@ -0,0 +1,70 @@ +package selection + +import ( + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" +) + +type SelectedMsg struct { + Name string + Index int +} + +type Bubble struct { + NormalStyle lipgloss.Style + SelectedStyle lipgloss.Style + Items []string + selectedItem int +} + +func NewBubble(items []string) *Bubble { + return &Bubble{ + NormalStyle: normalStyle, + SelectedStyle: selectedStyle, + Items: items, + selectedItem: -1, + } +} + +func (b *Bubble) Init() tea.Cmd { + return nil +} + +func (b *Bubble) View() string { + s := "" + for i, item := range b.Items { + if i == b.selectedItem { + s += b.SelectedStyle.Render(item) + "\n" + } else { + s += b.NormalStyle.Render(item) + "\n" + } + } + return s +} + +func (b *Bubble) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + cmds := make([]tea.Cmd, 0) + switch msg := msg.(type) { + case tea.KeyMsg: + switch msg.String() { + case "k", "up": + if b.selectedItem > 0 { + b.selectedItem-- + } + case "j", "down": + if b.selectedItem < len(b.Items)-1 { + b.selectedItem++ + } + case "enter": + cmds = append(cmds, b.sendMessage) + } + } + return b, tea.Batch(cmds...) +} + +func (b *Bubble) sendMessage() tea.Msg { + return SelectedMsg{ + Name: b.Items[b.selectedItem], + Index: b.selectedItem, + } +} diff --git a/tui/bubbles/selection/style.go b/tui/bubbles/selection/style.go new file mode 100644 index 0000000000000000000000000000000000000000..8aeeb002b267f9eb4c99208be42b95c92bac6ebc --- /dev/null +++ b/tui/bubbles/selection/style.go @@ -0,0 +1,11 @@ +package selection + +import ( + "github.com/charmbracelet/lipgloss" +) + +var normalStyle = lipgloss.NewStyle(). + Foreground(lipgloss.Color("#FFFFFF")) + +var selectedStyle = lipgloss.NewStyle(). + Foreground(lipgloss.Color("#714C7B")) diff --git a/tui/commands.go b/tui/commands.go index e26b9564acd3f358abdb8553210811b13543d572..3317d36520e72424c303aeb13c385fca80e3766e 100644 --- a/tui/commands.go +++ b/tui/commands.go @@ -2,6 +2,7 @@ package tui import ( "smoothie/tui/bubbles/commits" + "smoothie/tui/bubbles/selection" tea "github.com/charmbracelet/bubbletea" ) @@ -23,7 +24,13 @@ func (m *Model) windowChangesCmd() tea.Msg { } func (m *Model) loadGitCmd() tea.Msg { - m.commitTimeline = commits.NewBubble(m.height, 2, 80, m.repoSource.GetCommits(200)) + rs := make([]string, 0) + for _, r := range m.repoSource.AllRepos() { + rs = append(rs, r.Name) + } + m.bubbles[0] = selection.NewBubble(rs) + m.bubbles[1] = commits.NewBubble(m.height, 7, 80, m.repoSource.GetCommits(200)) + m.activeBubble = 0 m.state = loadedState return nil } diff --git a/tui/style.go b/tui/style.go index dc0d2f4bd0efad5142f31dd2b30af385049aaf27..2cd8e6c0cf17853ecf082fbdfc63b7fc39005dae 100644 --- a/tui/style.go +++ b/tui/style.go @@ -9,6 +9,18 @@ var appBoxStyle = lipgloss.NewStyle(). PaddingRight(2). MarginBottom(1) +var inactiveBoxStyle = lipgloss.NewStyle(). + Foreground(lipgloss.Color("#606060")). + BorderStyle(lipgloss.RoundedBorder()). + BorderForeground(lipgloss.Color("#303030")). + Padding(1) + +var activeBoxStyle = lipgloss.NewStyle(). + Foreground(lipgloss.Color("#FFFFFF")). + BorderStyle(lipgloss.RoundedBorder()). + BorderForeground(lipgloss.Color("#714C7B")). + Padding(1) + var headerStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("#670083")). Align(lipgloss.Right).