This PR refactors the report popover to have an optional confirmation
message after completing the request. This was initially meant for
#32584, but then I realized I can first test it out on the user
profiles, so I've implemented it here as well. Can be reviewed commit by
commit.
https://github.com/user-attachments/assets/cd59c560-c824-4a5e-bab6-5ecbf5125af1
---------
Co-authored-by: Dean Herbert <pe@ppy.sh>
This removes the disabled sound, but I think that's fine. If we want
that, it should be handled by `HoverClickSounds` (which I'm currently
intentionally not using because it can be a bit noisy).
Closes#36503.
See inline commentary. I don't really have any energy left to provide
anything else, other than maybe a demonstration of how this dies in
framework:
diff --git a/osu.Framework.Tests/Visual/UserInterface/TestSceneScreenStackUnbindOnExit.cs b/osu.Framework.Tests/Visual/UserInterface/TestSceneScreenStackUnbindOnExit.cs
new file mode 100644
index 000000000..c74ce6636
--- /dev/null
+++ b/osu.Framework.Tests/Visual/UserInterface/TestSceneScreenStackUnbindOnExit.cs
@@ -0,0 +1,59 @@
+// 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 NUnit.Framework;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics.UserInterface;
+using osu.Framework.Screens;
+
+namespace osu.Framework.Tests.Visual.UserInterface
+{
+ public partial class TestSceneScreenStackUnbindOnExit : FrameworkTestScene
+ {
+ [Cached]
+ private ScreenStack screenStack = new ScreenStack();
+
+ [Test]
+ public void TestScreenExitUnbindDoesNotInterruptLoadComplete()
+ {
+ AddStep("set up the scenario", () =>
+ {
+ Child = screenStack;
+ screenStack.Push(new Screen());
+ screenStack.Push(new BrokenScreen());
+ });
+ AddUntilStep("wait to get to target screen", () => screenStack.CurrentScreen, Is.InstanceOf<Screen>);
+ }
+
+ private partial class BrokenSlider : BasicSliderBar<float>
+ {
+ [Resolved]
+ private ScreenStack screenStack { get; set; } = null!;
+
+ protected override void LoadComplete()
+ {
+ // exiting the current screen provokes the behaviour of unbinding all bindables in the screen's subtree
+ screenStack.CurrentScreen.Exit();
+
+ // ...but the following calls should still take correct effect inside `SliderBar`
+ // (namely one consisting of propagating `{Min,Max}Value` into `currentNumberInstantaneous`)
+ // so that it doesn't have its internal invariants violated
+ CurrentNumber.MinValue = -10;
+ CurrentNumber.MaxValue = 10;
+
+ // this notably calls `Scheduler.AddOnce(updateValue)` inside, which will happen *in the imminent future, in the same frame as `LoadComplete()` here.
+ // if the above mutations of `{Min,Max}Value` don't correctly propagate inside the slider bar due to an overly eager unbind, this will cause a crash.
+ base.LoadComplete();
+ }
+ }
+
+ private partial class BrokenScreen : Screen
+ {
+ [BackgroundDependencyLoader]
+ private void load()
+ {
+ InternalChild = new BrokenSlider();
+ }
+ }
+ }
+}
I attempted to address what I perceive to be the root issue here which
is that `ScreenStack` is allowed to arbitrarily unbind bindables under
drawables which are by all means still in the scene graph. The attempt
consisted of scheduling the unbind until after children of the screen
stack, but that caused 150 game-side tests to fail, seemingly on
something relevant to bindable leases, so I give up.
The test scene doesn't exercise the custom sample playback, but I hope I
can be forgiven for this as setting up a custom editor beatmap just for
this to work is rather cumbersome.