mirror of
https://github.com/ppy/osu.git
synced 2026-05-19 07:51:17 +08:00
Merge pull request #34419 from bdach/online-status-stuff
Update beatmap online statuses when the set is selected in song select
This commit is contained in:
@@ -43,6 +43,9 @@ namespace osu.Game.Tests.Visual.SongSelectV2
|
||||
|
||||
private APIBeatmapSet? currentOnlineSet;
|
||||
|
||||
[Cached]
|
||||
private RealmPopulatingOnlineLookupSource lookupSource = new RealmPopulatingOnlineLookupSource();
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(RulesetStore rulesets)
|
||||
{
|
||||
@@ -55,6 +58,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2
|
||||
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
lookupSource,
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
|
||||
@@ -8,18 +8,19 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
using osu.Game.Rulesets;
|
||||
@@ -69,10 +70,14 @@ namespace osu.Game.Screens.SelectV2
|
||||
private LocalisationManager localisation { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; } = null!;
|
||||
private RealmPopulatingOnlineLookupSource onlineLookupSource { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private RealmAccess realm { get; set; } = null!;
|
||||
|
||||
private APIBeatmapSet? currentOnlineBeatmapSet;
|
||||
private GetBeatmapSetRequest? currentRequest;
|
||||
private CancellationTokenSource? cancellationTokenSource;
|
||||
private Task<APIBeatmapSet?>? currentFetchTask;
|
||||
|
||||
private FillFlowContainer statisticsFlow = null!;
|
||||
|
||||
@@ -288,28 +293,27 @@ namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
var beatmapSetInfo = working.Value.BeatmapSetInfo;
|
||||
|
||||
currentRequest?.Cancel();
|
||||
currentRequest = null;
|
||||
cancellationTokenSource?.Cancel();
|
||||
currentOnlineBeatmapSet = null;
|
||||
|
||||
if (beatmapSetInfo.OnlineID >= 1)
|
||||
{
|
||||
// todo: consider introducing a BeatmapSetLookupCache for caching benefits.
|
||||
currentRequest = new GetBeatmapSetRequest(beatmapSetInfo.OnlineID);
|
||||
currentRequest.Failure += _ => updateOnlineDisplay();
|
||||
currentRequest.Success += s =>
|
||||
cancellationTokenSource = new CancellationTokenSource();
|
||||
currentFetchTask = onlineLookupSource.GetBeatmapSetAsync(beatmapSetInfo.OnlineID);
|
||||
currentFetchTask.ContinueWith(t =>
|
||||
{
|
||||
currentOnlineBeatmapSet = s;
|
||||
updateOnlineDisplay();
|
||||
};
|
||||
|
||||
api.Queue(currentRequest);
|
||||
if (t.IsCompletedSuccessfully)
|
||||
currentOnlineBeatmapSet = t.GetResultSafely();
|
||||
if (t.Exception != null)
|
||||
Logger.Log($"Error when fetching online beatmap set: {t.Exception}", LoggingTarget.Network);
|
||||
Scheduler.AddOnce(updateOnlineDisplay);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updateOnlineDisplay()
|
||||
{
|
||||
if (currentRequest?.CompletionState == APIRequestCompletionState.Waiting)
|
||||
if (currentFetchTask?.IsCompleted == false)
|
||||
{
|
||||
playCount.Value = null;
|
||||
favouriteButton.SetLoading();
|
||||
@@ -319,6 +323,20 @@ namespace osu.Game.Screens.SelectV2
|
||||
var onlineBeatmap = currentOnlineBeatmapSet?.Beatmaps.SingleOrDefault(b => b.OnlineID == working.Value.BeatmapInfo.OnlineID);
|
||||
playCount.Value = new StatisticPlayCount.Data(onlineBeatmap?.PlayCount ?? -1, onlineBeatmap?.UserPlayCount ?? -1);
|
||||
favouriteButton.SetBeatmapSet(currentOnlineBeatmapSet);
|
||||
|
||||
// the online fetch may have also updated the beatmap's status.
|
||||
// this needs to be checked against the *local* beatmap model rather than the online one, because it's not known here whether the status change has occurred or not
|
||||
// (think scenarios like the beatmap being locally modified).
|
||||
// it also has to be handled explicitly like this because the working beatmap's `BeatmapInfo` will not receive these updates due to being detached
|
||||
// (and because of https://github.com/ppy/osu/blob/4b73afd1957a9161e2956fc4191c8114d9958372/osu.Game/Screens/SelectV2/SongSelect.cs#L487-L488
|
||||
// which prevents working beatmap refetches caused by changes to the realm model of perceived low importance).
|
||||
var status = realm.Run(r =>
|
||||
{
|
||||
var refetchedBeatmap = r.Find<BeatmapInfo>(working.Value.BeatmapInfo.ID);
|
||||
return refetchedBeatmap?.Status;
|
||||
});
|
||||
if (status != null)
|
||||
statusPill.Status = status.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ using osu.Game.Extensions;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using Realms;
|
||||
|
||||
namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
@@ -25,6 +24,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
/// This component is designed to locally persist potentially-volatile online information such as:
|
||||
/// <list type="bullet">
|
||||
/// <item>user tags assigned to difficulties of a beatmap,</item>
|
||||
/// <item>the beatmap's <see cref="BeatmapInfo.Status"/>,</item>
|
||||
/// <item>guest mappers assigned to difficulties of a beatmap,</item>
|
||||
/// <item>the local user's best score on a given beatmap.</item>
|
||||
/// </list>
|
||||
@@ -54,20 +54,34 @@ namespace osu.Game.Screens.SelectV2
|
||||
var onlineBeatmaps = onlineBeatmapSet.Beatmaps.ToDictionary(b => b.OnlineID);
|
||||
realm.Write(r =>
|
||||
{
|
||||
foreach (var dbBeatmap in r.All<BeatmapInfo>().Filter($@"{nameof(BeatmapInfo.BeatmapSet)}.{nameof(BeatmapSetInfo.OnlineID)} == $0", id))
|
||||
var beatmapSet = r.All<BeatmapSetInfo>().Where(b => b.OnlineID == id);
|
||||
|
||||
foreach (var dbBeatmapSet in beatmapSet)
|
||||
{
|
||||
if (onlineBeatmaps.TryGetValue(dbBeatmap.OnlineID, out var onlineBeatmap))
|
||||
dbBeatmapSet.Status = onlineBeatmapSet.Status;
|
||||
|
||||
foreach (var dbBeatmap in dbBeatmapSet.Beatmaps)
|
||||
{
|
||||
string[] userTagsArray = onlineBeatmap.TopTags?
|
||||
.Select(t => (topTag: t, relatedTag: tagsById.GetValueOrDefault(t.TagId)))
|
||||
.Where(t => t.relatedTag != null)
|
||||
// see https://github.com/ppy/osu-web/blob/bb3bd2e7c6f84f26066df5ea20a81c77ec9bb60a/resources/js/beatmapsets-show/controller.ts#L103-L106 for sort criteria
|
||||
.OrderByDescending(t => t.topTag.VoteCount)
|
||||
.ThenBy(t => t.relatedTag!.Name)
|
||||
.Select(t => t.relatedTag!.Name)
|
||||
.ToArray() ?? [];
|
||||
dbBeatmap.Metadata.UserTags.Clear();
|
||||
dbBeatmap.Metadata.UserTags.AddRange(userTagsArray);
|
||||
if (onlineBeatmaps.TryGetValue(dbBeatmap.OnlineID, out var onlineBeatmap))
|
||||
{
|
||||
// compare `BeatmapUpdaterMetadataLookup`
|
||||
dbBeatmap.OnlineMD5Hash = onlineBeatmap.MD5Hash;
|
||||
dbBeatmap.LastOnlineUpdate = onlineBeatmap.LastUpdated;
|
||||
|
||||
if (dbBeatmap.MatchesOnlineVersion)
|
||||
dbBeatmap.Status = onlineBeatmap.Status;
|
||||
|
||||
string[] userTagsArray = onlineBeatmap.TopTags?
|
||||
.Select(t => (topTag: t, relatedTag: tagsById.GetValueOrDefault(t.TagId)))
|
||||
.Where(t => t.relatedTag != null)
|
||||
// see https://github.com/ppy/osu-web/blob/bb3bd2e7c6f84f26066df5ea20a81c77ec9bb60a/resources/js/beatmapsets-show/controller.ts#L103-L106 for sort criteria
|
||||
.OrderByDescending(t => t.topTag.VoteCount)
|
||||
.ThenBy(t => t.relatedTag!.Name)
|
||||
.Select(t => t.relatedTag!.Name)
|
||||
.ToArray() ?? [];
|
||||
dbBeatmap.Metadata.UserTags.Clear();
|
||||
dbBeatmap.Metadata.UserTags.AddRange(userTagsArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user