From 923acfbeaf5d49a643c047a90a1d0be1bf112316 Mon Sep 17 00:00:00 2001
From: Dean Herbert <pe@ppy.sh>
Date: Wed, 5 Sep 2018 10:23:23 +0900
Subject: [PATCH 1/2] Fix some web requests being run after disposal of their
 owner

---
 .../BeatmapSet/Scores/ScoresContainer.cs       |  2 +-
 .../Beatmaps/PaginatedBeatmapContainer.cs      | 17 +++++++++++------
 .../PaginatedMostPlayedBeatmapContainer.cs     | 18 +++++++++++++-----
 .../Profile/Sections/PaginatedContainer.cs     |  1 +
 .../Sections/Ranks/PaginatedScoreContainer.cs  | 16 +++++++++++-----
 .../Recent/PaginatedRecentActivityContainer.cs | 17 ++++++++++++-----
 osu.Game/Overlays/UserProfileOverlay.cs        | 15 +++++++--------
 7 files changed, 56 insertions(+), 30 deletions(-)

diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs
index 626de14c98..6cb85c778b 100644
--- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs
+++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs
@@ -62,7 +62,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
                 loading = true;
 
                 getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset);
-                getScoresRequest.Success += r => Scores = r.Scores;
+                getScoresRequest.Success += r => Schedule(() => Scores = r.Scores);
                 api.Queue(getScoresRequest);
             }
         }
diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs
index 0b06acd426..621f752b9c 100644
--- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs
@@ -14,8 +14,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
     public class PaginatedBeatmapContainer : PaginatedContainer
     {
         private const float panel_padding = 10f;
-
         private readonly BeatmapSetType type;
+        private GetUserBeatmapsRequest request;
 
         public PaginatedBeatmapContainer(BeatmapSetType type, Bindable<User> user, string header, string missing = "None... yet.")
             : base(user, header, missing)
@@ -31,9 +31,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
         {
             base.ShowMore();
 
-            var req = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
-
-            req.Success += sets =>
+            request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
+            request.Success += sets => Schedule(() =>
             {
                 ShowMoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0);
                 ShowMoreLoading.Hide();
@@ -52,9 +51,15 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
                     var panel = new DirectGridPanel(s.ToBeatmapSet(Rulesets));
                     ItemsContainer.Add(panel);
                 }
-            };
+            });
 
-            Api.Queue(req);
+            Api.Queue(request);
+        }
+
+        protected override void Dispose(bool isDisposing)
+        {
+            base.Dispose(isDisposing);
+            request?.Cancel();
         }
     }
 }
diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs
index 42784682be..ad886c363b 100644
--- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs
@@ -12,6 +12,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
 {
     public class PaginatedMostPlayedBeatmapContainer : PaginatedContainer
     {
+        private GetUserMostPlayedBeatmapsRequest request;
+
         public PaginatedMostPlayedBeatmapContainer(Bindable<User> user)
             :base(user, "Most Played Beatmaps", "No records. :(")
         {
@@ -24,9 +26,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
         {
             base.ShowMore();
 
-            var req = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
-
-            req.Success += beatmaps =>
+            request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
+            request.Success += beatmaps => Schedule(() =>
             {
                 ShowMoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0);
                 ShowMoreLoading.Hide();
@@ -43,9 +44,16 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
                 {
                     ItemsContainer.Add(new DrawableMostPlayedRow(beatmap.GetBeatmapInfo(Rulesets), beatmap.PlayCount));
                 }
-            };
+            });
 
-            Api.Queue(req);
+            Api.Queue(request);
+        }
+
+
+        protected override void Dispose(bool isDisposing)
+        {
+            base.Dispose(isDisposing);
+            request?.Cancel();
         }
     }
 }
diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs
index 6dbb9b9ba3..db93fcbc1b 100644
--- a/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/PaginatedContainer.cs
@@ -28,6 +28,7 @@ namespace osu.Game.Overlays.Profile.Sections
         protected readonly Bindable<User> User = new Bindable<User>();
 
         protected APIAccess Api;
+        protected APIRequest RetrievalRequest;
         protected RulesetStore Rulesets;
 
         public PaginatedContainer(Bindable<User> user, string header, string missing)
diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs
index 707de0a10f..ed82c62e5c 100644
--- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs
@@ -16,6 +16,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
     {
         private readonly bool includeWeight;
         private readonly ScoreType type;
+        private GetUserScoresRequest request;
 
         public PaginatedScoreContainer(ScoreType type, Bindable<User> user, string header, string missing, bool includeWeight = false)
             : base(user, header, missing)
@@ -32,9 +33,8 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
         {
             base.ShowMore();
 
-            var req = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
-
-            req.Success += scores =>
+            request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
+            request.Success += scores => Schedule(() =>
             {
                 foreach (var s in scores)
                     s.ApplyRuleset(Rulesets.GetRuleset(s.OnlineRulesetID));
@@ -66,9 +66,15 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
 
                     ItemsContainer.Add(drawableScore);
                 }
-            };
+            });
 
-            Api.Queue(req);
+            Api.Queue(request);
+        }
+
+        protected override void Dispose(bool isDisposing)
+        {
+            base.Dispose(isDisposing);
+            request?.Cancel();
         }
     }
 }
diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs
index ee2f2f5973..fd5eda4e44 100644
--- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs
@@ -12,6 +12,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
 {
     public class PaginatedRecentActivityContainer : PaginatedContainer
     {
+        private GetUserRecentActivitiesRequest request;
+
         public PaginatedRecentActivityContainer(Bindable<User> user, string header, string missing)
             : base(user, header, missing)
         {
@@ -22,9 +24,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
         {
             base.ShowMore();
 
-            var req = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
-
-            req.Success += activities =>
+            request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
+            request.Success += activities => Schedule(() =>
             {
                 ShowMoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0);
                 ShowMoreLoading.Hide();
@@ -41,9 +42,15 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
                 {
                     ItemsContainer.Add(new DrawableRecentActivity(activity));
                 }
-            };
+            });
 
-            Api.Queue(req);
+            Api.Queue(request);
+        }
+
+        protected override void Dispose(bool isDisposing)
+        {
+            base.Dispose(isDisposing);
+            request?.Cancel();
         }
     }
 }
diff --git a/osu.Game/Overlays/UserProfileOverlay.cs b/osu.Game/Overlays/UserProfileOverlay.cs
index 11b68b0e09..ea077ff645 100644
--- a/osu.Game/Overlays/UserProfileOverlay.cs
+++ b/osu.Game/Overlays/UserProfileOverlay.cs
@@ -73,16 +73,15 @@ namespace osu.Game.Overlays
             FadeEdgeEffectTo(0, WaveContainer.DISAPPEAR_DURATION, Easing.Out);
         }
 
-        public void ShowUser(long userId)
-        {
-            if (userId == Header.User.Id)
-                return;
-
-            ShowUser(new User { Id = userId });
-        }
+        public void ShowUser(long userId) => ShowUser(new User { Id = userId });
 
         public void ShowUser(User user, bool fetchOnline = true)
         {
+            Show();
+
+            if (user.Id == Header?.User.Id)
+                return;
+
             userReq?.Cancel();
             Clear();
             lastSection = null;
@@ -97,6 +96,7 @@ namespace osu.Game.Overlays
                 new BeatmapsSection(),
                 new KudosuSection()
             };
+
             tabs = new ProfileTabControl
             {
                 RelativeSizeAxes = Axes.X,
@@ -161,7 +161,6 @@ namespace osu.Game.Overlays
                 userLoadComplete(user);
             }
 
-            Show();
             sectionsContainer.ScrollToTop();
         }
 

From ccd7c1a17d10e43d5467c99197d7f6d54ef01181 Mon Sep 17 00:00:00 2001
From: Dean Herbert <pe@ppy.sh>
Date: Thu, 6 Sep 2018 17:04:33 +0900
Subject: [PATCH 2/2] Cancel request on disposal for safety

---
 osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs
index 6cb85c778b..60811d8b12 100644
--- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs
+++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs
@@ -134,5 +134,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
             this.api = api;
             updateDisplay();
         }
+
+        protected override void Dispose(bool isDisposing)
+        {
+            getScoresRequest?.Cancel();
+        }
     }
 }