1package git
2
3import (
4 tea "github.com/charmbracelet/bubbletea"
5 "github.com/charmbracelet/lipgloss"
6 "github.com/charmbracelet/soft-serve/internal/tui/bubbles/git/about"
7 "github.com/charmbracelet/soft-serve/internal/tui/bubbles/git/log"
8 "github.com/charmbracelet/soft-serve/internal/tui/bubbles/git/refs"
9 "github.com/charmbracelet/soft-serve/internal/tui/bubbles/git/tree"
10 "github.com/charmbracelet/soft-serve/internal/tui/bubbles/git/types"
11 "github.com/charmbracelet/soft-serve/internal/tui/style"
12 "github.com/go-git/go-git/v5/plumbing"
13)
14
15const (
16 repoNameMaxWidth = 32
17)
18
19type pageState int
20
21const (
22 aboutPage pageState = iota
23 refsPage
24 logPage
25 treePage
26)
27
28type Bubble struct {
29 state pageState
30 repo types.Repo
31 height int
32 heightMargin int
33 width int
34 widthMargin int
35 style *style.Styles
36 boxes []tea.Model
37}
38
39func NewBubble(repo types.Repo, styles *style.Styles, width, wm, height, hm int) *Bubble {
40 b := &Bubble{
41 repo: repo,
42 state: aboutPage,
43 width: width,
44 widthMargin: wm,
45 height: height,
46 heightMargin: hm,
47 style: styles,
48 boxes: make([]tea.Model, 4),
49 }
50 heightMargin := hm + lipgloss.Height(b.headerView())
51 b.boxes[aboutPage] = about.NewBubble(repo, b.style, b.width, wm, b.height, heightMargin)
52 b.boxes[refsPage] = refs.NewBubble(repo, b.style, b.width, wm, b.height, heightMargin)
53 b.boxes[logPage] = log.NewBubble(repo, b.style, width, wm, height, heightMargin)
54 b.boxes[treePage] = tree.NewBubble(repo, b.style, width, wm, height, heightMargin)
55 return b
56}
57
58func (b *Bubble) Init() tea.Cmd {
59 return b.setupCmd
60}
61
62func (b *Bubble) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
63 cmds := make([]tea.Cmd, 0)
64 switch msg := msg.(type) {
65 case tea.KeyMsg:
66 if b.repo.Name() != "config" {
67 switch msg.String() {
68 case "R":
69 b.state = aboutPage
70 case "B":
71 b.state = refsPage
72 case "C":
73 b.state = logPage
74 case "F":
75 b.state = treePage
76 }
77 }
78 case tea.WindowSizeMsg:
79 b.width = msg.Width
80 b.height = msg.Height
81 for i, bx := range b.boxes {
82 m, cmd := bx.Update(msg)
83 b.boxes[i] = m
84 if cmd != nil {
85 cmds = append(cmds, cmd)
86 }
87 }
88 case refs.RefMsg:
89 b.state = treePage
90 }
91 m, cmd := b.boxes[b.state].Update(msg)
92 b.boxes[b.state] = m
93 if cmd != nil {
94 cmds = append(cmds, cmd)
95 }
96 return b, tea.Batch(cmds...)
97}
98
99func (b *Bubble) Help() []types.HelpEntry {
100 h := []types.HelpEntry{}
101 h = append(h, b.boxes[b.state].(types.BubbleHelper).Help()...)
102 if b.repo.Name() != "config" {
103 h = append(h, types.HelpEntry{"R", "readme"})
104 h = append(h, types.HelpEntry{"F", "files"})
105 h = append(h, types.HelpEntry{"C", "commits"})
106 h = append(h, types.HelpEntry{"B", "branches"})
107 }
108 return h
109}
110
111func (b *Bubble) Reference() plumbing.ReferenceName {
112 return b.repo.GetReference().Name()
113}
114
115func (b *Bubble) headerView() string {
116 // TODO better header, tabs?
117 return ""
118}
119
120func (b *Bubble) View() string {
121 header := b.headerView()
122 return header + b.boxes[b.state].View()
123}
124
125func (b *Bubble) setupCmd() tea.Msg {
126 cmds := make([]tea.Cmd, 0)
127 for _, bx := range b.boxes {
128 if bx != nil {
129 initCmd := bx.Init()
130 if initCmd != nil {
131 msg := initCmd()
132 switch msg := msg.(type) {
133 case types.ErrMsg:
134 return msg
135 }
136 }
137 cmds = append(cmds, initCmd)
138 }
139 }
140 return tea.Batch(cmds...)
141}