summaryrefslogtreecommitdiff
path: root/internal/ui/plugins.go
diff options
context:
space:
mode:
authorspiperac <[email protected]>2026-06-15 06:42:13 +0200
committerspiperac <[email protected]>2026-06-15 06:42:13 +0200
commit0a477fd288d064d265395c88dbd0f261b723804e (patch)
tree9b129f8f41c907285b89ed8385679934bb59c14f /internal/ui/plugins.go
Initial release
Diffstat (limited to 'internal/ui/plugins.go')
-rw-r--r--internal/ui/plugins.go179
1 files changed, 179 insertions, 0 deletions
diff --git a/internal/ui/plugins.go b/internal/ui/plugins.go
new file mode 100644
index 0000000..cf29f37
--- /dev/null
+++ b/internal/ui/plugins.go
@@ -0,0 +1,179 @@
+package ui
+
+import (
+ "strings"
+
+ "fyne.io/fyne/v2"
+ "fyne.io/fyne/v2/container"
+ "fyne.io/fyne/v2/dialog"
+ "fyne.io/fyne/v2/layout"
+ "fyne.io/fyne/v2/storage"
+ "fyne.io/fyne/v2/widget"
+
+ "github.com/shiv/internal/events"
+ "github.com/shiv/internal/store"
+ "github.com/shiv/internal/ui/widgets"
+)
+
+type pluginsTab struct {
+ projectStore *store.Store
+ bus *events.Bus
+ win fyne.Window
+}
+
+func newPluginsTab(projectStore *store.Store, bus *events.Bus, win fyne.Window) *pluginsTab {
+ return &pluginsTab{
+ projectStore: projectStore,
+ bus: bus,
+ win: win,
+ }
+}
+
+func (t *pluginsTab) build() fyne.CanvasObject {
+ var plugins []store.PluginEntry
+ selectedIdx := -1
+
+ logView := widgets.NewTextView()
+ logView.SetWindow(t.win)
+
+ toggleBtn := widget.NewButton("Disable", nil)
+ toggleBtn.Disable()
+
+ var pluginList *widget.List
+
+ refreshLogs := func() {
+ if selectedIdx < 0 || selectedIdx >= len(plugins) {
+ logView.SetText("")
+ return
+ }
+ lines := t.projectStore.PluginLogs(plugins[selectedIdx].Name)
+ logView.SetText(strings.Join(lines, "\n"))
+ }
+
+ refreshAll := func() {
+ entries, err := t.projectStore.AllPlugins()
+ if err != nil {
+ return
+ }
+ plugins = entries
+ pluginList.Refresh()
+
+ // Keep toggle button label in sync after external state change.
+ if selectedIdx >= 0 && selectedIdx < len(plugins) {
+ if plugins[selectedIdx].Enabled {
+ toggleBtn.SetText("Disable")
+ } else {
+ toggleBtn.SetText("Enable")
+ }
+ toggleBtn.Enable()
+ }
+
+ refreshLogs()
+ }
+
+ pluginList = widget.NewList(
+ func() int { return len(plugins) },
+ func() fyne.CanvasObject {
+ return container.NewHBox(
+ widget.NewLabel(""),
+ widget.NewLabel(""),
+ )
+ },
+ func(id widget.ListItemID, item fyne.CanvasObject) {
+ if id >= len(plugins) {
+ return
+ }
+ p := plugins[id]
+ box := item.(*fyne.Container)
+ status := box.Objects[0].(*widget.Label)
+ name := box.Objects[1].(*widget.Label)
+ if p.Enabled {
+ status.SetText("✓")
+ status.Importance = widget.SuccessImportance
+ } else {
+ status.SetText("✗")
+ status.Importance = widget.DangerImportance
+ }
+ name.SetText(p.Name)
+ },
+ )
+
+ pluginList.OnSelected = func(id widget.ListItemID) {
+ selectedIdx = id
+ if id >= len(plugins) {
+ toggleBtn.Disable()
+ return
+ }
+ if plugins[id].Enabled {
+ toggleBtn.SetText("Disable")
+ } else {
+ toggleBtn.SetText("Enable")
+ }
+ toggleBtn.Enable()
+ refreshLogs()
+ }
+
+ pluginList.OnUnselected = func(_ widget.ListItemID) {
+ selectedIdx = -1
+ toggleBtn.Disable()
+ logView.SetText("")
+ }
+
+ toggleBtn.OnTapped = func() {
+ if selectedIdx < 0 || selectedIdx >= len(plugins) {
+ return
+ }
+ p := plugins[selectedIdx]
+ t.bus.EmitSetPluginEnabled(events.SetPluginEnabledEvent{
+ Name: p.Name,
+ Enabled: !p.Enabled,
+ })
+ }
+
+ addBtn := widget.NewButton("Add", func() {
+ fd := dialog.NewFileOpen(func(uc fyne.URIReadCloser, err error) {
+ if err != nil || uc == nil {
+ return
+ }
+ uc.Close()
+ t.bus.EmitLoadPlugin(events.LoadPluginEvent{
+ SourcePath: uc.URI().Path(),
+ })
+ }, t.win)
+ fd.SetFilter(storage.NewExtensionFileFilter([]string{".lua"}))
+ fd.Show()
+ })
+
+ // Listen for plugin state and log changes from the store.
+ go func() {
+ for range t.projectStore.PluginEntries {
+ fyne.Do(refreshAll)
+ }
+ }()
+
+ // Initial population.
+ refreshAll()
+
+ toolbar := container.New(
+ layout.NewCustomPaddedLayout(8, 8, 0, 0),
+ container.NewHBox(addBtn, toggleBtn),
+ )
+
+ leftPane := container.NewBorder(
+ newBoldLabel("Plugins"),
+ toolbar,
+ nil, nil,
+ pluginList,
+ )
+
+ rightPane := container.NewBorder(
+ newBoldLabel("Log"),
+ nil, nil, nil,
+ logView.Build(),
+ )
+
+ split := container.NewHSplit(leftPane, rightPane)
+ split.SetOffset(0.3)
+
+ return split
+}