Merge pull request #5081 from peppy/notification-overlay-always-present

Fix NotificationOverlay being always present
This commit is contained in:
Dan Balasescu
2019-06-21 13:28:47 +09:00
committed by GitHub
3 changed files with 198 additions and 120 deletions

View File

@ -18,9 +18,6 @@ namespace osu.Game.Tests.Visual.UserInterface
[TestFixture] [TestFixture]
public class TestSceneNotificationOverlay : OsuTestScene public class TestSceneNotificationOverlay : OsuTestScene
{ {
private readonly NotificationOverlay manager;
private readonly List<ProgressNotification> progressingNotifications = new List<ProgressNotification>();
public override IReadOnlyList<Type> RequiredTypes => new[] public override IReadOnlyList<Type> RequiredTypes => new[]
{ {
typeof(NotificationSection), typeof(NotificationSection),
@ -31,25 +28,33 @@ namespace osu.Game.Tests.Visual.UserInterface
typeof(Notification) typeof(Notification)
}; };
public TestSceneNotificationOverlay() private NotificationOverlay notificationOverlay;
private readonly List<ProgressNotification> progressingNotifications = new List<ProgressNotification>();
private SpriteText displayedCount;
[SetUp]
public void SetUp() => Schedule(() =>
{ {
progressingNotifications.Clear(); progressingNotifications.Clear();
Content.Add(manager = new NotificationOverlay Content.Children = new Drawable[]
{
notificationOverlay = new NotificationOverlay
{ {
Anchor = Anchor.TopRight, Anchor = Anchor.TopRight,
Origin = Anchor.TopRight Origin = Anchor.TopRight
},
displayedCount = new OsuSpriteText()
};
notificationOverlay.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count.NewValue}"; };
}); });
SpriteText displayedCount = new OsuSpriteText(); [Test]
public void TestBasicFlow()
Content.Add(displayedCount); {
void setState(Visibility state) => AddStep(state.ToString(), () => manager.State.Value = state);
void checkProgressingCount(int expected) => AddAssert($"progressing count is {expected}", () => progressingNotifications.Count == expected);
manager.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count.NewValue}"; };
setState(Visibility.Visible); setState(Visibility.Visible);
AddStep(@"simple #1", sendHelloNotification); AddStep(@"simple #1", sendHelloNotification);
AddStep(@"simple #2", sendAmazingNotification); AddStep(@"simple #2", sendAmazingNotification);
@ -61,6 +66,7 @@ namespace osu.Game.Tests.Visual.UserInterface
setState(Visibility.Hidden); setState(Visibility.Hidden);
AddRepeatStep(@"add many simple", sendManyNotifications, 3); AddRepeatStep(@"add many simple", sendManyNotifications, 3);
AddWaitStep("wait some", 5); AddWaitStep("wait some", 5);
checkProgressingCount(0); checkProgressingCount(0);
@ -69,18 +75,122 @@ namespace osu.Game.Tests.Visual.UserInterface
checkProgressingCount(1); checkProgressingCount(1);
AddAssert("Displayed count is 33", () => manager.UnreadCount.Value == 33); checkDisplayedCount(33);
AddWaitStep("wait some", 10); AddWaitStep("wait some", 10);
checkProgressingCount(0); checkProgressingCount(0);
setState(Visibility.Visible);
//AddStep(@"barrage", () => sendBarrage());
} }
private void sendBarrage(int remaining = 10) [Test]
public void TestImportantWhileClosed()
{
AddStep(@"simple #1", sendHelloNotification);
AddAssert("Is visible", () => notificationOverlay.State.Value == Visibility.Visible);
checkDisplayedCount(1);
AddStep(@"progress #1", sendUploadProgress);
AddStep(@"progress #2", sendDownloadProgress);
checkProgressingCount(2);
checkDisplayedCount(3);
}
[Test]
public void TestUnimportantWhileClosed()
{
AddStep(@"background #1", sendBackgroundNotification);
AddAssert("Is not visible", () => notificationOverlay.State.Value == Visibility.Hidden);
checkDisplayedCount(1);
AddStep(@"background progress #1", sendBackgroundUploadProgress);
AddWaitStep("wait some", 5);
checkProgressingCount(0);
checkDisplayedCount(2);
AddStep(@"simple #1", sendHelloNotification);
checkDisplayedCount(3);
}
[Test]
public void TestSpam()
{
setState(Visibility.Visible);
AddRepeatStep("send barrage", sendBarrage, 10);
}
protected override void Update()
{
base.Update();
progressingNotifications.RemoveAll(n => n.State == ProgressNotificationState.Completed);
if (progressingNotifications.Count(n => n.State == ProgressNotificationState.Active) < 3)
{
var p = progressingNotifications.Find(n => n.State == ProgressNotificationState.Queued);
if (p != null)
p.State = ProgressNotificationState.Active;
}
foreach (var n in progressingNotifications.FindAll(n => n.State == ProgressNotificationState.Active))
{
if (n.Progress < 1)
n.Progress += (float)(Time.Elapsed / 400) * RNG.NextSingle();
else
n.State = ProgressNotificationState.Completed;
}
}
private void checkDisplayedCount(int expected) =>
AddAssert($"Displayed count is {expected}", () => notificationOverlay.UnreadCount.Value == expected);
private void sendDownloadProgress()
{
var n = new ProgressNotification
{
Text = @"Downloading Haitai...",
CompletionText = "Downloaded Haitai!",
};
notificationOverlay.Post(n);
progressingNotifications.Add(n);
}
private void sendUploadProgress()
{
var n = new ProgressNotification
{
Text = @"Uploading to BSS...",
CompletionText = "Uploaded to BSS!",
};
notificationOverlay.Post(n);
progressingNotifications.Add(n);
}
private void sendBackgroundUploadProgress()
{
var n = new BackgroundProgressNotification
{
Text = @"Uploading to BSS...",
CompletionText = "Uploaded to BSS!",
};
notificationOverlay.Post(n);
progressingNotifications.Add(n);
}
private void setState(Visibility state) => AddStep(state.ToString(), () => notificationOverlay.State.Value = state);
private void checkProgressingCount(int expected) => AddAssert($"progressing count is {expected}", () => progressingNotifications.Count == expected);
private void sendBarrage()
{ {
switch (RNG.Next(0, 4)) switch (RNG.Next(0, 4))
{ {
@ -100,69 +210,37 @@ namespace osu.Game.Tests.Visual.UserInterface
sendDownloadProgress(); sendDownloadProgress();
break; break;
} }
if (remaining > 0)
Scheduler.AddDelayed(() => sendBarrage(remaining - 1), 80);
}
protected override void Update()
{
base.Update();
progressingNotifications.RemoveAll(n => n.State == ProgressNotificationState.Completed);
if (progressingNotifications.Count(n => n.State == ProgressNotificationState.Active) < 3)
{
var p = progressingNotifications.Find(n => n.State == ProgressNotificationState.Queued);
if (p != null)
p.State = ProgressNotificationState.Active;
}
foreach (var n in progressingNotifications.FindAll(n => n.State == ProgressNotificationState.Active))
{
if (n.Progress < 1)
n.Progress += (float)(Time.Elapsed / 400) * RNG.NextSingle();
else
n.State = ProgressNotificationState.Completed;
}
}
private void sendDownloadProgress()
{
var n = new ProgressNotification
{
Text = @"Downloading Haitai...",
CompletionText = "Downloaded Haitai!",
};
manager.Post(n);
progressingNotifications.Add(n);
}
private void sendUploadProgress()
{
var n = new ProgressNotification
{
Text = @"Uploading to BSS...",
CompletionText = "Uploaded to BSS!",
};
manager.Post(n);
progressingNotifications.Add(n);
} }
private void sendAmazingNotification() private void sendAmazingNotification()
{ {
manager.Post(new SimpleNotification { Text = @"You are amazing" }); notificationOverlay.Post(new SimpleNotification { Text = @"You are amazing" });
} }
private void sendHelloNotification() private void sendHelloNotification()
{ {
manager.Post(new SimpleNotification { Text = @"Welcome to osu!. Enjoy your stay!" }); notificationOverlay.Post(new SimpleNotification { Text = @"Welcome to osu!. Enjoy your stay!" });
}
private void sendBackgroundNotification()
{
notificationOverlay.Post(new BackgroundNotification { Text = @"Welcome to osu!. Enjoy your stay!" });
} }
private void sendManyNotifications() private void sendManyNotifications()
{ {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
manager.Post(new SimpleNotification { Text = @"Spam incoming!!" }); notificationOverlay.Post(new SimpleNotification { Text = @"Spam incoming!!" });
}
private class BackgroundNotification : SimpleNotification
{
public override bool IsImportant => false;
}
private class BackgroundProgressNotification : ProgressNotification
{
public override bool IsImportant => false;
} }
} }
} }

