diff --git a/Content.Client/Changelog/ChangelogEntry.xaml b/Content.Client/Changelog/ChangelogEntry.xaml new file mode 100644 index 0000000000..3e1b2719d9 --- /dev/null +++ b/Content.Client/Changelog/ChangelogEntry.xaml @@ -0,0 +1,8 @@ + + + + + + diff --git a/Content.Client/Changelog/ChangelogEntry.xaml.cs b/Content.Client/Changelog/ChangelogEntry.xaml.cs new file mode 100644 index 0000000000..67b533a513 --- /dev/null +++ b/Content.Client/Changelog/ChangelogEntry.xaml.cs @@ -0,0 +1,66 @@ +using System.Numerics; +using Content.Client.Resources; +using Robust.Client.AutoGenerated; +using Robust.Client.Graphics; +using Robust.Client.ResourceManagement; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Utility; +using static Content.Client.Changelog.ChangelogManager; + +namespace Content.Client.Changelog; + +[GenerateTypedNameReferences] +public sealed partial class ChangelogEntry : Control +{ + [Dependency] private IResourceCache _resourceCache = default!; + + public ChangelogEntry() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + } + + public void SetText(FormattedMessage text) + { + Text.SetMessage(text); + } + + public void SetIcons(ChangelogLineType type, bool experimental) + { + var icon = GetIcon(type); + Icon.Texture = icon.Item1; + Icon.ModulateSelfOverride = icon.Item2; + + if (experimental) + { + var expIcon = new TextureRect + { + Texture = _resourceCache.GetTexture( + new ResPath("/Textures/Interface/Changelog/test-tube.svg.192dpi.png")), + TextureScale = new Vector2(0.5f, 0.5f), + VerticalAlignment = VAlignment.Top, + Margin = new Thickness(2, 4, 0, 2), + ModulateSelfOverride = Color.FromHex("#A0d16E"), + }; + + Icon.Parent!.AddChild(expIcon); + expIcon.SetPositionInParent(1); + } + } + + private (Texture, Color) GetIcon(ChangelogLineType type) + { + var (file, color) = type switch + { + ChangelogLineType.Add => ("plus.svg.192dpi.png", "#6ED18D"), + ChangelogLineType.Remove => ("minus.svg.192dpi.png", "#D16E6E"), + ChangelogLineType.Fix => ("bug.svg.192dpi.png", "#D1BA6E"), + ChangelogLineType.Tweak => ("wrench.svg.192dpi.png", "#6E96D1"), + _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) + }; + + return (_resourceCache.GetTexture(new ResPath($"/Textures/Interface/Changelog/{file}")), Color.FromHex(color)); + } +} diff --git a/Content.Client/Changelog/ChangelogManager.cs b/Content.Client/Changelog/ChangelogManager.cs index 1bf99af19d..c233873ee3 100644 --- a/Content.Client/Changelog/ChangelogManager.cs +++ b/Content.Client/Changelog/ChangelogManager.cs @@ -195,17 +195,23 @@ namespace Content.Client.Changelog [DataDefinition] public sealed partial class ChangelogEntry { - [DataField("id")] + [DataField] public int Id { get; private set; } - [DataField("author")] + [DataField] public string Author { get; private set; } = ""; [DataField] public DateTime Time { get; private set; } - [DataField("changes")] + [DataField] public List Changes { get; private set; } = default!; + + /// + /// Labels attached to the related PR, passed on via the SS14.Changelog parser. + /// + [DataField] + public List Labels { get; private set; } = []; } [DataDefinition] diff --git a/Content.Client/Changelog/ChangelogTab.xaml.cs b/Content.Client/Changelog/ChangelogTab.xaml.cs index 24d4f39036..3cbc2a4547 100644 --- a/Content.Client/Changelog/ChangelogTab.xaml.cs +++ b/Content.Client/Changelog/ChangelogTab.xaml.cs @@ -7,7 +7,6 @@ using Robust.Client.ResourceManagement; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; -using Robust.Shared.ContentPack; using Robust.Shared.Utility; using static Content.Client.Changelog.ChangelogManager; using static Robust.Client.UserInterface.Controls.BoxContainer; @@ -22,6 +21,11 @@ public sealed partial class ChangelogTab : Control public bool AdminOnly; + /// + /// Changelog is from a PR marked "Experimental" and should therefore have an additional icon. + /// + private static string _experimentalString = "Intent: Experimental"; + public ChangelogTab() { RobustXamlLoader.Load(this); @@ -134,43 +138,17 @@ public sealed partial class ChangelogTab : Control FormattedMessage.FromMarkupOrThrow(Loc.GetString("changelog-author-changed", ("author", FormattedMessage.EscapeText(author))))); ChangelogBody.AddChild(authorLabel); - foreach (var change in groupedEntry.SelectMany(c => c.Changes)) + foreach (var (labels, changes) in groupedEntry.Select(c => (c.Labels, c.Changes))) { - var text = new RichTextLabel(); - text.SetMessage(FormattedMessage.FromUnformatted(change.Message)); - ChangelogBody.AddChild(new BoxContainer + foreach (var change in changes) { - Orientation = LayoutOrientation.Horizontal, - Margin = new Thickness(14, 1, 10, 2), - Children = - { - GetIcon(change.Type), - text - } - }); + var entry = new ChangelogEntry(); + entry.SetText(FormattedMessage.FromUnformatted(change.Message)); + entry.SetIcons(change.Type, labels.Contains(_experimentalString)); + ChangelogBody.AddChild(entry); + } } } } } - - private TextureRect GetIcon(ChangelogLineType type) - { - var (file, color) = type switch - { - ChangelogLineType.Add => ("plus.svg.192dpi.png", "#6ED18D"), - ChangelogLineType.Remove => ("minus.svg.192dpi.png", "#D16E6E"), - ChangelogLineType.Fix => ("bug.svg.192dpi.png", "#D1BA6E"), - ChangelogLineType.Tweak => ("wrench.svg.192dpi.png", "#6E96D1"), - _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) - }; - - return new TextureRect - { - Texture = _resourceCache.GetTexture(new ResPath($"/Textures/Interface/Changelog/{file}")), - VerticalAlignment = VAlignment.Top, - TextureScale = new Vector2(0.5f, 0.5f), - Margin = new Thickness(2, 4, 6, 2), - ModulateSelfOverride = Color.FromHex(color) - }; - } } diff --git a/Resources/Textures/Interface/Changelog/attributions.yml b/Resources/Textures/Interface/Changelog/attributions.yml new file mode 100644 index 0000000000..da5a3dcee7 --- /dev/null +++ b/Resources/Textures/Interface/Changelog/attributions.yml @@ -0,0 +1,4 @@ +- files: ["test-tube.svg"] + license: "CC-BY-4.0" + copyright: "Solar Icons" + source: "https://www.svgrepo.com/svg/526351/test-tube-minimalistic" diff --git a/Resources/Textures/Interface/Changelog/test-tube.svg b/Resources/Textures/Interface/Changelog/test-tube.svg new file mode 100644 index 0000000000..54d968351a --- /dev/null +++ b/Resources/Textures/Interface/Changelog/test-tube.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + diff --git a/Resources/Textures/Interface/Changelog/test-tube.svg.192dpi.png b/Resources/Textures/Interface/Changelog/test-tube.svg.192dpi.png new file mode 100644 index 0000000000..dd38ab7fac Binary files /dev/null and b/Resources/Textures/Interface/Changelog/test-tube.svg.192dpi.png differ diff --git a/Resources/Textures/Interface/Changelog/test-tube.svg.192dpi.png.yml b/Resources/Textures/Interface/Changelog/test-tube.svg.192dpi.png.yml new file mode 100644 index 0000000000..5c43e23305 --- /dev/null +++ b/Resources/Textures/Interface/Changelog/test-tube.svg.192dpi.png.yml @@ -0,0 +1,2 @@ +sample: + filter: true diff --git a/Tools/actions_changelog_rss.py b/Tools/actions_changelog_rss.py index 5c696f5b01..ebcbe82272 100755 --- a/Tools/actions_changelog_rss.py +++ b/Tools/actions_changelog_rss.py @@ -55,6 +55,9 @@ TYPES_TO_EMOJI = { "Tweak": "โš’๏ธ" } +EXPERIMENTAL_LABEL = "Intent: Experimental" +EXPERIMENTAL_EMOJI = "๐Ÿงช" + XML_NS = "https://spacestation14.com/changelog_rss" XML_NS_B = f"{{{XML_NS}}}" @@ -181,6 +184,8 @@ def generate_description_for_entries(entries: List[Any]) -> str: for entry in sorted(group, key=lambda x: x["time"]): for change in entry["changes"]: emoji = TYPES_TO_EMOJI.get(change["type"], "") + if EXPERIMENTAL_LABEL in entry["labels"] + emoji = f"{emoji}{EXPERIMENTAL_EMOJI}" msg = change["message"] desc.write(f"
  • {emoji} {html.escape(msg)}
  • ") diff --git a/Tools/actions_changelogs_since_last_run.py b/Tools/actions_changelogs_since_last_run.py index 876fb65aa5..b80463fd21 100755 --- a/Tools/actions_changelogs_since_last_run.py +++ b/Tools/actions_changelogs_since_last_run.py @@ -31,6 +31,9 @@ CHANGELOG_FILE = "Resources/Changelog/Changelog.yml" TYPES_TO_EMOJI = {"Fix": "๐Ÿ›", "Add": "๐Ÿ†•", "Remove": "โŒ", "Tweak": "โš’๏ธ"} +EXPERIMENTAL_LABEL = "Intent: Experimental" +EXPERIMENTAL_EMOJI = "๐Ÿงช" + ChangelogEntry = dict[str, Any] @@ -239,6 +242,9 @@ def changelog_entries_to_message_lines(entries: Iterable[ChangelogEntry]) -> lis emoji = TYPES_TO_EMOJI.get(change["type"], "โ“") message = change["message"] + if EXPERIMENTAL_LABEL in entry["labels"] + emoji = f"{emoji}{EXPERIMENTAL_EMOJI}" + message_lines.append(create_change_line(emoji, message, url)) return message_lines