project-manager

Project directory management for macOS
git clone git://git.lair.cx/project-manager
Log | Files | Refs | README | LICENSE

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 }