Skip to content

Commit

Permalink
Add CancelButton, hook up install button to install command again
Browse files Browse the repository at this point in the history
  • Loading branch information
tr4wzified committed Dec 1, 2024
1 parent 6b8a232 commit 4efe3fd
Show file tree
Hide file tree
Showing 7 changed files with 317 additions and 24 deletions.
249 changes: 249 additions & 0 deletions ';w
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Input;
using DynamicData.Binding;
using MahApps.Metro.Controls;
using Microsoft.Extensions.Logging;
using ReactiveUI;
using Wabbajack.Common;
using Wabbajack.Messages;
using Wabbajack.Paths.IO;
using Wabbajack.Util;
using ReactiveMarbles.ObservableEvents;
using System.Reactive;
using System.Diagnostics;

namespace Wabbajack;

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : MetroWindow
{
private MainWindowVM _mwvm;
private readonly ILogger<MainWindow> _logger;
private readonly SystemParametersConstructor _systemParams;
private readonly Stopwatch _mousePressedTimer;

public MainWindow(ILogger<MainWindow> logger, SystemParametersConstructor systemParams, LauncherUpdater updater, MainWindowVM vm)
{
InitializeComponent();
_mwvm = vm;
DataContext = vm;
_logger = logger;
_systemParams = systemParams;
_mousePressedTimer = new Stopwatch();

try
{
// Wire any unhandled crashing exceptions to log before exiting
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
// Don't do any special logging side effects
_logger.LogError((Exception)e.ExceptionObject, "Uncaught error");
Environment.Exit(-1);
};

Closed += (s, e) =>
{
_logger.LogInformation("Beginning shutdown...");
_mwvm.CancelRunningTasks(TimeSpan.FromSeconds(10));

// Cleaning the temp folder when the app closes since it can take up multiple Gigabytes of Storage
var tempDirectory = Environment.CurrentDirectory + "\\temp";
_logger.LogInformation("Clearing {TempDir}",tempDirectory);
var directoryInfo = new DirectoryInfo(tempDirectory);
try
{
foreach (var file in directoryInfo.EnumerateFiles())
{
file.Delete();
}

foreach (var dir in directoryInfo.EnumerateDirectories())
{
dir.Delete(true);
}

_logger.LogInformation("Finished clearing {TempDir}", tempDirectory);
}
catch (DirectoryNotFoundException)
{
_logger.LogInformation("Unable to find {TempDir}", tempDirectory);
}

Application.Current.Shutdown();
};

MessageBus.Current.Listen<TaskBarUpdate>()
.ObserveOnGuiThread()
.Subscribe(u =>
{
TaskbarItemInfoControl.Description = u.Description;
TaskbarItemInfoControl.ProgressValue = u.ProgressValue;
TaskbarItemInfoControl.ProgressState = u.State;
});


_logger.LogInformation("Wabbajack Build - {Sha}",ThisAssembly.Git.Sha);
_logger.LogInformation("Running in {EntryPoint}", KnownFolders.EntryPoint);

var p = _systemParams.Create();

_logger.LogInformation("Detected Windows Version: {Version}", Environment.OSVersion.VersionString);

_logger.LogInformation(
"System settings - ({MemorySize} RAM) ({PageSize} Page), Display: {ScreenWidth} x {ScreenHeight} ({Vram} VRAM - VideoMemorySizeMb={ENBVRam})",
p.SystemMemorySize.ToFileSizeString(), p.SystemPageSize.ToFileSizeString(), p.ScreenWidth, p.ScreenHeight, p.VideoMemorySize.ToFileSizeString(), p.EnbLEVRAMSize);

if (p.SystemPageSize == 0)
_logger.LogInformation("Pagefile is disabled! This will cause issues such as crashing with Wabbajack and other applications!");

var _ = updater.Run();

// Bring window to the front if it isn't already
this.Initialized += (s, e) =>
{
this.Activate();
this.Topmost = true;
this.Focus();
};
this.ContentRendered += (s, e) =>
{
this.Topmost = false;
};

vm.WhenAnyValue(vm => vm.ActivePane)
.Subscribe(pane => WizardSteps.Visibility = (pane is IProgressVM) ? Visibility.Visible : Visibility.Collapsed);

vm.WhenAnyValue(vm => vm.ActivePane)
.Where(pane => pane is IProgressVM)
.Subscribe(pane =>
{
var wizardVM = (ProgressViewModel)pane;

wizardVM.WhenAnyValue(x => x.ConfigurationText)
.BindTo(this, view => view.ConfigurationText.Text)
.DisposeWith(wizardVM.CompositeDisposable);
wizardVM.WhenAnyValue(x => x.ProgressText)
.BindTo(this, view => view.ProgressText.Text)
.DisposeWith(wizardVM.CompositeDisposable);
wizardVM.WhenAnyValue(x => x.ProgressPercent.Value)
.Select(x => x.IsGreaterThan(0) && !x.IsOne() ? Visibility.Visible : Visibility.Hidden)
.BindTo(this, view => view.ProgressPercentage.Visibility)
.DisposeWith(wizardVM.CompositeDisposable);
wizardVM.WhenAnyValue(x => x.ProgressPercent.Value)
.Select(x => (int)(x * 100) + "%")
.BindTo(this, view => view.ProgressPercentage.Text)
.DisposeWith(wizardVM.CompositeDisposable);
wizardVM.WhenAnyValue(x => x.ProgressPercent.Value)
.BindTo(this, view => view.WizardProgress.Value)
.DisposeWith(wizardVM.CompositeDisposable);
wizardVM.WhenAnyValue(x => x.CurrentStep)
.ObserveOnGuiThread()
.Subscribe(step =>
{
ConfigurationText.Width = double.NaN;
ConfigurationText.HorizontalAlignment = HorizontalAlignment.Center;
ProgressText.Width = double.NaN;
ProgressText.HorizontalAlignment = HorizontalAlignment.Center;
if (step == Step.Configuration)
{
ConfigurationText.Width = 500;
ConfigurationText.HorizontalAlignment = HorizontalAlignment.Left;
}
else if (step == Step.Busy)
{
ProgressText.Width = 500;
ProgressText.HorizontalAlignment = HorizontalAlignment.Left;
}
})
.DisposeWith(wizardVM.CompositeDisposable);

});

vm.WhenAnyValue(vm => vm.ActivePane)
.Subscribe(pane => InfoButton.Visibility = (pane is IHasInfoVM) ? Visibility.Visible : Visibility.Collapsed);
vm.WhenAnyValue(vm => vm.InfoCommand)
.BindTo(this, view => view.InfoButton.Command);

vm.WhenAnyValue(vm => vm.MinimizeCommand)
.BindTo(this, view => view.MinimizeButton.Command);

vm.WhenAnyValue(vm => vm.MaximizeCommand)
.BindTo(this, view => view.MaximizeButton.Command);

vm.WhenAnyValue(vm => vm.CloseCommand)
.BindTo(this, view => view.CloseButton.Command);

vm.WhenAnyValue(vm => vm.NavigationVisible)
.Subscribe(v => NavigationColumn.Width = v ? new GridLength(115, GridUnitType.Pixel) : new GridLength(0, GridUnitType.Pixel));

TitleBar.Events().MouseDown
.Subscribe(x => TitleBar_OnMouseDown(this, x));

FloatingWindowBackground.Events().MouseDown
.Subscribe(x => FloatingWindowBackground_OnMouseDown(this, x));

vm.WhenAnyValue(vm => vm.ActiveFloatingPane)
.Select(x => x == null ? Visibility.Hidden : Visibility.Visible)
.BindTo(this, view => view.FloatingWindow.Visibility);

this.Events().KeyDown
.Subscribe(x => HandleKeyDown(this, x));

}
catch (Exception ex)
{
_logger.LogError(ex, "During Main Window Startup");
Environment.Exit(-1);
}

vm.WhenAnyValue(vm => vm.WindowTitle)
.BindToStrict(this, view => view.AppName.Text);

}

