ui: migrate client to gtk
This commit is contained in:
348
ModpackUpdater.Apps.Client/MainWindow.cs
Normal file
348
ModpackUpdater.Apps.Client/MainWindow.cs
Normal file
@@ -0,0 +1,348 @@
|
||||
using Gtk;
|
||||
using ModpackUpdater.Manager;
|
||||
using ModpackUpdater.My.Resources;
|
||||
using Pilz.Extensions;
|
||||
using Pilz.UI.Gtk.Dialogs;
|
||||
using Pilz.UI.Symbols;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using UI = Gtk.Builder.ObjectAttribute;
|
||||
|
||||
namespace ModpackUpdater.Apps.Client;
|
||||
|
||||
internal class MainWindow : Window
|
||||
{
|
||||
[UI] private readonly Entry textBox_MinecraftFolder;
|
||||
[UI] private readonly Entry textBox_ModpackUrl;
|
||||
[UI] private readonly Entry textBox_InstallationKey;
|
||||
[UI] private readonly Button button_SearchMinecraftFolder;
|
||||
[UI] private readonly Button button_Install;
|
||||
[UI] private readonly Button button_CheckForUpdates;
|
||||
[UI] private readonly ImageMenuItem menuItem_Repair;
|
||||
[UI] private readonly Label label_Status;
|
||||
[UI] private readonly Image image_Status;
|
||||
[UI] private readonly Image image_Repair;
|
||||
|
||||
private readonly UpdateCheckOptionsAdv updateOptions;
|
||||
private ModpackInfo modpackInfo = new();
|
||||
private ModpackConfig updateConfig = new();
|
||||
private ModpackFeatures features;
|
||||
private UpdateCheckResult lastUpdateCheckResult;
|
||||
private bool currentUpdating;
|
||||
private bool loadingData;
|
||||
|
||||
public MainWindow(UpdateCheckOptionsAdv updateOptions) : this(new Builder("MainWindow.glade"), updateOptions)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private MainWindow(Builder builder, UpdateCheckOptionsAdv updateOptions) : base(builder.GetRawOwnedObject("MainWindow"))
|
||||
{
|
||||
this.updateOptions = updateOptions;
|
||||
|
||||
builder.Autoconnect(this);
|
||||
|
||||
Title = $"{Title} (v{Assembly.GetExecutingAssembly().GetAppVersion()})";
|
||||
|
||||
button_CheckForUpdates.Image = AppGlobals.Symbols.GetImage(AppSymbols.update_done, SymbolSize.Small);
|
||||
button_SearchMinecraftFolder.Image = AppGlobals.Symbols.GetImage(AppSymbols.opened_folder, SymbolSize.Small);
|
||||
button_Install.Image = AppGlobals.Symbols.GetImage(AppSymbols.software_installer, SymbolSize.Small);
|
||||
image_Repair.Pixbuf = AppGlobals.Symbols.GetPixbuf(AppSymbols.wrench, SymbolSize.Small);
|
||||
|
||||
LoadProfileToUi();
|
||||
|
||||
DeleteEvent += MainWindow_DeleteEvent;
|
||||
Shown += MainWindow_Shown;
|
||||
|
||||
textBox_MinecraftFolder.Changed += TextBox_MinecraftFolder_TextInserted;
|
||||
textBox_ModpackUrl.Changed += TextBox_ModpackUrl_TextInserted;
|
||||
textBox_InstallationKey.Changed += TextBox_InstallationKey_TextInserted;
|
||||
button_SearchMinecraftFolder.Clicked += Button_SearchMinecraftFolder_Clicked;
|
||||
button_Install.Clicked += Button_Install_Clicked;
|
||||
button_CheckForUpdates.Clicked += Button_CheckForUpdates_Clicked;
|
||||
menuItem_Repair.Activated += MenuItem_Repair_Activated;
|
||||
}
|
||||
|
||||
#region Gui
|
||||
|
||||
private void MainWindow_DeleteEvent(object o, DeleteEventArgs args)
|
||||
{
|
||||
AppConfig.Instance.LastMinecraftProfilePath = textBox_MinecraftFolder.Text.Trim();
|
||||
Application.Quit();
|
||||
}
|
||||
|
||||
private async void MainWindow_Shown(object sender, EventArgs e)
|
||||
{
|
||||
var updater = new AppUpdater();
|
||||
if (!updateOptions.NoUpdate && await updater.Check() && MessageBox.Show(this, ButtonsType.YesNo, MessageType.Info, LangRes.MsgBox_UpdateAvailable) == ResponseType.Yes)
|
||||
{
|
||||
SetStatus(LangRes.StatusText_InstallingAppUpdate, AppGlobals.Symbols.GetPixbuf(AppSymbols.software_installer, SymbolSize.Small));
|
||||
Sensitive = false;
|
||||
await updater.Install();
|
||||
Program.Restart();
|
||||
return;
|
||||
}
|
||||
|
||||
CheckStatusAndUpdate(true);
|
||||
LoadProfileToUi();
|
||||
}
|
||||
|
||||
private void TextBox_MinecraftFolder_TextInserted(object o, EventArgs args)
|
||||
{
|
||||
if (!loadingData)
|
||||
CheckStatusAndUpdate(false);
|
||||
}
|
||||
|
||||
private void TextBox_ModpackUrl_TextInserted(object o, EventArgs args)
|
||||
{
|
||||
if (!loadingData)
|
||||
CheckStatusAndUpdate(false);
|
||||
}
|
||||
|
||||
private void TextBox_InstallationKey_TextInserted(object o, EventArgs args)
|
||||
{
|
||||
if (!loadingData)
|
||||
CheckStatusAndUpdate(false);
|
||||
}
|
||||
|
||||
private void Button_SearchMinecraftFolder_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
var ofd = new FileChooserDialog("Select Minecraft profile folder", this, FileChooserAction.SelectFolder, "Accept", ResponseType.Ok, "Cancel", ResponseType.Cancel);
|
||||
ofd.Response += SearchMinecraftFolder_Response;
|
||||
ofd.Present();
|
||||
}
|
||||
|
||||
private void SearchMinecraftFolder_Response(object o, ResponseArgs args)
|
||||
{
|
||||
if (o is not FileChooserDialog ofd)
|
||||
return;
|
||||
if (args.ResponseId == ResponseType.Ok)
|
||||
textBox_MinecraftFolder.Text = ofd.Filename;
|
||||
ofd.Destroy();
|
||||
}
|
||||
|
||||
private async void Button_CheckForUpdates_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
ClearStatus();
|
||||
await ExecuteUpdate(false, false);
|
||||
}
|
||||
|
||||
private async void Button_Install_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (!currentUpdating)
|
||||
{
|
||||
ClearStatus();
|
||||
await ExecuteUpdate(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
private async void MenuItem_Repair_Activated(object sender, EventArgs e)
|
||||
{
|
||||
if (!currentUpdating)
|
||||
{
|
||||
ClearStatus();
|
||||
await ExecuteUpdate(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Features
|
||||
|
||||
private void SetStatus(string statusText, Gdk.Pixbuf image)
|
||||
{
|
||||
label_Status.Text = statusText;
|
||||
image_Status.Pixbuf = image;
|
||||
}
|
||||
|
||||
private void ClearStatus()
|
||||
{
|
||||
label_Status.Text = "-";
|
||||
image_Status.Pixbuf = null;
|
||||
}
|
||||
|
||||
private void LoadProfileToUi()
|
||||
{
|
||||
loadingData = true;
|
||||
textBox_MinecraftFolder.Text = modpackInfo?.LocaLPath ?? updateOptions.ProfileFolder ?? AppConfig.Instance.LastMinecraftProfilePath ?? textBox_MinecraftFolder.Text;
|
||||
textBox_ModpackUrl.Text = modpackInfo?.ConfigUrl ?? updateOptions.ModpackConfig ?? textBox_ModpackUrl.Text;
|
||||
textBox_InstallationKey.Text = modpackInfo?.ExtrasKey ?? updateOptions.ExtrasKey ?? textBox_InstallationKey.Text;
|
||||
loadingData = false;
|
||||
}
|
||||
|
||||
private async void CheckStatusAndUpdate(bool loadProfileToUi)
|
||||
{
|
||||
if (CheckStatus(loadProfileToUi))
|
||||
await ExecuteUpdate(false, false);
|
||||
}
|
||||
|
||||
private bool CheckStatus(bool loadProfileToUi)
|
||||
{
|
||||
try
|
||||
{
|
||||
modpackInfo = ModpackInfo.TryLoad(textBox_MinecraftFolder.Text.Trim());
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
if (loadProfileToUi)
|
||||
LoadProfileToUi();
|
||||
|
||||
try
|
||||
{
|
||||
updateConfig = ModpackConfig.LoadFromUrl(textBox_ModpackUrl.Text);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
if (modpackInfo != null)
|
||||
features = new(updateConfig);
|
||||
|
||||
if (modpackInfo == null || string.IsNullOrWhiteSpace(textBox_MinecraftFolder.Text) /*|| modpackInfo.Valid*/)
|
||||
{
|
||||
SetStatus(LangRes.StatusText_MinecraftProfileWarning, AppGlobals.Symbols.GetPixbuf(AppSymbols.general_warning_sign, SymbolSize.Small));
|
||||
button_CheckForUpdates.Sensitive = false;
|
||||
button_Install.Sensitive = false;
|
||||
return false;
|
||||
}
|
||||
else if (updateConfig == null || string.IsNullOrWhiteSpace(textBox_ModpackUrl.Text))
|
||||
{
|
||||
SetStatus(LangRes.StatusText_ConfigIncompleteOrNotLoaded, AppGlobals.Symbols.GetPixbuf(AppSymbols.general_warning_sign, SymbolSize.Small));
|
||||
button_CheckForUpdates.Sensitive = false;
|
||||
button_Install.Sensitive = false;
|
||||
return false;
|
||||
}
|
||||
else if (updateConfig.Maintenance && !updateOptions.IgnoreMaintenance)
|
||||
{
|
||||
SetStatus(LangRes.StatusText_Maintenance, AppGlobals.Symbols.GetPixbuf(AppSymbols.services, SymbolSize.Small));
|
||||
button_CheckForUpdates.Sensitive = false;
|
||||
button_Install.Sensitive = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
button_CheckForUpdates.Sensitive = true;
|
||||
button_Install.Sensitive = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task ExecuteUpdate(bool doInstall, bool repair)
|
||||
{
|
||||
// Ensure set extras key
|
||||
modpackInfo.ExtrasKey = textBox_InstallationKey.Text.Trim();
|
||||
|
||||
var updater = new ModpackInstaller(updateConfig, modpackInfo)
|
||||
{
|
||||
OverwriteRefTag = Program.Options.RefTag,
|
||||
OverwriteVersion = Program.Options.Version,
|
||||
};
|
||||
updater.InstallProgessUpdated += Update_InstallProgessUpdated;
|
||||
updater.CheckingProgressUpdated += Updated_CheckingProgresssUpdated;
|
||||
|
||||
void error()
|
||||
{
|
||||
SetStatus(LangRes.StatusText_ErrorWhileUpdateCheckOrUpdate, AppGlobals.Symbols.GetPixbuf(AppSymbols.close, SymbolSize.Small));
|
||||
currentUpdating = false;
|
||||
}
|
||||
void installing()
|
||||
{
|
||||
SetStatus(LangRes.StatusText_Installing, AppGlobals.Symbols.GetPixbuf(AppSymbols.software_installer, SymbolSize.Small));
|
||||
currentUpdating = true;
|
||||
}
|
||||
void updatesAvailable()
|
||||
{
|
||||
SetStatus(LangRes.StatusText_UpdateAvailable, AppGlobals.Symbols.GetPixbuf(AppSymbols.software_installer, SymbolSize.Small));
|
||||
}
|
||||
void everythingOk()
|
||||
{
|
||||
SetStatus(LangRes.StatusTest_EverythingOk, AppGlobals.Symbols.GetPixbuf(AppSymbols.done, SymbolSize.Small));
|
||||
currentUpdating = false;
|
||||
}
|
||||
|
||||
// Check only if not pressed "install", not really needed otherwise.
|
||||
if (lastUpdateCheckResult is null || !doInstall || repair)
|
||||
{
|
||||
SetStatus(LangRes.StatusText_CheckingForUpdates, AppGlobals.Symbols.GetPixbuf(AppSymbols.update_done, SymbolSize.Small));
|
||||
|
||||
// Check for extras once again
|
||||
updateOptions.IncludeExtras = features.IsEnabled(ModpackFeatures.FeatureAllowExtas, new AllowExtrasFeatureContext(modpackInfo));
|
||||
|
||||
// Force re-install on repair
|
||||
updateOptions.IgnoreInstalledVersion = repair;
|
||||
|
||||
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 Updated_CheckingProgresssUpdated(int toCheck, int processed)
|
||||
{
|
||||
SetStatus(Math.Round(processed / (double)toCheck * 100d, 1) + "%", AppGlobals.Symbols.GetPixbuf(AppSymbols.update_done, SymbolSize.Small));
|
||||
}
|
||||
|
||||
private void Update_InstallProgessUpdated(UpdateCheckResult result, int processedSyncs)
|
||||
{
|
||||
int actionCount = result.Actions.Count;
|
||||
SetStatus(Math.Round(processedSyncs / (double)actionCount * 100d, 1) + "%", AppGlobals.Symbols.GetPixbuf(AppSymbols.software_installer, SymbolSize.Small));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user