diff --git a/osu.Game.Rulesets.Karaoke/Online/API/Requests/Responses/APIChangelogBuild.cs b/osu.Game.Rulesets.Karaoke/Online/API/Requests/Responses/APIChangelogBuild.cs index ca07baff6..aa5de09e2 100644 --- a/osu.Game.Rulesets.Karaoke/Online/API/Requests/Responses/APIChangelogBuild.cs +++ b/osu.Game.Rulesets.Karaoke/Online/API/Requests/Responses/APIChangelogBuild.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Text.RegularExpressions; namespace osu.Game.Rulesets.Karaoke.Online.API.Requests.Responses; @@ -76,4 +77,14 @@ public APIChangelogBuild CreateBuildWithContent(string content) PublishedAt = PublishedAt, }; } + + public string? GetFormattedContent() + { + if (Content == null) + return null; + + // for able to parsing the badge, need to replace the " [content] " with " [content](content) "; + const string pattern = @"(?<=\s)\[(.*?)\](?=\s)"; + return Regex.Replace(Content, pattern, m => $"[{m.Groups[1].Value}]({m.Groups[1].Value})"); + } } diff --git a/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangeLogMarkdownContainer.cs b/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangeLogMarkdownContainer.cs index c1ce7c354..a4563fc1b 100644 --- a/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangeLogMarkdownContainer.cs +++ b/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangeLogMarkdownContainer.cs @@ -5,10 +5,14 @@ using System.Linq; using Markdig.Syntax.Inlines; using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Layout; using osu.Game.Graphics; using osu.Game.Graphics.Containers.Markdown; +using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Karaoke.Online.API.Requests.Responses; using osuTK; @@ -20,7 +24,7 @@ public ChangeLogMarkdownContainer(APIChangelogBuild build) { DocumentUrl = build.DocumentUrl; RootUrl = build.RootUrl; - Text = build.Content; + Text = build.GetFormattedContent(); } public override OsuMarkdownTextFlowContainer CreateTextFlow() => new ChangeLogMarkdownTextFlowContainer(); @@ -44,12 +48,25 @@ protected override void AddLinkText(string text, LinkInline linkInline) var pullRequestInfo = ChangelogPullRequestInfo.GetPullRequestInfoFromLink(text, linkInline.Url); - if (pullRequestInfo == null) + if (pullRequestInfo != null) { - base.AddLinkText(text, linkInline); + addPullRequestInfo(pullRequestInfo); return; } + var badgeInfo = ChangelogBadgeInfo.GetBadgeInfoFromLink(text); + + if (badgeInfo != null) + { + addBadgeInfo(badgeInfo); + return; + } + + base.AddLinkText(text, linkInline); + } + + private void addPullRequestInfo(ChangelogPullRequestInfo pullRequestInfo) + { var pullRequests = pullRequestInfo.PullRequests; var users = pullRequestInfo.Users; @@ -57,14 +74,15 @@ protected override void AddLinkText(string text, LinkInline linkInline) { AddText("("); - foreach (var pullRequest in pullRequests) + for (int index = 0; index < pullRequests.Length; index++) { - AddDrawable(new OsuMarkdownLinkText($"{text}#{pullRequest.Number}", new LinkInline + var pullRequest = pullRequests[index]; + AddDrawable(new OsuMarkdownLinkText($"{pullRequestInfo.RepoName}#{pullRequest.Number}", new LinkInline { Url = pullRequest.Url, })); - if (pullRequest != pullRequests.LastOrDefault()) + if (index != pullRequests.Length - 1) AddText(", "); } @@ -81,7 +99,7 @@ protected override void AddLinkText(string text, LinkInline linkInline) }); AddDrawable(new UserLinkText(user.UserName, new LinkInline { - Url = user.UserUrl, + Url = user.Url, }) { Scale = textScale, @@ -90,6 +108,15 @@ protected override void AddLinkText(string text, LinkInline linkInline) } } + private void addBadgeInfo(ChangelogBadgeInfo badgeInfo) + { + AddDrawable(new Badge + { + BadgeText = badgeInfo.Text, + BadgeColour = badgeInfo.Color, + }); + } + /// /// Override to limit image display size /// @@ -145,5 +172,46 @@ public UserLinkText(string text, LinkInline linkInline) Padding = new MarginPadding { Top = 6 }; } } + + private partial class Badge : CompositeDrawable + { + private readonly Box background; + private readonly OsuSpriteText text; + + public Badge() + { + AutoSizeAxes = Axes.Both; + Masking = true; + CornerRadius = 5; + + InternalChildren = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Colour4.White, + }, + text = new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Margin = new MarginPadding { Horizontal = 5, Vertical = 3 }, + }, + }; + } + + public ColourInfo BadgeColour + { + get => background.Colour; + set => background.Colour = value; + } + + public string BadgeText + { + get => text.Text.ToString(); + set => text.Text = value; + } + } } } diff --git a/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangelogBadgeInfo.cs b/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangelogBadgeInfo.cs new file mode 100644 index 000000000..a2d11be15 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangelogBadgeInfo.cs @@ -0,0 +1,43 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Extensions.Color4Extensions; +using osuTK.Graphics; + +namespace osu.Game.Rulesets.Karaoke.Overlays.Changelog; + +public class ChangelogBadgeInfo +{ + // follow the definition in the https://github.com/karaoke-dev/karaoke-dev.github.io/blob/master/layouts/partials/script/badge.html + private static readonly IDictionary colour_mappings = new Dictionary + { + { "outdated", "#808080" }, + { "rejected", "#FF0000" }, + }; + + public Color4 Color { get; init; } = Color4.White; + + public string Text { get; init; } = string.Empty; + + /// + /// Trying to parse the badge from the text. + /// + /// + /// [outdated]
+ /// [rejected] + ///
+ /// Link text + /// + public static ChangelogBadgeInfo? GetBadgeInfoFromLink(string text) + { + if (!colour_mappings.TryGetValue(text, out string? repoUrl)) + return null; + + return new ChangelogBadgeInfo + { + Text = text, + Color = Color4Extensions.FromHex(repoUrl), + }; + } +} diff --git a/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangelogPullRequestInfo.cs b/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangelogPullRequestInfo.cs index cab7994bc..7df1e8142 100644 --- a/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangelogPullRequestInfo.cs +++ b/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangelogPullRequestInfo.cs @@ -22,22 +22,35 @@ public class ChangelogPullRequestInfo { "font-package", "https://github.com/karaoke-dev/osu-framework-font/" }, }; - public PullRequestInfo[] PullRequests { get; set; } = Array.Empty(); + public string RepoName { get; init; } = string.Empty; - public UserInfo[] Users { get; set; } = Array.Empty(); + public PullRequestInfo[] PullRequests { get; init; } = Array.Empty(); - public class PullRequestInfo + public UserInfo[] Users { get; init; } = Array.Empty(); + + public readonly struct PullRequestInfo { - public int Number { get; set; } + public PullRequestInfo(string repoName, int number) + { + Number = number; + Url = new Uri(new Uri(repo_urls[repoName]), $"pull/{number}").AbsoluteUri; + } + + public int Number { get; } = 0; - public string Url { get; set; } = string.Empty; + public string Url { get; } = string.Empty; } - public class UserInfo + public readonly struct UserInfo { - public string UserName { get; set; } = string.Empty; + public UserInfo(string useName) + { + UserName = useName; + } + + public string UserName { get; } = string.Empty; - public string UserUrl => $"https://github.com/{UserName}"; + public string Url => $"https://github.com/{UserName}"; } /// @@ -50,12 +63,12 @@ public class UserInfo /// @andy840119
/// @andy@andy840119 /// - /// Link text - /// Link url + /// Link text + /// Link url /// - public static ChangelogPullRequestInfo? GetPullRequestInfoFromLink(string text, string url) + public static ChangelogPullRequestInfo? GetPullRequestInfoFromLink(string repo, string info) { - if (!repo_urls.ContainsKey(text)) + if (!repo_urls.ContainsKey(repo)) return null; const string pull_request_key = "pull_request"; @@ -63,7 +76,7 @@ public class UserInfo const string pull_request_regex = $"#(?<{pull_request_key}>[0-9]+)|@(?<{username_key}>[0-9A-z]+)"; // note: should have at least one pr number or one username, - var result = Regex.Matches(url, pull_request_regex, RegexOptions.IgnoreCase); + var result = Regex.Matches(info, pull_request_regex, RegexOptions.IgnoreCase); if (!result.Any()) return null; @@ -77,21 +90,9 @@ public class UserInfo return new ChangelogPullRequestInfo { - PullRequests = prs.Select(x => generatePullRequestInfo(repo_urls[text], x)).ToArray(), - Users = usernames.Select(generateUserInfo).ToArray(), + RepoName = repo, + PullRequests = prs.Select(pr => new PullRequestInfo(repo, int.Parse(pr))).ToArray(), + Users = usernames.Select(userName => new UserInfo(userName)).ToArray(), }; - - static PullRequestInfo generatePullRequestInfo(string url, string pr) => - new() - { - Number = int.Parse(pr), - Url = new Uri(new Uri(url), $"pull/{pr}").AbsoluteUri, - }; - - static UserInfo generateUserInfo(string username) => - new() - { - UserName = username, - }; } } diff --git a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Content/Components/Lyrics/Carets/DrawableRecordingTimeTagCaret.cs b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Content/Components/Lyrics/Carets/DrawableRecordingTimeTagCaret.cs index b26f9269a..f59601c79 100644 --- a/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Content/Components/Lyrics/Carets/DrawableRecordingTimeTagCaret.cs +++ b/osu.Game.Rulesets.Karaoke/Screens/Edit/Beatmaps/Lyrics/Content/Components/Lyrics/Carets/DrawableRecordingTimeTagCaret.cs @@ -110,7 +110,7 @@ private partial class TextIndexInfo : CompositeDrawable { private const int border_radius = 5; - private DrawableTimeTag currentTextTag = null!; + private DrawableTimeTag currentTimeTag = null!; private FillFlowContainer pendingTimeTags = null!; [Resolved] @@ -175,7 +175,7 @@ private void load(LyricEditorColourProvider colourProvider, ILyricEditorState st RelativeSizeAxes = Axes.Both, Colour = colourProvider.Background5(state.Mode), }, - currentTextTag = new DrawableTimeTag + currentTimeTag = new DrawableTimeTag { Anchor = Anchor.Centre, Origin = Anchor.Centre, @@ -199,7 +199,7 @@ private void load(LyricEditorColourProvider colourProvider, ILyricEditorState st public void UpdateCaret(RecordingTimeTagCaretPosition caret) { - currentTextTag.TimeTag = caret.TimeTag; + currentTimeTag.TimeTag = caret.TimeTag; int paddingIndicator = caret.GetPaddingTextIndex(); pendingTimeTags.Clear();