4 Commits

Author SHA1 Message Date
bbec2cbe07 fix build of cli 2025-11-18 07:22:17 +01:00
07bb19771a ui(manager)+manager: improve display version 2025-11-18 07:20:05 +01:00
49845e841d ui(manager): fix zip archive path binding 2025-11-18 06:54:25 +01:00
d44ccbaaab enable trimming 2025-11-18 06:53:23 +01:00
15 changed files with 107 additions and 49 deletions

View File

@@ -5,6 +5,7 @@
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<ImplicitUsings>true</ImplicitUsings> <ImplicitUsings>true</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
@@ -20,4 +21,13 @@
<DebugType>None</DebugType> <DebugType>None</DebugType>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<TrimmerRootAssembly Include="Newtonsoft.Json"/>
<TrimmerRootAssembly Include="Pilz"/>
<TrimmerRootAssembly Include="Yggdrasil.Engine"/>
<TrimmerRootAssembly Include="Octokit"/>
<TrimmerRootAssembly Include="Modrinth.Net"/>
<TrimmerRootAssembly Include="CurseForge.APIClient"/>
</ItemGroup>
</Project> </Project>

View File

@@ -189,7 +189,7 @@ public partial class MainForm : Window
{ {
lastUpdateCheckResult = await updater.Check(updateOptions); lastUpdateCheckResult = await updater.Check(updateOptions);
} }
catch (Exception) catch
{ {
error(); error();
if (Debugger.IsAttached) if (Debugger.IsAttached)
@@ -275,7 +275,7 @@ public partial class MainForm : Window
private async void MainForm_Loaded(object? sender, RoutedEventArgs e) private async void MainForm_Loaded(object? sender, RoutedEventArgs e)
{ {
var updates = new AppUpdates(Program.UpdateUrl, this); var updates = new AppUpdates(Program.UpdateUrl, this);
updates.OnDownloadProgramUpdate += (o, args) => SetStatus(GeneralLangRes.DownloadProgramUpdate, AppGlobals.Symbols.GetImageSource(AppSymbols.software_installer)); updates.OnDownloadProgramUpdate += (o, _) => SetStatus(GeneralLangRes.DownloadProgramUpdate, AppGlobals.Symbols.GetImageSource(AppSymbols.software_installer));
await updates.UpdateApp(); await updates.UpdateApp();
ClearStatus(); ClearStatus();

View File

@@ -9,6 +9,17 @@
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault> <AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<TrimmerRootAssembly Include="MinecraftModpackUpdater"/>
<TrimmerRootAssembly Include="ModpackUpdater.Manager"/>
<TrimmerRootAssembly Include="ModpackUpdater.Apps"/>
<TrimmerRootAssembly Include="ModpackUpdater"/>
<TrimmerRootAssembly Include="Pilz.Updating"/>
<TrimmerRootAssembly Include="Pilz.Updating.Client"/>
<TrimmerRootAssembly Include="Pilz.Configuration"/>
<TrimmerRootAssembly Include="ExCSS"/>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Version.cs" /> <Compile Include="..\Version.cs" />
</ItemGroup> </ItemGroup>

View File

@@ -36,7 +36,7 @@ IconFiles = """
# DOTNET PUBLISH # DOTNET PUBLISH
DotnetProjectPath = ModpackUpdater.Apps.Client.Gui.csproj DotnetProjectPath = ModpackUpdater.Apps.Client.Gui.csproj
DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false -p:PublishSingleFile=true -p:PublishTrimmed=false DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false -p:PublishSingleFile=true -p:PublishTrimmed=true
DotnetPostPublish = DotnetPostPublish =
DotnetPostPublishOnWindows = DotnetPostPublishOnWindows =

View File

@@ -6,6 +6,12 @@
<AssemblyName>MinecraftModpackUpdaterCli</AssemblyName> <AssemblyName>MinecraftModpackUpdaterCli</AssemblyName>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<TrimmerRootAssembly Include="MinecraftModpackUpdaterCli"/>
<TrimmerRootAssembly Include="ModpackUpdater.Manager"/>
<TrimmerRootAssembly Include="ModpackUpdater"/>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Version.cs" /> <Compile Include="..\Version.cs" />
</ItemGroup> </ItemGroup>

View File

@@ -34,7 +34,7 @@ IconFiles = """
# DOTNET PUBLISH # DOTNET PUBLISH
DotnetProjectPath = ModpackUpdater.Apps.Client.csproj DotnetProjectPath = ModpackUpdater.Apps.Client.csproj
DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false -p:PublishSingleFile=true -p:PublishTrimmed=false DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false -p:PublishSingleFile=true -p:PublishTrimmed=true
DotnetPostPublish = DotnetPostPublish =
DotnetPostPublishOnWindows = DotnetPostPublishOnWindows =

View File

@@ -6,7 +6,6 @@ using ModpackUpdater.Apps.Manager.Ui;
using ModpackUpdater.Apps.Manager.Ui.Models.MainWindow; using ModpackUpdater.Apps.Manager.Ui.Models.MainWindow;
using ModpackUpdater.Apps.Manager.Ui.Models.UpdatesCollectorViewMode; using ModpackUpdater.Apps.Manager.Ui.Models.UpdatesCollectorViewMode;
using ModpackUpdater.Manager; using ModpackUpdater.Manager;
using MsBox.Avalonia;
using OfficeOpenXml; using OfficeOpenXml;
using OfficeOpenXml.Table; using OfficeOpenXml.Table;
using Pilz.UI.AvaloniaUI.Dialogs; using Pilz.UI.AvaloniaUI.Dialogs;
@@ -39,7 +38,7 @@ internal static class SharedFunctions
var result = await factory.ResolveSourceUrl(row.Action); var result = await factory.ResolveSourceUrl(row.Action);
failed = string.IsNullOrWhiteSpace(result); failed = string.IsNullOrWhiteSpace(result);
} }
catch (Exception ex) catch
{ {
// Ignore // Ignore
} }
@@ -65,12 +64,12 @@ internal static class SharedFunctions
return false; return false;
// Collect versions with changes // Collect versions with changes
var updates = resultUpdates.List.Where(update => update.Origin.SourceTag != update.AvailableVersions[update.NewVersion].Key).ToList(); var updates = resultUpdates.List.Where(update => update.Origin.SourceTag != update.AvailableVersions[update.NewVersion].Tag).ToList();
// Path install actions // Path install actions
foreach (var update in updates) foreach (var update in updates)
{ {
var sourceTag = update.AvailableVersions[update.NewVersion].Key; var sourceTag = update.AvailableVersions[update.NewVersion].Tag;
if (api.Model.CurrentGridRows?.FirstOrDefault(n => n.Action == update.Origin) is { } row) if (api.Model.CurrentGridRows?.FirstOrDefault(n => n.Action == update.Origin) is { } row)
row.SourceTag = sourceTag; row.SourceTag = sourceTag;
else else

View File

@@ -9,6 +9,18 @@
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault> <AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<TrimmerRootAssembly Include="MinecraftModpackUpdateManager"/>
<TrimmerRootAssembly Include="ModpackUpdater.Manager"/>
<TrimmerRootAssembly Include="ModpackUpdater.Apps"/>
<TrimmerRootAssembly Include="ModpackUpdater"/>
<TrimmerRootAssembly Include="NGitLab"/>
<TrimmerRootAssembly Include="Pilz.Updating"/>
<TrimmerRootAssembly Include="Pilz.Updating.Client"/>
<TrimmerRootAssembly Include="Pilz.Configuration"/>
<TrimmerRootAssembly Include="ExCSS"/>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Version.cs" /> <Compile Include="..\Version.cs" />
<Compile Update="LangRes\UpdateActionTypeLangRes.Designer.cs"> <Compile Update="LangRes\UpdateActionTypeLangRes.Designer.cs">

View File

@@ -420,7 +420,7 @@
<TextBox <TextBox
Grid.Row="7" Grid.Column="1" Grid.Row="7" Grid.Column="1"
x:Name="TextBoxInstallActionZipArchivePath" x:Name="TextBoxInstallActionZipArchivePath"
Text="{Binding SourceUrl}"/> Text="{Binding ZipPath}"/>
</Grid> </Grid>
<!-- Metadata --> <!-- Metadata -->

View File

@@ -1,18 +1,30 @@
using System.ComponentModel; using System.ComponentModel;
using ModpackUpdater.Manager;
namespace ModpackUpdater.Apps.Manager.Ui.Models.UpdatesCollectorViewMode; namespace ModpackUpdater.Apps.Manager.Ui.Models.UpdatesCollectorViewMode;
public record ModUpdateInfo(KeyValuePair<string, string>[] AvailableVersions, InstallAction Origin) : INotifyPropertyChanged public record ModUpdateInfo(ModVersionInfo[] AvailableVersions, InstallAction Origin) : INotifyPropertyChanged
{ {
public event PropertyChangedEventHandler? PropertyChanged; public event PropertyChangedEventHandler? PropertyChanged;
public int NewVersion { get; set; } public int NewVersion { get; set; }
public bool Visible { get; set; } = true; public bool Visible { get; set; } = true;
public string? OldVersion
{
get
{
if (AvailableVersions.FirstOrDefault(n => n.Tag.Equals(Origin.SourceTag)) is { } old
&& !old.Name.Equals(old.Tag, StringComparison.InvariantCulture))
return $"{old.Name} ({old.Tag})";
return Origin.SourceTag;
}
}
public IEnumerable<string> DisplayVersions { get; } = AvailableVersions.Select(n => public IEnumerable<string> DisplayVersions { get; } = AvailableVersions.Select(n =>
{ {
if (string.IsNullOrWhiteSpace(n.Value) || n.Value.Equals(n.Key, StringComparison.InvariantCulture)) if (string.IsNullOrWhiteSpace(n.Tag) || n.Tag.Equals(n.Name, StringComparison.InvariantCulture))
return n.Key; return n.Name;
return $"{n.Value} ({n.Value})"; return $"{n.Name} ({n.Tag})";
}); });
} }

View File

@@ -56,7 +56,7 @@
<TextBlock <TextBlock
Grid.Column="1" Grid.Column="1"
VerticalAlignment="Center" VerticalAlignment="Center"
Text="{Binding Origin.SourceTag}"/> Text="{Binding OldVersion}"/>
<!-- ComboBox: Version (new) --> <!-- ComboBox: Version (new) -->
<ComboBox <ComboBox

View File

@@ -33,7 +33,7 @@ public partial class UpdatesCollectorView : AvaloniaFlyoutBase
Model.Progress.Increment(); Model.Progress.Increment();
if (updates == null || updates.Length == 0 || updates[0].Value == action.SourceTag) if (updates == null || updates.Length == 0 || updates[0].Tag == action.SourceTag)
continue; continue;
Model.Updates.Add(new(updates, action)); Model.Updates.Add(new(updates, action));

View File

@@ -36,7 +36,7 @@ IconFiles = """
# DOTNET PUBLISH # DOTNET PUBLISH
DotnetProjectPath = ModpackUpdater.Apps.Manager.csproj DotnetProjectPath = ModpackUpdater.Apps.Manager.csproj
DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false -p:PublishSingleFile=true -p:PublishTrimmed=false DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false -p:PublishSingleFile=true -p:PublishTrimmed=true
DotnetPostPublish = DotnetPostPublish =
DotnetPostPublishOnWindows = DotnetPostPublishOnWindows =

View File

@@ -0,0 +1,3 @@
namespace ModpackUpdater.Manager;
public record ModVersionInfo(string Name, string Tag);

View File

@@ -1,7 +1,8 @@
using CurseForge.APIClient.Models.Mods; using System.Text.RegularExpressions;
using CurseForge.APIClient.Models.Mods;
using Modrinth; using Modrinth;
using Octokit; using Octokit;
using System.Text.RegularExpressions; using ApiClient = CurseForge.APIClient.ApiClient;
namespace ModpackUpdater.Manager; namespace ModpackUpdater.Manager;
@@ -11,7 +12,7 @@ public class ModpackFactory
{ {
Credentials = new Credentials("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"), Credentials = new Credentials("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"),
}; };
private readonly CurseForge.APIClient.ApiClient curseForge = new("$2a$10$pE4dD09gmr7IcOe8hjWhleWWjXopJcDNpq1P9FlrDMCBw05pCyAXa", "pilzinsel64@gmx.de"); private readonly ApiClient curseForge = new("$2a$10$pE4dD09gmr7IcOe8hjWhleWWjXopJcDNpq1P9FlrDMCBw05pCyAXa", "pilzinsel64@gmx.de");
private readonly ModrinthClient modrinth = new(new ModrinthClientConfig private readonly ModrinthClient modrinth = new(new ModrinthClientConfig
{ {
ModrinthToken = "mrp_zUlDSET5actMUdTU3FK242TXgvlWgaErSSEFuegNG7thLgkC50IiK2NCGOzW", ModrinthToken = "mrp_zUlDSET5actMUdTU3FK242TXgvlWgaErSSEFuegNG7thLgkC50IiK2NCGOzW",
@@ -26,37 +27,41 @@ public class ModpackFactory
public async Task<string> ResolveSourceUrl(InstallAction action, Version? targetVersion = null, string? overwriteVersion = null) public async Task<string> ResolveSourceUrl(InstallAction action, Version? targetVersion = null, string? overwriteVersion = null)
{ {
if (action.SourceType == SourceType.GitHub) switch (action.SourceType)
{ {
var repo = await github.Repository.Get(action.SourceOwner, action.SourceName); case SourceType.GitHub:
var release = await github.Repository.Release.Get(repo.Id, action.SourceTag); {
var assets = await github.Repository.Release.GetAllAssets(repo.Id, release.Id); var repo = await github.Repository.Get(action.SourceOwner, action.SourceName);
var release = await github.Repository.Release.Get(repo.Id, action.SourceTag);
var assets = await github.Repository.Release.GetAllAssets(repo.Id, release.Id);
if (assets.LastOrDefault(asset => Regex.IsMatch(asset.Name, action.SourceRegex)) is ReleaseAsset asset) if (assets.LastOrDefault(a => Regex.IsMatch(a.Name, action.SourceRegex)) is ReleaseAsset asset)
return asset.BrowserDownloadUrl; return asset.BrowserDownloadUrl;
} break;
else if (action.SourceType == SourceType.GitLab) }
{ case SourceType.GitLab:
throw new NotImplementedException("To be implemented soon."); throw new NotSupportedException("To be implemented soon.");
} case SourceType.CurseForge:
else if (action.SourceType == SourceType.CurseForge) {
{ var res = await curseForge.GetModFileDownloadUrlAsync(Convert.ToInt32(action.SourceName), Convert.ToInt32(action.SourceTag));
var res = await curseForge.GetModFileDownloadUrlAsync(Convert.ToInt32(action.SourceName), Convert.ToInt32(action.SourceTag)); if (!string.IsNullOrWhiteSpace(res.Data))
if (!string.IsNullOrWhiteSpace(res.Data)) return res.Data;
return res.Data; break;
} }
else if (action.SourceType == SourceType.Modrinth) case SourceType.Modrinth:
{ {
var res = await modrinth.VersionFile.GetVersionByHashAsync(action.SourceTag); var res = await modrinth.VersionFile.GetVersionByHashAsync(action.SourceTag);
var file = res.Files.Length == 1 ? res.Files[0] : res.Files.FirstOrDefault(n => Regex.IsMatch(n.FileName, action.SourceRegex)); var file = res.Files.Length == 1 ? res.Files[0] : res.Files.FirstOrDefault(n => Regex.IsMatch(n.FileName, action.SourceRegex));
if (file != null) if (file != null)
return file.Url; return file.Url;
break;
}
} }
return action.GetSourceUrl(targetVersion, overwriteVersion: overwriteVersion); return action.GetSourceUrl(targetVersion, overwriteVersion: overwriteVersion);
} }
public async Task<KeyValuePair<string, string>[]?> FindUpdates(InstallAction action, string? gameVersion, ModLoader modLoader) public async Task<ModVersionInfo[]?> FindUpdates(InstallAction action, string? gameVersion, ModLoader modLoader)
{ {
switch (action.SourceType) switch (action.SourceType)
{ {
@@ -65,7 +70,7 @@ public class ModpackFactory
{ {
var repo = await github.Repository.Get(action.SourceOwner, action.SourceName); var repo = await github.Repository.Get(action.SourceOwner, action.SourceName);
var releases = await github.Repository.Release.GetAll(repo.Id); var releases = await github.Repository.Release.GetAll(repo.Id);
return releases.Select(r => new KeyValuePair<string, string>(r.TagName, r.Name ?? r.TagName)).ToArray(); return releases.Select(r => new ModVersionInfo(r.TagName, r.Name ?? r.TagName)).ToArray();
} }
catch catch
{ {
@@ -73,18 +78,18 @@ public class ModpackFactory
} }
break; break;
case SourceType.GitLab: case SourceType.GitLab:
throw new NotImplementedException("To be implemented soon."); throw new NotSupportedException("To be implemented soon.");
case SourceType.CurseForge: case SourceType.CurseForge:
{ {
var res = await curseForge.GetModFilesAsync(Convert.ToInt32(action.SourceName), gameVersion: gameVersion, modLoaderType: GetModLoaderForCurseForge(modLoader)); var res = await curseForge.GetModFilesAsync(Convert.ToInt32(action.SourceName), gameVersion: gameVersion, modLoaderType: GetModLoaderForCurseForge(modLoader));
if (res.Data != null) if (res.Data != null)
return res.Data.Select(n => new KeyValuePair<string, string>(n.DisplayName, n.Id.ToString())).ToArray(); return res.Data.Select(n => new ModVersionInfo(n.DisplayName, n.Id.ToString())).ToArray();
break; break;
} }
case SourceType.Modrinth: case SourceType.Modrinth:
{ {
var res = await modrinth.Version.GetProjectVersionListAsync(action.SourceName, gameVersions: GetGameVersionForModrinth(gameVersion), loaders: GetModLoaderForModrinth(modLoader)); var res = await modrinth.Version.GetProjectVersionListAsync(action.SourceName, gameVersions: GetGameVersionForModrinth(gameVersion), loaders: GetModLoaderForModrinth(modLoader));
return res.Select(v => new KeyValuePair<string, string>($"{v.VersionNumber} {v.ProjectVersionType} {v.Name}", v.Id)).ToArray(); return res.Select(v => new ModVersionInfo(v.VersionNumber, v.Id)).ToArray();
} }
} }
return null; return null;
@@ -116,7 +121,7 @@ public class ModpackFactory
ModLoader.LiteLoader => ["liteloader"], ModLoader.LiteLoader => ["liteloader"],
ModLoader.Cauldron => ["cauldron"], ModLoader.Cauldron => ["cauldron"],
ModLoader.Quilt => ["quilt"], ModLoader.Quilt => ["quilt"],
_ => null, _ => [],
}; };
} }