View File

@ -35,8 +35,6 @@ namespace osu.Game.Overlays
Width = width; Width = width;
RelativeSizeAxes = Axes.Y; RelativeSizeAxes = Axes.Y;
AlwaysPresent = true;
Children = new Drawable[] Children = new Drawable[]
{ {
new Box new Box
@ -100,9 +98,6 @@ namespace osu.Game.Overlays
OverlayActivationMode.BindValueChanged(_ => updateProcessingMode(), true); OverlayActivationMode.BindValueChanged(_ => updateProcessingMode(), true);
} }
private int totalCount => sections.Select(c => c.DisplayedCount).Sum();
private int unreadCount => sections.Select(c => c.UnreadCount).Sum();
public readonly BindableInt UnreadCount = new BindableInt(); public readonly BindableInt UnreadCount = new BindableInt();
private int runningDepth; private int runningDepth;
@ -111,6 +106,8 @@ namespace osu.Game.Overlays
private readonly Scheduler postScheduler = new Scheduler(); private readonly Scheduler postScheduler = new Scheduler();
public override bool IsPresent => base.IsPresent || postScheduler.HasPendingTasks;
private bool processingPosts = true; private bool processingPosts = true;
public void Post(Notification notification) => postScheduler.Add(() => public void Post(Notification notification) => postScheduler.Add(() =>
@ -160,7 +157,7 @@ namespace osu.Game.Overlays
private void updateCounts() private void updateCounts()
{ {
UnreadCount.Value = unreadCount; UnreadCount.Value = sections.Select(c => c.UnreadCount).Sum();
} }
private void markAllRead() private void markAllRead()

View File

@ -23,10 +23,16 @@ namespace osu.Game.Overlays.Notifications
public string CompletionText { get; set; } = "Task has completed!"; public string CompletionText { get; set; } = "Task has completed!";
private float progress;
public float Progress public float Progress
{ {
get => progressBar.Progress; get => progress;
set => Schedule(() => progressBar.Progress = value); set
{
progress = value;
Scheduler.AddOnce(() => progressBar.Progress = progress);
}
} }
protected override void LoadComplete() protected override void LoadComplete()
@ -34,23 +40,28 @@ namespace osu.Game.Overlays.Notifications
base.LoadComplete(); base.LoadComplete();
//we may have received changes before we were displayed. //we may have received changes before we were displayed.
State = state; updateState();
} }
private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
public CancellationToken CancellationToken => cancellationTokenSource.Token; public CancellationToken CancellationToken => cancellationTokenSource.Token;
public virtual ProgressNotificationState State public ProgressNotificationState State
{ {
get => state; get => state;
set => set
Schedule(() =>
{ {
bool stateChanged = state != value; if (state == value) return;
state = value; state = value;
if (IsLoaded) if (IsLoaded)
Schedule(updateState);
}
}
private void updateState()
{ {
switch (state) switch (state)
{ {
@ -73,21 +84,13 @@ namespace osu.Game.Overlays.Notifications
Light.Pulsate = false; Light.Pulsate = false;
progressBar.Active = false; progressBar.Active = false;
break; break;
}
}
if (stateChanged)
{
switch (state)
{
case ProgressNotificationState.Completed: case ProgressNotificationState.Completed:
NotificationContent.MoveToY(-DrawSize.Y / 2, 200, Easing.OutQuint); NotificationContent.MoveToY(-DrawSize.Y / 2, 200, Easing.OutQuint);
this.FadeOut(200).Finally(d => Completed()); this.FadeOut(200).Finally(d => Completed());
break; break;
} }
} }
});
}
private ProgressNotificationState state; private ProgressNotificationState state;