mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Work on the launch page
This commit is contained in:
parent
07ec856ee4
commit
6bc1662399
@ -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 =>
|
||||
|
15
Wabbajack.App/Screens/LauncherView.axaml
Normal file
15
Wabbajack.App/Screens/LauncherView.axaml
Normal file
@ -0,0 +1,15 @@
|
||||
<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"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Wabbajack.App.Screens.LauncherScreen">
|
||||
<Grid RowDefinitions="40, *, Auto">
|
||||
<TextBlock Grid.Row="0" x:Name="StatusText" FontSize="20" FontWeight="Bold">[20/30] Installing Files</TextBlock>
|
||||
<Viewbox Grid.Row="1" HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Stretch="Uniform">
|
||||
<Image x:Name="SlideImage"></Image>
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</UserControl>
|
23
Wabbajack.App/Screens/LauncherView.axaml.cs
Normal file
23
Wabbajack.App/Screens/LauncherView.axaml.cs
Normal file
@ -0,0 +1,23 @@
|
||||
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 LauncherScreen : ScreenBase<LauncherViewModel>
|
||||
{
|
||||
public LauncherScreen()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.OneWayBind(ViewModel, vm => vm.Image, view => view.SlideImage.Source)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
52
Wabbajack.App/Screens/LauncherViewModel.cs
Normal file
52
Wabbajack.App/Screens/LauncherViewModel.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using Avalonia.Media.Imaging;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Wabbajack.App.Extensions;
|
||||
using Wabbajack.App.Messages;
|
||||
using Wabbajack.App.Models;
|
||||
using Wabbajack.App.ViewModels;
|
||||
using Wabbajack.DTOs.SavedSettings;
|
||||
using Wabbajack.Paths;
|
||||
|
||||
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; }
|
||||
|
||||
public LauncherViewModel(InstallationStateManager manager)
|
||||
{
|
||||
Activator = new ViewModelActivator();
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.WhenAnyValue(v => v.InstallFolder)
|
||||
.SelectAsync(disposables, async folder => await manager.GetByInstallFolder(folder))
|
||||
.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);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
}
|
||||
}
|
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)
|
||||
|
@ -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