145 Commits

Author SHA1 Message Date
f5e84b6da7 fix delete Artifacts directory 2025-11-21 19:57:52 +01:00
c864d9125a merge update urls and include app short name in distro 2025-11-21 19:52:58 +01:00
Pascal
e7aa79db64 ui(client): recent profile selector 2025-11-20 06:49:21 +01:00
Pascal
c0f013a6c5 code clenaup 2025-11-19 07:56:55 +01:00
Pascal
f21e31ebcc ui(manager): use popup for app update message 2025-11-19 07:55:46 +01:00
Pascal
0ae2a780b0 ui(manager): arrange DataGrid columns width & order 2025-11-19 07:47:25 +01:00
Pascal
474f76df4a disable update on debug builds 2025-11-19 07:40:05 +01:00
Pascal
6454d97173 ui(manager): add name column 2025-11-19 07:30:56 +01:00
Pascal
e57d2316de ui(manager): search for DataGrid 2025-11-19 07:21:19 +01:00
2cbe25e0f8 ui(manager): improve search bindings 2025-11-18 16:21:34 +01:00
86f93cf3d7 publish: remove artifacts 2025-11-18 07:30:05 +01:00
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
b87d896b8f update 2025-11-17 19:15:53 +01:00
26a807c8be appupdater 2025-11-17 19:02:40 +01:00
4e657469b3 move to right directory 2025-11-17 18:40:37 +01:00
535679d4ee fix publish script 2025-11-17 18:38:06 +01:00
c220d7f2b8 publish script for manager 2025-11-17 18:34:55 +01:00
ada6f59434 hotkey fix & contextmenu 2025-11-17 18:25:21 +01:00
ce09b47456 optimizations 2025-11-17 16:54:15 +01:00
cd1006b422 fixes 2025-11-17 16:44:49 +01:00
b2331926d7 translation update 2025-11-17 16:37:11 +01:00
e04e5f0b13 local folder workspace 2025-11-17 16:35:02 +01:00
5df8019cfb update nuget packages 2025-11-17 16:02:27 +01:00
fb36f897d6 fixes 2025-11-17 15:59:49 +01:00
d68df750a6 progressbar tweaks 2025-11-17 15:51:50 +01:00
ea8d1522f1 fixes 2025-11-17 15:08:31 +01:00
1a8b03696d add missing icon 2025-11-17 15:02:58 +01:00
7e2a103dbe complete 2025-11-17 15:02:47 +01:00
d80f5c47b1 localization of enums 2025-11-17 13:57:19 +01:00
c2ac96938e work 2025-11-17 09:45:25 +01:00
0bc93bb24b fix 2025-11-17 07:36:20 +01:00
c9eb3e32b4 fix search 2025-11-17 07:35:19 +01:00
afc9ceaa1f fix 2025-11-17 07:31:46 +01:00
7c745cc2f7 visible fix 2025-11-17 07:21:00 +01:00
e584996043 work 2025-11-17 07:19:43 +01:00
72a81e05ad fixes 2025-11-16 22:34:14 +01:00
da79ada91e fix 2025-11-16 20:09:30 +01:00
e47d6599b5 work 2025-11-16 19:48:28 +01:00
7469d037d5 ui(client): improve margin of window & minheight of status label 2025-11-16 13:55:15 +01:00
8f132afe92 complete visual ui 2025-11-16 13:36:47 +01:00
a5db244bc1 update 2025-11-16 10:06:37 +01:00
0b50f1ade2 and even more work 2025-11-16 09:48:03 +01:00
f6b39cb678 progress 2025-11-15 22:55:15 +01:00
d2a454aca0 update 2025-11-15 18:38:17 +01:00
795e3dd1a7 fix 2025-11-15 17:20:29 +01:00
b9ddc20b7d a lot of work 2025-11-15 17:17:52 +01:00
Pascal
336b6ad1fd more work 2025-11-14 11:40:30 +01:00
Pascal
a22f6238d4 more work 2025-11-14 11:38:51 +01:00
Pascal
bb96755232 update 2025-11-14 11:38:25 +01:00
Pascal
b4e4154445 update 2025-11-14 11:35:40 +01:00
Pascal
cd766f73fc part of manager main window 2025-11-14 08:10:42 +01:00
d798eea1d8 update 2025-11-12 14:29:31 +01:00
8ab1689309 width & height 2025-11-10 19:07:30 +01:00
6cf27b4867 manager: migrate base project structure & deps 2025-11-10 18:28:20 +01:00
da25510543 ui(client): more theme tests 2025-11-09 17:55:08 +01:00
a2d15425d1 ui(client): use fluent normal theme (again) 2025-11-09 17:50:18 +01:00
3618d83ef8 ui(client): use fluent compact theme 2025-11-09 17:48:49 +01:00
2edbcf72c7 fixes for client cli publish script 2025-11-09 14:18:50 +01:00
19b9a64721 fix missing version 2025-11-09 14:17:31 +01:00
ec6830e636 also add the new file !!!! 2025-11-09 14:16:06 +01:00
9a5c70581b build also cli 2025-11-09 14:15:53 +01:00
a6175b3874 ui(client) also publish win-arm64, osx-x64, osx-arm64 2025-11-09 14:04:24 +01:00
27ce41e0d1 ui(client): disable flatpak build 2025-11-09 13:59:30 +01:00
574a8d5ec2 final fix 2025-11-09 13:58:43 +01:00
d570d29c92 update nuget packages 2025-11-09 13:43:20 +01:00
562ce27341 ui(client): optimize installation key caching & show invalid key hint 2025-11-09 08:40:18 +01:00
463c2bbf2b ui(client): use Margin instead of RowSpacing and ColumnSpacing
-> fixes visible spacing of invisible rows
2025-11-09 08:11:27 +01:00
145a5771a1 ignore .idea 2025-11-08 22:51:12 +01:00
3adfcda472 update 2025-11-08 22:50:45 +01:00
078d5c0661 version improvement 2025-11-08 22:49:46 +01:00
06db3289c0 fix home share permission 2025-11-08 18:40:51 +01:00
a573f4fb89 fix release build 2025-11-08 18:36:45 +01:00
091d820332 fix build 2025-11-08 18:29:04 +01:00
1d44f93a92 enable network & home directory access for flatpak 2025-11-08 18:17:13 +01:00
3de764b833 fixes 2025-11-08 17:31:17 +01:00
3e6b70bc4c fixes 2025-11-08 16:36:40 +01:00
065d915d46 improvements & deployment 2025-11-08 15:46:56 +01:00
11b76ee73b add license 2025-11-08 11:33:29 +00:00
1c070891f1 ui(client): formatting & code improvements 2025-11-07 15:22:28 +01:00
4baf571713 Merge branch 'feat/migrate-client-to-avalonia' into 'master'
Feat/migrate client to avalonia

