131 lines
2.8 KiB
Go
131 lines
2.8 KiB
Go
package app
|
|
|
|
import (
|
|
_ "embed"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
|
|
"git.sr.ht/~rockorager/vaxis"
|
|
"git.sr.ht/~rockorager/vaxis/widgets/textinput"
|
|
"git.tilde.town/nbsp/directory/ui"
|
|
)
|
|
|
|
//go:embed homepage.txt
|
|
var homepage []byte
|
|
|
|
type App struct {
|
|
allUsers []string
|
|
users ui.List
|
|
filter textinput.Model
|
|
searching bool
|
|
}
|
|
|
|
func New() *App {
|
|
users := []string{"(home)"}
|
|
userDirs, _ := os.ReadDir("/home")
|
|
for _, user := range userDirs {
|
|
if user.IsDir() {
|
|
users = append(users, "~"+user.Name())
|
|
}
|
|
}
|
|
return &App{users: ui.NewList(users, 0), allUsers: users}
|
|
}
|
|
|
|
func (app *App) Event(state *ui.State, event vaxis.Event) {
|
|
if key, ok := event.(vaxis.Key); ok && key.EventType == vaxis.EventPress {
|
|
other := false
|
|
switch key.String() {
|
|
case "Ctrl+c", "Ctrl+d":
|
|
close(ui.Quit)
|
|
case "Down", "Ctrl+n":
|
|
app.users.Down()
|
|
case "Up", "Ctrl+p":
|
|
app.users.Up()
|
|
case "End":
|
|
app.users.End()
|
|
case "Home":
|
|
app.users.Home()
|
|
case "Escape":
|
|
app.searching = false
|
|
default:
|
|
other = true
|
|
}
|
|
if other {
|
|
if !app.searching {
|
|
switch key.String() {
|
|
case "q":
|
|
close(ui.Quit)
|
|
case "j":
|
|
app.users.Down()
|
|
case "k":
|
|
app.users.Up()
|
|
case "g":
|
|
app.users.Home()
|
|
case "Shift+g":
|
|
app.users.End()
|
|
case "/":
|
|
app.searching = true
|
|
app.filter.SetContent("")
|
|
app.users.SetItems(app.allUsers)
|
|
}
|
|
} else {
|
|
app.filter.Update(event)
|
|
app.users.SetItems(filter(app.allUsers, app.filter.String()))
|
|
}
|
|
}
|
|
}
|
|
|
|
// render sidebar
|
|
win := state.Window()
|
|
w, h := win.Size()
|
|
if len(app.users.Items()) > 0 {
|
|
app.users.Draw(win.New(0, 0, 20, h-1))
|
|
}
|
|
|
|
// render search bar
|
|
for x := 0; x < w; x++ {
|
|
setCell(win, x, h-2, '─', vaxis.Style{})
|
|
}
|
|
if app.searching {
|
|
app.filter.Draw(win.New(0, h-1, w, 1))
|
|
} else {
|
|
win.New(0, h-1, w, 1).Print(vaxis.Segment{Text: "press / to search users", Style: vaxis.Style{Foreground: vaxis.IndexColor(8)}})
|
|
}
|
|
|
|
// render page
|
|
if len(app.users.Items()) == 0 {
|
|
return
|
|
}
|
|
main := win.New(20, 0, w, h-2)
|
|
if app.users.Items()[app.users.Index()] == "(home)" {
|
|
// special homepage
|
|
aligned := win.New(main.Width/2, main.Height/2-8, 47, 15)
|
|
aligned.Print(vaxis.Segment{Text: string(homepage)})
|
|
} else {
|
|
// user page
|
|
user := app.users.Items()[app.users.Index()][1:]
|
|
art, _ := exec.Command("figlet", "-f", "script", user).CombinedOutput()
|
|
main.Print(vaxis.Segment{Text: string(art)})
|
|
}
|
|
}
|
|
|
|
func setCell(win vaxis.Window, x int, y int, r rune, st vaxis.Style) {
|
|
win.SetCell(x, y, vaxis.Cell{
|
|
Character: vaxis.Character{
|
|
Grapheme: string([]rune{r}),
|
|
},
|
|
Style: st,
|
|
})
|
|
}
|
|
|
|
func filter(users []string, query string) []string {
|
|
var filtered []string
|
|
for _, s := range users {
|
|
if strings.Contains(s, query) {
|
|
filtered = append(filtered, s)
|
|
}
|
|
}
|
|
return filtered
|
|
}
|