2using System.Collections.Concurrent;
4using System.Threading.Tasks;
5using Microsoft.Extensions.DependencyInjection;
6using Microsoft.Maui.ApplicationModel;
7using Microsoft.Maui.Controls;
16 private readonly ConcurrentQueue<Func<Task>> taskQueue =
new();
17 private bool isExecutingQueue;
18 private View? activeToast;
20 private CancellationTokenSource? autoHideTokenSource;
39 throw new ArgumentNullException(nameof(Toast));
42 return this.Enqueue(async () => await this.ShowInternalAsync(Toast, EffectiveOptions));
48 return this.Enqueue(async () => await this.HideInternalAsync(
null,
false));
51 private async Task ShowInternalAsync(View Toast,
ToastOptions Options)
53 await this.HideInternalAsync(
null,
true);
55 this.autoHideTokenSource?.Cancel();
56 this.autoHideTokenSource =
null;
58 this.activeToast = Toast;
59 this.activeOptions = Options;
63 this.RaiseToastChanged();
66 this.ScheduleAutoHide(Options);
69 private async Task HideInternalAsync(ToastOptions? Options,
bool IsReplacing)
71 if (this.activeToast is
null)
74 ToastOptions EffectiveOptions = Options ?? this.activeOptions ??
new ToastOptions();
75 this.autoHideTokenSource?.Cancel();
76 this.autoHideTokenSource =
null;
81 await Presenter.HideToast(EffectiveOptions.HideTransition);
88 this.activeToast =
null;
89 this.activeOptions =
null;
92 this.RaiseToastChanged();
95 private void ScheduleAutoHide(ToastOptions Options)
97 CancellationTokenSource TokenSource =
new();
98 this.autoHideTokenSource = TokenSource;
100 _ = Task.Run(async () =>
104 await Task.Delay(Options.Duration, TokenSource.Token);
105 if (!TokenSource.Token.IsCancellationRequested)
106 await this.Enqueue(async () => await this.HideInternalAsync(Options,
false));
108 catch (TaskCanceledException)
113 ServiceRef.LogService.LogException(Ex);
118 private Task Enqueue(Func<Task> Action)
120 TaskCompletionSource<bool> Completion =
new(TaskCreationOptions.RunContinuationsAsynchronously);
122 this.taskQueue.Enqueue(async () =>
127 Completion.TrySetResult(
true);
131 Completion.TrySetException(Ex);
135 this.StartQueueProcessing();
136 return Completion.Task;
139 private void StartQueueProcessing()
141 if (this.isExecutingQueue)
144 this.isExecutingQueue =
true;
145 MainThread.BeginInvokeOnMainThread(async () => await this.ProcessQueueAsync());
148 private async Task ProcessQueueAsync()
152 while (this.taskQueue.TryDequeue(out Func<Task>? Action))
157 ServiceRef.LogService.LogException(Ex);
161 this.isExecutingQueue =
false;
165 private IShellPresenter GetPresenter()
167 Page? MainPage = Application.Current?.MainPage;
168 if (MainPage is
null)
169 throw new InvalidOperationException(
"No main page is available for toast presentation.");
171 IShellPresenter? Presenter = (MainPage as NavigationPage)?.CurrentPage as IShellPresenter ?? MainPage as IShellPresenter;
172 if (Presenter is
null)
173 throw new InvalidOperationException(
"CustomShell presenter not found.");
178 private void RaiseToastChanged()
Base class that references services in the app.
static IServiceProvider Provider
The service provider for the app. This is set before the app is started, and will be used to resolve ...
static ILogService LogService
Log service.
Options controlling toast presentation.
bool AutoDismiss
Gets or sets whether the toast is dismissed automatically after Duration.
ToastTransition ShowTransition
Gets or sets the transition used when the toast is shown.
ToastPlacement Placement
Gets or sets the preferred placement for the toast overlay.
EventHandler? ToastChanged
Task ShowAsync(View Toast, ToastOptions? Options=null)
Shows a toast view instance.
Task ShowAsync< TToast >(ToastOptions? Options=null)
Shows a toast view resolved from dependency injection.
bool HasActiveToast
Returns true if a toast is currently presented.
Task HideAsync()
Hides the currently active toast, if any.
Presenter abstraction host for page, popup and toast transitions.
Service for presenting transient toast notifications.
Action
The Action field indicates the action performed by the Reporting-MTA as a result of its attempt to de...