From 7d166fbeb3838893a34b63e9ac4b9064057aff02 Mon Sep 17 00:00:00 2001
From: slxdy
Date: Sat, 16 Nov 2024 00:30:02 +0100
Subject: [PATCH 01/10] Version name update; cleanup
---
Directory.Build.props | 12 +++++++-----
MelonLoader.Installer/App.axaml.cs | 2 +-
MelonLoader.Installer/InstallerUtils.cs | 2 +-
MelonLoader.Installer/MLManager.cs | 6 +++---
MelonLoader.Installer/MelonLoader.Installer.csproj | 4 +---
MelonLoader.Installer/Program.cs | 12 ++++++------
MelonLoader.Installer/Updater.cs | 10 +++-------
MelonLoader.Installer/ViewModels/DetailsViewModel.cs | 4 ++--
MelonLoader.Installer/ViewModels/GameModel.cs | 2 +-
MelonLoader.Installer/ViewModels/MainViewModel.cs | 6 +++---
MelonLoader.Installer/Views/DetailsView.axaml | 2 --
MelonLoader.Installer/Views/ErrorBox.axaml | 2 +-
MelonLoader.Installer/Views/MainView.axaml | 2 +-
MelonLoader.Installer/Views/MainWindow.axaml | 2 --
MelonLoader.Installer/Views/MainWindow.axaml.cs | 6 +++---
MelonLoader.Installer/Views/UpdaterView.axaml | 2 --
MelonLoader.Installer/Views/UpdaterView.axaml.cs | 2 +-
17 files changed, 34 insertions(+), 44 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index ee4489e..6858d78 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,6 +1,8 @@
-
- enable
- 11.2.1
-
-
+
+ 4.0.0
+
+ enable
+ 11.2.1
+
+
\ No newline at end of file
diff --git a/MelonLoader.Installer/App.axaml.cs b/MelonLoader.Installer/App.axaml.cs
index 4177f3a..b5fd626 100644
--- a/MelonLoader.Installer/App.axaml.cs
+++ b/MelonLoader.Installer/App.axaml.cs
@@ -9,7 +9,7 @@
namespace MelonLoader.Installer;
-public partial class App : Application
+public class App : Application
{
public override void Initialize()
{
diff --git a/MelonLoader.Installer/InstallerUtils.cs b/MelonLoader.Installer/InstallerUtils.cs
index 050e437..ef8cf31 100644
--- a/MelonLoader.Installer/InstallerUtils.cs
+++ b/MelonLoader.Installer/InstallerUtils.cs
@@ -9,7 +9,7 @@ public static class InstallerUtils
static InstallerUtils()
{
Http = new();
- Http.DefaultRequestHeaders.Add("User-Agent", $"MelonLoader Installer v{Program.Version.ToString(3)}");
+ Http.DefaultRequestHeaders.Add("User-Agent", $"MelonLoader Installer v{Program.VersionName}");
}
public static async Task DownloadFileAsync(string url, Stream destination, InstallProgressEventHandler? onProgress)
diff --git a/MelonLoader.Installer/MLManager.cs b/MelonLoader.Installer/MLManager.cs
index b9a7a4c..8a7fa6e 100644
--- a/MelonLoader.Installer/MLManager.cs
+++ b/MelonLoader.Installer/MLManager.cs
@@ -81,7 +81,7 @@ private static async Task GetVersionsAsync(List versions)
try
{
- resp = await InstallerUtils.Http.GetAsync(run!["artifacts_url"]!.ToString()).ConfigureAwait(false);
+ resp = await InstallerUtils.Http.GetAsync(run["artifacts_url"]!.ToString()).ConfigureAwait(false);
}
catch
{
@@ -387,7 +387,7 @@ void SetProgress(double progress, string? newStatus = null)
onProgress?.Invoke(currentTask / (double)tasks + progress / tasks, newStatus);
}
- SetProgress(0, "Downloading MelonLoader " + version.ToString());
+ SetProgress(0, "Downloading MelonLoader " + version);
using var bufferStr = new MemoryStream();
var result = await InstallerUtils.DownloadFileAsync(downloadUrl, bufferStr, SetProgress);
@@ -400,7 +400,7 @@ void SetProgress(double progress, string? newStatus = null)
currentTask++;
- SetProgress(0, "Installing " + version.ToString());
+ SetProgress(0, "Installing " + version);
var extRes = InstallerUtils.Extract(bufferStr, gameDir, SetProgress);
if (extRes != null)
diff --git a/MelonLoader.Installer/MelonLoader.Installer.csproj b/MelonLoader.Installer/MelonLoader.Installer.csproj
index e7adc02..66f5bb7 100644
--- a/MelonLoader.Installer/MelonLoader.Installer.csproj
+++ b/MelonLoader.Installer/MelonLoader.Installer.csproj
@@ -10,7 +10,7 @@
latest
true
Assets/icon.ico
- ../Output/win-x64
+ ../Output/$(RuntimeIdentifier)
true
true
embedded
@@ -21,8 +21,6 @@
Lava Gang
discord.gg/2Wn3N2P
-
- 4.0.0
diff --git a/MelonLoader.Installer/Program.cs b/MelonLoader.Installer/Program.cs
index 9984a52..c2697b9 100644
--- a/MelonLoader.Installer/Program.cs
+++ b/MelonLoader.Installer/Program.cs
@@ -9,7 +9,10 @@ internal static class Program
public static event Action? Exiting;
- public static Version Version { get; private set; } = typeof(Program).Assembly.GetName().Version!;
+ public static Version Version { get; } = typeof(Program).Assembly.GetName().Version!;
+
+ public static string VersionName { get; } =
+ $"v{Version.Major}.{Version.Minor}.{Version.Build}{(Version.Revision > 0 ? $"-ci.{Version.Revision}" : string.Empty)}";
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
@@ -69,11 +72,8 @@ private static bool CheckProcessLock()
var procId = BitConverter.ToInt32(procIdRaw);
var proc = Process.GetProcessById(procId);
- if (proc != null)
- {
- GrabAttention(proc);
- return false;
- }
+ GrabAttention(proc);
+ return false;
}
catch { return false; }
}
diff --git a/MelonLoader.Installer/Updater.cs b/MelonLoader.Installer/Updater.cs
index 3c6f40f..cb5b506 100644
--- a/MelonLoader.Installer/Updater.cs
+++ b/MelonLoader.Installer/Updater.cs
@@ -87,11 +87,7 @@ private static async Task UpdateAsync(string downloadUrl)
}
}
- if (Process.Start(newPath, ["-handleupdate", Environment.ProcessPath!, Environment.ProcessId.ToString()]) == null)
- {
- Finish("Failed to start the new installer.");
- return;
- }
+ Process.Start(newPath, ["-handleupdate", Environment.ProcessPath!, Environment.ProcessId.ToString()]);
Finish(null);
}
@@ -101,8 +97,8 @@ public static bool CheckLegacyUpdate()
if (!Environment.ProcessPath!.EndsWith(".tmp.exe", StringComparison.OrdinalIgnoreCase))
return false;
- var dir = Path.GetDirectoryName(Environment.ProcessPath!)!;
- var name = Path.GetFileNameWithoutExtension(Environment.ProcessPath!);
+ var dir = Path.GetDirectoryName(Environment.ProcessPath)!;
+ var name = Path.GetFileNameWithoutExtension(Environment.ProcessPath);
name = name.Remove(name.Length - 4) + ".exe";
var final = Path.Combine(dir, name);
diff --git a/MelonLoader.Installer/ViewModels/DetailsViewModel.cs b/MelonLoader.Installer/ViewModels/DetailsViewModel.cs
index be2cc71..1aded3c 100644
--- a/MelonLoader.Installer/ViewModels/DetailsViewModel.cs
+++ b/MelonLoader.Installer/ViewModels/DetailsViewModel.cs
@@ -14,7 +14,7 @@ public bool Installing
set
{
_installing = value;
- OnPropertyChanged(nameof(Installing));
+ OnPropertyChanged();
OnPropertyChanged(nameof(CanInstall));
OnPropertyChanged(nameof(EnableSettings));
}
@@ -26,7 +26,7 @@ public bool Confirmation
set
{
_confirmation = value;
- OnPropertyChanged(nameof(Confirmation));
+ OnPropertyChanged();
OnPropertyChanged(nameof(CanInstall));
}
}
diff --git a/MelonLoader.Installer/ViewModels/GameModel.cs b/MelonLoader.Installer/ViewModels/GameModel.cs
index 56633f5..f0b60be 100644
--- a/MelonLoader.Installer/ViewModels/GameModel.cs
+++ b/MelonLoader.Installer/ViewModels/GameModel.cs
@@ -22,7 +22,7 @@ public SemVersion? MLVersion
set
{
mlVersion = value;
- OnPropertyChanged(nameof(MLVersion));
+ OnPropertyChanged();
OnPropertyChanged(nameof(MLVersionText));
OnPropertyChanged(nameof(MLStatusText));
OnPropertyChanged(nameof(MLInstalled));
diff --git a/MelonLoader.Installer/ViewModels/MainViewModel.cs b/MelonLoader.Installer/ViewModels/MainViewModel.cs
index 8859821..35c81a4 100644
--- a/MelonLoader.Installer/ViewModels/MainViewModel.cs
+++ b/MelonLoader.Installer/ViewModels/MainViewModel.cs
@@ -2,7 +2,7 @@
namespace MelonLoader.Installer.ViewModels;
-public partial class MainViewModel : ViewModelBase
+public class MainViewModel : ViewModelBase
{
private static bool _ready;
@@ -12,11 +12,11 @@ public bool Ready
set
{
_ready = value;
- OnPropertyChanged(nameof(Ready));
+ OnPropertyChanged();
}
}
public ObservableCollection Games => GameManager.Games;
- public string Version => 'v' + Program.Version.ToString(3);
+ public string Version => Program.VersionName;
}
diff --git a/MelonLoader.Installer/Views/DetailsView.axaml b/MelonLoader.Installer/Views/DetailsView.axaml
index bfe2440..662f8ad 100644
--- a/MelonLoader.Installer/Views/DetailsView.axaml
+++ b/MelonLoader.Installer/Views/DetailsView.axaml
@@ -3,8 +3,6 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:MelonLoader.Installer.ViewModels"
- xmlns:views="clr-namespace:MelonLoader.Installer.Views"
- xmlns:root="clr-namespace:MelonLoader.Installer"
mc:Ignorable="d" d:DesignWidth="450" d:DesignHeight="650"
x:Class="MelonLoader.Installer.Views.DetailsView"
x:DataType="vm:DetailsViewModel">
diff --git a/MelonLoader.Installer/Views/ErrorBox.axaml b/MelonLoader.Installer/Views/ErrorBox.axaml
index bb455d6..2888aa5 100644
--- a/MelonLoader.Installer/Views/ErrorBox.axaml
+++ b/MelonLoader.Installer/Views/ErrorBox.axaml
@@ -15,7 +15,7 @@
RenderOptions.BitmapInterpolationMode="HighQuality">
-
+
\ No newline at end of file
diff --git a/MelonLoader.Installer/Views/MainView.axaml b/MelonLoader.Installer/Views/MainView.axaml
index 3fabd96..b60b660 100644
--- a/MelonLoader.Installer/Views/MainView.axaml
+++ b/MelonLoader.Installer/Views/MainView.axaml
@@ -15,7 +15,7 @@
-
diff --git a/MelonLoader.Installer/Views/MainWindow.axaml b/MelonLoader.Installer/Views/MainWindow.axaml
index 0b261a4..3bb21a8 100644
--- a/MelonLoader.Installer/Views/MainWindow.axaml
+++ b/MelonLoader.Installer/Views/MainWindow.axaml
@@ -1,9 +1,7 @@
diff --git a/MelonLoader.Installer/Views/UpdaterView.axaml.cs b/MelonLoader.Installer/Views/UpdaterView.axaml.cs
index debc750..691604c 100644
--- a/MelonLoader.Installer/Views/UpdaterView.axaml.cs
+++ b/MelonLoader.Installer/Views/UpdaterView.axaml.cs
@@ -9,7 +9,7 @@ public UpdaterView()
{
InitializeComponent();
- Updater.Progress += (progress, newStatus) => Dispatcher.UIThread.Post(() => OnProgress(progress));
+ Updater.Progress += (progress, _) => Dispatcher.UIThread.Post(() => OnProgress(progress));
}
private void OnProgress(double progress)
From 45eee4217457d661bfc63f57d873472ded79840e Mon Sep 17 00:00:00 2001
From: slxdy
Date: Sat, 16 Nov 2024 00:50:00 +0100
Subject: [PATCH 02/10] Added workflows
---
.github/workflows/build-final.yml | 30 ++++++++++++++++++++++++++++
.github/workflows/build.yml | 33 +++++++++++++++++++++++++++++++
2 files changed, 63 insertions(+)
create mode 100644 .github/workflows/build-final.yml
create mode 100644 .github/workflows/build.yml
diff --git a/.github/workflows/build-final.yml b/.github/workflows/build-final.yml
new file mode 100644
index 0000000..b795d17
--- /dev/null
+++ b/.github/workflows/build-final.yml
@@ -0,0 +1,30 @@
+name: Build Installer Final
+
+run-name: Final Build
+
+env:
+ DEVVERSION: "4.0.0"
+
+on:
+ push:
+ branches: [ master ]
+
+jobs:
+ build:
+ name: Build Installer
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup dotnet
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 9.0.x
+
+ - name: Build
+ run: dotnet publish -p:Version="${{ env.DEVVERSION }}"
+
+ - name: Upload Artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: MelonLoader.Installer
+ path: Output/win-x64/
\ No newline at end of file
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..4604855
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,33 @@
+name: Build Installer
+
+run-name: 4.0.0-ci.${{ github.run_number }} | ${{ github.event_name != 'workflow_dispatch' && (github.event.head_commit.message || format('`[PR]` {0}', github.event.pull_request.title)) || 'Manual Build' }}
+
+env:
+ DEVVERSION: "4.0.0"
+
+on:
+ push:
+ branches: [ development ]
+ pull_request:
+ branches: [ development ]
+ workflow_dispatch:
+
+jobs:
+ build:
+ name: Build Installer
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup dotnet
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 9.0.x
+
+ - name: Build
+ run: dotnet publish -p:Version="${{ env.DEVVERSION }}.${{ github.run_number }}"
+
+ - name: Upload Artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: MelonLoader.Installer
+ path: Output/win-x64/
\ No newline at end of file
From 9131f16d649fdb1a0102e801abc321e13003174d Mon Sep 17 00:00:00 2001
From: slxdy
Date: Sat, 16 Nov 2024 00:55:30 +0100
Subject: [PATCH 03/10] Removed explicit version from final workflow
---
.github/workflows/build-final.yml | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/.github/workflows/build-final.yml b/.github/workflows/build-final.yml
index b795d17..ce1b32e 100644
--- a/.github/workflows/build-final.yml
+++ b/.github/workflows/build-final.yml
@@ -2,9 +2,6 @@ name: Build Installer Final
run-name: Final Build
-env:
- DEVVERSION: "4.0.0"
-
on:
push:
branches: [ master ]
@@ -21,7 +18,7 @@ jobs:
dotnet-version: 9.0.x
- name: Build
- run: dotnet publish -p:Version="${{ env.DEVVERSION }}"
+ run: dotnet publish
- name: Upload Artifact
uses: actions/upload-artifact@v4
From fa21df7c51d00625952c174d21f853fcd7cbd8d2 Mon Sep 17 00:00:00 2001
From: slxdy
Date: Sat, 16 Nov 2024 01:01:51 +0100
Subject: [PATCH 04/10] Disable auto-updating on CI builds
---
MelonLoader.Installer/Updater.cs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/MelonLoader.Installer/Updater.cs b/MelonLoader.Installer/Updater.cs
index cb5b506..c44653b 100644
--- a/MelonLoader.Installer/Updater.cs
+++ b/MelonLoader.Installer/Updater.cs
@@ -13,6 +13,10 @@ public static class Updater
public static bool UpdateIfPossible()
{
+ // Don't auto-update on CI builds
+ if (Program.Version.Revision > 0)
+ return false;
+
var downloadUrl = CheckForUpdateAsync().GetAwaiter().GetResult();
if (downloadUrl == null)
return false;
From 375d8c586198d08dbac91c44fafe56526742137e Mon Sep 17 00:00:00 2001
From: slxdy
Date: Sat, 16 Nov 2024 15:16:31 +0100
Subject: [PATCH 05/10] Update the README
---
README.md | 27 +++++++++++++++++++++------
1 file changed, 21 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
index ab6ef45..b540d40 100644
--- a/README.md
+++ b/README.md
@@ -4,14 +4,16 @@
# MelonLoader Installer
-This is the Official Dedicated Installer for [MelonLoader](https://github.com/LavaGang/MelonLoader).
+
+
+The Official Dedicated Installer for [MelonLoader](https://github.com/LavaGang/MelonLoader).
## Report an issue
### Join our official Discord server
## How does it work?
-The installer should automatically list installed Unity games found in your Steam library.
+The installer should automatically list installed Unity games on your machine.
If the game you're trying to mod isn't listed, you can locate it manually by clicking on the `Add Game Manually` button.
@@ -22,9 +24,22 @@ To install MelonLoader, click on the game you wish to mod. Next, select your pre
Nightly builds are bleeding-edge builds, generated right after any changes are made to the project. They can be enabled with the switch under the version selection menu.
-## Compilation
-The project can be compiled using the .NET 8.0 compiler.
-To create a single-file build, use the `dotnet publish` command in the repository's root directory.
+## Contribution
+
+Contributions to this project are welcome! If you wish to contribute, please adhere to the following guidelines:
+
+### Requirements:
+Ensure you have the .NET 9.0 SDK installed on your machine. This is required to build the project.
+
+### Building the Project:
+You can build the project locally using the following command:
+```bash
+dotnet publish
+```
+
+### Pull Requests:
+All pull requests should be made towards the `development` branch.
+The master branch contains the source code for the stable release and is protected to ensure stability.
## LICENSING & CREDITS:
MelonLoader.Installer is licensed under the Apache License, Version 2.0. See [LICENSE](https://github.com/LavaGang/MelonLoader.Installer/blob/master/LICENSE.md) for the full License.
@@ -38,4 +53,4 @@ MelonLoader.Installer is licensed under the Apache License, Version 2.0. See [LI
-> See [MelonLoader Wiki](https://melonwiki.xyz/#/credits) for the full Credits.
\ No newline at end of file
+> See [MelonLoader Wiki](https://melonwiki.xyz/#/credits) for the full Credits.
From 0cc3604de06941bfaf00a1a58d907bb0ca6c5cf0 Mon Sep 17 00:00:00 2001
From: Herp Derpinstine
Date: Sat, 16 Nov 2024 09:11:12 -0600
Subject: [PATCH 06/10] Reworked ErrorBox into a Generic DialogBox for multiple
use-cases
---
.../Views/DetailsView.axaml.cs | 8 +-
MelonLoader.Installer/Views/DialogBox.axaml | 27 +++++
.../Views/DialogBox.axaml.cs | 107 ++++++++++++++++++
MelonLoader.Installer/Views/ErrorBox.axaml | 21 ----
MelonLoader.Installer/Views/ErrorBox.axaml.cs | 33 ------
MelonLoader.Installer/Views/MainView.axaml.cs | 2 +-
.../Views/MainWindow.axaml.cs | 2 +-
7 files changed, 140 insertions(+), 60 deletions(-)
create mode 100644 MelonLoader.Installer/Views/DialogBox.axaml
create mode 100644 MelonLoader.Installer/Views/DialogBox.axaml.cs
delete mode 100644 MelonLoader.Installer/Views/ErrorBox.axaml
delete mode 100644 MelonLoader.Installer/Views/ErrorBox.axaml.cs
diff --git a/MelonLoader.Installer/Views/DetailsView.axaml.cs b/MelonLoader.Installer/Views/DetailsView.axaml.cs
index 670a249..3559c21 100644
--- a/MelonLoader.Installer/Views/DetailsView.axaml.cs
+++ b/MelonLoader.Installer/Views/DetailsView.axaml.cs
@@ -49,7 +49,7 @@ protected override void OnDataContextChanged(EventArgs e)
if (!MLManager.Init())
{
Model.Offline = true;
- ErrorBox.Open("Failed to fetch MelonLoader releases. Ensure you're online.");
+ DialogBox.ShowError("Failed to fetch MelonLoader releases. Ensure you're online.");
}
}
@@ -145,7 +145,7 @@ private void OnInstallFinished(string? errorMessage)
if (errorMessage != null)
{
- ErrorBox.Open(errorMessage);
+ DialogBox.ShowError(errorMessage);
return;
}
@@ -174,7 +174,7 @@ private void UninstallHandler(object sender, RoutedEventArgs args)
if (!MLManager.Uninstall(Path.GetDirectoryName(Model.Game.Path)!, !KeepFilesCheck.IsChecked!.Value, out var error))
{
- ErrorBox.Open(error);
+ DialogBox.ShowError(error);
}
Model.Game.ValidateGame();
@@ -215,7 +215,7 @@ private async void SelectZipHandler(object sender, TappedEventArgs args)
var ver = MLManager.Versions[0];
if ((Model.Game.Is32Bit ? ver.DownloadX86Url : ver.DownloadUrl) == null)
{
- ErrorBox.Open($"The selected version does not support the architechture of the current game: {(Model.Game.Is32Bit ? "x86" : "x64")}");
+ DialogBox.ShowError($"The selected version does not support the architechture of the current game: {(Model.Game.Is32Bit ? "x86" : "x64")}");
}
}
diff --git a/MelonLoader.Installer/Views/DialogBox.axaml b/MelonLoader.Installer/Views/DialogBox.axaml
new file mode 100644
index 0000000..9e9fabc
--- /dev/null
+++ b/MelonLoader.Installer/Views/DialogBox.axaml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MelonLoader.Installer/Views/DialogBox.axaml.cs b/MelonLoader.Installer/Views/DialogBox.axaml.cs
new file mode 100644
index 0000000..ef64d29
--- /dev/null
+++ b/MelonLoader.Installer/Views/DialogBox.axaml.cs
@@ -0,0 +1,107 @@
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using Avalonia.Media.Imaging;
+using Avalonia.Platform;
+
+namespace MelonLoader.Installer.Views;
+
+public partial class DialogBox : Window
+{
+ public delegate void dCallback(object sender, RoutedEventArgs args);
+ private dCallback? OnConfirm;
+ private dCallback? OnCancel;
+
+ private static Bitmap? ErrorIcon = new Bitmap(AssetLoader.Open(new("avares://" + typeof(GameControl).Assembly.GetName().Name + "/Assets/error.png")));
+
+ public DialogBox()
+ => InitializeComponent();
+
+ public static void ShowError(string message)
+ {
+ DialogBox dialogBox = new DialogBox();
+ dialogBox.Title = "Error";
+ dialogBox.Message.Text = message;
+ dialogBox.HeaderImage.Source = ErrorIcon;
+ dialogBox.Open();
+ }
+
+ public static void ShowNotice(string message)
+ => ShowNotice("Notice", message);
+ public static void ShowNotice(string title, string message)
+ {
+ DialogBox dialogBox = new DialogBox();
+ dialogBox.Title = title;
+ dialogBox.Message.Text = message;
+ dialogBox.Open();
+ }
+
+ public static void ShowConfirmation(
+ string message,
+ dCallback? onConfirm = null,
+ dCallback? onCancel = null,
+ string confirmText = "YES",
+ string cancelText = "NO")
+ => ShowConfirmation("Confirmation",
+ message,
+ onConfirm,
+ onCancel,
+ confirmText,
+ cancelText);
+
+ public static void ShowConfirmation(
+ string title,
+ string message,
+ dCallback? onConfirm = null,
+ dCallback? onCancel = null,
+ string confirmText = "YES",
+ string cancelText = "NO")
+ {
+ DialogBox dialogBox = new DialogBox();
+
+ dialogBox.Title = title;
+ dialogBox.Message.Text = message;
+
+ dialogBox.ConfirmButton.Content = confirmText;
+
+ dialogBox.CancelButton.IsVisible = true;
+ dialogBox.CancelButton.Content = cancelText;
+
+ dialogBox.OnConfirm = onConfirm;
+ dialogBox.OnCancel = onCancel;
+
+ dialogBox.NoticeGrid.IsVisible = false;
+ dialogBox.ConfirmationGrid.IsVisible = true;
+
+ dialogBox.Open();
+ }
+
+ private void Open()
+ {
+ BringToFront();
+
+ if (MainWindow.Instance.IsVisible)
+ ShowDialog(MainWindow.Instance);
+ else
+ Show();
+ }
+
+ private void BringToFront()
+ {
+ Topmost = true;
+ Topmost = false;
+ Program.GrabAttention();
+ Focus();
+ }
+
+ private void ConfirmHandler(object sender, RoutedEventArgs args)
+ {
+ Close();
+ OnConfirm?.Invoke(sender, args);
+ }
+
+ private void CancelHandler(object sender, RoutedEventArgs args)
+ {
+ Close();
+ OnCancel?.Invoke(sender, args);
+ }
+}
\ No newline at end of file
diff --git a/MelonLoader.Installer/Views/ErrorBox.axaml b/MelonLoader.Installer/Views/ErrorBox.axaml
deleted file mode 100644
index 2888aa5..0000000
--- a/MelonLoader.Installer/Views/ErrorBox.axaml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/MelonLoader.Installer/Views/ErrorBox.axaml.cs b/MelonLoader.Installer/Views/ErrorBox.axaml.cs
deleted file mode 100644
index 7e3812f..0000000
--- a/MelonLoader.Installer/Views/ErrorBox.axaml.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.Interactivity;
-
-namespace MelonLoader.Installer.Views;
-
-public partial class ErrorBox : Window
-{
- public ErrorBox()
- {
- InitializeComponent();
- }
-
- public static void Open(string message)
- {
- var box = new ErrorBox();
- box.Message.Text = message;
- box.Topmost = true;
- box.Topmost = false;
-
- Program.GrabAttention();
- box.Focus();
-
- if (MainWindow.Instance.IsVisible)
- box.ShowDialog(MainWindow.Instance);
- else
- box.Show();
- }
-
- private void OkHandler(object sender, RoutedEventArgs args)
- {
- Close();
- }
-}
\ No newline at end of file
diff --git a/MelonLoader.Installer/Views/MainView.axaml.cs b/MelonLoader.Installer/Views/MainView.axaml.cs
index c42f039..141a6cf 100644
--- a/MelonLoader.Installer/Views/MainView.axaml.cs
+++ b/MelonLoader.Installer/Views/MainView.axaml.cs
@@ -69,7 +69,7 @@ public async void AddGameManuallyHandler(object sender, RoutedEventArgs args)
GameManager.TryAddGame(path, null, null, null, out var error);
if (error != null)
{
- ErrorBox.Open(error);
+ DialogBox.ShowError(error);
return;
}
diff --git a/MelonLoader.Installer/Views/MainWindow.axaml.cs b/MelonLoader.Installer/Views/MainWindow.axaml.cs
index 74b462d..4001292 100644
--- a/MelonLoader.Installer/Views/MainWindow.axaml.cs
+++ b/MelonLoader.Installer/Views/MainWindow.axaml.cs
@@ -36,7 +36,7 @@ private void OnUpdateFinished(string? errorMessage)
{
if (errorMessage != null)
{
- ErrorBox.Open(errorMessage);
+ DialogBox.ShowError(errorMessage);
ShowMainView();
return;
}
From 10143382d3aaa3b8d038b81155cf4ffd9b546e38 Mon Sep 17 00:00:00 2001
From: Herp Derpinstine
Date: Sat, 16 Nov 2024 09:16:00 -0600
Subject: [PATCH 07/10] Cleanup
---
MelonLoader.Installer/Views/DialogBox.axaml | 2 +-
MelonLoader.Installer/Views/DialogBox.axaml.cs | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/MelonLoader.Installer/Views/DialogBox.axaml b/MelonLoader.Installer/Views/DialogBox.axaml
index 9e9fabc..bfe2697 100644
--- a/MelonLoader.Installer/Views/DialogBox.axaml
+++ b/MelonLoader.Installer/Views/DialogBox.axaml
@@ -4,7 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="MelonLoader.Installer.Views.DialogBox"
- Title="Notice"
+ Title="NOTICE"
Icon="/Assets/icon.ico"
WindowStartupLocation="CenterScreen"
Background="#121217"
diff --git a/MelonLoader.Installer/Views/DialogBox.axaml.cs b/MelonLoader.Installer/Views/DialogBox.axaml.cs
index ef64d29..c486d2f 100644
--- a/MelonLoader.Installer/Views/DialogBox.axaml.cs
+++ b/MelonLoader.Installer/Views/DialogBox.axaml.cs
@@ -19,14 +19,14 @@ public DialogBox()
public static void ShowError(string message)
{
DialogBox dialogBox = new DialogBox();
- dialogBox.Title = "Error";
+ dialogBox.Title = "ERROR";
dialogBox.Message.Text = message;
dialogBox.HeaderImage.Source = ErrorIcon;
dialogBox.Open();
}
public static void ShowNotice(string message)
- => ShowNotice("Notice", message);
+ => ShowNotice("NOTICE", message);
public static void ShowNotice(string title, string message)
{
DialogBox dialogBox = new DialogBox();
@@ -41,7 +41,7 @@ public static void ShowConfirmation(
dCallback? onCancel = null,
string confirmText = "YES",
string cancelText = "NO")
- => ShowConfirmation("Confirmation",
+ => ShowConfirmation("CONFIRMATION",
message,
onConfirm,
onCancel,
From 0b56ba1f28b11411032d04778ef263f2054164ca Mon Sep 17 00:00:00 2001
From: Herp Derpinstine
Date: Sat, 16 Nov 2024 09:57:22 -0600
Subject: [PATCH 08/10] Implemented Success Dialog Box
---
MelonLoader.Installer/Views/DetailsView.axaml.cs | 5 +++--
MelonLoader.Installer/Views/DialogBox.axaml | 2 +-
README.md | 2 +-
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/MelonLoader.Installer/Views/DetailsView.axaml.cs b/MelonLoader.Installer/Views/DetailsView.axaml.cs
index 3559c21..699f11b 100644
--- a/MelonLoader.Installer/Views/DetailsView.axaml.cs
+++ b/MelonLoader.Installer/Views/DetailsView.axaml.cs
@@ -142,6 +142,8 @@ private void OnInstallFinished(string? errorMessage)
Model.Game.ValidateGame();
Model.Installing = false;
+ NightlyCheck.IsEnabled = true;
+ VersionCombobox.IsEnabled = true;
if (errorMessage != null)
{
@@ -149,8 +151,7 @@ private void OnInstallFinished(string? errorMessage)
return;
}
- InstallStatus.Text = "Done!";
- Model.Confirmation = true;
+ DialogBox.ShowNotice("SUCCESS!", $"MelonLoader v{((MLVersion)VersionCombobox.SelectedItem!).Version} was Installed Successfully!");
}
private void OpenDirHandler(object sender, RoutedEventArgs args)
diff --git a/MelonLoader.Installer/Views/DialogBox.axaml b/MelonLoader.Installer/Views/DialogBox.axaml
index bfe2697..6d2813b 100644
--- a/MelonLoader.Installer/Views/DialogBox.axaml
+++ b/MelonLoader.Installer/Views/DialogBox.axaml
@@ -13,7 +13,7 @@
Height="100"
SizeToContent="WidthAndHeight"
RenderOptions.BitmapInterpolationMode="HighQuality">
-
+
diff --git a/README.md b/README.md
index ab6ef45..64985df 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ To install MelonLoader, click on the game you wish to mod. Next, select your pre
Nightly builds are bleeding-edge builds, generated right after any changes are made to the project. They can be enabled with the switch under the version selection menu.
## Compilation
-The project can be compiled using the .NET 8.0 compiler.
+The project can be compiled using the .NET 9.0 compiler.
To create a single-file build, use the `dotnet publish` command in the repository's root directory.
## LICENSING & CREDITS:
From a93e1da34157618adb5569202dc75d22110bb611 Mon Sep 17 00:00:00 2001
From: Herp Derpinstine
Date: Sat, 16 Nov 2024 10:05:16 -0600
Subject: [PATCH 09/10] Update DetailsView.axaml.cs
---
MelonLoader.Installer/Views/DetailsView.axaml.cs | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/MelonLoader.Installer/Views/DetailsView.axaml.cs b/MelonLoader.Installer/Views/DetailsView.axaml.cs
index 699f11b..1b8b628 100644
--- a/MelonLoader.Installer/Views/DetailsView.axaml.cs
+++ b/MelonLoader.Installer/Views/DetailsView.axaml.cs
@@ -139,6 +139,7 @@ private void OnInstallFinished(string? errorMessage)
if (Model == null)
return;
+ bool wasReinstall = Model.Game.MLInstalled;
Model.Game.ValidateGame();
Model.Installing = false;
@@ -151,7 +152,7 @@ private void OnInstallFinished(string? errorMessage)
return;
}
- DialogBox.ShowNotice("SUCCESS!", $"MelonLoader v{((MLVersion)VersionCombobox.SelectedItem!).Version} was Installed Successfully!");
+ DialogBox.ShowNotice("SUCCESS!", $"{(wasReinstall ? "Reinstall" : "Install")} was Successful!");
}
private void OpenDirHandler(object sender, RoutedEventArgs args)
@@ -176,9 +177,12 @@ private void UninstallHandler(object sender, RoutedEventArgs args)
if (!MLManager.Uninstall(Path.GetDirectoryName(Model.Game.Path)!, !KeepFilesCheck.IsChecked!.Value, out var error))
{
DialogBox.ShowError(error);
+ Model.Game.ValidateGame();
+ return;
}
Model.Game.ValidateGame();
+ DialogBox.ShowNotice("SUCCESS!", "Uninstall was Successful!");
}
private async void SelectZipHandler(object sender, TappedEventArgs args)
From cbdb6982da068a8949d9437fff989c83d3b61416 Mon Sep 17 00:00:00 2001
From: slxdy
Date: Sat, 16 Nov 2024 17:56:57 +0100
Subject: [PATCH 10/10] Cleanup
---
.../ViewModels/DetailsViewModel.cs | 16 +---
.../ViewModels/DialogBoxModel.cs | 10 ++
MelonLoader.Installer/Views/DetailsView.axaml | 4 +-
.../Views/DetailsView.axaml.cs | 8 +-
MelonLoader.Installer/Views/DialogBox.axaml | 17 ++--
.../Views/DialogBox.axaml.cs | 95 ++++++++++---------
.../Views/MainWindow.axaml.cs | 2 +-
7 files changed, 75 insertions(+), 77 deletions(-)
create mode 100644 MelonLoader.Installer/ViewModels/DialogBoxModel.cs
diff --git a/MelonLoader.Installer/ViewModels/DetailsViewModel.cs b/MelonLoader.Installer/ViewModels/DetailsViewModel.cs
index 1aded3c..0520f4b 100644
--- a/MelonLoader.Installer/ViewModels/DetailsViewModel.cs
+++ b/MelonLoader.Installer/ViewModels/DetailsViewModel.cs
@@ -3,7 +3,6 @@
public class DetailsViewModel(GameModel game) : ViewModelBase
{
private bool _installing;
- private bool _confirmation;
private bool _offline;
public GameModel Game => game;
@@ -15,33 +14,20 @@ public bool Installing
{
_installing = value;
OnPropertyChanged();
- OnPropertyChanged(nameof(CanInstall));
OnPropertyChanged(nameof(EnableSettings));
}
}
- public bool Confirmation
- {
- get => _confirmation;
- set
- {
- _confirmation = value;
- OnPropertyChanged();
- OnPropertyChanged(nameof(CanInstall));
- }
- }
-
public bool Offline
{
get => _offline;
set
{
_offline = value;
- OnPropertyChanged(nameof(Confirmation));
+ OnPropertyChanged();
OnPropertyChanged(nameof(EnableSettings));
}
}
- public bool CanInstall => !Installing && !Confirmation;
public bool EnableSettings => !Offline && !Installing;
}
diff --git a/MelonLoader.Installer/ViewModels/DialogBoxModel.cs b/MelonLoader.Installer/ViewModels/DialogBoxModel.cs
new file mode 100644
index 0000000..897c853
--- /dev/null
+++ b/MelonLoader.Installer/ViewModels/DialogBoxModel.cs
@@ -0,0 +1,10 @@
+namespace MelonLoader.Installer.ViewModels;
+
+public class DialogBoxModel : ViewModelBase
+{
+ public required string Message { get; init; }
+ public string ConfirmText { get; init; } = "YES";
+ public string CancelText { get; init; } = "NO";
+ public bool IsError { get; init; }
+ public bool IsConfirmation { get; init; }
+}
diff --git a/MelonLoader.Installer/Views/DetailsView.axaml b/MelonLoader.Installer/Views/DetailsView.axaml
index 662f8ad..1d799e3 100644
--- a/MelonLoader.Installer/Views/DetailsView.axaml
+++ b/MelonLoader.Installer/Views/DetailsView.axaml
@@ -40,7 +40,7 @@
IsVisible="{Binding Game.MLInstalled}" IsChecked="True">Keep mods and settings
-
+
-
+
diff --git a/MelonLoader.Installer/Views/DetailsView.axaml.cs b/MelonLoader.Installer/Views/DetailsView.axaml.cs
index 1b8b628..0daba6c 100644
--- a/MelonLoader.Installer/Views/DetailsView.axaml.cs
+++ b/MelonLoader.Installer/Views/DetailsView.axaml.cs
@@ -89,8 +89,6 @@ public void UpdateVersionInfo()
if (Model == null || VersionCombobox.SelectedItem == null)
return;
- Model.Confirmation = false;
-
MelonIcon.Opacity = Model.Game.MLInstalled ? 1 : 0.3;
if (Model.Game.MLVersion == null)
@@ -139,7 +137,7 @@ private void OnInstallFinished(string? errorMessage)
if (Model == null)
return;
- bool wasReinstall = Model.Game.MLInstalled;
+ var wasReinstall = Model.Game.MLInstalled;
Model.Game.ValidateGame();
Model.Installing = false;
@@ -152,7 +150,7 @@ private void OnInstallFinished(string? errorMessage)
return;
}
- DialogBox.ShowNotice("SUCCESS!", $"{(wasReinstall ? "Reinstall" : "Install")} was Successful!");
+ DialogBox.ShowNotice("Success!", $"{(wasReinstall ? "Reinstall" : "Install")} was Successful!");
}
private void OpenDirHandler(object sender, RoutedEventArgs args)
@@ -182,7 +180,7 @@ private void UninstallHandler(object sender, RoutedEventArgs args)
}
Model.Game.ValidateGame();
- DialogBox.ShowNotice("SUCCESS!", "Uninstall was Successful!");
+ DialogBox.ShowNotice("Success!", "Uninstall was Successful!");
}
private async void SelectZipHandler(object sender, TappedEventArgs args)
diff --git a/MelonLoader.Installer/Views/DialogBox.axaml b/MelonLoader.Installer/Views/DialogBox.axaml
index 6d2813b..8640116 100644
--- a/MelonLoader.Installer/Views/DialogBox.axaml
+++ b/MelonLoader.Installer/Views/DialogBox.axaml
@@ -2,8 +2,10 @@
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:vm="clr-namespace:MelonLoader.Installer.ViewModels"
mc:Ignorable="d"
x:Class="MelonLoader.Installer.Views.DialogBox"
+ x:DataType="vm:DialogBoxModel"
Title="NOTICE"
Icon="/Assets/icon.ico"
WindowStartupLocation="CenterScreen"
@@ -14,14 +16,15 @@
SizeToContent="WidthAndHeight"
RenderOptions.BitmapInterpolationMode="HighQuality">
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
\ No newline at end of file
diff --git a/MelonLoader.Installer/Views/DialogBox.axaml.cs b/MelonLoader.Installer/Views/DialogBox.axaml.cs
index c486d2f..02a1a75 100644
--- a/MelonLoader.Installer/Views/DialogBox.axaml.cs
+++ b/MelonLoader.Installer/Views/DialogBox.axaml.cs
@@ -1,78 +1,79 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
-using Avalonia.Media.Imaging;
-using Avalonia.Platform;
+using MelonLoader.Installer.ViewModels;
namespace MelonLoader.Installer.Views;
public partial class DialogBox : Window
{
- public delegate void dCallback(object sender, RoutedEventArgs args);
- private dCallback? OnConfirm;
- private dCallback? OnCancel;
-
- private static Bitmap? ErrorIcon = new Bitmap(AssetLoader.Open(new("avares://" + typeof(GameControl).Assembly.GetName().Name + "/Assets/error.png")));
+ private Action? OnConfirm;
+ private Action? OnCancel;
public DialogBox()
=> InitializeComponent();
public static void ShowError(string message)
{
- DialogBox dialogBox = new DialogBox();
- dialogBox.Title = "ERROR";
- dialogBox.Message.Text = message;
- dialogBox.HeaderImage.Source = ErrorIcon;
- dialogBox.Open();
+ new DialogBox
+ {
+ Title = "Error",
+ DataContext = new DialogBoxModel
+ {
+ Message = message,
+ IsError = true
+ }
+ }.Open();
}
public static void ShowNotice(string message)
- => ShowNotice("NOTICE", message);
+ => ShowNotice("Notice", message);
+
public static void ShowNotice(string title, string message)
{
- DialogBox dialogBox = new DialogBox();
- dialogBox.Title = title;
- dialogBox.Message.Text = message;
- dialogBox.Open();
+ new DialogBox
+ {
+ Title = title,
+ DataContext = new DialogBoxModel
+ {
+ Message = message
+ }
+ }.Open();
}
public static void ShowConfirmation(
- string message,
- dCallback? onConfirm = null,
- dCallback? onCancel = null,
+ string message,
+ Action? onConfirm = null,
+ Action? onCancel = null,
string confirmText = "YES",
string cancelText = "NO")
- => ShowConfirmation("CONFIRMATION",
- message,
- onConfirm,
- onCancel,
- confirmText,
+ => ShowConfirmation("CONFIRMATION",
+ message,
+ onConfirm,
+ onCancel,
+ confirmText,
cancelText);
public static void ShowConfirmation(
string title,
- string message,
- dCallback? onConfirm = null,
- dCallback? onCancel = null,
+ string message,
+ Action? onConfirm = null,
+ Action? onCancel = null,
string confirmText = "YES",
string cancelText = "NO")
{
- DialogBox dialogBox = new DialogBox();
-
- dialogBox.Title = title;
- dialogBox.Message.Text = message;
-
- dialogBox.ConfirmButton.Content = confirmText;
-
- dialogBox.CancelButton.IsVisible = true;
- dialogBox.CancelButton.Content = cancelText;
-
- dialogBox.OnConfirm = onConfirm;
- dialogBox.OnCancel = onCancel;
-
- dialogBox.NoticeGrid.IsVisible = false;
- dialogBox.ConfirmationGrid.IsVisible = true;
-
- dialogBox.Open();
+ new DialogBox
+ {
+ Title = title,
+ DataContext = new DialogBoxModel
+ {
+ Message = message,
+ IsConfirmation = true,
+ ConfirmText = confirmText,
+ CancelText = cancelText
+ },
+ OnConfirm = onConfirm,
+ OnCancel = onCancel
+ }.Open();
}
private void Open()
@@ -96,12 +97,12 @@ private void BringToFront()
private void ConfirmHandler(object sender, RoutedEventArgs args)
{
Close();
- OnConfirm?.Invoke(sender, args);
+ OnConfirm?.Invoke();
}
private void CancelHandler(object sender, RoutedEventArgs args)
{
Close();
- OnCancel?.Invoke(sender, args);
+ OnCancel?.Invoke();
}
}
\ No newline at end of file
diff --git a/MelonLoader.Installer/Views/MainWindow.axaml.cs b/MelonLoader.Installer/Views/MainWindow.axaml.cs
index 4001292..5a910e7 100644
--- a/MelonLoader.Installer/Views/MainWindow.axaml.cs
+++ b/MelonLoader.Installer/Views/MainWindow.axaml.cs
@@ -48,7 +48,7 @@ private static void OnActivation(object? sender, EventArgs e)
{
if (sender is not Window window)
return;
-
+
window.Topmost = true;
window.Topmost = false;
Program.GrabAttention();