diff --git a/Wabbajack/View Models/BackNavigatingVM.cs b/Wabbajack/View Models/BackNavigatingVM.cs index 59408f39..bf89054a 100644 --- a/Wabbajack/View Models/BackNavigatingVM.cs +++ b/Wabbajack/View Models/BackNavigatingVM.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reactive; @@ -35,8 +35,7 @@ namespace Wabbajack canExecute: this.ConstructCanNavigateBack() .ObserveOnGuiThread()); - _IsActive = mainWindowVM.WhenAny(x => x.ActivePane) - .Select(x => object.ReferenceEquals(this, x)) + _IsActive = this.ConstructIsActive(mainWindowVM) .ToProperty(this, nameof(IsActive)); } } @@ -48,5 +47,11 @@ namespace Wabbajack return vm.WhenAny(x => x.NavigateBackTarget) .Select(x => x != null); } + + public static IObservable<bool> ConstructIsActive(this IBackNavigatingVM vm, MainWindowVM mwvm) + { + return mwvm.WhenAny(x => x.ActivePane) + .Select(x => object.ReferenceEquals(vm, x)); + } } } diff --git a/Wabbajack/View Models/Installers/InstallerVM.cs b/Wabbajack/View Models/Installers/InstallerVM.cs index 3beca8df..29d262e4 100644 --- a/Wabbajack/View Models/Installers/InstallerVM.cs +++ b/Wabbajack/View Models/Installers/InstallerVM.cs @@ -1,4 +1,4 @@ -using Syroot.Windows.IO; +using Syroot.Windows.IO; using System; using ReactiveUI; using System.Diagnostics; @@ -30,8 +30,8 @@ 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); + public static BitmapImage WabbajackLogo { get; } = UIUtils.BitmapImageFromStream(Application.GetResourceStream(new Uri("pack://application:,,,/Wabbajack;component/Resources/Wabba_Mouth_No_Text.png")).Stream); + public static 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; @@ -92,6 +92,9 @@ namespace Wabbajack private readonly ObservableAsPropertyHelper<bool> _LoadingModlist; public bool LoadingModlist => _LoadingModlist.Value; + private readonly ObservableAsPropertyHelper<bool> _IsActive; + public bool IsActive => _IsActive.Value; + // Command properties public IReactiveCommand ShowReportCommand { get; } public IReactiveCommand OpenReadmeCommand { get; } @@ -154,8 +157,28 @@ namespace Wabbajack }) .DisposeWith(CompositeDisposable); - _modList = this.WhenAny(x => x.ModListLocation.TargetPath) + _IsActive = this.ConstructIsActive(MWVM) + .ToProperty(this, nameof(IsActive)); + + // Active path represents the path to currently have loaded + // If we're not actively showing, then "unload" the active path + var activePath = Observable.CombineLatest( + this.WhenAny(x => x.ModListLocation.TargetPath), + this.WhenAny(x => x.IsActive), + resultSelector: (path, active) => (path, active)) + .Select(x => + { + if (!x.active) return default(string); + return x.path; + }) + // Throttle slightly so changes happen more atomically + .Throttle(TimeSpan.FromMilliseconds(50)) + .Replay(1) + .RefCount(); + + _modList = activePath .ObserveOn(RxApp.TaskpoolScheduler) + // Convert from active path to modlist VM .Select(modListPath => { if (modListPath == null) return default(ModListVM); @@ -166,8 +189,8 @@ namespace Wabbajack .StartWith(default(ModListVM)) .ToProperty(this, nameof(ModList)); _LoadingModlist = Observable.Merge( - // When target location changes, mark as loading - this.WhenAny(x => x.ModListLocation.TargetPath) + // When active path changes, mark as loading + activePath .Select(_ => true), // When the resulting modlist comes in, mark it as done this.WhenAny(x => x.ModList) @@ -230,20 +253,21 @@ namespace Wabbajack _image = Observable.CombineLatest( this.WhenAny(x => x.ModList.Error), this.WhenAny(x => x.ModList) - .Select(x => x?.ImageObservable ?? Observable.Return(WabbajackLogo)) + .Select(x => x?.ImageObservable ?? Observable.Return(default(BitmapImage))) .Switch() - .StartWith(WabbajackLogo), + .StartWith(default(BitmapImage)), this.WhenAny(x => x.Slideshow.Image) .StartWith(default(BitmapImage)), this.WhenAny(x => x.Installing), - resultSelector: (err, modList, slideshow, installing) => + this.WhenAny(x => x.LoadingModlist), + resultSelector: (err, modList, slideshow, installing, loading) => { if (err != null) { return WabbajackErrLogo; } - var ret = installing ? slideshow : modList; - return ret ?? WabbajackLogo; + if (loading) return default; + return installing ? slideshow : modList; }) .Select<BitmapImage, ImageSource>(x => x) .ToProperty(this, nameof(Image)); diff --git a/Wabbajack/View Models/ModListVM.cs b/Wabbajack/View Models/ModListVM.cs index b08f933f..94962a4e 100644 --- a/Wabbajack/View Models/ModListVM.cs +++ b/Wabbajack/View Models/ModListVM.cs @@ -42,6 +42,7 @@ namespace Wabbajack } ImageObservable = Observable.Return(Unit.Default) + // Download and retrieve bytes on background thread .ObserveOn(RxApp.TaskpoolScheduler) .Select(filePath => { @@ -66,6 +67,7 @@ namespace Wabbajack return default(MemoryStream); } }) + // Create Bitmap image on GUI thread .ObserveOnGuiThread() .Select(memStream => { @@ -80,6 +82,11 @@ namespace Wabbajack return default(BitmapImage); } }) + // If ever would return null, show WJ logo instead + .Select(x => + { + return x ?? InstallerVM.WabbajackLogo; + }) .Replay(1) .RefCount(); }