Merge pull request #11 from samox73/master

Rework the bubble-tea scene files to provide a more consistent experience
This commit is contained in:
Vilsol 2023-06-18 19:59:44 +03:00 committed by GitHub
commit daa6fba7e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 212 additions and 222 deletions

13
.gitignore vendored
View file

@ -22,6 +22,19 @@
/vendor/ /vendor/
/Godeps/ /Godeps/
### VS Code
# Reference: https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
# Local History for Visual Studio Code
.history/
# Built Visual Studio Code Extensions
*.vsix
### JetBrains+all ### ### JetBrains+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

18
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,18 @@
{
// needs to attach to running dlv process execute
// dlv debug --headless --listen=:2345 .
// in the root of the package first
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Process",
"type": "go",
"debugAdapter": "dlv-dap",
"request": "attach",
"mode": "remote",
"remotePath": "${workspaceFolder}",
"host": "127.0.0.1",
"port": 2345
}
]
}

View file

@ -32,7 +32,7 @@ func (e ErrorComponent) Init() tea.Cmd {
return nil return nil
} }
func (e ErrorComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (e ErrorComponent) Update(_ tea.Msg) (tea.Model, tea.Cmd) {
return e, nil return e, nil
} }

View file

@ -25,7 +25,7 @@ func (h headerComponent) Init() tea.Cmd {
return nil return nil
} }
func (h headerComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (h headerComponent) Update(_ tea.Msg) (tea.Model, tea.Cmd) {
return h, nil return h, nil
} }

View file