private void Window_Closing(object sender, CancelEventArgs e)
{
_mwvm.ShutdownApplication().Wait();
}

private void TitleBar_OnMouseDown(object sender, MouseButtonEventArgs e)
{
DragMove();
}

private void FloatingWindowBackground_OnMouseDown(object sender, MouseButtonEventArgs x)
{
if (x.ButtonState == MouseButtonState.Pressed)
{
_mousePressedTimer.Restart();
DragMove();
}
if(x.ButtonState == MouseButtonState.Released)
{
if(_mousePressedTimer.Elapsed < TimeSpan.FromSeconds(0.2))
{
ShowFloatingWindow.Send(FloatingScreenType.None);
}
_mousePressedTimer.Stop();
}
}

private void HandleKeyDown(MainWindow mainWindow, KeyEventArgs x)
{
if(x.Key == Key.Escape)
{
if (((MainWindowVM)DataContext).ActiveFloatingPane != null)
ShowFloatingWindow.Send(FloatingScreenType.None);
}
}

}
64 changes: 43 additions & 21 deletions Wabbajack.App.Wpf/ViewModels/Installers/InstallationVM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
using Wabbajack.VFS;
using Humanizer;
using System.Text.RegularExpressions;
using System.Windows.Input;

namespace Wabbajack;

