app.go (2901B)
1 package main 2 3 import ( 4 "github.com/charmbracelet/bubbles/help" 5 "github.com/charmbracelet/bubbles/key" 6 "github.com/charmbracelet/bubbles/list" 7 tea "github.com/charmbracelet/bubbletea" 8 "github.com/charmbracelet/lipgloss" 9 ) 10 11 const ( 12 defaultWidth = 20 13 listHeight = 14 14 ) 15 16 type appModel struct { 17 projects []*Project 18 19 projectList list.Model 20 actionSelector list.Model 21 help help.Model 22 23 selectedProject *Project 24 selectedAction string 25 showActionSelector bool 26 shouldSave bool 27 quitting bool 28 } 29 30 func newAppModel(projects []*Project) *appModel { 31 return &appModel{ 32 projects: projects, 33 projectList: newProjectListModel(projects), 34 actionSelector: newActionSelectorModel(), 35 help: initialHelp(), 36 } 37 } 38 39 func (m appModel) Init() tea.Cmd { 40 return nil 41 } 42 43 func (m appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { 44 switch msg := msg.(type) { 45 case tea.WindowSizeMsg: 46 h, _ := appStyle.GetFrameSize() 47 width := msg.Width - h 48 m.actionSelector.SetSize(width, listHeight) 49 m.projectList.SetSize(width, listHeight) 50 51 case tea.KeyMsg: 52 switch { 53 54 case key.Matches(msg, keys.ForceQuit): 55 m.shouldSave = false 56 m.quitting = true 57 return m, tea.Quit 58 } 59 } 60 61 var cmds []tea.Cmd 62 63 if m.showActionSelector { 64 cmds = append(cmds, m.updateActionSelector(msg)) 65 } else { 66 cmds = append(cmds, m.updateProjectList(msg)) 67 } 68 69 return m, tea.Batch(cmds...) 70 } 71 72 func (m *appModel) updateActionSelector(msg tea.Msg) tea.Cmd { 73 switch msg := msg.(type) { 74 case tea.KeyMsg: 75 switch { 76 case key.Matches(msg, keys.CloseActionSelector): 77 m.showActionSelector = false 78 m.selectedProject = nil 79 return nil 80 81 case key.Matches(msg, keys.Select): 82 action := m.actionSelector.SelectedItem().(actionItem) 83 m.selectedAction = action.command 84 m.showActionSelector = false 85 m.shouldSave = true 86 m.quitting = true 87 return tea.Quit 88 } 89 } 90 91 var cmd tea.Cmd 92 m.actionSelector, cmd = m.actionSelector.Update(msg) 93 return cmd 94 } 95 96 func (m *appModel) updateProjectList(msg tea.Msg) tea.Cmd { 97 switch msg := msg.(type) { 98 case tea.KeyMsg: 99 switch { 100 case key.Matches(msg, keys.Toggle): 101 project := m.projectList.SelectedItem().(*Project) 102 project.IsActive = !project.IsActive 103 return nil 104 105 case key.Matches(msg, keys.Select): 106 project := m.projectList.SelectedItem().(*Project) 107 m.selectedProject = project 108 m.showActionSelector = true 109 return nil 110 111 case key.Matches(msg, keys.Quit): 112 m.shouldSave = true 113 m.quitting = true 114 return tea.Quit 115 } 116 } 117 118 var cmd tea.Cmd 119 m.projectList, cmd = m.projectList.Update(msg) 120 return cmd 121 } 122 123 func (m appModel) View() string { 124 if m.quitting { 125 return "" 126 } 127 var views []string 128 if m.showActionSelector { 129 views = append(views, m.actionSelector.View()) 130 } else { 131 views = append(views, m.projectList.View()) 132 } 133 return appStyle.Render(lipgloss.JoinVertical(lipgloss.Left, views...)) 134 }