diff --git a/Wabbajack.App.Wpf/ViewModels/Compilers/CompilerSettingsVM.cs b/Wabbajack.App.Wpf/ViewModels/Compilers/CompilerSettingsVM.cs new file mode 100644 index 00000000..5c514d10 --- /dev/null +++ b/Wabbajack.App.Wpf/ViewModels/Compilers/CompilerSettingsVM.cs @@ -0,0 +1,143 @@ +using Microsoft.Web.WebView2.Core; +using ReactiveUI.Fody.Helpers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; +using Wabbajack.Common; +using Wabbajack.Compiler; +using Wabbajack.DTOs; +using Wabbajack.Paths; + +namespace Wabbajack; + +public class CompilerSettingsVM : ViewModel +{ + public CompilerSettingsVM() { } + public CompilerSettingsVM(CompilerSettings cs) + { + ModlistIsNSFW = cs.ModlistIsNSFW; + Source = cs.Source; + Downloads = cs.Downloads; + Game = cs.Game; + OutputFile = cs.OutputFile; + ModListImage = cs.ModListImage; + UseGamePaths = cs.UseGamePaths; + UseTextureRecompression = cs.UseTextureRecompression; + OtherGames = cs.OtherGames; + MaxVerificationTime = cs.MaxVerificationTime; + ModListName = cs.ModListName; + ModListAuthor = cs.ModListAuthor; + ModListDescription = cs.ModListDescription; + ModListReadme = cs.ModListReadme; + ModListWebsite = cs.ModListWebsite; + ModlistVersion = cs.ModlistVersion; + PublishUpdate = cs.PublishUpdate; + MachineUrl = cs.MachineUrl; + Profile = cs.Profile; + AdditionalProfiles = cs.AdditionalProfiles; + NoMatchInclude = cs.NoMatchInclude; + Include = cs.Include; + Ignore = cs.Ignore; + AlwaysEnabled = cs.AlwaysEnabled; + Version = cs.Version; + Description = cs.Description; + } + + [Reactive] public bool ModlistIsNSFW { get; set; } + [Reactive] public AbsolutePath Source { get; set; } + [Reactive] public AbsolutePath Downloads { get; set; } + [Reactive] public Game Game { get; set; } + [Reactive] public AbsolutePath OutputFile { get; set; } + + [Reactive] public AbsolutePath ModListImage { get; set; } + [Reactive] public bool UseGamePaths { get; set; } + + [Reactive] public bool UseTextureRecompression { get; set; } = false; + [Reactive] public Game[] OtherGames { get; set; } = Array.Empty(); + + [Reactive] public TimeSpan MaxVerificationTime { get; set; } = TimeSpan.FromMinutes(1); + [Reactive] public string ModListName { get; set; } = ""; + [Reactive] public string ModListAuthor { get; set; } = ""; + [Reactive] public string ModListDescription { get; set; } = ""; + [Reactive] public string ModListReadme { get; set; } = ""; + [Reactive] public Uri? ModListWebsite { get; set; } + [Reactive] public Version ModlistVersion { get; set; } = Version.Parse("0.0.1.0"); + [Reactive] public bool PublishUpdate { get; set; } = false; + [Reactive] public string MachineUrl { get; set; } = ""; + + /// + /// The main (default) profile + /// + [Reactive] public string Profile { get; set; } = ""; + + /// + /// Secondary profiles to include in the modlist + /// + [Reactive] public string[] AdditionalProfiles { get; set; } = Array.Empty(); + + + /// + /// All profiles to be added to the compiled modlist + /// + public IEnumerable AllProfiles => AdditionalProfiles.Append(Profile); + + public bool IsMO2Modlist => AllProfiles.Any(p => !string.IsNullOrWhiteSpace(p)); + + + + /// + /// This file, or files in these folders, are automatically included if they don't match + /// any other step + /// + [Reactive] public RelativePath[] NoMatchInclude { get; set; } = Array.Empty(); + + /// + /// These files are inlined into the modlist + /// + [Reactive] public RelativePath[] Include { get; set; } = Array.Empty(); + + /// + /// These files are ignored when compiling the modlist + /// + [Reactive] public RelativePath[] Ignore { get; set; } = Array.Empty(); + + [Reactive] public RelativePath[] AlwaysEnabled { get; set; } = Array.Empty(); + [Reactive] public Version Version { get; set; } + [Reactive] public string Description { get; set; } + + public CompilerSettings ToCompilerSettings() + { + return new CompilerSettings() + { + ModlistIsNSFW = ModlistIsNSFW, + Source = Source, + Downloads = Downloads, + Game = Game, + OutputFile = OutputFile, + ModListImage = ModListImage, + UseGamePaths = UseGamePaths, + UseTextureRecompression = UseTextureRecompression, + OtherGames = OtherGames, + MaxVerificationTime = MaxVerificationTime, + ModListName = ModListName, + ModListAuthor = ModListAuthor, + ModListDescription = ModListDescription, + ModListReadme = ModListReadme, + ModListWebsite = ModListWebsite, + ModlistVersion = ModlistVersion, + PublishUpdate = PublishUpdate, + MachineUrl = MachineUrl, + Profile = Profile, + AdditionalProfiles = AdditionalProfiles, + NoMatchInclude = NoMatchInclude, + Include = Include, + Ignore = Ignore, + AlwaysEnabled = AlwaysEnabled, + Version = Version, + Description = Description + }; + } + public AbsolutePath CompilerSettingsPath => Source.Combine(ModListName).WithExtension(Ext.CompilerSettings); + public AbsolutePath ProfilePath => Source.Combine("profiles").Combine(Profile).Combine("modlist").WithExtension(Ext.Txt); +} diff --git a/Wabbajack.App.Wpf/ViewModels/Compilers/CompilerVM.cs b/Wabbajack.App.Wpf/ViewModels/Compilers/CompilerVM.cs index b9c0ba34..1ca754df 100644 --- a/Wabbajack.App.Wpf/ViewModels/Compilers/CompilerVM.cs +++ b/Wabbajack.App.Wpf/ViewModels/Compilers/CompilerVM.cs @@ -61,36 +61,10 @@ namespace Wabbajack public FilePickerVM ModlistLocation { get; } public FilePickerVM DownloadLocation { get; } public FilePickerVM OutputLocation { get; } - - // Modlist Settings - - [Reactive] public string ModListName { get; set; } - [Reactive] public string Version { get; set; } - [Reactive] public string Author { get; set; } - [Reactive] public string Description { get; set; } - public FilePickerVM ModListImagePath { get; } = new(); - [Reactive] public ImageSource ModListImage { get; set; } - [Reactive] public string Website { get; set; } - [Reactive] public string Readme { get; set; } - [Reactive] public bool IsNSFW { get; set; } - [Reactive] public bool PublishUpdate { get; set; } - [Reactive] public string MachineUrl { get; set; } - [Reactive] public Game BaseGame { get; set; } - [Reactive] public string SelectedProfile { get; set; } - [Reactive] public AbsolutePath GamePath { get; set; } - [Reactive] public bool IsMO2Compilation { get; set; } - [Reactive] public RelativePath[] AlwaysEnabled { get; set; } = Array.Empty(); - [Reactive] public RelativePath[] NoMatchInclude { get; set; } = Array.Empty(); - [Reactive] public RelativePath[] Include { get; set; } = Array.Empty(); - [Reactive] public RelativePath[] Ignore { get; set; } = Array.Empty(); - - [Reactive] public string[] OtherProfiles { get; set; } = Array.Empty(); - - [Reactive] public AbsolutePath Source { get; set; } - - public AbsolutePath SettingsOutputLocation => Source.Combine(ModListName).WithExtension(Ext.CompilerSettings); - + [Reactive] public CompilerSettingsVM Settings { get; set; } = new(); + + public FilePickerVM ModListImageLocation { get; } = new(); public ReactiveCommand ExecuteCommand { get; } public ReactiveCommand ReInferSettingsCommand { get; set; } @@ -115,27 +89,33 @@ namespace Wabbajack _wjClient = wjClient; MessageBus.Current.Listen() - .Subscribe(msg => LoadCompilerSettings(msg.CompilerSettings)) + .Subscribe(msg => { + var csVm = new CompilerSettingsVM(msg.CompilerSettings); + ModlistLocation.TargetPath = csVm.ProfilePath; + ModListImageLocation.TargetPath = csVm.ModListImage; + DownloadLocation.TargetPath = csVm.Downloads; + OutputLocation.TargetPath = csVm.OutputFile; + Settings = csVm; + }) .DisposeWith(CompositeDisposable); StatusText = "Compiler Settings"; StatusProgress = Percent.Zero; - BackCommand = - ReactiveCommand.CreateFromTask(async () => - { - await SaveSettingsFile(); - NavigateToGlobal.Send(ScreenType.Home); - }); - + BackCommand = ReactiveCommand.CreateFromTask(async () => + { + await SaveSettingsFile(); + NavigateToGlobal.Send(ScreenType.Home); + }); + SubCompilerVM = new MO2CompilerVM(this); ExecuteCommand = ReactiveCommand.CreateFromTask(async () => await StartCompilation()); ReInferSettingsCommand = ReactiveCommand.CreateFromTask(async () => await ReInferSettings(), - this.WhenAnyValue(vm => vm.Source) + this.WhenAnyValue(vm => vm.Settings.Source) .ObserveOnGuiThread() .Select(v => v != default) - .CombineLatest(this.WhenAnyValue(vm => vm.ModListName) + .CombineLatest(this.WhenAnyValue(vm => vm.Settings.ModListName) .ObserveOnGuiThread() .Select(p => !string.IsNullOrWhiteSpace(p))) .Select(v => v.First && v.Second)); @@ -174,23 +154,37 @@ namespace Wabbajack Disposable.Empty.DisposeWith(disposables); ModlistLocation.WhenAnyValue(vm => vm.TargetPath) - .Subscribe(p => InferModListFromLocation(p).FireAndForget()) + .Subscribe(async p => { + if (string.IsNullOrEmpty(Settings.ModListName)) + { + Settings = new CompilerSettingsVM(await InferModListFromLocation(p)); + } + else await ReInferSettings(); + }) .DisposeWith(disposables); - this.WhenAnyValue(x => x.DownloadLocation.TargetPath) .CombineLatest(this.WhenAnyValue(x => x.ModlistLocation.TargetPath), this.WhenAnyValue(x => x.OutputLocation.TargetPath), this.WhenAnyValue(x => x.DownloadLocation.ErrorState), this.WhenAnyValue(x => x.ModlistLocation.ErrorState), - this.WhenAnyValue(x => x.OutputLocation.ErrorState), - this.WhenAnyValue(x => x.ModListName), - this.WhenAnyValue(x => x.Version)) + this.WhenAnyValue(x => x.OutputLocation.ErrorState)) .Select(_ => Validate()) .BindToStrict(this, vm => vm.ErrorState) .DisposeWith(disposables); - - //LoadLastSavedSettings().FireAndForget(); + + this.WhenAnyValue(x => x.Settings) + .Throttle(TimeSpan.FromSeconds(2)) + .Subscribe(_ => SaveSettingsFile().FireAndForget()) + .DisposeWith(disposables); + + this.WhenAnyValue(x => x.ModListImageLocation.TargetPath) + .BindToStrict(this, vm => vm.Settings.ModListImage) + .DisposeWith(disposables); + + this.WhenAnyValue(x => x.DownloadLocation.TargetPath) + .BindToStrict(this, vm => vm.Settings.Downloads) + .DisposeWith(disposables); }); } @@ -199,7 +193,7 @@ namespace Wabbajack private async Task ReInferSettings() { var newSettings = await _inferencer.InferModListFromLocation( - Source.Combine("profiles", SelectedProfile, "modlist.txt")); + Settings.Source.Combine("profiles", Settings.Profile, "modlist.txt")); if (newSettings == null) { @@ -207,28 +201,30 @@ namespace Wabbajack return; } - Include = newSettings.Include; - Ignore = newSettings.Ignore; - AlwaysEnabled = newSettings.AlwaysEnabled; - NoMatchInclude = newSettings.NoMatchInclude; - OtherProfiles = newSettings.AdditionalProfiles; + Settings.Include = newSettings.Include; + Settings.Ignore = newSettings.Ignore; + Settings.AlwaysEnabled = newSettings.AlwaysEnabled; + Settings.NoMatchInclude = newSettings.NoMatchInclude; + Settings.AdditionalProfiles = newSettings.AdditionalProfiles; } private ErrorResponse Validate() { - var errors = new List(); - errors.Add(DownloadLocation.ErrorState); - errors.Add(ModlistLocation.ErrorState); - errors.Add(OutputLocation.ErrorState); + var errors = new List + { + DownloadLocation.ErrorState, + ModlistLocation.ErrorState, + OutputLocation.ErrorState + }; return ErrorResponse.Combine(errors); } - private async Task InferModListFromLocation(AbsolutePath path) + private async Task InferModListFromLocation(AbsolutePath path) { using var _ = LoadingLock.WithLoading(); CompilerSettings settings; - if (path == default) return; + if (path == default) return new(); if (path.FileName.Extension == Ext.CompilerSettings) { await using var fs = path.Open(FileMode.Open, FileAccess.Read, FileShare.Read); @@ -237,46 +233,14 @@ namespace Wabbajack else if (path.FileName == "modlist.txt".ToRelativePath()) { settings = await _inferencer.InferModListFromLocation(path); - if (settings == null) return; + if (settings == null) return new(); } else { - return; + return new(); } - LoadCompilerSettings(settings); - - if (path.FileName == "modlist.txt".ToRelativePath()) - { - await LoadLastSavedSettings(); - } - } - - private void LoadCompilerSettings(CompilerSettings settings) - { - BaseGame = settings.Game; - ModListName = settings.ModListName; - Version = settings.Version?.ToString() ?? ""; - Author = settings.ModListAuthor; - Description = settings.Description; - ModListImagePath.TargetPath = settings.ModListImage; - Website = settings.ModListWebsite?.ToString() ?? ""; - Readme = settings.ModListReadme?.ToString() ?? ""; - IsNSFW = settings.ModlistIsNSFW; - - Source = settings.Source; - DownloadLocation.TargetPath = settings.Downloads; - if (settings.OutputFile.Extension == Ext.Wabbajack) - settings.OutputFile = settings.OutputFile.Parent; - OutputLocation.TargetPath = settings.OutputFile; - SelectedProfile = settings.Profile; - PublishUpdate = settings.PublishUpdate; - MachineUrl = settings.MachineUrl; - OtherProfiles = settings.AdditionalProfiles; - AlwaysEnabled = settings.AlwaysEnabled; - NoMatchInclude = settings.NoMatchInclude; - Include = settings.Include; - Ignore = settings.Ignore; + return settings; } private async Task StartCompilation() @@ -285,24 +249,22 @@ namespace Wabbajack { try { - await SaveSettingsFile(); var token = CancellationToken.None; State = CompilerState.Compiling; - var mo2Settings = GetSettings(); - mo2Settings.UseGamePaths = true; - if (mo2Settings.OutputFile.DirectoryExists()) - mo2Settings.OutputFile = mo2Settings.OutputFile.Combine(mo2Settings.ModListName.ToRelativePath() + Settings.UseGamePaths = true; + if (Settings.OutputFile.DirectoryExists()) + Settings.OutputFile = Settings.OutputFile.Combine(Settings.ModListName.ToRelativePath() .WithExtension(Ext.Wabbajack)); - if (PublishUpdate && !await RunPreflightChecks(token)) + if (Settings.PublishUpdate && !await RunPreflightChecks(token)) { State = CompilerState.Errored; return; } - var compiler = MO2Compiler.Create(_serviceProvider, mo2Settings); + var compiler = MO2Compiler.Create(_serviceProvider, Settings.ToCompilerSettings()); var events = Observable.FromEventPattern(h => compiler.OnStatusUpdate += h, h => compiler.OnStatusUpdate -= h) @@ -327,12 +289,12 @@ namespace Wabbajack events.Dispose(); } - if (PublishUpdate) + if (Settings.PublishUpdate) { _logger.LogInformation("Publishing List"); var downloadMetadata = _dtos.Deserialize( - await mo2Settings.OutputFile.WithExtension(Ext.Meta).WithExtension(Ext.Json).ReadAllTextAsync())!; - await _wjClient.PublishModlist(MachineUrl, System.Version.Parse(Version), mo2Settings.OutputFile, downloadMetadata); + await Settings.OutputFile.WithExtension(Ext.Meta).WithExtension(Ext.Json).ReadAllTextAsync())!; + await _wjClient.PublishModlist(Settings.MachineUrl, Settings.Version, Settings.OutputFile, downloadMetadata); } _logger.LogInformation("Compiler Finished"); @@ -366,15 +328,9 @@ namespace Wabbajack private async Task RunPreflightChecks(CancellationToken token) { var lists = await _wjClient.GetMyModlists(token); - if (!lists.Any(x => x.Equals(MachineUrl, StringComparison.InvariantCultureIgnoreCase))) + if (!lists.Any(x => x.Equals(Settings.MachineUrl, StringComparison.InvariantCultureIgnoreCase))) { - _logger.LogError("Preflight Check failed, list {MachineUrl} not found in any repository", MachineUrl); - return false; - } - - if (!System.Version.TryParse(Version, out var v)) - { - _logger.LogError("Bad Version Number {Version}", Version); + _logger.LogError("Preflight Check failed, list {MachineUrl} not found in any repository", Settings.MachineUrl); return false; } @@ -383,16 +339,14 @@ namespace Wabbajack private async Task SaveSettingsFile() { - if (Source == default) return; + if (Settings.Source == default) return; - var settings = GetSettings(); - - await using var st = SettingsOutputLocation.Open(FileMode.Create, FileAccess.Write, FileShare.None); - await JsonSerializer.SerializeAsync(st, settings, _dtos.Options); + await using var st = Settings.CompilerSettingsPath.Open(FileMode.Create, FileAccess.Write, FileShare.None); + await JsonSerializer.SerializeAsync(st, Settings.ToCompilerSettings(), _dtos.Options); var allSavedCompilerSettings = await _settingsManager.Load>(Consts.AllSavedCompilerSettingsPaths); - allSavedCompilerSettings.Remove(SettingsOutputLocation); - allSavedCompilerSettings.Insert(0, SettingsOutputLocation); + allSavedCompilerSettings.Remove(Settings.CompilerSettingsPath); + allSavedCompilerSettings.Insert(0, Settings.CompilerSettingsPath); await _settingsManager.Save(Consts.AllSavedCompilerSettingsPaths, allSavedCompilerSettings); } @@ -408,89 +362,57 @@ namespace Wabbajack ModlistLocation.TargetPath = lastPath; } - private CompilerSettings GetSettings() - { - - System.Version.TryParse(Version, out var pversion); - Uri.TryCreate(Website, UriKind.Absolute, out var websiteUri); - - return new CompilerSettings - { - ModListName = ModListName, - ModListAuthor = Author, - Version = pversion ?? new Version(), - Description = Description, - ModListReadme = Readme, - ModListImage = ModListImagePath.TargetPath, - ModlistIsNSFW = IsNSFW, - ModListWebsite = websiteUri ?? new Uri("http://www.wabbajack.org"), - Downloads = DownloadLocation.TargetPath, - Source = Source, - Game = BaseGame, - PublishUpdate = PublishUpdate, - MachineUrl = MachineUrl, - Profile = SelectedProfile, - UseGamePaths = true, - OutputFile = OutputLocation.TargetPath, - AlwaysEnabled = AlwaysEnabled, - AdditionalProfiles = OtherProfiles, - NoMatchInclude = NoMatchInclude, - Include = Include, - Ignore = Ignore - }; - } - #region ListOps public void AddOtherProfile(string profile) { - OtherProfiles = (OtherProfiles ?? Array.Empty()).Append(profile).Distinct().ToArray(); + Settings.AdditionalProfiles = (Settings.AdditionalProfiles ?? Array.Empty()).Append(profile).Distinct().ToArray(); } public void RemoveProfile(string profile) { - OtherProfiles = OtherProfiles.Where(p => p != profile).ToArray(); + Settings.AdditionalProfiles = Settings.AdditionalProfiles.Where(p => p != profile).ToArray(); } public void AddAlwaysEnabled(RelativePath path) { - AlwaysEnabled = (AlwaysEnabled ?? Array.Empty()).Append(path).Distinct().ToArray(); + Settings.AlwaysEnabled = (Settings.AlwaysEnabled ?? Array.Empty()).Append(path).Distinct().ToArray(); } public void RemoveAlwaysEnabled(RelativePath path) { - AlwaysEnabled = AlwaysEnabled.Where(p => p != path).ToArray(); + Settings.AlwaysEnabled = Settings.AlwaysEnabled.Where(p => p != path).ToArray(); } public void AddNoMatchInclude(RelativePath path) { - NoMatchInclude = (NoMatchInclude ?? Array.Empty()).Append(path).Distinct().ToArray(); + Settings.NoMatchInclude = (Settings.NoMatchInclude ?? Array.Empty()).Append(path).Distinct().ToArray(); } public void RemoveNoMatchInclude(RelativePath path) { - NoMatchInclude = NoMatchInclude.Where(p => p != path).ToArray(); + Settings.NoMatchInclude = Settings.NoMatchInclude.Where(p => p != path).ToArray(); } public void AddInclude(RelativePath path) { - Include = (Include ?? Array.Empty()).Append(path).Distinct().ToArray(); + Settings.Include = (Settings.Include ?? Array.Empty()).Append(path).Distinct().ToArray(); } public void RemoveInclude(RelativePath path) { - Include = Include.Where(p => p != path).ToArray(); + Settings.Include = Settings.Include.Where(p => p != path).ToArray(); } public void AddIgnore(RelativePath path) { - Ignore = (Ignore ?? Array.Empty()).Append(path).Distinct().ToArray(); + Settings.Ignore = (Settings.Ignore ?? Array.Empty()).Append(path).Distinct().ToArray(); } public void RemoveIgnore(RelativePath path) { - Ignore = Ignore.Where(p => p != path).ToArray(); + Settings.Ignore = Settings.Ignore.Where(p => p != path).ToArray(); } #endregion diff --git a/Wabbajack.App.Wpf/ViewModels/CreateModListVM.cs b/Wabbajack.App.Wpf/ViewModels/CreateModListVM.cs index 5a8b189b..5ca18d42 100644 --- a/Wabbajack.App.Wpf/ViewModels/CreateModListVM.cs +++ b/Wabbajack.App.Wpf/ViewModels/CreateModListVM.cs @@ -49,7 +49,10 @@ namespace Wabbajack _serviceProvider = serviceProvider; _dtos = dtos; CompileModListCommand = ReactiveCommand.Create(() => NavigateToGlobal.Send(ScreenType.Compiler)); - LoadAllCompilerSettings().FireAndForget(); + this.WhenActivated(disposables => + { + LoadAllCompilerSettings().DisposeWith(disposables); + }); } private async Task LoadAllCompilerSettings() diff --git a/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml b/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml index 346744bd..4ce3f79d 100644 --- a/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml +++ b/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml @@ -28,7 +28,7 @@ - + diff --git a/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml.cs b/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml.cs index 65ac7241..b4e56de8 100644 --- a/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml.cs +++ b/Wabbajack.App.Wpf/Views/Compilers/CompilerView.xaml.cs @@ -40,20 +40,20 @@ namespace Wabbajack .BindToStrict(this, x => x.CompilationComplete.TitleText.Text) .DisposeWith(disposables); - ViewModel.WhenAny(vm => vm.ModListImagePath.TargetPath) + ViewModel.WhenAny(vm => vm.ModListImageLocation.TargetPath) .Where(i => i.FileExists()) .Select(i => (UIUtils.TryGetBitmapImageFromFile(i, out var img), img)) .Where(i => i.Item1) .Select(i => i.img) .BindToStrict(this, view => view.DetailImage.Image); - ViewModel.WhenAny(vm => vm.ModListName) + ViewModel.WhenAny(vm => vm.Settings.ModListName) .BindToStrict(this, view => view.DetailImage.Title); - ViewModel.WhenAny(vm => vm.Author) + ViewModel.WhenAny(vm => vm.Settings.ModListAuthor) .BindToStrict(this, view => view.DetailImage.Author); - ViewModel.WhenAny(vm => vm.Description) + ViewModel.WhenAny(vm => vm.Settings.ModListDescription) .BindToStrict(this, view => view.DetailImage.Description); CompilationComplete.GoToModlistButton.Command = ReactiveCommand.Create(() => @@ -75,18 +75,6 @@ namespace Wabbajack .BindToStrict(this, view => view.BeginButton.Command) .DisposeWith(disposables); - /* - ViewModel.WhenAnyValue(vm => vm.BackCommand) - .BindToStrict(this, view => view.BackButton.Command) - .DisposeWith(disposables); - */ - - /* - ViewModel.WhenAnyValue(vm => vm.ReInferSettingsCommand) - .BindToStrict(this, view => view.ReInferSettings.Command) - .DisposeWith(disposables); - */ - ViewModel.WhenAnyValue(vm => vm.State) .Select(v => v == CompilerState.Configuration ? Visibility.Visible : Visibility.Collapsed) .BindToStrict(this, view => view.BottomCompilerSettingsGrid.Visibility) @@ -148,38 +136,45 @@ namespace Wabbajack // Settings - this.Bind(ViewModel, vm => vm.ModListName, view => view.ModListNameSetting.Text) + this.Bind(ViewModel, vm => vm.Settings.ModListName, view => view.ModListNameSetting.Text) .DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.SelectedProfile, view => view.SelectedProfile.Text) + this.Bind(ViewModel, vm => vm.Settings.Profile, view => view.SelectedProfile.Text) .DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.Author, view => view.AuthorNameSetting.Text) + this.Bind(ViewModel, vm => vm.Settings.ModListAuthor, view => view.AuthorNameSetting.Text) .DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.Version, view => view.VersionSetting.Text) + this.Bind(ViewModel, + vm => vm.Settings.Version, + view => view.VersionSetting.Text, + vmVersion => vmVersion?.ToString() ?? "", + viewVersion => { + Version.TryParse(viewVersion, out var version); + return version ?? Version.Parse("1.0.0"); + }) .DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.Description, view => view.DescriptionSetting.Text) + this.Bind(ViewModel, vm => vm.Settings.ModListDescription, view => view.DescriptionSetting.Text) .DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.ModListImagePath, view => view.ImageFilePicker.PickerVM) + this.Bind(ViewModel, vm => vm.ModListImageLocation, view => view.ImageFilePicker.PickerVM) .DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.Website, view => view.WebsiteSetting.Text) + this.Bind(ViewModel, vm => vm.Settings.ModListWebsite, view => view.WebsiteSetting.Text) .DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.Readme, view => view.ReadmeSetting.Text) + this.Bind(ViewModel, vm => vm.Settings.ModListReadme, view => view.ReadmeSetting.Text) .DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.IsNSFW, view => view.NSFWSetting.IsChecked) + this.Bind(ViewModel, vm => vm.Settings.ModlistIsNSFW, view => view.NSFWSetting.IsChecked) .DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.PublishUpdate, view => view.PublishUpdate.IsChecked) + this.Bind(ViewModel, vm => vm.Settings.PublishUpdate, view => view.PublishUpdate.IsChecked) .DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.MachineUrl, view => view.MachineUrl.Text) + this.Bind(ViewModel, vm => vm.Settings.MachineUrl, view => view.MachineUrl.Text) .DisposeWith(disposables); @@ -194,7 +189,7 @@ namespace Wabbajack .DisposeWith(disposables); */ - ViewModel.WhenAnyValue(vm => vm.AlwaysEnabled) + ViewModel.WhenAnyValue(vm => vm.Settings.AlwaysEnabled) .WhereNotNull() .Select(itms => itms.Select(itm => new RemovableItemViewModel(itm.ToString(), () => ViewModel.RemoveAlwaysEnabled(itm))).ToArray()) .BindToStrict(this, view => view.AlwaysEnabled.ItemsSource) @@ -203,7 +198,7 @@ namespace Wabbajack AddAlwaysEnabled.Command = ReactiveCommand.CreateFromTask(async () => await AddAlwaysEnabledCommand()); - ViewModel.WhenAnyValue(vm => vm.OtherProfiles) + ViewModel.WhenAnyValue(vm => vm.Settings.AdditionalProfiles) .WhereNotNull() .Select(itms => itms.Select(itm => new RemovableItemViewModel(itm.ToString(), () => ViewModel.RemoveProfile(itm))).ToArray()) .BindToStrict(this, view => view.OtherProfiles.ItemsSource) @@ -211,7 +206,7 @@ namespace Wabbajack AddOtherProfile.Command = ReactiveCommand.CreateFromTask(async () => await AddOtherProfileCommand()); - ViewModel.WhenAnyValue(vm => vm.NoMatchInclude) + ViewModel.WhenAnyValue(vm => vm.Settings.NoMatchInclude) .WhereNotNull() .Select(itms => itms.Select(itm => new RemovableItemViewModel(itm.ToString(), () => ViewModel.RemoveNoMatchInclude(itm))).ToArray()) .BindToStrict(this, view => view.NoMatchInclude.ItemsSource) @@ -219,7 +214,7 @@ namespace Wabbajack AddNoMatchInclude.Command = ReactiveCommand.CreateFromTask(async () => await AddNoMatchIncludeCommand()); - ViewModel.WhenAnyValue(vm => vm.Include) + ViewModel.WhenAnyValue(vm => vm.Settings.Include) .WhereNotNull() .Select(itms => itms.Select(itm => new RemovableItemViewModel(itm.ToString(), () => ViewModel.RemoveInclude(itm))).ToArray()) .BindToStrict(this, view => view.Include.ItemsSource) @@ -228,7 +223,7 @@ namespace Wabbajack AddInclude.Command = ReactiveCommand.CreateFromTask(async () => await AddIncludeCommand()); AddIncludeFiles.Command = ReactiveCommand.CreateFromTask(async () => await AddIncludeFilesCommand()); - ViewModel.WhenAnyValue(vm => vm.Ignore) + ViewModel.WhenAnyValue(vm => vm.Settings.Ignore) .WhereNotNull() .Select(itms => itms.Select(itm => new RemovableItemViewModel(itm.ToString(), () => ViewModel.RemoveIgnore(itm))).ToArray()) .BindToStrict(this, view => view.Ignore.ItemsSource) @@ -246,13 +241,13 @@ namespace Wabbajack { AbsolutePath dirPath; - if (ViewModel!.Source != default && ViewModel.Source.Combine("mods").DirectoryExists()) + if (ViewModel!.Settings.Source != default && ViewModel.Settings.Source.Combine("mods").DirectoryExists()) { - dirPath = ViewModel.Source.Combine("mods"); + dirPath = ViewModel.Settings.Source.Combine("mods"); } else { - dirPath = ViewModel.Source; + dirPath = ViewModel.Settings.Source; } var dlg = new CommonOpenFileDialog @@ -276,9 +271,9 @@ namespace Wabbajack { var selectedPath = fileName.ToAbsolutePath(); - if (!selectedPath.InFolder(ViewModel.Source)) continue; + if (!selectedPath.InFolder(ViewModel.Settings.Source)) continue; - ViewModel.AddAlwaysEnabled(selectedPath.RelativeTo(ViewModel.Source)); + ViewModel.AddAlwaysEnabled(selectedPath.RelativeTo(ViewModel.Settings.Source)); } } @@ -286,13 +281,13 @@ namespace Wabbajack { AbsolutePath dirPath; - if (ViewModel!.Source != default && ViewModel.Source.Combine("mods").DirectoryExists()) + if (ViewModel!.Settings.Source != default && ViewModel.Settings.Source.Combine("mods").DirectoryExists()) { - dirPath = ViewModel.Source.Combine("mods"); + dirPath = ViewModel.Settings.Source.Combine("mods"); } else { - dirPath = ViewModel.Source; + dirPath = ViewModel.Settings.Source; } var dlg = new CommonOpenFileDialog @@ -316,7 +311,7 @@ namespace Wabbajack { var selectedPath = filename.ToAbsolutePath(); - if (!selectedPath.InFolder(ViewModel.Source.Combine("profiles"))) continue; + if (!selectedPath.InFolder(ViewModel.Settings.Source.Combine("profiles"))) continue; ViewModel.AddOtherProfile(selectedPath.FileName.ToString()); } @@ -328,10 +323,10 @@ namespace Wabbajack { Title = "Please select a folder", IsFolderPicker = true, - InitialDirectory = ViewModel!.Source.ToString(), + InitialDirectory = ViewModel!.Settings.Source.ToString(), AddToMostRecentlyUsedList = false, AllowNonFileSystemItems = false, - DefaultDirectory = ViewModel!.Source.ToString(), + DefaultDirectory = ViewModel!.Settings.Source.ToString(), EnsureFileExists = true, EnsurePathExists = true, EnsureReadOnly = false, @@ -345,9 +340,9 @@ namespace Wabbajack { var selectedPath = filename.ToAbsolutePath(); - if (!selectedPath.InFolder(ViewModel.Source)) continue; + if (!selectedPath.InFolder(ViewModel.Settings.Source)) continue; - ViewModel.AddNoMatchInclude(selectedPath.RelativeTo(ViewModel!.Source)); + ViewModel.AddNoMatchInclude(selectedPath.RelativeTo(ViewModel!.Settings.Source)); } return Task.CompletedTask; @@ -359,10 +354,10 @@ namespace Wabbajack { Title = "Please select folders to include", IsFolderPicker = true, - InitialDirectory = ViewModel!.Source.ToString(), + InitialDirectory = ViewModel!.Settings.Source.ToString(), AddToMostRecentlyUsedList = false, AllowNonFileSystemItems = false, - DefaultDirectory = ViewModel!.Source.ToString(), + DefaultDirectory = ViewModel!.Settings.Source.ToString(), EnsureFileExists = true, EnsurePathExists = true, EnsureReadOnly = false, @@ -376,9 +371,9 @@ namespace Wabbajack { var selectedPath = filename.ToAbsolutePath(); - if (!selectedPath.InFolder(ViewModel.Source)) continue; + if (!selectedPath.InFolder(ViewModel.Settings.Source)) continue; - ViewModel.AddInclude(selectedPath.RelativeTo(ViewModel!.Source)); + ViewModel.AddInclude(selectedPath.RelativeTo(ViewModel!.Settings.Source)); } } @@ -388,10 +383,10 @@ namespace Wabbajack { Title = "Please select files to include", IsFolderPicker = false, - InitialDirectory = ViewModel!.Source.ToString(), + InitialDirectory = ViewModel!.Settings.Source.ToString(), AddToMostRecentlyUsedList = false, AllowNonFileSystemItems = false, - DefaultDirectory = ViewModel!.Source.ToString(), + DefaultDirectory = ViewModel!.Settings.Source.ToString(), EnsureFileExists = true, EnsurePathExists = true, EnsureReadOnly = false, @@ -405,9 +400,9 @@ namespace Wabbajack { var selectedPath = filename.ToAbsolutePath(); - if (!selectedPath.InFolder(ViewModel.Source)) continue; + if (!selectedPath.InFolder(ViewModel.Settings.Source)) continue; - ViewModel.AddInclude(selectedPath.RelativeTo(ViewModel!.Source)); + ViewModel.AddInclude(selectedPath.RelativeTo(ViewModel!.Settings.Source)); } } @@ -417,10 +412,10 @@ namespace Wabbajack { Title = "Please select folders to ignore", IsFolderPicker = true, - InitialDirectory = ViewModel!.Source.ToString(), + InitialDirectory = ViewModel!.Settings.Source.ToString(), AddToMostRecentlyUsedList = false, AllowNonFileSystemItems = false, - DefaultDirectory = ViewModel!.Source.ToString(), + DefaultDirectory = ViewModel!.Settings.Source.ToString(), EnsureFileExists = true, EnsurePathExists = true, EnsureReadOnly = false, @@ -434,9 +429,9 @@ namespace Wabbajack { var selectedPath = filename.ToAbsolutePath(); - if (!selectedPath.InFolder(ViewModel.Source)) continue; + if (!selectedPath.InFolder(ViewModel.Settings.Source)) continue; - ViewModel.AddIgnore(selectedPath.RelativeTo(ViewModel!.Source)); + ViewModel.AddIgnore(selectedPath.RelativeTo(ViewModel!.Settings.Source)); } } @@ -446,10 +441,10 @@ namespace Wabbajack { Title = "Please select files to ignore", IsFolderPicker = false, - InitialDirectory = ViewModel!.Source.ToString(), + InitialDirectory = ViewModel!.Settings.Source.ToString(), AddToMostRecentlyUsedList = false, AllowNonFileSystemItems = false, - DefaultDirectory = ViewModel!.Source.ToString(), + DefaultDirectory = ViewModel!.Settings.Source.ToString(), EnsureFileExists = true, EnsurePathExists = true, EnsureReadOnly = false, @@ -463,9 +458,9 @@ namespace Wabbajack { var selectedPath = filename.ToAbsolutePath(); - if (!selectedPath.InFolder(ViewModel.Source)) continue; + if (!selectedPath.InFolder(ViewModel.Settings.Source)) continue; - ViewModel.AddIgnore(selectedPath.RelativeTo(ViewModel!.Source)); + ViewModel.AddIgnore(selectedPath.RelativeTo(ViewModel!.Settings.Source)); } } } diff --git a/Wabbajack.App.Wpf/Views/Compilers/CreateModListView.xaml b/Wabbajack.App.Wpf/Views/Compilers/CreateModListView.xaml index fd695ed2..cde9c458 100644 --- a/Wabbajack.App.Wpf/Views/Compilers/CreateModListView.xaml +++ b/Wabbajack.App.Wpf/Views/Compilers/CreateModListView.xaml @@ -50,7 +50,7 @@ Grid.Row="0" Grid.Column="1" VerticalAlignment="Top" - Symbol="AppsAddIn" + Symbol="Add" IsFilled="True" FontSize="28" /> @@ -81,7 +81,7 @@ Grid.Row="0" Grid.Column="1" VerticalAlignment="Top" - Symbol="AppsAddIn" + Symbol="ArrowImport" IsFilled="True" FontSize="28" />