diff --git a/cmd/sqv-tea/main.go b/cmd/sqv-tea/main.go index ca52d26..07dcdca 100644 --- a/cmd/sqv-tea/main.go +++ b/cmd/sqv-tea/main.go @@ -4,6 +4,7 @@ import ( "log" "os" "strconv" + "strings" engine "git.pablu.de/pablu/sqv-engine" "github.com/charmbracelet/bubbles/table" @@ -15,12 +16,29 @@ var baseStyle = lipgloss.NewStyle(). BorderStyle(lipgloss.NormalBorder()). BorderForeground(lipgloss.Color("240")) +func tabBorderWithBottom(left, middle, right string) lipgloss.Border { + border := lipgloss.RoundedBorder() + border.BottomLeft = left + border.Bottom = middle + border.BottomRight = right + return border +} + +var ( + inactiveTabBorder = tabBorderWithBottom("┴", "─", "┴") + activeTabBorder = tabBorderWithBottom("┘", " ", "└") + docStyle = lipgloss.NewStyle().Padding(1, 2, 1, 2) + highlightColor = lipgloss.AdaptiveColor{Light: "#874BFD", Dark: "#7D56F4"} + inactiveTabStyle = lipgloss.NewStyle().Border(inactiveTabBorder, true).BorderForeground(highlightColor).Padding(0, 1) + activeTabStyle = inactiveTabStyle.Border(activeTabBorder, true) + windowStyle = lipgloss.NewStyle().BorderForeground(highlightColor).Padding(2, 0).Align(lipgloss.Center).Border(lipgloss.NormalBorder()).UnsetBorderTop() +) + type model struct { - table table.Model + tables []table.Model + tableNames []string - currTableName string - - manager *engine.Manager + currTable int } func (m model) Init() tea.Cmd { @@ -32,39 +50,65 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.KeyMsg: switch msg.String() { - case "esc": - if m.table.Focused() { - m.table.Blur() - } else { - m.table.Focus() - } case "ctrl+c", "q": return m, tea.Quit - case "enter": - return m, tea.Batch( - tea.Printf("Let's go to %s!", m.table.SelectedRow()[1]), - ) - case "n": - return m, updateTable(m.manager, m.currTableName) + case "right", "l", "n", "tab": + m.currTable = min(m.currTable+1, len(m.tables)-1) + return m, nil + case "left", "h", "p", "shift+tab": + m.currTable = max(m.currTable-1, 0) + return m, nil } - case newTableMsg: - m.table.SetRows(msg.rows) - m.table.SetColumns(msg.columns) } - m.table, cmd = m.table.Update(msg) + + m.tables[m.currTable], cmd = m.tables[m.currTable].Update(msg) return m, cmd } -type newTableMsg struct { - columns []table.Column - rows []table.Row +func (m model) View() string { + doc := strings.Builder{} + + var renderedTabs []string + + for i, t := range m.tableNames { + var style lipgloss.Style + isFirst, isLast, isActive := i == 0, i == len(m.tables)-1, i == m.currTable + if isActive { + style = activeTabStyle + } else { + style = inactiveTabStyle + } + border, _, _, _, _ := style.GetBorder() + if isFirst && isActive { + border.BottomLeft = "│" + } else if isFirst && !isActive { + border.BottomLeft = "├" + } else if isLast && isActive { + border.BottomRight = "│" + } else if isLast && !isActive { + border.BottomRight = "┤" + } + + style = style.Border(border) + renderedTabs = append(renderedTabs, style.Render(t)) + } + + row := lipgloss.JoinHorizontal(lipgloss.Top, renderedTabs...) + doc.WriteString(row) + doc.WriteString("\n") + doc.WriteString(windowStyle.Width((lipgloss.Width(row) - windowStyle.GetHorizontalFrameSize())).Render(m.tables[m.currTable].View())) + + return docStyle.Render(doc.String()) + // return baseStyle.Render(m.table.View()) + "\n" } -func updateTable(m *engine.Manager, tableName string) tea.Cmd { - return func() tea.Msg { - t, _ := m.GetTable(tableName) +func convertToViewTable(m *engine.Manager) ([]string, []table.Model) { + tables := m.GetTables() + res := make([]table.Model, len(tables)) + resNames := make([]string, len(tables)) + for j, t := range tables { columns := make([]table.Column, len(t.Columns)) for i, column := range t.Columns { columns[i] = table.Column{ @@ -73,10 +117,10 @@ func updateTable(m *engine.Manager, tableName string) tea.Cmd { } } - for range 5 { + for k := range 50 { row := engine.Row{Values: make([]string, len(t.Columns))} for i := range t.Columns { - row.Values[i] = "test " + strconv.Itoa(i) + row.Values[i] = "test " + strconv.Itoa(k) } t.Rows = append(t.Rows, row) } @@ -86,12 +130,30 @@ func updateTable(m *engine.Manager, tableName string) tea.Cmd { rows[i] = row.Values } - return newTableMsg{columns: columns, rows: rows} - } -} + resTable := table.New( + table.WithColumns(columns), + table.WithRows(rows), + table.WithFocused(true), + table.WithHeight(7), + ) -func (m model) View() string { - return baseStyle.Render(m.table.View()) + "\n" + s := table.DefaultStyles() + s.Header = s.Header. + BorderStyle(lipgloss.NormalBorder()). + BorderForeground(lipgloss.Color("240")). + BorderBottom(true). + Bold(false) + s.Selected = s.Selected. + Foreground(lipgloss.Color("229")). + Background(lipgloss.Color("57")). + Bold(false) + resTable.SetStyles(s) + + resNames[j] = t.Name + res[j] = resTable + } + + return resNames, res } func main() { @@ -102,49 +164,10 @@ func main() { m := engine.NewManagerFromFile(string(file)) m.Start() - lobby, _ := m.GetTable("lobbys") - lobby.Rows = []engine.Row{ - {Values: []string{"1", "me@pablu.de", "1"}}, - {Values: []string{"2", "pablu23@gmx.de", "2"}}, - {Values: []string{"5", "max@mustermann.org", "5"}}, - {Values: []string{"8", "eins@zwei.de", "8"}}, - {Values: []string{"19", "heinz.bongo@katzen.us", "19"}}, - {Values: []string{"22", "thessa@katze.de", "22"}}, - } - columns := make([]table.Column, len(lobby.Columns)) - for i, column := range lobby.Columns { - columns[i] = table.Column{ - Title: column.Name, - Width: 10, - } - } + tableNames, tables := convertToViewTable(m) - rows := make([]table.Row, len(lobby.Rows)) - for i, row := range lobby.Rows { - rows[i] = row.Values - } - - t := table.New( - table.WithColumns(columns), - table.WithRows(rows), - table.WithFocused(true), - table.WithHeight(7), - ) - - s := table.DefaultStyles() - s.Header = s.Header. - BorderStyle(lipgloss.NormalBorder()). - BorderForeground(lipgloss.Color("240")). - BorderBottom(true). - Bold(false) - s.Selected = s.Selected. - Foreground(lipgloss.Color("229")). - Background(lipgloss.Color("57")). - Bold(false) - t.SetStyles(s) - - p := tea.NewProgram(model{table: t, manager: m, currTableName: lobby.Name}) + p := tea.NewProgram(model{tables: tables, tableNames: tableNames}, tea.WithAltScreen()) if _, err := p.Run(); err != nil { log.Fatalf("Alas, theres been an error: %v", err) }