浏览代码

Added delete functionality to collection viewer

arianagiroux 1 周之前
父节点
当前提交
0764e5717c
共有 1 个文件被更改,包括 115 次插入4 次删除
  1. 115 4
      tui.go

+ 115 - 4
tui.go

@@ -7,6 +7,7 @@ package issues
 
 import (
 	"fmt"
+	"os"
 	"path/filepath"
 	"strings"
 
@@ -70,6 +71,13 @@ type Model struct {
 	width         int
 }
 
+// update signal types
+type (
+	validateMsg  bool
+	deleteResult string
+	deletePath   string
+)
+
 // The bubbletea init function
 func (m Model) Init() tea.Cmd { return m.load }
 
@@ -132,6 +140,15 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		i.Width = 30
 		wg.input = i
 		cmds = append(cmds, func() tea.Msg { return wg })
+	case deletePath:
+		wg := confirmDelete{Path: string(msg), prompt: "Delete", validateString: "yes"}
+		i := textinput.New()
+		i.Placeholder = "yes"
+		i.Focus()
+		i.CharLimit = 80
+		i.Width = 30
+		wg.input = i
+		cmds = append(cmds, func() tea.Msg { return wg })
 	case string:
 		m.content = msg
 		m.viewport.SetContent(m.content)
@@ -153,6 +170,9 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 	case setTitle:
 		m.widget, cmd = w.update(msg)
 		cmds = append(cmds, cmd)
+	case confirmDelete:
+		m.widget, cmd = w.update(msg)
+		cmds = append(cmds, cmd)
 	}
 
 	return m, tea.Batch(cmds...)
@@ -717,10 +737,13 @@ func (ic IssueCollection) update(msg tea.Msg) (widget, tea.Cmd) {
 			ic.Path = ic.Collection[ic.selection].Path
 			return ic, ic.sendLoad
 		case "c":
-			return ic, ic.newIssueInCollection
+			return ic, func() tea.Msg { return setTitleMsg(ic.Path) }
 		case "e":
 			ic.Path = ic.Collection[ic.selection].Path
 			return ic, ic.edit
+		case "d":
+			ic.Path = ic.Collection[ic.selection].Path
+			return ic, func() tea.Msg { return deletePath(ic.Path) }
 		}
 	}
 
@@ -729,8 +752,6 @@ func (ic IssueCollection) update(msg tea.Msg) (widget, tea.Cmd) {
 
 func (ic IssueCollection) sendLoad() tea.Msg { return loadPath(ic.Path) }
 
-func (ic IssueCollection) newIssueInCollection() tea.Msg { return setTitleMsg(ic.Path) }
-
 func (ic IssueCollection) edit() tea.Msg { return newEditWidget(ic.Path) }
 
 // render cmd for IssueCollection widget
@@ -763,7 +784,7 @@ func (ic IssueCollection) render() tea.Msg {
 // keyhelp cmd for IssueCollection widget
 func (ic IssueCollection) keyhelp() string {
 	var output string
-	output = output + "tab/shift+tab: select\t\tenter: view issue\n\nc: create new issue\t\te: edit selected issue"
+	output = output + "tab/shift+tab: select\t\tenter: view issue\nc: create new issue\t\td: delete selected issue\ne: edit selected issue"
 	return output
 }
 
@@ -810,3 +831,93 @@ func (w setTitle) render() tea.Msg {
 }
 
 func (w setTitle) keyhelp() string { return "enter: submit" }
+
+type confirmDelete struct {
+	Path           string
+	input          textinput.Model
+	prompt         string
+	validateString string
+	err            string
+	success        bool
+}
+
+func (w confirmDelete) update(msg tea.Msg) (widget, tea.Cmd) {
+	var cmds []tea.Cmd
+	var cmd tea.Cmd
+	w.input, cmd = w.input.Update(msg)
+	cmds = append(cmds, cmd)
+
+	switch msg := msg.(type) {
+	case tea.KeyMsg:
+		switch msg.String() {
+		case "enter":
+			if w.success {
+				cmds = append(cmds, w.back)
+			} else {
+				cmds = append(cmds, w.validate)
+			}
+		case "esc":
+			cmds = append(cmds, w.back)
+		}
+		cmds = append(cmds, w.render)
+	case validateMsg:
+		switch msg {
+		case true:
+			cmds = append(cmds, w.deletePath)
+		case false:
+			cmds = append(cmds, w.back)
+		}
+	case deleteResult:
+		if len(msg) > 0 {
+			w.success = true
+			cmds = append(cmds, w.render)
+		} else {
+			w.err = string(msg)
+		}
+	}
+
+	return w, tea.Batch(cmds...)
+}
+
+func (w confirmDelete) render() tea.Msg {
+	if len(w.err) == 0 {
+		if w.success {
+			return fmt.Sprintf("Successfully deleted %s", w.Path)
+		}
+		prompt := fmt.Sprintf("%s (%s)...\n", w.prompt, w.Path)
+		return fmt.Sprintf("%s%s", prompt, w.input.View())
+	}
+
+	// wrap in string so its caught by the content update signal
+	return w.err
+}
+
+func (w confirmDelete) keyhelp() string {
+	if w.success {
+		return "enter: continue\t\tesc: continue"
+	}
+	return "enter: submit\t\tesc: cancel"
+}
+
+func (w confirmDelete) validate() tea.Msg {
+	if w.input.Value() == w.validateString {
+		return validateMsg(true)
+	}
+	return validateMsg(false)
+}
+
+func (w confirmDelete) deletePath() tea.Msg {
+	if err := os.RemoveAll(w.Path); err != nil {
+		return deleteResult(err.Error())
+	}
+	return deleteResult("")
+}
+
+func (w confirmDelete) back() tea.Msg {
+	remainder, _ := filepath.Split(w.Path)
+	remainder = strings.TrimRight(remainder, "/")
+	if len(remainder) == 0 {
+		return nil
+	}
+	return loadPath(remainder)
+}