using ModpackUpdater.Manager; using ModpackUpdater.My.Resources; using Pilz.Extensions; using Pilz.UI.Symbols; using Pilz.UI.WinForms.Extensions; using System.Diagnostics; using System.Reflection; using Telerik.WinControls; using Telerik.WinControls.UI; namespace ModpackUpdater.Apps.Client; public partial class MainForm { 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 MainForm() : this(new()) { } public MainForm(UpdateCheckOptionsAdv updateOptions) { this.updateOptions = updateOptions; InitializeComponent(); Text = $"{Text} (v{Assembly.GetExecutingAssembly().GetAppVersion()})"; RadButton_Install.DefaultItem = radMenuItem_Install; RadButton_CheckForUpdates.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.update_done, SymbolSize.Small); RadButton_SearchMinecraftProfileFolder.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.opened_folder, SymbolSize.Small); RadButton_Install.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small); radMenuItem_Install.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small); radMenuItem_Repair.SvgImage = AppGlobals.Symbols.GetSvgImage(AppSymbols.wrench, SymbolSize.Small); LoadProfileToUi(); } #region Features 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 LoadProfileToUi() { loadingData = true; RadTextBox_MinecraftProfileFolder.Text = modpackInfo?.LocaLPath ?? updateOptions.ProfileFolder ?? AppConfig.Instance.LastMinecraftProfilePath ?? RadTextBox_MinecraftProfileFolder.Text; RadTextBox_ModpackConfig.Text = modpackInfo?.ConfigUrl ?? updateOptions.ModpackConfig ?? RadTextBox_ModpackConfig.Text; radTextBox_InstallKey.Text = modpackInfo?.ExtrasKey ?? updateOptions.ExtrasKey ?? radTextBox_InstallKey.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(RadTextBox_MinecraftProfileFolder.Text.Trim()); } catch { } if (loadProfileToUi) LoadProfileToUi(); try { updateConfig = ModpackConfig.LoadFromUrl(RadTextBox_ModpackConfig.Text); } catch (Exception) { } if (modpackInfo != null) features = new(updateConfig); radTextBox_InstallKey.Visible = radLabel_InstallationKey.Visible = !string.IsNullOrWhiteSpace(updateConfig.UnleashApiUrl); if (modpackInfo == null || string.IsNullOrWhiteSpace(RadTextBox_MinecraftProfileFolder.Text) /*|| modpackInfo.Valid*/) { SetStatus(LangRes.StatusText_MinecraftProfileWarning, AppGlobals.Symbols.GetSvgImage(AppSymbols.general_warning_sign, SymbolSize.Small)); 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_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_CheckForUpdates.Enabled = false; RadButton_Install.Enabled = false; return false; } RadButton_CheckForUpdates.Enabled = true; RadButton_Install.Enabled = true; return true; } private async Task ExecuteUpdate(bool doInstall, bool repair) { // Ensure set extras key modpackInfo.ExtrasKey = radTextBox_InstallKey.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.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 || repair) { 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)); // 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.GetSvgImage(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.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small)); } #endregion #region Gui private void Form1_FormClosing(object sender, FormClosingEventArgs e) { AppConfig.Instance.LastMinecraftProfilePath = RadTextBox_MinecraftProfileFolder.Text.Trim(); } private void Form1_Load(object sender, EventArgs e) { } 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).IsYes()) { SetStatus(LangRes.StatusText_InstallingAppUpdate, AppGlobals.Symbols.GetSvgImage(AppSymbols.software_installer, SymbolSize.Small)); Enabled = false; await updater.Install(); Application.Restart(); return; } CheckStatusAndUpdate(true); } private void RadTextBox_MinecraftFolder_TextInserted(object o, EventArgs args) { if (!loadingData) CheckStatusAndUpdate(false); } private void RadTextBox_ModpackUrl_TextInserted(object o, EventArgs args) { if (!loadingData) CheckStatusAndUpdate(false); } private void RadTextBox_InstallationKey_TextInserted(object o, EventArgs args) { if (!loadingData) CheckStatusAndUpdate(false); } private void ButtonX_SearchMinecraftProfile_Click(object sender, EventArgs e) { var ofd = new RadOpenFolderDialog(); if (ofd.ShowDialog(this) == DialogResult.OK) RadTextBox_MinecraftProfileFolder.Text = ofd.FileName; } private async void ButtonX_CheckForUpdates_Click(object sender, EventArgs e) { ClearStatus(); await ExecuteUpdate(false, false); } private async void RadMenuItem_Install_Click(object sender, EventArgs e) { if (!currentUpdating) { ClearStatus(); await ExecuteUpdate(true, false); } } private async void RadMenuItem_Repair_Click(object sender, EventArgs e) { if (!currentUpdating) { ClearStatus(); await ExecuteUpdate(true, true); } } #endregion }