commit
7004ee5963
85
README.md
85
README.md
@ -106,6 +106,16 @@ Thanks !
|
|||||||
|
|
||||||
* [IgnoreState](#ignorestate)
|
* [IgnoreState](#ignorestate)
|
||||||
|
|
||||||
|
|
||||||
|
- [Navigation and NavigationController (v4.0.0)](#navigation-and-navigationcontroller)
|
||||||
|
|
||||||
|
* [As of Now](#as-of-now)
|
||||||
|
|
||||||
|
* [How to use](#how-to-use-)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- [Examples](#examples)
|
- [Examples](#examples)
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -1073,6 +1083,81 @@ public class Registration : STForm
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Navigation and NavigationController
|
||||||
|
|
||||||
|
### As of now
|
||||||
|
|
||||||
|
As from earlier topics on this readme you already know the default way for (cross) navigation between Forms.
|
||||||
|
It will look something like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
var f = new FormBase();
|
||||||
|
await this.NavigateTo(f);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Depending on the model and structure of your bot it can make sense, to have more linear navigation instead of "cross" navigation.
|
||||||
|
|
||||||
|
In example you have a bot which shows a list of football teams. And when clicking on it you want to open the team details and latest matches.
|
||||||
|
|
||||||
|
After the matches you want to maybe switch to a different teams and take a look at their statistics and matches.
|
||||||
|
|
||||||
|
At some point, you "just" want to get back to the first team so like on Android your clicking the "back" button multiple times.
|
||||||
|
|
||||||
|
This can become really complicated, when not having some controller below which handle these "Push/Pop" calls.
|
||||||
|
|
||||||
|
Thats why I introduced a NavigationController class which manages these situations and the stack.
|
||||||
|
|
||||||
|
|
||||||
|
### How to use ?
|
||||||
|
|
||||||
|
First you need to create a NavigationController instance at the same position in code, where you want to start the navigation.
|
||||||
|
|
||||||
|
You will use the current FormBase instance as a root class within the constructor. So you can later come back to this one.
|
||||||
|
|
||||||
|
**Tip**: *You can add also a completely new instance of i.e. a main menu form here to get back to it then. So you are free to choose.*
|
||||||
|
|
||||||
|
We are using the same FormBase instance as above.
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
var nc = new NavigationController(this);
|
||||||
|
|
||||||
|
var f = new FormBase();
|
||||||
|
|
||||||
|
//Replace the current form in the context with the controller.
|
||||||
|
await this.NavigateTo(nc);
|
||||||
|
|
||||||
|
//Push the new from onto the stack to render it
|
||||||
|
nc.PushAsync(f);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Later to open a new form use PushAsync again:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
await this.NavigationController.PushAsync(newForm);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
When you want to go back one Form on the stack use PopAsync:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
await this.NavigationController.PopAsync();
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notice**: *By default the NavigationController has ForceCleanupOnLastPop enabled, which means that when the stack is again at 1 (due to PopAsync or PopToRootAsync calls) it will replace the controller automatically with the root form you have given to the constructor at the beginning.*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using TelegramBotBase.Controls.Hybrid;
|
||||||
using TelegramBotBase.Form;
|
using TelegramBotBase.Form;
|
||||||
|
|
||||||
namespace TelegramBotBase.Args
|
namespace TelegramBotBase.Args
|
||||||
@ -18,6 +19,8 @@ namespace TelegramBotBase.Args
|
|||||||
|
|
||||||
public object Tag { get; set; }
|
public object Tag { get; set; }
|
||||||
|
|
||||||
|
public ButtonRow Row { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public ButtonClickedEventArgs()
|
public ButtonClickedEventArgs()
|
||||||
{
|
{
|
||||||
@ -36,5 +39,11 @@ namespace TelegramBotBase.Args
|
|||||||
this.Index = Index;
|
this.Index = Index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ButtonClickedEventArgs(ButtonBase button, int Index, ButtonRow row)
|
||||||
|
{
|
||||||
|
this.Button = button;
|
||||||
|
this.Index = Index;
|
||||||
|
this.Row = row;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using TelegramBotBase.Controls.Hybrid;
|
||||||
using TelegramBotBase.Form;
|
using TelegramBotBase.Form;
|
||||||
|
|
||||||
namespace TelegramBotBase.Args
|
namespace TelegramBotBase.Args
|
||||||
@ -17,7 +18,7 @@ namespace TelegramBotBase.Args
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains all buttons within this row, excluding the checkbox.
|
/// Contains all buttons within this row, excluding the checkbox.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ButtonBase> Row { get; set; }
|
public ButtonRow Row { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -31,7 +32,7 @@ namespace TelegramBotBase.Args
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CheckedChangedEventArgs(List<ButtonBase> row, int Index, bool Checked)
|
public CheckedChangedEventArgs(ButtonRow row, int Index, bool Checked)
|
||||||
{
|
{
|
||||||
this.Row = row;
|
this.Row = row;
|
||||||
this.Index = Index;
|
this.Index = Index;
|
||||||
|
|||||||
@ -6,6 +6,7 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using TelegramBotBase.Args;
|
using TelegramBotBase.Args;
|
||||||
using TelegramBotBase.Base;
|
using TelegramBotBase.Base;
|
||||||
|
using TelegramBotBase.Form.Navigation;
|
||||||
using TelegramBotBase.Sessions;
|
using TelegramBotBase.Sessions;
|
||||||
using static TelegramBotBase.Base.Async;
|
using static TelegramBotBase.Base.Async;
|
||||||
|
|
||||||
@ -17,6 +18,8 @@ namespace TelegramBotBase.Form
|
|||||||
public class FormBase : IDisposable
|
public class FormBase : IDisposable
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public NavigationController NavigationController { get; set; }
|
||||||
|
|
||||||
public DeviceSession Device { get; set; }
|
public DeviceSession Device { get; set; }
|
||||||
|
|
||||||
public MessageClient Client { get; set; }
|
public MessageClient Client { get; set; }
|
||||||
|
|||||||
@ -10,6 +10,7 @@ using Telegram.Bot.Types.Enums;
|
|||||||
using Telegram.Bot.Types.ReplyMarkups;
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
using TelegramBotBase.Args;
|
using TelegramBotBase.Args;
|
||||||
using TelegramBotBase.Base;
|
using TelegramBotBase.Base;
|
||||||
|
using TelegramBotBase.Datasources;
|
||||||
using TelegramBotBase.Enums;
|
using TelegramBotBase.Enums;
|
||||||
using TelegramBotBase.Exceptions;
|
using TelegramBotBase.Exceptions;
|
||||||
using TelegramBotBase.Form;
|
using TelegramBotBase.Form;
|
||||||
@ -30,7 +31,26 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
private readonly EventHandlerList Events = new EventHandlerList();
|
private readonly EventHandlerList Events = new EventHandlerList();
|
||||||
|
|
||||||
public ButtonForm ButtonsForm { get; set; }
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("This property is obsolete. Please use the DataSource property instead.")]
|
||||||
|
public ButtonForm ButtonsForm
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return DataSource.ButtonForm;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
DataSource = new ButtonFormDataSource(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Data source of the items.
|
||||||
|
/// </summary>
|
||||||
|
public ButtonFormDataSource DataSource { get; set; }
|
||||||
|
|
||||||
public int? MessageId { get; set; }
|
public int? MessageId { get; set; }
|
||||||
|
|
||||||
@ -89,12 +109,12 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Layout of the buttons which should be displayed always on top.
|
/// Layout of the buttons which should be displayed always on top.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ButtonBase> HeadLayoutButtonRow { get; set; }
|
public ButtonRow HeadLayoutButtonRow { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Layout of columns which should be displayed below the header
|
/// Layout of columns which should be displayed below the header
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ButtonBase> SubHeadLayoutButtonRow { get; set; }
|
public ButtonRow SubHeadLayoutButtonRow { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines which type of Button Keyboard should be rendered.
|
/// Defines which type of Button Keyboard should be rendered.
|
||||||
@ -123,8 +143,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
public ButtonGrid()
|
public ButtonGrid()
|
||||||
{
|
{
|
||||||
this.ButtonsForm = new ButtonForm();
|
this.DataSource = new ButtonFormDataSource();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +155,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
public ButtonGrid(ButtonForm form)
|
public ButtonGrid(ButtonForm form)
|
||||||
{
|
{
|
||||||
this.ButtonsForm = form;
|
this.DataSource = new ButtonFormDataSource(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -188,22 +207,49 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
if (!result.IsFirstHandler)
|
if (!result.IsFirstHandler)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (result.MessageText == null)
|
if (result.MessageText == null || result.MessageText == "")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
var matches = new List<ButtonRow>();
|
||||||
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
ButtonRow match = null;
|
||||||
?? ButtonsForm.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText);
|
int index = -1;
|
||||||
|
|
||||||
var index = ButtonsForm.FindRowByButton(button);
|
if (HeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
|
||||||
|
|
||||||
if (button != null)
|
|
||||||
{
|
{
|
||||||
await OnButtonClicked(new ButtonClickedEventArgs(button, index));
|
match = HeadLayoutButtonRow;
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
//Remove button click message
|
if (SubHeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
|
||||||
if (this.DeleteReplyMessage)
|
{
|
||||||
await Device.DeleteMessage(result.MessageId);
|
match = SubHeadLayoutButtonRow;
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
|
var br = DataSource.FindRow(result.MessageText);
|
||||||
|
if (br != null)
|
||||||
|
{
|
||||||
|
match = br.Item1;
|
||||||
|
index = br.Item2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//var button = HeadLayoutButtonRow?. .FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
||||||
|
// ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText);
|
||||||
|
|
||||||
|
// bf.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
||||||
|
|
||||||
|
//var index = bf.FindRowByButton(button);
|
||||||
|
|
||||||
|
check:
|
||||||
|
|
||||||
|
//Remove button click message
|
||||||
|
if (this.DeleteReplyMessage)
|
||||||
|
await Device.DeleteMessage(result.MessageId);
|
||||||
|
|
||||||
|
if (match != null)
|
||||||
|
{
|
||||||
|
await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.MessageText), index, match));
|
||||||
|
|
||||||
result.Handled = true;
|
result.Handled = true;
|
||||||
return;
|
return;
|
||||||
@ -261,22 +307,48 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
if (!result.IsFirstHandler)
|
if (!result.IsFirstHandler)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await result.ConfirmAction(this.ConfirmationText ?? "");
|
|
||||||
|
|
||||||
//Find clicked button depending on Text or Value (depending on markup type)
|
//Find clicked button depending on Text or Value (depending on markup type)
|
||||||
if (this.KeyboardType != eKeyboardType.InlineKeyBoard)
|
if (this.KeyboardType != eKeyboardType.InlineKeyBoard)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
await result.ConfirmAction(this.ConfirmationText ?? "");
|
||||||
|
|
||||||
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
ButtonRow match = null;
|
||||||
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
int index = -1;
|
||||||
?? ButtonsForm.ToList().FirstOrDefault(a => a.Value == result.RawData);
|
|
||||||
|
|
||||||
var index = ButtonsForm.FindRowByButton(button);
|
if (HeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
|
||||||
|
|
||||||
if (button != null)
|
|
||||||
{
|
{
|
||||||
await OnButtonClicked(new ButtonClickedEventArgs(button, index));
|
match = HeadLayoutButtonRow;
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SubHeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
|
||||||
|
{
|
||||||
|
match = SubHeadLayoutButtonRow;
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
|
var br = DataSource.FindRow(result.RawData, false);
|
||||||
|
if (br != null)
|
||||||
|
{
|
||||||
|
match = br.Item1;
|
||||||
|
index = br.Item2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//var bf = DataSource.ButtonForm;
|
||||||
|
|
||||||
|
//var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
||||||
|
// ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
||||||
|
// ?? bf.ToList().FirstOrDefault(a => a.Value == result.RawData);
|
||||||
|
|
||||||
|
//var index = bf.FindRowByButton(button);
|
||||||
|
|
||||||
|
check:
|
||||||
|
if (match != null)
|
||||||
|
{
|
||||||
|
await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.RawData, false), index, match));
|
||||||
|
|
||||||
result.Handled = true;
|
result.Handled = true;
|
||||||
return;
|
return;
|
||||||
@ -313,28 +385,28 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
{
|
{
|
||||||
case eKeyboardType.InlineKeyBoard:
|
case eKeyboardType.InlineKeyBoard:
|
||||||
|
|
||||||
if (ButtonsForm.Rows > Constants.Telegram.MaxInlineKeyBoardRows && !this.EnablePaging)
|
if (DataSource.RowCount > Constants.Telegram.MaxInlineKeyBoardRows && !this.EnablePaging)
|
||||||
{
|
{
|
||||||
throw new MaximumRowsReachedException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxInlineKeyBoardRows };
|
throw new MaximumRowsReachedException() { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxInlineKeyBoardRows };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ButtonsForm.Cols > Constants.Telegram.MaxInlineKeyBoardCols)
|
if (DataSource.ColumnCount > Constants.Telegram.MaxInlineKeyBoardCols)
|
||||||
{
|
{
|
||||||
throw new MaximumColsException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxInlineKeyBoardCols };
|
throw new MaximumColsException() { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxInlineKeyBoardCols };
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eKeyboardType.ReplyKeyboard:
|
case eKeyboardType.ReplyKeyboard:
|
||||||
|
|
||||||
if (ButtonsForm.Rows > Constants.Telegram.MaxReplyKeyboardRows && !this.EnablePaging)
|
if (DataSource.RowCount > Constants.Telegram.MaxReplyKeyboardRows && !this.EnablePaging)
|
||||||
{
|
{
|
||||||
throw new MaximumRowsReachedException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxReplyKeyboardRows };
|
throw new MaximumRowsReachedException() { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxReplyKeyboardRows };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ButtonsForm.Cols > Constants.Telegram.MaxReplyKeyboardCols)
|
if (DataSource.ColumnCount > Constants.Telegram.MaxReplyKeyboardCols)
|
||||||
{
|
{
|
||||||
throw new MaximumColsException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxReplyKeyboardCols };
|
throw new MaximumColsException() { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxReplyKeyboardCols };
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -351,22 +423,21 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
this.RenderNecessary = false;
|
this.RenderNecessary = false;
|
||||||
|
|
||||||
Message m = null;
|
ButtonForm form = this.DataSource.PickItems(CurrentPageIndex * ItemRowsPerPage, ItemRowsPerPage, (this.EnableSearch ? this.SearchQuery : null));
|
||||||
|
|
||||||
ButtonForm form = this.ButtonsForm;
|
|
||||||
|
|
||||||
if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
||||||
{
|
//{
|
||||||
form = form.FilterDuplicate(this.SearchQuery, true);
|
// form = form.FilterDuplicate(this.SearchQuery, true);
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
form = form.Duplicate();
|
// form = form.Duplicate();
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (this.EnablePaging)
|
if (this.EnablePaging)
|
||||||
{
|
{
|
||||||
form = GeneratePagingView(form);
|
IntegratePagingView(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.HeadLayoutButtonRow != null && HeadLayoutButtonRow.Count > 0)
|
if (this.HeadLayoutButtonRow != null && HeadLayoutButtonRow.Count > 0)
|
||||||
@ -386,26 +457,37 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Message m = null;
|
||||||
|
|
||||||
switch (this.KeyboardType)
|
switch (this.KeyboardType)
|
||||||
{
|
{
|
||||||
//Reply Keyboard could only be updated with a new keyboard.
|
//Reply Keyboard could only be updated with a new keyboard.
|
||||||
case eKeyboardType.ReplyKeyboard:
|
case eKeyboardType.ReplyKeyboard:
|
||||||
|
|
||||||
if (this.MessageId != null)
|
|
||||||
|
if (form.Count == 0)
|
||||||
{
|
{
|
||||||
if (form.Count == 0)
|
if (this.MessageId != null)
|
||||||
{
|
{
|
||||||
await this.Device.HideReplyKeyboard();
|
await this.Device.HideReplyKeyboard();
|
||||||
this.MessageId = null;
|
this.MessageId = null;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.DeletePreviousMessage)
|
return;
|
||||||
await this.Device.DeleteMessage(this.MessageId.Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (form.Count == 0)
|
//if (this.MessageId != null)
|
||||||
return;
|
//{
|
||||||
|
// if (form.Count == 0)
|
||||||
|
// {
|
||||||
|
// await this.Device.HideReplyKeyboard();
|
||||||
|
// this.MessageId = null;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (form.Count == 0)
|
||||||
|
// return;
|
||||||
|
|
||||||
|
|
||||||
var rkm = (ReplyKeyboardMarkup)form;
|
var rkm = (ReplyKeyboardMarkup)form;
|
||||||
@ -413,6 +495,10 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
rkm.OneTimeKeyboard = this.OneTimeKeyboard;
|
rkm.OneTimeKeyboard = this.OneTimeKeyboard;
|
||||||
m = await this.Device.Send(this.Title, rkm, disableNotification: true, parseMode: MessageParseMode, MarkdownV2AutoEscape: false);
|
m = await this.Device.Send(this.Title, rkm, disableNotification: true, parseMode: MessageParseMode, MarkdownV2AutoEscape: false);
|
||||||
|
|
||||||
|
//Prevent flicker of keyboard
|
||||||
|
if (this.DeletePreviousMessage && this.MessageId != null)
|
||||||
|
await this.Device.DeleteMessage(this.MessageId.Value);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eKeyboardType.InlineKeyBoard:
|
case eKeyboardType.InlineKeyBoard:
|
||||||
@ -443,47 +529,31 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ButtonForm GeneratePagingView(ButtonForm dataForm)
|
private void IntegratePagingView(ButtonForm dataForm)
|
||||||
{
|
{
|
||||||
|
|
||||||
ButtonForm bf = new ButtonForm();
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < this.MaximumRow - LayoutRows; i++)
|
|
||||||
{
|
|
||||||
int it = (this.CurrentPageIndex * (this.MaximumRow - LayoutRows)) + i;
|
|
||||||
|
|
||||||
if (it > dataForm.Rows - 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
bf.AddButtonRow(dataForm[it]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//No Items
|
//No Items
|
||||||
if (this.ButtonsForm.Count == 0)
|
if (dataForm.Rows == 0)
|
||||||
{
|
{
|
||||||
bf.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
|
dataForm.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.IsNavigationBarVisible)
|
if (this.IsNavigationBarVisible)
|
||||||
{
|
{
|
||||||
//🔍
|
//🔍
|
||||||
List<ButtonBase> lst = new List<ButtonBase>();
|
ButtonRow row = new ButtonRow();
|
||||||
lst.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
|
row.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
|
||||||
lst.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
|
row.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
|
||||||
lst.Add(new ButtonBase(NextPageLabel, "$next$"));
|
row.Add(new ButtonBase(NextPageLabel, "$next$"));
|
||||||
|
|
||||||
if (this.EnableSearch)
|
if (this.EnableSearch)
|
||||||
{
|
{
|
||||||
lst.Insert(2, new ButtonBase("🔍 " + (this.SearchQuery ?? ""), "$search$"));
|
row.Insert(2, new ButtonBase("🔍 " + (this.SearchQuery ?? ""), "$search$"));
|
||||||
}
|
}
|
||||||
|
|
||||||
bf.InsertButtonRow(0, lst);
|
dataForm.InsertButtonRow(0, row);
|
||||||
|
|
||||||
bf.AddButtonRow(lst);
|
dataForm.AddButtonRow(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool PagingNecessary
|
public bool PagingNecessary
|
||||||
@ -545,7 +615,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return this.LayoutRows + ButtonsForm.Rows;
|
return this.LayoutRows + DataSource.RowCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -572,24 +642,40 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of item rows per page.
|
||||||
|
/// </summary>
|
||||||
|
public int ItemRowsPerPage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.MaximumRow - this.LayoutRows;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the number of pages.
|
||||||
|
/// </summary>
|
||||||
public int PageCount
|
public int PageCount
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (this.ButtonsForm.Count == 0)
|
if (DataSource.RowCount == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
var bf = this.ButtonsForm;
|
//var bf = this.DataSource.PickAllItems(this.EnableSearch ? this.SearchQuery : null);
|
||||||
|
|
||||||
if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
var max = this.DataSource.CalculateMax(this.EnableSearch ? this.SearchQuery : null);
|
||||||
{
|
|
||||||
bf = bf.FilterDuplicate(this.SearchQuery);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bf.Rows == 0)
|
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
||||||
|
//{
|
||||||
|
// bf = bf.FilterDuplicate(this.SearchQuery);
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (max == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return (int)Math.Ceiling((decimal)(bf.Rows / (decimal)(MaximumRow - this.LayoutRows)));
|
return (int)Math.Ceiling((decimal)((decimal)max / (decimal)ItemRowsPerPage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
112
TelegramBotBase/Controls/Hybrid/ButtonRow.cs
Normal file
112
TelegramBotBase/Controls/Hybrid/ButtonRow.cs
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text;
|
||||||
|
using TelegramBotBase.Form;
|
||||||
|
|
||||||
|
namespace TelegramBotBase.Controls.Hybrid
|
||||||
|
{
|
||||||
|
[DebuggerDisplay("{Count} columns")]
|
||||||
|
public class ButtonRow
|
||||||
|
{
|
||||||
|
|
||||||
|
List<ButtonBase> __buttons = new List<ButtonBase>();
|
||||||
|
|
||||||
|
public ButtonRow()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ButtonRow(params ButtonBase[] buttons)
|
||||||
|
{
|
||||||
|
__buttons = buttons.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ButtonBase this[int index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return __buttons[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return __buttons.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(ButtonBase button)
|
||||||
|
{
|
||||||
|
__buttons.Add(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRange(ButtonBase button)
|
||||||
|
{
|
||||||
|
__buttons.Add(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Insert(int index, ButtonBase button)
|
||||||
|
{
|
||||||
|
__buttons.Insert(index, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<ButtonBase> GetEnumerator()
|
||||||
|
{
|
||||||
|
return __buttons.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ButtonBase[] ToArray()
|
||||||
|
{
|
||||||
|
return __buttons.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ButtonBase> ToList()
|
||||||
|
{
|
||||||
|
return __buttons.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Matches(String text, bool useText = true)
|
||||||
|
{
|
||||||
|
foreach (var b in __buttons)
|
||||||
|
{
|
||||||
|
if (useText && b.Text.Trim().Equals(text, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!useText && b.Value.Equals(text, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the button inside of the row which matches.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text"></param>
|
||||||
|
/// <param name="useText"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public ButtonBase GetButtonMatch(String text, bool useText = true)
|
||||||
|
{
|
||||||
|
foreach (var b in __buttons)
|
||||||
|
{
|
||||||
|
if (useText && b.Text.Trim().Equals(text, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
return b;
|
||||||
|
if (!useText && b.Value.Equals(text, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ButtonRow(List<ButtonBase> list)
|
||||||
|
{
|
||||||
|
return new ButtonRow() { __buttons = list };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,6 +10,7 @@ using Telegram.Bot.Types.Enums;
|
|||||||
using Telegram.Bot.Types.ReplyMarkups;
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
using TelegramBotBase.Args;
|
using TelegramBotBase.Args;
|
||||||
using TelegramBotBase.Base;
|
using TelegramBotBase.Base;
|
||||||
|
using TelegramBotBase.Datasources;
|
||||||
using TelegramBotBase.Enums;
|
using TelegramBotBase.Enums;
|
||||||
using TelegramBotBase.Exceptions;
|
using TelegramBotBase.Exceptions;
|
||||||
using TelegramBotBase.Form;
|
using TelegramBotBase.Form;
|
||||||
@ -32,7 +33,23 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
private readonly EventHandlerList Events = new EventHandlerList();
|
private readonly EventHandlerList Events = new EventHandlerList();
|
||||||
|
|
||||||
public ButtonForm ButtonsForm { get; set; }
|
[Obsolete("This property is obsolete. Please use the DataSource property instead.")]
|
||||||
|
public ButtonForm ButtonsForm
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return DataSource.ButtonForm;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
DataSource = new ButtonFormDataSource(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Data source of the items.
|
||||||
|
/// </summary>
|
||||||
|
public ButtonFormDataSource DataSource { get; set; }
|
||||||
|
|
||||||
List<int> CheckedRows { get; set; } = new List<int>();
|
List<int> CheckedRows { get; set; } = new List<int>();
|
||||||
|
|
||||||
@ -51,6 +68,11 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
public bool DeletePreviousMessage { get; set; } = true;
|
public bool DeletePreviousMessage { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the reply message from a user.
|
||||||
|
/// </summary>
|
||||||
|
public bool DeleteReplyMessage { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parsemode of the message.
|
/// Parsemode of the message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -92,12 +114,12 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Layout of the buttons which should be displayed always on top.
|
/// Layout of the buttons which should be displayed always on top.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ButtonBase> HeadLayoutButtonRow { get; set; }
|
public ButtonRow HeadLayoutButtonRow { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Layout of columns which should be displayed below the header
|
/// Layout of columns which should be displayed below the header
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ButtonBase> SubHeadLayoutButtonRow { get; set; }
|
public ButtonRow SubHeadLayoutButtonRow { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines which type of Button Keyboard should be rendered.
|
/// Defines which type of Button Keyboard should be rendered.
|
||||||
@ -126,7 +148,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
public CheckedButtonList()
|
public CheckedButtonList()
|
||||||
{
|
{
|
||||||
this.ButtonsForm = new ButtonForm();
|
this.DataSource = new ButtonFormDataSource();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -139,7 +161,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
public CheckedButtonList(ButtonForm form)
|
public CheckedButtonList(ButtonForm form)
|
||||||
{
|
{
|
||||||
this.ButtonsForm = form;
|
this.DataSource = new ButtonFormDataSource(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
public event AsyncEventHandler<ButtonClickedEventArgs> ButtonClicked
|
public event AsyncEventHandler<ButtonClickedEventArgs> ButtonClicked
|
||||||
@ -198,16 +220,50 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
if (!result.IsFirstHandler)
|
if (!result.IsFirstHandler)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (result.MessageText == null)
|
if (result.MessageText == null || result.MessageText == "")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
var matches = new List<ButtonRow>();
|
||||||
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
ButtonRow match = null;
|
||||||
?? ButtonsForm.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText);
|
int index = -1;
|
||||||
|
|
||||||
var index = ButtonsForm.FindRowByButton(button);
|
if (HeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
|
||||||
|
{
|
||||||
|
match = HeadLayoutButtonRow;
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
if (button == null)
|
if (SubHeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
|
||||||
|
{
|
||||||
|
match = SubHeadLayoutButtonRow;
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
|
var br = DataSource.FindRow(result.MessageText);
|
||||||
|
if (br != null)
|
||||||
|
{
|
||||||
|
match = br.Item1;
|
||||||
|
index = br.Item2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//var button = HeadLayoutButtonRow?. .FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
||||||
|
// ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText);
|
||||||
|
|
||||||
|
// bf.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
||||||
|
|
||||||
|
//var index = bf.FindRowByButton(button);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
check:
|
||||||
|
|
||||||
|
|
||||||
|
//Remove button click message
|
||||||
|
if (this.DeleteReplyMessage)
|
||||||
|
await Device.DeleteMessage(result.MessageId);
|
||||||
|
|
||||||
|
if (match == null)
|
||||||
{
|
{
|
||||||
if (result.MessageText == PreviousPageLabel)
|
if (result.MessageText == PreviousPageLabel)
|
||||||
{
|
{
|
||||||
@ -226,7 +282,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
else if (result.MessageText.EndsWith(CheckedIconLabel))
|
else if (result.MessageText.EndsWith(CheckedIconLabel))
|
||||||
{
|
{
|
||||||
var s = result.MessageText.Split(' ', '.');
|
var s = result.MessageText.Split(' ', '.');
|
||||||
index = int.Parse(s[0]);
|
index = int.Parse(s[0]) - 1;
|
||||||
|
|
||||||
if (!this.CheckedRows.Contains(index))
|
if (!this.CheckedRows.Contains(index))
|
||||||
return;
|
return;
|
||||||
@ -241,7 +297,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
else if (result.MessageText.EndsWith(UncheckedIconLabel))
|
else if (result.MessageText.EndsWith(UncheckedIconLabel))
|
||||||
{
|
{
|
||||||
var s = result.MessageText.Split(' ', '.');
|
var s = result.MessageText.Split(' ', '.');
|
||||||
index = int.Parse(s[0]);
|
index = int.Parse(s[0]) - 1;
|
||||||
|
|
||||||
if (this.CheckedRows.Contains(index))
|
if (this.CheckedRows.Contains(index))
|
||||||
return;
|
return;
|
||||||
@ -285,14 +341,18 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
await OnButtonClicked(new ButtonClickedEventArgs(button, index));
|
await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.MessageText), index, match));
|
||||||
|
|
||||||
//Remove button click message
|
|
||||||
if (this.DeletePreviousMessage)
|
|
||||||
await Device.DeleteMessage(result.MessageId);
|
|
||||||
|
|
||||||
result.Handled = true;
|
result.Handled = true;
|
||||||
|
|
||||||
|
//await OnButtonClicked(new ButtonClickedEventArgs(button, index));
|
||||||
|
|
||||||
|
////Remove button click message
|
||||||
|
//if (this.DeletePreviousMessage)
|
||||||
|
// await Device.DeleteMessage(result.MessageId);
|
||||||
|
|
||||||
|
//result.Handled = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async override Task Action(MessageResult result, string value = null)
|
public async override Task Action(MessageResult result, string value = null)
|
||||||
@ -309,20 +369,55 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
await result.ConfirmAction(this.ConfirmationText ?? "");
|
await result.ConfirmAction(this.ConfirmationText ?? "");
|
||||||
|
|
||||||
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
ButtonRow match = null;
|
||||||
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
int index = -1;
|
||||||
?? ButtonsForm.ToList().FirstOrDefault(a => a.Value == result.RawData);
|
|
||||||
|
|
||||||
var index = ButtonsForm.FindRowByButton(button);
|
if (HeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
|
||||||
|
|
||||||
if (button != null)
|
|
||||||
{
|
{
|
||||||
await OnButtonClicked(new ButtonClickedEventArgs(button, index));
|
match = HeadLayoutButtonRow;
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SubHeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
|
||||||
|
{
|
||||||
|
match = SubHeadLayoutButtonRow;
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
|
var br = DataSource.FindRow(result.RawData, false);
|
||||||
|
if (br != null)
|
||||||
|
{
|
||||||
|
match = br.Item1;
|
||||||
|
index = br.Item2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//var bf = DataSource.ButtonForm;
|
||||||
|
|
||||||
|
//var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
||||||
|
// ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
||||||
|
// ?? bf.ToList().FirstOrDefault(a => a.Value == result.RawData);
|
||||||
|
|
||||||
|
//var index = bf.FindRowByButton(button);
|
||||||
|
|
||||||
|
check:
|
||||||
|
if (match != null)
|
||||||
|
{
|
||||||
|
await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.RawData, false), index, match));
|
||||||
|
|
||||||
result.Handled = true;
|
result.Handled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if (button != null)
|
||||||
|
//{
|
||||||
|
// await OnButtonClicked(new ButtonClickedEventArgs(button, index));
|
||||||
|
|
||||||
|
// result.Handled = true;
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
switch (result.RawData)
|
switch (result.RawData)
|
||||||
{
|
{
|
||||||
case "$previous$":
|
case "$previous$":
|
||||||
@ -396,28 +491,28 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
{
|
{
|
||||||
case eKeyboardType.InlineKeyBoard:
|
case eKeyboardType.InlineKeyBoard:
|
||||||
|
|
||||||
if (ButtonsForm.Rows > Constants.Telegram.MaxInlineKeyBoardRows && !this.EnablePaging)
|
if (DataSource.RowCount > Constants.Telegram.MaxInlineKeyBoardRows && !this.EnablePaging)
|
||||||
{
|
{
|
||||||
throw new MaximumRowsReachedException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxInlineKeyBoardRows };
|
throw new MaximumRowsReachedException() { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxInlineKeyBoardRows };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ButtonsForm.Cols > Constants.Telegram.MaxInlineKeyBoardCols)
|
if (DataSource.ColumnCount > Constants.Telegram.MaxInlineKeyBoardCols)
|
||||||
{
|
{
|
||||||
throw new MaximumColsException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxInlineKeyBoardCols };
|
throw new MaximumColsException() { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxInlineKeyBoardCols };
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eKeyboardType.ReplyKeyboard:
|
case eKeyboardType.ReplyKeyboard:
|
||||||
|
|
||||||
if (ButtonsForm.Rows > Constants.Telegram.MaxReplyKeyboardRows && !this.EnablePaging)
|
if (DataSource.RowCount > Constants.Telegram.MaxReplyKeyboardRows && !this.EnablePaging)
|
||||||
{
|
{
|
||||||
throw new MaximumRowsReachedException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxReplyKeyboardRows };
|
throw new MaximumRowsReachedException() { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxReplyKeyboardRows };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ButtonsForm.Cols > Constants.Telegram.MaxReplyKeyboardCols)
|
if (DataSource.ColumnCount > Constants.Telegram.MaxReplyKeyboardCols)
|
||||||
{
|
{
|
||||||
throw new MaximumColsException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxReplyKeyboardCols };
|
throw new MaximumColsException() { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxReplyKeyboardCols };
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -436,7 +531,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
Message m = null;
|
Message m = null;
|
||||||
|
|
||||||
ButtonForm form = this.ButtonsForm;
|
ButtonForm form = this.DataSource.PickItems(CurrentPageIndex * ItemRowsPerPage, ItemRowsPerPage, null);
|
||||||
|
|
||||||
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
||||||
//{
|
//{
|
||||||
@ -444,12 +539,12 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
//}
|
//}
|
||||||
//else
|
//else
|
||||||
//{
|
//{
|
||||||
form = form.Duplicate();
|
//form = form.Duplicate();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
if (this.EnablePaging)
|
if (this.EnablePaging)
|
||||||
{
|
{
|
||||||
form = GeneratePagingView(form);
|
IntegratePagingView(form);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -458,18 +553,18 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
if (this.HeadLayoutButtonRow != null && HeadLayoutButtonRow.Count > 0)
|
if (this.HeadLayoutButtonRow != null && HeadLayoutButtonRow.Count > 0)
|
||||||
{
|
{
|
||||||
form.InsertButtonRow(0, this.HeadLayoutButtonRow);
|
form.InsertButtonRow(0, this.HeadLayoutButtonRow.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.SubHeadLayoutButtonRow != null && SubHeadLayoutButtonRow.Count > 0)
|
if (this.SubHeadLayoutButtonRow != null && SubHeadLayoutButtonRow.Count > 0)
|
||||||
{
|
{
|
||||||
if (this.IsNavigationBarVisible)
|
if (this.IsNavigationBarVisible)
|
||||||
{
|
{
|
||||||
form.InsertButtonRow(2, this.SubHeadLayoutButtonRow);
|
form.InsertButtonRow(2, this.SubHeadLayoutButtonRow.ToArray());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
form.InsertButtonRow(1, this.SubHeadLayoutButtonRow);
|
form.InsertButtonRow(1, this.SubHeadLayoutButtonRow.ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,21 +573,19 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
//Reply Keyboard could only be updated with a new keyboard.
|
//Reply Keyboard could only be updated with a new keyboard.
|
||||||
case eKeyboardType.ReplyKeyboard:
|
case eKeyboardType.ReplyKeyboard:
|
||||||
|
|
||||||
if (this.MessageId != null)
|
if (form.Count == 0)
|
||||||
{
|
{
|
||||||
if (form.Count == 0)
|
if (this.MessageId != null)
|
||||||
{
|
{
|
||||||
await this.Device.HideReplyKeyboard();
|
await this.Device.HideReplyKeyboard();
|
||||||
this.MessageId = null;
|
this.MessageId = null;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.DeletePreviousMessage)
|
return;
|
||||||
await this.Device.DeleteMessage(this.MessageId.Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (form.Count == 0)
|
//if (form.Count == 0)
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
|
|
||||||
var rkm = (ReplyKeyboardMarkup)form;
|
var rkm = (ReplyKeyboardMarkup)form;
|
||||||
@ -500,6 +593,10 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
rkm.OneTimeKeyboard = this.OneTimeKeyboard;
|
rkm.OneTimeKeyboard = this.OneTimeKeyboard;
|
||||||
m = await this.Device.Send(this.Title, rkm, disableNotification: true, parseMode: MessageParseMode, MarkdownV2AutoEscape: false);
|
m = await this.Device.Send(this.Title, rkm, disableNotification: true, parseMode: MessageParseMode, MarkdownV2AutoEscape: false);
|
||||||
|
|
||||||
|
//Prevent flicker of keyboard
|
||||||
|
if (this.DeletePreviousMessage && this.MessageId != null)
|
||||||
|
await this.Device.DeleteMessage(this.MessageId.Value);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eKeyboardType.InlineKeyBoard:
|
case eKeyboardType.InlineKeyBoard:
|
||||||
@ -524,58 +621,52 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ButtonForm GeneratePagingView(ButtonForm dataForm)
|
private void IntegratePagingView(ButtonForm dataForm)
|
||||||
{
|
{
|
||||||
|
//No Items
|
||||||
|
if (dataForm.Rows == 0)
|
||||||
|
{
|
||||||
|
dataForm.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
|
||||||
|
}
|
||||||
|
|
||||||
ButtonForm bf = new ButtonForm();
|
ButtonForm bf = new ButtonForm();
|
||||||
|
|
||||||
bf = PrepareCheckableLayout(dataForm);
|
bf = PrepareCheckableLayout(dataForm);
|
||||||
|
|
||||||
//No Items
|
|
||||||
if (this.ButtonsForm.Count == 0)
|
|
||||||
{
|
|
||||||
bf.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.IsNavigationBarVisible)
|
if (this.IsNavigationBarVisible)
|
||||||
{
|
{
|
||||||
//🔍
|
//🔍
|
||||||
List<ButtonBase> lst = new List<ButtonBase>();
|
ButtonRow row = new ButtonRow();
|
||||||
lst.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
|
row.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
|
||||||
lst.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
|
row.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
|
||||||
lst.Add(new ButtonBase(NextPageLabel, "$next$"));
|
row.Add(new ButtonBase(NextPageLabel, "$next$"));
|
||||||
|
|
||||||
//if (this.EnableSearch)
|
|
||||||
//{
|
|
||||||
// lst.Insert(2, new ButtonBase("🔍 " + (this.SearchQuery ?? ""), "$search$"));
|
|
||||||
//}
|
|
||||||
|
|
||||||
bf.InsertButtonRow(0, lst);
|
dataForm.InsertButtonRow(0, row);
|
||||||
|
|
||||||
bf.AddButtonRow(lst);
|
dataForm.AddButtonRow(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ButtonForm PrepareCheckableLayout(ButtonForm dataForm)
|
private ButtonForm PrepareCheckableLayout(ButtonForm dataForm)
|
||||||
{
|
{
|
||||||
var bf = new ButtonForm();
|
var bf = new ButtonForm();
|
||||||
for (int i = 0; i < this.MaximumRow - LayoutRows; i++)
|
for (int i = 0; i < dataForm.Rows; i++)
|
||||||
{
|
{
|
||||||
int it = (this.CurrentPageIndex * (this.MaximumRow - LayoutRows)) + i;
|
int it = (this.CurrentPageIndex * (this.MaximumRow - LayoutRows)) + i;
|
||||||
|
|
||||||
if (it > dataForm.Rows - 1)
|
//if (it > dataForm.Rows - 1)
|
||||||
break;
|
// break;
|
||||||
|
|
||||||
var r = dataForm[it];
|
var r = dataForm[i];
|
||||||
|
|
||||||
String s = CheckedRows.Contains(it) ? this.CheckedIconLabel : this.UncheckedIconLabel;
|
String s = CheckedRows.Contains(it) ? this.CheckedIconLabel : this.UncheckedIconLabel;
|
||||||
|
|
||||||
//On reply keyboards we need a unique text.
|
//On reply keyboards we need a unique text.
|
||||||
if (this.KeyboardType == eKeyboardType.ReplyKeyboard)
|
if (this.KeyboardType == eKeyboardType.ReplyKeyboard)
|
||||||
{
|
{
|
||||||
s = $"{it}. " + s;
|
s = $"{it + 1}. " + s;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CheckedRows.Contains(it))
|
if (CheckedRows.Contains(it))
|
||||||
@ -652,7 +743,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return this.LayoutRows + ButtonsForm.Rows;
|
return this.LayoutRows + DataSource.RowCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,24 +770,37 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of item rows per page.
|
||||||
|
/// </summary>
|
||||||
|
public int ItemRowsPerPage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.MaximumRow - this.LayoutRows;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int PageCount
|
public int PageCount
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (this.ButtonsForm.Count == 0)
|
if (DataSource.RowCount == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
var bf = this.ButtonsForm;
|
//var bf = this.DataSource.PickAllItems(this.EnableSearch ? this.SearchQuery : null);
|
||||||
|
|
||||||
|
var max = this.DataSource.RowCount;
|
||||||
|
|
||||||
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
||||||
//{
|
//{
|
||||||
// bf = bf.FilterDuplicate(this.SearchQuery);
|
// bf = bf.FilterDuplicate(this.SearchQuery);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
if (bf.Rows == 0)
|
if (max == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return (int)Math.Ceiling((decimal)(bf.Rows / (decimal)(MaximumRow - this.LayoutRows)));
|
return (int)Math.Ceiling((decimal)((decimal)max / (decimal)ItemRowsPerPage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,9 +7,11 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Telegram.Bot.Types;
|
using Telegram.Bot.Types;
|
||||||
using Telegram.Bot.Types.Enums;
|
using Telegram.Bot.Types.Enums;
|
||||||
|
using Telegram.Bot.Types.InlineQueryResults;
|
||||||
using Telegram.Bot.Types.ReplyMarkups;
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
using TelegramBotBase.Args;
|
using TelegramBotBase.Args;
|
||||||
using TelegramBotBase.Base;
|
using TelegramBotBase.Base;
|
||||||
|
using TelegramBotBase.Datasources;
|
||||||
using TelegramBotBase.Enums;
|
using TelegramBotBase.Enums;
|
||||||
using TelegramBotBase.Exceptions;
|
using TelegramBotBase.Exceptions;
|
||||||
using TelegramBotBase.Form;
|
using TelegramBotBase.Form;
|
||||||
@ -30,7 +32,23 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
private readonly EventHandlerList Events = new EventHandlerList();
|
private readonly EventHandlerList Events = new EventHandlerList();
|
||||||
|
|
||||||
public ButtonForm ButtonsForm { get; set; }
|
[Obsolete("This property is obsolete. Please use the DataSource property instead.")]
|
||||||
|
public ButtonForm ButtonsForm
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return DataSource.ButtonForm;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
DataSource = new ButtonFormDataSource(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Data source of the items.
|
||||||
|
/// </summary>
|
||||||
|
public ButtonFormDataSource DataSource { get; set; }
|
||||||
|
|
||||||
public int? MessageId { get; set; }
|
public int? MessageId { get; set; }
|
||||||
|
|
||||||
@ -47,6 +65,11 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
public bool DeletePreviousMessage { get; set; } = true;
|
public bool DeletePreviousMessage { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the reply message from a user.
|
||||||
|
/// </summary>
|
||||||
|
public bool DeleteReplyMessage { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parsemode of the message.
|
/// Parsemode of the message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -57,6 +80,11 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnablePaging { get; set; } = false;
|
public bool EnablePaging { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shows un-/check all tags options
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableCheckAllTools { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enabled a search function.
|
/// Enabled a search function.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -82,15 +110,24 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
public String BackLabel = Localizations.Default.Language["ButtonGrid_Back"];
|
public String BackLabel = Localizations.Default.Language["ButtonGrid_Back"];
|
||||||
|
|
||||||
|
public String CheckAllLabel = Localizations.Default.Language["ButtonGrid_CheckAll"];
|
||||||
|
|
||||||
|
public String UncheckAllLabel = Localizations.Default.Language["ButtonGrid_UncheckAll"];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Layout of the buttons which should be displayed always on top.
|
/// Layout of the buttons which should be displayed always on top.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ButtonBase> HeadLayoutButtonRow { get; set; }
|
public ButtonRow HeadLayoutButtonRow { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Layout of columns which should be displayed below the header
|
/// Layout of columns which should be displayed below the header
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ButtonBase> SubHeadLayoutButtonRow { get; set; }
|
public ButtonRow SubHeadLayoutButtonRow { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Layout of columns which should be displayed below the header
|
||||||
|
/// </summary>
|
||||||
|
private ButtonRow TagsSubHeadLayoutButtonRow { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of Tags which will be allowed to filter by.
|
/// List of Tags which will be allowed to filter by.
|
||||||
@ -129,7 +166,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
public TaggedButtonGrid()
|
public TaggedButtonGrid()
|
||||||
{
|
{
|
||||||
this.ButtonsForm = new ButtonForm();
|
this.DataSource = new ButtonFormDataSource();
|
||||||
|
|
||||||
this.SelectedViewIndex = 0;
|
this.SelectedViewIndex = 0;
|
||||||
}
|
}
|
||||||
@ -142,7 +179,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
public TaggedButtonGrid(ButtonForm form)
|
public TaggedButtonGrid(ButtonForm form)
|
||||||
{
|
{
|
||||||
this.ButtonsForm = form;
|
this.DataSource = new ButtonFormDataSource(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -194,30 +231,63 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
if (!result.IsFirstHandler)
|
if (!result.IsFirstHandler)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (result.MessageText == null)
|
if (result.MessageText == null || result.MessageText == "")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
var matches = new List<ButtonRow>();
|
||||||
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
ButtonRow match = null;
|
||||||
?? ButtonsForm.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText);
|
int index = -1;
|
||||||
|
|
||||||
|
if (HeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
|
||||||
|
{
|
||||||
|
match = HeadLayoutButtonRow;
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SubHeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
|
||||||
|
{
|
||||||
|
match = SubHeadLayoutButtonRow;
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TagsSubHeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
|
||||||
|
{
|
||||||
|
match = TagsSubHeadLayoutButtonRow;
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
|
var br = DataSource.FindRow(result.MessageText);
|
||||||
|
if (br != null)
|
||||||
|
{
|
||||||
|
match = br.Item1;
|
||||||
|
index = br.Item2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//var button = HeadLayoutButtonRow?. .FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
||||||
|
// ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText);
|
||||||
|
|
||||||
|
// bf.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
||||||
|
|
||||||
|
//var index = bf.FindRowByButton(button);
|
||||||
|
|
||||||
|
check:
|
||||||
|
|
||||||
var index = ButtonsForm.FindRowByButton(button);
|
|
||||||
|
|
||||||
|
|
||||||
switch (this.SelectedViewIndex)
|
switch (this.SelectedViewIndex)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
|
|
||||||
if (button != null)
|
//Remove button click message
|
||||||
{
|
if (this.DeleteReplyMessage)
|
||||||
await OnButtonClicked(new ButtonClickedEventArgs(button, index));
|
await Device.DeleteMessage(result.MessageId);
|
||||||
|
|
||||||
//Remove button click message
|
if (match != null)
|
||||||
if (this.DeletePreviousMessage)
|
{
|
||||||
await Device.DeleteMessage(result.MessageId);
|
await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.MessageText), index, match));
|
||||||
|
|
||||||
result.Handled = true;
|
result.Handled = true;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,17 +352,25 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
|
||||||
|
//Remove button click message
|
||||||
|
if (this.DeleteReplyMessage)
|
||||||
|
await Device.DeleteMessage(result.MessageId);
|
||||||
|
|
||||||
if (result.MessageText == this.BackLabel)
|
if (result.MessageText == this.BackLabel)
|
||||||
{
|
{
|
||||||
//Remove button click message
|
|
||||||
if (this.DeletePreviousMessage)
|
|
||||||
await Device.DeleteMessage(result.MessageId);
|
|
||||||
|
|
||||||
this.SelectedViewIndex = 0;
|
this.SelectedViewIndex = 0;
|
||||||
this.Updated();
|
this.Updated();
|
||||||
result.Handled = true;
|
result.Handled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (result.MessageText == this.CheckAllLabel)
|
||||||
|
{
|
||||||
|
this.CheckAllTags();
|
||||||
|
}
|
||||||
|
else if (result.MessageText == this.UncheckAllLabel)
|
||||||
|
{
|
||||||
|
this.UncheckAllTags();
|
||||||
|
}
|
||||||
|
|
||||||
var i = result.MessageText.LastIndexOf(" ");
|
var i = result.MessageText.LastIndexOf(" ");
|
||||||
if (i == -1)
|
if (i == -1)
|
||||||
@ -323,27 +401,60 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
public async override Task Action(MessageResult result, string value = null)
|
public async override Task Action(MessageResult result, string value = null)
|
||||||
{
|
{
|
||||||
//Find clicked button depending on Text or Value (depending on markup type)
|
|
||||||
if (this.KeyboardType != eKeyboardType.InlineKeyBoard)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (result.Handled)
|
if (result.Handled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!result.IsFirstHandler)
|
if (!result.IsFirstHandler)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
//Find clicked button depending on Text or Value (depending on markup type)
|
||||||
|
if (this.KeyboardType != eKeyboardType.InlineKeyBoard)
|
||||||
|
return;
|
||||||
|
|
||||||
await result.ConfirmAction(this.ConfirmationText ?? "");
|
await result.ConfirmAction(this.ConfirmationText ?? "");
|
||||||
|
|
||||||
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
ButtonRow match = null;
|
||||||
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
int index = -1;
|
||||||
?? ButtonsForm.ToList().FirstOrDefault(a => a.Value == result.RawData);
|
|
||||||
|
|
||||||
var index = ButtonsForm.FindRowByButton(button);
|
if (HeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
|
||||||
|
|
||||||
if (button != null)
|
|
||||||
{
|
{
|
||||||
await OnButtonClicked(new ButtonClickedEventArgs(button, index));
|
match = HeadLayoutButtonRow;
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SubHeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
|
||||||
|
{
|
||||||
|
match = SubHeadLayoutButtonRow;
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TagsSubHeadLayoutButtonRow?.Matches(result.RawData) ?? false)
|
||||||
|
{
|
||||||
|
match = TagsSubHeadLayoutButtonRow;
|
||||||
|
goto check;
|
||||||
|
}
|
||||||
|
|
||||||
|
var br = DataSource.FindRow(result.RawData, false);
|
||||||
|
if (br != null)
|
||||||
|
{
|
||||||
|
match = br.Item1;
|
||||||
|
index = br.Item2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//var bf = DataSource.ButtonForm;
|
||||||
|
|
||||||
|
//var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
||||||
|
// ?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
||||||
|
// ?? bf.ToList().FirstOrDefault(a => a.Value == result.RawData);
|
||||||
|
|
||||||
|
//var index = bf.FindRowByButton(button);
|
||||||
|
|
||||||
|
check:
|
||||||
|
if (match != null)
|
||||||
|
{
|
||||||
|
await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.RawData, false), index, match));
|
||||||
|
|
||||||
result.Handled = true;
|
result.Handled = true;
|
||||||
return;
|
return;
|
||||||
@ -381,6 +492,18 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
this.SelectedViewIndex = 0;
|
this.SelectedViewIndex = 0;
|
||||||
this.Updated();
|
this.Updated();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "$checkall$":
|
||||||
|
|
||||||
|
this.CheckAllTags();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "$uncheckall$":
|
||||||
|
|
||||||
|
this.UncheckAllTags();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,28 +518,28 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
{
|
{
|
||||||
case eKeyboardType.InlineKeyBoard:
|
case eKeyboardType.InlineKeyBoard:
|
||||||
|
|
||||||
if (ButtonsForm.Rows > Constants.Telegram.MaxInlineKeyBoardRows && !this.EnablePaging)
|
if (DataSource.RowCount > Constants.Telegram.MaxInlineKeyBoardRows && !this.EnablePaging)
|
||||||
{
|
{
|
||||||
throw new MaximumRowsReachedException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxInlineKeyBoardRows };
|
throw new MaximumRowsReachedException() { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxInlineKeyBoardRows };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ButtonsForm.Cols > Constants.Telegram.MaxInlineKeyBoardCols)
|
if (DataSource.ColumnCount > Constants.Telegram.MaxInlineKeyBoardCols)
|
||||||
{
|
{
|
||||||
throw new MaximumColsException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxInlineKeyBoardCols };
|
throw new MaximumColsException() { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxInlineKeyBoardCols };
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eKeyboardType.ReplyKeyboard:
|
case eKeyboardType.ReplyKeyboard:
|
||||||
|
|
||||||
if (ButtonsForm.Rows > Constants.Telegram.MaxReplyKeyboardRows && !this.EnablePaging)
|
if (DataSource.RowCount > Constants.Telegram.MaxReplyKeyboardRows && !this.EnablePaging)
|
||||||
{
|
{
|
||||||
throw new MaximumRowsReachedException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxReplyKeyboardRows };
|
throw new MaximumRowsReachedException() { Value = DataSource.RowCount, Maximum = Constants.Telegram.MaxReplyKeyboardRows };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ButtonsForm.Cols > Constants.Telegram.MaxReplyKeyboardCols)
|
if (DataSource.ColumnCount > Constants.Telegram.MaxReplyKeyboardCols)
|
||||||
{
|
{
|
||||||
throw new MaximumColsException() { Value = ButtonsForm.Rows, Maximum = Constants.Telegram.MaxReplyKeyboardCols };
|
throw new MaximumColsException() { Value = DataSource.ColumnCount, Maximum = Constants.Telegram.MaxReplyKeyboardCols };
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -463,16 +586,16 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
{
|
{
|
||||||
Message m = null;
|
Message m = null;
|
||||||
|
|
||||||
ButtonForm form = this.ButtonsForm;
|
ButtonForm form = this.DataSource.PickItems(CurrentPageIndex * ItemRowsPerPage, ItemRowsPerPage, (this.EnableSearch ? this.SearchQuery : null));
|
||||||
|
|
||||||
if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
||||||
{
|
//{
|
||||||
form = form.FilterDuplicate(this.SearchQuery, true);
|
// form = form.FilterDuplicate(this.SearchQuery, true);
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
form = form.Duplicate();
|
// form = form.Duplicate();
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (this.Tags != null && this.SelectedTags != null)
|
if (this.Tags != null && this.SelectedTags != null)
|
||||||
{
|
{
|
||||||
@ -481,23 +604,23 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
if (this.EnablePaging)
|
if (this.EnablePaging)
|
||||||
{
|
{
|
||||||
form = GeneratePagingView(form);
|
IntegratePagingView(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.HeadLayoutButtonRow != null && HeadLayoutButtonRow.Count > 0)
|
if (this.HeadLayoutButtonRow != null && HeadLayoutButtonRow.Count > 0)
|
||||||
{
|
{
|
||||||
form.InsertButtonRow(0, this.HeadLayoutButtonRow);
|
form.InsertButtonRow(0, this.HeadLayoutButtonRow.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.SubHeadLayoutButtonRow != null && SubHeadLayoutButtonRow.Count > 0)
|
if (this.SubHeadLayoutButtonRow != null && SubHeadLayoutButtonRow.Count > 0)
|
||||||
{
|
{
|
||||||
if (this.IsNavigationBarVisible)
|
if (this.IsNavigationBarVisible)
|
||||||
{
|
{
|
||||||
form.InsertButtonRow(2, this.SubHeadLayoutButtonRow);
|
form.InsertButtonRow(2, this.SubHeadLayoutButtonRow.ToArray());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
form.InsertButtonRow(1, this.SubHeadLayoutButtonRow);
|
form.InsertButtonRow(1, this.SubHeadLayoutButtonRow.ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,21 +629,15 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
//Reply Keyboard could only be updated with a new keyboard.
|
//Reply Keyboard could only be updated with a new keyboard.
|
||||||
case eKeyboardType.ReplyKeyboard:
|
case eKeyboardType.ReplyKeyboard:
|
||||||
|
|
||||||
if (this.MessageId != null)
|
if (form.Count == 0)
|
||||||
{
|
{
|
||||||
if (form.Count == 0)
|
if (this.MessageId != null)
|
||||||
{
|
{
|
||||||
await this.Device.HideReplyKeyboard();
|
await this.Device.HideReplyKeyboard();
|
||||||
this.MessageId = null;
|
this.MessageId = null;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.DeletePreviousMessage)
|
|
||||||
await this.Device.DeleteMessage(this.MessageId.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (form.Count == 0)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var rkm = (ReplyKeyboardMarkup)form;
|
var rkm = (ReplyKeyboardMarkup)form;
|
||||||
@ -528,6 +645,10 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
rkm.OneTimeKeyboard = this.OneTimeKeyboard;
|
rkm.OneTimeKeyboard = this.OneTimeKeyboard;
|
||||||
m = await this.Device.Send(this.Title, rkm, disableNotification: true, parseMode: MessageParseMode, MarkdownV2AutoEscape: false);
|
m = await this.Device.Send(this.Title, rkm, disableNotification: true, parseMode: MessageParseMode, MarkdownV2AutoEscape: false);
|
||||||
|
|
||||||
|
//Prevent flicker of keyboard
|
||||||
|
if (this.DeletePreviousMessage && this.MessageId != null)
|
||||||
|
await this.Device.DeleteMessage(this.MessageId.Value);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eKeyboardType.InlineKeyBoard:
|
case eKeyboardType.InlineKeyBoard:
|
||||||
@ -556,52 +677,37 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ButtonForm GeneratePagingView(ButtonForm dataForm)
|
private void IntegratePagingView(ButtonForm dataForm)
|
||||||
{
|
{
|
||||||
ButtonForm bf = new ButtonForm();
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < this.MaximumRow - LayoutRows; i++)
|
|
||||||
{
|
|
||||||
int it = (this.CurrentPageIndex * (this.MaximumRow - LayoutRows)) + i;
|
|
||||||
|
|
||||||
if (it > dataForm.Rows - 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
bf.AddButtonRow(dataForm[it]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//No Items
|
//No Items
|
||||||
if (this.ButtonsForm.Count == 0)
|
if (dataForm.Rows == 0)
|
||||||
{
|
{
|
||||||
bf.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
|
dataForm.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.IsNavigationBarVisible)
|
if (this.IsNavigationBarVisible)
|
||||||
{
|
{
|
||||||
//🔍
|
//🔍
|
||||||
List<ButtonBase> lst = new List<ButtonBase>();
|
ButtonRow row = new ButtonRow();
|
||||||
lst.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
|
row.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
|
||||||
lst.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
|
row.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
|
||||||
|
|
||||||
if (this.Tags != null && this.Tags.Count > 0)
|
if (this.Tags != null && this.Tags.Count > 0)
|
||||||
{
|
{
|
||||||
lst.Add(new ButtonBase("📁", "$filter$"));
|
row.Add(new ButtonBase("📁", "$filter$"));
|
||||||
}
|
}
|
||||||
|
|
||||||
lst.Add(new ButtonBase(NextPageLabel, "$next$"));
|
row.Add(new ButtonBase(NextPageLabel, "$next$"));
|
||||||
|
|
||||||
if (this.EnableSearch)
|
if (this.EnableSearch)
|
||||||
{
|
{
|
||||||
lst.Insert(2, new ButtonBase("🔍 " + (this.SearchQuery ?? ""), "$search$"));
|
row.Insert(2, new ButtonBase("🔍 " + (this.SearchQuery ?? ""), "$search$"));
|
||||||
}
|
}
|
||||||
|
|
||||||
bf.InsertButtonRow(0, lst);
|
dataForm.InsertButtonRow(0, row);
|
||||||
|
|
||||||
bf.AddButtonRow(lst);
|
dataForm.AddButtonRow(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -617,6 +723,12 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
bf.AddButtonRow(this.BackLabel, "$back$");
|
bf.AddButtonRow(this.BackLabel, "$back$");
|
||||||
|
|
||||||
|
if (EnableCheckAllTools)
|
||||||
|
{
|
||||||
|
this.TagsSubHeadLayoutButtonRow = new ButtonRow(new ButtonBase(CheckAllLabel, "$checkall$"), new ButtonBase(UncheckAllLabel, "$uncheckall$"));
|
||||||
|
bf.AddButtonRow(TagsSubHeadLayoutButtonRow);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var t in this.Tags)
|
foreach (var t in this.Tags)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -636,21 +748,18 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
//Reply Keyboard could only be updated with a new keyboard.
|
//Reply Keyboard could only be updated with a new keyboard.
|
||||||
case eKeyboardType.ReplyKeyboard:
|
case eKeyboardType.ReplyKeyboard:
|
||||||
|
|
||||||
if (this.MessageId != null)
|
if (bf.Count == 0)
|
||||||
{
|
{
|
||||||
if (bf.Count == 0)
|
if (this.MessageId != null)
|
||||||
{
|
{
|
||||||
await this.Device.HideReplyKeyboard();
|
await this.Device.HideReplyKeyboard();
|
||||||
this.MessageId = null;
|
this.MessageId = null;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
if (this.DeletePreviousMessage)
|
|
||||||
await this.Device.DeleteMessage(this.MessageId.Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bf.Count == 0)
|
//if (bf.Count == 0)
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
|
|
||||||
var rkm = (ReplyKeyboardMarkup)bf;
|
var rkm = (ReplyKeyboardMarkup)bf;
|
||||||
@ -658,6 +767,10 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
rkm.OneTimeKeyboard = this.OneTimeKeyboard;
|
rkm.OneTimeKeyboard = this.OneTimeKeyboard;
|
||||||
m = await this.Device.Send("Choose category", rkm, disableNotification: true, parseMode: MessageParseMode, MarkdownV2AutoEscape: false);
|
m = await this.Device.Send("Choose category", rkm, disableNotification: true, parseMode: MessageParseMode, MarkdownV2AutoEscape: false);
|
||||||
|
|
||||||
|
//Prevent flicker of keyboard
|
||||||
|
if (this.DeletePreviousMessage && this.MessageId != null)
|
||||||
|
await this.Device.DeleteMessage(this.MessageId.Value);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eKeyboardType.InlineKeyBoard:
|
case eKeyboardType.InlineKeyBoard:
|
||||||
@ -744,7 +857,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return this.LayoutRows + ButtonsForm.Rows;
|
return this.LayoutRows + DataSource.RowCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -767,28 +880,46 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
if (this.SubHeadLayoutButtonRow != null && this.SubHeadLayoutButtonRow.Count > 0)
|
if (this.SubHeadLayoutButtonRow != null && this.SubHeadLayoutButtonRow.Count > 0)
|
||||||
layoutRows++;
|
layoutRows++;
|
||||||
|
|
||||||
|
if (EnableCheckAllTools && this.SelectedViewIndex == 1)
|
||||||
|
{
|
||||||
|
layoutRows++;
|
||||||
|
}
|
||||||
|
|
||||||
return layoutRows;
|
return layoutRows;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of item rows per page.
|
||||||
|
/// </summary>
|
||||||
|
public int ItemRowsPerPage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.MaximumRow - this.LayoutRows;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int PageCount
|
public int PageCount
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (this.ButtonsForm.Count == 0)
|
if (DataSource.RowCount == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
var bf = this.ButtonsForm;
|
//var bf = this.DataSource.PickAllItems(this.EnableSearch ? this.SearchQuery : null);
|
||||||
|
|
||||||
if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
var max = this.DataSource.CalculateMax(this.EnableSearch ? this.SearchQuery : null);
|
||||||
{
|
|
||||||
bf = bf.FilterDuplicate(this.SearchQuery);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bf.Rows == 0)
|
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
||||||
|
//{
|
||||||
|
// bf = bf.FilterDuplicate(this.SearchQuery);
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (max == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return (int)Math.Ceiling((decimal)(bf.Rows / (decimal)(MaximumRow - this.LayoutRows)));
|
return (int)Math.Ceiling((decimal)((decimal)max / (decimal)ItemRowsPerPage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -840,9 +971,30 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks all tags for filtering.
|
||||||
|
/// </summary>
|
||||||
|
public void CheckAllTags()
|
||||||
|
{
|
||||||
|
this.SelectedTags.Clear();
|
||||||
|
|
||||||
|
this.SelectedTags = this.Tags.Select(a => a).ToList();
|
||||||
|
|
||||||
|
this.Updated();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unchecks all tags for filtering.
|
||||||
|
/// </summary>
|
||||||
|
public void UncheckAllTags()
|
||||||
|
{
|
||||||
|
this.SelectedTags.Clear();
|
||||||
|
|
||||||
|
this.Updated();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
142
TelegramBotBase/Datasources/ButtonFormDataSource.cs
Normal file
142
TelegramBotBase/Datasources/ButtonFormDataSource.cs
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using TelegramBotBase.Controls.Hybrid;
|
||||||
|
using TelegramBotBase.Form;
|
||||||
|
using TelegramBotBase.Interfaces;
|
||||||
|
|
||||||
|
namespace TelegramBotBase.Datasources
|
||||||
|
{
|
||||||
|
public class ButtonFormDataSource : Interfaces.IDataSource<ButtonRow>
|
||||||
|
{
|
||||||
|
public virtual ButtonForm ButtonForm
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return __buttonform;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
__buttonform = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ButtonForm __buttonform = null;
|
||||||
|
|
||||||
|
public ButtonFormDataSource()
|
||||||
|
{
|
||||||
|
__buttonform = new ButtonForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ButtonFormDataSource(ButtonForm bf)
|
||||||
|
{
|
||||||
|
__buttonform = bf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the amount of rows exisiting.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual int Count => ButtonForm.Count;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the amount of rows.
|
||||||
|
/// </summary>
|
||||||
|
public virtual int RowCount => ButtonForm.Rows;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the maximum amount of columns.
|
||||||
|
/// </summary>
|
||||||
|
public virtual int ColumnCount => ButtonForm.Cols;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the row with the specific index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="index"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual ButtonRow ItemAt(int index)
|
||||||
|
{
|
||||||
|
return ButtonForm[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual List<ButtonRow> ItemRange(int start, int count)
|
||||||
|
{
|
||||||
|
return ButtonForm.GetRange(start, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual List<ButtonRow> AllItems()
|
||||||
|
{
|
||||||
|
return ButtonForm.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual ButtonForm PickItems(int start, int count, String filter = null)
|
||||||
|
{
|
||||||
|
ButtonForm bf = new ButtonForm();
|
||||||
|
ButtonForm dataForm = null;
|
||||||
|
|
||||||
|
if (filter == null)
|
||||||
|
{
|
||||||
|
dataForm = ButtonForm.Duplicate();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dataForm = ButtonForm.FilterDuplicate(filter, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
int it = start + i;
|
||||||
|
|
||||||
|
if (it > dataForm.Rows - 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
bf.AddButtonRow(dataForm[it]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual ButtonForm PickAllItems(String filter = null)
|
||||||
|
{
|
||||||
|
if (filter == null)
|
||||||
|
return ButtonForm.Duplicate();
|
||||||
|
|
||||||
|
|
||||||
|
return ButtonForm.FilterDuplicate(filter, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual Tuple<ButtonRow, int> FindRow(String text, bool useText = true)
|
||||||
|
{
|
||||||
|
return ButtonForm.FindRow(text, useText);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the maximum items of this data source.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filter"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual int CalculateMax(String filter = null)
|
||||||
|
{
|
||||||
|
return PickAllItems(filter).Rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual ButtonRow Render(object data)
|
||||||
|
{
|
||||||
|
return data as ButtonRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static implicit operator ButtonFormDataSource(ButtonForm bf)
|
||||||
|
{
|
||||||
|
return new ButtonFormDataSource(bf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator ButtonForm(ButtonFormDataSource ds)
|
||||||
|
{
|
||||||
|
return ds.ButtonForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
46
TelegramBotBase/Datasources/StaticDataSource.cs
Normal file
46
TelegramBotBase/Datasources/StaticDataSource.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace TelegramBotBase.Datasources
|
||||||
|
{
|
||||||
|
public class StaticDataSource<T> : Interfaces.IDataSource<T>
|
||||||
|
{
|
||||||
|
List<T> Data { get; set; }
|
||||||
|
|
||||||
|
public StaticDataSource()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public StaticDataSource(List<T> data)
|
||||||
|
{
|
||||||
|
this.Data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Data.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public T ItemAt(int index)
|
||||||
|
{
|
||||||
|
return Data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> ItemRange(int start, int count)
|
||||||
|
{
|
||||||
|
return Data.Skip(start).Take(count).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> AllItems()
|
||||||
|
{
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,8 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Telegram.Bot.Exceptions;
|
||||||
using Telegram.Bot.Types;
|
using Telegram.Bot.Types;
|
||||||
using TelegramBotBase.Args;
|
using TelegramBotBase.Args;
|
||||||
using TelegramBotBase.Attributes;
|
using TelegramBotBase.Attributes;
|
||||||
@ -127,25 +129,79 @@ namespace TelegramBotBase.Form
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task MessageCleanup()
|
public async Task MessageCleanup()
|
||||||
{
|
{
|
||||||
while (this.OldMessages.Count > 0)
|
var oldMessages = OldMessages.AsEnumerable();
|
||||||
|
|
||||||
|
#if !NET472
|
||||||
|
while (oldMessages.Any())
|
||||||
{
|
{
|
||||||
var tasks = new List<Task>();
|
using var cts = new CancellationTokenSource();
|
||||||
var msgs = this.OldMessages.Take(Constants.Telegram.MessageDeletionsPerSecond);
|
var deletedMessages = new ConcurrentBag<int>();
|
||||||
|
var parallelQuery = OldMessages.AsParallel()
|
||||||
foreach (var msg in msgs)
|
.WithCancellation(cts.Token);
|
||||||
|
Task retryAfterTask = null;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
tasks.Add(this.Device.DeleteMessage(msg));
|
parallelQuery.ForAll(i =>
|
||||||
|
{
|
||||||
|
Device.DeleteMessage(i).GetAwaiter().GetResult();
|
||||||
|
deletedMessages.Add(i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (AggregateException ex)
|
||||||
|
{
|
||||||
|
cts.Cancel();
|
||||||
|
|
||||||
|
var retryAfterSeconds = ex.InnerExceptions
|
||||||
|
.Where(e => e is ApiRequestException apiEx && apiEx.ErrorCode == 429)
|
||||||
|
.Max(e =>(int?) ((ApiRequestException)e).Parameters.RetryAfter) ?? 0;
|
||||||
|
retryAfterTask = Task.Delay(retryAfterSeconds * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.WhenAll(tasks);
|
deletedMessages.AsParallel().ForAll(i => Device.OnMessageDeleted(new MessageDeletedEventArgs(i)));
|
||||||
|
|
||||||
foreach(var m in msgs)
|
oldMessages = oldMessages.Where(x => !deletedMessages.Contains(x));
|
||||||
{
|
if (retryAfterTask != null)
|
||||||
Device.OnMessageDeleted(new MessageDeletedEventArgs(m));
|
await retryAfterTask;
|
||||||
}
|
|
||||||
|
|
||||||
this.OldMessages.RemoveRange(0, msgs.Count());
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
while (oldMessages.Any())
|
||||||
|
{
|
||||||
|
using (var cts = new CancellationTokenSource())
|
||||||
|
{
|
||||||
|
var deletedMessages = new ConcurrentBag<int>();
|
||||||
|
var parallelQuery = OldMessages.AsParallel()
|
||||||
|
.WithCancellation(cts.Token);
|
||||||
|
Task retryAfterTask = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
parallelQuery.ForAll(i =>
|
||||||
|
{
|
||||||
|
Device.DeleteMessage(i).GetAwaiter().GetResult();
|
||||||
|
deletedMessages.Add(i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (AggregateException ex)
|
||||||
|
{
|
||||||
|
cts.Cancel();
|
||||||
|
|
||||||
|
var retryAfterSeconds = ex.InnerExceptions
|
||||||
|
.Where(e => e is ApiRequestException apiEx && apiEx.ErrorCode == 429)
|
||||||
|
.Max(e => (int?)((ApiRequestException)e).Parameters.RetryAfter) ?? 0;
|
||||||
|
retryAfterTask = Task.Delay(retryAfterSeconds * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
deletedMessages.AsParallel().ForAll(i => Device.OnMessageDeleted(new MessageDeletedEventArgs(i)));
|
||||||
|
|
||||||
|
oldMessages = oldMessages.Where(x => !deletedMessages.Contains(x));
|
||||||
|
if (retryAfterTask != null)
|
||||||
|
await retryAfterTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OldMessages.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Telegram.Bot.Types.ReplyMarkups;
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
using TelegramBotBase.Base;
|
using TelegramBotBase.Base;
|
||||||
|
using TelegramBotBase.Controls.Hybrid;
|
||||||
|
|
||||||
namespace TelegramBotBase.Form
|
namespace TelegramBotBase.Form
|
||||||
{
|
{
|
||||||
@ -13,7 +14,7 @@ namespace TelegramBotBase.Form
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ButtonForm
|
public class ButtonForm
|
||||||
{
|
{
|
||||||
List<List<ButtonBase>> Buttons = new List<List<ButtonBase>>();
|
List<ButtonRow> Buttons = new List<ButtonRow>();
|
||||||
|
|
||||||
|
|
||||||
public IReplyMarkup Markup { get; set; }
|
public IReplyMarkup Markup { get; set; }
|
||||||
@ -43,7 +44,7 @@ namespace TelegramBotBase.Form
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<ButtonBase> this[int row]
|
public ButtonRow this[int row]
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@ -66,9 +67,14 @@ namespace TelegramBotBase.Form
|
|||||||
Buttons.Add(new List<ButtonBase>() { new ButtonBase(Text, Value, Url) });
|
Buttons.Add(new List<ButtonBase>() { new ButtonBase(Text, Value, Url) });
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddButtonRow(IEnumerable<ButtonBase> row)
|
//public void AddButtonRow(ButtonRow row)
|
||||||
|
//{
|
||||||
|
// Buttons.Add(row.ToList());
|
||||||
|
//}
|
||||||
|
|
||||||
|
public void AddButtonRow(ButtonRow row)
|
||||||
{
|
{
|
||||||
Buttons.Add(row.ToList());
|
Buttons.Add(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddButtonRow(params ButtonBase[] row)
|
public void AddButtonRow(params ButtonBase[] row)
|
||||||
@ -76,16 +82,26 @@ namespace TelegramBotBase.Form
|
|||||||
AddButtonRow(row.ToList());
|
AddButtonRow(row.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddButtonRows(IEnumerable<ButtonRow> rows)
|
||||||
|
{
|
||||||
|
Buttons.AddRange(rows);
|
||||||
|
}
|
||||||
|
|
||||||
public void InsertButtonRow(int index, IEnumerable<ButtonBase> row)
|
public void InsertButtonRow(int index, IEnumerable<ButtonBase> row)
|
||||||
{
|
{
|
||||||
Buttons.Insert(index, row.ToList());
|
Buttons.Insert(index, row.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InsertButtonRow(int index, params ButtonBase[] row)
|
public void InsertButtonRow(int index, ButtonRow row)
|
||||||
{
|
{
|
||||||
InsertButtonRow(index, row.ToList());
|
Buttons.Insert(index, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//public void InsertButtonRow(int index, params ButtonBase[] row)
|
||||||
|
//{
|
||||||
|
// InsertButtonRow(index, row.ToList());
|
||||||
|
//}
|
||||||
|
|
||||||
public static T[][] SplitTo<T>(IEnumerable<T> items, int itemsPerRow = 2)
|
public static T[][] SplitTo<T>(IEnumerable<T> items, int itemsPerRow = 2)
|
||||||
{
|
{
|
||||||
T[][] splitted = default(T[][]);
|
T[][] splitted = default(T[][]);
|
||||||
@ -132,34 +148,62 @@ namespace TelegramBotBase.Form
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a range of rows from the buttons.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start"></param>
|
||||||
|
/// <param name="count"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public List<ButtonRow> GetRange(int start, int count)
|
||||||
|
{
|
||||||
|
return Buttons.Skip(start).Take(count).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<ButtonBase> ToList()
|
public List<ButtonBase> ToList()
|
||||||
{
|
{
|
||||||
return this.Buttons.DefaultIfEmpty(new List<ButtonBase>()).Aggregate((a, b) => a.Union(b).ToList());
|
return this.Buttons.DefaultIfEmpty(new List<ButtonBase>()).Select(a => a.ToList()).Aggregate((a, b) => a.Union(b).ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public InlineKeyboardButton[][] ToInlineButtonArray()
|
public InlineKeyboardButton[][] ToInlineButtonArray()
|
||||||
{
|
{
|
||||||
var ikb = this.Buttons.Select(a => a.Select(b => b.ToInlineButton(this)).ToArray()).ToArray();
|
var ikb = this.Buttons.Select(a => a.ToArray().Select(b => b.ToInlineButton(this)).ToArray()).ToArray();
|
||||||
|
|
||||||
return ikb;
|
return ikb;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyboardButton[][] ToReplyButtonArray()
|
public KeyboardButton[][] ToReplyButtonArray()
|
||||||
{
|
{
|
||||||
var ikb = this.Buttons.Select(a => a.Select(b => b.ToKeyboardButton(this)).ToArray()).ToArray();
|
var ikb = this.Buttons.Select(a => a.ToArray().Select(b => b.ToKeyboardButton(this)).ToArray()).ToArray();
|
||||||
|
|
||||||
return ikb;
|
return ikb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ButtonRow> ToArray()
|
||||||
|
{
|
||||||
|
return Buttons;
|
||||||
|
}
|
||||||
|
|
||||||
public int FindRowByButton(ButtonBase button)
|
public int FindRowByButton(ButtonBase button)
|
||||||
{
|
{
|
||||||
var row = this.Buttons.FirstOrDefault(a => a.Count(b => b == button) > 0);
|
var row = this.Buttons.FirstOrDefault(a => a.ToArray().Count(b => b == button) > 0);
|
||||||
if (row == null)
|
if (row == null)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return this.Buttons.IndexOf(row);
|
return this.Buttons.IndexOf(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Tuple<ButtonRow, int> FindRow(String text, bool useText = true)
|
||||||
|
{
|
||||||
|
var r = this.Buttons.FirstOrDefault(a => a.Matches(text, useText));
|
||||||
|
if (r == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var i = this.Buttons.IndexOf(r);
|
||||||
|
return new Tuple<ButtonRow, int>(r, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the first Button with the given value.
|
/// Returns the first Button with the given value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -204,7 +248,7 @@ namespace TelegramBotBase.Form
|
|||||||
|
|
||||||
foreach (var b in Buttons)
|
foreach (var b in Buttons)
|
||||||
{
|
{
|
||||||
var lst = new List<ButtonBase>();
|
var lst = new ButtonRow();
|
||||||
foreach (var b2 in b)
|
foreach (var b2 in b)
|
||||||
{
|
{
|
||||||
lst.Add(b2);
|
lst.Add(b2);
|
||||||
@ -229,7 +273,7 @@ namespace TelegramBotBase.Form
|
|||||||
|
|
||||||
foreach (var b in Buttons)
|
foreach (var b in Buttons)
|
||||||
{
|
{
|
||||||
var lst = new List<ButtonBase>();
|
var lst = new ButtonRow();
|
||||||
foreach (var b2 in b)
|
foreach (var b2 in b)
|
||||||
{
|
{
|
||||||
if (b2.Text.IndexOf(filter, StringComparison.InvariantCultureIgnoreCase) == -1)
|
if (b2.Text.IndexOf(filter, StringComparison.InvariantCultureIgnoreCase) == -1)
|
||||||
@ -238,7 +282,7 @@ namespace TelegramBotBase.Form
|
|||||||
//Copy full row, when at least one match has found.
|
//Copy full row, when at least one match has found.
|
||||||
if (ByRow)
|
if (ByRow)
|
||||||
{
|
{
|
||||||
lst.AddRange(b);
|
lst = b;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -268,7 +312,7 @@ namespace TelegramBotBase.Form
|
|||||||
|
|
||||||
foreach (var b in Buttons)
|
foreach (var b in Buttons)
|
||||||
{
|
{
|
||||||
var lst = new List<ButtonBase>();
|
var lst = new ButtonRow();
|
||||||
foreach (var b2 in b)
|
foreach (var b2 in b)
|
||||||
{
|
{
|
||||||
if (!(b2 is TagButtonBase tb))
|
if (!(b2 is TagButtonBase tb))
|
||||||
@ -280,7 +324,7 @@ namespace TelegramBotBase.Form
|
|||||||
//Copy full row, when at least one match has found.
|
//Copy full row, when at least one match has found.
|
||||||
if (ByRow)
|
if (ByRow)
|
||||||
{
|
{
|
||||||
lst.AddRange(b);
|
lst = b;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
358
TelegramBotBase/Form/Navigation/NavigationController.cs
Normal file
358
TelegramBotBase/Form/Navigation/NavigationController.cs
Normal file
@ -0,0 +1,358 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TelegramBotBase.Args;
|
||||||
|
using TelegramBotBase.Attributes;
|
||||||
|
using TelegramBotBase.Base;
|
||||||
|
using TelegramBotBase.Interfaces;
|
||||||
|
|
||||||
|
namespace TelegramBotBase.Form.Navigation
|
||||||
|
{
|
||||||
|
[DebuggerDisplay("{Index+1} Forms")]
|
||||||
|
public class NavigationController : FormBase, IStateForm
|
||||||
|
{
|
||||||
|
|
||||||
|
[SaveState]
|
||||||
|
private List<FormBase> History { get; set; }
|
||||||
|
|
||||||
|
[SaveState]
|
||||||
|
public int Index { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Will replace the controller when poping a form to the root form.
|
||||||
|
/// </summary>
|
||||||
|
[SaveState]
|
||||||
|
public bool ForceCleanupOnLastPop { get; set; }
|
||||||
|
|
||||||
|
public NavigationController()
|
||||||
|
{
|
||||||
|
History = new List<FormBase>();
|
||||||
|
Index = -1;
|
||||||
|
ForceCleanupOnLastPop = true;
|
||||||
|
|
||||||
|
this.Init += NavigationController_Init;
|
||||||
|
this.Opened += NavigationController_Opened;
|
||||||
|
this.Closed += NavigationController_Closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NavigationController(FormBase startForm, params FormBase[] forms) : this()
|
||||||
|
{
|
||||||
|
this.Client = startForm.Client;
|
||||||
|
this.Device = startForm.Device;
|
||||||
|
startForm.NavigationController = this;
|
||||||
|
|
||||||
|
History.Add(startForm);
|
||||||
|
Index = 0;
|
||||||
|
|
||||||
|
if (forms.Length > 0)
|
||||||
|
{
|
||||||
|
History.AddRange(forms);
|
||||||
|
Index = History.Count - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task NavigationController_Init(object sender, Args.InitEventArgs e)
|
||||||
|
{
|
||||||
|
if (CurrentForm == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await CurrentForm.OnInit(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task NavigationController_Opened(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (CurrentForm == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await CurrentForm.OnOpened(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task NavigationController_Closed(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (CurrentForm == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await CurrentForm.OnClosed(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove the current active form on the stack.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual async Task PopAsync()
|
||||||
|
{
|
||||||
|
if (History.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var form = History[Index];
|
||||||
|
|
||||||
|
form.NavigationController = null;
|
||||||
|
History.Remove(form);
|
||||||
|
Index--;
|
||||||
|
|
||||||
|
Device.FormSwitched = true;
|
||||||
|
|
||||||
|
await form.OnClosed(new EventArgs());
|
||||||
|
|
||||||
|
//Leave NavigationController and move to the last one
|
||||||
|
if (ForceCleanupOnLastPop && History.Count == 1)
|
||||||
|
{
|
||||||
|
var last_form = History[0];
|
||||||
|
last_form.NavigationController = null;
|
||||||
|
await this.NavigateTo(last_form);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (History.Count > 0)
|
||||||
|
{
|
||||||
|
form = History[Index];
|
||||||
|
await form.OnOpened(new EventArgs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pop's through all forms back to the root form.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual async Task PopToRootAsync()
|
||||||
|
{
|
||||||
|
while (Index > 0)
|
||||||
|
{
|
||||||
|
await PopAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pushing the given form to the stack and renders it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="form"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual async Task PushAsync(FormBase form, params object[] args)
|
||||||
|
{
|
||||||
|
form.Client = this.Client;
|
||||||
|
form.Device = this.Device;
|
||||||
|
form.NavigationController = this;
|
||||||
|
|
||||||
|
this.History.Add(form);
|
||||||
|
Index++;
|
||||||
|
|
||||||
|
Device.FormSwitched = true;
|
||||||
|
|
||||||
|
if (Index < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await form.OnInit(new InitEventArgs(args));
|
||||||
|
|
||||||
|
await form.OnOpened(new EventArgs());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pops the current form and pushes a new one.
|
||||||
|
/// Will help to remove forms so you can not navigate back to them.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="form"></param>
|
||||||
|
/// <param name="args"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual async Task PushAndReplaceAsync(FormBase form, params object[] args)
|
||||||
|
{
|
||||||
|
await PopAsync();
|
||||||
|
|
||||||
|
await PushAsync(form, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the current form from the stack.
|
||||||
|
/// </summary>
|
||||||
|
public FormBase CurrentForm
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (this.History.Count == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return this.History[Index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FormBase> GetAllForms()
|
||||||
|
{
|
||||||
|
return History.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void LoadState(LoadStateEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Get("$controller.history.count") == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
int historyCount = e.GetInt("$controller.history.count");
|
||||||
|
|
||||||
|
for (int i = 0; i < historyCount; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
var c = e.GetObject($"$controller.history[{i}]") as Dictionary<String, object>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var qname = e.Get($"$controller.history[{i}].type");
|
||||||
|
|
||||||
|
if (qname == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Type t = Type.GetType(qname.ToString());
|
||||||
|
if (t == null || !t.IsSubclassOf(typeof(FormBase)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var form = t.GetConstructor(new Type[] { })?.Invoke(new object[] { }) as FormBase;
|
||||||
|
|
||||||
|
//No default constructor, fallback
|
||||||
|
if (form == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var properties = c.Where(a => a.Key.StartsWith("$"));
|
||||||
|
|
||||||
|
var fields = form.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).Where(a => a.GetCustomAttributes(typeof(SaveState), true).Length != 0).ToList();
|
||||||
|
|
||||||
|
foreach (var p in properties)
|
||||||
|
{
|
||||||
|
var f = fields.FirstOrDefault(a => a.Name == p.Key.Substring(1));
|
||||||
|
if (f == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (f.PropertyType.IsEnum)
|
||||||
|
{
|
||||||
|
var ent = Enum.Parse(f.PropertyType, p.Value.ToString());
|
||||||
|
|
||||||
|
f.SetValue(form, ent);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
f.SetValue(form, p.Value);
|
||||||
|
}
|
||||||
|
catch (ArgumentException ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
Tools.Conversion.CustomConversionChecks(form, p, f);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
form.Device = this.Device;
|
||||||
|
form.Client = this.Client;
|
||||||
|
form.NavigationController = this;
|
||||||
|
|
||||||
|
form.OnInit(new InitEventArgs());
|
||||||
|
|
||||||
|
this.History.Add(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveState(SaveStateEventArgs e)
|
||||||
|
{
|
||||||
|
e.Set("$controller.history.count", History.Count.ToString());
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
foreach (var form in History)
|
||||||
|
{
|
||||||
|
var fields = form.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).Where(a => a.GetCustomAttributes(typeof(SaveState), true).Length != 0).ToList();
|
||||||
|
|
||||||
|
var dt = new Dictionary<String, object>();
|
||||||
|
foreach (var f in fields)
|
||||||
|
{
|
||||||
|
var val = f.GetValue(form);
|
||||||
|
|
||||||
|
dt.Add("$" + f.Name, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Set($"$controller.history[{i}].type", form.GetType().AssemblyQualifiedName);
|
||||||
|
|
||||||
|
e.SetObject($"$controller.history[{i}]", dt);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#region "Methods passthrough"
|
||||||
|
|
||||||
|
public override async Task NavigateTo(FormBase newForm, params object[] args)
|
||||||
|
{
|
||||||
|
await CurrentForm.NavigateTo(newForm, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task LoadControls(MessageResult message)
|
||||||
|
{
|
||||||
|
await CurrentForm.LoadControls(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Load(MessageResult message)
|
||||||
|
{
|
||||||
|
await CurrentForm.Load(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task ActionControls(MessageResult message)
|
||||||
|
{
|
||||||
|
await CurrentForm.ActionControls(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Action(MessageResult message)
|
||||||
|
{
|
||||||
|
await CurrentForm.Action(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public override async Task Edited(MessageResult message)
|
||||||
|
{
|
||||||
|
await CurrentForm.Edited(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Render(MessageResult message)
|
||||||
|
{
|
||||||
|
await CurrentForm.Render(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task RenderControls(MessageResult message)
|
||||||
|
{
|
||||||
|
await CurrentForm.RenderControls(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task PreLoad(MessageResult message)
|
||||||
|
{
|
||||||
|
await CurrentForm.PreLoad(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task ReturnFromModal(ModalDialog modal)
|
||||||
|
{
|
||||||
|
await CurrentForm.ReturnFromModal(modal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task SentData(DataResult message)
|
||||||
|
{
|
||||||
|
await CurrentForm.SentData(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
43
TelegramBotBase/Interfaces/IDataSource.cs
Normal file
43
TelegramBotBase/Interfaces/IDataSource.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using TelegramBotBase.Controls.Hybrid;
|
||||||
|
|
||||||
|
namespace TelegramBotBase.Interfaces
|
||||||
|
{
|
||||||
|
public interface IDataSource<T>
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the amount of items within this source.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
int Count { get; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the item at the specific index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="index"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
T ItemAt(int index);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all items from this source within this range.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start"></param>
|
||||||
|
/// <param name="count"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<T> ItemRange(int start, int count);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list of all items of this datasource.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<T> AllItems();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -16,6 +16,8 @@ namespace TelegramBotBase.Localizations
|
|||||||
Values["ButtonGrid_CurrentPage"] = "Page {0} of {1}";
|
Values["ButtonGrid_CurrentPage"] = "Page {0} of {1}";
|
||||||
Values["ButtonGrid_SearchFeature"] = "💡 Send a message to filter the list. Click the 🔍 to reset the filter.";
|
Values["ButtonGrid_SearchFeature"] = "💡 Send a message to filter the list. Click the 🔍 to reset the filter.";
|
||||||
Values["ButtonGrid_Back"] = "Back";
|
Values["ButtonGrid_Back"] = "Back";
|
||||||
|
Values["ButtonGrid_CheckAll"] = "Check all";
|
||||||
|
Values["ButtonGrid_UncheckAll"] = "Uncheck all";
|
||||||
Values["CalendarPicker_Title"] = "Pick date";
|
Values["CalendarPicker_Title"] = "Pick date";
|
||||||
Values["CalendarPicker_PreviousPage"] = "◀️";
|
Values["CalendarPicker_PreviousPage"] = "◀️";
|
||||||
Values["CalendarPicker_NextPage"] = "▶️";
|
Values["CalendarPicker_NextPage"] = "▶️";
|
||||||
|
|||||||
@ -8,7 +8,32 @@ namespace TelegramBotBase.Localizations
|
|||||||
{
|
{
|
||||||
public German() : base()
|
public German() : base()
|
||||||
{
|
{
|
||||||
|
Values["Language"] = "Deutsch (German)";
|
||||||
|
Values["ButtonGrid_Title"] = "Menü";
|
||||||
|
Values["ButtonGrid_NoItems"] = "Es sind keine Einträge vorhanden.";
|
||||||
|
Values["ButtonGrid_PreviousPage"] = "◀️";
|
||||||
|
Values["ButtonGrid_NextPage"] = "▶️";
|
||||||
|
Values["ButtonGrid_CurrentPage"] = "Seite {0} von {1}";
|
||||||
|
Values["ButtonGrid_SearchFeature"] = "💡 Sende eine Nachricht um die Liste zu filtern. Klicke die 🔍 um den Filter zurückzusetzen.";
|
||||||
|
Values["ButtonGrid_Back"] = "Zurück";
|
||||||
|
Values["ButtonGrid_CheckAll"] = "Alle auswählen";
|
||||||
|
Values["ButtonGrid_UncheckAll"] = "Keine auswählen";
|
||||||
|
Values["CalendarPicker_Title"] = "Datum auswählen";
|
||||||
|
Values["CalendarPicker_PreviousPage"] = "◀️";
|
||||||
|
Values["CalendarPicker_NextPage"] = "▶️";
|
||||||
|
Values["TreeView_Title"] = "Knoten auswählen";
|
||||||
|
Values["TreeView_LevelUp"] = "🔼 Stufe hoch";
|
||||||
|
Values["ToggleButton_On"] = "An";
|
||||||
|
Values["ToggleButton_Off"] = "Aus";
|
||||||
|
Values["ToggleButton_OnIcon"] = "⚫";
|
||||||
|
Values["ToggleButton_OffIcon"] = "⚪";
|
||||||
|
Values["ToggleButton_Title"] = "Schalter";
|
||||||
|
Values["ToggleButton_Changed"] = "Ausgewählt";
|
||||||
|
Values["MultiToggleButton_SelectedIcon"] = "✅";
|
||||||
|
Values["MultiToggleButton_Title"] = "Mehrfach-Schalter";
|
||||||
|
Values["MultiToggleButton_Changed"] = "Ausgewählt";
|
||||||
|
Values["PromptDialog_Back"] = "Zurück";
|
||||||
|
Values["ToggleButton_Changed"] = "Einstellung geändert";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ using System.Text;
|
|||||||
|
|
||||||
namespace TelegramBotBase.Localizations
|
namespace TelegramBotBase.Localizations
|
||||||
{
|
{
|
||||||
public class Localization
|
public abstract class Localization
|
||||||
{
|
{
|
||||||
public Dictionary<String, String> Values = new Dictionary<string, string>();
|
public Dictionary<String, String> Values = new Dictionary<string, string>();
|
||||||
|
|
||||||
@ -18,30 +18,7 @@ namespace TelegramBotBase.Localizations
|
|||||||
|
|
||||||
public Localization()
|
public Localization()
|
||||||
{
|
{
|
||||||
Values["Language"] = "Deutsch (German)";
|
|
||||||
Values["ButtonGrid_Title"] = "Menü";
|
|
||||||
Values["ButtonGrid_NoItems"] = "Es sind keine Einträge vorhanden.";
|
|
||||||
Values["ButtonGrid_PreviousPage"] = "◀️";
|
|
||||||
Values["ButtonGrid_NextPage"] = "▶️";
|
|
||||||
Values["ButtonGrid_CurrentPage"] = "Seite {0} von {1}";
|
|
||||||
Values["ButtonGrid_SearchFeature"] = "💡 Sende eine Nachricht um die Liste zu filtern. Klicke die 🔍 um den Filter zurückzusetzen.";
|
|
||||||
Values["ButtonGrid_Back"] = "Zurück";
|
|
||||||
Values["CalendarPicker_Title"] = "Datum auswählen";
|
|
||||||
Values["CalendarPicker_PreviousPage"] = "◀️";
|
|
||||||
Values["CalendarPicker_NextPage"] = "▶️";
|
|
||||||
Values["TreeView_Title"] = "Knoten auswählen";
|
|
||||||
Values["TreeView_LevelUp"] = "🔼 Stufe hoch";
|
|
||||||
Values["ToggleButton_On"] = "An";
|
|
||||||
Values["ToggleButton_Off"] = "Aus";
|
|
||||||
Values["ToggleButton_OnIcon"] = "⚫";
|
|
||||||
Values["ToggleButton_OffIcon"] = "⚪";
|
|
||||||
Values["ToggleButton_Title"] = "Schalter";
|
|
||||||
Values["ToggleButton_Changed"] = "Ausgewählt";
|
|
||||||
Values["MultiToggleButton_SelectedIcon"] = "✅";
|
|
||||||
Values["MultiToggleButton_Title"] = "Mehrfach-Schalter";
|
|
||||||
Values["MultiToggleButton_Changed"] = "Ausgewählt";
|
|
||||||
Values["PromptDialog_Back"] = "Zurück";
|
|
||||||
Values["ToggleButton_Changed"] = "Einstellung geändert";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -208,6 +208,13 @@ namespace TelegramBotBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form.Client = Client;
|
||||||
|
var device = new DeviceSession(s.DeviceId, form);
|
||||||
|
|
||||||
|
device.ChatTitle = s.ChatTitle;
|
||||||
|
|
||||||
|
this.SessionList.Add(s.DeviceId, device);
|
||||||
|
|
||||||
//Is Subclass of IStateForm
|
//Is Subclass of IStateForm
|
||||||
var iform = form as IStateForm;
|
var iform = form as IStateForm;
|
||||||
if (iform != null)
|
if (iform != null)
|
||||||
@ -217,14 +224,6 @@ namespace TelegramBotBase
|
|||||||
iform.LoadState(ls);
|
iform.LoadState(ls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
form.Client = Client;
|
|
||||||
var device = new DeviceSession(s.DeviceId, form);
|
|
||||||
|
|
||||||
device.ChatTitle = s.ChatTitle;
|
|
||||||
|
|
||||||
this.SessionList.Add(s.DeviceId, device);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await form.OnInit(new InitEventArgs());
|
await form.OnInit(new InitEventArgs());
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||||
<PackageProjectUrl>https://github.com/MajMcCloud/TelegramBotFramework</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/MajMcCloud/TelegramBotFramework</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/MajMcCloud/TelegramBotFramework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/MajMcCloud/TelegramBotFramework</RepositoryUrl>
|
||||||
<PackageReleaseNotes>- moving from .Net Framework 4.7.2 to .Net Standard 2.1 for the Library and .Net Core 3.1 for the test project!</PackageReleaseNotes>
|
<PackageReleaseNotes>- moving from .Net Framework 4.7.2 to .Net Standard 2.1 for the Library and .Net Core 3.1 for the test project!</PackageReleaseNotes>
|
||||||
<Configurations>Debug;Release;</Configurations>
|
<Configurations>Debug;Release;</Configurations>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
|
<RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
|
||||||
@ -62,27 +62,9 @@
|
|||||||
<None Remove="Archive\**" />
|
<None Remove="Archive\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Remove="cpack.ps1" />
|
|
||||||
<None Remove="cpack_bak.ps1" />
|
|
||||||
<None Remove="cpush.ps1" />
|
|
||||||
<None Remove="nuget.exe" />
|
|
||||||
<None Remove="TelegramBotBase.1.5.0.nupkg" />
|
|
||||||
<None Remove="TelegramBotBase.1.5.0.zip" />
|
|
||||||
<None Remove="TelegramBotBase.1.5.1.nupkg" />
|
|
||||||
<None Remove="TelegramBotBase.1.5.1.zip" />
|
|
||||||
<None Remove="TelegramBotBase.1.5.2.nupkg" />
|
|
||||||
<None Remove="TelegramBotBase.1.5.2.zip" />
|
|
||||||
<None Remove="TelegramBotBase.2.0.0.nupkg" />
|
|
||||||
<None Remove="TelegramBotBase.2.1.0.nupkg" />
|
|
||||||
<None Remove="TelegramBotBase.2.1.0.zip" />
|
|
||||||
<None Remove="TelegramBotBase.3.0.0.nupkg" />
|
|
||||||
<None Remove="TelegramBotBase.3.0.0.zip" />
|
|
||||||
<None Remove="TelegramBotBase.nuspec" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="System.ComponentModel" Version="4.3.0" />
|
<PackageReference Include="System.ComponentModel" Version="4.3.0" />
|
||||||
<PackageReference Include="System.Drawing.Common" Version="5.0.2" />
|
<PackageReference Include="System.Drawing.Common" Version="5.0.2" />
|
||||||
<PackageReference Include="Telegram.Bot" Version="16.0.2" />
|
<PackageReference Include="Telegram.Bot" Version="16.0.2" />
|
||||||
|
|||||||
@ -7,7 +7,7 @@ using Telegram.Bot.Types;
|
|||||||
using TelegramBotBase;
|
using TelegramBotBase;
|
||||||
using TelegramBotBase.Form;
|
using TelegramBotBase.Form;
|
||||||
using TelegramBotBaseTest.Tests;
|
using TelegramBotBaseTest.Tests;
|
||||||
|
using TelegramBotBase.Commands;
|
||||||
namespace TelegramBotBaseTest
|
namespace TelegramBotBaseTest
|
||||||
{
|
{
|
||||||
class Program
|
class Program
|
||||||
@ -17,7 +17,9 @@ namespace TelegramBotBaseTest
|
|||||||
|
|
||||||
BotBase<Start> bb = new BotBase<Start>(APIKey);
|
BotBase<Start> bb = new BotBase<Start>(APIKey);
|
||||||
|
|
||||||
bb.BotCommands.Add(new BotCommand() { Command = "start", Description = "Starts the bot" });
|
bb.BotCommands.AddStartCommand("Starts the bot");
|
||||||
|
bb.BotCommands.AddHelpCommand("Should show you some help");
|
||||||
|
bb.BotCommands.AddSettingsCommand("Should show you some settings");
|
||||||
bb.BotCommands.Add(new BotCommand() { Command = "form1", Description = "Opens test form 1" });
|
bb.BotCommands.Add(new BotCommand() { Command = "form1", Description = "Opens test form 1" });
|
||||||
bb.BotCommands.Add(new BotCommand() { Command = "form2", Description = "Opens test form 2" });
|
bb.BotCommands.Add(new BotCommand() { Command = "form2", Description = "Opens test form 2" });
|
||||||
bb.BotCommands.Add(new BotCommand() { Command = "params", Description = "Returns all send parameters as a message." });
|
bb.BotCommands.Add(new BotCommand() { Command = "params", Description = "Returns all send parameters as a message." });
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFrameworks>netcoreapp3.0;net472</TargetFrameworks>
|
<TargetFrameworks>netcoreapp3.1;net5</TargetFrameworks>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@ -33,6 +33,7 @@ namespace TelegramBotBaseTest.Tests.Controls
|
|||||||
|
|
||||||
m_Buttons.HeadLayoutButtonRow = new List<ButtonBase>() { new ButtonBase("Back", "back") };
|
m_Buttons.HeadLayoutButtonRow = new List<ButtonBase>() { new ButtonBase("Back", "back") };
|
||||||
|
|
||||||
|
|
||||||
var countries = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
|
var countries = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
|
||||||
|
|
||||||
ButtonForm bf = new ButtonForm();
|
ButtonForm bf = new ButtonForm();
|
||||||
@ -45,7 +46,9 @@ namespace TelegramBotBaseTest.Tests.Controls
|
|||||||
m_Buttons.Tags = countries.Select(a => a.Parent.EnglishName).Distinct().OrderBy(a => a).ToList();
|
m_Buttons.Tags = countries.Select(a => a.Parent.EnglishName).Distinct().OrderBy(a => a).ToList();
|
||||||
m_Buttons.SelectedTags = countries.Select(a => a.Parent.EnglishName).Distinct().OrderBy(a => a).ToList();
|
m_Buttons.SelectedTags = countries.Select(a => a.Parent.EnglishName).Distinct().OrderBy(a => a).ToList();
|
||||||
|
|
||||||
m_Buttons.ButtonsForm = bf;
|
m_Buttons.EnableCheckAllTools = true;
|
||||||
|
|
||||||
|
m_Buttons.DataSource = new TelegramBotBase.Datasources.ButtonFormDataSource(bf);
|
||||||
|
|
||||||
m_Buttons.ButtonClicked += Bg_ButtonClicked;
|
m_Buttons.ButtonClicked += Bg_ButtonClicked;
|
||||||
|
|
||||||
@ -57,11 +60,13 @@ namespace TelegramBotBaseTest.Tests.Controls
|
|||||||
if (e.Button == null)
|
if (e.Button == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (e.Button.Value == "back")
|
switch (e.Button.Value)
|
||||||
{
|
{
|
||||||
var start = new Menu();
|
|
||||||
await this.NavigateTo(start);
|
case "back":
|
||||||
return;
|
var start = new Menu();
|
||||||
|
await this.NavigateTo(start);
|
||||||
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,12 +35,12 @@ namespace TelegramBotBaseTest.Tests.Controls
|
|||||||
|
|
||||||
ButtonForm bf = new ButtonForm();
|
ButtonForm bf = new ButtonForm();
|
||||||
|
|
||||||
for(int i = 0;i < 30;i++)
|
for (int i = 0; i < 30; i++)
|
||||||
{
|
{
|
||||||
bf.AddButtonRow($"{i}. Item", i.ToString());
|
bf.AddButtonRow($"{i + 1}. Item", i.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Buttons.ButtonsForm = bf;
|
m_Buttons.DataSource = new TelegramBotBase.Datasources.ButtonFormDataSource(bf);
|
||||||
|
|
||||||
m_Buttons.ButtonClicked += Bg_ButtonClicked;
|
m_Buttons.ButtonClicked += Bg_ButtonClicked;
|
||||||
m_Buttons.CheckedChanged += M_Buttons_CheckedChanged;
|
m_Buttons.CheckedChanged += M_Buttons_CheckedChanged;
|
||||||
@ -58,29 +58,32 @@ namespace TelegramBotBaseTest.Tests.Controls
|
|||||||
if (e.Button == null)
|
if (e.Button == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (e.Button.Value == "back")
|
switch (e.Button.Value)
|
||||||
{
|
{
|
||||||
var start = new Menu();
|
case "back":
|
||||||
await this.NavigateTo(start);
|
|
||||||
}
|
var start = new Menu();
|
||||||
else if (e.Button.Value == "switch")
|
await NavigateTo(start);
|
||||||
{
|
break;
|
||||||
switch (m_Buttons.KeyboardType)
|
|
||||||
{
|
|
||||||
case TelegramBotBase.Enums.eKeyboardType.ReplyKeyboard:
|
|
||||||
m_Buttons.KeyboardType = TelegramBotBase.Enums.eKeyboardType.InlineKeyBoard;
|
|
||||||
break;
|
|
||||||
case TelegramBotBase.Enums.eKeyboardType.InlineKeyBoard:
|
|
||||||
m_Buttons.KeyboardType = TelegramBotBase.Enums.eKeyboardType.ReplyKeyboard;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
case "switch":
|
||||||
else
|
switch (m_Buttons.KeyboardType)
|
||||||
{
|
{
|
||||||
|
case TelegramBotBase.Enums.eKeyboardType.ReplyKeyboard:
|
||||||
|
m_Buttons.KeyboardType = TelegramBotBase.Enums.eKeyboardType.InlineKeyBoard;
|
||||||
|
break;
|
||||||
|
case TelegramBotBase.Enums.eKeyboardType.InlineKeyBoard:
|
||||||
|
m_Buttons.KeyboardType = TelegramBotBase.Enums.eKeyboardType.ReplyKeyboard;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
await this.Device.Send($"Button clicked with Text: {e.Button.Text} and Value {e.Button.Value}");
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
await Device.Send($"Button clicked with Text: {e.Button.Text} and Value {e.Button.Value}");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
163
TelegramBotBaseTest/Tests/Datasources/CustomDataSource.cs
Normal file
163
TelegramBotBaseTest/Tests/Datasources/CustomDataSource.cs
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using TelegramBotBase.Controls.Hybrid;
|
||||||
|
using TelegramBotBase.Datasources;
|
||||||
|
using TelegramBotBase.Form;
|
||||||
|
|
||||||
|
namespace TelegramBotBaseTest.Tests.Datasources
|
||||||
|
{
|
||||||
|
public class CustomDataSource : ButtonFormDataSource
|
||||||
|
{
|
||||||
|
|
||||||
|
public List<String> Countries = new List<string>() { "Country 1", "Country 2", "Country 3" };
|
||||||
|
|
||||||
|
public CustomDataSource()
|
||||||
|
{
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method has the example purpose of creating and loading some example data.
|
||||||
|
/// When using a database you do not need this kind of method.
|
||||||
|
/// </summary>
|
||||||
|
private void loadData()
|
||||||
|
{
|
||||||
|
//Exists data source? Read it
|
||||||
|
if (File.Exists(AppContext.BaseDirectory + "countries.json"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var List = Newtonsoft.Json.JsonConvert.DeserializeObject<List<String>>(File.ReadAllText("countries.json"));
|
||||||
|
|
||||||
|
|
||||||
|
Countries = List;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If not, create it
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var countries = CultureInfo.GetCultures(CultureTypes.SpecificCultures).Select(a => a.DisplayName).ToList();
|
||||||
|
|
||||||
|
Countries = countries;
|
||||||
|
|
||||||
|
var tmp = Newtonsoft.Json.JsonConvert.SerializeObject(countries);
|
||||||
|
|
||||||
|
File.WriteAllText( AppContext.BaseDirectory + "countries.json", tmp);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ButtonRow ItemAt(int index)
|
||||||
|
{
|
||||||
|
var item = Countries.ElementAt(index);
|
||||||
|
if (item == null)
|
||||||
|
return new ButtonRow();
|
||||||
|
|
||||||
|
return Render(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<ButtonRow> ItemRange(int start, int count)
|
||||||
|
{
|
||||||
|
var items = Countries.Skip(start).Take(count);
|
||||||
|
|
||||||
|
List<ButtonRow> lst = new List<ButtonRow>();
|
||||||
|
foreach (var c in items)
|
||||||
|
{
|
||||||
|
lst.Add(Render(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
return lst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<ButtonRow> AllItems()
|
||||||
|
{
|
||||||
|
List<ButtonRow> lst = new List<ButtonRow>();
|
||||||
|
foreach (var c in Countries)
|
||||||
|
{
|
||||||
|
lst.Add(Render(c));
|
||||||
|
}
|
||||||
|
return lst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ButtonForm PickItems(int start, int count, string filter = null)
|
||||||
|
{
|
||||||
|
List<ButtonRow> rows = ItemRange(start, count);
|
||||||
|
|
||||||
|
ButtonForm lst = new ButtonForm();
|
||||||
|
foreach (var c in rows)
|
||||||
|
{
|
||||||
|
lst.AddButtonRow(c);
|
||||||
|
}
|
||||||
|
return lst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ButtonForm PickAllItems(string filter = null)
|
||||||
|
{
|
||||||
|
List<ButtonRow> rows = AllItems();
|
||||||
|
|
||||||
|
ButtonForm bf = new ButtonForm();
|
||||||
|
|
||||||
|
bf.AddButtonRows(rows);
|
||||||
|
|
||||||
|
return bf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int CalculateMax(string filter = null)
|
||||||
|
{
|
||||||
|
if (filter == null)
|
||||||
|
return Countries.Count;
|
||||||
|
|
||||||
|
return Countries.Where(a => a.IndexOf(filter, StringComparison.InvariantCultureIgnoreCase) != -1).Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ButtonRow Render(object data)
|
||||||
|
{
|
||||||
|
var s = data as String;
|
||||||
|
if (s == null)
|
||||||
|
return new ButtonRow(new ButtonBase("Empty", "zero"));
|
||||||
|
|
||||||
|
return new ButtonRow(new ButtonBase(s, s));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Count
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Countries.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int ColumnCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int RowCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
65
TelegramBotBaseTest/Tests/Datasources/List.cs
Normal file
65
TelegramBotBaseTest/Tests/Datasources/List.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TelegramBotBase.Base;
|
||||||
|
using TelegramBotBase.Controls.Hybrid;
|
||||||
|
using TelegramBotBase.Form;
|
||||||
|
|
||||||
|
namespace TelegramBotBaseTest.Tests.Datasources
|
||||||
|
{
|
||||||
|
public class List : FormBase
|
||||||
|
{
|
||||||
|
ButtonGrid __buttons = null;
|
||||||
|
|
||||||
|
public List()
|
||||||
|
{
|
||||||
|
this.Init += List_Init;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task List_Init(object sender, TelegramBotBase.Args.InitEventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
__buttons = new ButtonGrid();
|
||||||
|
|
||||||
|
__buttons.EnablePaging = true;
|
||||||
|
__buttons.EnableSearch = false;
|
||||||
|
__buttons.ButtonClicked += __buttons_ButtonClicked;
|
||||||
|
__buttons.KeyboardType = TelegramBotBase.Enums.eKeyboardType.ReplyKeyboard;
|
||||||
|
__buttons.DeleteReplyMessage = true;
|
||||||
|
|
||||||
|
__buttons.HeadLayoutButtonRow = new ButtonRow(new ButtonBase("Back", "back"));
|
||||||
|
|
||||||
|
var cds = new CustomDataSource();
|
||||||
|
__buttons.DataSource = cds;
|
||||||
|
|
||||||
|
AddControl(__buttons);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task __buttons_ButtonClicked(object sender, TelegramBotBase.Args.ButtonClickedEventArgs e)
|
||||||
|
{
|
||||||
|
switch(e.Button.Value)
|
||||||
|
{
|
||||||
|
case "back":
|
||||||
|
|
||||||
|
var mn = new Menu();
|
||||||
|
await NavigateTo(mn);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Load(MessageResult message)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override async Task Render(MessageResult message)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -41,7 +41,9 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
if (call == null)
|
if (call == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch(call.Value)
|
message.Handled = true;
|
||||||
|
|
||||||
|
switch (call.Value)
|
||||||
{
|
{
|
||||||
case "text":
|
case "text":
|
||||||
|
|
||||||
@ -93,8 +95,6 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
|
|
||||||
case "data":
|
case "data":
|
||||||
|
|
||||||
message.Handled = true;
|
|
||||||
|
|
||||||
var data = new DataForm();
|
var data = new DataForm();
|
||||||
|
|
||||||
await this.NavigateTo(data);
|
await this.NavigateTo(data);
|
||||||
@ -103,8 +103,6 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
|
|
||||||
case "calendar":
|
case "calendar":
|
||||||
|
|
||||||
message.Handled = true;
|
|
||||||
|
|
||||||
var calendar = new Controls.CalendarPickerForm();
|
var calendar = new Controls.CalendarPickerForm();
|
||||||
|
|
||||||
await this.NavigateTo(calendar);
|
await this.NavigateTo(calendar);
|
||||||
@ -113,8 +111,6 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
|
|
||||||
case "month":
|
case "month":
|
||||||
|
|
||||||
message.Handled = true;
|
|
||||||
|
|
||||||
var month = new Controls.MonthPickerForm();
|
var month = new Controls.MonthPickerForm();
|
||||||
|
|
||||||
await this.NavigateTo(month);
|
await this.NavigateTo(month);
|
||||||
@ -123,8 +119,6 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
|
|
||||||
case "treeview":
|
case "treeview":
|
||||||
|
|
||||||
message.Handled = true;
|
|
||||||
|
|
||||||
var tree = new Controls.TreeViewForms();
|
var tree = new Controls.TreeViewForms();
|
||||||
|
|
||||||
await this.NavigateTo(tree);
|
await this.NavigateTo(tree);
|
||||||
@ -133,8 +127,6 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
|
|
||||||
case "togglebuttons":
|
case "togglebuttons":
|
||||||
|
|
||||||
message.Handled = true;
|
|
||||||
|
|
||||||
var tb = new Controls.ToggleButtons();
|
var tb = new Controls.ToggleButtons();
|
||||||
|
|
||||||
await this.NavigateTo(tb);
|
await this.NavigateTo(tb);
|
||||||
@ -143,8 +135,6 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
|
|
||||||
case "multitogglebuttons":
|
case "multitogglebuttons":
|
||||||
|
|
||||||
message.Handled = true;
|
|
||||||
|
|
||||||
var mtb = new Controls.MultiToggleButtons();
|
var mtb = new Controls.MultiToggleButtons();
|
||||||
|
|
||||||
await this.NavigateTo(mtb);
|
await this.NavigateTo(mtb);
|
||||||
@ -153,8 +143,6 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
|
|
||||||
case "buttongrid":
|
case "buttongrid":
|
||||||
|
|
||||||
message.Handled = true;
|
|
||||||
|
|
||||||
var bg = new Controls.ButtonGridForm();
|
var bg = new Controls.ButtonGridForm();
|
||||||
|
|
||||||
await this.NavigateTo(bg);
|
await this.NavigateTo(bg);
|
||||||
@ -163,8 +151,6 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
|
|
||||||
case "buttongridfilter":
|
case "buttongridfilter":
|
||||||
|
|
||||||
message.Handled = true;
|
|
||||||
|
|
||||||
var bg2 = new Controls.ButtonGridPagingForm();
|
var bg2 = new Controls.ButtonGridPagingForm();
|
||||||
|
|
||||||
await this.NavigateTo(bg2);
|
await this.NavigateTo(bg2);
|
||||||
@ -173,8 +159,6 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
|
|
||||||
case "buttongridtags":
|
case "buttongridtags":
|
||||||
|
|
||||||
message.Handled = true;
|
|
||||||
|
|
||||||
var bg3 = new Controls.ButtonGridTagForm();
|
var bg3 = new Controls.ButtonGridTagForm();
|
||||||
|
|
||||||
await this.NavigateTo(bg3);
|
await this.NavigateTo(bg3);
|
||||||
@ -183,8 +167,6 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
|
|
||||||
case "multiview":
|
case "multiview":
|
||||||
|
|
||||||
message.Handled = true;
|
|
||||||
|
|
||||||
var mvf = new MultiViewForm();
|
var mvf = new MultiViewForm();
|
||||||
|
|
||||||
await NavigateTo(mvf);
|
await NavigateTo(mvf);
|
||||||
@ -194,13 +176,41 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
|
|
||||||
case "checkedbuttonlist":
|
case "checkedbuttonlist":
|
||||||
|
|
||||||
message.Handled = true;
|
|
||||||
|
|
||||||
var cbl = new CheckedButtonListForm();
|
var cbl = new CheckedButtonListForm();
|
||||||
|
|
||||||
await NavigateTo(cbl);
|
await NavigateTo(cbl);
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "navigationcontroller":
|
||||||
|
|
||||||
|
var nc = new Navigation.Start();
|
||||||
|
|
||||||
|
await NavigateTo(nc);
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "dynamicbuttongrid":
|
||||||
|
|
||||||
|
var dg = new Datasources.List();
|
||||||
|
|
||||||
|
await NavigateTo(dg);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "notifications":
|
||||||
|
|
||||||
|
var not = new Notifications.Start();
|
||||||
|
await NavigateTo(not);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
message.Handled = false;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,6 +250,12 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
|
|
||||||
btn.AddButtonRow(new ButtonBase("#16 CheckedButtonList", new CallbackData("a", "checkedbuttonlist").Serialize()));
|
btn.AddButtonRow(new ButtonBase("#16 CheckedButtonList", new CallbackData("a", "checkedbuttonlist").Serialize()));
|
||||||
|
|
||||||
|
btn.AddButtonRow(new ButtonBase("#17 NavigationController (Push/Pop)", new CallbackData("a", "navigationcontroller").Serialize()));
|
||||||
|
|
||||||
|
btn.AddButtonRow(new ButtonBase("#18 Dynamic ButtonGrid (DataSources)", new CallbackData("a", "dynamicbuttongrid").Serialize()));
|
||||||
|
|
||||||
|
btn.AddButtonRow(new ButtonBase("#19 Notifications", new CallbackData("a", "notifications").Serialize()));
|
||||||
|
|
||||||
await this.Device.Send("Choose your test:", btn);
|
await this.Device.Send("Choose your test:", btn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
44
TelegramBotBaseTest/Tests/Navigation/CustomController.cs
Normal file
44
TelegramBotBaseTest/Tests/Navigation/CustomController.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TelegramBotBase.Form;
|
||||||
|
using TelegramBotBase.Form.Navigation;
|
||||||
|
|
||||||
|
namespace TelegramBotBaseTest.Tests.Navigation
|
||||||
|
{
|
||||||
|
class CustomController : NavigationController
|
||||||
|
{
|
||||||
|
public CustomController(FormBase form) : base(form)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override Task PushAsync(FormBase form, params object[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Pushes form (Count on stack {this.Index + 1})");
|
||||||
|
//Device.Send($"Pushes form (Count on stack {this.Index + 1})");
|
||||||
|
|
||||||
|
return base.PushAsync(form, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override Task PopAsync()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Pops one form (Count on stack {this.Index + 1})");
|
||||||
|
//Device.Send($"Pops one form (Count on stack {this.Index + 1})");
|
||||||
|
|
||||||
|
return base.PopAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task PopToRootAsync()
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Moved back to root (Count on stack {this.Index + 1})");
|
||||||
|
//Device.Send($"Moved back to root (Count on stack {this.Index + 1})");
|
||||||
|
|
||||||
|
return base.PopToRootAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
88
TelegramBotBaseTest/Tests/Navigation/Form1.cs
Normal file
88
TelegramBotBaseTest/Tests/Navigation/Form1.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using TelegramBotBase.Base;
|
||||||
|
using TelegramBotBase.Form;
|
||||||
|
|
||||||
|
namespace TelegramBotBaseTest.Tests.Navigation
|
||||||
|
{
|
||||||
|
public class Form1 : FormBase
|
||||||
|
{
|
||||||
|
Message msg = null;
|
||||||
|
|
||||||
|
public Form1()
|
||||||
|
{
|
||||||
|
this.Closed += Form1_Closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Form1_Closed(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (msg == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await Device.DeleteMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Action(MessageResult message)
|
||||||
|
{
|
||||||
|
if (message.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await message.ConfirmAction();
|
||||||
|
|
||||||
|
switch (message.RawData)
|
||||||
|
{
|
||||||
|
case "next":
|
||||||
|
|
||||||
|
message.Handled = true;
|
||||||
|
|
||||||
|
var f1 = new Form1();
|
||||||
|
|
||||||
|
await NavigationController.PushAsync(f1);
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "previous":
|
||||||
|
|
||||||
|
message.Handled = true;
|
||||||
|
|
||||||
|
//Pop's the current form and move the previous one. The root form will be the Start class.
|
||||||
|
await NavigationController.PopAsync();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "root":
|
||||||
|
|
||||||
|
message.Handled = true;
|
||||||
|
|
||||||
|
await NavigationController.PopToRootAsync();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Render(MessageResult message)
|
||||||
|
{
|
||||||
|
if (msg != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var bf = new ButtonForm();
|
||||||
|
bf.AddButtonRow("Next page", "next");
|
||||||
|
bf.AddButtonRow("Previous page", "previous");
|
||||||
|
bf.AddButtonRow("Back to root", "root");
|
||||||
|
|
||||||
|
msg = await Device.Send($"Choose your options (Count on stack {NavigationController.Index + 1})", bf);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
88
TelegramBotBaseTest/Tests/Navigation/Start.cs
Normal file
88
TelegramBotBaseTest/Tests/Navigation/Start.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using TelegramBotBase.Base;
|
||||||
|
using TelegramBotBase.Form;
|
||||||
|
using TelegramBotBase.Form.Navigation;
|
||||||
|
|
||||||
|
namespace TelegramBotBaseTest.Tests.Navigation
|
||||||
|
{
|
||||||
|
public class Start : FormBase
|
||||||
|
{
|
||||||
|
|
||||||
|
Message msg = null;
|
||||||
|
|
||||||
|
public Start()
|
||||||
|
{
|
||||||
|
this.Closed += Start_Closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Start_Closed(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (msg == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await Device.DeleteMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Load(MessageResult message)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Action(MessageResult message)
|
||||||
|
{
|
||||||
|
if (message.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await message.ConfirmAction();
|
||||||
|
|
||||||
|
switch (message.RawData)
|
||||||
|
{
|
||||||
|
case "yes":
|
||||||
|
|
||||||
|
message.Handled = true;
|
||||||
|
|
||||||
|
//Create navigation controller and navigate to it, keep the current form as root form so we can get back to here later
|
||||||
|
var nc = new CustomController(this);
|
||||||
|
|
||||||
|
var f1 = new Form1();
|
||||||
|
|
||||||
|
await NavigateTo(nc);
|
||||||
|
|
||||||
|
await nc.PushAsync(f1);
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "no":
|
||||||
|
|
||||||
|
message.Handled = true;
|
||||||
|
|
||||||
|
var mn = new Menu();
|
||||||
|
|
||||||
|
await NavigateTo(mn);
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Render(MessageResult message)
|
||||||
|
{
|
||||||
|
var bf = new ButtonForm();
|
||||||
|
|
||||||
|
bf.AddButtonRow("Yes", "yes");
|
||||||
|
bf.AddButtonRow("No", "no");
|
||||||
|
|
||||||
|
msg = await Device.Send("Open controller?", bf);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
63
TelegramBotBaseTest/Tests/Notifications/Start.cs
Normal file
63
TelegramBotBaseTest/Tests/Notifications/Start.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using TelegramBotBase.Base;
|
||||||
|
using TelegramBotBase.Form;
|
||||||
|
|
||||||
|
namespace TelegramBotBaseTest.Tests.Notifications
|
||||||
|
{
|
||||||
|
public class Start : AutoCleanForm
|
||||||
|
{
|
||||||
|
bool sent = false;
|
||||||
|
|
||||||
|
public Start()
|
||||||
|
{
|
||||||
|
this.DeleteMode = TelegramBotBase.Enums.eDeleteMode.OnLeavingForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Action(MessageResult message)
|
||||||
|
{
|
||||||
|
if (message.Handled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (message.RawData)
|
||||||
|
{
|
||||||
|
case "alert":
|
||||||
|
|
||||||
|
await message.ConfirmAction("This is an alert.", true);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "back":
|
||||||
|
|
||||||
|
var mn = new Menu();
|
||||||
|
await NavigateTo(mn);
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
|
||||||
|
await message.ConfirmAction("This is feedback");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Render(MessageResult message)
|
||||||
|
{
|
||||||
|
if (sent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var bf = new ButtonForm();
|
||||||
|
bf.AddButtonRow("Normal feeback", "normal");
|
||||||
|
bf.AddButtonRow("Alert Box", "alert");
|
||||||
|
bf.AddButtonRow("Back", "back");
|
||||||
|
|
||||||
|
await Device.Send("Choose your test", bf);
|
||||||
|
|
||||||
|
sent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net452" />
|
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net5" />
|
||||||
<package id="System.Net.Requests" version="4.3.0" targetFramework="net452" />
|
<package id="System.Net.Requests" version="4.3.0" targetFramework="net5" />
|
||||||
<package id="Telegram.Bot" version="14.12.0" targetFramework="net452" />
|
<package id="Telegram.Bot" version="14.12.0" targetFramework="net5" />
|
||||||
</packages>
|
</packages>
|
||||||
Loading…
x
Reference in New Issue
Block a user