Add (WIP) CreateModListView, other miscellaneous changes

This commit is contained in:
trawzified 2024-04-27 13:50:55 +02:00
parent 1dd4a642ef
commit ee086596fc
19 changed files with 891 additions and 190 deletions

View File

@ -166,12 +166,12 @@ namespace Wabbajack
services.AddSingleton<LauncherUpdater>(); services.AddSingleton<LauncherUpdater>();
services.AddSingleton<ResourceMonitor>(); services.AddSingleton<ResourceMonitor>();
services.AddTransient<CompilerVM>();
services.AddTransient<InstallerVM>();
services.AddTransient<HomeVM>(); services.AddTransient<HomeVM>();
services.AddTransient<ModListGalleryVM>(); services.AddTransient<ModListGalleryVM>();
services.AddTransient<CreateModListVM>();
services.AddTransient<CompilerVM>(); services.AddTransient<CompilerVM>();
services.AddTransient<InstallerVM>(); services.AddTransient<InstallerVM>();
services.AddTransient<InstallerVM>();
services.AddTransient<SettingsVM>(); services.AddTransient<SettingsVM>();
services.AddTransient<WebBrowserVM>(); services.AddTransient<WebBrowserVM>();

View File

@ -8,7 +8,7 @@ public enum ScreenType
ModListGallery, ModListGallery,
Installer, Installer,
Settings, Settings,
Compiler, CreateAList,
ModListContents, ModListContents,
WebBrowser WebBrowser
} }

View File

@ -0,0 +1,74 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;
using DynamicData;
using Microsoft.Extensions.Logging;
using ReactiveUI;
using Wabbajack.Common;
using Wabbajack.Networking.WabbajackClientApi;
using Wabbajack.Services.OSIntegrated;
using Wabbajack.Services.OSIntegrated.Services;
namespace Wabbajack
{
public class CreateModListVM : ViewModel
{
private readonly SettingsManager _settingsManager;
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<CreateModListVM> _logger;
private readonly Client _wjClient;
private readonly ModListDownloadMaintainer _maintainer;
private readonly CancellationToken _cancellationToken;
private readonly SourceCache<CreateModListMetadataVM, string> _modLists = new(x => x.Metadata.NamespacedName);
public ReadOnlyObservableCollection<CreateModListMetadataVM> _filteredModLists;
public ReadOnlyObservableCollection<CreateModListMetadataVM> ModLists => _filteredModLists;
public CreateModListVM(ILogger<CreateModListVM> logger, SettingsManager settingsManager,
IServiceProvider serviceProvider, Client wjClient, ModListDownloadMaintainer maintainer)
{
_logger = logger;
_settingsManager = settingsManager;
_serviceProvider = serviceProvider;
_wjClient = wjClient;
_maintainer = maintainer;
LoadModLists().FireAndForget();
this.WhenActivated(disposables =>
{
_modLists.Connect()
.ObserveOn(RxApp.MainThreadScheduler)
.Bind(out _filteredModLists)
.Subscribe((_) => { })
.DisposeWith(disposables);
});
}
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 CreateModListMetadataVM(_logger, this, m, _maintainer, _wjClient, _cancellationToken)));
});
}
catch (Exception ex)
{
_logger.LogError(ex, "While loading lists");
ll.Fail();
}
ll.Succeed();
}
}
}

View File

