2022-03-13 22:47:30 +00:00
|
|
|
|
using DynamicData.Binding;
|
|
|
|
|
using ReactiveUI;
|
|
|
|
|
using ReactiveUI.Fody.Helpers;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Reactive.Disposables;
|
|
|
|
|
using System.Reactive.Linq;
|
|
|
|
|
using System.Reflection;
|
2022-05-15 22:38:22 +00:00
|
|
|
|
using System.Threading;
|
2022-03-13 22:47:30 +00:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Windows;
|
|
|
|
|
using System.Windows.Input;
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
2022-10-16 12:00:50 +00:00
|
|
|
|
using Orc.FileAssociation;
|
2022-03-13 22:47:30 +00:00
|
|
|
|
using Wabbajack.Common;
|
2022-05-16 22:14:52 +00:00
|
|
|
|
using Wabbajack.DTOs.Interventions;
|
2022-03-13 22:47:30 +00:00
|
|
|
|
using Wabbajack.Interventions;
|
|
|
|
|
using Wabbajack.Messages;
|
|
|
|
|
using Wabbajack.Models;
|
|
|
|
|
using Wabbajack.Networking.WabbajackClientApi;
|
|
|
|
|
using Wabbajack.Paths;
|
2022-10-16 12:17:30 +00:00
|
|
|
|
using Wabbajack.Paths.IO;
|
2022-03-13 22:47:30 +00:00
|
|
|
|
using Wabbajack.UserIntervention;
|
|
|
|
|
using Wabbajack.View_Models;
|
|
|
|
|
|
|
|
|
|
namespace Wabbajack
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Main View Model for the application.
|
|
|
|
|
/// Keeps track of which sub view is being shown in the window, and has some singleton wiring like WorkQueue and Logging.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class MainWindowVM : ViewModel
|
|
|
|
|
{
|
|
|
|
|
public MainWindow MainWindow { get; }
|
|
|
|
|
|
|
|
|
|
[Reactive]
|
|
|
|
|
public ViewModel ActivePane { get; private set; }
|
|
|
|
|
|
|
|
|
|
public ObservableCollectionExtended<IStatusMessage> Log { get; } = new ObservableCollectionExtended<IStatusMessage>();
|
|
|
|
|
|
|
|
|
|
public readonly CompilerVM Compiler;
|
|
|
|
|
public readonly InstallerVM Installer;
|
|
|
|
|
public readonly SettingsVM SettingsPane;
|
|
|
|
|
public readonly ModListGalleryVM Gallery;
|
|
|
|
|
public readonly ModeSelectionVM ModeSelectionVM;
|
|
|
|
|
public readonly WebBrowserVM WebBrowserVM;
|
|
|
|
|
public readonly Lazy<ModListContentsVM> ModListContentsVM;
|
|
|
|
|
public readonly UserInterventionHandlers UserInterventionHandlers;
|
|
|
|
|
private readonly Client _wjClient;
|
|
|
|
|
private readonly ILogger<MainWindowVM> _logger;
|
|
|
|
|
private readonly ResourceMonitor _resourceMonitor;
|
|
|
|
|
|
|
|
|
|
private List<ViewModel> PreviousPanes = new();
|
|
|
|
|
private readonly IServiceProvider _serviceProvider;
|
|
|
|
|
|
|
|
|
|
public ICommand CopyVersionCommand { get; }
|
|
|
|
|
public ICommand ShowLoginManagerVM { get; }
|
|
|
|
|
public ICommand OpenSettingsCommand { get; }
|
|
|
|
|
|
|
|
|
|
public string VersionDisplay { get; }
|
2022-10-21 12:43:36 +00:00
|
|
|
|
|
2022-03-13 22:47:30 +00:00
|
|
|
|
[Reactive]
|
|
|
|
|
public string ResourceStatus { get; set; }
|
2022-10-21 12:43:36 +00:00
|
|
|
|
|
2022-05-20 22:33:09 +00:00
|
|
|
|
[Reactive]
|
|
|
|
|
public string AppName { get; set; }
|
2022-03-13 22:47:30 +00:00
|
|
|
|
|
|
|
|
|
[Reactive]
|
|
|
|
|
public bool UpdateAvailable { get; private set; }
|
|
|
|
|
|
2023-10-12 18:33:06 +00:00
|
|
|
|
public MainWindowVM(ILogger<MainWindowVM> logger, Client wjClient,
|
2022-03-13 22:47:30 +00:00
|
|
|
|
IServiceProvider serviceProvider, ModeSelectionVM modeSelectionVM, ModListGalleryVM modListGalleryVM, ResourceMonitor resourceMonitor,
|
|
|
|
|
InstallerVM installer, CompilerVM compilerVM, SettingsVM settingsVM, WebBrowserVM webBrowserVM)
|
|
|
|
|
{
|
|
|
|
|
_logger = logger;
|
|
|
|
|
_wjClient = wjClient;
|
|
|
|
|
_resourceMonitor = resourceMonitor;
|
|
|
|
|
_serviceProvider = serviceProvider;
|
|
|
|
|
ConverterRegistration.Register();
|
|
|
|
|
Installer = installer;
|
|
|
|
|
Compiler = compilerVM;
|
|
|
|
|
SettingsPane = settingsVM;
|
|
|
|
|
Gallery = modListGalleryVM;
|
|
|
|
|
ModeSelectionVM = modeSelectionVM;
|
|
|
|
|
WebBrowserVM = webBrowserVM;
|
|
|
|
|
ModListContentsVM = new Lazy<ModListContentsVM>(() => new ModListContentsVM(serviceProvider.GetRequiredService<ILogger<ModListContentsVM>>(), this));
|
|
|
|
|
UserInterventionHandlers = new UserInterventionHandlers(serviceProvider.GetRequiredService<ILogger<UserInterventionHandlers>>(), this);
|
|
|
|
|
|
|
|
|
|
MessageBus.Current.Listen<NavigateToGlobal>()
|
|
|
|
|
.Subscribe(m => HandleNavigateTo(m.Screen))
|
|
|
|
|
.DisposeWith(CompositeDisposable);
|
2022-10-21 12:43:36 +00:00
|
|
|
|
|
2022-03-13 22:47:30 +00:00
|
|
|
|
MessageBus.Current.Listen<NavigateTo>()
|
|
|
|
|
.Subscribe(m => HandleNavigateTo(m.ViewModel))
|
|
|
|
|
.DisposeWith(CompositeDisposable);
|
|
|
|
|
|
|
|
|
|
MessageBus.Current.Listen<NavigateBack>()
|
|
|
|
|
.Subscribe(HandleNavigateBack)
|
|
|
|
|
.DisposeWith(CompositeDisposable);
|
2022-10-21 12:43:36 +00:00
|
|
|
|
|
2022-05-20 04:12:16 +00:00
|
|
|
|
MessageBus.Current.Listen<SpawnBrowserWindow>()
|
|
|
|
|
.ObserveOnGuiThread()
|
|
|
|
|
.Subscribe(HandleSpawnBrowserWindow)
|
2022-05-19 03:21:38 +00:00
|
|
|
|
.DisposeWith(CompositeDisposable);
|
|
|
|
|
|
2022-03-13 22:47:30 +00:00
|
|
|
|
_resourceMonitor.Updates
|
|
|
|
|
.Select(r => string.Join(", ", r.Where(r => r.Throughput > 0)
|
|
|
|
|
.Select(s => $"{s.Name} - {s.Throughput.ToFileSizeString()}/sec")))
|
|
|
|
|
.BindToStrict(this, view => view.ResourceStatus);
|
2022-10-21 12:43:36 +00:00
|
|
|
|
|
2022-03-13 22:47:30 +00:00
|
|
|
|
|
|
|
|
|
if (IsStartingFromModlist(out var path))
|
|
|
|
|
{
|
|
|
|
|
LoadModlistForInstalling.Send(path, null);
|
|
|
|
|
NavigateToGlobal.Send(NavigateToGlobal.ScreenType.Installer);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Start on mode selection
|
|
|
|
|
NavigateToGlobal.Send(NavigateToGlobal.ScreenType.ModeSelectionView);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var assembly = Assembly.GetExecutingAssembly();
|
2022-11-05 11:28:34 +00:00
|
|
|
|
var assemblyLocation = assembly.Location;
|
|
|
|
|
var processLocation = Process.GetCurrentProcess().MainModule?.FileName ?? throw new Exception("Process location is unavailable!");
|
2022-10-21 12:43:36 +00:00
|
|
|
|
|
2022-11-05 11:28:34 +00:00
|
|
|
|
_logger.LogInformation("Assembly Location: {AssemblyLocation}", assemblyLocation);
|
|
|
|
|
_logger.LogInformation("Process Location: {ProcessLocation}", processLocation);
|
|
|
|
|
|
|
|
|
|
var fvi = FileVersionInfo.GetVersionInfo(string.IsNullOrWhiteSpace(assemblyLocation) ? processLocation : assemblyLocation);
|
2022-03-13 22:47:30 +00:00
|
|
|
|
Consts.CurrentMinimumWabbajackVersion = Version.Parse(fvi.FileVersion);
|
|
|
|
|
VersionDisplay = $"v{fvi.FileVersion}";
|
2022-05-20 22:33:09 +00:00
|
|
|
|
AppName = "WABBAJACK " + VersionDisplay;
|
2022-03-13 22:47:30 +00:00
|
|
|
|
_logger.LogInformation("Wabbajack Version: {FileVersion}", fvi.FileVersion);
|
2022-10-21 12:43:36 +00:00
|
|
|
|
|
2022-03-13 22:47:30 +00:00
|
|
|
|
Task.Run(() => _wjClient.SendMetric("started_wabbajack", fvi.FileVersion)).FireAndForget();
|
|
|
|
|
Task.Run(() => _wjClient.SendMetric("started_sha", ThisAssembly.Git.Sha));
|
2022-10-21 12:43:36 +00:00
|
|
|
|
|
2022-10-16 12:00:50 +00:00
|
|
|
|
// setup file association
|
2022-10-19 22:17:25 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
2022-10-21 12:43:36 +00:00
|
|
|
|
var applicationRegistrationService = _serviceProvider.GetRequiredService<IApplicationRegistrationService>();
|
2022-10-19 22:17:25 +00:00
|
|
|
|
|
2022-11-04 10:53:24 +00:00
|
|
|
|
var applicationInfo = new ApplicationInfo("Wabbajack", "Wabbajack", "Wabbajack", processLocation);
|
2022-10-19 22:17:25 +00:00
|
|
|
|
applicationInfo.SupportedExtensions.Add("wabbajack");
|
|
|
|
|
applicationRegistrationService.RegisterApplication(applicationInfo);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError(ex, "While setting up file associations");
|
|
|
|
|
}
|
2022-03-13 22:47:30 +00:00
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError(ex, "During App configuration");
|
|
|
|
|
VersionDisplay = "ERROR";
|
|
|
|
|
}
|
|
|
|
|
CopyVersionCommand = ReactiveCommand.Create(() =>
|
|
|
|
|
{
|
|
|
|
|
Clipboard.SetText($"Wabbajack {VersionDisplay}\n{ThisAssembly.Git.Sha}");
|
|
|
|
|
});
|
|
|
|
|
OpenSettingsCommand = ReactiveCommand.Create(
|
|
|
|
|
canExecute: this.WhenAny(x => x.ActivePane)
|
|
|
|
|
.Select(active => !object.ReferenceEquals(active, SettingsPane)),
|
|
|
|
|
execute: () => NavigateToGlobal.Send(NavigateToGlobal.ScreenType.Settings));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void HandleNavigateTo(ViewModel objViewModel)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
ActivePane = objViewModel;
|
|
|
|
|
}
|
2022-10-21 12:43:36 +00:00
|
|
|
|
|
2022-03-13 22:47:30 +00:00
|
|
|
|
private void HandleNavigateBack(NavigateBack navigateBack)
|
|
|
|
|
{
|
|
|
|
|
ActivePane = PreviousPanes.Last();
|
|
|
|
|
PreviousPanes.RemoveAt(PreviousPanes.Count - 1);
|
|
|
|
|
}
|
2022-10-21 12:43:36 +00:00
|
|
|
|
|
2022-05-16 22:14:52 +00:00
|
|
|
|
private void HandleManualDownload(ManualDownload manualDownload)
|
|
|
|
|
{
|
|
|
|
|
var handler = _serviceProvider.GetRequiredService<ManualDownloadHandler>();
|
|
|
|
|
handler.Intervention = manualDownload;
|
2022-05-20 03:23:16 +00:00
|
|
|
|
//MessageBus.Current.SendMessage(new OpenBrowserTab(handler));
|
2022-05-16 22:14:52 +00:00
|
|
|
|
}
|
2022-10-21 12:43:36 +00:00
|
|
|
|
|
2022-05-19 03:21:38 +00:00
|
|
|
|
private void HandleManualBlobDownload(ManualBlobDownload manualDownload)
|
|
|
|
|
{
|
|
|
|
|
var handler = _serviceProvider.GetRequiredService<ManualBlobDownloadHandler>();
|
|
|
|
|
handler.Intervention = manualDownload;
|
2022-05-20 03:23:16 +00:00
|
|
|
|
//MessageBus.Current.SendMessage(new OpenBrowserTab(handler));
|
2022-05-19 03:21:38 +00:00
|
|
|
|
}
|
2022-10-21 12:43:36 +00:00
|
|
|
|
|
2022-05-20 04:12:16 +00:00
|
|
|
|
private void HandleSpawnBrowserWindow(SpawnBrowserWindow msg)
|
|
|
|
|
{
|
|
|
|
|
var window = _serviceProvider.GetRequiredService<BrowserWindow>();
|
|
|
|
|
window.DataContext = msg.Vm;
|
|
|
|
|
window.Show();
|
|
|
|
|
}
|
2022-03-13 22:47:30 +00:00
|
|
|
|
|
|
|
|
|
private void HandleNavigateTo(NavigateToGlobal.ScreenType s)
|
|
|
|
|
{
|
|
|
|
|
if (s is NavigateToGlobal.ScreenType.Settings)
|
|
|
|
|
PreviousPanes.Add(ActivePane);
|
2022-10-21 12:43:36 +00:00
|
|
|
|
|
2022-03-13 22:47:30 +00:00
|
|
|
|
ActivePane = s switch
|
|
|
|
|
{
|
|
|
|
|
NavigateToGlobal.ScreenType.ModeSelectionView => ModeSelectionVM,
|
|
|
|
|
NavigateToGlobal.ScreenType.ModListGallery => Gallery,
|
|
|
|
|
NavigateToGlobal.ScreenType.Installer => Installer,
|
|
|
|
|
NavigateToGlobal.ScreenType.Compiler => Compiler,
|
|
|
|
|
NavigateToGlobal.ScreenType.Settings => SettingsPane,
|
|
|
|
|
_ => ActivePane
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static bool IsStartingFromModlist(out AbsolutePath modlistPath)
|
|
|
|
|
{
|
2022-10-16 12:17:30 +00:00
|
|
|
|
var args = Environment.GetCommandLineArgs();
|
|
|
|
|
if (args.Length == 2)
|
2022-03-13 22:47:30 +00:00
|
|
|
|
{
|
2022-10-16 12:17:30 +00:00
|
|
|
|
var arg = args[1].ToAbsolutePath();
|
|
|
|
|
if (arg.FileExists() && arg.Extension == Ext.Wabbajack)
|
|
|
|
|
{
|
|
|
|
|
modlistPath = arg;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2022-03-13 22:47:30 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
modlistPath = default;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-07 20:32:18 +00:00
|
|
|
|
public void CancelRunningTasks(TimeSpan timeout)
|
|
|
|
|
{
|
|
|
|
|
var endTime = DateTime.Now.Add(timeout);
|
|
|
|
|
var cancellationTokenSource = _serviceProvider.GetRequiredService<CancellationTokenSource>();
|
|
|
|
|
cancellationTokenSource.Cancel();
|
|
|
|
|
|
|
|
|
|
bool IsInstalling() => Installer.InstallState is InstallState.Installing;
|
|
|
|
|
|
|
|
|
|
while (DateTime.Now < endTime && IsInstalling())
|
|
|
|
|
{
|
|
|
|
|
Thread.Sleep(TimeSpan.FromSeconds(1));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-13 22:47:30 +00:00
|
|
|
|
/*
|
|
|
|
|
public void NavigateTo(ViewModel vm)
|
|
|
|
|
{
|
|
|
|
|
ActivePane = vm;
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
public void NavigateTo<T>(T vm)
|
|
|
|
|
where T : ViewModel, IBackNavigatingVM
|
|
|
|
|
{
|
|
|
|
|
vm.NavigateBackTarget = ActivePane;
|
|
|
|
|
ActivePane = vm;
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
public async Task ShutdownApplication()
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
Dispose();
|
|
|
|
|
Settings.PosX = MainWindow.Left;
|
|
|
|
|
Settings.PosY = MainWindow.Top;
|
|
|
|
|
Settings.Width = MainWindow.Width;
|
|
|
|
|
Settings.Height = MainWindow.Height;
|
|
|
|
|
await MainSettings.SaveSettings(Settings);
|
|
|
|
|
Application.Current.Shutdown();
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|