Expand Down Expand Up @@ -109,7 +110,7 @@ public class InstallationVM : ProgressViewModel
private readonly HttpClient _client;
private readonly DownloadDispatcher _downloadDispatcher;
private readonly IEnumerable<INeedsLogin> _logins;
private readonly CancellationToken _cancellationToken;
private readonly CancellationTokenSource _cancellationTokenSource;
public ReadOnlyObservableCollection<CPUDisplayVM> StatusList => _resourceMonitor.Tasks;

[Reactive]
Expand All @@ -129,22 +130,23 @@ public class InstallationVM : ProgressViewModel


// Command properties
public ReactiveCommand<Unit, Unit> OpenManifestCommand { get; }
public ReactiveCommand<Unit, Unit> OpenReadmeCommand { get; }
public ReactiveCommand<Unit, Unit> OpenWikiCommand { get; }
public ReactiveCommand<Unit, Unit> OpenDiscordButton { get; }
public ReactiveCommand<Unit, Unit> OpenWebsiteCommand { get; }
public ICommand OpenManifestCommand { get; }
public ICommand OpenReadmeCommand { get; }
public ICommand OpenWikiCommand { get; }
public ICommand OpenDiscordButton { get; }
public ICommand OpenWebsiteCommand { get; }

public ReactiveCommand<Unit, Unit> CloseWhenCompleteCommand { get; }
public ReactiveCommand<Unit, Unit> OpenLogsCommand { get; }
public ReactiveCommand<Unit, Unit> GoToInstallCommand { get; }
public ReactiveCommand<Unit, Unit> BeginCommand { get; }
public ReactiveCommand<Unit, Unit> VerifyCommand { get; }
public ICommand CloseWhenCompleteCommand { get; }
public ICommand OpenLogsCommand { get; }
public ICommand OpenInstallFolderCommand { get; }
public ICommand InstallCommand { get; }
public ICommand CancelCommand { get; }
public ICommand VerifyCommand { get; }

