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

303 lines
10 KiB
C#
Raw Normal View History

using System.Collections.ObjectModel;
2024-02-06 18:59:39 -05:00
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows.Input;
using Avalonia.Threading;
2023-08-22 10:21:52 -04:00
using DialogHostAvalonia;
using Newtonsoft.Json;
using ReactiveUI;
2023-07-29 14:26:45 -04:00
using Serilog;
2023-05-11 23:11:39 -04:00
using SPTInstaller.Controllers;
2023-08-25 23:46:11 -04:00
using SPTInstaller.CustomControls;
2023-08-22 10:21:52 -04:00
using SPTInstaller.CustomControls.Dialogs;
2023-05-11 23:11:39 -04:00
using SPTInstaller.Helpers;
using SPTInstaller.Models;
using SPTInstaller.Models.ReleaseInfo;
2023-05-11 23:11:39 -04:00
namespace SPTInstaller.ViewModels;
public class PreChecksViewModel : ViewModelBase
2023-05-11 23:11:39 -04:00
{
2024-03-25 18:19:16 -04:00
private bool _hasPreCheckSelected;
2024-05-01 10:31:55 -04:00
2024-03-25 18:19:16 -04:00
public bool HasPreCheckSelected
{
2024-03-25 18:19:16 -04:00
get => _hasPreCheckSelected;
set => this.RaiseAndSetIfChanged(ref _hasPreCheckSelected, value);
}
public ObservableCollection<PreCheckBase> PreChecks { get; set; } = new(ServiceHelper.GetAll<PreCheckBase>());
public ICommand SelectPreCheckCommand { get; set; }
public ICommand StartInstallCommand { get; set; }
2024-05-01 10:31:55 -04:00
2024-02-06 18:59:39 -05:00
public ICommand LaunchWithDebug { get; set; }
2024-05-01 10:31:55 -04:00
2024-02-06 18:59:39 -05:00
private bool _debugging;
2024-05-01 10:31:55 -04:00
2024-02-06 18:59:39 -05:00
public bool Debugging
{
get => _debugging;
set => this.RaiseAndSetIfChanged(ref _debugging, value);
}
2024-05-01 10:31:55 -04:00
2023-08-03 18:02:38 -04:00
private string _installPath;
2024-05-01 10:31:55 -04:00
public string InstallPath
{
get => _installPath;
set => this.RaiseAndSetIfChanged(ref _installPath, value);
}
2024-05-01 10:31:55 -04:00
private string _installButtonText;
2024-05-01 10:31:55 -04:00
public string InstallButtonText
{
get => _installButtonText;
set => this.RaiseAndSetIfChanged(ref _installButtonText, value);
}
2023-07-12 09:00:00 +02:00
2023-08-03 18:02:38 -04:00
private bool _allowInstall;
2024-05-01 10:31:55 -04:00
2023-07-30 16:15:52 -04:00
public bool AllowInstall
2023-07-12 09:00:00 +02:00
{
2023-07-12 16:39:37 +02:00
get => _allowInstall;
set => this.RaiseAndSetIfChanged(ref _allowInstall, value);
2023-07-12 09:00:00 +02:00
}
2024-05-01 10:31:55 -04:00
private bool _allowDetailsButton = false;
2024-05-01 10:31:55 -04:00
2023-08-03 18:02:38 -04:00
public bool AllowDetailsButton
{
get => _allowDetailsButton;
set => this.RaiseAndSetIfChanged(ref _allowDetailsButton, value);
}
2024-05-01 10:31:55 -04:00
2023-08-25 23:46:11 -04:00
private string _cacheInfoText;
2024-05-01 10:31:55 -04:00
2023-08-25 23:46:11 -04:00
public string CacheInfoText
{
get => _cacheInfoText;
set => this.RaiseAndSetIfChanged(ref _cacheInfoText, value);
}
2024-05-01 10:31:55 -04:00
2023-08-25 23:46:11 -04:00
private StatusSpinner.SpinnerState _cacheCheckState;
2024-05-01 10:31:55 -04:00
2023-08-25 23:46:11 -04:00
public StatusSpinner.SpinnerState CacheCheckState
{
get => _cacheCheckState;
set => this.RaiseAndSetIfChanged(ref _cacheCheckState, value);
}
private StatusSpinner.SpinnerState _installButtonCheckState;
2024-05-01 10:31:55 -04:00
public StatusSpinner.SpinnerState InstallButtonCheckState
{
get => _installButtonCheckState;
set => this.RaiseAndSetIfChanged(ref _installButtonCheckState, value);
}
2024-05-01 10:31:55 -04:00
private void ReCheckRequested(object? sender, EventArgs e)
{
Task.Run(async () =>
{
if (sender is InstallController installer)
{
var result = await installer.RunPreChecks();
AllowInstall = result.Succeeded;
}
});
}
2024-05-01 10:31:55 -04:00
2024-02-06 18:59:39 -05:00
public PreChecksViewModel(IScreen host, bool debugging) : base(host)
{
2024-02-06 18:59:39 -05:00
Debugging = debugging;
var data = ServiceHelper.Get<InternalData?>();
var installer = ServiceHelper.Get<InstallController?>();
2024-05-01 10:31:55 -04:00
installer.RecheckRequested += ReCheckRequested;
2024-05-01 10:31:55 -04:00
InstallButtonText = "Please wait ...";
InstallButtonCheckState = StatusSpinner.SpinnerState.Pending;
2024-05-01 10:31:55 -04:00
if (data == null || installer == null)
2023-05-11 23:11:39 -04:00
{
2024-05-01 10:31:55 -04:00
NavigateTo(new MessageViewModel(HostScreen,
Result.FromError("Failed to get required service for prechecks")));
return;
}
2024-05-01 10:31:55 -04:00
data.OriginalGamePath = PreCheckHelper.DetectOriginalGamePath();
InstallPath = data.TargetInstallPath;
2024-05-01 10:31:55 -04:00
Log.Information($"Install Path: {FileHelper.GetRedactedPath(InstallPath)}");
2024-05-01 10:31:55 -04:00
2023-08-22 10:21:52 -04:00
#if !TEST
if (data.OriginalGamePath == null)
{
2024-05-01 10:31:55 -04:00
NavigateTo(new MessageViewModel(HostScreen,
Result.FromError("Could not find where you installed EFT.\n\nDo you own and have the game installed?")));
return;
}
2023-08-22 10:21:52 -04:00
#endif
2024-05-01 10:31:55 -04:00
if (data.OriginalGamePath == data.TargetInstallPath)
{
Log.CloseAndFlush();
2024-05-01 10:31:55 -04:00
var logFiles = Directory.GetFiles(InstallPath, "spt-installer_*.log");
2024-05-01 10:31:55 -04:00
// remove log file from original game path if they exist
foreach (var file in logFiles)
{
try
{
File.Delete(file);
}
2024-05-01 10:31:55 -04:00
catch
{
}
}
2024-05-01 10:31:55 -04:00
NavigateTo(new MessageViewModel(HostScreen,
Result.FromError(
2024-06-29 11:25:30 -04:00
"You have chosen to install in the same folder as EFT. Please choose a another folder. Refer to the install guide on where best to place the installer before running it."),
2024-05-01 10:31:55 -04:00
noLog: true));
return;
}
2024-05-01 10:31:55 -04:00
Task.Run(async () =>
2023-07-30 16:15:52 -04:00
{
2024-05-01 10:31:55 -04:00
if (FileHelper.CheckPathForProblemLocations(InstallPath, out var failedCheck))
2023-08-22 10:21:52 -04:00
{
2024-05-01 10:31:55 -04:00
switch (failedCheck.CheckAction)
{
case PathCheckAction.Warn:
{
2024-05-01 10:31:55 -04:00
await Dispatcher.UIThread.InvokeAsync(async () =>
{
2024-05-01 10:31:55 -04:00
Log.Warning("Problem path detected, confirming install path ...");
var confirmation = await DialogHost.Show(new ConfirmationDialog(
$"It appears you are installing into a folder known to cause problems: {failedCheck.Target}." +
$"\nPlease consider installing SPT somewhere else to avoid issues later on." +
$"\n\nAre you sure you want to install to this path?\n{InstallPath}"));
2024-05-01 10:31:55 -04:00
if (confirmation == null || !bool.TryParse(confirmation.ToString(), out var confirm) ||
!confirm)
{
2024-06-29 11:05:35 -04:00
Log.Information("User declined install path");
NavigateBack();
2024-05-01 10:31:55 -04:00
}
});
2024-05-01 10:31:55 -04:00
break;
}
2024-05-01 10:31:55 -04:00
case PathCheckAction.Deny:
{
Log.Error("Problem path detected, install denied");
NavigateTo(new MessageViewModel(HostScreen,
Result.FromError(
2024-06-29 11:25:30 -04:00
$"We suspect you may be installing into a problematic folder: {failedCheck.Target}.\nWe won't be letting you install here. How did you do this?")));
2024-05-01 10:31:55 -04:00
break;
}
default:
throw new ArgumentOutOfRangeException();
}
Log.Information("User accepted install path");
2023-08-22 10:21:52 -04:00
}
});
2024-05-01 10:31:55 -04:00
2024-02-06 18:59:39 -05:00
LaunchWithDebug = ReactiveCommand.Create(async () =>
{
try
{
var installerPath = Path.Join(Environment.CurrentDirectory, "SPTInstaller.exe");
2024-02-06 18:59:39 -05:00
Process.Start(new ProcessStartInfo()
{
FileName = installerPath,
Arguments = "debug"
});
2024-05-01 10:31:55 -04:00
2024-02-06 18:59:39 -05:00
Environment.Exit(0);
}
catch (Exception ex)
{
Log.Error(ex, "Failed to enter debug mode");
}
});
2024-05-01 10:31:55 -04:00
SelectPreCheckCommand = ReactiveCommand.Create(async (PreCheckBase check) =>
{
foreach (var precheck in PreChecks)
{
if (check.Id == precheck.Id)
{
precheck.IsSelected = true;
2024-05-01 10:31:55 -04:00
2024-03-25 18:19:16 -04:00
HasPreCheckSelected = true;
continue;
}
2024-05-01 10:31:55 -04:00
precheck.IsSelected = false;
}
2023-07-30 16:15:52 -04:00
});
2024-05-01 10:31:55 -04:00
StartInstallCommand = ReactiveCommand.Create(async () =>
2023-07-29 14:26:45 -04:00
{
NavigateTo(new InstallViewModel(HostScreen));
2023-07-29 14:26:45 -04:00
});
2024-05-01 10:31:55 -04:00
Task.Run(async () =>
{
// run prechecks
var result = await installer.RunPreChecks();
2024-05-01 10:31:55 -04:00
// get latest spt version
InstallButtonText = "Getting latest release ...";
InstallButtonCheckState = StatusSpinner.SpinnerState.Running;
2024-05-01 10:31:55 -04:00
var progress = new Progress<double>((d) => { });
2024-05-04 16:18:49 -04:00
var SPTReleaseInfoFile =
2024-05-04 16:18:49 -04:00
await DownloadCacheHelper.GetOrDownloadFileAsync("release.json", DownloadCacheHelper.ReleaseMirrorUrl,
progress, DownloadCacheHelper.SuggestedTtl);
if (SPTReleaseInfoFile == null)
{
InstallButtonText = "Could not get SPT release metadata";
InstallButtonCheckState = StatusSpinner.SpinnerState.Error;
return;
}
2024-05-01 10:31:55 -04:00
var SPTReleaseInfo =
JsonConvert.DeserializeObject<ReleaseInfo>(File.ReadAllText(SPTReleaseInfoFile.FullName));
if (SPTReleaseInfo == null)
{
InstallButtonText = "Could not parse latest SPT release";
InstallButtonCheckState = StatusSpinner.SpinnerState.Error;
return;
}
2024-05-01 10:31:55 -04:00
InstallButtonText = $"Start Install: SPT v{SPTReleaseInfo.SPTVersion}";
InstallButtonCheckState = StatusSpinner.SpinnerState.OK;
2023-08-03 18:02:38 -04:00
AllowDetailsButton = true;
2023-07-12 16:39:37 +02:00
AllowInstall = result.Succeeded;
});
2024-05-01 10:31:55 -04:00
2023-08-25 23:46:11 -04:00
Task.Run(() =>
{
CacheInfoText = "Getting cache size ...";
CacheCheckState = StatusSpinner.SpinnerState.Running;
2024-05-01 10:31:55 -04:00
2023-08-25 23:46:11 -04:00
CacheInfoText = $"Cache Size: {DownloadCacheHelper.GetCacheSizeText()}";
CacheCheckState = StatusSpinner.SpinnerState.OK;
});
2023-05-11 23:11:39 -04:00
}
}