Skip to content

Commit

Permalink
refactor(ui): resolve race conditions and clean up code
Browse files Browse the repository at this point in the history
  • Loading branch information
aymanbagabas committed Oct 5, 2023
1 parent 06fae16 commit bc6a9f2
Show file tree
Hide file tree
Showing 10 changed files with 542 additions and 353 deletions.
110 changes: 86 additions & 24 deletions cmd/soft/browse.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,21 @@ var browseCmd = &cobra.Command{
return err

Check failure on line 33 in cmd/soft/browse.go

View workflow job for this annotation

GitHub Actions / lint-soft

error returned from external package is unwrapped: sig: func path/filepath.Abs(path string) (string, error) (wrapcheck)
}

rp = abs

r, err := git.Open(rp)
if err != nil {
return err
}

// Bubble Tea uses Termenv default output so we have to use the same
// thing here.
output := termenv.DefaultOutput()
ctx := cmd.Context()
c := common.NewCommon(ctx, output, 0, 0)
m := &model{
m: repo.New(c),
r: r,
c: c,
m: repo.New(c,
repo.NewReadme(c),
repo.NewFiles(c),
repo.NewLog(c),
repo.NewRefs(c, git.RefsHeads),
repo.NewRefs(c, git.RefsTags),
),
repoPath: abs,
c: c,
}

m.f = footer.New(c, m)
Expand All @@ -69,24 +68,25 @@ func init() {
rootCmd.AddCommand(browseCmd)
}

type state int

const (
startState state = iota
errorState
)

type model struct {
m *repo.Repo
f *footer.Footer
r *git.Repository
repoPath string
c common.Common
state state
showFooter bool
error error
}

var _ tea.Model = &model{}

func (m model) repo() proto.Repository {
return repository{r: m.r}
}

func (m model) repoCmd() tea.Msg {
return repo.RepoMsg(m.repo())
}