See merge request litw-refined/minecraft-modpack-updater!2
2025-11-07 13:58:36 +00:00
Pascal
b899d2ee7d ui(client): improvements 2025-11-07 10:45:55 +01:00
Pascal
05b94a3189 migrate to Pilz.Features 2025-11-06 12:20:03 +01:00
Pascal
6a6fd7efe6 ui(client): translation 2025-11-06 11:42:08 +01:00
Pascal
a89145071d ui(client): migrate to AvaloniaUI 2025-11-06 07:42:44 +01:00
554304c801 version bump, again 2025-08-23 09:28:24 +02:00
785c4ce41d version bump 2025-08-23 08:41:02 +02:00
bd7ce5bbe7 use full version string for {version} 2025-08-23 08:40:09 +02:00
8ef522bc6c 1.9.3 2025-08-20 08:32:27 +02:00
582752c987 seperated cli & some work for options 2025-08-20 08:17:33 +02:00
b434ddf480 preparation for dynamic options 2025-07-31 14:51:30 +02:00
8300f571a3 update nuget packages 2025-07-31 14:43:27 +02:00
e86fe2ee17 another fix 2025-07-04 22:27:37 +02:00
531c2a60bf fix option shit 2025-07-04 22:13:47 +02:00
b1ac3cd73c uff, enough for now 2025-06-30 18:55:30 +02:00
6674872848 more release shit 2025-06-30 17:31:42 +02:00
03f27214d6 update client app symbol 2025-06-30 14:44:07 +02:00
d8c798fe09 remove linux update url 2025-06-30 11:49:24 +02:00
70786fc169 version bump 2025-06-30 11:45:38 +02:00
aed70d4f3f update publish profile 2025-06-30 05:53:38 +02:00
45ef76e647 ui: hide installation key if no extras key can be used 2025-06-30 05:50:41 +02:00
433613e43d ui: migrate client back to WinForms
-> let's use wine for comatibility again
-> easier to maintain
-> easier to build dynamic options with
2025-06-29 20:03:02 +02:00
6e8b4f0a9d manager: tree view & action set infos editor panel 2025-06-29 14:19:58 +02:00
87cb9b8b37 update nuget packages 2025-06-29 13:40:36 +02:00
Pascal
77a93b585a manager: add proper support for options 2025-06-27 11:24:53 +02:00
Pascal
d0e3d2fa61 finalize model for option sets 2025-06-27 09:29:57 +02:00
Pascal
f5596ab0ba manager: allow parent path annotations
- Allows unlimited amount of `..\` or `../` at the start of DestPath string.
- Each of then will go back one folder.
- Similar to how Linux works or Visual Studio project styles.
- This allows us to install/update lwjgl3ify in PrismLauncher.
2025-06-27 09:10:18 +02:00
Pascal
09c1ac8b08 ui: simplify workspaces menu 2025-06-27 08:34:03 +02:00
Pascal
4e69acaf04 ui: row context menu fine tuning 2025-06-27 08:24:20 +02:00
Pascal
55db801c4c update nuget packages 2025-06-27 08:22:08 +02:00
Pascal
cbbb546f30 ui: fixed adding new row beeing empty 2025-06-27 08:09:26 +02:00
04848d4622 repair manager project 2025-06-26 18:53:00 +02:00
d85a41c158 update url 2025-06-19 12:54:11 +02:00
798961ea22 update publish profiles 2025-06-19 12:25:33 +02:00
bf0037cf79 hide console on windows only 2025-06-19 12:15:31 +02:00
c52c4059a0 version bump 2025-06-19 11:41:52 +02:00
03fefa33fe update AppUpdate to support linux updates 2025-06-19 11:41:04 +02:00
30b1832cd0 ui: migrate client to gtk 2025-06-17 09:40:10 +02:00
0aa6ed98c6 add install options (WIP) 2025-06-16 15:34:15 +02:00
c1616fecf0 fix modlist plugin not loading 2025-06-16 15:33:37 +02:00
a5eb9fad43 fix some null reference exceptions 2025-04-23 15:40:01 +02:00
df21d8180d version bump 2025-04-23 14:46:04 +02:00
f19974599f add repair mode 2025-04-23 14:45:22 +02:00
e14dedc924 support first placeholder & overwriting version 2025-04-23 13:38:51 +02:00
0285892f20 fixes 2025-04-21 20:55:55 +02:00
01fc5606cb add reftag commandline argument 2025-04-21 20:50:16 +02:00
70805083ba version bump 2025-04-21 20:48:19 +02:00
96cd9bcaac add support for {ref} placeholder 2025-04-21 20:43:09 +02:00
986257c0a4 v1.6.5 2025-04-21 18:40:19 +02:00
b11ad06287 add support for version placeholder in download links 2025-04-21 18:39:47 +02:00
d68dd09ad2 add option to generate markdown table 2025-04-03 06:19:47 +02:00
1b3070493c order by name 2025-01-28 20:46:47 +01:00
1c9c50778a add the missing files from the last commit (wtf?) 2025-01-28 20:43:27 +01:00
33a209a01a add generate modlist feature 2025-01-28 20:38:27 +01:00
2ce73ad032 list only relevant modrinth versions 2025-01-26 09:19:07 +01:00
ecb7ae0d1a fail silently if url can not be resolved 2024-12-22 18:48:30 +01:00
40380d088f version bump 2024-12-07 18:11:48 +01:00
50cbf081e1 fix endless update 2024-12-07 18:11:04 +01:00
3b79335e85 more logging 2024-12-05 07:22:01 +01:00
3e1ab72162 update deps & enable console logging 2024-12-05 07:06:06 +01:00
a83d109f24 fix first install includes ALL updates 2024-12-05 06:56:45 +01:00
e50d5f4874 v1.6.2 2024-10-31 21:16:00 +01:00
72b765e6fd final fix 2024-10-31 21:15:15 +01:00
160 changed files with 5944 additions and 9223 deletions

2
.gitignore vendored
View File

@@ -349,3 +349,5 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder # Ionide (cross platform F# VS Code tools) working folder
.ionide/ .ionide/
*.json *.json
.idea/

37
Directory.Build.props Normal file
View File

@@ -0,0 +1,37 @@
<Project>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>true</ImplicitUsings>
<Nullable>enable</Nullable>
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>
<PropertyGroup>
<PackageProjectUrl>https://git.pilzinsel64.de/litw-refined/minecraft-modpack-updater</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<GenerateSerializationAssemblies>False</GenerateSerializationAssemblies>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<NoWarn>1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<DefineConstants>$(DefineConstants);DISABLE_UPDATE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<DebugSymbols>False</DebugSymbols>
<DebugType>None</DebugType>
</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>

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Pilzinsel64
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,11 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ModpackUpdater.Apps.Client.Gui.App"
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<Application.Styles>
<FluentTheme />
<StyleInclude Source="avares://Pilz.UI.AvaloniaUI/Assets/Styles/EnhancedDefaults.axaml"/>
</Application.Styles>
</Application>

View File

@@ -0,0 +1,21 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
namespace ModpackUpdater.Apps.Client.Gui;
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
AppGlobals.Initialize();
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
desktop.MainWindow = new MainForm();
base.OnFrameworkInitializationCompleted();
}
}

View File

@@ -0,0 +1,29 @@
using Newtonsoft.Json;
using Pilz.Configuration;
namespace ModpackUpdater.Apps.Client.Gui;
public class AppConfig : ISettingsNode, ISettingsIdentifier
{
public static string Identifier => "pilz.appconfig";
public List<string> RecentMinecraftProfilePaths { get; } = [];
[JsonProperty, Obsolete]
private string? LastMinecraftProfilePath
{
get => RecentMinecraftProfilePaths.FirstOrDefault();
set
{
if (!string.IsNullOrWhiteSpace(value))
RecentMinecraftProfilePaths.Insert(0, value);
}
}
public void Reset()
{
RecentMinecraftProfilePaths.Clear();
}
public static AppConfig Instance => Program.Settings.Get<AppConfig>();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="480" height="480" viewBox="0 0 480 480" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="clip_path_1">
<rect width="480" height="480" />
</clipPath>
</defs>
<g clip-path="url(#clip_path_1)">
<path d="M360 40L180 40L140 0C140 0 40 0 40 0C17.91 0 0 17.91 0 40C0 40 0 120 0 120L400 120C400 120 400 80 400 80C400 57.91 382.09 40 360 40C360 40 360 40 360 40Z" fill="#FFA000" transform="translate(20 100)" />
<g transform="translate(53 -7)">
<path d="M160.042 63.3334L0 7.91667L13.9167 213.75L160.042 300.833L278.333 205.833L292.25 0L160.042 63.3334Z" fill="#5D4037" fill-rule="evenodd" transform="translate(20.875 63.333)" />
<path d="M0 0L13.9167 205.834L160.042 292.917L160.042 55.4167L0 0Z" fill="#8D6E63" fill-rule="evenodd" transform="translate(20.875 71.25)" />
<path d="M13.9167 112.084L13.9167 79.1667L27.8333 72.2554L27.8333 95L41.75 87.0833L41.75 118.75L62.625 109.028L62.625 55.4167L76.5417 48.6954L76.5417 87.0833L90.4583 80.5679L90.4583 63.3333L104.375 55.4167L104.375 35.3637L118.292 28.6979L118.292 47.5L129.425 41.1667L132.208 0L0 63.3333L0 118.75L13.9167 112.084Z" fill="#43A047" fill-rule="evenodd" transform="translate(180.917 63.333)" />
<path d="M0 47.5L139.167 0L292.25 39.5833L160.042 102.917L0 47.5Z" fill="#B2FF59" fill-rule="evenodd" transform="translate(20.875 23.75)" />
<path d="M0 0L2.78333 40.6442L13.9167 44.3888L13.9167 34.9363L27.8333 39.5833L27.8333 65.0513L48.7083 72.2792L48.7083 34.6196L62.625 39.5833L62.625 77.1004L76.5417 81.9217L76.5417 58.9713L90.4583 63.7925L90.4583 86.743L104.375 91.5563L104.375 82.1671L118.292 87.0834L118.292 74.6067L132.208 79.1667L132.208 101.199L160.042 110.833L160.042 55.4167L0 0Z" fill="#66BB6A" fill-rule="evenodd" transform="translate(20.875 71.25)" />
</g>
<path d="M360 0C360 0 40 0 40 0C17.91 0 0 15.1595 0 33.8571C0 33.8571 0 203.143 0 203.143C0 221.84 17.91 237 40 237C40 237 360 237 360 237C382.09 237 400 221.84 400 203.143C400 203.143 400 33.8571 400 33.8571C400 15.1595 382.09 0 360 0C360 0 360 0 360 0Z" fill="#FFCA28" transform="translate(20 183)" />
<path d="M70 80L0 0L140 0L70 80Z" fill="#1565C0" transform="translate(150 380)" />
<path d="M0 0L60 0L60 111.25L0 111.25L0 0Z" fill="#1565C0" transform="translate(190 280)" />
<path d="M30 15C30 23.28 23.29 30 15 30C6.71002 30 0 23.28 0 15C0 6.72 6.71002 0 15 0C23.29 0 30 6.72 30 15C30 15 30 15 30 15Z" fill="#4A148C" transform="translate(430 60)" />
<path d="M125 100C72.62 100 30 57.38 30 5C30 5 30 0 30 0L0 0L0 10C0 10 0.25 10 0.25 10C2.84 74.93 55.08 127.16 120 129.75C120 129.75 120 130 120 130L130 130L130 100L125 100C125 100 125 100 125 100Z" fill="#9C27B0" transform="translate(330 60)" />
<path d="M75 50C50.19 50 30 29.81 30 5C30 5 30 0 30 0L0 0L0 10C0 10 0.25 10 0.25 10C2.73004 47.36 32.63 77.27 70 79.75C70 79.75 70 80 70 80L80 80L80 50L75 50C75 50 75 50 75 50Z" fill="#7B1FA2" transform="translate(380 60)" />
<path d="M175 150C95.05 150 30 84.95 30 5C30 5 30 0 30 0L0 0L0 10C0 10 0.25 10 0.25 10C2.88998 102.5 77.51 177.11 170 179.75C170 179.75 170 180 170 180L180 180L180 150L175 150C175 150 175 150 175 150Z" fill="#BA68C8" transform="translate(280 60)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -8,7 +8,7 @@
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace ModpackUpdater.My.Resources { namespace ModpackUpdater.Apps.Client.Gui {
using System; using System;
@@ -39,7 +39,7 @@ namespace ModpackUpdater.My.Resources {
internal static global::System.Resources.ResourceManager ResourceManager { internal static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModpackUpdater.Apps.Client.FiledialogFilters", typeof(FiledialogFilters).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModpackUpdater.Apps.Client.Gui.FiledialogFilters", typeof(FiledialogFilters).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;

View File

@@ -0,0 +1,242 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ModpackUpdater.Apps.Client.Gui.LangRes {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class GeneralLangRes {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal GeneralLangRes() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModpackUpdater.Apps.Client.Gui.LangRes.GeneralLangRes", typeof(GeneralLangRes).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to An update is available!.
/// </summary>
public static string AnUpdateIsAvailable {
get {
return ResourceManager.GetString("AnUpdateIsAvailable", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Check for updates.
/// </summary>
public static string CheckForUpdates {
get {
return ResourceManager.GetString("CheckForUpdates", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Checking for Updates....
/// </summary>
public static string CheckingForUpdates {
get {
return ResourceManager.GetString("CheckingForUpdates", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Config incomplete or not loaded!.
/// </summary>
public static string ConfigIncompleteOrNotLoaded {
get {
return ResourceManager.GetString("ConfigIncompleteOrNotLoaded", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Downloading program update....
/// </summary>
public static string DownloadProgramUpdate {
get {
return ResourceManager.GetString("DownloadProgramUpdate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Error on update check or while updating!.
/// </summary>
public static string ErrorOnUpdateCheckOrUpdating {
get {
return ResourceManager.GetString("ErrorOnUpdateCheckOrUpdating", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Everything is right and up-to-date..
/// </summary>
public static string EverythingIsRightAndUpToDate {
get {
return ResourceManager.GetString("EverythingIsRightAndUpToDate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Install.
/// </summary>
public static string Install {
get {
return ResourceManager.GetString("Install", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Installation key.
/// </summary>
public static string InstallationKey {
get {
return ResourceManager.GetString("InstallationKey", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Installation key seems to be invalid.
/// </summary>
public static string InstallationKeyNotValid {
get {
return ResourceManager.GetString("InstallationKeyNotValid", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Installing....
/// </summary>
public static string Installing {
get {
return ResourceManager.GetString("Installing", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Minecraft profile.
/// </summary>
public static string MinecraftProfile {
get {
return ResourceManager.GetString("MinecraftProfile", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Minecraft profile folder seems to be not valid..
/// </summary>
public static string MinecraftProfileFolderSeemsInvalid {
get {
return ResourceManager.GetString("MinecraftProfileFolderSeemsInvalid", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Modpack config url.
/// </summary>
public static string ModpackConfigUrl {
get {
return ResourceManager.GetString("ModpackConfigUrl", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No recent profiles available..
/// </summary>
public static string NoRecentProfilesAvailable {
get {
return ResourceManager.GetString("NoRecentProfilesAvailable", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Repair.
/// </summary>
public static string Repair {
get {
return ResourceManager.GetString("Repair", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Select.
/// </summary>
public static string Select {
get {
return ResourceManager.GetString("Select", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Select the minecraft profile folder (usually named .minecraft).
/// </summary>
public static string SelectMinecraftProfileFolder {
get {
return ResourceManager.GetString("SelectMinecraftProfileFolder", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Status.
/// </summary>
public static string Status {
get {
return ResourceManager.GetString("Status", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to The update servers are in maintenance..
/// </summary>
public static string UpdateServerInMaintenance {
get {
return ResourceManager.GetString("UpdateServerInMaintenance", resourceCulture);
}
}
}
}

View File

@@ -117,37 +117,64 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="MsgBox_UpdateAvailable" xml:space="preserve"> <data name="AnUpdateIsAvailable" xml:space="preserve">
<value>A new version of this program is available. If you confirm, the update will be installed automatically. It takes just a few seconds. Continue?</value>
</data>
<data name="MsgBox_UpdateAvailable_Title" xml:space="preserve">
<value>New program version available</value>
</data>
<data name="StatusTest_EverythingOk" xml:space="preserve">
<value>Everything is right and up-to-date.</value>
</data>
<data name="StatusText_CheckingForUpdates" xml:space="preserve">
<value>Checking for Updates...</value>
</data>
<data name="StatusText_ConfigIncompleteOrNotLoaded" xml:space="preserve">
<value>Config incomplete or not loaded!</value>
</data>
<data name="StatusText_ErrorWhileUpdateCheckOrUpdate" xml:space="preserve">
<value>Error on update check or while updating!</value>
</data>
<data name="StatusText_Installing" xml:space="preserve">
<value>Installing...</value>
</data>
<data name="StatusText_InstallingAppUpdate" xml:space="preserve">
<value>Downloading program update...</value>
</data>
<data name="StatusText_Maintenance" xml:space="preserve">
<value>The update servers are in maintenance.</value>
</data>
<data name="StatusText_MinecraftProfileWarning" xml:space="preserve">
<value>Minecraft profile folder seems to be not valid.</value>
</data>
<data name="StatusText_UpdateAvailable" xml:space="preserve">
<value>An update is available!</value> <value>An update is available!</value>
</data> </data>
<data name="CheckForUpdates" xml:space="preserve">
<value>Check for updates</value>
</data>
<data name="CheckingForUpdates" xml:space="preserve">
<value>Checking for Updates...</value>
</data>
<data name="ConfigIncompleteOrNotLoaded" xml:space="preserve">
<value>Config incomplete or not loaded!</value>
</data>
<data name="DownloadProgramUpdate" xml:space="preserve">
<value>Downloading program update...</value>
</data>
<data name="ErrorOnUpdateCheckOrUpdating" xml:space="preserve">
<value>Error on update check or while updating!</value>
</data>
<data name="EverythingIsRightAndUpToDate" xml:space="preserve">
<value>Everything is right and up-to-date.</value>
</data>
<data name="Install" xml:space="preserve">
<value>Install</value>
</data>
<data name="InstallationKey" xml:space="preserve">
<value>Installation key</value>
</data>
<data name="Installing" xml:space="preserve">
<value>Installing...</value>
</data>
<data name="MinecraftProfile" xml:space="preserve">
<value>Minecraft profile</value>
</data>
<data name="MinecraftProfileFolderSeemsInvalid" xml:space="preserve">
<value>Minecraft profile folder seems to be not valid.</value>
</data>
<data name="ModpackConfigUrl" xml:space="preserve">
<value>Modpack config url</value>
</data>
<data name="Repair" xml:space="preserve">
<value>Repair</value>
</data>
<data name="Select" xml:space="preserve">
<value>Select</value>
</data>
<data name="SelectMinecraftProfileFolder" xml:space="preserve">
<value>Select the minecraft profile folder (usually named .minecraft)</value>
</data>
<data name="Status" xml:space="preserve">
<value>Status</value>
</data>
<data name="UpdateServerInMaintenance" xml:space="preserve">
<value>The update servers are in maintenance.</value>
</data>
<data name="InstallationKeyNotValid" xml:space="preserve">
<value>Installation key seems to be invalid</value>
</data>
<data name="NoRecentProfilesAvailable" xml:space="preserve">
<value>No recent profiles available.</value>
</data>
</root> </root>

View File

@@ -0,0 +1,72 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ModpackUpdater.Apps.Client.Gui.LangRes {
using System;
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class MsgBoxLangRes {
private static System.Resources.ResourceManager resourceMan;
private static System.Globalization.CultureInfo resourceCulture;
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal MsgBoxLangRes() {
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
public static System.Resources.ResourceManager ResourceManager {
get {
if (object.Equals(null, resourceMan)) {
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("ModpackUpdater.Apps.Client.Gui.LangRes.MsgBoxLangRes", typeof(MsgBoxLangRes).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
public static System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
public static string UpdateAvailable {
get {
return ResourceManager.GetString("UpdateAvailable", resourceCulture);
}
}
public static string UpdateAvailable_Title {
get {
return ResourceManager.GetString("UpdateAvailable_Title", resourceCulture);
}
}
public static string ErrorWhileUpdate_Title {
get {
return ResourceManager.GetString("ErrorWhileUpdate_Title", resourceCulture);
}
}
public static string ErrorWhileUpdate {
get {
return ResourceManager.GetString("ErrorWhileUpdate", resourceCulture);
}
}
}
}

View File

@@ -117,4 +117,17 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="UpdateAvailable" xml:space="preserve">
<value>A new version of this program is available! Install now?
If you confirm, the update will be installed automatically within a few seconds.</value>
</data>
<data name="UpdateAvailable_Title" xml:space="preserve">
<value>New program version available</value>
</data>
<data name="ErrorWhileUpdate_Title" xml:space="preserve">
<value>Error while updating</value>
</data>
<data name="ErrorWhileUpdate" xml:space="preserve">
<value>An error happened while updating the program. Error message:\n{0}</value>
</data>
</root> </root>

View File

@@ -0,0 +1,114 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:lang="clr-namespace:ModpackUpdater.Apps.Client.Gui.LangRes"
xmlns:pilz="https://git.pilzinsel64.de/pilz-framework/pilz"
xmlns:symbols="clr-namespace:Pilz.UI.Symbols;assembly=Pilz.UI"
mc:Ignorable="d"
x:Class="ModpackUpdater.Apps.Client.Gui.MainForm"
Width="520"
SizeToContent="Height"
WindowStartupLocation="CenterScreen"
CanMaximize="false"
Title="Minecraft Modpack Updater"
Icon="/Assets/app.ico"
Loaded="MainForm_Loaded">
<Grid
RowDefinitions="Auto,Auto,Auto,Auto,Auto"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
Margin="3"
x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" MinWidth="250"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- Labels -->
<Label Grid.Row="0" Grid.Column="0" Margin="3" Content="{x:Static lang:GeneralLangRes.MinecraftProfile}" Target="TextBoxMinecraftProfileFolder"/>
<Label Grid.Row="1" Grid.Column="0" Margin="3" Content="{x:Static lang:GeneralLangRes.ModpackConfigUrl}" Target="TextBoxModpackConfig"/>
<Label Grid.Row="2" Grid.Column="0" Margin="3" IsVisible="false" x:Name="LabelInstallKey" Content="{x:Static lang:GeneralLangRes.InstallationKey}" Target="TextBoxInstallKey"/>
<TextBlock Grid.Row="3" Grid.Column="0" Margin="3" Text="{x:Static lang:GeneralLangRes.Status}"/>
<StackPanel Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Margin="3" Orientation="Horizontal" Spacing="6" MinHeight="{Binding MinHeight, ElementName=TextBoxMinecraftProfileFolder}">
<Image Width="{x:Static symbols:SymbolGlobals.DefaultImageSmallSize}" x:Name="ImageStatus"/>
<TextBlock x:Name="TextStatus"/>
</StackPanel>
<!-- TextBoxes: Profile -->
<TextBox
x:Name="TextBoxMinecraftProfileFolder"
Grid.Row="0"
Grid.Column="1"
Margin="3"
VerticalAlignment="Center"
Watermark="C:\..."
TextChanged="TextBoxMinecraftProfileFolder_TextChanged"/>
<!-- TextBoxes: ModpackConfig -->
<TextBox
x:Name="TextBoxModpackConfig"
Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="2"
Margin="3"
VerticalAlignment="Center"
Watermark="https://..."
TextChanged="TextBoxModpackConfig_TextChanged"/>
<!-- TextBoxes: InstallKey -->
<TextBox
x:Name="TextBoxInstallKey"
Grid.Row="2"
Grid.Column="1"
Grid.ColumnSpan="2"
Margin="3"
VerticalAlignment="Center"
Watermark="XXXXX-YYYYY-ZZZZZ-AAAAA-BBBBB"
TextChanged="TextBoxInstallKey_TextChanged"
IsVisible="false"/>
<!-- Button: SearchProfileFolder -->
<pilz:ImageSplitButton
x:Name="ButtonSearchProfileFolder"
Grid.Row="0"
Grid.Column="2"
Margin="3"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Text="{x:Static lang:GeneralLangRes.Select}"
Click="ButtonSearchProfileFolder_Click"/>
<!-- Button: CheckForUpdates -->
<pilz:ImageButton
x:Name="ButtonCheckForUpdates"
Grid.Row="4"
Grid.Column="1"
Margin="3"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Text="{x:Static lang:GeneralLangRes.CheckForUpdates}"
Click="ButtonCheckForUpdates_Click"/>
<!-- Button: Install -->
<pilz:ImageSplitButton
x:Name="ButtonInstall"
Grid.Row="4"
Grid.Column="2"
Margin="3"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center"
Text="{x:Static lang:GeneralLangRes.Install}"
Click="ButtonInstall_Click">
<SplitButton.Flyout>
<MenuFlyout>
<MenuItem x:Name="MenuItemRepair" Header="{x:Static lang:GeneralLangRes.Repair}" Click="MenuItemRepair_Click"/>
</MenuFlyout>
</SplitButton.Flyout>
</pilz:ImageSplitButton>
</Grid>
</Window>

View File

@@ -0,0 +1,379 @@
using System.Diagnostics;
using System.Reflection;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using ModpackUpdater.Apps.Client.Gui.LangRes;
using ModpackUpdater.Manager;
using Pilz.Extensions;
using Pilz.Extensions.Collections;
using Pilz.UI.Symbols;
namespace ModpackUpdater.Apps.Client.Gui;
public partial class MainForm : Window
{
private readonly MenuFlyout menuFlyoutSearchProfileFolder = new();
private readonly UpdateCheckOptions updateOptions = new();
private ModpackInfo modpackInfo = new();
private ModpackConfig updateConfig = new();
private ModpackFeatures? features;
private UpdateCheckResult? lastUpdateCheckResult;
private bool currentUpdating;
private bool loadingData;
public MainForm()
{
InitializeComponent();
Title = $"{Title} (v{Assembly.GetExecutingAssembly().GetAppVersion().ToShortString()})";
ButtonSearchProfileFolder.Flyout = menuFlyoutSearchProfileFolder;
ButtonSearchProfileFolder.ImageSource = AppGlobals.Symbols.GetImageSource(AppSymbols.opened_folder);
ButtonCheckForUpdates.ImageSource = AppGlobals.Symbols.GetImageSource(AppSymbols.update_done);
ButtonInstall.ImageSource = AppGlobals.Symbols.GetImageSource(AppSymbols.software_installer);
MenuItemRepair.Icon = AppGlobals.Symbols.GetImage(AppSymbols.wrench, SymbolSize.Small);
ClearStatus();
LoadProfileToUi();
}
#region Features
private void SetStatus(string statusText, IImage? image)
{
TextStatus.Text = statusText;
ImageStatus.Source = image;
}
private void ClearStatus()
{
TextStatus.Text = "-";
ImageStatus.Source = null;
}
private void LoadRecentFilesToUi()
{
menuFlyoutSearchProfileFolder.Items.Clear();
if (AppConfig.Instance.RecentMinecraftProfilePaths.Count == 0)
{
menuFlyoutSearchProfileFolder.Items.Add(new TextBlock
{
Text = GeneralLangRes.NoRecentProfilesAvailable,
FontStyle = FontStyle.Italic,
});
return;
}
AppConfig.Instance.RecentMinecraftProfilePaths.ForEach(path =>
{
if (File.Exists(path))
return;
var item = new MenuItem
{
Header = path.Length > 50 ? $"...{path[^50..]}" : path,
DataContext = path,
};
item.Click += MenuItemRecentMinecraftProfilePathItem_Click;
menuFlyoutSearchProfileFolder.Items.Add(item);
});
}
private void StoreRecentMinecraftProfilePath(string? path)
{
if (string.IsNullOrWhiteSpace(path))
return;
AppConfig.Instance.RecentMinecraftProfilePaths.Remove(path);
AppConfig.Instance.RecentMinecraftProfilePaths.Insert(0, path);
AppConfig.Instance.RecentMinecraftProfilePaths.Skip(10).ForEach(n => AppConfig.Instance.RecentMinecraftProfilePaths.Remove(n));
}
private void LoadProfileToUi()
{
loadingData = true;
TextBoxMinecraftProfileFolder.Text = modpackInfo.LocalPath ?? AppConfig.Instance.RecentMinecraftProfilePaths.FirstOrDefault() ?? TextBoxMinecraftProfileFolder.Text;
TextBoxModpackConfig.Text = modpackInfo.ConfigUrl ?? TextBoxModpackConfig.Text;
TextBoxInstallKey.Text = modpackInfo.ExtrasKey ?? TextBoxInstallKey.Text;
Dispatcher.UIThread.Post(() => loadingData = false, DispatcherPriority.Background);
}
private void LoadOptionsToUi()
{
//foreach (var set in )
//{
// // ...
//}
}
private async void CheckStatusAndUpdate(bool loadProfileToUi)
{
if (!CheckStatus(loadProfileToUi))
return;
await ExecuteUpdate(false, false);
StoreRecentMinecraftProfilePath(modpackInfo.LocalPath);
LoadRecentFilesToUi();
}
private bool CheckStatus(bool loadProfileToUi)
{
try
{
modpackInfo = ModpackInfo.TryLoad(TextBoxMinecraftProfileFolder.Text?.Trim());
}
catch
{
// Ignore
}
if (loadProfileToUi)
LoadProfileToUi();
try
{
updateConfig = ModpackConfig.LoadFromUrl(TextBoxModpackConfig.Text);
}
catch
{
// Ignore
}
features = new(updateConfig);
modpackInfo.ExtrasKey = TextBoxInstallKey.Text?.Trim();
if (!features.IsInvalid() && !string.IsNullOrWhiteSpace(TextBoxInstallKey.Text) && !AllowExtras())
{
SetStatus(GeneralLangRes.InstallationKeyNotValid, AppGlobals.Symbols.GetImageSource(AppSymbols.general_warning_sign));
return false;
}
LabelInstallKey.IsVisible = TextBoxInstallKey.IsVisible = !string.IsNullOrWhiteSpace(updateConfig.UnleashApiUrl);
if (string.IsNullOrWhiteSpace(TextBoxMinecraftProfileFolder.Text) /*|| modpackInfo.Valid*/)
{
SetStatus(GeneralLangRes.MinecraftProfileFolderSeemsInvalid, AppGlobals.Symbols.GetImageSource(AppSymbols.general_warning_sign));
ButtonCheckForUpdates.IsEnabled = false;
ButtonInstall.IsEnabled = false;
return false;
}
else if (string.IsNullOrWhiteSpace(TextBoxModpackConfig.Text))
{
SetStatus(GeneralLangRes.ConfigIncompleteOrNotLoaded, AppGlobals.Symbols.GetImageSource(AppSymbols.general_warning_sign));
ButtonCheckForUpdates.IsEnabled = false;
ButtonInstall.IsEnabled = false;
return false;
}
else if (updateConfig.Maintenance && !updateOptions.IgnoreMaintenance)
{
SetStatus(GeneralLangRes.UpdateServerInMaintenance, AppGlobals.Symbols.GetImageSource(AppSymbols.services));
ButtonCheckForUpdates.IsEnabled = false;
ButtonInstall.IsEnabled = false;
return false;
}
LoadOptionsToUi();
ButtonCheckForUpdates.IsEnabled = true;
ButtonInstall.IsEnabled = true;
return true;
}
private async Task ExecuteUpdate(bool doInstall, bool repair)
{
// Ensure set extras key
modpackInfo.ExtrasKey = TextBoxInstallKey.Text?.Trim();
var updater = new ModpackInstaller(updateConfig, modpackInfo);
updater.InstallProgessUpdated += Update_InstallProgessUpdated;
updater.CheckingProgressUpdated += Updated_CheckingProgresssUpdated;
void error()
{
SetStatus(GeneralLangRes.ErrorOnUpdateCheckOrUpdating, AppGlobals.Symbols.GetImageSource(AppSymbols.close));
currentUpdating = false;
}
void installing()
{
SetStatus(GeneralLangRes.Installing, AppGlobals.Symbols.GetImageSource(AppSymbols.software_installer));
currentUpdating = true;
}
void updatesAvailable()
{
SetStatus(GeneralLangRes.AnUpdateIsAvailable, AppGlobals.Symbols.GetImageSource(AppSymbols.software_installer));
}
void everythingOk()
{
SetStatus(GeneralLangRes.EverythingIsRightAndUpToDate, AppGlobals.Symbols.GetImageSource(AppSymbols.done));
currentUpdating = false;
}
// Check only if not pressed "install", not really needed otherwise.
if (lastUpdateCheckResult is null || !doInstall || repair)
{
SetStatus(GeneralLangRes.CheckingForUpdates, AppGlobals.Symbols.GetImageSource(AppSymbols.update_done));
// Check for extras once again
updateOptions.IncludeExtras = AllowExtras();
// Force re-install on repair
updateOptions.IgnoreInstalledVersion = repair;
try
{
lastUpdateCheckResult = await updater.Check(updateOptions);
}
catch
{
error();
if (Debugger.IsAttached)
throw;
}
}
// Error while update check
if (lastUpdateCheckResult is null || lastUpdateCheckResult.HasError)
{
error();
return;
}
// Load options
// lastUpdateCheckResult.OptionsAvailable...
// lastUpdateCheckResult.OptionsEnabled...
// No updates available
if (!lastUpdateCheckResult.HasUpdates)
{
everythingOk();
return;
}
// Updates available (but don't install)
if (!doInstall)
{
updatesAvailable();
return;
}
// Install updates
installing();
currentUpdating = true;
try
{
// Install
if (await updater.Install(lastUpdateCheckResult) == false)
{
error();
return;
}
// Success
lastUpdateCheckResult = null; // Reset last update check, a new one would be needed now.
everythingOk();
}
catch (Exception)
{
// Error
error();
if (Debugger.IsAttached)
throw;
}
}
private bool AllowExtras()
{
return features != null && features.IsEnabled(ModpackFeatures.FeatureAllowExtas, new AllowExtrasFeatureContext(modpackInfo));
}
private void Updated_CheckingProgresssUpdated(int toCheck, int processed)
{
SetStatus(Math.Round(processed / (double)toCheck * 100d, 1) + "%", AppGlobals.Symbols.GetImageSource(AppSymbols.update_done));
}
private void Update_InstallProgessUpdated(UpdateCheckResult result, int processedSyncs)
{
var actionCount = result.Actions.Count;
SetStatus(Math.Round(processedSyncs / (double)actionCount * 100d, 1) + "%", AppGlobals.Symbols.GetImageSource(AppSymbols.software_installer));
}
#endregion
#region Gui
private async void MainForm_Loaded(object? sender, RoutedEventArgs e)
{
var updates = new AppUpdates("manager", this);
updates.OnDownloadProgramUpdate += (_, _) => SetStatus(GeneralLangRes.DownloadProgramUpdate, AppGlobals.Symbols.GetImageSource(AppSymbols.software_installer));
await updates.UpdateApp();
ClearStatus();
LoadRecentFilesToUi();
CheckStatusAndUpdate(true);
}
private void TextBoxMinecraftProfileFolder_TextChanged(object? o, TextChangedEventArgs args)
{
if (!loadingData)
CheckStatusAndUpdate(true);
}
private void TextBoxModpackConfig_TextChanged(object? o, RoutedEventArgs args)
{
if (!loadingData)
CheckStatusAndUpdate(false);
}
private void TextBoxInstallKey_TextChanged(object? o, RoutedEventArgs args)
{
if (!loadingData)
CheckStatusAndUpdate(false);
}
private async void ButtonSearchProfileFolder_Click(object? sender, RoutedEventArgs e)
{
var filePaths = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{
Title = GeneralLangRes.SelectMinecraftProfileFolder,
SuggestedStartLocation = await StorageProvider.TryGetFolderFromPathAsync(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)),
AllowMultiple = false,
});
if (filePaths.Count >= 1)
TextBoxMinecraftProfileFolder.Text = filePaths[0].Path.AbsolutePath;
}
private async void ButtonCheckForUpdates_Click(object? sender, RoutedEventArgs e)
{
ClearStatus();
await ExecuteUpdate(false, false);
}
private async void ButtonInstall_Click(object? sender, RoutedEventArgs e)
{
if (currentUpdating)
return;
ClearStatus();
await ExecuteUpdate(true, false);
}
private async void MenuItemRepair_Click(object? sender, RoutedEventArgs e)
{
if (currentUpdating)
return;
ClearStatus();
await ExecuteUpdate(true, true);
}
private void MenuItemRecentMinecraftProfilePathItem_Click(object? sender, RoutedEventArgs e)
{
if (sender is MenuItem item && item.DataContext is string path)
TextBoxMinecraftProfileFolder.Text = path;
}
#endregion
}

View File

@@ -0,0 +1,98 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<ApplicationIcon>Assets\app.ico</ApplicationIcon>
<AssemblyName>MinecraftModpackUpdater</AssemblyName>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</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>
<Compile Include="..\Version.cs" />
</ItemGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
<ItemGroup>
<Compile Update="FiledialogFilters.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>FiledialogFilters.resx</DependentUpon>
</Compile>
<Compile Update="LangRes\GeneralLangRes.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>GeneralLangRes.resx</DependentUpon>
</Compile>
<Compile Update="LangRes\MsgBoxLangRes.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>MsgBoxLangRes.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="FiledialogFilters.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>FiledialogFilters.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="LangRes\GeneralLangRes.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>GeneralLangRes.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="LangRes\MsgBoxLangRes.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>MsgBoxLangRes.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia.BuildServices" Version="11.3.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="MessageBox.Avalonia" Version="3.3.0" />
<PackageReference Include="Mono.Options" Version="6.12.0.148" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="Pilz" Version="2.6.1" />
<PackageReference Include="Pilz.Configuration" Version="3.2.7" />
<PackageReference Include="Pilz.Cryptography" Version="2.1.2" />
<PackageReference Include="Pilz.IO" Version="2.1.0" />
<PackageReference Include="Pilz.UI" Version="3.1.4" />
<PackageReference Include="Pilz.UI.AvaloniaUI" Version="1.2.18" />
<PackageReference Include="Avalonia" Version="11.3.8" />
<PackageReference Include="Avalonia.Desktop" Version="11.3.8" />
<PackageReference Include="Avalonia.Svg" Version="11.3.0" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.8" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.8" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics" Version="11.3.8">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="Pilz.Updating" Version="4.3.5" />
<PackageReference Include="Pilz.Updating.Client" Version="4.4.6" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ModpackUpdater.Apps\ModpackUpdater.Apps.csproj" />
<ProjectReference Include="..\ModpackUpdater.Manager\ModpackUpdater.Manager.csproj" />
<ProjectReference Include="..\ModpackUpdater\ModpackUpdater.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,47 @@
using Avalonia;
using Castle.Core.Logging;
using Newtonsoft.Json;
using Pilz;
using Pilz.Configuration;
namespace ModpackUpdater.Apps.Client.Gui;
public static class Program
{
private static readonly SettingsManager settingsManager;
public static ISettings Settings => settingsManager.Instance;
public static ILogger Log { get; } = new ConsoleLogger();
static Program()
{
settingsManager = new(GetSettingsPath(2), true);
}
[STAThread]
internal static void Main(string[] args)
{
BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
}
public static AppBuilder BuildAvaloniaApp()
{
return AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace();
}
private static string GetSettingsPath(int? settingsVersion = 3)
{
const string appDataDirectoryName = "MinecraftModpackUpdater";
var fileNamePostfix = settingsVersion == null ? string.Empty : $"V{settingsVersion}";
var settingsFileName = $"Settings{fileNamePostfix}.json";
var settingsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), appDataDirectoryName);
Directory.CreateDirectory(settingsPath);
settingsPath = Path.Combine(settingsPath, settingsFileName);
return settingsPath;
}
}

View File

@@ -6,12 +6,12 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<PropertyGroup> <PropertyGroup>
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
<Platform>Any CPU</Platform> <Platform>Any CPU</Platform>
<PublishDir>bin\publish\general\</PublishDir> <PublishDir>..\publish\ui\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol> <PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId> <_TargetId>Folder</_TargetId>
<TargetFramework>net8.0-windows</TargetFramework> <TargetFramework>net8.0-windows</TargetFramework>
<RuntimeIdentifier>win-x86</RuntimeIdentifier> <RuntimeIdentifier>win-x86</RuntimeIdentifier>
<SelfContained>false</SelfContained> <SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile> <PublishSingleFile>true</PublishSingleFile>
<PublishReadyToRun>false</PublishReadyToRun> <PublishReadyToRun>false</PublishReadyToRun>
</PropertyGroup> </PropertyGroup>

View File

@@ -0,0 +1,92 @@
# PUPNET DEPLOY: 1.9.1
# Use: 'pupnet --help conf' for information.
# APP PREAMBLE
AppBaseName = MinecraftModpackUpdater
AppFriendlyName = Minecraft Modpack Updater
AppId = de.pilzinsel64.minecraft-modpack-updater
AppVersionRelease = 1.0.0[1]
AppShortSummary = Install and Update Minecraft Modpacks easliy.
AppDescription = """
Minecraft Modpack Updater is a simple tool to install and update a modpack to a selected minecraft profile by a selected modpack configuration file. It downloads a config file via https and checks the version there and what files has been changed and download the updateded files via a given link from the config.
"""
AppLicenseId = MIT
AppLicenseFile = ../LICENSE
AppChangeFile =
# PUBLISHER
PublisherName = Pilzinsel64
PublisherId = de.pilzinsel64
PublisherCopyright = Copyright (C) Pilzinsel64 2025
PublisherLinkName = Pilzinsel64 Homepage
PublisherLinkUrl = https://pilzinsel64.de
PublisherEmail =
# DESKTOP INTEGRATION
DesktopNoDisplay = false
DesktopTerminal = false
DesktopFile =
StartCommand =
PrimeCategory =
MetaFile =
IconFiles = """
Assets/app.ico
Assets/app.svg
"""
# DOTNET PUBLISH
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=true
DotnetPostPublish =
DotnetPostPublishOnWindows =
# PACKAGE OUTPUT
PackageName = minecraft-modpack-updater
OutputDirectory = ../publish/client-ui
# APPIMAGE OPTIONS
AppImageArgs =
AppImageRuntimePath =
AppImageVersionOutput = false
# FLATPAK OPTIONS
FlatpakPlatformRuntime = org.freedesktop.Platform
FlatpakPlatformSdk = org.freedesktop.Sdk
FlatpakPlatformVersion = 25.08
FlatpakFinishArgs = """
--socket=wayland
--socket=fallback-x11
--filesystem=home
--share=network
"""
FlatpakBuilderArgs =
# RPM OPTIONS
RpmAutoReq = false
RpmAutoProv = true
RpmRequires = """
krb5-libs
libicu
openssl-libs
"""
# DEBIAN OPTIONS
DebianRecommends = """
libc6
libgcc1
libgssapi-krb5-2
libicu70
libssl3
libstdc++6
zlib1g
"""
# WINDOWS SETUP OPTIONS
SetupGroupName =
SetupAdminInstall = false
SetupCommandPrompt =
SetupMinWindowsVersion = 10
SetupSignTool =
SetupSuffixOutput =
SetupVersionOutput = false
SetupUninstallScript =

View File

@@ -0,0 +1,12 @@
pupnet -y -v "$1[1]" -r linux-x64 -k appimage
#pupnet -y -v "$1[1]" -r linux-x64 -k flatpak -p DefineConstants=DISABLE_UPDATE
#pupnet -y -v "$1[1]"-r linux-x64 -k deb -p DefineConstants=DISABLE_UPDATE
#pupnet -y -v "$1[1]"-r linux-x64 -k rpm -p DefineConstants=DISABLE_UPDATE
pupnet -y -v "$1[1]" -r linux-arm64 -k appimage
#pupnet -y -v "$1[1]" -r linux-arm64 -k flatpak -p DefineConstants=DISABLE_UPDATE
#pupnet -y -v "$1[1]"-r linux-arm64 -k deb -p DefineConstants=DISABLE_UPDATE
#pupnet -y -v "$1[1]"-r linux-arm64 -k rpm -p DefineConstants=DISABLE_UPDATE
pupnet -y -v "$1[1]" -r win-x64 -k zip
pupnet -y -v "$1[1]" -r win-arm64 -k zip
pupnet -y -v "$1[1]" -r osx-x64 -k zip
pupnet -y -v "$1[1]" -r osx-arm64 -k zip

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="TelerikWinFormsThemeName" value="Windows11CompactDark" />
</appSettings>
</configuration>

View File

@@ -1,26 +0,0 @@
using Newtonsoft.Json;
using Pilz.Configuration;
namespace ModpackUpdater.Apps.Client;
public class AppConfig : IChildSettings, ISettingsIdentifier
{
public static string Identifier => "pilz.appconfig";
public string LastMinecraftProfilePath { get; set; }
[JsonIgnore, Obsolete]
public string ConfigFilePath { get; private set; }
[JsonProperty("ConfigFilePath"), Obsolete]
private string ConfigFilePathLegacy
{
set => ConfigFilePath = value;
}
public void Reset()
{
LastMinecraftProfilePath = null;
}
public static AppConfig Instance => Program.Settings.Get<AppConfig>();
}

View File

@@ -1,79 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Pilz.Extensions;
using System.Reflection;
namespace ModpackUpdater.Apps.Client;
public class AppUpdater
{
private class UpdateInfo
{
[JsonConverter(typeof(VersionConverter))]
public Version Version { get; set; }
public string DownloadUrl { get; set; }
}
private const string UPDATE_URL = "https://git.pilzinsel64.de/gaming/minecraft/minecraft-modpack-updater/-/snippets/3/raw/main/updates.json";
private readonly HttpClient httpClient = new();
private UpdateInfo info;
public async Task<bool> Check()
{
var hasUpdate = false;
try
{
var appVersion = Assembly.GetExecutingAssembly().GetAppVersion().Version;
var result = await httpClient.GetStringAsync(UPDATE_URL);
info = JsonConvert.DeserializeObject<UpdateInfo>(result);
if (info is not null && info.Version > appVersion)
hasUpdate = true;
}
catch
{
}
return hasUpdate;
}
public async Task Install()
{
var client = new HttpClient();
var tempFileName = Path.GetTempFileName();
var appFileName = Pilz.Win32.NativeTools.GetExecutablePath();
var oldFileName = appFileName + ".old";
// Delete old file
try
{
File.Delete(oldFileName);
}
catch
{
}
// Download the new file
using (var tempFileStream = new FileStream(tempFileName, FileMode.Create, FileAccess.ReadWrite))
{
Stream downloadStream = null;
try
{
downloadStream = await client.GetStreamAsync(info.DownloadUrl);
await downloadStream.CopyToAsync(tempFileStream);
}
catch
{
}
finally
{
downloadStream?.Dispose();
}
}
// Replace current application file with new file
File.Move(appFileName, oldFileName, true);
File.Move(tempFileName, appFileName);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="480" height="480" viewBox="0 0 480 480" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="clip_path_1">
<rect width="480" height="480" />
</clipPath>
</defs>
<g clip-path="url(#clip_path_1)">
<path d="M360 40L180 40L140 0C140 0 40 0 40 0C17.91 0 0 17.91 0 40C0 40 0 120 0 120L400 120C400 120 400 80 400 80C400 57.91 382.09 40 360 40C360 40 360 40 360 40Z" fill="#FFA000" transform="translate(20 100)" />
<g transform="translate(53 -7)">
<path d="M160.042 63.3334L0 7.91667L13.9167 213.75L160.042 300.833L278.333 205.833L292.25 0L160.042 63.3334Z" fill="#5D4037" fill-rule="evenodd" transform="translate(20.875 63.333)" />
<path d="M0 0L13.9167 205.834L160.042 292.917L160.042 55.4167L0 0Z" fill="#8D6E63" fill-rule="evenodd" transform="translate(20.875 71.25)" />
<path d="M13.9167 112.084L13.9167 79.1667L27.8333 72.2554L27.8333 95L41.75 87.0833L41.75 118.75L62.625 109.028L62.625 55.4167L76.5417 48.6954L76.5417 87.0833L90.4583 80.5679L90.4583 63.3333L104.375 55.4167L104.375 35.3637L118.292 28.6979L118.292 47.5L129.425 41.1667L132.208 0L0 63.3333L0 118.75L13.9167 112.084Z" fill="#43A047" fill-rule="evenodd" transform="translate(180.917 63.333)" />
<path d="M0 47.5L139.167 0L292.25 39.5833L160.042 102.917L0 47.5Z" fill="#B2FF59" fill-rule="evenodd" transform="translate(20.875 23.75)" />
<path d="M0 0L2.78333 40.6442L13.9167 44.3888L13.9167 34.9363L27.8333 39.5833L27.8333 65.0513L48.7083 72.2792L48.7083 34.6196L62.625 39.5833L62.625 77.1004L76.5417 81.9217L76.5417 58.9713L90.4583 63.7925L90.4583 86.743L104.375 91.5563L104.375 82.1671L118.292 87.0834L118.292 74.6067L132.208 79.1667L132.208 101.199L160.042 110.833L160.042 55.4167L0 0Z" fill="#66BB6A" fill-rule="evenodd" transform="translate(20.875 71.25)" />
</g>
<path d="M360 0C360 0 40 0 40 0C17.91 0 0 15.1595 0 33.8571C0 33.8571 0 203.143 0 203.143C0 221.84 17.91 237 40 237C40 237 360 237 360 237C382.09 237 400 221.84 400 203.143C400 203.143 400 33.8571 400 33.8571C400 15.1595 382.09 0 360 0C360 0 360 0 360 0Z" fill="#FFCA28" transform="translate(20 183)" />
<path d="M70 80L0 0L140 0L70 80Z" fill="#1565C0" transform="translate(150 380)" />
<path d="M0 0L60 0L60 111.25L0 111.25L0 0Z" fill="#1565C0" transform="translate(190 280)" />
<path d="M30 15C30 23.28 23.29 30 15 30C6.71002 30 0 23.28 0 15C0 6.72 6.71002 0 15 0C23.29 0 30 6.72 30 15C30 15 30 15 30 15Z" fill="#4A148C" transform="translate(430 60)" />
<path d="M125 100C72.62 100 30 57.38 30 5C30 5 30 0 30 0L0 0L0 10C0 10 0.25 10 0.25 10C2.84 74.93 55.08 127.16 120 129.75C120 129.75 120 130 120 130L130 130L130 100L125 100C125 100 125 100 125 100Z" fill="#9C27B0" transform="translate(330 60)" />
<path d="M75 50C50.19 50 30 29.81 30 5C30 5 30 0 30 0L0 0L0 10C0 10 0.25 10 0.25 10C2.73004 47.36 32.63 77.27 70 79.75C70 79.75 70 80 70 80L80 80L80 50L75 50C75 50 75 50 75 50Z" fill="#7B1FA2" transform="translate(380 60)" />
<path d="M175 150C95.05 150 30 84.95 30 5C30 5 30 0 30 0L0 0L0 10C0 10 0.25 10 0.25 10C2.88998 102.5 77.51 177.11 170 179.75C170 179.75 170 180 170 180L180 180L180 150L175 150C175 150 175 150 175 150Z" fill="#BA68C8" transform="translate(280 60)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -1,334 +0,0 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
namespace ModpackUpdater.Apps.Client
{
[Microsoft.VisualBasic.CompilerServices.DesignerGenerated()]
public partial class Form1 : Telerik.WinControls.UI.RadForm
{
// Das Formular überschreibt den Löschvorgang, um die Komponentenliste zu bereinigen.
[DebuggerNonUserCode()]
protected override void Dispose(bool disposing)
{
try
{
if (disposing && components is not null)
components.Dispose();
}
finally
{
base.Dispose(disposing);
}
}
// Wird vom Windows Form-Designer benötigt.
private System.ComponentModel.IContainer components = new System.ComponentModel.Container();
// Hinweis: Die folgende Prozedur ist für den Windows Form-Designer erforderlich.
// Das Bearbeiten ist mit dem Windows Form-Designer möglich.
// Das Bearbeiten mit dem Code-Editor ist nicht möglich.
[DebuggerStepThrough()]
private void InitializeComponent()
{
var resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
RadLabel1 = new Telerik.WinControls.UI.RadLabel();
RadLabel2 = new Telerik.WinControls.UI.RadLabel();
RadLabel3 = new Telerik.WinControls.UI.RadLabel();
RadLabel_Status = new Telerik.WinControls.UI.RadLabel();
RadTextBox_MinecraftProfileFolder = new Telerik.WinControls.UI.RadTextBox();
RadTextBox_ModpackConfig = new Telerik.WinControls.UI.RadTextBox();
RadButton_Install = new Telerik.WinControls.UI.RadButton();
RadButton_CheckForUpdates = new Telerik.WinControls.UI.RadButton();
RadButton_PasteModpackConfig = new Telerik.WinControls.UI.RadButton();
RadButton_SearchMinecraftProfileFolder = new Telerik.WinControls.UI.RadButton();
tableLayoutPanel1 = new TableLayoutPanel();
radLabel4 = new Telerik.WinControls.UI.RadLabel();
radTextBox_InstallKey = new Telerik.WinControls.UI.RadTextBox();
radButton_PasteInstallKey = new Telerik.WinControls.UI.RadButton();
radButton_RefreshConfig = new Telerik.WinControls.UI.RadButton();
((System.ComponentModel.ISupportInitialize)RadLabel1).BeginInit();
((System.ComponentModel.ISupportInitialize)RadLabel2).BeginInit();
((System.ComponentModel.ISupportInitialize)RadLabel3).BeginInit();
((System.ComponentModel.ISupportInitialize)RadLabel_Status).BeginInit();
((System.ComponentModel.ISupportInitialize)RadTextBox_MinecraftProfileFolder).BeginInit();
((System.ComponentModel.ISupportInitialize)RadTextBox_ModpackConfig).BeginInit();
((System.ComponentModel.ISupportInitialize)RadButton_Install).BeginInit();
((System.ComponentModel.ISupportInitialize)RadButton_CheckForUpdates).BeginInit();
((System.ComponentModel.ISupportInitialize)RadButton_PasteModpackConfig).BeginInit();
((System.ComponentModel.ISupportInitialize)RadButton_SearchMinecraftProfileFolder).BeginInit();
tableLayoutPanel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)radLabel4).BeginInit();
((System.ComponentModel.ISupportInitialize)radTextBox_InstallKey).BeginInit();
((System.ComponentModel.ISupportInitialize)radButton_PasteInstallKey).BeginInit();
((System.ComponentModel.ISupportInitialize)radButton_RefreshConfig).BeginInit();
((System.ComponentModel.ISupportInitialize)this).BeginInit();
SuspendLayout();
//
// RadLabel1
//
RadLabel1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
RadLabel1.AutoSize = false;
RadLabel1.Location = new Point(3, 3);
RadLabel1.Name = "RadLabel1";
RadLabel1.Size = new Size(144, 24);
RadLabel1.TabIndex = 0;
RadLabel1.Text = "Minecraft profile folder:";
//
// RadLabel2
//
RadLabel2.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
RadLabel2.AutoSize = false;
RadLabel2.Location = new Point(3, 63);
RadLabel2.Name = "RadLabel2";
RadLabel2.Size = new Size(144, 24);
RadLabel2.TabIndex = 1;
RadLabel2.Text = "Modpack config:";
//
// RadLabel3
//
RadLabel3.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
RadLabel3.AutoSize = false;
RadLabel3.Location = new Point(3, 183);
RadLabel3.Name = "RadLabel3";
RadLabel3.Size = new Size(144, 24);
RadLabel3.TabIndex = 2;
RadLabel3.Text = "Status:";
//
// RadLabel_Status
//
RadLabel_Status.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
RadLabel_Status.AutoSize = false;
tableLayoutPanel1.SetColumnSpan(RadLabel_Status, 6);
RadLabel_Status.Location = new Point(153, 183);
RadLabel_Status.Name = "RadLabel_Status";
RadLabel_Status.Size = new Size(266, 24);
RadLabel_Status.TabIndex = 3;
RadLabel_Status.Text = "-";
RadLabel_Status.TextImageRelation = TextImageRelation.ImageBeforeText;
//
// RadTextBox_MinecraftProfileFolder
//
RadTextBox_MinecraftProfileFolder.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
tableLayoutPanel1.SetColumnSpan(RadTextBox_MinecraftProfileFolder, 6);
RadTextBox_MinecraftProfileFolder.Location = new Point(153, 3);
RadTextBox_MinecraftProfileFolder.Name = "RadTextBox_MinecraftProfileFolder";
RadTextBox_MinecraftProfileFolder.NullText = "No file loaded!";
RadTextBox_MinecraftProfileFolder.ReadOnly = true;
RadTextBox_MinecraftProfileFolder.Size = new Size(266, 24);
RadTextBox_MinecraftProfileFolder.TabIndex = 4;
//
// RadTextBox_ModpackConfig
//
RadTextBox_ModpackConfig.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
tableLayoutPanel1.SetColumnSpan(RadTextBox_ModpackConfig, 6);
RadTextBox_ModpackConfig.Location = new Point(153, 63);
RadTextBox_ModpackConfig.Name = "RadTextBox_ModpackConfig";
RadTextBox_ModpackConfig.NullText = "No config url provided.";
RadTextBox_ModpackConfig.ReadOnly = true;
RadTextBox_ModpackConfig.Size = new Size(266, 24);
RadTextBox_ModpackConfig.TabIndex = 5;
//
// RadButton_Install
//
RadButton_Install.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
tableLayoutPanel1.SetColumnSpan(RadButton_Install, 2);
RadButton_Install.ImageAlignment = ContentAlignment.MiddleRight;
RadButton_Install.Location = new Point(325, 213);
RadButton_Install.Name = "RadButton_Install";
RadButton_Install.Size = new Size(94, 24);
RadButton_Install.TabIndex = 10;
RadButton_Install.Text = "Install";
RadButton_Install.TextAlignment = ContentAlignment.MiddleLeft;
RadButton_Install.TextImageRelation = TextImageRelation.ImageBeforeText;
RadButton_Install.Click += ButtonX_StartUpdate_Click;
//
// RadButton_CheckForUpdates
//
RadButton_CheckForUpdates.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
tableLayoutPanel1.SetColumnSpan(RadButton_CheckForUpdates, 3);
RadButton_CheckForUpdates.ImageAlignment = ContentAlignment.MiddleRight;
RadButton_CheckForUpdates.Location = new Point(175, 213);
RadButton_CheckForUpdates.Name = "RadButton_CheckForUpdates";
RadButton_CheckForUpdates.Size = new Size(144, 24);
RadButton_CheckForUpdates.TabIndex = 0;
RadButton_CheckForUpdates.Text = "Check for Updates";
RadButton_CheckForUpdates.TextAlignment = ContentAlignment.MiddleLeft;
RadButton_CheckForUpdates.TextImageRelation = TextImageRelation.ImageBeforeText;
RadButton_CheckForUpdates.Click += ButtonX_CheckForUpdates_Click;
//
// RadButton_PasteModpackConfig
//
RadButton_PasteModpackConfig.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
tableLayoutPanel1.SetColumnSpan(RadButton_PasteModpackConfig, 2);
RadButton_PasteModpackConfig.ImageAlignment = ContentAlignment.MiddleRight;
RadButton_PasteModpackConfig.Location = new Point(325, 93);
RadButton_PasteModpackConfig.Name = "RadButton_PasteModpackConfig";
RadButton_PasteModpackConfig.Size = new Size(94, 24);
RadButton_PasteModpackConfig.TabIndex = 7;
RadButton_PasteModpackConfig.Text = "Paste";
RadButton_PasteModpackConfig.TextAlignment = ContentAlignment.MiddleLeft;
RadButton_PasteModpackConfig.TextImageRelation = TextImageRelation.ImageBeforeText;
RadButton_PasteModpackConfig.Click += RadButton_PasteModpackConfig_Click;
//
// RadButton_SearchMinecraftProfileFolder
//
RadButton_SearchMinecraftProfileFolder.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
tableLayoutPanel1.SetColumnSpan(RadButton_SearchMinecraftProfileFolder, 2);
RadButton_SearchMinecraftProfileFolder.ImageAlignment = ContentAlignment.MiddleRight;
RadButton_SearchMinecraftProfileFolder.Location = new Point(325, 33);
RadButton_SearchMinecraftProfileFolder.Name = "RadButton_SearchMinecraftProfileFolder";
RadButton_SearchMinecraftProfileFolder.Size = new Size(94, 24);
RadButton_SearchMinecraftProfileFolder.TabIndex = 6;
RadButton_SearchMinecraftProfileFolder.Text = "Search";
RadButton_SearchMinecraftProfileFolder.TextAlignment = ContentAlignment.MiddleLeft;
RadButton_SearchMinecraftProfileFolder.TextImageRelation = TextImageRelation.ImageBeforeText;
RadButton_SearchMinecraftProfileFolder.Click += ButtonX_SearchMinecraftProfile_Click;
//
// tableLayoutPanel1
//
tableLayoutPanel1.AutoSize = true;
tableLayoutPanel1.AutoSizeMode = AutoSizeMode.GrowAndShrink;
tableLayoutPanel1.ColumnCount = 7;
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 150F));
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 50F));
tableLayoutPanel1.Controls.Add(RadButton_CheckForUpdates, 2, 7);
tableLayoutPanel1.Controls.Add(RadLabel1, 0, 0);
tableLayoutPanel1.Controls.Add(RadLabel2, 0, 2);
tableLayoutPanel1.Controls.Add(RadTextBox_MinecraftProfileFolder, 1, 0);
tableLayoutPanel1.Controls.Add(RadTextBox_ModpackConfig, 1, 2);
tableLayoutPanel1.Controls.Add(RadLabel_Status, 1, 6);
tableLayoutPanel1.Controls.Add(RadLabel3, 0, 6);
tableLayoutPanel1.Controls.Add(RadButton_SearchMinecraftProfileFolder, 5, 1);
tableLayoutPanel1.Controls.Add(RadButton_Install, 5, 7);
tableLayoutPanel1.Controls.Add(radLabel4, 0, 4);
tableLayoutPanel1.Controls.Add(radTextBox_InstallKey, 1, 4);
tableLayoutPanel1.Controls.Add(radButton_PasteInstallKey, 5, 5);
tableLayoutPanel1.Controls.Add(RadButton_PasteModpackConfig, 5, 3);
tableLayoutPanel1.Controls.Add(radButton_RefreshConfig, 4, 3);
tableLayoutPanel1.Dock = DockStyle.Fill;
tableLayoutPanel1.Location = new Point(0, 0);
tableLayoutPanel1.Name = "tableLayoutPanel1";
tableLayoutPanel1.RowCount = 8;
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.Size = new Size(422, 249);
tableLayoutPanel1.TabIndex = 7;
//
// radLabel4
//
radLabel4.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
radLabel4.AutoSize = false;
radLabel4.Location = new Point(3, 123);
radLabel4.Name = "radLabel4";
radLabel4.Size = new Size(144, 24);
radLabel4.TabIndex = 12;
radLabel4.Text = "Installation key:";
//
// radTextBox_InstallKey
//
radTextBox_InstallKey.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
tableLayoutPanel1.SetColumnSpan(radTextBox_InstallKey, 6);
radTextBox_InstallKey.Location = new Point(153, 123);
radTextBox_InstallKey.Name = "radTextBox_InstallKey";
radTextBox_InstallKey.NullText = "No key provided. Only for private servers.";
radTextBox_InstallKey.ReadOnly = true;
radTextBox_InstallKey.Size = new Size(266, 24);
radTextBox_InstallKey.TabIndex = 13;
//
// radButton_PasteInstallKey
//
radButton_PasteInstallKey.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
tableLayoutPanel1.SetColumnSpan(radButton_PasteInstallKey, 2);
radButton_PasteInstallKey.ImageAlignment = ContentAlignment.MiddleRight;
radButton_PasteInstallKey.Location = new Point(325, 153);
radButton_PasteInstallKey.Name = "radButton_PasteInstallKey";
radButton_PasteInstallKey.Size = new Size(94, 24);
radButton_PasteInstallKey.TabIndex = 14;
radButton_PasteInstallKey.Text = "Paste";
radButton_PasteInstallKey.TextAlignment = ContentAlignment.MiddleLeft;
radButton_PasteInstallKey.TextImageRelation = TextImageRelation.ImageBeforeText;
radButton_PasteInstallKey.Click += RadButton_PasteInstallKey_Click;
//
// radButton_RefreshConfig
//
radButton_RefreshConfig.Anchor = AnchorStyles.Top | AnchorStyles.Right;
radButton_RefreshConfig.DisplayStyle = Telerik.WinControls.DisplayStyle.Image;
radButton_RefreshConfig.ImageAlignment = ContentAlignment.MiddleCenter;
radButton_RefreshConfig.Location = new Point(295, 93);
radButton_RefreshConfig.Name = "radButton_RefreshConfig";
radButton_RefreshConfig.Size = new Size(24, 24);
radButton_RefreshConfig.TabIndex = 11;
radButton_RefreshConfig.Text = "Reload";
radButton_RefreshConfig.Click += RadButton_RefreshConfig_Click;
//
// Form1
//
AutoScaleBaseSize = new Size(7, 15);
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
AutoSize = true;
AutoSizeMode = AutoSizeMode.GrowAndShrink;
ClientSize = new Size(422, 249);
Controls.Add(tableLayoutPanel1);
Icon = (Icon)resources.GetObject("$this.Icon");
MaximizeBox = false;
MinimumSize = new Size(430, 0);
Name = "Form1";
StartPosition = FormStartPosition.CenterScreen;
Text = "Minecraft Modpack Updater";
FormClosing += Form1_FormClosing;
Load += Form1_Load;
Shown += Form1_Shown;
((System.ComponentModel.ISupportInitialize)RadLabel1).EndInit();
((System.ComponentModel.ISupportInitialize)RadLabel2).EndInit();
((System.ComponentModel.ISupportInitialize)RadLabel3).EndInit();
((System.ComponentModel.ISupportInitialize)RadLabel_Status).EndInit();
((System.ComponentModel.ISupportInitialize)RadTextBox_MinecraftProfileFolder).EndInit();
((System.ComponentModel.ISupportInitialize)RadTextBox_ModpackConfig).EndInit();
((System.ComponentModel.ISupportInitialize)RadButton_Install).EndInit();
((System.ComponentModel.ISupportInitialize)RadButton_CheckForUpdates).EndInit();
((System.ComponentModel.ISupportInitialize)RadButton_PasteModpackConfig).EndInit();
((System.ComponentModel.ISupportInitialize)RadButton_SearchMinecraftProfileFolder).EndInit();
tableLayoutPanel1.ResumeLayout(false);
tableLayoutPanel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)radLabel4).EndInit();
((System.ComponentModel.ISupportInitialize)radTextBox_InstallKey).EndInit();
((System.ComponentModel.ISupportInitialize)radButton_PasteInstallKey).EndInit();
((System.ComponentModel.ISupportInitialize)radButton_RefreshConfig).EndInit();
((System.ComponentModel.ISupportInitialize)this).EndInit();
ResumeLayout(false);
PerformLayout();
}
internal Telerik.WinControls.UI.RadLabel RadLabel1;
internal Telerik.WinControls.UI.RadLabel RadLabel2;
internal Telerik.WinControls.UI.RadLabel RadLabel3;
internal Telerik.WinControls.UI.RadLabel RadLabel_Status;
internal Telerik.WinControls.UI.RadTextBox RadTextBox_MinecraftProfileFolder;
internal Telerik.WinControls.UI.RadTextBox RadTextBox_ModpackConfig;
internal Telerik.WinControls.UI.RadButton RadButton_Install;
internal Telerik.WinControls.UI.RadButton RadButton_CheckForUpdates;
internal Telerik.WinControls.UI.RadButton RadButton_SearchMinecraftProfileFolder;
internal Telerik.WinControls.UI.RadButton RadButton_PasteModpackConfig;
private TableLayoutPanel tableLayoutPanel1;
private Telerik.WinControls.UI.RadButton radButton_RefreshConfig;
internal Telerik.WinControls.UI.RadLabel radLabel4;
internal Telerik.WinControls.UI.RadTextBox radTextBox_InstallKey;
internal Telerik.WinControls.UI.RadButton radButton_PasteInstallKey;
}
}

View File

@@ -1,310 +0,0 @@
using ModpackUpdater.Manager;
using ModpackUpdater.My.Resources;
using Pilz.Extensions;
using Pilz.UI.Symbols;
using System.Diagnostics;
using System.Reflection;
using Telerik.WinControls;
using Telerik.WinControls.UI;
namespace ModpackUpdater.Apps.Client;
public partial class Form1
{
private ModpackInfo modpackInfo = new();
private ModpackConfig updateConfig = new();
private ModpackFeatures features;
private bool currentUpdating = false;
private UpdateCheckResult lastUpdateCheckResult = null;
private readonly UpdateCheckOptionsAdv updateOptions;
public Form1(UpdateCheckOptionsAdv updateOptions) : this()
{
this.updateOptions = updateOptions;
if (!string.IsNullOrWhiteSpace(updateOptions.ProfileFolder))
LoadMinecraftProfile(updateOptions.ProfileFolder);
else if (!string.IsNullOrWhiteSpace(AppConfig.Instance.LastMinecraftProfilePath))
LoadMinecraftProfile(AppConfig.Instance.LastMinecraftProfilePath);
}
public Form1()
{
InitializeComponent();
Text = $"{Text} (v{Assembly.GetExecutingAssembly().GetAppVersion()})";
RadButton_Install.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small);
RadButton_CheckForUpdates.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.update_done, SymbolSize.Small);
radButton_RefreshConfig.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.refresh, SymbolSize.Small);
RadButton_SearchMinecraftProfileFolder.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.opened_folder, SymbolSize.Small);
radButton_PasteInstallKey.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.paste, SymbolSize.Small);
RadButton_PasteModpackConfig.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.paste, SymbolSize.Small);
}
private void LoadMinecraftProfile(string folderPath)
{
RadTextBox_MinecraftProfileFolder.Text = folderPath;
AppConfig.Instance.LastMinecraftProfilePath = folderPath;
CheckStatusAndUpdate(loadedProfile: true);
}
private void LoadUpdateConfigFile(string filePath)
{
RadTextBox_ModpackConfig.Text = filePath;
CheckStatusAndUpdate();
}
private void LoadInstallKey(string installKey)
{
radTextBox_InstallKey.Text = installKey;
CheckStatusAndUpdate();
}
private void SetStatus(string statusText, RadSvgImage image)
{
RadLabel_Status.Text = statusText;
RadLabel_Status.SvgImage = image;
}
private void ClearStatus()
{
RadLabel_Status.Text = "-";
RadLabel_Status.SvgImage = null;
}
private void CheckStatusAndUpdate(bool loadedProfile = false)
{
if (CheckStatus(loadedProfile))
RadButton_CheckForUpdates.PerformClick();
}
private bool CheckStatus(bool loadedProfile)
{
try
{
modpackInfo = ModpackInfo.TryLoad(RadTextBox_MinecraftProfileFolder.Text.Trim());
if (loadedProfile)
{
RadTextBox_ModpackConfig.Text = modpackInfo.ConfigUrl;
radTextBox_InstallKey.Text = modpackInfo.ExtrasKey;
}
else
radTextBox_InstallKey.Text = radTextBox_InstallKey.Text;
}
catch
{
}
try
{
updateConfig = ModpackConfig.LoadFromUrl(RadTextBox_ModpackConfig.Text);
}
catch (Exception)
{
}
if (modpackInfo != null)
features = new(updateConfig);
if (modpackInfo == null || string.IsNullOrWhiteSpace(RadTextBox_MinecraftProfileFolder.Text) /*|| modpackInfo.Valid*/)
{
SetStatus(LangRes.StatusText_MinecraftProfileWarning, AppGlobals.Symbols.GetSvgImage(AppSymbols.general_warning_sign, SymbolSize.Small));
RadButton_PasteModpackConfig.Enabled = false;
radButton_PasteInstallKey.Enabled = false;
RadButton_CheckForUpdates.Enabled = false;
RadButton_Install.Enabled = false;
return false;
}
else if (updateConfig == null || string.IsNullOrWhiteSpace(RadTextBox_ModpackConfig.Text))
{
SetStatus(LangRes.StatusText_ConfigIncompleteOrNotLoaded, AppGlobals.Symbols.GetSvgImage(AppSymbols.general_warning_sign, SymbolSize.Small));
RadButton_PasteModpackConfig.Enabled = true;
radButton_PasteInstallKey.Enabled = false;
RadButton_CheckForUpdates.Enabled = false;
RadButton_Install.Enabled = false;
return false;
}
else if (updateConfig.Maintenance && !updateOptions.IgnoreMaintenance)
{
SetStatus(LangRes.StatusText_Maintenance, AppGlobals.Symbols.GetSvgImage(AppSymbols.services, SymbolSize.Small));
RadButton_PasteModpackConfig.Enabled = true;
radButton_PasteInstallKey.Enabled = true;
RadButton_CheckForUpdates.Enabled = false;
RadButton_Install.Enabled = false;
return false;
}
RadButton_PasteModpackConfig.Enabled = true;
radButton_PasteInstallKey.Enabled = true;
RadButton_CheckForUpdates.Enabled = true;
RadButton_Install.Enabled = true;
return true;
}
private async Task ExecuteUpdate(bool doInstall)
{
var updater = new ModpackInstaller(updateConfig, modpackInfo);
updater.InstallProgessUpdated += Update_InstallProgessUpdated;
updater.CheckingProgressUpdated += Updated_CheckingProgresssUpdated;
void error()
{
SetStatus(LangRes.StatusText_ErrorWhileUpdateCheckOrUpdate, AppGlobals.Symbols.GetSvgImage(AppSymbols.close, SymbolSize.Small));
currentUpdating = false;
}
void installing()
{
SetStatus(LangRes.StatusText_Installing, AppGlobals.Symbols.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small));
currentUpdating = true;
}
void updatesAvailable()
{
SetStatus(LangRes.StatusText_UpdateAvailable, AppGlobals.Symbols.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small));
}
void everythingOk()
{
SetStatus(LangRes.StatusTest_EverythingOk, AppGlobals.Symbols.GetSvgImage(AppSymbols.done, SymbolSize.Small));
currentUpdating = false;
}
// Check only if not pressed "install", not really needed otherwise.
if (lastUpdateCheckResult is null || !doInstall)
{
SetStatus(LangRes.StatusText_CheckingForUpdates, AppGlobals.Symbols.GetSvgImage(AppSymbols.update_done, SymbolSize.Small));
// Check for extras once again
updateOptions.IncludeExtras = features.IsEnabled(ModpackFeatures.FeatureAllowExtas, new AllowExtrasFeatureContext(modpackInfo));
try
{
lastUpdateCheckResult = await updater.Check(updateOptions);
}
catch(Exception)
{
error();
if (Debugger.IsAttached)
throw;
}
finally
{
}
}
// Error while update check
if (lastUpdateCheckResult is null || lastUpdateCheckResult.HasError)
{
error();
return;
}
// No updates available
if (!lastUpdateCheckResult.HasUpdates)
{
everythingOk();
return;
}
// Updates available (but don't install)
if (!doInstall)
{
updatesAvailable();
return;
}
// Install updates
installing();
currentUpdating = true;
try
{
// Install
if (await updater.Install(lastUpdateCheckResult) == false)
{
error();
return;
}
// Success
lastUpdateCheckResult = null; // Reset last update check, a new one would be needed now.
everythingOk();
}
catch (Exception)
{
// Error
error();
if (Debugger.IsAttached)
throw;
}
}
private void Update_InstallProgessUpdated(UpdateCheckResult result, int processedSyncs)
{
int actionCount = result.Actions.Count;
SetStatus(Math.Round(processedSyncs / (double)actionCount * 100d, 1) + "%", AppGlobals.Symbols.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small));
}
private void Updated_CheckingProgresssUpdated(int toCheck, int processed)
{
SetStatus(Math.Round(processed / (double)toCheck * 100d, 1) + "%", AppGlobals.Symbols.GetSvgImage(AppSymbols.update_done, SymbolSize.Small));
}
private void ButtonX_SearchMinecraftProfile_Click(object sender, EventArgs e)
{
var ofd = new RadOpenFolderDialog();
if (ofd.ShowDialog(this) == DialogResult.OK)
LoadMinecraftProfile(ofd.FileName);
}
private void RadButton_PasteModpackConfig_Click(object sender, EventArgs e)
{
LoadUpdateConfigFile(Clipboard.GetText());
}
private void RadButton_PasteInstallKey_Click(object sender, EventArgs e)
{
LoadInstallKey(Clipboard.GetText());
}
private void RadButton_RefreshConfig_Click(object sender, EventArgs e)
{
LoadUpdateConfigFile(RadTextBox_ModpackConfig.Text);
}
private async void ButtonX_CheckForUpdates_Click(object sender, EventArgs e)
{
ClearStatus();
await ExecuteUpdate(false);
}
private async void ButtonX_StartUpdate_Click(object sender, EventArgs e)
{
if (!currentUpdating)
{
ClearStatus();
await ExecuteUpdate(true);
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
AppConfig.Instance.LastMinecraftProfilePath = RadTextBox_MinecraftProfileFolder.Text;
}
private void Form1_Load(object sender, EventArgs e)
{
if (Directory.Exists(AppConfig.Instance.LastMinecraftProfilePath))
LoadMinecraftProfile(AppConfig.Instance.LastMinecraftProfilePath);
}
private async void Form1_Shown(object sender, EventArgs e)
{
var updater = new AppUpdater();
if (!updateOptions.NoUpdate && await updater.Check() && RadMessageBox.Show(LangRes.MsgBox_UpdateAvailable, LangRes.MsgBox_UpdateAvailable_Title, MessageBoxButtons.YesNo, RadMessageIcon.Info) == DialogResult.Yes)
{
SetStatus(LangRes.StatusText_InstallingAppUpdate, AppGlobals.Symbols.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small));
Enabled = false;
await updater.Install();
Application.Restart();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,162 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ModpackUpdater.My.Resources {
using System;
/// <summary>
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
/// </summary>
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class LangRes {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal LangRes() {
}
/// <summary>
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModpackUpdater.Apps.Client.LangRes", typeof(LangRes).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die A new version of this program is available. If you confirm, the update will be installed automatically. It takes just a few seconds. Continue? ähnelt.
/// </summary>
internal static string MsgBox_UpdateAvailable {
get {
return ResourceManager.GetString("MsgBox_UpdateAvailable", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die New program version available ähnelt.
/// </summary>
internal static string MsgBox_UpdateAvailable_Title {
get {
return ResourceManager.GetString("MsgBox_UpdateAvailable_Title", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Everything is right and up-to-date. ähnelt.
/// </summary>
internal static string StatusTest_EverythingOk {
get {
return ResourceManager.GetString("StatusTest_EverythingOk", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Checking for Updates... ähnelt.
/// </summary>
internal static string StatusText_CheckingForUpdates {
get {
return ResourceManager.GetString("StatusText_CheckingForUpdates", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Config incomplete or not loaded! ähnelt.
/// </summary>
internal static string StatusText_ConfigIncompleteOrNotLoaded {
get {
return ResourceManager.GetString("StatusText_ConfigIncompleteOrNotLoaded", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Error on update check or while updating! ähnelt.
/// </summary>
internal static string StatusText_ErrorWhileUpdateCheckOrUpdate {
get {
return ResourceManager.GetString("StatusText_ErrorWhileUpdateCheckOrUpdate", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Installing... ähnelt.
/// </summary>
internal static string StatusText_Installing {
get {
return ResourceManager.GetString("StatusText_Installing", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Downloading program update... ähnelt.
/// </summary>
internal static string StatusText_InstallingAppUpdate {
get {
return ResourceManager.GetString("StatusText_InstallingAppUpdate", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die The update servers are in maintenance. ähnelt.
/// </summary>
internal static string StatusText_Maintenance {
get {
return ResourceManager.GetString("StatusText_Maintenance", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Minecraft profile folder seems to be not valid. ähnelt.
/// </summary>
internal static string StatusText_MinecraftProfileWarning {
get {
return ResourceManager.GetString("StatusText_MinecraftProfileWarning", resourceCulture);
}
}
/// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die An update is available! ähnelt.
/// </summary>
internal static string StatusText_UpdateAvailable {
get {
return ResourceManager.GetString("StatusText_UpdateAvailable", resourceCulture);
}
}
}
}

View File

@@ -2,54 +2,33 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework> <ApplicationIcon>Assets\app.ico</ApplicationIcon>
<UseWindowsForms>true</UseWindowsForms> <AssemblyName>MinecraftModpackUpdaterCli</AssemblyName>
<ApplicationIcon>icons8_download_from_ftp.ico</ApplicationIcon>
<AssemblyName>Minecraft Modpack Updater</AssemblyName>
<ImplicitUsings>true</ImplicitUsings>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Update="FiledialogFilters.Designer.cs"> <TrimmerRootAssembly Include="MinecraftModpackUpdaterCli"/>
<DesignTime>True</DesignTime> <TrimmerRootAssembly Include="ModpackUpdater.Manager"/>
<AutoGen>True</AutoGen> <TrimmerRootAssembly Include="ModpackUpdater"/>
<DependentUpon>FiledialogFilters.resx</DependentUpon>
</Compile>
<Compile Update="LangRes.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>LangRes.resx</DependentUpon>
</Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Update="FiledialogFilters.resx"> <Compile Include="..\Version.cs" />
<Generator>ResXFileCodeGenerator</Generator> </ItemGroup>
<CustomToolNamespace>ModpackUpdater.My.Resources</CustomToolNamespace>
<LastGenOutput>FiledialogFilters.Designer.cs</LastGenOutput> <ItemGroup>
</EmbeddedResource> <AvaloniaResource Include="Assets\**" />
<EmbeddedResource Update="LangRes.resx">
<Generator>ResXFileCodeGenerator</Generator>
<CustomToolNamespace>ModpackUpdater.My.Resources</CustomToolNamespace>
<LastGenOutput>LangRes.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Mono.Options" Version="6.12.0.148" /> <PackageReference Include="Mono.Options" Version="6.12.0.148" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="Pilz.Configuration" Version="3.1.3" /> <PackageReference Include="Pilz" Version="2.6.1" />
<PackageReference Include="Pilz.Cryptography" Version="2.1.1" /> <PackageReference Include="Pilz.Cryptography" Version="2.1.2" />
<PackageReference Include="Pilz.IO" Version="2.1.0" /> <PackageReference Include="Pilz.IO" Version="2.1.0" />
<PackageReference Include="Pilz.UI" Version="2.3.10" />
<PackageReference Include="Pilz.UI.Telerik" Version="2.7.4" />
<PackageReference Include="Pilz.Win32" Version="2.1.0" />
<PackageReference Include="UI.for.WinForms.Common" Version="2024.3.806" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ModpackUpdater.Apps\ModpackUpdater.Apps.csproj" />
<ProjectReference Include="..\ModpackUpdater.Manager\ModpackUpdater.Manager.csproj" /> <ProjectReference Include="..\ModpackUpdater.Manager\ModpackUpdater.Manager.csproj" />
<ProjectReference Include="..\ModpackUpdater\ModpackUpdater.csproj" /> <ProjectReference Include="..\ModpackUpdater\ModpackUpdater.csproj" />
</ItemGroup> </ItemGroup>

View File

@@ -10,7 +10,8 @@ internal class Options
public IReadOnlyList<string> Additionals => additionals; public IReadOnlyList<string> Additionals => additionals;
public bool Help { get; private set; } public bool Help { get; private set; }
public bool Silent { get; private set; } public bool Silent { get; private set; }
public bool NoUi { get; private set; } public string? RefTag { get; private set; }
public string? Version { get; private set; }
public UpdateCheckOptionsAdv UpdateOptions { get; } = new(); public UpdateCheckOptionsAdv UpdateOptions { get; } = new();
public Options(string[] args) public Options(string[] args)
@@ -19,15 +20,15 @@ internal class Options
{ {
{ "silent", "Do not output anything.", s => Silent = true }, { "silent", "Do not output anything.", s => Silent = true },
{ "h|help", "Writes the help text as output.", h => Help = true }, { "h|help", "Writes the help text as output.", h => Help = true },
{ "n|noui", "Install without user interface.", n => NoUi = true },
{ "p|profile=", "Sets the minecraft profile folder.", p => UpdateOptions.ProfileFolder = p }, { "p|profile=", "Sets the minecraft profile folder.", p => UpdateOptions.ProfileFolder = p },
{ "c|config=", "Sets the modpack update info url.", c => UpdateOptions.ModpackConfig = c }, { "c|config=", "Sets the modpack update info url.", c => UpdateOptions.ModpackConfig = c },
{ "s|side=", "Sets the installation side.\nDefault side is Client.\nAvailable: Client, Server", s => UpdateOptions.Side = Enum.Parse<Side>(s)}, { "s|side=", "Sets the installation side.\nDefault side is Client.\nAvailable: Client, Server", s => UpdateOptions.Side = Enum.Parse<Side>(s)},
{ "u|uai", "Disallow an update directly after install. This only has effect if there is no existing installation.", uai => UpdateOptions.AllowUpdaterAfterInstall = false}, { "u|uai", "Disallow an update directly after install. This only has effect if there is no existing installation.", uai => UpdateOptions.AllowUpdaterAfterInstall = false},
{ "noupdate", "Skip the update check.", noupdate => UpdateOptions.NoUpdate = true},
{ "m|maintenance", "Ignores the maintenance mode.", m => UpdateOptions.IgnoreMaintenance = true}, { "m|maintenance", "Ignores the maintenance mode.", m => UpdateOptions.IgnoreMaintenance = true},
{ "i|nonpublic", "Include non public (currently hidden) updates.", i => UpdateOptions.IncludeNonPublic = true}, { "i|nonpublic", "Include non public (currently hidden) updates.", i => UpdateOptions.IncludeNonPublic = true},
{ "k|key=", "An key for retriving extra files on updates.", k => UpdateOptions.ExtrasKey = k}, { "k|key=", "An key for retriving extra files on updates.", k => UpdateOptions.ExtrasKey = k},
{ "r|reftag=", "Force uses a specific reference tag, if supported.", r => RefTag = r},
{ "v|version=", "Force uses a specific version, if supported.", v => Version = v},
}; };
additionals.AddRange(options.Parse(args)); additionals.AddRange(options.Parse(args));

View File

@@ -1,93 +1,29 @@
using ModpackUpdater.Manager; using Castle.Core.Logging;
using Newtonsoft.Json; using ModpackUpdater.Manager;
using Pilz;
using Pilz.Configuration;
using System.Runtime.InteropServices;
[assembly: AssemblyAppVersion("1.6.1.0")]
namespace ModpackUpdater.Apps.Client; namespace ModpackUpdater.Apps.Client;
public static class Program public static class Program
{ {
private static readonly SettingsManager settingsManager; private static readonly ILogger log = new ConsoleLogger();
public static ISettings Settings => settingsManager.Instance; public static ILogger Log => log;
internal static Options Options { get; private set; } = null!;
[DllImport("kernel32.dll")]
static extern nint GetConsoleWindow();
[DllImport("user32.dll")]
static extern bool ShowWindow(nint hWnd, int nCmdShow);
static Program()
{
settingsManager = new(GetSettingsPath(2), true);
MigrateLegacySettings(GetSettingsPath(null));
}
[STAThread] [STAThread]
internal static void Main(string[] args) internal static void Main(string[] args)
{ {
var options = new Options(args); Options = new Options(args);
if (options.Help) if (Options.Help)
options.DrawHelp(); Options.DrawHelp();
else if (options.NoUi)
InstallWithoutGui(options.UpdateOptions, options.Silent);
else else
{ InstallWithoutGui(Options.UpdateOptions, Options.Silent);
ShowWindow(GetConsoleWindow(), 0);
RunApp(options.UpdateOptions);
}
}
private static void RunApp(UpdateCheckOptionsAdv updateOptions)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);
AppGlobals.Initialize();
Application.Run(new Form1(updateOptions));
}
private static string GetSettingsPath(int? settingsVersion = 3)
{
const string AppDataDirectoryName = "MinecraftModpackUpdater";
var fileNamePostfix = settingsVersion == null ? string.Empty : $"V{settingsVersion}";
var SettingsFileName = $"Settings{fileNamePostfix}.json";
var settingsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), AppDataDirectoryName);
Directory.CreateDirectory(settingsPath);
settingsPath = Path.Combine(settingsPath, SettingsFileName);
return settingsPath;
}
private static void MigrateLegacySettings(string settingsPath)
{
// Try load legacy config file
if (!File.Exists(settingsPath) || JsonConvert.DeserializeObject<AppConfig>(File.ReadAllText(settingsPath)) is not AppConfig legacyConfig)
return;
// Migrate
var newConfig = Settings.Get<AppConfig>();
newConfig.LastMinecraftProfilePath = legacyConfig.LastMinecraftProfilePath;
if (ModpackInfo.TryLoad(legacyConfig.LastMinecraftProfilePath) is ModpackInfo info)
#pragma warning disable CS0612 // Typ oder Element ist veraltet
info.ConfigUrl = legacyConfig.ConfigFilePath;
// Ensure save settings
settingsManager.Save();
// Delete legacy config file
File.Delete(settingsPath);
} }
private static void InstallWithoutGui(UpdateCheckOptionsAdv updateOptions, bool silent) private static void InstallWithoutGui(UpdateCheckOptionsAdv updateOptions, bool silent)
{ {
var info = ModpackInfo.TryLoad(updateOptions.ProfileFolder); var info = ModpackInfo.TryLoad(updateOptions.ProfileFolder);
var config = ModpackConfig.LoadFromUrl(CheckModpackConfigUrl(updateOptions.ModpackConfig, info)); var config = ModpackConfig.LoadFromUrl(CheckModpackConfigUrl(updateOptions.ModpackConfig!, info));
var features = new ModpackFeatures(config); var features = new ModpackFeatures(config);
// Check features // Check features
@@ -97,20 +33,22 @@ public static class Program
updateOptions.IncludeExtras = features.IsEnabled(ModpackFeatures.FeatureAllowExtas, new AllowExtrasFeatureContext(info)); updateOptions.IncludeExtras = features.IsEnabled(ModpackFeatures.FeatureAllowExtas, new AllowExtrasFeatureContext(info));
// Check for update // Check for update
var installer = new ModpackInstaller(config, info); var installer = new ModpackInstaller(config, info)
{
OverwriteRefTag = Options.RefTag,
OverwriteVersion = Options.Version,
Log = Log,
};
var result = installer.Check(updateOptions).Result; var result = installer.Check(updateOptions).Result;
if (!silent && !updateOptions.NoUpdate && new AppUpdater().Check().Result)
Console.WriteLine("A new version is available!");
if (result.HasUpdates) if (result.HasUpdates)
{ {
var success = installer.Install(result).Result; var success = installer.Install(result).Result;
if (!silent) if (!silent)
Console.WriteLine($"Installation {(success ?? false ? "completed successfully" : "failed")}!"); Log.Info($"Installation {(success ?? false ? "completed successfully" : "failed")}!");
} }
else if (!silent) else if (!silent)
Console.WriteLine("No updates available"); Log.Info("No updates available");
} }
private static string CheckModpackConfigUrl(string configUrl, ModpackInfo info) private static string CheckModpackConfigUrl(string configUrl, ModpackInfo info)

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
<Project>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>..\publish\cli\linux-arm64</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>linux-arm64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
<Project>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>..\publish\cli\linux-x64</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
<Project>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>..\publish\cli\windows\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishReadyToRun>false</PublishReadyToRun>
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
</Project>

View File

@@ -4,8 +4,7 @@ namespace ModpackUpdater.Apps.Client;
public class UpdateCheckOptionsAdv : UpdateCheckOptions public class UpdateCheckOptionsAdv : UpdateCheckOptions
{ {
public string ProfileFolder { get; set; } public string? ProfileFolder { get; set; }
public string ModpackConfig { get; set; } public string? ModpackConfig { get; set; }
public bool NoUpdate { get; set; } public string? ExtrasKey { get; set; }
public string ExtrasKey { get; set; }
} }

View File

@@ -0,0 +1,90 @@
# PUPNET DEPLOY: 1.9.1
# Use: 'pupnet --help conf' for information.
# APP PREAMBLE
AppBaseName = MinecraftModpackUpdaterCli
AppFriendlyName = Minecraft Modpack Updater CLI
AppId = de.pilzinsel64.minecraft-modpack-updater-cli
AppVersionRelease = 1.0.0[1]
AppShortSummary = Install and Update Minecraft Modpacks easliy.
AppDescription = """
Minecraft Modpack Updater is a simple tool to install and update a modpack to a selected minecraft profile by a selected modpack configuration file. It downloads a config file via https and checks the version there and what files has been changed and download the updateded files via a given link from the config.
"""
AppLicenseId = MIT
AppLicenseFile = ../LICENSE
AppChangeFile =
# PUBLISHER
PublisherName = Pilzinsel64
PublisherId = de.pilzinsel64
PublisherCopyright = Copyright (C) Pilzinsel64 2025
PublisherLinkName = Pilzinsel64 Homepage
PublisherLinkUrl = https://pilzinsel64.de
PublisherEmail =
# DESKTOP INTEGRATION
DesktopNoDisplay = true
DesktopTerminal = false
DesktopFile =
StartCommand =
PrimeCategory =
MetaFile =
IconFiles = """
"""
# DOTNET PUBLISH
DotnetProjectPath = ModpackUpdater.Apps.Client.csproj
DotnetPublishArgs = -p:Version=${APP_VERSION} --self-contained true -p:DebugType=None -p:DebugSymbols=false -p:PublishSingleFile=true -p:PublishTrimmed=true
DotnetPostPublish =
DotnetPostPublishOnWindows =
# PACKAGE OUTPUT
PackageName = minecraft-modpack-updater-cli
OutputDirectory = ../publish/client-cli
# APPIMAGE OPTIONS
AppImageArgs =
AppImageRuntimePath =
AppImageVersionOutput = false
# FLATPAK OPTIONS
FlatpakPlatformRuntime = org.freedesktop.Platform
FlatpakPlatformSdk = org.freedesktop.Sdk
FlatpakPlatformVersion = 25.08
FlatpakFinishArgs = """
--socket=wayland
--socket=fallback-x11
--filesystem=home
--share=network
"""
FlatpakBuilderArgs =
# RPM OPTIONS
RpmAutoReq = false
RpmAutoProv = true
RpmRequires = """
krb5-libs
libicu
openssl-libs
"""
# DEBIAN OPTIONS
DebianRecommends = """
libc6
libgcc1
libgssapi-krb5-2
libicu70
libssl3
libstdc++6
zlib1g
"""
# WINDOWS SETUP OPTIONS
SetupGroupName =
SetupAdminInstall = false
SetupCommandPrompt =
SetupMinWindowsVersion = 10
SetupSignTool =
SetupSuffixOutput =
SetupVersionOutput = false
SetupUninstallScript =

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

View File

@@ -0,0 +1,12 @@
pupnet -y -v "$1[1]" -r linux-x64 -k appimage
#pupnet -y -v "$1[1]" -r linux-x64 -k flatpak
#pupnet -y -v "$1[1]"-r linux-x64 -k deb
#pupnet -y -v "$1[1]"-r linux-x64 -k rpm
pupnet -y -v "$1[1]" -r linux-arm64 -k appimage
#pupnet -y -v "$1[1]" -r linux-arm64 -k flatpak
#pupnet -y -v "$1[1]"-r linux-arm64 -k deb
#pupnet -y -v "$1[1]"-r linux-arm64 -k rpm
pupnet -y -v "$1[1]" -r win-x64 -k zip
pupnet -y -v "$1[1]" -r win-arm64 -k zip
pupnet -y -v "$1[1]" -r osx-x64 -k zip
pupnet -y -v "$1[1]" -r osx-arm64 -k zip

View File

@@ -1,4 +1,4 @@
namespace ModpackUpdater.Apps.Manager; namespace ModpackUpdater.Apps.Manager.Api;
public static class FeatureTypes public static class FeatureTypes
{ {

View File

@@ -1,14 +1,12 @@
namespace ModpackUpdater.Apps.Manager.Api.Model; using Avalonia.Controls;
using ModpackUpdater.Apps.Manager.Ui.Models;
using ModpackUpdater.Apps.Manager.Ui.Models.MainWindow;
namespace ModpackUpdater.Apps.Manager.Api.Model;
public interface IMainApi public interface IMainApi
{ {
IWorkspace? CurWorkspace { get; } Window MainWindow { get; }
MainWindowViewModel Model { get; }
IActionSetInfos? CurActionSet { get; } bool HasClosed { get; }
Form MainWindow { get; }
void UpdateItem(InstallAction action);
void UpdateItem(IActionSetInfos actionSetInfos);
} }

View File

@@ -0,0 +1,8 @@
namespace ModpackUpdater.Apps.Manager.Api.Model;
public class WorkspaceContext(IMainApi mainApi, IWorkspace? workspace)
{
public IMainApi MainApi => mainApi;
public IWorkspace? Workspace { get; set; } = workspace;
public bool Canceled { get; set; }
}

View File

@@ -1,5 +1,5 @@
using ModpackUpdater.Apps.Manager.Api.Model; using ModpackUpdater.Apps.Manager.Api.Model;
using Pilz.Plugins.Advanced; using Pilz.Features;
namespace ModpackUpdater.Apps.Manager.Api.Plugins.Features; namespace ModpackUpdater.Apps.Manager.Api.Plugins.Features;
@@ -10,16 +10,12 @@ public abstract class WorkspaceFeature(string identifier, string name) : PluginF
return workspace?.Config == null || workspace.Config.ProviderId == Identifier; return workspace?.Config == null || workspace.Config.ProviderId == Identifier;
} }
public virtual bool Configure(ref IWorkspace? workspace) public virtual async Task Configure(WorkspaceContext context)
{ {
OnConfigure(ref workspace); await OnConfigure(context);
if (workspace?.Config is null) if (!context.Canceled && context.Workspace?.Config is not null)
return false; context.Workspace.Config.ProviderId = Identifier;
workspace.Config.ProviderId = Identifier;
return true;
} }
public virtual IWorkspace CreateFromConfig(WorkspaceConfig config) public virtual IWorkspace CreateFromConfig(WorkspaceConfig config)
@@ -30,5 +26,5 @@ public abstract class WorkspaceFeature(string identifier, string name) : PluginF
protected abstract void OnCreate(out IWorkspace workspace, WorkspaceConfig config); protected abstract void OnCreate(out IWorkspace workspace, WorkspaceConfig config);
protected abstract bool OnConfigure(ref IWorkspace? workspace); protected abstract Task OnConfigure(WorkspaceContext context);
} }

View File

@@ -1,5 +1,5 @@
using ModpackUpdater.Apps.Manager.Api.Model; using ModpackUpdater.Apps.Manager.Api.Model;
using Pilz.Plugins.Advanced; using Pilz.Features;
namespace ModpackUpdater.Apps.Manager.Api.Plugins.Params; namespace ModpackUpdater.Apps.Manager.Api.Plugins.Params;

View File

@@ -0,0 +1,15 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ModpackUpdater.Apps.Manager.App"
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<Application.Styles>
<FluentTheme DensityStyle="Normal" />
<!-- <FluentTheme DensityStyle="Compact" /> -->
<!-- <SimpleTheme /> -->
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml"/>
<!-- <StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Simple.xaml"/> -->
<StyleInclude Source="avares://Pilz.UI.AvaloniaUI/Assets/Styles/EnhancedDefaults.axaml"/>
</Application.Styles>
</Application>

View File

@@ -0,0 +1,24 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using ModpackUpdater.Apps.Manager.Ui;
using Pilz.Features;
namespace ModpackUpdater.Apps.Manager;
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
AppGlobals.Initialize();
PluginFeatureController.Instance.RegisterAllOwn();
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
desktop.MainWindow = new MainWindow();
base.OnFrameworkInitializationCompleted();
}
}

View File

@@ -0,0 +1 @@
[assembly: PropertyChanged.FilterType("ModpackUpdater.Apps.Manager.Ui.Models")]

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="480" height="480" viewBox="0 0 480 480" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="clip_path_1">
<rect width="480" height="480" />
</clipPath>
</defs>
<g clip-path="url(#clip_path_1)">
<path d="M360 40L180 40L140 0C140 0 40 0 40 0C17.91 0 0 17.91 0 40C0 40 0 120 0 120L400 120C400 120 400 80 400 80C400 57.91 382.09 40 360 40C360 40 360 40 360 40Z" fill="#FFA000" transform="translate(20 100)" />
<g transform="translate(53 -7)">
<path d="M160.042 63.3334L0 7.91667L13.9167 213.75L160.042 300.833L278.333 205.833L292.25 0L160.042 63.3334Z" fill="#5D4037" fill-rule="evenodd" transform="translate(20.875 63.333)" />
<path d="M0 0L13.9167 205.834L160.042 292.917L160.042 55.4167L0 0Z" fill="#8D6E63" fill-rule="evenodd" transform="translate(20.875 71.25)" />
<path d="M13.9167 112.084L13.9167 79.1667L27.8333 72.2554L27.8333 95L41.75 87.0833L41.75 118.75L62.625 109.028L62.625 55.4167L76.5417 48.6954L76.5417 87.0833L90.4583 80.5679L90.4583 63.3333L104.375 55.4167L104.375 35.3637L118.292 28.6979L118.292 47.5L129.425 41.1667L132.208 0L0 63.3333L0 118.75L13.9167 112.084Z" fill="#43A047" fill-rule="evenodd" transform="translate(180.917 63.333)" />
<path d="M0 47.5L139.167 0L292.25 39.5833L160.042 102.917L0 47.5Z" fill="#B2FF59" fill-rule="evenodd" transform="translate(20.875 23.75)" />
<path d="M0 0L2.78333 40.6442L13.9167 44.3888L13.9167 34.9363L27.8333 39.5833L27.8333 65.0513L48.7083 72.2792L48.7083 34.6196L62.625 39.5833L62.625 77.1004L76.5417 81.9217L76.5417 58.9713L90.4583 63.7925L90.4583 86.743L104.375 91.5563L104.375 82.1671L118.292 87.0834L118.292 74.6067L132.208 79.1667L132.208 101.199L160.042 110.833L160.042 55.4167L0 0Z" fill="#66BB6A" fill-rule="evenodd" transform="translate(20.875 71.25)" />
</g>
<path d="M360 0C360 0 40 0 40 0C17.91 0 0 15.1595 0 33.8571C0 33.8571 0 203.143 0 203.143C0 221.84 17.91 237 40 237C40 237 360 237 360 237C382.09 237 400 221.84 400 203.143C400 203.143 400 33.8571 400 33.8571C400 15.1595 382.09 0 360 0C360 0 360 0 360 0Z" fill="#FFCA28" transform="translate(20 183)" />
<path d="M70 80L0 0L140 0L70 80Z" fill="#1565C0" transform="translate(150 380)" />
<path d="M0 0L60 0L60 111.25L0 111.25L0 0Z" fill="#1565C0" transform="translate(190 280)" />
<path d="M30 15C30 23.28 23.29 30 15 30C6.71002 30 0 23.28 0 15C0 6.72 6.71002 0 15 0C23.29 0 30 6.72 30 15C30 15 30 15 30 15Z" fill="#4A148C" transform="translate(430 60)" />
<path d="M125 100C72.62 100 30 57.38 30 5C30 5 30 0 30 0L0 0L0 10C0 10 0.25 10 0.25 10C2.84 74.93 55.08 127.16 120 129.75C120 129.75 120 130 120 130L130 130L130 100L125 100C125 100 125 100 125 100Z" fill="#9C27B0" transform="translate(330 60)" />
<path d="M75 50C50.19 50 30 29.81 30 5C30 5 30 0 30 0L0 0L0 10C0 10 0.25 10 0.25 10C2.73004 47.36 32.63 77.27 70 79.75C70 79.75 70 80 70 80L80 80L80 50L75 50C75 50 75 50 75 50Z" fill="#7B1FA2" transform="translate(380 60)" />
<path d="M175 150C95.05 150 30 84.95 30 5C30 5 30 0 30 0L0 0L0 10C0 10 0.25 10 0.25 10C2.88998 102.5 77.51 177.11 170 179.75C170 179.75 170 180 170 180L180 180L180 150L175 150C175 150 175 150 175 150Z" fill="#BA68C8" transform="translate(280 60)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -1,11 +0,0 @@
namespace ModpackUpdater.Apps.Manager;
internal static class Extensions
{
public static string? Nullify(this string? @this)
{
if (string.IsNullOrEmpty(@this))
return null;
return @this;
}
}

View File

@@ -1,8 +1,8 @@
using ModpackUpdater.Apps.Manager.Api.Plugins.Params; using ModpackUpdater.Apps.Manager.Api;
using ModpackUpdater.Apps.Manager.Api.Plugins.Params;
using ModpackUpdater.Apps.Manager.LangRes; using ModpackUpdater.Apps.Manager.LangRes;
using ModpackUpdater.Apps.Manager.Ui; using Pilz.Features;
using Pilz.Plugins.Advanced; using Pilz.UI.Symbols;
using Telerik.WinControls.UI;
namespace ModpackUpdater.Apps.Manager.Features.CM; namespace ModpackUpdater.Apps.Manager.Features.CM;
@@ -12,19 +12,15 @@ internal class CheckSingleActionHealthyFeature : PluginFunction, IPluginFeatureP
public CheckSingleActionHealthyFeature() : base(FeatureTypes.ActionsContextMenu, "origin.checksingleactionhearlthy", FeatureNamesLangRes.CheckSingleActionHealthy) public CheckSingleActionHealthyFeature() : base(FeatureTypes.ActionsContextMenu, "origin.checksingleactionhearlthy", FeatureNamesLangRes.CheckSingleActionHealthy)
{ {
Icon = AppGlobals.Symbols.GetSvgImage(AppSymbols.heart_with_pulse, Pilz.UI.Symbols.SymbolSize.Small); Icon = AppGlobals.Symbols.GetImage(AppSymbols.heart_with_pulse, SymbolSize.Small);
} }
protected override object? ExecuteFunction(PluginFunctionParameter? @params) protected override async Task<object?> ExecuteFunctionAsync(PluginFunctionParameter? @params)
{ {
if (@params is not MainApiParameters p if (@params is not MainApiParameters p || p.Api.Model.SelectedGridRow is not { } row)
|| p.Api.MainWindow is not MainForm mainForm
|| mainForm.Controls.Find("radGridView_Actions", true).FirstOrDefault() is not RadGridView gridView
|| gridView.SelectedRows.FirstOrDefault() is not GridViewRowInfo row
|| row.Tag is not InstallAction)
return null; return null;
SharedFunctions.CheckActionHealthy(p.Api, row); await SharedFunctions.CheckActionHealthy(p.Api, row);
return null; return null;
} }

View File

@@ -1,8 +1,8 @@
using ModpackUpdater.Apps.Manager.Api.Plugins.Params; using ModpackUpdater.Apps.Manager.Api;
using ModpackUpdater.Apps.Manager.Api.Plugins.Params;
using ModpackUpdater.Apps.Manager.LangRes; using ModpackUpdater.Apps.Manager.LangRes;
using ModpackUpdater.Apps.Manager.Ui; using Pilz.Features;
using Pilz.Plugins.Advanced; using Pilz.UI.Symbols;
using Telerik.WinControls.UI;
namespace ModpackUpdater.Apps.Manager.Features.CM; namespace ModpackUpdater.Apps.Manager.Features.CM;
@@ -12,19 +12,13 @@ internal class ClearDirectLinkFeature : PluginFunction, IPluginFeatureProvider<C
public ClearDirectLinkFeature() : base(FeatureTypes.ActionsContextMenu, "origin.cleardirectlink", FeatureNamesLangRes.ClearDirectLinkFeature) public ClearDirectLinkFeature() : base(FeatureTypes.ActionsContextMenu, "origin.cleardirectlink", FeatureNamesLangRes.ClearDirectLinkFeature)
{ {
Icon = AppGlobals.Symbols.GetSvgImage(AppSymbols.broom, Pilz.UI.Symbols.SymbolSize.Small); Icon = AppGlobals.Symbols.GetImage(AppSymbols.broom, SymbolSize.Small);
} }
protected override object? ExecuteFunction(PluginFunctionParameter? @params) protected override Task<object?> ExecuteFunctionAsync(PluginFunctionParameter? @params)
{ {
if (@params is not MainApiParameters p if (@params is MainApiParameters p && p.Api.Model.SelectedGridRow is { } row)
|| p.Api.MainWindow is not MainForm mainForm SharedFunctions.ClearDirectLinks(p.Api, row);
|| mainForm.Controls.Find("radGridView_Actions", true).FirstOrDefault() is not RadGridView gridView return Task.FromResult<object?>(null);
|| gridView.SelectedRows.FirstOrDefault()?.Tag is not InstallAction selectedAction)
return null;
SharedFunctions.ClearDirectLinks(p.Api, selectedAction);
return null;
} }
} }

View File

@@ -1,9 +1,8 @@
using ModpackUpdater.Apps.Manager.Api.Plugins.Params; using ModpackUpdater.Apps.Manager.Api;
using ModpackUpdater.Apps.Manager.Api.Plugins.Params;
using ModpackUpdater.Apps.Manager.LangRes; using ModpackUpdater.Apps.Manager.LangRes;
using ModpackUpdater.Apps.Manager.Ui; using Pilz.Features;
using Pilz.Plugins.Advanced;
using Pilz.UI.Symbols; using Pilz.UI.Symbols;
using Telerik.WinControls.UI;
namespace ModpackUpdater.Apps.Manager.Features.CM; namespace ModpackUpdater.Apps.Manager.Features.CM;
internal class UpdateCollectorFeature : PluginFunction, IPluginFeatureProvider<UpdateCollectorFeature> internal class UpdateCollectorFeature : PluginFunction, IPluginFeatureProvider<UpdateCollectorFeature>
@@ -12,19 +11,15 @@ internal class UpdateCollectorFeature : PluginFunction, IPluginFeatureProvider<U
public UpdateCollectorFeature() : base(FeatureTypes.ActionsContextMenu, "origin.updatecollector", FeatureNamesLangRes.UpdateCollectorFeature) public UpdateCollectorFeature() : base(FeatureTypes.ActionsContextMenu, "origin.updatecollector", FeatureNamesLangRes.UpdateCollectorFeature)
{ {
Icon = AppGlobals.Symbols.GetSvgImage(AppSymbols.search, SymbolSize.Small); Icon = AppGlobals.Symbols.GetImage(AppSymbols.search, SymbolSize.Small);
} }
protected override object? ExecuteFunction(PluginFunctionParameter? @params) protected override async Task<object?> ExecuteFunctionAsync(PluginFunctionParameter? @params)
{ {
if (@params is not MainApiParameters p if (@params is not MainApiParameters p || p.Api.Model.SelectedGridRow is not { } row)
|| p.Api.CurWorkspace?.UpdateInfos is null
|| p.Api.MainWindow is not MainForm mainForm
|| mainForm.Controls.Find("radGridView_Actions", true).FirstOrDefault() is not RadGridView gridView
|| gridView.SelectedRows.FirstOrDefault()?.Tag is not InstallAction selectedAction)
return null; return null;
SharedFunctions.CollectUpdates(p.Api, selectedAction); await SharedFunctions.CollectUpdates(p.Api, row.Action);
return null; return null;
} }

View File

@@ -1,8 +1,9 @@
using ModpackUpdater.Apps.Manager.Api.Plugins.Params; using ModpackUpdater.Apps.Manager.Api;
using ModpackUpdater.Apps.Manager.Api.Plugins.Params;
using ModpackUpdater.Apps.Manager.LangRes; using ModpackUpdater.Apps.Manager.LangRes;
using ModpackUpdater.Apps.Manager.Ui; using ModpackUpdater.Apps.Manager.Ui.Models.MainWindow;
using Pilz.Plugins.Advanced; using Pilz.Features;
using Telerik.WinControls.UI; using Pilz.UI.Symbols;
namespace ModpackUpdater.Apps.Manager.Features.CM; namespace ModpackUpdater.Apps.Manager.Features.CM;
@@ -12,18 +13,15 @@ internal class UpdateDirectLinkFeature : PluginFunction, IPluginFeatureProvider<
public UpdateDirectLinkFeature() : base(FeatureTypes.ActionsContextMenu, "origin.updatedirectlink", FeatureNamesLangRes.UpdateDirectLinkFeature) public UpdateDirectLinkFeature() : base(FeatureTypes.ActionsContextMenu, "origin.updatedirectlink", FeatureNamesLangRes.UpdateDirectLinkFeature)
{ {
Icon = AppGlobals.Symbols.GetSvgImage(AppSymbols.renew, Pilz.UI.Symbols.SymbolSize.Small); Icon = AppGlobals.Symbols.GetImage(AppSymbols.renew, SymbolSize.Small);
} }
protected override object? ExecuteFunction(PluginFunctionParameter? @params) protected override async Task<object?> ExecuteFunctionAsync(PluginFunctionParameter? @params)
{ {
if (@params is not MainApiParameters p if (@params is not MainApiParameters p || p.Api.Model.SelectedGridRow is not MainWindowGridRow row)
|| p.Api.MainWindow is not MainForm mainForm
|| mainForm.Controls.Find("radGridView_Actions", true).FirstOrDefault() is not RadGridView gridView
|| gridView.SelectedRows.FirstOrDefault()?.Tag is not InstallAction selectedAction)
return null; return null;
SharedFunctions.FindNewDirectLinks(p.Api, selectedAction); await SharedFunctions.FindNewDirectLinks(p.Api, row);
return null; return null;
} }

View File

@@ -1,97 +1,79 @@
using Microsoft.Extensions.Primitives; using System.Text;
using Avalonia.Media;
using ModpackUpdater.Apps.Manager.Api.Model; using ModpackUpdater.Apps.Manager.Api.Model;
using ModpackUpdater.Apps.Manager.LangRes;
using ModpackUpdater.Apps.Manager.Ui; using ModpackUpdater.Apps.Manager.Ui;
using ModpackUpdater.Apps.Manager.Ui.Models.MainWindow;
using ModpackUpdater.Apps.Manager.Ui.Models.UpdatesCollectorViewMode;
using ModpackUpdater.Manager; using ModpackUpdater.Manager;
using Pilz.UI.Extensions; using OfficeOpenXml;
using System.Text; using OfficeOpenXml.Table;
using Telerik.WinControls.UI; using Pilz.UI.AvaloniaUI.Dialogs;
namespace ModpackUpdater.Apps.Manager.Features; namespace ModpackUpdater.Apps.Manager.Features;
internal static class SharedFunctions internal static class SharedFunctions
{ {
public static bool CheckActionHealthy(IMainApi api, params GridViewRowInfo[] selectedRows) 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)
{ {
if (api.MainWindow is not MainForm mainForm var rowsCount = rows.Length;
|| mainForm.Controls.Find("radGridView_Actions", true).FirstOrDefault() is not RadGridView gridView
|| mainForm.Controls.Find("radWaitingBar_Actions", true).FirstOrDefault() is not RadWaitingBar rwb)
return false;
rwb.StartWaiting();
rwb.ShowText = true;
var rowsCount = selectedRows.Length;
rwb.Text = "0 / " + rowsCount;
gridView.BeginUpdate();
var failed = false; var failed = false;
var msg = default(string);
var factory = new ModpackFactory(); var factory = new ModpackFactory();
var rows = new Dictionary<GridViewRowInfo, InstallAction>(); api.Model.Progress.Start(rowsCount);
for (var i = 0; i < selectedRows.Length; i++)
{
var row = selectedRows[i];
if (row.Tag is InstallAction action) for (var i = 0; i < rowsCount; i++)
{
Task.Run(async () =>
{ {
var row = rows[i];
if (row.SourceType == SourceType.DirectLink)
continue;
row.StateImage = imageSourceWorking;
try try
{ {
var result = await factory.ResolveSourceUrl(action); var result = await factory.ResolveSourceUrl(row.Action);
failed = string.IsNullOrWhiteSpace(result); failed = string.IsNullOrWhiteSpace(result);
} }
catch (Exception ex) catch
{ {
msg = ex.Message; // Ignore
}
}).Wait();
} }
foreach (var c in row.Cells) 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)
{ {
c.Style.CustomizeFill = true; if (api.Model.CurrentWorkspace?.UpdateInfos is null || api.Model.CurrentTreeNodes is null)
c.Style.BackColor = failed ? Color.IndianRed : Color.ForestGreen;
}
rwb.Text = $"{i} / {rowsCount}";
Application.DoEvents();
}
gridView.EndUpdate();
rwb.ShowText = false;
rwb.StopWaiting();
if (rowsCount == 1 && failed && !string.IsNullOrWhiteSpace(msg))
MessageBox.Show(msg);
return true;
}
public static bool CollectUpdates(IMainApi api, params InstallAction[] actions)
{
if (api.CurWorkspace?.UpdateInfos is null)
return false; return false;
// Collect updates // Collect updates
var ucDialog = new UpdatesCollectorUi(api.CurWorkspace, actions); var result = await AvaloniaFlyoutBase.Show(new UpdatesCollectorView(api.Model.CurrentWorkspace, actions), api.MainWindow);
if (!ucDialog.ShowDialog(api.MainWindow).IsOk() || ucDialog.CurrentUpdates is null) if (api.HasClosed || result.Result is not ModUpdates resultUpdates)
return false; return false;
// Collect versions with changes // Collect versions with changes
var updates = new List<UpdatesCollectorUi.ModUpdateInfo>(); var updates = resultUpdates.List.Where(update => update.Origin.SourceTag != update.AvailableVersions[update.NewVersion].Tag).ToList();
foreach (var update in ucDialog.CurrentUpdates.List)
{
if (update.Origin.SourceTag != update.AvailableVersions[update.NewVersion].Value)
updates.Add(update);
}
// Path install actions // Path install actions
foreach (var update in updates) foreach (var update in updates)
{ {
update.Origin.SourceTag = update.AvailableVersions[update.NewVersion].Value; var sourceTag = update.AvailableVersions[update.NewVersion].Tag;
api.UpdateItem(update.Origin); 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 // Create update actions
@@ -103,58 +85,59 @@ internal static class SharedFunctions
InheritFrom = update.Origin.Id, InheritFrom = update.Origin.Id,
}); });
} }
api.CurWorkspace.UpdateInfos.Updates.Insert(0, updateSet); api.Model.CurrentWorkspace.UpdateInfos.Updates.Insert(0, updateSet);
api.UpdateItem(updateSet);
// Add update to ui
api.Model.CurrentTreeNodes[1].Nodes.Insert(0, new ActionSetTreeNode(updateSet));
return true; return true;
} }
public static void FindNewDirectLinks(IMainApi api, params InstallAction[] actions) public static async Task FindNewDirectLinks(IMainApi api, params MainWindowGridRow[] rows)
{ {
var mainForm = api.MainWindow as MainForm;
var gridView = mainForm?.Controls.Find("radGridView_Actions", true).FirstOrDefault() as RadGridView;
var rwb = mainForm?.Controls.Find("radWaitingBar_Actions", true).FirstOrDefault() as RadWaitingBar;
var factory = new ModpackFactory(); var factory = new ModpackFactory();
rwb?.StartWaiting(); api.Model.Progress.Start(rows.Length);
gridView?.BeginUpdate();
foreach (var action in actions) for (var i = 0; i < rows.Length; i++)
{ {
if (action.SourceType != SourceType.DirectLink) var row = rows[i];
if (row.SourceType == SourceType.DirectLink)
continue;
row.StateImage = imageSourceWorking;
try
{ {
Task.Run(async () => row.SourceUrl = await factory.ResolveSourceUrl(row.Action);
{ row.StateImage = imageSourceSuccess;
action.SourceUrl = await factory.ResolveSourceUrl(action);
}).Wait();
api.UpdateItem(action);
} }
catch (Exception)
{
row.StateImage = imageSourceFailed;
} }
gridView?.EndUpdate(); if (api.HasClosed)
rwb?.StopWaiting(); return;
api.Model.Progress.Set(i);
} }
public static void ClearDirectLinks(IMainApi api, params InstallAction[] actions) api.Model.Progress.Stop();
{
var mainForm = api.MainWindow as MainForm;
var gridView = mainForm?.Controls.Find("radGridView_Actions", true).FirstOrDefault() as RadGridView;
var rwb = mainForm?.Controls.Find("radWaitingBar_Actions", true).FirstOrDefault() as RadWaitingBar;
rwb?.StartWaiting();
gridView?.BeginUpdate();
foreach (var action in actions)
{
if (action.SourceType != SourceType.DirectLink)
{
action.SourceUrl = null;
api.UpdateItem(action);
}
} }
gridView?.EndUpdate(); public static void ClearDirectLinks(IMainApi api, params MainWindowGridRow[] rows)
rwb?.StopWaiting(); {
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) public static string GenerateChangelog(InstallInfos installInfos, UpdateInfo updateInfos)
@@ -202,4 +185,100 @@ internal static class SharedFunctions
return log.ToString().TrimEnd(); 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;
}
} }

View File

@@ -1,8 +1,8 @@
using ModpackUpdater.Apps.Manager.Api.Plugins.Params; using ModpackUpdater.Apps.Manager.Api;
using ModpackUpdater.Apps.Manager.Api.Plugins.Params;
using ModpackUpdater.Apps.Manager.LangRes; using ModpackUpdater.Apps.Manager.LangRes;
using ModpackUpdater.Apps.Manager.Ui; using Pilz.Features;
using Pilz.Plugins.Advanced; using Pilz.UI.Symbols;
using Telerik.WinControls.UI;
namespace ModpackUpdater.Apps.Manager.Features.Tools; namespace ModpackUpdater.Apps.Manager.Features.Tools;
@@ -12,17 +12,15 @@ internal class CheckAllActionsHealthyFeature : PluginFunction, IPluginFeaturePro
public CheckAllActionsHealthyFeature() : base(FeatureTypes.Tools, "origin.checkallactionshearlthy", FeatureNamesLangRes.CheckAllActionsHealthy) public CheckAllActionsHealthyFeature() : base(FeatureTypes.Tools, "origin.checkallactionshearlthy", FeatureNamesLangRes.CheckAllActionsHealthy)
{ {
Icon = AppGlobals.Symbols.GetSvgImage(AppSymbols.heart_with_pulse, Pilz.UI.Symbols.SymbolSize.Small); Icon = AppGlobals.Symbols.GetImage(AppSymbols.heart_with_pulse, SymbolSize.Small);
} }
protected override object? ExecuteFunction(PluginFunctionParameter? @params) protected override async Task<object?> ExecuteFunctionAsync(PluginFunctionParameter? @params)
{ {
if (@params is not MainApiParameters p if (@params is not MainApiParameters p)
|| p.Api.MainWindow is not MainForm mainForm
|| mainForm.Controls.Find("radGridView_Actions", true).FirstOrDefault() is not RadGridView gridView)
return null; return null;
SharedFunctions.CheckActionHealthy(p.Api, [.. gridView.Rows]); await SharedFunctions.CheckActionHealthy(p.Api, [.. p.Api.Model.CurrentGridRows.View]);
return null; return null;
} }

View File

@@ -1,6 +1,8 @@
using ModpackUpdater.Apps.Manager.Api.Plugins.Params; using ModpackUpdater.Apps.Manager.Api;
using ModpackUpdater.Apps.Manager.Api.Plugins.Params;
using ModpackUpdater.Apps.Manager.LangRes; using ModpackUpdater.Apps.Manager.LangRes;
using Pilz.Plugins.Advanced; using Pilz.Features;
using Pilz.UI.Symbols;
namespace ModpackUpdater.Apps.Manager.Features.Tools; namespace ModpackUpdater.Apps.Manager.Features.Tools;
@@ -10,16 +12,13 @@ internal class ClearDirectLinksFeature : PluginFunction, IPluginFeatureProvider<
public ClearDirectLinksFeature() : base(FeatureTypes.Tools, "origin.cleardirectlinks", FeatureNamesLangRes.ClearDirectLinksFeature) public ClearDirectLinksFeature() : base(FeatureTypes.Tools, "origin.cleardirectlinks", FeatureNamesLangRes.ClearDirectLinksFeature)
{ {
Icon = AppGlobals.Symbols.GetSvgImage(AppSymbols.broom, Pilz.UI.Symbols.SymbolSize.Small); Icon = AppGlobals.Symbols.GetImage(AppSymbols.broom, SymbolSize.Small);
} }
protected override object? ExecuteFunction(PluginFunctionParameter? @params) protected override Task<object?> ExecuteFunctionAsync(PluginFunctionParameter? @params)
{ {
if (@params is not MainApiParameters p || p.Api.CurWorkspace?.InstallInfos is null) if (@params is MainApiParameters p)
return null; SharedFunctions.ClearDirectLinks(p.Api, [.. p.Api.Model.CurrentGridRows.View]);
return Task.FromResult<object?>(null);
SharedFunctions.ClearDirectLinks(p.Api, [.. p.Api.CurWorkspace.InstallInfos.Actions]);
return null;
} }
} }

View File

@@ -1,7 +1,11 @@
using ModpackUpdater.Apps.Manager.Api.Plugins.Params; using ModpackUpdater.Apps.Manager.Api;
using ModpackUpdater.Apps.Manager.Api.Plugins.Params;
using ModpackUpdater.Apps.Manager.LangRes; using ModpackUpdater.Apps.Manager.LangRes;
using Pilz.Plugins.Advanced; using ModpackUpdater.Apps.Manager.Ui.Models.MainWindow;
using Telerik.WinControls; using MsBox.Avalonia;
using MsBox.Avalonia.Enums;
using Pilz.Features;
using Pilz.UI.Symbols;
namespace ModpackUpdater.Apps.Manager.Features.Tools; namespace ModpackUpdater.Apps.Manager.Features.Tools;
@@ -11,20 +15,23 @@ internal class GenerateChangelogFeature : PluginFunction, IPluginFeatureProvider
public GenerateChangelogFeature() : base(FeatureTypes.Tools, "origin.genchangelog", FeatureNamesLangRes.GenerateChangelogFeature) public GenerateChangelogFeature() : base(FeatureTypes.Tools, "origin.genchangelog", FeatureNamesLangRes.GenerateChangelogFeature)
{ {
Icon = AppGlobals.Symbols.GetSvgImage(AppSymbols.time_machine, Pilz.UI.Symbols.SymbolSize.Small); Icon = AppGlobals.Symbols.GetImage(AppSymbols.time_machine, SymbolSize.Small);
} }
protected override object? ExecuteFunction(PluginFunctionParameter? @params) protected override async Task<object?> ExecuteFunctionAsync(PluginFunctionParameter? @params)
{ {
if (@params is not MainApiParameters p || p.Api.CurWorkspace?.InstallInfos is null || p.Api.CurActionSet is not UpdateInfo updateInfos) if (@params is not MainApiParameters p
|| p.Api.Model.CurrentWorkspace?.InstallInfos is null
|| p.Api.Model.SelectedTreeNode is not ActionSetTreeNode node
|| node.Infos is not UpdateInfo updateInfo)
return null; return null;
var changelog = SharedFunctions.GenerateChangelog(p.Api.CurWorkspace.InstallInfos, updateInfos); var changelog = SharedFunctions.GenerateChangelog(p.Api.Model.CurrentWorkspace.InstallInfos, updateInfo);
if (!string.IsNullOrWhiteSpace(changelog)) if (string.IsNullOrWhiteSpace(changelog))
{ return null;
Clipboard.SetText(changelog);
RadMessageBox.Show(p.Api.MainWindow, MsgBoxLangRes.ChangelogCopiedToClipboard, MsgBoxLangRes.ChangelogCopiedToClipboard_Title, MessageBoxButtons.OK, RadMessageIcon.Info); await p.Api.MainWindow.Clipboard?.SetTextAsync(changelog);
} await MessageBoxManager.GetMessageBoxStandard(MsgBoxLangRes.ChangelogCopiedToClipboard_Title, MsgBoxLangRes.ChangelogCopiedToClipboard, ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Info).ShowAsPopupAsync(p.Api.MainWindow);
return null; return null;
} }

View File

@@ -0,0 +1,43 @@
using Avalonia.Controls;
using ModpackUpdater.Apps.Manager.Api;
using ModpackUpdater.Apps.Manager.Api.Plugins.Params;
using ModpackUpdater.Apps.Manager.LangRes;
using ModpackUpdater.Apps.Manager.Utils;
using MsBox.Avalonia;
using MsBox.Avalonia.Enums;
using Pilz.Features;
using Pilz.UI.Symbols;
namespace ModpackUpdater.Apps.Manager.Features.Tools;
internal class GenerateModlistAsExcelFeature : PluginFunction, IPluginFeatureProvider<GenerateModlistAsExcelFeature>
{
public static GenerateModlistAsExcelFeature Instance { get; } = new();
public GenerateModlistAsExcelFeature() : base(FeatureTypes.Tools, "origin.genmodlist.xlsx", FeatureNamesLangRes.GenerateModlistAsExcelFeature)
{
Icon = AppGlobals.Symbols.GetImage(AppSymbols.list_view, SymbolSize.Small);
}
protected override async Task<object?> ExecuteFunctionAsync(PluginFunctionParameter? @params)
{
if (@params is not MainApiParameters p || p.Api.Model.CurrentWorkspace?.InstallInfos is null)
return null;
// Generate excel
using var pkg = SharedFunctions.GenerateModlistAsExcel(p.Api.Model.CurrentWorkspace.InstallInfos);
// Ask for save
var file = await TopLevel.GetTopLevel(p.Api.MainWindow)!.StorageProvider.SaveFilePickerAsync(new()
{
FileTypeChoices = [MyFilePickerFileTypes.Excel]
});
if (file is null)
return null;
// Save file
await pkg.SaveAsAsync(file.Path.AbsolutePath);
await MessageBoxManager.GetMessageBoxStandard(MsgBoxLangRes.ModlistGenerated_Title, MsgBoxLangRes.ModlistGenerated, ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Info).ShowAsPopupAsync(p.Api.MainWindow);
return null;
}
}

View File

@@ -0,0 +1,31 @@
using ModpackUpdater.Apps.Manager.Api;
using ModpackUpdater.Apps.Manager.Api.Plugins.Params;
using ModpackUpdater.Apps.Manager.LangRes;
using MsBox.Avalonia;
using MsBox.Avalonia.Enums;
using Pilz.Features;
using Pilz.UI.Symbols;
namespace ModpackUpdater.Apps.Manager.Features.Tools;
internal class GenerateModlistAsMarkdownFeature : PluginFunction, IPluginFeatureProvider<GenerateModlistAsMarkdownFeature>
{
public static GenerateModlistAsMarkdownFeature Instance { get; } = new();
public GenerateModlistAsMarkdownFeature() : base(FeatureTypes.Tools, "origin.genmodlist.md", FeatureNamesLangRes.GenerateModlistAsMarkdownFeature)
{
Icon = AppGlobals.Symbols.GetImage(AppSymbols.list_view, SymbolSize.Small);
}
protected override async Task<object?> ExecuteFunctionAsync(PluginFunctionParameter? @params)
{
if (@params is not MainApiParameters p || p.Api.Model.CurrentWorkspace?.InstallInfos is null)
return null;
p.Api.MainWindow.Clipboard?.SetTextAsync(SharedFunctions.GenerateModlistAsMarkdown(p.Api.Model.CurrentWorkspace.InstallInfos));
await MessageBoxManager.GetMessageBoxStandard(MsgBoxLangRes.ModlistCopiedToClipboard_Title, MsgBoxLangRes.ModlistCopiedToClipboard, ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Info).ShowAsPopupAsync(p.Api.MainWindow);
return null;
}
}

View File

@@ -1,6 +1,8 @@
using ModpackUpdater.Apps.Manager.Api.Plugins.Params; using ModpackUpdater.Apps.Manager.Api;
using ModpackUpdater.Apps.Manager.Api.Plugins.Params;
using ModpackUpdater.Apps.Manager.LangRes; using ModpackUpdater.Apps.Manager.LangRes;
using Pilz.Plugins.Advanced; using Pilz.Features;
using Pilz.UI.Symbols;
namespace ModpackUpdater.Apps.Manager.Features.Tools; namespace ModpackUpdater.Apps.Manager.Features.Tools;
@@ -10,15 +12,15 @@ internal class UpdateDirectLinksFeature : PluginFunction, IPluginFeatureProvider
public UpdateDirectLinksFeature() : base(FeatureTypes.Tools, "origin.updatedirectlinks", FeatureNamesLangRes.UpdateDirectLinksFeature) public UpdateDirectLinksFeature() : base(FeatureTypes.Tools, "origin.updatedirectlinks", FeatureNamesLangRes.UpdateDirectLinksFeature)
{ {
Icon = AppGlobals.Symbols.GetSvgImage(AppSymbols.renew, Pilz.UI.Symbols.SymbolSize.Small); Icon = AppGlobals.Symbols.GetImage(AppSymbols.renew, SymbolSize.Small);
} }
protected override object? ExecuteFunction(PluginFunctionParameter? @params) protected override async Task<object?> ExecuteFunctionAsync(PluginFunctionParameter? @params)
{ {
if (@params is not MainApiParameters p || p.Api.CurWorkspace?.InstallInfos is null) if (@params is not MainApiParameters p)
return null; return null;
SharedFunctions.FindNewDirectLinks(p.Api, [.. p.Api.CurWorkspace.InstallInfos.Actions]); await SharedFunctions.FindNewDirectLinks(p.Api, [.. p.Api.Model.CurrentGridRows.View]);
return null; return null;
} }

View File

@@ -1,6 +1,7 @@
using ModpackUpdater.Apps.Manager.Api.Plugins.Params; using ModpackUpdater.Apps.Manager.Api;
using ModpackUpdater.Apps.Manager.Api.Plugins.Params;
using ModpackUpdater.Apps.Manager.LangRes; using ModpackUpdater.Apps.Manager.LangRes;
using Pilz.Plugins.Advanced; using Pilz.Features;
using Pilz.UI.Symbols; using Pilz.UI.Symbols;
namespace ModpackUpdater.Apps.Manager.Features.Tools; namespace ModpackUpdater.Apps.Manager.Features.Tools;
@@ -11,15 +12,15 @@ internal class UpdatesCollectorFeature : PluginFunction, IPluginFeatureProvider<
public UpdatesCollectorFeature() : base(FeatureTypes.Tools, "origin.updatescollector", FeatureNamesLangRes.UpdatesCollectorFeature) public UpdatesCollectorFeature() : base(FeatureTypes.Tools, "origin.updatescollector", FeatureNamesLangRes.UpdatesCollectorFeature)
{ {
Icon = AppGlobals.Symbols.GetSvgImage(AppSymbols.search, SymbolSize.Small); Icon = AppGlobals.Symbols.GetImage(AppSymbols.search, SymbolSize.Small);
} }
protected override object? ExecuteFunction(PluginFunctionParameter? @params) protected override async Task<object?> ExecuteFunctionAsync(PluginFunctionParameter? @params)
{ {
if (@params is not MainApiParameters p || p.Api.CurWorkspace?.InstallInfos is null) if (@params is not MainApiParameters p || p.Api.Model.CurrentWorkspace?.InstallInfos is null)
return null; return null;
SharedFunctions.CollectUpdates(p.Api, [.. p.Api.CurWorkspace.InstallInfos.Actions]); await SharedFunctions.CollectUpdates(p.Api, [.. p.Api.Model.CurrentWorkspace.InstallInfos.Actions]);
return null; return null;
} }

View File

@@ -1,25 +1,19 @@
using ModpackUpdater.Apps.Manager.Api.Model; using ModpackUpdater.Apps.Manager.Api.Model;
using NGitLab; using NGitLab;
using NGitLab.Models; using NGitLab.Models;
using System.Text.Encodings.Web;
namespace ModpackUpdater.Apps.Manager.Features.Workspaces.GitLabRepo; namespace ModpackUpdater.Apps.Manager.Features.Workspaces.GitLabRepo;
internal class GitLabRepoWorkspace(GitLabRepoWorkspaceConfig config) : IWorkspace internal class GitLabRepoWorkspace(GitLabRepoWorkspaceConfig config) : IWorkspace
{ {
private string? rawInstallInfos = null; private string? rawInstallInfos;
private string? rawUpdateInfos = null; private string? rawUpdateInfos;
public WorkspaceConfig Config => ConfigX; public WorkspaceConfig Config => ConfigX;
public GitLabRepoWorkspaceConfig ConfigX { get; } = config; public GitLabRepoWorkspaceConfig ConfigX { get; } = config;
public IGitLabClient Gitlab { get; } = new GitLabClient(config.InstanceUrl, config.ApiToken); public IGitLabClient Gitlab { get; } = new GitLabClient(config.InstanceUrl, config.ApiToken);
public ModpackConfig? ModpackConfig { get; private set; } public ModpackConfig? ModpackConfig { get; private set; }
public InstallInfos? InstallInfos { get; private set; } public InstallInfos? InstallInfos { get; private set; }
public UpdateInfos? UpdateInfos { get; private set; } public UpdateInfos? UpdateInfos { get; private set; }
public async Task<bool> Load() public async Task<bool> Load()
@@ -40,13 +34,17 @@ internal class GitLabRepoWorkspace(GitLabRepoWorkspaceConfig config) : IWorkspac
public async Task<bool> Save() public async Task<bool> Save()
{ {
var failed = true;
if (InstallInfos != null) if (InstallInfos != null)
{ {
var newInstallInfos = InstallInfos.ToString(); var newInstallInfos = InstallInfos.ToString();
if (newInstallInfos != rawInstallInfos) if (newInstallInfos != rawInstallInfos)
{ {
await SaveContent(ConfigX.FileLocationInstallJson, newInstallInfos); if (await SaveContent(ConfigX.FileLocationInstallJson, newInstallInfos))
rawInstallInfos = newInstallInfos; rawInstallInfos = newInstallInfos;
else
failed = true;
} }
} }
@@ -55,12 +53,14 @@ internal class GitLabRepoWorkspace(GitLabRepoWorkspaceConfig config) : IWorkspac
var newUpdateInfos = UpdateInfos.ToString(); var newUpdateInfos = UpdateInfos.ToString();
if (newUpdateInfos != rawUpdateInfos) if (newUpdateInfos != rawUpdateInfos)
{ {
await SaveContent(ConfigX.FileLocationUpdateJson, newUpdateInfos); if (await SaveContent(ConfigX.FileLocationUpdateJson, newUpdateInfos))
rawUpdateInfos = newUpdateInfos; rawUpdateInfos = newUpdateInfos;
else
failed = true;
} }
} }
return true; return failed;
} }
private async Task<string> GetContent(string path) private async Task<string> GetContent(string path)

View File

@@ -2,21 +2,19 @@
namespace ModpackUpdater.Apps.Manager.Features.Workspaces.GitLabRepo; namespace ModpackUpdater.Apps.Manager.Features.Workspaces.GitLabRepo;
internal class GitLabRepoWorkspaceConfig : WorkspaceConfig public class GitLabRepoWorkspaceConfig : WorkspaceConfig, ICloneable
{ {
public override string DisplayText => $"{RepoName ?? "?"} | {RepoBranche} | {InstanceUrl}"; public override string DisplayText => $"{RepoName ?? "?"} | {RepoBranche} | {InstanceUrl}";
public string? RepoName { get; set; } public string? RepoName { get; set; }
public string InstanceUrl { get; set; } = "https://gitlab.com"; public string InstanceUrl { get; set; } = "https://gitlab.com";
public string? ApiToken { get; set; } public string? ApiToken { get; set; }
public long RepoId { get; set; } = 0L; public long RepoId { get; set; } = 0L;
public string RepoBranche { get; set; } = "master"; public string RepoBranche { get; set; } = "master";
public string FileLocationInstallJson { get; set; } = "install.json"; public string FileLocationInstallJson { get; set; } = "install.json";
public string FileLocationUpdateJson { get; set; } = "updates.json"; public string FileLocationUpdateJson { get; set; } = "updates.json";
public object Clone()
{
return MemberwiseClone();
}
} }

View File

@@ -1,266 +0,0 @@
namespace ModpackUpdater.Apps.Manager.Features.Workspaces.GitLabRepo;
partial class GitLabRepoWorkspaceConfigEditor
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Vom Komponenten-Designer generierter Code
/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
tableLayoutPanel1 = new TableLayoutPanel();
radTextBox_FileLocUpdateJson = new Telerik.WinControls.UI.RadTextBox();
radTextBox_FileLocInstallJson = new Telerik.WinControls.UI.RadTextBox();
radTextBox_RepoBranche = new Telerik.WinControls.UI.RadTextBox();
radSpinEditor_RepoId = new Telerik.WinControls.UI.RadSpinEditor();
radTextBox_ApiToken = new Telerik.WinControls.UI.RadTextBox();
radTextBox_InstanceUrl = new Telerik.WinControls.UI.RadTextBox();
radLabel1 = new Telerik.WinControls.UI.RadLabel();
radLabel2 = new Telerik.WinControls.UI.RadLabel();
radLabel3 = new Telerik.WinControls.UI.RadLabel();
radLabel4 = new Telerik.WinControls.UI.RadLabel();
radLabel5 = new Telerik.WinControls.UI.RadLabel();
radLabel6 = new Telerik.WinControls.UI.RadLabel();
radLabel7 = new Telerik.WinControls.UI.RadLabel();
radTextBox_ModpackConfigUrl = new Telerik.WinControls.UI.RadTextBox();
tableLayoutPanel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)radTextBox_FileLocUpdateJson).BeginInit();
((System.ComponentModel.ISupportInitialize)radTextBox_FileLocInstallJson).BeginInit();
((System.ComponentModel.ISupportInitialize)radTextBox_RepoBranche).BeginInit();
((System.ComponentModel.ISupportInitialize)radSpinEditor_RepoId).BeginInit();
((System.ComponentModel.ISupportInitialize)radTextBox_ApiToken).BeginInit();
((System.ComponentModel.ISupportInitialize)radTextBox_InstanceUrl).BeginInit();
((System.ComponentModel.ISupportInitialize)radLabel1).BeginInit();
((System.ComponentModel.ISupportInitialize)radLabel2).BeginInit();
((System.ComponentModel.ISupportInitialize)radLabel3).BeginInit();
((System.ComponentModel.ISupportInitialize)radLabel4).BeginInit();
((System.ComponentModel.ISupportInitialize)radLabel5).BeginInit();
((System.ComponentModel.ISupportInitialize)radLabel6).BeginInit();
((System.ComponentModel.ISupportInitialize)radLabel7).BeginInit();
((System.ComponentModel.ISupportInitialize)radTextBox_ModpackConfigUrl).BeginInit();
SuspendLayout();
//
// tableLayoutPanel1
//
tableLayoutPanel1.AutoSize = true;
tableLayoutPanel1.AutoSizeMode = AutoSizeMode.GrowAndShrink;
tableLayoutPanel1.ColumnCount = 1;
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
tableLayoutPanel1.Controls.Add(radTextBox_FileLocUpdateJson, 0, 11);
tableLayoutPanel1.Controls.Add(radTextBox_FileLocInstallJson, 0, 9);
tableLayoutPanel1.Controls.Add(radTextBox_RepoBranche, 0, 7);
tableLayoutPanel1.Controls.Add(radSpinEditor_RepoId, 0, 5);
tableLayoutPanel1.Controls.Add(radTextBox_ApiToken, 0, 3);
tableLayoutPanel1.Controls.Add(radTextBox_InstanceUrl, 0, 1);
tableLayoutPanel1.Controls.Add(radLabel1, 0, 0);
tableLayoutPanel1.Controls.Add(radLabel2, 0, 2);
tableLayoutPanel1.Controls.Add(radLabel3, 0, 4);
tableLayoutPanel1.Controls.Add(radLabel4, 0, 6);
tableLayoutPanel1.Controls.Add(radLabel5, 0, 8);
tableLayoutPanel1.Controls.Add(radLabel6, 0, 10);
tableLayoutPanel1.Controls.Add(radLabel7, 0, 12);
tableLayoutPanel1.Controls.Add(radTextBox_ModpackConfigUrl, 0, 13);
tableLayoutPanel1.Dock = DockStyle.Fill;
tableLayoutPanel1.Location = new Point(0, 30);
tableLayoutPanel1.Name = "tableLayoutPanel1";
tableLayoutPanel1.RowCount = 14;
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.RowStyles.Add(new RowStyle());
tableLayoutPanel1.Size = new Size(300, 406);
tableLayoutPanel1.TabIndex = 4;
//
// radTextBox_FileLocUpdateJson
//
radTextBox_FileLocUpdateJson.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
radTextBox_FileLocUpdateJson.Location = new Point(3, 321);
radTextBox_FileLocUpdateJson.Name = "radTextBox_FileLocUpdateJson";
radTextBox_FileLocUpdateJson.Size = new Size(294, 24);
radTextBox_FileLocUpdateJson.TabIndex = 4;
//
// radTextBox_FileLocInstallJson
//
radTextBox_FileLocInstallJson.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
radTextBox_FileLocInstallJson.Location = new Point(3, 263);
radTextBox_FileLocInstallJson.Name = "radTextBox_FileLocInstallJson";
radTextBox_FileLocInstallJson.Size = new Size(294, 24);
radTextBox_FileLocInstallJson.TabIndex = 3;
//
// radTextBox_RepoBranche
//
radTextBox_RepoBranche.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
radTextBox_RepoBranche.Location = new Point(3, 205);
radTextBox_RepoBranche.Name = "radTextBox_RepoBranche";
radTextBox_RepoBranche.Size = new Size(294, 24);
radTextBox_RepoBranche.TabIndex = 2;
//
// radSpinEditor_RepoId
//
radSpinEditor_RepoId.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
radSpinEditor_RepoId.Location = new Point(3, 147);
radSpinEditor_RepoId.Maximum = new decimal(new int[] { -1, int.MaxValue, 0, 0 });
radSpinEditor_RepoId.Name = "radSpinEditor_RepoId";
radSpinEditor_RepoId.Size = new Size(294, 24);
radSpinEditor_RepoId.TabIndex = 6;
//
// radTextBox_ApiToken
//
radTextBox_ApiToken.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
radTextBox_ApiToken.Location = new Point(3, 89);
radTextBox_ApiToken.Name = "radTextBox_ApiToken";
radTextBox_ApiToken.Size = new Size(294, 24);
radTextBox_ApiToken.TabIndex = 1;
//
// radTextBox_InstanceUrl
//
radTextBox_InstanceUrl.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
radTextBox_InstanceUrl.Location = new Point(3, 31);
radTextBox_InstanceUrl.Name = "radTextBox_InstanceUrl";
radTextBox_InstanceUrl.Size = new Size(294, 24);
radTextBox_InstanceUrl.TabIndex = 0;
//
// radLabel1
//
radLabel1.Location = new Point(3, 3);
radLabel1.Name = "radLabel1";
radLabel1.Size = new Size(80, 22);
radLabel1.TabIndex = 7;
radLabel1.Text = "Instance url";
//
// radLabel2
//
radLabel2.Location = new Point(3, 61);
radLabel2.Name = "radLabel2";
radLabel2.Size = new Size(69, 22);
radLabel2.TabIndex = 8;
radLabel2.Text = "Api token";
//
// radLabel3
//
radLabel3.Location = new Point(3, 119);
radLabel3.Name = "radLabel3";
radLabel3.Size = new Size(91, 22);
radLabel3.TabIndex = 9;
radLabel3.Text = "Repository id";
//
// radLabel4
//
radLabel4.Location = new Point(3, 177);
radLabel4.Name = "radLabel4";
radLabel4.Size = new Size(130, 22);
radLabel4.TabIndex = 10;
radLabel4.Text = "Repository branche";
//
// radLabel5
//
radLabel5.Location = new Point(3, 235);
radLabel5.Name = "radLabel5";
radLabel5.Size = new Size(181, 22);
radLabel5.TabIndex = 11;
radLabel5.Text = "File location for install infos";
//
// radLabel6
//
radLabel6.Location = new Point(3, 293);
radLabel6.Name = "radLabel6";
radLabel6.Size = new Size(189, 22);
radLabel6.TabIndex = 12;
radLabel6.Text = "File location for updates info";
//
// radLabel7
//
radLabel7.Location = new Point(3, 351);
radLabel7.Name = "radLabel7";
radLabel7.Size = new Size(131, 22);
radLabel7.TabIndex = 13;
radLabel7.Text = "Modpack config url";
//
// radTextBox_ModpackConfigUrl
//
radTextBox_ModpackConfigUrl.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
radTextBox_ModpackConfigUrl.Location = new Point(3, 379);
radTextBox_ModpackConfigUrl.Name = "radTextBox_ModpackConfigUrl";
radTextBox_ModpackConfigUrl.Size = new Size(294, 24);
radTextBox_ModpackConfigUrl.TabIndex = 14;
//
// GitLabRepoWorkspaceConfigEditor
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
AutoSize = true;
AutoSizeMode = AutoSizeMode.GrowAndShrink;
BackColor = Color.Transparent;
Controls.Add(tableLayoutPanel1);
MinimumSize = new Size(300, 0);
Name = "GitLabRepoWorkspaceConfigEditor";
Size = new Size(300, 466);
Controls.SetChildIndex(tableLayoutPanel1, 0);
tableLayoutPanel1.ResumeLayout(false);
tableLayoutPanel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)radTextBox_FileLocUpdateJson).EndInit();
((System.ComponentModel.ISupportInitialize)radTextBox_FileLocInstallJson).EndInit();
((System.ComponentModel.ISupportInitialize)radTextBox_RepoBranche).EndInit();
((System.ComponentModel.ISupportInitialize)radSpinEditor_RepoId).EndInit();
((System.ComponentModel.ISupportInitialize)radTextBox_ApiToken).EndInit();
((System.ComponentModel.ISupportInitialize)radTextBox_InstanceUrl).EndInit();
((System.ComponentModel.ISupportInitialize)radLabel1).EndInit();
((System.ComponentModel.ISupportInitialize)radLabel2).EndInit();
((System.ComponentModel.ISupportInitialize)radLabel3).EndInit();
((System.ComponentModel.ISupportInitialize)radLabel4).EndInit();
((System.ComponentModel.ISupportInitialize)radLabel5).EndInit();
((System.ComponentModel.ISupportInitialize)radLabel6).EndInit();
((System.ComponentModel.ISupportInitialize)radLabel7).EndInit();
((System.ComponentModel.ISupportInitialize)radTextBox_ModpackConfigUrl).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private TableLayoutPanel tableLayoutPanel1;
private Telerik.WinControls.UI.RadTextBox radTextBox_InstanceUrl;
private Telerik.WinControls.UI.RadTextBox radTextBox_ApiToken;
private Telerik.WinControls.UI.RadTextBox radTextBox_RepoBranche;
private Telerik.WinControls.UI.RadTextBox radTextBox_FileLocInstallJson;
private Telerik.WinControls.UI.RadTextBox radTextBox_FileLocUpdateJson;
private Telerik.WinControls.UI.RadSpinEditor radSpinEditor_RepoId;
private Telerik.WinControls.UI.RadLabel radLabel1;
private Telerik.WinControls.UI.RadLabel radLabel2;
private Telerik.WinControls.UI.RadLabel radLabel3;
private Telerik.WinControls.UI.RadLabel radLabel4;
private Telerik.WinControls.UI.RadLabel radLabel5;
private Telerik.WinControls.UI.RadLabel radLabel6;
private Telerik.WinControls.UI.RadLabel radLabel7;
private Telerik.WinControls.UI.RadTextBox radTextBox_ModpackConfigUrl;
}

View File

@@ -1,45 +0,0 @@
using Pilz.UI;
using Pilz.UI.Telerik.Dialogs;
namespace ModpackUpdater.Apps.Manager.Features.Workspaces.GitLabRepo;
internal partial class GitLabRepoWorkspaceConfigEditor : RadFlyoutBase, ILoadContent
{
private readonly GitLabRepoWorkspaceConfig settings;
public GitLabRepoWorkspaceConfigEditor(GitLabRepoWorkspaceConfig settings)
{
this.settings = settings;
InitializeComponent();
var defaults = new GitLabRepoWorkspaceConfig();
radTextBox_InstanceUrl.NullText = defaults.InstanceUrl;
radTextBox_RepoBranche.NullText = defaults.RepoBranche;
radTextBox_FileLocInstallJson.NullText = defaults.InstanceUrl;
radTextBox_FileLocUpdateJson.NullText = defaults.FileLocationUpdateJson;
}
public void LoadContent()
{
radTextBox_InstanceUrl.Text = settings.InstanceUrl;
radTextBox_ApiToken.Text = settings.ApiToken;
radSpinEditor_RepoId.Value = settings.RepoId;
radTextBox_RepoBranche.Text = settings.RepoBranche;
radTextBox_FileLocInstallJson.Text = settings.FileLocationInstallJson;
radTextBox_FileLocUpdateJson.Text = settings.FileLocationUpdateJson;
radTextBox_ModpackConfigUrl.Text = settings.ModpackConfigUrl;
}
protected override bool ValidateOK()
{
settings.InstanceUrl = radTextBox_InstanceUrl.Text.Trim();
settings.ApiToken = radTextBox_ApiToken.Text.Trim();
settings.RepoId = (long)radSpinEditor_RepoId.Value;
settings.RepoBranche = radTextBox_RepoBranche.Text.Trim();
settings.FileLocationInstallJson = radTextBox_FileLocInstallJson.Text.Trim();
settings.FileLocationUpdateJson = radTextBox_FileLocUpdateJson.Text.Trim();
settings.ModpackConfigUrl = radTextBox_ModpackConfigUrl.Text.Trim();
return base.ValidateOK();
}
}

View File

@@ -0,0 +1,37 @@
<dialogs:AvaloniaFlyoutBase
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:dialogs="https://git.pilzinsel64.de/pilz-framework/pilz"
xmlns:gitLabRepo="clr-namespace:ModpackUpdater.Apps.Manager.Features.Workspaces.GitLabRepo"
xmlns:langRes="clr-namespace:ModpackUpdater.Apps.Manager.LangRes"
mc:Ignorable="d"
d:DesignWidth="800"
d:DesignHeight="450"
Width="300"
x:Class="ModpackUpdater.Apps.Manager.Features.Workspaces.GitLabRepo.GitLabRepoWorkspaceConfigEditorView"
x:DataType="gitLabRepo:GitLabRepoWorkspaceConfig">
<dialogs:AvaloniaFlyoutBase.MainContent>
<StackPanel Spacing="6">
<Label Target="TextBoxInstanceUrl" Content="{x:Static langRes:GeneralLangRes.GitLabInstanceUrl}"/>
<TextBox Name="TextBoxInstanceUrl" Text="{Binding InstanceUrl}"/>
<Label Target="TextBoxApiToken" Content="{x:Static langRes:GeneralLangRes.GitLabApiToken}"/>
<TextBox Name="TextBoxApiToken" Text="{Binding ApiToken}"/>
<Label Target="NumericUpDownRepoId" Content="{x:Static langRes:GeneralLangRes.RepositoryId}"/>
<NumericUpDown Name="NumericUpDownRepoId" Value="{Binding RepoId}"/>
<Label Target="TextBoxInstallJson" Content="{x:Static langRes:GeneralLangRes.FileLocationOfInstallJson}"/>
<TextBox Name="TextBoxInstallJson" Text="{Binding FileLocationInstallJson}"/>
<Label Target="TextBoxUpdateJson" Content="{x:Static langRes:GeneralLangRes.FileLocationOfUpdateJson}"/>
<TextBox Name="TextBoxUpdateJson" Text="{Binding FileLocationUpdateJson}"/>
<Label Target="TextBoxModpackConfigUrl" Content="{x:Static langRes:GeneralLangRes.ModpackConfigUrl}"/>
<TextBox Name="TextBoxModpackConfigUrl" Text="{Binding ModpackConfigUrl}"/>
</StackPanel>
</dialogs:AvaloniaFlyoutBase.MainContent>
</dialogs:AvaloniaFlyoutBase>

View File

@@ -0,0 +1,23 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Pilz.UI.AvaloniaUI.Dialogs;
namespace ModpackUpdater.Apps.Manager.Features.Workspaces.GitLabRepo;
public partial class GitLabRepoWorkspaceConfigEditorView : AvaloniaFlyoutBase
{
public GitLabRepoWorkspaceConfig Settings { get; }
public GitLabRepoWorkspaceConfigEditorView(GitLabRepoWorkspaceConfig settings)
{
Settings = settings;
DataContext = settings;
InitializeComponent();
}
protected override object? GetResult()
{
return Settings;
}
}

View File

@@ -1,39 +1,37 @@
using ModpackUpdater.Apps.Manager.Api.Model; using ModpackUpdater.Apps.Manager.Api.Model;
using ModpackUpdater.Apps.Manager.Api.Plugins.Features; using ModpackUpdater.Apps.Manager.Api.Plugins.Features;
using ModpackUpdater.Apps.Manager.LangRes; using ModpackUpdater.Apps.Manager.LangRes;
using Pilz.Plugins.Advanced; using Pilz.Features;
using Pilz.UI.Extensions; using Pilz.UI.AvaloniaUI.Dialogs;
using Pilz.UI.Symbols; using Pilz.UI.Symbols;
using Pilz.UI.Telerik.Dialogs;
namespace ModpackUpdater.Apps.Manager.Features.Workspaces.GitLabRepo; namespace ModpackUpdater.Apps.Manager.Features.Workspaces.GitLabRepo;
internal class GitLabRepoWorkspaceFeature : WorkspaceFeature, IPluginFeatureProvider<GitLabRepoWorkspaceFeature> internal class GitLabRepoWorkspaceFeature() : WorkspaceFeature("origin.gitlab", FeatureNamesLangRes.GitLabWorkspace), IPluginFeatureProvider<GitLabRepoWorkspaceFeature>
{ {
public static GitLabRepoWorkspaceFeature Instance { get; } = new(); public static GitLabRepoWorkspaceFeature Instance { get; } = new();
public GitLabRepoWorkspaceFeature() : base("origin.gitlab", FeatureNamesLangRes.GitLabWorkspace) public override object? Icon => AppGlobals.Symbols.GetImage(AppSymbols.gitlab, SymbolSize.Small);
protected override async Task OnConfigure(WorkspaceContext context)
{ {
Icon = AppGlobals.Symbols.GetSvgImage(AppSymbols.gitlab, SymbolSize.Small); var settings = context.Workspace?.Config as GitLabRepoWorkspaceConfig ?? new();
}
protected override bool OnConfigure(ref IWorkspace? workspace) if ((await AvaloniaFlyoutBase.Show(
{ new GitLabRepoWorkspaceConfigEditorView((GitLabRepoWorkspaceConfig)settings.Clone()),
var settings = workspace?.Config as GitLabRepoWorkspaceConfig ?? new(); context.MainApi.MainWindow,
TitlesLangRes.GitLabRepoWorkspaceEditor,
if (RadDialogBase.ShowDialog(new GitLabRepoWorkspaceConfigEditor(settings), TitlesLangRes.GitLabRepoWorkspaceEditor, AppGlobals.Symbols.GetSvgImage(AppSymbols.gitlab, SymbolSize.Small)).Result.IsNotOk()) AppGlobals.Symbols.GetImageSource(AppSymbols.gitlab)))
return false; .Result is GitLabRepoWorkspaceConfig settingsNew)
context.Workspace = new GitLabRepoWorkspace(settingsNew);
workspace = new GitLabRepoWorkspace(settings); else
context.Canceled = true;
return true;
} }
protected override void OnCreate(out IWorkspace workspace, WorkspaceConfig config) protected override void OnCreate(out IWorkspace workspace, WorkspaceConfig config)
{ {
if (config is not GitLabRepoWorkspaceConfig gitlabConfig) if (config is not GitLabRepoWorkspaceConfig gitlabConfig)
throw new NotImplementedException($"Only configs of type {typeof(GitLabRepoWorkspaceConfig).Name} are allowed."); throw new NotSupportedException($"Only configs of type {nameof(GitLabRepoWorkspaceConfig)} are allowed.");
workspace = new GitLabRepoWorkspace(gitlabConfig); workspace = new GitLabRepoWorkspace(gitlabConfig);
} }
} }

View File

@@ -0,0 +1,85 @@
using ModpackUpdater.Apps.Manager.Api.Model;
namespace ModpackUpdater.Apps.Manager.Features.Workspaces.LocalFolder;
internal class LocalFolderWorkspace(LocalFolderWorkspaceConfig config) : IWorkspace
{
private string? rawInstallInfos;
private string? rawUpdateInfos;
public WorkspaceConfig Config => ConfigX;
public LocalFolderWorkspaceConfig ConfigX { get; } = config;
public ModpackConfig? ModpackConfig { get; private set; }
public InstallInfos? InstallInfos { get; private set; }
public UpdateInfos? UpdateInfos { get; private set; }
public async Task<bool> Load()
{
if (!string.IsNullOrWhiteSpace(Config.ModpackConfigUrl))
ModpackConfig = ModpackConfig.LoadFromUrl(Config.ModpackConfigUrl);
rawInstallInfos = await GetContent(ConfigX.FileLocationInstallJson);
InstallInfos = InstallInfos.Parse(rawInstallInfos);
rawUpdateInfos = await GetContent(ConfigX.FileLocationUpdateJson);
UpdateInfos = UpdateInfos.Parse(rawUpdateInfos);
if (string.IsNullOrWhiteSpace(ConfigX.FolderName))
ConfigX.FolderName = Path.GetFileName(ConfigX.RootFolderPath);
return InstallInfos != null && UpdateInfos != null;
}
public async Task<bool> Save()
{
var failed = false;
if (InstallInfos != null)
{
var newInstallInfos = InstallInfos.ToString();
if (newInstallInfos != rawInstallInfos)
{
if (await SaveContent(ConfigX.FileLocationInstallJson, newInstallInfos))
rawInstallInfos = newInstallInfos;
else
failed = true;
}
}
if (UpdateInfos != null)
{
var newUpdateInfos = UpdateInfos.ToString();
if (newUpdateInfos != rawUpdateInfos)
{
if (await SaveContent(ConfigX.FileLocationUpdateJson, newUpdateInfos))
rawUpdateInfos = newUpdateInfos;
else
failed = true;
}
}
return !failed;
}
private async Task<string?> GetContent(string path)
{
if (ConfigX.RootFolderPath == null)
return null;
var filePath = Path.Combine(ConfigX.RootFolderPath!, path);
return File.Exists(filePath) ? await File.ReadAllTextAsync(filePath) : null;
}
private async Task<bool> SaveContent(string path, string content)
{
if (ConfigX.RootFolderPath == null)
return false;
var filePath = Path.Combine(ConfigX.RootFolderPath!, path);
if (!File.Exists(filePath))
return false;
await File.WriteAllTextAsync(filePath, content);
return true;
}
}

View File

@@ -0,0 +1,17 @@
using ModpackUpdater.Apps.Manager.Api.Model;
namespace ModpackUpdater.Apps.Manager.Features.Workspaces.LocalFolder;
public class LocalFolderWorkspaceConfig : WorkspaceConfig, ICloneable
{
public override string DisplayText => FolderName ?? string.Empty;
public string? FolderName { get; set; }
public string? RootFolderPath { get; set; }
public string FileLocationInstallJson { get; set; } = "install.json";
public string FileLocationUpdateJson { get; set; } = "updates.json";
public object Clone()
{
return MemberwiseClone();
}
}

View File

@@ -0,0 +1,50 @@
<dialogs:AvaloniaFlyoutBase
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:dialogs="https://git.pilzinsel64.de/pilz-framework/pilz"
xmlns:langRes="clr-namespace:ModpackUpdater.Apps.Manager.LangRes"
xmlns:localFolder="clr-namespace:ModpackUpdater.Apps.Manager.Features.Workspaces.LocalFolder"
mc:Ignorable="d"
d:DesignWidth="800"
d:DesignHeight="450"
Width="300"
x:Class="ModpackUpdater.Apps.Manager.Features.Workspaces.LocalFolder.LocalFolderWorkspaceConfigEditorView"
x:DataType="localFolder:LocalFolderWorkspaceConfig">
<dialogs:AvaloniaFlyoutBase.MainContent>
<StackPanel Spacing="6">
<Label Target="TextBoxName" Content="{x:Static langRes:GeneralLangRes.Name}"/>
<TextBox Name="TextBoxName" Text="{Binding FolderName}"/>
<Label Target="TextBoxRootFolderPath" Content="{x:Static langRes:GeneralLangRes.RootFolderPath}"/>
<Grid
ColumnDefinitions="*,Auto"
ColumnSpacing="6">
<TextBox
Grid.Column="0"
x:Name="TextBoxRootFolderPath"
Text="{Binding RootFolderPath}"/>
<dialogs:ImageButton
Grid.Column="1"
x:Name="ButtonSearch"
VerticalAlignment="Stretch"
HorizontalAlignment="Right"
Text="{x:Static langRes:GeneralLangRes.Select}"
Click="ButtonSearch_OnClick"/>
</Grid>
<Label Target="TextBoxInstallJson" Content="{x:Static langRes:GeneralLangRes.FileLocationOfInstallJson}"/>
<TextBox Name="TextBoxInstallJson" Text="{Binding FileLocationInstallJson}"/>
<Label Target="TextBoxUpdateJson" Content="{x:Static langRes:GeneralLangRes.FileLocationOfUpdateJson}"/>
<TextBox Name="TextBoxUpdateJson" Text="{Binding FileLocationUpdateJson}"/>
<Label Target="TextBoxModpackConfigUrl" Content="{x:Static langRes:GeneralLangRes.ModpackConfigUrl}"/>
<TextBox Name="TextBoxModpackConfigUrl" Text="{Binding ModpackConfigUrl}"/>
</StackPanel>
</dialogs:AvaloniaFlyoutBase.MainContent>
</dialogs:AvaloniaFlyoutBase>

View File

@@ -0,0 +1,49 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
using ModpackUpdater.Apps.Manager.LangRes;
using Pilz.UI.AvaloniaUI.Dialogs;
namespace ModpackUpdater.Apps.Manager.Features.Workspaces.LocalFolder;
public partial class LocalFolderWorkspaceConfigEditorView : AvaloniaFlyoutBase
{
public LocalFolderWorkspaceConfig Settings { get; }
public LocalFolderWorkspaceConfigEditorView() : this(new())
{
}
public LocalFolderWorkspaceConfigEditorView(LocalFolderWorkspaceConfig settings)
{
Settings = settings;
DataContext = settings;
InitializeComponent();
ButtonSearch.ImageSource = AppGlobals.Symbols.GetImageSource(AppSymbols.opened_folder);
}
protected override object? GetResult()
{
return Settings;
}
private async void ButtonSearch_OnClick(object? sender, RoutedEventArgs e)
{
if (TopLevel.GetTopLevel(this) is not { } topLevel)
return;
var filePaths = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{
Title = GeneralLangRes.SelectRootFolder,
AllowMultiple = false,
});
if (filePaths.Count < 1)
return;
TextBoxRootFolderPath.Text = filePaths[0].Path.AbsolutePath;
if (string.IsNullOrWhiteSpace(TextBoxName.Text))
TextBoxName.Text = filePaths[0].Name;
}
}

View File

@@ -0,0 +1,37 @@
using ModpackUpdater.Apps.Manager.Api.Model;
using ModpackUpdater.Apps.Manager.Api.Plugins.Features;
using ModpackUpdater.Apps.Manager.LangRes;
using Pilz.Features;
using Pilz.UI.AvaloniaUI.Dialogs;
using Pilz.UI.Symbols;
namespace ModpackUpdater.Apps.Manager.Features.Workspaces.LocalFolder;
internal class LocalFolderWorkspaceFeature() : WorkspaceFeature("origin.localfolder", FeatureNamesLangRes.LocalFolderWorkspace), IPluginFeatureProvider<LocalFolderWorkspaceFeature>
{
public static LocalFolderWorkspaceFeature Instance { get; } = new();
public override object? Icon => AppGlobals.Symbols.GetImage(AppSymbols.opened_folder, SymbolSize.Small);
protected override async Task OnConfigure(WorkspaceContext context)
{
var settings = context.Workspace?.Config as LocalFolderWorkspaceConfig ?? new();
if ((await AvaloniaFlyoutBase.Show(
new LocalFolderWorkspaceConfigEditorView((LocalFolderWorkspaceConfig)settings.Clone()),
context.MainApi.MainWindow,
TitlesLangRes.LocalFolderWorkspaceEditor,
AppGlobals.Symbols.GetImageSource(AppSymbols.gitlab)))
.Result is LocalFolderWorkspaceConfig settingsNew)
context.Workspace = new LocalFolderWorkspace(settingsNew);
else
context.Canceled = true;
}
protected override void OnCreate(out IWorkspace workspace, WorkspaceConfig config)
{
if (config is not LocalFolderWorkspaceConfig gitlabConfig)
throw new NotSupportedException($"Only configs of type {nameof(LocalFolderWorkspaceConfig)} are allowed.");
workspace = new LocalFolderWorkspace(gitlabConfig);
}
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<PropertyChanged />
</Weavers>

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="PropertyChanged" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="InjectOnPropertyNameChanged" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the On_PropertyName_Changed feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="TriggerDependentProperties" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the Dependent properties feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="EnableIsChangedProperty" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the IsChanged property feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="EventInvokerNames" type="xs:string">
<xs:annotation>
<xs:documentation>Used to change the name of the method that fires the notify event. This is a string that accepts multiple values in a comma separated form.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CheckForEquality" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should be inserted. If false, equality checking will be disabled for the project.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CheckForEqualityUsingBaseEquals" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should use the Equals method resolved from the base class.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UseStaticEqualsFromBase" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should use the static Equals method resolved from the base class.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="SuppressWarnings" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to turn off build warnings from this weaver.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="SuppressOnPropertyNameChangedWarning" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to turn off build warnings about mismatched On_PropertyName_Changed methods.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@@ -1,10 +1,9 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// Dieser Code wurde von einem Tool generiert. // This code was generated by a tool.
// Laufzeitversion:4.0.30319.42000
// //
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // Changes to this file may cause incorrect behavior and will be lost if
// der Code erneut generiert wird. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -12,46 +11,32 @@ namespace ModpackUpdater.Apps.Manager.LangRes {
using System; using System;
/// <summary> [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. [System.Diagnostics.DebuggerNonUserCodeAttribute()]
/// </summary> [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert public class ActionsListLangRes {
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class ActionsListLangRes {
private static global::System.Resources.ResourceManager resourceMan; private static System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture; private static System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal ActionsListLangRes() { internal ActionsListLangRes() {
} }
/// <summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. public static System.Resources.ResourceManager ResourceManager {
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (object.Equals(null, resourceMan)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModpackUpdater.Apps.Manager.LangRes.ActionsListLangRes", typeof(ActionsListLangRes).Assembly); System.Resources.ResourceManager temp = new System.Resources.ResourceManager("ModpackUpdater.Apps.Manager.LangRes.ActionsListLangRes", typeof(ActionsListLangRes).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;
} }
} }
/// <summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle public static System.Globalization.CultureInfo Culture {
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get { get {
return resourceCulture; return resourceCulture;
} }
@@ -60,163 +45,109 @@ namespace ModpackUpdater.Apps.Manager.LangRes {
} }
} }
/// <summary> public static string Col_DestPath {
/// Sucht eine lokalisierte Zeichenfolge, die Destination path ähnelt.
/// </summary>
internal static string Col_DestPath {
get { get {
return ResourceManager.GetString("Col_DestPath", resourceCulture); return ResourceManager.GetString("Col_DestPath", resourceCulture);
} }
} }
/// <summary> public static string Col_Id {
/// Sucht eine lokalisierte Zeichenfolge, die Id ähnelt.
/// </summary>
internal static string Col_Id {
get { get {
return ResourceManager.GetString("Col_Id", resourceCulture); return ResourceManager.GetString("Col_Id", resourceCulture);
} }
} }
/// <summary> public static string Col_InheritFrom {
/// Sucht eine lokalisierte Zeichenfolge, die Inherit from ähnelt.
/// </summary>
internal static string Col_InheritFrom {
get { get {
return ResourceManager.GetString("Col_InheritFrom", resourceCulture); return ResourceManager.GetString("Col_InheritFrom", resourceCulture);
} }
} }
/// <summary> public static string Col_IsDir {
/// Sucht eine lokalisierte Zeichenfolge, die Is directory ähnelt.
/// </summary>
internal static string Col_IsDir {
get { get {
return ResourceManager.GetString("Col_IsDir", resourceCulture); return ResourceManager.GetString("Col_IsDir", resourceCulture);
} }
} }
/// <summary> public static string Col_IsExtra {
/// Sucht eine lokalisierte Zeichenfolge, die Is Extra ähnelt.
/// </summary>
internal static string Col_IsExtra {
get { get {
return ResourceManager.GetString("Col_IsExtra", resourceCulture); return ResourceManager.GetString("Col_IsExtra", resourceCulture);
} }
} }
/// <summary> public static string Col_IsZip {
/// Sucht eine lokalisierte Zeichenfolge, die Is ZIP ähnelt.
/// </summary>
internal static string Col_IsZip {
get { get {
return ResourceManager.GetString("Col_IsZip", resourceCulture); return ResourceManager.GetString("Col_IsZip", resourceCulture);
} }
} }
/// <summary> public static string Col_Name {
/// Sucht eine lokalisierte Zeichenfolge, die Name ähnelt.
/// </summary>
internal static string Col_Name {
get { get {
return ResourceManager.GetString("Col_Name", resourceCulture); return ResourceManager.GetString("Col_Name", resourceCulture);
} }
} }
/// <summary> public static string Col_Side {
/// Sucht eine lokalisierte Zeichenfolge, die Side ähnelt.
/// </summary>
internal static string Col_Side {
get { get {
return ResourceManager.GetString("Col_Side", resourceCulture); return ResourceManager.GetString("Col_Side", resourceCulture);
} }
} }
/// <summary> public static string Col_SrcName {
/// Sucht eine lokalisierte Zeichenfolge, die Source name ähnelt.
/// </summary>
internal static string Col_SrcName {
get { get {
return ResourceManager.GetString("Col_SrcName", resourceCulture); return ResourceManager.GetString("Col_SrcName", resourceCulture);
} }
} }
/// <summary> public static string Col_SrcOwner {
/// Sucht eine lokalisierte Zeichenfolge, die Source owner ähnelt.
/// </summary>
internal static string Col_SrcOwner {
get { get {
return ResourceManager.GetString("Col_SrcOwner", resourceCulture); return ResourceManager.GetString("Col_SrcOwner", resourceCulture);
} }
} }
/// <summary> public static string Col_SrcPath {
/// Sucht eine lokalisierte Zeichenfolge, die Source path ähnelt.
/// </summary>
internal static string Col_SrcPath {
get { get {
return ResourceManager.GetString("Col_SrcPath", resourceCulture); return ResourceManager.GetString("Col_SrcPath", resourceCulture);
} }
} }
/// <summary> public static string Col_SrcRegEx {
/// Sucht eine lokalisierte Zeichenfolge, die Source RegEx ähnelt.
/// </summary>
internal static string Col_SrcRegEx {
get { get {
return ResourceManager.GetString("Col_SrcRegEx", resourceCulture); return ResourceManager.GetString("Col_SrcRegEx", resourceCulture);
} }
} }
/// <summary> public static string Col_SrcTag {
/// Sucht eine lokalisierte Zeichenfolge, die Source tag ähnelt.
/// </summary>
internal static string Col_SrcTag {
get { get {
return ResourceManager.GetString("Col_SrcTag", resourceCulture); return ResourceManager.GetString("Col_SrcTag", resourceCulture);
} }
} }
/// <summary> public static string Col_SrcType {
/// Sucht eine lokalisierte Zeichenfolge, die Source type ähnelt.
/// </summary>
internal static string Col_SrcType {
get { get {
return ResourceManager.GetString("Col_SrcType", resourceCulture); return ResourceManager.GetString("Col_SrcType", resourceCulture);
} }
} }
/// <summary> public static string Col_SrcUrl {
/// Sucht eine lokalisierte Zeichenfolge, die Source URL ähnelt.
/// </summary>
internal static string Col_SrcUrl {
get { get {
return ResourceManager.GetString("Col_SrcUrl", resourceCulture); return ResourceManager.GetString("Col_SrcUrl", resourceCulture);
} }
} }
/// <summary> public static string Col_UpdateType {
/// Sucht eine lokalisierte Zeichenfolge, die Update type ähnelt.
/// </summary>
internal static string Col_UpdateType {
get { get {
return ResourceManager.GetString("Col_UpdateType", resourceCulture); return ResourceManager.GetString("Col_UpdateType", resourceCulture);
} }
} }
/// <summary> public static string Col_Website {
/// Sucht eine lokalisierte Zeichenfolge, die Website ähnelt.
/// </summary>
internal static string Col_Website {
get { get {
return ResourceManager.GetString("Col_Website", resourceCulture); return ResourceManager.GetString("Col_Website", resourceCulture);
} }
} }
/// <summary> public static string Col_ZipPath {
/// Sucht eine lokalisierte Zeichenfolge, die ZIP archive path ähnelt.
/// </summary>
internal static string Col_ZipPath {
get { get {
return ResourceManager.GetString("Col_ZipPath", resourceCulture); return ResourceManager.GetString("Col_ZipPath", resourceCulture);
} }

View File

@@ -1,10 +1,9 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// Dieser Code wurde von einem Tool generiert. // This code was generated by a tool.
// Laufzeitversion:4.0.30319.42000
// //
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // Changes to this file may cause incorrect behavior and will be lost if
// der Code erneut generiert wird. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -12,46 +11,32 @@ namespace ModpackUpdater.Apps.Manager.LangRes {
using System; using System;
/// <summary> [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. [System.Diagnostics.DebuggerNonUserCodeAttribute()]
/// </summary> [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert public class FeatureNamesLangRes {
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class FeatureNamesLangRes {
private static global::System.Resources.ResourceManager resourceMan; private static System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture; private static System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal FeatureNamesLangRes() { internal FeatureNamesLangRes() {
} }
/// <summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. public static System.Resources.ResourceManager ResourceManager {
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (object.Equals(null, resourceMan)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModpackUpdater.Apps.Manager.LangRes.FeatureNamesLangRes", typeof(FeatureNamesLangRes).Assembly); System.Resources.ResourceManager temp = new System.Resources.ResourceManager("ModpackUpdater.Apps.Manager.LangRes.FeatureNamesLangRes", typeof(FeatureNamesLangRes).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;
} }
} }
/// <summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle public static System.Globalization.CultureInfo Culture {
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get { get {
return resourceCulture; return resourceCulture;
} }
@@ -60,91 +45,79 @@ namespace ModpackUpdater.Apps.Manager.LangRes {
} }
} }
/// <summary> public static string CheckAllActionsHealthy {
/// Sucht eine lokalisierte Zeichenfolge, die Check healthy ähnelt.
/// </summary>
internal static string CheckAllActionsHealthy {
get { get {
return ResourceManager.GetString("CheckAllActionsHealthy", resourceCulture); return ResourceManager.GetString("CheckAllActionsHealthy", resourceCulture);
} }
} }
/// <summary> public static string CheckSingleActionHealthy {
/// Sucht eine lokalisierte Zeichenfolge, die Check healthy ähnelt.
/// </summary>
internal static string CheckSingleActionHealthy {
get { get {
return ResourceManager.GetString("CheckSingleActionHealthy", resourceCulture); return ResourceManager.GetString("CheckSingleActionHealthy", resourceCulture);
} }
} }
/// <summary> public static string ClearDirectLinkFeature {
/// Sucht eine lokalisierte Zeichenfolge, die Clear direct link ähnelt.
/// </summary>
internal static string ClearDirectLinkFeature {
get { get {
return ResourceManager.GetString("ClearDirectLinkFeature", resourceCulture); return ResourceManager.GetString("ClearDirectLinkFeature", resourceCulture);
} }
} }
/// <summary> public static string ClearDirectLinksFeature {
/// Sucht eine lokalisierte Zeichenfolge, die Clear direct links ähnelt.
/// </summary>
internal static string ClearDirectLinksFeature {
get { get {
return ResourceManager.GetString("ClearDirectLinksFeature", resourceCulture); return ResourceManager.GetString("ClearDirectLinksFeature", resourceCulture);
} }
} }
/// <summary> public static string GenerateChangelogFeature {
/// Sucht eine lokalisierte Zeichenfolge, die Generate changelog ähnelt.
/// </summary>
internal static string GenerateChangelogFeature {
get { get {
return ResourceManager.GetString("GenerateChangelogFeature", resourceCulture); return ResourceManager.GetString("GenerateChangelogFeature", resourceCulture);
} }
} }
/// <summary> public static string GenerateModlistAsExcelFeature {
/// Sucht eine lokalisierte Zeichenfolge, die GitLab workspace ähnelt. get {
/// </summary> return ResourceManager.GetString("GenerateModlistAsExcelFeature", resourceCulture);
internal static string GitLabWorkspace { }
}
public static string GenerateModlistAsMarkdownFeature {
get {
return ResourceManager.GetString("GenerateModlistAsMarkdownFeature", resourceCulture);
}
}
public static string GitLabWorkspace {
get { get {
return ResourceManager.GetString("GitLabWorkspace", resourceCulture); return ResourceManager.GetString("GitLabWorkspace", resourceCulture);
} }
} }
/// <summary> public static string LocalFolderWorkspace {
/// Sucht eine lokalisierte Zeichenfolge, die Find update ähnelt. get {
/// </summary> return ResourceManager.GetString("LocalFolderWorkspace", resourceCulture);
internal static string UpdateCollectorFeature { }
}
public static string UpdateCollectorFeature {
get { get {
return ResourceManager.GetString("UpdateCollectorFeature", resourceCulture); return ResourceManager.GetString("UpdateCollectorFeature", resourceCulture);
} }
} }
/// <summary> public static string UpdateDirectLinkFeature {
/// Sucht eine lokalisierte Zeichenfolge, die Update direct link ähnelt.
/// </summary>
internal static string UpdateDirectLinkFeature {
get { get {
return ResourceManager.GetString("UpdateDirectLinkFeature", resourceCulture); return ResourceManager.GetString("UpdateDirectLinkFeature", resourceCulture);
} }
} }
/// <summary> public static string UpdateDirectLinksFeature {
/// Sucht eine lokalisierte Zeichenfolge, die Update direct links ähnelt.
/// </summary>
internal static string UpdateDirectLinksFeature {
get { get {
return ResourceManager.GetString("UpdateDirectLinksFeature", resourceCulture); return ResourceManager.GetString("UpdateDirectLinksFeature", resourceCulture);
} }
} }
/// <summary> public static string UpdatesCollectorFeature {
/// Sucht eine lokalisierte Zeichenfolge, die Find updates ähnelt.
/// </summary>
internal static string UpdatesCollectorFeature {
get { get {
return ResourceManager.GetString("UpdatesCollectorFeature", resourceCulture); return ResourceManager.GetString("UpdatesCollectorFeature", resourceCulture);
} }

View File

@@ -132,8 +132,17 @@
<data name="GenerateChangelogFeature" xml:space="preserve"> <data name="GenerateChangelogFeature" xml:space="preserve">
<value>Generate changelog</value> <value>Generate changelog</value>
</data> </data>
<data name="GenerateModlistAsExcelFeature" xml:space="preserve">
<value>Generate modlist excel file</value>
</data>
<data name="GenerateModlistAsMarkdownFeature" xml:space="preserve">
<value>Generate modlist markdown table</value>
</data>
<data name="GitLabWorkspace" xml:space="preserve"> <data name="GitLabWorkspace" xml:space="preserve">
<value>GitLab workspace</value> <value>GitLab</value>
</data>
<data name="LocalFolderWorkspace" xml:space="preserve">
<value>Local folder</value>
</data> </data>
<data name="UpdateCollectorFeature" xml:space="preserve"> <data name="UpdateCollectorFeature" xml:space="preserve">
<value>Find update</value> <value>Find update</value>

View File

@@ -1,10 +1,9 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// Dieser Code wurde von einem Tool generiert. // This code was generated by a tool.
// Laufzeitversion:4.0.30319.42000
// //
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // Changes to this file may cause incorrect behavior and will be lost if
// der Code erneut generiert wird. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -13,16 +12,16 @@ namespace ModpackUpdater.Apps.Manager.LangRes {
/// <summary> /// <summary>
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. /// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary> /// </summary>
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert // This class was auto-generated by the StronglyTypedResourceBuilder
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. // class via a tool like ResGen or Visual Studio.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen // To add or remove a member, edit your .ResX file then rerun ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. // with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class GeneralLangRes { public class GeneralLangRes {
private static global::System.Resources.ResourceManager resourceMan; private static global::System.Resources.ResourceManager resourceMan;
@@ -33,10 +32,10 @@ namespace ModpackUpdater.Apps.Manager.LangRes {
} }
/// <summary> /// <summary>
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. /// Returns the cached ResourceManager instance used by this class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager { public static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModpackUpdater.Apps.Manager.LangRes.GeneralLangRes", typeof(GeneralLangRes).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModpackUpdater.Apps.Manager.LangRes.GeneralLangRes", typeof(GeneralLangRes).Assembly);
@@ -47,11 +46,11 @@ namespace ModpackUpdater.Apps.Manager.LangRes {
} }
/// <summary> /// <summary>
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle /// Overrides the current thread's CurrentUICulture property for all
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. /// resource lookups using this strongly typed resource class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture { public static global::System.Globalization.CultureInfo Culture {
get { get {
return resourceCulture; return resourceCulture;
} }
@@ -61,20 +60,416 @@ namespace ModpackUpdater.Apps.Manager.LangRes {
} }
/// <summary> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Installation: {0} ähnelt. /// Looks up a localized string similar to Add.
/// </summary> /// </summary>
internal static string Node_Install { public static string Add {
get { get {
return ResourceManager.GetString("Node_Install", resourceCulture); return ResourceManager.GetString("Add", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Sucht eine lokalisierte Zeichenfolge, die Update: {0} ähnelt. /// Looks up a localized string similar to Create update.
/// </summary> /// </summary>
internal static string Node_Update { public static string CreateUpdate {
get { get {
return ResourceManager.GetString("Node_Update", resourceCulture); return ResourceManager.GetString("CreateUpdate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Destination.
/// </summary>
public static string Destination {
get {
return ResourceManager.GetString("Destination", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Destination path.
/// </summary>
public static string DestinationPath {
get {
return ResourceManager.GetString("DestinationPath", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to File location of &quot;install.json&quot;.
/// </summary>
public static string FileLocationOfInstallJson {
get {
return ResourceManager.GetString("FileLocationOfInstallJson", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to File location of &quot;update.json&quot;.
/// </summary>
public static string FileLocationOfUpdateJson {
get {
return ResourceManager.GetString("FileLocationOfUpdateJson", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to General.
/// </summary>
public static string General {
get {
return ResourceManager.GetString("General", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to GitLab Api token.
/// </summary>
public static string GitLabApiToken {
get {
return ResourceManager.GetString("GitLabApiToken", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to GitLab instance url.
/// </summary>
public static string GitLabInstanceUrl {
get {
return ResourceManager.GetString("GitLabInstanceUrl", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Id.
/// </summary>
public static string Id {
get {
return ResourceManager.GetString("Id", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Inherit from.
/// </summary>
public static string InheritFrom {
get {
return ResourceManager.GetString("InheritFrom", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Is directory.
/// </summary>
public static string IsDirectory {
get {
return ResourceManager.GetString("IsDirectory", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Is extra.
/// </summary>
public static string IsExtra {
get {
return ResourceManager.GetString("IsExtra", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Is Zip archive.
/// </summary>
public static string IsZipArchive {
get {
return ResourceManager.GetString("IsZipArchive", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Metadata.
/// </summary>
public static string Metadata {
get {
return ResourceManager.GetString("Metadata", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Modlist for v{0}.
/// </summary>
public static string ModlistForVersionX {
get {
return ResourceManager.GetString("ModlistForVersionX", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Modpack config url.
/// </summary>
public static string ModpackConfigUrl {
get {
return ResourceManager.GetString("ModpackConfigUrl", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Name.
/// </summary>
public static string Name {
get {
return ResourceManager.GetString("Name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to New workspace.
/// </summary>
public static string NewWorkspace {
get {
return ResourceManager.GetString("NewWorkspace", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Public.
/// </summary>
public static string Public {
get {
return ResourceManager.GetString("Public", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Recent workspace.
/// </summary>
public static string RecentWorkspaces {
get {
return ResourceManager.GetString("RecentWorkspaces", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Remove.
/// </summary>
public static string Remove {
get {
return ResourceManager.GetString("Remove", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Remove update.
/// </summary>
public static string RemoveUpdate {
get {
return ResourceManager.GetString("RemoveUpdate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Repository Id.
/// </summary>
public static string RepositoryId {
get {
return ResourceManager.GetString("RepositoryId", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Root folder path.
/// </summary>
public static string RootFolderPath {
get {
return ResourceManager.GetString("RootFolderPath", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Save workspace.
/// </summary>
public static string SaveWorkspace {
get {
return ResourceManager.GetString("SaveWorkspace", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Search.
/// </summary>
public static string Search {
get {
return ResourceManager.GetString("Search", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Select.
/// </summary>
public static string Select {
get {
return ResourceManager.GetString("Select", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Select root folder.
/// </summary>
public static string SelectRootFolder {
get {
return ResourceManager.GetString("SelectRootFolder", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Side.
/// </summary>
public static string Side {
get {
return ResourceManager.GetString("Side", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Source.
/// </summary>
public static string Source {
get {
return ResourceManager.GetString("Source", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Source name.
/// </summary>
public static string SourceName {
get {
return ResourceManager.GetString("SourceName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Source owner.
/// </summary>
public static string SourceOwner {
get {
return ResourceManager.GetString("SourceOwner", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Source path.
/// </summary>
public static string SourcePath {
get {
return ResourceManager.GetString("SourcePath", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Source RegEx.
/// </summary>
public static string SourceRegex {
get {
return ResourceManager.GetString("SourceRegex", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Source type.
/// </summary>
public static string SourceType {
get {
return ResourceManager.GetString("SourceType", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Source URL.
/// </summary>
public static string SourceUrl {
get {
return ResourceManager.GetString("SourceUrl", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to State.
/// </summary>
public static string State {
get {
return ResourceManager.GetString("State", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Tools.
/// </summary>
public static string Tools {
get {
return ResourceManager.GetString("Tools", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Update.
/// </summary>
public static string Update {
get {
return ResourceManager.GetString("Update", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Updates.
/// </summary>
public static string Updates {
get {
return ResourceManager.GetString("Updates", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Update type.
/// </summary>
public static string UpdateType {
get {
return ResourceManager.GetString("UpdateType", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Website.
/// </summary>
public static string Website {
get {
return ResourceManager.GetString("Website", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Workspace.
/// </summary>
public static string Workspace {
get {
return ResourceManager.GetString("Workspace", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Workspace preferences.
/// </summary>
public static string WorkspacePreferences {
get {
return ResourceManager.GetString("WorkspacePreferences", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ZIP archive path.
/// </summary>
public static string ZipArchivePath {
get {
return ResourceManager.GetString("ZipArchivePath", resourceCulture);
} }
} }
} }

View File

@@ -117,10 +117,142 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="Node_Install" xml:space="preserve"> <data name="ModlistForVersionX" xml:space="preserve">
<value>Installation: {0}</value> <value>Modlist for v{0}</value>
</data> </data>
<data name="Node_Update" xml:space="preserve"> <data name="GitLabInstanceUrl" xml:space="preserve">
<value>Update: {0}</value> <value>GitLab instance url</value>
</data>
<data name="GitLabApiToken" xml:space="preserve">
<value>GitLab Api token</value>
</data>
<data name="RepositoryId" xml:space="preserve">
<value>Repository Id</value>
</data>
<data name="RootFolderPath" xml:space="preserve">
<value>Root folder path</value>
</data>
<data name="FileLocationOfInstallJson" xml:space="preserve">
<value>File location of "install.json"</value>
</data>
<data name="FileLocationOfUpdateJson" xml:space="preserve">
<value>File location of "update.json"</value>
</data>
<data name="ModpackConfigUrl" xml:space="preserve">
<value>Modpack config url</value>
</data>
<data name="Remove" xml:space="preserve">
<value>Remove</value>
</data>
<data name="WorkspacePreferences" xml:space="preserve">
<value>Workspace preferences</value>
</data>
<data name="SaveWorkspace" xml:space="preserve">
<value>Save workspace</value>
</data>
<data name="NewWorkspace" xml:space="preserve">
<value>New workspace</value>
</data>
<data name="RecentWorkspaces" xml:space="preserve">
<value>Recent workspace</value>
</data>
<data name="Workspace" xml:space="preserve">
<value>Workspace</value>
</data>
<data name="CreateUpdate" xml:space="preserve">
<value>Create update</value>
</data>
<data name="RemoveUpdate" xml:space="preserve">
<value>Remove update</value>
</data>
<data name="Update" xml:space="preserve">
<value>Update</value>
</data>
<data name="Tools" xml:space="preserve">
<value>Tools</value>
</data>
<data name="Updates" xml:space="preserve">
<value>Updates</value>
</data>
<data name="Add" xml:space="preserve">
<value>Add</value>
</data>
<data name="Public" xml:space="preserve">
<value>Public</value>
</data>
<data name="Id" xml:space="preserve">
<value>Id</value>
</data>
<data name="Side" xml:space="preserve">
<value>Side</value>
</data>
<data name="UpdateType" xml:space="preserve">
<value>Update type</value>
</data>
<data name="SourceType" xml:space="preserve">
<value>Source type</value>
</data>
<data name="DestinationPath" xml:space="preserve">
<value>Destination path</value>
</data>
<data name="State" xml:space="preserve">
<value>State</value>
</data>
<data name="InheritFrom" xml:space="preserve">
<value>Inherit from</value>
</data>
<data name="SourcePath" xml:space="preserve">
<value>Source path</value>
</data>
<data name="IsDirectory" xml:space="preserve">
<value>Is directory</value>
</data>
<data name="General" xml:space="preserve">
<value>General</value>
</data>
<data name="Name" xml:space="preserve">
<value>Name</value>
</data>
<data name="IsExtra" xml:space="preserve">
<value>Is extra</value>
</data>
<data name="Destination" xml:space="preserve">
<value>Destination</value>
</data>
<data name="Source" xml:space="preserve">
<value>Source</value>
</data>
<data name="IsZipArchive" xml:space="preserve">
<value>Is Zip archive</value>
</data>
<data name="SourceOwner" xml:space="preserve">
<value>Source owner</value>
</data>
<data name="SourceName" xml:space="preserve">
<value>Source name</value>
</data>
<data name="SourceRegex" xml:space="preserve">
<value>Source RegEx</value>
</data>
<data name="SourceUrl" xml:space="preserve">
<value>Source URL</value>
</data>
<data name="ZipArchivePath" xml:space="preserve">
<value>ZIP archive path</value>
</data>
<data name="Metadata" xml:space="preserve">
<value>Metadata</value>
</data>
<data name="Website" xml:space="preserve">
<value>Website</value>
</data>
<data name="Select" xml:space="preserve">
<value>Select</value>
</data>
<data name="SelectRootFolder" xml:space="preserve">
<value>Select root folder</value>
</data>
<data name="Search" xml:space="preserve">
<value>Search</value>
</data> </data>
</root> </root>

View File

@@ -1,10 +1,9 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// Dieser Code wurde von einem Tool generiert. // This code was generated by a tool.
// Laufzeitversion:4.0.30319.42000
// //
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // Changes to this file may cause incorrect behavior and will be lost if
// der Code erneut generiert wird. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -12,46 +11,32 @@ namespace ModpackUpdater.Apps.Manager.LangRes {
using System; using System;
/// <summary> [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. [System.Diagnostics.DebuggerNonUserCodeAttribute()]
/// </summary> [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert public class MsgBoxLangRes {
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class MsgBoxLangRes {
private static global::System.Resources.ResourceManager resourceMan; private static System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture; private static System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal MsgBoxLangRes() { internal MsgBoxLangRes() {
} }
/// <summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. public static System.Resources.ResourceManager ResourceManager {
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (object.Equals(null, resourceMan)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModpackUpdater.Apps.Manager.LangRes.MsgBoxLangRes", typeof(MsgBoxLangRes).Assembly); System.Resources.ResourceManager temp = new System.Resources.ResourceManager("ModpackUpdater.Apps.Manager.LangRes.MsgBoxLangRes", typeof(MsgBoxLangRes).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;
} }
} }
/// <summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle public static System.Globalization.CultureInfo Culture {
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get { get {
return resourceCulture; return resourceCulture;
} }
@@ -60,40 +45,64 @@ namespace ModpackUpdater.Apps.Manager.LangRes {
} }
} }
/// <summary> public static string ChangelogCopiedToClipboard {
/// Sucht eine lokalisierte Zeichenfolge, die The changelog for the selected version has been generated and copied to the clipboard. ähnelt.
/// </summary>
internal static string ChangelogCopiedToClipboard {
get { get {
return ResourceManager.GetString("ChangelogCopiedToClipboard", resourceCulture); return ResourceManager.GetString("ChangelogCopiedToClipboard", resourceCulture);
} }
} }
/// <summary> public static string ChangelogCopiedToClipboard_Title {
/// Sucht eine lokalisierte Zeichenfolge, die Changelog generated successfully ähnelt.
/// </summary>
internal static string ChangelogCopiedToClipboard_Title {
get { get {
return ResourceManager.GetString("ChangelogCopiedToClipboard_Title", resourceCulture); return ResourceManager.GetString("ChangelogCopiedToClipboard_Title", resourceCulture);
} }
} }
/// <summary> public static string ModlistCopiedToClipboard {
/// Sucht eine lokalisierte Zeichenfolge, die Are you sure that you want to delete this update? ähnelt. get {
/// </summary> return ResourceManager.GetString("ModlistCopiedToClipboard", resourceCulture);
internal static string RemoveUpdate { }
}
public static string ModlistCopiedToClipboard_Title {
get {
return ResourceManager.GetString("ModlistCopiedToClipboard_Title", resourceCulture);
}
}
public static string ModlistGenerated {
get {
return ResourceManager.GetString("ModlistGenerated", resourceCulture);
}
}
public static string ModlistGenerated_Title {
get {
return ResourceManager.GetString("ModlistGenerated_Title", resourceCulture);
}
}
public static string RemoveUpdate {
get { get {
return ResourceManager.GetString("RemoveUpdate", resourceCulture); return ResourceManager.GetString("RemoveUpdate", resourceCulture);
} }
} }
/// <summary> public static string RemoveUpdate_Title {
/// Sucht eine lokalisierte Zeichenfolge, die Remove update ähnelt.
/// </summary>
internal static string RemoveUpdate_Title {
get { get {
return ResourceManager.GetString("RemoveUpdate_Title", resourceCulture); return ResourceManager.GetString("RemoveUpdate_Title", resourceCulture);
} }
} }
public static string UpdateAvailable {
get {
return ResourceManager.GetString("UpdateAvailable", resourceCulture);
}
}
public static string UpdateAvailable_Title {
get {
return ResourceManager.GetString("UpdateAvailable_Title", resourceCulture);
}
}
} }
} }

View File

@@ -123,10 +123,29 @@
<data name="ChangelogCopiedToClipboard_Title" xml:space="preserve"> <data name="ChangelogCopiedToClipboard_Title" xml:space="preserve">
<value>Changelog generated successfully</value> <value>Changelog generated successfully</value>
</data> </data>
<data name="ModlistCopiedToClipboard" xml:space="preserve">
<value>The modlist has been generated and copied to the clipboard.</value>
</data>
<data name="ModlistCopiedToClipboard_Title" xml:space="preserve">
<value>Modlist generated successfully</value>
</data>
<data name="ModlistGenerated" xml:space="preserve">
<value>The modlist has been generated successfully and saved to the selected location.</value>
</data>
<data name="ModlistGenerated_Title" xml:space="preserve">
<value>Modlist generated successfully</value>
</data>
<data name="RemoveUpdate" xml:space="preserve"> <data name="RemoveUpdate" xml:space="preserve">
<value>Are you sure that you want to delete this update?</value> <value>Are you sure that you want to delete this update?</value>
</data> </data>
<data name="RemoveUpdate_Title" xml:space="preserve"> <data name="RemoveUpdate_Title" xml:space="preserve">
<value>Remove update</value> <value>Remove update</value>
</data> </data>
<data name="UpdateAvailable" xml:space="preserve">
<value>A new version of this program is available! Install now?
If you confirm, the update will be installed automatically within a few seconds.</value>
</data>
<data name="UpdateAvailable_Title" xml:space="preserve">
<value>New program version available</value>
</data>
</root> </root>

View File

@@ -0,0 +1,66 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ModpackUpdater.Apps.Manager.LangRes {
using System;
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class SideLangRes {
private static System.Resources.ResourceManager resourceMan;
private static System.Globalization.CultureInfo resourceCulture;
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal SideLangRes() {
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
internal static System.Resources.ResourceManager ResourceManager {
get {
if (object.Equals(null, resourceMan)) {
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("ModpackUpdater.Apps.Manager.LangRes.SideLangRes", typeof(SideLangRes).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
internal static System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
internal static string Client {
get {
return ResourceManager.GetString("Client", resourceCulture);
}
}
internal static string Server {
get {
return ResourceManager.GetString("Server", resourceCulture);
}
}
internal static string Both {
get {
return ResourceManager.GetString("Both", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Client" xml:space="preserve">
<value>Client</value>
</data>
<data name="Server" xml:space="preserve">
<value>Server</value>
</data>
<data name="Both" xml:space="preserve">
<value>Both</value>
</data>
</root>

View File

@@ -0,0 +1,78 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ModpackUpdater.Apps.Manager.LangRes {
using System;
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class SourceTypeLangRes {
private static System.Resources.ResourceManager resourceMan;
private static System.Globalization.CultureInfo resourceCulture;
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal SourceTypeLangRes() {
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
internal static System.Resources.ResourceManager ResourceManager {
get {
if (object.Equals(null, resourceMan)) {
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("ModpackUpdater.Apps.Manager.LangRes.SourceTypeLangRes", typeof(SourceTypeLangRes).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
internal static System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
internal static string DirectLink {
get {
return ResourceManager.GetString("DirectLink", resourceCulture);
}
}
internal static string GitHub {
get {
return ResourceManager.GetString("GitHub", resourceCulture);
}
}
internal static string GitLab {
get {
return ResourceManager.GetString("GitLab", resourceCulture);
}
}
internal static string CurseForge {
get {
return ResourceManager.GetString("CurseForge", resourceCulture);
}
}
internal static string Modrinth {
get {
return ResourceManager.GetString("Modrinth", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="DirectLink" xml:space="preserve">
<value>Direct link</value>
</data>
<data name="GitHub" xml:space="preserve">
<value>GitHub</value>
</data>
<data name="GitLab" xml:space="preserve">
<value>GitLab</value>
</data>
<data name="CurseForge" xml:space="preserve">
<value>CurseForge</value>
</data>
<data name="Modrinth" xml:space="preserve">
<value>Modrinth</value>
</data>
</root>

View File

@@ -1,10 +1,9 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// Dieser Code wurde von einem Tool generiert. // This code was generated by a tool.
// Laufzeitversion:4.0.30319.42000
// //
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // Changes to this file may cause incorrect behavior and will be lost if
// der Code erneut generiert wird. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -12,46 +11,32 @@ namespace ModpackUpdater.Apps.Manager.LangRes {
using System; using System;
/// <summary> [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. [System.Diagnostics.DebuggerNonUserCodeAttribute()]
/// </summary> [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert public class TitlesLangRes {
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class TitlesLangRes {
private static global::System.Resources.ResourceManager resourceMan; private static System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture; private static System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal TitlesLangRes() { internal TitlesLangRes() {
} }
/// <summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. public static System.Resources.ResourceManager ResourceManager {
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (object.Equals(null, resourceMan)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ModpackUpdater.Apps.Manager.LangRes.TitlesLangRes", typeof(TitlesLangRes).Assembly); System.Resources.ResourceManager temp = new System.Resources.ResourceManager("ModpackUpdater.Apps.Manager.LangRes.TitlesLangRes", typeof(TitlesLangRes).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;
} }
} }
/// <summary> [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle public static System.Globalization.CultureInfo Culture {
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get { get {
return resourceCulture; return resourceCulture;
} }
@@ -60,31 +45,28 @@ namespace ModpackUpdater.Apps.Manager.LangRes {
} }
} }
/// <summary> public static string CreateUpdate {
/// Sucht eine lokalisierte Zeichenfolge, die Create update ähnelt.
/// </summary>
internal static string CreateUpdate {
get { get {
return ResourceManager.GetString("CreateUpdate", resourceCulture); return ResourceManager.GetString("CreateUpdate", resourceCulture);
} }
} }
/// <summary> public static string EditUpdate {
/// Sucht eine lokalisierte Zeichenfolge, die Edit update ähnelt.
/// </summary>
internal static string EditUpdate {
get { get {
return ResourceManager.GetString("EditUpdate", resourceCulture); return ResourceManager.GetString("EditUpdate", resourceCulture);
} }
} }
/// <summary> public static string GitLabRepoWorkspaceEditor {
/// Sucht eine lokalisierte Zeichenfolge, die Setup GitLab workspace ähnelt.
/// </summary>
internal static string GitLabRepoWorkspaceEditor {
get { get {
return ResourceManager.GetString("GitLabRepoWorkspaceEditor", resourceCulture); return ResourceManager.GetString("GitLabRepoWorkspaceEditor", resourceCulture);
} }
} }
public static string LocalFolderWorkspaceEditor {
get {
return ResourceManager.GetString("LocalFolderWorkspaceEditor", resourceCulture);
}
}
} }
} }

View File

@@ -124,6 +124,9 @@
<value>Edit update</value> <value>Edit update</value>
</data> </data>
<data name="GitLabRepoWorkspaceEditor" xml:space="preserve"> <data name="GitLabRepoWorkspaceEditor" xml:space="preserve">
<value>Setup GitLab workspace</value> <value>Setup GitLab</value>
</data>
<data name="LocalFolderWorkspaceEditor" xml:space="preserve">
<value>Setup local folder</value>
</data> </data>
</root> </root>

View File

@@ -0,0 +1,78 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ModpackUpdater.Apps.Manager.LangRes {
using System;
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class UpdateActionTypeLangRes {
private static System.Resources.ResourceManager resourceMan;
private static System.Globalization.CultureInfo resourceCulture;
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal UpdateActionTypeLangRes() {
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
internal static System.Resources.ResourceManager ResourceManager {
get {
if (object.Equals(null, resourceMan)) {
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("ModpackUpdater.Apps.Manager.LangRes.UpdateActionTypeLangRes", typeof(UpdateActionTypeLangRes).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
internal static System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
internal static string None {
get {
return ResourceManager.GetString("None", resourceCulture);
}
}
internal static string Update {
get {
return ResourceManager.GetString("Update", resourceCulture);
}
}
internal static string Delete {
get {
return ResourceManager.GetString("Delete", resourceCulture);
}
}
internal static string Move {
get {
return ResourceManager.GetString("Move", resourceCulture);
}
}
internal static string Copy {
get {
return ResourceManager.GetString("Copy", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="None" xml:space="preserve">
<value>None</value>
</data>
<data name="Update" xml:space="preserve">
<value>Update</value>
</data>
<data name="Delete" xml:space="preserve">
<value>Delete</value>
</data>
<data name="Move" xml:space="preserve">
<value>Move</value>
</data>
<data name="Copy" xml:space="preserve">
<value>Copy</value>
</data>
</root>

View File

@@ -2,24 +2,76 @@
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework> <ApplicationIcon>Assets\app.ico</ApplicationIcon>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
<ApplicationIcon>icons8_Windows_Update.ico</ApplicationIcon>
<AssemblyName>MinecraftModpackUpdateManager</AssemblyName> <AssemblyName>MinecraftModpackUpdateManager</AssemblyName>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="NGitLab" Version="6.55.0" /> <TrimmerRootAssembly Include="MinecraftModpackUpdateManager"/>
<PackageReference Include="Pilz.Configuration" Version="3.1.3" /> <TrimmerRootAssembly Include="ModpackUpdater.Manager"/>
<PackageReference Include="Pilz.Plugins.Advanced" Version="2.10.1" /> <TrimmerRootAssembly Include="ModpackUpdater.Apps"/>
<PackageReference Include="Pilz.Plugins.Advanced.UI" Version="1.7.0" /> <TrimmerRootAssembly Include="ModpackUpdater"/>
<PackageReference Include="Pilz.Plugins.Advanced.UI.Telerik" Version="1.7.0" /> <TrimmerRootAssembly Include="NGitLab"/>
<PackageReference Include="Pilz.UI" Version="2.3.10" /> <TrimmerRootAssembly Include="Pilz.Updating"/>
<PackageReference Include="Pilz.UI.Telerik" Version="2.7.4" /> <TrimmerRootAssembly Include="Pilz.Updating.Client"/>
<PackageReference Include="UI.for.WinForms.Common" Version="2024.3.806" /> <TrimmerRootAssembly Include="Pilz.Configuration"/>
<PackageReference Include="UI.for.WinForms.GridView" Version="2024.3.806" /> <TrimmerRootAssembly Include="ExCSS"/>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Version.cs" />
<Compile Update="LangRes\UpdateActionTypeLangRes.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>UpdateActionTypeLangRes.resx</DependentUpon>
</Compile>
<Compile Update="LangRes\SideLangRes.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>SideLangRes.resx</DependentUpon>
</Compile>
<Compile Update="LangRes\SourceTypeLangRes.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>SourceTypeLangRes.resx</DependentUpon>
</Compile>
<Compile Update="Features\Workspaces\LocalFolder\LocalFolderWorkspaceConfigEditorView.axaml.cs">
<DependentUpon>GitLabRepoWorkspaceConfigEditorView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.3.8" />
<PackageReference Include="DynamicData" Version="9.4.1" />
<PackageReference Include="MessageBox.Avalonia" Version="3.3.0" />
<PackageReference Include="EPPlus" Version="8.2.1" />
<PackageReference Include="NGitLab" Version="11.0.1" />
<PackageReference Include="Pilz" Version="2.6.1" />
<PackageReference Include="Pilz.Configuration" Version="3.2.7" />
<PackageReference Include="Pilz.Cryptography" Version="2.1.2" />
<PackageReference Include="Pilz.Features" Version="2.13.0" />
<PackageReference Include="Pilz.UI" Version="3.1.4" />
<PackageReference Include="Pilz.UI.AvaloniaUI" Version="1.2.18" />
<PackageReference Include="Pilz.UI.AvaloniaUI.Features" Version="1.0.1" />
<PackageReference Include="Avalonia" Version="11.3.8" />
<PackageReference Include="Avalonia.Desktop" Version="11.3.8" />
<PackageReference Include="Avalonia.Svg" Version="11.3.0" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.8" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.8" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics" Version="11.3.8">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
</PackageReference>
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" PrivateAssets='All' />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -58,25 +110,43 @@
<ItemGroup> <ItemGroup>
<EmbeddedResource Update="LangRes\ActionsListLangRes.resx"> <EmbeddedResource Update="LangRes\ActionsListLangRes.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>ActionsListLangRes.Designer.cs</LastGenOutput> <LastGenOutput>ActionsListLangRes.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Update="LangRes\FeatureNamesLangRes.resx"> <EmbeddedResource Update="LangRes\FeatureNamesLangRes.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>FeatureNamesLangRes.Designer.cs</LastGenOutput> <LastGenOutput>FeatureNamesLangRes.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Update="LangRes\GeneralLangRes.resx"> <EmbeddedResource Update="LangRes\GeneralLangRes.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>GeneralLangRes.Designer.cs</LastGenOutput> <LastGenOutput>GeneralLangRes.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Update="LangRes\MsgBoxLangRes.resx"> <EmbeddedResource Update="LangRes\MsgBoxLangRes.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>MsgBoxLangRes.Designer.cs</LastGenOutput> <LastGenOutput>MsgBoxLangRes.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Update="LangRes\TitlesLangRes.resx"> <EmbeddedResource Update="LangRes\TitlesLangRes.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>TitlesLangRes.Designer.cs</LastGenOutput> <LastGenOutput>TitlesLangRes.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Update="LangRes\UpdateActionTypeLangRes.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>UpdateActionTypeLangRes.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="LangRes\SideLangRes.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>SideLangRes.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Update="LangRes\SourceTypeLangRes.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>SourceTypeLangRes.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Reference Include="Pilz">
<HintPath>..\..\..\.nuget\packages\pilz\2.6.1\lib\net8.0\Pilz.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,44 +1,50 @@
using Pilz; using Avalonia;
using Castle.Core.Logging;
using OfficeOpenXml;
using Pilz.Configuration; using Pilz.Configuration;
using Pilz.Plugins.Advanced;
[assembly: AssemblyAppVersion("1.0.0.0")]
namespace ModpackUpdater.Apps.Manager; namespace ModpackUpdater.Apps.Manager;
public static class Program public static class Program
{ {
private static readonly SettingsManager settingsManager; internal static readonly SettingsManager settingsManager;
public static ISettings Settings => settingsManager.Instance; public static ISettings Settings => settingsManager.Instance;
static Program() static Program()
{ {
ExcelPackage.License.SetNonCommercialPersonal("Pilzinsel64");
settingsManager = new(GetSettingsPath(), true); settingsManager = new(GetSettingsPath(), true);
settingsManager.Instance.Logger = new ConsoleLogger("Settings");
} }
/// <summary> /// <summary>
/// The main entry point for the application. /// The main entry point for the application.
/// </summary> /// </summary>
[STAThread] [STAThread]
internal static void Main() internal static void Main(string[] args)
{ {
// To customize application configuration such as set high DPI settings or default font, // To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration. // see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize(); BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
AppGlobals.Initialize(); }
PluginFeatureController.Instance.RegisterAllOwn();
Application.Run(new Ui.MainForm()); public static AppBuilder BuildAvaloniaApp()
{
return AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace();
} }
private static string GetSettingsPath() private static string GetSettingsPath()
{ {
const string AppDataDirectoryName = "MinecraftModpackUpdateManager"; const string AppDataDirectoryName = "MinecraftModpackUpdateManager";
var SettingsFileName = $"Settings.json"; const string settingsFileName = "Settings.json";
var settingsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), AppDataDirectoryName); var settingsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), AppDataDirectoryName);
Directory.CreateDirectory(settingsPath); Directory.CreateDirectory(settingsPath);
settingsPath = Path.Combine(settingsPath, SettingsFileName); settingsPath = Path.Combine(settingsPath, settingsFileName);
return settingsPath; return settingsPath;
} }

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
<Project>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>H:\Applications\Minecraft Modpack Manager</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId>
<TargetFramework>net8.0-windows</TargetFramework>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>

View File

@@ -1,353 +0,0 @@
namespace ModpackUpdater.Apps.Manager.Ui;
partial class MainForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
var tableViewDefinition1 = new Telerik.WinControls.UI.TableViewDefinition();
var resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
radSplitContainer1 = new Telerik.WinControls.UI.RadSplitContainer();
splitPanel1 = new Telerik.WinControls.UI.SplitPanel();
tableLayoutPanel2 = new TableLayoutPanel();
radListControl_Updates = new Telerik.WinControls.UI.RadListControl();
splitPanel2 = new Telerik.WinControls.UI.SplitPanel();
tableLayoutPanel1 = new TableLayoutPanel();
radGridView_Actions = new Telerik.WinControls.UI.RadGridView();
radMenuItem_Workspace = new Telerik.WinControls.UI.RadMenuItem();
radMenuItem_WorkspacePreferences = new Telerik.WinControls.UI.RadMenuItem();
radMenuItem_SaveWorkspace = new Telerik.WinControls.UI.RadMenuItem();
radMenuSeparatorItem1 = new Telerik.WinControls.UI.RadMenuSeparatorItem();
radMenuItem_OpenNewWorkspace = new Telerik.WinControls.UI.RadMenuItem();
radMenuItem_RecentWorkspaces = new Telerik.WinControls.UI.RadMenuItem();
radMenuItem_Tools = new Telerik.WinControls.UI.RadMenuItem();
radMenu1 = new Telerik.WinControls.UI.RadMenu();
radMenuItem_Updates = new Telerik.WinControls.UI.RadMenuItem();
radMenuItem_EditUpdate = new Telerik.WinControls.UI.RadMenuItem();
radMenuSeparatorItem2 = new Telerik.WinControls.UI.RadMenuSeparatorItem();
radMenuItem_CreateUpdate = new Telerik.WinControls.UI.RadMenuItem();
radMenuItem_RemoveUpdate = new Telerik.WinControls.UI.RadMenuItem();
radWaitingBar_Updates = new Telerik.WinControls.UI.RadWaitingBar();
dotsRingWaitingBarIndicatorElement1 = new Telerik.WinControls.UI.DotsRingWaitingBarIndicatorElement();
radWaitingBar_Actions = new Telerik.WinControls.UI.RadWaitingBar();
dotsRingWaitingBarIndicatorElement2 = new Telerik.WinControls.UI.DotsRingWaitingBarIndicatorElement();
((System.ComponentModel.ISupportInitialize)radSplitContainer1).BeginInit();
radSplitContainer1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)splitPanel1).BeginInit();
splitPanel1.SuspendLayout();
tableLayoutPanel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)radListControl_Updates).BeginInit();
((System.ComponentModel.ISupportInitialize)splitPanel2).BeginInit();
splitPanel2.SuspendLayout();
tableLayoutPanel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)radGridView_Actions).BeginInit();
((System.ComponentModel.ISupportInitialize)radGridView_Actions.MasterTemplate).BeginInit();
((System.ComponentModel.ISupportInitialize)radMenu1).BeginInit();
((System.ComponentModel.ISupportInitialize)radWaitingBar_Updates).BeginInit();
((System.ComponentModel.ISupportInitialize)radWaitingBar_Actions).BeginInit();
((System.ComponentModel.ISupportInitialize)this).BeginInit();
SuspendLayout();
//
// radSplitContainer1
//
radSplitContainer1.Controls.Add(splitPanel1);
radSplitContainer1.Controls.Add(splitPanel2);
radSplitContainer1.Dock = DockStyle.Fill;
radSplitContainer1.Location = new Point(0, 28);
radSplitContainer1.Name = "radSplitContainer1";
//
//
//
radSplitContainer1.RootElement.MinSize = new Size(25, 25);
radSplitContainer1.Size = new Size(800, 422);
radSplitContainer1.TabIndex = 0;
radSplitContainer1.TabStop = false;
//
// splitPanel1
//
splitPanel1.Controls.Add(tableLayoutPanel2);
splitPanel1.Location = new Point(0, 0);
splitPanel1.Name = "splitPanel1";
//
//
//
splitPanel1.RootElement.MinSize = new Size(25, 25);
splitPanel1.Size = new Size(200, 422);
splitPanel1.SizeInfo.AutoSizeScale = new SizeF(-0.190954775F, 0F);
splitPanel1.SizeInfo.SizeMode = Telerik.WinControls.UI.Docking.SplitPanelSizeMode.Absolute;
splitPanel1.SizeInfo.SplitterCorrection = new Size(-152, 0);
splitPanel1.TabIndex = 0;
splitPanel1.TabStop = false;
//
// tableLayoutPanel2
//
tableLayoutPanel2.ColumnCount = 1;
tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
tableLayoutPanel2.Controls.Add(radListControl_Updates, 0, 0);
tableLayoutPanel2.Dock = DockStyle.Fill;
tableLayoutPanel2.Location = new Point(0, 0);
tableLayoutPanel2.Name = "tableLayoutPanel2";
tableLayoutPanel2.RowCount = 1;
tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
tableLayoutPanel2.Size = new Size(200, 422);
tableLayoutPanel2.TabIndex = 1;
//
// radListControl_Updates
//
radListControl_Updates.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
radListControl_Updates.ItemHeight = 24;
radListControl_Updates.Location = new Point(3, 3);
radListControl_Updates.Name = "radListControl_Updates";
radListControl_Updates.Size = new Size(194, 416);
radListControl_Updates.TabIndex = 0;
radListControl_Updates.SelectedIndexChanged += RadListControl_Updates_SelectedIndexChanged;
//
// splitPanel2
//
splitPanel2.Controls.Add(tableLayoutPanel1);
splitPanel2.Location = new Point(204, 0);
splitPanel2.Name = "splitPanel2";
//
//
//
splitPanel2.RootElement.MinSize = new Size(25, 25);
splitPanel2.Size = new Size(596, 422);
splitPanel2.SizeInfo.AutoSizeScale = new SizeF(0.190954745F, 0F);
splitPanel2.SizeInfo.SplitterCorrection = new Size(152, 0);
splitPanel2.TabIndex = 1;
splitPanel2.TabStop = false;
//
// tableLayoutPanel1
//
tableLayoutPanel1.ColumnCount = 1;
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
tableLayoutPanel1.Controls.Add(radGridView_Actions, 0, 0);
tableLayoutPanel1.Dock = DockStyle.Fill;
tableLayoutPanel1.Location = new Point(0, 0);
tableLayoutPanel1.Name = "tableLayoutPanel1";
tableLayoutPanel1.RowCount = 1;
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
tableLayoutPanel1.Size = new Size(596, 422);
tableLayoutPanel1.TabIndex = 0;
//
// radGridView_Actions
//
radGridView_Actions.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
radGridView_Actions.Location = new Point(3, 3);
//
//
//
radGridView_Actions.MasterTemplate.AddNewRowPosition = Telerik.WinControls.UI.SystemRowPosition.Bottom;
radGridView_Actions.MasterTemplate.AllowColumnChooser = false;
radGridView_Actions.MasterTemplate.AllowDragToGroup = false;
radGridView_Actions.MasterTemplate.AllowRowResize = false;
radGridView_Actions.MasterTemplate.AllowSearchRow = true;
radGridView_Actions.MasterTemplate.EnableGrouping = false;
radGridView_Actions.MasterTemplate.ViewDefinition = tableViewDefinition1;
radGridView_Actions.Name = "radGridView_Actions";
radGridView_Actions.Size = new Size(590, 416);
radGridView_Actions.TabIndex = 0;
radGridView_Actions.CellFormatting += RadGridView_Actions_CellFormatting;
radGridView_Actions.UserAddedRow += RadGridView_Actions_UserAddedRow;
radGridView_Actions.UserDeletingRow += RadGridView_Actions_UserDeletingRow;
radGridView_Actions.CellValueChanged += RadGridView_Actions_CellValueChanged;
radGridView_Actions.ContextMenuOpening += RadGridView_Actions_ContextMenuOpening;
//
// radMenuItem_Workspace
//
radMenuItem_Workspace.Items.AddRange(new Telerik.WinControls.RadItem[] { radMenuItem_WorkspacePreferences, radMenuItem_SaveWorkspace, radMenuSeparatorItem1, radMenuItem_OpenNewWorkspace, radMenuItem_RecentWorkspaces });
radMenuItem_Workspace.Name = "radMenuItem_Workspace";
radMenuItem_Workspace.Text = "Workspace";
//
// radMenuItem_WorkspacePreferences
//
radMenuItem_WorkspacePreferences.Name = "radMenuItem_WorkspacePreferences";
radMenuItem_WorkspacePreferences.Text = "Preferences";
radMenuItem_WorkspacePreferences.Click += RadMenuItem_WorkspacePreferences_Click;
//
// radMenuItem_SaveWorkspace
//
radMenuItem_SaveWorkspace.Name = "radMenuItem_SaveWorkspace";
radMenuItem_SaveWorkspace.Text = "Save";
radMenuItem_SaveWorkspace.Click += RadMenuItem_SaveWorkspace_Click;
//
// radMenuSeparatorItem1
//
radMenuSeparatorItem1.Name = "radMenuSeparatorItem1";
radMenuSeparatorItem1.Text = "radMenuSeparatorItem1";
radMenuSeparatorItem1.TextAlignment = ContentAlignment.MiddleLeft;
//
// radMenuItem_OpenNewWorkspace
//
radMenuItem_OpenNewWorkspace.Name = "radMenuItem_OpenNewWorkspace";
radMenuItem_OpenNewWorkspace.Text = "Open new workspace";
//
// radMenuItem_RecentWorkspaces
//
radMenuItem_RecentWorkspaces.Name = "radMenuItem_RecentWorkspaces";
radMenuItem_RecentWorkspaces.Text = "Recent workspaces";
//
// radMenuItem_Tools
//
radMenuItem_Tools.Name = "radMenuItem_Tools";
radMenuItem_Tools.Text = "Tools";
//
// radMenu1
//
radMenu1.Items.AddRange(new Telerik.WinControls.RadItem[] { radMenuItem_Workspace, radMenuItem_Updates, radMenuItem_Tools });
radMenu1.Location = new Point(0, 0);
radMenu1.Name = "radMenu1";
radMenu1.Size = new Size(800, 28);
radMenu1.TabIndex = 1;
//
// radMenuItem_Updates
//
radMenuItem_Updates.Items.AddRange(new Telerik.WinControls.RadItem[] { radMenuItem_EditUpdate, radMenuSeparatorItem2, radMenuItem_CreateUpdate, radMenuItem_RemoveUpdate });
radMenuItem_Updates.Name = "radMenuItem_Updates";
radMenuItem_Updates.Text = "Updates";
radMenuItem_Updates.DropDownOpening += RadMenuItem_Updates_DropDownOpening;
//
// radMenuItem_EditUpdate
//
radMenuItem_EditUpdate.Name = "radMenuItem_EditUpdate";
radMenuItem_EditUpdate.Text = "Edit";
radMenuItem_EditUpdate.Click += RadMenuItem_EditUpdate_Click;
//
// radMenuSeparatorItem2
//
radMenuSeparatorItem2.Name = "radMenuSeparatorItem2";
radMenuSeparatorItem2.Text = "radMenuSeparatorItem2";
radMenuSeparatorItem2.TextAlignment = ContentAlignment.MiddleLeft;
//
// radMenuItem_CreateUpdate
//
radMenuItem_CreateUpdate.Name = "radMenuItem_CreateUpdate";
radMenuItem_CreateUpdate.Text = "Create";
radMenuItem_CreateUpdate.Click += RadMenuItem_CreateUpdate_Click;
//
// radMenuItem_RemoveUpdate
//
radMenuItem_RemoveUpdate.Name = "radMenuItem_RemoveUpdate";
radMenuItem_RemoveUpdate.Text = "Remove";
radMenuItem_RemoveUpdate.Click += RadMenuItem_RemoveUpdate_Click;
//
// radWaitingBar_Updates
//
radWaitingBar_Updates.AssociatedControl = radListControl_Updates;
radWaitingBar_Updates.Location = new Point(0, 78);
radWaitingBar_Updates.Name = "radWaitingBar_Updates";
radWaitingBar_Updates.Size = new Size(70, 70);
radWaitingBar_Updates.TabIndex = 2;
radWaitingBar_Updates.Text = "radWaitingBar1";
radWaitingBar_Updates.WaitingIndicators.Add(dotsRingWaitingBarIndicatorElement1);
radWaitingBar_Updates.WaitingIndicatorSize = new Size(100, 14);
radWaitingBar_Updates.WaitingSpeed = 50;
radWaitingBar_Updates.WaitingStyle = Telerik.WinControls.Enumerations.WaitingBarStyles.DotsRing;
//
// dotsRingWaitingBarIndicatorElement1
//
dotsRingWaitingBarIndicatorElement1.Name = "dotsRingWaitingBarIndicatorElement1";
//
// radWaitingBar_Actions
//
radWaitingBar_Actions.AssociatedControl = radGridView_Actions;
radWaitingBar_Actions.ForeColor = Color.Black;
radWaitingBar_Actions.Location = new Point(0, 145);
radWaitingBar_Actions.Name = "radWaitingBar_Actions";
radWaitingBar_Actions.Size = new Size(70, 70);
radWaitingBar_Actions.TabIndex = 3;
radWaitingBar_Actions.WaitingIndicators.Add(dotsRingWaitingBarIndicatorElement2);
radWaitingBar_Actions.WaitingIndicatorSize = new Size(100, 14);
radWaitingBar_Actions.WaitingSpeed = 50;
radWaitingBar_Actions.WaitingStyle = Telerik.WinControls.Enumerations.WaitingBarStyles.DotsRing;
//
// dotsRingWaitingBarIndicatorElement2
//
dotsRingWaitingBarIndicatorElement2.Name = "dotsRingWaitingBarIndicatorElement2";
//
// MainForm
//
AutoScaleBaseSize = new Size(7, 15);
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(800, 450);
Controls.Add(radWaitingBar_Actions);
Controls.Add(radWaitingBar_Updates);
Controls.Add(radSplitContainer1);
Controls.Add(radMenu1);
Icon = (Icon)resources.GetObject("$this.Icon");
Name = "MainForm";
StartPosition = FormStartPosition.CenterScreen;
Text = "Minecraft Modpack Updates Manager";
WindowState = FormWindowState.Maximized;
Load += Form1_Load;
((System.ComponentModel.ISupportInitialize)radSplitContainer1).EndInit();
radSplitContainer1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)splitPanel1).EndInit();
splitPanel1.ResumeLayout(false);
tableLayoutPanel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)radListControl_Updates).EndInit();
((System.ComponentModel.ISupportInitialize)splitPanel2).EndInit();
splitPanel2.ResumeLayout(false);
tableLayoutPanel1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)radGridView_Actions.MasterTemplate).EndInit();
((System.ComponentModel.ISupportInitialize)radGridView_Actions).EndInit();
((System.ComponentModel.ISupportInitialize)radMenu1).EndInit();
((System.ComponentModel.ISupportInitialize)radWaitingBar_Updates).EndInit();
((System.ComponentModel.ISupportInitialize)radWaitingBar_Actions).EndInit();
((System.ComponentModel.ISupportInitialize)this).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private Telerik.WinControls.UI.RadSplitContainer radSplitContainer1;
private Telerik.WinControls.UI.SplitPanel splitPanel1;
private Telerik.WinControls.UI.SplitPanel splitPanel2;
private Telerik.WinControls.UI.RadMenu radMenu1;
private Telerik.WinControls.UI.RadMenuItem radMenuItem_Workspace;
private Telerik.WinControls.UI.RadMenuItem radMenuItem_WorkspacePreferences;
private Telerik.WinControls.UI.RadMenuItem radMenuItem_Tools;
private TableLayoutPanel tableLayoutPanel2;
private TableLayoutPanel tableLayoutPanel1;
private Telerik.WinControls.UI.RadGridView radGridView_Actions;
private Telerik.WinControls.UI.RadMenuSeparatorItem radMenuSeparatorItem1;
private Telerik.WinControls.UI.RadMenuItem radMenuItem_OpenNewWorkspace;
private Telerik.WinControls.UI.RadMenuItem radMenuItem_RecentWorkspaces;
private Telerik.WinControls.UI.RadMenuItem radMenuItem_SaveWorkspace;
private Telerik.WinControls.UI.RadWaitingBar radWaitingBar_Updates;
private Telerik.WinControls.UI.DotsRingWaitingBarIndicatorElement dotsRingWaitingBarIndicatorElement1;
private Telerik.WinControls.UI.RadWaitingBar radWaitingBar_Actions;
private Telerik.WinControls.UI.DotsRingWaitingBarIndicatorElement dotsRingWaitingBarIndicatorElement2;
private Telerik.WinControls.UI.RadListControl radListControl_Updates;
private Telerik.WinControls.UI.RadMenuItem radMenuItem_Updates;
private Telerik.WinControls.UI.RadMenuItem radMenuItem_EditUpdate;
private Telerik.WinControls.UI.RadMenuSeparatorItem radMenuSeparatorItem2;
private Telerik.WinControls.UI.RadMenuItem radMenuItem_CreateUpdate;
private Telerik.WinControls.UI.RadMenuItem radMenuItem_RemoveUpdate;
}

View File

@@ -1,599 +0,0 @@
using ModpackUpdater.Apps.Manager.Api.Model;
using ModpackUpdater.Apps.Manager.Api.Plugins.Features;
using ModpackUpdater.Apps.Manager.Api.Plugins.Params;
using ModpackUpdater.Apps.Manager.LangRes;
using ModpackUpdater.Apps.Manager.Settings;
using Pilz.Plugins.Advanced;
using Pilz.Plugins.Advanced.UI.Telerik;
using Pilz.UI.Extensions;
using Pilz.UI.Symbols;
using Pilz.UI.Telerik.Dialogs;
using Pilz.UI.Telerik.Extensions.Extensions;
using Telerik.WinControls;
using Telerik.WinControls.UI;
namespace ModpackUpdater.Apps.Manager.Ui;
public partial class MainForm : RadForm, IMainApi
{
private WorkspaceTag? wsInfo;
Form IMainApi.MainWindow => this;
IWorkspace? IMainApi.CurWorkspace => wsInfo?.Workspace;
public IActionSetInfos? CurActionSet => radListControl_Updates.SelectedValue as IActionSetInfos;
private record RecentFilesItemTag(WorkspaceConfig Config, WorkspaceFeature Feature);
private record WorkspaceTag(IWorkspace Workspace, WorkspaceFeature Feature);
public MainForm()
{
InitializeComponent();
radMenuItem_Workspace.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.workspace, SymbolSize.Small);
radMenuItem_WorkspacePreferences.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.settings, SymbolSize.Small);
radMenuItem_SaveWorkspace.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.save, SymbolSize.Small);
radMenuItem_OpenNewWorkspace.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.new_window, SymbolSize.Small);
radMenuItem_RecentWorkspaces.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.time_machine, SymbolSize.Small);
radMenuItem_Updates.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.update_done, SymbolSize.Small);
radMenuItem_EditUpdate.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.edit, SymbolSize.Small);
radMenuItem_CreateUpdate.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.add, SymbolSize.Small);
radMenuItem_RemoveUpdate.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.remove, SymbolSize.Small);
radMenuItem_Tools.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.tools, SymbolSize.Small);
radMenuItem_SaveWorkspace.Shortcuts.Add(new(Keys.Control, Keys.S));
PluginFeatureController.Instance.Features.Get(FeatureTypes.Workspace).InsertItemsTo(radMenuItem_OpenNewWorkspace.Items, customClickHandler: RadMenuItem_OpenNewWorkspace_Click);
PluginFeatureController.Instance.Functions.Get(FeatureTypes.Tools).InsertItemsTo(radMenuItem_Tools.Items, customClickHandler: RadMenuItem_ToolsItem_Click);
}
private void LoadRecentWorkspaces()
{
var settings = Program.Settings.Get<WorkspaceSettings>();
radMenuItem_RecentWorkspaces.Items.Clear();
foreach (var config in settings.Workspaces.ToArray())
{
if (PluginFeatureController.Instance.Features.Get(FeatureTypes.Workspace).OfType<WorkspaceFeature>().FirstOrDefault(n => n.Identifier == config.ProviderId) is not WorkspaceFeature feature)
{
settings.Workspaces.Remove(config);
continue;
}
var item = new RadMenuItem
{
Text = config.DisplayText,
Tag = new RecentFilesItemTag(config, feature),
SvgImage = feature.Icon as RadSvgImage,
};
item.Click += RadMenuItem_OpenRecentWorkspace_Click;
radMenuItem_RecentWorkspaces.Items.Add(item);
}
if (radMenuItem_RecentWorkspaces.Items.Any())
radMenuItem_RecentWorkspaces.Visibility = ElementVisibility.Visible;
else
radMenuItem_RecentWorkspaces.Visibility = ElementVisibility.Collapsed;
}
private void AddToRecentFiles(IWorkspace workspace)
{
var settings = Program.Settings.Get<WorkspaceSettings>();
settings.Workspaces.Remove(workspace.Config);
settings.Workspaces.Insert(0, workspace.Config);
while (settings.Workspaces.Count > 20)
settings.Workspaces.RemoveAt(20);
}
private async Task LoadNewWorkspace(IWorkspace? workspace, WorkspaceFeature feature)
{
if (workspace is null)
return;
if (workspace != wsInfo?.Workspace)
wsInfo = new(workspace, feature);
AddToRecentFiles(workspace);
Invoke(LoadRecentWorkspaces);
radWaitingBar_Updates.StartWaiting();
if (!await workspace.Load())
{
radWaitingBar_Updates.StopWaiting();
return;
}
Invoke(LoadWorkspace);
}
private void LoadWorkspace()
{
if (wsInfo?.Workspace.Config is null || wsInfo.Workspace.InstallInfos is null || wsInfo.Workspace.UpdateInfos is null)
return;
radWaitingBar_Updates.StartWaiting();
Text = wsInfo.Workspace.Config.DisplayText;
radListControl_Updates.BeginUpdate();
radListControl_Updates.Items.Clear();
AddUpdateItem(wsInfo.Workspace.InstallInfos);
wsInfo.Workspace.UpdateInfos.Updates.ForEach(n => AddUpdateItem(n));
radListControl_Updates.EndUpdate();
radWaitingBar_Updates.StopWaiting();
}
private RadListDataItem AddUpdateItem(IActionSetInfos infos)
{
var item = CreateUpdateItem(infos);
radListControl_Updates.Items.Add(item);
return item;
}
private RadListDataItem InsertUpdateItem(IActionSetInfos infos)
{
var item = CreateUpdateItem(infos);
radListControl_Updates.Items.Insert(Math.Min(1, radListControl_Updates.Items.Count), item);
return item;
}
private RadListDataItem CreateUpdateItem(IActionSetInfos infos)
{
var item = new RadListDataItem();
UpdateUpdateItem(item, infos);
return item;
}
private void UpdateUpdateItem(RadListDataItem item)
{
if (item.Value is IActionSetInfos infos)
UpdateUpdateItem(item, infos);
}
private void UpdateUpdateItem(RadListDataItem item, IActionSetInfos infos)
{
if (item.Value != infos)
item.Value = infos;
if (infos is UpdateInfo)
item.Text = string.Format(GeneralLangRes.Node_Update, infos.Version?.ToString() ?? "?");
else if (infos is InstallInfos)
item.Text = string.Format(GeneralLangRes.Node_Install, infos.Version?.ToString() ?? "?");
else
item.Text = infos.Version.ToString();
item.SvgImage = AppGlobals.Symbols.GetSvgImage(infos.IsPublic ? AppSymbols.eye : AppSymbols.invisible, SymbolSize.Small);
}
public void UpdateItem(IActionSetInfos actionSetInfos)
{
RadListDataItem? item = null;
foreach (var iitem in radListControl_Updates.Items)
{
if (item == null && iitem.Value == actionSetInfos)
item = iitem;
}
if (item == null)
InsertUpdateItem(actionSetInfos);
else if (wsInfo?.Workspace.UpdateInfos != null && !wsInfo.Workspace.UpdateInfos.Updates.Contains(actionSetInfos))
radListControl_Updates.Items.Remove(item);
else
UpdateUpdateItem(item);
}
public void UpdateItem(InstallAction action)
{
foreach (var row in radGridView_Actions.Rows)
{
if (row.Tag == action)
UpdateActionRow(row);
}
}
private void LoadActionSet(IActionSetInfos infos)
{
radGridView_Actions.BeginUpdate();
radGridView_Actions.Rows.Clear();
radGridView_Actions.Columns.Clear();
// Add columns
radGridView_Actions.Columns.AddRange([
new GridViewTextBoxColumn
{
Name = "id",
HeaderText = ActionsListLangRes.Col_Id,
Width = 150,
IsVisible = infos is not UpdateInfo,
IsPinned = true,
},
new GridViewTextBoxColumn
{
Name = "name",
HeaderText = ActionsListLangRes.Col_Name,
Width = 150,
IsVisible = infos is not UpdateInfo,
},
new GridViewTextBoxColumn
{
Name = "inherit",
HeaderText = ActionsListLangRes.Col_InheritFrom,
Width = 150,
IsVisible = infos is UpdateInfo,
IsPinned = true,
},
new GridViewComboBoxColumn
{
Name = "utype",
HeaderText = ActionsListLangRes.Col_UpdateType,
Width = 150,
DataSource = Enum.GetValues<UpdateActionType>(),
IsVisible = infos is UpdateInfo,
},
new GridViewComboBoxColumn
{
Name = "side",
HeaderText = ActionsListLangRes.Col_Side,
Width = 100,
DataSource = Enum.GetValues<Side>(),
},
new GridViewCheckBoxColumn
{
Name = "isextra",
HeaderText = ActionsListLangRes.Col_IsExtra,
Width = 50,
},
new GridViewCheckBoxColumn
{
Name = "iszip",
HeaderText = ActionsListLangRes.Col_IsZip,
Width = 50,
},
new GridViewCheckBoxColumn
{
Name = "isdir",
HeaderText = ActionsListLangRes.Col_IsDir,
Width = 50,
IsVisible = infos is UpdateInfo,
},
new GridViewComboBoxColumn
{
Name = "srctype",
HeaderText = ActionsListLangRes.Col_SrcType,
Width = 150,
DataSource = Enum.GetValues<SourceType>(),
},
new GridViewTextBoxColumn
{
Name = "srcowner",
HeaderText = ActionsListLangRes.Col_SrcOwner,
Width = 150,
},
new GridViewTextBoxColumn
{
Name = "srcname",
HeaderText = ActionsListLangRes.Col_SrcName,
Width = 150,
},
new GridViewTextBoxColumn
{
Name = "srcregex",
HeaderText = ActionsListLangRes.Col_SrcRegEx,
Width = 200,
},
new GridViewTextBoxColumn
{
Name = "srctag",
HeaderText = ActionsListLangRes.Col_SrcTag,
Width = 150,
},
new GridViewTextBoxColumn
{
Name = "srcurl",
HeaderText = ActionsListLangRes.Col_SrcUrl,
Width = 350,
},
new GridViewTextBoxColumn
{
Name = "zippath",
HeaderText = ActionsListLangRes.Col_ZipPath,
Width = 200,
},
new GridViewTextBoxColumn
{
Name = "srcpath",
HeaderText = ActionsListLangRes.Col_SrcPath,
Width = 250,
IsVisible = infos is UpdateInfo,
},
new GridViewTextBoxColumn
{
Name = "destpath",
HeaderText = ActionsListLangRes.Col_DestPath,
Width = 250,
},
new GridViewTextBoxColumn
{
Name = "website",
HeaderText = ActionsListLangRes.Col_Website,
Width = 350,
},
]);
// Add rows
foreach (var action in infos.Actions)
{
var row = radGridView_Actions.Rows.AddNew();
row.Tag = action;
UpdateActionRow(row);
}
radGridView_Actions.EndUpdate();
}
private void UpdateActionRow(GridViewRowInfo row)
{
if (row.Tag is not InstallAction action)
return;
row.Cells["id"].Value = action.Id;
row.Cells["name"].Value = action.Name;
row.Cells["iszip"].Value = action.IsZip;
row.Cells["zippath"].Value = action.ZipPath;
row.Cells["destpath"].Value = action.DestPath;
row.Cells["srcurl"].Value = action.SourceUrl;
row.Cells["srctype"].Value = action.SourceType;
row.Cells["srcowner"].Value = action.SourceOwner;
row.Cells["srcname"].Value = action.SourceName;
row.Cells["srcregex"].Value = action.SourceRegex;
row.Cells["srctag"].Value = action.SourceTag;
row.Cells["side"].Value = action.Side;
row.Cells["isextra"].Value = action.IsExtra;
row.Cells["website"].Value = action.Website;
if (action is not UpdateAction uaction)
return;
row.Cells["inherit"].Value = uaction.InheritFrom; // TODO: Find inherit action and put it in here!
row.Cells["utype"].Value = uaction.Type;
row.Cells["srcpath"].Value = uaction.SrcPath;
row.Cells["isdir"].Value = uaction.IsDirectory;
}
private void Form1_Load(object sender, EventArgs e)
{
LoadRecentWorkspaces();
}
private async void RadMenuItem_OpenNewWorkspace_Click(object? sender, EventArgs e)
{
if (sender is RadMenuItem item && item.Tag is WorkspaceFeature feature)
{
var ws = wsInfo?.Workspace;
if (feature.Configure(ref ws))
await LoadNewWorkspace(ws, feature);
}
}
private async void RadMenuItem_OpenRecentWorkspace_Click(object? sender, EventArgs e)
{
if (sender is RadMenuItem item && item.Tag is RecentFilesItemTag tag && tag.Feature.CreateFromConfig(tag.Config) is IWorkspace workspace)
await LoadNewWorkspace(workspace, tag.Feature);
}
private async void RadMenuItem_WorkspacePreferences_Click(object sender, EventArgs e)
{
if (wsInfo != null)
{
var ws = wsInfo.Workspace;
if (wsInfo.Feature.Configure(ref ws))
await LoadNewWorkspace(ws, wsInfo.Feature);
}
}
private void RadMenuItem_SaveWorkspace_Click(object sender, EventArgs e)
{
wsInfo?.Workspace.Save();
}
private void RadMenuItem_ToolsItem_Click(object? sender, EventArgs e)
{
if (sender is RadMenuItem item && item.Tag is PluginFunction func)
func.Execute(new MainApiParameters(this));
}
private void RadListControl_Updates_SelectedIndexChanged(object sender, Telerik.WinControls.UI.Data.PositionChangedEventArgs e)
{
if (radListControl_Updates.Items.ElementAtOrDefault(e.Position)?.Value is IActionSetInfos infos)
LoadActionSet(infos);
}
private void RadGridView_Actions_CellFormatting(object sender, CellFormattingEventArgs e)
{
//var cellElement = e.CellElement;
//var cellInfo = e.Row.Cells[e.Column.Name];
//if (e.Column.Name == "srctype" && cellInfo?.Value is string sourceTypeStr && Enum.Parse<SourceType>(sourceTypeStr) is SourceType sourceType)
//{
// cellElement.SvgImage = sourceType switch
// {
// SourceType.DirectLink => AppGlobals.Symbols.GetSvgImage(AppSymbols.link, SymbolSize.Small),
// SourceType.GitHub => AppGlobals.Symbols.GetSvgImage(AppSymbols.github, SymbolSize.Small),
// _ => null,
// };
// cellElement.DrawImage = cellElement.SvgImage != null;
// cellElement.TextImageRelation = TextImageRelation.ImageBeforeText;
// cellElement.ImageAlignment = ContentAlignment.MiddleLeft;
//}
//else
//{
// cellElement.ResetValue(LightVisualElement.SvgImageProperty, ValueResetFlags.Local);
// cellElement.ResetValue(LightVisualElement.DrawImageProperty, ValueResetFlags.Local);
// cellElement.ResetValue(LightVisualElement.TextImageRelationProperty, ValueResetFlags.Local);
// cellElement.ResetValue(LightVisualElement.ImageAlignmentProperty, ValueResetFlags.Local);
//}
}
private void RadGridView_Actions_CellValueChanged(object sender, GridViewCellEventArgs e)
{
if (e.Row?.Tag is not InstallAction action)
return;
var uaction = action as UpdateAction;
var newValue = e.Row.Cells[e.Column.Name].Value;
var colName = e.Column.Name;
if (newValue is bool valueBool)
{
switch (colName)
{
case "iszip":
action.IsZip = valueBool;
break;
case "isextra":
action.IsExtra = valueBool;
break;
case "isdir":
if (uaction is not null)
uaction.IsDirectory = valueBool;
break;
}
}
else
{
var valueStr = newValue as string ?? string.Empty;
var valueNullStr = valueStr.Nullify();
switch (colName)
{
case "id":
action.Id = valueNullStr;
break;
case "name":
action.Name = valueNullStr;
break;
case "zippath":
action.ZipPath = valueNullStr;
break;
case "destpath":
action.DestPath = valueNullStr;
break;
case "srcurl":
action.SourceUrl = valueNullStr;
break;
case "srctype":
action.SourceType = Enum.Parse<SourceType>(valueStr);
break;
case "srcowner":
action.SourceOwner = valueNullStr;
break;
case "srcname":
action.SourceName = valueNullStr;
break;
case "srcregex":
action.SourceRegex = valueNullStr;
break;
case "srctag":
action.SourceTag = valueNullStr;
break;
case "website":
action.Website = valueNullStr;
break;
case "side":
action.Side = Enum.Parse<Side>(valueStr);
break;
case "inherit":
if (uaction is not null)
uaction.InheritFrom = valueNullStr;
break;
case "utype":
if (uaction is not null)
uaction.Type = Enum.Parse<UpdateActionType>(valueStr);
break;
case "srcpath":
if (uaction is not null)
uaction.SrcPath = valueNullStr;
break;
}
}
}
private void RadMenuItem_Updates_DropDownOpening(object sender, System.ComponentModel.CancelEventArgs e)
{
radMenuItem_EditUpdate.Enabled = radListControl_Updates.SelectedItem?.Value is IActionSetInfos;
radMenuItem_RemoveUpdate.Enabled = radListControl_Updates.SelectedItem?.Value is UpdateInfo;
}
private void RadMenuItem_EditUpdate_Click(object sender, EventArgs e)
{
if (radListControl_Updates.SelectedItem?.Value is IActionSetInfos infos
&& RadDialogBase.ShowDialog(new UpdatePropertiesEditorFlyout(infos), TitlesLangRes.EditUpdate, AppGlobals.Symbols.GetSvgImage(AppSymbols.edit, SymbolSize.Small)).IsValid())
UpdateUpdateItem(radListControl_Updates.SelectedItem);
}
private void RadMenuItem_CreateUpdate_Click(object sender, EventArgs e)
{
var infos = new UpdateInfo();
if (wsInfo?.Workspace.UpdateInfos is not null
&& RadDialogBase.ShowDialog(new UpdatePropertiesEditorFlyout(infos), TitlesLangRes.EditUpdate, AppGlobals.Symbols.GetSvgImage(AppSymbols.edit, SymbolSize.Small)).IsValid())
{
wsInfo.Workspace.UpdateInfos.Updates.Insert(0, infos);
InsertUpdateItem(infos);
}
}
private void RadMenuItem_RemoveUpdate_Click(object sender, EventArgs e)
{
if (radListControl_Updates.SelectedItem?.Value is UpdateInfo infos && wsInfo?.Workspace.UpdateInfos is not null
&& RadMessageBox.Show(MsgBoxLangRes.RemoveUpdate, MsgBoxLangRes.RemoveUpdate_Title, MessageBoxButtons.YesNo, RadMessageIcon.Exclamation).IsYes())
{
wsInfo.Workspace.UpdateInfos.Updates.Remove(infos);
radListControl_Updates.Items.Remove(radListControl_Updates.SelectedItem);
}
}
private void RadGridView_Actions_UserAddedRow(object sender, GridViewRowEventArgs e)
{
foreach (var row in e.Rows)
{
if (CurActionSet is UpdateInfo uinfo)
{
var action = new UpdateAction();
// ...
uinfo.Actions.Add(action);
}
if (CurActionSet is InstallInfos iinfo)
{
var action = new InstallAction();
// ...
iinfo.Actions.Add(action);
}
}
}
private void RadGridView_Actions_UserDeletingRow(object sender, GridViewRowCancelEventArgs e)
{
foreach (var row in e.Rows)
{
if (row.Tag is UpdateAction uaction && CurActionSet is UpdateInfo uinfo)
uinfo.Actions.Remove(uaction);
else if (row.Tag is InstallAction iaction && CurActionSet is InstallInfos iinfo)
iinfo.Actions.Remove(iaction);
}
}
private void RadGridView_Actions_ContextMenuOpening(object sender, ContextMenuOpeningEventArgs e)
{
PluginFeatureController.Instance.Functions.Get(FeatureTypes.ActionsContextMenu).InsertItemsTo(e.ContextMenu.Items, customClickHandler: RadMenuItem_ToolsItem_Click);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,474 @@
<Window
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ModpackUpdater.Apps.Manager.Ui"
xmlns:pilz="https://git.pilzinsel64.de/pilz-framework/pilz"
xmlns:symbols="clr-namespace:Pilz.UI.Symbols;assembly=Pilz.UI"
xmlns:mainWindow="clr-namespace:ModpackUpdater.Apps.Manager.Ui.Models.MainWindow"
xmlns:langRes="clr-namespace:ModpackUpdater.Apps.Manager.LangRes"
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="450"
x:Class="ModpackUpdater.Apps.Manager.Ui.MainWindow"
Title="Minecraft Modpack Manager"
WindowState="Maximized"
Loaded="Window_OnLoaded"
Closed="Window_OnClosed"
KeyDown="Window_OnKeyDown">
<Grid
x:Name="GridMain"
x:DataType="mainWindow:MainWindowViewModel"
RowDefinitions="Auto,*"
ColumnDefinitions="Auto,*,500"
RowSpacing="6"
ColumnSpacing="6"
Margin="3">
<!-- StackPanel: Workspace -->
<StackPanel
Grid.Column="0"
Grid.Row="0"
Orientation="Horizontal">
<!-- Button: Workspace -->
<pilz:ImageButton
x:Name="ButtonWorkspace"
Text="{x:Static langRes:GeneralLangRes.Workspace}"
Background="Transparent">
<pilz:ImageButton.Flyout>
<MenuFlyout>
<MenuFlyout.Items>
<MenuItem x:Name="MenuItemWorkspacePreferences" Header="{x:Static langRes:GeneralLangRes.WorkspacePreferences}" Click="MenuItemWorkspacePreferences_OnClick"/>
<MenuItem x:Name="MenuItemSaveWorkspace" Header="{x:Static langRes:GeneralLangRes.SaveWorkspace}" HotKey="Ctrl+S" Click="MenuItemSaveWorkspace_OnClick"/>
<Separator/>
<MenuItem x:Name="MenuItemNewWorkspace" Header="{x:Static langRes:GeneralLangRes.NewWorkspace}"/>
<Separator/>
<MenuItem x:Name="MenuItemRecentWorkspaces" Header="{x:Static langRes:GeneralLangRes.RecentWorkspaces}"/>
</MenuFlyout.Items>
</MenuFlyout>
</pilz:ImageButton.Flyout>
</pilz:ImageButton>
<!-- Button: Update -->
<pilz:ImageButton
x:Name="ButtonUpdate"
Text="{x:Static langRes:GeneralLangRes.Update}"
Background="Transparent">
<pilz:ImageButton.Flyout>
<MenuFlyout>
<MenuFlyout.Items>
<MenuItem x:Name="MenuItemCreateUpdate" Header="{x:Static langRes:GeneralLangRes.CreateUpdate}" Click="MenuItemCreateUpdate_OnClick"/>
<MenuItem x:Name="MenuItemRemoveUpdate" Header="{x:Static langRes:GeneralLangRes.RemoveUpdate}" Click="MenuItemRemoveUpdate_OnClick"/>
</MenuFlyout.Items>
</MenuFlyout>
</pilz:ImageButton.Flyout>
</pilz:ImageButton>
<!-- Button: Tools -->
<pilz:ImageButton
x:Name="ButtonTools"
Text="{x:Static langRes:GeneralLangRes.Tools}"
Background="Transparent"/>
</StackPanel>
<!-- TreeView: Workspace -->
<ScrollViewer
Grid.Column="0"
Grid.Row="1"
VerticalScrollBarVisibility="Auto">
<StackPanel>
<TreeView
ItemsSource="{Binding CurrentTreeNodes}"
SelectedItem="{Binding SelectedTreeNode}">
<TreeView.ItemTemplate>
<TreeDataTemplate
ItemsSource="{Binding Nodes}">
<StackPanel Orientation="Horizontal" Spacing="6">
<Image
Source="{Binding Image}"
Width="{x:Static symbols:SymbolGlobals.DefaultImageSmallSize}"/>
<TextBlock Text="{Binding DisplayText}"/>
</StackPanel>
</TreeDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
</ScrollViewer>
<!-- Panel: List header -->
<StackPanel
Grid.Column="1"
Grid.Row="0"
Spacing="6"
Orientation="Horizontal"
VerticalAlignment="Center">
<!-- Panel: Menu list -->
<StackPanel
Orientation="Horizontal">
<!-- Button: Add action -->
<pilz:ImageButton
x:Name="ButtonAddAction"
Text="{x:Static langRes:GeneralLangRes.Add}"
ImageSource="{x:Static local:MainWindow.ButtonImageAddAction}"
Background="Transparent"
Click="ButtonAddAction_OnClick"/>
<!-- Button: Remove action -->
<pilz:ImageButton
x:Name="ButtonRemoveAction"
Text="{x:Static langRes:GeneralLangRes.Remove}"
ImageSource="{x:Static local:MainWindow.ButtonImageRemoveAction}"
Background="Transparent"
Click="ButtonRemoveAction_OnClick"/>
</StackPanel>
<!-- TextBox: Search -->
<TextBox
Width="200"
Watermark="{x:Static langRes:GeneralLangRes.Search}"
Text="{Binding CurrentGridRows.SearchText}"/>
<!-- Panel: Menu -->
<ContentControl
Content="{Binding SelectedTreeNode}"
>
<ContentControl.DataTemplates>
<DataTemplate
DataType="mainWindow:ActionSetTreeNode">
<StackPanel
Orientation="Horizontal"
Spacing="6">
<!-- TextBox: Version -->
<TextBox
Width="100"
Text="{Binding Version}"/>
<!-- CheckBox: Is public -->
<CheckBox
Content="{x:Static langRes:GeneralLangRes.Public}"
IsChecked="{Binding IsPublic}"/>
</StackPanel>
</DataTemplate>
<DataTemplate
DataType="mainWindow:MainWindowTreeNode"/>
</ContentControl.DataTemplates>
</ContentControl>
<!-- ProgressBar: Status -->
<ProgressBar
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
Maximum="{Binding Progress.MaxValue}"
Value="{Binding Progress.Value}"
ShowProgressText="{Binding Progress.ShowText}"
IsIndeterminate="{Binding Progress.IsGeneric}"
IsVisible="{Binding Progress.IsVisible}"/>
</StackPanel>
<!-- DataGrid -->
<DataGrid
Grid.Column="1"
Grid.Row="1"
x:Name="DataGridActions"
VerticalAlignment="Stretch"
ItemsSource="{Binding CurrentGridRows.View}"
SelectedItem="{Binding SelectedGridRow}">
<DataGrid.ContextMenu>
<ContextMenu x:Name="ContextMenuActions"/>
</DataGrid.ContextMenu>
<DataGrid.Columns>
<DataGridTextColumn
Header="{x:Static langRes:GeneralLangRes.Id}"
Binding="{Binding InheritedId}"
Width="*"/>
<DataGridTextColumn
Header="{x:Static langRes:GeneralLangRes.Name}"
Binding="{Binding InheritedName}"
Width="*"/>
<DataGridTextColumn
Header="{x:Static langRes:GeneralLangRes.UpdateType}"
Binding="{Binding InheritedUpdateType}"
IsVisible="{Binding IsUpdate}"/>
<DataGridTextColumn
Header="{x:Static langRes:GeneralLangRes.Side}"
Binding="{Binding InheritedSide}"/>
<DataGridTextColumn
Header="{x:Static langRes:GeneralLangRes.SourceType}"
Binding="{Binding InheritedSourceType}"/>
<DataGridTextColumn
Header="{x:Static langRes:GeneralLangRes.DestinationPath}"
Binding="{Binding InheritedDestPath}"
Width="*"/>
<DataGridTemplateColumn
Header="{x:Static langRes:GeneralLangRes.State}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image
Width="{x:Static symbols:SymbolGlobals.DefaultImageSmallSize}"
Source="{Binding StateImage}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<!-- Action editor -->
<ScrollViewer
x:Name="ScrollViewerInstallAction"
Grid.Column="2"
Grid.Row="1"
DataContext="{Binding SelectedGridRow}"
VerticalScrollBarVisibility="Auto">
<StackPanel
Spacing="6">
<!-- Update -->
<Grid
ColumnDefinitions="150,*"
RowDefinitions="Auto,Auto,Auto,Auto,Auto"
RowSpacing="6"
ColumnSpacing="6"
IsVisible="{Binding IsUpdate}">
<!-- Header -->
<StackPanel
Grid.ColumnSpan="2"
Orientation="Horizontal"
Spacing="6">
<Image x:Name="ImageUpdate" Width="{x:Static symbols:SymbolGlobals.DefaultImageMediumSize}"/>
<TextBlock Text="{x:Static langRes:GeneralLangRes.Update}" FontSize="{x:Static symbols:SymbolGlobals.DefaultImageMediumSize}"/>
</StackPanel>
<!-- Inherit from -->
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static langRes:GeneralLangRes.InheritFrom}" Target="TextBoxUpdateActionInheritFrom"/>
<TextBox
Grid.Row="1" Grid.Column="1"
x:Name="TextBoxUpdateActionInheritFrom"
Text="{Binding InheritFrom}"/>
<!-- Update type -->
<Label Grid.Row="2" Grid.Column="0" Content="{x:Static langRes:GeneralLangRes.UpdateType}" Target="ComboBoxUpdateActionSourceType"/>
<ComboBox
Grid.Row="2" Grid.Column="1"
x:Name="ComboBoxUpdateActionSourceType"
ItemsSource="{x:Static mainWindow:MainWindowGridRow.UpdateActionTypes}"
DisplayMemberBinding="{Binding Value}"
SelectedValueBinding="{Binding Key}"
SelectedValue="{Binding UpdateType}"/>
<!-- Source path -->
<Label Grid.Row="3" Grid.Column="0" Content="{x:Static langRes:GeneralLangRes.SourcePath}" Target="TextBoxInstallActionSourcePath"/>
<TextBox
Grid.Row="3" Grid.Column="1"
x:Name="TextBoxInstallActionSourcePath"
Text="{Binding SrcPath}"/>
<!-- Is Directory -->
<CheckBox Grid.Row="4" Grid.Column="1"
x:Name="CheckBoxUpdateActionIsDir"
Content="{x:Static langRes:GeneralLangRes.IsDirectory}"
IsChecked="{Binding IsDirectory}"/>
</Grid>
<!-- General -->
<Grid
ColumnDefinitions="150,*"
RowDefinitions="Auto,Auto,Auto,Auto,Auto"
RowSpacing="6"
ColumnSpacing="6">
<!-- Header -->
<StackPanel
Grid.ColumnSpan="2"
Orientation="Horizontal"
Spacing="6">
<Image
x:Name="ImageGeneral"
Width="{x:Static symbols:SymbolGlobals.DefaultImageMediumSize}"/>
<TextBlock Text="{x:Static langRes:GeneralLangRes.General}" FontSize="20"/>
</StackPanel>
<!-- Id -->
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static langRes:GeneralLangRes.Id}" Target="TextBoxInstallActionId"/>
<TextBox
Grid.Row="1" Grid.Column="1"
x:Name="TextBoxInstallActionId"
Text="{Binding Id}"/>
<!-- Name -->
<Label Grid.Row="2" Grid.Column="0" Content="{x:Static langRes:GeneralLangRes.Name}" Target="TextBoxInstallActionName"/>
<TextBox
Grid.Row="2" Grid.Column="1"
x:Name="TextBoxInstallActionName"
Text="{Binding Name}"/>
<!-- Side -->
<Label Grid.Row="3" Grid.Column="0" Content="{x:Static langRes:GeneralLangRes.Side}" Target="ComboBoxInstallActionSide"/>
<ComboBox
Grid.Row="3" Grid.Column="1"
x:Name="ComboBoxInstallActionSide"
ItemsSource="{x:Static mainWindow:MainWindowGridRow.Sides}"
DisplayMemberBinding="{Binding Value}"
SelectedValueBinding="{Binding Key}"
SelectedValue="{Binding Side}"/>
<!-- Is Extra -->
<CheckBox
Grid.Row="4" Grid.Column="1"
x:Name="CheckBoxInstallActionIsExtra"
Content="{x:Static langRes:GeneralLangRes.IsExtra}"
IsChecked="{Binding IsExtra}"/>
</Grid>
<!-- Destination -->
<Grid
ColumnDefinitions="150,*"
RowDefinitions="Auto,Auto"
RowSpacing="6"
ColumnSpacing="6">
<!-- Header -->
<StackPanel
Grid.ColumnSpan="2"
Orientation="Horizontal"
Spacing="6">
<Image
x:Name="ImageDestination"
Width="{x:Static symbols:SymbolGlobals.DefaultImageMediumSize}"/>
<TextBlock Text="{x:Static langRes:GeneralLangRes.Destination}" FontSize="20"/>
</StackPanel>
<!-- Destination path -->
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static langRes:GeneralLangRes.DestinationPath}" Target="TextBoxInstallDestPath"/>
<TextBox
Grid.Row="1" Grid.Column="1"
x:Name="TextBoxInstallDestPath"
Text="{Binding DestPath}"/>
</Grid>
<!-- Source -->
<Grid
ColumnDefinitions="150,*"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto"
RowSpacing="6"
ColumnSpacing="6">
<!-- Header -->
<StackPanel
Grid.ColumnSpan="2"
Orientation="Horizontal"
Spacing="6">
<Image
x:Name="ImageSource"
Width="{x:Static symbols:SymbolGlobals.DefaultImageMediumSize}"/>
<TextBlock Text="{x:Static langRes:GeneralLangRes.Source}" FontSize="20"/>
</StackPanel>
<!-- Source types -->
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static langRes:GeneralLangRes.SourceType}" Target="CheckBoxInstallActionSourceType"/>
<ComboBox
Grid.Row="1" Grid.Column="1"
x:Name="CheckBoxInstallActionSourceType"
ItemsSource="{x:Static mainWindow:MainWindowGridRow.SourceTypes}"
DisplayMemberBinding="{Binding Value}"
SelectedValueBinding="{Binding Key}"
SelectedValue="{Binding SourceType}"/>
<!-- Is Zip -->
<CheckBox Grid.Row="2" Grid.Column="1"
x:Name="CheckBoxInstallActionIsZip"
Content="{x:Static langRes:GeneralLangRes.IsZipArchive}"
IsChecked="{Binding IsZip}"/>
<!-- Source owner -->
<Label Grid.Row="3" Grid.Column="0" Content="{x:Static langRes:GeneralLangRes.SourceOwner}" Target="TextBoxInstallActionSourceOwner"/>
<TextBox
Grid.Row="3" Grid.Column="1"
x:Name="TextBoxInstallActionSourceOwner"
Text="{Binding SourceOwner}"/>
<!-- Source name -->
<Label Grid.Row="4" Grid.Column="0" Content="{x:Static langRes:GeneralLangRes.SourceName}" Target="TextBoxInstallActionSourceName"/>
<TextBox
Grid.Row="4" Grid.Column="1"
x:Name="TextBoxInstallActionSourceName"
Text="{Binding SourceName}"/>
<!-- Source RegEx -->
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static langRes:GeneralLangRes.SourceRegex}" Target="TextBoxInstallActionSourceRegEx"/>
<TextBox
Grid.Row="5" Grid.Column="1"
x:Name="TextBoxInstallActionSourceRegEx"
Text="{Binding SourceRegex}"/>
<!-- Source url -->
<Label Grid.Row="6" Grid.Column="0" Content="{x:Static langRes:GeneralLangRes.SourceUrl}" Target="TextBoxInstallActionSourceUrl"/>
<TextBox
Grid.Row="6" Grid.Column="1"
x:Name="TextBoxInstallActionSourceUrl" Text="{Binding SourceUrl}"/>
<!-- Zip archive path -->
<Label Grid.Row="7" Grid.Column="0" Content="{x:Static langRes:GeneralLangRes.ZipArchivePath}" Target="TextBoxInstallActionZipArchivePath"/>
<TextBox
Grid.Row="7" Grid.Column="1"
x:Name="TextBoxInstallActionZipArchivePath"
Text="{Binding ZipPath}"/>
</Grid>
<!-- Metadata -->
<Grid
ColumnDefinitions="150,*"
RowDefinitions="Auto,Auto"
RowSpacing="6"
ColumnSpacing="6"
VerticalAlignment="Center">
<!-- Header -->
<StackPanel
Grid.ColumnSpan="2"
Orientation="Horizontal"
Spacing="6">
<Image
x:Name="ImageMetadata"
Width="{x:Static symbols:SymbolGlobals.DefaultImageMediumSize}"/>
<TextBlock Text="{x:Static langRes:GeneralLangRes.Metadata}" FontSize="20"/>
</StackPanel>
<!-- Website -->
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static langRes:GeneralLangRes.Website}" Target="TextBoxInstallActionWebsite"/>
<TextBox
Grid.Row="1" Grid.Column="1"
x:Name="TextBoxInstallActionWebsite"
Text="{Binding Website}"/>
</Grid>
</StackPanel>
</ScrollViewer>
</Grid>
</Window>

View File

@@ -0,0 +1,269 @@
using System.Reflection;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
using DynamicData;
using ModpackUpdater.Apps.Manager.Api;
using ModpackUpdater.Apps.Manager.Api.Model;
using ModpackUpdater.Apps.Manager.Api.Plugins.Features;
using ModpackUpdater.Apps.Manager.Api.Plugins.Params;
using ModpackUpdater.Apps.Manager.Settings;
using ModpackUpdater.Apps.Manager.Ui.Models.MainWindow;
using Pilz.Extensions;
using Pilz.Extensions.Collections;
using Pilz.Features;
using Pilz.UI.AvaloniaUI.Features;
using Pilz.UI.Symbols;
namespace ModpackUpdater.Apps.Manager.Ui;
public partial class MainWindow : Window, IMainApi
{
public static IImage? ButtonImageAddAction => AppGlobals.Symbols.GetImageSource(AppSymbols.add);
public static IImage? ButtonImageRemoveAction => AppGlobals.Symbols.GetImageSource(AppSymbols.remove);
private WorkspaceFeature? curWs;
public MainWindowViewModel Model { get; } = new();
Window IMainApi.MainWindow => this;
public IMainApi MainApi => this;
public bool HasClosed { get; private set; }
public MainWindow()
{
InitializeComponent();
Title = $"{Title} (v{Assembly.GetExecutingAssembly().GetAppVersion().ToShortString()})";
GridMain.DataContext = Model;
ButtonWorkspace.ImageSource = AppGlobals.Symbols.GetImageSource(AppSymbols.workspace);
MenuItemWorkspacePreferences.Icon = AppGlobals.Symbols.GetImage(AppSymbols.settings, SymbolSize.Small);
MenuItemSaveWorkspace.Icon = AppGlobals.Symbols.GetImage(AppSymbols.save, SymbolSize.Small);
MenuItemNewWorkspace.Icon = AppGlobals.Symbols.GetImage(AppSymbols.new_window, SymbolSize.Small);
MenuItemRecentWorkspaces.Icon = AppGlobals.Symbols.GetImage(AppSymbols.time_machine, SymbolSize.Small);
ButtonUpdate.ImageSource = AppGlobals.Symbols.GetImageSource(AppSymbols.update_done);
ButtonTools.ImageSource = AppGlobals.Symbols.GetImageSource(AppSymbols.tools);
MenuItemCreateUpdate.Icon = AppGlobals.Symbols.GetImage(AppSymbols.add, SymbolSize.Small);
MenuItemRemoveUpdate.Icon = AppGlobals.Symbols.GetImage(AppSymbols.remove, SymbolSize.Small);
ImageUpdate.Source = AppGlobals.Symbols.GetImageSource(AppSymbols.update_done);
ImageMetadata.Source = AppGlobals.Symbols.GetImageSource(AppSymbols.show_property);
ImageGeneral.Source = AppGlobals.Symbols.GetImageSource(AppSymbols.normal_screen);
ImageSource.Source = AppGlobals.Symbols.GetImageSource(AppSymbols.input);
ImageDestination.Source = AppGlobals.Symbols.GetImageSource(AppSymbols.output);
PluginFeatureController.Instance.Features.Get(FeatureTypes.Workspace).Ordered().InsertItemsTo(MenuItemNewWorkspace.Items,
customClickHandler: MenuItemNewWorkspaceItem_Click,
insertPrioSplitters: true);
PluginFeatureController.Instance.Features.Get(FeatureTypes.ActionsContextMenu).Ordered().InsertItemsTo(ContextMenuActions.Items,
customClickHandler: MenuItemActionItem_Click,
insertPrioSplitters: true);
var menuFlyoutTools = new MenuFlyout();
ButtonTools.Flyout = menuFlyoutTools;
PluginFeatureController.Instance.Functions.Get(FeatureTypes.Tools).InsertItemsTo(menuFlyoutTools.Items,
customClickHandler: MenuItemToolsItem_Click,
insertPrioSplitters: true);
}
private async Task LoadNewWorkspace(IWorkspace? workspace, WorkspaceFeature feature)
{
if (workspace is null)
return;
if (!await workspace.Load())
return;
if (workspace != Model.CurrentWorkspace)
{
Model.CurrentWorkspace = workspace;
curWs = feature;
}
AddToRecentFiles(workspace);
LoadRecentWorkspaces();
}
private async Task SaveWorkspace()
{
if (Model.CurrentWorkspace is not { } ws)
return;
Model.Progress.Start();
await ws.Save();
Model.Progress.Stop();
}
private void LoadRecentWorkspaces()
{
var settings = Program.Settings.Get<WorkspaceSettings>();
MenuItemRecentWorkspaces.Items.Clear();
settings.Workspaces.ForEach(config =>
{
if (PluginFeatureController.Instance.Features.Get(FeatureTypes.Workspace).OfType<WorkspaceFeature>().FirstOrDefault(n => n.Identifier == config.ProviderId) is not WorkspaceFeature feature)
return;
var item = new MenuItem
{
Header = config.DisplayText,
Icon = feature.Icon,
DataContext = new MainWindowRecentFilesItem(config, feature),
};
item.Click += MenuItemRecentWorkspaceItem_Click;
MenuItemRecentWorkspaces.Items.Add(item);
});
}
private static void AddToRecentFiles(IWorkspace workspace)
{
var settings = Program.Settings.Get<WorkspaceSettings>();
settings.Workspaces.Remove(workspace.Config);
settings.Workspaces.Insert(0, workspace.Config);
settings.Workspaces.Skip(20).ForEach(n => settings.Workspaces.Remove(n));
}
private async void Window_OnLoaded(object? sender, RoutedEventArgs e)
{
var updater = new AppUpdates("client", this)
{
UsePopups = true,
};
updater.OnDownloadProgramUpdate += (_, _) => Model.Progress.Start();
await updater.UpdateApp();
Model.Progress.Stop();
LoadRecentWorkspaces();
}
private void Window_OnClosed(object? sender, EventArgs e)
{
HasClosed = true;
}
private async void Window_OnKeyDown(object? sender, KeyEventArgs e)
{
if (e.KeyModifiers == KeyModifiers.Control && e.Key == Key.Space)
await SaveWorkspace();
}
private async void MenuItemNewWorkspaceItem_Click(object? sender, RoutedEventArgs e)
{
if (sender is not MenuItem item || item.Tag is not WorkspaceFeature feature)
return;
var context = new WorkspaceContext(MainApi, null);
await feature.Configure(context);
if (!context.Canceled)
await LoadNewWorkspace(context.Workspace, feature);
}
private async void MenuItemWorkspacePreferences_OnClick(object? sender, RoutedEventArgs e)
{
if (curWs is null || Model.CurrentWorkspace is null)
return;
var context = new WorkspaceContext(MainApi, Model.CurrentWorkspace);
await curWs.Configure(context);
if (!context.Canceled)
await LoadNewWorkspace(context.Workspace, curWs);
}
private async void MenuItemSaveWorkspace_OnClick(object? sender, RoutedEventArgs e)
{
await SaveWorkspace();
}
private async void MenuItemRecentWorkspaceItem_Click(object? sender, RoutedEventArgs e)
{
if (sender is MenuItem item && item.DataContext is MainWindowRecentFilesItem tag && tag.Feature.CreateFromConfig(tag.Config) is IWorkspace workspace)
await LoadNewWorkspace(workspace, tag.Feature);
}
private async void MenuItemToolsItem_Click(object? sender, RoutedEventArgs e)
{
if (sender is MenuItem item && item.Tag is PluginFunction func)
await func.ExecuteAsync(new MainApiParameters(this));
}
private async void MenuItemActionItem_Click(object? sender, RoutedEventArgs e)
{
if (sender is MenuItem item && item.Tag is PluginFunction func)
await func.ExecuteAsync(new MainApiParameters(this));
}
private void MenuItemCreateUpdate_OnClick(object? sender, RoutedEventArgs e)
{
if (Model.CurrentWorkspace?.UpdateInfos is null
|| Model.CurrentTreeNodes?.ElementAtOrDefault(1) is not { } nodeUpdates)
return;
var update = new UpdateInfo
{
Version = new(),
};
Model.CurrentWorkspace.UpdateInfos.Updates.Insert(0, update);
nodeUpdates.Nodes.Insert(0, new ActionSetTreeNode(update));
}
private void MenuItemRemoveUpdate_OnClick(object? sender, RoutedEventArgs e)
{
if (Model.CurrentWorkspace?.UpdateInfos is null
|| Model.CurrentTreeNodes?.ElementAtOrDefault(1) is not { } nodeUpdates
|| Model.SelectedTreeNode is not ActionSetTreeNode nodeUpdate
|| nodeUpdate.Infos is not UpdateInfo update)
return;
nodeUpdates.Nodes.Remove(nodeUpdate);
Model.CurrentWorkspace.UpdateInfos.Updates.Remove(update);
}
private void ButtonAddAction_OnClick(object? sender, RoutedEventArgs e)
{
if (Model.CurrentWorkspace?.InstallInfos is not { } rootInfos
|| Model.SelectedTreeNode is not ActionSetTreeNode nodeUpdate
|| Model.CurrentGridRows is not { } rows)
return;
InstallAction action;
switch (nodeUpdate.Infos)
{
case UpdateInfo updateInfos:
updateInfos.Actions.Add((UpdateAction)(action = new UpdateAction()));
break;
case InstallInfos installInfos:
installInfos.Actions.Add(action = new InstallAction());
break;
default:
return;
}
rows.List.Add(new MainWindowGridRow(action, rootInfos));
}
private void ButtonRemoveAction_OnClick(object? sender, RoutedEventArgs e)
{
if (Model.SelectedGridRow is not { } row
|| Model.SelectedTreeNode is not ActionSetTreeNode nodeUpdate
|| Model.CurrentGridRows is not { } rows)
return;
switch (nodeUpdate.Infos)
{
case UpdateInfo updateInfos:
if (row.Action is UpdateAction action)
updateInfos.Actions.Remove(action);
break;
case InstallInfos installInfos:
installInfos.Actions.Remove(row.Action);
break;
default:
return;
}
rows.List.Remove(row);
}
}

Some files were not shown because too many files have changed in this diff Show More