mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
commit
3180678a87
@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Media.Imaging;
|
||||
@ -17,6 +18,7 @@ using Wabbajack.App.ViewModels;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Downloaders;
|
||||
using Wabbajack.DTOs;
|
||||
using Wabbajack.DTOs.JsonConverters;
|
||||
using Wabbajack.Installer;
|
||||
using Wabbajack.Paths;
|
||||
using Wabbajack.Paths.IO;
|
||||
@ -43,6 +45,7 @@ namespace Wabbajack.App.Controls
|
||||
private readonly DownloadDispatcher _dispatcher;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IResource<DownloadDispatcher> _downloadLimiter;
|
||||
private readonly DTOSerializer _dtos;
|
||||
|
||||
public string Title => _metadata.ImageContainsTitle ? "" : _metadata.Title;
|
||||
public string MachineURL => _metadata.Links.MachineURL;
|
||||
@ -74,7 +77,7 @@ namespace Wabbajack.App.Controls
|
||||
|
||||
public BrowseItemViewModel(ModlistMetadata metadata, ModListSummary summary, HttpClient client, IResource<HttpClient> limiter,
|
||||
FileHashCache hashCache, Configuration configuration, DownloadDispatcher dispatcher, IResource<DownloadDispatcher> downloadLimiter, GameLocator gameLocator,
|
||||
ILogger logger)
|
||||
DTOSerializer dtos, ILogger logger)
|
||||
{
|
||||
Activator = new ViewModelActivator();
|
||||
_metadata = metadata;
|
||||
@ -86,6 +89,8 @@ namespace Wabbajack.App.Controls
|
||||
_dispatcher = dispatcher;
|
||||
_downloadLimiter = downloadLimiter;
|
||||
_logger = logger;
|
||||
_dtos = dtos;
|
||||
|
||||
var haveGame = gameLocator.IsInstalled(_metadata.Game);
|
||||
Tags = metadata.tags
|
||||
.Select(t => new TagViewModel(t, "ModList"))
|
||||
@ -150,6 +155,9 @@ namespace Wabbajack.App.Controls
|
||||
|
||||
_hashCache.FileHashWriteCache(ModListLocation, hash);
|
||||
|
||||
var metadataPath = ModListLocation.WithExtension(Ext.MetaData);
|
||||
await metadataPath.WriteAllTextAsync(_dtos.Serialize(_metadata));
|
||||
|
||||
await UpdateState();
|
||||
}
|
||||
|
||||
|
9
Wabbajack.App/Messages/ConfigureLauncher.cs
Normal file
9
Wabbajack.App/Messages/ConfigureLauncher.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using Wabbajack.Paths;
|
||||
|
||||
namespace Wabbajack.App.Messages
|
||||
{
|
||||
public record ConfigureLauncher(AbsolutePath InstallFolder)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ using Wabbajack.Paths;
|
||||
|
||||
namespace Wabbajack.App.Messages
|
||||
{
|
||||
public record StartInstallation(AbsolutePath ModListPath, AbsolutePath Install, AbsolutePath Download)
|
||||
public record StartInstallation(AbsolutePath ModListPath, AbsolutePath Install, AbsolutePath Download, ModlistMetadata? Metadata)
|
||||
{
|
||||
}
|
||||
}
|
@ -73,5 +73,10 @@ namespace Wabbajack.App.Models
|
||||
{
|
||||
return (await GetAll()).Settings.FirstOrDefault(f => f.ModList == modListPath);
|
||||
}
|
||||
|
||||
public async Task<InstallationConfigurationSetting?> GetByInstallFolder(AbsolutePath folder)
|
||||
{
|
||||
return (await GetAll()).Settings.FirstOrDefault(f => f.Install == folder);
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ using Wabbajack.Networking.WabbajackClientApi;
|
||||
using DynamicData.Binding;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Wabbajack.Downloaders;
|
||||
using Wabbajack.DTOs.JsonConverters;
|
||||
using Wabbajack.Installer;
|
||||
using Wabbajack.Paths;
|
||||
using Wabbajack.Paths.IO;
|
||||
@ -52,6 +53,7 @@ namespace Wabbajack.App.Screens
|
||||
private SourceCache<GameSelectorItemViewModel, string> _gamesList = new(x => x.Name);
|
||||
public readonly ReadOnlyObservableCollection<GameSelectorItemViewModel> _filteredGamesList;
|
||||
private readonly GameLocator _gameLocator;
|
||||
private readonly DTOSerializer _dtos;
|
||||
public ReadOnlyObservableCollection<GameSelectorItemViewModel> GamesList => _filteredGamesList;
|
||||
|
||||
[Reactive]
|
||||
@ -67,7 +69,7 @@ namespace Wabbajack.App.Screens
|
||||
[Reactive] public bool ShowNSFW { get; set; } = false;
|
||||
|
||||
public BrowseViewModel(ILogger<BrowseViewModel> logger, Client wjClient, HttpClient httpClient, IResource<HttpClient> limiter, FileHashCache hashCache,
|
||||
IResource<DownloadDispatcher> dispatcherLimiter, DownloadDispatcher dispatcher, GameLocator gameLocator, Configuration configuration)
|
||||
IResource<DownloadDispatcher> dispatcherLimiter, DownloadDispatcher dispatcher, GameLocator gameLocator, DTOSerializer dtos, Configuration configuration)
|
||||
{
|
||||
Activator = new ViewModelActivator();
|
||||
_wjClient = wjClient;
|
||||
@ -79,6 +81,7 @@ namespace Wabbajack.App.Screens
|
||||
_dispatcher = dispatcher;
|
||||
_dispatcherLimiter = dispatcherLimiter;
|
||||
_gameLocator = gameLocator;
|
||||
_dtos = dtos;
|
||||
|
||||
|
||||
IObservable<Func<BrowseItemViewModel, bool>> searchTextPredicates = this.ObservableForProperty(vm => vm.SearchText)
|
||||
@ -198,7 +201,7 @@ namespace Wabbajack.App.Screens
|
||||
summary = new ModListSummary();
|
||||
}
|
||||
|
||||
return new BrowseItemViewModel(m, summary, _httpClient, _limiter, _hashCache, _configuration, _dispatcher, _dispatcherLimiter, _gameLocator, _logger);
|
||||
return new BrowseItemViewModel(m, summary, _httpClient, _limiter, _hashCache, _configuration, _dispatcher, _dispatcherLimiter, _gameLocator, _dtos, _logger);
|
||||
});
|
||||
|
||||
_modLists.Edit(lsts =>
|
||||
|
37
Wabbajack.App/Screens/LauncherView.axaml
Normal file
37
Wabbajack.App/Screens/LauncherView.axaml
Normal file
@ -0,0 +1,37 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:Wabbajack.App.Controls"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Wabbajack.App.Screens.LauncherView">
|
||||
<Grid RowDefinitions="*, Auto">
|
||||
<Viewbox Grid.Row="0"
|
||||
Name="Banner"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="UniformToFill">
|
||||
<Image x:Name="ModListImage" Margin="0,0,0,0" Source="../Assets/Wabba_Mouth.png" />
|
||||
</Viewbox>
|
||||
<Grid Grid.Row="0" RowDefinitions="40, 40" HorizontalAlignment="Left" VerticalAlignment="Bottom">
|
||||
<TextBlock x:Name="ModListName"></TextBlock>
|
||||
</Grid>
|
||||
<Grid Margin="40" RowDefinitions="40, 40, 40, *" ColumnDefinitions="100, *, 200" Grid.Row="1">
|
||||
<Label Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Center">ModList:</Label>
|
||||
<TextBox Grid.Column="1" Grid.Row="0" IsEnabled="False" Height="20" x:Name="ModList"></TextBox>
|
||||
|
||||
<Label Grid.Column="0" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Center">Location:</Label>
|
||||
<TextBox Grid.Column="1" Grid.Row="1" IsEnabled="False" Height="20" x:Name="InstallPath"></TextBox>
|
||||
|
||||
<Grid Grid.Column="1" Grid.Row="3" Grid.ColumnDefinitions="*, *, *" HorizontalAlignment="Center">
|
||||
<Button Grid.Column="0" x:Name="WebsiteButton">Website</Button>
|
||||
<Button Grid.Column="1" x:Name="ReadmeButton">Readme</Button>
|
||||
<Button Grid.Column="2" x:Name="LocalFilesButton">Local Files</Button>
|
||||
</Grid>
|
||||
|
||||
<controls:LargeIconButton x:Name="PlayGame" Margin="40, 0, 0, 0" Grid.Row="0" Grid.Column="2" Grid.RowSpan="4" Icon="PlayCircle" Text="Play">
|
||||
|
||||
</controls:LargeIconButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
33
Wabbajack.App/Screens/LauncherView.axaml.cs
Normal file
33
Wabbajack.App/Screens/LauncherView.axaml.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System.Reactive.Disposables;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using ReactiveUI;
|
||||
using Wabbajack.App.Views;
|
||||
|
||||
namespace Wabbajack.App.Screens
|
||||
{
|
||||
public partial class LauncherView : ScreenBase<LauncherViewModel>
|
||||
{
|
||||
public LauncherView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.OneWayBind(ViewModel, vm => vm.Image, view => view.ModListImage.Source)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.OneWayBind(ViewModel, vm => vm.Title, view => view.ModList.Text)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.OneWayBind(ViewModel, vm => vm.InstallFolder, view => view.InstallPath.Text,
|
||||
v => v.ToString())
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.PlayButton, view => view.PlayGame.Button)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
102
Wabbajack.App/Screens/LauncherViewModel.cs
Normal file
102
Wabbajack.App/Screens/LauncherViewModel.cs
Normal file
@ -0,0 +1,102 @@
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Media.Imaging;
|
||||
using GameFinder.StoreHandlers.Origin.DTO;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Wabbajack.App.Extensions;
|
||||
using Wabbajack.App.Messages;
|
||||
using Wabbajack.App.Models;
|
||||
using Wabbajack.App.ViewModels;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.DTOs;
|
||||
using Wabbajack.DTOs.SavedSettings;
|
||||
using Wabbajack.Paths;
|
||||
using Wabbajack.Paths.IO;
|
||||
|
||||
namespace Wabbajack.App.Screens
|
||||
{
|
||||
public class LauncherViewModel : ViewModelBase, IActivatableViewModel, IReceiver<ConfigureLauncher>
|
||||
{
|
||||
|
||||
[Reactive]
|
||||
public AbsolutePath InstallFolder { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public IBitmap Image { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public InstallationConfigurationSetting? Setting { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string Title { get; set; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> PlayButton;
|
||||
private readonly ILogger<LauncherViewModel> _logger;
|
||||
|
||||
public LauncherViewModel(ILogger<LauncherViewModel> logger, InstallationStateManager manager)
|
||||
{
|
||||
Activator = new ViewModelActivator();
|
||||
PlayButton = ReactiveCommand.Create(() =>
|
||||
{
|
||||
StartGame().FireAndForget();
|
||||
});
|
||||
_logger = logger;
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.WhenAnyValue(v => v.InstallFolder)
|
||||
.SelectAsync(disposables, async folder => await manager.GetByInstallFolder(folder))
|
||||
.ObserveOn(RxApp.MainThreadScheduler)
|
||||
.Where(v => v != null)
|
||||
.BindTo(this, vm => vm.Setting)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.WhenAnyValue(v => v.Setting)
|
||||
.Where(v => v != default)
|
||||
.Select(v => new Bitmap((v!.Image).ToString()))
|
||||
.BindTo(this, vm => vm.Image)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
this.WhenAnyValue(v => v.Setting)
|
||||
.Where(v => v is { Metadata: { } })
|
||||
.Select(v => $"{v!.Metadata!.Title} v{v!.Metadata.Version}")
|
||||
.BindTo(this, vm => vm.Title)
|
||||
.DisposeWith(disposables);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private async Task StartGame()
|
||||
{
|
||||
var mo2Path = InstallFolder.Combine("ModOrganizer.exe");
|
||||
var gamePath = GameRegistry.Games.Values.Select(g => g.MainExecutable)
|
||||
.Where(ge => ge != null)
|
||||
.Select(ge => InstallFolder.Combine(ge!))
|
||||
.FirstOrDefault(ge => ge.FileExists());
|
||||
if (mo2Path.FileExists())
|
||||
{
|
||||
Process.Start(mo2Path.ToString());
|
||||
}
|
||||
else if (gamePath.FileExists())
|
||||
{
|
||||
Process.Start(gamePath.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("No way to launch game, no acceptable executable found");
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(ConfigureLauncher val)
|
||||
{
|
||||
InstallFolder = val.InstallFolder;
|
||||
}
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
<Viewbox Grid.Row="3" HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform">
|
||||
<Image x:Name="SlideImage" Source="C:\tmp\modlist-image.png"></Image>
|
||||
<Image x:Name="SlideImage"></Image>
|
||||
</Viewbox>
|
||||
<Grid Grid.Row="4" HorizontalAlignment="Center" ColumnDefinitions="40, 40, 40, 40">
|
||||
<Button Grid.Column="0" x:Name="PrevSlide"><i:MaterialIcon Kind="ArrowLeft"></i:MaterialIcon></Button>
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reactive;
|
||||
@ -13,12 +14,17 @@ using Microsoft.Extensions.Logging;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Wabbajack.App.Messages;
|
||||
using Wabbajack.App.Models;
|
||||
using Wabbajack.App.Screens;
|
||||
using Wabbajack.App.Utilities;
|
||||
using Wabbajack.App.ViewModels.SubViewModels;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.DTOs;
|
||||
using Wabbajack.DTOs.DownloadStates;
|
||||
using Wabbajack.DTOs.JsonConverters;
|
||||
using Wabbajack.DTOs.SavedSettings;
|
||||
using Wabbajack.Installer;
|
||||
using Wabbajack.Paths.IO;
|
||||
using Wabbajack.RateLimiter;
|
||||
|
||||
namespace Wabbajack.App.ViewModels
|
||||
@ -36,6 +42,7 @@ namespace Wabbajack.App.ViewModels
|
||||
private readonly HttpClient _httpClient;
|
||||
private Timer _slideTimer;
|
||||
private int _currentSlideIndex;
|
||||
private readonly InstallationStateManager _installStateManager;
|
||||
|
||||
[Reactive]
|
||||
public SlideViewModel Slide { get; set; }
|
||||
@ -58,13 +65,15 @@ namespace Wabbajack.App.ViewModels
|
||||
[Reactive] public Percent StepsProgress { get; set; } = Percent.Zero;
|
||||
[Reactive] public Percent StepProgress { get; set; } = Percent.Zero;
|
||||
|
||||
public StandardInstallationViewModel(ILogger<StandardInstallationViewModel> logger, IServiceProvider provider, GameLocator locator, DTOSerializer dtos, HttpClient httpClient)
|
||||
public StandardInstallationViewModel(ILogger<StandardInstallationViewModel> logger, IServiceProvider provider, GameLocator locator, DTOSerializer dtos,
|
||||
HttpClient httpClient, InstallationStateManager manager)
|
||||
{
|
||||
_provider = provider;
|
||||
_locator = locator;
|
||||
_logger = logger;
|
||||
_dtos = dtos;
|
||||
_httpClient = httpClient;
|
||||
_installStateManager = manager;
|
||||
Activator = new ViewModelActivator();
|
||||
|
||||
this.WhenActivated(disposables => {
|
||||
@ -142,6 +151,7 @@ namespace Wabbajack.App.ViewModels
|
||||
_config.Downloads = msg.Download;
|
||||
_config.Install = msg.Install;
|
||||
_config.ModlistArchive = msg.ModListPath;
|
||||
_config.Metadata = msg.Metadata;
|
||||
|
||||
_logger.LogInformation("Loading ModList Data");
|
||||
_config.ModList = await StandardInstaller.LoadFromFile(_dtos, msg.ModListPath);
|
||||
@ -180,7 +190,34 @@ namespace Wabbajack.App.ViewModels
|
||||
};
|
||||
|
||||
_logger.LogInformation("Installer created, starting the installation process");
|
||||
await _installer.Begin(CancellationToken.None);
|
||||
var result = await _installer.Begin(CancellationToken.None);
|
||||
|
||||
if (result)
|
||||
{
|
||||
await SaveConfigAndContinue(_config);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveConfigAndContinue(InstallerConfiguration config)
|
||||
{
|
||||
var path = config.Install.Combine("modlist-image.png");
|
||||
{
|
||||
var image = await ModListUtilities.GetModListImageStream(config.ModlistArchive);
|
||||
await using var os = path.Open(FileMode.Create, FileAccess.Write);
|
||||
await image.CopyToAsync(os);
|
||||
}
|
||||
|
||||
await _installStateManager.SetLastState(new InstallationConfigurationSetting
|
||||
{
|
||||
Downloads = config.Downloads,
|
||||
Install = config.Install,
|
||||
Metadata = config.Metadata,
|
||||
ModList = config.ModlistArchive,
|
||||
Image = path
|
||||
});
|
||||
|
||||
MessageBus.Instance.Send(new ConfigureLauncher(config.Install));
|
||||
MessageBus.Instance.Send(new NavigateTo(typeof(LauncherViewModel)));
|
||||
}
|
||||
}
|
||||
}
|
@ -46,6 +46,8 @@ namespace Wabbajack.App
|
||||
services.AddSingleton<IScreenView, StandardInstallationView>();
|
||||
services.AddSingleton<IScreenView, SettingsView>();
|
||||
services.AddSingleton<IScreenView, BrowseView>();
|
||||
services.AddSingleton<IScreenView, LauncherView>();
|
||||
|
||||
services.AddSingleton<InstallationStateManager>();
|
||||
services.AddSingleton<HttpClient>();
|
||||
|
||||
@ -56,6 +58,7 @@ namespace Wabbajack.App
|
||||
services.AddAllSingleton<IReceiverMarker, NexusLoginViewModel>();
|
||||
services.AddAllSingleton<IReceiverMarker, LoversLabOAuthLoginViewModel>();
|
||||
services.AddAllSingleton<IReceiverMarker, VectorPlexusOAuthLoginViewModel>();
|
||||
services.AddAllSingleton<IReceiverMarker, LauncherViewModel>();
|
||||
|
||||
// Services
|
||||
services.AddAllSingleton<IDownloader, IDownloader<Manual>, ManualDownloader>();
|
||||
|
21
Wabbajack.App/Utilities/ModListUtilities.cs
Normal file
21
Wabbajack.App/Utilities/ModListUtilities.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Threading.Tasks;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Paths;
|
||||
using Wabbajack.Paths.IO;
|
||||
|
||||
namespace Wabbajack.App.Utilities
|
||||
{
|
||||
public class ModListUtilities
|
||||
{
|
||||
public static async Task<MemoryStream> GetModListImageStream(AbsolutePath modList)
|
||||
{
|
||||
await using var fs = modList.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
using var ar = new ZipArchive(fs, ZipArchiveMode.Read);
|
||||
var entry = ar.GetEntry("modlist-image.png");
|
||||
await using var stream = entry!.Open();
|
||||
return new MemoryStream(await stream.ReadAllAsync());
|
||||
}
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ using ReactiveUI.Validation.Extensions;
|
||||
using Wabbajack.App.Extensions;
|
||||
using Wabbajack.App.Messages;
|
||||
using Wabbajack.App.Models;
|
||||
using Wabbajack.App.Utilities;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.DTOs;
|
||||
using Wabbajack.DTOs.JsonConverters;
|
||||
@ -63,7 +64,7 @@ namespace Wabbajack.App.ViewModels
|
||||
this.ValidationRule(x => x.Install, p => p.DirectoryExists(), "Install folder file must exist");
|
||||
this.ValidationRule(x => x.Download, p => p != default, "Download folder must be set");
|
||||
|
||||
BeginCommand = ReactiveCommand.Create(StartInstall, this.IsValid());
|
||||
BeginCommand = ReactiveCommand.Create(() => {StartInstall().FireAndForget();}, this.IsValid());
|
||||
|
||||
|
||||
this.WhenAnyValue(t => t.ModListPath)
|
||||
@ -97,26 +98,30 @@ namespace Wabbajack.App.ViewModels
|
||||
|
||||
}
|
||||
|
||||
private void StartInstall()
|
||||
private async Task StartInstall()
|
||||
{
|
||||
ModlistMetadata? metadata = null;
|
||||
var metadataPath = ModListPath.WithExtension(Ext.MetaData);
|
||||
if (metadataPath.FileExists())
|
||||
{
|
||||
metadata = _dtos.Deserialize<ModlistMetadata>(await metadataPath.ReadAllTextAsync());
|
||||
}
|
||||
|
||||
_stateManager.SetLastState(new InstallationConfigurationSetting
|
||||
{
|
||||
ModList = ModListPath,
|
||||
Downloads = Download,
|
||||
Install = Install
|
||||
Install = Install,
|
||||
Metadata = metadata
|
||||
}).FireAndForget();
|
||||
|
||||
MessageBus.Instance.Send(new NavigateTo(typeof(StandardInstallationViewModel)));
|
||||
MessageBus.Instance.Send(new StartInstallation(ModListPath, Install, Download));
|
||||
MessageBus.Instance.Send(new StartInstallation(ModListPath, Install, Download, metadata));
|
||||
}
|
||||
|
||||
private async Task<IBitmap> LoadModListImage(AbsolutePath path)
|
||||
{
|
||||
await using var fs = path.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
using var ar = new ZipArchive(fs, ZipArchiveMode.Read);
|
||||
var entry = ar.GetEntry("modlist-image.png");
|
||||
await using var stream = entry!.Open();
|
||||
return new Bitmap(new MemoryStream(await stream.ReadAllAsync()));
|
||||
return new Bitmap(await ModListUtilities.GetModListImageStream(path));
|
||||
}
|
||||
|
||||
private async Task<ModList> LoadModList(AbsolutePath modlist)
|
||||
|
@ -14,9 +14,11 @@ using ReactiveUI.Fody.Helpers;
|
||||
using ReactiveUI.Validation.Helpers;
|
||||
using Wabbajack.App.Interfaces;
|
||||
using Wabbajack.App.Messages;
|
||||
using Wabbajack.App.Models;
|
||||
using Wabbajack.App.Screens;
|
||||
using Wabbajack.App.Views;
|
||||
using Wabbajack.Common;
|
||||
using Wabbajack.Paths.IO;
|
||||
using Wabbajack.RateLimiter;
|
||||
|
||||
namespace Wabbajack.App.ViewModels
|
||||
@ -28,6 +30,7 @@ namespace Wabbajack.App.ViewModels
|
||||
private readonly IResource[] _resources;
|
||||
private StatusReport[] _prevReport;
|
||||
private readonly Task _resourcePoller;
|
||||
private readonly InstallationStateManager _manager;
|
||||
|
||||
[Reactive]
|
||||
public Control CurrentScreen { get; set; }
|
||||
@ -44,11 +47,13 @@ namespace Wabbajack.App.ViewModels
|
||||
[Reactive]
|
||||
public string ResourceStatus { get; set; }
|
||||
|
||||
public MainWindowViewModel(IEnumerable<IScreenView> screens, IEnumerable<IResource> resources, IServiceProvider provider)
|
||||
public MainWindowViewModel(IEnumerable<IScreenView> screens, IEnumerable<IResource> resources, IServiceProvider provider,
|
||||
InstallationStateManager manager)
|
||||
{
|
||||
_provider = provider;
|
||||
_screens = screens;
|
||||
_resources = resources.ToArray();
|
||||
_manager = manager;
|
||||
|
||||
_prevReport = NextReport();
|
||||
|
||||
@ -73,9 +78,26 @@ namespace Wabbajack.App.ViewModels
|
||||
.DisposeWith(disposables);
|
||||
|
||||
});
|
||||
|
||||
Receive(new NavigateTo(typeof(ModeSelectionViewModel)));
|
||||
|
||||
LoadFirstScreen().FireAndForget();
|
||||
|
||||
}
|
||||
|
||||
private async Task LoadFirstScreen()
|
||||
{
|
||||
var setting = await _manager.GetLastState();
|
||||
if (setting.Install != default && setting.Install.DirectoryExists())
|
||||
{
|
||||
BreadCrumbs =
|
||||
BreadCrumbs.Push((Control)_screens.First(s => s.ViewModelType == typeof(ModeSelectionViewModel)));
|
||||
|
||||
MessageBus.Instance.Send(new ConfigureLauncher(setting.Install));
|
||||
Receive(new NavigateTo(typeof(LauncherViewModel)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Receive(new NavigateTo(typeof(ModeSelectionViewModel)));
|
||||
}
|
||||
}
|
||||
|
||||
private StatusReport[] NextReport()
|
||||
|
@ -41,6 +41,10 @@
|
||||
<DependentUpon>SettingsView.axaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Screens\StandardInstallationView.axaml.cs">
|
||||
<DependentUpon>StandardInstallationView.axaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="AferBuild" AfterTargets="Build">
|
||||
|
@ -19,5 +19,6 @@ namespace Wabbajack.Common
|
||||
public static Extension Dds = new(".dds");
|
||||
public static Extension Json = new(".json");
|
||||
public static Extension Md = new(".md");
|
||||
public static Extension MetaData = new(".metadata");
|
||||
}
|
||||
}
|
@ -16,5 +16,9 @@ namespace Wabbajack.DTOs.SavedSettings
|
||||
public AbsolutePath ModList { get; set; }
|
||||
public AbsolutePath Install { get; set; }
|
||||
public AbsolutePath Downloads { get; set; }
|
||||
|
||||
public ModlistMetadata? Metadata { get; set; }
|
||||
|
||||
public AbsolutePath Image { get; set; }
|
||||
}
|
||||
}
|
@ -12,5 +12,7 @@ namespace Wabbajack.Installer
|
||||
public SystemParameters? SystemParameters { get; set; }
|
||||
public Game Game { get; set; }
|
||||
public AbsolutePath GameFolder { get; set; }
|
||||
|
||||
public ModlistMetadata? Metadata { get; set; }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user