Add support for multiple changelog files, add admin changelog (#20849)
This commit is contained in:
@@ -1,29 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Serialization.Markdown;
|
||||
using Robust.Shared.Serialization.Markdown.Mapping;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
|
||||
namespace Content.Client.Changelog
|
||||
{
|
||||
public sealed partial class ChangelogManager
|
||||
public sealed partial class ChangelogManager : IPostInjectInit
|
||||
{
|
||||
[Dependency] private readonly ILogManager _logManager = default!;
|
||||
[Dependency] private readonly IResourceManager _resource = default!;
|
||||
[Dependency] private readonly ISerializationManager _serialization = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configManager = default!;
|
||||
|
||||
private const string SawmillName = "changelog";
|
||||
public const string MainChangelogName = "Changelog";
|
||||
|
||||
private ISawmill _sawmill = default!;
|
||||
|
||||
public bool NewChangelogEntries { get; private set; }
|
||||
public int LastReadId { get; private set; }
|
||||
public int MaxId { get; private set; }
|
||||
@@ -51,17 +51,39 @@ namespace Content.Client.Changelog
|
||||
public async void Initialize()
|
||||
{
|
||||
// Open changelog purely to compare to the last viewed date.
|
||||
var changelog = await LoadChangelog();
|
||||
var changelogs = await LoadChangelog();
|
||||
UpdateChangelogs(changelogs);
|
||||
}
|
||||
|
||||
if (changelog.Count == 0)
|
||||
private void UpdateChangelogs(List<Changelog> changelogs)
|
||||
{
|
||||
if (changelogs.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MaxId = changelog.Max(c => c.Id);
|
||||
var mainChangelogs = changelogs.Where(c => c.Name == MainChangelogName).ToArray();
|
||||
if (mainChangelogs.Length == 0)
|
||||
{
|
||||
_sawmill.Error($"No changelog file found in Resources/Changelog with name {MainChangelogName}");
|
||||
return;
|
||||
}
|
||||
|
||||
var changelog = changelogs[0];
|
||||
if (mainChangelogs.Length > 1)
|
||||
{
|
||||
_sawmill.Error($"More than one file found in Resource/Changelog with name {MainChangelogName}");
|
||||
}
|
||||
|
||||
if (changelog.Entries.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MaxId = changelog.Entries.Max(c => c.Id);
|
||||
|
||||
var path = new ResPath($"/changelog_last_seen_{_configManager.GetCVar(CCVars.ServerId)}");
|
||||
if(_resource.UserData.TryReadAllText(path, out var lastReadIdText))
|
||||
if (_resource.UserData.TryReadAllText(path, out var lastReadIdText))
|
||||
{
|
||||
LastReadId = int.Parse(lastReadIdText);
|
||||
}
|
||||
@@ -71,20 +93,74 @@ namespace Content.Client.Changelog
|
||||
NewChangelogEntriesChanged?.Invoke();
|
||||
}
|
||||
|
||||
public Task<List<ChangelogEntry>> LoadChangelog()
|
||||
public Task<List<Changelog>> LoadChangelog()
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
var yamlData = _resource.ContentFileReadYaml(new ("/Changelog/Changelog.yml"));
|
||||
var changelogs = new List<Changelog>();
|
||||
var directory = new ResPath("/Changelog");
|
||||
foreach (var file in _resource.ContentFindFiles(new ResPath("/Changelog/")))
|
||||
{
|
||||
if (file.Directory != directory || file.Extension != "yml")
|
||||
continue;
|
||||
|
||||
if (yamlData.Documents.Count == 0)
|
||||
return new List<ChangelogEntry>();
|
||||
var yamlData = _resource.ContentFileReadYaml(file);
|
||||
|
||||
var node = (MappingDataNode)yamlData.Documents[0].RootNode.ToDataNode();
|
||||
return _serialization.Read<List<ChangelogEntry>>(node["Entries"], notNullableOverride: true);
|
||||
if (yamlData.Documents.Count == 0)
|
||||
continue;
|
||||
|
||||
var node = yamlData.Documents[0].RootNode.ToDataNodeCast<MappingDataNode>();
|
||||
var changelog = _serialization.Read<Changelog>(node, notNullableOverride: true);
|
||||
if (string.IsNullOrWhiteSpace(changelog.Name))
|
||||
changelog.Name = file.FilenameWithoutExtension;
|
||||
|
||||
changelogs.Add(changelog);
|
||||
}
|
||||
|
||||
changelogs.Sort((a, b) => a.Order.CompareTo(b.Order));
|
||||
return changelogs;
|
||||
});
|
||||
}
|
||||
|
||||
public void PostInject()
|
||||
{
|
||||
_sawmill = _logManager.GetSawmill(SawmillName);
|
||||
}
|
||||
|
||||
[DataDefinition]
|
||||
public sealed partial class Changelog
|
||||
{
|
||||
/// <summary>
|
||||
/// The name to use for this changelog.
|
||||
/// If left unspecified, the name of the file is used instead.
|
||||
/// Used during localization to find the user-displayed name of this changelog.
|
||||
/// </summary>
|
||||
[DataField("Name")]
|
||||
public string Name = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The individual entries in this changelog.
|
||||
/// These are not kept around in memory in the changelog manager.
|
||||
/// </summary>
|
||||
[DataField("Entries")]
|
||||
public List<ChangelogEntry> Entries = new();
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not this changelog will be displayed as a tab to non-admins.
|
||||
/// These are still loaded by all clients, but not shown if they aren't an admin,
|
||||
/// as they do not contain sensitive data and are publicly visible on GitHub.
|
||||
/// </summary>
|
||||
[DataField("AdminOnly")]
|
||||
public bool AdminOnly;
|
||||
|
||||
/// <summary>
|
||||
/// Used when ordering the changelog tabs for the user to see.
|
||||
/// Larger numbers are displayed later, smaller numbers are displayed earlier.
|
||||
/// </summary>
|
||||
[DataField("Order")]
|
||||
public int Order;
|
||||
}
|
||||
|
||||
[DataDefinition]
|
||||
public sealed partial class ChangelogEntry : ISerializationHooks
|
||||
{
|
||||
@@ -108,7 +184,7 @@ namespace Content.Client.Changelog
|
||||
}
|
||||
|
||||
[DataDefinition]
|
||||
public sealed partial class ChangelogChange : ISerializationHooks
|
||||
public sealed partial class ChangelogChange
|
||||
{
|
||||
[DataField("type")]
|
||||
public ChangelogLineType Type { get; private set; }
|
||||
|
||||
Reference in New Issue
Block a user