SPT-AKI-Installer/SPTInstaller/ViewModels/PreChecksViewModel.cs

239 lines
8.0 KiB
C#

using System.Collections.ObjectModel;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Input;
using Avalonia.Controls;
using Avalonia.Threading;
using DialogHostAvalonia;
using Gitea.Api;
using Gitea.Client;
using ReactiveUI;
using Serilog;
using SPTInstaller.Controllers;
using SPTInstaller.CustomControls;
using SPTInstaller.CustomControls.Dialogs;
using SPTInstaller.Helpers;
using SPTInstaller.Models;
namespace SPTInstaller.ViewModels;
public class PreChecksViewModel : ViewModelBase
{
public ObservableCollection<PreCheckBase> PreChecks { get; set; } = new(ServiceHelper.GetAll<PreCheckBase>());
public ICommand StartInstallCommand { get; set; }
public ICommand ShowDetailedViewCommand { get; set; }
public ICommand UpdateInstallerCommand { get; set; }
public ICommand DismissUpdateCommand { get; set; }
public InstallerUpdateInfo UpdateInfo { get; set; } = new();
private string _installPath;
public string InstallPath
{
get => _installPath;
set => this.RaiseAndSetIfChanged(ref _installPath, value);
}
private string _installButtonText;
public string InstallButtonText
{
get => _installButtonText;
set => this.RaiseAndSetIfChanged(ref _installButtonText, value);
}
private bool _allowInstall;
public bool AllowInstall
{
get => _allowInstall;
set => this.RaiseAndSetIfChanged(ref _allowInstall, value);
}
private bool _allowDetailsButton = false;
public bool AllowDetailsButton
{
get => _allowDetailsButton;
set => this.RaiseAndSetIfChanged(ref _allowDetailsButton, value);
}
private string _cacheInfoText;
public string CacheInfoText
{
get => _cacheInfoText;
set => this.RaiseAndSetIfChanged(ref _cacheInfoText, value);
}
private StatusSpinner.SpinnerState _cacheCheckState;
public StatusSpinner.SpinnerState CacheCheckState
{
get => _cacheCheckState;
set => this.RaiseAndSetIfChanged(ref _cacheCheckState, value);
}
private StatusSpinner.SpinnerState _installButtonCheckState;
public StatusSpinner.SpinnerState InstallButtonCheckState
{
get => _installButtonCheckState;
set => this.RaiseAndSetIfChanged(ref _installButtonCheckState, value);
}
private void ReCheckRequested(object? sender, EventArgs e)
{
Task.Run(async () =>
{
if (sender is InstallController installer)
{
var result = await installer.RunPreChecks();
AllowInstall = result.Succeeded;
}
});
}
public PreChecksViewModel(IScreen host) : base(host)
{
var data = ServiceHelper.Get<InternalData?>();
var installer = ServiceHelper.Get<InstallController?>();
installer.RecheckRequested += ReCheckRequested;
InstallButtonText = "Please wait ...";
InstallButtonCheckState = StatusSpinner.SpinnerState.Pending;
if (data == null || installer == null)
{
NavigateTo(new MessageViewModel(HostScreen, Result.FromError("Failed to get required service for prechecks")));
return;
}
data.OriginalGamePath = PreCheckHelper.DetectOriginalGamePath();
data.TargetInstallPath = Environment.CurrentDirectory;
InstallPath = data.TargetInstallPath;
Log.Information($"Install Path: {FileHelper.GetRedactedPath(InstallPath)}");
#if !TEST
if (data.OriginalGamePath == null)
{
NavigateTo(new MessageViewModel(HostScreen, Result.FromError("Could not find EFT install.\n\nDo you own and have the game installed?")));
return;
}
#endif
if (data.OriginalGamePath == data.TargetInstallPath)
{
Log.CloseAndFlush();
var logFiles = Directory.GetFiles(InstallPath, "spt-aki-installer_*.log");
// remove log file from original game path if they exist
foreach (var file in logFiles)
{
try
{
File.Delete(file);
}
catch { }
}
NavigateTo(new MessageViewModel(HostScreen, Result.FromError("Installer is located in EFT's original directory. Please move the installer to a seperate folder as per the guide"), noLog: true));
return;
}
Task.Run(async () =>
{
if (FileHelper.CheckPathForProblemLocations(InstallPath, out var detectedName))
{
await Dispatcher.UIThread.InvokeAsync(async () =>
{
Log.Warning("Problem folder detected, confirming install path ...");
var confirmation = await DialogHost.Show(new ConfirmationDialog($"We suspect you may be installing into a problematic folder: {detectedName}.\nYou might want to consider installing somewhere else to avoid issues.\n\nAre you sure you want to install to this path?\n{InstallPath}"));
if (confirmation == null || !bool.TryParse(confirmation.ToString(), out var confirm) || !confirm)
{
Log.Information("User declined install path, exiting");
Environment.Exit(0);
}
});
Log.Information("User accepted install path");
}
});
StartInstallCommand = ReactiveCommand.Create(async () =>
{
UpdateInfo.ShowCard = false;
NavigateTo(new InstallViewModel(HostScreen));
});
ShowDetailedViewCommand = ReactiveCommand.Create(() =>
{
UpdateInfo.ShowCard = false;
Log.Logger.Information("Opening Detailed PreCheck View");
installer.RecheckRequested -= ReCheckRequested;
NavigateTo(new DetailedPreChecksViewModel(HostScreen));
});
UpdateInstallerCommand = ReactiveCommand.Create(async () =>
{
AllowDetailsButton = false;
AllowInstall = false;
await UpdateInfo.UpdateInstaller();
});
DismissUpdateCommand = ReactiveCommand.Create(() =>
{
UpdateInfo.ShowCard = false;
});
Task.Run(async () =>
{
// run prechecks
var result = await installer.RunPreChecks();
// check for updates
await UpdateInfo.CheckForUpdates(Assembly.GetExecutingAssembly().GetName()?.Version);
// get latest spt version
InstallButtonText = "Getting latest release ...";
InstallButtonCheckState = StatusSpinner.SpinnerState.Running;
var repo = new RepositoryApi(Configuration.Default);
var akiRepoReleases = await repo.RepoListReleasesAsync("SPT-AKI", "Stable-releases");
if (akiRepoReleases == null || akiRepoReleases.Count == 0)
{
InstallButtonText = "Could not get SPT releases from repo";
InstallButtonCheckState = StatusSpinner.SpinnerState.Error;
return;
}
var latestAkiRelease = akiRepoReleases.FindAll(x => !x.Prerelease)[0];
if (latestAkiRelease == null)
{
InstallButtonText = "Could not find the latest SPT release";
InstallButtonCheckState = StatusSpinner.SpinnerState.Error;
return;
}
InstallButtonText = $"Start Install: SPT v{latestAkiRelease.TagName}";
InstallButtonCheckState = StatusSpinner.SpinnerState.OK;
AllowDetailsButton = true;
AllowInstall = result.Succeeded;
});
Task.Run(() =>
{
CacheInfoText = "Getting cache size ...";
CacheCheckState = StatusSpinner.SpinnerState.Running;
CacheInfoText = $"Cache Size: {DownloadCacheHelper.GetCacheSizeText()}";
CacheCheckState = StatusSpinner.SpinnerState.OK;
});
}
}