fix new installation styling, add blinking, fix version selection
This commit is contained in:
parent
ac1dfb6148
commit
a5e08cea62
6 changed files with 119 additions and 25 deletions
|
@ -124,7 +124,6 @@ func (m modMenu) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
newModel, cmd := i.Activate(msg, m)
|
newModel, cmd := i.Activate(msg, m)
|
||||||
if newModel != nil || cmd != nil {
|
if newModel != nil || cmd != nil {
|
||||||
if newModel == nil {
|
if newModel == nil {
|
||||||
newModel.Update(m.root.Size())
|
|
||||||
newModel = m
|
newModel = m
|
||||||
}
|
}
|
||||||
return newModel, cmd
|
return newModel, cmd
|
||||||
|
|
|
@ -38,7 +38,7 @@ func NewModSemver(root components.RootModel, parent tea.Model, mod utils.Mod) te
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m modSemver) Init() tea.Cmd {
|
func (m modSemver) Init() tea.Cmd {
|
||||||
return nil
|
return textinput.Blink
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m modSemver) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
func (m modSemver) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
@ -66,6 +66,10 @@ func (m modSemver) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
m.root.SetSize(msg)
|
m.root.SetSize(msg)
|
||||||
case components.ErrorComponentTimeoutMsg:
|
case components.ErrorComponentTimeoutMsg:
|
||||||
m.error = nil
|
m.error = nil
|
||||||
|
default:
|
||||||
|
var cmd tea.Cmd
|
||||||
|
m.input, cmd = m.input.Update(msg)
|
||||||
|
return m, cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|
|
@ -21,7 +21,7 @@ type modVersionMenu struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewModVersion(root components.RootModel, parent tea.Model, mod utils.Mod) tea.Model {
|
func NewModVersion(root components.RootModel, parent tea.Model, mod utils.Mod) tea.Model {
|
||||||
model := modMenu{
|
model := modVersionMenu{
|
||||||
root: root,
|
root: root,
|
||||||
parent: parent,
|
parent: parent,
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,6 @@ func (m modVersionMenu) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
newModel, cmd := i.Activate(msg, m)
|
newModel, cmd := i.Activate(msg, m)
|
||||||
if newModel != nil || cmd != nil {
|
if newModel != nil || cmd != nil {
|
||||||
if newModel == nil {
|
if newModel == nil {
|
||||||
newModel.Update(m.root.Size())
|
|
||||||
newModel = m
|
newModel = m
|
||||||
}
|
}
|
||||||
return newModel, cmd
|
return newModel, cmd
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
package scenes
|
package scenes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/charmbracelet/bubbles/key"
|
"github.com/charmbracelet/bubbles/key"
|
||||||
"github.com/charmbracelet/bubbles/list"
|
"github.com/charmbracelet/bubbles/list"
|
||||||
"github.com/charmbracelet/bubbles/spinner"
|
"github.com/charmbracelet/bubbles/spinner"
|
||||||
"github.com/sahilm/fuzzy"
|
|
||||||
|
|
||||||
"github.com/charmbracelet/bubbles/textinput"
|
"github.com/charmbracelet/bubbles/textinput"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
"github.com/muesli/reflow/truncate"
|
||||||
|
"github.com/sahilm/fuzzy"
|
||||||
"github.com/satisfactorymodding/ficsit-cli/tea/components"
|
"github.com/satisfactorymodding/ficsit-cli/tea/components"
|
||||||
"github.com/satisfactorymodding/ficsit-cli/tea/utils"
|
"github.com/satisfactorymodding/ficsit-cli/tea/utils"
|
||||||
)
|
)
|
||||||
|
@ -29,7 +32,9 @@ type newInstallation struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNewInstallation(root components.RootModel, parent tea.Model) tea.Model {
|
func NewNewInstallation(root components.RootModel, parent tea.Model) tea.Model {
|
||||||
l := list.New([]list.Item{}, utils.NewItemDelegate(), root.Size().Width, root.Size().Height-root.Height())
|
listDelegate := CustomDelegate{ItemDelegate: utils.NewItemDelegate()}
|
||||||
|
|
||||||
|
l := list.New([]list.Item{}, listDelegate, root.Size().Width, root.Size().Height-root.Height())
|
||||||
l.SetShowStatusBar(true)
|
l.SetShowStatusBar(true)
|
||||||
l.SetFilteringEnabled(false)
|
l.SetFilteringEnabled(false)
|
||||||
l.SetSpinner(spinner.MiniDot)
|
l.SetSpinner(spinner.MiniDot)
|
||||||
|
@ -58,7 +63,7 @@ func NewNewInstallation(root components.RootModel, parent tea.Model) tea.Model {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m newInstallation) Init() tea.Cmd {
|
func (m newInstallation) Init() tea.Cmd {
|
||||||
return nil
|
return textinput.Blink
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m newInstallation) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
func (m newInstallation) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
@ -96,7 +101,7 @@ func (m newInstallation) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
newDir := newDirItem.(utils.SimpleItem[newInstallation]).ItemTitle
|
newDir := newDirItem.(utils.SimpleItemExtra[newInstallation, string]).ItemTitle
|
||||||
|
|
||||||
newPath := ""
|
newPath := ""
|
||||||
_, err := os.ReadDir(m.input.Value())
|
_, err := os.ReadDir(m.input.Value())
|
||||||
|
@ -135,6 +140,10 @@ func (m newInstallation) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
m.root.SetSize(msg)
|
m.root.SetSize(msg)
|
||||||
case components.ErrorComponentTimeoutMsg:
|
case components.ErrorComponentTimeoutMsg:
|
||||||
m.error = nil
|
m.error = nil
|
||||||
|
default:
|
||||||
|
var cmd tea.Cmd
|
||||||
|
m.input, cmd = m.input.Update(msg)
|
||||||
|
return m, cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
|
@ -151,13 +160,22 @@ func (m newInstallation) View() string {
|
||||||
|
|
||||||
if len(m.dirList.Items()) > 0 {
|
if len(m.dirList.Items()) > 0 {
|
||||||
m.dirList.SetSize(m.dirList.Width(), m.root.Size().Height-lipgloss.Height(mandatory)-1)
|
m.dirList.SetSize(m.dirList.Width(), m.root.Size().Height-lipgloss.Height(mandatory)-1)
|
||||||
|
|
||||||
return lipgloss.JoinVertical(lipgloss.Left, mandatory, m.dirList.View())
|
return lipgloss.JoinVertical(lipgloss.Left, mandatory, m.dirList.View())
|
||||||
}
|
}
|
||||||
|
|
||||||
return mandatory
|
infoBox := lipgloss.NewStyle().
|
||||||
|
BorderStyle(lipgloss.ThickBorder()).
|
||||||
|
BorderForeground(lipgloss.Color("39")).
|
||||||
|
Padding(0, 1).
|
||||||
|
Margin(0, 0, 0, 2).
|
||||||
|
Render("Enter the path to the satisfactory installation")
|
||||||
|
|
||||||
|
return lipgloss.JoinVertical(lipgloss.Left, mandatory, infoBox)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I know this is awful, but beats re-implementing the entire list model
|
||||||
|
var globalMatches []fuzzy.Match
|
||||||
|
|
||||||
func getDirItems(inputValue string) []list.Item {
|
func getDirItems(inputValue string) []list.Item {
|
||||||
filter := ""
|
filter := ""
|
||||||
dir, err := os.ReadDir(inputValue)
|
dir, err := os.ReadDir(inputValue)
|
||||||
|
@ -170,22 +188,81 @@ func getDirItems(inputValue string) []list.Item {
|
||||||
|
|
||||||
newItems := make([]list.Item, 0)
|
newItems := make([]list.Item, 0)
|
||||||
|
|
||||||
|
globalMatches = nil
|
||||||
|
|
||||||
if inputValue != "" {
|
if inputValue != "" {
|
||||||
|
if filter != "" {
|
||||||
|
dirNames := make([]string, 0)
|
||||||
for _, entry := range dir {
|
for _, entry := range dir {
|
||||||
if entry.IsDir() {
|
if entry.IsDir() {
|
||||||
if filter != "" {
|
dirNames = append(dirNames, entry.Name())
|
||||||
matches := fuzzy.Find(filter, []string{entry.Name()})
|
|
||||||
if len(matches) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newItems = append(newItems, utils.SimpleItem[newInstallation]{
|
matches := fuzzy.Find(filter, dirNames)
|
||||||
ItemTitle: entry.Name(),
|
sort.Stable(matches)
|
||||||
|
|
||||||
|
for _, match := range matches {
|
||||||
|
newItems = append(newItems, utils.SimpleItemExtra[newInstallation, string]{
|
||||||
|
SimpleItem: utils.SimpleItem[newInstallation]{
|
||||||
|
ItemTitle: match.Str,
|
||||||
|
},
|
||||||
|
Extra: match.Str,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
globalMatches = matches
|
||||||
|
} else {
|
||||||
|
for _, entry := range dir {
|
||||||
|
if entry.IsDir() {
|
||||||
|
newItems = append(newItems, utils.SimpleItemExtra[newInstallation, string]{
|
||||||
|
SimpleItem: utils.SimpleItem[newInstallation]{
|
||||||
|
ItemTitle: entry.Name(),
|
||||||
|
},
|
||||||
|
Extra: entry.Name(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return newItems
|
return newItems
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CustomDelegate struct {
|
||||||
|
list.ItemDelegate
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CustomDelegate) Render(w io.Writer, m list.Model, index int, item list.Item) {
|
||||||
|
realItem := item.(utils.SimpleItemExtra[newInstallation, string])
|
||||||
|
realDelegate := c.ItemDelegate.(list.DefaultDelegate)
|
||||||
|
|
||||||
|
title := realItem.Title()
|
||||||
|
|
||||||
|
s := &realDelegate.Styles
|
||||||
|
|
||||||
|
if m.Width() <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
textwidth := uint(m.Width() - s.NormalTitle.GetPaddingLeft() - s.NormalTitle.GetPaddingRight())
|
||||||
|
title = truncate.StringWithTail(title, textwidth, "…")
|
||||||
|
|
||||||
|
if index == m.Index() {
|
||||||
|
if globalMatches != nil {
|
||||||
|
unmatched := s.SelectedTitle.Inline(true)
|
||||||
|
matched := unmatched.Copy().Inherit(s.FilterMatch)
|
||||||
|
title = lipgloss.StyleRunes(title, globalMatches[index].MatchedIndexes, matched, unmatched)
|
||||||
|
}
|
||||||
|
title = s.SelectedTitle.Render(title)
|
||||||
|
} else {
|
||||||
|
if globalMatches != nil {
|
||||||
|
unmatched := s.NormalTitle.Inline(true)
|
||||||
|
matched := unmatched.Copy().Inherit(s.FilterMatch)
|
||||||
|
title = lipgloss.StyleRunes(title, globalMatches[index].MatchedIndexes, matched, unmatched)
|
||||||
|
}
|
||||||
|
title = s.NormalTitle.Render(title)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(w, "%s", title)
|
||||||
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ func NewNewProfile(root components.RootModel, parent tea.Model) tea.Model {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m newProfile) Init() tea.Cmd {
|
func (m newProfile) Init() tea.Cmd {
|
||||||
return nil
|
return textinput.Blink
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m newProfile) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
func (m newProfile) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
@ -63,6 +63,10 @@ func (m newProfile) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
m.root.SetSize(msg)
|
m.root.SetSize(msg)
|
||||||
case components.ErrorComponentTimeoutMsg:
|
case components.ErrorComponentTimeoutMsg:
|
||||||
m.error = nil
|
m.error = nil
|
||||||
|
default:
|
||||||
|
var cmd tea.Cmd
|
||||||
|
m.input, cmd = m.input.Update(msg)
|
||||||
|
return m, cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
|
@ -75,5 +79,12 @@ func (m newProfile) View() string {
|
||||||
return lipgloss.JoinVertical(lipgloss.Left, m.root.View(), m.title, (*m.error).View(), inputView)
|
return lipgloss.JoinVertical(lipgloss.Left, m.root.View(), m.title, (*m.error).View(), inputView)
|
||||||
}
|
}
|
||||||
|
|
||||||
return lipgloss.JoinVertical(lipgloss.Left, m.root.View(), m.title, inputView)
|
infoBox := lipgloss.NewStyle().
|
||||||
|
BorderStyle(lipgloss.ThickBorder()).
|
||||||
|
BorderForeground(lipgloss.Color("39")).
|
||||||
|
Padding(0, 1).
|
||||||
|
Margin(0, 0, 0, 2).
|
||||||
|
Render("Enter the name of the profile")
|
||||||
|
|
||||||
|
return lipgloss.JoinVertical(lipgloss.Left, m.root.View(), m.title, inputView, infoBox)
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ func NewRenameProfile(root components.RootModel, parent tea.Model, profileData *
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m renameProfile) Init() tea.Cmd {
|
func (m renameProfile) Init() tea.Cmd {
|
||||||
return nil
|
return textinput.Blink
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m renameProfile) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
func (m renameProfile) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
@ -68,6 +68,10 @@ func (m renameProfile) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
m.root.SetSize(msg)
|
m.root.SetSize(msg)
|
||||||
case components.ErrorComponentTimeoutMsg:
|
case components.ErrorComponentTimeoutMsg:
|
||||||
m.error = nil
|
m.error = nil
|
||||||
|
default:
|
||||||
|
var cmd tea.Cmd
|
||||||
|
m.input, cmd = m.input.Update(msg)
|
||||||
|
return m, cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|
Loading…
Reference in a new issue