@ -7,6 +7,7 @@ import (
"github.com/satisfactorymodding/ficsit-cli/cli" "github.com/satisfactorymodding/ficsit-cli/cli"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -149,13 +150,13 @@ func (m apply) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
switch keypress := msg.String(); keypress { switch keypress := msg.String(); keypress {
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case KeyEscape: case keys.KeyEscape:
m.cancelled = true m.cancelled = true
m.cancelChannel <- true m.cancelChannel <- true
return m, nil return m, nil
case KeyEnter: case keys.KeyEnter:
if m.status.done { if m.status.done {
if m.parent != nil { if m.parent != nil {
return m.parent, m.parent.Init() return m.parent, m.parent.Init()

View file

@ -1,4 +1,4 @@
package scenes package errors
const ( const (
ErrorFailedAddMod = "failed to add mod" ErrorFailedAddMod = "failed to add mod"

View file

@ -1,16 +1,16 @@
package scenes package installation
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/list" "github.com/charmbracelet/bubbles/list"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
"github.com/satisfactorymodding/ficsit-cli/cli" "github.com/satisfactorymodding/ficsit-cli/cli"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -66,19 +66,7 @@ func NewInstallation(root components.RootModel, parent tea.Model, installationDa
model.list.Styles = utils.ListStyles model.list.Styles = utils.ListStyles
model.list.SetSize(model.list.Width(), model.list.Height()) model.list.SetSize(model.list.Width(), model.list.Height())
model.list.StatusMessageLifetime = time.Second * 3 model.list.StatusMessageLifetime = time.Second * 3
model.list.DisableQuitKeybindings() model.list.KeyMap.Quit.SetHelp("q", "back")
model.list.AdditionalShortHelpKeys = func() []key.Binding {
return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")),
}
}
model.list.AdditionalFullHelpKeys = func() []key.Binding {
return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")),
}
}
return model return model
} }
@ -91,7 +79,7 @@ func (m installation) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
switch keypress := msg.String(); keypress { switch keypress := msg.String(); keypress {
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case "q": case "q":
if m.parent != nil { if m.parent != nil {
@ -104,7 +92,7 @@ func (m installation) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m.parent, nil return m.parent, nil
} }
return m, nil return m, nil
case KeyEnter: case keys.KeyEnter:
i, ok := m.list.SelectedItem().(utils.SimpleItem[installation]) i, ok := m.list.SelectedItem().(utils.SimpleItem[installation])
if ok { if ok {
if i.Activate != nil { if i.Activate != nil {

View file

@ -1,4 +1,4 @@
package scenes package installation
import ( import (
"github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/key"
@ -8,6 +8,7 @@ import (
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -28,12 +29,10 @@ func NewInstallations(root components.RootModel, parent tea.Model) tea.Model {
l.Styles = utils.ListStyles l.Styles = utils.ListStyles
l.SetSize(l.Width(), l.Height()) l.SetSize(l.Width(), l.Height())
l.KeyMap.Quit.SetHelp("q", "back") l.KeyMap.Quit.SetHelp("q", "back")
l.DisableQuitKeybindings()
l.AdditionalShortHelpKeys = func() []key.Binding { l.AdditionalShortHelpKeys = func() []key.Binding {
return []key.Binding{ return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")), key.NewBinding(key.WithKeys("n"), key.WithHelp("n", "new installation")),
key.NewBinding(key.WithHelp("n", "new installation")),
} }
} }
@ -51,9 +50,6 @@ func (m installations) Init() tea.Cmd {
} }
func (m installations) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m installations) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// List enables its own keybindings when they were previously disabled
m.list.DisableQuitKeybindings()
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
if m.list.SettingFilter() { if m.list.SettingFilter() {
@ -66,7 +62,7 @@ func (m installations) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case "n": case "n":
newModel := NewNewInstallation(m.root, m) newModel := NewNewInstallation(m.root, m)
return newModel, newModel.Init() return newModel, newModel.Init()
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case "q": case "q":
if m.parent != nil { if m.parent != nil {
@ -74,7 +70,7 @@ func (m installations) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m.parent, nil return m.parent, nil
} }
return m, tea.Quit return m, tea.Quit
case KeyEnter: case keys.KeyEnter:
i, ok := m.list.SelectedItem().(utils.SimpleItem[installations]) i, ok := m.list.SelectedItem().(utils.SimpleItem[installations])
if ok { if ok {
if i.Activate != nil { if i.Activate != nil {

View file

@ -0,0 +1,15 @@
package installation
import tea "github.com/charmbracelet/bubbletea"
type updateInstallationList struct{}
func updateInstallationListCmd() tea.Msg {
return updateInstallationList{}
}
type updateInstallationNames struct{}
func updateInstallationNamesCmd() tea.Msg {
return updateInstallationNames{}
}

View file

@ -1,8 +1,9 @@
package scenes package installation
import ( import (
"fmt" "fmt"
"io" "io"
"io/fs"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
@ -18,6 +19,7 @@ import (
"github.com/sahilm/fuzzy" "github.com/sahilm/fuzzy"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -42,10 +44,16 @@ func NewNewInstallation(root components.RootModel, parent tea.Model) tea.Model {
l.SetShowTitle(false) l.SetShowTitle(false)
l.Styles = utils.ListStyles l.Styles = utils.ListStyles
l.SetSize(l.Width(), l.Height()) l.SetSize(l.Width(), l.Height())
l.KeyMap.Quit.SetHelp("esc", "back")
l.DisableQuitKeybindings()
l.SetShowHelp(false)
l.SetShowStatusBar(false) l.SetShowStatusBar(false)
l.KeyMap.ShowFullHelp.Unbind()
l.KeyMap.Quit.SetHelp("esc", "back")
l.KeyMap.CursorDown.SetHelp("↓", "down")
l.KeyMap.CursorUp.SetHelp("↑", "up")
l.AdditionalShortHelpKeys = func() []key.Binding {
return []key.Binding{
key.NewBinding(key.WithKeys(keys.KeyTab), key.WithHelp(keys.KeyTab, "select")),
}
}
model := newInstallation{ model := newInstallation{
root: root, root: root,
@ -69,11 +77,11 @@ func (m newInstallation) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
switch keypress := msg.String(); keypress { switch keypress := msg.String(); keypress {
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case KeyEscape: case keys.KeyEscape:
return m.parent, nil return m.parent, nil
case KeyEnter: case keys.KeyEnter:
newInstall, err := m.root.GetGlobal().Installations.AddInstallation(m.root.GetGlobal(), m.input.Value(), m.root.GetGlobal().Profiles.SelectedProfile) newInstall, err := m.root.GetGlobal().Installations.AddInstallation(m.root.GetGlobal(), m.input.Value(), m.root.GetGlobal().Profiles.SelectedProfile)
if err != nil { if err != nil {
errorComponent, cmd := components.NewErrorComponent(err.Error(), time.Second*5) errorComponent, cmd := components.NewErrorComponent(err.Error(), time.Second*5)
@ -90,7 +98,7 @@ func (m newInstallation) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} }
return m.parent, updateInstallationListCmd return m.parent, updateInstallationListCmd
case KeyTab: case keys.KeyTab:
var cmd tea.Cmd var cmd tea.Cmd
m.input, cmd = m.input.Update(msg) m.input, cmd = m.input.Update(msg)
@ -149,7 +157,8 @@ func (m newInstallation) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} }
func (m newInstallation) View() string { func (m newInstallation) View() string {
inputView := lipgloss.NewStyle().Padding(1, 2).Render(m.input.View()) style := lipgloss.NewStyle().Padding(1, 2)
inputView := style.Render(m.input.View())
mandatory := lipgloss.JoinVertical(lipgloss.Left, m.root.View(), m.title, inputView) mandatory := lipgloss.JoinVertical(lipgloss.Left, m.root.View(), m.title, inputView)
@ -157,19 +166,18 @@ func (m newInstallation) View() string {
return lipgloss.JoinVertical(lipgloss.Left, mandatory, m.error.View()) return lipgloss.JoinVertical(lipgloss.Left, mandatory, m.error.View())
} }
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)
return lipgloss.JoinVertical(lipgloss.Left, mandatory, m.dirList.View())
}
infoBox := lipgloss.NewStyle(). infoBox := lipgloss.NewStyle().
BorderStyle(lipgloss.ThickBorder()). BorderStyle(lipgloss.ThickBorder()).
BorderForeground(lipgloss.Color("39")). BorderForeground(lipgloss.Color("39")).
Padding(0, 1). Padding(0, 1).
Margin(0, 0, 0, 2). Margin(0, 0, 0, 2).
Render("Enter the path to the satisfactory installation") Render("Enter the path to the satisfactory installation")
mandatory = lipgloss.JoinVertical(lipgloss.Left, mandatory, infoBox)
}
return lipgloss.JoinVertical(lipgloss.Left, mandatory, infoBox) m.dirList.SetSize(m.dirList.Width(), m.root.Size().Height-lipgloss.Height(mandatory)-1)
return lipgloss.JoinVertical(lipgloss.Left, mandatory, m.dirList.View())
} }
// I know this is awful, but beats re-implementing the entire list model // I know this is awful, but beats re-implementing the entire list model
@ -193,7 +201,7 @@ func getDirItems(inputValue string) []list.Item {
if filter != "" { if filter != "" {
dirNames := make([]string, 0) dirNames := make([]string, 0)
for _, entry := range dir { for _, entry := range dir {
if entry.IsDir() { if entry.IsDir() || entry.Type() == fs.ModeSymlink {
dirNames = append(dirNames, entry.Name()) dirNames = append(dirNames, entry.Name())
} }
} }
@ -213,7 +221,7 @@ func getDirItems(inputValue string) []list.Item {
globalMatches = matches globalMatches = matches
} else { } else {
for _, entry := range dir { for _, entry := range dir {
if entry.IsDir() { if entry.IsDir() || entry.Type() == fs.ModeSymlink {
newItems = append(newItems, utils.SimpleItemExtra[newInstallation, string]{ newItems = append(newItems, utils.SimpleItemExtra[newInstallation, string]{
SimpleItem: utils.SimpleItem[newInstallation]{ SimpleItem: utils.SimpleItem[newInstallation]{
ItemTitle: entry.Name(), ItemTitle: entry.Name(),

View file

@ -1,4 +1,4 @@
package scenes package keys
const ( const (
KeyControlC = "ctrl+c" KeyControlC = "ctrl+c"

View file

@ -11,6 +11,11 @@ import (
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/errors"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/installation"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/mods"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/profile"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -63,28 +68,28 @@ func NewMainMenu(root components.RootModel) tea.Model {
utils.SimpleItem[mainMenu]{ utils.SimpleItem[mainMenu]{
ItemTitle: "Installations", ItemTitle: "Installations",
Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) { Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) {
newModel := NewInstallations(root, currentModel) newModel := installation.NewInstallations(root, currentModel)
return newModel, newModel.Init() return newModel, newModel.Init()
}, },
}, },
utils.SimpleItem[mainMenu]{ utils.SimpleItem[mainMenu]{
ItemTitle: "Profiles", ItemTitle: "Profiles",
Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) { Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) {
newModel := NewProfiles(root, currentModel) newModel := profile.NewProfiles(root, currentModel)
return newModel, newModel.Init() return newModel, newModel.Init()
}, },
}, },
utils.SimpleItem[mainMenu]{ utils.SimpleItem[mainMenu]{
ItemTitle: "All Mods", ItemTitle: "All Mods",
Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) { Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) {
newModel := NewMods(root, currentModel) newModel := mods.NewMods(root, currentModel)
return newModel, newModel.Init() return newModel, newModel.Init()
}, },
}, },
utils.SimpleItem[mainMenu]{ utils.SimpleItem[mainMenu]{
ItemTitle: "Installed Mods", ItemTitle: "Installed Mods",
Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) { Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) {
newModel := NewInstalledMods(root, currentModel) newModel := mods.NewInstalledMods(root, currentModel)
return newModel, newModel.Init() return newModel, newModel.Init()
}, },
}, },
@ -92,7 +97,7 @@ func NewMainMenu(root components.RootModel) tea.Model {
ItemTitle: "Apply Changes", ItemTitle: "Apply Changes",
Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) { Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) {
if err := root.GetGlobal().Save(); err != nil { if err := root.GetGlobal().Save(); err != nil {
log.Error().Err(err).Msg(ErrorFailedAddMod) log.Error().Err(err).Msg(errors.ErrorFailedAddMod)
errorComponent, cmd := components.NewErrorComponent(err.Error(), time.Second*5) errorComponent, cmd := components.NewErrorComponent(err.Error(), time.Second*5)
currentModel.error = errorComponent currentModel.error = errorComponent
return currentModel, cmd return currentModel, cmd
@ -106,7 +111,7 @@ func NewMainMenu(root components.RootModel) tea.Model {
ItemTitle: "Save", ItemTitle: "Save",
Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) { Activate: func(msg tea.Msg, currentModel mainMenu) (tea.Model, tea.Cmd) {
if err := root.GetGlobal().Save(); err != nil { if err := root.GetGlobal().Save(); err != nil {
log.Error().Err(err).Msg(ErrorFailedAddMod) log.Error().Err(err).Msg(errors.ErrorFailedAddMod)
errorComponent, cmd := components.NewErrorComponent(err.Error(), time.Second*5) errorComponent, cmd := components.NewErrorComponent(err.Error(), time.Second*5)
currentModel.error = errorComponent currentModel.error = errorComponent
return currentModel, cmd return currentModel, cmd
@ -127,7 +132,6 @@ func NewMainMenu(root components.RootModel) tea.Model {
model.list.SetFilteringEnabled(false) model.list.SetFilteringEnabled(false)
model.list.Title = "Main Menu" model.list.Title = "Main Menu"
model.list.Styles = utils.ListStyles model.list.Styles = utils.ListStyles
model.list.DisableQuitKeybindings()
return model return model
} }
@ -140,11 +144,11 @@ func (m mainMenu) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
switch keypress := msg.String(); keypress { switch keypress := msg.String(); keypress {
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case "q": case "q":
return m, tea.Quit return m, tea.Quit
case KeyEnter: case keys.KeyEnter:
i, ok := m.list.SelectedItem().(utils.SimpleItem[mainMenu]) i, ok := m.list.SelectedItem().(utils.SimpleItem[mainMenu])
if ok { if ok {
if i.Activate != nil { if i.Activate != nil {
@ -202,6 +206,6 @@ func (m mainMenu) View() string {
return lipgloss.JoinVertical(lipgloss.Left, header, err, m.list.View()) return lipgloss.JoinVertical(lipgloss.Left, header, err, m.list.View())
} }
m.list.SetSize(m.list.Width(), m.root.Size().Height-lipgloss.Height(header)) m.list.SetSize(m.list.Width(), m.root.Size().Height-lipgloss.Height(header)-1)
return lipgloss.JoinVertical(lipgloss.Left, header, m.list.View()) return lipgloss.JoinVertical(lipgloss.Left, header, m.list.View())
} }

View file

@ -1,11 +1,10 @@
package scenes package mods
import ( import (
"context" "context"
"sort" "sort"
"time" "time"
"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"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
@ -13,6 +12,7 @@ import (
"github.com/satisfactorymodding/ficsit-cli/ficsit" "github.com/satisfactorymodding/ficsit-cli/ficsit"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -43,19 +43,6 @@ func NewInstalledMods(root components.RootModel, parent tea.Model) tea.Model {
l.Styles = utils.ListStyles l.Styles = utils.ListStyles
l.SetSize(l.Width(), l.Height()) l.SetSize(l.Width(), l.Height())
l.KeyMap.Quit.SetHelp("q", "back") l.KeyMap.Quit.SetHelp("q", "back")
l.DisableQuitKeybindings()
l.AdditionalShortHelpKeys = func() []key.Binding {
return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")),
}
}
l.AdditionalFullHelpKeys = func() []key.Binding {
return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")),
}
}
m := &installedModsList{ m := &installedModsList{
root: root, root: root,
@ -160,9 +147,6 @@ func (m installedModsList) LoadModData() {
} }
func (m installedModsList) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m installedModsList) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// List enables its own keybindings when they were previously disabled
m.list.DisableQuitKeybindings()
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
if m.list.SettingFilter() { if m.list.SettingFilter() {
@ -172,7 +156,7 @@ func (m installedModsList) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} }
switch keypress := msg.String(); keypress { switch keypress := msg.String(); keypress {
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case "q": case "q":
if m.parent != nil { if m.parent != nil {
@ -180,7 +164,7 @@ func (m installedModsList) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m.parent, nil return m.parent, nil
} }
return m, tea.Quit return m, tea.Quit
case KeyEnter: case keys.KeyEnter:
i, ok := m.list.SelectedItem().(utils.SimpleItem[installedModsList]) i, ok := m.list.SelectedItem().(utils.SimpleItem[installedModsList])
if ok { if ok {
return m.processActivation(i, msg) return m.processActivation(i, msg)

View file

@ -1,15 +1,16 @@
package scenes package mods
import ( import (
"time" "time"
"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/list" "github.com/charmbracelet/bubbles/list"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/errors"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -70,8 +71,8 @@ func NewModMenu(root components.RootModel, parent tea.Model, mod utils.Mod) tea.
Activate: func(msg tea.Msg, currentModel modMenu) (tea.Model, tea.Cmd) { Activate: func(msg tea.Msg, currentModel modMenu) (tea.Model, tea.Cmd) {
err := root.GetCurrentProfile().AddMod(mod.Reference, ">=0.0.0") err := root.GetCurrentProfile().AddMod(mod.Reference, ">=0.0.0")
if err != nil { if err != nil {
log.Error().Err(err).Msg(ErrorFailedAddMod) log.Error().Err(err).Msg(errors.ErrorFailedAddMod)
cmd := currentModel.list.NewStatusMessage(ErrorFailedAddMod) cmd := currentModel.list.NewStatusMessage(errors.ErrorFailedAddMod)
return currentModel, cmd return currentModel, cmd
} }
return currentModel.parent, nil return currentModel.parent, nil
@ -101,21 +102,8 @@ func NewModMenu(root components.RootModel, parent tea.Model, mod utils.Mod) tea.
model.list.Title = mod.Name model.list.Title = mod.Name
model.list.Styles = utils.ListStyles model.list.Styles = utils.ListStyles
model.list.SetSize(model.list.Width(), model.list.Height()) model.list.SetSize(model.list.Width(), model.list.Height())
model.list.KeyMap.Quit.SetHelp("q", "back")
model.list.StatusMessageLifetime = time.Second * 3 model.list.StatusMessageLifetime = time.Second * 3
model.list.DisableQuitKeybindings() model.list.KeyMap.Quit.SetHelp("q", "back")
model.list.AdditionalShortHelpKeys = func() []key.Binding {
return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")),
}
}
model.list.AdditionalFullHelpKeys = func() []key.Binding {
return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")),
}
}
return model return model
} }
@ -128,7 +116,7 @@ func (m modMenu) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
switch keypress := msg.String(); keypress { switch keypress := msg.String(); keypress {
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case "q": case "q":
if m.parent != nil { if m.parent != nil {
@ -136,7 +124,7 @@ func (m modMenu) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m.parent, nil return m.parent, nil
} }
return m, tea.Quit return m, tea.Quit
case KeyEnter: case keys.KeyEnter:
i, ok := m.list.SelectedItem().(utils.SimpleItem[modMenu]) i, ok := m.list.SelectedItem().(utils.SimpleItem[modMenu])
if ok { if ok {
if i.Activate != nil { if i.Activate != nil {

View file

@ -1,4 +1,4 @@
package scenes package mods
import ( import (
"context" "context"
@ -19,6 +19,7 @@ import (
"github.com/satisfactorymodding/ficsit-cli/ficsit" "github.com/satisfactorymodding/ficsit-cli/ficsit"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -133,7 +134,7 @@ func (m modInfo) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
switch keypress := msg.String(); keypress { switch keypress := msg.String(); keypress {
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case "q": case "q":
if m.parent != nil { if m.parent != nil {

View file

@ -1,4 +1,4 @@
package scenes package mods
import ( import (
"time" "time"
@ -8,6 +8,7 @@ import (
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -46,11 +47,11 @@ func (m modSemver) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
switch keypress := msg.String(); keypress { switch keypress := msg.String(); keypress {
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case KeyEscape: case keys.KeyEscape:
return m.parent, nil return m.parent, nil
case KeyEnter: case keys.KeyEnter:
err := m.root.GetCurrentProfile().AddMod(m.mod.Reference, m.input.Value()) err := m.root.GetCurrentProfile().AddMod(m.mod.Reference, m.input.Value())
if err != nil { if err != nil {
errorComponent, cmd := components.NewErrorComponent(err.Error(), time.Second*5) errorComponent, cmd := components.NewErrorComponent(err.Error(), time.Second*5)

View file

@ -1,15 +1,16 @@
package scenes package mods
import ( import (
"time" "time"
"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/list" "github.com/charmbracelet/bubbles/list"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/errors"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -51,8 +52,8 @@ func NewModVersion(root components.RootModel, parent tea.Model, mod utils.Mod) t
Activate: func(msg tea.Msg, currentModel modVersionMenu) (tea.Model, tea.Cmd) { Activate: func(msg tea.Msg, currentModel modVersionMenu) (tea.Model, tea.Cmd) {
err := root.GetCurrentProfile().AddMod(mod.Reference, ">=0.0.0") err := root.GetCurrentProfile().AddMod(mod.Reference, ">=0.0.0")
if err != nil { if err != nil {
log.Error().Err(err).Msg(ErrorFailedAddMod) log.Error().Err(err).Msg(errors.ErrorFailedAddMod)
cmd := currentModel.list.NewStatusMessage(ErrorFailedAddMod) cmd := currentModel.list.NewStatusMessage(errors.ErrorFailedAddMod)
return currentModel, cmd return currentModel, cmd
} }
return currentModel.parent, nil return currentModel.parent, nil
@ -67,21 +68,8 @@ func NewModVersion(root components.RootModel, parent tea.Model, mod utils.Mod) t
model.list.Title = mod.Name model.list.Title = mod.Name
model.list.Styles = utils.ListStyles model.list.Styles = utils.ListStyles
model.list.SetSize(model.list.Width(), model.list.Height()) model.list.SetSize(model.list.Width(), model.list.Height())
model.list.KeyMap.Quit.SetHelp("q", "back")
model.list.StatusMessageLifetime = time.Second * 3 model.list.StatusMessageLifetime = time.Second * 3
model.list.DisableQuitKeybindings() model.list.KeyMap.Quit.SetHelp("q", "back")
model.list.AdditionalShortHelpKeys = func() []key.Binding {
return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")),
}
}
model.list.AdditionalFullHelpKeys = func() []key.Binding {
return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")),
}
}
return model return model
} }
@ -94,7 +82,7 @@ func (m modVersionMenu) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
switch keypress := msg.String(); keypress { switch keypress := msg.String(); keypress {
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case "q": case "q":
if m.parent != nil { if m.parent != nil {
@ -102,7 +90,7 @@ func (m modVersionMenu) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m.parent, nil return m.parent, nil
} }
return m, tea.Quit return m, tea.Quit
case KeyEnter: case keys.KeyEnter:
i, ok := m.list.SelectedItem().(utils.SimpleItem[modVersionMenu]) i, ok := m.list.SelectedItem().(utils.SimpleItem[modVersionMenu])
if ok { if ok {
if i.Activate != nil { if i.Activate != nil {

View file

@ -1,4 +1,4 @@
package scenes package mods
import ( import (
"context" "context"
@ -17,6 +17,7 @@ import (
"github.com/satisfactorymodding/ficsit-cli/cli" "github.com/satisfactorymodding/ficsit-cli/cli"
"github.com/satisfactorymodding/ficsit-cli/ficsit" "github.com/satisfactorymodding/ficsit-cli/ficsit"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -36,6 +37,8 @@ type listUpdate struct {
Done bool Done bool
} }
// type keys
type modsList struct { type modsList struct {
list list.Model list list.Model
sortFieldList list.Model sortFieldList list.Model
@ -52,7 +55,7 @@ type modsList struct {
} }
func NewMods(root components.RootModel, parent tea.Model) tea.Model { func NewMods(root components.RootModel, parent tea.Model) tea.Model {
l := list.New([]list.Item{}, ModsListDelegate{ l := list.New([]list.Item{}, ListDelegate{
ItemDelegate: utils.NewItemDelegate(), ItemDelegate: utils.NewItemDelegate(),
Context: root.GetGlobal(), Context: root.GetGlobal(),
}, root.Size().Width, root.Size().Height-root.Height()) }, root.Size().Width, root.Size().Height-root.Height())
@ -64,23 +67,14 @@ func NewMods(root components.RootModel, parent tea.Model) tea.Model {
l.Styles = utils.ListStyles l.Styles = utils.ListStyles
l.SetSize(l.Width(), l.Height()) l.SetSize(l.Width(), l.Height())
l.KeyMap.Quit.SetHelp("q", "back") l.KeyMap.Quit.SetHelp("q", "back")
l.DisableQuitKeybindings()
l.AdditionalShortHelpKeys = func() []key.Binding { l.AdditionalShortHelpKeys = func() []key.Binding {
return []key.Binding{ return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")), key.NewBinding(key.WithKeys("s"), key.WithHelp("s", "sort")),
key.NewBinding(key.WithHelp("s", "sort")), key.NewBinding(key.WithKeys("o"), key.WithHelp("o", "order")),
key.NewBinding(key.WithHelp("o", "order")),
}
}
l.AdditionalFullHelpKeys = func() []key.Binding {
return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")),
key.NewBinding(key.WithHelp("s", "sort")),
key.NewBinding(key.WithHelp("o", "order")),
} }
} }
l.AdditionalFullHelpKeys = l.AdditionalShortHelpKeys
sortFieldList := list.New([]list.Item{ sortFieldList := list.New([]list.Item{
utils.SimpleItemExtra[modsList, ficsit.ModsModsGetModsModsMod]{ utils.SimpleItemExtra[modsList, ficsit.ModsModsGetModsModsMod]{
@ -167,8 +161,6 @@ func NewMods(root components.RootModel, parent tea.Model) tea.Model {
sortFieldList.Title = modsTitle sortFieldList.Title = modsTitle
sortFieldList.Styles = utils.ListStyles sortFieldList.Styles = utils.ListStyles
sortFieldList.SetSize(l.Width(), l.Height()) sortFieldList.SetSize(l.Width(), l.Height())
sortFieldList.KeyMap.Quit.SetHelp("q", "back")
sortFieldList.DisableQuitKeybindings()
sortOrderList := list.New([]list.Item{ sortOrderList := list.New([]list.Item{
utils.SimpleItemExtra[modsList, ficsit.ModsModsGetModsModsMod]{ utils.SimpleItemExtra[modsList, ficsit.ModsModsGetModsModsMod]{
@ -200,8 +192,6 @@ func NewMods(root components.RootModel, parent tea.Model) tea.Model {
sortOrderList.Title = modsTitle sortOrderList.Title = modsTitle
sortOrderList.Styles = utils.ListStyles sortOrderList.Styles = utils.ListStyles
sortOrderList.SetSize(l.Width(), l.Height()) sortOrderList.SetSize(l.Width(), l.Height())
sortOrderList.KeyMap.Quit.SetHelp("q", "back")
sortOrderList.DisableQuitKeybindings()
m := &modsList{ m := &modsList{
root: root, root: root,
@ -281,8 +271,7 @@ func (m modsList) Init() tea.Cmd {
} }
func (m modsList) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m modsList) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// List enables its own keybindings when they were previously disabled m.list.KeyMap.Quit.SetHelp("q", "back")
m.list.DisableQuitKeybindings()
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
@ -299,7 +288,7 @@ func (m modsList) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case "o": case "o":
m.showSortOrderList = !m.showSortOrderList m.showSortOrderList = !m.showSortOrderList
return m, nil return m, nil
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case "q": case "q":
if m.showSortFieldList { if m.showSortFieldList {
@ -317,7 +306,7 @@ func (m modsList) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m.parent, nil return m.parent, nil
} }
return m, tea.Quit return m, tea.Quit
case KeyEnter: case keys.KeyEnter:
if m.showSortFieldList { if m.showSortFieldList {
m.showSortFieldList = false m.showSortFieldList = false
i, ok := m.sortFieldList.SelectedItem().(utils.SimpleItemExtra[modsList, ficsit.ModsModsGetModsModsMod]) i, ok := m.sortFieldList.SelectedItem().(utils.SimpleItemExtra[modsList, ficsit.ModsModsGetModsModsMod])
@ -473,12 +462,12 @@ func ascDesc(order sortOrder, result bool) bool {
return !result return !result
} }
type ModsListDelegate struct { type ListDelegate struct {
list.ItemDelegate list.ItemDelegate
Context *cli.GlobalContext Context *cli.GlobalContext
} }
func (c ModsListDelegate) Render(w io.Writer, m list.Model, index int, item list.Item) { func (c ListDelegate) Render(w io.Writer, m list.Model, index int, item list.Item) {
realItem := item.(utils.SimpleItemExtra[modsList, ficsit.ModsModsGetModsModsMod]) realItem := item.(utils.SimpleItemExtra[modsList, ficsit.ModsModsGetModsModsMod])
realDelegate := c.ItemDelegate.(list.DefaultDelegate) realDelegate := c.ItemDelegate.(list.DefaultDelegate)

View file

@ -1,11 +1,10 @@
package scenes package mods
import ( import (
"context" "context"
"fmt" "fmt"
"time" "time"
"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"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
@ -13,6 +12,7 @@ import (
"github.com/satisfactorymodding/ficsit-cli/ficsit" "github.com/satisfactorymodding/ficsit-cli/ficsit"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -36,19 +36,6 @@ func NewModVersionList(root components.RootModel, parent tea.Model, mod utils.Mo
l.Styles = utils.ListStyles l.Styles = utils.ListStyles
l.SetSize(l.Width(), l.Height()) l.SetSize(l.Width(), l.Height())
l.KeyMap.Quit.SetHelp("q", "back") l.KeyMap.Quit.SetHelp("q", "back")
l.DisableQuitKeybindings()
l.AdditionalShortHelpKeys = func() []key.Binding {
return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")),
}
}
l.AdditionalFullHelpKeys = func() []key.Binding {
return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")),
}
}
m := &selectModVersionList{ m := &selectModVersionList{
root: root, root: root,
@ -115,7 +102,7 @@ func (m selectModVersionList) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
switch keypress := msg.String(); keypress { switch keypress := msg.String(); keypress {
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case "q": case "q":
if m.parent != nil { if m.parent != nil {
@ -123,7 +110,7 @@ func (m selectModVersionList) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m.parent, nil return m.parent, nil
} }
return m, tea.Quit return m, tea.Quit
case KeyEnter: case keys.KeyEnter:
i, ok := m.list.SelectedItem().(utils.SimpleItem[selectModVersionList]) i, ok := m.list.SelectedItem().(utils.SimpleItem[selectModVersionList])
if ok { if ok {
if i.Activate != nil { if i.Activate != nil {

View file

@ -1,4 +1,4 @@
package scenes package profile
import ( import (
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
@ -15,15 +15,3 @@ type updateProfileNames struct{}
func updateProfileNamesCmd() tea.Msg { func updateProfileNamesCmd() tea.Msg {
return updateProfileNames{} return updateProfileNames{}
} }
type updateInstallationList struct{}
func updateInstallationListCmd() tea.Msg {
return updateInstallationList{}
}
type updateInstallationNames struct{}
func updateInstallationNamesCmd() tea.Msg {
return updateInstallationNames{}
}

View file

@ -1,24 +1,45 @@
package scenes package profile
import ( import (
"time" "time"
"github.com/charmbracelet/bubbles/help"
"github.com/charmbracelet/bubbles/key"
"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/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
var _ tea.Model = (*newProfile)(nil) var _ tea.Model = (*newProfile)(nil)
type keyMap struct {
Back key.Binding
Quit key.Binding
Enter key.Binding
}
func (k keyMap) ShortHelp() []key.Binding {
return []key.Binding{k.Enter, k.Back}
}
func (k keyMap) FullHelp() [][]key.Binding {
return [][]key.Binding{
{k.Enter, k.Back},
}
}
type newProfile struct { type newProfile struct {
input textinput.Model input textinput.Model
root components.RootModel root components.RootModel
parent tea.Model parent tea.Model
error *components.ErrorComponent error *components.ErrorComponent
title string title string
help help.Model
keys keyMap
} }
func NewNewProfile(root components.RootModel, parent tea.Model) tea.Model { func NewNewProfile(root components.RootModel, parent tea.Model) tea.Model {
@ -27,6 +48,20 @@ func NewNewProfile(root components.RootModel, parent tea.Model) tea.Model {
parent: parent, parent: parent,
input: textinput.New(), input: textinput.New(),
title: utils.NonListTitleStyle.Render("New Profile"), title: utils.NonListTitleStyle.Render("New Profile"),
help: help.New(),
keys: keyMap{
Back: key.NewBinding(
key.WithKeys(keys.KeyEscape, keys.KeyControlC),
key.WithHelp(keys.KeyEscape, "back"),
),
Enter: key.NewBinding(
key.WithKeys(keys.KeyEnter),
key.WithHelp(keys.KeyEnter, "create"),
),
Quit: key.NewBinding(
key.WithKeys(keys.KeyControlC),
),
},
} }
model.input.Focus() model.input.Focus()
@ -42,12 +77,12 @@ func (m newProfile) Init() tea.Cmd {
func (m newProfile) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m newProfile) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
switch keypress := msg.String(); keypress { switch {
case KeyControlC: case key.Matches(msg, m.keys.Quit):
return m, tea.Quit return m, tea.Quit
case KeyEscape: case key.Matches(msg, m.keys.Back):
return m.parent, nil return m.parent, nil
case KeyEnter: case key.Matches(msg, m.keys.Enter):
if _, err := m.root.GetGlobal().Profiles.AddProfile(m.input.Value()); err != nil { if _, err := m.root.GetGlobal().Profiles.AddProfile(m.input.Value()); err != nil {
errorComponent, cmd := components.NewErrorComponent(err.Error(), time.Second*5) errorComponent, cmd := components.NewErrorComponent(err.Error(), time.Second*5)
m.error = errorComponent m.error = errorComponent
@ -74,7 +109,8 @@ func (m newProfile) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} }
func (m newProfile) View() string { func (m newProfile) View() string {
inputView := lipgloss.NewStyle().Padding(1, 2).Render(m.input.View()) style := lipgloss.NewStyle().Padding(1, 2)
inputView := style.Render(m.input.View())
if m.error != nil { if m.error != nil {
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)
@ -87,5 +123,5 @@ func (m newProfile) View() string {
Margin(0, 0, 0, 2). Margin(0, 0, 0, 2).
Render("Enter the name of the profile") Render("Enter the name of the profile")
return lipgloss.JoinVertical(lipgloss.Left, m.root.View(), m.title, inputView, infoBox) return lipgloss.JoinVertical(lipgloss.Left, m.root.View(), m.title, inputView, infoBox, style.Render(m.help.View(m.keys)))
} }

View file

@ -1,16 +1,16 @@
package scenes package profile
import ( import (
"fmt" "fmt"
"time" "time"
"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/list" "github.com/charmbracelet/bubbles/list"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
"github.com/satisfactorymodding/ficsit-cli/cli" "github.com/satisfactorymodding/ficsit-cli/cli"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -78,19 +78,7 @@ func NewProfile(root components.RootModel, parent tea.Model, profileData *cli.Pr
model.list.Styles = utils.ListStyles model.list.Styles = utils.ListStyles
model.list.SetSize(model.list.Width(), model.list.Height()) model.list.SetSize(model.list.Width(), model.list.Height())
model.list.StatusMessageLifetime = time.Second * 3 model.list.StatusMessageLifetime = time.Second * 3
model.list.DisableQuitKeybindings() model.list.KeyMap.Quit.SetHelp("q", "back")
model.list.AdditionalShortHelpKeys = func() []key.Binding {
return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")),
}
}
model.list.AdditionalFullHelpKeys = func() []key.Binding {
return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")),
}
}
return model return model
} }
@ -103,7 +91,7 @@ func (m profile) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
switch keypress := msg.String(); keypress { switch keypress := msg.String(); keypress {
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case "q": case "q":
if m.parent != nil { if m.parent != nil {
@ -116,7 +104,7 @@ func (m profile) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m.parent, nil return m.parent, nil
} }
return m, nil return m, nil
case KeyEnter: case keys.KeyEnter:
i, ok := m.list.SelectedItem().(utils.SimpleItem[profile]) i, ok := m.list.SelectedItem().(utils.SimpleItem[profile])
if ok { if ok {
if i.Activate != nil { if i.Activate != nil {

View file

@ -1,4 +1,4 @@
package scenes package profile
import ( import (
"github.com/charmbracelet/bubbles/key" "github.com/charmbracelet/bubbles/key"
@ -8,6 +8,7 @@ import (
"github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -28,12 +29,10 @@ func NewProfiles(root components.RootModel, parent tea.Model) tea.Model {
l.Styles = utils.ListStyles l.Styles = utils.ListStyles
l.SetSize(l.Width(), l.Height()) l.SetSize(l.Width(), l.Height())
l.KeyMap.Quit.SetHelp("q", "back") l.KeyMap.Quit.SetHelp("q", "back")
l.DisableQuitKeybindings()
l.AdditionalShortHelpKeys = func() []key.Binding { l.AdditionalShortHelpKeys = func() []key.Binding {
return []key.Binding{ return []key.Binding{
key.NewBinding(key.WithHelp("q", "back")), key.NewBinding(key.WithKeys("n"), key.WithHelp("n", "new profile")),
key.NewBinding(key.WithHelp("n", "new profile")),
} }
} }
@ -51,9 +50,6 @@ func (m profiles) Init() tea.Cmd {
} }
func (m profiles) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m profiles) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// List enables its own keybindings when they were previously disabled
m.list.DisableQuitKeybindings()
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
if m.list.SettingFilter() { if m.list.SettingFilter() {
@ -66,7 +62,7 @@ func (m profiles) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case "n": case "n":
newModel := NewNewProfile(m.root, m) newModel := NewNewProfile(m.root, m)
return newModel, newModel.Init() return newModel, newModel.Init()
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case "q": case "q":
if m.parent != nil { if m.parent != nil {
@ -74,7 +70,7 @@ func (m profiles) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m.parent, nil return m.parent, nil
} }
return m, tea.Quit return m, tea.Quit
case KeyEnter: case keys.KeyEnter:
i, ok := m.list.SelectedItem().(utils.SimpleItem[profiles]) i, ok := m.list.SelectedItem().(utils.SimpleItem[profiles])
if ok { if ok {
if i.Activate != nil { if i.Activate != nil {

View file

@ -1,4 +1,4 @@
package scenes package profile
import ( import (
"fmt" "fmt"
@ -10,6 +10,7 @@ import (
"github.com/satisfactorymodding/ficsit-cli/cli" "github.com/satisfactorymodding/ficsit-cli/cli"
"github.com/satisfactorymodding/ficsit-cli/tea/components" "github.com/satisfactorymodding/ficsit-cli/tea/components"
"github.com/satisfactorymodding/ficsit-cli/tea/scenes/keys"
"github.com/satisfactorymodding/ficsit-cli/tea/utils" "github.com/satisfactorymodding/ficsit-cli/tea/utils"
) )
@ -48,11 +49,11 @@ func (m renameProfile) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.KeyMsg: case tea.KeyMsg:
switch keypress := msg.String(); keypress { switch keypress := msg.String(); keypress {
case KeyControlC: case keys.KeyControlC:
return m, tea.Quit return m, tea.Quit
case KeyEscape: case keys.KeyEscape:
return m.parent, nil return m.parent, nil
case KeyEnter: case keys.KeyEnter:
if err := m.root.GetGlobal().Profiles.RenameProfile(m.root.GetGlobal(), m.oldName, m.input.Value()); err != nil { if err := m.root.GetGlobal().Profiles.RenameProfile(m.root.GetGlobal(), m.oldName, m.input.Value()); err != nil {
errorComponent, cmd := components.NewErrorComponent(err.Error(), time.Second*5) errorComponent, cmd := components.NewErrorComponent(err.Error(), time.Second*5)
m.error = errorComponent m.error = errorComponent