public void Enqueue(object content, object actionContent, Action <object> actionHandler, object actionArgument, bool promote, bool neverConsiderToBeDuplicate) { if (content == null) { throw new ArgumentNullException(nameof(content)); } if (actionContent == null ^ actionHandler == null) { throw new ArgumentException("All action arguments must be provided if any are provided.", actionContent != null ? nameof(actionContent) : nameof(actionHandler)); } var snackbarMessageQueueItem = new SnackbarMessageQueueItem(content, actionContent, actionHandler, actionArgument, promote, neverConsiderToBeDuplicate); if (promote) { InsertAsLastNotPromotedNode(snackbarMessageQueueItem); } else { _snackbarMessages.AddLast(snackbarMessageQueueItem); } _messageWaitingEvent.Set(); }
private static SnackbarMessage Create(SnackbarMessageQueueItem messageQueueItem) { return(new SnackbarMessage { Content = messageQueueItem.Content, ActionContent = messageQueueItem.ActionContent }); }
private static void DoActionCallback(SnackbarMessageQueueItem messageQueueItem) { try { messageQueueItem.ActionHandler(messageQueueItem.ActionArgument); } catch (Exception exc) { Trace.WriteLine("Error during SnackbarMessageQueue message action callback, exception will be rethrown."); Trace.WriteLine($"{exc.Message} ({exc.GetType().FullName})"); Trace.WriteLine(exc.StackTrace); throw; } }
private void InsertAsLastNotPromotedNode(SnackbarMessageQueueItem snackbarMessageQueueItem) { var node = _snackbarMessages.First; while (node != null) { if (!node.Value.IsPromoted) { _snackbarMessages.AddBefore(node, snackbarMessageQueueItem); return; } node = node.Next; } _snackbarMessages.AddLast(snackbarMessageQueueItem); }
private async Task ShowAsync(Snackbar snackbar, SnackbarMessageQueueItem messageQueueItem) { await Task.Run(async() => { //create and show the message, setting up all the handles we need to wait on var actionClickWaitHandle = new ManualResetEvent(false); var mouseNotOverManagedWaitHandle = await snackbar.Dispatcher.InvokeAsync( () => CreateAndShowMessage(snackbar, messageQueueItem, actionClickWaitHandle)); var durationPassedWaitHandle = new ManualResetEvent(false); DurationMonitor.Start(_messageDuration.Add(snackbar.ActivateStoryboardDuration), _pausedEvent, durationPassedWaitHandle, _disposedEvent); //wait until time span completed (including pauses and mouse overs), or the action is clicked await WaitForCompletionAsync(mouseNotOverManagedWaitHandle, durationPassedWaitHandle, actionClickWaitHandle); //close message on snackbar await snackbar.Dispatcher.InvokeAsync( () => snackbar.SetCurrentValue(Snackbar.IsActiveProperty, false)); //we could wait for the animation event, but just doing //this for now...at least it is prevent extra call back hell _disposedEvent.WaitOne(snackbar.DeactivateStoryboardDuration); //remove message on snackbar await snackbar.Dispatcher.InvokeAsync( () => snackbar.SetCurrentValue(Snackbar.MessageProperty, null)); mouseNotOverManagedWaitHandle.Dispose(); durationPassedWaitHandle.Dispose(); }) .ContinueWith(t => { if (t.Exception == null) { return; } var exc = t.Exception.InnerExceptions.FirstOrDefault() ?? t.Exception; Trace.WriteLine("Error occured whilst showing Snackbar, exception will be rethrown."); Trace.WriteLine($"{exc.Message} ({exc.GetType().FullName})"); Trace.WriteLine(exc.StackTrace); throw t.Exception; }); }
private static MouseNotOverManagedWaitHandle CreateAndShowMessage(UIElement snackbar, SnackbarMessageQueueItem messageQueueItem, EventWaitHandle actionClickWaitHandle) { var clickCount = 0; var snackbarMessage = Create(messageQueueItem); snackbarMessage.ActionClick += (sender, args) => { if (++clickCount == 1) { DoActionCallback(messageQueueItem); } actionClickWaitHandle.Set(); }; snackbar.SetCurrentValue(Snackbar.MessageProperty, snackbarMessage); snackbar.SetCurrentValue(Snackbar.IsActiveProperty, true); return(new MouseNotOverManagedWaitHandle(snackbar)); }