add a custom compositing layer

This commit is contained in:
2026-01-01 05:15:40 +00:00
parent 4fdf207e50
commit 2cc3451603
2 changed files with 202 additions and 21 deletions
+50 -21
View File
@@ -2,12 +2,12 @@ package main
import (
"fmt"
"mend/compositor"
fs "mend/fstree"
"mend/styles"
"os"
"time"
fs "mend/fstree"
"github.com/charmbracelet/bubbles/spinner"
"github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea"
@@ -44,10 +44,11 @@ type model struct {
tree *fs.FsTree
// spinner needs to be state as I need to update the spinner on
// each tick in update func
spinner spinner.Model
loading bool
viewport viewport.Model
hoverLine int // track which line is being hovered
spinner spinner.Model
loading bool
viewport viewport.Model
hoverLine int // track which line is being hovered
showDialog bool
}
// initial model state
@@ -65,6 +66,7 @@ func createModel() model {
loading: true,
viewport: viewport.New(0, 0),
hoverLine: -1, // no hover initially
showDialog: false,
}
}
@@ -129,6 +131,12 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg.String() {
case "q", "ctrl+c":
return m, tea.Quit
case "d", "D":
m.showDialog = !m.showDialog
return m, nil
}
switch msg.String() {
case "up", "k":
if err := m.tree.MoveUp(); err != nil {
fmt.Println("Error moving up:", err)
@@ -154,26 +162,47 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
func (m model) View() string {
var baseUI string
if m.loading {
return fmt.Sprintf("%s Loading files...", m.spinner.View())
baseUI = fmt.Sprintf("%s Loading files...", m.spinner.View())
} else {
left := lipgloss.NewStyle().
Width(m.width).
Render(m.tree.Render(m.hoverLine))
right := lipgloss.NewStyle().
Width(m.terminalWidth - m.width - 1).
Height(m.terminalHeight).
Render(m.viewport.View())
divider := lipgloss.NewStyle().
Width(1).
Height(m.terminalHeight).
Background(styles.Primary).
Render("")
baseUI = lipgloss.JoinHorizontal(lipgloss.Top, left, divider, right)
}
left := lipgloss.NewStyle().
Width(m.width).
Render(m.tree.Render(m.hoverLine))
// no compositing needed, optimised return
if !m.showDialog {
return baseUI
}
right := lipgloss.NewStyle().
Width(m.terminalWidth - m.width - 1).
Height(m.terminalHeight).
Render(m.viewport.View())
// manual compositing
grid := compositor.NewGrid(m.terminalWidth, m.terminalHeight)
grid.Write(0, 0, baseUI)
dialog := lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(styles.Primary).
Background(lipgloss.Color("#222")).
Foreground(lipgloss.Color("#FFF")).
Padding(1, 2).
Align(lipgloss.Center).
Render("this is a sample dialog\npress d to close")
divider := lipgloss.NewStyle().
Width(1).
Height(m.terminalHeight).
Background(styles.Primary).
Render("") // everything is a string in tui
return lipgloss.JoinHorizontal(lipgloss.Top, left, divider, right)
grid.Write(2, 2, dialog)
return grid.Render()
}
// =================== bubbletea ui fns ===================