From 0c2fc5c74f360855fcc65a81e36b95eda14da476 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Jun 2025 15:31:51 +0900 Subject: [PATCH] Debounce leaderboard load operations This avoids needless web requests / server load, but also improves the placeholder display. It used to update during ruleset changes three (or more) times since it had no debounce and was reacting to multiple changes. This is no longer the case. --- .../SelectV2/BeatmapLeaderboardWedge.cs | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/osu.Game/Screens/SelectV2/BeatmapLeaderboardWedge.cs b/osu.Game/Screens/SelectV2/BeatmapLeaderboardWedge.cs index ff70596b2f..3d2494ef45 100644 --- a/osu.Game/Screens/SelectV2/BeatmapLeaderboardWedge.cs +++ b/osu.Game/Screens/SelectV2/BeatmapLeaderboardWedge.cs @@ -14,6 +14,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; +using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -192,33 +193,40 @@ namespace osu.Game.Screens.SelectV2 private bool initialFetchComplete; + private ScheduledDelegate? refetchOperation; + private void refetchScores() { - SetScores(Array.Empty()); - - if (beatmap.IsDefault) + refetchOperation?.Cancel(); + refetchOperation = Scheduler.AddDelayed(() => { - SetState(LeaderboardState.NoneSelected); - return; - } + SetScores(Array.Empty()); - SetState(LeaderboardState.Retrieving); + if (beatmap.IsDefault) + { + SetState(LeaderboardState.NoneSelected); + return; + } - var fetchBeatmapInfo = beatmap.Value.BeatmapInfo; - var fetchRuleset = ruleset.Value ?? fetchBeatmapInfo.Ruleset; + SetState(LeaderboardState.Retrieving); - // For now, we forcefully refresh to keep things simple. - // In the future, removing this requirement may be deemed useful, but will need ample testing of edge case scenarios - // (like returning from gameplay after setting a new score, returning to song select after main menu). - leaderboardManager.FetchWithCriteria(new LeaderboardCriteria(fetchBeatmapInfo, fetchRuleset, Scope.Value, FilterBySelectedMods.Value ? mods.Value.ToArray() : null), forceRefresh: true); + var fetchBeatmapInfo = beatmap.Value.BeatmapInfo; + var fetchRuleset = ruleset.Value ?? fetchBeatmapInfo.Ruleset; - if (!initialFetchComplete) - { - // only bind this after the first fetch to avoid reading stale scores. - fetchedScores.BindTo(leaderboardManager.Scores); - fetchedScores.BindValueChanged(_ => updateScores(), true); - initialFetchComplete = true; - } + // For now, we forcefully refresh to keep things simple. + // In the future, removing this requirement may be deemed useful, but will need ample testing of edge case scenarios + // (like returning from gameplay after setting a new score, returning to song select after main menu). + leaderboardManager.FetchWithCriteria(new LeaderboardCriteria(fetchBeatmapInfo, fetchRuleset, Scope.Value, FilterBySelectedMods.Value ? mods.Value.ToArray() : null), + forceRefresh: true); + + if (!initialFetchComplete) + { + // only bind this after the first fetch to avoid reading stale scores. + fetchedScores.BindTo(leaderboardManager.Scores); + fetchedScores.BindValueChanged(_ => updateScores(), true); + initialFetchComplete = true; + } + }, initialFetchComplete ? 200 : 0); } private void updateScores()