- Update of FormBase for better async event management

- Update of ControlBase for partial rendering options
- Updating serveral base classes to better asyc event management
- separating Enums into different folder
- some small bug fixes
- removed "CustomEventManagement" cause it doesnt make sense now
This commit is contained in:
FlorianDahn
2019-07-14 22:22:04 +02:00
parent cb4a797b12
commit e4da70d37d
17 changed files with 404 additions and 103 deletions
+25
View File
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TelegramBotBase.Base
{
public static class Async
{
public delegate Task AsyncEventHandler<TEventArgs>(object sender, TEventArgs e) where TEventArgs : EventArgs;
public static IEnumerable<AsyncEventHandler<TEventArgs>> GetHandlers<TEventArgs>(
this AsyncEventHandler<TEventArgs> handler)
where TEventArgs : EventArgs
=> handler.GetInvocationList().Cast<AsyncEventHandler<TEventArgs>>();
public static Task InvokeAllAsync<TEventArgs>(this AsyncEventHandler<TEventArgs> handler, object sender, TEventArgs e)
where TEventArgs : EventArgs
=> Task.WhenAll(
handler.GetHandlers()
.Select(handleAsync => handleAsync(sender, e)));
}
}
+18 -1
View File
@@ -13,9 +13,26 @@ namespace TelegramBotBase.Base
{
public Sessions.DeviceSession Device { get; set; }
public virtual async Task Render()
public int ID { get; set; }
/// <summary>
/// Defines if the control should be rendered and invoked with actions
/// </summary>
public bool Enabled { get; set; } = true;
public virtual async Task Action(MessageResult result)
{
}
public virtual async Task Render(MessageResult result)
{
}
public virtual async Task Cleanup()
+143 -14
View File
@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TelegramBotBase.Base;
using TelegramBotBase.Sessions;
using static TelegramBotBase.Base.Async;
namespace TelegramBotBase.Form
{
@@ -13,12 +15,11 @@ namespace TelegramBotBase.Form
/// </summary>
public class FormBase : IDisposable
{
public DeviceSession Device { get; set; }
public MessageClient Client { get; set; }
public bool CustomEventManagement { get; set; } = false;
/// <summary>
/// has this formular already been disposed ?
/// </summary>
@@ -26,34 +27,119 @@ namespace TelegramBotBase.Form
public List<ControlBase> Controls { get; set; }
private EventHandlerList Events = new EventHandlerList();
private static object __evInit = new object();
private static object __evOpened = new object();
private static object __evClosed = new object();
public FormBase()
{
this.Controls = new List<Base.ControlBase>();
}
public FormBase(MessageClient Client): this()
public FormBase(MessageClient Client) : this()
{
this.Client = Client;
}
/// <summary>
/// Will get called at the initialization (once per context)
/// </summary>
public virtual async Task Init(params object[] args)
public async Task OnInit(InitEventArgs e)
{
if (this.Events[__evInit] == null)
return;
var handler = this.Events[__evInit].GetInvocationList().Cast<AsyncEventHandler<InitEventArgs>>();
foreach(var h in handler)
{
await Async.InvokeAllAsync<InitEventArgs>(h, this, e);
}
}
///// <summary>
///// Will get called at the initialization (once per context)
///// </summary>
public event AsyncEventHandler<InitEventArgs> Init
{
add
{
this.Events.AddHandler(__evInit, value);
}
remove
{
this.Events.RemoveHandler(__evInit, value);
}
}
public async Task OnOpened(EventArgs e)
{
if (this.Events[__evOpened] == null)
return;
var handler = this.Events[__evOpened].GetInvocationList().Cast<AsyncEventHandler<EventArgs>>();
foreach (var h in handler)
{
await Async.InvokeAllAsync<EventArgs>(h, this, e);
}
}
/// <summary>
/// Gets invoked if gets navigated to this form
/// </summary>
/// <returns></returns>
public virtual async Task Opened()
public event AsyncEventHandler<EventArgs> Opened
{
add
{
this.Events.AddHandler(__evOpened, value);
}
remove
{
this.Events.RemoveHandler(__evOpened, value);
}
}
public virtual async Task Closed()
public async Task OnClosed(EventArgs e)
{
if (this.Events[__evClosed] == null)
return;
var handler = this.Events[__evClosed].GetInvocationList().Cast<AsyncEventHandler<EventArgs>>();
foreach (var h in handler)
{
await Async.InvokeAllAsync<EventArgs>(h, this, e);
}
}
/// <summary>
/// Form has been closed (left)
/// </summary>
/// <returns></returns>
public event AsyncEventHandler<EventArgs> Closed
{
add
{
this.Events.AddHandler(__evClosed, value);
}
remove
{
this.Events.RemoveHandler(__evClosed, value);
}
}
/// <summary>
/// Pre to form close, cleanup all controls
/// </summary>
/// <returns></returns>
public async Task CloseControls()
{
foreach (var b in this.Controls)
{
@@ -76,6 +162,22 @@ namespace TelegramBotBase.Form
}
/// <summary>
/// Gets invoked if the user clicked a button.
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public async Task ActionControls(MessageResult message)
{
foreach (var b in this.Controls)
{
if (!b.Enabled)
continue;
await b.Action(message);
}
}
/// <summary>
/// Gets invoked if the user has clicked a button.
/// </summary>
@@ -96,6 +198,22 @@ namespace TelegramBotBase.Form
}
/// <summary>
/// Gets invoked at the end of the cycle to "Render" text, images, buttons, etc...
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public async Task RenderControls(MessageResult message)
{
foreach (var b in this.Controls)
{
if (!b.Enabled)
continue;
await b.Render(message);
}
}
/// <summary>
/// Gets invoked at the end of the cycle to "Render" text, images, buttons, etc...
/// </summary>
@@ -106,6 +224,8 @@ namespace TelegramBotBase.Form
}
/// <summary>
/// Navigates to a new form
/// </summary>
@@ -125,11 +245,20 @@ namespace TelegramBotBase.Form
newForm.Client = this.Client;
newForm.Device = ds;
await newForm.Init(args);
await newForm.OnInit(new InitEventArgs(args));
await this.Closed();
await this.CloseControls();
await newForm.Opened();
await this.OnClosed(new EventArgs());
await newForm.OnOpened(new EventArgs());
}
public void AddControl(ControlBase control)
{
control.ID = this.Controls.Count + 1;
control.Device = this.Device;
this.Controls.Add(control);
}
/// <summary>
+18
View File
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TelegramBotBase.Base
{
public class InitEventArgs : EventArgs
{
public object[] Args { get; set; }
public InitEventArgs(params object[] args)
{
this.Args = args;
}
}
}
+9 -9
View File
@@ -258,16 +258,12 @@ namespace TelegramBotBase
do
{
i++;
//Reset navigation
ds.FormSwitched = false;
activeForm = ds.ActiveForm;
//If the form manages the events by itselfs, skip here
if (activeForm.CustomEventManagement)
return;
//Pre Loading Event
await activeForm.PreLoad(e);
@@ -337,10 +333,6 @@ namespace TelegramBotBase
activeForm = ds.ActiveForm;
//If the form manages the events by itselfs, skip here
if (activeForm.CustomEventManagement)
return;
//Pre Loading Event
await activeForm.PreLoad(e);
@@ -350,6 +342,10 @@ namespace TelegramBotBase
//Action Event
if (!ds.FormSwitched)
{
//Send Action event to controls
await activeForm.ActionControls(e);
//Send Action event to form itself
await activeForm.Action(e);
if (!e.Handled)
@@ -374,7 +370,11 @@ namespace TelegramBotBase
//Render Event
if (!ds.FormSwitched)
{
await activeForm.RenderControls(e);
await activeForm.Render(e);
}
} while (ds.FormSwitched && i < NavigationMaximum);
+56
View File
@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TelegramBotBase.Enums
{
public enum eDeleteMode
{
/// <summary>
/// Don't delete any message.
/// </summary>
None = 0,
/// <summary>
/// Delete messages on every callback/action.
/// </summary>
OnEveryCall = 1,
/// <summary>
/// Delete on leaving this form.
/// </summary>
OnLeavingForm = 2
}
public enum eSide
{
/// <summary>
/// Delete only messages from this bot.
/// </summary>
BotOnly = 0,
/// <summary>
/// Delete only user messages.
/// </summary>
UserOnly = 1,
/// <summary>
/// Delete all messages in this context.
/// </summary>
Both = 2
}
public enum eMonthPickerMode
{
/// <summary>
/// Shows the calendar with day picker mode
/// </summary>
day = 0,
/// <summary>
/// Shows the calendar with month overview
/// </summary>
month = 1,
/// <summary>
/// Shows the calendar with year overview
/// </summary>
year = 2
}
}
+9 -34
View File
@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using Telegram.Bot.Types;
using TelegramBotBase.Base;
using TelegramBotBase.Enums;
namespace TelegramBotBase.Form
{
@@ -19,37 +20,7 @@ namespace TelegramBotBase.Form
public eSide DeleteSide { get; set; }
public enum eDeleteMode
{
/// <summary>
/// Don't delete any message.
/// </summary>
None = 0,
/// <summary>
/// Delete messages on every callback/action.
/// </summary>
OnEveryCall = 1,
/// <summary>
/// Delete on leaving this form.
/// </summary>
OnLeavingForm = 2
}
public enum eSide
{
/// <summary>
/// Delete only messages from this bot.
/// </summary>
BotOnly = 0,
/// <summary>
/// Delete only user messages.
/// </summary>
UserOnly = 1,
/// <summary>
/// Delete all messages in this context.
/// </summary>
Both = 2
}
public AutoCleanForm()
{
@@ -57,9 +28,14 @@ namespace TelegramBotBase.Form
this.DeleteMode = eDeleteMode.OnEveryCall;
this.DeleteSide = eSide.BotOnly;
this.Init += AutoCleanForm_Init;
this.Closed += AutoCleanForm_Closed;
}
public override async Task Init(params object[] args)
private async Task AutoCleanForm_Init(object sender, InitEventArgs e)
{
if (this.Device == null)
return;
@@ -127,7 +103,7 @@ namespace TelegramBotBase.Form
this.OldMessages.RemoveAt(this.OldMessages.Count - 1);
}
public async override Task Closed()
private async Task AutoCleanForm_Closed(object sender, EventArgs e)
{
if (this.DeleteMode != eDeleteMode.OnLeavingForm)
return;
@@ -135,7 +111,6 @@ namespace TelegramBotBase.Form
await MessageCleanup();
}
/// <summary>
/// Cleans up all remembered messages.
/// </summary>
+3
View File
@@ -77,6 +77,9 @@ namespace TelegramBotBase.Form
public static implicit operator InlineKeyboardMarkup(ButtonForm form)
{
if (form == null)
return null;
InlineKeyboardMarkup ikm = new InlineKeyboardMarkup(form.ToArray());
return ikm;
+2 -2
View File
@@ -67,9 +67,9 @@ namespace TelegramBotBase
DeviceSession ds = new Sessions.DeviceSession(deviceId, start);
start.Device = ds;
await start.Init();
await start.OnInit(new InitEventArgs());
await start.Opened();
await start.OnOpened(new EventArgs());
this[deviceId] = ds;
return ds;
+37 -20
View File
@@ -127,11 +127,7 @@ namespace TelegramBotBase.Sessions
if (this.ActiveForm == null)
return null;
InlineKeyboardMarkup markup = null;
if (buttons != null)
{
markup = buttons;
}
InlineKeyboardMarkup markup = buttons;
try
{
@@ -160,11 +156,7 @@ namespace TelegramBotBase.Sessions
if (this.ActiveForm == null)
return null;
InlineKeyboardMarkup markup = null;
if (buttons != null)
{
markup = buttons;
}
InlineKeyboardMarkup markup = buttons;
try
{
@@ -194,11 +186,7 @@ namespace TelegramBotBase.Sessions
if (this.ActiveForm == null)
return null;
InlineKeyboardMarkup markup = null;
if (buttons != null)
{
markup = buttons;
}
InlineKeyboardMarkup markup = buttons;
Message m = null;
@@ -253,6 +241,39 @@ namespace TelegramBotBase.Sessions
return m;
}
/// <summary>
/// Sends a simple text message
/// </summary>
/// <param name="text"></param>
/// <param name="markup"></param>
/// <param name="replyTo"></param>
/// <param name="disableNotification"></param>
/// <returns></returns>
public async Task<Message> Send(String text, ReplyKeyboardMarkup markup, int replyTo = 0, bool disableNotification = false)
{
if (this.ActiveForm == null)
return null;
Message m = null;
try
{
m = await (this.Client.TelegramClient.SendTextMessageAsync(this.DeviceId, text, replyToMessageId: replyTo, replyMarkup: markup, disableNotification: disableNotification));
OnMessageSent(new MessageSentEventArgs(m));
}
catch (ApiRequestException ex)
{
return null;
}
catch
{
return null;
}
return m;
}
/// <summary>
/// Sends an image
/// </summary>
@@ -266,11 +287,7 @@ namespace TelegramBotBase.Sessions
if (this.ActiveForm == null)
return null;
InlineKeyboardMarkup markup = null;
if (buttons != null)
{
markup = buttons;
}
InlineKeyboardMarkup markup = buttons;
Message m = null;