Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VERSION
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
v1.1.0
v1.1.1
7 changes: 2 additions & 5 deletions cmd/book/collection.go
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
package cmd

import (
tea "charm.land/bubbletea/v2"
"github.com/polymorcodeus/book/internal/book"
"github.com/polymorcodeus/book/internal/model"
)
Expand All@@ -20,13 +19,11 @@ func collections(bs *book.BookShelves, shelfName string, format string, config *
return book.PrintCatalog(names, format)
}

_, err := tea.NewProgram(collectionRootScreen(bs, "list", config)).Run()
return err
return runProgram(collectionRootScreen(bs, "list", config))
}

func addCollection(bs *book.BookShelves, config *book.Config) error {
_, err := tea.NewProgram(collectionRootScreen(bs, "add", config)).Run()
return err
return runProgram(collectionRootScreen(bs, "add", config))
}

func collectionRootScreen(bs *book.BookShelves, action string, config *book.Config) model.RootScreen {
Expand Down
19 changes: 19 additions & 0 deletions cmd/book/main.go
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,7 @@ import (
"os"
"path/filepath"

tea "charm.land/bubbletea/v2"
"github.com/polymorcodeus/gofiglet"
altsrc "github.com/urfave/cli-altsrc/v3"
alttoml "github.com/urfave/cli-altsrc/v3/toml"
Expand All@@ -18,6 +19,7 @@ import (

"github.com/polymorcodeus/book/internal/book"
"github.com/polymorcodeus/book/internal/catalog"
"github.com/polymorcodeus/book/internal/model"
)

var (
Expand DownExpand Up@@ -533,3 +535,20 @@ func Main() {
log.Fatal(err)
}
}

// runProgram runs a RootScreen TUI and prints its completion output after the
// program exits. The interactive form renders in the alternate screen buffer
// and is discarded on exit, so the caller prints the result below the banner
// instead of leaving selector fragments behind.
func runProgram(screen model.RootScreen) error {
m, err := tea.NewProgram(screen).Run()
if err != nil {
return err
}
if rp, ok := m.(model.ResultProvider); ok {
if v := rp.ResultView(); v != "" {
fmt.Print(v)
}
}
return nil
}
16 changes: 5 additions & 11 deletions cmd/book/mark.go
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,16 +6,14 @@ import (
"net/url"
"strings"

tea "charm.land/bubbletea/v2"
"github.com/polymorcodeus/book/internal/book"
"github.com/polymorcodeus/book/internal/catalog"
"github.com/polymorcodeus/book/internal/model"
"github.com/polymorcodeus/book/internal/web"
)

func mark(bs *book.BookShelves, config *book.Config) error {
_, err := tea.NewProgram(markRootScreen(bs, &book.Mark{}, "get", config)).Run()
return err
return runProgram(markRootScreen(bs, &book.Mark{}, "get", config))
}

func marks(bs *book.BookShelves, shelfName string, collectionName string, format string, config *book.Config) error {
Expand All@@ -31,13 +29,11 @@ func marks(bs *book.BookShelves, shelfName string, collectionName string, format
}
return book.PrintCatalog(collection, format)
}
_, err := tea.NewProgram(markRootScreen(bs, &book.Mark{}, "list", config)).Run()
return err
return runProgram(markRootScreen(bs, &book.Mark{}, "list", config))
}

func editMark(bs *book.BookShelves, config *book.Config) error {
_, err := tea.NewProgram(markRootScreen(bs, &book.Mark{}, "edit", config)).Run()
return err
return runProgram(markRootScreen(bs, &book.Mark{}, "edit", config))
}

func searchMarks(query string, tags string, shelfName string, collectionName string, format string, config *book.Config) error {
Expand DownExpand Up@@ -139,13 +135,11 @@ func addMark(bs *book.BookShelves, URL string, tags string, shelfName string, co
return nil
}

_, err := tea.NewProgram(markRootScreen(bs, &mark, "add", config)).Run()
return err
return runProgram(markRootScreen(bs, &mark, "add", config))
}

func removeMark(bs *book.BookShelves, config *book.Config) error {
_, err := tea.NewProgram(markRootScreen(bs, &book.Mark{}, "delete", config)).Run()
return err
return runProgram(markRootScreen(bs, &book.Mark{}, "delete", config))
}

func markRootScreen(bs *book.BookShelves, mark *book.Mark, action string, config *book.Config) model.RootScreen {
Expand Down
7 changes: 2 additions & 5 deletions cmd/book/shelf.go
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
package cmd

import (
tea "charm.land/bubbletea/v2"
"github.com/polymorcodeus/book/internal/book"
"github.com/polymorcodeus/book/internal/model"
)
Expand All@@ -19,13 +18,11 @@ func shelves(bs *book.BookShelves, format string, config *book.Config) error {
return book.PrintCatalog(names, format)
}

_, err := tea.NewProgram(shelfRootScreen(bs, "list", config)).Run()
return err
return runProgram(shelfRootScreen(bs, "list", config))
}

func addShelf(bs *book.BookShelves, config *book.Config) error {
_, err := tea.NewProgram(shelfRootScreen(bs, "add", config)).Run()
return err
return runProgram(shelfRootScreen(bs, "add", config))
}

func shelfRootScreen(bs *book.BookShelves, action string, config *book.Config) model.RootScreen {
Expand Down
117 changes: 60 additions & 57 deletions internal/model/collection_model.go
Original file line numberDiff line numberDiff line change
Expand Up@@ -75,13 +75,12 @@ func (m getCollectionModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}

func (m getCollectionModel) View() tea.View {
s := m.get.book.styles
t := m.get.book.tmpls

if m.action == "list" && m.get.book.form.State == huh.StateCompleted {
return renderCompletedView(s, t, "collection-list", m.get.shelf)
if m.get.book.form.State == huh.StateCompleted || m.get.book.width <= 0 {
return altScreenView("")
}

s := m.get.book.styles

// Form (left side)
v := strings.TrimSuffix(m.get.book.form.View(), "\n\n")
form := s.Form.Render(v)
Expand All@@ -100,13 +99,7 @@ func (m getCollectionModel) View() tea.View {

currentShelf = lipglossDimmer(s.StatusHeader, "Picked Shelf", displayShelf)

const statusWidth = 68
statusMarginLeft := m.get.book.width - statusWidth - lipgloss.Width(form) - s.Status.GetMarginRight()
status = s.Status.
Height(10).
Width(statusWidth).
MarginLeft(statusMarginLeft).
Render(currentShelf)
status = m.get.book.statusPanel(form, currentShelf, 10)
}

errors := m.get.book.form.Errors()
Expand All@@ -120,12 +113,21 @@ func (m getCollectionModel) View() tea.View {
if len(errors) > 0 {
footer = m.get.book.appErrorBoundaryView("")
}
return tea.NewView(s.Base.Render(header + "\n" + body + "\n\n" + footer))
return altScreenView(s.Base.Render(header + "\n" + body + "\n\n" + footer))
}

// ResultView returns the completion output for the caller to print after the
// program exits.
func (m getCollectionModel) ResultView() string {
if m.get.book.form.State != huh.StateCompleted || m.action != "list" {
return ""
}
return renderCompletedView(m.get.book.styles, m.get.book.tmpls, "collection-list", m.get.shelf).Content
}

// GetCollectionForm to be used for editing descriptions/names in future
func GetCollectionForm(bs *book.BookShelves, config *book.Config, action string) getCollectionModel {
m := collectionModel{book: &Book{width: maxWidth}}
m := collectionModel{book: &Book{width: 0}}
m.book.styles = NewStyles(config)
m.book.tmpls = config.Templates
m.book.shelves = bs
Expand DownExpand Up@@ -240,56 +242,57 @@ func (m editCollectionModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}

func (m editCollectionModel) View() tea.View {
if m.editor.book.form.State == huh.StateCompleted || m.editor.book.width <= 0 {
return altScreenView("")
}

s := m.editor.book.styles
t := m.editor.book.tmpls

switch m.editor.book.form.State {
case huh.StateCompleted:
return renderCompletedView(s, t, "collection-add", m.editor.collection)
default:
// Form (left side)
v := strings.TrimSuffix(m.editor.book.form.View(), "\n\n")
form := s.Form.Render(v)

// Status (right side)
var status string
{
var (
editShelfName string
editCollectionName string
editCollectionDesc string
)

editShelfName = s.StatusHeader.Render("Picked Shelf") + "\n" + m.editor.shelf.Name + "\n\n"
editCollectionName = lipglossDimmer(s.StatusHeader, "Collection Name", m.editor.collection.Name)
editCollectionDesc = lipglossDimmer(s.StatusHeader, "Collection Description", m.editor.collection.Description)

const statusWidth = 68
statusMarginLeft := m.editor.book.width - statusWidth - lipgloss.Width(form) - s.Status.GetMarginRight()
status = s.Status.
Height(10).
Width(statusWidth).
MarginLeft(statusMarginLeft).
Render(editShelfName + editCollectionName + editCollectionDesc)
}

errors := m.editor.book.form.Errors()
header := m.editor.book.appBoundaryView("book collection editing system")
if len(errors) > 0 {
header = m.editor.book.appErrorBoundaryView(m.editor.book.errorView())
}
body := lipgloss.JoinHorizontal(lipgloss.Left, form, status)
// Form (left side)
v := strings.TrimSuffix(m.editor.book.form.View(), "\n\n")
form := s.Form.Render(v)

footer := m.editor.book.appBoundaryView(m.editor.book.form.Help().ShortHelpView(m.editor.book.form.KeyBinds()))
if len(errors) > 0 {
footer = m.editor.book.appErrorBoundaryView("")
}
return tea.NewView(s.Base.Render(header + "\n" + body + "\n\n" + footer))
// Status (right side)
var status string
{
var (
editShelfName string
editCollectionName string
editCollectionDesc string
)

editShelfName = s.StatusHeader.Render("Picked Shelf") + "\n" + m.editor.shelf.Name + "\n\n"
editCollectionName = lipglossDimmer(s.StatusHeader, "Collection Name", m.editor.collection.Name)
editCollectionDesc = lipglossDimmer(s.StatusHeader, "Collection Description", m.editor.collection.Description)

status = m.editor.book.statusPanel(form, editShelfName+editCollectionName+editCollectionDesc, 10)
}

errors := m.editor.book.form.Errors()
header := m.editor.book.appBoundaryView("book collection editing system")
if len(errors) > 0 {
header = m.editor.book.appErrorBoundaryView(m.editor.book.errorView())
}
body := lipgloss.JoinHorizontal(lipgloss.Left, form, status)

footer := m.editor.book.appBoundaryView(m.editor.book.form.Help().ShortHelpView(m.editor.book.form.KeyBinds()))
if len(errors) > 0 {
footer = m.editor.book.appErrorBoundaryView("")
}
return altScreenView(s.Base.Render(header + "\n" + body + "\n\n" + footer))
}

// ResultView returns the completion output for the caller to print after the
// program exits.
func (m editCollectionModel) ResultView() string {
if m.editor.book.form.State != huh.StateCompleted {
return ""
}
return renderCompletedView(m.editor.book.styles, m.editor.book.tmpls, "collection-add", m.editor.collection).Content
}

func editCollectionForm(bs *book.BookShelves, shelf *book.Shelf, config *book.Config, action string) editCollectionModel {
m := collectionModel{book: &Book{width: maxWidth}}
m := collectionModel{book: &Book{width: 0}}
m.book.styles = NewStyles(config)
m.book.tmpls = config.Templates
m.book.shelves = bs
Expand Down
Loading
Loading