add:clean all func
This commit is contained in:
5
internal/pages/clean_all.go
Normal file
5
internal/pages/clean_all.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package pages
|
||||
|
||||
type CleanAllPageMsg struct {
|
||||
ServerName string
|
||||
}
|
||||
@@ -77,6 +77,14 @@ func (s *StorageService) Send(localPaths []string) error {
|
||||
|
||||
// CleanAll removes all files from remote storage.
|
||||
func (s *StorageService) CleanAll() error {
|
||||
// TODO: implement
|
||||
return fmt.Errorf("clean all: not yet implemented")
|
||||
cmd := SSHCmd(s.server,
|
||||
"rm -f "+defaultStoragePath+"/*",
|
||||
)
|
||||
debugLog("CleanAll | args: %v", cmd.Args)
|
||||
out, err := cmd.CombinedOutput()
|
||||
debugLog("CleanAll | exit_err: %v | output: %q", err, strings.TrimSpace(string(out)))
|
||||
if err != nil {
|
||||
return fmt.Errorf("clean all failed: %w\n%s", err, strings.TrimSpace(string(out)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -86,6 +86,12 @@ var (
|
||||
Foreground(lipgloss.Color("203")).
|
||||
MarginTop(1)
|
||||
|
||||
CleanWarningStyle = lipgloss.NewStyle().
|
||||
Foreground(lipgloss.Color("203")).
|
||||
Bold(true).
|
||||
MarginBottom(1).
|
||||
Width(44)
|
||||
|
||||
// Footer
|
||||
FooterStyle = lipgloss.NewStyle().
|
||||
Foreground(lipgloss.Color("240")).
|
||||
|
||||
@@ -3,6 +3,8 @@ package tui
|
||||
import (
|
||||
"filepass/internal/pages"
|
||||
"filepass/internal/services"
|
||||
|
||||
"charm.land/bubbles/v2/textinput"
|
||||
)
|
||||
|
||||
type page int
|
||||
@@ -15,6 +17,7 @@ const (
|
||||
pageServerActions
|
||||
pageFileAction
|
||||
pageSend
|
||||
pageCleanAll
|
||||
)
|
||||
|
||||
type TUIInterface struct {
|
||||
@@ -45,6 +48,10 @@ type TUIInterface struct {
|
||||
FileOpLoading bool
|
||||
FileOpErr error
|
||||
FileOpSuccess string
|
||||
// clean all confirmation page
|
||||
CleanInput textinput.Model
|
||||
CleanOpLoading bool
|
||||
CleanOpErr error
|
||||
// send / file picker page
|
||||
Picker picker
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"filepass/internal/pages"
|
||||
"filepass/internal/services"
|
||||
|
||||
"charm.land/bubbles/v2/textinput"
|
||||
tea "charm.land/bubbletea/v2"
|
||||
)
|
||||
|
||||
@@ -60,6 +61,30 @@ func deleteFileCmd(store *services.ServicesStore, serverName, filename string) t
|
||||
}
|
||||
}
|
||||
|
||||
type cleanAllMsg struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func cleanAllCmd(store *services.ServicesStore, serverName string) tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
storage, err := store.NewStorageService(serverName)
|
||||
if err != nil {
|
||||
return cleanAllMsg{err: err}
|
||||
}
|
||||
return cleanAllMsg{err: storage.CleanAll()}
|
||||
}
|
||||
}
|
||||
|
||||
func newCleanInput() textinput.Model {
|
||||
ti := textinput.New()
|
||||
ti.Placeholder = "yes"
|
||||
ti.Prompt = ""
|
||||
ti.CharLimit = 3
|
||||
ti.SetWidth(10)
|
||||
ti.Focus()
|
||||
return ti
|
||||
}
|
||||
|
||||
func checkStorageCmd(store *services.ServicesStore, serverName string) tea.Cmd {
|
||||
return func() tea.Msg {
|
||||
storage, err := store.NewStorageService(serverName)
|
||||
@@ -152,6 +177,22 @@ func (m TUIInterface) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
m.FileOpSuccess = ""
|
||||
return m, nil
|
||||
|
||||
case pages.CleanAllPageMsg:
|
||||
m.Page = pageCleanAll
|
||||
m.CleanInput = newCleanInput()
|
||||
m.CleanOpLoading = false
|
||||
m.CleanOpErr = nil
|
||||
return m, nil
|
||||
|
||||
case cleanAllMsg:
|
||||
m.CleanOpLoading = false
|
||||
if msg.err != nil {
|
||||
m.CleanOpErr = msg.err
|
||||
return m, nil
|
||||
}
|
||||
server := m.ActiveServer
|
||||
return m, func() tea.Msg { return pages.ServerActionsPageMsg{ServerName: server} }
|
||||
|
||||
case pages.SendPageMsg:
|
||||
m.Page = pageSend
|
||||
m.Picker = newPicker(m.LocalDir)
|
||||
@@ -222,6 +263,9 @@ func (m TUIInterface) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
if m.Page == pageSend {
|
||||
return m.updateSend(msg)
|
||||
}
|
||||
if m.Page == pageCleanAll {
|
||||
return m.updateCleanAll(msg)
|
||||
}
|
||||
|
||||
switch msg.String() {
|
||||
case "up", "k":
|
||||
@@ -313,7 +357,7 @@ func (m TUIInterface) updateServerActions(msg tea.KeyPressMsg) (tea.Model, tea.C
|
||||
case "send":
|
||||
return m, func() tea.Msg { return pages.SendPageMsg{ServerName: server} }
|
||||
case "clean":
|
||||
// TODO: navigate to clean all page
|
||||
return m, func() tea.Msg { return pages.CleanAllPageMsg{ServerName: server} }
|
||||
}
|
||||
|
||||
case "ctrl+c":
|
||||
@@ -429,6 +473,36 @@ func (m TUIInterface) updateSend(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m TUIInterface) updateCleanAll(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
|
||||
if m.CleanOpLoading {
|
||||
if msg.String() == "ctrl+c" {
|
||||
m.Quitting = true
|
||||
return m, tea.Quit
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
switch msg.String() {
|
||||
case "enter":
|
||||
if m.CleanInput.Value() == "yes" {
|
||||
m.CleanOpLoading = true
|
||||
m.CleanOpErr = nil
|
||||
return m, cleanAllCmd(m.Services, m.ActiveServer)
|
||||
}
|
||||
case "ctrl+c":
|
||||
m.Quitting = true
|
||||
return m, tea.Quit
|
||||
case "esc":
|
||||
server := m.ActiveServer
|
||||
return m, func() tea.Msg { return pages.ServerActionsPageMsg{ServerName: server} }
|
||||
}
|
||||
|
||||
// route all other keys to the text input
|
||||
var cmd tea.Cmd
|
||||
m.CleanInput, cmd = m.CleanInput.Update(msg)
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
func (m TUIInterface) updateSelectServer(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
|
||||
last := len(m.ServerNames) - 1
|
||||
switch msg.String() {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package tui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"filepass/internal/styles"
|
||||
|
||||
tea "charm.land/bubbletea/v2"
|
||||
@@ -34,6 +36,8 @@ func (m TUIInterface) subtitle() string {
|
||||
return m.ActiveFile
|
||||
case pageSend:
|
||||
return "Send File"
|
||||
case pageCleanAll:
|
||||
return "Clean All"
|
||||
default:
|
||||
return "Secure file transfer"
|
||||
}
|
||||
@@ -65,6 +69,8 @@ func (m TUIInterface) View() tea.View {
|
||||
body = m.viewFileAction()
|
||||
case pageSend:
|
||||
body = m.viewSend()
|
||||
case pageCleanAll:
|
||||
body = m.viewCleanAll()
|
||||
default:
|
||||
body = m.viewMenu()
|
||||
}
|
||||
@@ -108,6 +114,10 @@ func (m TUIInterface) View() tea.View {
|
||||
footerHint("enter", "confirm") +
|
||||
footerSep() +
|
||||
footerHint("esc", "back")
|
||||
case pageCleanAll:
|
||||
footerStr = footerHint("enter", "confirm") +
|
||||
footerSep() +
|
||||
footerHint("esc", "back")
|
||||
case pageSend:
|
||||
footerStr = footerHint("↑↓", "navigate") +
|
||||
footerSep() +
|
||||
@@ -252,6 +262,30 @@ func (m TUIInterface) viewSend() string {
|
||||
return lipgloss.JoinVertical(lipgloss.Left, crumb, queryLine, list)
|
||||
}
|
||||
|
||||
func (m TUIInterface) viewCleanAll() string {
|
||||
fileCount := len(m.StorageFiles)
|
||||
warning := styles.CleanWarningStyle.Render(
|
||||
fmt.Sprintf("This will permanently delete all %d file(s) from remote storage.", fileCount),
|
||||
)
|
||||
|
||||
promptLabel := styles.FieldLabelStyle(true).Render("Type \"yes\" to confirm")
|
||||
input := m.CleanInput.View()
|
||||
|
||||
var statusLine string
|
||||
switch {
|
||||
case m.CleanOpLoading:
|
||||
statusLine = styles.StatusWarnStyle.Render(" deleting…")
|
||||
case m.CleanOpErr != nil:
|
||||
statusLine = styles.StatusErrStyle.Render("✗ " + m.CleanOpErr.Error())
|
||||
}
|
||||
|
||||
parts := []string{warning, promptLabel, input}
|
||||
if statusLine != "" {
|
||||
parts = append(parts, statusLine)
|
||||
}
|
||||
return lipgloss.JoinVertical(lipgloss.Left, parts...)
|
||||
}
|
||||
|
||||
func (m TUIInterface) viewSelectServer() string {
|
||||
if len(m.ServerNames) == 0 {
|
||||
return styles.StatusWarnStyle.Render("⚠ No servers configured.")
|
||||
|
||||
Reference in New Issue
Block a user