screen.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package tg
  2. import (
  3. "path"
  4. )
  5. // The type implements changing screen to the underlying ScreenId
  6. type ScreenGo struct {
  7. Path Path
  8. Args []any
  9. }
  10. func (sc ScreenGo) Act(c *Context) {
  11. c.Go(sc.Path, sc.Args...)
  12. }
  13. // The same as Act.
  14. func (sc ScreenGo) Serve(c *Context) {
  15. sc.Act(c)
  16. }
  17. // Unique identifier for the screen
  18. // and relative paths to the screen.
  19. type Path string
  20. // Returns true if the path is empty.
  21. func (p Path) IsEmpty() bool {
  22. return p == ""
  23. }
  24. // Returns true if the path is absolute.
  25. func (p Path) IsAbs() bool {
  26. if len(p) == 0 {
  27. return false
  28. }
  29. return p[0] == '/'
  30. }
  31. func (p Path) Dir() Path {
  32. return Path(path.Dir(string(p)))
  33. }
  34. // Clean the path deleting exceed ., .. and / .
  35. func (p Path) Clean() Path {
  36. return Path(path.Clean(string(p)))
  37. }
  38. // Screen statement of the bot.
  39. // Mostly what buttons to show.
  40. type Screen struct {
  41. // The widget to run when reaching the screen.
  42. Widget Widget
  43. }
  44. // The first node with the "/" path.
  45. type RootNode struct {
  46. Screen *Screen
  47. Subs []*Node
  48. }
  49. // The node is a simple way to represent
  50. // tree-like structured applications.
  51. type Node struct {
  52. Path Path
  53. Screen *Screen
  54. Subs []*Node
  55. }
  56. // Return new root node with the specified widget in the screen.
  57. func NewRootNode(widget Widget, subs ...*Node) *RootNode {
  58. ret := &RootNode{}
  59. ret.Screen = NewScreen(widget)
  60. ret.Subs = subs
  61. return ret
  62. }
  63. func NewNode(relPath Path, widget Widget, subs ...*Node) *Node {
  64. ret := &Node{}
  65. ret.Path = relPath
  66. ret.Screen = NewScreen(widget)
  67. ret.Subs = subs
  68. return ret
  69. }
  70. func (n *RootNode) ScreenMap() ScreenMap {
  71. m := make(ScreenMap)
  72. var root Path = "/"
  73. m[root] = n.Screen
  74. for _, sub := range n.Subs {
  75. buf := sub.ScreenMap(root)
  76. for k, v := range buf {
  77. _, ok := m[k]
  78. if ok {
  79. panic("duplicate paths in node definition")
  80. }
  81. m[k] = v
  82. }
  83. }
  84. return m
  85. }
  86. func (n *Node) ScreenMap(root Path) ScreenMap {
  87. m := make(ScreenMap)
  88. pth := (root + n.Path).Clean()
  89. m[pth] = n.Screen
  90. for _, sub := range n.Subs {
  91. buf := sub.ScreenMap(pth + "/")
  92. for k, v := range buf {
  93. _, ok := m[k]
  94. if ok {
  95. panic("duplicate paths in node definition")
  96. }
  97. m[k] = v
  98. }
  99. }
  100. return m
  101. }
  102. // Map structure for the screens.
  103. type ScreenMap map[Path] *Screen
  104. // Returns the new screen with specified name and widget.
  105. func NewScreen(widget Widget) *Screen {
  106. return &Screen{
  107. Widget: widget,
  108. }
  109. }