diff --git a/ui/components/issuessection/issuessection.go b/ui/components/issuessection/issuessection.go index d8b2508e..46165218 100644 --- a/ui/components/issuessection/issuessection.go +++ b/ui/components/issuessection/issuessection.go @@ -412,6 +412,10 @@ func (m Model) IsLoading() bool { return m.Table.IsLoading() } +func (m *Model) SetIsLoading(val bool) { + m.Table.SetIsLoading(val) +} + func (m Model) GetPagerContent() string { pagerContent := "" if m.TotalCount > 0 { diff --git a/ui/components/prssection/prssection.go b/ui/components/prssection/prssection.go index 6357a17a..6d8c2eb9 100644 --- a/ui/components/prssection/prssection.go +++ b/ui/components/prssection/prssection.go @@ -373,6 +373,7 @@ func (m *Model) FetchNextPageSectionRows() []tea.Cmd { startCursor = m.PageInfo.StartCursor } taskId := fmt.Sprintf("fetching_prs_%d_%s", m.Id, startCursor) + isFirstFetch := m.LastFetchTaskId == "" m.LastFetchTaskId = taskId task := context.Task{ Id: taskId, @@ -416,7 +417,7 @@ func (m *Model) FetchNextPageSectionRows() []tea.Cmd { } cmds = append(cmds, fetchCmd) - if m.PageInfo == nil { + if isFirstFetch { m.Table.SetIsLoading(true) cmds = append(cmds, m.Table.StartLoadingSpinner()) @@ -432,16 +433,22 @@ func (m *Model) ResetRows() { func FetchAllSections( ctx context.ProgramContext, + prs []section.Section, ) (sections []section.Section, fetchAllCmd tea.Cmd) { fetchPRsCmds := make([]tea.Cmd, 0, len(ctx.Config.PRSections)) sections = make([]section.Section, 0, len(ctx.Config.PRSections)) for i, sectionConfig := range ctx.Config.PRSections { sectionModel := NewModel( - i+1, + i+1, // 0 is the search section &ctx, sectionConfig, time.Now(), - ) // 0 is the search section + ) + if len(prs) > 0 && len(prs) >= i+1 && prs[i+1] != nil { + oldSection := prs[i+1].(*Model) + sectionModel.Prs = oldSection.Prs + sectionModel.LastFetchTaskId = oldSection.LastFetchTaskId + } sections = append(sections, §ionModel) fetchPRsCmds = append( fetchPRsCmds, @@ -502,13 +509,23 @@ func (m Model) IsLoading() bool { return m.Table.IsLoading() } +func (m *Model) SetIsLoading(val bool) { + m.Table.SetIsLoading(val) +} + func (m Model) GetPagerContent() string { pagerContent := "" + timeElapsed := utils.TimeElapsed(m.LastUpdated()) + if timeElapsed == "now" { + timeElapsed = "just now" + } else { + timeElapsed = fmt.Sprintf("~%v ago", timeElapsed) + } if m.TotalCount > 0 { pagerContent = fmt.Sprintf( - "%v %v • %v %v/%v • Fetched %v", + "%v Updated %v • %v %v/%v (fetched %v)", constants.WaitingIcon, - m.LastUpdated().Format("01/02 15:04:05"), + timeElapsed, m.SingularForm, m.Table.GetCurrItem()+1, m.TotalCount, diff --git a/ui/components/reposection/reposection.go b/ui/components/reposection/reposection.go index bcb29ed0..83adc592 100644 --- a/ui/components/reposection/reposection.go +++ b/ui/components/reposection/reposection.go @@ -557,6 +557,10 @@ func (m *Model) GetTotalCount() *int { return utils.IntPtr(len(m.Branches)) } +func (m *Model) SetIsLoading(val bool) { + m.Table.SetIsLoading(val) +} + func (m *Model) GetPagerContent() string { s := lipgloss.NewStyle().Background(m.Ctx.Styles.ListViewPort.PagerStyle.GetBackground()) mod := s.Foreground(lipgloss.Color("#e0af68")).Render(fmt.Sprintf(" %d", len(m.repo.Status.Modified))) diff --git a/ui/components/section/section.go b/ui/components/section/section.go index 74502c18..64e4b719 100644 --- a/ui/components/section/section.go +++ b/ui/components/section/section.go @@ -88,7 +88,7 @@ func NewModel( ), )), "Loading...", - true, + false, ) return m } @@ -129,6 +129,7 @@ type Table interface { BuildRows() []table.Row ResetRows() IsLoading() bool + SetIsLoading(val bool) } type Search interface { diff --git a/ui/ui.go b/ui/ui.go index 5aaae9ba..0909d6a6 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -230,6 +230,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case key.Matches(msg, m.keys.Refresh): currSection.ResetFilters() currSection.ResetRows() + currSection.SetIsLoading(true) cmds = append(cmds, currSection.FetchNextPageSectionRows()...) case key.Matches(msg, m.keys.RefreshAll): @@ -489,7 +490,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.syncMainContentWidth() newSections, fetchSectionsCmds := m.fetchAllViewSections() m.setCurrentViewSections(newSections) - cmds = append(cmds, fetchSectionsCmds, fetchUser, m.doRefreshAtInterval()) + cmds = append(cmds, fetchSectionsCmds, fetchUser, m.doRefreshAtInterval(), m.doUpdateFooterAtInterval()) case intervalRefresh: newSections, fetchSectionsCmds := m.fetchAllViewSections() @@ -553,6 +554,10 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.WindowSizeMsg: m.onWindowSizeChanged(msg) + case updateFooterMsg: + m.footer, cmd = m.footer.Update(msg) + cmds = append(cmds, cmd, m.doUpdateFooterAtInterval()) + case constants.ErrMsg: m.ctx.Error = msg.Err } @@ -754,7 +759,7 @@ func (m *Model) fetchAllViewSections() ([]section.Section, tea.Cmd) { m.repo = &s return nil, cmd } else if m.ctx.View == config.PRsView { - return prssection.FetchAllSections(m.ctx) + return prssection.FetchAllSections(m.ctx, m.prs) } else { return issuessection.FetchAllSections(m.ctx) } @@ -955,9 +960,20 @@ func (m *Model) doRefreshAtInterval() tea.Cmd { } return tea.Tick( - time.Minute*time.Duration(m.ctx.Config.Defaults.RefetchIntervalMinutes), + time.Second*30, func(t time.Time) tea.Msg { return intervalRefresh(t) }, ) } + +type updateFooterMsg struct{} + +func (m *Model) doUpdateFooterAtInterval() tea.Cmd { + return tea.Tick( + time.Second*10, + func(t time.Time) tea.Msg { + return updateFooterMsg{} + }, + ) +}