From 5117c51105419a3d48774b86d4a04b893e0cc47f Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 19 Apr 2021 16:24:47 +0700 Subject: [PATCH 01/27] initial wiki header --- .../Visual/Online/TestSceneWikiHeader.cs | 25 +++++++++++++++ osu.Game/Overlays/Wiki/WikiHeader.cs | 31 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs create mode 100644 osu.Game/Overlays/Wiki/WikiHeader.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs new file mode 100644 index 0000000000..51d8abc516 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs @@ -0,0 +1,25 @@ +// 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.Game.Overlays; +using osu.Game.Overlays.Wiki; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneWikiHeader : OsuTestScene + { + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Orange); + + public TestSceneWikiHeader() + { + Child = new WikiHeader + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }; + } + } +} diff --git a/osu.Game/Overlays/Wiki/WikiHeader.cs b/osu.Game/Overlays/Wiki/WikiHeader.cs new file mode 100644 index 0000000000..91377c63da --- /dev/null +++ b/osu.Game/Overlays/Wiki/WikiHeader.cs @@ -0,0 +1,31 @@ +// 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.Graphics; + +namespace osu.Game.Overlays.Wiki +{ + public class WikiHeader : BreadcrumbControlOverlayHeader + { + private const string index_page_string = "index"; + + public WikiHeader() + { + TabControl.AddItem(index_page_string); + } + + protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/wiki"); + + protected override OverlayTitle CreateTitle() => new WikiHeaderTitle(); + + private class WikiHeaderTitle : OverlayTitle + { + public WikiHeaderTitle() + { + Title = "wiki"; + Description = "knowledge base"; + IconTexture = "Icons/Hexacons/wiki"; + } + } + } +} From 460d656a0e504ec85b2da9be90d4b89fbc050e15 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Wed, 21 Apr 2021 16:21:07 +0700 Subject: [PATCH 02/27] initial wiki overlay --- .../Visual/Online/TestSceneWikiOverlay.cs | 22 +++++++++++++++++++ osu.Game/Overlays/WikiOverlay.cs | 17 ++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs create mode 100644 osu.Game/Overlays/WikiOverlay.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs new file mode 100644 index 0000000000..737c97c0bd --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs @@ -0,0 +1,22 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Overlays; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneWikiOverlay : OsuTestScene + { + private WikiOverlay wiki; + + [SetUp] + public void SetUp() => Schedule(() => Child = wiki = new WikiOverlay()); + + [Test] + public void TestOverlay() + { + AddStep("Show", () => wiki.Show()); + } + } +} diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs new file mode 100644 index 0000000000..7105fbf953 --- /dev/null +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -0,0 +1,17 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Overlays.Wiki; + +namespace osu.Game.Overlays +{ + public class WikiOverlay : OnlineOverlay + { + public WikiOverlay() + : base(OverlayColourScheme.Orange, false) + { + } + + protected override WikiHeader CreateHeader() => new WikiHeader(); + } +} From f3555ad08cfdc71a61efeb88fde64104484bf8e5 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 20 Apr 2021 16:12:32 +0700 Subject: [PATCH 03/27] add APIWikiPage response --- .../API/Requests/Responses/APIWikiPage.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 osu.Game/Online/API/Requests/Responses/APIWikiPage.cs diff --git a/osu.Game/Online/API/Requests/Responses/APIWikiPage.cs b/osu.Game/Online/API/Requests/Responses/APIWikiPage.cs new file mode 100644 index 0000000000..957396b17a --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APIWikiPage.cs @@ -0,0 +1,32 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APIWikiPage + { + [JsonProperty("layout")] + public string Layout { get; set; } + + [JsonProperty("locale")] + public string Locale { get; set; } + + [JsonProperty("markdown")] + public string Markdown { get; set; } + + [JsonProperty("path")] + public string Path { get; set; } + + [JsonProperty("subtitle")] + public string Subtitle { get; set; } + + [JsonProperty("tags")] + public List Tags { get; set; } + + [JsonProperty("title")] + public string Title { get; set; } + } +} From d4013bd8852aaaa833004969037089477279cfd6 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 20 Apr 2021 16:40:30 +0700 Subject: [PATCH 04/27] add GetWikiRequest --- .../Online/API/Requests/GetWikiRequest.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 osu.Game/Online/API/Requests/GetWikiRequest.cs diff --git a/osu.Game/Online/API/Requests/GetWikiRequest.cs b/osu.Game/Online/API/Requests/GetWikiRequest.cs new file mode 100644 index 0000000000..248fcc03e3 --- /dev/null +++ b/osu.Game/Online/API/Requests/GetWikiRequest.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Online.API.Requests +{ + public class GetWikiRequest : APIRequest + { + private readonly string path; + private readonly string locale; + + public GetWikiRequest(string path, string locale = "en") + { + this.path = path; + this.locale = locale; + } + + protected override string Target => $"wiki/{locale}/{path}"; + } +} From f6a088e699854eb449047410e6ef6835ea79451a Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Wed, 19 May 2021 19:09:03 +0700 Subject: [PATCH 05/27] add request logic in wiki overlay --- osu.Game/Overlays/WikiOverlay.cs | 90 ++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index 7105fbf953..964daa3368 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -1,17 +1,107 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Threading; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Wiki; +using osu.Game.Overlays.Wiki.Markdown; namespace osu.Game.Overlays { public class WikiOverlay : OnlineOverlay { + private const string index_path = "Main_Page"; + + private readonly Bindable path = new Bindable(index_path); + + [Cached] + private readonly Bindable wikiData = new Bindable(); + + [Resolved] + private IAPIProvider api { get; set; } + + private GetWikiRequest request; + + private CancellationTokenSource cancellationToken; + + private bool displayUpdateRequired = true; + public WikiOverlay() : base(OverlayColourScheme.Orange, false) { } + private void onPathChanged(ValueChangedEvent e) + { + cancellationToken?.Cancel(); + request?.Cancel(); + + request = new GetWikiRequest(e.NewValue); + + Loading.Show(); + + request.Success += response => Schedule(() => onSuccess(response)); + + api.PerformAsync(request); + } + + private void onSuccess(APIWikiPage response) + { + wikiData.Value = response; + LoadDisplay(new WikiMarkdownContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + CurrentPath = $"{path.Value}/", + Text = response.Markdown, + }); + } + protected override WikiHeader CreateHeader() => new WikiHeader(); + + protected override void LoadComplete() + { + base.LoadComplete(); + path.BindValueChanged(onPathChanged); + } + + protected override void PopIn() + { + base.PopIn(); + + if (displayUpdateRequired) + { + path.TriggerChange(); + displayUpdateRequired = false; + } + } + + protected override void PopOutComplete() + { + base.PopOutComplete(); + displayUpdateRequired = true; + } + + protected void LoadDisplay(Drawable display) + { + ScrollFlow.ScrollToStart(); + LoadComponentAsync(display, loaded => + { + Child = loaded; + Loading.Hide(); + }, (cancellationToken = new CancellationTokenSource()).Token); + } + + protected override void Dispose(bool isDisposing) + { + cancellationToken?.Cancel(); + request?.Cancel(); + base.Dispose(isDisposing); + } } } From 416e08ae7af79700be96fdb5e1070cd0f5d6b9db Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Wed, 21 Apr 2021 17:25:13 +0700 Subject: [PATCH 06/27] add dummy response API in TestSceneWikiOverlay `TestSceneNewsOverlay` is used as example for this test. --- .../Visual/Online/TestSceneWikiOverlay.cs | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs index 737c97c0bd..371be8a003 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs @@ -2,21 +2,51 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; +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.Online { public class TestSceneWikiOverlay : OsuTestScene { + private DummyAPIAccess dummyAPI => (DummyAPIAccess)API; + private WikiOverlay wiki; [SetUp] public void SetUp() => Schedule(() => Child = wiki = new WikiOverlay()); [Test] - public void TestOverlay() + public void TestMainPage() { - AddStep("Show", () => wiki.Show()); + setUpNewsResponse(responseExample); + AddStep("Show Main Page", () => wiki.Show()); } + + private void setUpNewsResponse(APIWikiPage r) + => AddStep("set up response", () => + { + dummyAPI.HandleRequest = request => + { + if (!(request is GetWikiRequest getWikiRequest)) + return false; + + getWikiRequest.TriggerSuccess(r); + return true; + }; + }); + + // From https://osu.ppy.sh/api/v2/wiki/en/Main_Page + private APIWikiPage responseExample => new APIWikiPage + { + Title = "Main Page", + Layout = "main_page", + Path = "Main_Page", + Locale = "en", + Subtitle = null, + Markdown = "---\nlayout: main_page\n---\n\n\n\n
\nWelcome to the osu! wiki, a project containing a wide range of osu! related information.\n
\n\n
\n
\n\n# Getting started\n\n[Welcome](/wiki/Welcome) • [Installation](/wiki/Installation) • [Registration](/wiki/Registration) • [Help Centre](/wiki/Help_Centre) • [FAQ](/wiki/FAQ)\n\n
\n
\n\n# Game client\n\n[Interface](/wiki/Interface) • [Options](/wiki/Options) • [Visual settings](/wiki/Visual_Settings) • [Shortcut key reference](/wiki/Shortcut_key_reference) • [Configuration file](/wiki/osu!_Program_Files/User_Configuration_File) • [Program files](/wiki/osu!_Program_Files)\n\n[File formats](/wiki/osu!_File_Formats): [.osz](/wiki/osu!_File_Formats/Osz_(file_format)) • [.osk](/wiki/osu!_File_Formats/Osk_(file_format)) • [.osr](/wiki/osu!_File_Formats/Osr_(file_format)) • [.osu](/wiki/osu!_File_Formats/Osu_(file_format)) • [.osb](/wiki/osu!_File_Formats/Osb_(file_format)) • [.db](/wiki/osu!_File_Formats/Db_(file_format))\n\n
\n
\n\n# Gameplay\n\n[Game modes](/wiki/Game_mode): [osu!](/wiki/Game_mode/osu!) • [osu!taiko](/wiki/Game_mode/osu!taiko) • [osu!catch](/wiki/Game_mode/osu!catch) • [osu!mania](/wiki/Game_mode/osu!mania)\n\n[Beatmap](/wiki/Beatmap) • [Hit object](/wiki/Hit_object) • [Mods](/wiki/Game_modifier) • [Score](/wiki/Score) • [Replay](/wiki/Replay) • [Multi](/wiki/Multi)\n\n
\n
\n\n# [Beatmap editor](/wiki/Beatmap_Editor)\n\nSections: [Compose](/wiki/Beatmap_Editor/Compose) • [Design](/wiki/Beatmap_Editor/Design) • [Timing](/wiki/Beatmap_Editor/Timing) • [Song setup](/wiki/Beatmap_Editor/Song_Setup)\n\nComponents: [AiMod](/wiki/Beatmap_Editor/AiMod) • [Beat snap divisor](/wiki/Beatmap_Editor/Beat_Snap_Divisor) • [Distance snap](/wiki/Beatmap_Editor/Distance_Snap) • [Menu](/wiki/Beatmap_Editor/Menu) • [SB load](/wiki/Beatmap_Editor/SB_Load) • [Timelines](/wiki/Beatmap_Editor/Timelines)\n\n[Beatmapping](/wiki/Beatmapping) • [Difficulty](/wiki/Beatmap/Difficulty) • [Mapping techniques](/wiki/Mapping_Techniques) • [Storyboarding](/wiki/Storyboarding)\n\n
\n
\n\n# Beatmap submission and ranking\n\n[Submission](/wiki/Submission) • [Modding](/wiki/Modding) • [Ranking procedure](/wiki/Beatmap_ranking_procedure) • [Mappers' Guild](/wiki/Mappers_Guild) • [Project Loved](/wiki/Project_Loved)\n\n[Ranking criteria](/wiki/Ranking_Criteria): [osu!](/wiki/Ranking_Criteria/osu!) • [osu!taiko](/wiki/Ranking_Criteria/osu!taiko) • [osu!catch](/wiki/Ranking_Criteria/osu!catch) • [osu!mania](/wiki/Ranking_Criteria/osu!mania)\n\n
\n
\n\n# Community\n\n[Tournaments](/wiki/Tournaments) • [Skinning](/wiki/Skinning) • [Projects](/wiki/Projects) • [Guides](/wiki/Guides) • [osu!dev Discord server](/wiki/osu!dev_Discord_server) • [How you can help](/wiki/How_You_Can_Help!) • [Glossary](/wiki/Glossary)\n\n
\n
\n\n# People\n\n[The Team](/wiki/People/The_Team): [Developers](/wiki/People/The_Team/Developers) • [Global Moderation Team](/wiki/People/The_Team/Global_Moderation_Team) • [Support Team](/wiki/People/The_Team/Support_Team) • [Nomination Assessment Team](/wiki/People/The_Team/Nomination_Assessment_Team) • [Beatmap Nominators](/wiki/People/The_Team/Beatmap_Nominators) • [osu! Alumni](/wiki/People/The_Team/osu!_Alumni) • [Project Loved Team](/wiki/People/The_Team/Project_Loved_Team)\n\nOrganisations: [osu! UCI](/wiki/Organisations/osu!_UCI)\n\n[Community Contributors](/wiki/People/Community_Contributors) • [Users with unique titles](/wiki/People/Users_with_unique_titles)\n\n
\n
\n\n# For developers\n\n[API](/wiki/osu!api) • [Bot account](/wiki/Bot_account) • [Brand identity guidelines](/wiki/Brand_identity_guidelines)\n\n
\n
\n\n# About the wiki\n\n[Sitemap](/wiki/Sitemap) • [Contribution guide](/wiki/osu!_wiki_Contribution_Guide) • [Article styling criteria](/wiki/Article_Styling_Criteria) • [News styling criteria](/wiki/News_Styling_Criteria)\n\n
\n
\n", + }; } } From 25f2c582e7f6ab9d54fba269c26d656bef1dcb97 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 22 Apr 2021 16:15:20 +0700 Subject: [PATCH 07/27] add ToolbarWikiButton --- .../Overlays/Toolbar/ToolbarWikiButton.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs diff --git a/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs b/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs new file mode 100644 index 0000000000..a521219b4f --- /dev/null +++ b/osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs @@ -0,0 +1,19 @@ +// 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; + +namespace osu.Game.Overlays.Toolbar +{ + public class ToolbarWikiButton : ToolbarOverlayToggleButton + { + protected override Anchor TooltipAnchor => Anchor.TopRight; + + [BackgroundDependencyLoader(true)] + private void load(WikiOverlay wiki) + { + StateContainer = wiki; + } + } +} From 004cd7c8344162cae74380a12605b3d54a7b6a9a Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 22 Apr 2021 16:16:12 +0700 Subject: [PATCH 08/27] add wiki button in main toolbar --- osu.Game/OsuGame.cs | 5 ++++- osu.Game/Overlays/Toolbar/Toolbar.cs | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index b7946f1c2f..42a49aa65e 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -81,6 +81,8 @@ namespace osu.Game private BeatmapSetOverlay beatmapSetOverlay; + private WikiOverlay wikiOverlay; + private SkinEditorOverlay skinEditor; private Container overlayContent; @@ -719,6 +721,7 @@ namespace osu.Game var changelogOverlay = loadComponentSingleFile(new ChangelogOverlay(), overlayContent.Add, true); loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true); loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true); + loadComponentSingleFile(wikiOverlay = new WikiOverlay(), overlayContent.Add, true); loadComponentSingleFile(skinEditor = new SkinEditorOverlay(screenContainer), overlayContent.Add); loadComponentSingleFile(new LoginOverlay @@ -769,7 +772,7 @@ namespace osu.Game } // ensure only one of these overlays are open at once. - var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, news, dashboard, beatmapListing, changelogOverlay, rankingsOverlay }; + var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, news, dashboard, beatmapListing, changelogOverlay, rankingsOverlay, wikiOverlay }; foreach (var overlay in singleDisplayOverlays) { diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs index d049c2d3ec..3d88171ba7 100644 --- a/osu.Game/Overlays/Toolbar/Toolbar.cs +++ b/osu.Game/Overlays/Toolbar/Toolbar.cs @@ -92,6 +92,7 @@ namespace osu.Game.Overlays.Toolbar new ToolbarBeatmapListingButton(), new ToolbarChatButton(), new ToolbarSocialButton(), + new ToolbarWikiButton(), new ToolbarMusicButton(), //new ToolbarButton //{ From 463774d4f2621d7e5a42de0d4e9ed9612873f3de Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Wed, 19 May 2021 19:12:16 +0700 Subject: [PATCH 09/27] add ShowPage method in WikiOverlay --- osu.Game/Overlays/WikiOverlay.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index 964daa3368..1022c56f26 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -62,6 +62,12 @@ namespace osu.Game.Overlays }); } + public void ShowPage(string pagePath = index_path) + { + path.Value = pagePath.Trim('/'); + Show(); + } + protected override WikiHeader CreateHeader() => new WikiHeader(); protected override void LoadComplete() From f2de28814a3388c4d1544f4af4df13688a6b467c Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 17 May 2021 00:43:59 +0700 Subject: [PATCH 10/27] add and handle OpenWiki link action --- osu.Game/Online/Chat/MessageFormatter.cs | 6 +++++- osu.Game/OsuGame.cs | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index b80720a0aa..1041758b0c 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -167,6 +167,9 @@ namespace osu.Game.Online.Chat case "u": case "users": return new LinkDetails(LinkAction.OpenUserProfile, mainArg); + + case "wiki": + return new LinkDetails(LinkAction.OpenWiki, string.Join('/', args.Skip(3))); } } @@ -311,7 +314,8 @@ namespace osu.Game.Online.Chat JoinMultiplayerMatch, Spectate, OpenUserProfile, - Custom + OpenWiki, + Custom, } public class Link : IComparable diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 42a49aa65e..b3b0773eff 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -309,6 +309,10 @@ namespace osu.Game ShowUser(userId); break; + case LinkAction.OpenWiki: + ShowWiki(link.Argument); + break; + default: throw new NotImplementedException($"This {nameof(LinkAction)} ({link.Action.ToString()}) is missing an associated action."); } @@ -356,6 +360,12 @@ namespace osu.Game /// The beatmap to show. public void ShowBeatmap(int beatmapId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId)); + /// + /// Show a wiki's page as an overlay + /// + /// The wiki page to show + public void ShowWiki(string path) => waitForReady(() => wikiOverlay, _ => wikiOverlay.ShowPage(path)); + /// /// Present a beatmap at song select immediately. /// The user should have already requested this interactively. From bc1cad0963c4624ec3cd09acd3124ebc349c8e7a Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 20 May 2021 00:28:26 +0700 Subject: [PATCH 11/27] change header breadcrumb when page change --- osu.Game/Overlays/Wiki/WikiHeader.cs | 31 ++++++++++++++++++++++++++++ osu.Game/Overlays/WikiOverlay.cs | 1 + 2 files changed, 32 insertions(+) diff --git a/osu.Game/Overlays/Wiki/WikiHeader.cs b/osu.Game/Overlays/Wiki/WikiHeader.cs index 91377c63da..f5010d82b6 100644 --- a/osu.Game/Overlays/Wiki/WikiHeader.cs +++ b/osu.Game/Overlays/Wiki/WikiHeader.cs @@ -1,17 +1,48 @@ // 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.Bindables; using osu.Framework.Graphics; +using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Overlays.Wiki { public class WikiHeader : BreadcrumbControlOverlayHeader { private const string index_page_string = "index"; + private const string index_path = "Main_Page"; + + public Bindable WikiPageData = new Bindable(); public WikiHeader() { TabControl.AddItem(index_page_string); + Current.Value = index_page_string; + + WikiPageData.BindValueChanged(onWikiPageChange); + } + + private void onWikiPageChange(ValueChangedEvent e) + { + if (e.NewValue == null) + return; + + TabControl.Clear(); + Current.Value = null; + + TabControl.AddItem(index_page_string); + + if (e.NewValue.Path == index_path) + { + Current.Value = index_page_string; + return; + } + + if (e.NewValue.Subtitle != null) + TabControl.AddItem(e.NewValue.Subtitle); + + TabControl.AddItem(e.NewValue.Title); + Current.Value = e.NewValue.Title; } protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/wiki"); diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index 1022c56f26..366923a4f1 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -74,6 +74,7 @@ namespace osu.Game.Overlays { base.LoadComplete(); path.BindValueChanged(onPathChanged); + wikiData.BindTo(Header.WikiPageData); } protected override void PopIn() From 1578b0462d10a9c63d1f378f080c07fa27cf43a0 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 20 May 2021 13:58:17 +0700 Subject: [PATCH 12/27] add showParentPage method --- osu.Game/Overlays/WikiOverlay.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index 366923a4f1..1efa84d026 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Linq; using System.Threading; using osu.Framework.Allocation; using osu.Framework.Bindables; @@ -62,6 +63,12 @@ namespace osu.Game.Overlays }); } + private void showParentPage() + { + var parentPath = string.Join("/", path.Value.Split('/').SkipLast(1)); + ShowPage(parentPath); + } + public void ShowPage(string pagePath = index_path) { path.Value = pagePath.Trim('/'); From 9c824ece1b068c91d84cab4fe6508336090ce5c9 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 20 May 2021 14:00:22 +0700 Subject: [PATCH 13/27] handle page change when clicking breadcrumb --- osu.Game/Overlays/Wiki/WikiHeader.cs | 22 +++++++++++++++++++++- osu.Game/Overlays/WikiOverlay.cs | 6 +++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/Wiki/WikiHeader.cs b/osu.Game/Overlays/Wiki/WikiHeader.cs index f5010d82b6..6b8cba48b4 100644 --- a/osu.Game/Overlays/Wiki/WikiHeader.cs +++ b/osu.Game/Overlays/Wiki/WikiHeader.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; +using System.Linq; using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Online.API.Requests.Responses; @@ -12,7 +14,10 @@ namespace osu.Game.Overlays.Wiki private const string index_page_string = "index"; private const string index_path = "Main_Page"; - public Bindable WikiPageData = new Bindable(); + public readonly Bindable WikiPageData = new Bindable(); + + public Action ShowIndexPage; + public Action ShowParentPage; public WikiHeader() { @@ -20,6 +25,7 @@ namespace osu.Game.Overlays.Wiki Current.Value = index_page_string; WikiPageData.BindValueChanged(onWikiPageChange); + Current.BindValueChanged(onCurrentChange); } private void onWikiPageChange(ValueChangedEvent e) @@ -45,6 +51,20 @@ namespace osu.Game.Overlays.Wiki Current.Value = e.NewValue.Title; } + private void onCurrentChange(ValueChangedEvent e) + { + if (e.NewValue == TabControl.Items.LastOrDefault()) + return; + + if (e.NewValue == index_page_string) + { + ShowIndexPage?.Invoke(); + return; + } + + ShowParentPage?.Invoke(); + } + protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/wiki"); protected override OverlayTitle CreateTitle() => new WikiHeaderTitle(); diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index 1efa84d026..5505eeac68 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -75,7 +75,11 @@ namespace osu.Game.Overlays Show(); } - protected override WikiHeader CreateHeader() => new WikiHeader(); + protected override WikiHeader CreateHeader() => new WikiHeader + { + ShowIndexPage = () => ShowPage(), + ShowParentPage = showParentPage, + }; protected override void LoadComplete() { From 11099702780ab3f7366781aad49aa940eb7261d1 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 20 May 2021 14:24:28 +0700 Subject: [PATCH 14/27] add more test for Wiki Header --- .../Visual/Online/TestSceneWikiHeader.cs | 83 ++++++++++++++++++- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs index 51d8abc516..863fa48ddf 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs @@ -1,8 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; +using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Overlays.Wiki; @@ -13,13 +18,85 @@ namespace osu.Game.Tests.Visual.Online [Cached] private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Orange); - public TestSceneWikiHeader() + [Cached] + private readonly Bindable wikiPageData = new Bindable(new APIWikiPage { - Child = new WikiHeader + Title = "Main Page", + Path = "Main_Page", + }); + + private TestHeader header; + + [SetUp] + public void SetUp() => Schedule(() => + { + Child = header = new TestHeader { Anchor = Anchor.Centre, - Origin = Anchor.Centre + Origin = Anchor.Centre, + ShowIndexPage = dummyShowIndexPage, + ShowParentPage = dummyShowParentPage, }; + wikiPageData.BindTo(header.WikiPageData); + }); + + [Test] + public void TestWikiHeader() + { + AddAssert("Current is index", () => checkCurrent("index")); + + AddStep("Change wiki page data", () => wikiPageData.Value = new APIWikiPage + { + Title = "Welcome", + Path = "Welcome" + }); + AddAssert("Current is welcome", () => checkCurrent("Welcome")); + AddAssert("Check breadcrumb", checkBreadcrumb); + + AddStep("Change current to index", () => header.Current.Value = "index"); + AddAssert("Current is index", () => checkCurrent("index")); + + AddStep("Change wiki page data", () => wikiPageData.Value = new APIWikiPage + { + Title = "Developers", + Path = "People/The_Team/Developers", + Subtitle = "The Team", + }); + AddAssert("Current is 'Developers'", () => checkCurrent("Developers")); + AddAssert("Check breadcrumb", checkBreadcrumb); + + AddStep("Change current to 'The Team'", () => header.Current.Value = "The Team"); + AddAssert("Current is 'The Team'", () => checkCurrent("The Team")); + AddAssert("Check breadcrumb", checkBreadcrumb); + } + + private bool checkCurrent(string expectedCurrent) => header.Current.Value == expectedCurrent; + + private bool checkBreadcrumb() + { + var result = header.TabControlItems.Contains(wikiPageData.Value.Title); + + if (wikiPageData.Value.Subtitle != null) + result = header.TabControlItems.Contains(wikiPageData.Value.Subtitle) && result; + + return result; + } + + private void dummyShowIndexPage() => wikiPageData.SetDefault(); + + private void dummyShowParentPage() + { + wikiPageData.Value = new APIWikiPage + { + Path = "People/The_Team", + Title = "The Team", + Subtitle = "People" + }; + } + + private class TestHeader : WikiHeader + { + public IReadOnlyList TabControlItems => TabControl.Items; } } } From ae0949fc145d0f8aebb8424ec4ac99adf487c3a1 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 25 May 2021 14:20:04 +0700 Subject: [PATCH 15/27] add main page in wiki overlay --- osu.Game/Overlays/WikiOverlay.cs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index 5505eeac68..6e07de71d0 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -54,13 +54,24 @@ namespace osu.Game.Overlays private void onSuccess(APIWikiPage response) { wikiData.Value = response; - LoadDisplay(new WikiMarkdownContainer + + if (response.Layout == "main_page") { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - CurrentPath = $"{path.Value}/", - Text = response.Markdown, - }); + LoadDisplay(new WikiMainPage + { + Markdown = response.Markdown + }); + } + else + { + LoadDisplay(new WikiMarkdownContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + CurrentPath = $"{path.Value}/", + Text = response.Markdown, + }); + } } private void showParentPage() From 6257504bb6170bfb186f2dad856f96fa9052e284 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 25 May 2021 14:37:14 +0700 Subject: [PATCH 16/27] add padding spacing --- osu.Game/Overlays/WikiOverlay.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index 6e07de71d0..fa8ba66bcd 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -59,7 +59,12 @@ namespace osu.Game.Overlays { LoadDisplay(new WikiMainPage { - Markdown = response.Markdown + Markdown = response.Markdown, + Padding = new MarginPadding + { + Vertical = 20, + Horizontal = 50, + }, }); } else @@ -70,6 +75,13 @@ namespace osu.Game.Overlays AutoSizeAxes = Axes.Y, CurrentPath = $"{path.Value}/", Text = response.Markdown, + DocumentMargin = new MarginPadding(0), + DocumentPadding = new MarginPadding + { + Vertical = 20, + Left = 30, + Right = 50, + }, }); } } From 1ad3aee126e29aac93fb28089460c1acbe0e589c Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Thu, 20 May 2021 17:49:20 +0700 Subject: [PATCH 17/27] add article page test wiki overlay --- .../Visual/Online/TestSceneWikiOverlay.cs | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs index 371be8a003..da4bf82948 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs @@ -21,11 +21,18 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestMainPage() { - setUpNewsResponse(responseExample); + setUpWikiResponse(responseMainPage); AddStep("Show Main Page", () => wiki.Show()); } - private void setUpNewsResponse(APIWikiPage r) + [Test] + public void TestArticlePage() + { + setUpWikiResponse(responseArticlePage); + AddStep("Show Article Page", () => wiki.ShowPage("Interface")); + } + + private void setUpWikiResponse(APIWikiPage r) => AddStep("set up response", () => { dummyAPI.HandleRequest = request => @@ -39,14 +46,27 @@ namespace osu.Game.Tests.Visual.Online }); // From https://osu.ppy.sh/api/v2/wiki/en/Main_Page - private APIWikiPage responseExample => new APIWikiPage + private APIWikiPage responseMainPage => new APIWikiPage { Title = "Main Page", Layout = "main_page", Path = "Main_Page", Locale = "en", Subtitle = null, - Markdown = "---\nlayout: main_page\n---\n\n\n\n
\nWelcome to the osu! wiki, a project containing a wide range of osu! related information.\n
\n\n
\n
\n\n# Getting started\n\n[Welcome](/wiki/Welcome) • [Installation](/wiki/Installation) • [Registration](/wiki/Registration) • [Help Centre](/wiki/Help_Centre) • [FAQ](/wiki/FAQ)\n\n
\n
\n\n# Game client\n\n[Interface](/wiki/Interface) • [Options](/wiki/Options) • [Visual settings](/wiki/Visual_Settings) • [Shortcut key reference](/wiki/Shortcut_key_reference) • [Configuration file](/wiki/osu!_Program_Files/User_Configuration_File) • [Program files](/wiki/osu!_Program_Files)\n\n[File formats](/wiki/osu!_File_Formats): [.osz](/wiki/osu!_File_Formats/Osz_(file_format)) • [.osk](/wiki/osu!_File_Formats/Osk_(file_format)) • [.osr](/wiki/osu!_File_Formats/Osr_(file_format)) • [.osu](/wiki/osu!_File_Formats/Osu_(file_format)) • [.osb](/wiki/osu!_File_Formats/Osb_(file_format)) • [.db](/wiki/osu!_File_Formats/Db_(file_format))\n\n
\n
\n\n# Gameplay\n\n[Game modes](/wiki/Game_mode): [osu!](/wiki/Game_mode/osu!) • [osu!taiko](/wiki/Game_mode/osu!taiko) • [osu!catch](/wiki/Game_mode/osu!catch) • [osu!mania](/wiki/Game_mode/osu!mania)\n\n[Beatmap](/wiki/Beatmap) • [Hit object](/wiki/Hit_object) • [Mods](/wiki/Game_modifier) • [Score](/wiki/Score) • [Replay](/wiki/Replay) • [Multi](/wiki/Multi)\n\n
\n
\n\n# [Beatmap editor](/wiki/Beatmap_Editor)\n\nSections: [Compose](/wiki/Beatmap_Editor/Compose) • [Design](/wiki/Beatmap_Editor/Design) • [Timing](/wiki/Beatmap_Editor/Timing) • [Song setup](/wiki/Beatmap_Editor/Song_Setup)\n\nComponents: [AiMod](/wiki/Beatmap_Editor/AiMod) • [Beat snap divisor](/wiki/Beatmap_Editor/Beat_Snap_Divisor) • [Distance snap](/wiki/Beatmap_Editor/Distance_Snap) • [Menu](/wiki/Beatmap_Editor/Menu) • [SB load](/wiki/Beatmap_Editor/SB_Load) • [Timelines](/wiki/Beatmap_Editor/Timelines)\n\n[Beatmapping](/wiki/Beatmapping) • [Difficulty](/wiki/Beatmap/Difficulty) • [Mapping techniques](/wiki/Mapping_Techniques) • [Storyboarding](/wiki/Storyboarding)\n\n
\n
\n\n# Beatmap submission and ranking\n\n[Submission](/wiki/Submission) • [Modding](/wiki/Modding) • [Ranking procedure](/wiki/Beatmap_ranking_procedure) • [Mappers' Guild](/wiki/Mappers_Guild) • [Project Loved](/wiki/Project_Loved)\n\n[Ranking criteria](/wiki/Ranking_Criteria): [osu!](/wiki/Ranking_Criteria/osu!) • [osu!taiko](/wiki/Ranking_Criteria/osu!taiko) • [osu!catch](/wiki/Ranking_Criteria/osu!catch) • [osu!mania](/wiki/Ranking_Criteria/osu!mania)\n\n
\n
\n\n# Community\n\n[Tournaments](/wiki/Tournaments) • [Skinning](/wiki/Skinning) • [Projects](/wiki/Projects) • [Guides](/wiki/Guides) • [osu!dev Discord server](/wiki/osu!dev_Discord_server) • [How you can help](/wiki/How_You_Can_Help!) • [Glossary](/wiki/Glossary)\n\n
\n
\n\n# People\n\n[The Team](/wiki/People/The_Team): [Developers](/wiki/People/The_Team/Developers) • [Global Moderation Team](/wiki/People/The_Team/Global_Moderation_Team) • [Support Team](/wiki/People/The_Team/Support_Team) • [Nomination Assessment Team](/wiki/People/The_Team/Nomination_Assessment_Team) • [Beatmap Nominators](/wiki/People/The_Team/Beatmap_Nominators) • [osu! Alumni](/wiki/People/The_Team/osu!_Alumni) • [Project Loved Team](/wiki/People/The_Team/Project_Loved_Team)\n\nOrganisations: [osu! UCI](/wiki/Organisations/osu!_UCI)\n\n[Community Contributors](/wiki/People/Community_Contributors) • [Users with unique titles](/wiki/People/Users_with_unique_titles)\n\n
\n
\n\n# For developers\n\n[API](/wiki/osu!api) • [Bot account](/wiki/Bot_account) • [Brand identity guidelines](/wiki/Brand_identity_guidelines)\n\n
\n
\n\n# About the wiki\n\n[Sitemap](/wiki/Sitemap) • [Contribution guide](/wiki/osu!_wiki_Contribution_Guide) • [Article styling criteria](/wiki/Article_Styling_Criteria) • [News styling criteria](/wiki/News_Styling_Criteria)\n\n
\n
\n", + Markdown = + "---\nlayout: main_page\n---\n\n\n\n
\nWelcome to the osu! wiki, a project containing a wide range of osu! related information.\n
\n\n
\n
\n\n# Getting started\n\n[Welcome](/wiki/Welcome) • [Installation](/wiki/Installation) • [Registration](/wiki/Registration) • [Help Centre](/wiki/Help_Centre) • [FAQ](/wiki/FAQ)\n\n
\n
\n\n# Game client\n\n[Interface](/wiki/Interface) • [Options](/wiki/Options) • [Visual settings](/wiki/Visual_Settings) • [Shortcut key reference](/wiki/Shortcut_key_reference) • [Configuration file](/wiki/osu!_Program_Files/User_Configuration_File) • [Program files](/wiki/osu!_Program_Files)\n\n[File formats](/wiki/osu!_File_Formats): [.osz](/wiki/osu!_File_Formats/Osz_(file_format)) • [.osk](/wiki/osu!_File_Formats/Osk_(file_format)) • [.osr](/wiki/osu!_File_Formats/Osr_(file_format)) • [.osu](/wiki/osu!_File_Formats/Osu_(file_format)) • [.osb](/wiki/osu!_File_Formats/Osb_(file_format)) • [.db](/wiki/osu!_File_Formats/Db_(file_format))\n\n
\n
\n\n# Gameplay\n\n[Game modes](/wiki/Game_mode): [osu!](/wiki/Game_mode/osu!) • [osu!taiko](/wiki/Game_mode/osu!taiko) • [osu!catch](/wiki/Game_mode/osu!catch) • [osu!mania](/wiki/Game_mode/osu!mania)\n\n[Beatmap](/wiki/Beatmap) • [Hit object](/wiki/Hit_object) • [Mods](/wiki/Game_modifier) • [Score](/wiki/Score) • [Replay](/wiki/Replay) • [Multi](/wiki/Multi)\n\n
\n
\n\n# [Beatmap editor](/wiki/Beatmap_Editor)\n\nSections: [Compose](/wiki/Beatmap_Editor/Compose) • [Design](/wiki/Beatmap_Editor/Design) • [Timing](/wiki/Beatmap_Editor/Timing) • [Song setup](/wiki/Beatmap_Editor/Song_Setup)\n\nComponents: [AiMod](/wiki/Beatmap_Editor/AiMod) • [Beat snap divisor](/wiki/Beatmap_Editor/Beat_Snap_Divisor) • [Distance snap](/wiki/Beatmap_Editor/Distance_Snap) • [Menu](/wiki/Beatmap_Editor/Menu) • [SB load](/wiki/Beatmap_Editor/SB_Load) • [Timelines](/wiki/Beatmap_Editor/Timelines)\n\n[Beatmapping](/wiki/Beatmapping) • [Difficulty](/wiki/Beatmap/Difficulty) • [Mapping techniques](/wiki/Mapping_Techniques) • [Storyboarding](/wiki/Storyboarding)\n\n
\n
\n\n# Beatmap submission and ranking\n\n[Submission](/wiki/Submission) • [Modding](/wiki/Modding) • [Ranking procedure](/wiki/Beatmap_ranking_procedure) • [Mappers' Guild](/wiki/Mappers_Guild) • [Project Loved](/wiki/Project_Loved)\n\n[Ranking criteria](/wiki/Ranking_Criteria): [osu!](/wiki/Ranking_Criteria/osu!) • [osu!taiko](/wiki/Ranking_Criteria/osu!taiko) • [osu!catch](/wiki/Ranking_Criteria/osu!catch) • [osu!mania](/wiki/Ranking_Criteria/osu!mania)\n\n
\n
\n\n# Community\n\n[Tournaments](/wiki/Tournaments) • [Skinning](/wiki/Skinning) • [Projects](/wiki/Projects) • [Guides](/wiki/Guides) • [osu!dev Discord server](/wiki/osu!dev_Discord_server) • [How you can help](/wiki/How_You_Can_Help!) • [Glossary](/wiki/Glossary)\n\n
\n
\n\n# People\n\n[The Team](/wiki/People/The_Team): [Developers](/wiki/People/The_Team/Developers) • [Global Moderation Team](/wiki/People/The_Team/Global_Moderation_Team) • [Support Team](/wiki/People/The_Team/Support_Team) • [Nomination Assessment Team](/wiki/People/The_Team/Nomination_Assessment_Team) • [Beatmap Nominators](/wiki/People/The_Team/Beatmap_Nominators) • [osu! Alumni](/wiki/People/The_Team/osu!_Alumni) • [Project Loved Team](/wiki/People/The_Team/Project_Loved_Team)\n\nOrganisations: [osu! UCI](/wiki/Organisations/osu!_UCI)\n\n[Community Contributors](/wiki/People/Community_Contributors) • [Users with unique titles](/wiki/People/Users_with_unique_titles)\n\n
\n
\n\n# For developers\n\n[API](/wiki/osu!api) • [Bot account](/wiki/Bot_account) • [Brand identity guidelines](/wiki/Brand_identity_guidelines)\n\n
\n
\n\n# About the wiki\n\n[Sitemap](/wiki/Sitemap) • [Contribution guide](/wiki/osu!_wiki_Contribution_Guide) • [Article styling criteria](/wiki/Article_Styling_Criteria) • [News styling criteria](/wiki/News_Styling_Criteria)\n\n
\n
\n", + }; + + // From https://osu.ppy.sh/api/v2/wiki/en/Interface + private APIWikiPage responseArticlePage => new APIWikiPage + { + Title = "Interface", + Layout = "markdown_page", + Path = "Interface", + Locale = "en", + Subtitle = null, + Markdown = + "# Interface\n\n![](img/intro-screen.jpg \"Introduction screen\")\n\n## Main Menu\n\n![](img/main-menu.jpg \"Main Menu\")\n\nThe [osu!cookie](/wiki/Glossary#cookie) \\[1\\] pulses according to the [BPM](/wiki/Beatmapping/Beats_per_minute) of any song currently playing on the main menu. In addition, bars will extend out of the osu!cookie in accordance to the song's volume. If no song is playing, it pulses at a slow 60 BPM. The elements of the main menu are as follows:\n\n- \\[2\\] Click Play (`P`) or the logo to switch to the Solo mode song selection screen.\n- \\[3\\] Click Edit (`E`) to open the Editor mode song selection screen.\n- \\[4\\] Click Options (`O`) to go to the Options screen.\n- \\[5\\] Click Exit (`Esc`) to exit osu!.\n- \\[6\\] A random useful tip is displayed below the menu.\n- \\[7\\] In the lower-left is a link to the osu! website, as well as copyright information.\n- \\[8\\] Connection result to [Bancho](/wiki/Glossary#bancho)! In this picture it is not shown, but the connection result looks like a chain link.\n- \\[9\\] In the bottom right are the chat controls for the extended [chat window](/wiki/Chat_Console) (called \"Player List\" here) and the regular chat window (`F9` & `F8`, respectively).\n- \\[10\\] In the upper right is the osu! jukebox which plays the songs in random order. The top shows the song currently playing. The buttons, from left to right, do as follows:\n - Previous Track\n - Play\n - Pause\n - Stop (the difference between Play and Stop is that Stop will reset the song to the beginning, while Pause simply pauses it)\n - Next Track\n - View Song Info. This toggles the top bar showing the song info between being permanent and temporary. When permanent, the info bar will stay visible until it fades out with the rest of the UI. When temporary, it will disappear a little while after a song has been chosen. It will stay hidden until it is toggled again, or another song plays.\n- \\[11\\] The number of beatmaps you have available, how long your osu!client has been running, and your system clock.\n- \\[12\\] Your profile, click on it to display the User Options (see below).\n\n## User Options\n\n![](img/user-options.jpg \"User Options\")\n\nAccess this screen by clicking your profile at the top left of the main menu. You cannot access the Chat Consoles while viewing the user option screen. You can select any item by pressing the corresponding number on the option:\n\n1. `View Profile`: Opens up your profile page in your default web browser.\n2. `Sign Out`: Sign out of your account (after signing out, the [Options](/wiki/Options) sidebar will prompt you to sign in).\n3. `Change Avatar`: Open up the edit avatar page in your default web browser.\n4. `Close`: Close this dialog\n\n## Play Menu\n\n![](img/play-menu.jpg \"Play Menu\")\n\n- Click `Solo` (`P`) to play alone.\n- Click `Multi` (`M`) to play with other people. You will be directed to the [Multi](/wiki/Multi) Lobby (see below).\n- Click `Back` to return to the main menu.\n\n## Multi Lobby\n\n*Main page: [Multi](/wiki/Multi)*\n\n![](img/multi-lobby.jpg \"Multi Lobby\")\n\n![](img/multi-room.jpg \"Multi Host\")\n\n1. Your rank in the match. This is also shown next to your name.\n2. Your profile information.\n3. The jukebox.\n4. Player list - displays player names, their rank (host or player), their [mods](/wiki/Game_modifier) activated (if any, see \\#7), their osu! ranking, and their team (if applicable).\n5. The name of the match and the password settings.\n6. The beatmap selected. It shows the beatmap as it would in the solo song selection screen.\n7. The [mods](/wiki/Game_modifier) that you have activated (see #12), as well as the option to select them. The option marked \"Free Mods\" toggles whether or not players can select their own mods. If yes, they can pick any combination of mods *except for speed-altering mods like [Double Time](/wiki/Game_modifier/Double_Time)*. If no, the host decides what mods will be used. The host can pick speed-altering mods regardless of whether or not Free Mods is turned on.\n8. The team mode and win conditions.\n9. The ready button.\n10. The [chat console](/wiki/Chat_Console).\n11. The leave button.\n12. Where your activated mods appear.\n\n## Song Selection Screen\n\n![](img/song-selection.jpg \"Song Selection\")\n\nYou can identify the current mode selected by either looking at the icon in the bottom left, above Mode, or by looking at the transparent icon in the center of the screen. These are the four you will see:\n\n- ![](/wiki/shared/mode/osu.png) is [osu!](/wiki/Game_mode/osu!)\n- ![](/wiki/shared/mode/taiko.png) is [osu!taiko](/wiki/Game_mode/osu!taiko)\n- ![](/wiki/shared/mode/catch.png) is [osu!catch](/wiki/Game_mode/osu!catch)\n- ![](/wiki/shared/mode/mania.png) is [osu!mania](/wiki/Game_mode/osu!mania)\n\nBefore continuing on, this screen has too many elements to note with easily, noticeable numbers. The subsections below will focus on one part of the screen at a time, starting from the top down and left to right.\n\n### Beatmap Information\n\n![](img/metadata-comparison.jpg)\n\n![](img/beatmap-metadata.jpg)\n\nThis area displays **information on the beatmap difficulty currently selected.** By default, the beatmap whose song is heard in the osu! jukebox is selected when entering the selection screen. In the top left is the ranked status of the beatmap. The title is next. Normally, the romanised title is shown, but if you select `Prefer metadata in original language` in the [Options](/wiki/Options), it will show the Unicode title; this is shown in the upper picture. The beatmapper is also shown, and beatmap information is shown below. From left to right, the values are as follows:\n\n- **Length**: The total length of the beatmap, from start to finish and including breaks. Not to be confused with [drain time](/wiki/Glossary#drain-time).\n- **BPM**: The BPM of the beatmap. If (like in the lower picture) there are two BPMS and one in parentheses, this means that the BPM changes throughout the song. It shows the slowest and fastest BPMs, and the value in parentheses is the BPM at the start of the beatmap.\n- **Objects**: The total amount of [hit objects](/wiki/Hit_Objects) in the beatmap.\n- **Circles**: The total amount of hit circles in the beatmap.\n- **Sliders**: The total amount of sliders in the beatmap.\n- **Spinners**: The total amount of spinners in the beatmap.\n- **OD**: The Overall Difficulty of the beatmap.\n- **HP**: The drain rate of your HP. In osu!, this is how much of an HP loss you receive upon missing a note, how fast the life bar idly drains, and how much HP is received for hitting a note. In osu!mania, this is the same except there is no idle HP drain. In osu!taiko, this determines how slowly the HP bar fills and how much HP is lost when a note is missed. osu!catch is the same as osu!.\n- **Stars**: The star difficulty of the beatmap. This is graphically visible in the beatmap rectangle itself.\n\n### Group and Sort\n\n![](img/beatmap-filters.jpg)\n\nClick on one of the tabs to **sort your song list according to the selected criterion**.\n\n**Group** - Most options organize beatmaps into various expandable groups:\n\n- `No grouping` - Beatmaps will not be grouped but will still be sorted in the order specified by Sort.\n- `By Difficulty` - Beatmaps will be grouped by their star difficulty, rounded to the nearest whole number.\n- `By Artist` - Beatmaps will be grouped by the artist's first character of their name.\n- `Recently Played` - Beatmaps will be grouped by when you last played them.\n- `Collections` - This will show the collections you have created. *Note that this will hide beatmaps not listed in a collection!*\n- `By BPM` - Beatmaps will be grouped according to BPM in multiples of 60, starting at 120.\n- `By Creator` - Beatmaps will be grouped by the beatmap creator's name's first character.\n- `By Date Added` - Beatmaps will be grouped according to when they were added, from today to 4+ months ago.\n- `By Length` - Beatmaps will be grouped according to their length: 1 minute or less, 2 minutes or less, 3, 4, 5, and 10.\n- `By Mode` - Beatmaps will be grouped according to their game mode.\n- `By Rank Achieved` - Beatmaps will be sorted by the highest rank achieved on them.\n- `By Title` - Beatmaps will be grouped by the first letter of their title.\n- `Favourites` - Only beatmaps you have favorited online will be shown.\n- `My Maps` - Only beatmaps you have mapped (that is, whose creator matches your profile name) will be shown.\n- `Ranked Status` - Beatmaps will be grouped by their ranked status: ranked, pending, not submitted, unknown, or loved.\n\nThe first five groupings are available in tabs below Group and Sort.\n\n**Sort** - Sorts beatmaps in a certain order\n\n- `By Artist` - Beatmaps will be sorted alphabetically by the artist's name's first character.\n- `By BPM` - Beatmaps will be sorted lowest to highest by their BPM. For maps with multiple BPMs, the highest will be used.\n- `By Creator` - Beatmaps will be sorted alphabetically by the creator's name's first character.\n- `By Date Added` - Beatmaps will be sorted from oldest to newest by when they were added.\n- `By Difficulty` - Beatmaps will be sorted from easiest to hardest by star difficulty. *Note that this will split apart mapsets!*\n- `By Length` - Beatmaps will be sorted from shortest to longest by length.\n- `By Rank Achieved` - Beatmaps will be sorted from poorest to best by the highest rank achieved on them.\n- `By Title` - Beatmaps will be sorted alphabetically by the first character of their name.\n\n### Search\n\n![](img/search-bar.jpg)\n\n*Note: You cannot have the chat console or the options sidebar open if you want to search; otherwise, anything you type will be perceived as chat text or as an options search query.*\n\nOnly beatmaps that match the criteria of your search will be shown. By default, any search will be matched against the beatmaps' artists, titles, creators, and tags.\n\nIn addition to searching these fields, you can use filters to search through other metadata by combining one of the supported filters with a comparison to a value (for example, `ar=9`).\n\nSupported filters:\n\n- `artist`: Name of the artist\n- `creator`: Name of the beatmap creator\n- `ar`: Approach Rate\n- `cs`: Circle Size\n- `od`: Overall Difficulty\n- `hp`: HP Drain Rate\n- `keys`: Number of keys (osu!mania and converted beatmaps only)\n- `stars`: Star Difficulty\n- `bpm`: Beats per minute\n- `length`: Length in seconds\n- `drain`: Drain Time in seconds\n- `mode`: Mode. Value can be `osu`, `taiko`, `catchthebeat`, or `mania`, or `o`/`t`/`c`/`m` for short.\n- `status`: Ranked status. Value can be `ranked`, `approved`, `pending`, `notsubmitted`, `unknown`, or `loved`, or `r`/`a`/`p`/`n`/`u`/`l` for short.\n- `played`: Time since last played in days\n- `unplayed`: Shows only unplayed maps. A comparison with no set value must be used. The comparison itself is ignored.\n- `speed`: Saved osu!mania scroll speed. Always 0 for unplayed maps or if the [Remember osu!mania scroll speed per beatmap](/wiki/Options#gameplay) option is off\n\nSupported comparisons:\n\n- `=` or `==`: Equal to\n- `!=`: Not equal to\n- `<`: Less than\n- `>`: Greater than\n- `<=`: Less than or equal to\n- `>=`: Greater than or equal to\n\nYou may also enter a beatmap or beatmapset ID in your search to get a single result.\n\n### Rankings\n\n![](img/leaderboards.jpg)\n\n A variety of things can appear in this space:\n\n- A \"Not Submitted\" box denotes a beatmap that has not been uploaded to the osu! site using the Beatmap Submission System or was deleted by the mapper.\n- An \"Update to latest version\" box appears if there is a new version of the beatmap available for download. Click on the button to update.\n - **Note:** Once you update the beatmap, it cannot be reversed. If you want to preserve the older version for some reason (say, to keep scores), then do not update.\n- A \"Latest pending version\" box appears means that the beatmap has been uploaded to the osu!website but is not ranked yet.\n- If replays matching the view setting of the beatmap exist, they will be displayed instead of a box denoting the ranked/played status of the beatmap. This is shown in the above picture.\n - Under public rankings (e.g. Global, Friends, etc.), your high score will be shown at the bottom, as well as your rank on the leaderboard.\n- A \"No records set!\" box means that there are no replays for the current view setting (this is typically seen in the Local view setting if you just downloaded or edited the beatmap).\n - Note: Scores for Multi are not counted as records.\n\nThese are the view settings:\n\n- Local Ranking\n- Country Ranking\\*\n- Global Ranking\n- Global Ranking (Selected Mods)\\*\n- Friend Ranking\\*\n\n\\*Requires you to be an [osu!supporter](/wiki/osu!supporter) to access them.\n\nClick the word bubble icon to call up the **Quick Web Access** screen for the selected beatmap:\n\n- Press `1` or click the `Beatmap Listing/Scores` button and your default internet browser will pull up the Beatmap Listing and score page of the beatmap set the selected beatmap belongs to.\n- Press `2` or click `Beatmap Modding` and your default internet browser will pull up the modding page of the beatmap set the selected beatmap belongs to.\n- Press `3` or `Esc` or click `Cancel` to return to the Song Selection Screen.\n\nWhile you are on the Quick Web Access Screen, you cannot access the Chat and Extended Chat Consoles.\n\n### Song\n\n![](img/beatmap-cards.jpg)\n\nThe song list displays all available beatmaps. Different beatmaps may have different coloured boxes:\n\n- **Pink**: This beatmap has not been played yet.\n- **Orange**: At least one beatmap from the beatmapset has been completed.\n- **Light Blue**: Other beatmaps in the same set, shown when a mapset is expanded.\n- **White**: Currently selected beatmap.\n\nYou can navigate the beatmap list by using the mouse wheel, using the up and down arrow keys, dragging it while holding the left mouse button or clicking the right mouse button (previously known as Absolute Scrolling), which will move the scroll bar to your mouse's Y position. Click on a box to select that beatmap and display its information on the upper left, high scores (if any) on the left and, if you've cleared it, the letter grade of the highest score you've achieved. Click the box again, press `Enter` or click the osu!cookie at the lower right to begin playing the beatmap.\n\n### Gameplay toolbox\n\n![](img/game-mode-selector.jpg \"List of available game modes\")\n\n![](img/gameplay-toolbox.jpg)\n\nThis section can be called the gameplay toolbox. We will cover each button's use from left to right.\n\nPress `Esc` or click the `Back` button to return to main menu.\n\nClick on the `Mode` button to open up a list of gameplay modes available on osu!. Click on your desired gameplay mode and osu! will switch to that gameplay mode style - the scoreboard will change accordingly. Alternatively, you can press `Ctrl` and `1` (osu!), `2` (osu!taiko), `3` (osu!catch), or `4` (osu!mania) to change the gamemode.\n\nThe background transparent icon and the \"Mode\" box will change to depict what mode is currently selected.\n\n![](img/game-modifiers.jpg \"Mod Selection Screen\")\n\nClick the `Mods` button or press `F1` to open the **[Mod Selection Screen](/wiki/Game_modifier)**.\n\nIn this screen, you can apply modifications (\"mods\" for short) to gameplay. Some mods lower difficulty and apply a multiplier that lowers the score you achieve. Conversely, some mods increase the difficulty, but apply a multiplier that increases the score you achieve. Finally, some mods modify gameplay in a different way. [Relax](/wiki/Game_modifier/Relax) and [Auto Pilot](/wiki/Game_modifier/Autopilot) fall in that category.\n\nPlace your mouse on a mod's icon to see a short description of its effect. Click on an icon to select or deselect that mod. Some mods, like Double Time, have multiple variations; click on the mod again to cycle through. The score multiplier value displays the combined effect the multipliers of the mod(s) of you have selected will have on your score. Click `Reset all mods` or press `1` to deselect all currently selected mods. Click `Close` or press `2` or `Esc` to return to the Song Selection Screen.\n\nWhile you are on the Mod Selection Screen, you cannot access the Chat and Extended Chat Consoles. In addition, skins can alter the text and/or icon of the mods, but the effects will still be the same.\n\nClick the `Random` button or press `F2` to have the game **randomly scroll through all of your beatmaps and pick one.** You cannot select a beatmap yourself until it has finished scrolling.\n\n*Note: You can press `Shift` + the `Random` button or `F2` to go back to the beatmap you had selected before you randomized your selection.*\n\n![](img/beatmap-options.jpg \"Possible commands for a beatmap\")\n\nClick the `Beatmap Options` button, press `F3` or right-click your mouse while hovering over the beatmap to call up the **Beatmap Options Menu for options on the currently selected beatmap**.\n\n- Press `1` or click the `Manage Collections` button to bring up the Collections screen - here, you can manage pre-existing collections, as well as add or remove the currently selected beatmap or mapset to or from a collection.\n- Press `2` or click `Delete...` to delete the \\[1\\] currently selected beatmapset, \\[2\\] delete the currently selected beatmap, or \\[3\\] delete **all VISIBLE beatmaps**.\n - Note that deleted beatmaps are moved to the Recycle Bin.\n- Press `3` or click `Remove from Unplayed` to mark an unplayed beatmap as played (that is, change its box colour from pink to orange).\n- Press `4` or click `Clear local scores` to delete all records of the scores you have achieved in this beatmap.\n- Press `5` or click `Edit` to open the selected beatmap in osu!'s Editor.\n- Press `6` or `Esc` or click `Close` to return to the Song Selection Screen.\n\nClick on **your user panel** to access the **User Options Menu**.\n\nClick the **[osu!cookie](/wiki/Glossary#cookie)** to **start playing the selected beatmap**.\n\n## Results screen\n\n![](img/results-osu.jpg \"Accuracy in osu!\")\n\nThis is the results screen shown after you have successfully passed the beatmap. You can access your online results by scrolling down or pressing the obvious button.\n\n**Note:** The results screen may change depending on the used skin.\n\nBelow are the results screens of the other game modes.\n\n![](img/results-taiko.jpg \"Accuracy in osu!taiko\")\n\n![](img/results-mania.jpg \"Accuracy in osu!mania\")\n\n![](img/results-catch.jpg \"Accuracy in osu!catch\")\n\n### Online Leaderboard\n\n![](img/extended-results-screen.jpg \"An example of an osu!online score\")\n\nThis is your online leaderboard. You can go here by scrolling down from the results screen. Your Local Scoreboard will show your name and the score as usual.\n\n1. Your player bar. It shows your [PP](/wiki/Performance_Points), Global Rank, Total Score, Overall [Accuracy](/wiki/Accuracy), and level bar.\n2. `Save replay to Replays folder`: You can watch the replay later either by opening it from a local leaderboard, or by going to `Replays` directory and double clicking it.\n3. `Add as online favourite`: Include the beatmap into your list of favourites, which is located on your osu! profile page under the \"Beatmaps\" section.\n4. Local Leaderboard: All your results are stored on your computer. To see them, navigate to the [song selection screen](#song-selection-screen), then select `Local Rankings` from the drop-down menu on the left.\n5. `Beatmap Ranking` section. Available only for maps with online leaderboards ([qualified](/wiki/Beatmap/Category#qualified), [ranked](/wiki/Beatmap/Category#ranked), or [loved](/wiki/Beatmap/Category#loved)). You also need to be online to see this section.\n 1. `Overall`: Your position on the map's leaderboard, where you compete against players that used [mods](/wiki/Game_modifier), even if you didn't use any yourself.\n 2. `Accuracy`: How [precisely](/wiki/Accuracy) did you play the beatmap. Will only be counted when your old score is surpassed.\n 3. `Max Combo`: Your longest combo on the map you played.\n 4. `Ranked Score`: Your [best result](/wiki/Score#ranked-score) on the beatmap.\n 5. `Total Score`: Not taken into account, since it does not affect your position in online rankings.\n 6. `Performance`: The amount of [unweighted PP](/wiki/Performance_points#why-didnt-i-gain-the-full-amount-of-pp-from-a-map-i-played) you would receive for the play.\n6. `Overall Ranking` section. It's available only for beatmaps with online leaderboards. You also need to be online to see this section.\n 1. `Overall`: Your global ranking in the world.\n 2. `Accuracy`: Your average [accuracy](/wiki/Accuracy#accuracy) over all beatmaps you have played.\n 3. `Max Combo`: The longest combo over all beatmaps you have played.\n 4. [`Ranked Score`](/wiki/Score#ranked-score): The number of points earned from all ranked beatmaps that you have ever played, with every map being counted exactly once.\n 5. [`Total Score`](/wiki/Score#total-score): Same as ranked score, but it takes into account all beatmaps available on the osu! website, and also underplayed or failed beatmaps. This counts towards your level.\n 6. `Perfomance`: Displays your total amount of Performance Points, and also how many PP the submitted play was worth.\n7. Information about the beatmap with its playcount and pass rate.\n8. Beatmap rating. Use your personal discretion based on whether you enjoy the beatmap or not. Best left alone if you can't decide.\n9. Click here to return to the song selection screen.\n\n![](img/medal-unlock.jpg \"Unlocking a medal\")\n\nAbove is what it looks like to receive a medal.\n", }; } } From 4c8f19af69cd09f0db9b9ad79931d90294f3f3b0 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Tue, 25 May 2021 14:47:39 +0700 Subject: [PATCH 18/27] load empty page when fail --- osu.Game/Overlays/WikiOverlay.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index fa8ba66bcd..df93c35500 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -47,6 +47,7 @@ namespace osu.Game.Overlays Loading.Show(); request.Success += response => Schedule(() => onSuccess(response)); + request.Failure += _ => Schedule(() => LoadDisplay(Empty())); api.PerformAsync(request); } From ba8544f614570a565531fbcb04637bcacc66eb9e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 26 May 2021 14:55:44 +0900 Subject: [PATCH 19/27] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index b3842a528d..f7ad06f5ca 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -51,7 +51,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e3331cd365..a9152b8cb8 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -35,7 +35,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/osu.iOS.props b/osu.iOS.props index e35b1b5c42..a0894bc86a 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -71,7 +71,7 @@ - + From 7546611c1421fb83eae255dd6544d78023e89ee4 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Wed, 26 May 2021 19:32:49 +0700 Subject: [PATCH 20/27] remove unused cached --- osu.Game/Overlays/WikiOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index df93c35500..040e608574 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -20,7 +20,6 @@ namespace osu.Game.Overlays private readonly Bindable path = new Bindable(index_path); - [Cached] private readonly Bindable wikiData = new Bindable(); [Resolved] From 905364b5fefc07cd309b1e8b77327ad6d9a7e115 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Wed, 26 May 2021 19:34:34 +0700 Subject: [PATCH 21/27] add url as argument for link action external --- osu.Game/Online/Chat/MessageFormatter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 1041758b0c..c57fc732be 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -173,7 +173,7 @@ namespace osu.Game.Online.Chat } } - return new LinkDetails(LinkAction.External, null); + return new LinkDetails(LinkAction.External, url); case "osu": // every internal link also needs some kind of argument From 22a5af750e6be5cffea6f6a706f59581f39c9f1e Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Wed, 26 May 2021 20:25:48 +0700 Subject: [PATCH 22/27] fix test link external --- osu.Game.Tests/Chat/MessageFormatterTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Chat/MessageFormatterTests.cs b/osu.Game.Tests/Chat/MessageFormatterTests.cs index b80da928c8..c0fc19356e 100644 --- a/osu.Game.Tests/Chat/MessageFormatterTests.cs +++ b/osu.Game.Tests/Chat/MessageFormatterTests.cs @@ -24,10 +24,10 @@ namespace osu.Game.Tests.Chat [TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123#osu/456")] [TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123#osu/456?whatever")] [TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123/456")] - [TestCase(LinkAction.External, null, "https://dev.ppy.sh/beatmapsets/abc/def")] + [TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/abc/def", "https://dev.ppy.sh/beatmapsets/abc/def")] [TestCase(LinkAction.OpenBeatmapSet, "123", "https://dev.ppy.sh/beatmapsets/123")] [TestCase(LinkAction.OpenBeatmapSet, "123", "https://dev.ppy.sh/beatmapsets/123/whatever")] - [TestCase(LinkAction.External, null, "https://dev.ppy.sh/beatmapsets/abc")] + [TestCase(LinkAction.External, "https://dev.ppy.sh/beatmapsets/abc", "https://dev.ppy.sh/beatmapsets/abc")] public void TestBeatmapLinks(LinkAction expectedAction, string expectedArg, string link) { MessageFormatter.WebsiteRootUrl = "dev.ppy.sh"; From 113f90e92e341f826926a1a3d2f4dcd9387df952 Mon Sep 17 00:00:00 2001 From: Gagah Pangeran Rosfatiputra Date: Mon, 31 May 2021 10:49:16 +0700 Subject: [PATCH 23/27] add back schedule is CurrentPath setter --- osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs index 4e671cca6d..1c5fd99ce3 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs @@ -15,7 +15,7 @@ namespace osu.Game.Overlays.Wiki.Markdown { public string CurrentPath { - set => DocumentUrl = $"{DocumentUrl}wiki/{value}"; + set => Schedule(() => DocumentUrl = $"{DocumentUrl}wiki/{value}"); } protected override void AddMarkdownComponent(IMarkdownObject markdownObject, FillFlowContainer container, int level) From 3ff97f787aaf9a72ffec5f271c81fe2abbf81eb0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 1 Jun 2021 13:32:52 +0900 Subject: [PATCH 24/27] Localise all URL generation for now to avoid weird `Schedule` logic --- .../Containers/Markdown/OsuMarkdownContainer.cs | 12 ------------ .../Overlays/Wiki/Markdown/WikiMarkdownContainer.cs | 7 ++++++- osu.Game/Overlays/Wiki/WikiPanelContainer.cs | 4 +++- osu.Game/Overlays/WikiOverlay.cs | 2 +- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs index ad11a9625e..6facf4e26c 100644 --- a/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs +++ b/osu.Game/Graphics/Containers/Markdown/OsuMarkdownContainer.cs @@ -6,13 +6,11 @@ using Markdig.Extensions.AutoIdentifiers; using Markdig.Extensions.Tables; using Markdig.Extensions.Yaml; using Markdig.Syntax; -using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers.Markdown; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics.Sprites; -using osu.Game.Online.API; namespace osu.Game.Graphics.Containers.Markdown { @@ -23,16 +21,6 @@ namespace osu.Game.Graphics.Containers.Markdown LineSpacing = 21; } - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var api = parent.Get(); - - // needs to be set before the base BDL call executes to avoid invalidating any already populated markdown content. - DocumentUrl = api.WebsiteRootUrl; - - return base.CreateChildDependencies(parent); - } - protected override void AddMarkdownComponent(IMarkdownObject markdownObject, FillFlowContainer container, int level) { switch (markdownObject) diff --git a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs index 1c5fd99ce3..acaaa523a2 100644 --- a/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs +++ b/osu.Game/Overlays/Wiki/Markdown/WikiMarkdownContainer.cs @@ -5,17 +5,22 @@ using System.Linq; using Markdig.Extensions.Yaml; using Markdig.Syntax; using Markdig.Syntax.Inlines; +using osu.Framework.Allocation; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers.Markdown; using osu.Game.Graphics.Containers.Markdown; +using osu.Game.Online.API; namespace osu.Game.Overlays.Wiki.Markdown { public class WikiMarkdownContainer : OsuMarkdownContainer { + [Resolved] + private IAPIProvider api { get; set; } + public string CurrentPath { - set => Schedule(() => DocumentUrl = $"{DocumentUrl}wiki/{value}"); + set => DocumentUrl = value; } protected override void AddMarkdownComponent(IMarkdownObject markdownObject, FillFlowContainer container, int level) diff --git a/osu.Game/Overlays/Wiki/WikiPanelContainer.cs b/osu.Game/Overlays/Wiki/WikiPanelContainer.cs index db213e4951..e1c00a955b 100644 --- a/osu.Game/Overlays/Wiki/WikiPanelContainer.cs +++ b/osu.Game/Overlays/Wiki/WikiPanelContainer.cs @@ -13,6 +13,7 @@ using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Graphics; using osu.Game.Graphics.Containers.Markdown; +using osu.Game.Online.API; using osu.Game.Overlays.Wiki.Markdown; using osuTK; using osuTK.Graphics; @@ -37,7 +38,7 @@ namespace osu.Game.Overlays.Wiki } [BackgroundDependencyLoader] - private void load(OverlayColourProvider colourProvider) + private void load(OverlayColourProvider colourProvider, IAPIProvider api) { Children = new Drawable[] { @@ -61,6 +62,7 @@ namespace osu.Game.Overlays.Wiki }, panelContainer = new WikiPanelMarkdownContainer(isFullWidth) { + CurrentPath = $@"{api.WebsiteRootUrl}/wiki/", Text = text, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index 040e608574..a87a592b56 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -73,7 +73,7 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - CurrentPath = $"{path.Value}/", + CurrentPath = $@"{api.WebsiteRootUrl}/wiki/{path.Value}/", Text = response.Markdown, DocumentMargin = new MarginPadding(0), DocumentPadding = new MarginPadding From 6e4730652e6829a6b54014aebd6dc5a5ad5823d3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 1 Jun 2021 14:01:08 +0900 Subject: [PATCH 25/27] Push private methods down --- osu.Game/Overlays/WikiOverlay.cs | 92 ++++++++++++++++---------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index a87a592b56..8468a48bf5 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -36,6 +36,52 @@ namespace osu.Game.Overlays { } + public void ShowPage(string pagePath = index_path) + { + path.Value = pagePath.Trim('/'); + Show(); + } + + protected override WikiHeader CreateHeader() => new WikiHeader + { + ShowIndexPage = () => ShowPage(), + ShowParentPage = showParentPage, + }; + + protected override void LoadComplete() + { + base.LoadComplete(); + path.BindValueChanged(onPathChanged); + wikiData.BindTo(Header.WikiPageData); + } + + protected override void PopIn() + { + base.PopIn(); + + if (displayUpdateRequired) + { + path.TriggerChange(); + displayUpdateRequired = false; + } + } + + protected override void PopOutComplete() + { + base.PopOutComplete(); + displayUpdateRequired = true; + } + + protected void LoadDisplay(Drawable display) + { + ScrollFlow.ScrollToStart(); + LoadComponentAsync(display, loaded => + { + Child = loaded; + Loading.Hide(); + }, (cancellationToken = new CancellationTokenSource()).Token); + } + private void onPathChanged(ValueChangedEvent e) { cancellationToken?.Cancel(); @@ -92,52 +138,6 @@ namespace osu.Game.Overlays ShowPage(parentPath); } - public void ShowPage(string pagePath = index_path) - { - path.Value = pagePath.Trim('/'); - Show(); - } - - protected override WikiHeader CreateHeader() => new WikiHeader - { - ShowIndexPage = () => ShowPage(), - ShowParentPage = showParentPage, - }; - - protected override void LoadComplete() - { - base.LoadComplete(); - path.BindValueChanged(onPathChanged); - wikiData.BindTo(Header.WikiPageData); - } - - protected override void PopIn() - { - base.PopIn(); - - if (displayUpdateRequired) - { - path.TriggerChange(); - displayUpdateRequired = false; - } - } - - protected override void PopOutComplete() - { - base.PopOutComplete(); - displayUpdateRequired = true; - } - - protected void LoadDisplay(Drawable display) - { - ScrollFlow.ScrollToStart(); - LoadComponentAsync(display, loaded => - { - Child = loaded; - Loading.Hide(); - }, (cancellationToken = new CancellationTokenSource()).Token); - } - protected override void Dispose(bool isDisposing) { cancellationToken?.Cancel(); From 27b703952059d79c50f3563b04a85db77b73e74f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 1 Jun 2021 14:02:32 +0900 Subject: [PATCH 26/27] Use constant --- osu.Game/Overlays/WikiOverlay.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/WikiOverlay.cs b/osu.Game/Overlays/WikiOverlay.cs index 8468a48bf5..af7bc40f17 100644 --- a/osu.Game/Overlays/WikiOverlay.cs +++ b/osu.Game/Overlays/WikiOverlay.cs @@ -16,7 +16,7 @@ namespace osu.Game.Overlays { public class WikiOverlay : OnlineOverlay { - private const string index_path = "Main_Page"; + private const string index_path = @"main_page"; private readonly Bindable path = new Bindable(index_path); @@ -101,7 +101,7 @@ namespace osu.Game.Overlays { wikiData.Value = response; - if (response.Layout == "main_page") + if (response.Layout == index_path) { LoadDisplay(new WikiMainPage { From 00ffea5e2c2b7bfa666d1da7c57e18785a5f6aa1 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 1 Jun 2021 14:38:30 +0900 Subject: [PATCH 27/27] Update tests to specify full absolute path --- .../Visual/Online/TestSceneWikiMarkdownContainer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs index 1e19af933a..9d8f07969c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneWikiMarkdownContainer.cs @@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.Online [Test] public void TestLink() { - AddStep("set current path", () => markdownContainer.CurrentPath = "Article_styling_criteria/"); + AddStep("set current path", () => markdownContainer.CurrentPath = $"{API.WebsiteRootUrl}/wiki/Article_styling_criteria/"); AddStep("set '/wiki/Main_Page''", () => markdownContainer.Text = "[wiki main page](/wiki/Main_Page)"); AddAssert("check url", () => markdownContainer.Link.Url == $"{API.WebsiteRootUrl}/wiki/Main_Page"); @@ -113,7 +113,7 @@ needs_cleanup: true AddStep("Add relative image", () => { markdownContainer.DocumentUrl = "https://dev.ppy.sh"; - markdownContainer.CurrentPath = "Interface/"; + markdownContainer.CurrentPath = $"{API.WebsiteRootUrl}/wiki/Interface/"; markdownContainer.Text = "![intro](img/intro-screen.jpg)"; }); } @@ -124,7 +124,7 @@ needs_cleanup: true AddStep("Add paragraph with block image", () => { markdownContainer.DocumentUrl = "https://dev.ppy.sh"; - markdownContainer.CurrentPath = "Interface/"; + markdownContainer.CurrentPath = $"{API.WebsiteRootUrl}/wiki/Interface/"; markdownContainer.Text = @"Line before image ![play menu](img/play-menu.jpg ""Main Menu in osu!"")