public InstallationVM(ILogger<InstallationVM> logger, DTOSerializer dtos, SettingsManager settingsManager, IServiceProvider serviceProvider,
SystemParametersConstructor parametersConstructor, IGameLocator gameLocator, LogStream loggerProvider, ResourceMonitor resourceMonitor,
Wabbajack.Services.OSIntegrated.Configuration configuration, HttpClient client, DownloadDispatcher dispatcher, IEnumerable<INeedsLogin> logins,
CancellationToken cancellationToken)
CancellationTokenSource cancellationTokenSource)
{
_logger = logger;
_configuration = configuration;
Expand All @@ -158,14 +160,15 @@ public InstallationVM(ILogger<InstallationVM> logger, DTOSerializer dtos, Settin
_client = client;
_downloadDispatcher = dispatcher;
_logins = logins;
_cancellationToken = cancellationToken;
_cancellationTokenSource = cancellationTokenSource;

ConfigurationText = $"Loading... Please wait";
ProgressText = $"Installation";

Installer = new MO2InstallerVM(this);

BeginCommand = ReactiveCommand.Create(() => BeginInstall().FireAndForget());

CancelCommand = ReactiveCommand.Create(CancelInstall);
InstallCommand = ReactiveCommand.Create(() => BeginInstall().FireAndForget());

OpenReadmeCommand = ReactiveCommand.Create(() =>
{
Expand Down Expand Up @@ -208,7 +211,7 @@ public InstallationVM(ILogger<InstallationVM> logger, DTOSerializer dtos, Settin
Environment.Exit(0);
});

GoToInstallCommand = ReactiveCommand.Create(() =>
OpenInstallFolderCommand = ReactiveCommand.Create(() =>
{
UIUtils.OpenFolder(Installer.Location.TargetPath);
});
Expand Down Expand Up @@ -302,6 +305,25 @@ public InstallationVM(ILogger<InstallationVM> logger, DTOSerializer dtos, Settin

}

private async void CancelInstall()
{
switch(InstallState)
{
case InstallState.Configuration:
NavigateToGlobal.Send(ScreenType.ModListGallery);
break;

case InstallState.Installing:
// TODO - Cancel installation
await _cancellationTokenSource.CancelAsync();
_cancellationTokenSource.TryReset();
break;

default:
break;
}
}

private IEnumerable<ErrorResponse> Validate()
{
if (!WabbajackFileLocation.TargetPath.FileExists())
Expand Down Expand Up @@ -495,7 +517,7 @@ await Task.Run(async () =>
_serviceProvider.GetRequiredService<IResource<FileHashCache>>(),
_serviceProvider.GetRequiredService<TemporaryFileManager>());

var result = await cmd.Run(WabbajackFileLocation.TargetPath, Installer.Location.TargetPath, _cancellationToken);
var result = await cmd.Run(WabbajackFileLocation.TargetPath, Installer.Location.TargetPath, _cancellationTokenSource.Token);

if (result != 0)
{
Expand Down Expand Up @@ -581,16 +603,16 @@ await Task.Run(async () =>
update.StepsProgress.Value);
};

if (!await installer.Begin(_cancellationToken))
if (!await installer.Begin(_cancellationTokenSource.Token))
{
TaskBarUpdate.Send($"Error during install of {ModList.Name}", TaskbarItemProgressState.Error);
TaskBarUpdate.Send($"Error during installation of {ModList.Name}", TaskbarItemProgressState.Error);
InstallState = InstallState.Failure;
ProgressText = $"Error during install of {ModList.Name}";
ProgressText = $"Error during installation of {ModList.Name}";
ProgressPercent = Percent.Zero;
}
else
{
TaskBarUpdate.Send($"Finished install of {ModList.Name}", TaskbarItemProgressState.Normal);
TaskBarUpdate.Send($"Finished installing {ModList.Name}", TaskbarItemProgressState.Normal);
InstallState = InstallState.Success;

if (!string.IsNullOrWhiteSpace(ModList.Readme))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public InstallationCompleteView()
.Select(failed => $"Installation {(failed ? "Failed" : "Complete")}")
.BindToStrict(this, x => x.TitleText.Text)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.GoToInstallCommand)
this.WhenAny(x => x.ViewModel.OpenInstallFolderCommand)
.BindToStrict(this, x => x.GoToInstallButton.Command)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.OpenReadmeCommand)
Expand Down
Loading

0 comments on commit 4efe3fd

Please sign in to comment.