1package selection
2
3import (
4 "fmt"
5 "time"
6
7 "github.com/charmbracelet/bubbles/key"
8 "github.com/charmbracelet/bubbles/list"
9 tea "github.com/charmbracelet/bubbletea"
10 "github.com/charmbracelet/lipgloss"
11 appCfg "github.com/charmbracelet/soft-serve/config"
12 "github.com/charmbracelet/soft-serve/ui/common"
13 "github.com/charmbracelet/soft-serve/ui/components/selector"
14 "github.com/charmbracelet/soft-serve/ui/components/yankable"
15 "github.com/charmbracelet/soft-serve/ui/session"
16)
17
18type Selection struct {
19 s session.Session
20 common common.Common
21 selector *selector.Selector
22}
23
24func New(s session.Session, common common.Common) *Selection {
25 sel := &Selection{
26 s: s,
27 common: common,
28 selector: selector.New(common, []list.Item{}),
29 }
30 return sel
31}
32
33func (s *Selection) SetSize(width, height int) {
34 s.common.SetSize(width, height)
35 s.selector.SetSize(width, height)
36}
37
38func (s *Selection) ShortHelp() []key.Binding {
39 k := s.selector.KeyMap()
40 return []key.Binding{
41 s.common.Keymap.UpDown,
42 s.common.Keymap.Select,
43 k.Filter,
44 k.ClearFilter,
45 }
46}
47
48func (s *Selection) FullHelp() [][]key.Binding {
49 k := s.selector.KeyMap()
50 return [][]key.Binding{
51 {
52 k.CursorUp,
53 k.CursorDown,
54 k.NextPage,
55 k.PrevPage,
56 k.GoToStart,
57 k.GoToEnd,
58 },
59 {
60 k.Filter,
61 k.ClearFilter,
62 k.CancelWhileFiltering,
63 k.AcceptWhileFiltering,
64 k.ShowFullHelp,
65 k.CloseFullHelp,
66 },
67 // Ignore the following keys:
68 // k.Quit,
69 // k.ForceQuit,
70 }
71}
72
73func (s *Selection) Init() tea.Cmd {
74 items := make([]list.Item, 0)
75 cfg := s.s.Config()
76 yank := func(text string) *yankable.Yankable {
77 return yankable.New(
78 lipgloss.NewStyle().Foreground(lipgloss.Color("168")),
79 lipgloss.NewStyle().Foreground(lipgloss.Color("168")).SetString("Copied!"),
80 text,
81 )
82 }
83 // Put configured repos first
84 for _, r := range cfg.Repos {
85 items = append(items, selector.Item{
86 Title: r.Name,
87 Name: r.Repo,
88 Description: r.Note,
89 LastUpdate: time.Now(),
90 URL: yank(repoUrl(cfg, r.Name)),
91 })
92 }
93 for _, r := range cfg.Source.AllRepos() {
94 exists := false
95 for _, item := range items {
96 item := item.(selector.Item)
97 if item.Name == r.Name() {
98 exists = true
99 break
100 }
101 }
102 if !exists {
103 items = append(items, selector.Item{
104 Title: r.Name(),
105 Name: r.Name(),
106 Description: "",
107 LastUpdate: time.Now(),
108 URL: yank(repoUrl(cfg, r.Name())),
109 })
110 }
111 }
112 return s.selector.SetItems(items)
113}
114
115func (s *Selection) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
116 cmds := make([]tea.Cmd, 0)
117 switch msg := msg.(type) {
118 default:
119 m, cmd := s.selector.Update(msg)
120 s.selector = m.(*selector.Selector)
121 if cmd != nil {
122 cmds = append(cmds, cmd)
123 }
124 }
125 return s, tea.Batch(cmds...)
126}
127
128func (s *Selection) View() string {
129 return s.selector.View()
130}
131
132func repoUrl(cfg *appCfg.Config, name string) string {
133 port := ""
134 if cfg.Port != 22 {
135 port += fmt.Sprintf(":%d", cfg.Port)
136 }
137 return fmt.Sprintf("git clone ssh://%s/%s", cfg.Host+port, name)
138}