Use custom notification with timer

This commit is contained in:
Dan Balasescu 2022-09-20 15:51:56 +09:00
parent 92b2417d4c
commit 700000b583
3 changed files with 73 additions and 6 deletions

View File

@ -589,12 +589,7 @@ namespace osu.Game.Online.Multiplayer
if (countdown == null)
return;
PostNotification?.Invoke(new SimpleNotification
{
Text = countdown.FinalNotification
? $"The multiplayer server is restarting in {countdown.TimeRemaining:hh\\:mm\\:ss}. This multiplayer room will be closed shortly."
: $"The multiplayer server is restarting in {countdown.TimeRemaining:hh\\:mm\\:ss}."
});
PostNotification?.Invoke(new ServerShutdownNotification(countdown.TimeRemaining));
}
Task IMultiplayerClient.UserBeatmapAvailabilityChanged(int userId, BeatmapAvailability beatmapAvailability)

View File

@ -0,0 +1,49 @@
// 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.
using System;
using Humanizer.Localisation;
using osu.Framework.Allocation;
using osu.Game.Overlays.Notifications;
using osu.Game.Utils;
namespace osu.Game.Online.Multiplayer
{
public class ServerShutdownNotification : SimpleNotification
{
private readonly DateTimeOffset endDate;
public ServerShutdownNotification(TimeSpan duration)
{
endDate = DateTimeOffset.UtcNow + duration;
}
[BackgroundDependencyLoader]
private void load()
{
updateTime();
}
protected override void LoadComplete()
{
base.LoadComplete();
Scheduler.Add(updateTimeWithReschedule);
}
private void updateTimeWithReschedule()
{
updateTime();
// The remaining time on a countdown may be at a fractional portion between two seconds.
// We want to align certain audio/visual cues to the point at which integer seconds change.
// To do so, we schedule to the next whole second. Note that scheduler invocation isn't
// guaranteed to be accurate, so this may still occur slightly late, but even in such a case
// the next invocation will be roughly correct.
double timeToNextSecond = endDate.Subtract(DateTimeOffset.UtcNow).TotalMilliseconds % 1000;
Scheduler.AddDelayed(updateTimeWithReschedule, timeToNextSecond);
}
private void updateTime() => Text = $"The multiplayer server is restarting in {HumanizerUtils.Humanize(endDate.Subtract(DateTimeOffset.Now), precision: 2, minUnit: TimeUnit.Second)}.";
}
}

View File

@ -4,6 +4,7 @@
using System;
using System.Globalization;
using Humanizer;
using Humanizer.Localisation;
namespace osu.Game.Utils
{
@ -26,5 +27,27 @@ namespace osu.Game.Utils
return input.Humanize(culture: new CultureInfo("en-US"));
}
}
/// <summary>
/// Turns the current or provided timespan into a human readable sentence
/// </summary>
/// <param name="input">The date to be humanized</param>
/// <param name="precision">The maximum number of time units to return. Defaulted is 1 which means the largest unit is returned</param>
/// <param name="maxUnit">The maximum unit of time to output. The default value is <see cref="TimeUnit.Week"/>. The time units <see cref="TimeUnit.Month"/> and <see cref="TimeUnit.Year"/> will give approximations for time spans bigger 30 days by calculating with 365.2425 days a year and 30.4369 days a month.</param>
/// <param name="minUnit">The minimum unit of time to output.</param>
/// <param name="toWords">Uses words instead of numbers if true. E.g. one day.</param>
/// <returns>distance of time in words</returns>
public static string Humanize(TimeSpan input, int precision = 1, TimeUnit maxUnit = TimeUnit.Week, TimeUnit minUnit = TimeUnit.Millisecond, bool toWords = false)
{
// this works around https://github.com/xamarin/xamarin-android/issues/2012 and https://github.com/Humanizr/Humanizer/issues/690#issuecomment-368536282
try
{
return input.Humanize(precision: precision, maxUnit: maxUnit, minUnit: minUnit);
}
catch (ArgumentException)
{
return input.Humanize(culture: new CultureInfo("en-US"), precision: precision, maxUnit: maxUnit, minUnit: minUnit);
}
}
}
}