diff --git a/Wabbajack.Lib/Downloaders/INeedsLogin.cs b/Wabbajack.Lib/Downloaders/INeedsLogin.cs index 6917fe17..e581ba79 100644 --- a/Wabbajack.Lib/Downloaders/INeedsLogin.cs +++ b/Wabbajack.Lib/Downloaders/INeedsLogin.cs @@ -14,7 +14,7 @@ namespace Wabbajack.Lib.Downloaders ICommand ClearLogin { get; } IObservable IsLoggedIn { get; } string SiteName { get; } - string MetaInfo { get; } + IObservable MetaInfo { get; } Uri SiteURL { get; } Uri IconUri { get; } } diff --git a/Wabbajack.Lib/Downloaders/LoversLabDownloader.cs b/Wabbajack.Lib/Downloaders/LoversLabDownloader.cs index 1802b605..d52bdd1b 100644 --- a/Wabbajack.Lib/Downloaders/LoversLabDownloader.cs +++ b/Wabbajack.Lib/Downloaders/LoversLabDownloader.cs @@ -31,7 +31,7 @@ namespace Wabbajack.Lib.Downloaders public ICommand ClearLogin { get; } public IObservable IsLoggedIn => Utils.HaveEncryptedJsonObservable("loverslabcookies"); public string SiteName => "Lovers Lab"; - public string MetaInfo => ""; + public IObservable MetaInfo => Observable.Return(""); public Uri SiteURL => new Uri("https://loverslab.com"); public Uri IconUri => new Uri("https://www.loverslab.com/favicon.ico"); diff --git a/Wabbajack.Lib/Downloaders/NexusDownloader.cs b/Wabbajack.Lib/Downloaders/NexusDownloader.cs index e757d272..9914e711 100644 --- a/Wabbajack.Lib/Downloaders/NexusDownloader.cs +++ b/Wabbajack.Lib/Downloaders/NexusDownloader.cs @@ -24,7 +24,7 @@ namespace Wabbajack.Lib.Downloaders public string SiteName => "Nexus Mods"; - public string MetaInfo => ""; + public IObservable MetaInfo => Observable.Return(""); public Uri SiteURL => new Uri("https://www.nexusmods.com"); diff --git a/Wabbajack.Lib/ViewModel.cs b/Wabbajack.Lib/ViewModel.cs index 2c989c6c..6b2b06fc 100644 --- a/Wabbajack.Lib/ViewModel.cs +++ b/Wabbajack.Lib/ViewModel.cs @@ -1,4 +1,5 @@ -using ReactiveUI; +using Newtonsoft.Json; +using ReactiveUI; using System; using System.Collections.Generic; using System.Reactive.Disposables; @@ -9,6 +10,7 @@ namespace Wabbajack.Lib public class ViewModel : ReactiveObject, IDisposable { private readonly Lazy _compositeDisposable = new Lazy(); + [JsonIgnore] public CompositeDisposable CompositeDisposable => _compositeDisposable.Value; public virtual void Dispose() diff --git a/Wabbajack/Converters/CommandConverter.cs b/Wabbajack/Converters/CommandConverter.cs new file mode 100644 index 00000000..2cee9ae3 --- /dev/null +++ b/Wabbajack/Converters/CommandConverter.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using ReactiveUI; + +namespace Wabbajack +{ + public class CommandConverter : IBindingTypeConverter + { + public int GetAffinityForObjects(Type fromType, Type toType) + { + if (toType != typeof(ICommand)) return 0; + if (fromType == typeof(ICommand) + || fromType == typeof(IReactiveCommand)) + { + return 1; + } + return 0; + } + + public bool TryConvert(object from, Type toType, object conversionHint, out object result) + { + if (from == null) + { + result = default(ICommand); + return true; + } + result = from as ICommand; + return result != null; + } + } +} diff --git a/Wabbajack/Converters/ConverterRegistration.cs b/Wabbajack/Converters/ConverterRegistration.cs new file mode 100644 index 00000000..bb406c07 --- /dev/null +++ b/Wabbajack/Converters/ConverterRegistration.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ReactiveUI; +using Splat; + +namespace Wabbajack +{ + public static class ConverterRegistration + { + public static void Register() + { + Locator.CurrentMutable.RegisterConstant( + new CommandConverter(), + typeof(IBindingTypeConverter) + ); + Locator.CurrentMutable.RegisterConstant( + new IntDownCastConverter(), + typeof(IBindingTypeConverter) + ); + } + } +} diff --git a/Wabbajack/Converters/IntDownCastConverter.cs b/Wabbajack/Converters/IntDownCastConverter.cs new file mode 100644 index 00000000..ee8f9326 --- /dev/null +++ b/Wabbajack/Converters/IntDownCastConverter.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using ReactiveUI; + +namespace Wabbajack +{ + public class IntDownCastConverter : IBindingTypeConverter + { + public int GetAffinityForObjects(Type fromType, Type toType) + { + if (toType == typeof(int) || fromType == typeof(int?)) return 1; + if (fromType == typeof(ICommand) + || fromType == typeof(IReactiveCommand)) + { + return 1; + } + return 0; + } + + public bool TryConvert(object from, Type toType, object conversionHint, out object result) + { + if (from == null) + { + result = default(ICommand); + return true; + } + result = from as ICommand; + return result != null; + } + } +} diff --git a/Wabbajack/Extensions/IViewForExt.cs b/Wabbajack/Extensions/IViewForExt.cs new file mode 100644 index 00000000..2092137a --- /dev/null +++ b/Wabbajack/Extensions/IViewForExt.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; +using ReactiveUI; + +namespace Wabbajack +{ + public static class IViewForExt + { + public static IReactiveBinding OneWayBindStrict( + this TView view, + TViewModel viewModel, + Expression> vmProperty, + Expression> viewProperty) + where TViewModel : class + where TView : class, IViewFor + { + return view.OneWayBind( + viewModel: viewModel, + vmProperty: vmProperty, + viewProperty: viewProperty); + } + + public static IReactiveBinding OneWayBindStrict( + this TView view, + TViewModel viewModel, + Expression> vmProperty, + Expression> viewProperty, + Func selector) + where TViewModel : class + where TView : class, IViewFor + { + return view.OneWayBind( + viewModel: viewModel, + vmProperty: vmProperty, + viewProperty: viewProperty, + selector: selector); + } + + public static IReactiveBinding BindStrict( + this TView view, + TViewModel viewModel, + Expression> vmProperty, + Expression> viewProperty) + where TViewModel : class + where TView : class, IViewFor + { + return view.Bind( + viewModel: viewModel, + vmProperty: vmProperty, + viewProperty: viewProperty); + } + + public static IReactiveBinding BindStrict( + this TView view, + TViewModel viewModel, + Expression> vmProperty, + Expression> viewProperty, + Func vmToViewConverter, + Func viewToVmConverter) + where TViewModel : class + where TView : class, IViewFor + { + return view.Bind( + viewModel: viewModel, + vmProperty: vmProperty, + viewProperty: viewProperty, + vmToViewConverter: vmToViewConverter, + viewToVmConverter: viewToVmConverter); + } + } +} diff --git a/Wabbajack/Settings.cs b/Wabbajack/Settings.cs index 264b81bf..e7f3757f 100644 --- a/Wabbajack/Settings.cs +++ b/Wabbajack/Settings.cs @@ -1,4 +1,5 @@ using Newtonsoft.Json; +using ReactiveUI.Fody.Helpers; using System; using System.Collections.Generic; using System.IO; @@ -10,7 +11,7 @@ using Wabbajack.Lib; namespace Wabbajack { [JsonObject(MemberSerialization.OptOut)] - public class MainSettings : ViewModel + public class MainSettings { private static string _filename = "settings.json"; @@ -20,6 +21,7 @@ namespace Wabbajack public double Width { get; set; } public InstallerSettings Installer { get; set; } = new InstallerSettings(); public CompilerSettings Compiler { get; set; } = new CompilerSettings(); + public PerformanceSettings Performance { get; set; } = new PerformanceSettings(); private Subject _saveSignal = new Subject(); [JsonIgnore] @@ -70,6 +72,19 @@ namespace Wabbajack public VortexCompilationSettings VortexCompilation { get; } = new VortexCompilationSettings(); } + [JsonObject(MemberSerialization.OptOut)] + public class PerformanceSettings : ViewModel + { + private bool _Manual = false; + public bool Manual { get => _Manual; set => this.RaiseAndSetIfChanged(ref _Manual, value); } + + private byte _MaxCores = byte.MaxValue; + public byte MaxCores { get => _MaxCores; set => this.RaiseAndSetIfChanged(ref _MaxCores, value); } + + private double _TargetUsage = 1.0d; + public double TargetUsage { get => _TargetUsage; set => this.RaiseAndSetIfChanged(ref _TargetUsage, value); } + } + public class CompilationModlistSettings { public string ModListName { get; set; } diff --git a/Wabbajack/Themes/Styles.xaml b/Wabbajack/Themes/Styles.xaml index 5272aa42..d45a3c55 100644 --- a/Wabbajack/Themes/Styles.xaml +++ b/Wabbajack/Themes/Styles.xaml @@ -53,6 +53,7 @@ #00ffe7 #C7FC86 #8eb55e + #4b6130 #abf74d #868CFC #F686FC @@ -130,6 +131,7 @@ + @@ -250,9 +252,14 @@ + + - + + + + + + + + - + + + + + + - + diff --git a/Wabbajack/Views/Settings/SettingsView.xaml.cs b/Wabbajack/Views/Settings/SettingsView.xaml.cs index 63bfea37..bb30c151 100644 --- a/Wabbajack/Views/Settings/SettingsView.xaml.cs +++ b/Wabbajack/Views/Settings/SettingsView.xaml.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reactive.Disposables; using System.Text; using System.Threading.Tasks; using System.Windows; @@ -12,17 +13,27 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; +using ReactiveUI; namespace Wabbajack { /// /// Interaction logic for SettingsView.xaml /// - public partial class SettingsView : UserControl + public partial class SettingsView : ReactiveUserControl { public SettingsView() { InitializeComponent(); + this.WhenActivated(disposable => + { + this.OneWayBind(this.ViewModel, x => x.BackCommand, x => x.BackButton.Command) + .DisposeWith(disposable); + this.OneWayBind(this.ViewModel, x => x.Login, x => x.LoginView.ViewModel) + .DisposeWith(disposable); + this.OneWayBind(this.ViewModel, x => x.Performance, x => x.PerformanceView.ViewModel) + .DisposeWith(disposable); + }); } } } diff --git a/Wabbajack/Wabbajack.csproj b/Wabbajack/Wabbajack.csproj index 6a4742e7..2e933d87 100644 --- a/Wabbajack/Wabbajack.csproj +++ b/Wabbajack/Wabbajack.csproj @@ -172,6 +172,16 @@ MSBuild:Compile Designer + + + + + + LoginSettingsView.xaml + + + PerformanceSettingsView.xaml + @@ -270,9 +280,6 @@ ModListGalleryView.xaml - - LoginManagerView.xaml - TextViewer.xaml @@ -286,6 +293,14 @@ WebBrowserView.xaml + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -392,10 +407,6 @@ Designer MSBuild:Compile - - MSBuild:Compile - Designer - MSBuild:Compile Designer @@ -496,6 +507,9 @@ 6.14.3 + + 3.7.0 + 6.0.6 runtime; build; native; contentfiles; analyzers; buildtransitive