diff --git a/go.mod b/go.mod index dcb8113..e4fb41f 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module mend go 1.25.5 require ( + github.com/charmbracelet/bubbles v0.21.0 github.com/charmbracelet/bubbletea v1.3.10 github.com/charmbracelet/lipgloss v1.1.0 ) diff --git a/go.sum b/go.sum index 4789639..d1a20cb 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs= +github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg= github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= diff --git a/main.go b/main.go index 0ef9140..b17a3a6 100644 --- a/main.go +++ b/main.go @@ -4,7 +4,9 @@ import ( "fmt" "mend/styles" "os" + "time" + "github.com/charmbracelet/bubbles/spinner" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) @@ -27,32 +29,69 @@ notes: I anyways need to create the model struct even if blank - Init func is for bubbletea to call once at start so both are needed - all widths and heights are character count based +- async updates are via cmds (tea.Cmd ) that are no arg funcs that return +a tea.Msg ( that is basically a struct and hence has the data needed ) +this data in msg when returned to the update func is used to update the model */ type model struct { width int - quit bool + tree *FsTreeImpl + // spinner needs to be state as I need to update the spinner on + // each tick in update func + spinner spinner.Model + loading bool } // initial model state func createModel() model { + s := spinner.New() + s.Spinner = spinner.Dot + s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("205")) + return model{ - width: 20, // char count + width: 20, // char count + tree: nil, + spinner: s, + loading: true, } } // =================== bubbletea ui fns =================== // these need to be on the "model" ( duck typing "implements" interface ) + +type treeLoadedMsg struct { + tree *FsTreeImpl +} + +func loadTreeCmd() tea.Msg { + time.Sleep(3 * time.Second) // delay sim + + cwd, err := os.Getwd() + if err != nil { + fmt.Println("Error getting cwd:", err) + os.Exit(1) + } + return treeLoadedMsg{tree: NewFsTree(cwd)} +} + func (m model) Init() tea.Cmd { - return nil + return tea.Batch(m.spinner.Tick, loadTreeCmd) } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { + case treeLoadedMsg: + m.tree = msg.tree + m.loading = false + return m, nil + case spinner.TickMsg: + var cmd tea.Cmd + m.spinner, cmd = m.spinner.Update(msg) + return m, cmd case tea.KeyMsg: switch msg.String() { case "q", "ctrl+c": - m.quit = true return m, tea.Quit } } @@ -60,6 +99,10 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } func (m model) View() string { + if m.loading { + return fmt.Sprintf("%s Loading files...", m.spinner.View()) + } + left := lipgloss.NewStyle(). Width(m.width). Render("section1")