From 1dc420235349b591582e84d09b7095eb03637a0c Mon Sep 17 00:00:00 2001 From: "waffle.lord" Date: Fri, 28 Jun 2024 21:35:27 -0400 Subject: [PATCH] add path selection page new update page WIP --- .idea/.idea.SPTInstaller/.idea/avalonia.xml | 3 + SPTInstaller/App.axaml | 3 + SPTInstaller/Helpers/FileHelper.cs | 7 + .../InstallPathSelectionViewModel.cs | 136 ++++++++++++++++++ .../ViewModels/InstallerUpdateViewModel.cs | 12 ++ .../ViewModels/MainWindowViewModel.cs | 2 +- SPTInstaller/ViewModels/PreChecksViewModel.cs | 5 +- .../Views/InstallPathSelectionView.axaml | 63 ++++++++ .../Views/InstallPathSelectionView.axaml.cs | 18 +++ SPTInstaller/Views/InstallerUpdateView.axaml | 8 ++ .../Views/InstallerUpdateView.axaml.cs | 12 ++ 11 files changed, 266 insertions(+), 3 deletions(-) create mode 100644 SPTInstaller/ViewModels/InstallPathSelectionViewModel.cs create mode 100644 SPTInstaller/ViewModels/InstallerUpdateViewModel.cs create mode 100644 SPTInstaller/Views/InstallPathSelectionView.axaml create mode 100644 SPTInstaller/Views/InstallPathSelectionView.axaml.cs create mode 100644 SPTInstaller/Views/InstallerUpdateView.axaml create mode 100644 SPTInstaller/Views/InstallerUpdateView.axaml.cs diff --git a/.idea/.idea.SPTInstaller/.idea/avalonia.xml b/.idea/.idea.SPTInstaller/.idea/avalonia.xml index c49db03..64fdacd 100644 --- a/.idea/.idea.SPTInstaller/.idea/avalonia.xml +++ b/.idea/.idea.SPTInstaller/.idea/avalonia.xml @@ -19,6 +19,9 @@ + + + diff --git a/SPTInstaller/App.axaml b/SPTInstaller/App.axaml index 3331a7d..795db43 100644 --- a/SPTInstaller/App.axaml +++ b/SPTInstaller/App.axaml @@ -48,5 +48,8 @@ + + \ No newline at end of file diff --git a/SPTInstaller/Helpers/FileHelper.cs b/SPTInstaller/Helpers/FileHelper.cs index 61681c9..786dae3 100644 --- a/SPTInstaller/Helpers/FileHelper.cs +++ b/SPTInstaller/Helpers/FileHelper.cs @@ -134,12 +134,19 @@ public static class FileHelper } } + /// + /// Check if a path is problematic + /// + /// The path the check + /// The check that failed + /// Returns true if the path is bad, otherwise false public static bool CheckPathForProblemLocations(string path, out PathCheck failedCheck) { failedCheck = new(); var problemPaths = new List() { + new("SteamApps", PathCheckType.EndsWith, PathCheckAction.Warn), new("Documents", PathCheckType.EndsWith, PathCheckAction.Warn), new("Desktop", PathCheckType.EndsWith, PathCheckAction.Deny), new("Battlestate Games", PathCheckType.Contains, PathCheckAction.Deny), diff --git a/SPTInstaller/ViewModels/InstallPathSelectionViewModel.cs b/SPTInstaller/ViewModels/InstallPathSelectionViewModel.cs new file mode 100644 index 0000000..23c93c2 --- /dev/null +++ b/SPTInstaller/ViewModels/InstallPathSelectionViewModel.cs @@ -0,0 +1,136 @@ +using System.Linq; +using System.Threading.Tasks; +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Platform.Storage; +using ReactiveUI; +using SPTInstaller.Helpers; +using SPTInstaller.Models; + +namespace SPTInstaller.ViewModels; + +public class InstallPathSelectionViewModel : ViewModelBase +{ + private bool _debugging = false; + private InternalData _data; + + private string _selectedPath; + + public string SelectedPath + { + get => _selectedPath; + set => this.RaiseAndSetIfChanged(ref _selectedPath, value); + } + + private bool _validPath; + public bool ValidPath + { + get => _validPath; + set => this.RaiseAndSetIfChanged(ref _validPath, value); + } + + private string _errorMessage; + + public string ErrorMessage + { + get => _errorMessage; + set => this.RaiseAndSetIfChanged(ref _errorMessage, value); + } + + public InstallPathSelectionViewModel(IScreen host, bool debugging) : base(host) + { + _debugging = debugging; + _data = ServiceHelper.Get() ?? throw new Exception("Failed to get internal data"); + SelectedPath = Environment.CurrentDirectory; + ValidPath = false; + + AdjustInstallPath(); + } + + public async Task SelectFolderCommand() + { + if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + if (desktop.MainWindow == null) + { + return; + } + + var startingFolderPath = Directory.Exists(SelectedPath) ? SelectedPath : Environment.CurrentDirectory; + + var suggestedFolder = await desktop.MainWindow.StorageProvider.TryGetFolderFromPathAsync(startingFolderPath); + + var selections = await desktop.MainWindow.StorageProvider.OpenFolderPickerAsync( + new FolderPickerOpenOptions() + { + AllowMultiple = false, + SuggestedStartLocation = suggestedFolder, + Title = "Select a folder to install SPT into" + }); + + SelectedPath = selections.First().Path.AbsolutePath.Replace("/", "\\"); + } + } + + public void ValidatePath() + { + if (String.IsNullOrEmpty(SelectedPath)) + { + ErrorMessage = "Please provide an install path"; + ValidPath = false; + return; + } + + if (FileHelper.CheckPathForProblemLocations(SelectedPath, out var failedCheck)) + { + if (failedCheck.CheckType == PathCheckType.EndsWith) + { + ErrorMessage = "This folder can be install in, but only in a subdirectory"; + ValidPath = false; + return; + } + + if (failedCheck.CheckAction == PathCheckAction.Deny) + { + ErrorMessage = $"Sorry, you cannot install in {failedCheck.Target}"; + ValidPath = false; + return; + } + } + + ValidPath = true; + } + + private void AdjustInstallPath() + { + if (FileHelper.CheckPathForProblemLocations(SelectedPath, out var failedCheck)) + { + switch (failedCheck.CheckType) + { + case PathCheckType.EndsWith: + SelectedPath = Path.Join(Environment.CurrentDirectory, "SPT"); + break; + + case PathCheckType.Contains: + case PathCheckType.DriveRoot: + SelectedPath = Path.Join(Directory.GetDirectoryRoot(Environment.CurrentDirectory), "SPT"); + break; + + default: + throw new ArgumentOutOfRangeException(); + } + } + } + + public async Task NextCommand() + { + if (FileHelper.CheckPathForProblemLocations(SelectedPath, out _)) + { + return; + } + + _data.TargetInstallPath = SelectedPath; + + NavigateTo(new PreChecksViewModel(HostScreen, _debugging)); + } +} \ No newline at end of file diff --git a/SPTInstaller/ViewModels/InstallerUpdateViewModel.cs b/SPTInstaller/ViewModels/InstallerUpdateViewModel.cs new file mode 100644 index 0000000..ff53ff2 --- /dev/null +++ b/SPTInstaller/ViewModels/InstallerUpdateViewModel.cs @@ -0,0 +1,12 @@ +using ReactiveUI; + +namespace SPTInstaller.ViewModels; + +public class InstallerUpdateViewModel : ViewModelBase +{ + private bool _debugging; + public InstallerUpdateViewModel(IScreen Host, bool debugging) : base(Host) + { + _debugging = debugging; + } +} \ No newline at end of file diff --git a/SPTInstaller/ViewModels/MainWindowViewModel.cs b/SPTInstaller/ViewModels/MainWindowViewModel.cs index 908320d..40fc793 100644 --- a/SPTInstaller/ViewModels/MainWindowViewModel.cs +++ b/SPTInstaller/ViewModels/MainWindowViewModel.cs @@ -31,7 +31,7 @@ public class MainWindowViewModel : ReactiveObject, IActivatableViewModel, IScree Log.Information("System Language: {iso} - {name}", uiCulture.TwoLetterISOLanguageName, uiCulture.DisplayName); - Router.Navigate.Execute(new PreChecksViewModel(this, debugging)); + Router.Navigate.Execute(new InstallerUpdateViewModel(this, debugging)); } public void CloseCommand() diff --git a/SPTInstaller/ViewModels/PreChecksViewModel.cs b/SPTInstaller/ViewModels/PreChecksViewModel.cs index 41ba8f2..089dd3b 100644 --- a/SPTInstaller/ViewModels/PreChecksViewModel.cs +++ b/SPTInstaller/ViewModels/PreChecksViewModel.cs @@ -138,7 +138,6 @@ public class PreChecksViewModel : ViewModelBase data.OriginalGamePath = PreCheckHelper.DetectOriginalGamePath(); - data.TargetInstallPath = Environment.CurrentDirectory; InstallPath = data.TargetInstallPath; Log.Information($"Install Path: {FileHelper.GetRedactedPath(InstallPath)}"); @@ -224,7 +223,8 @@ public class PreChecksViewModel : ViewModelBase { try { - var installerPath = Path.Join(_installPath, "SPTInstaller.exe"); + var installerPath = Path.Join(Environment.CurrentDirectory, "SPTInstaller.exe"); + Process.Start(new ProcessStartInfo() { FileName = installerPath, @@ -302,6 +302,7 @@ public class PreChecksViewModel : ViewModelBase var SPTReleaseInfo = JsonConvert.DeserializeObject(File.ReadAllText(SPTReleaseInfoFile.FullName)); + if (SPTReleaseInfo == null) { InstallButtonText = "Could not parse latest SPT release"; diff --git a/SPTInstaller/Views/InstallPathSelectionView.axaml b/SPTInstaller/Views/InstallPathSelectionView.axaml new file mode 100644 index 0000000..bc46f44 --- /dev/null +++ b/SPTInstaller/Views/InstallPathSelectionView.axaml @@ -0,0 +1,63 @@ + + + + + + + + + + + + +