Merge pull request #16909 from peppy/startup-protocol-handling

Add handling of beatmap links on startup
This commit is contained in:
Bartłomiej Dach 2022-02-24 03:12:51 +01:00 committed by GitHub
commit f0681ccd09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 140 additions and 12 deletions

View File

@ -409,26 +409,26 @@ namespace osu.Game.Tests.Chat
Assert.AreEqual(result.Content, result.DisplayContent);
Assert.AreEqual(2, result.Links.Count);
Assert.AreEqual("osu://chan/#english", result.Links[0].Url);
Assert.AreEqual("osu://chan/#japanese", result.Links[1].Url);
Assert.AreEqual($"{OsuGameBase.OSU_PROTOCOL}chan/#english", result.Links[0].Url);
Assert.AreEqual($"{OsuGameBase.OSU_PROTOCOL}chan/#japanese", result.Links[1].Url);
}
[Test]
public void TestOsuProtocol()
{
Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a custom protocol osu://chan/#english." });
Message result = MessageFormatter.FormatMessage(new Message { Content = $"This is a custom protocol {OsuGameBase.OSU_PROTOCOL}chan/#english." });
Assert.AreEqual(result.Content, result.DisplayContent);
Assert.AreEqual(1, result.Links.Count);
Assert.AreEqual("osu://chan/#english", result.Links[0].Url);
Assert.AreEqual($"{OsuGameBase.OSU_PROTOCOL}chan/#english", result.Links[0].Url);
Assert.AreEqual(26, result.Links[0].Index);
Assert.AreEqual(19, result.Links[0].Length);
result = MessageFormatter.FormatMessage(new Message { Content = "This is a [custom protocol](osu://chan/#english)." });
result = MessageFormatter.FormatMessage(new Message { Content = $"This is a [custom protocol]({OsuGameBase.OSU_PROTOCOL}chan/#english)." });
Assert.AreEqual("This is a custom protocol.", result.DisplayContent);
Assert.AreEqual(1, result.Links.Count);
Assert.AreEqual("osu://chan/#english", result.Links[0].Url);
Assert.AreEqual($"{OsuGameBase.OSU_PROTOCOL}chan/#english", result.Links[0].Url);
Assert.AreEqual("#english", result.Links[0].Argument);
Assert.AreEqual(10, result.Links[0].Index);
Assert.AreEqual(15, result.Links[0].Length);

View File

@ -0,0 +1,54 @@
// 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 System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.BeatmapSet;
namespace osu.Game.Tests.Visual.Navigation
{
public class TestSceneStartupBeatmapDisplay : OsuGameTestScene
{
private const int requested_beatmap_id = 75;
private const int requested_beatmap_set_id = 1;
protected override TestOsuGame CreateTestGame() => new TestOsuGame(LocalStorage, API, new[] { $"osu://b/{requested_beatmap_id}" });
[SetUp]
public void Setup() => Schedule(() =>
{
((DummyAPIAccess)API).HandleRequest = request =>
{
switch (request)
{
case GetBeatmapSetRequest gbr:
var apiBeatmapSet = CreateAPIBeatmapSet();
apiBeatmapSet.OnlineID = requested_beatmap_set_id;
apiBeatmapSet.Beatmaps = apiBeatmapSet.Beatmaps.Append(new APIBeatmap
{
DifficultyName = "Target difficulty",
OnlineID = requested_beatmap_id,
}).ToArray();
gbr.TriggerSuccess(apiBeatmapSet);
return true;
}
return false;
};
});
[Test]
public void TestBeatmapLink()
{
AddUntilStep("Beatmap overlay displayed", () => Game.ChildrenOfType<BeatmapSetOverlay>().FirstOrDefault()?.State.Value == Visibility.Visible);
AddUntilStep("Beatmap overlay showing content", () => Game.ChildrenOfType<BeatmapPicker>().FirstOrDefault()?.Beatmap.Value.OnlineID == requested_beatmap_id);
}
}
}

View File

@ -0,0 +1,52 @@
// 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 System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
namespace osu.Game.Tests.Visual.Navigation
{
public class TestSceneStartupBeatmapSetDisplay : OsuGameTestScene
{
private const int requested_beatmap_set_id = 1;
protected override TestOsuGame CreateTestGame() => new TestOsuGame(LocalStorage, API, new[] { $"osu://s/{requested_beatmap_set_id}" });
[SetUp]
public void Setup() => Schedule(() =>
{
((DummyAPIAccess)API).HandleRequest = request =>
{
switch (request)
{
case GetBeatmapSetRequest gbr:
var apiBeatmapSet = CreateAPIBeatmapSet();
apiBeatmapSet.OnlineID = requested_beatmap_set_id;
apiBeatmapSet.Beatmaps = apiBeatmapSet.Beatmaps.Append(new APIBeatmap
{
DifficultyName = "Target difficulty",
OnlineID = 75,
}).ToArray();
gbr.TriggerSuccess(apiBeatmapSet);
return true;
}
return false;
};
});
[Test]
public void TestBeatmapSetLink()
{
AddUntilStep("Beatmap overlay displayed", () => Game.ChildrenOfType<BeatmapSetOverlay>().FirstOrDefault()?.State.Value == Visibility.Visible);
AddUntilStep("Beatmap overlay showing content", () => Game.ChildrenOfType<BeatmapSetOverlay>().FirstOrDefault()?.Header.BeatmapSet.Value.OnlineID == requested_beatmap_set_id);
}
}
}

View File

@ -87,8 +87,8 @@ namespace osu.Game.Tests.Visual.Online
addMessageWithChecks("likes to post this [https://dev.ppy.sh/home link].", 1, true, true, expectedActions: LinkAction.External);
addMessageWithChecks("Join my multiplayer game osump://12346.", 1, expectedActions: LinkAction.JoinMultiplayerMatch);
addMessageWithChecks("Join my [multiplayer game](osump://12346).", 1, expectedActions: LinkAction.JoinMultiplayerMatch);
addMessageWithChecks("Join my [#english](osu://chan/#english).", 1, expectedActions: LinkAction.OpenChannel);
addMessageWithChecks("Join my osu://chan/#english.", 1, expectedActions: LinkAction.OpenChannel);
addMessageWithChecks($"Join my [#english]({OsuGameBase.OSU_PROTOCOL}chan/#english).", 1, expectedActions: LinkAction.OpenChannel);
addMessageWithChecks($"Join my {OsuGameBase.OSU_PROTOCOL}chan/#english.", 1, expectedActions: LinkAction.OpenChannel);
addMessageWithChecks("Join my #english or #japanese channels.", 2, expectedActions: new[] { LinkAction.OpenChannel, LinkAction.OpenChannel });
addMessageWithChecks("Join my #english or #nonexistent #hashtag channels.", 1, expectedActions: LinkAction.OpenChannel);

View File

@ -268,10 +268,10 @@ namespace osu.Game.Online.Chat
handleAdvanced(advanced_link_regex, result, startIndex);
// handle editor times
handleMatches(time_regex, "{0}", "osu://edit/{0}", result, startIndex, LinkAction.OpenEditorTimestamp);
handleMatches(time_regex, "{0}", $@"{OsuGameBase.OSU_PROTOCOL}edit/{{0}}", result, startIndex, LinkAction.OpenEditorTimestamp);
// handle channels
handleMatches(channel_regex, "{0}", "osu://chan/{0}", result, startIndex, LinkAction.OpenChannel);
handleMatches(channel_regex, "{0}", $@"{OsuGameBase.OSU_PROTOCOL}chan/{{0}}", result, startIndex, LinkAction.OpenChannel);
string empty = "";
while (space-- > 0)

View File

@ -150,6 +150,7 @@ namespace osu.Game
protected SettingsOverlay Settings;
private VolumeOverlay volume;
private OsuLogo osuLogo;
private MainMenu menuScreen;
@ -898,8 +899,20 @@ namespace osu.Game
if (args?.Length > 0)
{
string[] paths = args.Where(a => !a.StartsWith('-')).ToArray();
if (paths.Length > 0)
Task.Run(() => Import(paths));
{
string firstPath = paths.First();
if (firstPath.StartsWith(OSU_PROTOCOL, StringComparison.Ordinal))
{
HandleLink(firstPath);
}
else
{
Task.Run(() => Import(paths));
}
}
}
}

View File

@ -52,6 +52,8 @@ namespace osu.Game
/// </summary>
public partial class OsuGameBase : Framework.Game, ICanAcceptFiles
{
public const string OSU_PROTOCOL = "osu://";
public const string CLIENT_STREAM_NAME = @"lazer";
public const int SAMPLE_CONCURRENCY = 6;

View File

@ -183,7 +183,14 @@ namespace osu.Game.Overlays.BeatmapSet
}
starRatingContainer.FadeOut(100);
Beatmap.Value = Difficulties.FirstOrDefault()?.Beatmap;
// If a selection is already made, try and maintain it.
if (Beatmap.Value != null)
Beatmap.Value = Difficulties.FirstOrDefault(b => b.Beatmap.OnlineID == Beatmap.Value.OnlineID)?.Beatmap;
// Else just choose the first available difficulty for now.
Beatmap.Value ??= Difficulties.FirstOrDefault()?.Beatmap;
plays.Value = BeatmapSet?.PlayCount ?? 0;
favourites.Value = BeatmapSet?.FavouriteCount ?? 0;