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.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TelegramBotBase.Controls.Hybrid;
|
||||
using TelegramBotBase.Form;
|
||||
|
||||
namespace TelegramBotBase.Args
|
||||
@ -18,6 +19,8 @@ namespace TelegramBotBase.Args
|
||||
|
||||
public object Tag { get; set; }
|
||||
|
||||
public ButtonRow Row { get; set; }
|
||||
|
||||
|
||||
public ButtonClickedEventArgs()
|
||||
{
|
||||
@ -36,5 +39,11 @@ namespace TelegramBotBase.Args
|
||||
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.Collections.Generic;
|
||||
using System.Text;
|
||||
using TelegramBotBase.Controls.Hybrid;
|
||||
using TelegramBotBase.Form;
|
||||
|
||||
namespace TelegramBotBase.Args
|
||||
@ -17,7 +18,7 @@ namespace TelegramBotBase.Args
|
||||
/// <summary>
|
||||
/// Contains all buttons within this row, excluding the checkbox.
|
||||
/// </summary>
|
||||
public List<ButtonBase> Row { get; set; }
|
||||
public ButtonRow Row { get; set; }
|
||||
|
||||
|
||||
/// <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.Index = Index;
|
||||
|
||||
@ -10,6 +10,7 @@ using Telegram.Bot.Types.Enums;
|
||||
using Telegram.Bot.Types.ReplyMarkups;
|
||||
using TelegramBotBase.Args;
|
||||
using TelegramBotBase.Base;
|
||||
using TelegramBotBase.Datasources;
|
||||
using TelegramBotBase.Enums;
|
||||
using TelegramBotBase.Exceptions;
|
||||
using TelegramBotBase.Form;
|
||||
@ -30,7 +31,26 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
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; }
|
||||
|
||||
@ -89,12 +109,12 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
/// <summary>
|
||||
/// Layout of the buttons which should be displayed always on top.
|
||||
/// </summary>
|
||||
public List<ButtonBase> HeadLayoutButtonRow { get; set; }
|
||||
public ButtonRow HeadLayoutButtonRow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Layout of columns which should be displayed below the header
|
||||
/// </summary>
|
||||
public List<ButtonBase> SubHeadLayoutButtonRow { get; set; }
|
||||
public ButtonRow SubHeadLayoutButtonRow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines which type of Button Keyboard should be rendered.
|
||||
@ -123,8 +143,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
public ButtonGrid()
|
||||
{
|
||||
this.ButtonsForm = new ButtonForm();
|
||||
|
||||
this.DataSource = new ButtonFormDataSource();
|
||||
|
||||
}
|
||||
|
||||
@ -136,7 +155,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
public ButtonGrid(ButtonForm form)
|
||||
{
|
||||
this.ButtonsForm = form;
|
||||
this.DataSource = new ButtonFormDataSource(form);
|
||||
}
|
||||
|
||||
|
||||
@ -188,22 +207,49 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
if (!result.IsFirstHandler)
|
||||
return;
|
||||
|
||||
if (result.MessageText == null)
|
||||
if (result.MessageText == null || result.MessageText == "")
|
||||
return;
|
||||
|
||||
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
||||
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
||||
?? ButtonsForm.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText);
|
||||
var matches = new List<ButtonRow>();
|
||||
ButtonRow match = null;
|
||||
int index = -1;
|
||||
|
||||
var index = ButtonsForm.FindRowByButton(button);
|
||||
|
||||
if (button != null)
|
||||
if (HeadLayoutButtonRow?.Matches(result.MessageText) ?? false)
|
||||
{
|
||||
await OnButtonClicked(new ButtonClickedEventArgs(button, index));
|
||||
match = HeadLayoutButtonRow;
|
||||
goto check;
|
||||
}
|
||||
|
||||
//Remove button click message
|
||||
if (this.DeleteReplyMessage)
|
||||
await Device.DeleteMessage(result.MessageId);
|
||||
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)
|
||||
{
|
||||
await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.MessageText), index, match));
|
||||
|
||||
result.Handled = true;
|
||||
return;
|
||||
@ -261,22 +307,48 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
if (!result.IsFirstHandler)
|
||||
return;
|
||||
|
||||
await result.ConfirmAction(this.ConfirmationText ?? "");
|
||||
|
||||
//Find clicked button depending on Text or Value (depending on markup type)
|
||||
if (this.KeyboardType != eKeyboardType.InlineKeyBoard)
|
||||
return;
|
||||
|
||||
await result.ConfirmAction(this.ConfirmationText ?? "");
|
||||
|
||||
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
||||
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
||||
?? ButtonsForm.ToList().FirstOrDefault(a => a.Value == result.RawData);
|
||||
ButtonRow match = null;
|
||||
int index = -1;
|
||||
|
||||
var index = ButtonsForm.FindRowByButton(button);
|
||||
|
||||
if (button != null)
|
||||
if (HeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
|
||||
{
|
||||
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;
|
||||
return;
|
||||
@ -313,28 +385,28 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
@ -351,22 +423,21 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
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 != "")
|
||||
{
|
||||
form = form.FilterDuplicate(this.SearchQuery, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
form = form.Duplicate();
|
||||
}
|
||||
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
||||
//{
|
||||
// form = form.FilterDuplicate(this.SearchQuery, true);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// form = form.Duplicate();
|
||||
//}
|
||||
|
||||
if (this.EnablePaging)
|
||||
{
|
||||
form = GeneratePagingView(form);
|
||||
IntegratePagingView(form);
|
||||
}
|
||||
|
||||
if (this.HeadLayoutButtonRow != null && HeadLayoutButtonRow.Count > 0)
|
||||
@ -386,26 +457,37 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
}
|
||||
}
|
||||
|
||||
Message m = null;
|
||||
|
||||
switch (this.KeyboardType)
|
||||
{
|
||||
//Reply Keyboard could only be updated with a new keyboard.
|
||||
case eKeyboardType.ReplyKeyboard:
|
||||
|
||||
if (this.MessageId != null)
|
||||
|
||||
if (form.Count == 0)
|
||||
{
|
||||
if (form.Count == 0)
|
||||
if (this.MessageId != null)
|
||||
{
|
||||
await this.Device.HideReplyKeyboard();
|
||||
this.MessageId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.DeletePreviousMessage)
|
||||
await this.Device.DeleteMessage(this.MessageId.Value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (form.Count == 0)
|
||||
return;
|
||||
//if (this.MessageId != null)
|
||||
//{
|
||||
// if (form.Count == 0)
|
||||
// {
|
||||
// await this.Device.HideReplyKeyboard();
|
||||
// this.MessageId = null;
|
||||
// return;
|
||||
// }
|
||||
//}
|
||||
|
||||
//if (form.Count == 0)
|
||||
// return;
|
||||
|
||||
|
||||
var rkm = (ReplyKeyboardMarkup)form;
|
||||
@ -413,6 +495,10 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
rkm.OneTimeKeyboard = this.OneTimeKeyboard;
|
||||
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;
|
||||
|
||||
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
|
||||
if (this.ButtonsForm.Count == 0)
|
||||
if (dataForm.Rows == 0)
|
||||
{
|
||||
bf.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
|
||||
dataForm.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
|
||||
}
|
||||
|
||||
if (this.IsNavigationBarVisible)
|
||||
{
|
||||
//🔍
|
||||
List<ButtonBase> lst = new List<ButtonBase>();
|
||||
lst.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
|
||||
lst.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
|
||||
lst.Add(new ButtonBase(NextPageLabel, "$next$"));
|
||||
ButtonRow row = new ButtonRow();
|
||||
row.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
|
||||
row.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
|
||||
row.Add(new ButtonBase(NextPageLabel, "$next$"));
|
||||
|
||||
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
|
||||
@ -545,7 +615,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
{
|
||||
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
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.ButtonsForm.Count == 0)
|
||||
if (DataSource.RowCount == 0)
|
||||
return 1;
|
||||
|
||||
var bf = this.ButtonsForm;
|
||||
//var bf = this.DataSource.PickAllItems(this.EnableSearch ? this.SearchQuery : null);
|
||||
|
||||
if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
||||
{
|
||||
bf = bf.FilterDuplicate(this.SearchQuery);
|
||||
}
|
||||
var max = this.DataSource.CalculateMax(this.EnableSearch ? this.SearchQuery : null);
|
||||
|
||||
if (bf.Rows == 0)
|
||||
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
||||
//{
|
||||
// bf = bf.FilterDuplicate(this.SearchQuery);
|
||||
//}
|
||||
|
||||
if (max == 0)
|
||||
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 TelegramBotBase.Args;
|
||||
using TelegramBotBase.Base;
|
||||
using TelegramBotBase.Datasources;
|
||||
using TelegramBotBase.Enums;
|
||||
using TelegramBotBase.Exceptions;
|
||||
using TelegramBotBase.Form;
|
||||
@ -32,7 +33,23 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
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>();
|
||||
|
||||
@ -51,6 +68,11 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
public bool DeletePreviousMessage { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Removes the reply message from a user.
|
||||
/// </summary>
|
||||
public bool DeleteReplyMessage { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Parsemode of the message.
|
||||
/// </summary>
|
||||
@ -92,12 +114,12 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
/// <summary>
|
||||
/// Layout of the buttons which should be displayed always on top.
|
||||
/// </summary>
|
||||
public List<ButtonBase> HeadLayoutButtonRow { get; set; }
|
||||
public ButtonRow HeadLayoutButtonRow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Layout of columns which should be displayed below the header
|
||||
/// </summary>
|
||||
public List<ButtonBase> SubHeadLayoutButtonRow { get; set; }
|
||||
public ButtonRow SubHeadLayoutButtonRow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines which type of Button Keyboard should be rendered.
|
||||
@ -126,7 +148,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
public CheckedButtonList()
|
||||
{
|
||||
this.ButtonsForm = new ButtonForm();
|
||||
this.DataSource = new ButtonFormDataSource();
|
||||
|
||||
|
||||
}
|
||||
@ -139,7 +161,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
public CheckedButtonList(ButtonForm form)
|
||||
{
|
||||
this.ButtonsForm = form;
|
||||
this.DataSource = new ButtonFormDataSource(form);
|
||||
}
|
||||
|
||||
public event AsyncEventHandler<ButtonClickedEventArgs> ButtonClicked
|
||||
@ -198,16 +220,50 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
if (!result.IsFirstHandler)
|
||||
return;
|
||||
|
||||
if (result.MessageText == null)
|
||||
if (result.MessageText == null || result.MessageText == "")
|
||||
return;
|
||||
|
||||
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
||||
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
||||
?? ButtonsForm.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText);
|
||||
var matches = new List<ButtonRow>();
|
||||
ButtonRow match = null;
|
||||
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)
|
||||
{
|
||||
@ -226,7 +282,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
else if (result.MessageText.EndsWith(CheckedIconLabel))
|
||||
{
|
||||
var s = result.MessageText.Split(' ', '.');
|
||||
index = int.Parse(s[0]);
|
||||
index = int.Parse(s[0]) - 1;
|
||||
|
||||
if (!this.CheckedRows.Contains(index))
|
||||
return;
|
||||
@ -241,7 +297,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
else if (result.MessageText.EndsWith(UncheckedIconLabel))
|
||||
{
|
||||
var s = result.MessageText.Split(' ', '.');
|
||||
index = int.Parse(s[0]);
|
||||
index = int.Parse(s[0]) - 1;
|
||||
|
||||
if (this.CheckedRows.Contains(index))
|
||||
return;
|
||||
@ -285,14 +341,18 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
}
|
||||
|
||||
|
||||
await OnButtonClicked(new ButtonClickedEventArgs(button, index));
|
||||
|
||||
//Remove button click message
|
||||
if (this.DeletePreviousMessage)
|
||||
await Device.DeleteMessage(result.MessageId);
|
||||
await OnButtonClicked(new ButtonClickedEventArgs(match.GetButtonMatch(result.MessageText), index, match));
|
||||
|
||||
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)
|
||||
@ -309,20 +369,55 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
await result.ConfirmAction(this.ConfirmationText ?? "");
|
||||
|
||||
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
||||
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
||||
?? ButtonsForm.ToList().FirstOrDefault(a => a.Value == result.RawData);
|
||||
ButtonRow match = null;
|
||||
int index = -1;
|
||||
|
||||
var index = ButtonsForm.FindRowByButton(button);
|
||||
|
||||
if (button != null)
|
||||
if (HeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
|
||||
{
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
//if (button != null)
|
||||
//{
|
||||
// await OnButtonClicked(new ButtonClickedEventArgs(button, index));
|
||||
|
||||
// result.Handled = true;
|
||||
// return;
|
||||
//}
|
||||
|
||||
switch (result.RawData)
|
||||
{
|
||||
case "$previous$":
|
||||
@ -396,28 +491,28 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
@ -436,7 +531,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
Message m = null;
|
||||
|
||||
ButtonForm form = this.ButtonsForm;
|
||||
ButtonForm form = this.DataSource.PickItems(CurrentPageIndex * ItemRowsPerPage, ItemRowsPerPage, null);
|
||||
|
||||
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
||||
//{
|
||||
@ -444,12 +539,12 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
form = form.Duplicate();
|
||||
//form = form.Duplicate();
|
||||
//}
|
||||
|
||||
if (this.EnablePaging)
|
||||
{
|
||||
form = GeneratePagingView(form);
|
||||
IntegratePagingView(form);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -458,18 +553,18 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
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.IsNavigationBarVisible)
|
||||
{
|
||||
form.InsertButtonRow(2, this.SubHeadLayoutButtonRow);
|
||||
form.InsertButtonRow(2, this.SubHeadLayoutButtonRow.ToArray());
|
||||
}
|
||||
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.
|
||||
case eKeyboardType.ReplyKeyboard:
|
||||
|
||||
if (this.MessageId != null)
|
||||
if (form.Count == 0)
|
||||
{
|
||||
if (form.Count == 0)
|
||||
if (this.MessageId != null)
|
||||
{
|
||||
await this.Device.HideReplyKeyboard();
|
||||
this.MessageId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.DeletePreviousMessage)
|
||||
await this.Device.DeleteMessage(this.MessageId.Value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (form.Count == 0)
|
||||
return;
|
||||
//if (form.Count == 0)
|
||||
// return;
|
||||
|
||||
|
||||
var rkm = (ReplyKeyboardMarkup)form;
|
||||
@ -500,6 +593,10 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
rkm.OneTimeKeyboard = this.OneTimeKeyboard;
|
||||
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;
|
||||
|
||||
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();
|
||||
|
||||
bf = PrepareCheckableLayout(dataForm);
|
||||
|
||||
//No Items
|
||||
if (this.ButtonsForm.Count == 0)
|
||||
{
|
||||
bf.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
|
||||
}
|
||||
|
||||
if (this.IsNavigationBarVisible)
|
||||
{
|
||||
//🔍
|
||||
List<ButtonBase> lst = new List<ButtonBase>();
|
||||
lst.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
|
||||
lst.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
|
||||
lst.Add(new ButtonBase(NextPageLabel, "$next$"));
|
||||
ButtonRow row = new ButtonRow();
|
||||
row.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
|
||||
row.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
if (it > dataForm.Rows - 1)
|
||||
break;
|
||||
//if (it > dataForm.Rows - 1)
|
||||
// break;
|
||||
|
||||
var r = dataForm[it];
|
||||
var r = dataForm[i];
|
||||
|
||||
String s = CheckedRows.Contains(it) ? this.CheckedIconLabel : this.UncheckedIconLabel;
|
||||
|
||||
//On reply keyboards we need a unique text.
|
||||
if (this.KeyboardType == eKeyboardType.ReplyKeyboard)
|
||||
{
|
||||
s = $"{it}. " + s;
|
||||
s = $"{it + 1}. " + s;
|
||||
}
|
||||
|
||||
if (CheckedRows.Contains(it))
|
||||
@ -652,7 +743,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
{
|
||||
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
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.ButtonsForm.Count == 0)
|
||||
if (DataSource.RowCount == 0)
|
||||
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 != "")
|
||||
//{
|
||||
// bf = bf.FilterDuplicate(this.SearchQuery);
|
||||
//}
|
||||
|
||||
if (bf.Rows == 0)
|
||||
if (max == 0)
|
||||
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 Telegram.Bot.Types;
|
||||
using Telegram.Bot.Types.Enums;
|
||||
using Telegram.Bot.Types.InlineQueryResults;
|
||||
using Telegram.Bot.Types.ReplyMarkups;
|
||||
using TelegramBotBase.Args;
|
||||
using TelegramBotBase.Base;
|
||||
using TelegramBotBase.Datasources;
|
||||
using TelegramBotBase.Enums;
|
||||
using TelegramBotBase.Exceptions;
|
||||
using TelegramBotBase.Form;
|
||||
@ -30,7 +32,23 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
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; }
|
||||
|
||||
@ -62,6 +80,11 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
/// </summary>
|
||||
public bool EnablePaging { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Shows un-/check all tags options
|
||||
/// </summary>
|
||||
public bool EnableCheckAllTools { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Enabled a search function.
|
||||
/// </summary>
|
||||
@ -87,15 +110,24 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
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>
|
||||
/// Layout of the buttons which should be displayed always on top.
|
||||
/// </summary>
|
||||
public List<ButtonBase> HeadLayoutButtonRow { get; set; }
|
||||
public ButtonRow HeadLayoutButtonRow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Layout of columns which should be displayed below the header
|
||||
/// </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>
|
||||
/// List of Tags which will be allowed to filter by.
|
||||
@ -134,7 +166,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
public TaggedButtonGrid()
|
||||
{
|
||||
this.ButtonsForm = new ButtonForm();
|
||||
this.DataSource = new ButtonFormDataSource();
|
||||
|
||||
this.SelectedViewIndex = 0;
|
||||
}
|
||||
@ -147,7 +179,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
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 == "")
|
||||
return;
|
||||
|
||||
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
||||
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Text.Trim() == result.MessageText)
|
||||
?? ButtonsForm.ToList().FirstOrDefault(a => a.Text.Trim() == result.MessageText);
|
||||
var matches = new List<ButtonRow>();
|
||||
ButtonRow match = null;
|
||||
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)
|
||||
{
|
||||
case 0:
|
||||
|
||||
if (button != null)
|
||||
{
|
||||
await OnButtonClicked(new ButtonClickedEventArgs(button, index));
|
||||
//Remove button click message
|
||||
if (this.DeleteReplyMessage)
|
||||
await Device.DeleteMessage(result.MessageId);
|
||||
|
||||
//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;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -287,17 +352,25 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
break;
|
||||
case 1:
|
||||
|
||||
//Remove button click message
|
||||
if (this.DeleteReplyMessage)
|
||||
await Device.DeleteMessage(result.MessageId);
|
||||
|
||||
if (result.MessageText == this.BackLabel)
|
||||
{
|
||||
//Remove button click message
|
||||
if (this.DeletePreviousMessage)
|
||||
await Device.DeleteMessage(result.MessageId);
|
||||
|
||||
this.SelectedViewIndex = 0;
|
||||
this.Updated();
|
||||
result.Handled = true;
|
||||
return;
|
||||
}
|
||||
else if (result.MessageText == this.CheckAllLabel)
|
||||
{
|
||||
this.CheckAllTags();
|
||||
}
|
||||
else if (result.MessageText == this.UncheckAllLabel)
|
||||
{
|
||||
this.UncheckAllTags();
|
||||
}
|
||||
|
||||
var i = result.MessageText.LastIndexOf(" ");
|
||||
if (i == -1)
|
||||
@ -340,15 +413,48 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
await result.ConfirmAction(this.ConfirmationText ?? "");
|
||||
|
||||
var button = HeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
||||
?? SubHeadLayoutButtonRow?.FirstOrDefault(a => a.Value == result.RawData)
|
||||
?? ButtonsForm.ToList().FirstOrDefault(a => a.Value == result.RawData);
|
||||
ButtonRow match = null;
|
||||
int index = -1;
|
||||
|
||||
var index = ButtonsForm.FindRowByButton(button);
|
||||
|
||||
if (button != null)
|
||||
if (HeadLayoutButtonRow?.Matches(result.RawData, false) ?? false)
|
||||
{
|
||||
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;
|
||||
return;
|
||||
@ -386,6 +492,18 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
this.SelectedViewIndex = 0;
|
||||
this.Updated();
|
||||
|
||||
break;
|
||||
|
||||
case "$checkall$":
|
||||
|
||||
this.CheckAllTags();
|
||||
|
||||
break;
|
||||
|
||||
case "$uncheckall$":
|
||||
|
||||
this.UncheckAllTags();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -400,28 +518,28 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
@ -468,16 +586,16 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
{
|
||||
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 != "")
|
||||
{
|
||||
form = form.FilterDuplicate(this.SearchQuery, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
form = form.Duplicate();
|
||||
}
|
||||
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
||||
//{
|
||||
// form = form.FilterDuplicate(this.SearchQuery, true);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// form = form.Duplicate();
|
||||
//}
|
||||
|
||||
if (this.Tags != null && this.SelectedTags != null)
|
||||
{
|
||||
@ -486,23 +604,23 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
if (this.EnablePaging)
|
||||
{
|
||||
form = GeneratePagingView(form);
|
||||
IntegratePagingView(form);
|
||||
}
|
||||
|
||||
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.IsNavigationBarVisible)
|
||||
{
|
||||
form.InsertButtonRow(2, this.SubHeadLayoutButtonRow);
|
||||
form.InsertButtonRow(2, this.SubHeadLayoutButtonRow.ToArray());
|
||||
}
|
||||
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
|
||||
if (this.ButtonsForm.Count == 0)
|
||||
if (dataForm.Rows == 0)
|
||||
{
|
||||
bf.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
|
||||
dataForm.AddButtonRow(new ButtonBase(NoItemsLabel, "$"));
|
||||
}
|
||||
|
||||
if (this.IsNavigationBarVisible)
|
||||
{
|
||||
//🔍
|
||||
List<ButtonBase> lst = new List<ButtonBase>();
|
||||
lst.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
|
||||
lst.Add(new ButtonBase(String.Format(Localizations.Default.Language["ButtonGrid_CurrentPage"], this.CurrentPageIndex + 1, this.PageCount), "$site$"));
|
||||
ButtonRow row = new ButtonRow();
|
||||
row.Add(new ButtonBase(PreviousPageLabel, "$previous$"));
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
@ -620,6 +723,12 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@ -748,7 +857,7 @@ namespace TelegramBotBase.Controls.Hybrid
|
||||
{
|
||||
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)
|
||||
layoutRows++;
|
||||
|
||||
if (EnableCheckAllTools && this.SelectedViewIndex == 1)
|
||||
{
|
||||
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
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.ButtonsForm.Count == 0)
|
||||
if (DataSource.RowCount == 0)
|
||||
return 1;
|
||||
|
||||
var bf = this.ButtonsForm;
|
||||
//var bf = this.DataSource.PickAllItems(this.EnableSearch ? this.SearchQuery : null);
|
||||
|
||||
if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
||||
{
|
||||
bf = bf.FilterDuplicate(this.SearchQuery);
|
||||
}
|
||||
var max = this.DataSource.CalculateMax(this.EnableSearch ? this.SearchQuery : null);
|
||||
|
||||
if (bf.Rows == 0)
|
||||
//if (this.EnableSearch && this.SearchQuery != null && this.SearchQuery != "")
|
||||
//{
|
||||
// bf = bf.FilterDuplicate(this.SearchQuery);
|
||||
//}
|
||||
|
||||
if (max == 0)
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 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 Telegram.Bot.Types.ReplyMarkups;
|
||||
using TelegramBotBase.Base;
|
||||
using TelegramBotBase.Controls.Hybrid;
|
||||
|
||||
namespace TelegramBotBase.Form
|
||||
{
|
||||
@ -13,7 +14,7 @@ namespace TelegramBotBase.Form
|
||||
/// </summary>
|
||||
public class ButtonForm
|
||||
{
|
||||
List<List<ButtonBase>> Buttons = new List<List<ButtonBase>>();
|
||||
List<ButtonRow> Buttons = new List<ButtonRow>();
|
||||
|
||||
|
||||
public IReplyMarkup Markup { get; set; }
|
||||
@ -43,7 +44,7 @@ namespace TelegramBotBase.Form
|
||||
}
|
||||
|
||||
|
||||
public List<ButtonBase> this[int row]
|
||||
public ButtonRow this[int row]
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -66,9 +67,14 @@ namespace TelegramBotBase.Form
|
||||
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)
|
||||
@ -76,16 +82,26 @@ namespace TelegramBotBase.Form
|
||||
AddButtonRow(row.ToList());
|
||||
}
|
||||
|
||||
public void AddButtonRows(IEnumerable<ButtonRow> rows)
|
||||
{
|
||||
Buttons.AddRange(rows);
|
||||
}
|
||||
|
||||
public void InsertButtonRow(int index, IEnumerable<ButtonBase> row)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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()
|
||||
{
|
||||
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()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public List<ButtonRow> ToArray()
|
||||
{
|
||||
return Buttons;
|
||||
}
|
||||
|
||||
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)
|
||||
return -1;
|
||||
|
||||
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>
|
||||
/// Returns the first Button with the given value.
|
||||
/// </summary>
|
||||
@ -204,7 +248,7 @@ namespace TelegramBotBase.Form
|
||||
|
||||
foreach (var b in Buttons)
|
||||
{
|
||||
var lst = new List<ButtonBase>();
|
||||
var lst = new ButtonRow();
|
||||
foreach (var b2 in b)
|
||||
{
|
||||
lst.Add(b2);
|
||||
@ -229,7 +273,7 @@ namespace TelegramBotBase.Form
|
||||
|
||||
foreach (var b in Buttons)
|
||||
{
|
||||
var lst = new List<ButtonBase>();
|
||||
var lst = new ButtonRow();
|
||||
foreach (var b2 in b)
|
||||
{
|
||||
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.
|
||||
if (ByRow)
|
||||
{
|
||||
lst.AddRange(b);
|
||||
lst = b;
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -268,7 +312,7 @@ namespace TelegramBotBase.Form
|
||||
|
||||
foreach (var b in Buttons)
|
||||
{
|
||||
var lst = new List<ButtonBase>();
|
||||
var lst = new ButtonRow();
|
||||
foreach (var b2 in b)
|
||||
{
|
||||
if (!(b2 is TagButtonBase tb))
|
||||
@ -280,7 +324,7 @@ namespace TelegramBotBase.Form
|
||||
//Copy full row, when at least one match has found.
|
||||
if (ByRow)
|
||||
{
|
||||
lst.AddRange(b);
|
||||
lst = b;
|
||||
break;
|
||||
}
|
||||
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.HeadLayoutButtonRow = new List<ButtonBase>() { new ButtonBase("Back", "back") };
|
||||
|
||||
|
||||
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.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;
|
||||
|
||||
@ -57,11 +60,13 @@ namespace TelegramBotBaseTest.Tests.Controls
|
||||
if (e.Button == null)
|
||||
return;
|
||||
|
||||
if (e.Button.Value == "back")
|
||||
switch (e.Button.Value)
|
||||
{
|
||||
var start = new Menu();
|
||||
await this.NavigateTo(start);
|
||||
return;
|
||||
|
||||
case "back":
|
||||
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);
|
||||
|
||||
|
||||
break;
|
||||
|
||||
case "dynamicbuttongrid":
|
||||
|
||||
var dg = new Datasources.List();
|
||||
|
||||
await NavigateTo(dg);
|
||||
|
||||
break;
|
||||
|
||||
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("#18 Dynamic ButtonGrid (DataSources)", new CallbackData("a", "dynamicbuttongrid").Serialize()));
|
||||
|
||||
await this.Device.Send("Choose your test:", btn);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user