Skip to content

Commit 91fe95b

Browse files
Implement M4 Files plugin
1 parent d763d73 commit 91fe95b

1 file changed

Lines changed: 100 additions & 0 deletions

File tree

plugins/files/files.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package files
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
tea "github.com/charmbracelet/bubbletea"
8+
"github.com/charmbracelet/lipgloss"
9+
10+
"github.com/profullstack/agentbbs/internal/auth"
11+
"github.com/profullstack/agentbbs/internal/plugin"
12+
)
13+
14+
type Plugin struct{}
15+
16+
func (Plugin) ID() string { return "files" }
17+
func (Plugin) Title() string { return "Files" }
18+
func (Plugin) Description() string { return "Browse your personal pod files" }
19+
func (Plugin) RequiresAuth() bool { return true }
20+
21+
func (Plugin) New(user auth.User, ctx plugin.Context) tea.Model {
22+
return model{user: user, dataDir: ctx.DataDir}
23+
}
24+
25+
type model struct {
26+
user auth.User
27+
dataDir string
28+
files []os.DirEntry
29+
cursor int
30+
err error
31+
}
32+
33+
func (m model) Init() tea.Cmd {
34+
return func() tea.Msg {
35+
if m.dataDir == "" {
36+
return fmt.Errorf("no data directory configured")
37+
}
38+
files, err := os.ReadDir(m.dataDir)
39+
if err != nil {
40+
return err
41+
}
42+
return files
43+
}
44+
}
45+
46+
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
47+
switch msg := msg.(type) {
48+
case error:
49+
m.err = msg
50+
return m, nil
51+
case []os.DirEntry:
52+
m.files = msg
53+
return m, nil
54+
case tea.KeyMsg:
55+
switch msg.String() {
56+
case "up", "k":
57+
if m.cursor > 0 {
58+
m.cursor--
59+
}
60+
case "down", "j":
61+
if m.cursor < len(m.files)-1 {
62+
m.cursor++
63+
}
64+
case "q", "esc", "ctrl+c":
65+
return m, plugin.Exit
66+
}
67+
}
68+
return m, nil
69+
}
70+
71+
var (
72+
titleStyle = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#4ade80"))
73+
itemStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("252"))
74+
selStyle = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#4ade80"))
75+
)
76+
77+
func (m model) View() string {
78+
if m.err != nil {
79+
return fmt.Sprintf("Error reading files: %v\n\npress any key to return", m.err)
80+
}
81+
s := titleStyle.Render("Files in your pod workspace:") + "\n\n"
82+
if len(m.files) == 0 {
83+
s += " (no files found)\n"
84+
}
85+
for i, file := range m.files {
86+
cur := " "
87+
style := itemStyle
88+
if i == m.cursor {
89+
cur = "❯ "
90+
style = selStyle
91+
}
92+
icon := "📄 "
93+
if file.IsDir() {
94+
icon = "📁 "
95+
}
96+
s += fmt.Sprintf("%s%s%s\n", cur, icon, style.Render(file.Name()))
97+
}
98+
s += "\n" + lipgloss.NewStyle().Foreground(lipgloss.Color("241")).Render("↑/↓ move · q back")
99+
return lipgloss.NewStyle().Padding(1, 2).Render(s)
100+
}

0 commit comments

Comments
 (0)