mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
ToGuiProperty convenience call
Automatically wires on GUI thread and disposes
This commit is contained in:
parent
04b2d13499
commit
8571003cfd
@ -2,10 +2,12 @@
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using DynamicData;
|
||||
using DynamicData.Kernel;
|
||||
using ReactiveUI;
|
||||
using Wabbajack.Lib;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
@ -78,6 +80,29 @@ namespace Wabbajack
|
||||
return new ChangeSet<TObject, TKey>(changes);
|
||||
}
|
||||
|
||||
public static ObservableAsPropertyHelper<TRet> ToGuiProperty<TRet>(
|
||||
this IObservable<TRet> source,
|
||||
ViewModel vm,
|
||||
string property,
|
||||
TRet initialValue = default,
|
||||
bool deferSubscription = false)
|
||||
{
|
||||
return source
|
||||
.ToProperty(vm, property, initialValue, deferSubscription, RxApp.MainThreadScheduler)
|
||||
.DisposeWith(vm.CompositeDisposable);
|
||||
}
|
||||
|
||||
public static void ToGuiProperty<TRet>(
|
||||
this IObservable<TRet> source,
|
||||
ViewModel vm,
|
||||
string property,
|
||||
out ObservableAsPropertyHelper<TRet> result,
|
||||
TRet initialValue = default,
|
||||
bool deferSubscription = false)
|
||||
{
|
||||
source.ToProperty(vm, property, out result, initialValue, deferSubscription, RxApp.MainThreadScheduler)
|
||||
.DisposeWith(vm.CompositeDisposable);
|
||||
}
|
||||
|
||||
internal static Optional<Change<TObject, TKey>> Reduce<TObject, TKey>(Optional<Change<TObject, TKey>> previous, Change<TObject, TKey> next)
|
||||
{
|
||||
|
@ -147,9 +147,8 @@ namespace Wabbajack
|
||||
}
|
||||
})
|
||||
.DistinctUntilChanged()
|
||||
.ObserveOnGuiThread()
|
||||
.StartWith(false)
|
||||
.ToProperty(this, nameof(Exists));
|
||||
.ToGuiProperty(this, nameof(Exists));
|
||||
|
||||
var passesFilters = Observable.CombineLatest(
|
||||
this.WhenAny(x => x.TargetPath),
|
||||
@ -218,12 +217,11 @@ namespace Wabbajack
|
||||
if (filter.Failed) return filter;
|
||||
return ErrorResponse.Convert(err);
|
||||
})
|
||||
.ObserveOnGuiThread()
|
||||
.ToProperty(this, nameof(ErrorState));
|
||||
.ToGuiProperty(this, nameof(ErrorState));
|
||||
|
||||
_inError = this.WhenAny(x => x.ErrorState)
|
||||
.Select(x => !x.Succeeded)
|
||||
.ToProperty(this, nameof(InError));
|
||||
.ToGuiProperty(this, nameof(InError));
|
||||
|
||||
// Doesn't derive from ErrorState, as we want to bubble non-empty tooltips,
|
||||
// which is slightly different logic
|
||||
@ -244,8 +242,7 @@ namespace Wabbajack
|
||||
if (!string.IsNullOrWhiteSpace(filters)) return filters;
|
||||
return err?.Reason;
|
||||
})
|
||||
.ObserveOnGuiThread()
|
||||
.ToProperty(this, nameof(ErrorTooltip));
|
||||
.ToGuiProperty(this, nameof(ErrorTooltip));
|
||||
}
|
||||
|
||||
public ICommand ConstructTypicalPickerCommand()
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
@ -36,7 +36,7 @@ namespace Wabbajack
|
||||
.ObserveOnGuiThread());
|
||||
|
||||
_IsActive = this.ConstructIsActive(mainWindowVM)
|
||||
.ToProperty(this, nameof(IsActive));
|
||||
.ToGuiProperty(this, nameof(IsActive));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,11 +115,11 @@ namespace Wabbajack
|
||||
pair.Previous?.Unload();
|
||||
})
|
||||
.Select(p => p.Current)
|
||||
.ToProperty(this, nameof(Compiler));
|
||||
.ToGuiProperty(this, nameof(Compiler));
|
||||
|
||||
// Let sub VM determine what settings we're displaying and when
|
||||
_currentModlistSettings = this.WhenAny(x => x.Compiler.ModlistSettings)
|
||||
.ToProperty(this, nameof(CurrentModlistSettings));
|
||||
.ToGuiProperty(this, nameof(CurrentModlistSettings));
|
||||
|
||||
_image = this.WhenAny(x => x.CurrentModlistSettings.ImagePath.TargetPath)
|
||||
// Throttle so that it only loads image after any sets of swaps have completed
|
||||
@ -135,12 +135,11 @@ namespace Wabbajack
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.ToProperty(this, nameof(Image));
|
||||
.ToGuiProperty(this, nameof(Image));
|
||||
|
||||
_compiling = this.WhenAny(x => x.Compiler.ActiveCompilation)
|
||||
.Select(compilation => compilation != null)
|
||||
.ObserveOnGuiThread()
|
||||
.ToProperty(this, nameof(Compiling));
|
||||
.ToGuiProperty(this, nameof(Compiling));
|
||||
|
||||
BackCommand = ReactiveCommand.Create(
|
||||
execute: () =>
|
||||
@ -176,7 +175,7 @@ namespace Wabbajack
|
||||
})
|
||||
.Switch()
|
||||
.Debounce(TimeSpan.FromMilliseconds(25))
|
||||
.ToProperty(this, nameof(PercentCompleted));
|
||||
.ToGuiProperty(this, nameof(PercentCompleted));
|
||||
|
||||
BeginCommand = ReactiveCommand.CreateFromTask(
|
||||
canExecute: this.WhenAny(x => x.Compiler.CanCompile)
|
||||
@ -217,8 +216,7 @@ namespace Wabbajack
|
||||
_ActiveGlobalUserIntervention = activeInterventions.Connect()
|
||||
.Filter(x => x.CpuID == WorkQueue.UnassignedCpuId)
|
||||
.QueryWhenChanged(query => query.FirstOrDefault())
|
||||
.ObserveOnGuiThread()
|
||||
.ToProperty(this, nameof(ActiveGlobalUserIntervention));
|
||||
.ToGuiProperty(this, nameof(ActiveGlobalUserIntervention));
|
||||
|
||||
CloseWhenCompleteCommand = ReactiveCommand.Create(
|
||||
canExecute: this.WhenAny(x => x.Completed)
|
||||
@ -263,12 +261,11 @@ namespace Wabbajack
|
||||
return "Configuring";
|
||||
}
|
||||
})
|
||||
.ToProperty(this, nameof(ProgressTitle));
|
||||
.ToGuiProperty(this, nameof(ProgressTitle));
|
||||
|
||||
_CurrentCpuCount = this.WhenAny(x => x.Compiler.ActiveCompilation.Queue.CurrentCpuCount)
|
||||
.Switch()
|
||||
.ObserveOnGuiThread()
|
||||
.ToProperty(this, nameof(CurrentCpuCount));
|
||||
.ToGuiProperty(this, nameof(CurrentCpuCount));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ namespace Wabbajack
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.ToProperty(this, nameof(Mo2Folder));
|
||||
.ToGuiProperty(this, nameof(Mo2Folder));
|
||||
_moProfile = this.WhenAny(x => x.ModListLocation.TargetPath)
|
||||
.Select(loc =>
|
||||
{
|
||||
@ -82,7 +82,7 @@ namespace Wabbajack
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.ToProperty(this, nameof(MOProfile));
|
||||
.ToGuiProperty(this, nameof(MOProfile));
|
||||
|
||||
// Wire missing Mo2Folder to signal error state for ModList Location
|
||||
ModListLocation.AdditionalError = this.WhenAny(x => x.Mo2Folder)
|
||||
@ -116,9 +116,7 @@ namespace Wabbajack
|
||||
pair.Current?.Init();
|
||||
})
|
||||
.Select(x => x.Current)
|
||||
// Save to property
|
||||
.ObserveOnGuiThread()
|
||||
.ToProperty(this, nameof(ModlistSettings));
|
||||
.ToGuiProperty(this, nameof(ModlistSettings));
|
||||
|
||||
CanCompile = Observable.CombineLatest(
|
||||
this.WhenAny(x => x.ModListLocation.InError),
|
||||
|
@ -94,9 +94,7 @@ namespace Wabbajack
|
||||
current?.Init();
|
||||
})
|
||||
.Select(x => x.Current)
|
||||
// Save to property
|
||||
.ObserveOnGuiThread()
|
||||
.ToProperty(this, nameof(ModlistSettings));
|
||||
.ToGuiProperty(this, nameof(ModlistSettings));
|
||||
|
||||
CanCompile = Observable.CombineLatest(
|
||||
this.WhenAny(x => x.GameLocation.InError),
|
||||
|
@ -1,4 +1,4 @@
|
||||
using Syroot.Windows.IO;
|
||||
using Syroot.Windows.IO;
|
||||
using System;
|
||||
using ReactiveUI;
|
||||
using System.Diagnostics;
|
||||
@ -147,7 +147,7 @@ namespace Wabbajack
|
||||
pair.Previous?.Unload();
|
||||
})
|
||||
.Select(p => p.Current)
|
||||
.ToProperty(this, nameof(Installer));
|
||||
.ToGuiProperty(this, nameof(Installer));
|
||||
|
||||
// Load settings
|
||||
MWVM.Settings.SaveSignal
|
||||
@ -158,7 +158,7 @@ namespace Wabbajack
|
||||
.DisposeWith(CompositeDisposable);
|
||||
|
||||
_IsActive = this.ConstructIsActive(MWVM)
|
||||
.ToProperty(this, nameof(IsActive));
|
||||
.ToGuiProperty(this, nameof(IsActive));
|
||||
|
||||
// Active path represents the path to currently have loaded
|
||||
// If we're not actively showing, then "unload" the active path
|
||||
@ -188,7 +188,7 @@ namespace Wabbajack
|
||||
.DisposeOld()
|
||||
.ObserveOnGuiThread()
|
||||
.StartWith(default(ModListVM))
|
||||
.ToProperty(this, nameof(ModList));
|
||||
.ToGuiProperty(this, nameof(ModList));
|
||||
|
||||
// Force GC collect when modlist changes, just to make sure we clean up any loose large items immediately
|
||||
this.WhenAny(x => x.ModList)
|
||||
@ -205,17 +205,16 @@ namespace Wabbajack
|
||||
// When the resulting modlist comes in, mark it as done
|
||||
this.WhenAny(x => x.ModList)
|
||||
.Select(_ => false))
|
||||
.ToProperty(this, nameof(LoadingModlist));
|
||||
.ToGuiProperty(this, nameof(LoadingModlist));
|
||||
_htmlReport = this.WhenAny(x => x.ModList)
|
||||
.Select(modList => modList?.ReportHTML)
|
||||
.ToProperty(this, nameof(HTMLReport));
|
||||
.ToGuiProperty(this, nameof(HTMLReport));
|
||||
_installing = this.WhenAny(x => x.Installer.ActiveInstallation)
|
||||
.Select(i => i != null)
|
||||
.ObserveOnGuiThread()
|
||||
.ToProperty(this, nameof(Installing));
|
||||
.ToGuiProperty(this, nameof(Installing));
|
||||
_TargetManager = this.WhenAny(x => x.ModList)
|
||||
.Select(modList => modList?.ModManager)
|
||||
.ToProperty(this, nameof(TargetManager));
|
||||
.ToGuiProperty(this, nameof(TargetManager));
|
||||
|
||||
// Add additional error check on ModList
|
||||
ModListLocation.AdditionalError = this.WhenAny(x => x.ModList)
|
||||
@ -254,7 +253,7 @@ namespace Wabbajack
|
||||
})
|
||||
.Switch()
|
||||
.Debounce(TimeSpan.FromMilliseconds(25))
|
||||
.ToProperty(this, nameof(PercentCompleted));
|
||||
.ToGuiProperty(this, nameof(PercentCompleted));
|
||||
|
||||
Slideshow = new SlideShow(this);
|
||||
|
||||
@ -280,7 +279,7 @@ namespace Wabbajack
|
||||
return installing ? slideshow : modList;
|
||||
})
|
||||
.Select<BitmapImage, ImageSource>(x => x)
|
||||
.ToProperty(this, nameof(Image));
|
||||
.ToGuiProperty(this, nameof(Image));
|
||||
_titleText = Observable.CombineLatest(
|
||||
this.WhenAny(x => x.ModList)
|
||||
.Select(modList => modList?.Name ?? string.Empty),
|
||||
@ -288,7 +287,7 @@ namespace Wabbajack
|
||||
.StartWith(default(string)),
|
||||
this.WhenAny(x => x.Installing),
|
||||
resultSelector: (modList, mod, installing) => installing ? mod : modList)
|
||||
.ToProperty(this, nameof(TitleText));
|
||||
.ToGuiProperty(this, nameof(TitleText));
|
||||
_authorText = Observable.CombineLatest(
|
||||
this.WhenAny(x => x.ModList)
|
||||
.Select(modList => modList?.Author ?? string.Empty),
|
||||
@ -296,7 +295,7 @@ namespace Wabbajack
|
||||
.StartWith(default(string)),
|
||||
this.WhenAny(x => x.Installing),
|
||||
resultSelector: (modList, mod, installing) => installing ? mod : modList)
|
||||
.ToProperty(this, nameof(AuthorText));
|
||||
.ToGuiProperty(this, nameof(AuthorText));
|
||||
_description = Observable.CombineLatest(
|
||||
this.WhenAny(x => x.ModList)
|
||||
.Select(modList => modList?.Description ?? string.Empty),
|
||||
@ -304,7 +303,7 @@ namespace Wabbajack
|
||||
.StartWith(default(string)),
|
||||
this.WhenAny(x => x.Installing),
|
||||
resultSelector: (modList, mod, installing) => installing ? mod : modList)
|
||||
.ToProperty(this, nameof(Description));
|
||||
.ToGuiProperty(this, nameof(Description));
|
||||
_modListName = Observable.CombineLatest(
|
||||
this.WhenAny(x => x.ModList.Error)
|
||||
.Select(x => x != null),
|
||||
@ -315,7 +314,7 @@ namespace Wabbajack
|
||||
if (err) return "Corrupted Modlist";
|
||||
return name;
|
||||
})
|
||||
.ToProperty(this, nameof(ModListName));
|
||||
.ToGuiProperty(this, nameof(ModListName));
|
||||
|
||||
// Define commands
|
||||
ShowReportCommand = ReactiveCommand.Create(ShowReport);
|
||||
@ -350,7 +349,7 @@ namespace Wabbajack
|
||||
return "Configuring";
|
||||
}
|
||||
})
|
||||
.ToProperty(this, nameof(ProgressTitle));
|
||||
.ToGuiProperty(this, nameof(ProgressTitle));
|
||||
|
||||
UIUtils.BindCpuStatus(
|
||||
this.WhenAny(x => x.Installer.ActiveInstallation)
|
||||
@ -405,8 +404,7 @@ namespace Wabbajack
|
||||
_ActiveGlobalUserIntervention = activeInterventions.Connect()
|
||||
.Filter(x => x.CpuID == WorkQueue.UnassignedCpuId)
|
||||
.QueryWhenChanged(query => query.FirstOrDefault())
|
||||
.ObserveOnGuiThread()
|
||||
.ToProperty(this, nameof(ActiveGlobalUserIntervention));
|
||||
.ToGuiProperty(this, nameof(ActiveGlobalUserIntervention));
|
||||
|
||||
CloseWhenCompleteCommand = ReactiveCommand.Create(
|
||||
canExecute: this.WhenAny(x => x.Completed)
|
||||
@ -429,8 +427,7 @@ namespace Wabbajack
|
||||
|
||||
_CurrentCpuCount = this.WhenAny(x => x.Installer.ActiveInstallation.Queue.CurrentCpuCount)
|
||||
.Switch()
|
||||
.ObserveOnGuiThread()
|
||||
.ToProperty(this, nameof(CurrentCpuCount));
|
||||
.ToGuiProperty(this, nameof(CurrentCpuCount));
|
||||
}
|
||||
|
||||
private void ShowReport()
|
||||
|
@ -88,7 +88,7 @@ namespace Wabbajack
|
||||
// Load settings
|
||||
_CurrentSettings = installerVM.WhenAny(x => x.ModListLocation.TargetPath)
|
||||
.Select(path => path == null ? null : installerVM.MWVM.Settings.Installer.Mo2ModlistSettings.TryCreate(path))
|
||||
.ToProperty(this, nameof(CurrentSettings));
|
||||
.ToGuiProperty(this, nameof(CurrentSettings));
|
||||
this.WhenAny(x => x.CurrentSettings)
|
||||
.Pairwise()
|
||||
.Subscribe(settingsPair =>
|
||||
|
@ -39,7 +39,7 @@ namespace Wabbajack
|
||||
Parent = installerVM;
|
||||
|
||||
_TargetGame = installerVM.WhenAny(x => x.ModList.SourceModList.GameType)
|
||||
.ToProperty(this, nameof(TargetGame));
|
||||
.ToGuiProperty(this, nameof(TargetGame));
|
||||
|
||||
CanInstall = Observable.CombineLatest(
|
||||
this.WhenAny(x => x.TargetGame)
|
||||
|
@ -119,11 +119,11 @@ namespace Wabbajack
|
||||
return true;
|
||||
}
|
||||
})
|
||||
.ToProperty(this, nameof(Exists));
|
||||
.ToGuiProperty(this, nameof(Exists));
|
||||
|
||||
_Image = Observable.Return(Metadata.Links.ImageUri)
|
||||
.DownloadBitmapImage((ex) => Utils.Log($"Error downloading modlist image {Metadata.Title}"))
|
||||
.ToProperty(this, nameof(Image));
|
||||
.ToGuiProperty(this, nameof(Image));
|
||||
}
|
||||
|
||||
private Task Download()
|
||||
|
@ -36,8 +36,7 @@ namespace Wabbajack
|
||||
{
|
||||
Login = login;
|
||||
_MetaInfo = (login.MetaInfo ?? Observable.Return(""))
|
||||
.ObserveOnGuiThread()
|
||||
.ToProperty(this, nameof(MetaInfo));
|
||||
.ToGuiProperty(this, nameof(MetaInfo));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,15 +109,14 @@ namespace Wabbajack
|
||||
return query.Items.ElementAtOrDefault(index);
|
||||
})
|
||||
.StartWith(default(ModVM))
|
||||
.ObserveOnGuiThread()
|
||||
.ToProperty(this, nameof(TargetMod));
|
||||
.ToGuiProperty(this, nameof(TargetMod));
|
||||
|
||||
// Mark interest and materialize image of target mod
|
||||
_image = this.WhenAny(x => x.TargetMod)
|
||||
// We want to Switch here, not SelectMany, as we want to hotswap to newest target without waiting on old ones
|
||||
.Select(x => x?.ImageObservable ?? Observable.Return(default(BitmapImage)))
|
||||
.Switch()
|
||||
.ToProperty(this, nameof(Image));
|
||||
.ToGuiProperty(this, nameof(Image));
|
||||
|
||||
VisitNexusSiteCommand = ReactiveCommand.Create(
|
||||
execute: () => Process.Start(TargetMod.ModURL),
|
||||
|
Loading…
Reference in New Issue
Block a user