diff --git a/config/parser.go b/config/parser.go index 47c2ed08..1ae87389 100644 --- a/config/parser.go +++ b/config/parser.go @@ -12,6 +12,7 @@ import ( type PRSectionConfig struct { Title string Filters string + Limit *int `yaml:"limit,omitempty"` } type PreviewConfig struct { @@ -20,7 +21,8 @@ type PreviewConfig struct { } type Defaults struct { - Preview PreviewConfig + Preview PreviewConfig + PrsLimit int `yaml:"prsLimit"` } type Config struct { @@ -46,6 +48,7 @@ func (parser ConfigParser) getDefaultConfig() Config { Open: true, Width: 50, }, + PrsLimit: 20, }, PRSections: []PRSectionConfig{ { diff --git a/data/api.go b/data/api.go index 36f3e984..e2299b70 100644 --- a/data/api.go +++ b/data/api.go @@ -9,10 +9,6 @@ import ( graphql "github.com/cli/shurcooL-graphql" ) -const ( - Limit = 20 -) - type PullRequestData struct { Number int Title string @@ -114,7 +110,7 @@ func makeQuery(query string) string { return fmt.Sprintf("is:pr %s", query) } -func FetchRepoPullRequests(query string) ([]PullRequestData, error) { +func FetchRepoPullRequests(query string, limit int) ([]PullRequestData, error) { var err error client, err := gh.GQLClient(nil) if err != nil { @@ -131,7 +127,7 @@ func FetchRepoPullRequests(query string) ([]PullRequestData, error) { } variables := map[string]interface{}{ "query": graphql.String(makeQuery(query)), - "limit": graphql.Int(Limit), + "limit": graphql.Int(limit), } err = client.Query("SearchPullRequests", &queryResult, variables) if err != nil { diff --git a/ui/mainViewport.go b/ui/mainViewport.go index 78e480ce..cfc30c83 100644 --- a/ui/mainViewport.go +++ b/ui/mainViewport.go @@ -49,6 +49,8 @@ func (m *Model) onLineDown() { m.mainViewport.bottomBoundId += 1 m.mainViewport.model.LineDown(prRowHeight) } + + m.sidebarViewport.YOffset = 0 } func (m *Model) onLineUp() { @@ -58,6 +60,7 @@ func (m *Model) onLineUp() { m.mainViewport.bottomBoundId -= 1 m.mainViewport.model.LineUp(prRowHeight) } + m.sidebarViewport.YOffset = 0 } func (m *Model) RenderMainViewPort() string { diff --git a/ui/model.go b/ui/model.go index 15dcf867..3907357e 100644 --- a/ui/model.go +++ b/ui/model.go @@ -36,14 +36,21 @@ func NewModel(logFile *os.File) Model { func (m *Model) updateOnConfigFetched(config config.Config) { m.config = &config - var data []section + var data []Section for i, sectionConfig := range m.config.PRSections { s := spinner.Model{Spinner: spinner.Dot} - data = append(data, section{ + data = append(data, Section{ Id: i, Config: sectionConfig, Spinner: s, IsLoading: true, + Limit: func() int { + if sectionConfig.Limit != nil { + return *sectionConfig.Limit + } + + return m.config.Defaults.PrsLimit + }(), }) } m.data = &data diff --git a/ui/modelUtils.go b/ui/modelUtils.go index a1a10149..d0516d90 100644 --- a/ui/modelUtils.go +++ b/ui/modelUtils.go @@ -2,7 +2,7 @@ package ui import "github.com/dlvhdr/gh-prs/utils" -func (m Model) getCurrSection() *section { +func (m Model) getCurrSection() *Section { if m.data == nil || len(*m.data) == 0 { return nil } @@ -43,7 +43,7 @@ func (m *Model) nextPr() { m.cursor.currPrId = newPrId } -func (m Model) getSectionAt(id int) *section { +func (m Model) getSectionAt(id int) *Section { return &(*m.data)[id] } diff --git a/ui/section.go b/ui/section.go index 148c31f3..8b32ded9 100644 --- a/ui/section.go +++ b/ui/section.go @@ -3,7 +3,6 @@ package ui import ( "fmt" - "github.com/charmbracelet/bubbles/paginator" "github.com/charmbracelet/bubbles/spinner" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" @@ -11,13 +10,13 @@ import ( "github.com/dlvhdr/gh-prs/data" ) -type section struct { +type Section struct { Id int Config config.PRSectionConfig Prs []PullRequest Spinner spinner.Model IsLoading bool - Paginator paginator.Model + Limit int } type tickMsg struct { @@ -25,7 +24,7 @@ type tickMsg struct { InternalTickMsg tea.Msg } -func (section *section) Tick(spinnerTickCmd tea.Cmd) func() tea.Msg { +func (section *Section) Tick(spinnerTickCmd tea.Cmd) func() tea.Msg { return func() tea.Msg { return tickMsg{ SectionId: section.Id, @@ -34,9 +33,9 @@ func (section *section) Tick(spinnerTickCmd tea.Cmd) func() tea.Msg { } } -func (section *section) fetchSectionPullRequests() tea.Cmd { +func (section *Section) fetchSectionPullRequests() tea.Cmd { return func() tea.Msg { - fetched, err := data.FetchRepoPullRequests(section.Config.Filters) + fetched, err := data.FetchRepoPullRequests(section.Config.Filters, section.Limit) if err != nil { return sectionPullRequestsFetchedMsg{ SectionId: section.Id, @@ -67,14 +66,14 @@ func (m Model) makeRenderPullRequestCmd(sectionId int) tea.Cmd { } } -func (section *section) renderLoadingState() string { +func (section *Section) renderLoadingState() string { if !section.IsLoading { return "" } return spinnerStyle.Render(fmt.Sprintf("%s Fetching Pull Requests...", section.Spinner.View())) } -func (section *section) renderEmptyState() string { +func (section *Section) renderEmptyState() string { emptyState := emptyStateStyle.Render(fmt.Sprintf( "No PRs were found that match the given filters: %s", lipgloss.NewStyle().Italic(true).Render(section.Config.Filters), @@ -102,6 +101,8 @@ func (m *Model) renderTableHeader() string { Render("Title") return headerStyle. + PaddingLeft(mainContentPadding). + PaddingRight(mainContentPadding). Width(m.mainViewport.model.Width). MaxWidth(m.mainViewport.model.Width). Render( @@ -155,6 +156,6 @@ func (m *Model) renderCurrentSection() string { Render(m.RenderMainViewPort()) } -func (section section) numPrs() int { +func (section Section) numPrs() int { return len(section.Prs) } diff --git a/ui/sidebar.go b/ui/sidebar.go index 424985f5..b2be80bb 100644 --- a/ui/sidebar.go +++ b/ui/sidebar.go @@ -1,6 +1,7 @@ package ui import ( + "fmt" "regexp" "strings" @@ -18,7 +19,7 @@ func (m *Model) renderSidebar() string { return "" } - height := m.sidebarViewport.Height + height := m.sidebarViewport.Height + pagerHeight style := sideBarStyle.Copy(). Height(height). MaxHeight(height). @@ -32,7 +33,11 @@ func (m *Model) renderSidebar() string { ) } - return style.Copy().Render(m.sidebarViewport.View()) + return style.Copy().Render(lipgloss.JoinVertical( + lipgloss.Left, + m.sidebarViewport.View(), + pagerStyle.Copy().Render(fmt.Sprintf("%d%%", int(m.sidebarViewport.ScrollPercent()*100))), + )) } func (m *Model) setSidebarViewportContent() { diff --git a/ui/styles.go b/ui/styles.go index 15aef898..e605470f 100644 --- a/ui/styles.go +++ b/ui/styles.go @@ -103,7 +103,7 @@ var ( BorderLeft(true). BorderStyle(lipgloss.Border{ Top: "", - Bottom: " ", + Bottom: "", Left: "│", Right: "", TopLeft: "", diff --git a/ui/ui.go b/ui/ui.go index 9fe5767f..626f5e81 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -19,7 +19,7 @@ type Model struct { keys utils.KeyMap err error config *config.Config - data *[]section + data *[]Section mainViewport MainViewport sidebarViewport viewport.Model cursor cursor @@ -123,7 +123,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { utils.OpenBrowser(currPR.Data.Url) return m, nil case key.Matches(msg, m.keys.Refresh): - var newData []section + var newData []Section for _, section := range *m.data { if section.IsLoading { return m, nil