Install config no longer breaks if pointed to bad modlist

This commit is contained in:
Justin Swanson 2019-12-02 23:35:51 -06:00
parent 36359e4416
commit 1a5e052aef
11 changed files with 76 additions and 30 deletions

BIN
Branding/PNGs/Wabba_Ded.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

View File

@ -18,7 +18,14 @@ namespace Wabbajack
{
if (Exception != null)
{
return Exception.ToString();
if (string.IsNullOrWhiteSpace(_reason))
{
return Exception.ToString();
}
else
{
return $"{_reason}: {Exception.Message}";
}
}
return _reason;
}
@ -53,9 +60,9 @@ namespace Wabbajack
return new ErrorResponse(true, reason);
}
public static ErrorResponse Fail(string reason)
public static ErrorResponse Fail(string reason, Exception ex = null)
{
return new ErrorResponse(false, reason: reason);
return new ErrorResponse(false, reason: reason, ex: ex);
}
public static ErrorResponse Fail(Exception ex)

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

View File

@ -1,4 +1,4 @@
using Syroot.Windows.IO;
using Syroot.Windows.IO;
using System;
using ReactiveUI;
using System.Diagnostics;
@ -28,6 +28,7 @@ namespace Wabbajack
public MainWindowVM MWVM { get; }
public BitmapImage WabbajackLogo { get; } = UIUtils.BitmapImageFromStream(Application.GetResourceStream(new Uri("pack://application:,,,/Wabbajack;component/Resources/Wabba_Mouth_No_Text.png")).Stream);
public BitmapImage WabbajackErrLogo { get; } = UIUtils.BitmapImageFromStream(Application.GetResourceStream(new Uri("pack://application:,,,/Wabbajack;component/Resources/Wabba_Ded.png")).Stream);
private readonly ObservableAsPropertyHelper<ModListVM> _modList;
public ModListVM ModList => _modList.Value;
@ -143,9 +144,7 @@ namespace Wabbajack
{
if (modListPath == null) return default(ModListVM);
if (!File.Exists(modListPath)) return default(ModListVM);
var modList = AInstaller.LoadFromFile(modListPath);
if (modList == null) return default(ModListVM);
return new ModListVM(modList, modListPath);
return new ModListVM(modListPath);
})
.ObserveOnGuiThread()
.StartWith(default(ModListVM))
@ -161,6 +160,15 @@ namespace Wabbajack
.Select(modList => modList?.ModManager)
.ToProperty(this, nameof(TargetManager));
// Add additional error check on modlist
ModListPath.AdditionalError = this.WhenAny(x => x.ModList)
.Select<ModListVM, IErrorResponse>(modList =>
{
if (modList == null) return ErrorResponse.Fail("Modlist path resulted in a null object.");
if (modList.Error != null) return ErrorResponse.Fail("Modlist is corrupt", modList.Error);
return ErrorResponse.Success;
});
BackCommand = ReactiveCommand.Create(
execute: () => mainWindowVM.ActivePane = mainWindowVM.ModeSelectionVM,
canExecute: this.WhenAny(x => x.Installing)
@ -186,6 +194,7 @@ namespace Wabbajack
// Set display items to modlist if configuring or complete,
// or to the current slideshow data if installing
_image = Observable.CombineLatest(
this.WhenAny(x => x.ModList.Error),
this.WhenAny(x => x.ModList)
.SelectMany(x => x?.ImageObservable ?? Observable.Empty<BitmapImage>())
.NotNull()
@ -193,7 +202,14 @@ namespace Wabbajack
this.WhenAny(x => x.Slideshow.Image)
.StartWith(default(BitmapImage)),
this.WhenAny(x => x.Installing),
resultSelector: (modList, slideshow, installing) => installing ? slideshow : modList)
resultSelector: (err, modList, slideshow, installing) =>
{
if (err != null)
{
return WabbajackErrLogo;
}
return installing ? slideshow : modList;
})
.Select<BitmapImage, ImageSource>(x => x)
.ToProperty(this, nameof(Image));
_titleText = Observable.CombineLatest(
@ -217,8 +233,16 @@ namespace Wabbajack
this.WhenAny(x => x.Installing),
resultSelector: (modList, mod, installing) => installing ? mod : modList)
.ToProperty(this, nameof(Description));
_modListName = this.WhenAny(x => x.ModList)
.Select(x => x?.Name)
_modListName = Observable.CombineLatest(
this.WhenAny(x => x.ModList.Error)
.Select(x => x != null),
this.WhenAny(x => x.ModList)
.Select(x => x?.Name),
resultSelector: (err, name) =>
{
if (err) return "Corrupted Modlist";
return name;
})
.ToProperty(this, nameof(ModListName));
// Define commands

View File

@ -54,9 +54,10 @@ namespace Wabbajack
canExecute: Observable.CombineLatest(
this.WhenAny(x => x.Location.InError),
this.WhenAny(x => x.DownloadLocation.InError),
resultSelector: (loc, download) =>
installerVM.WhenAny(x => x.ModListPath.InError),
resultSelector: (loc, modlist, download) =>
{
return !loc && !download;
return !loc && !download && !modlist;
})
.ObserveOnGuiThread(),
execute: async () =>

View File

@ -33,8 +33,11 @@ namespace Wabbajack
.ToProperty(this, nameof(TargetGame));
BeginCommand = ReactiveCommand.CreateFromTask(
canExecute: this.WhenAny(x => x.TargetGame)
.Select(game => VortexCompiler.IsActiveVortexGame(game)),
canExecute: Observable.CombineLatest(
this.WhenAny(x => x.TargetGame)
.Select(game => VortexCompiler.IsActiveVortexGame(game)),
installerVM.WhenAny(x => x.ModListPath.InError),
resultSelector: (isVortexGame, modListErr) => isVortexGame && !modListErr),
execute: async () =>
{
AInstaller installer;

View File

@ -12,25 +12,33 @@ namespace Wabbajack
public class ModListVM : ViewModel
{
public ModList SourceModList { get; }
public Exception Error { get; }
public string ModListPath { get; }
public string Name => SourceModList.Name;
public string ReportHTML => SourceModList.ReportHTML;
public string Readme => SourceModList.Readme;
public string ImageURL => SourceModList.Image;
public string Author => SourceModList.Author;
public string Description => SourceModList.Description;
public string Website => SourceModList.Website;
public ModManager ModManager => SourceModList.ModManager;
public string Name => SourceModList?.Name;
public string ReportHTML => SourceModList?.ReportHTML;
public string Readme => SourceModList?.Readme;
public string ImageURL => SourceModList?.Image;
public string Author => SourceModList?.Author;
public string Description => SourceModList?.Description;
public string Website => SourceModList?.Website;
public ModManager ModManager => SourceModList?.ModManager ?? ModManager.MO2;
// Image isn't exposed as a direct property, but as an observable.
// This acts as a caching mechanism, as interested parties will trigger it to be created,
// and the cached image will automatically be released when the last interested party is gone.
public IObservable<BitmapImage> ImageObservable { get; }
public ModListVM(ModList sourceModList, string modListPath)
public ModListVM(string modListPath)
{
ModListPath = modListPath;
SourceModList = sourceModList;
try
{
SourceModList = AInstaller.LoadFromFile(modListPath);
}
catch (Exception ex)
{
Error = ex;
}
ImageObservable = Observable.Return(ImageURL)
.ObserveOn(RxApp.TaskpoolScheduler)
@ -39,13 +47,13 @@ namespace Wabbajack
try
{
if (!File.Exists(url)) return default(MemoryStream);
if (string.IsNullOrWhiteSpace(sourceModList.Image)) return default(MemoryStream);
if (sourceModList.Image.Length != 36) return default(MemoryStream);
if (string.IsNullOrWhiteSpace(ImageURL)) return default(MemoryStream);
if (ImageURL.Length != 36) return default(MemoryStream);
using (var fs = new FileStream(ModListPath, FileMode.Open, FileAccess.Read, FileShare.Read))
using (var ar = new ZipArchive(fs, ZipArchiveMode.Read))
{
var ms = new MemoryStream();
var entry = ar.GetEntry(sourceModList.Image);
var entry = ar.GetEntry(ImageURL);
using (var e = entry.Open())
{
e.CopyTo(ms);

View File

@ -1,4 +1,4 @@
using DynamicData;
using DynamicData;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System;
@ -74,7 +74,7 @@ namespace Wabbajack
// Whenever modlist changes, grab the list of its slides
.Select(modList =>
{
if (modList == null)
if (modList?.SourceModList?.Archives == null)
{
return Observable.Empty<ModVM>()
.ToObservableChangeSet(x => x.ModID);

View File

@ -312,7 +312,7 @@
Grid.Column="2"
Height="30"
VerticalAlignment="Center"
DataContext="{Binding ModListPath}"
DataContext="{Binding ModListLocation}"
FontSize="14" />
<ContentPresenter
Grid.Row="2"

View File

@ -510,5 +510,8 @@
<ItemGroup>
<Resource Include="Resources\Wabba_Mouth_No_Text.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Wabba_Ded.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>