From 1b811e17862b9ef74787333bbc66f97b68fe1c48 Mon Sep 17 00:00:00 2001 From: FlorianDahn Date: Thu, 26 Sep 2019 20:54:35 +0200 Subject: [PATCH] - added ToKeyboardButton to ButtonBase - added eKeyboardType to switch between Inline and KeykboardButtons - addes some small functions to ButtonForm - added new control "ButtonGrid" which manages Button handling with Event Handler for each Button and can switch between InlineMode and KeyboardMode during runtime - added also Examples to it --- .../Tests/Controls/ButtonGridForm.cs | 79 +++++++ TelegramBaseTest/Tests/Start.cs | 11 + TelegramBotBase/Controls/ButtonGrid.cs | 212 ++++++++++++++++++ TelegramBotBase/Enums/eKeyboardType.cs | 22 ++ TelegramBotBase/Form/ButtonBase.cs | 12 + TelegramBotBase/Form/ButtonForm.cs | 34 ++- 6 files changed, 368 insertions(+), 2 deletions(-) create mode 100644 TelegramBaseTest/Tests/Controls/ButtonGridForm.cs create mode 100644 TelegramBotBase/Controls/ButtonGrid.cs create mode 100644 TelegramBotBase/Enums/eKeyboardType.cs diff --git a/TelegramBaseTest/Tests/Controls/ButtonGridForm.cs b/TelegramBaseTest/Tests/Controls/ButtonGridForm.cs new file mode 100644 index 0000000..86cb07c --- /dev/null +++ b/TelegramBaseTest/Tests/Controls/ButtonGridForm.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TelegramBotBase.Controls; +using TelegramBotBase.Form; + +namespace TelegramBaseTest.Tests.Controls +{ + public class ButtonGridForm : AutoCleanForm + { + + ButtonGrid m_Buttons = null; + + public ButtonGridForm() + { + this.DeleteMode = TelegramBotBase.Enums.eDeleteMode.OnLeavingForm; + + this.Init += ButtonGridForm_Init; + } + + private async Task ButtonGridForm_Init(object sender, TelegramBotBase.Base.InitEventArgs e) + { + m_Buttons = new ButtonGrid(); + + await m_Buttons.SetKeyboardType(TelegramBotBase.Enums.eKeyboardType.InlineKeyBoard); + + ButtonForm bf = new ButtonForm(); + + bf.AddButtonRow(new ButtonBase("Back", "back"), new ButtonBase("Switch Keyboard", "switch")); + + bf.AddButtonRow(new ButtonBase("Button1", "b1"), new ButtonBase("Button2", "b2")); + + bf.AddButtonRow(new ButtonBase("Button3", "b3"), new ButtonBase("Button4", "b4")); + + m_Buttons.ButtonsForm = bf; + + m_Buttons.ButtonClicked += Bg_ButtonClicked; + + this.AddControl(m_Buttons); + + + } + + private async void Bg_ButtonClicked(object sender, TelegramBotBase.Base.ButtonClickedEventArgs e) + { + if (e.Button == null) + return; + + if (e.Button.Value == "back") + { + var start = new Start(); + await this.NavigateTo(start); + } + else if (e.Button.Value == "switch") + { + switch (m_Buttons.KeyboardType) + { + case TelegramBotBase.Enums.eKeyboardType.ReplyKeyboard: + await m_Buttons.SetKeyboardType(TelegramBotBase.Enums.eKeyboardType.InlineKeyBoard); + break; + case TelegramBotBase.Enums.eKeyboardType.InlineKeyBoard: + await m_Buttons.SetKeyboardType(TelegramBotBase.Enums.eKeyboardType.ReplyKeyboard); + break; + } + + + } + else + { + + await this.Device.Send($"Button clicked with Text: {e.Button.Text} and Value {e.Button.Value}"); + } + + + } + } +} diff --git a/TelegramBaseTest/Tests/Start.cs b/TelegramBaseTest/Tests/Start.cs index e85550c..158f9bc 100644 --- a/TelegramBaseTest/Tests/Start.cs +++ b/TelegramBaseTest/Tests/Start.cs @@ -123,6 +123,15 @@ namespace TelegramBaseTest.Tests await this.NavigateTo(tb); + break; + case "buttongrid": + + message.Handled = true; + + var bg = new Controls.ButtonGridForm(); + + await this.NavigateTo(bg); + break; } @@ -150,6 +159,8 @@ namespace TelegramBaseTest.Tests btn.AddButtonRow(new ButtonBase("#11 ToggleButtons", new CallbackData("a", "togglebuttons").Serialize())); + btn.AddButtonRow(new ButtonBase("#12 ButtonGrid", new CallbackData("a", "buttongrid").Serialize())); + await this.Device.Send("Choose your test:", btn); } diff --git a/TelegramBotBase/Controls/ButtonGrid.cs b/TelegramBotBase/Controls/ButtonGrid.cs new file mode 100644 index 0000000..dc48c68 --- /dev/null +++ b/TelegramBotBase/Controls/ButtonGrid.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Telegram.Bot.Types; +using Telegram.Bot.Types.ReplyMarkups; +using TelegramBotBase.Base; +using TelegramBotBase.Enums; +using TelegramBotBase.Form; + +namespace TelegramBotBase.Controls +{ + public class ButtonGrid : Base.ControlBase + { + + public String Title { get; set; } = "Toggle"; + + private bool RenderNecessary = true; + + private static readonly object __evButtonClicked = new object(); + + private readonly EventHandlerList Events = new EventHandlerList(); + + public ButtonForm ButtonsForm { get; set; } + + public int? MessageId + { + get + { + return m_iMessageId; + } + set + { + m_iMessageId = value; + } + } + + private int? m_iMessageId = null; + + /// + /// Defines which type of Button Keyboard should be rendered. + /// + public eKeyboardType KeyboardType + { + get; private set; + } + + public async Task SetKeyboardType(eKeyboardType type) + { + if (KeyboardType == type) + return; + + this.RenderNecessary = true; + + Cleanup().Wait(); + + KeyboardType = type; + + } + + private bool m_bVisible = true; + + public ButtonGrid() + { + this.ButtonsForm = new ButtonForm(); + + + } + + public ButtonGrid(ButtonForm form) + { + this.ButtonsForm = form; + } + + + public event EventHandler ButtonClicked + { + add + { + this.Events.AddHandler(__evButtonClicked, value); + } + remove + { + this.Events.RemoveHandler(__evButtonClicked, value); + } + } + + public void OnButtonClicked(ButtonClickedEventArgs e) + { + (this.Events[__evButtonClicked] as EventHandler)?.Invoke(this, e); + } + + public async override Task Load(MessageResult result) + { + if (this.KeyboardType != eKeyboardType.ReplyKeyboard) + return; + + + var button = ButtonsForm.ToList().FirstOrDefault(a => a.Text == result.MessageText); + + if (button == null) + return; + + OnButtonClicked(new ButtonClickedEventArgs(button)); + + result.Handled = true; + + } + + public async override Task Action(MessageResult result, string value = null) + { + if (result.Handled) + return; + + await result.ConfirmAction(); + + //Find clicked button depending on Text or Value (depending on markup type) + switch (this.KeyboardType) + { + case eKeyboardType.InlineKeyBoard: + + var button = ButtonsForm.ToList().FirstOrDefault(a => a.Value == result.RawData); + + if (button == null) + return; + + OnButtonClicked(new ButtonClickedEventArgs(button)); + + result.Handled = true; + + break; + } + + } + + public async override Task Render(MessageResult result) + { + if (!this.RenderNecessary) + return; + + Message m = null; + if (this.MessageId != null) + { + switch (this.KeyboardType) + { + //Reply Keyboard could only be updated with a new keyboard. + case eKeyboardType.ReplyKeyboard: + if (this.ButtonsForm.Count == 0) + { + await this.Device.Send("", new ReplyKeyboardRemove()); + this.MessageId = null; + } + else + { + m = await this.Device.Send(this.Title, (ReplyKeyboardMarkup)this.ButtonsForm, disableNotification: true); + } + + break; + + case eKeyboardType.InlineKeyBoard: + m = await this.Device.Edit(this.MessageId.Value, this.Title, (InlineKeyboardMarkup)this.ButtonsForm); + break; + } + + + } + else + { + switch (this.KeyboardType) + { + case eKeyboardType.ReplyKeyboard: + m = await this.Device.Send(this.Title, (ReplyKeyboardMarkup)this.ButtonsForm, disableNotification: true); + break; + + case eKeyboardType.InlineKeyBoard: + m = await this.Device.Send(this.Title, (InlineKeyboardMarkup)this.ButtonsForm, disableNotification: true); + break; + } + + if (m != null) + { + this.MessageId = m.MessageId; + } + } + + this.RenderNecessary = false; + + } + + + public async override Task Cleanup() + { + if (this.MessageId == null) + return; + + await this.Device.DeleteMessage(this.MessageId.Value); + + this.MessageId = null; + + if (this.KeyboardType == eKeyboardType.ReplyKeyboard) + { + await this.Device.Send("", new ReplyKeyboardRemove()); + } + + } + + } + + +} diff --git a/TelegramBotBase/Enums/eKeyboardType.cs b/TelegramBotBase/Enums/eKeyboardType.cs new file mode 100644 index 0000000..3cd255e --- /dev/null +++ b/TelegramBotBase/Enums/eKeyboardType.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TelegramBotBase.Enums +{ + public enum eKeyboardType + { + /// + /// Uses a ReplyKeyboardMarkup + /// + ReplyKeyboard = 0, + + /// + /// Uses a InlineKeyboardMakup + /// + InlineKeyBoard = 1 + + } +} diff --git a/TelegramBotBase/Form/ButtonBase.cs b/TelegramBotBase/Form/ButtonBase.cs index 67d193a..303a9d1 100644 --- a/TelegramBotBase/Form/ButtonBase.cs +++ b/TelegramBotBase/Form/ButtonBase.cs @@ -48,5 +48,17 @@ namespace TelegramBotBase.Form } + public KeyboardButton ToKeyboardButton(ButtonForm form) + { + //String id = (form.DependencyControl != null ? form.DependencyControl.ControlID + "_" : ""); + if (this.Url == null) + { + return new KeyboardButton(this.Text); + } + + return new KeyboardButton(this.Text); + + } + } } diff --git a/TelegramBotBase/Form/ButtonForm.cs b/TelegramBotBase/Form/ButtonForm.cs index 7fe1df7..6fe043d 100644 --- a/TelegramBotBase/Form/ButtonForm.cs +++ b/TelegramBotBase/Form/ButtonForm.cs @@ -60,6 +60,14 @@ namespace TelegramBotBase.Form return splitted; } + public int Count + { + get + { + return this.Buttons.Select(a => a.ToArray()).Aggregate((a, b) => a.Union(b).ToArray()).Length; + } + } + /// /// Add buttons splitted in the amount of columns (i.e. 2 per row...) /// @@ -75,19 +83,41 @@ namespace TelegramBotBase.Form } } - public InlineKeyboardButton[][] ToArray() + public List ToList() + { + return this.Buttons.Aggregate((a, b) => a.Union(b).ToList()); + } + + public InlineKeyboardButton[][] ToInlineButtonArray() { var ikb = this.Buttons.Select(a => a.Select(b => b.ToInlineButton(this)).ToArray()).ToArray(); return ikb; } + public KeyboardButton[][] ToReplyButtonArray() + { + var ikb = this.Buttons.Select(a => a.Select(b => b.ToKeyboardButton(this)).ToArray()).ToArray(); + + return ikb; + } + public static implicit operator InlineKeyboardMarkup(ButtonForm form) { if (form == null) return null; - InlineKeyboardMarkup ikm = new InlineKeyboardMarkup(form.ToArray()); + InlineKeyboardMarkup ikm = new InlineKeyboardMarkup(form.ToInlineButtonArray()); + + return ikm; + } + + public static implicit operator ReplyKeyboardMarkup(ButtonForm form) + { + if (form == null) + return null; + + ReplyKeyboardMarkup ikm = new ReplyKeyboardMarkup(form.ToReplyButtonArray()); return ikm; }