mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Rework gallery loading, and VM creation
This commit is contained in:
parent
12bb5fe083
commit
bd71de5883
@ -37,6 +37,8 @@ namespace Wabbajack
|
|||||||
services.AddSingleton<MainSettings>();
|
services.AddSingleton<MainSettings>();
|
||||||
services.AddTransient<CompilerVM>();
|
services.AddTransient<CompilerVM>();
|
||||||
services.AddTransient<InstallerVM>();
|
services.AddTransient<InstallerVM>();
|
||||||
|
services.AddTransient<ModeSelectionVM>();
|
||||||
|
services.AddTransient<ModListGalleryVM>();
|
||||||
|
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
|
11
Wabbajack.App.Wpf/Messages/NavigateBack.cs
Normal file
11
Wabbajack.App.Wpf/Messages/NavigateBack.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace Wabbajack.Messages;
|
||||||
|
|
||||||
|
public class NavigateBack
|
||||||
|
{
|
||||||
|
public static void Send()
|
||||||
|
{
|
||||||
|
MessageBus.Current.SendMessage(new NavigateBack());
|
||||||
|
}
|
||||||
|
}
|
21
Wabbajack.App.Wpf/Messages/NavigateTo.cs
Normal file
21
Wabbajack.App.Wpf/Messages/NavigateTo.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using ReactiveUI;
|
||||||
|
using Wabbajack.Lib;
|
||||||
|
|
||||||
|
namespace Wabbajack.Messages;
|
||||||
|
|
||||||
|
public class NavigateTo
|
||||||
|
{
|
||||||
|
|
||||||
|
public ViewModel ViewModel { get; }
|
||||||
|
private NavigateTo(ViewModel vm)
|
||||||
|
{
|
||||||
|
ViewModel = vm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Send<T>(T vm)
|
||||||
|
where T : ViewModel
|
||||||
|
{
|
||||||
|
MessageBus.Current.SendMessage(new NavigateTo(vm));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
29
Wabbajack.App.Wpf/Messages/NavigateToGlobal.cs
Normal file
29
Wabbajack.App.Wpf/Messages/NavigateToGlobal.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace Wabbajack.Messages;
|
||||||
|
|
||||||
|
public class NavigateToGlobal
|
||||||
|
{
|
||||||
|
public enum ScreenType
|
||||||
|
{
|
||||||
|
ModeSelectionView,
|
||||||
|
ModListGallery,
|
||||||
|
Installer,
|
||||||
|
Settings,
|
||||||
|
Compiler,
|
||||||
|
ModListContents
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScreenType Screen { get; }
|
||||||
|
|
||||||
|
private NavigateToGlobal(ScreenType screen)
|
||||||
|
{
|
||||||
|
Screen = screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Send(ScreenType screen)
|
||||||
|
{
|
||||||
|
MessageBus.Current.SendMessage(new NavigateToGlobal(screen));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Reactive.Subjects;
|
using System.Reactive.Subjects;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@ -7,6 +8,7 @@ using ReactiveUI;
|
|||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using Wabbajack.Common;
|
using Wabbajack.Common;
|
||||||
using Wabbajack.Lib;
|
using Wabbajack.Lib;
|
||||||
|
using Wabbajack.Messages;
|
||||||
|
|
||||||
namespace Wabbajack
|
namespace Wabbajack
|
||||||
{
|
{
|
||||||
@ -25,26 +27,29 @@ namespace Wabbajack
|
|||||||
public ViewModel NavigateBackTarget { get; set; }
|
public ViewModel NavigateBackTarget { get; set; }
|
||||||
public ReactiveCommand<Unit, Unit> BackCommand { get; protected set; }
|
public ReactiveCommand<Unit, Unit> BackCommand { get; protected set; }
|
||||||
|
|
||||||
protected ObservableAsPropertyHelper<bool> _IsActive;
|
[Reactive]
|
||||||
public bool IsActive => _IsActive.Value;
|
public bool IsActive { get; set; }
|
||||||
|
|
||||||
public Subject<bool> IsBackEnabledSubject { get; } = new Subject<bool>();
|
public Subject<bool> IsBackEnabledSubject { get; } = new Subject<bool>();
|
||||||
public IObservable<bool> IsBackEnabled { get; }
|
public IObservable<bool> IsBackEnabled { get; }
|
||||||
|
|
||||||
public BackNavigatingVM(ILogger logger, MainWindowVM mainWindowVM)
|
public BackNavigatingVM(ILogger logger)
|
||||||
{
|
{
|
||||||
IsBackEnabled = IsBackEnabledSubject.StartWith(true);
|
IsBackEnabled = IsBackEnabledSubject.StartWith(true);
|
||||||
BackCommand = ReactiveCommand.Create(
|
BackCommand = ReactiveCommand.Create(
|
||||||
execute: () => logger.CatchAndLog(() =>
|
execute: () => logger.CatchAndLog(() =>
|
||||||
{
|
{
|
||||||
mainWindowVM.NavigateTo(NavigateBackTarget);
|
NavigateBack.Send();
|
||||||
Unload();
|
Unload();
|
||||||
}),
|
}),
|
||||||
canExecute: this.ConstructCanNavigateBack()
|
canExecute: this.ConstructCanNavigateBack()
|
||||||
.ObserveOnGuiThread());
|
.ObserveOnGuiThread());
|
||||||
|
|
||||||
_IsActive = this.ConstructIsActive(mainWindowVM)
|
this.WhenActivated(disposables =>
|
||||||
.ToGuiProperty(this, nameof(IsActive));
|
{
|
||||||
|
IsActive = true;
|
||||||
|
Disposable.Create(() => IsActive = false).DisposeWith(disposables);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Unload()
|
public virtual void Unload()
|
||||||
|
@ -13,6 +13,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using Wabbajack.Compiler;
|
using Wabbajack.Compiler;
|
||||||
using Wabbajack.Lib.Extensions;
|
using Wabbajack.Lib.Extensions;
|
||||||
using Wabbajack.Lib.Interventions;
|
using Wabbajack.Lib.Interventions;
|
||||||
|
using Wabbajack.Messages;
|
||||||
using Wabbajack.RateLimiter;
|
using Wabbajack.RateLimiter;
|
||||||
|
|
||||||
namespace Wabbajack
|
namespace Wabbajack
|
||||||
@ -64,7 +65,7 @@ namespace Wabbajack
|
|||||||
private readonly ObservableAsPropertyHelper<(int CurrentCPUs, int DesiredCPUs)> _CurrentCpuCount;
|
private readonly ObservableAsPropertyHelper<(int CurrentCPUs, int DesiredCPUs)> _CurrentCpuCount;
|
||||||
public (int CurrentCPUs, int DesiredCPUs) CurrentCpuCount => _CurrentCpuCount.Value;
|
public (int CurrentCPUs, int DesiredCPUs) CurrentCpuCount => _CurrentCpuCount.Value;
|
||||||
|
|
||||||
public CompilerVM(ILogger<CompilerVM> logger, MainWindowVM mainWindowVM) : base(logger, mainWindowVM)
|
public CompilerVM(ILogger<CompilerVM> logger, MainWindowVM mainWindowVM) : base(logger)
|
||||||
{
|
{
|
||||||
MWVM = mainWindowVM;
|
MWVM = mainWindowVM;
|
||||||
|
|
||||||
@ -133,7 +134,7 @@ namespace Wabbajack
|
|||||||
BackCommand = ReactiveCommand.Create(
|
BackCommand = ReactiveCommand.Create(
|
||||||
execute: () =>
|
execute: () =>
|
||||||
{
|
{
|
||||||
mainWindowVM.NavigateTo(mainWindowVM.ModeSelectionVM);
|
NavigateToGlobal.Send(NavigateToGlobal.ScreenType.ModeSelectionView);
|
||||||
StartedCompilation = false;
|
StartedCompilation = false;
|
||||||
Completed = null;
|
Completed = null;
|
||||||
},
|
},
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using DynamicData;
|
using DynamicData;
|
||||||
using DynamicData.Binding;
|
using DynamicData.Binding;
|
||||||
@ -17,6 +21,7 @@ using Wabbajack.DTOs;
|
|||||||
using Wabbajack.Hashing.xxHash64;
|
using Wabbajack.Hashing.xxHash64;
|
||||||
using Wabbajack.Lib.Extensions;
|
using Wabbajack.Lib.Extensions;
|
||||||
using Wabbajack.Networking.WabbajackClientApi;
|
using Wabbajack.Networking.WabbajackClientApi;
|
||||||
|
using Wabbajack.Services.OSIntegrated;
|
||||||
using Wabbajack.Services.OSIntegrated.Services;
|
using Wabbajack.Services.OSIntegrated.Services;
|
||||||
|
|
||||||
namespace Wabbajack
|
namespace Wabbajack
|
||||||
@ -25,66 +30,46 @@ namespace Wabbajack
|
|||||||
{
|
{
|
||||||
public MainWindowVM MWVM { get; }
|
public MainWindowVM MWVM { get; }
|
||||||
|
|
||||||
public ObservableCollectionExtended<ModListMetadataVM> ModLists { get; } = new ObservableCollectionExtended<ModListMetadataVM>();
|
private readonly SourceCache<ModListMetadataVM, string> _modLists = new(x => x.Metadata.Links.MachineURL);
|
||||||
|
public ReadOnlyObservableCollection<ModListMetadataVM> _filteredModLists;
|
||||||
|
public ReadOnlyObservableCollection<ModListMetadataVM> ModLists => _filteredModLists;
|
||||||
|
|
||||||
private const string ALL_GAME_TYPE = "All";
|
private const string ALL_GAME_TYPE = "All";
|
||||||
|
|
||||||
[Reactive]
|
[Reactive] public IErrorResponse Error { get; set; }
|
||||||
public IErrorResponse Error { get; set; }
|
|
||||||
|
|
||||||
[Reactive]
|
[Reactive] public string Search { get; set; }
|
||||||
public string Search { get; set; }
|
|
||||||
|
|
||||||
[Reactive]
|
[Reactive] public bool OnlyInstalled { get; set; }
|
||||||
public bool OnlyInstalled { get; set; }
|
|
||||||
|
|
||||||
[Reactive]
|
[Reactive] public bool ShowNSFW { get; set; }
|
||||||
public bool ShowNSFW { get; set; }
|
|
||||||
|
|
||||||
[Reactive]
|
[Reactive] public bool ShowUtilityLists { get; set; }
|
||||||
public bool ShowUtilityLists { get; set; }
|
|
||||||
|
|
||||||
[Reactive]
|
[Reactive] public string GameType { get; set; }
|
||||||
public string GameType { get; set; }
|
|
||||||
|
|
||||||
public List<string> GameTypeEntries { get { return GetGameTypeEntries(); } }
|
public List<string> GameTypeEntries => GetGameTypeEntries();
|
||||||
|
|
||||||
private readonly ObservableAsPropertyHelper<bool> _Loaded;
|
private ObservableAsPropertyHelper<bool> _Loaded;
|
||||||
private readonly Client _wjClient;
|
private readonly Client _wjClient;
|
||||||
private readonly ILogger<ModListGalleryVM> _logger;
|
private readonly ILogger<ModListGalleryVM> _logger;
|
||||||
private readonly GameLocator _locator;
|
private readonly GameLocator _locator;
|
||||||
|
private readonly ModListDownloadMaintainer _maintainer;
|
||||||
|
|
||||||
private FiltersSettings settings => MWVM.Settings.Filters;
|
private FiltersSettings settings { get; set; } = new();
|
||||||
|
|
||||||
public bool Loaded => _Loaded.Value;
|
public bool Loaded => _Loaded.Value;
|
||||||
|
|
||||||
public ICommand ClearFiltersCommand { get; }
|
public ICommand ClearFiltersCommand { get; set; }
|
||||||
|
|
||||||
public ModListGalleryVM(ILogger<ModListGalleryVM> logger, MainWindowVM mainWindowVM, Client wjClient,
|
public ModListGalleryVM(ILogger<ModListGalleryVM> logger, Client wjClient,
|
||||||
GameLocator locator, IServiceProvider provider)
|
GameLocator locator, SettingsManager settingsManager, ModListDownloadMaintainer maintainer)
|
||||||
: base(logger, mainWindowVM)
|
: base(logger)
|
||||||
{
|
{
|
||||||
MWVM = mainWindowVM;
|
|
||||||
_wjClient = wjClient;
|
_wjClient = wjClient;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_locator = locator;
|
_locator = locator;
|
||||||
|
_maintainer = maintainer;
|
||||||
// load persistent filter settings
|
|
||||||
if (settings.IsPersistent)
|
|
||||||
{
|
|
||||||
GameType = !string.IsNullOrEmpty(settings.Game) ? settings.Game : ALL_GAME_TYPE;
|
|
||||||
ShowNSFW = settings.ShowNSFW;
|
|
||||||
ShowUtilityLists = settings.ShowUtilityLists;
|
|
||||||
OnlyInstalled = settings.OnlyInstalled;
|
|
||||||
Search = settings.Search;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
GameType = ALL_GAME_TYPE;
|
|
||||||
|
|
||||||
// subscribe to save signal
|
|
||||||
MWVM.Settings.SaveSignal
|
|
||||||
.Subscribe(_ => UpdateFiltersSettings())
|
|
||||||
.DisposeWith(this.CompositeDisposable);
|
|
||||||
|
|
||||||
ClearFiltersCommand = ReactiveCommand.Create(
|
ClearFiltersCommand = ReactiveCommand.Create(
|
||||||
() =>
|
() =>
|
||||||
@ -97,101 +82,16 @@ namespace Wabbajack
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
this.WhenAny(x => x.OnlyInstalled)
|
this.WhenActivated(disposables =>
|
||||||
.Subscribe(val =>
|
{
|
||||||
{
|
var _ = LoadModLists();
|
||||||
if(val)
|
|
||||||
GameType = ALL_GAME_TYPE;
|
|
||||||
})
|
|
||||||
.DisposeWith(CompositeDisposable);
|
|
||||||
|
|
||||||
var sourceList = Observable.Return(Unit.Default)
|
_modLists.Connect()
|
||||||
.ObserveOn(RxApp.TaskpoolScheduler)
|
.ObserveOn(RxApp.MainThreadScheduler)
|
||||||
.SelectMany(async _ =>
|
.Bind(out _filteredModLists)
|
||||||
{
|
.Subscribe()
|
||||||
try
|
.DisposeWith(disposables);
|
||||||
{
|
});
|
||||||
Error = null;
|
|
||||||
var list = await _wjClient.LoadLists();
|
|
||||||
Error = ErrorResponse.Success;
|
|
||||||
return list
|
|
||||||
.AsObservableChangeSet(x => x.DownloadMetadata?.Hash ?? default);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "While Loading Lists");
|
|
||||||
Error = ErrorResponse.Fail(ex);
|
|
||||||
return Observable.Empty<IChangeSet<ModlistMetadata, Hash>>();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// Unsubscribe and release when not active
|
|
||||||
.FlowSwitch(
|
|
||||||
this.WhenAny(x => x.IsActive),
|
|
||||||
valueWhenOff: Observable.Return(ChangeSet<ModlistMetadata, Hash>.Empty))
|
|
||||||
.Switch()
|
|
||||||
.RefCount();
|
|
||||||
|
|
||||||
_Loaded = sourceList.CollectionCount()
|
|
||||||
.Select(c => c > 0)
|
|
||||||
.ToProperty(this, nameof(Loaded));
|
|
||||||
|
|
||||||
// Convert to VM and bind to resulting list
|
|
||||||
sourceList
|
|
||||||
.ObserveOnGuiThread()
|
|
||||||
.Transform(m => new ModListMetadataVM(provider.GetRequiredService<ILogger<ModListMetadataVM>>(),this, m,
|
|
||||||
provider.GetRequiredService<ModListDownloadMaintainer>(), provider.GetRequiredService<Client>()))
|
|
||||||
.DisposeMany()
|
|
||||||
// Filter only installed
|
|
||||||
.Filter(this.WhenAny(x => x.OnlyInstalled)
|
|
||||||
.Select<bool, Func<ModListMetadataVM, bool>>(onlyInstalled => (vm) =>
|
|
||||||
{
|
|
||||||
if (!onlyInstalled) return true;
|
|
||||||
if (!GameRegistry.Games.TryGetValue(vm.Metadata.Game, out var gameMeta)) return false;
|
|
||||||
return _locator.IsInstalled(gameMeta.Game);
|
|
||||||
}))
|
|
||||||
// Filter on search box
|
|
||||||
.Filter(this.WhenAny(x => x.Search)
|
|
||||||
.Debounce(TimeSpan.FromMilliseconds(150), RxApp.MainThreadScheduler)
|
|
||||||
.Select<string, Func<ModListMetadataVM, bool>>(search => (vm) =>
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(search)) return true;
|
|
||||||
return vm.Metadata.Title.ContainsCaseInsensitive(search) || vm.Metadata.tags.Any(t => t.ContainsCaseInsensitive(search));
|
|
||||||
}))
|
|
||||||
.Filter(this.WhenAny(x => x.ShowNSFW)
|
|
||||||
.Select<bool, Func<ModListMetadataVM, bool>>(showNSFW => vm =>
|
|
||||||
{
|
|
||||||
if (!vm.Metadata.NSFW) return true;
|
|
||||||
return vm.Metadata.NSFW && showNSFW;
|
|
||||||
}))
|
|
||||||
.Filter(this.WhenAny(x => x.ShowUtilityLists)
|
|
||||||
.Select<bool, Func<ModListMetadataVM, bool>>(showUtilityLists => vm => showUtilityLists ? vm.Metadata.UtilityList : !vm.Metadata.UtilityList))
|
|
||||||
// Filter by Game
|
|
||||||
.Filter(this.WhenAny(x => x.GameType)
|
|
||||||
.Debounce(TimeSpan.FromMilliseconds(150), RxApp.MainThreadScheduler)
|
|
||||||
.Select<string, Func<ModListMetadataVM, bool>>(GameType => (vm) =>
|
|
||||||
{
|
|
||||||
if (GameType == ALL_GAME_TYPE)
|
|
||||||
return true;
|
|
||||||
if (string.IsNullOrEmpty(GameType))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return GameType == vm.Metadata.Game.GetDescription<Game>().ToString();
|
|
||||||
|
|
||||||
}))
|
|
||||||
.Bind(ModLists)
|
|
||||||
.Subscribe()
|
|
||||||
.DisposeWith(CompositeDisposable);
|
|
||||||
|
|
||||||
// Extra GC when navigating away, just to immediately clean up modlist metadata
|
|
||||||
this.WhenAny(x => x.IsActive)
|
|
||||||
.Where(x => !x)
|
|
||||||
.Skip(1)
|
|
||||||
.Delay(TimeSpan.FromMilliseconds(50), RxApp.MainThreadScheduler)
|
|
||||||
.Subscribe(_ =>
|
|
||||||
{
|
|
||||||
GC.Collect();
|
|
||||||
})
|
|
||||||
.DisposeWith(CompositeDisposable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Unload()
|
public override void Unload()
|
||||||
@ -199,9 +99,30 @@ namespace Wabbajack
|
|||||||
Error = null;
|
Error = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task LoadModLists()
|
||||||
|
{
|
||||||
|
using var ll = LoadingLock.WithLoading();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var modLists = await _wjClient.LoadLists();
|
||||||
|
_modLists.Edit(e =>
|
||||||
|
{
|
||||||
|
e.Clear();
|
||||||
|
e.AddOrUpdate(modLists.Select(m =>
|
||||||
|
new ModListMetadataVM(_logger, this, m, _maintainer, _wjClient)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "While loading lists");
|
||||||
|
ll.Fail();
|
||||||
|
}
|
||||||
|
ll.Succeed();
|
||||||
|
}
|
||||||
|
|
||||||
private List<string> GetGameTypeEntries()
|
private List<string> GetGameTypeEntries()
|
||||||
{
|
{
|
||||||
List<string> gameEntries = new List<string> { ALL_GAME_TYPE };
|
List<string> gameEntries = new List<string> {ALL_GAME_TYPE};
|
||||||
gameEntries.AddRange(GameRegistry.Games.Values.Select(gameType => gameType.HumanFriendlyGameName));
|
gameEntries.AddRange(GameRegistry.Games.Values.Select(gameType => gameType.HumanFriendlyGameName));
|
||||||
gameEntries.Sort();
|
gameEntries.Sort();
|
||||||
return gameEntries;
|
return gameEntries;
|
||||||
|
@ -16,6 +16,7 @@ using Wabbajack.DTOs;
|
|||||||
using Wabbajack.DTOs.ServerResponses;
|
using Wabbajack.DTOs.ServerResponses;
|
||||||
using Wabbajack.Lib;
|
using Wabbajack.Lib;
|
||||||
using Wabbajack.Lib.Extensions;
|
using Wabbajack.Lib.Extensions;
|
||||||
|
using Wabbajack.Messages;
|
||||||
using Wabbajack.Networking.WabbajackClientApi;
|
using Wabbajack.Networking.WabbajackClientApi;
|
||||||
using Wabbajack.Paths;
|
using Wabbajack.Paths;
|
||||||
using Wabbajack.Paths.IO;
|
using Wabbajack.Paths.IO;
|
||||||
@ -126,7 +127,7 @@ namespace Wabbajack
|
|||||||
ArchiveStatus = a.Status,
|
ArchiveStatus = a.Status,
|
||||||
IsFailing = a.Status != ArchiveStatus.InValid
|
IsFailing = a.Status != ArchiveStatus.InValid
|
||||||
}));
|
}));
|
||||||
_parent.MWVM.NavigateTo(_parent.MWVM.ModListContentsVM.Value);
|
NavigateToGlobal.Send(NavigateToGlobal.ScreenType.ModListContents);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,7 @@ using Microsoft.WindowsAPICodePack.Shell;
|
|||||||
using Wabbajack.DTOs.JsonConverters;
|
using Wabbajack.DTOs.JsonConverters;
|
||||||
using Wabbajack.Lib.Extensions;
|
using Wabbajack.Lib.Extensions;
|
||||||
using Wabbajack.Lib.Interventions;
|
using Wabbajack.Lib.Interventions;
|
||||||
|
using Wabbajack.Messages;
|
||||||
using Wabbajack.RateLimiter;
|
using Wabbajack.RateLimiter;
|
||||||
using Wabbajack.View_Models;
|
using Wabbajack.View_Models;
|
||||||
using Wabbajack.Paths.IO;
|
using Wabbajack.Paths.IO;
|
||||||
@ -98,7 +99,7 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM, ICpuStatusVM
|
|||||||
public ReactiveCommand<Unit, Unit> GoToInstallCommand { get; }
|
public ReactiveCommand<Unit, Unit> GoToInstallCommand { get; }
|
||||||
public ReactiveCommand<Unit, Unit> BeginCommand { get; }
|
public ReactiveCommand<Unit, Unit> BeginCommand { get; }
|
||||||
|
|
||||||
public InstallerVM(ILogger<InstallerVM> logger, MainWindowVM mainWindowVM, IServiceProvider serviceProvider) : base(logger, mainWindowVM)
|
public InstallerVM(ILogger<InstallerVM> logger, MainWindowVM mainWindowVM, IServiceProvider serviceProvider) : base(logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
@ -163,9 +164,6 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM, ICpuStatusVM
|
|||||||
})
|
})
|
||||||
.DisposeWith(CompositeDisposable);
|
.DisposeWith(CompositeDisposable);
|
||||||
|
|
||||||
_IsActive = this.ConstructIsActive(MWVM)
|
|
||||||
.ToGuiProperty(this, nameof(IsActive));
|
|
||||||
|
|
||||||
// Active path represents the path to currently have loaded
|
// Active path represents the path to currently have loaded
|
||||||
// If we're not actively showing, then "unload" the active path
|
// If we're not actively showing, then "unload" the active path
|
||||||
var activePath = Observable.CombineLatest(
|
var activePath = Observable.CombineLatest(
|
||||||
@ -239,7 +237,7 @@ public class InstallerVM : BackNavigatingVM, IBackNavigatingVM, ICpuStatusVM
|
|||||||
{
|
{
|
||||||
StartedInstallation = false;
|
StartedInstallation = false;
|
||||||
Completed = null;
|
Completed = null;
|
||||||
mainWindowVM.NavigateTo(mainWindowVM.ModeSelectionVM);
|
NavigateToGlobal.Send(NavigateToGlobal.ScreenType.ModeSelectionView);
|
||||||
},
|
},
|
||||||
canExecute: Observable.CombineLatest(
|
canExecute: Observable.CombineLatest(
|
||||||
this.WhenAny(x => x.Installing)
|
this.WhenAny(x => x.Installing)
|
||||||
|
@ -3,6 +3,7 @@ using ReactiveUI;
|
|||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -14,6 +15,7 @@ using Wabbajack.Common;
|
|||||||
using Wabbajack.Downloaders.GameFile;
|
using Wabbajack.Downloaders.GameFile;
|
||||||
using Wabbajack.Lib;
|
using Wabbajack.Lib;
|
||||||
using Wabbajack.Lib.Interventions;
|
using Wabbajack.Lib.Interventions;
|
||||||
|
using Wabbajack.Messages;
|
||||||
using Wabbajack.Networking.WabbajackClientApi;
|
using Wabbajack.Networking.WabbajackClientApi;
|
||||||
using Wabbajack.Paths;
|
using Wabbajack.Paths;
|
||||||
using Wabbajack.View_Models;
|
using Wabbajack.View_Models;
|
||||||
@ -38,7 +40,7 @@ namespace Wabbajack
|
|||||||
public readonly Lazy<CompilerVM> Compiler;
|
public readonly Lazy<CompilerVM> Compiler;
|
||||||
public readonly Lazy<InstallerVM> Installer;
|
public readonly Lazy<InstallerVM> Installer;
|
||||||
public readonly Lazy<SettingsVM> SettingsPane;
|
public readonly Lazy<SettingsVM> SettingsPane;
|
||||||
public readonly Lazy<ModListGalleryVM> Gallery;
|
public readonly ModListGalleryVM Gallery;
|
||||||
public readonly ModeSelectionVM ModeSelectionVM;
|
public readonly ModeSelectionVM ModeSelectionVM;
|
||||||
public readonly Lazy<ModListContentsVM> ModListContentsVM;
|
public readonly Lazy<ModListContentsVM> ModListContentsVM;
|
||||||
public readonly UserInterventionHandlers UserInterventionHandlers;
|
public readonly UserInterventionHandlers UserInterventionHandlers;
|
||||||
@ -55,7 +57,7 @@ namespace Wabbajack
|
|||||||
public bool UpdateAvailable { get; private set; }
|
public bool UpdateAvailable { get; private set; }
|
||||||
|
|
||||||
public MainWindowVM(ILogger<MainWindowVM> logger, MainSettings settings, Client wjClient,
|
public MainWindowVM(ILogger<MainWindowVM> logger, MainSettings settings, Client wjClient,
|
||||||
IServiceProvider serviceProvider)
|
IServiceProvider serviceProvider, ModeSelectionVM modeSelectionVM, ModListGalleryVM modListGalleryVM)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_wjClient = wjClient;
|
_wjClient = wjClient;
|
||||||
@ -64,12 +66,15 @@ namespace Wabbajack
|
|||||||
Installer = new Lazy<InstallerVM>(() => new InstallerVM(serviceProvider.GetRequiredService<ILogger<InstallerVM>>(), this, serviceProvider));
|
Installer = new Lazy<InstallerVM>(() => new InstallerVM(serviceProvider.GetRequiredService<ILogger<InstallerVM>>(), this, serviceProvider));
|
||||||
Compiler = new Lazy<CompilerVM>(() => new CompilerVM(serviceProvider.GetRequiredService<ILogger<CompilerVM>>(), this));
|
Compiler = new Lazy<CompilerVM>(() => new CompilerVM(serviceProvider.GetRequiredService<ILogger<CompilerVM>>(), this));
|
||||||
SettingsPane = new Lazy<SettingsVM>(() => new SettingsVM(serviceProvider.GetRequiredService<ILogger<SettingsVM>>(), this, serviceProvider));
|
SettingsPane = new Lazy<SettingsVM>(() => new SettingsVM(serviceProvider.GetRequiredService<ILogger<SettingsVM>>(), this, serviceProvider));
|
||||||
Gallery = new Lazy<ModListGalleryVM>(() => new ModListGalleryVM(serviceProvider.GetRequiredService<ILogger<ModListGalleryVM>>(), this,
|
Gallery = modListGalleryVM;
|
||||||
serviceProvider.GetRequiredService<Client>(), serviceProvider.GetRequiredService<GameLocator>(), serviceProvider));
|
ModeSelectionVM = modeSelectionVM;
|
||||||
ModeSelectionVM = new ModeSelectionVM(this);
|
|
||||||
ModListContentsVM = new Lazy<ModListContentsVM>(() => new ModListContentsVM(serviceProvider.GetRequiredService<ILogger<ModListContentsVM>>(), this));
|
ModListContentsVM = new Lazy<ModListContentsVM>(() => new ModListContentsVM(serviceProvider.GetRequiredService<ILogger<ModListContentsVM>>(), this));
|
||||||
UserInterventionHandlers = new UserInterventionHandlers(serviceProvider.GetRequiredService<ILogger<UserInterventionHandlers>>(), this);
|
UserInterventionHandlers = new UserInterventionHandlers(serviceProvider.GetRequiredService<ILogger<UserInterventionHandlers>>(), this);
|
||||||
|
|
||||||
|
MessageBus.Current.Listen<NavigateToGlobal>()
|
||||||
|
.Subscribe(m => HandleNavigateTo(m.Screen))
|
||||||
|
.DisposeWith(CompositeDisposable);
|
||||||
|
|
||||||
// Set up logging
|
// Set up logging
|
||||||
/* TODO
|
/* TODO
|
||||||
Utils.LogMessages
|
Utils.LogMessages
|
||||||
@ -116,12 +121,12 @@ namespace Wabbajack
|
|||||||
if (IsStartingFromModlist(out var path))
|
if (IsStartingFromModlist(out var path))
|
||||||
{
|
{
|
||||||
Installer.Value.ModListLocation.TargetPath = path;
|
Installer.Value.ModListLocation.TargetPath = path;
|
||||||
NavigateTo(Installer.Value);
|
NavigateToGlobal.Send(NavigateToGlobal.ScreenType.Installer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Start on mode selection
|
// Start on mode selection
|
||||||
NavigateTo(ModeSelectionVM);
|
NavigateToGlobal.Send(NavigateToGlobal.ScreenType.ModeSelectionView);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -147,7 +152,19 @@ namespace Wabbajack
|
|||||||
OpenSettingsCommand = ReactiveCommand.Create(
|
OpenSettingsCommand = ReactiveCommand.Create(
|
||||||
canExecute: this.WhenAny(x => x.ActivePane)
|
canExecute: this.WhenAny(x => x.ActivePane)
|
||||||
.Select(active => !SettingsPane.IsValueCreated || !object.ReferenceEquals(active, SettingsPane.Value)),
|
.Select(active => !SettingsPane.IsValueCreated || !object.ReferenceEquals(active, SettingsPane.Value)),
|
||||||
execute: () => NavigateTo(SettingsPane.Value));
|
execute: () => NavigateToGlobal.Send(NavigateToGlobal.ScreenType.Settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleNavigateTo(NavigateToGlobal.ScreenType s)
|
||||||
|
{
|
||||||
|
ActivePane = s switch
|
||||||
|
{
|
||||||
|
NavigateToGlobal.ScreenType.ModeSelectionView => ModeSelectionVM,
|
||||||
|
NavigateToGlobal.ScreenType.ModListGallery => Gallery,
|
||||||
|
NavigateToGlobal.ScreenType.Installer => Installer.Value,
|
||||||
|
NavigateToGlobal.ScreenType.Settings => SettingsPane.Value,
|
||||||
|
_ => ActivePane
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsStartingFromModlist(out AbsolutePath modlistPath)
|
private static bool IsStartingFromModlist(out AbsolutePath modlistPath)
|
||||||
@ -171,21 +188,23 @@ namespace Wabbajack
|
|||||||
if (path == default) return;
|
if (path == default) return;
|
||||||
var installer = Installer.Value;
|
var installer = Installer.Value;
|
||||||
Settings.Installer.LastInstalledListLocation = path;
|
Settings.Installer.LastInstalledListLocation = path;
|
||||||
NavigateTo(installer);
|
NavigateToGlobal.Send(NavigateToGlobal.ScreenType.Installer);
|
||||||
installer.ModListLocation.TargetPath = path;
|
installer.ModListLocation.TargetPath = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
public void NavigateTo(ViewModel vm)
|
public void NavigateTo(ViewModel vm)
|
||||||
{
|
{
|
||||||
ActivePane = vm;
|
ActivePane = vm;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
/*
|
||||||
public void NavigateTo<T>(T vm)
|
public void NavigateTo<T>(T vm)
|
||||||
where T : ViewModel, IBackNavigatingVM
|
where T : ViewModel, IBackNavigatingVM
|
||||||
{
|
{
|
||||||
vm.NavigateBackTarget = ActivePane;
|
vm.NavigateBackTarget = ActivePane;
|
||||||
ActivePane = vm;
|
ActivePane = vm;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public async Task ShutdownApplication()
|
public async Task ShutdownApplication()
|
||||||
{
|
{
|
||||||
|
@ -31,7 +31,7 @@ namespace Wabbajack.View_Models
|
|||||||
private static readonly Regex NameMatcher = new(@"(?<=\.)[^\.]+(?=\+State)", RegexOptions.Compiled);
|
private static readonly Regex NameMatcher = new(@"(?<=\.)[^\.]+(?=\+State)", RegexOptions.Compiled);
|
||||||
private readonly ILogger<ModListContentsVM> _logger;
|
private readonly ILogger<ModListContentsVM> _logger;
|
||||||
|
|
||||||
public ModListContentsVM(ILogger<ModListContentsVM> logger, MainWindowVM mwvm) : base(logger, mwvm)
|
public ModListContentsVM(ILogger<ModListContentsVM> logger, MainWindowVM mwvm) : base(logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_mwvm = mwvm;
|
_mwvm = mwvm;
|
||||||
|
@ -8,6 +8,7 @@ using System.Reactive.Linq;
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Wabbajack.Common;
|
using Wabbajack.Common;
|
||||||
using Wabbajack.Lib;
|
using Wabbajack.Lib;
|
||||||
|
using Wabbajack.Messages;
|
||||||
using Wabbajack.Paths.IO;
|
using Wabbajack.Paths.IO;
|
||||||
|
|
||||||
namespace Wabbajack
|
namespace Wabbajack
|
||||||
@ -20,23 +21,23 @@ namespace Wabbajack
|
|||||||
public ICommand CompileCommand { get; }
|
public ICommand CompileCommand { get; }
|
||||||
public ReactiveCommand<Unit, Unit> UpdateCommand { get; }
|
public ReactiveCommand<Unit, Unit> UpdateCommand { get; }
|
||||||
|
|
||||||
public ModeSelectionVM(MainWindowVM mainVM)
|
public ModeSelectionVM()
|
||||||
{
|
{
|
||||||
_mainVM = mainVM;
|
|
||||||
|
|
||||||
InstallCommand = ReactiveCommand.Create(
|
InstallCommand = ReactiveCommand.Create(
|
||||||
execute: () =>
|
execute: () =>
|
||||||
{
|
{
|
||||||
|
/* TODO
|
||||||
var path = mainVM.Settings.Installer.LastInstalledListLocation;
|
var path = mainVM.Settings.Installer.LastInstalledListLocation;
|
||||||
if (path == default || !path.FileExists())
|
if (path == default || !path.FileExists())
|
||||||
{
|
{
|
||||||
path = UIUtils.OpenFileDialog($"*{Ext.Wabbajack}|*{Ext.Wabbajack}");
|
path = UIUtils.OpenFileDialog($"*{Ext.Wabbajack}|*{Ext.Wabbajack}");
|
||||||
}
|
}
|
||||||
_mainVM.OpenInstaller(path);
|
_mainVM.OpenInstaller(path);
|
||||||
|
*/
|
||||||
});
|
});
|
||||||
|
|
||||||
CompileCommand = ReactiveCommand.Create(() => mainVM.NavigateTo(mainVM.Compiler.Value));
|
CompileCommand = ReactiveCommand.Create(() => NavigateToGlobal.Send(NavigateToGlobal.ScreenType.Compiler));
|
||||||
BrowseCommand = ReactiveCommand.Create(() => mainVM.NavigateTo(mainVM.Gallery.Value));
|
BrowseCommand = ReactiveCommand.Create(() => NavigateToGlobal.Send(NavigateToGlobal.ScreenType.ModListGallery));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ namespace Wabbajack.View_Models.Settings
|
|||||||
private readonly Client _wjClient;
|
private readonly Client _wjClient;
|
||||||
private IObservable<bool> IsUploading { get; }
|
private IObservable<bool> IsUploading { get; }
|
||||||
|
|
||||||
public AuthorFilesVM(ILogger<AuthorFilesVM> logger, WabbajackApiTokenProvider token, Client wjClient, SettingsVM vm) : base(logger, vm.MWVM)
|
public AuthorFilesVM(ILogger<AuthorFilesVM> logger, WabbajackApiTokenProvider token, Client wjClient, SettingsVM vm) : base(logger)
|
||||||
{
|
{
|
||||||
_token = token;
|
_token = token;
|
||||||
_wjClient = wjClient;
|
_wjClient = wjClient;
|
||||||
|
@ -20,7 +20,7 @@ namespace Wabbajack
|
|||||||
public List<LoginTargetVM> Downloaders { get; }
|
public List<LoginTargetVM> Downloaders { get; }
|
||||||
|
|
||||||
public LoginManagerVM(ILogger<LoginManagerVM> logger, SettingsVM settingsVM)
|
public LoginManagerVM(ILogger<LoginManagerVM> logger, SettingsVM settingsVM)
|
||||||
: base(logger, settingsVM.MWVM)
|
: base(logger)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Downloaders = DownloadDispatcher.Downloaders
|
Downloaders = DownloadDispatcher.Downloaders
|
||||||
|
@ -28,7 +28,7 @@ namespace Wabbajack
|
|||||||
public ICommand OpenTerminalCommand { get; }
|
public ICommand OpenTerminalCommand { get; }
|
||||||
|
|
||||||
public SettingsVM(ILogger<SettingsVM> logger, MainWindowVM mainWindowVM, IServiceProvider provider)
|
public SettingsVM(ILogger<SettingsVM> logger, MainWindowVM mainWindowVM, IServiceProvider provider)
|
||||||
: base(logger, mainWindowVM)
|
: base(logger)
|
||||||
{
|
{
|
||||||
MWVM = mainWindowVM;
|
MWVM = mainWindowVM;
|
||||||
Login = new LoginManagerVM(provider.GetRequiredService<ILogger<LoginManagerVM>>(), this);
|
Login = new LoginManagerVM(provider.GetRequiredService<ILogger<LoginManagerVM>>(), this);
|
||||||
|
@ -7,6 +7,7 @@ using ReactiveUI;
|
|||||||
using Wabbajack.Common;
|
using Wabbajack.Common;
|
||||||
using Wabbajack.Lib;
|
using Wabbajack.Lib;
|
||||||
using Wabbajack.Lib.Interventions;
|
using Wabbajack.Lib.Interventions;
|
||||||
|
using Wabbajack.Messages;
|
||||||
|
|
||||||
namespace Wabbajack
|
namespace Wabbajack
|
||||||
{
|
{
|
||||||
@ -28,11 +29,11 @@ namespace Wabbajack
|
|||||||
var cancel = new CancellationTokenSource();
|
var cancel = new CancellationTokenSource();
|
||||||
var oldPane = MainWindow.ActivePane;
|
var oldPane = MainWindow.ActivePane;
|
||||||
using var vm = await WebBrowserVM.GetNew(_logger);
|
using var vm = await WebBrowserVM.GetNew(_logger);
|
||||||
MainWindow.NavigateTo(vm);
|
NavigateTo.Send(vm);
|
||||||
vm.BackCommand = ReactiveCommand.Create(() =>
|
vm.BackCommand = ReactiveCommand.Create(() =>
|
||||||
{
|
{
|
||||||
cancel.Cancel();
|
cancel.Cancel();
|
||||||
MainWindow.NavigateTo(oldPane);
|
NavigateTo.Send(oldPane);
|
||||||
intervention.Cancel();
|
intervention.Cancel();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ namespace Wabbajack
|
|||||||
wait.Dispose();
|
wait.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow.NavigateTo(oldPane);
|
NavigateTo.Send(oldPane);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Handle(IStatusMessage msg)
|
public async Task Handle(IStatusMessage msg)
|
||||||
|
@ -19,19 +19,19 @@ namespace Wabbajack
|
|||||||
this.WhenAny(x => x.ViewModel.ModLists)
|
this.WhenAny(x => x.ViewModel.ModLists)
|
||||||
.BindToStrict(this, x => x.ModListGalleryControl.ItemsSource)
|
.BindToStrict(this, x => x.ModListGalleryControl.ItemsSource)
|
||||||
.DisposeWith(dispose);
|
.DisposeWith(dispose);
|
||||||
Observable.CombineLatest(
|
|
||||||
this.WhenAny(x => x.ViewModel.Error),
|
this.WhenAny(x => x.ViewModel.LoadingLock.IsLoading)
|
||||||
this.WhenAny(x => x.ViewModel.Loaded),
|
|
||||||
resultSelector: (err, loaded) =>
|
|
||||||
{
|
|
||||||
if (!err?.Succeeded ?? false) return true;
|
|
||||||
return !loaded;
|
|
||||||
})
|
|
||||||
.DistinctUntilChanged()
|
|
||||||
.Select(x => x ? Visibility.Visible : Visibility.Collapsed)
|
.Select(x => x ? Visibility.Visible : Visibility.Collapsed)
|
||||||
.StartWith(Visibility.Collapsed)
|
.StartWith(Visibility.Collapsed)
|
||||||
.BindToStrict(this, x => x.LoadingRing.Visibility)
|
.BindTo(this, x => x.LoadingRing.Visibility)
|
||||||
.DisposeWith(dispose);
|
.DisposeWith(dispose);
|
||||||
|
|
||||||
|
this.WhenAny(x => x.ViewModel.LoadingLock.ErrorState)
|
||||||
|
.Select(e => (e?.Succeeded ?? true) ? Visibility.Collapsed : Visibility.Visible)
|
||||||
|
.StartWith(Visibility.Collapsed)
|
||||||
|
.BindToStrict(this, x => x.ErrorIcon.Visibility)
|
||||||
|
.DisposeWith(dispose);
|
||||||
|
|
||||||
Observable.CombineLatest(
|
Observable.CombineLatest(
|
||||||
this.WhenAny(x => x.ViewModel.ModLists.Count)
|
this.WhenAny(x => x.ViewModel.ModLists.Count)
|
||||||
.Select(x => x > 0),
|
.Select(x => x > 0),
|
||||||
@ -45,11 +45,7 @@ namespace Wabbajack
|
|||||||
.StartWith(Visibility.Collapsed)
|
.StartWith(Visibility.Collapsed)
|
||||||
.BindToStrict(this, x => x.NoneFound.Visibility)
|
.BindToStrict(this, x => x.NoneFound.Visibility)
|
||||||
.DisposeWith(dispose);
|
.DisposeWith(dispose);
|
||||||
this.WhenAny(x => x.ViewModel.Error)
|
|
||||||
.Select(e => (e?.Succeeded ?? true) ? Visibility.Collapsed : Visibility.Visible)
|
|
||||||
.StartWith(Visibility.Collapsed)
|
|
||||||
.BindToStrict(this, x => x.ErrorIcon.Visibility)
|
|
||||||
.DisposeWith(dispose);
|
|
||||||
|
|
||||||
this.BindStrict(ViewModel, vm => vm.Search, x => x.SearchBox.Text)
|
this.BindStrict(ViewModel, vm => vm.Search, x => x.SearchBox.Text)
|
||||||
.DisposeWith(dispose);
|
.DisposeWith(dispose);
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
<PackageReference Include="CefSharp.Wpf" Version="91.1.230">
|
<PackageReference Include="CefSharp.Wpf" Version="91.1.230">
|
||||||
<NoWarn>NU1701</NoWarn>
|
<NoWarn>NU1701</NoWarn>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="DynamicData" Version="7.2.1" />
|
<PackageReference Include="DynamicData" Version="7.3.1" />
|
||||||
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.1.0">
|
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.1.0">
|
||||||
<NoWarn>NU1701</NoWarn>
|
<NoWarn>NU1701</NoWarn>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@ -78,9 +78,9 @@
|
|||||||
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell" Version="1.1.4" />
|
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell" Version="1.1.4" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
|
||||||
<PackageReference Include="PInvoke.User32" Version="0.7.104" />
|
<PackageReference Include="PInvoke.User32" Version="0.7.104" />
|
||||||
<PackageReference Include="ReactiveUI" Version="14.1.1" />
|
<PackageReference Include="ReactiveUI" Version="16.2.6" />
|
||||||
<PackageReference Include="ReactiveUI.Fody" Version="14.1.1" />
|
<PackageReference Include="ReactiveUI.Fody" Version="16.2.6" />
|
||||||
<PackageReference Include="ReactiveUI.WPF" Version="14.1.1" />
|
<PackageReference Include="ReactiveUI.WPF" Version="16.2.6" />
|
||||||
<PackageReference Include="Silk.NET.DXGI" Version="2.6.0" />
|
<PackageReference Include="Silk.NET.DXGI" Version="2.6.0" />
|
||||||
<PackageReference Include="WPFThemes.DarkBlend" Version="1.0.8" />
|
<PackageReference Include="WPFThemes.DarkBlend" Version="1.0.8" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -104,4 +104,8 @@
|
|||||||
<SplashScreen Include="Resources\Wabba_Mouth_Small.png" />
|
<SplashScreen Include="Resources\Wabba_Mouth_Small.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Models" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
|
@ -4,8 +4,8 @@ namespace Wabbajack
|
|||||||
{
|
{
|
||||||
public struct ErrorResponse : IErrorResponse
|
public struct ErrorResponse : IErrorResponse
|
||||||
{
|
{
|
||||||
public readonly static ErrorResponse Success = Succeed();
|
public static readonly ErrorResponse Success = Succeed();
|
||||||
public readonly static ErrorResponse Failure = new ErrorResponse();
|
public static readonly ErrorResponse Failure = new ErrorResponse();
|
||||||
|
|
||||||
public bool Succeeded { get; }
|
public bool Succeeded { get; }
|
||||||
public Exception? Exception { get; }
|
public Exception? Exception { get; }
|
74
Wabbajack.Lib/LoadingLock.cs
Normal file
74
Wabbajack.Lib/LoadingLock.cs
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
|
using ReactiveUI;
|
||||||
|
using ReactiveUI.Fody.Helpers;
|
||||||
|
|
||||||
|
namespace Wabbajack.Models;
|
||||||
|
|
||||||
|
public class LoadingLock : ReactiveObject, IDisposable
|
||||||
|
{
|
||||||
|
private readonly CompositeDisposable _disposable;
|
||||||
|
|
||||||
|
public ErrorResponse? ErrorState { get; set; }
|
||||||
|
|
||||||
|
public LoadingLock()
|
||||||
|
{
|
||||||
|
_disposable = new CompositeDisposable();
|
||||||
|
|
||||||
|
this.WhenAnyValue(vm => vm.LoadLevel)
|
||||||
|
.Subscribe(v => IsLoading = v > 0)
|
||||||
|
.DisposeWith(_disposable);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Reactive] public int LoadLevel { get; private set; }
|
||||||
|
|
||||||
|
[Reactive] public bool IsLoading { get; private set; }
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
_disposable.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LockContext WithLoading()
|
||||||
|
{
|
||||||
|
RxApp.MainThreadScheduler.Schedule(0, (_, _) => { LoadLevel++;
|
||||||
|
return Disposable.Empty;
|
||||||
|
});
|
||||||
|
return new LockContext(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LockContext : IDisposable
|
||||||
|
{
|
||||||
|
private readonly LoadingLock _parent;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
public LockContext(LoadingLock parent)
|
||||||
|
{
|
||||||
|
_parent = parent;
|
||||||
|
_disposed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Succeed()
|
||||||
|
{
|
||||||
|
_parent.ErrorState = ErrorResponse.Success;
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fail()
|
||||||
|
{
|
||||||
|
_parent.ErrorState = ErrorResponse.Failure;
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_disposed) return;
|
||||||
|
_disposed = true;
|
||||||
|
|
||||||
|
RxApp.MainThreadScheduler.Schedule(0, (_, _) => { _parent.LoadLevel--;
|
||||||
|
return Disposable.Empty;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,15 +4,18 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using Wabbajack.Models;
|
||||||
|
|
||||||
namespace Wabbajack.Lib
|
namespace Wabbajack.Lib
|
||||||
{
|
{
|
||||||
public class ViewModel : ReactiveObject, IDisposable
|
public class ViewModel : ReactiveObject, IDisposable, IActivatableViewModel
|
||||||
{
|
{
|
||||||
private readonly Lazy<CompositeDisposable> _compositeDisposable = new Lazy<CompositeDisposable>();
|
private readonly Lazy<CompositeDisposable> _compositeDisposable = new();
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public CompositeDisposable CompositeDisposable => _compositeDisposable.Value;
|
public CompositeDisposable CompositeDisposable => _compositeDisposable.Value;
|
||||||
|
|
||||||
|
[JsonIgnore] public LoadingLock LoadingLock { get; } = new();
|
||||||
|
|
||||||
public virtual void Dispose()
|
public virtual void Dispose()
|
||||||
{
|
{
|
||||||
if (_compositeDisposable.IsValueCreated)
|
if (_compositeDisposable.IsValueCreated)
|
||||||
@ -30,5 +33,7 @@ namespace Wabbajack.Lib
|
|||||||
item = newItem;
|
item = newItem;
|
||||||
this.RaisePropertyChanged(propertyName);
|
this.RaisePropertyChanged(propertyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ViewModelActivator Activator { get; } = new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,10 +35,10 @@
|
|||||||
<Version>0.50.0</Version>
|
<Version>0.50.0</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="ReactiveUI">
|
<PackageReference Include="ReactiveUI">
|
||||||
<Version>14.1.1</Version>
|
<Version>16.2.6</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="ReactiveUI.Fody">
|
<PackageReference Include="ReactiveUI.Fody">
|
||||||
<Version>14.1.1</Version>
|
<Version>16.2.6</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="SharpCompress">
|
<PackageReference Include="SharpCompress">
|
||||||
<Version>0.28.3</Version>
|
<Version>0.28.3</Version>
|
||||||
|
Loading…
Reference in New Issue
Block a user