@ -1,30 +1,23 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reactive;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Reactive.Subjects; using System.Reactive.Subjects;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using DynamicData;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using ReactiveUI; using ReactiveUI;
using ReactiveUI.Fody.Helpers; using ReactiveUI.Fody.Helpers;
using Wabbajack.Common; using Wabbajack.Common;
using Wabbajack.DTOs; using Wabbajack.DTOs;
using Wabbajack.DTOs.ServerResponses;
using Wabbajack;
using Wabbajack.Extensions;
using Wabbajack.Messages; using Wabbajack.Messages;
using Wabbajack.Models; using Wabbajack.Models;
using Wabbajack.Networking.WabbajackClientApi; using Wabbajack.Networking.WabbajackClientApi;
using Wabbajack.Paths; using Wabbajack.Paths;
using Wabbajack.Paths.IO;
using Wabbajack.RateLimiter; using Wabbajack.RateLimiter;
using Wabbajack.Services.OSIntegrated.Services; using Wabbajack.Services.OSIntegrated.Services;
using System.Windows.Media;
namespace Wabbajack namespace Wabbajack
{ {
@ -39,19 +32,15 @@ namespace Wabbajack
public string Name { get; } public string Name { get; }
} }
public class ModListMetadataVM : ViewModel public class BaseModListMetadataVM : ViewModel
{ {
public ModlistMetadata Metadata { get; } public ModlistMetadata Metadata { get; }
private ModListGalleryVM _parent;
public ICommand OpenWebsiteCommand { get; } public ICommand OpenWebsiteCommand { get; }
public ICommand ExecuteCommand { get; } public ICommand ExecuteCommand { get; }
public ICommand ModListContentsCommend { get; } public ICommand ModListContentsCommend { get; }
private readonly ObservableAsPropertyHelper<bool> _Exists;
public bool Exists => _Exists.Value;
public AbsolutePath Location { get; } public AbsolutePath Location { get; }
public LoadingLock LoadingImageLock { get; } = new(); public LoadingLock LoadingImageLock { get; } = new();
@ -108,11 +97,10 @@ namespace Wabbajack
private readonly Client _wjClient; private readonly Client _wjClient;
private readonly CancellationToken _cancellationToken; private readonly CancellationToken _cancellationToken;
public ModListMetadataVM(ILogger logger, ModListGalleryVM parent, ModlistMetadata metadata, public BaseModListMetadataVM(ILogger logger, ModlistMetadata metadata,
ModListDownloadMaintainer maintainer, Client wjClient, CancellationToken cancellationToken) ModListDownloadMaintainer maintainer, Client wjClient, CancellationToken cancellationToken)
{ {
_logger = logger; _logger = logger;
_parent = parent;
_maintainer = maintainer; _maintainer = maintainer;
Metadata = metadata; Metadata = metadata;
_wjClient = wjClient; _wjClient = wjClient;
@ -162,23 +150,6 @@ namespace Wabbajack
.CombineLatest(this.WhenAnyValue(vm => vm.IsBroken)) .CombineLatest(this.WhenAnyValue(vm => vm.IsBroken))
.Select(v => !v.First && !v.Second)); .Select(v => !v.First && !v.Second));
_Exists = Observable.Interval(TimeSpan.FromSeconds(0.5))
.Unit()
.StartWith(Unit.Default)
.FlowSwitch(_parent.WhenAny(x => x.IsActive))
.SelectAsync(async _ =>
{
try
{
return !IsDownloading && await maintainer.HaveModList(metadata);
}
catch (Exception)
{
return true;
}
})
.ToGuiProperty(this, nameof(Exists));
var modlistImageSource = Metadata.ValidationSummary?.SmallImage?.ToString() ?? Metadata.Links.ImageUri; var modlistImageSource = Metadata.ValidationSummary?.SmallImage?.ToString() ?? Metadata.Links.ImageUri;
var imageObs = Observable.Return(modlistImageSource) var imageObs = Observable.Return(modlistImageSource)
.DownloadBitmapImage((ex) => _logger.LogError("Error downloading modlist image {Title} from {ImageUri}: {Exception}", Metadata.Title, modlistImageSource, ex.Message), LoadingImageLock); .DownloadBitmapImage((ex) => _logger.LogError("Error downloading modlist image {Title} from {ImageUri}: {Exception}", Metadata.Title, modlistImageSource, ex.Message), LoadingImageLock);
@ -194,7 +165,7 @@ namespace Wabbajack
private async Task Download() protected async Task Download()
{ {
try try
{ {
@ -222,7 +193,7 @@ namespace Wabbajack
} }
} }
private async Task UpdateStatus() protected async Task UpdateStatus()
{ {
if (await _maintainer.HaveModList(Metadata)) if (await _maintainer.HaveModList(Metadata))
Status = ModListStatus.Downloaded; Status = ModListStatus.Downloaded;

View File

@ -0,0 +1,25 @@
using System.Linq;
using System.Threading;
using Microsoft.Extensions.Logging;
using ReactiveUI.Fody.Helpers;
using Wabbajack.Compiler;
using Wabbajack.DTOs;
using Wabbajack.Networking.WabbajackClientApi;
using Wabbajack.Services.OSIntegrated.Services;
namespace Wabbajack
{
public class CreateModListMetadataVM : BaseModListMetadataVM
{
private CreateModListVM _parent;
[Reactive]
public CompilerSettings CompilerSettings { get; set; }
public CreateModListMetadataVM(ILogger logger, CreateModListVM parent, ModlistMetadata metadata,
ModListDownloadMaintainer maintainer, Client wjClient, CancellationToken cancellationToken) : base(logger, metadata, maintainer, wjClient, cancellationToken)
{
_parent = parent;
CompilerSettings = _parent.ModLists.FirstOrDefault(ml => ml.Metadata.Links.MachineURL == wjClient.GetMyModlists());
}
}
}

View File

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using DynamicData;
using Microsoft.Extensions.Logging;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Wabbajack.Common;
using Wabbajack.DTOs;
using Wabbajack.DTOs.ServerResponses;
using Wabbajack;
using Wabbajack.Extensions;
using Wabbajack.Messages;
using Wabbajack.Models;
using Wabbajack.Networking.WabbajackClientApi;
using Wabbajack.Paths;
using Wabbajack.Paths.IO;
using Wabbajack.RateLimiter;
using Wabbajack.Services.OSIntegrated.Services;
using System.Windows.Media;
namespace Wabbajack
{
public class GalleryModListMetadataVM : BaseModListMetadataVM
{
private ModListGalleryVM _parent;
private readonly ObservableAsPropertyHelper<bool> _Exists;
public bool Exists => _Exists.Value;
public GalleryModListMetadataVM(ILogger logger, ModListGalleryVM parent, ModlistMetadata metadata,
ModListDownloadMaintainer maintainer, Client wjClient, CancellationToken cancellationToken) : base(logger, metadata, maintainer, wjClient, cancellationToken)
{
_parent = parent;
_Exists = Observable.Interval(TimeSpan.FromSeconds(0.5))
.Unit()
.StartWith(Unit.Default)
.FlowSwitch(_parent.WhenAny(x => x.IsActive))
.SelectAsync(async _ =>
{
try
{
return !IsDownloading && await maintainer.HaveModList(metadata);
}
catch (Exception)
{
return true;
}
})
.ToGuiProperty(this, nameof(Exists));
}
}
}

View File

@ -1,6 +1,4 @@
 using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
@ -28,10 +26,10 @@ namespace Wabbajack
{ {
public MainWindowVM MWVM { get; } public MainWindowVM MWVM { get; }
private readonly SourceCache<ModListMetadataVM, string> _modLists = new(x => x.Metadata.NamespacedName); private readonly SourceCache<GalleryModListMetadataVM, string> _modLists = new(x => x.Metadata.NamespacedName);
public ReadOnlyObservableCollection<ModListMetadataVM> _filteredModLists; public ReadOnlyObservableCollection<GalleryModListMetadataVM> _filteredModLists;
public ReadOnlyObservableCollection<ModListMetadataVM> ModLists => _filteredModLists; public ReadOnlyObservableCollection<GalleryModListMetadataVM> ModLists => _filteredModLists;
private const string ALL_GAME_IDENTIFIER = "All games"; private const string ALL_GAME_IDENTIFIER = "All games";
@ -49,8 +47,8 @@ namespace Wabbajack
[Reactive] public double MinModlistSize { get; set; } [Reactive] public double MinModlistSize { get; set; }
[Reactive] public double MaxModlistSize { get; set; } [Reactive] public double MaxModlistSize { get; set; }
[Reactive] public ModListMetadataVM SmallestSizedModlist { get; set; } [Reactive] public GalleryModListMetadataVM SmallestSizedModlist { get; set; }
[Reactive] public ModListMetadataVM LargestSizedModlist { get; set; } [Reactive] public GalleryModListMetadataVM LargestSizedModlist { get; set; }
public class GameTypeEntry public class GameTypeEntry
{ {
@ -134,7 +132,7 @@ namespace Wabbajack
.Throttle(searchThrottle, RxApp.MainThreadScheduler) .Throttle(searchThrottle, RxApp.MainThreadScheduler)
.Select(change => change.Value.Trim()) .Select(change => change.Value.Trim())
.StartWith(Search) .StartWith(Search)
.Select<string, Func<ModListMetadataVM, bool>>(txt => .Select<string, Func<GalleryModListMetadataVM, bool>>(txt =>
{ {
if (string.IsNullOrWhiteSpace(txt)) return _ => true; if (string.IsNullOrWhiteSpace(txt)) return _ => true;
return item => item.Metadata.Title.ContainsCaseInsensitive(txt) || return item => item.Metadata.Title.ContainsCaseInsensitive(txt) ||
@ -144,7 +142,7 @@ namespace Wabbajack
var onlyInstalledGamesFilter = this.ObservableForProperty(vm => vm.OnlyInstalled) var onlyInstalledGamesFilter = this.ObservableForProperty(vm => vm.OnlyInstalled)
.Select(v => v.Value) .Select(v => v.Value)
.Select<bool, Func<ModListMetadataVM, bool>>(onlyInstalled => .Select<bool, Func<GalleryModListMetadataVM, bool>>(onlyInstalled =>
{ {
if (onlyInstalled == false) return _ => true; if (onlyInstalled == false) return _ => true;
return item => _locator.IsInstalled(item.Metadata.Game); return item => _locator.IsInstalled(item.Metadata.Game);
@ -154,7 +152,7 @@ namespace Wabbajack
var showUnofficial = this.ObservableForProperty(vm => vm.ShowUnofficialLists) var showUnofficial = this.ObservableForProperty(vm => vm.ShowUnofficialLists)
.Select(v => v.Value) .Select(v => v.Value)
.StartWith(false) .StartWith(false)
.Select<bool, Func<ModListMetadataVM, bool>>(unoffical => .Select<bool, Func<GalleryModListMetadataVM, bool>>(unoffical =>
{ {
if (unoffical) return x => true; if (unoffical) return x => true;
return x => x.Metadata.Official; return x => x.Metadata.Official;
@ -162,12 +160,12 @@ namespace Wabbajack
var showNSFWFilter = this.ObservableForProperty(vm => vm.ShowNSFW) var showNSFWFilter = this.ObservableForProperty(vm => vm.ShowNSFW)
.Select(v => v.Value) .Select(v => v.Value)
.Select<bool, Func<ModListMetadataVM, bool>>(showNsfw => { return item => item.Metadata.NSFW == showNsfw; }) .Select<bool, Func<GalleryModListMetadataVM, bool>>(showNsfw => { return item => item.Metadata.NSFW == showNsfw; })
.StartWith(item => item.Metadata.NSFW == false); .StartWith(item => item.Metadata.NSFW == false);
var gameFilter = this.ObservableForProperty(vm => vm.GameType) var gameFilter = this.ObservableForProperty(vm => vm.GameType)
.Select(v => v.Value) .Select(v => v.Value)
.Select<string, Func<ModListMetadataVM, bool>>(selected => .Select<string, Func<GalleryModListMetadataVM, bool>>(selected =>
{ {
_filteringOnGame = true; _filteringOnGame = true;
if (selected is null or ALL_GAME_IDENTIFIER) return _ => true; if (selected is null or ALL_GAME_IDENTIFIER) return _ => true;
@ -178,7 +176,7 @@ namespace Wabbajack
var minModlistSizeFilter = this.ObservableForProperty(vm => vm.MinModlistSize) var minModlistSizeFilter = this.ObservableForProperty(vm => vm.MinModlistSize)
.Throttle(TimeSpan.FromSeconds(0.05), RxApp.MainThreadScheduler) .Throttle(TimeSpan.FromSeconds(0.05), RxApp.MainThreadScheduler)
.Select(v => v.Value) .Select(v => v.Value)
.Select<double, Func<ModListMetadataVM, bool>>(minModlistSize => .Select<double, Func<GalleryModListMetadataVM, bool>>(minModlistSize =>
{ {
return item => item.Metadata.DownloadMetadata.TotalSize >= minModlistSize; return item => item.Metadata.DownloadMetadata.TotalSize >= minModlistSize;
}); });
@ -186,7 +184,7 @@ namespace Wabbajack
var maxModlistSizeFilter = this.ObservableForProperty(vm => vm.MaxModlistSize) var maxModlistSizeFilter = this.ObservableForProperty(vm => vm.MaxModlistSize)
.Throttle(TimeSpan.FromSeconds(0.05), RxApp.MainThreadScheduler) .Throttle(TimeSpan.FromSeconds(0.05), RxApp.MainThreadScheduler)
.Select(v => v.Value) .Select(v => v.Value)
.Select<double, Func<ModListMetadataVM, bool>>(maxModlistSize => .Select<double, Func<GalleryModListMetadataVM, bool>>(maxModlistSize =>
{ {
return item => item.Metadata.DownloadMetadata.TotalSize <= maxModlistSize; return item => item.Metadata.DownloadMetadata.TotalSize <= maxModlistSize;
}); });
@ -194,7 +192,7 @@ namespace Wabbajack
var searchSorter = this.WhenValueChanged(vm => vm.Search) var searchSorter = this.WhenValueChanged(vm => vm.Search)
.Throttle(searchThrottle, RxApp.MainThreadScheduler) .Throttle(searchThrottle, RxApp.MainThreadScheduler)
.Select(s => SortExpressionComparer<ModListMetadataVM> .Select(s => SortExpressionComparer<GalleryModListMetadataVM>
.Descending(m => m.Metadata.Title.StartsWith(s, StringComparison.InvariantCultureIgnoreCase)) .Descending(m => m.Metadata.Title.StartsWith(s, StringComparison.InvariantCultureIgnoreCase))
.ThenByDescending(m => m.Metadata.Title.Contains(s, StringComparison.InvariantCultureIgnoreCase)) .ThenByDescending(m => m.Metadata.Title.Contains(s, StringComparison.InvariantCultureIgnoreCase))
.ThenByDescending(m => !m.IsBroken)); .ThenByDescending(m => !m.IsBroken));
@ -278,7 +276,7 @@ namespace Wabbajack
{ {
e.Clear(); e.Clear();
e.AddOrUpdate(modLists.Select(m => e.AddOrUpdate(modLists.Select(m =>
new ModListMetadataVM(_logger, this, m, _maintainer, _wjClient, _cancellationToken))); new GalleryModListMetadataVM(_logger, this, m, _maintainer, _wjClient, _cancellationToken)));
}); });
SmallestSizedModlist = _modLists.Items.Any() ? _modLists.Items.MinBy(ml => ml.Metadata.DownloadMetadata.TotalSize) : null; SmallestSizedModlist = _modLists.Items.Any() ? _modLists.Items.MinBy(ml => ml.Metadata.DownloadMetadata.TotalSize) : null;
LargestSizedModlist = _modLists.Items.Any() ? _modLists.Items.MaxBy(ml => ml.Metadata.DownloadMetadata.TotalSize) : null; LargestSizedModlist = _modLists.Items.Any() ? _modLists.Items.MaxBy(ml => ml.Metadata.DownloadMetadata.TotalSize) : null;

View File

@ -24,7 +24,6 @@ namespace Wabbajack
{ {
private readonly ILogger<HomeVM> _logger; private readonly ILogger<HomeVM> _logger;
private readonly Client _wjClient; private readonly Client _wjClient;
private readonly SourceCache<ModListMetadataVM, string> _modLists = new(x => x.Metadata.NamespacedName);
public HomeVM(ILogger<HomeVM> logger, Client wjClient) public HomeVM(ILogger<HomeVM> logger, Client wjClient)
{ {

View File

@ -44,10 +44,10 @@ namespace Wabbajack
public ObservableCollectionExtended<IStatusMessage> Log { get; } = new ObservableCollectionExtended<IStatusMessage>(); public ObservableCollectionExtended<IStatusMessage> Log { get; } = new ObservableCollectionExtended<IStatusMessage>();
public readonly CompilerVM Compiler; public readonly CreateModListVM CreateAListVM;
public readonly InstallerVM Installer; public readonly InstallerVM InstallerVM;
public readonly SettingsVM SettingsPane; public readonly SettingsVM SettingsPaneVM;
public readonly ModListGalleryVM Gallery; public readonly ModListGalleryVM GalleryVM;
public readonly HomeVM HomeVM; public readonly HomeVM HomeVM;
public readonly WebBrowserVM WebBrowserVM; public readonly WebBrowserVM WebBrowserVM;
public readonly Lazy<ModListContentsVM> ModListContentsVM; public readonly Lazy<ModListContentsVM> ModListContentsVM;
@ -78,17 +78,17 @@ namespace Wabbajack
public MainWindowVM(ILogger<MainWindowVM> logger, Client wjClient, public MainWindowVM(ILogger<MainWindowVM> logger, Client wjClient,
IServiceProvider serviceProvider, HomeVM homeVM, ModListGalleryVM modListGalleryVM, ResourceMonitor resourceMonitor, IServiceProvider serviceProvider, HomeVM homeVM, ModListGalleryVM modListGalleryVM, ResourceMonitor resourceMonitor,
InstallerVM installer, CompilerVM compilerVM, SettingsVM settingsVM, WebBrowserVM webBrowserVM, NavigationVM navigationVM) InstallerVM installer, CreateModListVM createAListVM, SettingsVM settingsVM, WebBrowserVM webBrowserVM, NavigationVM navigationVM)
{ {
_logger = logger; _logger = logger;
_wjClient = wjClient; _wjClient = wjClient;
_resourceMonitor = resourceMonitor; _resourceMonitor = resourceMonitor;
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
ConverterRegistration.Register(); ConverterRegistration.Register();
Installer = installer; InstallerVM = installer;
Compiler = compilerVM; CreateAListVM = createAListVM;
SettingsPane = settingsVM; SettingsPaneVM = settingsVM;
Gallery = modListGalleryVM; GalleryVM = modListGalleryVM;
HomeVM = homeVM; HomeVM = homeVM;
WebBrowserVM = webBrowserVM; WebBrowserVM = webBrowserVM;
NavigationVM = navigationVM; NavigationVM = navigationVM;
@ -231,10 +231,10 @@ namespace Wabbajack
ActivePane = s switch ActivePane = s switch
{ {
ScreenType.Home => HomeVM, ScreenType.Home => HomeVM,
ScreenType.ModListGallery => Gallery, ScreenType.ModListGallery => GalleryVM,
ScreenType.Installer => Installer, ScreenType.Installer => InstallerVM,
ScreenType.Compiler => Compiler, ScreenType.CreateAList => CreateAListVM,
ScreenType.Settings => SettingsPane, ScreenType.Settings => SettingsPaneVM,
_ => ActivePane _ => ActivePane
}; };
} }
@ -263,7 +263,7 @@ namespace Wabbajack
var cancellationTokenSource = _serviceProvider.GetRequiredService<CancellationTokenSource>(); var cancellationTokenSource = _serviceProvider.GetRequiredService<CancellationTokenSource>();
cancellationTokenSource.Cancel(); cancellationTokenSource.Cancel();
bool IsInstalling() => Installer.InstallState is InstallState.Installing; bool IsInstalling() => InstallerVM.InstallState is InstallState.Installing;
while (DateTime.Now < endTime && IsInstalling()) while (DateTime.Now < endTime && IsInstalling())
{ {

View File

@ -37,7 +37,7 @@ namespace Wabbajack
LoadLastLoadedModlist.Send(); LoadLastLoadedModlist.Send();
NavigateToGlobal.Send(ScreenType.Installer); NavigateToGlobal.Send(ScreenType.Installer);
}); });
CompileCommand = ReactiveCommand.Create(() => NavigateToGlobal.Send(ScreenType.Compiler)); CreateAListCommand = ReactiveCommand.Create(() => NavigateToGlobal.Send(ScreenType.CreateAList));
SettingsCommand = ReactiveCommand.Create( SettingsCommand = ReactiveCommand.Create(
/* /*
canExecute: this.WhenAny(x => x.ActivePane) canExecute: this.WhenAny(x => x.ActivePane)
@ -58,7 +58,7 @@ namespace Wabbajack
public ICommand HomeCommand { get; } public ICommand HomeCommand { get; }
public ICommand BrowseCommand { get; } public ICommand BrowseCommand { get; }
public ICommand InstallCommand { get; } public ICommand InstallCommand { get; }
public ICommand CompileCommand { get; } public ICommand CreateAListCommand { get; }
public ICommand SettingsCommand { get; } public ICommand SettingsCommand { get; }
public string Version { get; } public string Version { get; }
} }

View File

@ -0,0 +1,131 @@
<rxui:ReactiveUserControl
x:Class="Wabbajack.CreateModListView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lib="clr-namespace:Wabbajack;assembly=Wabbajack"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:icon="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:local="clr-namespace:Wabbajack"
xmlns:mahapps="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:rxui="http://reactiveui.net"
xmlns:wabbacommon="clr-namespace:Wabbajack.Common;assembly=Wabbajack.Common"
xmlns:controls1="clr-namespace:Wabbajack.ViewModels.Controls"
xmlns:ic="clr-namespace:FluentIcons.WPF;assembly=FluentIcons.WPF"
d:DataContext="{d:DesignInstance local:CreateModListVM}"
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="local:CreateModListVM"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="3*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderBrush="{StaticResource PrimaryVariantBrush}" CornerRadius="8" BorderThickness="19" Margin="0, 0, 20, 20">
<Grid Background="{StaticResource PrimaryVariantBrush}" Margin="-1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock
Grid.Column="0"
Grid.Row="0"
Text="Compile a new list"
FontWeight="DemiBold"
FontSize="28"
/>
<ic:SymbolIcon
Grid.Row="0"
Grid.Column="1"
VerticalAlignment="Top"
Symbol="AppsAddIn"
IsFilled="True"
FontSize="28"
/>
<TextBlock Grid.Column="0" Grid.Row="1" Grid.RowSpan="2" LineHeight="24" FontSize="14" VerticalAlignment="Bottom">
Import the modlist.txt file to set up a new modlist export
</TextBlock>
</Grid>
</Border>
<Border Grid.Column="1" BorderBrush="{StaticResource PrimaryVariantBrush}" CornerRadius="8" BorderThickness="19" Margin="0, 0, 20, 20">
<Grid Background="{StaticResource PrimaryVariantBrush}" Margin="-1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock
Grid.Column="0"
Grid.Row="0"
Text="Load compile settings"
FontWeight="DemiBold"
FontSize="28"
/>
<ic:SymbolIcon
Grid.Row="0"
Grid.Column="1"
VerticalAlignment="Top"
Symbol="AppsAddIn"
IsFilled="True"
FontSize="28"
/>
<TextBlock Grid.Column="0" Grid.Row="1" Grid.RowSpan="2" LineHeight="24" FontSize="14" VerticalAlignment="Bottom">
Continue the export of an existing modlist or push an update
</TextBlock>
</Grid>
</Border>
</Grid>
<Grid Grid.Row="1" Margin="0, 10, 0, 10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="6*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="1" Background="{StaticResource DarkSecondaryBrush}" BorderBrush="{StaticResource DarkSecondaryBrush}" BorderThickness="2" CornerRadius="4" Margin="0, 10, 0, 10" />
</Grid>
<Grid Grid.Row="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<TextBlock LineHeight="24" FontSize="24" VerticalAlignment="Top" HorizontalAlignment="Center" FontWeight="Bold" Margin="0, 0, 0, 20">
Recently Compiled Modlists
</TextBlock>
<ScrollViewer Grid.Row="1" Background="Green" VerticalScrollBarVisibility="Auto">
<ItemsControl
x:Name="CreatedModListsControl"
HorizontalAlignment="Center"
ScrollViewer.VerticalScrollBarVisibility="Visible">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:CreateModListTileView ViewModel="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Grid>
</rxui:ReactiveUserControl>

View File

@ -0,0 +1,38 @@
using System;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Windows.Controls;
using ReactiveUI;
using System.Windows;
using System.Windows.Forms;
using DynamicData;
using Microsoft.WindowsAPICodePack.Dialogs;
using Wabbajack.Common;
using Wabbajack.Paths;
using Wabbajack.Paths.IO;
using Wabbajack.ViewModels.Controls;
namespace Wabbajack
{
/// <summary>
/// Interaction logic for CreateAListView.xaml
/// </summary>
public partial class CreateModListView : ReactiveUserControl<CreateModListVM>
{
public CreateModListView()
{
InitializeComponent();
this.WhenActivated(dispose =>
{
this.WhenAny(x => x.ViewModel.ModLists)
.BindToStrict(this, x => x.CreatedModListsControl.ItemsSource)
.DisposeWith(dispose);
});
}
}
}

View File

@ -0,0 +1,476 @@
<rxui:ReactiveUserControl
x:Class="Wabbajack.CreateModListTileView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:local="clr-namespace:Wabbajack"
xmlns:mahapps="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:rxui="http://reactiveui.net"
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="local:CreateModListMetadataVM"
mc:Ignorable="d">
<UserControl.Resources>
<Color x:Key="TextBackgroundFill">#92000000</Color>
<SolidColorBrush x:Key="TextBackgroundFillBrush" Color="{StaticResource TextBackgroundFill}" />
<Color x:Key="TextBackgroundHoverFill">#DF000000</Color>
<Style x:Key="BackgroundBlurStyle" TargetType="TextBlock">
<Setter Property="Background" Value="{StaticResource TextBackgroundFillBrush}" />
<Setter Property="Foreground" Value="Transparent" />
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(TextBlock.Background).(SolidColorBrush.Color)"
To="{StaticResource TextBackgroundHoverFill}"
Duration="0:0:0.06" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(TextBlock.Background).(SolidColorBrush.Color)"
To="{StaticResource TextBackgroundFill}"
Duration="0:0:0.06" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Border BorderThickness="0" CornerRadius="6" Background="{StaticResource DarkPrimaryBrush}" Margin="10, 0, 10, 20">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border
x:Name="CompiledModListTile"
Margin="10, 0, 10, 16"
Background="Transparent"
BorderThickness="0">
<Border.Effect>
<DropShadowEffect
BlurRadius="25"
Opacity="0.25"
ShadowDepth="3" />
</Border.Effect>
<Border.Style>
<Style TargetType="Border">
<Setter Property="BorderBrush" Value="{StaticResource ButtonBorder}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=CompiledModListTile}" Value="True">
<Setter Property="BorderBrush" Value="{StaticResource BorderInterestBrush}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid>
<Border x:Name="MaskBorder" BorderThickness="0" BorderBrush="Transparent" Background="{StaticResource DarkSecondaryBrush}" CornerRadius="10" Width="300" Height="169"/>
<Grid
Width="300"
Height="169"
Background="Transparent" ClipToBounds="True">
<Grid.OpacityMask>
<VisualBrush Visual="{Binding ElementName=MaskBorder}"/>
</Grid.OpacityMask>
<Grid ClipToBounds="True">
<mahapps:ProgressRing x:Name="LoadingProgress" />
<StackPanel Orientation="Horizontal" Margin="5, 5, 0, 0" VerticalAlignment="Top" HorizontalAlignment="Left" Panel.ZIndex="1">
<Border x:Name="GameIcon" Width="24" Height="24" CornerRadius="6">
<Border.Background>
<ImageBrush Stretch="Fill" ImageSource="{Binding GameMetaData.IconSource}"/>
</Border.Background>
</Border>
<Grid Margin="5, 0, 0, 0"
Visibility="{Binding ElementName=CompiledModListTile, Path=IsMouseOver, Converter={StaticResource bool2VisibilityConverter}}">
<TextBlock x:Name="GameName"
Text="{Binding GameMetaData.HumanFriendlyGameName}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Opacity="0.85"
Panel.ZIndex="2"/>
<Border Background="{StaticResource WindowBackgroundBrush}" Opacity="0.4" Width="{Binding ElementName=GameName, Path=ActualWidth,Converter={StaticResource MathConverter}, ConverterParameter=x+10}" Height="{Binding ElementName=GameIcon, Path=ActualHeight}" CornerRadius="6">
</Border>
</Grid>
</StackPanel>
<Border
BorderThickness="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Border.Background>
<ImageBrush x:Name="ModlistImage" Stretch="UniformToFill"/>
</Border.Background>
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<DataTrigger Binding="{Binding IsBroken}" Value="True">
<Setter Property="Effect">
<Setter.Value>
<BlurEffect Radius="35" />
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
<Rectangle
Height="120"
Margin="-80, -75, -80, 0"
VerticalAlignment="Top"
Fill="White"
Opacity="0.15">
<Rectangle.Effect>
<BlurEffect Radius="100" />
</Rectangle.Effect>
<Rectangle.Style>
<Style TargetType="Rectangle">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=CompiledModListTile}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="0.3"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="0.15"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
<Rectangle
Height="120"
Margin="-80, 0, -80, -75"
VerticalAlignment="Bottom"
Fill="Black"
Opacity="0.4">
<Rectangle.Effect>
<BlurEffect Radius="100" />
</Rectangle.Effect>
<Rectangle.Style>
<Style TargetType="Rectangle">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=CompiledModListTile}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="0.7"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="0.4"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
<Label
Margin="10,242,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Content="{Binding VersionText}"
Opacity="0">
<Label.Style>
<Style TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=CompiledModListTile}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
<Label
Margin="10,257,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Content="{Binding DownloadSizeText}"
Opacity="0">
<Label.Style>
<Style TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=CompiledModListTile}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
<Label
Margin="10,272,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Content="{Binding InstallSizeText}"
Opacity="0">
<Label.Style>
<Style TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=CompiledModListTile}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
<Label
Margin="10,287,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Content="{Binding TotalSizeRequirementText}"
Opacity="0">
<Label.Style>
<Style TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=CompiledModListTile}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</Grid>
<local:UnderMaintenanceOverlay Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
x:Name="Overlay"
Visibility="Collapsed"
ClipToBounds="True" />
<!--
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
x:Name="ModListTitleShadow"
Margin="5"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
FontFamily="{StaticResource PrimaryFont}"
FontSize="30"
FontWeight="Bold"
Style="{StaticResource BackgroundBlurStyle}"
TextWrapping="Wrap">
<TextBlock.Effect>
<BlurEffect Radius="25" />
</TextBlock.Effect>
</TextBlock>
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
x:Name="ModListTitle"
Margin="5"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
FontFamily="{StaticResource PrimaryFont}"
FontSize="30"
FontWeight="Bold"
TextWrapping="Wrap">
<TextBlock.Effect>
<DropShadowEffect />
</TextBlock.Effect>
</TextBlock>
<mahapps:MetroProgressBar Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
x:Name="DownloadProgressBar"
Height="3"
VerticalAlignment="Bottom"
Background="{StaticResource BackgroundBrush}"
Foreground="{StaticResource SecondaryBrush}"
Maximum="1"
Visibility="{Binding IsEnabled, ElementName=ExecuteButton, Converter={StaticResource bool2VisibilityHiddenConverter}, ConverterParameter=False}" />
<ScrollViewer Grid.Row="1" Grid.Column="0" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<TextBlock
x:Name="MetadataDescription"
Margin="8,5"
VerticalAlignment="Center"
FontSize="14"
TextWrapping="Wrap" />
</ScrollViewer>
<ItemsControl Grid.Row="2" Name="TagsList">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Grid.Row="0" Grid.ColumnSpan="2"
Margin="5,5,0,5"
Background="{StaticResource Analogous1Brush}"
BorderThickness="1"
CornerRadius="7,7,7,7"
VerticalAlignment="Center"
Opacity="0.90">
<TextBlock
Margin="5,5,5,5"
FontSize="15"
Text="{Binding Name}" />
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Grid Grid.Row="1" Grid.Column="1" Grid.RowSpan="2">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Grid.Row="0"
x:Name="OpenWebsiteButton"
Width="40"
Height="40"
Margin="5,0"
VerticalAlignment="Center"
Style="{StaticResource IconBareButtonStyle}"
ToolTip="View modlist website in browser">
<iconPacks:Material
Width="20"
Height="20"
Kind="Web" />
</Button>
<Button Grid.Row="1"
x:Name="ModListContentsButton"
Width="40"
Height="40"
Margin="5,0"
VerticalAlignment="Center"
Style="{StaticResource IconBareButtonStyle}"
ToolTip="View modlist archives in browser">
<iconPacks:Material
Width="20"
Height="20"
Kind="TableSearch" />
</Button>
<Button Grid.Row="2"
x:Name="ExecuteButton"
Width="40"
Height="40"
Margin="5,0"
VerticalAlignment="Center"
ToolTip="Download modlist">
<StackPanel x:Name="IconContainer">
<iconPacks:Material
x:Name="ErrorIcon"
Width="20"
Height="20"
Kind="Exclamation" />
</StackPanel>
</Button>
</Grid>
-->
</Grid>
</Grid>
</Border>
<TextBlock
Text="{Binding Metadata.Title}"
FontSize="16"
VerticalAlignment="Bottom"
Margin="10, 0, 0, 10"
Panel.ZIndex="1">
</TextBlock>
</Grid>
</Border>
</rxui:ReactiveUserControl>

View File

@ -0,0 +1,35 @@
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Windows;
using ReactiveUI;
namespace Wabbajack
{
/// <summary>
/// Interaction logic for CreateModListTileView.xaml
/// </summary>
public partial class CreateModListTileView : ReactiveUserControl<CreateModListMetadataVM>
{
public CreateModListTileView()
{
InitializeComponent();
this.WhenActivated(disposables =>
{
ViewModel.WhenAnyValue(vm => vm.Image)
.BindToStrict(this, v => v.ModlistImage.ImageSource)
.DisposeWith(disposables);
var textXformed = ViewModel.WhenAnyValue(vm => vm.Metadata.Title)
.CombineLatest(ViewModel.WhenAnyValue(vm => vm.Metadata.ImageContainsTitle),
ViewModel.WhenAnyValue(vm => vm.IsBroken))
.Select(x => x.Second && !x.Third ? "" : x.First);
ViewModel.WhenAnyValue(x => x.LoadingImageLock.IsLoading)
.Select(x => x ? Visibility.Visible : Visibility.Collapsed)
.BindToStrict(this, x => x.LoadingProgress.Visibility)
.DisposeWith(disposables);
});
}
}
}

View File

@ -12,7 +12,7 @@
d:DesignWidth="1000" d:DesignWidth="1000"
x:TypeArguments="local:HomeVM" x:TypeArguments="local:HomeVM"
mc:Ignorable="d"> mc:Ignorable="d">
<Grid Grid.Row="0" Grid.Column="0" VerticalAlignment="Stretch"> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
@ -47,7 +47,7 @@
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Border Grid.Row="0" Grid.Column="0" BorderBrush="{StaticResource PrimaryVariantBrush}" CornerRadius="8" BorderThickness="19" Margin="0, 0, 20, 20"> <Border Grid.Row="0" Grid.Column="0" BorderBrush="{StaticResource PrimaryVariantBrush}" CornerRadius="8" BorderThickness="19" Margin="0, 0, 20, 20">
<Grid Grid.Row="0" Grid.Column="0" Background="{StaticResource PrimaryVariantBrush}" Margin="-1"> <Grid Background="{StaticResource PrimaryVariantBrush}" Margin="-1">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
@ -78,7 +78,7 @@
</Grid> </Grid>
</Border> </Border>
<Border Grid.Row="0" Grid.Column="2" BorderBrush="{StaticResource PrimaryVariantBrush}" CornerRadius="8" BorderThickness="19" Margin="0, 0, 0, 20"> <Border Grid.Row="0" Grid.Column="2" BorderBrush="{StaticResource PrimaryVariantBrush}" CornerRadius="8" BorderThickness="19" Margin="0, 0, 0, 20">
<Grid Grid.Row="0" Grid.Column="0" Background="{StaticResource PrimaryVariantBrush}" Margin="-1"> <Grid Background="{StaticResource PrimaryVariantBrush}" Margin="-1">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
@ -109,7 +109,7 @@
</Grid> </Grid>
</Border> </Border>
<Border Grid.Row="2" Grid.Column="0" BorderBrush="{StaticResource PrimaryVariantBrush}" CornerRadius="8" BorderThickness="19" Margin="0, 0, 20, 0"> <Border Grid.Row="2" Grid.Column="0" BorderBrush="{StaticResource PrimaryVariantBrush}" CornerRadius="8" BorderThickness="19" Margin="0, 0, 20, 0">
<Grid Grid.Row="0" Grid.Column="0" Background="{StaticResource PrimaryVariantBrush}" Margin="-1"> <Grid Background="{StaticResource PrimaryVariantBrush}" Margin="-1">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
@ -140,7 +140,7 @@
</Grid> </Grid>
</Border> </Border>
<Border Grid.Row="2" Grid.Column="2" BorderBrush="{StaticResource PrimaryVariantBrush}" CornerRadius="8" BorderThickness="19"> <Border Grid.Row="2" Grid.Column="2" BorderBrush="{StaticResource PrimaryVariantBrush}" CornerRadius="8" BorderThickness="19">
<Grid Grid.Row="0" Grid.Column="0" Background="{StaticResource PrimaryVariantBrush}" Margin="-1"> <Grid Background="{StaticResource PrimaryVariantBrush}" Margin="-1">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />

View File

@ -67,9 +67,14 @@
<Border Grid.Column="1" Margin="0" Background="{StaticResource ComplementaryBackgroundBrush}" x:Name="MainContent" Padding="18" CornerRadius="8"> <Border Grid.Column="1" Margin="0" Background="{StaticResource ComplementaryBackgroundBrush}" x:Name="MainContent" Padding="18" CornerRadius="8">
<ContentPresenter Content="{Binding ActivePane}" VerticalAlignment="Stretch"> <ContentPresenter Content="{Binding ActivePane}" VerticalAlignment="Stretch">
<ContentPresenter.Resources> <ContentPresenter.Resources>
<!--
<DataTemplate DataType="{x:Type local:CompilerVM}"> <DataTemplate DataType="{x:Type local:CompilerVM}">
<local:CompilerView ViewModel="{Binding}" /> <local:CompilerView ViewModel="{Binding}" />
</DataTemplate> </DataTemplate>
-->
<DataTemplate DataType="{x:Type local:CreateModListVM}">
<local:CreateModListView ViewModel="{Binding}" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:InstallerVM}"> <DataTemplate DataType="{x:Type local:InstallerVM}">
<local:InstallationView ViewModel="{Binding}" /> <local:InstallationView ViewModel="{Binding}" />
</DataTemplate> </DataTemplate>

View File

@ -10,7 +10,7 @@
xmlns:rxui="http://reactiveui.net" xmlns:rxui="http://reactiveui.net"
d:DesignHeight="450" d:DesignHeight="450"
d:DesignWidth="800" d:DesignWidth="800"
x:TypeArguments="local:ModListMetadataVM" x:TypeArguments="local:GalleryModListMetadataVM"
mc:Ignorable="d"> mc:Ignorable="d">
<UserControl.Resources> <UserControl.Resources>
<Color x:Key="TextBackgroundFill">#92000000</Color> <Color x:Key="TextBackgroundFill">#92000000</Color>

View File

@ -14,7 +14,7 @@ namespace Wabbajack
/// <summary> /// <summary>
/// Interaction logic for ModListTileView.xaml /// Interaction logic for ModListTileView.xaml
/// </summary> /// </summary>
public partial class ModListTileView : ReactiveUserControl<ModListMetadataVM> public partial class ModListTileView : ReactiveUserControl<GalleryModListMetadataVM>
{ {
public ModListTileView() public ModListTileView()
{ {
@ -24,55 +24,12 @@ namespace Wabbajack
ViewModel.WhenAnyValue(vm => vm.Image) ViewModel.WhenAnyValue(vm => vm.Image)
.BindToStrict(this, v => v.ModlistImage.ImageSource) .BindToStrict(this, v => v.ModlistImage.ImageSource)
.DisposeWith(disposables); .DisposeWith(disposables);
/*
this.WhenAny(x => x.ViewModel.Metadata.Links.ImageUri)
.Select(x => new BitmapImage() { UriSource = new Uri(x) })
.BindToStrict(this, v => v.ModlistImage.ImageSource)
.DisposeWith(disposables);
*/
/*
ViewModel.WhenAnyValue(x => x.Metadata.Links.ImageUri)
.Select(x => {
var img = new BitmapImage();
img.BeginInit();
img.CacheOption = BitmapCacheOption.OnDemand;
img.DecodePixelWidth = 327;
var uri = new Uri(x, UriKind.Absolute);
img.UriSource = uri;
img.EndInit();
return img;
})
.BindToStrict(this, v => v.ModlistImage.ImageSource)
.DisposeWith(disposables);
*/
var textXformed = ViewModel.WhenAnyValue(vm => vm.Metadata.Title) var textXformed = ViewModel.WhenAnyValue(vm => vm.Metadata.Title)
.CombineLatest(ViewModel.WhenAnyValue(vm => vm.Metadata.ImageContainsTitle), .CombineLatest(ViewModel.WhenAnyValue(vm => vm.Metadata.ImageContainsTitle),
ViewModel.WhenAnyValue(vm => vm.IsBroken)) ViewModel.WhenAnyValue(vm => vm.IsBroken))
.Select(x => x.Second && !x.Third ? "" : x.First); .Select(x => x.Second && !x.Third ? "" : x.First);
/*
textXformed
.BindToStrict(this, view => view.ModListTitle.Text)
.DisposeWith(disposables);
textXformed
.BindToStrict(this, view => view.ModListTitleShadow.Text)
.DisposeWith(disposables);
ViewModel.WhenAnyValue(x => x.Metadata.Description)
.BindToStrict(this, x => x.MetadataDescription.Text)
.DisposeWith(disposables);
ViewModel.WhenAnyValue(x => x.ModListTagList)
.BindToStrict(this, x => x.TagsList.ItemsSource)
.DisposeWith(disposables);
*/
ViewModel.WhenAnyValue(x => x.LoadingImageLock.IsLoading) ViewModel.WhenAnyValue(x => x.LoadingImageLock.IsLoading)
.Select(x => x ? Visibility.Visible : Visibility.Collapsed) .Select(x => x ? Visibility.Visible : Visibility.Collapsed)
.BindToStrict(this, x => x.LoadingProgress.Visibility) .BindToStrict(this, x => x.LoadingProgress.Visibility)
@ -82,74 +39,6 @@ namespace Wabbajack
.Select(x => x ? Visibility.Visible : Visibility.Collapsed) .Select(x => x ? Visibility.Visible : Visibility.Collapsed)
.BindToStrict(this, view => view.Overlay.Visibility) .BindToStrict(this, view => view.Overlay.Visibility)
.DisposeWith(disposables); .DisposeWith(disposables);
/*
ViewModel.WhenAnyValue(x => x.OpenWebsiteCommand)
.BindToStrict(this, x => x.OpenWebsiteButton.Command)
.DisposeWith(disposables);
ViewModel.WhenAnyValue(x => x.ModListContentsCommend)
.BindToStrict(this, x => x.ModListContentsButton.Command)
.DisposeWith(disposables);
ViewModel.WhenAnyValue(x => x.ExecuteCommand)
.BindToStrict(this, x => x.ExecuteButton.Command)
.DisposeWith(disposables);
*/
/*
ViewModel.WhenAnyValue(x => x.ProgressPercent)
.ObserveOn(RxApp.MainThreadScheduler)
.Select(p => p.Value)
.BindTo(this, x => x.DownloadProgressBar.Value)
.DisposeWith(disposables);
*/
/*
ViewModel.WhenAnyValue(x => x.Status)
.ObserveOnGuiThread()
.Subscribe(x =>
{
IconContainer.Children.Clear();
IconContainer.Children.Add(new PackIconMaterial
{
Width = 20,
Height = 20,
Kind = x switch
{
ModListMetadataVM.ModListStatus.Downloaded => PackIconMaterialKind.Play,
ModListMetadataVM.ModListStatus.Downloading => PackIconMaterialKind.Network,
ModListMetadataVM.ModListStatus.NotDownloaded => PackIconMaterialKind.Download,
_ => throw new ArgumentOutOfRangeException(nameof(x), x, null)
}
});
})
.DisposeWith(disposables);
*/
/*
this.MarkAsNeeded<ModListTileView, ModListMetadataVM, bool>(this.ViewModel, x => x.IsBroken);
this.MarkAsNeeded<ModListTileView, ModListMetadataVM, bool>(this.ViewModel, x => x.Exists);
this.MarkAsNeeded<ModListTileView, ModListMetadataVM, string>(this.ViewModel, x => x.Metadata.Links.ImageUri);
this.WhenAny(x => x.ViewModel.ProgressPercent)
.Select(p => p.Value)
.BindToStrict(this, x => x.DownloadProgressBar.Value)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.ModListContentsCommend)
.BindToStrict(this, x => x.ModListContentsButton.Command)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Image)
.BindToStrict(this, x => x.ModListImage.Source)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.LoadingImage)
.Select(x => x ? Visibility.Visible : Visibility.Collapsed)
.BindToStrict(this, x => x.LoadingProgress.Visibility)
.DisposeWith(dispose);
*/
}); });
} }
} }

View File

@ -23,7 +23,7 @@ namespace Wabbajack
ScreenButtonDictionary = new() { ScreenButtonDictionary = new() {
{ ScreenType.Home, HomeButton }, { ScreenType.Home, HomeButton },
{ ScreenType.ModListGallery, BrowseButton }, { ScreenType.ModListGallery, BrowseButton },
{ ScreenType.Compiler, CompileButton }, { ScreenType.CreateAList, CompileButton },
{ ScreenType.Settings, SettingsButton }, { ScreenType.Settings, SettingsButton },
}; };
this.WhenActivated(dispose => this.WhenActivated(dispose =>
@ -32,7 +32,7 @@ namespace Wabbajack
.DisposeWith(dispose); .DisposeWith(dispose);
this.BindCommand(ViewModel, vm => vm.HomeCommand, v => v.HomeButton) this.BindCommand(ViewModel, vm => vm.HomeCommand, v => v.HomeButton)
.DisposeWith(dispose); .DisposeWith(dispose);
this.BindCommand(ViewModel, vm => vm.CompileCommand, v => v.CompileButton) this.BindCommand(ViewModel, vm => vm.CreateAListCommand, v => v.CompileButton)
.DisposeWith(dispose); .DisposeWith(dispose);
this.BindCommand(ViewModel, vm => vm.SettingsCommand, v => v.SettingsButton) this.BindCommand(ViewModel, vm => vm.SettingsCommand, v => v.SettingsButton)
.DisposeWith(dispose); .DisposeWith(dispose);