mirror of
https://github.com/ppy/osu.git
synced 2025-01-12 16:02:55 +08:00
Merge pull request #12950 from gagahpangeran/osu-wiki-overlay
Initial implementation of Wiki Overlay
This commit is contained in:
commit
dce24e3d4d
@ -51,7 +51,7 @@
|
|||||||
<Reference Include="Java.Interop" />
|
<Reference Include="Java.Interop" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.525.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.528.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.528.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -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")]
|
||||||
[TestCase(LinkAction.OpenBeatmap, "456", "https://dev.ppy.sh/beatmapsets/123#osu/456?whatever")]
|
[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.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")]
|
||||||
[TestCase(LinkAction.OpenBeatmapSet, "123", "https://dev.ppy.sh/beatmapsets/123/whatever")]
|
[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)
|
public void TestBeatmapLinks(LinkAction expectedAction, string expectedArg, string link)
|
||||||
{
|
{
|
||||||
MessageFormatter.WebsiteRootUrl = "dev.ppy.sh";
|
MessageFormatter.WebsiteRootUrl = "dev.ppy.sh";
|
||||||
|
102
osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs
Normal file
102
osu.Game.Tests/Visual/Online/TestSceneWikiHeader.cs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// 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.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;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Online
|
||||||
|
{
|
||||||
|
public class TestSceneWikiHeader : OsuTestScene
|
||||||
|
{
|
||||||
|
[Cached]
|
||||||
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Orange);
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private readonly Bindable<APIWikiPage> wikiPageData = new Bindable<APIWikiPage>(new APIWikiPage
|
||||||
|
{
|
||||||
|
Title = "Main Page",
|
||||||
|
Path = "Main_Page",
|
||||||
|
});
|
||||||
|
|
||||||
|
private TestHeader header;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp() => Schedule(() =>
|
||||||
|
{
|
||||||
|
Child = header = new TestHeader
|
||||||
|
{
|
||||||
|
Anchor = 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<string> TabControlItems => TabControl.Items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -48,7 +48,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestLink()
|
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)");
|
AddStep("set '/wiki/Main_Page''", () => markdownContainer.Text = "[wiki main page](/wiki/Main_Page)");
|
||||||
AddAssert("check url", () => markdownContainer.Link.Url == $"{API.WebsiteRootUrl}/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", () =>
|
AddStep("Add relative image", () =>
|
||||||
{
|
{
|
||||||
markdownContainer.DocumentUrl = "https://dev.ppy.sh";
|
markdownContainer.DocumentUrl = "https://dev.ppy.sh";
|
||||||
markdownContainer.CurrentPath = "Interface/";
|
markdownContainer.CurrentPath = $"{API.WebsiteRootUrl}/wiki/Interface/";
|
||||||
markdownContainer.Text = "![intro](img/intro-screen.jpg)";
|
markdownContainer.Text = "![intro](img/intro-screen.jpg)";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ needs_cleanup: true
|
|||||||
AddStep("Add paragraph with block image", () =>
|
AddStep("Add paragraph with block image", () =>
|
||||||
{
|
{
|
||||||
markdownContainer.DocumentUrl = "https://dev.ppy.sh";
|
markdownContainer.DocumentUrl = "https://dev.ppy.sh";
|
||||||
markdownContainer.CurrentPath = "Interface/";
|
markdownContainer.CurrentPath = $"{API.WebsiteRootUrl}/wiki/Interface/";
|
||||||
markdownContainer.Text = @"Line before image
|
markdownContainer.Text = @"Line before image
|
||||||
|
|
||||||
![play menu](img/play-menu.jpg ""Main Menu in osu!"")
|
![play menu](img/play-menu.jpg ""Main Menu in osu!"")
|
||||||
|
72
osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs
Normal file
72
osu.Game.Tests/Visual/Online/TestSceneWikiOverlay.cs
Normal file
File diff suppressed because one or more lines are too long
@ -6,13 +6,11 @@ using Markdig.Extensions.AutoIdentifiers;
|
|||||||
using Markdig.Extensions.Tables;
|
using Markdig.Extensions.Tables;
|
||||||
using Markdig.Extensions.Yaml;
|
using Markdig.Extensions.Yaml;
|
||||||
using Markdig.Syntax;
|
using Markdig.Syntax;
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Containers.Markdown;
|
using osu.Framework.Graphics.Containers.Markdown;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Online.API;
|
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Containers.Markdown
|
namespace osu.Game.Graphics.Containers.Markdown
|
||||||
{
|
{
|
||||||
@ -23,16 +21,6 @@ namespace osu.Game.Graphics.Containers.Markdown
|
|||||||
LineSpacing = 21;
|
LineSpacing = 21;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
|
||||||
{
|
|
||||||
var api = parent.Get<IAPIProvider>();
|
|
||||||
|
|
||||||
// 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)
|
protected override void AddMarkdownComponent(IMarkdownObject markdownObject, FillFlowContainer container, int level)
|
||||||
{
|
{
|
||||||
switch (markdownObject)
|
switch (markdownObject)
|
||||||
|
21
osu.Game/Online/API/Requests/GetWikiRequest.cs
Normal file
21
osu.Game/Online/API/Requests/GetWikiRequest.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// 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 osu.Game.Online.API.Requests.Responses;
|
||||||
|
|
||||||
|
namespace osu.Game.Online.API.Requests
|
||||||
|
{
|
||||||
|
public class GetWikiRequest : APIRequest<APIWikiPage>
|
||||||
|
{
|
||||||
|
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}";
|
||||||
|
}
|
||||||
|
}
|
32
osu.Game/Online/API/Requests/Responses/APIWikiPage.cs
Normal file
32
osu.Game/Online/API/Requests/Responses/APIWikiPage.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// 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.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<string> Tags { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("title")]
|
||||||
|
public string Title { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -167,10 +167,13 @@ namespace osu.Game.Online.Chat
|
|||||||
case "u":
|
case "u":
|
||||||
case "users":
|
case "users":
|
||||||
return new LinkDetails(LinkAction.OpenUserProfile, mainArg);
|
return new LinkDetails(LinkAction.OpenUserProfile, mainArg);
|
||||||
|
|
||||||
|
case "wiki":
|
||||||
|
return new LinkDetails(LinkAction.OpenWiki, string.Join('/', args.Skip(3)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LinkDetails(LinkAction.External, null);
|
return new LinkDetails(LinkAction.External, url);
|
||||||
|
|
||||||
case "osu":
|
case "osu":
|
||||||
// every internal link also needs some kind of argument
|
// every internal link also needs some kind of argument
|
||||||
@ -311,7 +314,8 @@ namespace osu.Game.Online.Chat
|
|||||||
JoinMultiplayerMatch,
|
JoinMultiplayerMatch,
|
||||||
Spectate,
|
Spectate,
|
||||||
OpenUserProfile,
|
OpenUserProfile,
|
||||||
Custom
|
OpenWiki,
|
||||||
|
Custom,
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Link : IComparable<Link>
|
public class Link : IComparable<Link>
|
||||||
|
@ -81,6 +81,8 @@ namespace osu.Game
|
|||||||
|
|
||||||
private BeatmapSetOverlay beatmapSetOverlay;
|
private BeatmapSetOverlay beatmapSetOverlay;
|
||||||
|
|
||||||
|
private WikiOverlay wikiOverlay;
|
||||||
|
|
||||||
private SkinEditorOverlay skinEditor;
|
private SkinEditorOverlay skinEditor;
|
||||||
|
|
||||||
private Container overlayContent;
|
private Container overlayContent;
|
||||||
@ -307,6 +309,10 @@ namespace osu.Game
|
|||||||
ShowUser(userId);
|
ShowUser(userId);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LinkAction.OpenWiki:
|
||||||
|
ShowWiki(link.Argument);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException($"This {nameof(LinkAction)} ({link.Action.ToString()}) is missing an associated action.");
|
throw new NotImplementedException($"This {nameof(LinkAction)} ({link.Action.ToString()}) is missing an associated action.");
|
||||||
}
|
}
|
||||||
@ -354,6 +360,12 @@ namespace osu.Game
|
|||||||
/// <param name="beatmapId">The beatmap to show.</param>
|
/// <param name="beatmapId">The beatmap to show.</param>
|
||||||
public void ShowBeatmap(int beatmapId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId));
|
public void ShowBeatmap(int beatmapId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Show a wiki's page as an overlay
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The wiki page to show</param>
|
||||||
|
public void ShowWiki(string path) => waitForReady(() => wikiOverlay, _ => wikiOverlay.ShowPage(path));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Present a beatmap at song select immediately.
|
/// Present a beatmap at song select immediately.
|
||||||
/// The user should have already requested this interactively.
|
/// The user should have already requested this interactively.
|
||||||
@ -719,6 +731,7 @@ namespace osu.Game
|
|||||||
var changelogOverlay = loadComponentSingleFile(new ChangelogOverlay(), overlayContent.Add, true);
|
var changelogOverlay = loadComponentSingleFile(new ChangelogOverlay(), overlayContent.Add, true);
|
||||||
loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true);
|
loadComponentSingleFile(userProfile = new UserProfileOverlay(), overlayContent.Add, true);
|
||||||
loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), 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(skinEditor = new SkinEditorOverlay(screenContainer), overlayContent.Add);
|
||||||
|
|
||||||
loadComponentSingleFile(new LoginOverlay
|
loadComponentSingleFile(new LoginOverlay
|
||||||
@ -769,7 +782,7 @@ namespace osu.Game
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ensure only one of these overlays are open at once.
|
// 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)
|
foreach (var overlay in singleDisplayOverlays)
|
||||||
{
|
{
|
||||||
|
@ -92,6 +92,7 @@ namespace osu.Game.Overlays.Toolbar
|
|||||||
new ToolbarBeatmapListingButton(),
|
new ToolbarBeatmapListingButton(),
|
||||||
new ToolbarChatButton(),
|
new ToolbarChatButton(),
|
||||||
new ToolbarSocialButton(),
|
new ToolbarSocialButton(),
|
||||||
|
new ToolbarWikiButton(),
|
||||||
new ToolbarMusicButton(),
|
new ToolbarMusicButton(),
|
||||||
//new ToolbarButton
|
//new ToolbarButton
|
||||||
//{
|
//{
|
||||||
|
19
osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs
Normal file
19
osu.Game/Overlays/Toolbar/ToolbarWikiButton.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// 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 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,17 +5,22 @@ using System.Linq;
|
|||||||
using Markdig.Extensions.Yaml;
|
using Markdig.Extensions.Yaml;
|
||||||
using Markdig.Syntax;
|
using Markdig.Syntax;
|
||||||
using Markdig.Syntax.Inlines;
|
using Markdig.Syntax.Inlines;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Containers.Markdown;
|
using osu.Framework.Graphics.Containers.Markdown;
|
||||||
using osu.Game.Graphics.Containers.Markdown;
|
using osu.Game.Graphics.Containers.Markdown;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Wiki.Markdown
|
namespace osu.Game.Overlays.Wiki.Markdown
|
||||||
{
|
{
|
||||||
public class WikiMarkdownContainer : OsuMarkdownContainer
|
public class WikiMarkdownContainer : OsuMarkdownContainer
|
||||||
{
|
{
|
||||||
|
[Resolved]
|
||||||
|
private IAPIProvider api { get; set; }
|
||||||
|
|
||||||
public string CurrentPath
|
public string CurrentPath
|
||||||
{
|
{
|
||||||
set => DocumentUrl = $"{DocumentUrl}wiki/{value}";
|
set => DocumentUrl = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void AddMarkdownComponent(IMarkdownObject markdownObject, FillFlowContainer container, int level)
|
protected override void AddMarkdownComponent(IMarkdownObject markdownObject, FillFlowContainer container, int level)
|
||||||
|
82
osu.Game/Overlays/Wiki/WikiHeader.cs
Normal file
82
osu.Game/Overlays/Wiki/WikiHeader.cs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
// 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;
|
||||||
|
using System.Linq;
|
||||||
|
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 readonly Bindable<APIWikiPage> WikiPageData = new Bindable<APIWikiPage>();
|
||||||
|
|
||||||
|
public Action ShowIndexPage;
|
||||||
|
public Action ShowParentPage;
|
||||||
|
|
||||||
|
public WikiHeader()
|
||||||
|
{
|
||||||
|
TabControl.AddItem(index_page_string);
|
||||||
|
Current.Value = index_page_string;
|
||||||
|
|
||||||
|
WikiPageData.BindValueChanged(onWikiPageChange);
|
||||||
|
Current.BindValueChanged(onCurrentChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onWikiPageChange(ValueChangedEvent<APIWikiPage> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onCurrentChange(ValueChangedEvent<string> 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();
|
||||||
|
|
||||||
|
private class WikiHeaderTitle : OverlayTitle
|
||||||
|
{
|
||||||
|
public WikiHeaderTitle()
|
||||||
|
{
|
||||||
|
Title = "wiki";
|
||||||
|
Description = "knowledge base";
|
||||||
|
IconTexture = "Icons/Hexacons/wiki";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ using osu.Framework.Graphics.Shapes;
|
|||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers.Markdown;
|
using osu.Game.Graphics.Containers.Markdown;
|
||||||
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Overlays.Wiki.Markdown;
|
using osu.Game.Overlays.Wiki.Markdown;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
@ -37,7 +38,7 @@ namespace osu.Game.Overlays.Wiki
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OverlayColourProvider colourProvider)
|
private void load(OverlayColourProvider colourProvider, IAPIProvider api)
|
||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
@ -61,6 +62,7 @@ namespace osu.Game.Overlays.Wiki
|
|||||||
},
|
},
|
||||||
panelContainer = new WikiPanelMarkdownContainer(isFullWidth)
|
panelContainer = new WikiPanelMarkdownContainer(isFullWidth)
|
||||||
{
|
{
|
||||||
|
CurrentPath = $@"{api.WebsiteRootUrl}/wiki/",
|
||||||
Text = text,
|
Text = text,
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
|
148
osu.Game/Overlays/WikiOverlay.cs
Normal file
148
osu.Game/Overlays/WikiOverlay.cs
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
// 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 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<WikiHeader>
|
||||||
|
{
|
||||||
|
private const string index_path = @"main_page";
|
||||||
|
|
||||||
|
private readonly Bindable<string> path = new Bindable<string>(index_path);
|
||||||
|
|
||||||
|
private readonly Bindable<APIWikiPage> wikiData = new Bindable<APIWikiPage>();
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private IAPIProvider api { get; set; }
|
||||||
|
|
||||||
|
private GetWikiRequest request;
|
||||||
|
|
||||||
|
private CancellationTokenSource cancellationToken;
|
||||||
|
|
||||||
|
private bool displayUpdateRequired = true;
|
||||||
|
|
||||||
|
public WikiOverlay()
|
||||||
|
: base(OverlayColourScheme.Orange, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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<string> e)
|
||||||
|
{
|
||||||
|
cancellationToken?.Cancel();
|
||||||
|
request?.Cancel();
|
||||||
|
|
||||||
|
request = new GetWikiRequest(e.NewValue);
|
||||||
|
|
||||||
|
Loading.Show();
|
||||||
|
|
||||||
|
request.Success += response => Schedule(() => onSuccess(response));
|
||||||
|
request.Failure += _ => Schedule(() => LoadDisplay(Empty()));
|
||||||
|
|
||||||
|
api.PerformAsync(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSuccess(APIWikiPage response)
|
||||||
|
{
|
||||||
|
wikiData.Value = response;
|
||||||
|
|
||||||
|
if (response.Layout == index_path)
|
||||||
|
{
|
||||||
|
LoadDisplay(new WikiMainPage
|
||||||
|
{
|
||||||
|
Markdown = response.Markdown,
|
||||||
|
Padding = new MarginPadding
|
||||||
|
{
|
||||||
|
Vertical = 20,
|
||||||
|
Horizontal = 50,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LoadDisplay(new WikiMarkdownContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
CurrentPath = $@"{api.WebsiteRootUrl}/wiki/{path.Value}/",
|
||||||
|
Text = response.Markdown,
|
||||||
|
DocumentMargin = new MarginPadding(0),
|
||||||
|
DocumentPadding = new MarginPadding
|
||||||
|
{
|
||||||
|
Vertical = 20,
|
||||||
|
Left = 30,
|
||||||
|
Right = 50,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showParentPage()
|
||||||
|
{
|
||||||
|
var parentPath = string.Join("/", path.Value.Split('/').SkipLast(1));
|
||||||
|
ShowPage(parentPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
cancellationToken?.Cancel();
|
||||||
|
request?.Cancel();
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -35,7 +35,7 @@
|
|||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2021.528.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2021.528.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.525.0" />
|
||||||
<PackageReference Include="Sentry" Version="3.3.4" />
|
<PackageReference Include="Sentry" Version="3.3.4" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.28.2" />
|
<PackageReference Include="SharpCompress" Version="0.28.2" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.528.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.528.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.525.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
|
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
Loading…
Reference in New Issue
Block a user