fix new installation styling, add blinking, fix version selection
Това подаване се съдържа в:
родител
ac1dfb6148
подаване
a5e08cea62
6 променени файла с 119 добавяния и 25 изтривания
|
@ -124,7 +124,6 @@ func (m modMenu) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
newModel, cmd := i.Activate(msg, m)
|
||||
if newModel != nil || cmd != nil {
|
||||
if newModel == nil {
|
||||
newModel.Update(m.root.Size())
|
||||
newModel = m
|
||||
}
|
||||
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 {
|
||||
return nil
|
||||
return textinput.Blink
|
||||
}
|
||||
|
||||
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)
|
||||
case components.ErrorComponentTimeoutMsg:
|
||||
m.error = nil
|
||||
default:
|
||||
var cmd tea.Cmd
|
||||
m.input, cmd = m.input.Update(msg)
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
return m, nil
|
||||
|
|
|
@ -21,7 +21,7 @@ type modVersionMenu struct {
|
|||
}
|
||||
|
||||
func NewModVersion(root components.RootModel, parent tea.Model, mod utils.Mod) tea.Model {
|
||||
model := modMenu{
|
||||
model := modVersionMenu{
|
||||
root: root,
|
||||
parent: parent,
|
||||
}
|
||||
|
@ -108,7 +108,6 @@ func (m modVersionMenu) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||
newModel, cmd := i.Activate(msg, m)
|
||||
if newModel != nil || cmd != nil {
|
||||
if newModel == nil {
|
||||
newModel.Update(m.root.Size())
|
||||
newModel = m
|
||||
}
|
||||
return newModel, cmd
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
package scenes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/charmbracelet/bubbles/key"
|
||||
"github.com/charmbracelet/bubbles/list"
|
||||
"github.com/charmbracelet/bubbles/spinner"
|
||||
"github.com/sahilm/fuzzy"
|
||||
|
||||
"github.com/charmbracelet/bubbles/textinput"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"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/utils"
|
||||
)
|
||||
|
@ -29,7 +32,9 @@ type newInstallation struct {
|
|||
}
|
||||
|
||||
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.SetFilteringEnabled(false)
|
||||
l.SetSpinner(spinner.MiniDot)
|
||||
|
@ -58,7 +63,7 @@ func NewNewInstallation(root components.RootModel, parent tea.Model) tea.Model {
|
|||
}
|
||||
|
||||
func (m newInstallation) Init() tea.Cmd {
|
||||
return nil
|
||||
return textinput.Blink
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
newDir := newDirItem.(utils.SimpleItem[newInstallation]).ItemTitle
|
||||
newDir := newDirItem.(utils.SimpleItemExtra[newInstallation, string]).ItemTitle
|
||||
|
||||
newPath := ""
|
||||
_, 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)
|
||||
case components.ErrorComponentTimeoutMsg:
|
||||
m.error = nil
|
||||
default:
|
||||
var cmd tea.Cmd
|
||||
m.input, cmd = m.input.Update(msg)
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
return m, nil
|
||||
|
@ -151,13 +160,22 @@ func (m newInstallation) View() string {
|
|||
|
||||
if len(m.dirList.Items()) > 0 {
|
||||
m.dirList.SetSize(m.dirList.Width(), m.root.Size().Height-lipgloss.Height(mandatory)-1)
|
||||
|
||||
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 {
|
||||
filter := ""
|
||||
dir, err := os.ReadDir(inputValue)
|
||||
|
@ -170,22 +188,81 @@ func getDirItems(inputValue string) []list.Item {
|
|||
|
||||
newItems := make([]list.Item, 0)
|
||||
|
||||
if inputValue != "" {
|
||||
for _, entry := range dir {
|
||||
if entry.IsDir() {
|
||||
if filter != "" {
|
||||
matches := fuzzy.Find(filter, []string{entry.Name()})
|
||||
if len(matches) == 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
globalMatches = nil
|
||||
|
||||
newItems = append(newItems, utils.SimpleItem[newInstallation]{
|
||||
ItemTitle: entry.Name(),
|
||||
if inputValue != "" {
|
||||
if filter != "" {
|
||||
dirNames := make([]string, 0)
|
||||
for _, entry := range dir {
|
||||
if entry.IsDir() {
|
||||
dirNames = append(dirNames, entry.Name())
|
||||
}
|
||||
}
|
||||
|
||||
matches := fuzzy.Find(filter, dirNames)
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil
|
||||
return textinput.Blink
|
||||
}
|
||||
|
||||
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)
|
||||
case components.ErrorComponentTimeoutMsg:
|
||||
m.error = nil
|
||||
default:
|
||||
var cmd tea.Cmd
|
||||
m.input, cmd = m.input.Update(msg)
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
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, 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 {
|
||||
return nil
|
||||
return textinput.Blink
|
||||
}
|
||||
|
||||
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)
|
||||
case components.ErrorComponentTimeoutMsg:
|
||||
m.error = nil
|
||||
default:
|
||||
var cmd tea.Cmd
|
||||
m.input, cmd = m.input.Update(msg)
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
return m, nil
|
||||
|
|
Зареждане…
Препратка в нова задача