@@ -2,10 +2,12 @@ package tbcomctl
22
33import (
44 "context"
5+ "errors"
56 "fmt"
67 "runtime/trace"
78 "strings"
89
10+ "github.com/rusq/dlog"
911 tb "gopkg.in/tucnak/telebot.v3"
1012)
1113
@@ -21,9 +23,11 @@ type Picklist struct {
2123 removeButtons bool
2224 noUpdate bool
2325 msgChoose bool
26+ backBtn bool
2427
25- vFn ValuesFunc
26- cbFn BtnCallbackFunc
28+ vFn ValuesFunc
29+ cbFn BtnCallbackFunc
30+ backTxtFn TextFunc
2731
2832 btnPattern []uint
2933}
@@ -102,6 +106,19 @@ func PickOptBtnPattern(pattern []uint) PicklistOption {
102106 }
103107}
104108
109+ func PickOptBtnBack (textFn TextFunc ) PicklistOption {
110+ return func (p * Picklist ) {
111+ p .backBtn = true
112+ p .backTxtFn = textFn
113+ }
114+ }
115+
116+ func PickOptBtnBackWithText (s string ) PicklistOption {
117+ return PickOptBtnBack (func (ctx context.Context , u * tb.User ) (string , error ) {
118+ return s , nil
119+ })
120+ }
121+
105122// NewPicklist creates a new picklist.
106123func NewPicklist (name string , textFn TextFunc , valuesFn ValuesFunc , callbackFn BtnCallbackFunc , opts ... PicklistOption ) * Picklist {
107124 if textFn == nil || valuesFn == nil || callbackFn == nil {
@@ -116,6 +133,9 @@ func NewPicklist(name string, textFn TextFunc, valuesFn ValuesFunc, callbackFn B
116133 for _ , opt := range opts {
117134 opt (p )
118135 }
136+ if p .backBtn {
137+ p .btnPattern = append (p .btnPattern , 1 )
138+ }
119139 return p
120140}
121141
@@ -169,12 +189,30 @@ func (p *Picklist) Callback(c tb.Context) error {
169189 p .logCallback (cb )
170190
171191 var resp tb.CallbackResponse
192+
193+ if p .backBtn {
194+ // back button is enabled, check if the callback data contains back button text.
195+ txt , err := p .backTxtFn (ctx , c .Sender ())
196+ if err != nil {
197+ trace .Logf (ctx , "back button" , "err=%s" , err )
198+ }
199+ if c .Data () == txt {
200+ trace .Log (ctx , "callback" , "back is pressed (option)" )
201+ return p .handleBackButton (ctx , c )
202+ }
203+ }
204+
172205 err := p .cbFn (WithController (ctx , p ), c )
173206 if err != nil {
207+ if errors .Is (err , BackPressed ) {
208+ // user callback function might return "back button is pressed" as well
209+ trace .Log (ctx , "callback" , "back is pressed (user)" )
210+ return p .handleBackButton (ctx , c )
211+ }
174212 if e , ok := err .(* Error ); ! ok {
175213 p .editMsg (ctx , c )
176214 if err := c .Respond (& tb.CallbackResponse {Text : err .Error (), ShowAlert : true }); err != nil {
177- trace .Logf (ctx , "respond" , err .Error ())
215+ trace .Log (ctx , "respond" , err .Error ())
178216 }
179217 p .unregister (c .Sender (), cb .Message .ID )
180218 return e
@@ -255,6 +293,13 @@ func (p *Picklist) format(u *tb.User, text string) string {
255293}
256294
257295func (p * Picklist ) inlineMarkup (c tb.Context , values []string ) * tb.ReplyMarkup {
296+ if p .backBtn {
297+ txt , err := p .backTxtFn (context .Background (), c .Sender ())
298+ if err != nil {
299+ dlog .Debugf ("backTextFn returned an error: %s" , err )
300+ }
301+ values = append (values , txt )
302+ }
258303 if len (p .btnPattern ) == 0 {
259304 return ButtonMarkup (c , values , p .maxButtons , p .Callback )
260305 }
@@ -292,8 +337,18 @@ func convertToMsg(cb *tb.Callback) *tb.Message {
292337
293338func (p * Picklist ) nextHandler (c tb.Context ) error {
294339 if p .next != nil {
295- // this call is part of the pipeline
296340 return p .next .Handler (c )
297341 }
298342 return nil
299343}
344+
345+ func (p * Picklist ) handleBackButton (ctx context.Context , c tb.Context ) error {
346+ if err := c .Respond (& tb.CallbackResponse {}); err != nil {
347+ trace .Log (ctx , "respond" , err .Error ())
348+ }
349+ c .Set (BackPressed .Error (), true )
350+ if p .prev != nil {
351+ return p .prev .Handler (c )
352+ }
353+ return nil
354+ }
0 commit comments