Better keyboard definition way with less code.

This commit is contained in:
Andrey Parhomenko 2023-09-19 14:38:57 +03:00
parent 86cfffc56f
commit 5a590a3cd0
2 changed files with 79 additions and 99 deletions

View file

@ -51,7 +51,7 @@ var (
startScreenButton = tg.NewButton("🏠 To the start screen").
ScreenChange("start")
incDecKeyboard = tg.NewReply().Row(
incDecKeyboard = tg.NewKeyboard().Row(
tg.NewButton("+").ActionFunc(func(c *tg.Context) {
d := ExtractSessionData(c)
d.Counter++
@ -66,51 +66,40 @@ var (
startScreenButton,
)
navKeyboard = tg.NewReply().
WithOneTime(true).
Row(
tg.NewButton("Inc/Dec").ScreenChange("start/inc-dec"),
).Row(
navKeyboard = tg.NewKeyboard().Row(
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")
}),
tg.NewButton("Lower case").ScreenChange("start/lower-case"),
).Row(
tg.NewButton("Send location").ScreenChange("start/send-location"),
)
).Reply().WithOneTime(true)
sendLocationKeyboard = tg.NewReply().
Row(
tg.NewButton("Send location").
WithSendLocation(true).
ActionFunc(func(c *tg.Context) {
var err error
if c.Message.Location != nil {
l := c.Message.Location
_, err = c.Sendf(
"Longitude: %f\n"+
"Latitude: %f\n"+
"Heading: %d"+
"",
l.Longitude,
l.Latitude,
l.Heading,
)
} else {
_, err = c.Sendf("Somehow location was not sent")
}
if err != nil {
c.Sendf("%q", err)
}
}),
).Row(
sendLocationKeyboard = tg.NewKeyboard().Row(
tg.NewButton("Send location").
WithSendLocation(true).
ActionFunc(func(c *tg.Context) {
l := c.Message.Location
c.Sendf(
"Longitude: %f\n"+
"Latitude: %f\n"+
"Heading: %d"+
"",
l.Longitude,
l.Latitude,
l.Heading,
)
}),
).Row(
startScreenButton,
)
).Reply()
// The keyboard to return to the start screen.
navToStartKeyboard = tg.NewReply().Row(
navToStartKeyboard = tg.NewKeyboard().Row(
startScreenButton,
)
).Reply()
)
var beh = tg.NewBehaviour().
@ -121,12 +110,12 @@ var beh = tg.NewBehaviour().
tg.NewScreen("start", tg.NewPage(
"",
).WithInline(
tg.NewInline().Row(
tg.NewKeyboard().Row(
tg.NewButton("GoT Github page").
WithUrl("https://github.com/mojosa-software/got"),
).Widget(""),
).Inline().Widget("The bot started!"),
).WithReply(
navKeyboard.Widget("The bot started!"),
navKeyboard.Widget("Choose what you are interested in"),
),
),
tg.NewScreen("start/inc-dec", tg.NewPage(
@ -135,7 +124,7 @@ var beh = tg.NewBehaviour().
"by saving the counter for each of users "+
"separately. ",
).WithReply(
incDecKeyboard.Widget("Press the buttons to increment and decrement"),
incDecKeyboard.Reply().Widget("Press the buttons to increment and decrement"),
).ActionFunc(func(c *tg.Context) {
// The function will be calleb before serving page.
d := ExtractSessionData(c)
@ -166,7 +155,7 @@ var beh = tg.NewBehaviour().
).WithReply(
sendLocationKeyboard.Widget(""),
).WithInline(
tg.NewInline().Row(
tg.NewKeyboard().Row(
tg.NewButton(
"Check",
).WithData(
@ -175,7 +164,7 @@ var beh = tg.NewBehaviour().
d := ExtractSessionData(c)
c.Sendf("Counter = %d", d.Counter)
}),
).Widget("Press the button to display your counter"),
).Inline().Widget("Press the button to display your counter"),
),
),
).WithCommands(

View file

@ -8,39 +8,29 @@ import (
type Keyboard struct {
// The action is called if there is no
// defined action for the button.
Action *action
Action Action
Rows []ButtonRow
buttonMap ButtonMap
}
// The type represents reply keyboards.
type ReplyKeyboard struct {
Keyboard
*Keyboard
// If true will be removed after one press.
OneTime bool
// If true will remove the keyboard on send.
Remove bool
}
// The type represents keyboard to be emdedded into the messages.
type InlineKeyboard struct {
Keyboard
}
// Returns new empty inline keyboard.
func NewInline() *InlineKeyboard {
ret := &InlineKeyboard{}
return ret
}
// Returns new empty reply keyboard.
func NewReply() *ReplyKeyboard {
ret := &ReplyKeyboard {}
// Returns the new keyboard with specified rows.
func NewKeyboard(rows ...ButtonRow) *Keyboard {
ret := &Keyboard{}
ret.Rows = rows
return ret
}
// Adds a new button row to the current keyboard.
func (kbd *InlineKeyboard) Row(btns ...*Button) *InlineKeyboard {
func (kbd *Keyboard) Row(btns ...*Button) *Keyboard {
// For empty row. We do not need that.
if len(btns) < 1 {
return kbd
@ -49,17 +39,53 @@ func (kbd *InlineKeyboard) Row(btns ...*Button) *InlineKeyboard {
return kbd
}
// Set default action for the buttons in keyboard.
func (kbd *InlineKeyboard) WithAction(a Action) *InlineKeyboard {
kbd.Action = newAction(a)
// Set the default action when no button provides
// key to the data we got.
func (kbd *Keyboard) WithAction(a Action) *Keyboard {
kbd.Action = a
return kbd
}
// Alias to WithAction to simpler define actions.
func (kbd *InlineKeyboard) ActionFunc(fn ActionFunc) *InlineKeyboard {
// Alias to WithAction but better typing when setting
// a specific function
func (kbd *Keyboard) ActionFunc(fn ActionFunc) *Keyboard {
return kbd.WithAction(fn)
}
// Returns the map of buttons. Used to define the Action.
func (kbd Keyboard) ButtonMap() ButtonMap {
if kbd.buttonMap != nil {
return kbd.buttonMap
}
ret := make(ButtonMap)
for _, vi := range kbd.Rows {
for _, vj := range vi {
ret[vj.Key()] = vj
}
}
kbd.buttonMap = ret
return ret
}
// Convert the keyboard to the more specific inline one.
func (kbd *Keyboard) Inline() *InlineKeyboard {
ret := &InlineKeyboard{}
ret.Keyboard = kbd
return ret
}
func (kbd *Keyboard) Reply() *ReplyKeyboard {
ret := &ReplyKeyboard{}
ret.Keyboard = kbd
return ret
}
// The type represents keyboard to be emdedded into the messages.
type InlineKeyboard struct {
*Keyboard
}
// Transform the keyboard to widget with the specified text.
func (kbd *InlineKeyboard) Widget(text string) *InlineKeyboardWidget {
ret := &InlineKeyboardWidget{}
@ -68,27 +94,7 @@ func (kbd *InlineKeyboard) Widget(text string) *InlineKeyboardWidget {
return ret
}
// Adds a new button row to the current keyboard.
func (kbd *ReplyKeyboard) Row(btns ...*Button) *ReplyKeyboard {
// For empty row. We do not need that.
if len(btns) < 1 {
return kbd
}
kbd.Rows = append(kbd.Rows, btns)
return kbd
}
// Set default action for the keyboard.
func (kbd *ReplyKeyboard) WithAction(a Action) *ReplyKeyboard {
kbd.Action = newAction(a)
return kbd
}
// Alias to WithAction for simpler callback declarations.
func (kbd *ReplyKeyboard) ActionFunc(fn ActionFunc) *ReplyKeyboard {
return kbd.WithAction(fn)
}
// Transform the keyboard to widget with the specified text.
func (kbd *ReplyKeyboard) Widget(text string) *ReplyKeyboardWidget {
ret := &ReplyKeyboardWidget{}
ret.ReplyKeyboard = kbd
@ -147,19 +153,4 @@ func (kbd *ReplyKeyboard) WithOneTime(oneTime bool) *ReplyKeyboard {
return kbd
}
// Returns the map of buttons. Used to define the Action.
func (kbd Keyboard) ButtonMap() ButtonMap {
if kbd.buttonMap != nil {
return kbd.buttonMap
}
ret := make(ButtonMap)
for _, vi := range kbd.Rows {
for _, vj := range vi {
ret[vj.Key()] = vj
}
}
kbd.buttonMap = ret
return ret
}