Compare commits
135
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ab30379f0 | ||
|
|
3ef4219999 | ||
|
|
23f5e54973 | ||
|
|
7d3b69cd7e | ||
|
|
4a4a89ac9c | ||
|
|
ebaef096fd | ||
|
|
c4ae501402 | ||
|
|
23a39f07bb | ||
|
|
43158a0661 | ||
|
|
dce67813d9 | ||
|
|
bce3730a91 | ||
|
|
65bb611bb5 | ||
|
|
3c5108c947 | ||
|
|
7ec55823e2 | ||
|
|
a5c9ff743f | ||
|
|
e51b9235f1 | ||
|
|
4b0b906462 | ||
|
|
50e3c6c7d0 | ||
|
|
72be469f49 | ||
|
|
203581f37c | ||
|
|
99df476d0f | ||
|
|
2568f159ff | ||
|
|
648a36b608 | ||
|
|
b47c7909cf | ||
|
|
cbfc7fe4bf | ||
|
|
0144dab073 | ||
|
|
46d82dafd2 | ||
|
|
6166f1462f | ||
|
|
d8edfeda3c | ||
|
|
702ecd21e0 | ||
|
|
5d8abc9bc6 | ||
|
|
a14f4e975d | ||
|
|
1f182dae3c | ||
|
|
0abc527c39 | ||
|
|
5bbaea73b6 | ||
|
|
ffd4a8b2a5 | ||
|
|
db0afda596 | ||
|
|
32007ff000 | ||
|
|
c45a2e1057 | ||
|
|
a7c5e1708c | ||
|
|
7f5fcd0943 | ||
|
|
3de90072b2 | ||
|
|
437b419df5 | ||
|
|
c4833c6135 | ||
|
|
b204005ab9 | ||
|
|
7fab8f8b27 | ||
|
|
1f760ed33d | ||
|
|
f66699b3f9 | ||
|
|
fe767e821d | ||
|
|
c67a62987d | ||
|
|
a4c543fb5a | ||
|
|
b279cd53b6 | ||
|
|
3bfaf8c34a | ||
|
|
0efba3074e | ||
|
|
847e363cf0 | ||
|
|
463ee8d0e0 | ||
|
|
ad8b6cc1a9 | ||
|
|
7d58ce6140 | ||
|
|
030ec84b1a | ||
|
|
7cc64bbbfb | ||
|
|
0778530d7d | ||
|
|
fc972d2baa | ||
|
|
ab1d3e6e74 | ||
|
|
d60db5f67b | ||
|
|
f57a971951 | ||
|
|
bef3300198 | ||
|
|
873875c33a | ||
|
|
a679d229f8 | ||
|
|
89b715ec9a | ||
|
|
a541745127 | ||
|
|
c2c8e87ea3 | ||
|
|
63d9fc5156 | ||
|
|
cf0d211fdb | ||
|
|
d0865afa9b | ||
|
|
5a3b036107 | ||
|
|
bccd669baa | ||
|
|
dd05b761b3 | ||
|
|
53757133fd | ||
|
|
2fc8ac37eb | ||
|
|
212327b7cf | ||
|
|
56ffcb8453 | ||
|
|
59ea015b24 | ||
|
|
d8a3a2bf8f | ||
|
|
37f29d675b | ||
|
|
f3e5772f63 | ||
|
|
20f0890b94 | ||
|
|
87472f6674 | ||
|
|
53dc114d19 | ||
|
|
edd3d71957 | ||
|
|
1b064134f3 | ||
|
|
8e997b769d | ||
|
|
aee8fedf14 | ||
|
|
a5e8c46fd9 | ||
|
|
2cf2d44e57 | ||
|
|
f5ce0a4dca | ||
|
|
cbd1d36516 | ||
|
|
439e77e095 | ||
|
|
ab16d26cc3 | ||
|
|
45211f4b89 | ||
|
|
069a4d178c | ||
|
|
0196e63579 | ||
|
|
60452be32d | ||
|
|
78b2afd4fb | ||
|
|
88fcada19d | ||
|
|
16e270371e | ||
|
|
cc0174ed24 | ||
|
|
8763bda3f4 | ||
|
|
212fa8be4d | ||
|
|
249e98d060 | ||
|
|
76964a6a00 | ||
|
|
6978b3dc47 | ||
|
|
b8865b41dc | ||
|
|
23fd21dbf5 | ||
|
|
2fcc42597d | ||
|
|
f3f8995d53 | ||
|
|
6c9320efae | ||
|
|
c9131bded8 | ||
|
|
e1fe23bcba | ||
|
|
d3febf1f6c | ||
|
|
0fe9679891 | ||
|
|
03c835139f | ||
|
|
af42df691b | ||
|
|
95b4fc1802 | ||
|
|
3874b2cc9d | ||
|
|
049e55c9c9 | ||
|
|
a370265e2e | ||
|
|
535dd86aba | ||
|
|
b0896539c8 | ||
|
|
28d9c9b659 | ||
|
|
6f9e1ec589 | ||
|
|
2adbe3004f | ||
|
|
da9fbaf347 | ||
|
|
5bca510e83 | ||
|
|
e76c63ccdc | ||
|
|
288c345a22 |
@@ -1,5 +1,4 @@
|
|||||||
/server
|
/server
|
||||||
/cli
|
|
||||||
*.properties
|
*.properties
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/vendor
|
/vendor
|
||||||
|
|||||||
+16
-1
@@ -1,9 +1,22 @@
|
|||||||
steps:
|
steps:
|
||||||
test:
|
test:
|
||||||
image: golang:1.24
|
image: golang:1.27
|
||||||
commands:
|
commands:
|
||||||
- go test ./...
|
- go test ./...
|
||||||
|
volumes:
|
||||||
|
- go_build_cache:/root/.cache/go-build
|
||||||
|
- go_mod_cache:/go/pkg/mod
|
||||||
build:
|
build:
|
||||||
|
image: golang:1.27
|
||||||
|
environment:
|
||||||
|
CGO_ENABLED: 0
|
||||||
|
GOOS: linux
|
||||||
|
commands:
|
||||||
|
- go build -o server ./cmd/serve
|
||||||
|
volumes:
|
||||||
|
- go_build_cache:/root/.cache/go-build
|
||||||
|
- go_mod_cache:/go/pkg/mod
|
||||||
|
container:
|
||||||
image: docker
|
image: docker
|
||||||
commands:
|
commands:
|
||||||
- apk add curl
|
- apk add curl
|
||||||
@@ -21,3 +34,5 @@
|
|||||||
branch: "master"
|
branch: "master"
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- go_build_cache:/root/.cache/go-build
|
||||||
|
- go_mod_cache:/go/pkg/mod
|
||||||
|
|||||||
+1
-7
@@ -1,9 +1,3 @@
|
|||||||
FROM golang:1.24
|
|
||||||
WORKDIR /src
|
|
||||||
COPY . ./
|
|
||||||
RUN CGO_ENABLED=0 GOOS=linux go build -o server ./cmd/serve
|
|
||||||
|
|
||||||
FROM scratch
|
FROM scratch
|
||||||
COPY --from=0 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
COPY server ./
|
||||||
COPY --from=0 /src/server ./
|
|
||||||
CMD ["/server"]
|
CMD ["/server"]
|
||||||
@@ -1,28 +1,21 @@
|
|||||||
.PHONY: up down run-server run-cli test
|
.PHONY: up down run test
|
||||||
|
|
||||||
GOFILES=$(shell find . -name '*.go' -o -name 'go.*')
|
GOFILES=$(shell find . -name '*.go' -o -name 'go.*')
|
||||||
STATICFILES=$(shell find . -name '*.js' -o -name '*.css' -o -name '*.html')
|
STATICFILES=$(shell find . -name '*.js' -o -name '*.css' -o -name '*.html')
|
||||||
SQLFILES=$(shell find . -name '*.sql')
|
|
||||||
|
|
||||||
ifneq (,$(wildcard ./local.properties))
|
ifneq (,$(wildcard ./local.properties))
|
||||||
include local.properties
|
include local.properties
|
||||||
export
|
export
|
||||||
endif
|
endif
|
||||||
|
|
||||||
build: server cli
|
build: server
|
||||||
|
|
||||||
run-server: build
|
run: build
|
||||||
./server
|
./server
|
||||||
|
|
||||||
run-cli: build
|
|
||||||
./cli
|
|
||||||
|
|
||||||
server: $(GOFILES) $(STATICFILES)
|
server: $(GOFILES) $(STATICFILES)
|
||||||
go build -o server ./cmd/serve
|
go build -o server ./cmd/serve
|
||||||
|
|
||||||
cli: $(GOFILES) $(SQLFILES)
|
|
||||||
go build -o cli ./cmd/cli
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
go test ./... -cover
|
go test ./... -cover
|
||||||
|
|
||||||
|
|||||||
@@ -1,113 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.yetaga.in/alazyreader/library/media"
|
|
||||||
"github.com/gdamore/tcell/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// error message
|
|
||||||
type EventError struct {
|
|
||||||
tcell.EventTime
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEventError(err error) *EventError {
|
|
||||||
e := &EventError{err: err}
|
|
||||||
e.SetEventNow()
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// save change to book
|
|
||||||
type EventBookUpdate struct {
|
|
||||||
tcell.EventTime
|
|
||||||
book *media.Book
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEventBookUpdate(b *media.Book) *EventBookUpdate {
|
|
||||||
e := &EventBookUpdate{book: b}
|
|
||||||
e.SetEventNow()
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *EventBookUpdate) Book() *media.Book {
|
|
||||||
return e.book
|
|
||||||
}
|
|
||||||
|
|
||||||
// open new book in display
|
|
||||||
type EventLoadBook struct {
|
|
||||||
tcell.EventTime
|
|
||||||
ID int
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEventLoadBook(id int) *EventLoadBook {
|
|
||||||
e := &EventLoadBook{ID: id}
|
|
||||||
e.SetEventNow()
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// open new book in display
|
|
||||||
type EventEnterBook struct {
|
|
||||||
tcell.EventTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEventEnterBook() *EventEnterBook {
|
|
||||||
e := &EventEnterBook{}
|
|
||||||
e.SetEventNow()
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// switch back to menu control
|
|
||||||
type EventExitBook struct {
|
|
||||||
tcell.EventTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEventExitBook() *EventExitBook {
|
|
||||||
e := &EventExitBook{}
|
|
||||||
e.SetEventNow()
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// open import window
|
|
||||||
type EventOpenImport struct {
|
|
||||||
tcell.EventTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEventOpenImport() *EventOpenImport {
|
|
||||||
e := &EventOpenImport{}
|
|
||||||
e.SetEventNow()
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// attempt to import given filename.csv
|
|
||||||
type EventAttemptImport struct {
|
|
||||||
tcell.EventTime
|
|
||||||
filename string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEventAttemptImport(f string) *EventAttemptImport {
|
|
||||||
e := &EventAttemptImport{filename: f}
|
|
||||||
e.SetEventNow()
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// close import window
|
|
||||||
type EventCloseImport struct {
|
|
||||||
tcell.EventTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEventCloseImport() *EventCloseImport {
|
|
||||||
e := &EventCloseImport{}
|
|
||||||
e.SetEventNow()
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
// quit
|
|
||||||
type EventQuit struct {
|
|
||||||
tcell.EventTime
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEventQuit() *EventQuit {
|
|
||||||
e := &EventQuit{}
|
|
||||||
e.SetEventNow()
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
-336
@@ -1,336 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"runtime/debug"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"git.yetaga.in/alazyreader/library/config"
|
|
||||||
"git.yetaga.in/alazyreader/library/database"
|
|
||||||
"git.yetaga.in/alazyreader/library/importer"
|
|
||||||
"git.yetaga.in/alazyreader/library/media"
|
|
||||||
"git.yetaga.in/alazyreader/library/ui"
|
|
||||||
"github.com/gdamore/tcell/v2"
|
|
||||||
"github.com/kelseyhightower/envconfig"
|
|
||||||
)
|
|
||||||
|
|
||||||
// State holds the UI state keys=>value map and manages access to the map with a mutex
|
|
||||||
type State struct {
|
|
||||||
m sync.Mutex
|
|
||||||
stateMap map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// key, present
|
|
||||||
func (s *State) Get(key string) interface{} {
|
|
||||||
s.m.Lock()
|
|
||||||
defer s.m.Unlock()
|
|
||||||
if s.stateMap == nil {
|
|
||||||
s.stateMap = make(map[string]interface{})
|
|
||||||
}
|
|
||||||
k, ok := s.stateMap[key]
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return k
|
|
||||||
}
|
|
||||||
|
|
||||||
// key, value
|
|
||||||
func (s *State) Set(key string, value interface{}) {
|
|
||||||
s.m.Lock()
|
|
||||||
defer s.m.Unlock()
|
|
||||||
if s.stateMap == nil {
|
|
||||||
s.stateMap = make(map[string]interface{})
|
|
||||||
}
|
|
||||||
s.stateMap[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
func max(a, b int) int {
|
|
||||||
if a > b {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// UI states
|
|
||||||
const (
|
|
||||||
IN_MENU = iota
|
|
||||||
IN_BOOK
|
|
||||||
IN_IMPORT
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var c config.Config
|
|
||||||
err := envconfig.Process("library", &c)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create state
|
|
||||||
state := State{}
|
|
||||||
|
|
||||||
// set up DB connection
|
|
||||||
if c.DBUser == "" || c.DBPass == "" || c.DBHost == "" || c.DBPort == "" || c.DBName == "" {
|
|
||||||
if c.DBPass != "" { // obscure password
|
|
||||||
c.DBPass = c.DBPass[0:max(3, len(c.DBPass))] + strings.Repeat("*", max(0, len(c.DBPass)-3))
|
|
||||||
}
|
|
||||||
log.Fatalf("vars: %+v", c)
|
|
||||||
}
|
|
||||||
lib, err := database.NewMySQLConnection(c.DBUser, c.DBPass, c.DBHost, c.DBPort, c.DBName)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
err = lib.PrepareDatabase(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
_, _, err = lib.RunMigrations(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
books, err := lib.GetAllBooks(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
state.Set("library", books)
|
|
||||||
|
|
||||||
screen, err := tcell.NewScreen()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
err = screen.Init()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
// cleanup our screen and log if we panic and crash out somewhere
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
if screen != nil {
|
|
||||||
screen.Fini()
|
|
||||||
}
|
|
||||||
fmt.Println("fatal panic;", r)
|
|
||||||
if c.Debug {
|
|
||||||
fmt.Println("stacktrace: \n" + string(debug.Stack()))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// book list and options menu (left column)
|
|
||||||
l := ui.NewList(Titles(state.Get("library").([]media.Book)), 0)
|
|
||||||
menu := ui.NewBox(
|
|
||||||
"library",
|
|
||||||
[]string{"˄˅ select", "⏎ edit", "(n)ew", "(i)mport", "(q)uit"},
|
|
||||||
ui.Contents{{
|
|
||||||
Offsets: ui.Offsets{Top: 1, Left: 2, Bottom: -2, Right: -2},
|
|
||||||
Container: l,
|
|
||||||
}},
|
|
||||||
ui.StyleActive,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
activeBookDetails := ui.NewBookDetails(&media.Book{})
|
|
||||||
|
|
||||||
// book display (right column)
|
|
||||||
activeBook := ui.NewBox(
|
|
||||||
"book",
|
|
||||||
[]string{"˄˅ select", "⏎ edit", "(esc) close"},
|
|
||||||
ui.Contents{{
|
|
||||||
Offsets: ui.Offsets{Top: 1, Left: 2, Bottom: 0, Right: 0},
|
|
||||||
Container: activeBookDetails,
|
|
||||||
}},
|
|
||||||
ui.StyleInactive,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
|
|
||||||
// parent container
|
|
||||||
container := ui.NewContainer(
|
|
||||||
ui.Contents{
|
|
||||||
{Container: menu, Offsets: ui.Offsets{Percent: 1}},
|
|
||||||
{Container: activeBook, Offsets: ui.Offsets{Percent: 2}},
|
|
||||||
},
|
|
||||||
ui.LayoutHorizontalPercent,
|
|
||||||
)
|
|
||||||
|
|
||||||
// import pop-up
|
|
||||||
wd, _ := os.Getwd()
|
|
||||||
fileSelector := ui.NewEditableTextLine(wd)
|
|
||||||
fileSelector.ResetCursor(false)
|
|
||||||
fileSelector.SetStyle(ui.StyleActive.Underline(true))
|
|
||||||
popup := ui.NewBox(
|
|
||||||
"import csv file",
|
|
||||||
[]string{"⏎ submit", "(esc)close"},
|
|
||||||
ui.Contents{
|
|
||||||
{Container: fileSelector, Offsets: ui.Offsets{Top: 2, Left: 2}},
|
|
||||||
},
|
|
||||||
ui.StyleActive,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
popup.SetVisible(false)
|
|
||||||
|
|
||||||
// error pop-up
|
|
||||||
errorMessage := ui.NewEditableTextLine("")
|
|
||||||
errorPopup := ui.NewBox(
|
|
||||||
"error",
|
|
||||||
[]string{"⏎ close"},
|
|
||||||
ui.Contents{
|
|
||||||
{Container: errorMessage, Offsets: ui.Offsets{Top: 1, Left: 1}},
|
|
||||||
},
|
|
||||||
ui.StyleActive.Bold(true).Foreground(tcell.ColorRed),
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
errorPopup.SetVisible(false)
|
|
||||||
|
|
||||||
// init
|
|
||||||
screen.Clear()
|
|
||||||
w, h := screen.Size()
|
|
||||||
container.SetSize(0, 0, h, w)
|
|
||||||
container.Draw(screen)
|
|
||||||
screen.Sync()
|
|
||||||
|
|
||||||
// init UI state
|
|
||||||
state.Set("ui_state", IN_MENU)
|
|
||||||
screen.PostEvent(NewEventLoadBook(l.SelectedID()))
|
|
||||||
|
|
||||||
// UI loop
|
|
||||||
for {
|
|
||||||
e := screen.PollEvent()
|
|
||||||
switch v := e.(type) {
|
|
||||||
case *tcell.EventError:
|
|
||||||
fmt.Fprintf(os.Stderr, "%v", v)
|
|
||||||
screen.Beep()
|
|
||||||
case *tcell.EventKey: // input handling
|
|
||||||
curr := state.Get("ui_state").(int)
|
|
||||||
if curr == IN_MENU {
|
|
||||||
if v.Key() == tcell.KeyUp && l.Selected() > 0 {
|
|
||||||
l.SetSelected(l.Selected() - 1)
|
|
||||||
screen.PostEvent(NewEventLoadBook(l.SelectedID()))
|
|
||||||
}
|
|
||||||
if v.Key() == tcell.KeyDown && l.Selected() < len(l.ListMembers())-1 {
|
|
||||||
l.SetSelected(l.Selected() + 1)
|
|
||||||
screen.PostEvent(NewEventLoadBook(l.SelectedID()))
|
|
||||||
}
|
|
||||||
if v.Key() == tcell.KeyEnter {
|
|
||||||
screen.PostEvent(NewEventEnterBook())
|
|
||||||
}
|
|
||||||
if v.Rune() == 'i' {
|
|
||||||
screen.PostEvent(NewEventOpenImport())
|
|
||||||
}
|
|
||||||
if v.Rune() == 'q' {
|
|
||||||
screen.PostEvent(NewEventQuit())
|
|
||||||
}
|
|
||||||
} else if curr == IN_BOOK {
|
|
||||||
if v.Key() == tcell.KeyEsc {
|
|
||||||
screen.PostEvent(NewEventExitBook())
|
|
||||||
}
|
|
||||||
} else if curr == IN_IMPORT {
|
|
||||||
if v.Key() == tcell.KeyEsc {
|
|
||||||
fileSelector.SetText(wd)
|
|
||||||
fileSelector.ResetCursor(false)
|
|
||||||
screen.PostEvent(NewEventCloseImport())
|
|
||||||
}
|
|
||||||
if v.Key() == tcell.KeyBackspace || v.Key() == tcell.KeyBackspace2 {
|
|
||||||
fileSelector.DeleteAtCursor()
|
|
||||||
} else if v.Key() == tcell.KeyRight {
|
|
||||||
fileSelector.MoveCursor(1)
|
|
||||||
|
|
||||||
} else if v.Key() == tcell.KeyLeft {
|
|
||||||
fileSelector.MoveCursor(-1)
|
|
||||||
} else if v.Key() == tcell.KeyEnter {
|
|
||||||
screen.PostEvent(NewEventAttemptImport(fileSelector.Text()))
|
|
||||||
} else if v.Rune() != 0 {
|
|
||||||
fileSelector.InsertAtCursor(v.Rune())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case *tcell.EventResize: // screen redraw
|
|
||||||
w, h := screen.Size()
|
|
||||||
container.SetSize(0, 0, h, w)
|
|
||||||
case *EventBookUpdate:
|
|
||||||
// TK
|
|
||||||
case *EventEnterBook:
|
|
||||||
activeBook.SetStyle(ui.StyleActive)
|
|
||||||
menu.SetStyle(ui.StyleInactive)
|
|
||||||
state.Set("ui_state", IN_BOOK)
|
|
||||||
case *EventExitBook:
|
|
||||||
state.Set("ui_state", IN_MENU)
|
|
||||||
activeBook.SetStyle(ui.StyleInactive)
|
|
||||||
menu.SetStyle(ui.StyleActive)
|
|
||||||
case *EventLoadBook:
|
|
||||||
activeBookDetails.SetBook(GetBookByID(v.ID, books))
|
|
||||||
case *EventOpenImport:
|
|
||||||
state.Set("ui_state", IN_IMPORT)
|
|
||||||
menu.SetStyle(ui.StyleInactive)
|
|
||||||
popup.SetVisible(true)
|
|
||||||
popup.SetSize(6, 3, 5, 80)
|
|
||||||
case *EventAttemptImport:
|
|
||||||
// this will block other events, but it shouldn't take too long...
|
|
||||||
f, err := os.Open(v.filename)
|
|
||||||
if err != nil {
|
|
||||||
screen.PostEvent(NewEventError(err))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
books, err := importer.CSVToBooks(f)
|
|
||||||
if err != nil {
|
|
||||||
screen.PostEvent(NewEventError(err))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for b := range books {
|
|
||||||
err = lib.AddBook(context.Background(), &books[b])
|
|
||||||
if err != nil {
|
|
||||||
screen.PostEvent(NewEventError(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
screen.PostEvent(NewEventCloseImport())
|
|
||||||
allbooks, err := lib.GetAllBooks(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
screen.PostEvent(NewEventError(err))
|
|
||||||
}
|
|
||||||
state.Set("library", allbooks)
|
|
||||||
state.Set("ui_state", IN_MENU)
|
|
||||||
case *EventCloseImport:
|
|
||||||
state.Set("ui_state", IN_MENU)
|
|
||||||
screen.HideCursor()
|
|
||||||
menu.SetStyle(ui.StyleActive)
|
|
||||||
popup.SetVisible(false)
|
|
||||||
case *EventError:
|
|
||||||
errorMessage.SetText(v.err.Error())
|
|
||||||
errorPopup.SetVisible(true)
|
|
||||||
case *EventQuit:
|
|
||||||
screen.Fini()
|
|
||||||
fmt.Printf("Thank you for playing Wing Commander!\n\n")
|
|
||||||
return
|
|
||||||
case *tcell.EventInterrupt:
|
|
||||||
case *tcell.EventMouse:
|
|
||||||
case *tcell.EventTime:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
// repaint
|
|
||||||
l.SetMembers(Titles(state.Get("library").([]media.Book)))
|
|
||||||
container.Draw(screen)
|
|
||||||
popup.Draw(screen)
|
|
||||||
errorPopup.Draw(screen)
|
|
||||||
screen.Show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Titles(lb []media.Book) []ui.ListKeyValue {
|
|
||||||
r := []ui.ListKeyValue{}
|
|
||||||
for i := range lb {
|
|
||||||
r = append(r, ui.ListKeyValue{
|
|
||||||
Key: lb[i].ID,
|
|
||||||
Value: lb[i].Title,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetBookByID(id int, lb []media.Book) *media.Book {
|
|
||||||
for i := range lb {
|
|
||||||
if lb[i].ID == id {
|
|
||||||
return &lb[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &media.Book{}
|
|
||||||
}
|
|
||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
"git.yetaga.in/alazyreader/library/media"
|
"git.yetaga.in/alazyreader/library/media"
|
||||||
"git.yetaga.in/alazyreader/library/query"
|
"git.yetaga.in/alazyreader/library/query"
|
||||||
"github.com/kelseyhightower/envconfig"
|
"github.com/kelseyhightower/envconfig"
|
||||||
|
_ "golang.org/x/crypto/x509roots/fallback"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
"tailscale.com/tsnet"
|
"tailscale.com/tsnet"
|
||||||
"tailscale.com/util/must"
|
"tailscale.com/util/must"
|
||||||
|
|||||||
+2
-2
@@ -221,8 +221,8 @@ func (m *MySQL) UpdateBook(ctx context.Context, old, new *media.Book) error {
|
|||||||
res, err := m.connection.ExecContext(ctx, `
|
res, err := m.connection.ExecContext(ctx, `
|
||||||
UPDATE `+m.tableName+`
|
UPDATE `+m.tableName+`
|
||||||
SET
|
SET
|
||||||
id=? title=? authors=? sortauthor=? isbn10=? isbn13=? format=? genre=? publisher=?
|
title=?, authors=?, sortauthor=?, isbn10=?, isbn13=?, format=?, genre=?, publisher=?,
|
||||||
series=? volume=? year=? signed=? description=? notes=? coverurl=? childrens=?
|
series=?, volume=?, year=?, signed=?, description=?, notes=?, coverurl=?, childrens=?
|
||||||
WHERE id=?`,
|
WHERE id=?`,
|
||||||
new.Title, strings.Join(new.Authors, ";"), new.SortAuthor, new.ISBN10, new.ISBN13, new.Format, new.Genre, new.Publisher,
|
new.Title, strings.Join(new.Authors, ";"), new.SortAuthor, new.ISBN10, new.ISBN13, new.Format, new.Genre, new.Publisher,
|
||||||
new.Series, new.Volume, new.Year, new.Signed, new.Description, new.Notes, new.CoverURL, new.Childrens, old.ID,
|
new.Series, new.Volume, new.Year, new.Signed, new.Description, new.Notes, new.CoverURL, new.Childrens, old.ID,
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ func (c *DiscogsCache) loadRecordsFromFS(ctx context.Context) ([]media.Record, t
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, time.Time{}, fmt.Errorf("error opening cache file %s: %w", c.persistFile, err)
|
return nil, time.Time{}, fmt.Errorf("error opening cache file %s: %w", c.persistFile, err)
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
err = gob.NewDecoder(f).Decode(p)
|
err = gob.NewDecoder(f).Decode(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, time.Time{}, fmt.Errorf("error readhing from cache file %s: %w", c.persistFile, err)
|
return nil, time.Time{}, fmt.Errorf("error readhing from cache file %s: %w", c.persistFile, err)
|
||||||
@@ -120,6 +121,7 @@ func (c *DiscogsCache) saveRecordsToCache(ctx context.Context, records []media.R
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error opening cache file %s: %w", c.persistFile, err)
|
return fmt.Errorf("error opening cache file %s: %w", c.persistFile, err)
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
err = gob.NewEncoder(f).Encode(p)
|
err = gob.NewEncoder(f).Encode(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error writing to cache file %s: %w", c.persistFile, err)
|
return fmt.Errorf("error writing to cache file %s: %w", c.persistFile, err)
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
version: "3.8"
|
version: "3.8"
|
||||||
services:
|
services:
|
||||||
mysql:
|
mysql:
|
||||||
image: mysql:9.0
|
image: mysql:26.7
|
||||||
ports:
|
ports:
|
||||||
- 3306:3306
|
- 3306:3306
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
+12
-8
@@ -72,6 +72,8 @@ function renderAddBookView() {
|
|||||||
volume: document.getElementById("volume").value,
|
volume: document.getElementById("volume").value,
|
||||||
year: document.getElementById("year").value,
|
year: document.getElementById("year").value,
|
||||||
coverURL: document.getElementById("coverURL").value,
|
coverURL: document.getElementById("coverURL").value,
|
||||||
|
childrens: document.getElementById("childrens").checked,
|
||||||
|
signed: document.getElementById("signed").checked,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -114,8 +116,8 @@ function renderTable(bookList, sortField) {
|
|||||||
}
|
}
|
||||||
bookList.sort((one, two) =>
|
bookList.sort((one, two) =>
|
||||||
(one[sortState.sortBy] + one["sortTitle"]).localeCompare(
|
(one[sortState.sortBy] + one["sortTitle"]).localeCompare(
|
||||||
two[sortState.sortBy] + two["sortTitle"]
|
two[sortState.sortBy] + two["sortTitle"],
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
if (sortState.sortOrder === "desc") {
|
if (sortState.sortOrder === "desc") {
|
||||||
bookList.reverse();
|
bookList.reverse();
|
||||||
@@ -135,7 +137,7 @@ function renderTable(bookList, sortField) {
|
|||||||
row.addEventListener("click", (e) => {
|
row.addEventListener("click", (e) => {
|
||||||
// add listener to swap current book
|
// add listener to swap current book
|
||||||
document.getElementById("current").innerHTML = BookTemplate(
|
document.getElementById("current").innerHTML = BookTemplate(
|
||||||
bookList[e.currentTarget.id]
|
bookList[e.currentTarget.id],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -146,7 +148,7 @@ function renderTable(bookList, sortField) {
|
|||||||
// only add callback when there's a sortBy attribute
|
// only add callback when there's a sortBy attribute
|
||||||
renderTable(bookList, e.target.dataset.sortBy);
|
renderTable(bookList, e.target.dataset.sortBy);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
// mark currently active column
|
// mark currently active column
|
||||||
bookElement
|
bookElement
|
||||||
@@ -187,7 +189,7 @@ function search(searchBy, includeChildrensBooks) {
|
|||||||
return inSearch && !childrens;
|
return inSearch && !childrens;
|
||||||
}
|
}
|
||||||
return inSearch;
|
return inSearch;
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +220,7 @@ function clearAddBookForm() {
|
|||||||
document
|
document
|
||||||
.getElementById("newBookForm")
|
.getElementById("newBookForm")
|
||||||
.childNodes.forEach((node) =>
|
.childNodes.forEach((node) =>
|
||||||
node.nodeName === "LABEL" ? (node.lastChild.value = "") : null
|
node.nodeName === "LABEL" ? (node.lastChild.value = "") : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +267,9 @@ function TableRowTemplate({
|
|||||||
return `<tr class="tRow" id="${rowNumber}">
|
return `<tr class="tRow" id="${rowNumber}">
|
||||||
<td class="title">
|
<td class="title">
|
||||||
${title} ${
|
${title} ${
|
||||||
signed ? '<span class="signed" title="Signed by the author" >✒</span>' : ""
|
signed
|
||||||
|
? '<span class="signed" title="Signed by the author" >✒</span>'
|
||||||
|
: ""
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td class="author">${authors}</td>
|
<td class="author">${authors}</td>
|
||||||
@@ -312,7 +316,7 @@ function AddBookTemplate() {
|
|||||||
type="${field.type}"
|
type="${field.type}"
|
||||||
name="${field.name.toLowerCase()}"
|
name="${field.name.toLowerCase()}"
|
||||||
id="${field.id}"
|
id="${field.id}"
|
||||||
/></label><br/>`
|
/></label><br/>`,
|
||||||
);
|
);
|
||||||
}, "")}
|
}, "")}
|
||||||
<input id="lookup" type="submit" value="look up">
|
<input id="lookup" type="submit" value="look up">
|
||||||
|
|||||||
@@ -1,94 +1,58 @@
|
|||||||
module git.yetaga.in/alazyreader/library
|
module git.yetaga.in/alazyreader/library
|
||||||
|
|
||||||
go 1.24.1
|
go 1.27.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.yetaga.in/alazyreader/go-openlibrary v0.0.1
|
git.yetaga.in/alazyreader/go-openlibrary v0.0.1
|
||||||
github.com/gdamore/tcell/v2 v2.8.1
|
github.com/go-sql-driver/mysql v1.10.1
|
||||||
github.com/go-sql-driver/mysql v1.9.1
|
|
||||||
github.com/irlndts/go-discogs v0.3.6
|
github.com/irlndts/go-discogs v0.3.6
|
||||||
github.com/kelseyhightower/envconfig v1.4.0
|
github.com/kelseyhightower/envconfig v1.4.0
|
||||||
golang.org/x/sync v0.13.0
|
golang.org/x/crypto/x509roots/fallback v0.0.0-20260921070245-7a4a4d6beae2
|
||||||
tailscale.com v1.82.0
|
golang.org/x/sync v0.23.0
|
||||||
|
tailscale.com v1.102.4
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
filippo.io/edwards25519 v1.2.0 // indirect
|
||||||
github.com/akutz/memconn v0.1.0 // indirect
|
github.com/akutz/memconn v0.1.0 // indirect
|
||||||
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect
|
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect
|
||||||
github.com/aws/aws-sdk-go-v2 v1.36.0 // indirect
|
github.com/coder/websocket v1.8.14 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.29.5 // indirect
|
github.com/creachadair/msync v0.8.1 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.58 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.27 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.31 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.31 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssm v1.44.7 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.14 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.13 // indirect
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.13 // indirect
|
|
||||||
github.com/aws/smithy-go v1.22.2 // indirect
|
|
||||||
github.com/coder/websocket v1.8.12 // indirect
|
|
||||||
github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6 // indirect
|
|
||||||
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa // indirect
|
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa // indirect
|
||||||
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e // indirect
|
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
github.com/gaissmai/bart v0.26.1 // indirect
|
||||||
github.com/gaissmai/bart v0.18.0 // indirect
|
github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 // indirect
|
||||||
github.com/gdamore/encoding v1.0.1 // indirect
|
github.com/godbus/dbus/v5 v5.2.2 // indirect
|
||||||
github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874 // indirect
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 // indirect
|
github.com/google/go-cmp v0.7.0 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
|
||||||
github.com/google/btree v1.1.2 // indirect
|
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
|
||||||
github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806 // indirect
|
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
|
||||||
github.com/gorilla/csrf v1.7.3-0.20250123201450-9dd6af1f6d30 // indirect
|
|
||||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
|
||||||
github.com/hdevalence/ed25519consensus v0.2.0 // indirect
|
github.com/hdevalence/ed25519consensus v0.2.0 // indirect
|
||||||
github.com/illarion/gonotify/v3 v3.0.2 // indirect
|
github.com/huin/goupnp v1.3.0 // indirect
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 // indirect
|
github.com/jsimonetti/rtnetlink v1.4.1 // indirect
|
||||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
github.com/klauspost/compress v1.19.1 // indirect
|
||||||
github.com/jsimonetti/rtnetlink v1.4.0 // indirect
|
|
||||||
github.com/klauspost/compress v1.17.11 // indirect
|
|
||||||
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a // indirect
|
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
|
||||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
|
||||||
github.com/mdlayher/genetlink v1.3.2 // indirect
|
|
||||||
github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 // indirect
|
github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 // indirect
|
||||||
github.com/mdlayher/sdnotify v1.0.0 // indirect
|
|
||||||
github.com/mdlayher/socket v0.5.0 // indirect
|
github.com/mdlayher/socket v0.5.0 // indirect
|
||||||
github.com/miekg/dns v1.1.58 // indirect
|
|
||||||
github.com/mitchellh/go-ps v1.0.0 // indirect
|
github.com/mitchellh/go-ps v1.0.0 // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
github.com/pires/go-proxyproto v0.8.1 // indirect
|
||||||
github.com/prometheus-community/pro-bing v0.4.0 // indirect
|
|
||||||
github.com/rivo/uniseg v0.4.4 // indirect
|
|
||||||
github.com/safchain/ethtool v0.3.0 // indirect
|
github.com/safchain/ethtool v0.3.0 // indirect
|
||||||
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e // indirect
|
github.com/tailscale/certstore v0.1.1-0.20260409135935-3638fb84b77d // indirect
|
||||||
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 // indirect
|
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 // indirect
|
||||||
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 // indirect
|
github.com/tailscale/hujson v0.0.0-20260302212456-ecc657c15afd // indirect
|
||||||
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a // indirect
|
|
||||||
github.com/tailscale/netlink v1.1.1-0.20240822203006-4d49adab4de7 // indirect
|
|
||||||
github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc // indirect
|
github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc // indirect
|
||||||
github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976 // indirect
|
github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976 // indirect
|
||||||
github.com/tailscale/wireguard-go v0.0.0-20250107165329-0b8b35511f19 // indirect
|
github.com/tailscale/wireguard-go v0.0.0-20260715223240-2e01ba5b00f0 // indirect
|
||||||
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect
|
|
||||||
github.com/vishvananda/netns v0.0.4 // indirect
|
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect
|
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
||||||
golang.org/x/crypto v0.35.0 // indirect
|
golang.org/x/crypto v0.54.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac // indirect
|
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
|
||||||
golang.org/x/mod v0.23.0 // indirect
|
golang.org/x/net v0.56.0 // indirect
|
||||||
golang.org/x/net v0.36.0 // indirect
|
golang.org/x/oauth2 v0.36.0 // indirect
|
||||||
golang.org/x/sys v0.30.0 // indirect
|
golang.org/x/sys v0.47.0 // indirect
|
||||||
golang.org/x/term v0.29.0 // indirect
|
golang.org/x/term v0.45.0 // indirect
|
||||||
golang.org/x/text v0.22.0 // indirect
|
golang.org/x/text v0.40.0 // indirect
|
||||||
golang.org/x/time v0.10.0 // indirect
|
golang.org/x/time v0.15.0 // indirect
|
||||||
golang.org/x/tools v0.30.0 // indirect
|
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
|
golang.zx2c4.com/wireguard/windows v0.5.3 // indirect
|
||||||
gvisor.dev/gvisor v0.0.0-20250205023644-9414b50a5633 // indirect
|
gvisor.dev/gvisor v0.0.0-20260224225140-573d5e7127a8 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,120 +1,125 @@
|
|||||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
9fans.net/go v0.0.8-0.20250307142834-96bdba94b63f h1:1C7nZuxUMNz7eiQALRfiqNOm04+m3edWlRff/BYHf0Q=
|
||||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
9fans.net/go v0.0.8-0.20250307142834-96bdba94b63f/go.mod h1:hHyrZRryGqVdqrknjq5OWDLGCTJ2NeEvtrpR96mjraM=
|
||||||
|
filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
|
||||||
|
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
|
||||||
filippo.io/mkcert v1.4.4 h1:8eVbbwfVlaqUM7OwuftKc2nuYOoTDQWqsoXmzoXZdbc=
|
filippo.io/mkcert v1.4.4 h1:8eVbbwfVlaqUM7OwuftKc2nuYOoTDQWqsoXmzoXZdbc=
|
||||||
filippo.io/mkcert v1.4.4/go.mod h1:VyvOchVuAye3BoUsPUOOofKygVwLV2KQMVFJNRq+1dA=
|
filippo.io/mkcert v1.4.4/go.mod h1:VyvOchVuAye3BoUsPUOOofKygVwLV2KQMVFJNRq+1dA=
|
||||||
git.yetaga.in/alazyreader/go-openlibrary v0.0.1 h1:5juCi8d7YyNxXFvHytQNBww5E6GmPetM7nz3kVUqNQY=
|
git.yetaga.in/alazyreader/go-openlibrary v0.0.1 h1:5juCi8d7YyNxXFvHytQNBww5E6GmPetM7nz3kVUqNQY=
|
||||||
git.yetaga.in/alazyreader/go-openlibrary v0.0.1/go.mod h1:o6zBFJTovdFcpA+As1bRFvk5PDhAs2Lf8iVzUt7dKw8=
|
git.yetaga.in/alazyreader/go-openlibrary v0.0.1/go.mod h1:o6zBFJTovdFcpA+As1bRFvk5PDhAs2Lf8iVzUt7dKw8=
|
||||||
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=
|
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||||
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
github.com/akutz/memconn v0.1.0 h1:NawI0TORU4hcOMsMr11g7vwlCdkYeLKXBcxWu2W/P8A=
|
github.com/akutz/memconn v0.1.0 h1:NawI0TORU4hcOMsMr11g7vwlCdkYeLKXBcxWu2W/P8A=
|
||||||
github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw=
|
github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw=
|
||||||
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
|
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
|
||||||
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.36.0 h1:b1wM5CcE65Ujwn565qcwgtOTT1aT4ADOHHgglKjG7fk=
|
github.com/aws/aws-sdk-go-v2 v1.42.1 h1:9eOTgu1z/dVtYpNZ3/8/XbbaX0x/BqE3HUzAzs6K0ek=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.36.0/go.mod h1:5PMILGVKiW32oDzjj6RU52yrNrDPUHcbZQYr1sM7qmM=
|
github.com/aws/aws-sdk-go-v2 v1.42.1/go.mod h1:5pKeft2eJj+gElQ38Jqg4ibCqh+/AK33/0X3hip7IjM=
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.29.5 h1:4lS2IB+wwkj5J43Tq/AwvnscBerBJtQQ6YS7puzCI1k=
|
github.com/aws/aws-sdk-go-v2/config v1.32.17 h1:FpL4/758/diKwqbytU0prpuiu60fgXKUWCpDJtApclU=
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.29.5/go.mod h1:SNzldMlDVbN6nWxM7XsUiNXPSa1LWlqiXtvh/1PrJGg=
|
github.com/aws/aws-sdk-go-v2/config v1.32.17/go.mod h1:OXqUMzgXytfoF9JaKkhrOYsyh72t9G+MJH8mMRaexOE=
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.58 h1:/d7FUpAPU8Lf2KUdjniQvfNdlMID0Sd9pS23FJ3SS9Y=
|
github.com/aws/aws-sdk-go-v2/credentials v1.19.16 h1:r3RJBuU7X9ibt8RHbMjWE6y60QbKBiII6wSrXnapxSU=
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.58/go.mod h1:aVYW33Ow10CyMQGFgC0ptMRIqJWvJ4nxZb0sUiuQT/A=
|
github.com/aws/aws-sdk-go-v2/credentials v1.19.16/go.mod h1:6cx7zqDENJDbBIIWX6P8s0h6hqHC8Avbjh9Dseo27ug=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.27 h1:7lOW8NUwE9UZekS1DYoiPdVAqZ6A+LheHWb+mHbNOq8=
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23 h1:UuSfcORqNSz/ey3VPRS8TcVH2Ikf0/sC+Hdj400QI6U=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.27/go.mod h1:w1BASFIPOPUae7AgaH4SbjNbfdkxuggLyGfNFTn8ITY=
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23/go.mod h1:+G/OSGiOFnSOkYloKj/9M35s74LgVAdJBSD5lsFfqKg=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.31 h1:lWm9ucLSRFiI4dQQafLrEOmEDGry3Swrz0BIRdiHJqQ=
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.30 h1:xM/Is9cKMHa8Jj8zkvWhvrFkZsXJV9E+BB4g0HW0duQ=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.31/go.mod h1:Huu6GG0YTfbPphQkDSo4dEGmQRTKb9k9G7RdtyQWxuI=
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.30/go.mod h1:WueJeNDZvK1fMYEWJIkcivBfEzUkTpBhzlrUKKY8EuA=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.31 h1:ACxDklUKKXb48+eg5ROZXi1vDgfMyfIA/WyvqHcHI0o=
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.30 h1:jn46zC9LdsVR/ZpMIJqMqb8hHv31BlLx3ulVqNspUOk=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.31/go.mod h1:yadnfsDwqXeVaohbGc/RaD287PuyRw2wugkh5ZL2J6k=
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.30/go.mod h1:1hTMsAgbdS/AtUi4bw8+gUuh1pceo+eXRLfpSuSQj3M=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 h1:Pg9URiobXy85kgFev3og2CuOZ8JZUBENF+dcgWBaYNk=
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 h1:OQqn11BtaYv1WLUowvcA30MpzIu8Ti4pcLPIIyoKZrA=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24/go.mod h1:X5ZJyfwVrWA96GzPmUCWFQaEARPR7gCrpq2E92PJwAE=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 h1:D4oz8/CzT9bAEYtVhSBmFj2dNOtaHOtMKc2vHBwYizA=
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.13 h1:mbRIur/BiHK6SKPjoBIXSE/hJ6g6JGRLuxQy1jGjlN4=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2/go.mod h1:Za3IHqTQ+yNcRHxu1OFucBh0ACZT4j4VQFF0BqpZcLY=
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.13/go.mod h1:ITg9em2KbJx1s0y4aqRX5OYWG6HBZ5TVR//OdpEZ2CQ=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12 h1:O+8vD2rGjfihBewr5bT+QUfYUHIxCVgG61LHoT59shM=
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.30 h1:/Z5jmNrKsSD7EmDjzAPsm/3L9IuOkzaynklJZ1qX7S4=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.12/go.mod h1:usVdWJaosa66NMvmCrr08NcWDBRv4E6+YFG2pUdw1Lk=
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.30/go.mod h1:lEzEZnOosE7zi8Z6royW1cFJTD9fpab4Ul1SBrllewk=
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssm v1.44.7 h1:a8HvP/+ew3tKwSXqL3BCSjiuicr+XTU2eFYeogV9GJE=
|
github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 h1:TdJ+HdzOBhU8+iVAOGUTU63VXopcumCOF1paFulHWZc=
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssm v1.44.7/go.mod h1:Q7XIWsMo0JcMpI/6TGD6XXcXcV1DbTj6e9BKNntIMIM=
|
github.com/aws/aws-sdk-go-v2/service/signin v1.0.11/go.mod h1:R82ZRExE/nheo0N+T8zHPcLRTcH8MGsnR3BiVGX0TwI=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.14 h1:c5WJ3iHz7rLIgArznb3JCSQT3uUMiz9DLZhIX+1G8ok=
|
github.com/aws/aws-sdk-go-v2/service/ssm v1.45.0 h1:IOdss+igJDFdic9w3WKwxGCmHqUxydvIhJOm9LJ32Dk=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.14/go.mod h1:+JJQTxB6N4niArC14YNtxcQtwEqzS3o9Z32n7q33Rfs=
|
github.com/aws/aws-sdk-go-v2/service/ssm v1.45.0/go.mod h1:Q7XIWsMo0JcMpI/6TGD6XXcXcV1DbTj6e9BKNntIMIM=
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.13 h1:f1L/JtUkVODD+k1+IiSJUUv8A++2qVr+Xvb3xWXETMU=
|
github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 h1:7byT8HUWrgoRp6sXjxtZwgOKfhss5fW6SkLBtqzgRoE=
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.13/go.mod h1:tvqlFoja8/s0o+UruA1Nrezo/df0PzdunMDDurUfg6U=
|
github.com/aws/aws-sdk-go-v2/service/sso v1.30.17/go.mod h1:xNWknVi4Ezm1vg1QsB/5EWpAJURq22uqd38U8qKvOJc=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.13 h1:3LXNnmtH3TURctC23hnC0p/39Q5gre3FI7BNOiDcVWc=
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21 h1:+1Kl1zx6bWi4X7cKi3VYh29h8BvsCoHQEQ6ST9X8w7w=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.13/go.mod h1:7Yn+p66q/jt38qMoVfNvjbm3D89mGBnkwDcijgtih8w=
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21/go.mod h1:4vIRDq+CJB2xFAXZ+YgGUTiEft7oAQlhIs71xcSeuVg=
|
||||||
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
|
github.com/aws/aws-sdk-go-v2/service/sts v1.42.1 h1:F/M5Y9I3nwr2IEpshZgh1GeHpOItExNM9L1euNuh/fk=
|
||||||
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
github.com/aws/aws-sdk-go-v2/service/sts v1.42.1/go.mod h1:mTNxImtovCOEEuD65mKW7DCsL+2gjEH+RPEAexAzAio=
|
||||||
github.com/cilium/ebpf v0.15.0 h1:7NxJhNiBT3NG8pZJ3c+yfrVdHY8ScgKD27sScgjLMMk=
|
github.com/aws/smithy-go v1.27.3 h1:F3Zb497UhhskkfpJmfkXswyo+t0sh9OTBnIHjogWbVY=
|
||||||
github.com/cilium/ebpf v0.15.0/go.mod h1:DHp1WyrLeiBh19Cf/tfiSMhqheEiK8fXFZ4No0P1Hso=
|
github.com/aws/smithy-go v1.27.3/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
|
||||||
github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
|
github.com/axiomhq/hyperloglog v0.0.0-20240319100328-84253e514e02 h1:bXAPYSbdYbS5VTy92NIUbeDI1qyggi+JYh5op9IFlcQ=
|
||||||
github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
|
github.com/axiomhq/hyperloglog v0.0.0-20240319100328-84253e514e02/go.mod h1:k08r+Yj1PRAmuayFiRK6MYuR5Ve4IuZtTfxErMIh0+c=
|
||||||
|
github.com/cilium/ebpf v0.16.0 h1:+BiEnHL6Z7lXnlGUsXQPPAE7+kenAd4ES8MQ5min0Ok=
|
||||||
|
github.com/cilium/ebpf v0.16.0/go.mod h1:L7u2Blt2jMM/vLAVgjxluxtBKlz3/GWjB0dMOEngfwE=
|
||||||
|
github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g=
|
||||||
|
github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
|
||||||
github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6 h1:8h5+bWd7R6AYUslN6c6iuZWTKsKxUFDlpnmilO6R2n0=
|
github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6 h1:8h5+bWd7R6AYUslN6c6iuZWTKsKxUFDlpnmilO6R2n0=
|
||||||
github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q=
|
||||||
github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0=
|
github.com/creachadair/mds v0.25.13 h1:PsSUHV6zsfPd29k4kvm1rMoee1YFia7JyNGeMPmDcPM=
|
||||||
github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
|
github.com/creachadair/mds v0.25.13/go.mod h1:4hatI3hRM+qhzuAmqPRFvaBM8mONkS7nsLxkcuTYUIs=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/creachadair/msync v0.8.1 h1:QRd8si3qZ2Q4TaDL7tS/MG/lFE3YND7U7J9fy42eAFM=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
github.com/creachadair/msync v0.8.1/go.mod h1:dt0bscS09J8Ie3AdccK9JpCb7LfStaDGlAmDLukOlY4=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/creachadair/taskgroup v0.13.2 h1:3KyqakBuFsm3KkXi/9XIb0QcA8tEzLHLgaoidf0MdVc=
|
||||||
|
github.com/creachadair/taskgroup v0.13.2/go.mod h1:i3V1Zx7H8RjwljUEeUWYT30Lmb9poewSb2XI1yTwD0g=
|
||||||
|
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
|
||||||
|
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
|
||||||
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa h1:h8TfIT1xc8FWbwwpmHn1J5i43Y0uZP97GqasGCzSRJk=
|
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa h1:h8TfIT1xc8FWbwwpmHn1J5i43Y0uZP97GqasGCzSRJk=
|
||||||
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa/go.mod h1:Nx87SkVqTKd8UtT+xu7sM/l+LgXs6c0aHrlKusR+2EQ=
|
github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa/go.mod h1:Nx87SkVqTKd8UtT+xu7sM/l+LgXs6c0aHrlKusR+2EQ=
|
||||||
|
github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc h1:8WFBn63wegobsYAX0YjD+8suexZDga5CctH4CCTx2+8=
|
||||||
|
github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
||||||
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e h1:vUmf0yezR0y7jJ5pceLHthLaYf4bA5T14B6q39S4q2Q=
|
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e h1:vUmf0yezR0y7jJ5pceLHthLaYf4bA5T14B6q39S4q2Q=
|
||||||
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e/go.mod h1:YTIHhz/QFSYnu/EhlF2SpU2Uk+32abacUYA5ZPljz1A=
|
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e/go.mod h1:YTIHhz/QFSYnu/EhlF2SpU2Uk+32abacUYA5ZPljz1A=
|
||||||
github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c=
|
github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c=
|
||||||
github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0=
|
github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0=
|
||||||
github.com/dsnet/try v0.0.3 h1:ptR59SsrcFUYbT/FhAbKTV6iLkeD6O18qfIWRml2fqI=
|
|
||||||
github.com/dsnet/try v0.0.3/go.mod h1:WBM8tRpUmnXXhY1U6/S8dt6UWdHTQ7y8A5YSkRCkq40=
|
|
||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||||
github.com/gaissmai/bart v0.18.0 h1:jQLBT/RduJu0pv/tLwXE+xKPgtWJejbxuXAR+wLJafo=
|
github.com/gaissmai/bart v0.26.1 h1:+w4rnLGNlA2GDVn382Tfe3jOsK5vOr5n4KmigJ9lbTo=
|
||||||
github.com/gaissmai/bart v0.18.0/go.mod h1:JJzMAhNF5Rjo4SF4jWBrANuJfqY+FvsFhW7t1UZJ+XY=
|
github.com/gaissmai/bart v0.26.1/go.mod h1:GREWQfTLRWz/c5FTOsIw+KkscuFkIV5t8Rp7Nd1Td5c=
|
||||||
github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw=
|
|
||||||
github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo=
|
|
||||||
github.com/gdamore/tcell/v2 v2.8.1 h1:KPNxyqclpWpWQlPLx6Xui1pMk8S+7+R37h3g07997NU=
|
|
||||||
github.com/gdamore/tcell/v2 v2.8.1/go.mod h1:bj8ori1BG3OYMjmb3IklZVWfZUJ1UBQt9JXrOCOhGWw=
|
|
||||||
github.com/github/fakeca v0.1.0 h1:Km/MVOFvclqxPM9dZBC4+QE564nU4gz4iZ0D9pMw28I=
|
github.com/github/fakeca v0.1.0 h1:Km/MVOFvclqxPM9dZBC4+QE564nU4gz4iZ0D9pMw28I=
|
||||||
github.com/github/fakeca v0.1.0/go.mod h1:+bormgoGMMuamOscx7N91aOuUST7wdaJ2rNjeohylyo=
|
github.com/github/fakeca v0.1.0/go.mod h1:+bormgoGMMuamOscx7N91aOuUST7wdaJ2rNjeohylyo=
|
||||||
github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874 h1:F8d1AJ6M9UQCavhwmO6ZsrYLfG8zVFWfEfMS2MXPkSY=
|
github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 h1:vymEbVwYFP/L05h5TKQxvkXoKxNvTpjxYKdF1Nlwuao=
|
||||||
github.com/go-json-experiment/json v0.0.0-20250223041408-d3c622f1b874/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M=
|
github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433/go.mod h1:tphK2c80bpPhMOI4v6bIc2xWywPfbqi1Z06+RcrMkDg=
|
||||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||||
github.com/go-sql-driver/mysql v1.9.1 h1:FrjNGn/BsJQjVRuSa8CBrM5BWA9BWoXXat3KrtSb/iI=
|
github.com/go-sql-driver/mysql v1.10.1 h1:arlSnNLq6a5yxGxV7qg9lF4j0C+KwD6NbQyKr9QL6ME=
|
||||||
github.com/go-sql-driver/mysql v1.9.1/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
github.com/go-sql-driver/mysql v1.10.1/go.mod h1:M+cqaI7+xxXGG9swrdeUIoPG3Y3KCkF0pZej+SK+nWk=
|
||||||
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 h1:sQspH8M4niEijh3PFscJRLDnkL547IeP7kpPe3uUhEg=
|
github.com/go4org/hashtriemap v0.0.0-20251130024219-545ba229f689 h1:0psnKZ+N2IP43/SZC8SKx6OpFJwLmQb9m9QyV9BC2f8=
|
||||||
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466/go.mod h1:ZiQxhyQ+bbbfxUKVvjfO498oPYvtYhZzycal3G/NHmU=
|
github.com/go4org/hashtriemap v0.0.0-20251130024219-545ba229f689/go.mod h1:OGmRfY/9QEK2P5zCRtmqfbCF283xPkU2dvVA4MvbvpI=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
github.com/go4org/plan9netshell v0.0.0-20250324183649-788daa080737 h1:cf60tHxREO3g1nroKr2osU3JWZsJzkfi7rEg+oAB0Lo=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/go4org/plan9netshell v0.0.0-20250324183649-788daa080737/go.mod h1:MIS0jDzbU/vuM9MC4YnBITCv+RYuTRq8dJzmCrFsK9g=
|
||||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
|
||||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
|
github.com/google/go-tpm v0.9.4 h1:awZRf9FwOeTunQmHoDYSHJps3ie6f1UlhS1fOdPEt1I=
|
||||||
|
github.com/google/go-tpm v0.9.4/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||||
github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806 h1:wG8RYIyctLhdFk6Vl1yPGtSRtwGpVkWyZww1OCil2MI=
|
github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806 h1:wG8RYIyctLhdFk6Vl1yPGtSRtwGpVkWyZww1OCil2MI=
|
||||||
github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806/go.mod h1:Beg6V6zZ3oEn0JuiUQ4wqwuyqqzasOltcoXPtgLbFp4=
|
github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806/go.mod h1:Beg6V6zZ3oEn0JuiUQ4wqwuyqqzasOltcoXPtgLbFp4=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/csrf v1.7.3-0.20250123201450-9dd6af1f6d30 h1:fiJdrgVBkjZ5B1HJ2WQwNOaXB+QyYcNXTA3t1XYLz0M=
|
|
||||||
github.com/gorilla/csrf v1.7.3-0.20250123201450-9dd6af1f6d30/go.mod h1:F1Fj3KG23WYHE6gozCmBAezKookxbIvUJT+121wTuLk=
|
|
||||||
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
|
||||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
|
||||||
github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU=
|
github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU=
|
||||||
github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo=
|
github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo=
|
||||||
|
github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
|
||||||
|
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
|
||||||
github.com/illarion/gonotify/v3 v3.0.2 h1:O7S6vcopHexutmpObkeWsnzMJt/r1hONIEogeVNmJMk=
|
github.com/illarion/gonotify/v3 v3.0.2 h1:O7S6vcopHexutmpObkeWsnzMJt/r1hONIEogeVNmJMk=
|
||||||
github.com/illarion/gonotify/v3 v3.0.2/go.mod h1:HWGPdPe817GfvY3w7cx6zkbzNZfi3QjcBm/wgVvEL1U=
|
github.com/illarion/gonotify/v3 v3.0.2/go.mod h1:HWGPdPe817GfvY3w7cx6zkbzNZfi3QjcBm/wgVvEL1U=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA=
|
github.com/insomniacslk/dhcp v0.0.0-20240129002554-15c9b8791914 h1:kD8PseueGeYiid/Mmcv17Q0Qqicc4F46jcX22L/e/Hs=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI=
|
github.com/insomniacslk/dhcp v0.0.0-20240129002554-15c9b8791914/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI=
|
||||||
github.com/irlndts/go-discogs v0.3.6 h1:3oIJEkLGQ1ffJcoo6wvtawPI4/SyHoRpnu25Y51U4wg=
|
github.com/irlndts/go-discogs v0.3.6 h1:3oIJEkLGQ1ffJcoo6wvtawPI4/SyHoRpnu25Y51U4wg=
|
||||||
github.com/irlndts/go-discogs v0.3.6/go.mod h1:UVQ05FdCzH4P/usnSxQDh77QYE37HvmPnSCgogioljo=
|
github.com/irlndts/go-discogs v0.3.6/go.mod h1:UVQ05FdCzH4P/usnSxQDh77QYE37HvmPnSCgogioljo=
|
||||||
github.com/jellydator/ttlcache/v3 v3.1.0 h1:0gPFG0IHHP6xyUyXq+JaD8fwkDCqgqwohXNJBcYE71g=
|
github.com/jellydator/ttlcache/v3 v3.1.0 h1:0gPFG0IHHP6xyUyXq+JaD8fwkDCqgqwohXNJBcYE71g=
|
||||||
github.com/jellydator/ttlcache/v3 v3.1.0/go.mod h1:hi7MGFdMAwZna5n2tuvh63DvFLzVKySzCVW6+0gA2n4=
|
github.com/jellydator/ttlcache/v3 v3.1.0/go.mod h1:hi7MGFdMAwZna5n2tuvh63DvFLzVKySzCVW6+0gA2n4=
|
||||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
github.com/jsimonetti/rtnetlink v1.4.1 h1:JfD4jthWBqZMEffc5RjgmlzpYttAVw1sdnmiNaPO3hE=
|
||||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
github.com/jsimonetti/rtnetlink v1.4.1/go.mod h1:xJjT7t59UIZ62GLZbv6PLLo8VFrostJMPBAheR6OM8w=
|
||||||
github.com/jsimonetti/rtnetlink v1.4.0 h1:Z1BF0fRgcETPEa0Kt0MRk3yV5+kF1FWTni6KUFKrq2I=
|
|
||||||
github.com/jsimonetti/rtnetlink v1.4.0/go.mod h1:5W1jDvWdnthFJ7fxYX1GMK07BUpI4oskfOqvPteYS6E=
|
|
||||||
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
||||||
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
||||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk=
|
||||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||||
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a h1:+RR6SqnTkDLWyICxS1xpjCi/3dhyV+TgZwA6Ww3KncQ=
|
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a h1:+RR6SqnTkDLWyICxS1xpjCi/3dhyV+TgZwA6Ww3KncQ=
|
||||||
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a/go.mod h1:YTtCCM3ryyfiu4F7t8HQ1mxvp1UBdWM2r6Xa+nGWvDk=
|
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a/go.mod h1:YTtCCM3ryyfiu4F7t8HQ1mxvp1UBdWM2r6Xa+nGWvDk=
|
||||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||||
@@ -123,10 +128,6 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
|||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
|
||||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
|
||||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
|
||||||
github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw=
|
github.com/mdlayher/genetlink v1.3.2 h1:KdrNKe+CTu+IbZnm/GVUMXSqBBLqcGpRDa0xkQy56gw=
|
||||||
github.com/mdlayher/genetlink v1.3.2/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o=
|
github.com/mdlayher/genetlink v1.3.2/go.mod h1:tcC3pkCrPUGIKKsCsp0B3AdaaKuHtaxoJRz3cc+528o=
|
||||||
github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 h1:A1Cq6Ysb0GM0tpKMbdCXCIfBclan4oHk1Jb+Hrejirg=
|
github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 h1:A1Cq6Ysb0GM0tpKMbdCXCIfBclan4oHk1Jb+Hrejirg=
|
||||||
@@ -143,40 +144,32 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
|
|||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
github.com/pierrec/lz4/v4 v4.1.26 h1:GrpZw1gZttORinvzBdXPUXATeqlJjqUG/D87TKMnhjY=
|
||||||
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
github.com/pierrec/lz4/v4 v4.1.26/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4=
|
||||||
|
github.com/pires/go-proxyproto v0.8.1 h1:9KEixbdJfhrbtjpz/ZwCdWDD2Xem0NZ38qMYaASJgp0=
|
||||||
|
github.com/pires/go-proxyproto v0.8.1/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU=
|
||||||
github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
|
github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
|
||||||
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
|
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/prometheus/common v0.69.0 h1:OA85nJQS/T/MaYh/Q2CcgDKSGWqNIgrBDvDH85CuiNk=
|
||||||
github.com/prometheus-community/pro-bing v0.4.0 h1:YMbv+i08gQz97OZZBwLyvmmQEEzyfyrrjEaAchdy3R4=
|
github.com/prometheus/common v0.69.0/go.mod h1:ZzL3f6u94qUxh9p+tJTrF+FvBS1XXbbRAZCQkytAL0Y=
|
||||||
github.com/prometheus-community/pro-bing v0.4.0/go.mod h1:b7wRYZtCcPmt4Sz319BykUU241rWLe1VFXyiyWK/dH4=
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
|
||||||
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
|
||||||
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
|
||||||
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
|
||||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
|
||||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
|
||||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
|
||||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
|
||||||
github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0=
|
github.com/safchain/ethtool v0.3.0 h1:gimQJpsI6sc1yIqP/y8GYgiXn/NjgvpM0RNoWLVVmP0=
|
||||||
github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=
|
github.com/safchain/ethtool v0.3.0/go.mod h1:SA9BwrgyAqNo7M+uaL6IYbxpm5wk3L7Mm6ocLW+CJUs=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/studio-b12/gowebdav v0.13.0 h1:OcwSg6IQHOFNdYHn3bPOHwSE8looG8N56Y5xTT1asqQ=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/studio-b12/gowebdav v0.13.0/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/tailscale/certstore v0.1.1-0.20260409135935-3638fb84b77d h1:JcGKBZAL7ePLwOhUdN8qGQZlP5GueEiIZwY7R62pejE=
|
||||||
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e h1:PtWT87weP5LWHEY//SWsYkSO3RWRZo4OSWagh3YD2vQ=
|
github.com/tailscale/certstore v0.1.1-0.20260409135935-3638fb84b77d/go.mod h1:XrBNfAFN+pwoWuksbFS9Ccxnopa15zJGgXRFN90l3K4=
|
||||||
github.com/tailscale/certstore v0.1.1-0.20231202035212-d3fa0460f47e/go.mod h1:XrBNfAFN+pwoWuksbFS9Ccxnopa15zJGgXRFN90l3K4=
|
github.com/tailscale/gliderssh v0.3.4-0.20260716005906-1a0f895faf28 h1:Azz5ILxxVsHN/KjIu3wkJPAmmtiijucZw4Ax5Ye8n+s=
|
||||||
|
github.com/tailscale/gliderssh v0.3.4-0.20260716005906-1a0f895faf28/go.mod h1:wn16Km1EZOX4UEAyaZa3dBwfFGOJ7neck40NcwosJUw=
|
||||||
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 h1:Gzfnfk2TWrk8Jj4P4c1a3CtQyMaTVCznlkLZI++hok4=
|
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55 h1:Gzfnfk2TWrk8Jj4P4c1a3CtQyMaTVCznlkLZI++hok4=
|
||||||
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55/go.mod h1:4k4QO+dQ3R5FofL+SanAUZe+/QfeK0+OIuwDIRu2vSg=
|
github.com/tailscale/go-winio v0.0.0-20231025203758-c4f33415bf55/go.mod h1:4k4QO+dQ3R5FofL+SanAUZe+/QfeK0+OIuwDIRu2vSg=
|
||||||
github.com/tailscale/golang-x-crypto v0.0.0-20250218230618-9a281fd8faca h1:ecjHwH73Yvqf/oIdQ2vxAX+zc6caQsYdPzsxNW1J3G8=
|
github.com/tailscale/golang-x-crypto v0.0.0-20260720153645-2ba0bf7866ed h1:uyvHhX1FQada0vVk8CSHa4tJT96EEAkTypaYz8Tq5Nc=
|
||||||
github.com/tailscale/golang-x-crypto v0.0.0-20250218230618-9a281fd8faca/go.mod h1:ikbF+YT089eInTp9f2vmvy4+ZVnW5hzX1q2WknxSprQ=
|
github.com/tailscale/golang-x-crypto v0.0.0-20260720153645-2ba0bf7866ed/go.mod h1:NC3xRCu4UR+m4n6ix8b6oLLbHa820Y0StbOQEdWTDo0=
|
||||||
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 h1:4chzWmimtJPxRs2O36yuGRW3f9SYV+bMTTvMBI0EKio=
|
github.com/tailscale/hujson v0.0.0-20260302212456-ecc657c15afd h1:Rf9uhF1+VJ7ZHqxrG8pJ6YacmHvVCmByDmGbAWCc/gA=
|
||||||
github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05/go.mod h1:PdCqy9JzfWMJf1H5UJW2ip33/d4YkoKN0r67yKH1mG8=
|
github.com/tailscale/hujson v0.0.0-20260302212456-ecc657c15afd/go.mod h1:EbW0wDK/qEUYI0A5bqq0C2kF8JTQwWONmGDBbzsxxHo=
|
||||||
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a h1:SJy1Pu0eH1C29XwJucQo73FrleVK6t4kYz4NVhp34Yw=
|
|
||||||
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a/go.mod h1:DFSS3NAGHthKo1gTlmEcSBiZrRJXi28rLNd/1udP1c8=
|
|
||||||
github.com/tailscale/netlink v1.1.1-0.20240822203006-4d49adab4de7 h1:uFsXVBE9Qr4ZoF094vE6iYTLDl0qCiKzYXlL6UeWObU=
|
github.com/tailscale/netlink v1.1.1-0.20240822203006-4d49adab4de7 h1:uFsXVBE9Qr4ZoF094vE6iYTLDl0qCiKzYXlL6UeWObU=
|
||||||
github.com/tailscale/netlink v1.1.1-0.20240822203006-4d49adab4de7/go.mod h1:NzVQi3Mleb+qzq8VmcWpSkcSYxXIg0DkI6XDzpVkhJ0=
|
github.com/tailscale/netlink v1.1.1-0.20240822203006-4d49adab4de7/go.mod h1:NzVQi3Mleb+qzq8VmcWpSkcSYxXIg0DkI6XDzpVkhJ0=
|
||||||
github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc h1:24heQPtnFR+yfntqhI3oAu9i27nEojcQ4NuBQOo5ZFA=
|
github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc h1:24heQPtnFR+yfntqhI3oAu9i27nEojcQ4NuBQOo5ZFA=
|
||||||
@@ -185,138 +178,77 @@ github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976 h1:U
|
|||||||
github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976/go.mod h1:agQPE6y6ldqCOui2gkIh7ZMztTkIQKH049tv8siLuNQ=
|
github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976/go.mod h1:agQPE6y6ldqCOui2gkIh7ZMztTkIQKH049tv8siLuNQ=
|
||||||
github.com/tailscale/wf v0.0.0-20240214030419-6fbb0a674ee6 h1:l10Gi6w9jxvinoiq15g8OToDdASBni4CyJOdHY1Hr8M=
|
github.com/tailscale/wf v0.0.0-20240214030419-6fbb0a674ee6 h1:l10Gi6w9jxvinoiq15g8OToDdASBni4CyJOdHY1Hr8M=
|
||||||
github.com/tailscale/wf v0.0.0-20240214030419-6fbb0a674ee6/go.mod h1:ZXRML051h7o4OcI0d3AaILDIad/Xw0IkXaHM17dic1Y=
|
github.com/tailscale/wf v0.0.0-20240214030419-6fbb0a674ee6/go.mod h1:ZXRML051h7o4OcI0d3AaILDIad/Xw0IkXaHM17dic1Y=
|
||||||
github.com/tailscale/wireguard-go v0.0.0-20250107165329-0b8b35511f19 h1:BcEJP2ewTIK2ZCsqgl6YGpuO6+oKqqag5HHb7ehljKw=
|
github.com/tailscale/wireguard-go v0.0.0-20260715223240-2e01ba5b00f0 h1:CnIEL2n7Xql6Ux1k+Vu5S5ubDHCT/kxFgkKCY8FjefU=
|
||||||
github.com/tailscale/wireguard-go v0.0.0-20250107165329-0b8b35511f19/go.mod h1:BOm5fXUBFM+m9woLNBoxI9TaBXXhGNP50LX/TGIvGb4=
|
github.com/tailscale/wireguard-go v0.0.0-20260715223240-2e01ba5b00f0/go.mod h1:6SerzcvHWQchKO2BfNdmquA77CHSECZuFl+D9fp4RnI=
|
||||||
github.com/tailscale/xnet v0.0.0-20240729143630-8497ac4dab2e h1:zOGKqN5D5hHhiYUp091JqK7DPCqSARyUfduhGUY8Bek=
|
github.com/tailscale/xnet v0.0.0-20240729143630-8497ac4dab2e h1:zOGKqN5D5hHhiYUp091JqK7DPCqSARyUfduhGUY8Bek=
|
||||||
github.com/tailscale/xnet v0.0.0-20240729143630-8497ac4dab2e/go.mod h1:orPd6JZXXRyuDusYilywte7k094d7dycXXU5YnWsrwg=
|
github.com/tailscale/xnet v0.0.0-20240729143630-8497ac4dab2e/go.mod h1:orPd6JZXXRyuDusYilywte7k094d7dycXXU5YnWsrwg=
|
||||||
github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA=
|
github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA=
|
||||||
github.com/tc-hib/winres v0.2.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk=
|
github.com/tc-hib/winres v0.2.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk=
|
||||||
github.com/u-root/u-root v0.12.0 h1:K0AuBFriwr0w/PGS3HawiAw89e3+MU7ks80GpghAsNs=
|
github.com/u-root/u-root v0.14.0 h1:Ka4T10EEML7dQ5XDvO9c3MBN8z4nuSnGjcd1jmU2ivg=
|
||||||
github.com/u-root/u-root v0.12.0/go.mod h1:FYjTOh4IkIZHhjsd17lb8nYW6udgXdJhG1c0r6u0arI=
|
github.com/u-root/u-root v0.14.0/go.mod h1:hAyZorapJe4qzbLWlAkmSVCJGbfoU9Pu4jpJ1WMluqE=
|
||||||
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM=
|
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM=
|
||||||
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA=
|
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA=
|
||||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
|
||||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
|
||||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
|
||||||
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 h1:Tl++JLUCe4sxGu8cTpDzRLd3tN7US4hOxG5YpKCzkek=
|
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 h1:Tl++JLUCe4sxGu8cTpDzRLd3tN7US4hOxG5YpKCzkek=
|
||||||
go4.org/mem v0.0.0-20240501181205-ae6ca9944745/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g=
|
go4.org/mem v0.0.0-20240501181205-ae6ca9944745/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
golang.org/x/crypto/x509roots/fallback v0.0.0-20260113154411-7d0074ccc6f1 h1:EBHQuS9qI8xJ96+YRgVV2ahFLUYbWpt1rf3wPfXN2wQ=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto/x509roots/fallback v0.0.0-20260113154411-7d0074ccc6f1/go.mod h1:MEIPiCnxvQEjA4astfaKItNwEVZA5Ki+3+nyGbJ5N18=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto/x509roots/fallback v0.0.0-20260902180247-86efde54dc70 h1:VwViOGcd7C8/Gs18efVlMxvUCS0un6KRKBPFEBvpUXg=
|
||||||
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
golang.org/x/crypto/x509roots/fallback v0.0.0-20260902180247-86efde54dc70/go.mod h1:HPze8vhfG6fO06AM+VSvxRm4E3+5Yk375mgrJ5M2z1E=
|
||||||
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
golang.org/x/crypto/x509roots/fallback v0.0.0-20260921070245-7a4a4d6beae2 h1:eZbx26MSkMP0nFHSVwZplOsFCdjlfBz822hYXljWbUo=
|
||||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo7yrN4mVcnkHDYz5vvs=
|
golang.org/x/crypto/x509roots/fallback v0.0.0-20260921070245-7a4a4d6beae2/go.mod h1:HPze8vhfG6fO06AM+VSvxRm4E3+5Yk375mgrJ5M2z1E=
|
||||||
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScyxUhjuVHR3HGaDPMn9rMSUUbxo=
|
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
|
||||||
|
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
|
||||||
golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f h1:phY1HzDcf18Aq9A8KkmRtY9WvOFIxN8wgfvy6Zm1DV8=
|
golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f h1:phY1HzDcf18Aq9A8KkmRtY9WvOFIxN8wgfvy6Zm1DV8=
|
||||||
golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
||||||
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
|
golang.org/x/image v0.41.0 h1:8wS72eGJMJaBxK6okTzd4WaXumUlTVlb753MlsSvTCo=
|
||||||
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
|
golang.org/x/image v0.41.0/go.mod h1:uIc348UZMSvS5Z65CVZ7iDPaNobNFEPeJ4kbqTOszmA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/net v0.56.0 h1:Rw8j/hFzGvJUZwNBXnAtf5sVDVt+65SK2C7IxCxZt5o=
|
||||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/net v0.56.0/go.mod h1:D3Ku6r+V6JROoZK144D2XfMHFcMq/0zSfLelVTCFKec=
|
||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
||||||
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
||||||
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
|
||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
|
||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
|
||||||
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
|
|
||||||
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk=
|
||||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0=
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
|
||||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
|
||||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
|
||||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
|
||||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
|
||||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
|
||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
|
||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
||||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
|
||||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
|
||||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
|
||||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
|
||||||
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
|
|
||||||
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
|
||||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
|
||||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
|
||||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
|
||||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
|
||||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
|
||||||
golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
|
|
||||||
golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
|
||||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
|
||||||
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
|
|
||||||
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||||
|
golang.zx2c4.com/wireguard v0.0.0-20260522210424-ecfc5a8d5446 h1:cqHQ3AycTHvM2R7ikgyX57D+XvtcSnGylsLkOVhta/w=
|
||||||
|
golang.zx2c4.com/wireguard v0.0.0-20260522210424-ecfc5a8d5446/go.mod h1:rpwXGsirqLqN2L0JDJQlwOboGHmptD5ZD6T2VmcqhTw=
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
|
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
|
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
|
||||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gvisor.dev/gvisor v0.0.0-20260224225140-573d5e7127a8 h1:Zy8IV/+FMLxy6j6p87vk/vQGKcdnbprwjTxc8UiUtsA=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gvisor.dev/gvisor v0.0.0-20260224225140-573d5e7127a8/go.mod h1:QkHjoMIBaYtpVufgwv3keYAbln78mBoCuShZrPrer1Q=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
honnef.co/go/tools v0.7.0 h1:w6WUp1VbkqPEgLz4rkBzH/CSU6HkoqNLp6GstyTx3lU=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
honnef.co/go/tools v0.7.0/go.mod h1:pm29oPxeP3P82ISxZDgIYeOaf9ta6Pi0EWvCFoLG2vc=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gvisor.dev/gvisor v0.0.0-20250205023644-9414b50a5633 h1:2gap+Kh/3F47cO6hAu3idFvsJ0ue6TRcEi2IUkv/F8k=
|
|
||||||
gvisor.dev/gvisor v0.0.0-20250205023644-9414b50a5633/go.mod h1:5DMfjtclAbTIjbXqO1qCe2K5GKKxWz2JHvCChuTcJEM=
|
|
||||||
honnef.co/go/tools v0.5.1 h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I=
|
|
||||||
honnef.co/go/tools v0.5.1/go.mod h1:e9irvo83WDG9/irijV44wr3tbhcFeRnfpVlRqVwpzMs=
|
|
||||||
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
|
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
|
||||||
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
||||||
software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k=
|
software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k=
|
||||||
software.sslmate.com/src/go-pkcs12 v0.4.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI=
|
software.sslmate.com/src/go-pkcs12 v0.4.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI=
|
||||||
tailscale.com v1.82.0 h1:pposomel4h6Je4brJydcdc2ixNQWDaZyGr5v5MdRr/o=
|
tailscale.com v1.102.3 h1:M1czCAtMuIcg+2Z+FBPbJyAk3ZEQGEFKnvHthtE1c6M=
|
||||||
tailscale.com v1.82.0/go.mod h1:iU6kohVzG+bP0/5XjqBAnW8/6nSG/Du++bO+x7VJZD0=
|
tailscale.com v1.102.3/go.mod h1:47bv91Xbg4K1p5wti7F1dmKvUVWV5BXF78d9EWJ+d6c=
|
||||||
|
tailscale.com v1.102.4 h1:FcAkb7MgfFFUIUASg18Mv5cAiraxb+eMgOQaOKqKyPo=
|
||||||
|
tailscale.com v1.102.4/go.mod h1:47bv91Xbg4K1p5wti7F1dmKvUVWV5BXF78d9EWJ+d6c=
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ func getPublisher(publishers []client.Publishers) string {
|
|||||||
|
|
||||||
func getAuthors(authors []client.Authors) []string {
|
func getAuthors(authors []client.Authors) []string {
|
||||||
ret := make([]string, len(authors))
|
ret := make([]string, len(authors))
|
||||||
for _, author := range authors {
|
for i, author := range authors {
|
||||||
ret = append(ret, author.Name)
|
ret[i] = author.Name
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|||||||
-156
@@ -1,156 +0,0 @@
|
|||||||
package ui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/gdamore/tcell/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type coord struct {
|
|
||||||
x, y int
|
|
||||||
}
|
|
||||||
|
|
||||||
type MockScreen struct {
|
|
||||||
x, y, h, w int
|
|
||||||
content map[coord]rune
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) Init() error {
|
|
||||||
m.content = map[coord]rune{}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) Fini() {}
|
|
||||||
|
|
||||||
func (m *MockScreen) Clear() {
|
|
||||||
m.content = map[coord]rune{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) Fill(rune, tcell.Style) {}
|
|
||||||
|
|
||||||
func (m *MockScreen) SetCell(x int, y int, style tcell.Style, ch ...rune) {}
|
|
||||||
|
|
||||||
func (m *MockScreen) GetContent(x, y int) (mainc rune, combc []rune, style tcell.Style, width int) {
|
|
||||||
return m.content[coord{x, y}], nil, tcell.StyleDefault, 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) SetContent(x int, y int, mainc rune, combc []rune, style tcell.Style) {
|
|
||||||
m.content[coord{x, y}] = mainc
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) Suspend() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) Resume() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) SetStyle(style tcell.Style) {}
|
|
||||||
|
|
||||||
func (m *MockScreen) SetCursorStyle(style tcell.CursorStyle, colors ...tcell.Color) {}
|
|
||||||
|
|
||||||
func (m *MockScreen) ShowCursor(x int, y int) {}
|
|
||||||
|
|
||||||
func (m *MockScreen) HideCursor() {}
|
|
||||||
|
|
||||||
func (m *MockScreen) Size() (int, int) {
|
|
||||||
return m.h, m.w
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) PollEvent() tcell.Event {
|
|
||||||
return tcell.NewEventError(fmt.Errorf("mock error"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) ChannelEvents(ch chan<- tcell.Event, quit <-chan struct{}) {}
|
|
||||||
|
|
||||||
func (m *MockScreen) HasPendingEvent() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) PostEvent(ev tcell.Event) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) PostEventWait(ev tcell.Event) {}
|
|
||||||
|
|
||||||
func (m *MockScreen) EnableMouse(...tcell.MouseFlags) {}
|
|
||||||
|
|
||||||
func (m *MockScreen) DisableMouse() {}
|
|
||||||
|
|
||||||
func (m *MockScreen) EnablePaste() {}
|
|
||||||
|
|
||||||
func (m *MockScreen) DisablePaste() {}
|
|
||||||
|
|
||||||
func (m *MockScreen) EnableFocus() {}
|
|
||||||
|
|
||||||
func (m *MockScreen) DisableFocus() {}
|
|
||||||
|
|
||||||
func (m *MockScreen) HasMouse() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) Colors() int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) Show() {}
|
|
||||||
|
|
||||||
func (m *MockScreen) Sync() {}
|
|
||||||
|
|
||||||
func (m *MockScreen) CharacterSet() string {
|
|
||||||
return "UTF-8"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) RegisterRuneFallback(r rune, subst string) {}
|
|
||||||
|
|
||||||
func (m *MockScreen) UnregisterRuneFallback(r rune) {}
|
|
||||||
|
|
||||||
func (m *MockScreen) CanDisplay(r rune, checkFallbacks bool) bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) Resize(x, y, h, w int) {
|
|
||||||
m.x, m.y, m.h, m.w = x, y, h, w
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) SetSize(h, w int) {
|
|
||||||
m.h, m.w = h, w
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) HasKey(tcell.Key) bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) Beep() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) SetTitle(string) {}
|
|
||||||
|
|
||||||
func (m *MockScreen) GetClipboard() {}
|
|
||||||
|
|
||||||
func (m *MockScreen) SetClipboard([]byte) {}
|
|
||||||
|
|
||||||
func (m *MockScreen) LockRegion(x, y, width, height int, lock bool) {}
|
|
||||||
|
|
||||||
func (m *MockScreen) Tty() (tcell.Tty, bool) {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockScreen) DumpContents() string {
|
|
||||||
var res string
|
|
||||||
for i := m.y; i < m.h; i++ {
|
|
||||||
str := []rune{}
|
|
||||||
for j := m.x; j < m.w; j++ {
|
|
||||||
r, ok := m.content[coord{x: j, y: i}]
|
|
||||||
if ok {
|
|
||||||
str = append(str, r)
|
|
||||||
} else {
|
|
||||||
str = append(str, ' ')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res = res + string(str) + "\n"
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
@@ -1,616 +0,0 @@
|
|||||||
package ui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.yetaga.in/alazyreader/library/media"
|
|
||||||
"github.com/gdamore/tcell/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Drawable interface {
|
|
||||||
Draw(tcell.Screen)
|
|
||||||
SetSize(x, y, h, w int)
|
|
||||||
SetStyle(tcell.Style)
|
|
||||||
SetVisible(bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Offsets struct {
|
|
||||||
Top int
|
|
||||||
Bottom int
|
|
||||||
Left int
|
|
||||||
Right int
|
|
||||||
Percent int
|
|
||||||
}
|
|
||||||
|
|
||||||
type Contents []struct {
|
|
||||||
Offsets Offsets
|
|
||||||
Container Drawable
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
LayoutUnmanaged = iota
|
|
||||||
LayoutHorizontalEven
|
|
||||||
LayoutVerticalEven
|
|
||||||
LayoutHorizontalPercent
|
|
||||||
LayoutVerticalPercent
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
StyleActive = tcell.Style{}.Foreground(tcell.ColorWhite).Background(tcell.ColorBlack)
|
|
||||||
StyleInactive = tcell.Style{}.Foreground(tcell.ColorGray).Background(tcell.ColorBlack)
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Container has no visible UI of its own, but arranges sub-components on the screen.
|
|
||||||
// layoutMethod manages how subcomponents are organized. If `LayoutUnmanaged`, it just uses the offsets
|
|
||||||
// in contents to paint on the screen. Otherwise, `LayoutHorizontalEven` and `LayoutVerticalEven` will
|
|
||||||
// have it compute even distributions of space for all components either horizontally or vertically,
|
|
||||||
// filling the container.
|
|
||||||
type Container struct {
|
|
||||||
x, y int
|
|
||||||
h, w int
|
|
||||||
layoutMethod int
|
|
||||||
contents Contents
|
|
||||||
visible bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewContainer(contents Contents, layoutMethod int) *Container {
|
|
||||||
return &Container{
|
|
||||||
layoutMethod: layoutMethod,
|
|
||||||
contents: contents,
|
|
||||||
visible: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Container) Draw(s tcell.Screen) {
|
|
||||||
if !c.visible {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := range c.contents {
|
|
||||||
c.contents[i].Container.Draw(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Container) SetSize(x, y, h, w int) {
|
|
||||||
c.x, c.y, c.h, c.w = x, y, h, w
|
|
||||||
carry := 0
|
|
||||||
if c.layoutMethod == LayoutVerticalEven {
|
|
||||||
num := len(c.contents)
|
|
||||||
extra := c.h % num
|
|
||||||
for r := range c.contents {
|
|
||||||
w := c.w
|
|
||||||
h := c.h / num
|
|
||||||
x := c.x
|
|
||||||
y := c.y + (h * r) + carry
|
|
||||||
if extra > 0 { // distribute "extra" space to containers as we have some left
|
|
||||||
h++
|
|
||||||
extra--
|
|
||||||
carry++
|
|
||||||
}
|
|
||||||
c.contents[r].Container.SetSize(x, y, h, w)
|
|
||||||
}
|
|
||||||
} else if c.layoutMethod == LayoutHorizontalEven {
|
|
||||||
num := len(c.contents)
|
|
||||||
extra := c.w % num
|
|
||||||
for r := range c.contents {
|
|
||||||
w := c.w / num
|
|
||||||
h := c.h
|
|
||||||
x := c.x + (w * r) + carry
|
|
||||||
y := c.y
|
|
||||||
if extra > 0 { // distribute "extra" space to containers as we have some left
|
|
||||||
w++
|
|
||||||
extra--
|
|
||||||
carry++
|
|
||||||
}
|
|
||||||
c.contents[r].Container.SetSize(x, y, h, w)
|
|
||||||
}
|
|
||||||
} else if c.layoutMethod == LayoutHorizontalPercent {
|
|
||||||
// first, work out overall distribution
|
|
||||||
total := 0
|
|
||||||
for r := range c.contents {
|
|
||||||
// `0` or negatives are set as minimum
|
|
||||||
if c.contents[r].Offsets.Percent < 1 {
|
|
||||||
total += 1
|
|
||||||
} else {
|
|
||||||
total += c.contents[r].Offsets.Percent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
carry := 0
|
|
||||||
// push around containers
|
|
||||||
for r := range c.contents {
|
|
||||||
ratio := (float64(c.contents[r].Offsets.Percent) / float64(total))
|
|
||||||
w := int(float64(c.w) * ratio)
|
|
||||||
h := c.h
|
|
||||||
x := c.x + carry
|
|
||||||
y := c.y
|
|
||||||
carry += w
|
|
||||||
// and add any remaining space to the last container
|
|
||||||
if r == len(c.contents)-1 {
|
|
||||||
w += (c.w - carry)
|
|
||||||
}
|
|
||||||
c.contents[r].Container.SetSize(x, y, h, w)
|
|
||||||
}
|
|
||||||
} else if c.layoutMethod == LayoutVerticalPercent {
|
|
||||||
// first, work out overall distribution
|
|
||||||
total := 0
|
|
||||||
for r := range c.contents {
|
|
||||||
// `0` or negatives are set as minimum
|
|
||||||
if c.contents[r].Offsets.Percent < 1 {
|
|
||||||
total += 1
|
|
||||||
} else {
|
|
||||||
total += c.contents[r].Offsets.Percent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
carry := 0
|
|
||||||
// push around containers
|
|
||||||
for r := range c.contents {
|
|
||||||
ratio := (float64(c.contents[r].Offsets.Percent) / float64(total))
|
|
||||||
w := c.w
|
|
||||||
h := int(float64(c.h) * ratio)
|
|
||||||
x := c.x
|
|
||||||
y := c.y + carry
|
|
||||||
carry += h
|
|
||||||
// and add any remaining space to the last container
|
|
||||||
if r == len(c.contents)-1 {
|
|
||||||
h += (c.h - carry)
|
|
||||||
}
|
|
||||||
c.contents[r].Container.SetSize(x, y, h, w)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for r := range c.contents {
|
|
||||||
x := c.x + c.contents[r].Offsets.Left
|
|
||||||
y := c.y + c.contents[r].Offsets.Top
|
|
||||||
h := c.h - c.contents[r].Offsets.Bottom
|
|
||||||
w := c.w - c.contents[r].Offsets.Right
|
|
||||||
c.contents[r].Container.SetSize(x, y, h, w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Container) SetStyle(s tcell.Style) {
|
|
||||||
// containers have no visible elements to style
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Container) SetVisible(b bool) {
|
|
||||||
c.visible = b
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Container) Contents() Contents {
|
|
||||||
return c.contents
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Container) SetContents(con Contents) {
|
|
||||||
c.contents = con
|
|
||||||
}
|
|
||||||
|
|
||||||
// A Box draws a ASCII box around its contents, with an optional title and footer.
|
|
||||||
type Box struct {
|
|
||||||
x, y int
|
|
||||||
h, w int
|
|
||||||
title Drawable
|
|
||||||
menuItems Drawable
|
|
||||||
contents Contents
|
|
||||||
style tcell.Style
|
|
||||||
cascade bool
|
|
||||||
visible bool
|
|
||||||
transparent bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewBox(title string, menuItems []string, contents Contents, initialStyle tcell.Style, cascade bool) *Box {
|
|
||||||
return &Box{
|
|
||||||
title: NewPaddedText(title),
|
|
||||||
menuItems: NewPaddedText(strings.Join(menuItems, " ")),
|
|
||||||
contents: contents,
|
|
||||||
style: initialStyle,
|
|
||||||
cascade: cascade,
|
|
||||||
visible: true,
|
|
||||||
transparent: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Box) SetSize(x, y, h, w int) {
|
|
||||||
b.x, b.y, b.h, b.w = x, y, h, w
|
|
||||||
b.title.SetSize(b.x+2, b.y, 0, 0)
|
|
||||||
b.menuItems.SetSize(b.x+2, b.y+b.h-1, 0, 0)
|
|
||||||
for c := range b.contents {
|
|
||||||
x := b.x + b.contents[c].Offsets.Left
|
|
||||||
y := b.y + b.contents[c].Offsets.Top
|
|
||||||
h := b.h - b.contents[c].Offsets.Bottom
|
|
||||||
w := b.w - b.contents[c].Offsets.Right
|
|
||||||
b.contents[c].Container.SetSize(x, y, h, w)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Box) Draw(s tcell.Screen) {
|
|
||||||
if !b.visible {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// blank out inner area
|
|
||||||
if !b.transparent {
|
|
||||||
for m := b.x + 1; m < b.x+b.w-1; m++ {
|
|
||||||
for n := b.y + 1; n < b.y+b.h-1; n++ {
|
|
||||||
s.SetContent(m, n, ' ', nil, b.style)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// draw outside bars
|
|
||||||
for m := b.x + 1; m < b.x+b.w-1; m++ {
|
|
||||||
s.SetContent(m, b.y, tcell.RuneHLine, nil, b.style)
|
|
||||||
s.SetContent(m, b.y+b.h-1, tcell.RuneHLine, nil, b.style)
|
|
||||||
}
|
|
||||||
for m := b.y + 1; m < b.y+b.h-1; m++ {
|
|
||||||
s.SetContent(b.x, m, tcell.RuneVLine, nil, b.style)
|
|
||||||
s.SetContent(b.x+b.w-1, m, tcell.RuneVLine, nil, b.style)
|
|
||||||
}
|
|
||||||
s.SetContent(b.x, b.y, tcell.RuneULCorner, nil, b.style)
|
|
||||||
s.SetContent(b.x+b.w-1, b.y, tcell.RuneURCorner, nil, b.style)
|
|
||||||
s.SetContent(b.x, b.y+b.h-1, tcell.RuneLLCorner, nil, b.style)
|
|
||||||
s.SetContent(b.x+b.w-1, b.y+b.h-1, tcell.RuneLRCorner, nil, b.style)
|
|
||||||
|
|
||||||
if b.title != nil {
|
|
||||||
b.title.Draw(s)
|
|
||||||
}
|
|
||||||
if b.menuItems != nil {
|
|
||||||
b.menuItems.Draw(s)
|
|
||||||
}
|
|
||||||
for c := range b.contents {
|
|
||||||
b.contents[c].Container.Draw(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Box) SetStyle(s tcell.Style) {
|
|
||||||
b.style = s
|
|
||||||
b.title.SetStyle(s)
|
|
||||||
b.menuItems.SetStyle(s)
|
|
||||||
if b.cascade {
|
|
||||||
for c := range b.contents {
|
|
||||||
b.contents[c].Container.SetStyle(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Box) SetVisible(v bool) {
|
|
||||||
b.visible = v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Box) SetTransparent(v bool) {
|
|
||||||
b.transparent = v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Box) Contents() Contents {
|
|
||||||
return b.contents
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Box) SetContents(c Contents) {
|
|
||||||
b.contents = c
|
|
||||||
}
|
|
||||||
|
|
||||||
// A List is a scrollable, pageable list with a selector token.
|
|
||||||
type List struct {
|
|
||||||
x, y int
|
|
||||||
h, w int
|
|
||||||
selected int
|
|
||||||
listItems []ListKeyValue
|
|
||||||
style tcell.Style
|
|
||||||
visible bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type ListKeyValue struct {
|
|
||||||
Key int
|
|
||||||
Value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewList(listItems []ListKeyValue, initialSelected int) *List {
|
|
||||||
return &List{
|
|
||||||
listItems: listItems,
|
|
||||||
selected: initialSelected,
|
|
||||||
visible: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *List) SetSize(x, y, h, w int) {
|
|
||||||
l.x, l.y, l.h, l.w = x, y, h, w
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *List) Draw(s tcell.Screen) {
|
|
||||||
if !l.visible {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for i := range l.listItems {
|
|
||||||
for j, r := range l.listItems[i].Value {
|
|
||||||
s.SetContent(l.x+j, l.y+i, r, nil, l.style)
|
|
||||||
}
|
|
||||||
if i == l.selected {
|
|
||||||
s.SetContent(l.x+len(l.listItems[i].Value)+1, l.y+i, '<', nil, l.style)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *List) SetVisible(b bool) {
|
|
||||||
l.visible = b
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *List) SetStyle(s tcell.Style) {
|
|
||||||
l.style = s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *List) Selected() int {
|
|
||||||
return l.selected
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *List) SelectedID() int {
|
|
||||||
if l.listItems == nil || len(l.listItems) == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return l.listItems[l.selected].Key
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *List) SetSelected(i int) {
|
|
||||||
l.selected = i
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *List) ListMembers() []ListKeyValue {
|
|
||||||
return l.listItems
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *List) SetMembers(lkv []ListKeyValue) {
|
|
||||||
l.listItems = lkv
|
|
||||||
}
|
|
||||||
|
|
||||||
// BookDetails displays an editable list of book details
|
|
||||||
type BookDetails struct {
|
|
||||||
x, y int
|
|
||||||
h, w int
|
|
||||||
book *media.Book
|
|
||||||
style tcell.Style
|
|
||||||
visible bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewBookDetails(b *media.Book) *BookDetails {
|
|
||||||
return &BookDetails{
|
|
||||||
book: b,
|
|
||||||
visible: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *BookDetails) SetBook(b *media.Book) {
|
|
||||||
l.book = b
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *BookDetails) SetSize(x, y, h, w int) {
|
|
||||||
l.x, l.y, l.h, l.w = x, y, h, w
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *BookDetails) Draw(s tcell.Screen) {
|
|
||||||
if l.book == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !l.visible {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
items := []struct {
|
|
||||||
label string
|
|
||||||
value string
|
|
||||||
}{
|
|
||||||
{"Title", l.book.Title},
|
|
||||||
{"Authors", strings.Join(l.book.Authors, ", ")},
|
|
||||||
{"Sort Author", l.book.SortAuthor},
|
|
||||||
{"ISBN-10", l.book.ISBN10},
|
|
||||||
{"ISBN-13", l.book.ISBN13},
|
|
||||||
{"Format", l.book.Format},
|
|
||||||
{"Genre", l.book.Genre},
|
|
||||||
{"Publisher", l.book.Publisher},
|
|
||||||
{"Series", l.book.Series},
|
|
||||||
{"Volume", l.book.Volume},
|
|
||||||
{"Year", l.book.Year},
|
|
||||||
{"Signed", strconv.FormatBool(l.book.Signed)},
|
|
||||||
{"Cover URL", l.book.CoverURL},
|
|
||||||
{"Notes", l.book.Notes},
|
|
||||||
{"Description", l.book.Description},
|
|
||||||
}
|
|
||||||
for i := range items {
|
|
||||||
if i < l.h-2 {
|
|
||||||
kv := NewKeyValue(items[i].label, ": ", items[i].value)
|
|
||||||
kv.SetSize(l.x, l.y+i, 0, 0)
|
|
||||||
kv.SetStyle(l.style)
|
|
||||||
kv.Draw(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *BookDetails) SetVisible(b bool) {
|
|
||||||
l.visible = b
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *BookDetails) SetStyle(s tcell.Style) {
|
|
||||||
l.style = s
|
|
||||||
}
|
|
||||||
|
|
||||||
// PaddedText outputs strings with a space on both sides.
|
|
||||||
// Useful for generating headings, footers, etc. Used by Box.
|
|
||||||
type PaddedText struct {
|
|
||||||
x, y int
|
|
||||||
h, w int
|
|
||||||
text string
|
|
||||||
style tcell.Style
|
|
||||||
visible bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewPaddedText(text string) *PaddedText {
|
|
||||||
return &PaddedText{text: text, visible: true}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PaddedText) SetSize(x, y, _, _ int) {
|
|
||||||
p.x, p.y, p.h, p.w = x, y, 1, len(p.text)+2
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PaddedText) SetStyle(s tcell.Style) {
|
|
||||||
p.style = s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PaddedText) Draw(s tcell.Screen) {
|
|
||||||
if p.text == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !p.visible {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t := p.x
|
|
||||||
s.SetContent(t, p.y, ' ', nil, p.style)
|
|
||||||
t++
|
|
||||||
for _, r := range p.text {
|
|
||||||
s.SetContent(t, p.y, r, nil, p.style)
|
|
||||||
t++
|
|
||||||
}
|
|
||||||
s.SetContent(t, p.y, ' ', nil, p.style)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PaddedText) SetVisible(b bool) {
|
|
||||||
p.visible = b
|
|
||||||
}
|
|
||||||
|
|
||||||
type KeyValue struct {
|
|
||||||
x, y int
|
|
||||||
h, w int
|
|
||||||
key string
|
|
||||||
value string
|
|
||||||
separator string
|
|
||||||
style tcell.Style
|
|
||||||
visible bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewKeyValue(key, separator, value string) *KeyValue {
|
|
||||||
return &KeyValue{
|
|
||||||
key: key,
|
|
||||||
separator: separator,
|
|
||||||
value: value,
|
|
||||||
visible: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *KeyValue) SetSize(x, y, _, _ int) {
|
|
||||||
p.x, p.y, p.h, p.w = x, y, 1, len(p.key)+len(p.separator)+len(p.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *KeyValue) SetStyle(s tcell.Style) {
|
|
||||||
p.style = s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *KeyValue) Draw(s tcell.Screen) {
|
|
||||||
if !p.visible {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for j, r := range p.key {
|
|
||||||
s.SetContent(p.x+j, p.y, r, nil, p.style)
|
|
||||||
}
|
|
||||||
for j, r := range p.separator {
|
|
||||||
s.SetContent(p.x+len(p.key)+j, p.y, r, nil, p.style)
|
|
||||||
}
|
|
||||||
for j, r := range p.value {
|
|
||||||
s.SetContent(p.x+len(p.key)+len(p.separator)+j, p.y, r, nil, p.style)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *KeyValue) SetVisible(b bool) {
|
|
||||||
p.visible = b
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *KeyValue) GetValue() string {
|
|
||||||
return p.value
|
|
||||||
}
|
|
||||||
|
|
||||||
type EditableTextLine struct {
|
|
||||||
x, y int
|
|
||||||
h, w int
|
|
||||||
text string
|
|
||||||
style tcell.Style
|
|
||||||
visible bool
|
|
||||||
cursorPos int
|
|
||||||
showCursor bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEditableTextLine(initialText string) *EditableTextLine {
|
|
||||||
return &EditableTextLine{
|
|
||||||
text: initialText,
|
|
||||||
visible: true,
|
|
||||||
showCursor: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EditableTextLine) SetSize(x, y, _, _ int) {
|
|
||||||
p.x, p.y, p.h, p.w = x, y, 1, len(p.text)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EditableTextLine) SetStyle(s tcell.Style) {
|
|
||||||
p.style = s
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EditableTextLine) Draw(s tcell.Screen) {
|
|
||||||
if !p.visible {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for j, r := range p.text {
|
|
||||||
s.SetContent(p.x+j, p.y, r, nil, p.style)
|
|
||||||
}
|
|
||||||
s.ShowCursor(p.x+p.cursorPos, p.y)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EditableTextLine) SetVisible(b bool) {
|
|
||||||
p.visible = b
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EditableTextLine) SetCursorVisible(b bool) {
|
|
||||||
p.showCursor = b
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EditableTextLine) SetText(t string) {
|
|
||||||
p.text = t
|
|
||||||
if len(p.text) == 0 {
|
|
||||||
p.ResetCursor(true)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.ResetCursor(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EditableTextLine) Text() string {
|
|
||||||
return p.text
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EditableTextLine) ResetCursor(beginning bool) {
|
|
||||||
if beginning {
|
|
||||||
p.cursorPos = 0
|
|
||||||
} else {
|
|
||||||
p.cursorPos = len(p.text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EditableTextLine) InsertAtCursor(r rune) {
|
|
||||||
if len(p.text) == 0 {
|
|
||||||
p.text = string(r)
|
|
||||||
p.cursorPos = 1
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.text = p.text[0:p.cursorPos] + string(r) + p.text[p.cursorPos:len(p.text)]
|
|
||||||
p.cursorPos = p.cursorPos + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EditableTextLine) MoveCursor(i int) {
|
|
||||||
if p.cursorPos+i < 0 {
|
|
||||||
p.cursorPos = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if p.cursorPos+i > len(p.text) {
|
|
||||||
p.cursorPos = len(p.text)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.cursorPos = p.cursorPos + i
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *EditableTextLine) DeleteAtCursor() {
|
|
||||||
if len(p.text) == 0 {
|
|
||||||
p.cursorPos = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.text = p.text[0:p.cursorPos-1] + p.text[p.cursorPos:len(p.text)]
|
|
||||||
p.cursorPos = p.cursorPos - 1
|
|
||||||
}
|
|
||||||
-241
@@ -1,241 +0,0 @@
|
|||||||
package ui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gdamore/tcell/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestContainerOneBox(t *testing.T) {
|
|
||||||
expect := `┌─ box one ────────┐
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
└──────────────────┘
|
|
||||||
`
|
|
||||||
m := &MockScreen{}
|
|
||||||
one := NewBox("box one", nil, Contents{}, tcell.Style{}, false)
|
|
||||||
container := NewContainer(
|
|
||||||
Contents{{Container: one}},
|
|
||||||
LayoutHorizontalEven,
|
|
||||||
)
|
|
||||||
m.Init()
|
|
||||||
m.Resize(0, 0, 5, 20)
|
|
||||||
container.SetSize(0, 0, 5, 20)
|
|
||||||
container.Draw(m)
|
|
||||||
result := m.DumpContents()
|
|
||||||
if result != expect {
|
|
||||||
fmt.Printf("expected:\n%+v", expect)
|
|
||||||
fmt.Printf("actual:\n%+v", result)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContainerTwoBoxesHStack(t *testing.T) {
|
|
||||||
expect := `┌─ one ──┐┌─ two ──┐
|
|
||||||
│ ││ │
|
|
||||||
│ ││ │
|
|
||||||
│ ││ │
|
|
||||||
└────────┘└────────┘
|
|
||||||
`
|
|
||||||
m := &MockScreen{}
|
|
||||||
one := NewBox("one", nil, Contents{}, tcell.Style{}, false)
|
|
||||||
two := NewBox("two", nil, Contents{}, tcell.Style{}, false)
|
|
||||||
container := NewContainer(
|
|
||||||
Contents{{Container: one}, {Container: two}},
|
|
||||||
LayoutHorizontalEven,
|
|
||||||
)
|
|
||||||
m.Init()
|
|
||||||
m.Resize(0, 0, 5, 20)
|
|
||||||
container.SetSize(0, 0, 5, 20)
|
|
||||||
container.Draw(m)
|
|
||||||
result := m.DumpContents()
|
|
||||||
if result != expect {
|
|
||||||
fmt.Printf("expected:\n%+v", expect)
|
|
||||||
fmt.Printf("actual:\n%+v", result)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContainerThreeBoxesUnevenHStack(t *testing.T) {
|
|
||||||
expect := `┌─ one ──┐┌─ two ──┐┌─ three
|
|
||||||
│ ││ ││ │
|
|
||||||
│ ││ ││ │
|
|
||||||
│ ││ ││ │
|
|
||||||
└────────┘└────────┘└───────┘
|
|
||||||
`
|
|
||||||
m := &MockScreen{}
|
|
||||||
one := NewBox("one", nil, Contents{}, tcell.Style{}, false)
|
|
||||||
two := NewBox("two", nil, Contents{}, tcell.Style{}, false)
|
|
||||||
three := NewBox("three", nil, Contents{}, tcell.Style{}, false)
|
|
||||||
container := NewContainer(
|
|
||||||
Contents{{Container: one}, {Container: two}, {Container: three}},
|
|
||||||
LayoutHorizontalEven,
|
|
||||||
)
|
|
||||||
m.Init()
|
|
||||||
m.Resize(0, 0, 5, 29)
|
|
||||||
container.SetSize(0, 0, 5, 29)
|
|
||||||
container.Draw(m)
|
|
||||||
result := m.DumpContents()
|
|
||||||
if result != expect {
|
|
||||||
fmt.Printf("expected:\n%+v", expect)
|
|
||||||
fmt.Printf("actual:\n%+v", result)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContainerTwoBoxesHPercentStack(t *testing.T) {
|
|
||||||
expect := `┌─ one ──────┐┌─ two ┐
|
|
||||||
│ ││ │
|
|
||||||
│ ││ │
|
|
||||||
│ ││ │
|
|
||||||
└────────────┘└──────┘
|
|
||||||
`
|
|
||||||
m := &MockScreen{}
|
|
||||||
one := NewBox("one", nil, Contents{}, tcell.Style{}, false)
|
|
||||||
two := NewBox("two", nil, Contents{}, tcell.Style{}, false)
|
|
||||||
container := NewContainer(
|
|
||||||
Contents{
|
|
||||||
{Container: one, Offsets: Offsets{Percent: 2}},
|
|
||||||
{Container: two, Offsets: Offsets{Percent: 1}}},
|
|
||||||
LayoutHorizontalPercent,
|
|
||||||
)
|
|
||||||
m.Init()
|
|
||||||
m.Resize(0, 0, 5, 22)
|
|
||||||
container.SetSize(0, 0, 5, 22)
|
|
||||||
container.Draw(m)
|
|
||||||
result := m.DumpContents()
|
|
||||||
if result != expect {
|
|
||||||
fmt.Printf("expected:\n%+v", expect)
|
|
||||||
fmt.Printf("actual:\n%+v", result)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContainerTwoBoxesVStack(t *testing.T) {
|
|
||||||
expect := `┌─ one ──┐
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
└────────┘
|
|
||||||
┌─ two ──┐
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
└────────┘
|
|
||||||
`
|
|
||||||
m := &MockScreen{}
|
|
||||||
one := NewBox("one", nil, Contents{}, tcell.Style{}, false)
|
|
||||||
two := NewBox("two", nil, Contents{}, tcell.Style{}, false)
|
|
||||||
container := NewContainer(
|
|
||||||
Contents{{Container: one}, {Container: two}},
|
|
||||||
LayoutVerticalEven,
|
|
||||||
)
|
|
||||||
m.Init()
|
|
||||||
m.Resize(0, 0, 10, 10)
|
|
||||||
container.SetSize(0, 0, 10, 10)
|
|
||||||
container.Draw(m)
|
|
||||||
result := m.DumpContents()
|
|
||||||
if result != expect {
|
|
||||||
fmt.Printf("expected:\n%+v", expect)
|
|
||||||
fmt.Printf("actual:\n%+v", result)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContainerTwoBoxesPercentageVStack(t *testing.T) {
|
|
||||||
expect := `┌─ one ──┐
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
└────────┘
|
|
||||||
┌─ two ──┐
|
|
||||||
│ │
|
|
||||||
│ │
|
|
||||||
└────────┘
|
|
||||||
`
|
|
||||||
m := &MockScreen{}
|
|
||||||
one := NewBox("one", nil, Contents{}, tcell.Style{}, false)
|
|
||||||
two := NewBox("two", nil, Contents{}, tcell.Style{}, false)
|
|
||||||
container := NewContainer(
|
|
||||||
Contents{
|
|
||||||
{Container: one, Offsets: Offsets{Percent: 2}},
|
|
||||||
{Container: two, Offsets: Offsets{Percent: 1}}},
|
|
||||||
LayoutVerticalPercent,
|
|
||||||
)
|
|
||||||
m.Init()
|
|
||||||
m.Resize(0, 0, 10, 10)
|
|
||||||
container.SetSize(0, 0, 10, 10)
|
|
||||||
container.Draw(m)
|
|
||||||
result := m.DumpContents()
|
|
||||||
if result != expect {
|
|
||||||
fmt.Printf("expected:\n%+v", expect)
|
|
||||||
fmt.Printf("actual:\n%+v", result)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewEditableTextLine(t *testing.T) {
|
|
||||||
e := NewEditableTextLine("")
|
|
||||||
e.InsertAtCursor('a')
|
|
||||||
e.InsertAtCursor('b')
|
|
||||||
e.InsertAtCursor('c')
|
|
||||||
if e.text != "abc" {
|
|
||||||
fmt.Printf("expected: 'abc', actual: '%+v'", e.text)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
e.MoveCursor(-1)
|
|
||||||
e.InsertAtCursor('d')
|
|
||||||
if e.text != "abdc" {
|
|
||||||
fmt.Printf("expected: 'abdc', actual: '%+v'", e.text)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
e.MoveCursor(-20)
|
|
||||||
e.InsertAtCursor('e')
|
|
||||||
if e.text != "eabdc" {
|
|
||||||
fmt.Printf("expected: 'eabdc', actual: '%+v'", e.text)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
e.MoveCursor(20)
|
|
||||||
e.InsertAtCursor('f')
|
|
||||||
if e.text != "eabdcf" {
|
|
||||||
fmt.Printf("expected: 'eabdcf', actual: '%+v'", e.text)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
e.MoveCursor(1)
|
|
||||||
e.InsertAtCursor('g')
|
|
||||||
if e.text != "eabdcfg" {
|
|
||||||
fmt.Printf("expected: 'eabdcfg', actual: '%+v'", e.text)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
e.DeleteAtCursor()
|
|
||||||
e.DeleteAtCursor()
|
|
||||||
e.MoveCursor(-1)
|
|
||||||
e.DeleteAtCursor()
|
|
||||||
if e.text != "eabc" {
|
|
||||||
fmt.Printf("expected: 'eabc', actual: '%+v'", e.text)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
e.ResetCursor(false)
|
|
||||||
e.InsertAtCursor('h')
|
|
||||||
e.ResetCursor(true)
|
|
||||||
e.InsertAtCursor('g')
|
|
||||||
if e.text != "geabch" {
|
|
||||||
fmt.Printf("expected: 'geabch', actual: '%+v'", e.text)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
e.SetText("the rain in spain")
|
|
||||||
e.InsertAtCursor('s')
|
|
||||||
if e.text != "the rain in spains" {
|
|
||||||
fmt.Printf("expected: 'the rain in spains', actual: '%+v'", e.text)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
e.SetText("")
|
|
||||||
e.InsertAtCursor('s')
|
|
||||||
if e.text != "s" {
|
|
||||||
fmt.Printf("expected: 's', actual: '%+v'", e.text)
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user