func (m *model) SetSize(w, h int) {
m.c.SetSize(w, h)
style := m.c.Styles.App.Copy()
Expand All @@ -102,35 +102,73 @@ func (m *model) SetSize(w, h int) {

// ShortHelp implements help.KeyMap.
func (m model) ShortHelp() []key.Binding {
return m.m.ShortHelp()
switch m.state {

Check failure on line 105 in cmd/soft/browse.go

View workflow job for this annotation

GitHub Actions / lint-soft

missing cases in switch of type main.state: main.startState (exhaustive)
case errorState:
return []key.Binding{
m.c.KeyMap.Back,
m.c.KeyMap.Quit,
m.c.KeyMap.Help,
}
default:
return m.m.ShortHelp()
}
}

// FullHelp implements help.KeyMap.
func (m model) FullHelp() [][]key.Binding {
return m.m.FullHelp()
switch m.state {

Check failure on line 119 in cmd/soft/browse.go

View workflow job for this annotation

GitHub Actions / lint-soft

missing cases in switch of type main.state: main.startState (exhaustive)
case errorState:
return [][]key.Binding{
{
m.c.KeyMap.Back,
},
{
m.c.KeyMap.Quit,
m.c.KeyMap.Help,
},
}
default:
return m.m.FullHelp()
}
}

// Init implements tea.Model.
func (m *model) Init() tea.Cmd {
rr, err := git.Open(m.repoPath)
if err != nil {
return common.ErrorCmd(err)
}

r := repository{rr}
return tea.Batch(
m.m.Init(),
m.f.Init(),
m.repoCmd,
repo.UpdateRefCmd(m.repo()),
func() tea.Msg {
return repo.RepoMsg(r)
},
repo.UpdateRefCmd(r),
)
}

// Update implements tea.Model.
func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.c.Logger.Debugf("msg received: %T", msg)
cmds := make([]tea.Cmd, 0)
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.SetSize(msg.Width, msg.Height)
case tea.KeyMsg:
switch {
case key.Matches(msg, m.c.KeyMap.Back) && m.error != nil:
m.error = nil
m.state = startState
// Always show the footer on error.
m.showFooter = m.f.ShowAll()
case key.Matches(msg, m.c.KeyMap.Help):
cmds = append(cmds, footer.ToggleFooterCmd)
case key.Matches(msg, m.c.KeyMap.Quit):
// Stop bubblezone background workers.
m.c.Zone.Close()
return m, tea.Quit
}
case tea.MouseMsg:
Expand All @@ -144,6 +182,10 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case footer.ToggleFooterMsg:
m.f.SetShowAll(!m.f.ShowAll())
m.showFooter = !m.showFooter
case common.ErrorMsg:
m.error = msg
m.state = errorState
m.showFooter = true
}

f, cmd := m.f.Update(msg)
Expand Down Expand Up @@ -171,7 +213,27 @@ func (m *model) View() string {
view = lipgloss.JoinVertical(lipgloss.Left, view, m.f.View())
}

return m.c.Zone.Scan(m.c.Styles.App.Render(view))
switch m.state {

Check failure on line 216 in cmd/soft/browse.go

View workflow job for this annotation

GitHub Actions / lint-soft

missing cases in switch of type main.state: main.startState (exhaustive)
case errorState:
appStyle := m.c.Styles.App.Copy()
wm, hm := appStyle.GetHorizontalFrameSize(), appStyle.GetVerticalFrameSize()
if m.showFooter {
hm += m.f.Height()
}

err := m.c.Styles.ErrorTitle.Render("Bummer")
err += m.c.Styles.ErrorBody.Render(m.error.Error())
return m.c.Styles.Error.Copy().
Width(m.c.Width -
wm -
m.c.Styles.ErrorBody.GetHorizontalFrameSize()).
Height(m.c.Height -
hm -
m.c.Styles.Error.GetVerticalFrameSize()).
Render(err)
default:
return m.c.Zone.Scan(m.c.Styles.App.Render(view))
}
}

type repository struct {
Expand Down
9 changes: 8 additions & 1 deletion server/ssh/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/charmbracelet/bubbles/list"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/soft-serve/git"
"github.com/charmbracelet/soft-serve/server/proto"
"github.com/charmbracelet/soft-serve/server/ui/common"
"github.com/charmbracelet/soft-serve/server/ui/components/footer"
Expand Down Expand Up @@ -133,7 +134,13 @@ func (ui *UI) SetSize(width, height int) {
// Init implements tea.Model.
func (ui *UI) Init() tea.Cmd {
ui.pages[selectionPage] = selection.New(ui.common)
ui.pages[repoPage] = repo.New(ui.common)
ui.pages[repoPage] = repo.New(ui.common,
repo.NewReadme(ui.common),
repo.NewFiles(ui.common),
repo.NewLog(ui.common),
repo.NewRefs(ui.common, git.RefsHeads),
repo.NewRefs(ui.common, git.RefsTags),
)
ui.SetSize(ui.common.Width, ui.common.Height)
cmds := make([]tea.Cmd, 0)
cmds = append(cmds,
Expand Down
18 changes: 18 additions & 0 deletions server/ui/common/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,21 @@ type Component interface {
help.KeyMap
SetSize(width, height int)
}

// TabComponenet represents a model that is mounted to a tab.
// TODO: find a better name

Check failure on line 16 in server/ui/common/component.go

View workflow job for this annotation

GitHub Actions / lint-soft

Comment should end in a period (godot)
type TabComponent interface {
Component

// StatusBarValue returns the status bar value component.
StatusBarValue() string

// StatusBarInfo returns the status bar info component.
StatusBarInfo() string

// SpinnerID returns the ID of the spinner.
SpinnerID() int

// TabName returns the name of the tab.
TabName() string
}
Loading

0 comments on commit bc6a9f2

Please sign in to comment.