diff --git a/ui/components/footer/footer.go b/ui/components/footer/footer.go index 05b66919cbabd1ee6018c22370aa17118c9817bb..eb97f8b9820780b77975217e62cbb414fe65678f 100644 --- a/ui/components/footer/footer.go +++ b/ui/components/footer/footer.go @@ -1,11 +1,10 @@ package footer import ( - "strings" - "github.com/charmbracelet/bubbles/help" "github.com/charmbracelet/bubbles/key" tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/soft-serve/ui/common" ) @@ -80,5 +79,5 @@ func (f *Footer) SetShowAll(show bool) { // Height returns the height of the footer. func (f *Footer) Height() int { - return len(strings.Split(f.View(), "\n")) + return lipgloss.Height(f.View()) } diff --git a/ui/pages/repo/files.go b/ui/pages/repo/files.go index 4e501b0e7c61ab76cc5cbdffc6b8fd3743582d9d..4c9e4e8ca657f2c42b89e071b538de86da3ac854 100644 --- a/ui/pages/repo/files.go +++ b/ui/pages/repo/files.go @@ -156,6 +156,7 @@ func (f *Files) Init() tea.Cmd { f.currentItem = nil f.activeView = filesViewFiles f.lastSelected = make([]int, 0) + f.selector.Select(0) return f.updateFilesCmd } @@ -164,7 +165,6 @@ func (f *Files) Update(msg tea.Msg) (tea.Model, tea.Cmd) { cmds := make([]tea.Cmd, 0) switch msg := msg.(type) { case RepoMsg: - f.selector.Select(0) f.repo = git.GitRepo(msg) cmds = append(cmds, f.Init()) case RefMsg: diff --git a/ui/pages/repo/log.go b/ui/pages/repo/log.go index db87084c3d6a4b667dadfa13b37e11caac1248f0..ee57f46b2dd6405399c6a14ba78a86281477bb32 100644 --- a/ui/pages/repo/log.go +++ b/ui/pages/repo/log.go @@ -147,9 +147,12 @@ func (l *Log) FullHelp() [][]key.Binding { // Init implements tea.Model. func (l *Log) Init() tea.Cmd { - cmds := make([]tea.Cmd, 0) - cmds = append(cmds, l.updateCommitsCmd) - return tea.Batch(cmds...) + l.activeView = logViewCommits + l.nextPage = 0 + l.count = 0 + l.activeCommit = nil + l.selector.Select(0) + return l.updateCommitsCmd } // Update implements tea.Model. @@ -157,15 +160,11 @@ func (l *Log) Update(msg tea.Msg) (tea.Model, tea.Cmd) { cmds := make([]tea.Cmd, 0) switch msg := msg.(type) { case RepoMsg: - l.count = 0 - l.selector.Select(0) - l.nextPage = 0 - l.activeView = 0 l.repo = git.GitRepo(msg) + cmds = append(cmds, l.Init()) case RefMsg: l.ref = msg - l.count = 0 - cmds = append(cmds, l.countCommitsCmd) + cmds = append(cmds, l.Init()) case LogCountMsg: l.count = int64(msg) case LogItemsMsg: diff --git a/ui/pages/repo/refsitem.go b/ui/pages/repo/refsitem.go index 1a1d0d876fdd139554277b984209504f36fd9c33..d60f9241539938feec2f6f42cb598ecb35af9597 100644 --- a/ui/pages/repo/refsitem.go +++ b/ui/pages/repo/refsitem.go @@ -11,43 +11,63 @@ import ( "github.com/charmbracelet/soft-serve/ui/styles" ) +// RefItem is a git reference item. type RefItem struct { *git.Reference } +// ID implements selector.IdentifiableItem. func (i RefItem) ID() string { return i.Reference.Name().String() } +// Title implements list.DefaultItem. func (i RefItem) Title() string { return i.Reference.Name().Short() } +// Description implements list.DefaultItem. func (i RefItem) Description() string { return "" } +// Short returns the short name of the reference. func (i RefItem) Short() string { return i.Reference.Name().Short() } +// FilterValue implements list.Item. func (i RefItem) FilterValue() string { return i.Short() } +// RefItems is a list of git references. type RefItems []RefItem -func (cl RefItems) Len() int { return len(cl) } +// Len implements sort.Interface. +func (cl RefItems) Len() int { return len(cl) } + +// Swap implements sort.Interface. func (cl RefItems) Swap(i, j int) { cl[i], cl[j] = cl[j], cl[i] } + +// Less implements sort.Interface. func (cl RefItems) Less(i, j int) bool { return cl[i].Short() < cl[j].Short() } +// RefItemDelegate is the delegate for the ref item. type RefItemDelegate struct { style *styles.Styles } -func (d RefItemDelegate) Height() int { return 1 } -func (d RefItemDelegate) Spacing() int { return 0 } +// Height implements list.ItemDelegate. +func (d RefItemDelegate) Height() int { return 1 } + +// Spacing implements list.ItemDelegate. +func (d RefItemDelegate) Spacing() int { return 0 } + +// Update implements list.ItemDelegate. func (d RefItemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd { return nil } + +// Render implements list.ItemDelegate. func (d RefItemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { s := d.style i, ok := listItem.(RefItem) diff --git a/ui/pages/selection/selection.go b/ui/pages/selection/selection.go index 66fc5c2e4689f175c2bd904c47f4a112f5bf96c4..61ea96b2480bb6f64850c7da6b5906aa59c944c1 100644 --- a/ui/pages/selection/selection.go +++ b/ui/pages/selection/selection.go @@ -1,6 +1,7 @@ package selection import ( + "errors" "fmt" "strings" @@ -229,6 +230,8 @@ func (s *Selection) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch { case key.Matches(msg, s.common.KeyMap.Section): s.activeBox = (s.activeBox + 1) % 2 + case msg.String() == "a": + cmds = append(cmds, common.ErrorCmd(errors.New("not implemented"))) } } switch s.activeBox { diff --git a/ui/styles/styles.go b/ui/styles/styles.go index 667a49705f9380a5b2dcd4367e0b9893e938cee7..aca808dac84f2602e3679cef01ee099d441c9861 100644 --- a/ui/styles/styles.go +++ b/ui/styles/styles.go @@ -227,7 +227,7 @@ func DefaultStyles() *Styles { SetString(" • ") s.Error = lipgloss.NewStyle(). - Padding(1) + MarginTop(2) s.ErrorTitle = lipgloss.NewStyle(). Foreground(lipgloss.Color("230")). diff --git a/ui/ui.go b/ui/ui.go index 4ace7c6b5dd18543bcf54ddc1e07d08dfac8881c..ccf61d64449b3ead3142b4f3bfdaa10a47ddaa40 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -16,6 +16,13 @@ import ( "github.com/charmbracelet/soft-serve/ui/session" ) +type page int + +const ( + selectionPage page = iota + repoPage +) + type sessionState int const ( @@ -29,7 +36,7 @@ type UI struct { s session.Session common common.Common pages []common.Page - activePage int + activePage page state sessionState header *header.Header footer *footer.Footer @@ -43,7 +50,7 @@ func New(s session.Session, c common.Common, initialRepo string) *UI { s: s, common: c, pages: make([]common.Page, 2), // selection & repo - activePage: 0, + activePage: selectionPage, state: startState, header: h, } @@ -108,13 +115,13 @@ func (ui *UI) SetSize(width, height int) { // Init implements tea.Model. func (ui *UI) Init() tea.Cmd { cfg := ui.s.Config() - ui.pages[0] = selection.New(ui.s, ui.common) - ui.pages[1] = repo.New(ui.common, &source{cfg.Source}) + ui.pages[selectionPage] = selection.New(ui.s, ui.common) + ui.pages[repoPage] = repo.New(ui.common, &source{cfg.Source}) ui.SetSize(ui.common.Width, ui.common.Height) ui.state = loadedState return tea.Batch( - ui.pages[0].Init(), - ui.pages[1].Init(), + ui.pages[selectionPage].Init(), + ui.pages[repoPage].Init(), ) } @@ -143,8 +150,8 @@ func (ui *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) { ui.footer.SetShowAll(!ui.footer.ShowAll()) case key.Matches(msg, ui.common.KeyMap.Quit): return ui, tea.Quit - case ui.activePage == 1 && key.Matches(msg, ui.common.KeyMap.Back): - ui.activePage = 0 + case ui.activePage == repoPage && key.Matches(msg, ui.common.KeyMap.Back): + ui.activePage = selectionPage } } case common.ErrorMsg: @@ -154,8 +161,8 @@ func (ui *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case selector.SelectMsg: switch msg.IdentifiableItem.(type) { case selection.Item: - if ui.activePage == 0 { - ui.activePage = 1 + if ui.activePage == selectionPage { + ui.activePage = repoPage cmds = append(cmds, ui.setRepoCmd(msg.ID())) } } @@ -185,6 +192,7 @@ func (ui *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // View implements tea.Model. func (ui *UI) View() string { var view string + wm, hm := ui.getMargins() footer := ui.footer.View() style := ui.common.Styles.App.Copy() switch ui.state { @@ -193,15 +201,13 @@ func (ui *UI) View() string { case errorState: err := ui.common.Styles.ErrorTitle.Render("Bummer") err += ui.common.Styles.ErrorBody.Render(ui.error.Error()) - view = ui.common.Styles.ErrorBody.Copy(). + view = ui.common.Styles.Error.Copy(). Width(ui.common.Width - - style.GetWidth() - - style.GetHorizontalFrameSize() - + wm - ui.common.Styles.ErrorBody.GetHorizontalFrameSize()). Height(ui.common.Height - - style.GetHeight() - - style.GetVerticalFrameSize() - - ui.common.Styles.Header.GetVerticalFrameSize() - 2). + hm - + ui.common.Styles.Error.GetVerticalFrameSize()). Render(err) case loadedState: view = ui.pages[ui.activePage].View() @@ -209,8 +215,7 @@ func (ui *UI) View() string { view = "Unknown state :/ this is a bug!" } return style.Render( - lipgloss.JoinVertical( - lipgloss.Bottom, + lipgloss.JoinVertical(lipgloss.Bottom, ui.header.View(), view, footer,