mirror of
https://github.com/mrusme/neonmodem.git
synced 2024-11-03 04:27:16 -05:00
Implemented first draft structure
This commit is contained in:
parent
9036561a8c
commit
770eb43e52
25
gobbs.go
Normal file
25
gobbs.go
Normal file
@ -0,0 +1,25 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/mrusme/gobbs/system"
|
||||
"github.com/mrusme/gobbs/ui"
|
||||
"github.com/mrusme/gobbs/ui/ctx"
|
||||
)
|
||||
|
||||
func main() {
|
||||
c := ctx.New()
|
||||
|
||||
discourse, err := system.New("discourse", nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c.AddSystem(&discourse)
|
||||
|
||||
tui := tea.NewProgram(ui.NewModel(&c), tea.WithAltScreen())
|
||||
err = tui.Start()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
19
models/post/post.go
Normal file
19
models/post/post.go
Normal file
@ -0,0 +1,19 @@
|
||||
package post
|
||||
|
||||
type Post struct {
|
||||
ID string
|
||||
|
||||
Subject string
|
||||
}
|
||||
|
||||
func (post Post) FilterValue() string {
|
||||
return post.Subject
|
||||
}
|
||||
|
||||
func (post Post) Title() string {
|
||||
return post.Subject
|
||||
}
|
||||
|
||||
func (post Post) Description() string {
|
||||
return post.ID
|
||||
}
|
6
system/adapter/adapter.go
Normal file
6
system/adapter/adapter.go
Normal file
@ -0,0 +1,6 @@
|
||||
package adapter
|
||||
|
||||
type Capability struct {
|
||||
ID string
|
||||
Name string
|
||||
}
|
36
system/discourse/discourse.go
Normal file
36
system/discourse/discourse.go
Normal file
@ -0,0 +1,36 @@
|
||||
package discourse
|
||||
|
||||
import (
|
||||
"github.com/mrusme/gobbs/models/post"
|
||||
"github.com/mrusme/gobbs/system/adapter"
|
||||
)
|
||||
|
||||
type System struct {
|
||||
}
|
||||
|
||||
func (sys *System) Load() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sys *System) ListPosts() ([]post.Post, error) {
|
||||
return []post.Post{}, nil
|
||||
}
|
||||
|
||||
func (sys *System) GetCapabilities() []adapter.Capability {
|
||||
var caps []adapter.Capability
|
||||
|
||||
caps = append(caps, adapter.Capability{
|
||||
ID: "posts",
|
||||
Name: "Posts",
|
||||
})
|
||||
caps = append(caps, adapter.Capability{
|
||||
ID: "groups",
|
||||
Name: "Groups",
|
||||
})
|
||||
caps = append(caps, adapter.Capability{
|
||||
ID: "search",
|
||||
Name: "Search",
|
||||
})
|
||||
|
||||
return caps
|
||||
}
|
36
system/lemmy/lemmy.go
Normal file
36
system/lemmy/lemmy.go
Normal file
@ -0,0 +1,36 @@
|
||||
package lemmy
|
||||
|
||||
import (
|
||||
"github.com/mrusme/gobbs/models/post"
|
||||
"github.com/mrusme/gobbs/system/adapter"
|
||||
)
|
||||
|
||||
type System struct {
|
||||
}
|
||||
|
||||
func (sys *System) Load() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sys *System) ListPosts() ([]post.Post, error) {
|
||||
return []post.Post{}, nil
|
||||
}
|
||||
|
||||
func (sys *System) GetCapabilities() []adapter.Capability {
|
||||
var caps []adapter.Capability
|
||||
|
||||
caps = append(caps, adapter.Capability{
|
||||
ID: "posts",
|
||||
Name: "Posts",
|
||||
})
|
||||
caps = append(caps, adapter.Capability{
|
||||
ID: "groups",
|
||||
Name: "Groups",
|
||||
})
|
||||
caps = append(caps, adapter.Capability{
|
||||
ID: "search",
|
||||
Name: "Search",
|
||||
})
|
||||
|
||||
return caps
|
||||
}
|
38
system/system.go
Normal file
38
system/system.go
Normal file
@ -0,0 +1,38 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/mrusme/gobbs/models/post"
|
||||
"github.com/mrusme/gobbs/system/adapter"
|
||||
"github.com/mrusme/gobbs/system/discourse"
|
||||
"github.com/mrusme/gobbs/system/lemmy"
|
||||
)
|
||||
|
||||
type System interface {
|
||||
GetCapabilities() []adapter.Capability
|
||||
|
||||
Load() error
|
||||
|
||||
ListPosts() ([]post.Post, error)
|
||||
}
|
||||
|
||||
func New(sysType string, sysConfig *map[string]interface{}) (System, error) {
|
||||
var sys System
|
||||
|
||||
switch sysType {
|
||||
case "discourse":
|
||||
sys = new(discourse.System)
|
||||
case "lemmy":
|
||||
sys = new(lemmy.System)
|
||||
default:
|
||||
return nil, errors.New("No such system")
|
||||
}
|
||||
|
||||
err := sys.Load()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sys, nil
|
||||
}
|
23
ui/ctx/ctx.go
Normal file
23
ui/ctx/ctx.go
Normal file
@ -0,0 +1,23 @@
|
||||
package ctx
|
||||
|
||||
import "github.com/mrusme/gobbs/system"
|
||||
|
||||
type Ctx struct {
|
||||
Screen [2]int
|
||||
Content [2]int
|
||||
Systems []*system.System
|
||||
Loading bool
|
||||
}
|
||||
|
||||
func New() Ctx {
|
||||
return Ctx{
|
||||
Screen: [2]int{0, 0},
|
||||
Content: [2]int{0, 0},
|
||||
Loading: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Ctx) AddSystem(sys *system.System) error {
|
||||
c.Systems = append(c.Systems, sys)
|
||||
return nil
|
||||
}
|
151
ui/navigation/navigation.go
Normal file
151
ui/navigation/navigation.go
Normal file
@ -0,0 +1,151 @@
|
||||
package navigation
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/mrusme/gobbs/ui/ctx"
|
||||
|
||||
"github.com/charmbracelet/bubbles/spinner"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
var (
|
||||
highlight = lipgloss.AdaptiveColor{Light: "#874BFD", Dark: "#7D56F4"}
|
||||
|
||||
activeTabBorder = lipgloss.Border{
|
||||
Top: "─",
|
||||
Bottom: " ",
|
||||
Left: "│",
|
||||
Right: "│",
|
||||
TopLeft: "╭",
|
||||
TopRight: "╮",
|
||||
BottomLeft: "┘",
|
||||
BottomRight: "└",
|
||||
}
|
||||
|
||||
tabBorder = lipgloss.Border{
|
||||
Top: "─",
|
||||
Bottom: "─",
|
||||
Left: "│",
|
||||
Right: "│",
|
||||
TopLeft: "╭",
|
||||
TopRight: "╮",
|
||||
BottomLeft: "┴",
|
||||
BottomRight: "┴",
|
||||
}
|
||||
|
||||
tab = lipgloss.NewStyle().
|
||||
Border(tabBorder, true).
|
||||
BorderForeground(highlight).
|
||||
Padding(0, 1)
|
||||
|
||||
activeTab = tab.Copy().Border(activeTabBorder, true)
|
||||
|
||||
tabGap = tab.Copy().
|
||||
BorderTop(false).
|
||||
BorderLeft(false).
|
||||
BorderRight(false)
|
||||
)
|
||||
|
||||
var Navigation = []string{}
|
||||
|
||||
type Model struct {
|
||||
CurrentId int
|
||||
ctx *ctx.Ctx
|
||||
spinner spinner.Model
|
||||
}
|
||||
|
||||
func NewModel(c *ctx.Ctx) Model {
|
||||
m := Model{
|
||||
CurrentId: 0,
|
||||
ctx: c,
|
||||
}
|
||||
|
||||
m.spinner = spinner.New()
|
||||
m.spinner.Spinner = spinner.Dot
|
||||
m.spinner.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("205"))
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m Model) Init() tea.Cmd {
|
||||
return m.spinner.Tick
|
||||
}
|
||||
|
||||
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
|
||||
var cmds []tea.Cmd
|
||||
|
||||
if m.ctx.Loading == true {
|
||||
cmds = append(cmds, m.spinner.Tick)
|
||||
}
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case spinner.TickMsg:
|
||||
var cmd tea.Cmd
|
||||
m.spinner, cmd = m.spinner.Update(msg)
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
|
||||
return m, tea.Batch(cmds...)
|
||||
}
|
||||
|
||||
func (m Model) View() string {
|
||||
var items []string
|
||||
|
||||
for i, nav := range Navigation {
|
||||
if m.CurrentId == i {
|
||||
items = append(items, activeTab.Render(nav))
|
||||
} else {
|
||||
items = append(items, tab.Render(nav))
|
||||
}
|
||||
}
|
||||
|
||||
row := lipgloss.JoinHorizontal(
|
||||
lipgloss.Top,
|
||||
items...,
|
||||
)
|
||||
|
||||
if m.ctx.Loading == false {
|
||||
gap := tabGap.Render(strings.Repeat(" ", max(0, m.ctx.Screen[0]-lipgloss.Width(row)-2)))
|
||||
row = lipgloss.JoinHorizontal(lipgloss.Bottom, row, gap)
|
||||
} else {
|
||||
gap := tabGap.Render(strings.Repeat(" ", max(0, m.ctx.Screen[0]-lipgloss.Width(row)-4)))
|
||||
row = lipgloss.JoinHorizontal(lipgloss.Bottom, row, gap, " ", m.spinner.View())
|
||||
}
|
||||
|
||||
return lipgloss.JoinHorizontal(lipgloss.Top, row, "\n\n")
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (m *Model) NthTab(nth int) {
|
||||
if nth > len(Navigation) {
|
||||
nth = len(Navigation)
|
||||
} else if nth < 1 {
|
||||
nth = 1
|
||||
}
|
||||
|
||||
m.CurrentId = nth - 1
|
||||
}
|
||||
|
||||
func (m *Model) PrevTab() {
|
||||
m.CurrentId--
|
||||
|
||||
if m.CurrentId < 0 {
|
||||
m.CurrentId = len(Navigation) - 1
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Model) NextTab() {
|
||||
m.CurrentId++
|
||||
|
||||
if m.CurrentId >= len(Navigation) {
|
||||
m.CurrentId = 0
|
||||
}
|
||||
}
|
237
ui/ui.go
Normal file
237
ui/ui.go
Normal file
@ -0,0 +1,237 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
// "fmt"
|
||||
|
||||
"strings"
|
||||
|
||||
"github.com/mrusme/gobbs/ui/ctx"
|
||||
"github.com/mrusme/gobbs/ui/navigation"
|
||||
|
||||
"github.com/mrusme/gobbs/ui/views"
|
||||
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
)
|
||||
|
||||
type KeyMap struct {
|
||||
FirstTab key.Binding
|
||||
SecondTab key.Binding
|
||||
ThirdTab key.Binding
|
||||
FourthTab key.Binding
|
||||
FifthTab key.Binding
|
||||
SixthTab key.Binding
|
||||
SeventhTab key.Binding
|
||||
EightTab key.Binding
|
||||
NinthTab key.Binding
|
||||
TenthTab key.Binding
|
||||
EleventhTab key.Binding
|
||||
TwelfthTab key.Binding
|
||||
ThirteenthTab key.Binding
|
||||
PrevTab key.Binding
|
||||
NextTab key.Binding
|
||||
Up key.Binding
|
||||
Down key.Binding
|
||||
Quit key.Binding
|
||||
}
|
||||
|
||||
var DefaultKeyMap = KeyMap{
|
||||
FirstTab: key.NewBinding(
|
||||
key.WithKeys("f1"),
|
||||
key.WithHelp("f1", "first tab"),
|
||||
),
|
||||
SecondTab: key.NewBinding(
|
||||
key.WithKeys("f2"),
|
||||
key.WithHelp("f2", "second tab"),
|
||||
),
|
||||
ThirdTab: key.NewBinding(
|
||||
key.WithKeys("f3"),
|
||||
key.WithHelp("f3", "third tab"),
|
||||
),
|
||||
FourthTab: key.NewBinding(
|
||||
key.WithKeys("f4"),
|
||||
key.WithHelp("f4", "fourth tab"),
|
||||
),
|
||||
FifthTab: key.NewBinding(
|
||||
key.WithKeys("f5"),
|
||||
key.WithHelp("f5", "fifth tab"),
|
||||
),
|
||||
SixthTab: key.NewBinding(
|
||||
key.WithKeys("f6"),
|
||||
key.WithHelp("f6", "sixth tab"),
|
||||
),
|
||||
SeventhTab: key.NewBinding(
|
||||
key.WithKeys("f7"),
|
||||
key.WithHelp("f7", "seventh tab"),
|
||||
),
|
||||
EightTab: key.NewBinding(
|
||||
key.WithKeys("f8"),
|
||||
key.WithHelp("f8", "eight tab"),
|
||||
),
|
||||
NinthTab: key.NewBinding(
|
||||
key.WithKeys("f9"),
|
||||
key.WithHelp("f9", "ninth tab"),
|
||||
),
|
||||
TenthTab: key.NewBinding(
|
||||
key.WithKeys("f10"),
|
||||
key.WithHelp("f10", "tenth tab"),
|
||||
),
|
||||
EleventhTab: key.NewBinding(
|
||||
key.WithKeys("f11"),
|
||||
key.WithHelp("f11", "eleventh tab"),
|
||||
),
|
||||
TwelfthTab: key.NewBinding(
|
||||
key.WithKeys("f12"),
|
||||
key.WithHelp("f12", "twelfth tab"),
|
||||
),
|
||||
ThirteenthTab: key.NewBinding(
|
||||
key.WithKeys("f13"),
|
||||
key.WithHelp("f13", "thirteenth tab"),
|
||||
),
|
||||
PrevTab: key.NewBinding(
|
||||
key.WithKeys("ctrl+p"),
|
||||
key.WithHelp("ctrl+p", "previous tab"),
|
||||
),
|
||||
NextTab: key.NewBinding(
|
||||
key.WithKeys("ctrl+n"),
|
||||
key.WithHelp("ctrl+n", "next tab"),
|
||||
),
|
||||
Up: key.NewBinding(
|
||||
key.WithKeys("k", "up"),
|
||||
key.WithHelp("↑/k", "move up"),
|
||||
),
|
||||
Down: key.NewBinding(
|
||||
key.WithKeys("j", "down"),
|
||||
key.WithHelp("↓/j", "move down"),
|
||||
),
|
||||
Quit: key.NewBinding(
|
||||
key.WithKeys("q", "ctrl+q"),
|
||||
key.WithHelp("q/Q", "quit"),
|
||||
),
|
||||
}
|
||||
|
||||
type Model struct {
|
||||
keymap KeyMap
|
||||
nav navigation.Model
|
||||
views []views.View
|
||||
ctx *ctx.Ctx
|
||||
}
|
||||
|
||||
func NewModel(c *ctx.Ctx) Model {
|
||||
m := Model{
|
||||
keymap: DefaultKeyMap,
|
||||
ctx: c,
|
||||
}
|
||||
|
||||
m.nav = navigation.NewModel(m.ctx)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m Model) Init() tea.Cmd {
|
||||
return tea.Batch(tea.EnterAltScreen)
|
||||
}
|
||||
|
||||
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
cmds := make([]tea.Cmd, 0)
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
switch {
|
||||
case key.Matches(msg, m.keymap.Quit):
|
||||
return m, tea.Quit
|
||||
|
||||
case key.Matches(msg, m.keymap.FirstTab):
|
||||
m.nav.NthTab(1)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.SecondTab):
|
||||
m.nav.NthTab(2)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.ThirdTab):
|
||||
m.nav.NthTab(3)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.FourthTab):
|
||||
m.nav.NthTab(4)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.FifthTab):
|
||||
m.nav.NthTab(5)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.SixthTab):
|
||||
m.nav.NthTab(6)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.SeventhTab):
|
||||
m.nav.NthTab(7)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.EightTab):
|
||||
m.nav.NthTab(8)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.NinthTab):
|
||||
m.nav.NthTab(9)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.TenthTab):
|
||||
m.nav.NthTab(10)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.EleventhTab):
|
||||
m.nav.NthTab(11)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.TwelfthTab):
|
||||
m.nav.NthTab(12)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.ThirteenthTab):
|
||||
m.nav.NthTab(13)
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.PrevTab):
|
||||
m.nav.PrevTab()
|
||||
return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.NextTab):
|
||||
m.nav.NextTab()
|
||||
return m, nil
|
||||
}
|
||||
|
||||
case tea.WindowSizeMsg:
|
||||
m.setSizes(msg.Width, msg.Height)
|
||||
for i := range m.views {
|
||||
v, cmd := m.views[i].Update(msg)
|
||||
m.views[i] = v
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
}
|
||||
|
||||
v, cmd := m.views[m.nav.CurrentId].Update(msg)
|
||||
m.views[m.nav.CurrentId] = v
|
||||
cmds = append(cmds, cmd)
|
||||
|
||||
nav, cmd := m.nav.Update(msg)
|
||||
m.nav = nav
|
||||
cmds = append(cmds, cmd)
|
||||
|
||||
return m, tea.Batch(cmds...)
|
||||
}
|
||||
|
||||
func (m Model) View() string {
|
||||
s := strings.Builder{}
|
||||
s.WriteString(m.nav.View() + "\n\n")
|
||||
s.WriteString(m.views[m.nav.CurrentId].View())
|
||||
return s.String()
|
||||
}
|
||||
|
||||
func (m Model) setSizes(winWidth int, winHeight int) {
|
||||
(*m.ctx).Screen[0] = winWidth
|
||||
(*m.ctx).Screen[1] = winHeight
|
||||
m.ctx.Content[0] = m.ctx.Screen[0]
|
||||
m.ctx.Content[1] = m.ctx.Screen[1] - 5
|
||||
}
|
195
ui/views/posts/posts.go
Normal file
195
ui/views/posts/posts.go
Normal file
@ -0,0 +1,195 @@
|
||||
package posts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
"github.com/charmbracelet/bubbles/list"
|
||||
"github.com/charmbracelet/bubbles/viewport"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/mrusme/gobbs/models/post"
|
||||
"github.com/mrusme/gobbs/ui/ctx"
|
||||
)
|
||||
|
||||
var (
|
||||
listStyle = lipgloss.NewStyle().
|
||||
Margin(0, 0, 0, 0).
|
||||
Padding(1, 1).
|
||||
Border(lipgloss.RoundedBorder()).
|
||||
BorderForeground(lipgloss.Color("#874BFD")).
|
||||
BorderTop(true).
|
||||
BorderLeft(true).
|
||||
BorderRight(true).
|
||||
BorderBottom(true)
|
||||
|
||||
viewportStyle = lipgloss.NewStyle().
|
||||
Margin(0, 0, 0, 0).
|
||||
Padding(1, 1).
|
||||
Border(lipgloss.RoundedBorder()).
|
||||
BorderForeground(lipgloss.Color("#874BFD")).
|
||||
BorderTop(true).
|
||||
BorderLeft(true).
|
||||
BorderRight(true).
|
||||
BorderBottom(true)
|
||||
)
|
||||
|
||||
type KeyMap struct {
|
||||
Refresh key.Binding
|
||||
Select key.Binding
|
||||
SwitchFocus key.Binding
|
||||
}
|
||||
|
||||
var DefaultKeyMap = KeyMap{
|
||||
Refresh: key.NewBinding(
|
||||
key.WithKeys("r", "R"),
|
||||
key.WithHelp("r/R", "refresh"),
|
||||
),
|
||||
Select: key.NewBinding(
|
||||
key.WithKeys("enter"),
|
||||
key.WithHelp("enter", "select"),
|
||||
),
|
||||
SwitchFocus: key.NewBinding(
|
||||
key.WithKeys("tab"),
|
||||
key.WithHelp("tab", "switch focus"),
|
||||
),
|
||||
}
|
||||
|
||||
type Model struct {
|
||||
keymap KeyMap
|
||||
list list.Model
|
||||
items []list.Item
|
||||
viewport viewport.Model
|
||||
ctx *ctx.Ctx
|
||||
|
||||
focused int
|
||||
focusables [2]tea.Model
|
||||
}
|
||||
|
||||
func (m Model) Init() tea.Cmd {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewModel(c *ctx.Ctx) Model {
|
||||
m := Model{
|
||||
keymap: DefaultKeyMap,
|
||||
focused: 0,
|
||||
}
|
||||
|
||||
// m.focusables = append(m.focusables, m.list)
|
||||
// m.focusables = append(m.focusables, m.viewport)
|
||||
|
||||
m.list = list.New(m.items, list.NewDefaultDelegate(), 0, 0)
|
||||
m.list.Title = "Posts"
|
||||
m.ctx = c
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
var cmds []tea.Cmd
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
switch {
|
||||
case key.Matches(msg, m.keymap.Refresh):
|
||||
m.ctx.Loading = true
|
||||
cmds = append(cmds, m.refresh())
|
||||
|
||||
case key.Matches(msg, m.keymap.SwitchFocus):
|
||||
m.focused++
|
||||
if m.focused >= len(m.focusables) {
|
||||
m.focused = 0
|
||||
}
|
||||
// return m, nil
|
||||
|
||||
case key.Matches(msg, m.keymap.Select):
|
||||
i, ok := m.list.SelectedItem().(post.Post)
|
||||
if ok {
|
||||
m.viewport.SetContent(m.renderViewport(&i))
|
||||
return m, nil
|
||||
}
|
||||
}
|
||||
|
||||
case tea.WindowSizeMsg:
|
||||
listWidth := int(math.Floor(float64(m.ctx.Content[0]) / 4.0))
|
||||
listHeight := m.ctx.Content[1] - 1
|
||||
viewportWidth := m.ctx.Content[0] - listWidth - 4
|
||||
viewportHeight := m.ctx.Content[1] - 1
|
||||
|
||||
listStyle.Width(listWidth)
|
||||
listStyle.Height(listHeight)
|
||||
m.list.SetSize(
|
||||
listWidth-2,
|
||||
listHeight-2,
|
||||
)
|
||||
|
||||
viewportStyle.Width(viewportWidth)
|
||||
viewportStyle.Height(viewportHeight)
|
||||
m.viewport = viewport.New(viewportWidth-4, viewportHeight-4)
|
||||
m.viewport.Width = viewportWidth - 4
|
||||
m.viewport.Height = viewportHeight - 4
|
||||
// cmds = append(cmds, viewport.Sync(m.viewport))
|
||||
|
||||
case []list.Item:
|
||||
m.items = msg
|
||||
m.list.SetItems(m.items)
|
||||
m.ctx.Loading = false
|
||||
}
|
||||
|
||||
var cmd tea.Cmd
|
||||
|
||||
if m.focused == 0 {
|
||||
listStyle.BorderForeground(lipgloss.Color("#FFFFFF"))
|
||||
viewportStyle.BorderForeground(lipgloss.Color("#874BFD"))
|
||||
m.list, cmd = m.list.Update(msg)
|
||||
cmds = append(cmds, cmd)
|
||||
} else if m.focused == 1 {
|
||||
listStyle.BorderForeground(lipgloss.Color("#874BFD"))
|
||||
viewportStyle.BorderForeground(lipgloss.Color("#FFFFFF"))
|
||||
m.viewport, cmd = m.viewport.Update(msg)
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
|
||||
return m, tea.Batch(cmds...)
|
||||
}
|
||||
|
||||
func (m Model) View() string {
|
||||
var view string
|
||||
|
||||
view = lipgloss.JoinHorizontal(
|
||||
lipgloss.Top,
|
||||
listStyle.Render(m.list.View()),
|
||||
viewportStyle.Render(m.viewport.View()),
|
||||
)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
func (m *Model) refresh() tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
var items []list.Item
|
||||
|
||||
posts, err := (*m.ctx.Systems[0]).ListPosts()
|
||||
if err != nil {
|
||||
fmt.Printf("%s", err) // TODO: Implement error message
|
||||
}
|
||||
for _, post := range posts {
|
||||
items = append(items, post)
|
||||
}
|
||||
|
||||
return items
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Model) renderViewport(post *post.Post) string {
|
||||
var vp string = ""
|
||||
|
||||
vp = fmt.Sprintf(
|
||||
"%s\n",
|
||||
post.Subject,
|
||||
)
|
||||
|
||||
return vp
|
||||
}
|
10
ui/views/views.go
Normal file
10
ui/views/views.go
Normal file
@ -0,0 +1,10 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
)
|
||||
|
||||
type View interface {
|
||||
View() string
|
||||
Update(msg tea.Msg) (tea.Model, tea.Cmd)
|
||||
}
|
Loading…
Reference in New Issue
Block a user