ui/home is now in the same app

Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
This commit is contained in:
Hadi
2026-05-19 14:34:48 +02:00
parent eaa960e6ab
commit 6f56e0b26a
4 changed files with 79 additions and 25 deletions
+11 -18
View File
@@ -127,33 +127,26 @@ func main() {
projectDir := config.ExpandPath(config.Global.App.ProjectDir)
// Resolve project: either from --project flag or by running the home UI.
var project *homeUI.Project
// If --project flag is set, skip the home screen entirely.
if *flagProject != "" {
p, err := homeUI.OpenProject(projectDir, *flagProject)
project, err := homeUI.OpenProject(projectDir, *flagProject)
if err != nil {
fmt.Fprintf(os.Stderr, "project: %v\n", err)
os.Exit(1)
}
project = p
} else {
finalModel, err := tea.NewProgram(homeUI.New(projectDir)).Run()
if err != nil {
fmt.Fprintf(os.Stderr, "tui: %v\n", err)
os.Exit(1)
}
project = finalModel.(homeUI.Model).Selected()
}
// User quit the home screen without selecting a project.
if project == nil {
return
}
broker := intercept.NewBroker()
m := appUI.New(broker, project.Name, project.Path)
if _, err := tea.NewProgram(m).Run(); err != nil {
fmt.Fprintf(os.Stderr, "tui: %v\n", err)
os.Exit(1)
}
return
}
// Run home + app in a single program to avoid a blank flash on transition.
root := rootModel{home: homeUI.New(projectDir)}
if _, err := tea.NewProgram(root).Run(); err != nil {
fmt.Fprintf(os.Stderr, "tui: %v\n", err)
os.Exit(1)
}
}
+60
View File
@@ -0,0 +1,60 @@
package main
import (
tea "charm.land/bubbletea/v2"
"github.com/anotherhadi/spilltea/internal/intercept"
appUI "github.com/anotherhadi/spilltea/internal/ui/app"
homeUI "github.com/anotherhadi/spilltea/internal/ui/home"
)
type rootState int
const (
rootStateHome rootState = iota
rootStateApp
)
type rootModel struct {
state rootState
home homeUI.Model
app tea.Model
width int
height int
}
func (m rootModel) Init() tea.Cmd {
return m.home.Init()
}
func (m rootModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if ws, ok := msg.(tea.WindowSizeMsg); ok {
m.width = ws.Width
m.height = ws.Height
}
if m.state == rootStateHome {
if sel, ok := msg.(homeUI.ProjectSelectedMsg); ok {
broker := intercept.NewBroker()
app := appUI.New(broker, sel.Project.Name, sel.Project.Path)
m.app = app
m.state = rootStateApp
return m, tea.Batch(app.Init(), func() tea.Msg {
return tea.WindowSizeMsg{Width: m.width, Height: m.height}
})
}
updated, cmd := m.home.Update(msg)
m.home = updated.(homeUI.Model)
return m, cmd
}
updated, cmd := m.app.Update(msg)
m.app = updated
return m, cmd
}
func (m rootModel) View() tea.View {
if m.state == rootStateApp {
return m.app.(interface{ View() tea.View }).View()
}
return m.home.View()
}
+5 -4
View File
@@ -142,6 +142,11 @@ type Project struct {
ModTime time.Time
}
// ProjectSelectedMsg is emitted when the user picks a project from the home screen.
type ProjectSelectedMsg struct {
Project *Project
}
type inputMode int
const (
@@ -161,15 +166,11 @@ type Model struct {
list list.Model
projectDir string
nameInput textinput.Model
selected *Project
width int
height int
teapotFrame int
}
// Selected returns the project chosen by the user, or nil if the program was
// quit without making a selection.
func (m Model) Selected() *Project { return m.selected }
func New(projectDir string) Model {
projects := loadProjects(projectDir)
+6 -6
View File
@@ -76,11 +76,11 @@ func (m Model) handleSelection() (tea.Model, tea.Cmd) {
return m, nil
}
initProjectFiles(dir)
m.selected = &Project{Name: "temporary", Path: filepath.Join(dir, "data.db")}
return m, tea.Quit
p := &Project{Name: "temporary", Path: filepath.Join(dir, "data.db")}
return m, func() tea.Msg { return ProjectSelectedMsg{Project: p} }
default:
m.selected = &Project{Name: item.name, Path: item.path}
return m, tea.Quit
p := &Project{Name: item.name, Path: item.path}
return m, func() tea.Msg { return ProjectSelectedMsg{Project: p} }
}
}
@@ -117,8 +117,8 @@ func (m Model) updateNaming(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
return m, nil
}
initProjectFiles(dir)
m.selected = &Project{Name: name, Path: filepath.Join(dir, "data.db")}
return m, tea.Quit
p := &Project{Name: name, Path: filepath.Join(dir, "data.db")}
return m, func() tea.Msg { return ProjectSelectedMsg{Project: p} }
default:
var cmd tea.Cmd
m.nameInput, cmd = m.nameInput.Update(msg)