Finished the node approach to the screens.
This commit is contained in:
parent
061add76a8
commit
7d149558f9
6 changed files with 81 additions and 60 deletions
|
@ -52,6 +52,11 @@ func ExtractSessionData(c *tg.Context) *SessionData {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
startScreenButton = tg.NewButton("Home").Go("/")
|
startScreenButton = tg.NewButton("Home").Go("/")
|
||||||
|
backButton = tg.NewButton("Back").Go("..")
|
||||||
|
backKeyboard = tg.NewKeyboard().Row(
|
||||||
|
backButton,
|
||||||
|
)
|
||||||
|
|
||||||
incDecKeyboard = tg.NewKeyboard().Row(
|
incDecKeyboard = tg.NewKeyboard().Row(
|
||||||
tg.NewButton("+").ActionFunc(func(c *tg.Context) {
|
tg.NewButton("+").ActionFunc(func(c *tg.Context) {
|
||||||
d := ExtractSessionData(c)
|
d := ExtractSessionData(c)
|
||||||
|
@ -70,10 +75,7 @@ var (
|
||||||
navKeyboard = tg.NewKeyboard().Row(
|
navKeyboard = tg.NewKeyboard().Row(
|
||||||
tg.NewButton("Inc/Dec").Go("/inc-dec"),
|
tg.NewButton("Inc/Dec").Go("/inc-dec"),
|
||||||
).Row(
|
).Row(
|
||||||
tg.NewButton("Upper case").ActionFunc(func(c *tg.Context){
|
tg.NewButton("Mutate messages").Go("/mutate-messages"),
|
||||||
c.Go("/upper-case", "this shit", "works")
|
|
||||||
}),
|
|
||||||
tg.NewButton("Lower case").Go("/case"),
|
|
||||||
).Row(
|
).Row(
|
||||||
tg.NewButton("Send location").Go("/send-location"),
|
tg.NewButton("Send location").Go("/send-location"),
|
||||||
).Reply().WithOneTime(true)
|
).Reply().WithOneTime(true)
|
||||||
|
@ -119,6 +121,37 @@ WithInitFunc(func(c *tg.Context) {
|
||||||
navKeyboard.Widget("Choose what you are interested in"),
|
navKeyboard.Widget("Choose what you are interested in"),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
tg.NewNode(
|
||||||
|
"mutate-messages", tg.NewPage().WithReply(
|
||||||
|
tg.NewKeyboard().Row(
|
||||||
|
tg.NewButton("Upper case").Go("upper-case"),
|
||||||
|
tg.NewButton("Lower case").Go("lower-case"),
|
||||||
|
).Row(
|
||||||
|
backButton,
|
||||||
|
).Reply().Widget(
|
||||||
|
"Choose the function to mutate string",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
tg.NewNode(
|
||||||
|
"upper-case", tg.NewPage().WithReply(
|
||||||
|
backKeyboard.Reply().Widget(
|
||||||
|
"Type a string and the bot will convert it to upper case",
|
||||||
|
),
|
||||||
|
).WithSub(
|
||||||
|
NewMutateMessageWidget(strings.ToUpper),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
tg.NewNode(
|
||||||
|
"lower-case", tg.NewPage().WithReply(
|
||||||
|
backKeyboard.Reply().Widget(
|
||||||
|
"Type a string and the bot will convert it to lower case",
|
||||||
|
),
|
||||||
|
).WithSub(
|
||||||
|
NewMutateMessageWidget(strings.ToLower),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
tg.NewNode(
|
tg.NewNode(
|
||||||
"inc-dec", tg.NewPage().WithReply(
|
"inc-dec", tg.NewPage().WithReply(
|
||||||
incDecKeyboard.Reply().Widget("Press the buttons to increment and decrement"),
|
incDecKeyboard.Reply().Widget("Press the buttons to increment and decrement"),
|
||||||
|
@ -129,26 +162,6 @@ WithInitFunc(func(c *tg.Context) {
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
|
||||||
tg.NewNode(
|
|
||||||
"upper-case", tg.NewPage().WithText(
|
|
||||||
"Type text and the bot will send you the upper case version to you",
|
|
||||||
).WithReply(
|
|
||||||
navToStartKeyboard.Widget(""),
|
|
||||||
).WithSub(
|
|
||||||
NewMutateMessageWidget(strings.ToUpper),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
tg.NewNode(
|
|
||||||
"lower-case", tg.NewPage().WithText(
|
|
||||||
"Type text and the bot will send you the lower case version",
|
|
||||||
).WithReply(
|
|
||||||
navToStartKeyboard.Widget(""),
|
|
||||||
).WithSub(
|
|
||||||
NewMutateMessageWidget(strings.ToLower),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
tg.NewNode(
|
tg.NewNode(
|
||||||
"send-location", tg.NewPage().WithReply(
|
"send-location", tg.NewPage().WithReply(
|
||||||
sendLocationKeyboard.Widget("Press the button to send your location!"),
|
sendLocationKeyboard.Widget("Press the button to send your location!"),
|
||||||
|
@ -169,8 +182,7 @@ WithInitFunc(func(c *tg.Context) {
|
||||||
tg.NewCommand("start").
|
tg.NewCommand("start").
|
||||||
Desc("start or restart the bot or move to the start screen").
|
Desc("start or restart the bot or move to the start screen").
|
||||||
ActionFunc(func(c *tg.Context){
|
ActionFunc(func(c *tg.Context){
|
||||||
c.Sendf("Your username is %q", c.Message.From.UserName)
|
c.Go("/")
|
||||||
c.Go("/start")
|
|
||||||
}),
|
}),
|
||||||
tg.NewCommand("hello").
|
tg.NewCommand("hello").
|
||||||
Desc("sends the 'Hello, World!' message back").
|
Desc("sends the 'Hello, World!' message back").
|
||||||
|
@ -227,7 +239,6 @@ func main() {
|
||||||
}
|
}
|
||||||
bot = bot.
|
bot = bot.
|
||||||
WithBehaviour(beh).
|
WithBehaviour(beh).
|
||||||
WithGroupBehaviour(gBeh).
|
|
||||||
Debug(true)
|
Debug(true)
|
||||||
|
|
||||||
bot.Data = &BotData{
|
bot.Data = &BotData{
|
||||||
|
|
|
@ -63,8 +63,11 @@ func (btn *Button) ActionFunc(fn ActionFunc) *Button {
|
||||||
return btn.WithAction(fn)
|
return btn.WithAction(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (btn *Button) Go(sc ScreenChange) *Button {
|
func (btn *Button) Go(pth Path, args ...any) *Button {
|
||||||
return btn.WithAction(sc)
|
return btn.WithAction(ScreenGo{
|
||||||
|
Path: pth,
|
||||||
|
Args: args,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (btn *Button) ToTelegram() apix.KeyboardButton {
|
func (btn *Button) ToTelegram() apix.KeyboardButton {
|
||||||
|
|
|
@ -13,7 +13,7 @@ var (
|
||||||
func initEncoding() {
|
func initEncoding() {
|
||||||
actions := map[string]Action{
|
actions := map[string]Action{
|
||||||
"action-func": ActionFunc(nil),
|
"action-func": ActionFunc(nil),
|
||||||
"screen-change": ScreenChange(""),
|
"screen-change": ScreenGo{},
|
||||||
}
|
}
|
||||||
for k, action := range actions {
|
for k, action := range actions {
|
||||||
DefineAction(k, action)
|
DefineAction(k, action)
|
||||||
|
|
|
@ -143,33 +143,22 @@ func (af ActionFunc) Act(c *Context) {
|
||||||
af(c)
|
af(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The type implements changing screen to the underlying ScreenId
|
|
||||||
type ScreenChange Path
|
|
||||||
|
|
||||||
func (sc ScreenChange) Act(c *Context) {
|
|
||||||
if !c.Bot.behaviour.PathExist(Path(sc)) {
|
|
||||||
panic(ScreenNotExistErr)
|
|
||||||
}
|
|
||||||
err := c.Go(Path(sc))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type C = Context
|
type C = Context
|
||||||
|
|
||||||
// Changes screen of user to the Id one.
|
// Changes screen of user to the Id one.
|
||||||
func (c *Context) Go(pth Path, args ...any) error {
|
func (c *Context) Go(pth Path, args ...any) error {
|
||||||
if !c.PathExist(pth) {
|
|
||||||
return ScreenNotExistErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Getting the screen and changing to
|
// Getting the screen and changing to
|
||||||
// then executing its widget.
|
// then executing its widget.
|
||||||
if !pth.IsAbs() {
|
if !pth.IsAbs() {
|
||||||
pth = (c.Path() + "/" + pth).Clean()
|
pth = (c.Path() + "/" + pth).Clean()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.Sendf("path: %q\nmap: %v", pth, c.Bot.behaviour.Screens)
|
||||||
|
|
||||||
|
if !c.PathExist(pth) {
|
||||||
|
return ScreenNotExistErr
|
||||||
|
}
|
||||||
c.prevPath = c.path
|
c.prevPath = c.path
|
||||||
c.path = pth
|
c.path = pth
|
||||||
|
|
||||||
|
@ -217,16 +206,6 @@ func (c *Context) RunWidget(widget Widget, args ...any) *UpdateChan {
|
||||||
return updates
|
return updates
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go to the root screen.
|
|
||||||
func (c *Context) GoRoot() {
|
|
||||||
c.Go("/")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go one level upper in the screen hierarchy.
|
|
||||||
func (c *Context) GoUp() {
|
|
||||||
c.Go(c.Path().Dir())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change screen to the previous.
|
// Change screen to the previous.
|
||||||
// To get to the parent screen use GoUp.
|
// To get to the parent screen use GoUp.
|
||||||
func (c *Context) GoPrev() {
|
func (c *Context) GoPrev() {
|
||||||
|
|
20
tg/screen.go
20
tg/screen.go
|
@ -4,6 +4,24 @@ import (
|
||||||
"path"
|
"path"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// The type implements changing screen to the underlying ScreenId
|
||||||
|
type ScreenGo struct {
|
||||||
|
Path Path
|
||||||
|
Args []any
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sc ScreenGo) Act(c *Context) {
|
||||||
|
err := c.Go(sc.Path, sc.Args...)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The same as Act.
|
||||||
|
func (sc ScreenGo) Serve(c *Context) {
|
||||||
|
sc.Act(c)
|
||||||
|
}
|
||||||
|
|
||||||
// Unique identifier for the screen
|
// Unique identifier for the screen
|
||||||
// and relative paths to the screen.
|
// and relative paths to the screen.
|
||||||
type Path string
|
type Path string
|
||||||
|
@ -89,7 +107,7 @@ func (n *Node) ScreenMap(root Path) ScreenMap {
|
||||||
pth := (root + n.Path).Clean()
|
pth := (root + n.Path).Clean()
|
||||||
m[pth] = n.Screen
|
m[pth] = n.Screen
|
||||||
for _, sub := range n.Subs {
|
for _, sub := range n.Subs {
|
||||||
buf := sub.ScreenMap((pth + "/").Clean())
|
buf := sub.ScreenMap(pth + "/")
|
||||||
for k, v := range buf {
|
for k, v := range buf {
|
||||||
_, ok := m[k]
|
_, ok := m[k]
|
||||||
if ok {
|
if ok {
|
||||||
|
|
16
tg/widget.go
16
tg/widget.go
|
@ -20,11 +20,11 @@ type Widget interface {
|
||||||
Serve(*Context)
|
Serve(*Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Needs implementation.
|
// Implementing the interface provides ability to
|
||||||
// Behaviour can be the root widget or something like
|
// be used as the root widget for contexts.
|
||||||
// that.
|
|
||||||
type RootWidget interface {
|
type RootWidget interface {
|
||||||
Widget
|
Widget
|
||||||
|
SetSub(Widget)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementing the interface provides way
|
// Implementing the interface provides way
|
||||||
|
@ -36,6 +36,15 @@ type Filterer interface {
|
||||||
Filter(*Update, MessageMap) bool
|
Filter(*Update, MessageMap) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// General type function for faster typing.
|
||||||
|
type Func func(*Context)
|
||||||
|
func (f Func) Act(c *Context) {
|
||||||
|
f(c)
|
||||||
|
}
|
||||||
|
func (f Func) Serve(c *Context) {
|
||||||
|
f(c)
|
||||||
|
}
|
||||||
|
|
||||||
// The type represents general update channel.
|
// The type represents general update channel.
|
||||||
type UpdateChan struct {
|
type UpdateChan struct {
|
||||||
chn chan *Update
|
chn chan *Update
|
||||||
|
@ -48,6 +57,7 @@ func NewUpdateChan() *UpdateChan {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (updates *UpdateChan) Chan() chan *Update {
|
func (updates *UpdateChan) Chan() chan *Update {
|
||||||
return updates.chn
|
return updates.chn
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue