mirror of
https://github.com/ppy/osu.git
synced 2024-11-15 02:08:21 +08:00
Add handling of expiration
This commit is contained in:
parent
f0614928b1
commit
057f86dd14
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -141,5 +142,64 @@ namespace osu.Game.Tests.Visual.Menus
|
|||||||
return !images.First().IsPresent && images.Last().IsPresent;
|
return !images.First().IsPresent && images.Last().IsPresent;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestExpiry()
|
||||||
|
{
|
||||||
|
AddStep("set multiple images, second expiring soon", () => onlineMenuBanner.Current.Value = new APIMenuContent
|
||||||
|
{
|
||||||
|
Images = new[]
|
||||||
|
{
|
||||||
|
new APIMenuImage
|
||||||
|
{
|
||||||
|
Image = @"https://assets.ppy.sh/main-menu/project-loved-2@2x.png",
|
||||||
|
Url = @"https://osu.ppy.sh/home/news/2023-12-21-project-loved-december-2023",
|
||||||
|
},
|
||||||
|
new APIMenuImage
|
||||||
|
{
|
||||||
|
Image = @"https://assets.ppy.sh/main-menu/wf2023-vote@2x.png",
|
||||||
|
Url = @"https://osu.ppy.sh/community/contests/189",
|
||||||
|
Expires = DateTimeOffset.Now.AddSeconds(2),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("wait for first image shown", () =>
|
||||||
|
{
|
||||||
|
var images = onlineMenuBanner.ChildrenOfType<OnlineMenuBanner.MenuImage>();
|
||||||
|
|
||||||
|
if (images.Count() != 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return images.First().IsPresent && !images.Last().IsPresent;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("wait for second image shown", () =>
|
||||||
|
{
|
||||||
|
var images = onlineMenuBanner.ChildrenOfType<OnlineMenuBanner.MenuImage>();
|
||||||
|
|
||||||
|
if (images.Count() != 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !images.First().IsPresent && images.Last().IsPresent;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("wait for expiry", () =>
|
||||||
|
{
|
||||||
|
return onlineMenuBanner
|
||||||
|
.ChildrenOfType<OnlineMenuBanner.MenuImage>()
|
||||||
|
.Any(i => !i.Image.IsCurrent);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("wait for first image shown", () =>
|
||||||
|
{
|
||||||
|
var images = onlineMenuBanner.ChildrenOfType<OnlineMenuBanner.MenuImage>();
|
||||||
|
|
||||||
|
if (images.Count() != 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return images.First().IsPresent && !images.Last().IsPresent;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,10 @@ namespace osu.Game.Online.API.Requests.Responses
|
|||||||
[JsonProperty(@"url")]
|
[JsonProperty(@"url")]
|
||||||
public string Url { get; init; } = string.Empty;
|
public string Url { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
public bool IsCurrent =>
|
||||||
|
(Begins == null || Begins < DateTimeOffset.UtcNow) &&
|
||||||
|
(Expires == null || Expires > DateTimeOffset.UtcNow);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The time at which this item should begin displaying. If <c>null</c>, will display immediately.
|
/// The time at which this item should begin displaying. If <c>null</c>, will display immediately.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -29,7 +29,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
|
|
||||||
private const float transition_duration = 500;
|
private const float transition_duration = 500;
|
||||||
|
|
||||||
private Container content = null!;
|
private Container<MenuImage> content = null!;
|
||||||
private CancellationTokenSource? cancellationTokenSource;
|
private CancellationTokenSource? cancellationTokenSource;
|
||||||
|
|
||||||
private int displayIndex = -1;
|
private int displayIndex = -1;
|
||||||
@ -43,7 +43,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
AutoSizeDuration = transition_duration;
|
AutoSizeDuration = transition_duration;
|
||||||
AutoSizeEasing = Easing.OutQuint;
|
AutoSizeEasing = Easing.OutQuint;
|
||||||
|
|
||||||
InternalChild = content = new Container
|
InternalChild = content = new Container<MenuImage>
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
@ -59,8 +59,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
Current.BindValueChanged(_ => loadNewImages(), true);
|
Current.BindValueChanged(loadNewImages, true);
|
||||||
|
|
||||||
checkForUpdates();
|
checkForUpdates();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,25 +85,24 @@ namespace osu.Game.Screens.Menu
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadNewImages()
|
/// <summary>
|
||||||
|
/// Takes <see cref="Current"/> and materialises and displays drawables for all valid images to be displayed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="images"></param>
|
||||||
|
private void loadNewImages(ValueChangedEvent<APIMenuContent> images)
|
||||||
{
|
{
|
||||||
nextDisplay?.Cancel();
|
nextDisplay?.Cancel();
|
||||||
|
|
||||||
cancellationTokenSource?.Cancel();
|
cancellationTokenSource?.Cancel();
|
||||||
cancellationTokenSource = null;
|
cancellationTokenSource = null;
|
||||||
|
|
||||||
var newContent = Current.Value;
|
|
||||||
|
|
||||||
// A better fade out would be nice, but the menu content changes *very* rarely
|
// A better fade out would be nice, but the menu content changes *very* rarely
|
||||||
// so let's keep things simple for now.
|
// so let's keep things simple for now.
|
||||||
content.Clear(true);
|
content.Clear(true);
|
||||||
|
|
||||||
if (newContent.Images.Length == 0)
|
LoadComponentsAsync(images.NewValue.Images.Select(i => new MenuImage(i)), loaded =>
|
||||||
return;
|
|
||||||
|
|
||||||
LoadComponentsAsync(newContent.Images.Select(i => new MenuImage(i)), loaded =>
|
|
||||||
{
|
{
|
||||||
if (!newContent.Equals(Current.Value))
|
if (!images.NewValue.Equals(Current.Value))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// start hidden
|
// start hidden
|
||||||
@ -127,20 +125,38 @@ namespace osu.Game.Screens.Menu
|
|||||||
|
|
||||||
if (!anyHovered)
|
if (!anyHovered)
|
||||||
{
|
{
|
||||||
bool previousShowing = displayIndex >= 0;
|
int previousIndex = displayIndex;
|
||||||
if (previousShowing)
|
|
||||||
content[displayIndex % content.Count].FadeOut(400, Easing.OutQuint);
|
|
||||||
|
|
||||||
displayIndex++;
|
if (displayIndex == -1)
|
||||||
|
displayIndex = 0;
|
||||||
|
|
||||||
using (BeginDelayedSequence(previousShowing ? 300 : 0))
|
// To handle expiration simply, arrange all images in best-next order.
|
||||||
content[displayIndex % content.Count].Show();
|
// Fade in the first valid one, then handle fading out the last if required.
|
||||||
|
var currentRotation = content
|
||||||
|
.Skip(displayIndex + 1)
|
||||||
|
.Concat(content.Take(displayIndex + 1));
|
||||||
|
|
||||||
|
foreach (var image in currentRotation)
|
||||||
|
{
|
||||||
|
if (!image.Image.IsCurrent) continue;
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(previousIndex >= 0 ? 300 : 0))
|
||||||
|
{
|
||||||
|
displayIndex = content.IndexOf(image);
|
||||||
|
|
||||||
|
if (displayIndex != previousIndex)
|
||||||
|
image.Show();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previousIndex >= 0 && previousIndex != displayIndex)
|
||||||
|
content[previousIndex].FadeOut(400, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (content.Count > 1)
|
// Re-scheduling this method will both handle rotation and re-checking for expiration dates.
|
||||||
{
|
nextDisplay = Scheduler.AddDelayed(showNext, DelayBetweenRotation);
|
||||||
nextDisplay = Scheduler.AddDelayed(showNext, DelayBetweenRotation);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[LongRunningLoad]
|
[LongRunningLoad]
|
||||||
|
Loading…
Reference in New Issue
Block a user