101 lines
2.6 KiB
Go
101 lines
2.6 KiB
Go
package tui
|
|
|
|
import "proxyctl/internal/app"
|
|
|
|
func targetActionLabel(kind app.TargetActionKind) string {
|
|
switch kind {
|
|
case app.EnableTargetAction:
|
|
return "Enable"
|
|
case app.DisableTargetAction:
|
|
return "Disable"
|
|
case app.ApplyProfileTargetAction:
|
|
return "Apply Profile"
|
|
case app.ResolveDriftTargetAction:
|
|
return "Resolve"
|
|
case app.ReapplyActiveProfileAction:
|
|
return "Reapply Active Profile"
|
|
case app.RestoreOriginalAction:
|
|
return "Restore Original"
|
|
default:
|
|
return "Unavailable"
|
|
}
|
|
}
|
|
|
|
type dashboardPane uint8
|
|
|
|
const (
|
|
targetListPane dashboardPane = iota
|
|
targetDetailsPane
|
|
)
|
|
|
|
// targetCatalog owns the dashboard's product-ordered Target projection. It is
|
|
// the only place where availability filtering and identity-based selection are
|
|
// combined, so rendering and input handling cannot accidentally select by a
|
|
// transient row number.
|
|
type targetCatalog struct {
|
|
items []app.TargetSnapshot
|
|
}
|
|
|
|
func newTargetCatalog(snapshot app.Snapshot, includeUnavailable bool, selectedID string) targetCatalog {
|
|
items := make([]app.TargetSnapshot, 0, len(snapshot.Targets))
|
|
for _, item := range snapshot.Targets {
|
|
// Available Targets are the routine default. If progressive detection
|
|
// proves the selected identity unavailable, keep that one row visible
|
|
// until the user selects another Target rather than silently moving the
|
|
// selection to a different product.
|
|
if item.Available || includeUnavailable || item.ID == selectedID || item.DetectionPhase != app.TargetReady {
|
|
items = append(items, item)
|
|
}
|
|
}
|
|
return targetCatalog{items: items}
|
|
}
|
|
|
|
func (c targetCatalog) firstID() string {
|
|
if len(c.items) == 0 {
|
|
return ""
|
|
}
|
|
return c.items[0].ID
|
|
}
|
|
|
|
func (c targetCatalog) index(id string) int {
|
|
for i := range c.items {
|
|
if c.items[i].ID == id {
|
|
return i
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
func (c targetCatalog) selected(id string) (app.TargetSnapshot, bool) {
|
|
index := c.index(id)
|
|
if index < 0 {
|
|
return app.TargetSnapshot{}, false
|
|
}
|
|
return c.items[index], true
|
|
}
|
|
|
|
func (c targetCatalog) move(id string, delta int) string {
|
|
if len(c.items) == 0 {
|
|
return ""
|
|
}
|
|
index := c.index(id)
|
|
if index < 0 {
|
|
index = 0
|
|
}
|
|
index = max(0, min(len(c.items)-1, index+delta))
|
|
return c.items[index].ID
|
|
}
|
|
|
|
// retain keeps an identity when possible and otherwise chooses the product row
|
|
// nearest its former position. This is used after refresh and visibility
|
|
// changes; terminal resize never needs to touch selection at all.
|
|
func (c targetCatalog) retain(id string, formerIndex int) string {
|
|
if c.index(id) >= 0 {
|
|
return id
|
|
}
|
|
if len(c.items) == 0 {
|
|
return ""
|
|
}
|
|
return c.items[max(0, min(len(c.items)-1, formerIndex))].ID
|
|
}
|