pi-agent: Implement Help navigation consistency

This commit is contained in:
proxyctl coordinator
2026-07-17 23:33:56 +08:00
parent 112f700650
commit c93dc61ef6
10 changed files with 544 additions and 64 deletions
+40 -27
View File
@@ -23,7 +23,7 @@ func (p terminalPresentation) mainView(model presentationState, width, height in
catalog := newTargetCatalog(model.snapshot, model.showUnavailable, model.selectedTargetID)
footer := p.dashboardFooter(model, catalog)
if model.confirmation != nil && !model.operationActive {
footer = "y: confirm Enter/n/Esc: Cancel q: exit"
footer = "←/→/Tab: choose y: confirm Enter: choose n/q/Esc: cancel ?: help"
}
if model.currentError != nil {
footer += "\ne: expand/collapse current error x: acknowledge error"
@@ -45,13 +45,16 @@ func (p terminalPresentation) mainView(model presentationState, width, height in
if model.picker.open {
page.dashboard = nil
page.primary = model.picker.view(model.snapshot, width, max(5, height-9))
page.footer = "↑/↓ PgUp/PgDn: select Enter: activate Esc: cancel"
page.footer = "Type to search ↑/↓ PgUp/PgDn: select Enter: activate\nEsc: cancel ?: help"
if width < 70 {
page.footer = "Type: search ↑/↓: select Enter: activate\nEsc: cancel ?: help"
}
}
if model.driftResolutionTargetID != "" && model.confirmation == nil {
if selected, ok := newTargetCatalog(model.snapshot, true, model.driftResolutionTargetID).selected(model.driftResolutionTargetID); ok {
page.dashboard = nil
page.primary, page.context = p.driftResolutionView(selected)
page.footer = "r: Reapply Active Profile o: Restore Original\nEnter/Esc: Cancel"
page.footer = "r: Reapply Active Profile o: Restore Original\nEnter/q/Esc: cancel ?: help"
}
}
if model.confirmation != nil {
@@ -62,6 +65,7 @@ func (p terminalPresentation) mainView(model presentationState, width, height in
page.dashboard = nil
page.primary = dialog.view()
page.context = "Cancellation is selected by default."
page.footer = "←/→/Tab: choose y: confirm Enter: choose\nn/q/Esc: cancel ?: help"
}
return page
}
@@ -95,7 +99,16 @@ func (p terminalPresentation) dashboardFooter(model presentationState, catalog t
visibility = "u: hide unavailable"
}
if model.dashboardFocus == targetDetailsPane {
footer := "↑/k ↓/j PgUp/PgDn: scroll Tab: focus Targets " + visibility + "\np: switch Active Profile m: manage Proxy Profiles ?: help q: quit"
if model.width < wideWidth {
if model.operationActive {
return "↑/k ↓/j PgUp/PgDn: browse Tab: focus Targets\n?: help q/Ctrl+C: defer exit; mutations disabled"
}
if model.width < 70 {
return "↑/k ↓/j PgUp/PgDn: scroll Tab: focus Targets\np: switch Profile m: manage ?: help q: quit"
}
return "↑/k ↓/j PgUp/PgDn: scroll Tab: focus Targets\np: switch Active Profile m: manage Proxy Profiles ?: help q: quit"
}
footer := "↑/k ↓/j PgUp/PgDn: scroll Tab: focus Targets " + visibility + "\np: switch Active Profile m: manage Proxy Profiles ?: help q/Ctrl+C: quit"
if model.operationActive {
footer = "↑/k ↓/j PgUp/PgDn: scroll Tab: focus Targets ?: help\nMutations disabled: wait for the current mutation to finish"
}
@@ -110,31 +123,28 @@ func (p terminalPresentation) dashboardFooter(model presentationState, catalog t
} else {
actions = "Space: " + label + " disabled (" + availability.compactReason + ") " + actions
}
footer := actions + "\np: switch Active Profile m: manage Proxy Profiles r: refresh ?: help q: quit"
if model.width < wideWidth {
if availability.available {
actions = "Space: " + label + " ↑/k ↓/j: select Tab: details"
} else {
actions = "Space: " + label + " disabled ↑/k ↓/j: select Tab: details"
}
if model.operationActive {
return actions + "\n?: help q/Ctrl+C: defer exit; mutations disabled"
}
if model.width < 70 {
return actions + "\np: switch Profile m: manage ?: help q: quit"
}
return actions + "\np: switch Active Profile m: manage Proxy Profiles ?: help q: quit"
}
footer := actions + "\np: switch Active Profile m: manage Proxy Profiles r: refresh ?: help q/Ctrl+C: quit"
if model.operationActive {
footer = actions + "\n?: help q: defer safe exit; new mutations disabled"
}
return footer
}
func (p terminalPresentation) helpView(model presentationState) terminalPage {
var body strings.Builder
for _, item := range model.snapshot.Targets {
fmt.Fprintf(&body, "%s\n%s\n%s\n", p.theme.section.Render(item.Description.Name), item.Description.Summary, item.Description.Details)
if item.Available {
fmt.Fprintf(&body, "Detected: %s\n\n", item.AvailabilityEvidence)
} else {
fmt.Fprintf(&body, "Not detected: %s\n\n", item.AvailabilityEvidence)
}
}
return terminalPage{
header: p.theme.title.Render("proxyctl Help — built-in Targets"),
primary: strings.TrimRight(body.String(), "\n"),
footer: "↑/k ↓/j: navigate Space: toggle p: switch Active Profile\nm: manage Proxy Profiles r: refresh ?: help q/Escape: back",
focusLine: 0,
}
}
func (p terminalPresentation) profilesView(model presentationState) terminalPage {
var list strings.Builder
if len(model.snapshot.Profiles) == 0 {
@@ -155,15 +165,18 @@ func (p terminalPresentation) profilesView(model presentationState) terminalPage
}
context := selectedProfileDetails(p, model)
footer := "n: create e: edit Enter: edit d: delete PgUp/PgDn: scroll details\n↑/k ↓/j: select q/Esc: back"
footer := "n: create e: edit Enter: edit d: delete PgUp/PgDn: scroll details\n↑/k ↓/j: select ?: help q/Esc: back"
if model.width < 80 {
footer = "↑/k ↓/j: select PgUp/PgDn: details n: create\ne/Enter: edit d: delete ?: help q/Esc: back"
}
if len(model.snapshot.Profiles) == 0 {
footer = "n: create a Proxy Profile q/Esc: back"
footer = "n: create a Proxy Profile ?: help q/Esc: back"
}
if model.profileDelete != nil {
return terminalPage{
header: p.theme.title.Render("Proxy Profile management"),
primary: model.profileDelete.dialog.view(),
footer: "←/→/Tab: choose Enter: choose y: delete n/q/Esc: cancel",
footer: "←/→/Tab: choose Enter: choose y: delete\nn/q/Esc: cancel ?: help",
focusLine: -1,
}
}
@@ -226,7 +239,7 @@ func (p terminalPresentation) formView(model presentationState) terminalPage {
return terminalPage{
header: p.theme.title.Render(fmt.Sprintf("%s Proxy Profile — %s mode", action, model.form.profile.Mode)),
primary: fields.String(),
footer: "Tab/↑/↓: move Ctrl+T: toggle Single/Advanced\nCtrl+S: save Ctrl+D: detect protocol Esc: cancel",
footer: "Tab/↑/↓: move Ctrl+T: mode Ctrl+S: save\nCtrl+D: probe ?: help q/Esc: cancel",
focusLine: model.form.field,
}
}