sidebar.go

  1package chat
  2
  3import (
  4	"fmt"
  5
  6	tea "github.com/charmbracelet/bubbletea"
  7	"github.com/charmbracelet/lipgloss"
  8	"github.com/kujtimiihoxha/termai/internal/config"
  9	"github.com/kujtimiihoxha/termai/internal/tui/styles"
 10	"github.com/kujtimiihoxha/termai/internal/version"
 11)
 12
 13type sidebarCmp struct {
 14	width, height int
 15}
 16
 17func (m *sidebarCmp) Init() tea.Cmd {
 18	return nil
 19}
 20
 21func (m *sidebarCmp) Update(tea.Msg) (tea.Model, tea.Cmd) {
 22	return m, nil
 23}
 24
 25func (m *sidebarCmp) View() string {
 26	return styles.BaseStyle.Width(m.width).Render(
 27		lipgloss.JoinVertical(
 28			lipgloss.Top,
 29			m.header(),
 30			" ",
 31			m.session(),
 32			" ",
 33			m.modifiedFiles(),
 34			" ",
 35			m.lspsConfigured(),
 36		),
 37	)
 38}
 39
 40func (m *sidebarCmp) session() string {
 41	sessionKey := styles.BaseStyle.Foreground(styles.PrimaryColor).Render("Session")
 42	sessionValue := styles.BaseStyle.
 43		Foreground(styles.Forground).
 44		Width(m.width - lipgloss.Width(sessionKey)).
 45		Render(": New Session")
 46	return lipgloss.JoinHorizontal(
 47		lipgloss.Left,
 48		sessionKey,
 49		sessionValue,
 50	)
 51}
 52
 53func (m *sidebarCmp) modifiedFile(filePath string, additions, removals int) string {
 54	stats := ""
 55	if additions > 0 && removals > 0 {
 56		stats = styles.BaseStyle.Foreground(styles.ForgroundDim).Render(fmt.Sprintf("%d additions and  %d removals", additions, removals))
 57	} else if additions > 0 {
 58		stats = styles.BaseStyle.Foreground(styles.ForgroundDim).Render(fmt.Sprintf("%d additions", additions))
 59	} else if removals > 0 {
 60		stats = styles.BaseStyle.Foreground(styles.ForgroundDim).Render(fmt.Sprintf("%d removals", removals))
 61	}
 62	filePathStr := styles.BaseStyle.Foreground(styles.Forground).Render(filePath)
 63
 64	return styles.BaseStyle.
 65		Width(m.width).
 66		Render(
 67			lipgloss.JoinHorizontal(
 68				lipgloss.Left,
 69				filePathStr,
 70				" ",
 71				stats,
 72			),
 73		)
 74}
 75
 76func (m *sidebarCmp) lspsConfigured() string {
 77	lsps := styles.BaseStyle.Width(m.width).Foreground(styles.PrimaryColor).Render("LSP Configuration:")
 78	lspsConfigured := []struct {
 79		name string
 80		path string
 81	}{
 82		{"golsp", "path/to/lsp1"},
 83		{"vtsls", "path/to/lsp2"},
 84	}
 85
 86	var lspViews []string
 87	for _, lsp := range lspsConfigured {
 88		lspName := styles.BaseStyle.Foreground(styles.Forground).Render(
 89			fmt.Sprintf("• %s", lsp.name),
 90		)
 91		lspPath := styles.BaseStyle.Foreground(styles.ForgroundDim).Render(
 92			fmt.Sprintf("(%s)", lsp.path),
 93		)
 94		lspViews = append(lspViews,
 95			styles.BaseStyle.
 96				Width(m.width).
 97				Render(
 98					lipgloss.JoinHorizontal(
 99						lipgloss.Left,
100						lspName,
101						" ",
102						lspPath,
103					),
104				),
105		)
106
107	}
108	return styles.BaseStyle.
109		Width(m.width).
110		Render(
111			lipgloss.JoinVertical(
112				lipgloss.Left,
113				lsps,
114				lipgloss.JoinVertical(
115					lipgloss.Left,
116					lspViews...,
117				),
118			),
119		)
120}
121
122func (m *sidebarCmp) modifiedFiles() string {
123	modifiedFiles := styles.BaseStyle.Width(m.width).Foreground(styles.PrimaryColor).Render("Modified Files:")
124	files := []struct {
125		path      string
126		additions int
127		removals  int
128	}{
129		{"file1.txt", 10, 5},
130		{"file2.txt", 20, 0},
131		{"file3.txt", 0, 15},
132	}
133	var fileViews []string
134	for _, file := range files {
135		fileViews = append(fileViews, m.modifiedFile(file.path, file.additions, file.removals))
136	}
137
138	return styles.BaseStyle.
139		Width(m.width).
140		Render(
141			lipgloss.JoinVertical(
142				lipgloss.Top,
143				modifiedFiles,
144				lipgloss.JoinVertical(
145					lipgloss.Left,
146					fileViews...,
147				),
148			),
149		)
150}
151
152func (m *sidebarCmp) logo() string {
153	logo := fmt.Sprintf("%s %s", styles.OpenCodeIcon, "OpenCode")
154
155	version := styles.BaseStyle.Foreground(styles.ForgroundDim).Render(version.Version)
156
157	return styles.BaseStyle.
158		Bold(true).
159		Width(m.width).
160		Render(
161			lipgloss.JoinHorizontal(
162				lipgloss.Left,
163				logo,
164				" ",
165				version,
166			),
167		)
168}
169
170func (m *sidebarCmp) header() string {
171	header := lipgloss.JoinVertical(
172		lipgloss.Top,
173		m.logo(),
174		m.cwd(),
175	)
176	return header
177}
178
179func (m *sidebarCmp) cwd() string {
180	cwd := fmt.Sprintf("cwd: %s", config.WorkingDirectory())
181	return styles.BaseStyle.
182		Foreground(styles.ForgroundDim).
183		Width(m.width).
184		Render(cwd)
185}
186
187func (m *sidebarCmp) SetSize(width, height int) {
188	m.width = width
189	m.height = height
190}
191
192func (m *sidebarCmp) GetSize() (int, int) {
193	return m.width, m.height
194}
195
196func NewSidebarCmp() tea.Model {
197	return &sidebarCmp{}
198}