diff --git a/ui/components/statusbar/statusbar.go b/ui/components/statusbar/statusbar.go index dc9f8cc7fda4a786169fdd035acae81f28aab470..5a677d67bba111fe23a53eb9cc449fd5d2f4652d 100644 --- a/ui/components/statusbar/statusbar.go +++ b/ui/components/statusbar/statusbar.go @@ -51,13 +51,14 @@ func (s *StatusBar) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (s *StatusBar) View() string { st := s.common.Styles w := lipgloss.Width + help := st.StatusBarHelp.Render("? Help") key := st.StatusBarKey.Render(s.msg.Key) info := "" if s.msg.Info != "" { info = st.StatusBarInfo.Render(s.msg.Info) } branch := st.StatusBarBranch.Render(s.msg.Branch) - maxWidth := s.common.Width - w(key) - w(info) - w(branch) + maxWidth := s.common.Width - w(key) - w(info) - w(branch) - w(help) v := truncate.StringWithTail(s.msg.Value, uint(maxWidth-st.StatusBarValue.GetHorizontalFrameSize()), "…") value := st.StatusBarValue. Width(maxWidth). @@ -68,5 +69,6 @@ func (s *StatusBar) View() string { value, info, branch, + help, ) } diff --git a/ui/pages/repo/filesitem.go b/ui/pages/repo/filesitem.go index f0e53a508b4ec7b3c5260dee3682e47d56a76652..d59dba7abc545b47da9165fd37d48b97adc5f19b 100644 --- a/ui/pages/repo/filesitem.go +++ b/ui/pages/repo/filesitem.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "io/fs" + "strings" "github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/list" @@ -103,8 +104,9 @@ func (d FileItemDelegate) Render(w io.Writer, m list.Model, index int, listItem name := i.Title() size := humanize.Bytes(uint64(i.entry.Size())) + sizeLen := lipgloss.Width(size) if i.entry.IsTree() { - size = "" + size = strings.Repeat(" ", sizeLen) name = s.TreeFileDir.Render(name) } var cs lipgloss.Style @@ -116,23 +118,20 @@ func (d FileItemDelegate) Render(w io.Writer, m list.Model, index int, listItem cs = s.TreeItemInactive fmt.Fprint(w, s.TreeItemSelector.Render(" ")) } + sizeStyle := s.TreeFileSize.Copy(). + Width(8). + Align(lipgloss.Right). + MarginLeft(1) leftMargin := s.TreeItemSelector.GetMarginLeft() + s.TreeItemSelector.GetWidth() + s.TreeFileMode.GetMarginLeft() + s.TreeFileMode.GetWidth() + - cs.GetMarginLeft() - rightMargin := s.TreeFileSize.GetMarginLeft() + lipgloss.Width(size) - name = common.TruncateString(name, m.Width()-leftMargin-rightMargin) - sizeStyle := s.TreeFileSize.Copy(). - Width(m.Width() - - leftMargin - - s.TreeFileSize.GetMarginLeft() - - lipgloss.Width(name)). - Align(lipgloss.Right) - if index == m.Index() { - sizeStyle = sizeStyle.Bold(true) - } - fmt.Fprint(w, s.TreeFileMode.Render(mode.String())+ - cs.Render(name)+ - sizeStyle.Render(size)) + cs.GetMarginLeft() + + sizeStyle.GetHorizontalFrameSize() + name = common.TruncateString(name, m.Width()-leftMargin) + fmt.Fprint(w, + s.TreeFileMode.Render(mode.String()), + sizeStyle.Render(size), + cs.Render(name), + ) } diff --git a/ui/pages/repo/repo.go b/ui/pages/repo/repo.go index 98d759fd3bd86d785fc921099914b317d3e5827f..8fca562d6315d986ba2e03cc5dda6b32947f45fa 100644 --- a/ui/pages/repo/repo.go +++ b/ui/pages/repo/repo.go @@ -289,11 +289,15 @@ func (r *Repo) updateStatusBarCmd() tea.Msg { } value := r.boxes[r.activeTab].(statusbar.Model).StatusBarValue() info := r.boxes[r.activeTab].(statusbar.Model).StatusBarInfo() + ref := "" + if r.ref != nil { + ref = r.ref.Name().Short() + } return statusbar.StatusBarMsg{ Key: r.selectedRepo.Repo(), Value: value, Info: info, - Branch: fmt.Sprintf(" %s", r.ref.Name().Short()), + Branch: fmt.Sprintf(" %s", ref), } } diff --git a/ui/styles/styles.go b/ui/styles/styles.go index 58470cdef135e3ca6a1702c70de7278426e026ec..5b25dfe6c11310bff563b5d1b40d35fd8bf66d8d 100644 --- a/ui/styles/styles.go +++ b/ui/styles/styles.go @@ -91,6 +91,7 @@ type Styles struct { StatusBarValue lipgloss.Style StatusBarInfo lipgloss.Style StatusBarBranch lipgloss.Style + StatusBarHelp lipgloss.Style Tabs lipgloss.Style TabInactive lipgloss.Style @@ -110,8 +111,9 @@ func DefaultStyles() *Styles { s.Header = lipgloss.NewStyle(). Foreground(lipgloss.Color("15")). - Align(lipgloss.Right). + Align(lipgloss.Left). Height(1). + MarginBottom(1). Bold(true) s.Menu = lipgloss.NewStyle(). @@ -199,7 +201,7 @@ func DefaultStyles() *Styles { s.RepoHeader = lipgloss.NewStyle(). Height(2). Border(lipgloss.NormalBorder(), false, false, true, false). - BorderForeground(lipgloss.Color("241")) + BorderForeground(lipgloss.Color("238")) s.RepoHeaderName = lipgloss.NewStyle(). Foreground(lipgloss.Color("15")). @@ -210,6 +212,7 @@ func DefaultStyles() *Styles { Foreground(lipgloss.Color("15")) s.Footer = lipgloss.NewStyle(). + MarginTop(1). Padding(0, 1). Height(1) @@ -356,8 +359,8 @@ func DefaultStyles() *Styles { s.StatusBarValue = lipgloss.NewStyle(). Padding(0, 1). - Background(lipgloss.Color("#373737")). - Foreground(lipgloss.Color("#F1F1F1")) + Background(lipgloss.Color("235")). + Foreground(lipgloss.Color("243")) s.StatusBarInfo = lipgloss.NewStyle(). Padding(0, 1). @@ -369,6 +372,11 @@ func DefaultStyles() *Styles { Background(lipgloss.Color("#6E6ED8")). Foreground(lipgloss.Color("#F1F1F1")) + s.StatusBarHelp = lipgloss.NewStyle(). + Padding(0, 1). + Background(lipgloss.Color("237")). + Foreground(lipgloss.Color("243")) + s.Tabs = lipgloss.NewStyle() s.TabInactive = lipgloss.NewStyle(). @@ -381,7 +389,7 @@ func DefaultStyles() *Styles { s.TabSeparator = lipgloss.NewStyle(). SetString("│"). Padding(0, 1). - Foreground(lipgloss.Color("241")) + Foreground(lipgloss.Color("238")) return s } diff --git a/ui/ui.go b/ui/ui.go index 3992f0fb4851389960392cbe50e4e7a90ef4efa7..d51a07c001ae7611348256165021050640904c51 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -45,6 +45,7 @@ type UI struct { state sessionState header *header.Header footer *footer.Footer + showFooter bool error error } @@ -62,22 +63,28 @@ func New(cfg *config.Config, s ssh.Session, c common.Common, initialRepo string) state: startState, header: h, initialRepo: initialRepo, + showFooter: true, } ui.footer = footer.New(c, ui) return ui } func (ui *UI) getMargins() (wm, hm int) { - wm = ui.common.Styles.App.GetHorizontalFrameSize() - hm = ui.common.Styles.App.GetVerticalFrameSize() + - ui.common.Styles.Footer.GetVerticalFrameSize() + - ui.footer.Height() + style := ui.common.Styles.App.Copy() switch ui.activePage { case selectionPage: hm += ui.common.Styles.Header.GetHeight() + ui.common.Styles.Header.GetVerticalFrameSize() case repoPage: } + wm += style.GetHorizontalFrameSize() + hm += style.GetVerticalFrameSize() + if ui.showFooter { + // NOTE: we don't use the footer's style to determine the margins + // because footer.Height() is the height of the footer after applying + // the styles. + hm += ui.footer.Height() + } return } @@ -175,16 +182,26 @@ func (ui *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case key.Matches(msg, ui.common.KeyMap.Back) && ui.error != nil: ui.error = nil ui.state = loadedState + // Always show the footer on error. + ui.showFooter = true case key.Matches(msg, ui.common.KeyMap.Help): ui.footer.SetShowAll(!ui.footer.ShowAll()) + // Show the footer when on repo page and shot all help. + if ui.activePage == repoPage { + ui.showFooter = !ui.showFooter + } case key.Matches(msg, ui.common.KeyMap.Quit): return ui, tea.Quit case ui.activePage == repoPage && key.Matches(msg, ui.common.KeyMap.Back): ui.activePage = selectionPage + // Always show the footer on selection page. + ui.showFooter = true } } case repo.RepoMsg: ui.activePage = repoPage + // Show the footer on repo page if show all is set. + ui.showFooter = ui.footer.ShowAll() case common.ErrorMsg: ui.error = msg ui.state = errorState @@ -223,7 +240,6 @@ func (ui *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) { 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 { case startState: @@ -252,11 +268,14 @@ func (ui *UI) View() string { ) case repoPage: } - return style.Render( - lipgloss.JoinVertical(lipgloss.Bottom, + if ui.showFooter { + view = lipgloss.JoinVertical(lipgloss.Bottom, view, - footer, - ), + ui.footer.View(), + ) + } + return style.Render( + view, ) }