Add support for multiple changelog files, add admin changelog (#20849)
This commit is contained in:
@@ -1,28 +1,22 @@
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Client.Resources;
|
||||
using Content.Client.Administration.Managers;
|
||||
using Content.Client.Stylesheets;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Client.UserInterface.Systems.EscapeMenu;
|
||||
using Content.Shared.Administration;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Utility;
|
||||
using static Content.Client.Changelog.ChangelogManager;
|
||||
using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||
|
||||
namespace Content.Client.Changelog
|
||||
{
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class ChangelogWindow : FancyWindow
|
||||
{
|
||||
[Dependency] private readonly IClientAdminManager _adminManager = default!;
|
||||
[Dependency] private readonly ChangelogManager _changelog = default!;
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
|
||||
public ChangelogWindow()
|
||||
{
|
||||
@@ -39,154 +33,84 @@ namespace Content.Client.Changelog
|
||||
PopulateChangelog();
|
||||
}
|
||||
|
||||
protected override void EnteredTree()
|
||||
{
|
||||
base.EnteredTree();
|
||||
_adminManager.AdminStatusUpdated += OnAdminStatusUpdated;
|
||||
}
|
||||
|
||||
protected override void ExitedTree()
|
||||
{
|
||||
base.ExitedTree();
|
||||
_adminManager.AdminStatusUpdated -= OnAdminStatusUpdated;
|
||||
}
|
||||
|
||||
private void OnAdminStatusUpdated()
|
||||
{
|
||||
TabsUpdated();
|
||||
}
|
||||
|
||||
private async void PopulateChangelog()
|
||||
{
|
||||
// Changelog is not kept in memory so load it again.
|
||||
var changelog = await _changelog.LoadChangelog();
|
||||
var changelogs = await _changelog.LoadChangelog();
|
||||
|
||||
var byDay = changelog
|
||||
.GroupBy(e => e.Time.ToLocalTime().Date)
|
||||
.OrderByDescending(c => c.Key);
|
||||
Tabs.DisposeAllChildren();
|
||||
|
||||
var hasRead = _changelog.MaxId <= _changelog.LastReadId;
|
||||
foreach (var dayEntries in byDay)
|
||||
var i = 0;
|
||||
foreach (var changelog in changelogs)
|
||||
{
|
||||
var day = dayEntries.Key;
|
||||
var tab = new ChangelogTab { AdminOnly = changelog.AdminOnly };
|
||||
tab.PopulateChangelog(changelog);
|
||||
|
||||
var groupedEntries = dayEntries
|
||||
.GroupBy(c => (c.Author, Read: c.Id <= _changelog.LastReadId))
|
||||
.OrderBy(c => c.Key.Read)
|
||||
.ThenBy(c => c.Key.Author);
|
||||
|
||||
string dayNice;
|
||||
var today = DateTime.Today;
|
||||
if (day == today)
|
||||
dayNice = Loc.GetString("changelog-today");
|
||||
else if (day == today.AddDays(-1))
|
||||
dayNice = Loc.GetString("changelog-yesterday");
|
||||
else
|
||||
dayNice = day.ToShortDateString();
|
||||
|
||||
ChangelogBody.AddChild(new Label
|
||||
{
|
||||
Text = dayNice,
|
||||
StyleClasses = { StyleBase.StyleClassLabelHeading },
|
||||
Margin = new Thickness(4, 6, 0, 0)
|
||||
});
|
||||
|
||||
var first = true;
|
||||
|
||||
foreach (var groupedEntry in groupedEntries)
|
||||
{
|
||||
var (author, read) = groupedEntry.Key;
|
||||
|
||||
if (!first)
|
||||
{
|
||||
ChangelogBody.AddChild(new Control { Margin = new Thickness(4) });
|
||||
}
|
||||
|
||||
if (read && !hasRead)
|
||||
{
|
||||
hasRead = true;
|
||||
|
||||
var upArrow =
|
||||
_resourceCache.GetTexture("/Textures/Interface/Changelog/up_arrow.svg.192dpi.png");
|
||||
|
||||
var readDivider = new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Vertical
|
||||
};
|
||||
|
||||
var hBox = new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Horizontal,
|
||||
HorizontalAlignment = HAlignment.Center,
|
||||
Children =
|
||||
{
|
||||
new TextureRect
|
||||
{
|
||||
Texture = upArrow,
|
||||
ModulateSelfOverride = Color.FromHex("#888"),
|
||||
TextureScale = new Vector2(0.5f, 0.5f),
|
||||
Margin = new Thickness(4, 3),
|
||||
VerticalAlignment = VAlignment.Bottom
|
||||
},
|
||||
new Label
|
||||
{
|
||||
Align = Label.AlignMode.Center,
|
||||
Text = Loc.GetString("changelog-new-changes"),
|
||||
FontColorOverride = Color.FromHex("#888"),
|
||||
},
|
||||
new TextureRect
|
||||
{
|
||||
Texture = upArrow,
|
||||
ModulateSelfOverride = Color.FromHex("#888"),
|
||||
TextureScale = new Vector2(0.5f, 0.5f),
|
||||
Margin = new Thickness(4, 3),
|
||||
VerticalAlignment = VAlignment.Bottom
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
readDivider.AddChild(hBox);
|
||||
readDivider.AddChild(new PanelContainer { StyleClasses = { StyleBase.ClassLowDivider } });
|
||||
ChangelogBody.AddChild(readDivider);
|
||||
|
||||
if (first)
|
||||
readDivider.SetPositionInParent(ChangelogBody.ChildCount - 2);
|
||||
}
|
||||
|
||||
first = false;
|
||||
|
||||
var authorLabel = new RichTextLabel
|
||||
{
|
||||
Margin = new Thickness(6, 0, 0, 0),
|
||||
};
|
||||
authorLabel.SetMessage(
|
||||
FormattedMessage.FromMarkup(Loc.GetString("changelog-author-changed", ("author", author))));
|
||||
ChangelogBody.AddChild(authorLabel);
|
||||
|
||||
foreach (var change in groupedEntry.SelectMany(c => c.Changes))
|
||||
{
|
||||
var text = new RichTextLabel();
|
||||
text.SetMessage(FormattedMessage.FromMarkup(change.Message));
|
||||
ChangelogBody.AddChild(new BoxContainer
|
||||
{
|
||||
Orientation = LayoutOrientation.Horizontal,
|
||||
Margin = new Thickness(14, 1, 10, 2),
|
||||
Children =
|
||||
{
|
||||
GetIcon(change.Type),
|
||||
text
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Tabs.AddChild(tab);
|
||||
Tabs.SetTabTitle(i++, Loc.GetString($"changelog-tab-title-{changelog.Name}"));
|
||||
}
|
||||
|
||||
var version = typeof(ChangelogWindow).Assembly.GetName().Version ?? new Version(1, 0);
|
||||
VersionLabel.Text = Loc.GetString("changelog-version-tag", ("version", version.ToString()));
|
||||
|
||||
TabsUpdated();
|
||||
}
|
||||
|
||||
private TextureRect GetIcon(ChangelogLineType type)
|
||||
private void TabsUpdated()
|
||||
{
|
||||
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)
|
||||
};
|
||||
var tabs = Tabs.Children.OfType<ChangelogTab>().ToArray();
|
||||
var isAdmin = _adminManager.IsAdmin(true);
|
||||
|
||||
return new TextureRect
|
||||
var visibleTabs = 0;
|
||||
int? firstVisible = null;
|
||||
for (var i = 0; i < tabs.Length; i++)
|
||||
{
|
||||
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)
|
||||
};
|
||||
var tab = tabs[i];
|
||||
|
||||
if (!tab.AdminOnly || isAdmin)
|
||||
{
|
||||
Tabs.SetTabVisible(i, true);
|
||||
tab.Visible = true;
|
||||
visibleTabs++;
|
||||
firstVisible ??= i;
|
||||
}
|
||||
else
|
||||
{
|
||||
Tabs.SetTabVisible(i, false);
|
||||
tab.Visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
Tabs.TabsVisible = visibleTabs > 1;
|
||||
|
||||
// Current tab became invisible, select the first one that is visible
|
||||
if (!Tabs.GetTabVisible(Tabs.CurrentTab) && firstVisible != null)
|
||||
{
|
||||
Tabs.CurrentTab = firstVisible.Value;
|
||||
}
|
||||
|
||||
// We are only displaying one tab, hide its header
|
||||
if (!Tabs.TabsVisible && firstVisible != null)
|
||||
{
|
||||
Tabs.SetTabVisible(firstVisible.Value, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user