Files
minecraft-modpack-updater/ModpackUpdater.Apps.Manager/Features/SharedFunctions.cs

285 lines
9.5 KiB
C#

using System.Text;
using Avalonia.Media;
using ModpackUpdater.Apps.Manager.Api.Model;
using ModpackUpdater.Apps.Manager.LangRes;
using ModpackUpdater.Apps.Manager.Ui;
using ModpackUpdater.Apps.Manager.Ui.Models.MainWindow;
using ModpackUpdater.Apps.Manager.Ui.Models.UpdatesCollectorViewMode;
using ModpackUpdater.Manager;
using OfficeOpenXml;
using OfficeOpenXml.Table;
using Pilz.UI.AvaloniaUI.Dialogs;
namespace ModpackUpdater.Apps.Manager.Features;
internal static class SharedFunctions
{
private static readonly IImage? imageSourceSuccess = AppGlobals.Symbols.GetImageSource(AppSymbols.done);
private static readonly IImage? imageSourceWorking = AppGlobals.Symbols.GetImageSource(AppSymbols.hourglass);
private static readonly IImage? imageSourceFailed = AppGlobals.Symbols.GetImageSource(AppSymbols.close);
public static async Task CheckActionHealthy(IMainApi api, params MainWindowGridRow[] rows)
{
var rowsCount = rows.Length;
var failed = false;
var factory = new ModpackFactory();
api.Model.Progress.Start(rowsCount);
for (var i = 0; i < rowsCount; i++)
{
var row = rows[i];
if (row.SourceType == SourceType.DirectLink)
continue;
row.StateImage = imageSourceWorking;
try
{
var result = await factory.ResolveSourceUrl(row.Action);
failed = string.IsNullOrWhiteSpace(result);
}
catch
{
// Ignore
}
if (api.HasClosed)
return;
row.StateImage = failed ? imageSourceFailed : imageSourceSuccess;
api.Model.Progress.Set(i);
}
api.Model.Progress.Stop();
}
public static async Task<bool> CollectUpdates(IMainApi api, params InstallAction[] actions)
{
if (api.Model.CurrentWorkspace?.UpdateInfos is null || api.Model.CurrentTreeNodes is null)
return false;
// Collect updates
var result = await AvaloniaFlyoutBase.Show(new UpdatesCollectorView(api.Model.CurrentWorkspace, actions), api.MainWindow);
if (api.HasClosed || result.Result is not ModUpdates resultUpdates)
return false;
// Collect versions with changes
var updates = resultUpdates.List.Where(update => update.Origin.SourceTag != update.AvailableVersions[update.NewVersion].Tag).ToList();
// Path install actions
foreach (var update in updates)
{
var sourceTag = update.AvailableVersions[update.NewVersion].Tag;
if (api.Model.CurrentGridRows.List.Items.FirstOrDefault(n => n.Action == update.Origin) is { } row)
row.SourceTag = sourceTag;
else
update.Origin.SourceTag = sourceTag;
}
// Create update actions
var updateSet = new UpdateInfo();
foreach (var update in updates)
{
updateSet.Actions.Add(new()
{
InheritFrom = update.Origin.Id,
});
}
api.Model.CurrentWorkspace.UpdateInfos.Updates.Insert(0, updateSet);
// Add update to ui
api.Model.CurrentTreeNodes[1].Nodes.Insert(0, new ActionSetTreeNode(updateSet));
return true;
}
public static async Task FindNewDirectLinks(IMainApi api, params MainWindowGridRow[] rows)
{
var factory = new ModpackFactory();
api.Model.Progress.Start(rows.Length);
for (var i = 0; i < rows.Length; i++)
{
var row = rows[i];
if (row.SourceType == SourceType.DirectLink)
continue;
row.StateImage = imageSourceWorking;
try
{
row.SourceUrl = await factory.ResolveSourceUrl(row.Action);
row.StateImage = imageSourceSuccess;
}
catch (Exception)
{
row.StateImage = imageSourceFailed;
}
if (api.HasClosed)
return;
api.Model.Progress.Set(i);
}
api.Model.Progress.Stop();
}
public static void ClearDirectLinks(IMainApi api, params MainWindowGridRow[] rows)
{
api.Model.Progress.Start(rows.Length);
for (var i = 0; i < rows.Length; i++)
{
var row = rows[i];
if (row.SourceType != SourceType.DirectLink)
row.SourceUrl = null;
row.StateImage = null;
api.Model.Progress.Set(i);
}
api.Model.Progress.Stop();
}
public static string GenerateChangelog(InstallInfos installInfos, UpdateInfo updateInfos)
{
var log = new StringBuilder();
foreach (var action in updateInfos.Actions.OrderBy(n => n.Type))
{
// Create copy
var copy = new UpdateAction();
ModpackInstaller.DuplicateTo(action, copy);
// Resolve inherit
if (!string.IsNullOrWhiteSpace(copy.InheritFrom))
ModpackInstaller.ResolveInherit(copy, installInfos);
if (string.IsNullOrWhiteSpace(copy.Name) || copy.Type != UpdateActionType.Update)
continue;
// Append bullet
log.Append('-');
// Append action indicator
log.Append(' ');
log.Append("⚒️");
// Append name
log.Append(' ');
log.Append("**");
log.Append(copy.Name);
log.Append("**");
// Append new version
if (!string.IsNullOrWhiteSpace(copy.SourceTag))
{
log.Append(' ');
log.Append('`');
log.Append(copy.SourceTag);
log.Append('`');
}
// Append new line
log.AppendLine();
}
return log.ToString().TrimEnd();
}
public static string GenerateModlistAsMarkdown(InstallInfos installInfos)
{
var sb = new StringBuilder();
sb.Append("|" + ActionsListLangRes.Col_Name);
sb.Append("|" + ActionsListLangRes.Col_SrcTag);
sb.Append("|" + ActionsListLangRes.Col_Side);
sb.Append("|" + ActionsListLangRes.Col_SrcType);
sb.Append("|" + ActionsListLangRes.Col_SrcOwner);
sb.Append("|" + ActionsListLangRes.Col_SrcName);
sb.AppendLine("|");
sb.AppendLine("|---|---|---|---|---|---|");
// Rows
foreach (var action in installInfos.Actions.OrderBy(n => n.Name))
{
if (action.IsExtra || action.IsZip || string.IsNullOrWhiteSpace(action.Id) || !action.Id.StartsWith("mod:"))
continue;
if (string.IsNullOrWhiteSpace(action.Website))
sb.Append($"|{action.Name}");
else
sb.Append($"|[{action.Name}]({action.Website})");
if (string.IsNullOrWhiteSpace(action.SourceUrl))
sb.Append($"|{action.SourceTag}");
else
sb.Append($"|[{action.SourceTag}]({action.GetSourceUrl(installInfos.Version)})");
sb.Append($"|{action.Side.ToString()}");
sb.Append($"|{action.SourceType}");
sb.Append($"|{action.SourceOwner}");
sb.Append($"|{action.SourceName}");
sb.AppendLine("|");
}
return sb.ToString().TrimEnd();
}
public static ExcelPackage GenerateModlistAsExcel(InstallInfos installInfos)
{
var pkg = new ExcelPackage();
var ws = pkg.Workbook.Worksheets.Add(string.Format(GeneralLangRes.ModlistForVersionX, installInfos.Version));
var cr = 1;
var cc = 1;
// Header
ws.Cells[cr, cc++].Value = ActionsListLangRes.Col_Name;
ws.Cells[cr, cc++].Value = ActionsListLangRes.Col_SrcTag;
ws.Cells[cr, cc++].Value = ActionsListLangRes.Col_Side;
ws.Cells[cr, cc++].Value = ActionsListLangRes.Col_SrcType;
ws.Cells[cr, cc++].Value = ActionsListLangRes.Col_SrcOwner;
ws.Cells[cr, cc++].Value = ActionsListLangRes.Col_SrcName;
cr += 1;
cc = 1;
// Rows
foreach (var action in installInfos.Actions.OrderBy(n => n.Name))
{
if (action.IsExtra || action.IsZip || string.IsNullOrWhiteSpace(action.Id) || !action.Id.StartsWith("mod:"))
continue;
var cellName = ws.Cells[cr, cc++];
cellName.Value = action.Name;
if (!string.IsNullOrWhiteSpace(action.Website))
cellName.SetHyperlink(new Uri(action.Website));
var cellTag = ws.Cells[cr, cc++];
cellTag.Value = string.IsNullOrWhiteSpace(action.SourceTag) ? "direct link" : action.SourceTag;
if (!string.IsNullOrWhiteSpace(action.SourceUrl))
cellTag.SetHyperlink(new Uri(action.GetSourceUrl(installInfos.Version)));
ws.Cells[cr, cc++].Value = action.Side.ToString();
ws.Cells[cr, cc++].Value = action.SourceType;
ws.Cells[cr, cc++].Value = action.SourceOwner;
ws.Cells[cr, cc++].Value = action.SourceName;
cr += 1;
cc = 1;
}
// Styling
cc = 1;
ws.Column(cc++).Width = 30;
ws.Column(cc++).Width = 20;
ws.Column(cc++).Width = 10;
ws.Column(cc++).Width = 20;
ws.Column(cc++).Width = 20;
ws.Column(cc++).Width = 30;
var tableDef = ws.Tables.Add(ws.Cells[1, 1, cr - 1, cc - 1], "Table");
tableDef.TableStyle = TableStyles.Medium16;
tableDef.ShowHeader = true;
return pkg;
}
}