Skip to content

Commit 03c2674

Browse files
committed
changes:
- created a options component for collections - created a config so that the list within the options is highly customizable - create a template for how the options component should operate
1 parent 3bb9be3 commit 03c2674

11 files changed

Lines changed: 281 additions & 21 deletions

File tree

internal/tui/app/model.go

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,91 @@
11
package app
22

33
import (
4+
"strings"
5+
46
tea "github.com/charmbracelet/bubbletea"
57
"github.com/charmbracelet/lipgloss"
68
"github.com/maniac-en/req/internal/tui/styles"
9+
"github.com/maniac-en/req/internal/tui/views"
10+
)
11+
12+
type ViewName string
13+
14+
const (
15+
Collections ViewName = "collections"
716
)
817

918
type AppModel struct {
10-
width int
11-
height int
19+
ctx *Context
20+
width int
21+
height int
22+
Views map[ViewName]views.ViewInterface
23+
focusedView ViewName
1224
}
1325

1426
func (a AppModel) Init() tea.Cmd {
1527
return nil
1628
}
1729

1830
func (a AppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
31+
var cmd tea.Cmd
32+
var cmds []tea.Cmd
1933
switch msg := msg.(type) {
2034
case tea.WindowSizeMsg:
2135
a.height = msg.Height
2236
a.width = msg.Width
37+
a.Views[a.focusedView], cmd = a.Views[a.focusedView].Update(tea.WindowSizeMsg{Height: a.AvailableHeight(), Width: msg.Width})
38+
cmds = append(cmds, cmd)
2339
case tea.KeyMsg:
2440
switch msg.String() {
2541
case "ctrl+c":
2642
return a, tea.Quit
2743
}
2844
}
29-
return a, nil
45+
return a, tea.Batch(cmds...)
3046
}
3147

3248
func (a AppModel) View() string {
3349
footer := a.Footer()
3450
header := a.Header()
35-
availableHeight := a.height - lipgloss.Height(header) - lipgloss.Height(footer)
36-
view := lipgloss.NewStyle().Height(availableHeight).Width(a.width).Align(lipgloss.Center, lipgloss.Center).Render("Hello world!")
51+
view := a.Views[a.focusedView].View()
3752
return lipgloss.JoinVertical(lipgloss.Top, header, view, footer)
3853
}
3954

55+
func (a *AppModel) AvailableHeight() int {
56+
footer := a.Footer()
57+
header := a.Header()
58+
return a.height - lipgloss.Height(header) - lipgloss.Height(footer)
59+
}
60+
4061
func (a AppModel) Header() string {
41-
return "Hello World"
62+
var b strings.Builder
63+
64+
for key, value := range a.Views {
65+
if key == a.focusedView {
66+
b.WriteString(styles.TabHeadingActive.Render(value.Name()))
67+
} else {
68+
b.WriteString(styles.TabHeadingInactive.Render(value.Name()))
69+
}
70+
}
71+
b.WriteString(styles.TabHeadingInactive.Render(""))
72+
return b.String()
4273
}
4374

4475
func (a AppModel) Footer() string {
4576
name := styles.GradientText("REQ", styles.FooterNameFGFrom, styles.FooterNameFGTo, styles.FooterNameStyle, styles.FooterNameBGStyle)
46-
version := styles.FooterVersionStyle.Width(a.width - lipgloss.Width(name)).Render("v0.1.0-alpha2")
47-
return lipgloss.JoinHorizontal(lipgloss.Left, name, version)
77+
footerText := styles.FooterSegmentStyle.Render(a.Views[a.focusedView].GetFooterSegment())
78+
version := styles.FooterVersionStyle.Width(a.width - lipgloss.Width(name) - lipgloss.Width(footerText)).Render("v0.1.0-alpha2")
79+
return lipgloss.JoinHorizontal(lipgloss.Left, name, footerText, version)
4880
}
4981

