mirror of
https://github.com/charmbracelet/glow
synced 2024-11-10 14:14:17 +00:00
Draw a spinner in the file listing while stuff is loading
This commit is contained in:
parent
df95fa6ba9
commit
70070d2948
2 changed files with 69 additions and 59 deletions
79
ui/stash.go
79
ui/stash.go
|
@ -74,6 +74,20 @@ func (m markdownsByLocalFirst) Less(i, j int) bool {
|
|||
return m[i].CreatedAt.After(*m[j].CreatedAt)
|
||||
}
|
||||
|
||||
type loadedState byte
|
||||
|
||||
const (
|
||||
loadedStash loadedState = 1 << iota
|
||||
loadedNews
|
||||
loadedLocalFiles
|
||||
)
|
||||
|
||||
func (s loadedState) done() bool {
|
||||
return s&loadedStash != 0 &&
|
||||
s&loadedNews != 0 &&
|
||||
s&loadedLocalFiles != 0
|
||||
}
|
||||
|
||||
type stashState int
|
||||
|
||||
const (
|
||||
|
@ -84,18 +98,19 @@ const (
|
|||
)
|
||||
|
||||
type stashModel struct {
|
||||
cc *charm.Client
|
||||
state stashState
|
||||
markdowns []*markdown
|
||||
spinner spinner.Model
|
||||
noteInput textinput.Model
|
||||
terminalWidth int
|
||||
terminalHeight int
|
||||
loading bool // are we currently loading something?
|
||||
fullyLoaded bool // Have we loaded everything from the server?
|
||||
hasStash bool // do we have stashed files to show?
|
||||
hasLocalFiles bool // do we have local files to show?
|
||||
hasNews bool // do we have news to show?
|
||||
cc *charm.Client
|
||||
state stashState
|
||||
markdowns []*markdown
|
||||
spinner spinner.Model
|
||||
noteInput textinput.Model
|
||||
terminalWidth int
|
||||
terminalHeight int
|
||||
stashFullyLoaded bool // have we loaded everything from the server?
|
||||
hasStash bool // do we have stashed files to show?
|
||||
hasLocalFiles bool // do we have local files to show?
|
||||
hasNews bool // do we have news to show?
|
||||
loadingFromNetwork bool // are we currently loading something from the network?
|
||||
loaded loadedState // what's loaded? we find out with bitmasking
|
||||
|
||||
// This is just the index of the current page in view. To get the index
|
||||
// of the selected item as it relates to the full set of documents we've
|
||||
|
@ -171,11 +186,11 @@ func newStashModel() stashModel {
|
|||
ni.Focus()
|
||||
|
||||
m := stashModel{
|
||||
spinner: s,
|
||||
noteInput: ni,
|
||||
page: 1,
|
||||
paginator: p,
|
||||
loading: true,
|
||||
spinner: s,
|
||||
noteInput: ni,
|
||||
page: 1,
|
||||
paginator: p,
|
||||
loadingFromNetwork: true,
|
||||
}
|
||||
|
||||
return m
|
||||
|
@ -191,13 +206,22 @@ func stashUpdate(msg tea.Msg, m stashModel) (stashModel, tea.Cmd) {
|
|||
|
||||
switch msg := msg.(type) {
|
||||
|
||||
// We're finished searching for local files
|
||||
case localFileSearchFinished:
|
||||
m.loaded |= loadedLocalFiles
|
||||
|
||||
// Stash results have come in from the server
|
||||
case gotStashMsg:
|
||||
m.loading = false
|
||||
// This doesn't mean the whole stash listing is loaded, but some we've
|
||||
// finished checking for the stash, at least, so mark the stash as
|
||||
// loaded here.
|
||||
m.loaded |= loadedStash
|
||||
|
||||
m.loadingFromNetwork = false
|
||||
|
||||
if len(msg) == 0 {
|
||||
// If the server comes back with nothing then we've got everything
|
||||
m.fullyLoaded = true
|
||||
m.stashFullyLoaded = true
|
||||
} else {
|
||||
docs := wrapMarkdowns(stashedMarkdown, msg)
|
||||
m.addMarkdowns(docs...)
|
||||
|
@ -206,6 +230,7 @@ func stashUpdate(msg tea.Msg, m stashModel) (stashModel, tea.Cmd) {
|
|||
|
||||
// News has come in from the server
|
||||
case gotNewsMsg:
|
||||
m.loaded |= loadedNews
|
||||
if len(msg) > 0 {
|
||||
docs := wrapMarkdowns(newsMarkdown, msg)
|
||||
m.addMarkdowns(docs...)
|
||||
|
@ -213,7 +238,7 @@ func stashUpdate(msg tea.Msg, m stashModel) (stashModel, tea.Cmd) {
|
|||
}
|
||||
|
||||
case spinner.TickMsg:
|
||||
if m.state == stashStateLoadingDocument {
|
||||
if !m.loaded.done() || m.loadingFromNetwork || m.state == stashStateLoadingDocument {
|
||||
m.spinner, cmd = spinner.Update(msg, m.spinner)
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
|
@ -320,9 +345,9 @@ func stashUpdate(msg tea.Msg, m stashModel) (stashModel, tea.Cmd) {
|
|||
|
||||
// If we're on the last page and we haven't loaded everything, get
|
||||
// more stuff.
|
||||
if m.paginator.OnLastPage() && !m.loading && !m.fullyLoaded {
|
||||
if m.paginator.OnLastPage() && !m.loadingFromNetwork && !m.stashFullyLoaded {
|
||||
m.page++
|
||||
m.loading = true
|
||||
m.loadingFromNetwork = true
|
||||
cmds = append(cmds, loadStash(m))
|
||||
}
|
||||
|
||||
|
@ -397,6 +422,11 @@ func stashView(m stashModel) string {
|
|||
s += " " + spinner.View(m.spinner) + " Loading document..."
|
||||
case stashStateReady, stashStateSettingNote, stashStatePromptDelete:
|
||||
|
||||
loadingIndicator := ""
|
||||
if !m.loaded.done() || m.loadingFromNetwork {
|
||||
loadingIndicator = spinner.View(m.spinner)
|
||||
}
|
||||
|
||||
// We need to fill any empty height with newlines so the footer reaches
|
||||
// the bottom.
|
||||
numBlankLines := max(0, (m.terminalHeight-stashViewTopPadding-stashViewBottomPadding)%stashViewItemHeight)
|
||||
|
@ -431,14 +461,15 @@ func stashView(m stashModel) string {
|
|||
if m.paginator.TotalPages > 1 {
|
||||
pagination = paginator.View(m.paginator)
|
||||
|
||||
if !m.fullyLoaded {
|
||||
if !m.stashFullyLoaded {
|
||||
pagination += common.Subtle(" ···")
|
||||
}
|
||||
}
|
||||
|
||||
s += fmt.Sprintf(
|
||||
" %s\n\n %s\n\n%s\n\n%s %s\n\n %s",
|
||||
" %s %s\n\n %s\n\n%s\n\n%s %s\n\n %s",
|
||||
glowLogoView(" Glow "),
|
||||
loadingIndicator,
|
||||
header,
|
||||
stashPopulatedView(m),
|
||||
blankLines,
|
||||
|
|
49
ui/ui.go
49
ui/ui.go
|
@ -7,6 +7,7 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/bubbles/spinner"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/charm"
|
||||
"github.com/charmbracelet/charm/ui/common"
|
||||
|
@ -59,20 +60,6 @@ type gotNewsMsg []*charm.Markdown
|
|||
|
||||
// MODEL
|
||||
|
||||
type loadedState byte
|
||||
|
||||
const (
|
||||
loadedStash loadedState = 1 << iota
|
||||
loadedNews
|
||||
loadedLocalFiles
|
||||
)
|
||||
|
||||
func (s loadedState) done() bool {
|
||||
return s&loadedStash != 0 &&
|
||||
s&loadedNews != 0 &&
|
||||
s&loadedLocalFiles != 0
|
||||
}
|
||||
|
||||
type state int
|
||||
|
||||
const (
|
||||
|
@ -111,8 +98,7 @@ type model struct {
|
|||
pager pagerModel
|
||||
terminalWidth int
|
||||
terminalHeight int
|
||||
cwd string // directory from which we're running Glow
|
||||
loaded loadedState // what's loaded? we find out with bitmasking
|
||||
cwd string // directory from which we're running Glow
|
||||
|
||||
// Channel that receives paths to local markdown files
|
||||
// (via the github.com/muesli/gitcha package)
|
||||
|
@ -139,15 +125,18 @@ func initialize(style string) func() (tea.Model, tea.Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
return model{
|
||||
stash: newStashModel(),
|
||||
pager: newPagerModel(style),
|
||||
state: stateShowStash,
|
||||
keygenState: keygenUnstarted,
|
||||
}, tea.Batch(
|
||||
findLocalFiles,
|
||||
newCharmClient,
|
||||
)
|
||||
m := model{
|
||||
stash: newStashModel(),
|
||||
pager: newPagerModel(style),
|
||||
state: stateShowStash,
|
||||
keygenState: keygenUnstarted,
|
||||
}
|
||||
|
||||
return m, tea.Batch(
|
||||
findLocalFiles,
|
||||
newCharmClient,
|
||||
spinner.Tick(m.stash.spinner),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,10 +239,6 @@ func update(msg tea.Msg, mdl tea.Model) (tea.Model, tea.Cmd) {
|
|||
}
|
||||
cmds = append(cmds, findNextLocalFile(m))
|
||||
|
||||
// We're finished searching for local files
|
||||
case localFileSearchFinished:
|
||||
m.loaded |= loadedLocalFiles
|
||||
|
||||
case sshAuthErrMsg:
|
||||
// If we haven't run the keygen yet, do that
|
||||
if m.keygenState != keygenFinished {
|
||||
|
@ -278,12 +263,6 @@ func update(msg tea.Msg, mdl tea.Model) (tea.Model, tea.Cmd) {
|
|||
m.pager.cc = msg
|
||||
cmds = append(cmds, loadStash(m.stash), loadNews(m.stash))
|
||||
|
||||
case gotStashMsg:
|
||||
m.loaded |= loadedStash
|
||||
|
||||
case gotNewsMsg:
|
||||
m.loaded |= loadedNews
|
||||
|
||||
case noteSavedMsg:
|
||||
// A note was saved to a document. This will have be done in the
|
||||
// pager, so we'll need to find the corresponding note in the stash.
|
||||
|
|
Loading…
Reference in a new issue