package views import ( "fmt" "strings" "unicode" ) // SyncAction is a sync menu choice. type SyncAction string const ( SyncActionPull SyncAction = "pull" SyncActionPush SyncAction = "push" ) // SyncOption is one row in the sync menu. type SyncOption struct { Action SyncAction Label string Shortcut rune } // SyncMenu renders a pull/push picker overlay. type SyncMenu struct { Cursor int Width int Title string Options []SyncOption Styles StatusMenuStyles } // NewSyncMenu creates a sync action menu for the given backend label. func NewSyncMenu(width int, styles StatusMenuStyles, backendLabel string) SyncMenu { if backendLabel == "" { backendLabel = "Sync" } opts := []SyncOption{ {Action: SyncActionPull, Label: "Pull from " + backendLabel, Shortcut: 'p'}, {Action: SyncActionPush, Label: "Push to " + backendLabel, Shortcut: 'u'}, } return SyncMenu{Cursor: 0, Width: width, Title: backendLabel, Options: opts, Styles: styles} } // MoveDown moves the selection down. func (m *SyncMenu) MoveDown() { if m.Cursor < len(m.Options)-1 { m.Cursor++ } } // MoveUp moves the selection up. func (m *SyncMenu) MoveUp() { if m.Cursor > 0 { m.Cursor-- } } // JumpToShortcut selects the option whose shortcut matches r. func (m *SyncMenu) JumpToShortcut(r rune) bool { r = unicode.ToLower(r) for i, opt := range m.Options { if opt.Shortcut == r { m.Cursor = i return true } } return false } // Selected returns the highlighted action. func (m SyncMenu) Selected() SyncAction { if m.Cursor < 0 || m.Cursor >= len(m.Options) { return SyncActionPull } return m.Options[m.Cursor].Action } // View renders the sync menu. func (m SyncMenu) View() string { var lines []string lines = append(lines, m.Styles.Title.Render(m.Title)) for i, opt := range m.Options { entry := fmt.Sprintf("%c %s", opt.Shortcut, opt.Label) if i == m.Cursor { lines = append(lines, m.Styles.Selected.Render("▸ "+entry)) } else { lines = append(lines, m.Styles.Normal.Render(" "+entry)) } } body := strings.Join(lines, "\n") w := m.Width if w < 20 { w = 20 } return m.Styles.Box.Width(min(44, w-2)).Render(body) }