154 lines
3.9 KiB
C#
154 lines
3.9 KiB
C#
|
|
|
|
|
|
// ReSharper disable once CheckNamespace
|
|
namespace WPFluent.Controls;
|
|
|
|
public class SnackbarPresenter : System.Windows.Controls.ContentPresenter
|
|
{
|
|
public SnackbarPresenter()
|
|
{
|
|
Unloaded += static(sender, _) =>
|
|
{
|
|
var self = (SnackbarPresenter)sender;
|
|
self.OnUnloaded();
|
|
};
|
|
}
|
|
|
|
~SnackbarPresenter()
|
|
{
|
|
if(!CancellationTokenSource.IsCancellationRequested)
|
|
{
|
|
CancellationTokenSource.Cancel();
|
|
}
|
|
|
|
CancellationTokenSource.Dispose();
|
|
}
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
|
"WpfAnalyzers.DependencyProperty",
|
|
"WPF0041:Set mutable dependency properties using SetCurrentValue",
|
|
Justification = "SetCurrentValue(ContentProperty, ...) will not work")]
|
|
private async Task HidSnackbar(Snackbar snackbar)
|
|
{
|
|
snackbar.SetCurrentValue(Snackbar.IsShownProperty, false);
|
|
|
|
await Task.Delay(300);
|
|
|
|
Content = null;
|
|
}
|
|
|
|
private void ImmediatelyHideCurrent()
|
|
{
|
|
if(Content is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CancellationTokenSource.Cancel();
|
|
ImmediatelyHidSnackbar(Content);
|
|
}
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
|
"WpfAnalyzers.DependencyProperty",
|
|
"WPF0041:Set mutable dependency properties using SetCurrentValue",
|
|
Justification = "SetCurrentValue(ContentProperty, ...) will not work")]
|
|
private void ImmediatelyHidSnackbar(Snackbar snackbar)
|
|
{
|
|
snackbar.SetCurrentValue(Snackbar.IsShownProperty, false);
|
|
Content = null;
|
|
}
|
|
|
|
private async Task ShowQueuedSnackbarsAsync()
|
|
{
|
|
while(Queue.Count > 0 && !CancellationTokenSource.IsCancellationRequested)
|
|
{
|
|
Snackbar snackbar = Queue.Dequeue();
|
|
|
|
await ShowSnackbar(snackbar);
|
|
}
|
|
}
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
|
"WpfAnalyzers.DependencyProperty",
|
|
"WPF0041:Set mutable dependency properties using SetCurrentValue",
|
|
Justification = "SetCurrentValue(ContentProperty, ...) will not work")]
|
|
private async Task ShowSnackbar(Snackbar snackbar)
|
|
{
|
|
Content = snackbar;
|
|
|
|
snackbar.SetCurrentValue(Snackbar.IsShownProperty, true);
|
|
|
|
try
|
|
{
|
|
await Task.Delay(snackbar.Timeout, CancellationTokenSource.Token);
|
|
} catch
|
|
{
|
|
return;
|
|
}
|
|
|
|
await HidSnackbar(snackbar);
|
|
}
|
|
|
|
protected virtual void OnUnloaded()
|
|
{
|
|
if(CancellationTokenSource.IsCancellationRequested)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ImmediatelyHideCurrent();
|
|
ResetCancellationTokenSource();
|
|
}
|
|
|
|
protected void ResetCancellationTokenSource()
|
|
{
|
|
CancellationTokenSource.Dispose();
|
|
CancellationTokenSource = new CancellationTokenSource();
|
|
}
|
|
|
|
protected CancellationTokenSource CancellationTokenSource { get; set; } = new();
|
|
|
|
protected Queue<Snackbar> Queue { get; } = new();
|
|
|
|
public virtual void AddToQue(Snackbar snackbar)
|
|
{
|
|
Queue.Enqueue(snackbar);
|
|
|
|
if(Content is null)
|
|
{
|
|
_ = ShowQueuedSnackbarsAsync(); // TODO: Fix detached process
|
|
}
|
|
}
|
|
|
|
public virtual async Task HideCurrent()
|
|
{
|
|
if(Content is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CancellationTokenSource.Cancel();
|
|
await HidSnackbar(Content);
|
|
ResetCancellationTokenSource();
|
|
}
|
|
|
|
public virtual async Task ImmediatelyDisplay(Snackbar snackbar)
|
|
{
|
|
await HideCurrent();
|
|
await ShowSnackbar(snackbar);
|
|
|
|
await ShowQueuedSnackbarsAsync();
|
|
}
|
|
|
|
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
|
"WpfAnalyzers.DependencyProperty",
|
|
"WPF0012:CLR property type should match registered type",
|
|
Justification = "seems harmless")]
|
|
public new Snackbar? Content
|
|
{
|
|
get => (Snackbar?)GetValue(ContentProperty);
|
|
protected set => SetValue(ContentProperty, value);
|
|
}
|
|
}
|