50-
func NewAppModel() AppModel {
51-
return AppModel{}
82+
func NewAppModel(ctx *Context) AppModel {
83+
model := AppModel{
84+
focusedView: Collections,
85+
ctx: ctx,
86+
}
87+
model.Views = map[ViewName]views.ViewInterface{
88+
Collections: views.NewCollectionsView(model.ctx.Collections),
89+
}
90+
return model
5291
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package optionsProvider
2+
3+
import (
4+
"github.com/charmbracelet/bubbles/list"
5+
tea "github.com/charmbracelet/bubbletea"
6+
"github.com/charmbracelet/lipgloss"
7+
)
8+
9+
type OptionsProvider struct {
10+
list list.Model
11+
onSelectAction tea.Msg
12+
width int
13+
height int
14+
}
15+
16+
type Option struct {
17+
title string
18+
value string
19+
description string
20+
}
21+
22+
func (o Option) Title() string { return o.title }
23+
func (o Option) Description() string { return o.description }
24+
func (o Option) Value() string { return o.value }
25+
func (o Option) FilterValue() string { return o.title }
26+
27+
func (o OptionsProvider) Init() tea.Cmd {
28+
return nil
29+
}
30+
31+
func (o OptionsProvider) Update(msg tea.Msg) (OptionsProvider, tea.Cmd) {
32+
switch msg := msg.(type) {
33+
case tea.WindowSizeMsg:
34+
o.height = msg.Height
35+
o.width = msg.Width
36+
}
37+
return o, nil
38+
}
39+
40+
func (o OptionsProvider) View() string {
41+
return lipgloss.NewStyle().Height(o.height).Width(o.width).Align(lipgloss.Center, lipgloss.Center).Render("Hello world from select")
42+
}
43+
44+
func (o OptionsProvider) OnFocus() {
45+
46+
}
47+
48+
func (o OptionsProvider) OnBlur() {
49+
50+
}
51+
52+
func initList[T any](config *ListConfig[T]) list.Model {
53+
54+
// items := config.ItemMapper(config.Items)
55+
56+
list := list.New([]list.Item{}, list.NewDefaultDelegate(), 0, 0)
57+
58+
// list configuration
59+
list.SetFilteringEnabled(config.FilteringEnabled)
60+
list.SetShowPagination(config.ShowPagination)
61+
list.SetShowHelp(config.ShowHelp)
62+
list.SetShowTitle(config.ShowTitle)
63+
64+
// list.KeyMap = config.KeyMap
65+
66+
return list
67+
}
68+
69+
func NewOptionsProvider[T any](config *ListConfig[T]) OptionsProvider {
70+
return OptionsProvider{
71+
list: initList(config),
72+
// onSelectAction: config.OnSelectAction,
73+
}
74+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package optionsProvider
2+
3+
import (
4+
"github.com/charmbracelet/bubbles/list"
5+
tea "github.com/charmbracelet/bubbletea"
6+
)
7+
8+
type ListConfig[T any] struct {
9+
Items []T
10+
OnSelectAction tea.Msg
11+
12+
ShowPagination bool
13+
ShowHelp bool
14+
ShowTitle bool
15+
Width, Height int
16+
17+
FilteringEnabled bool
18+
19+
Delegate list.ItemDelegate
20+
KeyMap list.KeyMap
21+
22+
ItemMapper func([]T) []list.Item
23+
24+
// CrudOps Crud
25+
// Style lipgloss.Style
26+
}

internal/tui/keybinds/keys.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package keybinds
2+
3+
import (
4+
"github.com/charmbracelet/bubbles/key"
5+
)
6+
7+
type Keymaps struct {
8+
InsertItem key.Binding
9+
DeleteItem key.Binding
10+
EditItem key.Binding
11+
Choose key.Binding
12+
Remove key.Binding
13+
Back key.Binding
14+
}
15+
16+
var Keys = Keymaps{
17+
Back: key.NewBinding(
18+
key.WithKeys("esc"),
19+
key.WithHelp("esc", "back"),
20+
),
21+
InsertItem: key.NewBinding(
22+
key.WithKeys("a"),
23+
key.WithHelp("a", "add item"),
24+
),
25+
EditItem: key.NewBinding(
26+
key.WithKeys("e"),
27+
key.WithHelp("e", "edit item"),
28+
),
29+
Choose: key.NewBinding(
30+
key.WithKeys("enter"),
31+
key.WithHelp("enter", "Choose"),
32+
),
33+
Remove: key.NewBinding(
34+
key.WithKeys("x", "backspace"),
35+
key.WithHelp("x", "delete"),
36+
),
37+
}

internal/tui/keys/keys.go

Whitespace-only changes.

internal/tui/styles/app-styles.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package styles
22

3-
import "github.com/charmbracelet/lipgloss"
3+
import (
4+
"github.com/charmbracelet/lipgloss"
5+
)
46

57
var (
68
FooterNameStyle = lipgloss.NewStyle().Bold(true)
79
FooterNameBGStyle = lipgloss.NewStyle().Background(FooterNameBG).Padding(0, 3, 0)
10+
FooterSegmentStyle = lipgloss.NewStyle().Background(lipgloss.Color("#262626")).PaddingLeft(2).Foreground(lipgloss.Color("#656565"))
811
FooterVersionStyle = lipgloss.NewStyle().Background(lipgloss.Color("#262626")).AlignHorizontal(lipgloss.Right).PaddingRight(2).Foreground(lipgloss.Color("#656565"))
12+
TabHeadingInactive = lipgloss.NewStyle().Width(25).AlignHorizontal(lipgloss.Center).Border(lipgloss.NormalBorder(), false, false, false, true)
13+
TabHeadingActive = lipgloss.NewStyle().Background(Accent).Foreground(HeadingForeground).Width(25).AlignHorizontal(lipgloss.Center).Border(lipgloss.NormalBorder(), false, false, false, true)
914
)

internal/tui/styles/colors.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package styles
33
import "github.com/charmbracelet/lipgloss"
44

55
var (
6-
FooterNameBG = lipgloss.Color("#1a1a1a")
7-
FooterNameFGFrom = lipgloss.Color("#6D51FE")
8-
FooterNameFGTo = lipgloss.Color("#8B0F7D")
6+
FooterNameBG = lipgloss.Color("#1a1a1a")
7+
FooterNameFGFrom = lipgloss.Color("#41A0AE")
8+
FooterNameFGTo = lipgloss.Color("#77F07F")
9+
Accent = lipgloss.Color("#77F07F")
10+
HeadingForeground = lipgloss.Color("#000000")
911
)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package views
2+
3+
import (
4+
optionsProvider "github.com/maniac-en/req/internal/tui/components/OptionsProvider"
5+
)
6+
7+
func defaultListConfig[T any]() *optionsProvider.ListConfig[T] {
8+
config := optionsProvider.ListConfig[T]{
9+
ShowPagination: false,
10+
ShowHelp: false,
11+
ShowTitle: false,
12+
FilteringEnabled: false,
13+
}
14+
return &config
15+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package views
2+
3+
import (
4+
tea "github.com/charmbracelet/bubbletea"
5+
"github.com/maniac-en/req/internal/backend/collections"
6+
optionsProvider "github.com/maniac-en/req/internal/tui/components/OptionsProvider"
7+
)
8+
9+
type CollectionsView struct {
10+
width int
11+
height int
12+
list optionsProvider.OptionsProvider
13+
}
14+
15+
func (c CollectionsView) Init() tea.Cmd {
16+
return nil
17+
}
18+
19+
func (c CollectionsView) Name() string {
20+
return "Collections"
21+
}
22+
23+
func (c CollectionsView) Help() string {
24+
return ""
25+
}
26+
27+
func (c CollectionsView) GetFooterSegment() string {
28+
return "Collections"
29+
}
30+
31+
func (c CollectionsView) Update(msg tea.Msg) (ViewInterface, tea.Cmd) {
32+
var cmd tea.Cmd
33+
var cmds []tea.Cmd
34+
switch msg := msg.(type) {
35+
case tea.WindowSizeMsg:
36+
c.height = msg.Height
37+
c.width = msg.Width
38+
c.list, cmd = c.list.Update(msg)
39+
cmds = append(cmds, cmd)
40+
}
41+
return c, tea.Batch(cmds...)
42+
}
43+
44+
func (c CollectionsView) View() string {
45+
return c.list.View()
46+
}
47+
48+
func (c CollectionsView) OnFocus() {
49+
50+
}
51+
52+
func (c CollectionsView) OnBlur() {
53+
54+
}
55+
56+
func NewCollectionsView(collManager *collections.CollectionsManager) *CollectionsView {
57+
config := defaultListConfig[string]()
58+
return &CollectionsView{
59+
list: optionsProvider.NewOptionsProvider(config),
60+
}
61+
}

internal/tui/views/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type ViewInterface interface {
88
Init() tea.Cmd
99
Name() string
1010
Help() string
11+
GetFooterSegment() string
1112
Update(tea.Msg) (ViewInterface, tea.Cmd)
1213
View() string
1314
OnFocus()

0 commit comments

Comments
 (0)