mirror of
https://github.com/RWejlgaard/org.git
synced 2026-05-06 04:34:45 +00:00
723 lines
19 KiB
Go
723 lines
19 KiB
Go
package ui
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/charmbracelet/bubbles/key"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/charmbracelet/lipgloss"
|
|
)
|
|
|
|
// settingsSection represents different sections in the settings view
|
|
type settingsSection int
|
|
|
|
const (
|
|
settingsSectionTags settingsSection = iota
|
|
settingsSectionStates
|
|
settingsSectionKeybindings
|
|
)
|
|
|
|
// settingsState tracks the state of the settings editor
|
|
type settingsState struct {
|
|
section settingsSection
|
|
cursor int
|
|
scroll int
|
|
editing bool
|
|
editingField string
|
|
editingValue string
|
|
modified bool
|
|
}
|
|
|
|
// initSettings initializes the settings state
|
|
func (m *uiModel) initSettings() {
|
|
m.settingsCursor = 0
|
|
m.settingsScroll = 0
|
|
}
|
|
|
|
// updateSettings handles updates in settings mode
|
|
func (m *uiModel) updateSettings(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
switch msg := msg.(type) {
|
|
case tea.KeyMsg:
|
|
// If editing, handle text input
|
|
if m.textinput.Focused() {
|
|
switch {
|
|
case key.Matches(msg, m.keys.Quit):
|
|
m.textinput.Blur()
|
|
return m, nil
|
|
case msg.Type == tea.KeyEnter:
|
|
// Save the edited value
|
|
m.saveSettingsEdit()
|
|
m.textinput.Blur()
|
|
return m, nil
|
|
default:
|
|
var cmd tea.Cmd
|
|
m.textinput, cmd = m.textinput.Update(msg)
|
|
return m, cmd
|
|
}
|
|
}
|
|
|
|
// Navigation and actions
|
|
switch {
|
|
case key.Matches(msg, m.keys.Quit), key.Matches(msg, m.keys.Settings):
|
|
// Exit settings
|
|
m.mode = modeList
|
|
return m, nil
|
|
|
|
case key.Matches(msg, m.keys.Up):
|
|
if m.settingsCursor > 0 {
|
|
m.settingsCursor--
|
|
}
|
|
|
|
case key.Matches(msg, m.keys.Down):
|
|
maxCursor := m.getSettingsItemCount() - 1
|
|
if m.settingsCursor < maxCursor {
|
|
m.settingsCursor++
|
|
}
|
|
|
|
case key.Matches(msg, m.keys.ShiftUp):
|
|
// Move item up
|
|
m.moveSettingsItemUp()
|
|
|
|
case key.Matches(msg, m.keys.ShiftDown):
|
|
// Move item down
|
|
m.moveSettingsItemDown()
|
|
|
|
case key.Matches(msg, m.keys.Left):
|
|
// Previous section
|
|
if m.settingsSection > settingsSectionTags {
|
|
m.settingsSection--
|
|
m.settingsCursor = 0
|
|
m.settingsScroll = 0
|
|
}
|
|
|
|
case key.Matches(msg, m.keys.Right):
|
|
// Next section
|
|
if m.settingsSection < settingsSectionKeybindings {
|
|
m.settingsSection++
|
|
m.settingsCursor = 0
|
|
m.settingsScroll = 0
|
|
}
|
|
|
|
case key.Matches(msg, m.keys.EditNotes):
|
|
// Enter edit mode
|
|
m.startSettingsEdit()
|
|
|
|
case key.Matches(msg, m.keys.Delete):
|
|
// Delete tag
|
|
m.deleteSettingsItem()
|
|
|
|
case key.Matches(msg, m.keys.Capture):
|
|
// Add new tag or state
|
|
switch m.settingsSection {
|
|
case settingsSectionTags:
|
|
m.addNewTag()
|
|
case settingsSectionStates:
|
|
m.addNewState()
|
|
case settingsSectionKeybindings:
|
|
// Cannot add keybindings yet
|
|
}
|
|
|
|
case key.Matches(msg, m.keys.Save):
|
|
// Save config to disk
|
|
if err := m.config.Save(); err != nil {
|
|
m.setStatus(fmt.Sprintf("Error saving config: %v", err))
|
|
} else {
|
|
m.setStatus("Configuration saved!")
|
|
// Reload keybindings and styles
|
|
m.keys = newKeyMapFromConfig(m.config)
|
|
m.styles = newStyleMapFromConfig(m.config)
|
|
}
|
|
}
|
|
}
|
|
|
|
return m, nil
|
|
}
|
|
|
|
// getSettingsItemCount returns the number of items in the current settings view
|
|
func (m *uiModel) getSettingsItemCount() int {
|
|
switch m.settingsSection {
|
|
case settingsSectionTags:
|
|
return len(m.config.Tags.Tags) + 1 // +1 for "Add new tag" option
|
|
case settingsSectionStates:
|
|
return len(m.config.States.States) + 1 // +1 for "Add new state" option
|
|
case settingsSectionKeybindings:
|
|
return len(m.config.GetAllKeybindings())
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
// startSettingsEdit starts editing a settings item
|
|
func (m *uiModel) startSettingsEdit() {
|
|
switch m.settingsSection {
|
|
case settingsSectionTags:
|
|
if m.settingsCursor >= len(m.config.Tags.Tags) {
|
|
return
|
|
}
|
|
tag := m.config.Tags.Tags[m.settingsCursor]
|
|
m.textinput.SetValue(tag.Name + "," + tag.Color)
|
|
m.textinput.Placeholder = "name,color (e.g., work,99)"
|
|
m.textinput.Focus()
|
|
|
|
case settingsSectionStates:
|
|
if m.settingsCursor >= len(m.config.States.States) {
|
|
return
|
|
}
|
|
state := m.config.States.States[m.settingsCursor]
|
|
m.textinput.SetValue(state.Name + "," + state.Color)
|
|
m.textinput.Placeholder = "name,color (e.g., TODO,202)"
|
|
m.textinput.Focus()
|
|
|
|
case settingsSectionKeybindings:
|
|
// Edit keybinding
|
|
keybindings := m.config.GetAllKeybindings()
|
|
|
|
// Convert to sorted slice
|
|
type kbPair struct {
|
|
action string
|
|
keys []string
|
|
}
|
|
var kbList []kbPair
|
|
for action, keys := range keybindings {
|
|
kbList = append(kbList, kbPair{action, keys})
|
|
}
|
|
|
|
// Sort alphabetically
|
|
for i := 0; i < len(kbList)-1; i++ {
|
|
for j := i + 1; j < len(kbList); j++ {
|
|
if kbList[i].action > kbList[j].action {
|
|
kbList[i], kbList[j] = kbList[j], kbList[i]
|
|
}
|
|
}
|
|
}
|
|
|
|
if m.settingsCursor >= len(kbList) {
|
|
return
|
|
}
|
|
|
|
kb := kbList[m.settingsCursor]
|
|
m.textinput.SetValue(strings.Join(kb.keys, ","))
|
|
m.textinput.Placeholder = "Enter keys separated by commas (e.g., up,k)"
|
|
m.textinput.Focus()
|
|
}
|
|
}
|
|
|
|
// saveSettingsEdit saves the edited value and auto-saves to disk
|
|
func (m *uiModel) saveSettingsEdit() {
|
|
switch m.settingsSection {
|
|
case settingsSectionTags:
|
|
if m.settingsCursor >= len(m.config.Tags.Tags) {
|
|
return
|
|
}
|
|
// Parse "name,color" format
|
|
parts := strings.Split(m.textinput.Value(), ",")
|
|
if len(parts) >= 2 {
|
|
tag := &m.config.Tags.Tags[m.settingsCursor]
|
|
tag.Name = strings.TrimSpace(parts[0])
|
|
tag.Color = strings.TrimSpace(parts[1])
|
|
m.setStatus(fmt.Sprintf("Updated tag '%s' (saved)", tag.Name))
|
|
} else {
|
|
m.setStatus("Invalid format. Use: name,color")
|
|
return
|
|
}
|
|
|
|
case settingsSectionStates:
|
|
if m.settingsCursor >= len(m.config.States.States) {
|
|
return
|
|
}
|
|
// Parse "name,color" format
|
|
parts := strings.Split(m.textinput.Value(), ",")
|
|
if len(parts) >= 2 {
|
|
state := &m.config.States.States[m.settingsCursor]
|
|
state.Name = strings.TrimSpace(parts[0])
|
|
state.Color = strings.TrimSpace(parts[1])
|
|
m.setStatus(fmt.Sprintf("Updated state '%s' (saved)", state.Name))
|
|
} else {
|
|
m.setStatus("Invalid format. Use: name,color")
|
|
return
|
|
}
|
|
|
|
case settingsSectionKeybindings:
|
|
// Save keybinding
|
|
keybindings := m.config.GetAllKeybindings()
|
|
|
|
// Convert to sorted slice
|
|
type kbPair struct {
|
|
action string
|
|
keys []string
|
|
}
|
|
var kbList []kbPair
|
|
for action, keys := range keybindings {
|
|
kbList = append(kbList, kbPair{action, keys})
|
|
}
|
|
|
|
// Sort alphabetically
|
|
for i := 0; i < len(kbList)-1; i++ {
|
|
for j := i + 1; j < len(kbList); j++ {
|
|
if kbList[i].action > kbList[j].action {
|
|
kbList[i], kbList[j] = kbList[j], kbList[i]
|
|
}
|
|
}
|
|
}
|
|
|
|
if m.settingsCursor >= len(kbList) {
|
|
return
|
|
}
|
|
|
|
kb := kbList[m.settingsCursor]
|
|
// Parse comma-separated keys
|
|
keysStr := m.textinput.Value()
|
|
var newKeys []string
|
|
for _, k := range strings.Split(keysStr, ",") {
|
|
k = strings.TrimSpace(k)
|
|
if k != "" {
|
|
newKeys = append(newKeys, k)
|
|
}
|
|
}
|
|
|
|
if len(newKeys) > 0 {
|
|
if err := m.config.UpdateKeybinding(kb.action, newKeys); err != nil {
|
|
m.setStatus(fmt.Sprintf("Error updating keybinding: %v", err))
|
|
return
|
|
} else {
|
|
m.setStatus(fmt.Sprintf("Updated keybinding for '%s' (saved)", kb.action))
|
|
}
|
|
}
|
|
}
|
|
|
|
// Auto-save configuration to disk
|
|
if err := m.config.Save(); err != nil {
|
|
m.setStatus(fmt.Sprintf("Error auto-saving config: %v", err))
|
|
} else {
|
|
// Reload keybindings and styles from updated config
|
|
m.keys = newKeyMapFromConfig(m.config)
|
|
m.styles = newStyleMapFromConfig(m.config)
|
|
}
|
|
}
|
|
|
|
// deleteSettingsItem deletes the current settings item and auto-saves
|
|
func (m *uiModel) deleteSettingsItem() {
|
|
switch m.settingsSection {
|
|
case settingsSectionTags:
|
|
if m.settingsCursor >= len(m.config.Tags.Tags) {
|
|
return
|
|
}
|
|
tag := m.config.Tags.Tags[m.settingsCursor]
|
|
m.config.RemoveTag(tag.Name)
|
|
m.setStatus(fmt.Sprintf("Deleted tag '%s' (saved)", tag.Name))
|
|
|
|
// Adjust cursor if needed
|
|
if m.settingsCursor >= len(m.config.Tags.Tags) {
|
|
m.settingsCursor = len(m.config.Tags.Tags) - 1
|
|
if m.settingsCursor < 0 {
|
|
m.settingsCursor = 0
|
|
}
|
|
}
|
|
|
|
case settingsSectionStates:
|
|
if m.settingsCursor >= len(m.config.States.States) {
|
|
return
|
|
}
|
|
state := m.config.States.States[m.settingsCursor]
|
|
m.config.RemoveState(state.Name)
|
|
m.setStatus(fmt.Sprintf("Deleted state '%s' (saved)", state.Name))
|
|
|
|
// Adjust cursor if needed
|
|
if m.settingsCursor >= len(m.config.States.States) {
|
|
m.settingsCursor = len(m.config.States.States) - 1
|
|
if m.settingsCursor < 0 {
|
|
m.settingsCursor = 0
|
|
}
|
|
}
|
|
|
|
case settingsSectionKeybindings:
|
|
// Keybindings cannot be deleted
|
|
return
|
|
}
|
|
|
|
// Auto-save configuration to disk
|
|
if err := m.config.Save(); err != nil {
|
|
m.setStatus(fmt.Sprintf("Error auto-saving config: %v", err))
|
|
}
|
|
}
|
|
|
|
// addNewTag adds a new tag
|
|
func (m *uiModel) addNewTag() {
|
|
m.textinput.SetValue("")
|
|
m.textinput.Placeholder = "Enter tag name"
|
|
m.textinput.Focus()
|
|
m.textinput.Blur() // Will be refocused when user types
|
|
|
|
// Prompt for tag name first, then color
|
|
m.mode = modeSettingsAddTag
|
|
}
|
|
|
|
// addNewState adds a new state
|
|
func (m *uiModel) addNewState() {
|
|
m.textinput.SetValue("")
|
|
m.textinput.Placeholder = "Enter state name"
|
|
m.textinput.Focus()
|
|
m.textinput.Blur() // Will be refocused when user types
|
|
|
|
// Prompt for state name first, then color
|
|
m.mode = modeSettingsAddState
|
|
}
|
|
|
|
// viewSettings renders the settings view
|
|
func (m *uiModel) viewSettings() string {
|
|
var content strings.Builder
|
|
|
|
// Title
|
|
title := m.styles.titleStyle.Render("⚙ Settings")
|
|
content.WriteString(title + "\n\n")
|
|
|
|
// Tab selector
|
|
tabStyle := lipgloss.NewStyle().Padding(0, 2)
|
|
activeTabStyle := lipgloss.NewStyle().Padding(0, 2).Bold(true).Foreground(lipgloss.Color(m.config.Colors.Title))
|
|
|
|
tabs := ""
|
|
if m.settingsSection == settingsSectionTags {
|
|
tabs += activeTabStyle.Render("[Tags]")
|
|
} else {
|
|
tabs += tabStyle.Render("Tags")
|
|
}
|
|
tabs += " "
|
|
if m.settingsSection == settingsSectionStates {
|
|
tabs += activeTabStyle.Render("[States]")
|
|
} else {
|
|
tabs += tabStyle.Render("States")
|
|
}
|
|
tabs += " "
|
|
if m.settingsSection == settingsSectionKeybindings {
|
|
tabs += activeTabStyle.Render("[Keybindings]")
|
|
} else {
|
|
tabs += tabStyle.Render("Keybindings")
|
|
}
|
|
content.WriteString(tabs + "\n\n")
|
|
|
|
// Instructions
|
|
var instructions string
|
|
switch m.settingsSection {
|
|
case settingsSectionTags:
|
|
instructions = "←/→: Switch tabs • ↑/↓: Navigate • Enter: Edit • D: Delete • c: Add new tag • ctrl+s: Save • q/,: Exit"
|
|
case settingsSectionStates:
|
|
instructions = "←/→: Switch tabs • ↑/↓: Navigate • shift+↑/↓: Reorder • Enter: Edit • D: Delete • c: Add new state • ctrl+s: Save • q/,: Exit"
|
|
case settingsSectionKeybindings:
|
|
instructions = "←/→: Switch tabs • ↑/↓: Navigate • Enter: Edit keybinding • ctrl+s: Save • q/,: Exit"
|
|
}
|
|
content.WriteString(m.styles.statusStyle.Render(instructions) + "\n\n")
|
|
|
|
// Render the appropriate section
|
|
switch m.settingsSection {
|
|
case settingsSectionTags:
|
|
content.WriteString(m.viewSettingsTags())
|
|
case settingsSectionStates:
|
|
content.WriteString(m.viewSettingsStates())
|
|
case settingsSectionKeybindings:
|
|
content.WriteString(m.viewSettingsKeybindings())
|
|
}
|
|
|
|
// If editing, show input
|
|
if m.textinput.Focused() {
|
|
content.WriteString("\n")
|
|
content.WriteString(m.textinput.View() + "\n")
|
|
content.WriteString(m.styles.statusStyle.Render("Enter: Save • ESC/q: Cancel") + "\n")
|
|
}
|
|
|
|
return content.String()
|
|
}
|
|
|
|
// viewSettingsTags renders the tags section
|
|
func (m *uiModel) viewSettingsTags() string {
|
|
var content strings.Builder
|
|
|
|
for i, tag := range m.config.Tags.Tags {
|
|
line := ""
|
|
|
|
// Cursor
|
|
if i == m.settingsCursor && !m.textinput.Focused() {
|
|
line += "▶ "
|
|
} else {
|
|
line += " "
|
|
}
|
|
|
|
// Tag name with its color
|
|
tagStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(tag.Color))
|
|
line += fmt.Sprintf(":%s: ", tag.Name)
|
|
line += tagStyle.Render(fmt.Sprintf("(color: %s)", tag.Color))
|
|
|
|
content.WriteString(line + "\n")
|
|
}
|
|
|
|
// Add new tag option
|
|
if m.settingsCursor == len(m.config.Tags.Tags) && !m.textinput.Focused() {
|
|
content.WriteString("▶ ")
|
|
} else {
|
|
content.WriteString(" ")
|
|
}
|
|
content.WriteString(m.styles.statusStyle.Render("+ Add new tag (press 'c')") + "\n")
|
|
|
|
return content.String()
|
|
}
|
|
|
|
// viewSettingsStates renders the states section
|
|
func (m *uiModel) viewSettingsStates() string {
|
|
var content strings.Builder
|
|
|
|
for i, state := range m.config.States.States {
|
|
line := ""
|
|
|
|
// Cursor
|
|
if i == m.settingsCursor && !m.textinput.Focused() {
|
|
line += "▶ "
|
|
} else {
|
|
line += " "
|
|
}
|
|
|
|
// State name with its color
|
|
stateStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(state.Color))
|
|
line += stateStyle.Render(fmt.Sprintf("%s", state.Name))
|
|
line += fmt.Sprintf(" (color: %s)", state.Color)
|
|
|
|
content.WriteString(line + "\n")
|
|
}
|
|
|
|
// Add new state option
|
|
if m.settingsCursor == len(m.config.States.States) && !m.textinput.Focused() {
|
|
content.WriteString("▶ ")
|
|
} else {
|
|
content.WriteString(" ")
|
|
}
|
|
content.WriteString(m.styles.statusStyle.Render("+ Add new state (press 'c')") + "\n")
|
|
|
|
return content.String()
|
|
}
|
|
|
|
// viewSettingsKeybindings renders the keybindings section
|
|
func (m *uiModel) viewSettingsKeybindings() string {
|
|
var content strings.Builder
|
|
|
|
// Get all keybindings
|
|
keybindings := m.config.GetAllKeybindings()
|
|
|
|
// Convert to sorted slice for consistent display
|
|
type kbPair struct {
|
|
action string
|
|
keys []string
|
|
}
|
|
var kbList []kbPair
|
|
for action, keys := range keybindings {
|
|
kbList = append(kbList, kbPair{action, keys})
|
|
}
|
|
|
|
// Simple alphabetical sort by action name
|
|
for i := 0; i < len(kbList)-1; i++ {
|
|
for j := i + 1; j < len(kbList); j++ {
|
|
if kbList[i].action > kbList[j].action {
|
|
kbList[i], kbList[j] = kbList[j], kbList[i]
|
|
}
|
|
}
|
|
}
|
|
|
|
for i, kb := range kbList {
|
|
line := ""
|
|
|
|
// Cursor
|
|
if i == m.settingsCursor && !m.textinput.Focused() {
|
|
line += "▶ "
|
|
} else {
|
|
line += " "
|
|
}
|
|
|
|
// Format keybinding
|
|
keysStr := strings.Join(kb.keys, ", ")
|
|
line += fmt.Sprintf("%-20s : %s", kb.action, keysStr)
|
|
|
|
content.WriteString(line + "\n")
|
|
}
|
|
|
|
return content.String()
|
|
}
|
|
|
|
// modeSettingsAddTag is a special mode for adding tags
|
|
const modeSettingsAddTag viewMode = 100
|
|
|
|
// modeSettingsAddState is a special mode for adding states
|
|
const modeSettingsAddState viewMode = 101
|
|
|
|
// updateSettingsAddTag handles the add tag flow
|
|
func (m *uiModel) updateSettingsAddTag(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
switch msg := msg.(type) {
|
|
case tea.KeyMsg:
|
|
if !m.textinput.Focused() {
|
|
m.textinput.Focus()
|
|
}
|
|
|
|
switch {
|
|
case key.Matches(msg, m.keys.Quit):
|
|
m.textinput.Blur()
|
|
m.mode = modeSettings
|
|
return m, nil
|
|
|
|
case msg.Type == tea.KeyEnter:
|
|
tagName := m.textinput.Value()
|
|
if tagName != "" {
|
|
// Default color
|
|
m.config.AddTag(tagName, "99")
|
|
// Auto-save
|
|
if err := m.config.Save(); err != nil {
|
|
m.setStatus(fmt.Sprintf("Error saving: %v", err))
|
|
} else {
|
|
m.setStatus(fmt.Sprintf("Added tag '%s' (saved)", tagName))
|
|
}
|
|
}
|
|
m.textinput.Blur()
|
|
m.mode = modeSettings
|
|
return m, nil
|
|
|
|
default:
|
|
var cmd tea.Cmd
|
|
m.textinput, cmd = m.textinput.Update(msg)
|
|
return m, cmd
|
|
}
|
|
}
|
|
|
|
return m, nil
|
|
}
|
|
|
|
// viewSettingsAddTag renders the add tag view
|
|
func (m *uiModel) viewSettingsAddTag() string {
|
|
var content strings.Builder
|
|
|
|
content.WriteString(m.styles.titleStyle.Render("Add New Tag") + "\n\n")
|
|
content.WriteString(m.textinput.View() + "\n\n")
|
|
content.WriteString(m.styles.statusStyle.Render("Enter tag name • Press Enter to add • ESC to cancel") + "\n")
|
|
|
|
return content.String()
|
|
}
|
|
|
|
// updateSettingsAddState handles the add state flow
|
|
func (m *uiModel) updateSettingsAddState(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
switch msg := msg.(type) {
|
|
case tea.KeyMsg:
|
|
if !m.textinput.Focused() {
|
|
m.textinput.Focus()
|
|
}
|
|
|
|
switch {
|
|
case key.Matches(msg, m.keys.Quit):
|
|
m.textinput.Blur()
|
|
m.mode = modeSettings
|
|
return m, nil
|
|
|
|
case msg.Type == tea.KeyEnter:
|
|
stateName := m.textinput.Value()
|
|
if stateName != "" {
|
|
// Default color
|
|
m.config.AddState(stateName, "99")
|
|
// Auto-save
|
|
if err := m.config.Save(); err != nil {
|
|
m.setStatus(fmt.Sprintf("Error saving: %v", err))
|
|
} else {
|
|
m.setStatus(fmt.Sprintf("Added state '%s' (saved)", stateName))
|
|
}
|
|
}
|
|
m.textinput.Blur()
|
|
m.mode = modeSettings
|
|
return m, nil
|
|
|
|
default:
|
|
var cmd tea.Cmd
|
|
m.textinput, cmd = m.textinput.Update(msg)
|
|
return m, cmd
|
|
}
|
|
}
|
|
|
|
return m, nil
|
|
}
|
|
|
|
// viewSettingsAddState renders the add state view
|
|
func (m *uiModel) viewSettingsAddState() string {
|
|
var content strings.Builder
|
|
|
|
content.WriteString(m.styles.titleStyle.Render("Add New State") + "\n\n")
|
|
content.WriteString(m.textinput.View() + "\n\n")
|
|
content.WriteString(m.styles.statusStyle.Render("Enter state name • Press Enter to add • ESC to cancel") + "\n")
|
|
|
|
return content.String()
|
|
}
|
|
|
|
// moveSettingsItemUp moves the current settings item up and auto-saves
|
|
func (m *uiModel) moveSettingsItemUp() {
|
|
switch m.settingsSection {
|
|
case settingsSectionTags:
|
|
if m.settingsCursor > 0 && m.settingsCursor < len(m.config.Tags.Tags) {
|
|
// Swap with previous item
|
|
m.config.Tags.Tags[m.settingsCursor], m.config.Tags.Tags[m.settingsCursor-1] =
|
|
m.config.Tags.Tags[m.settingsCursor-1], m.config.Tags.Tags[m.settingsCursor]
|
|
m.settingsCursor--
|
|
// Auto-save
|
|
if err := m.config.Save(); err != nil {
|
|
m.setStatus(fmt.Sprintf("Error saving: %v", err))
|
|
} else {
|
|
m.setStatus("Reordered (saved)")
|
|
}
|
|
}
|
|
|
|
case settingsSectionStates:
|
|
if m.settingsCursor > 0 && m.settingsCursor < len(m.config.States.States) {
|
|
// Swap with previous item
|
|
m.config.States.States[m.settingsCursor], m.config.States.States[m.settingsCursor-1] =
|
|
m.config.States.States[m.settingsCursor-1], m.config.States.States[m.settingsCursor]
|
|
m.settingsCursor--
|
|
// Auto-save
|
|
if err := m.config.Save(); err != nil {
|
|
m.setStatus(fmt.Sprintf("Error saving: %v", err))
|
|
} else {
|
|
m.setStatus("Reordered (saved)")
|
|
}
|
|
}
|
|
|
|
case settingsSectionKeybindings:
|
|
// Keybindings cannot be reordered
|
|
return
|
|
}
|
|
}
|
|
|
|
// moveSettingsItemDown moves the current settings item down and auto-saves
|
|
func (m *uiModel) moveSettingsItemDown() {
|
|
switch m.settingsSection {
|
|
case settingsSectionTags:
|
|
if m.settingsCursor >= 0 && m.settingsCursor < len(m.config.Tags.Tags)-1 {
|
|
// Swap with next item
|
|
m.config.Tags.Tags[m.settingsCursor], m.config.Tags.Tags[m.settingsCursor+1] =
|
|
m.config.Tags.Tags[m.settingsCursor+1], m.config.Tags.Tags[m.settingsCursor]
|
|
m.settingsCursor++
|
|
// Auto-save
|
|
if err := m.config.Save(); err != nil {
|
|
m.setStatus(fmt.Sprintf("Error saving: %v", err))
|
|
} else {
|
|
m.setStatus("Reordered (saved)")
|
|
}
|
|
}
|
|
|
|
case settingsSectionStates:
|
|
if m.settingsCursor >= 0 && m.settingsCursor < len(m.config.States.States)-1 {
|
|
// Swap with next item
|
|
m.config.States.States[m.settingsCursor], m.config.States.States[m.settingsCursor+1] =
|
|
m.config.States.States[m.settingsCursor+1], m.config.States.States[m.settingsCursor]
|
|
m.settingsCursor++
|
|
// Auto-save
|
|
if err := m.config.Save(); err != nil {
|
|
m.setStatus(fmt.Sprintf("Error saving: %v", err))
|
|
} else {
|
|
m.setStatus("Reordered (saved)")
|
|
}
|
|
}
|
|
|
|
case settingsSectionKeybindings:
|
|
// Keybindings cannot be reordered
|
|
return
|
|
}
|
|
}
|