Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update guided installer abstraction and FOMOD installer #541

Merged
merged 19 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,11 @@
<PackageVersion Include="ini-parser-netstandard" Version="2.5.2" />
<PackageVersion Include="Mutagen.Bethesda.Skyrim" Version="0.41.0-pr002" />
<PackageVersion Include="NLog.Extensions.Logging" Version="5.3.2" />
<PackageVersion Include="OneOf" Version="3.0.255" />
<PackageVersion Include="ReactiveUI.Fody" Version="19.4.1" />
<PackageVersion Include="Sewer56.BitStream" Version="1.3.0" />
<PackageVersion Include="Spectre.Console" Version="0.47.0" />
<PackageVersion Include="Splat.Microsoft.Extensions.Logging" Version="14.6.37" />
<PackageVersion Include="Vogen" Version="3.0.20" />
</ItemGroup>
</Project>
</Project>
7 changes: 7 additions & 0 deletions NexusMods.App.sln
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NexusMods.Abstractions", "s
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NexusMods.Games.Generic.Tests", "tests\Games\NexusMods.Games.Generic.Tests\NexusMods.Games.Generic.Tests.csproj", "{AA95B93F-23AC-46D5-83B3-2E7AE4BD309C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NexusMods.Games.FOMOD.UI", "src\Games\NexusMods.Games.FOMOD.UI\NexusMods.Games.FOMOD.UI.csproj", "{500CE772-93C3-4DA9-9AB3-E9E9EC0A9429}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -307,6 +309,10 @@ Global
{AA95B93F-23AC-46D5-83B3-2E7AE4BD309C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA95B93F-23AC-46D5-83B3-2E7AE4BD309C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AA95B93F-23AC-46D5-83B3-2E7AE4BD309C}.Release|Any CPU.Build.0 = Release|Any CPU
{500CE772-93C3-4DA9-9AB3-E9E9EC0A9429}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{500CE772-93C3-4DA9-9AB3-E9E9EC0A9429}.Debug|Any CPU.Build.0 = Debug|Any CPU
{500CE772-93C3-4DA9-9AB3-E9E9EC0A9429}.Release|Any CPU.ActiveCfg = Release|Any CPU
{500CE772-93C3-4DA9-9AB3-E9E9EC0A9429}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -361,6 +367,7 @@ Global
{09B037AB-07BB-4154-95FD-6EA2E55C4568} = {897C4198-884F-448A-B0B0-C2A6D971EAE0}
{1E20E979-5F04-44FD-BE07-54B6686ECB13} = {E7BAE287-D505-4D6D-A090-665A64309B2D}
{AA95B93F-23AC-46D5-83B3-2E7AE4BD309C} = {05B06AC1-7F2B-492F-983E-5BC63CDBF20D}
{500CE772-93C3-4DA9-9AB3-E9E9EC0A9429} = {70D38D24-79AE-4600-8E83-17F3C11BA81F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9F9F8352-34DD-42C0-8564-EE9AF34A3501}
Expand Down
49 changes: 49 additions & 0 deletions src/Games/NexusMods.Games.FOMOD.UI/GuidedInstallerStepViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Reactive;
using System.Reactive.Linq;
using JetBrains.Annotations;
using NexusMods.App.UI;
using NexusMods.Common.GuidedInstaller;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;

namespace NexusMods.Games.FOMOD.UI;

[UsedImplicitly]
public class GuidedInstallerStepViewModel : AViewModel<IGuidedInstallerStepViewModel>, IGuidedInstallerStepViewModel
{
[Reactive]
public GuidedInstallationStep? InstallationStep { get; set; }

[Reactive]
public TaskCompletionSource<UserChoice>? TaskCompletionSource { get; set; }

public ReactiveCommand<Unit, Unit> NextStepCommand { get; set; }
public ReactiveCommand<Unit, Unit> PreviousStepCommand { get; set; }
public ReactiveCommand<Unit, Unit> CancelInstallerCommand { get; set; }

public GuidedInstallerStepViewModel()
{
// TODO: other validation
var hasTaskCompletionSource = this
.WhenAnyValue(vm => vm.TaskCompletionSource)
.OnUI()
.Select(tcs => tcs is not null);

NextStepCommand = ReactiveCommand.Create(() =>
{
// TODO: set result
var selectedOptions = Array.Empty<SelectedOption>();
TaskCompletionSource?.TrySetResult(new UserChoice(new UserChoice.GoToNextStep(selectedOptions)));
}, hasTaskCompletionSource);

PreviousStepCommand = ReactiveCommand.Create(() =>
{
TaskCompletionSource?.TrySetResult(new UserChoice(new UserChoice.GoToPreviousStep()));
}, hasTaskCompletionSource);

CancelInstallerCommand = ReactiveCommand.Create(() =>
{
TaskCompletionSource?.TrySetResult(new UserChoice(new UserChoice.CancelInstallation()));
}, hasTaskCompletionSource);
}
}
64 changes: 64 additions & 0 deletions src/Games/NexusMods.Games.FOMOD.UI/GuidedInstallerUi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System.Diagnostics;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using NexusMods.Common.GuidedInstaller;

namespace NexusMods.Games.FOMOD.UI;

[UsedImplicitly]
public sealed class GuidedInstallerUi : IGuidedInstaller, IDisposable
{
private readonly IServiceProvider _serviceProvider;

private IServiceScope? _currentScope;
private IGuidedInstallerWindowViewModel? _windowViewModel;

public GuidedInstallerUi(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}

public void SetupInstaller(string windowName)
{
Debug.Assert(_currentScope is null);
_currentScope = _serviceProvider.CreateScope();

// TODO: create/show window?
_windowViewModel = _currentScope.ServiceProvider.GetRequiredService<IGuidedInstallerWindowViewModel>();
_windowViewModel.WindowName = windowName;
}

public void CleanupInstaller()
{
if (_windowViewModel is not null)
{
// TODO: dispose & close window?
_windowViewModel.ActiveStepViewModel = null;
_windowViewModel = null;
}

_currentScope?.Dispose();
_currentScope = null;
}

public async Task<UserChoice> RequestUserChoice(
GuidedInstallationStep installationStep,
CancellationToken cancellationToken)
{
Debug.Assert(_currentScope is not null);
Debug.Assert(_windowViewModel is not null);

_windowViewModel.ActiveStepViewModel ??= _currentScope.ServiceProvider.GetRequiredService<IGuidedInstallerStepViewModel>();

var activeStepViewModel = _windowViewModel.ActiveStepViewModel;
activeStepViewModel.InstallationStep = installationStep;

var tcs = new TaskCompletionSource<UserChoice>();
activeStepViewModel.TaskCompletionSource = tcs;

await tcs.Task;
return tcs.Task.Result;
}

public void Dispose() => CleanupInstaller();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using JetBrains.Annotations;
using NexusMods.App.UI;
using ReactiveUI.Fody.Helpers;

namespace NexusMods.Games.FOMOD.UI;

[UsedImplicitly]
public class GuidedInstallerWindowViewModel : AViewModel<IGuidedInstallerWindowViewModel>, IGuidedInstallerWindowViewModel
{
[Reactive] public string WindowName { get; set; } = string.Empty;

[Reactive]
public IGuidedInstallerStepViewModel? ActiveStepViewModel { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Reactive;
using NexusMods.App.UI;
using NexusMods.Common.GuidedInstaller;
using ReactiveUI;

namespace NexusMods.Games.FOMOD.UI;

public interface IGuidedInstallerStepViewModel : IViewModelInterface
{
public GuidedInstallationStep? InstallationStep { get; set; }

public TaskCompletionSource<UserChoice>? TaskCompletionSource { get; set; }

public ReactiveCommand<Unit, Unit> NextStepCommand { get; set; }

public ReactiveCommand<Unit, Unit> PreviousStepCommand { get; set; }

public ReactiveCommand<Unit, Unit> CancelInstallerCommand { get; set; }
}
erri120 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using NexusMods.App.UI;

namespace NexusMods.Games.FOMOD.UI;

public interface IGuidedInstallerWindowViewModel : IViewModelInterface
{
public string WindowName { get; set; }

public IGuidedInstallerStepViewModel? ActiveStepViewModel { get; set; }
}
13 changes: 13 additions & 0 deletions src/Games/NexusMods.Games.FOMOD.UI/NexusMods.Games.FOMOD.UI.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\NexusMods.App.UI\NexusMods.App.UI.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="GuidedInstallerWindowViewModel.cs">
<DependentUpon>IGuidedInstallerWindowViewModel.cs</DependentUpon>
</Compile>
<Compile Update="GuidedInstallerStepViewModel.cs">
<DependentUpon>IGuidedInstallerStepViewModel.cs</DependentUpon>
</Compile>
</ItemGroup>
</Project>
16 changes: 16 additions & 0 deletions src/Games/NexusMods.Games.FOMOD.UI/Services.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Microsoft.Extensions.DependencyInjection;
using NexusMods.App.UI;
using NexusMods.Common.GuidedInstaller;

namespace NexusMods.Games.FOMOD.UI;

public static class Services
{
public static IServiceCollection AddFomodInstallerUi(this IServiceCollection serviceCollection)
{
return serviceCollection
.AddTransient<IGuidedInstaller, GuidedInstallerUi>()
.AddViewModel<GuidedInstallerStepViewModel, IGuidedInstallerStepViewModel>()
.AddViewModel<GuidedInstallerWindowViewModel, IGuidedInstallerWindowViewModel>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using FomodInstaller.Interface.ui;
using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
using NexusMods.Common.UserInput;
using NexusMods.Common.GuidedInstaller;

namespace NexusMods.Games.FOMOD.CoreDelegates;

Expand All @@ -14,10 +14,10 @@ public sealed class InstallerDelegates : ICoreDelegates
public IPluginDelegates plugin { get; }
public IUIDelegates ui { get; }

public InstallerDelegates(ILoggerFactory loggerFactory, IOptionSelector optionSelector)
public InstallerDelegates(ILoggerFactory loggerFactory, IGuidedInstaller guidedInstaller)
{
context = new ContextDelegates(loggerFactory.CreateLogger<ContextDelegates>());
plugin = new PluginDelegates(loggerFactory.CreateLogger<PluginDelegates>());
ui = new UiDelegates(loggerFactory.CreateLogger<UiDelegates>(), optionSelector);
ui = new UiDelegates(loggerFactory.CreateLogger<UiDelegates>(), guidedInstaller);
}
}
Loading
Loading