public MO2InstallerVM(InstallerVM installerVM) { Parent = installerVM; Location = new FilePickerVM() { ExistCheckOption = FilePickerVM.CheckOptions.Off, PathType = FilePickerVM.PathTypeOptions.Folder, PromptTitle = "Select Installation Directory", }; DownloadLocation = new FilePickerVM() { ExistCheckOption = FilePickerVM.CheckOptions.Off, PathType = FilePickerVM.PathTypeOptions.Folder, PromptTitle = "Select a location for MO2 downloads", }; DownloadLocation.AdditionalError = this.WhenAny(x => x.DownloadLocation.TargetPath) .Select(x => Utils.IsDirectoryPathValid(x)); Location.AdditionalError = Observable.CombineLatest( this.WhenAny(x => x.Location.TargetPath), this.WhenAny(x => x.DownloadLocation.TargetPath), resultSelector: (target, download) => (target, download)) .ObserveOn(RxApp.TaskpoolScheduler) .Select(i => MO2Installer.CheckValidInstallPath(i.target, i.download)) .ObserveOnGuiThread(); _CanInstall = Observable.CombineLatest( this.WhenAny(x => x.Location.ErrorState), this.WhenAny(x => x.DownloadLocation.ErrorState), installerVM.WhenAny(x => x.ModListLocation.ErrorState), resultSelector: (loc, modlist, download) => { return(ErrorResponse.FirstFail(loc, modlist, download)); }) .ToProperty(this, nameof(CanInstall)); // Have Installation location updates modify the downloads location if empty or the same path this.WhenAny(x => x.Location.TargetPath) .Skip(1) // Don't do it initially .Subscribe(installPath => { if (DownloadLocation.TargetPath == default || DownloadLocation.TargetPath == installPath) { DownloadLocation.TargetPath = installPath.Combine("downloads"); } }) .DisposeWith(CompositeDisposable); // Have Download location updates change if the same as the install path this.WhenAny(x => x.DownloadLocation.TargetPath) .Skip(1) // Don't do it initially .Subscribe(downloadPath => { if (downloadPath != default && downloadPath == Location.TargetPath) { DownloadLocation.TargetPath = Location.TargetPath.Combine("downloads"); } }) .DisposeWith(CompositeDisposable); // Load settings _CurrentSettings = installerVM.WhenAny(x => x.ModListLocation.TargetPath) .Select(path => path == default ? null : installerVM.MWVM.Settings.Installer.Mo2ModlistSettings.TryCreate(path)) .ToGuiProperty(this, nameof(CurrentSettings)); this.WhenAny(x => x.CurrentSettings) .Pairwise() .Subscribe(settingsPair => { SaveSettings(settingsPair.Previous); if (settingsPair.Current == null) { return; } Location.TargetPath = settingsPair.Current.InstallationLocation; DownloadLocation.TargetPath = settingsPair.Current.DownloadLocation; AutomaticallyOverwrite = settingsPair.Current.AutomaticallyOverrideExistingInstall; }) .DisposeWith(CompositeDisposable); installerVM.MWVM.Settings.SaveSignal .Subscribe(_ => SaveSettings(CurrentSettings)) .DisposeWith(CompositeDisposable); // Hook onto user interventions, and intercept MO2 specific ones for customization this.WhenAny(x => x.ActiveInstallation) .Select(x => x?.LogMessages ?? Observable.Empty <IStatusMessage>()) .Switch() .Subscribe(x => { switch (x) { case ConfirmUpdateOfExistingInstall c: if (AutomaticallyOverwrite) { c.Confirm(); } break; default: break; } }) .DisposeWith(CompositeDisposable); }