feat: add dedicated Profile management page

This commit is contained in:
proxyctl coordinator
2026-07-17 22:37:25 +08:00
parent 7c0b4481d7
commit d34ce0cd6b
11 changed files with 583 additions and 160 deletions
+30 -23
View File
@@ -42,16 +42,12 @@ func (p terminalPresentation) mainView(model presentationState, width, height in
},
}
if model.confirmation != nil {
var details strings.Builder
details.WriteString(p.theme.section.Render(model.confirmation.Title))
if model.confirmation.Summary != "" {
fmt.Fprintf(&details, "\n%s", model.confirmation.Summary)
}
for _, detail := range model.confirmation.Details {
fmt.Fprintf(&details, "\n• %s", detail)
dialog := newConfirmationDialog(*model.confirmation)
if model.confirmationDialog != nil {
dialog = *model.confirmationDialog
}
page.dashboard = nil
page.primary = details.String()
page.primary = dialog.view()
page.context = "Cancellation is selected by default."
}
return page
@@ -108,7 +104,7 @@ func (p terminalPresentation) helpView(model presentationState) terminalPage {
func (p terminalPresentation) profilesView(model presentationState) terminalPage {
var list strings.Builder
if len(model.snapshot.Profiles) == 0 {
list.WriteString("No Proxy Profiles. Press n to create one.")
list.WriteString("No Proxy Profiles saved. Press n to create one.")
}
for i, item := range model.snapshot.Profiles {
cursor, active := " ", " "
@@ -125,22 +121,26 @@ func (p terminalPresentation) profilesView(model presentationState) terminalPage
}
context := selectedProfileDetails(p, model)
footer := "n: new e: edit d: delete a/Enter: activate\n↑/k ↓/j: select q/Esc: back"
switch {
case model.confirm:
footer = "y: confirm n/Esc: cancel"
if len(model.snapshot.Profiles) == 1 {
context = "Delete Profile — this is the final Proxy Profile. Managed configuration will remain in place and become Drifted."
} else {
context = "Delete Profile?"
footer := "n: create e: edit Enter: edit d: delete PgUp/PgDn: scroll details\n↑/k ↓/j: select q/Esc: back"
if len(model.snapshot.Profiles) == 0 {
footer = "n: create a Proxy Profile 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",
focusLine: -1,
}
}
return terminalPage{
header: p.theme.title.Render("Proxy Profiles"),
primary: list.String(),
context: context,
footer: footer,
focusLine: model.selected,
header: p.theme.title.Render("Proxy Profile management"),
primary: list.String(),
context: context,
footer: footer,
focusLine: model.selected,
primaryOffset: model.profileOffset,
contextOffset: model.profileDetails,
}
}
@@ -158,7 +158,14 @@ func selectedProfileDetails(p terminalPresentation, model presentationState) str
fmt.Fprintf(&details, "\nHTTP: %s\nHTTPS: %s\nALL/SOCKS: %s",
profile.ObscureURL(selected.HTTPURL), profile.ObscureURL(selected.HTTPSURL), profile.ObscureURL(selected.AllURL))
}
fmt.Fprintf(&details, "\nBypass: %s", strings.Join(selected.Bypass, ", "))
details.WriteString("\nBypass:")
if len(selected.Bypass) == 0 {
details.WriteString(" (none)")
} else {
for _, item := range selected.Bypass {
fmt.Fprintf(&details, "\n • %s", item)
}
}
return details.String()
}