bubble.go

  1package tui
  2
  3import (
  4	"fmt"
  5	"smoothie/git"
  6	"smoothie/tui/bubbles/commits"
  7	"time"
  8
  9	tea "github.com/charmbracelet/bubbletea"
 10	"github.com/gliderlabs/ssh"
 11)
 12
 13type sessionState int
 14
 15const (
 16	startState sessionState = iota
 17	errorState
 18	loadedState
 19	quittingState
 20	quitState
 21)
 22
 23type Model struct {
 24	state          sessionState
 25	error          string
 26	info           string
 27	width          int
 28	height         int
 29	windowChanges  <-chan ssh.Window
 30	repoSource     *git.RepoSource
 31	commitTimeline *commits.Bubble
 32}
 33
 34func NewModel(width int, height int, windowChanges <-chan ssh.Window, repoSource *git.RepoSource) *Model {
 35	m := &Model{
 36		width:         width,
 37		height:        height,
 38		windowChanges: windowChanges,
 39		repoSource:    repoSource,
 40	}
 41	m.state = startState
 42	return m
 43}
 44
 45func (m *Model) Init() tea.Cmd {
 46	return tea.Batch(m.windowChangesCmd, m.loadGitCmd)
 47}
 48
 49func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 50	cmds := make([]tea.Cmd, 0)
 51	// Always allow state, error, info, window resize and quit messages
 52	switch msg := msg.(type) {
 53	case stateMsg:
 54		m.state = msg.state
 55	case tea.KeyMsg:
 56		switch msg.String() {
 57		case "q", "ctrl+c":
 58			return m, tea.Quit
 59		case "j", "k", "up", "down":
 60			_, cmd := m.commitTimeline.Update(msg)
 61			cmds = append(cmds, cmd)
 62		}
 63	case errMsg:
 64		m.error = msg.Error()
 65		m.state = errorState
 66		return m, nil
 67	case infoMsg:
 68		m.info = msg.text
 69	case windowMsg:
 70		cmds = append(cmds, m.windowChangesCmd)
 71	case tea.WindowSizeMsg:
 72		m.width = msg.Width
 73		m.height = msg.Height
 74		m.commitTimeline.Height = msg.Height
 75	}
 76	return m, tea.Batch(cmds...)
 77}
 78
 79func (m *Model) View() string {
 80	pad := 6
 81	h := headerStyle.Width(m.width - pad).Render("Charm Beta")
 82	f := footerStyle.Render(m.info)
 83	s := ""
 84	content := ""
 85	switch m.state {
 86	case loadedState:
 87		s += m.commitTimeline.View()
 88	case errorState:
 89		s += errorStyle.Render(fmt.Sprintf("Bummer: %s", m.error))
 90	default:
 91		s = normalStyle.Render(fmt.Sprintf("Doing something weird %d", m.state))
 92	}
 93	content = h + "\n" + s + "\n" + f
 94	return appBoxStyle.Render(content)
 95}
 96
 97func SessionHandler(reposPath string) func(ssh.Session) (tea.Model, []tea.ProgramOption) {
 98	rs := git.NewRepoSource(reposPath, time.Second*10)
 99	return func(s ssh.Session) (tea.Model, []tea.ProgramOption) {
100		if len(s.Command()) == 0 {
101			pty, changes, active := s.Pty()
102			if !active {
103				return nil, nil
104			}
105			return NewModel(pty.Window.Width, pty.Window.Height, changes, rs), []tea.ProgramOption{tea.WithAltScreen()}
106		}
107		return nil, nil
108	}
109}