tg/screen.go

129 lines
2.3 KiB
Go
Raw Permalink Normal View History

2023-08-19 09:12:26 +03:00
package tg
2023-07-09 01:28:59 +03:00
import (
"path"
)
// The type implements changing screen to the underlying ScreenId
type ScreenGo struct {
Path Path
Args []any
}
func (sc ScreenGo) Act(c *Context) {
c.Go(sc.Path, sc.Args...)
}
// The same as Act.
func (sc ScreenGo) Serve(c *Context) {
sc.Act(c)
}
// Unique identifier for the screen
// and relative paths to the screen.
type Path string
// Returns true if the path is empty.
func (p Path) IsEmpty() bool {
return p == ""
}
// Returns true if the path is absolute.
func (p Path) IsAbs() bool {
if len(p) == 0 {
return false
}
return p[0] == '/'
}
func (p Path) Dir() Path {
return Path(path.Dir(string(p)))
}
// Clean the path deleting exceed ., .. and / .
func (p Path) Clean() Path {
return Path(path.Clean(string(p)))
}
2023-07-09 01:28:59 +03:00
// Screen statement of the bot.
// Mostly what buttons to show.
type Screen struct {
// The widget to run when reaching the screen.
Widget Widget
2023-07-09 01:28:59 +03:00
}
// The first node with the "/" path.
type RootNode struct {
Screen *Screen
Subs []*Node
}
// The node is a simple way to represent
// tree-like structured applications.
type Node struct {
Path Path
Screen *Screen
Subs []*Node
}
// Return new root node with the specified widget in the screen.
func NewRootNode(widget Widget, subs ...*Node) *RootNode {
ret := &RootNode{}
ret.Screen = NewScreen(widget)
ret.Subs = subs
return ret
}
func NewNode(relPath Path, widget Widget, subs ...*Node) *Node {
ret := &Node{}
ret.Path = relPath
ret.Screen = NewScreen(widget)
ret.Subs = subs
return ret
}
func (n *RootNode) ScreenMap() ScreenMap {
m := make(ScreenMap)
var root Path = "/"
m[root] = n.Screen
for _, sub := range n.Subs {
buf := sub.ScreenMap(root)
for k, v := range buf {
_, ok := m[k]
if ok {
panic("duplicate paths in node definition")
}
m[k] = v
}
}
return m
}
func (n *Node) ScreenMap(root Path) ScreenMap {
m := make(ScreenMap)
pth := (root + n.Path).Clean()
m[pth] = n.Screen
for _, sub := range n.Subs {
buf := sub.ScreenMap(pth + "/")
for k, v := range buf {
_, ok := m[k]
if ok {
panic("duplicate paths in node definition")
}
m[k] = v
}
}
return m
}
2023-07-09 01:28:59 +03:00
// Map structure for the screens.
type ScreenMap map[Path] *Screen
2023-07-09 01:28:59 +03:00
// Returns the new screen with specified name and widget.
func NewScreen(widget Widget) *Screen {
return &Screen{
Widget: widget,
2023-07-09 01:28:59 +03:00
}
}