feat: wip tui updates
This commit is contained in:
parent
5d7e9d79c4
commit
dde2d98a84
5 changed files with 158 additions and 24 deletions
30
tui/app.go
30
tui/app.go
|
|
@ -1,6 +1,7 @@
|
|||
package tui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
|
|
@ -11,13 +12,19 @@ type (
|
|||
Size Size
|
||||
Header HeaderModel
|
||||
Screen tea.Model
|
||||
Screens []tea.Model
|
||||
}
|
||||
)
|
||||
|
||||
func NewApp() AppModel {
|
||||
screens := []tea.Model{
|
||||
NewHomeScreen(),
|
||||
NewNotificationScreen(),
|
||||
}
|
||||
return AppModel{
|
||||
Header: NewHeader(),
|
||||
Screen: NewHomeScreen(),
|
||||
Screen: screens[0],
|
||||
Screens: screens,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -30,7 +37,11 @@ func (m AppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
|
||||
switch msg := msg.(type) {
|
||||
case tea.WindowSizeMsg:
|
||||
m.Size = NewSizeFromWindow(msg)
|
||||
m.SetSize(msg.Width, msg.Height)
|
||||
case SwitchHomeScreenMsg:
|
||||
m.Screen = m.Screens[0]
|
||||
case SwitchNotificationScreenMsg:
|
||||
m.Screen = m.Screens[1]
|
||||
}
|
||||
|
||||
m.Header, headerCmd = m.Header.Update(msg)
|
||||
|
|
@ -39,8 +50,23 @@ func (m AppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
return m, tea.Batch(cmd, headerCmd, screenCmd)
|
||||
}
|
||||
|
||||
func (m *AppModel) SetSize(width, height int) {
|
||||
m.Size = NewSize(width, height)
|
||||
m.Header.SetWidth(width)
|
||||
screenHeight := height - m.Header.Size.Height
|
||||
switch screen := m.Screen.(type) {
|
||||
case Sized:
|
||||
m.Screen = screen.SetSize(width, screenHeight)
|
||||
case SizedWidth:
|
||||
m.Screen = screen.SetWidth(width)
|
||||
case SizedHeight:
|
||||
m.Screen = screen.SetHeight(screenHeight)
|
||||
}
|
||||
}
|
||||
|
||||
func (m AppModel) View() string {
|
||||
return strings.Join([]string{
|
||||
fmt.Sprintf("%d x %d", m.Size.Width, m.Size.Height),
|
||||
m.Header.View(),
|
||||
m.Screen.View(),
|
||||
}, "\n")
|
||||
|
|
|
|||
|
|
@ -9,13 +9,15 @@ import (
|
|||
|
||||
type (
|
||||
HeaderModel struct{
|
||||
Size Size
|
||||
Tabs []HeaderTabModel
|
||||
Width int
|
||||
}
|
||||
|
||||
HeaderTabModel struct{
|
||||
Current bool
|
||||
Size Size
|
||||
Active bool
|
||||
Name string
|
||||
Key rune
|
||||
Unread int
|
||||
}
|
||||
)
|
||||
|
|
@ -23,16 +25,16 @@ type (
|
|||
func NewHeader() HeaderModel {
|
||||
return HeaderModel{
|
||||
Tabs: []HeaderTabModel {
|
||||
NewHeaderTab("Home", 10, true),
|
||||
NewHeaderTab("Notifications", 3, false),
|
||||
NewHeaderTab("Lists", 5, false),
|
||||
NewHeaderTab("Private", 0, false),
|
||||
NewHeaderTab("Home", 'H', 10, true),
|
||||
NewHeaderTab("Notifications", 'N', 3, false),
|
||||
NewHeaderTab("Lists", 'L', 5, false),
|
||||
NewHeaderTab("Private", 'P', 0, false),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewHeaderTab(name string, unread int, current bool) HeaderTabModel {
|
||||
return HeaderTabModel{ Name: name, Unread: unread, Current: current }
|
||||
func NewHeaderTab(name string, key rune, unread int, current bool) HeaderTabModel {
|
||||
return HeaderTabModel{ Name: name, Key: key, Unread: unread, Active: current }
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
@ -59,6 +61,7 @@ var (
|
|||
}
|
||||
|
||||
headerTabStyle = lipgloss.NewStyle().
|
||||
Padding(0, 1).
|
||||
Border(tabBorder, true)
|
||||
|
||||
activeHeaderTabStyle = headerTabStyle.
|
||||
|
|
@ -72,43 +75,80 @@ func (m HeaderModel) Init() tea.Cmd {
|
|||
func (m HeaderModel) Update(msg tea.Msg) (HeaderModel, tea.Cmd) {
|
||||
var cmd tea.Cmd
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case Size:
|
||||
m.Width = msg.Width
|
||||
switch msg.(type) {
|
||||
case SwitchHomeScreenMsg:
|
||||
m.SetActive(0)
|
||||
case SwitchNotificationScreenMsg:
|
||||
m.SetActive(1)
|
||||
}
|
||||
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
func (m *HeaderModel) SetActive(tabIndex int) {
|
||||
for i := range m.Tabs {
|
||||
m.Tabs[i].Active = i == tabIndex
|
||||
}
|
||||
}
|
||||
|
||||
func (m *HeaderModel) SetWidth(width int) {
|
||||
tabWidth := width / len(m.Tabs)
|
||||
var maxTabHeight int
|
||||
for i := range m.Tabs {
|
||||
m.Tabs[i].SetSize(tabWidth)
|
||||
maxTabHeight = max(maxTabHeight, m.Tabs[i].Size.Height)
|
||||
}
|
||||
m.Size = Size{
|
||||
Width: width,
|
||||
Height: 3+maxTabHeight,
|
||||
}
|
||||
}
|
||||
|
||||
func (m HeaderModel) View() string {
|
||||
header := lipgloss.NewStyle().
|
||||
Padding(1, 0).
|
||||
Align(lipgloss.Center).
|
||||
Width(m.Width)
|
||||
Width(m.Size.Width)
|
||||
|
||||
renderedTabs := make([]string, len(m.Tabs))
|
||||
for i, tab := range m.Tabs {
|
||||
renderedTabs[i] = tab.View()
|
||||
}
|
||||
joinedTabs := lipgloss.JoinHorizontal(lipgloss.Bottom, renderedTabs...)
|
||||
|
||||
return header.Render(renderedTabs...)
|
||||
return header.Render(joinedTabs)
|
||||
}
|
||||
|
||||
func (m HeaderTabModel) Init() tea.Cmd {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m HeaderTabModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
func (m HeaderTabModel) Update(msg tea.Msg) (HeaderTabModel, tea.Cmd) {
|
||||
var cmd tea.Cmd
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
func (m *HeaderTabModel) SetSize(width int) {
|
||||
m.Size = Size{
|
||||
Width: width,
|
||||
Height: 1,
|
||||
}
|
||||
}
|
||||
|
||||
func (m HeaderTabModel) View() string {
|
||||
content := lipgloss.JoinHorizontal(lipgloss.Center, m.Name, fmt.Sprintf("(%d)", m.Unread))
|
||||
contentWidth := m.Size.Width - 4
|
||||
content := fmt.Sprintf("[%c] %s - %d", m.Key, m.Name, m.Unread)
|
||||
if len(content) > contentWidth {
|
||||
content = fmt.Sprintf("[%c] %d", m.Key, m.Unread)
|
||||
if len(content) > contentWidth {
|
||||
content = fmt.Sprintf("[%c]", m.Key)
|
||||
}
|
||||
}
|
||||
content = lipgloss.PlaceHorizontal(contentWidth, lipgloss.Center, content)
|
||||
|
||||
if m.Current {
|
||||
return lipgloss.NewStyle().Underline(true).Render(content)
|
||||
if m.Active {
|
||||
return activeHeaderTabStyle.Render(content)
|
||||
}
|
||||
|
||||
return content
|
||||
return headerTabStyle.Render(content)
|
||||
}
|
||||
|
|
|
|||
13
tui/home.go
13
tui/home.go
|
|
@ -11,8 +11,14 @@ type (
|
|||
HomeScreenModel struct{
|
||||
Size Size
|
||||
}
|
||||
|
||||
SwitchHomeScreenMsg struct{}
|
||||
)
|
||||
|
||||
func SwitchHomeScreen() tea.Msg {
|
||||
return SwitchHomeScreenMsg{}
|
||||
}
|
||||
|
||||
func NewHomeScreen() HomeScreenModel {
|
||||
return HomeScreenModel{}
|
||||
}
|
||||
|
|
@ -29,6 +35,8 @@ func (m HomeScreenModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
switch msg.String() {
|
||||
case "q", "ctrl-c":
|
||||
cmd = tea.Quit
|
||||
case "N":
|
||||
cmd = SwitchNotificationScreen
|
||||
}
|
||||
case Size:
|
||||
m.Size = msg
|
||||
|
|
@ -37,6 +45,11 @@ func (m HomeScreenModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
return m, cmd
|
||||
}
|
||||
|
||||
func (m HomeScreenModel) SetSize(width, height int) HomeScreenModel {
|
||||
m.Size = NewSize(width, height)
|
||||
return m
|
||||
}
|
||||
|
||||
func (m HomeScreenModel) View() string {
|
||||
header := lipgloss.NewStyle().
|
||||
Align(lipgloss.Center).
|
||||
|
|
|
|||
43
tui/notifications.go
Normal file
43
tui/notifications.go
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
package tui
|
||||
|
||||
import tea "github.com/charmbracelet/bubbletea"
|
||||
|
||||
type (
|
||||
NotificationScreenModel struct{
|
||||
Size Size
|
||||
}
|
||||
|
||||
SwitchNotificationScreenMsg struct{}
|
||||
)
|
||||
|
||||
func SwitchNotificationScreen() tea.Msg {
|
||||
return SwitchNotificationScreenMsg{}
|
||||
}
|
||||
|
||||
func NewNotificationScreen() NotificationScreenModel {
|
||||
return NotificationScreenModel{}
|
||||
}
|
||||
|
||||
func (m NotificationScreenModel) Init() tea.Cmd {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m NotificationScreenModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
var cmd tea.Cmd
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
case "q", "ctrl-c":
|
||||
cmd = tea.Quit
|
||||
case "H":
|
||||
cmd = SwitchHomeScreen
|
||||
}
|
||||
}
|
||||
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
func (m NotificationScreenModel) View() string {
|
||||
return "notification screen"
|
||||
}
|
||||
14
tui/size.go
14
tui/size.go
|
|
@ -2,10 +2,22 @@ package tui
|
|||
|
||||
import tea "github.com/charmbracelet/bubbletea"
|
||||
|
||||
type Size struct{
|
||||
type (
|
||||
Size struct{
|
||||
Width, Height int
|
||||
}
|
||||
|
||||
Sized interface{
|
||||
SetSize(width, height int) tea.Model
|
||||
}
|
||||
SizedWidth interface{
|
||||
SetWidth(width int) tea.Model
|
||||
}
|
||||
SizedHeight interface{
|
||||
SetHeight(height int) tea.Model
|
||||
}
|
||||
)
|
||||
|
||||
func NewSize(width, height int) Size {
|
||||
return Size { Width: width, Height: height }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue