package views import ( "fmt" tea "github.com/charmbracelet/bubbletea" "github.com/lucasdataproyects/devfactory/tui" ) type imagesState int const ( imagesLoading imagesState = iota imagesList imagesAction ) type imagesLoadedMsg []DockerImage type imagesActionMsg struct{ output string; err error } type ImagesModel struct { state imagesState list tui.FilteredListModel spinner tui.SpinnerModel styles tui.Styles images []DockerImage err error } func NewImagesModel(styles tui.Styles) ImagesModel { return ImagesModel{ state: imagesLoading, list: tui.NewFilteredList(nil, "Filter images..."), spinner: tui.NewSpinner("Loading images..."), styles: styles, } } func (m ImagesModel) Init() tea.Cmd { return tea.Batch(m.spinner.Init(), loadImages) } func loadImages() tea.Msg { images, err := ListImages() if err != nil { return imagesLoadedMsg(nil) } return imagesLoadedMsg(images) } func (m ImagesModel) Update(msg tea.Msg) (ImagesModel, tea.Cmd) { switch msg := msg.(type) { case imagesLoadedMsg: m.images = []DockerImage(msg) items := make([]tui.ListItem, len(m.images)) for i, img := range m.images { tag := img.Tag if tag == "" { tag = "latest" } items[i] = tui.ListItem{ Title: fmt.Sprintf("%s:%s", img.Repository, tag), Description: fmt.Sprintf("Size: %s — %s", img.Size, img.ID[:12]), Value: img, } } m.list.SetItems(items) m.state = imagesList return m, nil case imagesActionMsg: if msg.err != nil { m.err = msg.err } m.state = imagesList return m, loadImages case tea.KeyMsg: if m.state == imagesList { switch msg.String() { case "r": m.state = imagesLoading return m, tea.Batch(m.spinner.Init(), loadImages) case "d", "delete": if item := m.list.SelectedItem(); item != nil { img := item.Value.(DockerImage) m.state = imagesAction return m, func() tea.Msg { err := RemoveImage(img.ID) return imagesActionMsg{output: "Removed", err: err} } } } } } var cmd tea.Cmd switch m.state { case imagesLoading, imagesAction: var model tea.Model model, cmd = m.spinner.Update(msg) m.spinner = model.(tui.SpinnerModel) case imagesList: var model tea.Model model, cmd = m.list.Update(msg) m.list = model.(tui.FilteredListModel) } return m, cmd } // HandleBack retrocede un nivel. Retorna true si ya estaba en estado base. func (m *ImagesModel) HandleBack() bool { return true } func (m ImagesModel) View() string { switch m.state { case imagesLoading, imagesAction: return m.spinner.View() case imagesList: if len(m.images) == 0 { return m.styles.Muted.Render("No images found. Press 'r' to refresh.") } help := m.styles.Muted.Render(" d: remove │ r: refresh │ /: filter") 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 "" }