summaryrefslogtreecommitdiff
path: root/internal/ui/scope.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/scope.go
Initial release
Diffstat (limited to 'internal/ui/scope.go')
-rw-r--r--internal/ui/scope.go126
1 files changed, 126 insertions, 0 deletions
diff --git a/internal/ui/scope.go b/internal/ui/scope.go
new file mode 100644
index 0000000..037472c
--- /dev/null
+++ b/internal/ui/scope.go
@@ -0,0 +1,126 @@
+package ui
+
+import (
+ "net"
+ "strings"
+
+ "fyne.io/fyne/v2"
+ "fyne.io/fyne/v2/container"
+ "fyne.io/fyne/v2/dialog"
+ "fyne.io/fyne/v2/theme"
+ "fyne.io/fyne/v2/widget"
+
+ "github.com/shiv/internal/logger"
+ "github.com/shiv/internal/store"
+)
+
+func showScopeDialog(projectStore *store.Store, win fyne.Window, onChanged func()) {
+ entries, err := projectStore.AllScopeEntries()
+ if err != nil {
+ logger.Error("scope: load entries: %v", err)
+ entries = nil
+ }
+
+ // we keep a local copy to drive the list
+ type row struct {
+ id int64
+ host string
+ }
+ rows := make([]row, len(entries))
+ for i, entry := range entries {
+ rows[i] = row{entry.ID, entry.Host}
+ }
+
+ var list *widget.List
+ var deleteBtn *widget.Button
+ selectedIdx := -1
+
+ list = widget.NewList(
+ func() int { return len(rows) },
+ func() fyne.CanvasObject {
+ return widget.NewLabel("")
+ },
+ func(i widget.ListItemID, obj fyne.CanvasObject) {
+ obj.(*widget.Label).SetText(rows[i].host)
+ },
+ )
+ list.OnSelected = func(i widget.ListItemID) {
+ selectedIdx = i
+ deleteBtn.Enable()
+ }
+ list.OnUnselected = func(_ widget.ListItemID) {
+ selectedIdx = -1
+ deleteBtn.Disable()
+ }
+
+ hostEntry := widget.NewEntry()
+ hostEntry.SetPlaceHolder("example.com")
+
+ addBtn := widget.NewButtonWithIcon("Add", AppIcon("save"), func() {
+ host := strings.TrimSpace(hostEntry.Text)
+ if host == "" {
+ return
+ }
+ // strip protocol if someone pastes a URL
+ host = strings.TrimPrefix(host, "https://")
+ host = strings.TrimPrefix(host, "http://")
+ // strip path
+ if idx := strings.Index(host, "/"); idx >= 0 {
+ host = host[:idx]
+ }
+ // strip port, avoid breaking ipv6
+ if hostname, _, err := net.SplitHostPort(host); err == nil {
+ host = hostname
+ }
+ if err := projectStore.AddScopeEntry(host); err != nil {
+ logger.Error("scope: add entry: %v", err)
+ return
+ }
+ newEntries, _ := projectStore.AllScopeEntries()
+ rows = make([]row, len(newEntries))
+ for i, entry := range newEntries {
+ rows[i] = row{entry.ID, entry.Host}
+ }
+ hostEntry.SetText("")
+ list.Refresh()
+ onChanged()
+ })
+ addBtn.Importance = widget.HighImportance
+
+ deleteBtn = widget.NewButtonWithIcon("Remove", theme.DeleteIcon(), func() {
+ if selectedIdx < 0 || selectedIdx >= len(rows) {
+ return
+ }
+ entryId := rows[selectedIdx].id
+ if err := projectStore.DeleteScopeEntry(entryId); err != nil {
+ logger.Error("scope: delete entry: %v", err)
+ return
+ }
+ newEntries, _ := projectStore.AllScopeEntries()
+ rows = make([]row, len(newEntries))
+ for i, e := range newEntries {
+ rows[i] = row{e.ID, e.Host}
+ }
+ selectedIdx = -1
+ deleteBtn.Disable()
+ list.Refresh()
+ onChanged()
+ })
+ deleteBtn.Disable()
+
+ inputRow := container.NewBorder(nil, nil, nil, addBtn, hostEntry)
+
+ content := container.NewBorder(
+ inputRow,
+ deleteBtn,
+ nil, nil,
+ list,
+ )
+ content.Resize(fyne.NewSize(400, 300))
+
+ scopeDialog := dialog.NewCustom("Scope", "Close", content, win)
+ scopeDialog.Resize(fyne.NewSize(400, 350))
+
+ closeOnEscape(win, scopeDialog.Dismiss)
+ scopeDialog.Show()
+}