From 88d4310db555ee5bce5e980b80180a0e3144971d Mon Sep 17 00:00:00 2001 From: surdeus Date: Wed, 20 Sep 2023 23:38:29 +0300 Subject: [PATCH] Implemented the new way of thinking about ScreenIds. As PATHS. --- cmd/test/main.go | 11 ++++++----- tg/command.go | 2 +- tg/page.go | 2 +- tg/private.go | 25 ++++++++++++++++--------- tg/widget.go | 4 ++++ 5 files changed, 28 insertions(+), 16 deletions(-) diff --git a/cmd/test/main.go b/cmd/test/main.go index 23603ec..b5598b4 100644 --- a/cmd/test/main.go +++ b/cmd/test/main.go @@ -27,7 +27,7 @@ func NewMutateMessageWidget(fn func(string) string) *MutateMessageWidget { } func (w *MutateMessageWidget) Serve(c *tg.Context) { - args, ok := c.Arg.([]any) + args, ok := c.Arg.(tg.ArgSlice) if ok { for _, arg := range args { c.Sendf("%v", arg) @@ -51,8 +51,9 @@ func ExtractSessionData(c *tg.Context) *SessionData { } var ( - startScreenButton = tg.NewButton("🏠 To the start screen"). - ScreenChange("/start") + startScreenButton = tg.NewButton("Back").ActionFunc(func(c *tg.Context){ + c.GoUp() + }) incDecKeyboard = tg.NewKeyboard().Row( tg.NewButton("+").ActionFunc(func(c *tg.Context) { @@ -73,7 +74,7 @@ var ( tg.NewButton("Inc/Dec").ScreenChange("/start/inc-dec"), ).Row( tg.NewButton("Upper case").ActionFunc(func(c *tg.Context){ - c.ChangeScreen("/start/upper-case", "this shit", "works") + c.Go("/start/upper-case", "this shit", "works") }), tg.NewButton("Lower case").ScreenChange("/start/lower-case"), ).Row( @@ -175,7 +176,7 @@ var beh = tg.NewBehaviour(). Desc("start or restart the bot or move to the start screen"). ActionFunc(func(c *tg.Context){ c.Sendf("Your username is %q", c.Message.From.UserName) - c.ChangeScreen("/start") + c.Go("/start") }), tg.NewCommand("hello"). Desc("sends the 'Hello, World!' message back"). diff --git a/tg/command.go b/tg/command.go index a9ed948..396fc59 100644 --- a/tg/command.go +++ b/tg/command.go @@ -165,7 +165,7 @@ func (widget *CommandWidget) Serve(c *Context) { var cmdUpdates *UpdateChan for u := range c.Input() { - if c.ScreenId() == "" && u.Message != nil { + if c.CurScreen() == "" && u.Message != nil { // Skipping and executing the preinit action // while we have the empty screen. // E. g. the session did not start. diff --git a/tg/page.go b/tg/page.go index 076d556..811762c 100644 --- a/tg/page.go +++ b/tg/page.go @@ -92,7 +92,7 @@ func (p *Page) Serve(c *Context) { msgs, _ := c.Render(p) inlineMsg := msgs["page/inline"] - subUpdates := c.RunWidget(p.SubWidget) + subUpdates := c.RunWidget(p.SubWidget, c.Arg) defer subUpdates.Close() inlineUpdates := c.RunWidget(p.Inline) diff --git a/tg/private.go b/tg/private.go index 053d7b4..501f5cc 100644 --- a/tg/private.go +++ b/tg/private.go @@ -4,6 +4,7 @@ import ( "fmt" //tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" + "path" ) type ContextType string @@ -41,11 +42,11 @@ func (c *context) run(a Action, u *Update) { a.Act(&Context{context: c, Update: u}) } -func (c *Context) ScreenId() ScreenId { +func (c *Context) CurScreen() ScreenId { return c.screenId } -func (c *Context) PrevScreenId() ScreenId { +func (c *Context) PrevScreen() ScreenId { return c.prevScreenId } @@ -149,7 +150,7 @@ func (sc ScreenChange) Act(c *Context) { if !c.Bot.behaviour.ScreenExist(ScreenId(sc)) { panic(ScreenNotExistErr) } - err := c.ChangeScreen(ScreenId(sc)) + err := c.Go(ScreenId(sc)) if err != nil { panic(err) } @@ -158,7 +159,7 @@ func (sc ScreenChange) Act(c *Context) { type C = Context // Changes screen of user to the Id one. -func (c *Context) ChangeScreen(screenId ScreenId, args ...any) error { +func (c *Context) Go(screenId ScreenId, args ...any) error { if !c.Bot.behaviour.ScreenExist(screenId) { return ScreenNotExistErr } @@ -171,9 +172,8 @@ func (c *Context) ChangeScreen(screenId ScreenId, args ...any) error { // Stopping the current widget. c.skippedUpdates.Close() - c.skippedUpdates = nil if screen.Widget != nil { - c.skippedUpdates = c.RunWidget(screen.Widget, args) + c.skippedUpdates = c.RunWidget(screen.Widget, args...) } else { panic("no widget defined for the screen") } @@ -187,7 +187,6 @@ func (c *Context) RunWidget(widget Widget, args ...any) *UpdateChan { return nil } - var arg any if len(args) == 1 { arg = args[0] @@ -202,12 +201,20 @@ func (c *Context) RunWidget(widget Widget, args ...any) *UpdateChan { WithInput(updates). WithArg(arg), ) + // To let widgets finish themselves before + // the channel is closed. updates.Close() }() return updates } -func (c *Context) ChangeToPrevScreen() { - c.ChangeScreen(c.PrevScreenId()) +func (c *Context) GoUp() { + c.Go(ScreenId(path.Dir(string(c.CurScreen())))) +} + +// Change screen to the previous. +// To get to the parent screen use GoUp. +func (c *Context) GoPrev() { + c.Go(c.PrevScreen()) } diff --git a/tg/widget.go b/tg/widget.go index e0ce98b..4f8fa41 100644 --- a/tg/widget.go +++ b/tg/widget.go @@ -5,6 +5,10 @@ import ( //"fmt" ) +type ArgMap = map[string] any +type ArgSlice = []any +type ArgList[V any] []V + // Implementing the interface provides // ability to build your own widgets, // aka components.