diff --git a/.idea/.idea.osu.Desktop/.idea/dataSources.xml b/.idea/.idea.osu.Desktop/.idea/dataSources.xml
deleted file mode 100644
index 10f8c1c84d..0000000000
--- a/.idea/.idea.osu.Desktop/.idea/dataSources.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
- sqlite.xerial
- true
- org.sqlite.JDBC
- jdbc:sqlite:$USER_HOME$/.local/share/osu/client.db
-
-
-
-
-
-
\ No newline at end of file
diff --git a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs
index 07162c3cd1..b6ae91844a 100644
--- a/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs
+++ b/osu.Game.Tests/Visual/Editing/TestSceneEditorBeatmapCreation.cs
@@ -55,7 +55,12 @@ namespace osu.Game.Tests.Visual.Editing
[Test]
public void TestExitWithoutSave()
{
- AddStep("exit without save", () => Editor.Exit());
+ AddStep("exit without save", () =>
+ {
+ Editor.Exit();
+ DialogOverlay.CurrentDialog.PerformOkAction();
+ });
+
AddUntilStep("wait for exit", () => !Editor.IsCurrentScreen());
AddAssert("new beatmap not persisted", () => beatmapManager.QueryBeatmapSet(s => s.ID == EditorBeatmap.BeatmapInfo.BeatmapSet.ID)?.DeletePending == true);
}
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
index c5a6723508..599dfb082b 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
@@ -6,15 +6,20 @@ using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
+using osu.Framework.Graphics.Containers;
using osu.Framework.Platform;
using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
+using osu.Game.Graphics.UserInterface;
using osu.Game.Online.Multiplayer;
using osu.Game.Online.Rooms;
+using osu.Game.Overlays.Mods;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
+using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Screens.OnlinePlay.Components;
+using osu.Game.Screens.OnlinePlay.Match.Components;
using osu.Game.Screens.OnlinePlay.Multiplayer;
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
using osu.Game.Tests.Resources;
@@ -159,6 +164,50 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("play started", () => !multiplayerScreen.IsCurrentScreen());
}
+ [Test]
+ public void TestLeaveNavigation()
+ {
+ loadMultiplayer();
+
+ createRoom(() => new Room
+ {
+ Name = { Value = "Test Room" },
+ Playlist =
+ {
+ new PlaylistItem
+ {
+ Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.RulesetID == 0)).BeatmapInfo },
+ Ruleset = { Value = new OsuRuleset().RulesetInfo },
+ AllowedMods = { new OsuModHidden() }
+ }
+ }
+ });
+
+ AddStep("open mod overlay", () => this.ChildrenOfType().ElementAt(2).Click());
+
+ AddStep("invoke on back button", () => multiplayerScreen.OnBackButton());
+
+ AddAssert("mod overlay is hidden", () => this.ChildrenOfType().Single().State.Value == Visibility.Hidden);
+
+ AddAssert("dialog overlay is hidden", () => DialogOverlay.State.Value == Visibility.Hidden);
+
+ testLeave("lounge tab item", () => this.ChildrenOfType.BreadcrumbTabItem>().First().Click());
+
+ testLeave("back button", () => multiplayerScreen.OnBackButton());
+
+ // mimics home button and OS window close
+ testLeave("forced exit", () => multiplayerScreen.Exit());
+
+ void testLeave(string actionName, Action action)
+ {
+ AddStep($"leave via {actionName}", action);
+
+ AddAssert("dialog overlay is visible", () => DialogOverlay.State.Value == Visibility.Visible);
+
+ AddStep("close dialog overlay", () => InputManager.Key(Key.Escape));
+ }
+ }
+
private void createRoom(Func room)
{
AddStep("open room", () =>
diff --git a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs
index e85525b2f8..d7bd7d7e01 100644
--- a/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs
+++ b/osu.Game/Graphics/UserInterface/ScreenBreadcrumbControl.cs
@@ -3,6 +3,7 @@
using System.Linq;
using osu.Framework.Extensions.IEnumerableExtensions;
+using osu.Framework.Graphics.UserInterface;
using osu.Framework.Screens;
namespace osu.Game.Graphics.UserInterface
@@ -19,8 +20,13 @@ namespace osu.Game.Graphics.UserInterface
if (stack.CurrentScreen != null)
onPushed(null, stack.CurrentScreen);
+ }
- Current.ValueChanged += current => current.NewValue.MakeCurrent();
+ protected override void SelectTab(TabItem tab)
+ {
+ // override base method to prevent current item from being changed on click.
+ // depend on screen push/exit to change current item instead.
+ tab.Value.MakeCurrent();
}
private void onPushed(IScreen lastScreen, IScreen newScreen)
diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs
index 3a08ef684f..6195d8e1ea 100644
--- a/osu.Game/OsuGameBase.cs
+++ b/osu.Game/OsuGameBase.cs
@@ -258,7 +258,7 @@ namespace osu.Game
dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, API, contextFactory, Host, () => difficultyCache, LocalConfig));
dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, contextFactory, RulesetStore, API, Audio, Resources, Host, defaultBeatmap, true));
- // this should likely be moved to ArchiveModelManager when another case appers where it is necessary
+ // this should likely be moved to ArchiveModelManager when another case appears where it is necessary
// to have inter-dependent model managers. this could be obtained with an IHasForeign interface to
// allow lookups to be done on the child (ScoreManager in this case) to perform the cascading delete.
List getBeatmapScores(BeatmapSetInfo set)
diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs
index f9b3549f3c..4b8c4422ec 100644
--- a/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/Multiplayer/MultiplayerMatchSubScreen.cs
@@ -305,18 +305,34 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
return true;
}
+ return base.OnBackButton();
+ }
+
+ public override bool OnExiting(IScreen next)
+ {
+ if (client.Room == null)
+ {
+ // room has not been created yet; exit immediately.
+ return base.OnExiting(next);
+ }
+
if (!exitConfirmed && dialogOverlay != null)
{
- dialogOverlay.Push(new ConfirmDialog("Are you sure you want to leave this multiplayer match?", () =>
+ if (dialogOverlay.CurrentDialog is ConfirmDialog confirmDialog)
+ confirmDialog.PerformOkAction();
+ else
{
- exitConfirmed = true;
- this.Exit();
- }));
+ dialogOverlay.Push(new ConfirmDialog("Are you sure you want to leave this multiplayer match?", () =>
+ {
+ exitConfirmed = true;
+ this.Exit();
+ }));
+ }
return true;
}
- return base.OnBackButton();
+ return base.OnExiting(next);
}
private ModSettingChangeTracker modSettingChangeTracker;
diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs
index e418d36d40..ceee002c6e 100644
--- a/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/OnlinePlayScreen.cs
@@ -240,13 +240,15 @@ namespace osu.Game.Screens.OnlinePlay
public override bool OnExiting(IScreen next)
{
+ if (screenStack.CurrentScreen?.OnExiting(next) == true)
+ return true;
+
RoomManager.PartRoom();
waves.Hide();
this.Delay(WaveContainer.DISAPPEAR_DURATION).FadeOut();
- screenStack.CurrentScreen?.OnExiting(next);
base.OnExiting(next);
return false;
}
diff --git a/osu.Game/Tests/Visual/ScreenTestScene.cs b/osu.Game/Tests/Visual/ScreenTestScene.cs
index 33cc00e748..b30be05ac4 100644
--- a/osu.Game/Tests/Visual/ScreenTestScene.cs
+++ b/osu.Game/Tests/Visual/ScreenTestScene.cs
@@ -1,9 +1,11 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
+using osu.Game.Overlays;
using osu.Game.Screens;
namespace osu.Game.Tests.Visual
@@ -19,12 +21,16 @@ namespace osu.Game.Tests.Visual
protected override Container Content => content;
+ [Cached]
+ protected DialogOverlay DialogOverlay { get; private set; }
+
protected ScreenTestScene()
{
base.Content.AddRange(new Drawable[]
{
Stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both },
- content = new Container { RelativeSizeAxes = Axes.Both }
+ content = new Container { RelativeSizeAxes = Axes.Both },
+ DialogOverlay = new DialogOverlay()
});
}