MAJOR CHANGE for ButtonGrids, Dynamic data sources, etc
- introducing a dynamic data source class (IDataSource) - introducing a ButtonRow class for better managability - replacing that List<ButtonBase> with ButtonRow object - introducing ButtonFormDataSource with special methods for ButtonGrid controls - updating ButtonGrid and refactoring of the Load/Action methods - updating CheckButtonList and refactoring of the Load/Action methods - updating TaggedButtonGrid and refactoring of the Load/Action methods - adding example to the Test project
This commit is contained in:
parent
894d0799c8
commit
71433c0e4e
@ -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;
|
||||||
|
|||||||
@ -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; }
|
||||||
|
|
||||||
@ -62,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>
|
||||||
@ -87,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.
|
||||||
@ -134,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;
|
||||||
}
|
}
|
||||||
@ -147,7 +179,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
|
|
||||||
public TaggedButtonGrid(ButtonForm form)
|
public TaggedButtonGrid(ButtonForm form)
|
||||||
{
|
{
|
||||||
this.ButtonsForm = form;
|
this.DataSource = new ButtonFormDataSource(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -202,27 +234,60 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
if (result.MessageText == null || result.MessageText == "")
|
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.DeleteReplyMessage)
|
{
|
||||||
await Device.DeleteMessage(result.MessageId);
|
await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.MessageText), index, match));
|
||||||
|
|
||||||
result.Handled = true;
|
result.Handled = true;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,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)
|
||||||
@ -340,15 +413,48 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
@ -386,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,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;
|
||||||
@ -468,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)
|
||||||
{
|
{
|
||||||
@ -486,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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,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
|
||||||
@ -620,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)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -748,7 +857,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return this.LayoutRows + ButtonsForm.Rows;
|
return this.LayoutRows + DataSource.RowCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,6 +971,8 @@ namespace TelegramBotBase.Controls.Hybrid
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks all tags for filtering.
|
/// Checks all tags for filtering.
|
||||||
|
|||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
|||||||
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();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -32,6 +32,7 @@ namespace TelegramBotBaseTest.Tests.Controls
|
|||||||
m_Buttons.EnablePaging = true;
|
m_Buttons.EnablePaging = true;
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -190,6 +190,14 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
await NavigateTo(nc);
|
await NavigateTo(nc);
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "dynamicbuttongrid":
|
||||||
|
|
||||||
|
var dg = new Datasources.List();
|
||||||
|
|
||||||
|
await NavigateTo(dg);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -237,6 +245,8 @@ namespace TelegramBotBaseTest.Tests
|
|||||||
|
|
||||||
btn.AddButtonRow(new ButtonBase("#17 NavigationController (Push/Pop)", new CallbackData("a", "navigationcontroller").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()));
|
||||||
|
|
||||||
await this.Device.Send("Choose your test:", btn);
|
await this.Device.Send("Choose your test:", btn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user