Skip to content

Commit 8856183

Browse files
greuelpiratKeboo
andauthored
Fixed message discard prevents showing message at all (#1806)
* Check snackbar message duplicate before adding to queue. Removed time check for immediate show of new item. * Make the task pumping messages long running * Added null check to item Added unit tests for IsDuplicate method. Co-authored-by: Kevin Bost <[email protected]>
1 parent 4bb5623 commit 8856183

File tree

3 files changed

+88
-21
lines changed

3 files changed

+88
-21
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using System;
2+
using Xunit;
3+
4+
namespace MaterialDesignThemes.Wpf.Tests
5+
{
6+
public class SnackbarMessageQueueItemTests
7+
{
8+
[Fact]
9+
public void IsDuplicate_ThrowsOnNullArgument()
10+
{
11+
SnackbarMessageQueueItem item = CreateItem();
12+
Assert.Throws<ArgumentNullException>(() => item.IsDuplicate(null));
13+
}
14+
15+
[Fact]
16+
public void IsDuplicate_WithDuplicateItems_ItReturnsTrue()
17+
{
18+
SnackbarMessageQueueItem item = CreateItem();
19+
SnackbarMessageQueueItem other = CreateItem();
20+
21+
Assert.True(item.IsDuplicate(other));
22+
}
23+
24+
[Fact]
25+
public void IsDuplicate_IgnoreDuplicatesIsTrue_ItReturnsFalse()
26+
{
27+
SnackbarMessageQueueItem item = CreateItem(ignoreDuplicate:true);
28+
SnackbarMessageQueueItem other = CreateItem();
29+
30+
Assert.False(item.IsDuplicate(other));
31+
}
32+
33+
[Fact]
34+
public void IsDuplicate_WithDifferentContent_ItReturnsFalse()
35+
{
36+
SnackbarMessageQueueItem item = CreateItem();
37+
SnackbarMessageQueueItem other = CreateItem(content:Guid.NewGuid().ToString());
38+
39+
Assert.False(item.IsDuplicate(other));
40+
}
41+
42+
[Fact]
43+
public void IsDuplicate_WithDifferentActionContent_ItReturnsFalse()
44+
{
45+
SnackbarMessageQueueItem item = CreateItem();
46+
SnackbarMessageQueueItem other = CreateItem(actionContent:Guid.NewGuid().ToString());
47+
48+
Assert.False(item.IsDuplicate(other));
49+
}
50+
51+
52+
private static SnackbarMessageQueueItem CreateItem(
53+
string content = "Content",
54+
string actionContent = null,
55+
bool ignoreDuplicate = false)
56+
{
57+
return new SnackbarMessageQueueItem(content, TimeSpan.Zero, actionContent:actionContent, ignoreDuplicate: ignoreDuplicate);
58+
}
59+
}
60+
}

MaterialDesignThemes.Wpf/SnackbarMessageQueue.cs

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ public class SnackbarMessageQueue : ISnackbarMessageQueue, IDisposable
1818
private readonly ManualResetEvent _disposedEvent = new ManualResetEvent(false);
1919
private readonly ManualResetEvent _pausedEvent = new ManualResetEvent(false);
2020
private readonly ManualResetEvent _messageWaitingEvent = new ManualResetEvent(false);
21-
private Tuple<SnackbarMessageQueueItem, DateTime> _latestShownItem;
2221
private int _pauseCounter;
2322
private bool _isDisposed;
2423

@@ -157,7 +156,7 @@ public SnackbarMessageQueue() : this(TimeSpan.FromSeconds(3))
157156
public SnackbarMessageQueue(TimeSpan messageDuration)
158157
{
159158
_messageDuration = messageDuration;
160-
Task.Factory.StartNew(PumpAsync);
159+
Task.Factory.StartNew(PumpAsync, TaskCreationOptions.LongRunning);
161160
}
162161

163162
//oh if only I had Disposable.Create in this lib :) tempted to copy it in like dragabalz,
@@ -257,27 +256,27 @@ public void Enqueue(object content, object actionContent, Action<object> actionH
257256

258257
var snackbarMessageQueueItem = new SnackbarMessageQueueItem(content, durationOverride ?? _messageDuration,
259258
actionContent, actionHandler, actionArgument, promote, neverConsiderToBeDuplicate);
260-
if (promote)
261-
InsertAsLastNotPromotedNode(snackbarMessageQueueItem);
262-
else
263-
_snackbarMessages.AddLast(snackbarMessageQueueItem);
259+
InsertItem(snackbarMessageQueueItem);
264260

265261
_messageWaitingEvent.Set();
266262
}
267263

268-
private void InsertAsLastNotPromotedNode(SnackbarMessageQueueItem snackbarMessageQueueItem)
264+
private void InsertItem(SnackbarMessageQueueItem item)
269265
{
270266
var node = _snackbarMessages.First;
271267
while (node != null)
272268
{
273-
if (!node.Value.IsPromoted)
269+
if (!IgnoreDuplicate && item.IsDuplicate(node.Value))
270+
return;
271+
272+
if (item.IsPromoted && !node.Value.IsPromoted)
274273
{
275-
_snackbarMessages.AddBefore(node, snackbarMessageQueueItem);
274+
_snackbarMessages.AddBefore(node, item);
276275
return;
277276
}
278277
node = node.Next;
279278
}
280-
_snackbarMessages.AddLast(snackbarMessageQueueItem);
279+
_snackbarMessages.AddLast(item);
281280
}
282281

283282
private async void PumpAsync()
@@ -301,18 +300,9 @@ private async void PumpAsync()
301300
//show message
302301
if (snackbar != null)
303302
{
304-
var message = _snackbarMessages.First.Value;
303+
var message = _snackbarMessages.First!.Value;
304+
await ShowAsync(snackbar, message);
305305
_snackbarMessages.RemoveFirst();
306-
if (_latestShownItem == null
307-
|| IgnoreDuplicate
308-
|| message.IgnoreDuplicate
309-
|| !Equals(_latestShownItem.Item1.Content, message.Content)
310-
|| !Equals(_latestShownItem.Item1.ActionContent, message.ActionContent)
311-
|| _latestShownItem.Item2 <= DateTime.Now.Subtract(_latestShownItem.Item1.Duration))
312-
{
313-
await ShowAsync(snackbar, message);
314-
_latestShownItem = new Tuple<SnackbarMessageQueueItem, DateTime>(message, DateTime.Now);
315-
}
316306
}
317307
else
318308
{

MaterialDesignThemes.Wpf/SnackbarMessageQueueItem.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,22 @@ public SnackbarMessageQueueItem(object content, TimeSpan duration, object action
5050
/// Still display this message even if it is a duplicate.
5151
/// </summary>
5252
public bool IgnoreDuplicate { get; }
53+
54+
/// <summary>
55+
/// Checks if given item is a duplicate to this
56+
/// </summary>
57+
/// <param name="item">Item to check for duplicate</param>
58+
/// <returns><c>true</c> if given item is a duplicate to this, <c>false</c> otherwise</returns>
59+
public bool IsDuplicate(SnackbarMessageQueueItem item)
60+
{
61+
if (item is null)
62+
{
63+
throw new ArgumentNullException(nameof(item));
64+
}
65+
66+
return !IgnoreDuplicate
67+
&& Equals(item.Content, Content)
68+
&& Equals(item.ActionContent, ActionContent);
69+
}
5370
}
5471
}

0 commit comments

Comments
 (0)