Every workspace split into real panes: 19 panes across 7 workspaces, one program per panel
This commit is contained in:
85
tui/board.go
85
tui/board.go
@@ -49,6 +49,8 @@ type boardModel struct {
|
||||
activity []paperclip.Activity
|
||||
needsTab int
|
||||
|
||||
panel string
|
||||
scroll int
|
||||
zones *zone.Manager
|
||||
filter string
|
||||
typing bool
|
||||
@@ -64,10 +66,10 @@ const (
|
||||
focusCount
|
||||
)
|
||||
|
||||
func newBoardModel(c *paperclip.Client, proj paperclip.Project, folder string) boardModel {
|
||||
func newBoardModel(c *paperclip.Client, proj paperclip.Project, folder, panel string) boardModel {
|
||||
// One click-zone manager for the whole program, created once. Wrapping each
|
||||
// panel separately drifts as soon as a pane is resized.
|
||||
return boardModel{client: c, project: proj, folder: folder, loading: true, zones: zone.New()}
|
||||
return boardModel{client: c, project: proj, folder: folder, panel: panel, loading: true, zones: zone.New()}
|
||||
}
|
||||
|
||||
func (m boardModel) Init() tea.Cmd {
|
||||
@@ -228,14 +230,28 @@ func (m boardModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
}
|
||||
return m, tea.Quit
|
||||
case "up", "k":
|
||||
if m.panel == "detail" || m.panel == "needs" {
|
||||
m.scroll--
|
||||
return m, nil
|
||||
}
|
||||
if m.cursor > 0 {
|
||||
m.cursor--
|
||||
if m.panel != "" {
|
||||
_ = rememberTask(m.folder, m.visible()[m.cursor].Issue.Identifier)
|
||||
}
|
||||
return m, m.loadDetail(m.selectedID())
|
||||
}
|
||||
return m, nil
|
||||
case "down", "j":
|
||||
if m.panel == "detail" || m.panel == "needs" {
|
||||
m.scroll++
|
||||
return m, nil
|
||||
}
|
||||
if m.cursor < len(m.visible())-1 {
|
||||
m.cursor++
|
||||
if m.panel != "" {
|
||||
_ = rememberTask(m.folder, m.visible()[m.cursor].Issue.Identifier)
|
||||
}
|
||||
return m, m.loadDetail(m.selectedID())
|
||||
}
|
||||
return m, nil
|
||||
@@ -264,12 +280,12 @@ func (m boardModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
}
|
||||
return m, nil
|
||||
case "[", "h":
|
||||
if m.focus == focusNeeds && m.needsTab > 0 {
|
||||
if (m.panel == "needs" || m.focus == focusNeeds) && m.needsTab > 0 {
|
||||
m.needsTab--
|
||||
}
|
||||
return m, nil
|
||||
case "]", "l":
|
||||
if m.focus == focusNeeds && m.needsTab < 1 {
|
||||
if (m.panel == "needs" || m.focus == focusNeeds) && m.needsTab < 1 {
|
||||
m.needsTab++
|
||||
}
|
||||
return m, nil
|
||||
@@ -323,6 +339,9 @@ func (m boardModel) View() string {
|
||||
m.width, m.height))
|
||||
}
|
||||
|
||||
if m.panel != "" {
|
||||
return m.singleView()
|
||||
}
|
||||
if m.showHelp {
|
||||
return helpOverlay("keys on this panel", [][2]string{
|
||||
{"↑ ↓ j k", "choose a task"},
|
||||
@@ -395,6 +414,64 @@ func (m boardModel) View() string {
|
||||
return m.zones.Scan(strings.Join([]string{header, page, footer}, "\n"))
|
||||
}
|
||||
|
||||
// singleView is one panel filling the pane, for when the Board workspace is
|
||||
// split into real panes: tasks, the chosen task, and what needs a person.
|
||||
func (m boardModel) singleView() string {
|
||||
width := m.width
|
||||
height := m.height
|
||||
var body []string
|
||||
title := "tasks"
|
||||
tabs := []string(nil)
|
||||
active := 0
|
||||
footer := ""
|
||||
|
||||
switch m.panel {
|
||||
case "detail":
|
||||
title = "the chosen task"
|
||||
body = m.summaryLines(width - 3)
|
||||
footer = hintLine([]string{
|
||||
keyHint("r", "read again"),
|
||||
keyHint("R", "rebuild"),
|
||||
keyHint("?", "keys"),
|
||||
}, width)
|
||||
case "needs":
|
||||
title = "needs you"
|
||||
tabs = []string{"decisions", "activity"}
|
||||
active = m.needsTab
|
||||
if m.needsTab == 0 {
|
||||
body = m.needsLines(width-3, height-3)
|
||||
} else {
|
||||
body = m.activityLines(width-3, height-3)
|
||||
}
|
||||
footer = hintLine([]string{
|
||||
keyHint("[ ]", "switch tab"),
|
||||
keyHint("r", "read again"),
|
||||
keyHint("R", "rebuild"),
|
||||
}, width)
|
||||
default:
|
||||
body = m.treeLines(width - 3)
|
||||
footer = hintLine([]string{
|
||||
keyHint("↑↓ j k", "choose"),
|
||||
keyHint("enter", "show everywhere"),
|
||||
keyHint("a", "assign"),
|
||||
keyHint("u", "unblock"),
|
||||
keyHint("/", "filter"),
|
||||
keyHint("?", "keys"),
|
||||
}, width)
|
||||
}
|
||||
|
||||
if m.showHelp {
|
||||
return helpOverlay(title, [][2]string{
|
||||
{"↑ ↓ j k", "choose a task"},
|
||||
{"enter", "show it in every workspace"},
|
||||
{"a / u", "assign / unblock"},
|
||||
{"/", "filter"}, {"[ ]", "switch tab"},
|
||||
{"r / R", "read again / rebuild"}, {"q", "leave"},
|
||||
}, width, height)
|
||||
}
|
||||
return singlePanel(title, tabs, active, body, width, height, footer, m.scroll)
|
||||
}
|
||||
|
||||
func (m boardModel) headerLine() string {
|
||||
left := panelTitleStyle().Render("Board") + mutedStyle2().Render(" · "+m.project.Name)
|
||||
state := "reading…"
|
||||
|
||||
Reference in New Issue
Block a user