package views import ( "fmt" tea "github.com/charmbracelet/bubbletea" "github.com/lucasdataproyects/devfactory/tui" ) type volumesState int const ( volumesLoading volumesState = iota volumesList volumesAction ) type volumesLoadedMsg []DockerVolume type volumesActionMsg struct{ output string; err error } type VolumesModel struct { state volumesState list tui.ListModel spinner tui.SpinnerModel styles tui.Styles volumes []DockerVolume err error } func NewVolumesModel(styles tui.Styles) VolumesModel { return VolumesModel{ state: volumesLoading, list: tui.NewList(nil), spinner: tui.NewSpinner("Loading volumes..."), styles: styles, } } func (m VolumesModel) Init() tea.Cmd { return tea.Batch(m.spinner.Init(), loadVolumes) } func loadVolumes() tea.Msg { volumes, err := ListVolumes() if err != nil { return volumesLoadedMsg(nil) } return volumesLoadedMsg(volumes) } func (m VolumesModel) Update(msg tea.Msg) (VolumesModel, tea.Cmd) { switch msg := msg.(type) { case volumesLoadedMsg: m.volumes = []DockerVolume(msg) items := make([]tui.ListItem, len(m.volumes)) for i, v := range m.volumes { items[i] = tui.ListItem{ Title: v.Name, Description: fmt.Sprintf("Driver: %s", v.Driver), Value: v, } } m.list.SetItems(items) m.state = volumesList return m, nil case volumesActionMsg: if msg.err != nil { m.err = msg.err } m.state = volumesList return m, loadVolumes case tea.KeyMsg: if m.state == volumesList { switch msg.String() { case "r": m.state = volumesLoading return m, tea.Batch(m.spinner.Init(), loadVolumes) case "d", "delete": if item := m.list.SelectedItem(); item != nil { vol := item.Value.(DockerVolume) m.state = volumesAction return m, func() tea.Msg { err := RemoveVolume(vol.Name) return volumesActionMsg{output: "Removed", err: err} } } } } } var cmd tea.Cmd switch m.state { case volumesLoading, volumesAction: var model tea.Model model, cmd = m.spinner.Update(msg) m.spinner = model.(tui.SpinnerModel) case volumesList: var model tea.Model model, cmd = m.list.Update(msg) m.list = model.(tui.ListModel) } return m, cmd } // HandleBack retrocede un nivel. Retorna true si ya estaba en estado base. func (m *VolumesModel) HandleBack() bool { return true } func (m VolumesModel) View() string { switch m.state { case volumesLoading, volumesAction: return m.spinner.View() case volumesList: if len(m.volumes) == 0 { return m.styles.Muted.Render("No volumes found. Press 'r' to refresh.") } help := m.styles.Muted.Render(" d: remove │ r: refresh") view := m.list.View() + "\n" + help if m.err != nil { view += "\n" + m.styles.Error.Render(fmt.Sprintf(" Error: %v", m.err)) } return view } return "" }