Merge branch 'master' into bunny-cdn-push

This commit is contained in:
Timothy Baldridge 2020-01-21 20:46:10 -07:00 committed by GitHub
commit 1e2e364688
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 1075 additions and 580 deletions

View File

@ -1,5 +1,9 @@
### Changelog
=======
* Fix for website readme compilation
* Fix for compiler downloads folder specification (was always standard path)
#### Version - 1.0 beta 16 - 1/19/2020
* Progress ring displays when downloading modlist images
* GUI releases memory of download modlists better when navigating around

View File

@ -1,3 +1,13 @@
The Wabbajack Codebase is under the GPLv3 license.
Modlists produced by Wabbajack under the [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)
As such, Wabbajack modlists may *not* be paywalled (be it beta
pre-release or otherwise). Any quid-pro-quo payment structure in connection
with Wabbajack lists is strictly prohibited.
----------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
@ -671,4 +681,4 @@ into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@ -125,6 +125,17 @@ Look at the [`CONTRIBUTING.md`](https://github.com/halgari/wabbajack/blob/master
I (_halgari_) used to be a developer working on Automaton. Sadly development was moving a bit too slowly for my liking, and I realized that a complete rewrite would allow the implementation of some really nice features (like BSA packing). As such I made the decision to strike out on my own and make an app that worked first, and then make it pretty. The end result is an app with a ton of features, and a less than professional UI. But that's my motto when coding "_make it work, then make it pretty_".
**Can I charge for a Wabbajack Modlist I created?**
No, as specified in the license, Wabbajack modlists must be available for free. Any payment in exchange for access to a Wabbajack
installer is strictly prohibited. This includes paywalling, "pay for beta access", "pay for current version, previous version is free",
or any sort of other quid-pro-quo monitization structure. The Wabbajack team reserves the right to implement software that will prohibit the installation of any lists that are paywalled.
**Can I accept donations for my installer?**
Absolutely! As long as the act of donating does not entitle the donator to access to the installer. The installer must be free,
donations must be a "thank you" not a purchase of services or content.
## Thanks to
Our testers and Discord members who encourage development and help test the builds.

View File

@ -24,12 +24,12 @@
<PackageReference Include="ini-parser-netstandard" Version="2.5.2" />
<PackageReference Include="Microsoft.Win32.Registry" Version="4.7.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ReactiveUI" Version="11.1.11" />
<PackageReference Include="ReactiveUI" Version="11.1.12" />
<PackageReference Include="SharpZipLib" Version="1.2.0" />
<PackageReference Include="System.Data.HashFunction.xxHash" Version="2.0.0" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.7.0" />
<PackageReference Include="System.Security.Principal.Windows" Version="4.7.0" />
<PackageReference Include="YamlDotNet" Version="8.0.0" />
<PackageReference Include="YamlDotNet" Version="8.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Compression.BSA\Compression.BSA.csproj" />

View File

@ -22,7 +22,7 @@
<Version>0.15.1</Version>
</PackageReference>
<PackageReference Include="Fody">
<Version>6.0.6</Version>
<Version>6.0.7</Version>
</PackageReference>
<PackageReference Include="Genbox.AlphaFS">
<Version>2.2.2.1</Version>
@ -49,10 +49,10 @@
<Version>2.10.1</Version>
</PackageReference>
<PackageReference Include="ReactiveUI">
<Version>11.1.11</Version>
<Version>11.1.12</Version>
</PackageReference>
<PackageReference Include="ReactiveUI.Fody">
<Version>11.1.11</Version>
<Version>11.1.12</Version>
</PackageReference>
<PackageReference Include="SharpCompress">
<Version>0.24.0</Version>

View File

@ -188,7 +188,7 @@
<Version>12.0.3</Version>
</PackageReference>
<PackageReference Include="ReactiveUI">
<Version>11.1.11</Version>
<Version>11.1.12</Version>
</PackageReference>
<PackageReference Include="System.Reactive">
<Version>4.3.2</Version>

View File

@ -12,6 +12,7 @@
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
<ResourceDictionary Source="Themes\Styles.xaml" />
<ResourceDictionary Source="Themes\CustomControls.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

View File

@ -54,6 +54,26 @@ namespace Wabbajack
viewProperty: viewProperty);
}
public static IReactiveBinding<TView, TViewModel, (object view, bool isViewModel)> BindStrict<TViewModel, TView, TVMProp, TVProp, TDontCare>(
this TView view,
TViewModel viewModel,
Expression<Func<TViewModel, TVMProp>> vmProperty,
Expression<Func<TView, TVProp>> viewProperty,
IObservable<TDontCare> signalViewUpdate,
Func<TVMProp, TVProp> vmToViewConverter,
Func<TVProp, TVMProp> viewToVmConverter)
where TViewModel : class
where TView : class, IViewFor
{
return view.Bind(
viewModel: viewModel,
vmProperty: vmProperty,
viewProperty: viewProperty,
signalViewUpdate: signalViewUpdate,
vmToViewConverter: vmToViewConverter,
viewToVmConverter: viewToVmConverter);
}
public static IReactiveBinding<TView, TViewModel, (object view, bool isViewModel)> BindStrict<TViewModel, TView, TVMProp, TVProp>(
this TView view,
TViewModel viewModel,
@ -78,7 +98,9 @@ namespace Wabbajack
Expression<Func<TTarget, TValue>> property)
where TTarget : class
{
return @this.BindTo<TValue, TTarget, TValue>(target, property);
return @this
.ObserveOnGuiThread()
.BindTo<TValue, TTarget, TValue>(target, property);
}
/// <summary>

View File

@ -0,0 +1,118 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Wabbajack">
<Style TargetType="local:AttentionBorder">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:AttentionBorder">
<Border BorderThickness="1">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="{StaticResource WindowBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource DarkerSecondaryBrush}" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsVisible, RelativeSource={RelativeSource Self}}" Value="True" />
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="False" />
<Condition Binding="{Binding Failure, RelativeSource={RelativeSource AncestorType={x:Type local:AttentionBorder}}}" Value="False" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
AutoReverse="True"
RepeatBehavior="Forever"
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
To="{StaticResource Secondary}"
Duration="0:0:1.5" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
AutoReverse="True"
RepeatBehavior="Forever"
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
To="{StaticResource SecondaryBackground}"
Duration="0:0:1.5" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
To="{StaticResource DarkerSecondary}"
Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
To="{StaticResource WindowBackgroundColor}"
Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsVisible, RelativeSource={RelativeSource Self}}" Value="True" />
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="False" />
<Condition Binding="{Binding Failure, RelativeSource={RelativeSource AncestorType={x:Type local:AttentionBorder}}}" Value="True" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
AutoReverse="True"
RepeatBehavior="Forever"
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
To="#ff0026"
Duration="0:0:1.5" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
AutoReverse="True"
RepeatBehavior="Forever"
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
To="#540914"
Duration="0:0:1.5" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
To="#700d1c"
Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
To="#1c0307"
Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentPresenter Content="{TemplateBinding Content}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@ -48,9 +48,9 @@ namespace Wabbajack
public ObservableCollectionExtended<IStatusMessage> Log => MWVM.Log;
public ReactiveCommand<Unit, Unit> BackCommand { get; }
public IReactiveCommand GoToModlistCommand { get; }
public IReactiveCommand CloseWhenCompleteCommand { get; }
public IReactiveCommand BeginCommand { get; }
public ReactiveCommand<Unit, Unit> GoToModlistCommand { get; }
public ReactiveCommand<Unit, Unit> CloseWhenCompleteCommand { get; }
public ReactiveCommand<Unit, Unit> BeginCommand { get; }
public FilePickerVM OutputLocation { get; }

View File

@ -189,6 +189,7 @@ namespace Wabbajack
ModListWebsite = ModlistSettings.Website,
ModListReadme = ModlistSettings.ReadmeIsWebsite ? ModlistSettings.ReadmeWebsite : ModlistSettings.ReadmeFilePath.TargetPath,
ReadmeIsWebsite = ModlistSettings.ReadmeIsWebsite,
MO2DownloadsFolder = DownloadLocation.TargetPath,
})
{
Parent.MWVM.Settings.Performance.AttachToBatchProcessor(ActiveCompilation);

View File

@ -19,5 +19,6 @@ namespace Wabbajack
int ConfigVisualVerticalOffset { get; }
IObservable<bool> CanInstall { get; }
Task<bool> Install();
IUserIntervention InterventionConverter(IUserIntervention intervention);
}
}

View File

@ -96,13 +96,13 @@ namespace Wabbajack
public bool IsActive => _IsActive.Value;
// Command properties
public IReactiveCommand ShowReportCommand { get; }
public IReactiveCommand OpenReadmeCommand { get; }
public IReactiveCommand VisitWebsiteCommand { get; }
public ReactiveCommand<Unit, Unit> ShowManifestCommand { get; }
public ReactiveCommand<Unit, Unit> OpenReadmeCommand { get; }
public ReactiveCommand<Unit, Unit> VisitModListWebsiteCommand { get; }
public ReactiveCommand<Unit, Unit> BackCommand { get; }
public IReactiveCommand CloseWhenCompleteCommand { get; }
public IReactiveCommand GoToInstallCommand { get; }
public IReactiveCommand BeginCommand { get; }
public ReactiveCommand<Unit, Unit> CloseWhenCompleteCommand { get; }
public ReactiveCommand<Unit, Unit> GoToInstallCommand { get; }
public ReactiveCommand<Unit, Unit> BeginCommand { get; }
public InstallerVM(MainWindowVM mainWindowVM)
{
@ -317,14 +317,18 @@ namespace Wabbajack
.ToGuiProperty(this, nameof(ModListName));
// Define commands
ShowReportCommand = ReactiveCommand.Create(ShowReport);
ShowManifestCommand = ReactiveCommand.Create(ShowReport);
OpenReadmeCommand = ReactiveCommand.Create(
execute: () => this.ModList?.OpenReadmeWindow(),
canExecute: this.WhenAny(x => x.ModList)
.Select(modList => !string.IsNullOrEmpty(modList?.Readme))
.ObserveOnGuiThread());
VisitWebsiteCommand = ReactiveCommand.Create(
execute: () => Process.Start(ModList.Website),
VisitModListWebsiteCommand = ReactiveCommand.Create(
execute: () =>
{
Process.Start(ModList.Website);
return Unit.Default;
},
canExecute: this.WhenAny(x => x.ModList.Website)
.Select(x => x?.StartsWith("https://") ?? false)
.ObserveOnGuiThread());
@ -393,11 +397,19 @@ namespace Wabbajack
// Listen for user interventions, and compile a dynamic list of all unhandled ones
var activeInterventions = this.WhenAny(x => x.Installer.ActiveInstallation)
.SelectMany(c => c?.LogMessages ?? Observable.Empty<IStatusMessage>())
.WhereCastable<IStatusMessage, IUserIntervention>()
.ToObservableChangeSet()
.AutoRefresh(i => i.Handled)
.Filter(i => !i.Handled)
.WithLatestFrom(
this.WhenAny(x => x.Installer),
(activeInstall, installer) =>
{
if (activeInstall == null) return Observable.Empty<IChangeSet<IUserIntervention>>();
return activeInstall.LogMessages
.WhereCastable<IStatusMessage, IUserIntervention>()
.ToObservableChangeSet()
.AutoRefresh(i => i.Handled)
.Filter(i => !i.Handled)
.Transform(x => installer.InterventionConverter(x));
})
.Switch()
.AsObservableList();
// Find the top intervention /w no CPU ID to be marked as "global"

View File

@ -169,5 +169,16 @@ namespace Wabbajack
});
}
}
public IUserIntervention InterventionConverter(IUserIntervention intervention)
{
switch (intervention)
{
case ConfirmUpdateOfExistingInstall confirm:
return new ConfirmUpdateOfExistingInstallVM(this, confirm);
default:
return intervention;
}
}
}
}

View File

@ -87,5 +87,7 @@ namespace Wabbajack
});
}
}
public IUserIntervention InterventionConverter(IUserIntervention intervention) => intervention;
}
}

View File

@ -10,6 +10,8 @@ using System.Threading.Tasks;
using DynamicData;
using DynamicData.Binding;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Wabbajack.Common;
using Wabbajack.Lib;
using Wabbajack.Lib.ModListRegistry;
@ -23,6 +25,9 @@ namespace Wabbajack
private int missingHashFallbackCounter;
[Reactive]
public IErrorResponse Error { get; set; }
public ModListGalleryVM(MainWindowVM mainWindowVM)
: base(mainWindowVM)
{
@ -32,8 +37,18 @@ namespace Wabbajack
.ObserveOn(RxApp.TaskpoolScheduler)
.SelectTask(async _ =>
{
return (await ModlistMetadata.LoadFromGithub())
.AsObservableChangeSet(x => x.DownloadMetadata?.Hash ?? $"Fallback{missingHashFallbackCounter++}");
try
{
Error = null;
var list = await ModlistMetadata.LoadFromGithub();
return list.AsObservableChangeSet(x => x.DownloadMetadata?.Hash ?? $"Fallback{missingHashFallbackCounter++}");
}
catch (Exception ex)
{
Utils.Error(ex);
Error = ErrorResponse.Fail(ex);
return Observable.Empty<IChangeSet<ModlistMetadata, string>>();
}
})
// Unsubscribe and release when not active
.FlowSwitch(

View File

@ -166,7 +166,9 @@ namespace Wabbajack
}
});
await Metrics.Send(Metrics.Downloading, Metadata.Title);
Task.Run(() => Metrics.Send(Metrics.Downloading, Metadata.Title))
.FireAndForget(ex => Utils.Error(ex, "Error sending download metric"));
return await tcs.Task;
}

View File

@ -94,7 +94,7 @@ namespace Wabbajack
public void OpenReadmeWindow()
{
if (string.IsNullOrEmpty(Readme)) return;
if (false) //SourceModList.ReadmeIsWebsite)
if (SourceModList.ReadmeIsWebsite)
{
Process.Start(Readme);
}

View File

@ -32,8 +32,8 @@ namespace Wabbajack
private readonly ObservableAsPropertyHelper<ModVM> _targetMod;
public ModVM TargetMod => _targetMod.Value;
public IReactiveCommand SlideShowNextItemCommand { get; } = ReactiveCommand.Create(() => { });
public IReactiveCommand VisitNexusSiteCommand { get; }
public ReactiveCommand<Unit, Unit> SlideShowNextItemCommand { get; } = ReactiveCommand.Create(() => { });
public ReactiveCommand<Unit, Unit> VisitNexusSiteCommand { get; }
public const int PreloadAmount = 4;
@ -119,7 +119,11 @@ namespace Wabbajack
.ToGuiProperty(this, nameof(Image));
VisitNexusSiteCommand = ReactiveCommand.Create(
execute: () => Process.Start(TargetMod.ModURL),
execute: () =>
{
Process.Start(TargetMod.ModURL);
return Unit.Default;
},
canExecute: this.WhenAny(x => x.TargetMod.ModURL)
.Select(x => x?.StartsWith("https://") ?? false)
.ObserveOnGuiThread());

View File

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Wabbajack.Common;
using Wabbajack.Lib;
namespace Wabbajack
{
public class ConfirmUpdateOfExistingInstallVM : ViewModel, IUserIntervention
{
public ConfirmUpdateOfExistingInstall Source { get; }
public MO2InstallerVM Installer { get; }
public bool Handled => ((IUserIntervention)Source).Handled;
public int CpuID => ((IUserIntervention)Source).CpuID;
public DateTime Timestamp => ((IUserIntervention)Source).Timestamp;
public string ShortDescription => ((IUserIntervention)Source).ShortDescription;
public string ExtendedDescription => ((IUserIntervention)Source).ExtendedDescription;
public ConfirmUpdateOfExistingInstallVM(MO2InstallerVM installer, ConfirmUpdateOfExistingInstall confirm)
{
Source = confirm;
Installer = installer;
}
public void Cancel()
{
((IUserIntervention)Source).Cancel();
}
}
}

View File

@ -20,14 +20,6 @@ namespace Wabbajack
/// </summary>
public partial class AttentionBorder : UserControl
{
public object DisplayContent
{
get => (object)GetValue(DisplayContentProperty);
set => SetValue(DisplayContentProperty, value);
}
public static readonly DependencyProperty DisplayContentProperty = DependencyProperty.Register(nameof(DisplayContent), typeof(object), typeof(AttentionBorder),
new FrameworkPropertyMetadata(default(object)));
public bool Failure
{
get => (bool)GetValue(FailureProperty);
@ -35,10 +27,5 @@ namespace Wabbajack
}
public static readonly DependencyProperty FailureProperty = DependencyProperty.Register(nameof(Failure), typeof(bool), typeof(AttentionBorder),
new FrameworkPropertyMetadata(default(bool)));
public AttentionBorder()
{
InitializeComponent();
}
}
}

View File

@ -1,116 +0,0 @@
<UserControl
x:Class="Wabbajack.AttentionBorder"
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:local="clr-namespace:Wabbajack"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<Border BorderThickness="1">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="{StaticResource WindowBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource DarkerSecondaryBrush}" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsVisible, RelativeSource={RelativeSource Self}}" Value="True" />
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="False" />
<Condition Binding="{Binding Failure, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Value="False" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
AutoReverse="True"
RepeatBehavior="Forever"
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
To="{StaticResource Secondary}"
Duration="0:0:1.5" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
AutoReverse="True"
RepeatBehavior="Forever"
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
To="{StaticResource SecondaryBackground}"
Duration="0:0:1.5" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
To="{StaticResource DarkerSecondary}"
Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
To="{StaticResource WindowBackgroundColor}"
Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsVisible, RelativeSource={RelativeSource Self}}" Value="True" />
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Self}}" Value="False" />
<Condition Binding="{Binding Failure, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Value="True" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
AutoReverse="True"
RepeatBehavior="Forever"
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
To="#ff0026"
Duration="0:0:1.5" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
AutoReverse="True"
RepeatBehavior="Forever"
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
To="#540914"
Duration="0:0:1.5" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
To="#700d1c"
Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
To="#1c0307"
Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<ContentPresenter Content="{Binding DisplayContent, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
</Border>
</UserControl>

View File

@ -40,7 +40,7 @@ namespace Wabbajack
set => SetValue(SettingsHookProperty, value);
}
public static readonly DependencyProperty SettingsHookProperty = DependencyProperty.Register(nameof(SettingsHook), typeof(MainSettings), typeof(CpuView),
new FrameworkPropertyMetadata(default(SettingsVM)));
new FrameworkPropertyMetadata(default(SettingsVM), WireNotifyPropertyChanged));
private bool _ShowingSettings;
public bool ShowingSettings { get => _ShowingSettings; set => this.RaiseAndSetIfChanged(ref _ShowingSettings, value); }

View File

@ -1,4 +1,4 @@
<UserControl
<rxui:ReactiveUserControl
x:Class="Wabbajack.CompilationCompleteView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -6,106 +6,97 @@
xmlns:icon="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:local="clr-namespace:Wabbajack"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:rxui="http://reactiveui.net"
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="local:CompilerVM"
mc:Ignorable="d">
<local:AttentionBorder ClipToBounds="True" Failure="{Binding Completed.Failed}">
<local:AttentionBorder.DisplayContent>
<Grid Margin="5">
<local:AttentionBorder x:Name="AttentionBorder" ClipToBounds="True">
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="3*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
x:Name="TitleText"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="3"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
FontFamily="Lucida Sans"
FontSize="22"
FontWeight="Black">
<TextBlock.Effect>
<DropShadowEffect BlurRadius="25" Opacity="0.5" />
</TextBlock.Effect>
</TextBlock>
<Grid
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="3*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
<Button
x:Name="BackButton"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="3"
Width="55"
Height="55"
Style="{StaticResource CircleButtonStyle}">
<icon:PackIconMaterial
Width="28"
Height="28"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Kind="ArrowLeft" />
</Button>
<TextBlock
Grid.Row="1"
Margin="0,10,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
FontFamily="Lucida Sans"
FontSize="22"
FontWeight="Black">
<TextBlock.Effect>
<DropShadowEffect BlurRadius="25" Opacity="0.5" />
</TextBlock.Effect>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="Compilation Complete" />
<Style.Triggers>
<DataTrigger Binding="{Binding Completed.Failed}" Value="True">
<Setter Property="Text" Value="Compilation Failed" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<Grid
Text="Main Menu" />
</Grid>
<Grid
Grid.Row="1"
Grid.Column="1"
VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button
x:Name="GoToModlistButton"
Width="55"
Height="55"
Style="{StaticResource CircleButtonStyle}">
<icon:PackIconMaterial
Width="25"
Height="25"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Kind="FolderMove" />
</Button>
<TextBlock
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button
Grid.Row="0"
Width="55"
Height="55"
Command="{Binding BackCommand}"
Style="{StaticResource CircleButtonStyle}">
<icon:PackIconMaterial
Width="28"
Height="28"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Kind="ArrowLeft" />
</Button>
<TextBlock
Grid.Row="1"
Margin="0,10,0,0"
HorizontalAlignment="Center"
Text="Main Menu" />
</Grid>
<Grid
Grid.Row="1"
Grid.Column="1"
VerticalAlignment="Center"
Visibility="{Binding CompilerSupportsAfterCompileNavigation, Converter={StaticResource bool2VisibilityConverter}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button
Width="55"
Height="55"
Command="{Binding GoToModlistCommand}"
Style="{StaticResource CircleButtonStyle}">
<icon:PackIconMaterial
Width="25"
Height="25"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Kind="FolderMove" />
</Button>
<TextBlock
Grid.Row="1"
Margin="0,10,0,0"
HorizontalAlignment="Center"
Text="Go To Modlist" />
</Grid>
<Grid
Grid.Row="1"
Grid.Column="2"
VerticalAlignment="Center"
Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!--<Button
Margin="0,10,0,0"
HorizontalAlignment="Center"
Text="Go To Modlist" />
</Grid>
<Grid
Grid.Row="1"
Grid.Column="2"
VerticalAlignment="Center"
Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!--<Button
Width="55"
Height="55"
Background="{StaticResource PrimaryVariantBrush}"
@ -127,24 +118,23 @@
<BlurEffect Radius="15" />
</Button.Effect>
</Button>-->
<Button
Width="55"
Height="55"
Command="{Binding CloseWhenCompleteCommand}"
Style="{StaticResource CircleButtonStyle}">
<icon:PackIconMaterial
Width="30"
Height="30"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Kind="Check" />
</Button>
<TextBlock
Grid.Row="1"
Margin="0,10,0,0"
HorizontalAlignment="Center"
Text="Close" />
</Grid>
<Button
x:Name="CloseWhenCompletedButton"
Width="55"
Height="55"
Style="{StaticResource CircleButtonStyle}">
<icon:PackIconMaterial
Width="30"
Height="30"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Kind="Check" />
</Button>
<TextBlock
Grid.Row="1"
Margin="0,10,0,0"
HorizontalAlignment="Center"
Text="Close" />
</Grid>
</local:AttentionBorder.DisplayContent>
</Grid>
</local:AttentionBorder>
</UserControl>
</rxui:ReactiveUserControl>

View File

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
@ -12,17 +14,42 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ReactiveUI;
namespace Wabbajack
{
/// <summary>
/// Interaction logic for CompilationCompleteView.xaml
/// </summary>
public partial class CompilationCompleteView : UserControl
public partial class CompilationCompleteView : ReactiveUserControl<CompilerVM>
{
public CompilationCompleteView()
{
InitializeComponent();
this.WhenActivated(dispose =>
{
this.WhenAny(x => x.ViewModel.Completed)
.Select(x => x?.Failed ?? false)
.BindToStrict(this, x => x.AttentionBorder.Failure)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Completed)
.Select(x => x?.Failed ?? false)
.Select(failed =>
{
return $"Compilation {(failed ? "Failed" : "Complete")}";
})
.BindToStrict(this, x => x.TitleText.Text)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.BackCommand)
.BindToStrict(this, x => x.BackButton.Command)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.GoToModlistCommand)
.BindToStrict(this, x => x.GoToModlistButton.Command)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.CloseWhenCompleteCommand)
.BindToStrict(this, x => x.CloseWhenCompletedButton.Command)
.DisposeWith(dispose);
});
}
}
}

View File

@ -1,4 +1,4 @@
<UserControl
<rxui:ReactiveUserControl
x:Class="Wabbajack.CompilerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -8,10 +8,12 @@
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"
d:DataContext="{d:DesignInstance local:CompilerVM}"
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="local:CompilerVM"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
@ -27,11 +29,11 @@
<ColumnDefinition Width="5" />
</Grid.ColumnDefinitions>
<local:HeatedBackgroundView
x:Name="HeatedBackground"
Grid.Row="0"
Grid.RowSpan="3"
Grid.Column="0"
Grid.ColumnSpan="5"
PercentCompleted="{Binding PercentCompleted}" />
Grid.ColumnSpan="5" />
<Border
x:Name="ModlistDetailsBackground"
Grid.Row="1"
@ -54,30 +56,22 @@
Grid.ColumnSpan="2"
Margin="1,1,5,0"
BorderBrush="{StaticResource HeatedBorderBrush}"
BorderThickness="1"
Opacity="{Binding PercentCompleted}" />
BorderThickness="1" />
<Border
Grid.Row="1"
Grid.Column="3"
BorderBrush="{StaticResource BorderInterestBrush}"
BorderThickness="1,0,1,1">
<local:DetailImageView
Title="{Binding CurrentModlistSettings.ModListName}"
Author="{Binding CurrentModlistSettings.AuthorText}"
BorderThickness="0"
Description="{Binding CurrentModlistSettings.Description}"
Image="{Binding Image}" />
<local:DetailImageView x:Name="DetailImage" BorderThickness="0" />
</Border>
<!-- Comes after image area so shadow can overlay -->
<local:TopProgressView
Title="{Binding CurrentModlistSettings.ModListName, Mode=OneWay}"
x:Name="TopProgressBar"
Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="0"
Grid.ColumnSpan="5"
OverhangShadow="True"
ProgressPercent="{Binding PercentCompleted}"
StatePrefixTitle="{Binding ProgressTitle}" />
OverhangShadow="True" />
<Button
x:Name="BackButton"
Grid.Row="0"
@ -88,23 +82,21 @@
Margin="12,5,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Command="{Binding BackCommand}"
Style="{StaticResource IconCircleButtonStyle}"
ToolTip="Back to main menu">
<icon:PackIconMaterial Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Kind="ArrowLeft" />
</Button>
<ScrollViewer
x:Name="SettingsScrollViewer"
Grid.Row="1"
Grid.Column="1"
Margin="5"
Background="Transparent"
HorizontalScrollBarVisibility="Disabled"
IsEnabled="{Binding Compiling, Converter={StaticResource InverseBooleanConverter}}"
VerticalScrollBarVisibility="Auto">
<StackPanel
Margin="0,5,0,0"
Background="Transparent"
DataContext="{Binding CurrentModlistSettings}"
Orientation="Vertical">
<StackPanel.Resources>
<Thickness
@ -128,26 +120,26 @@
</Style>
</StackPanel.Resources>
<TextBlock Margin="{StaticResource TitleMargin}" Text="ModList Name" />
<TextBox Style="{StaticResource ValueStyle}" Text="{Binding ModListName, UpdateSourceTrigger=PropertyChanged}" />
<TextBox x:Name="ModListNameSetting" Style="{StaticResource ValueStyle}" />
<TextBlock Margin="{StaticResource TitleMargin}" Text="Author" />
<TextBox Style="{StaticResource ValueStyle}" Text="{Binding AuthorText, UpdateSourceTrigger=PropertyChanged}" />
<TextBox x:Name="AuthorNameSetting" Style="{StaticResource ValueStyle}" />
<TextBlock Margin="{StaticResource TitleMargin}" Text="Description" />
<TextBox
x:Name="DescriptionSetting"
Height="150"
mahapps:TextBoxHelper.Watermark="(700 characters max)"
AcceptsReturn="True"
AcceptsTab="False"
MaxLength="700"
Style="{StaticResource ValueStyle}"
Text="{Binding Description, UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" />
<TextBlock Margin="{StaticResource TitleMargin}" Text="Image" />
<local:FilePicker
PickerVM="{Binding ImagePath}"
x:Name="ImageFilePicker"
Style="{StaticResource PickerStyle}"
ToolTip="Path to an image to display for the modlist." />
<TextBlock Margin="{StaticResource TitleMargin}" Text="Website" />
<TextBox Style="{StaticResource ValueStyle}" Text="{Binding Website, UpdateSourceTrigger=PropertyChanged}" />
<TextBox x:Name="WebsiteSetting" Style="{StaticResource ValueStyle}" />
<TextBlock
Margin="{StaticResource TitleMargin}"
Text="Readme"
@ -159,30 +151,28 @@
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<local:FilePicker
x:Name="ReadmeFilePickerSetting"
Grid.Column="0"
Height="27"
Margin="0,0,3,0"
VerticalAlignment="Center"
PickerVM="{Binding ReadmeFilePath}"
ToolTip="Path to a readme file."
Visibility="{Binding ReadmeIsWebsite, Converter={StaticResource bool2VisibilityConverter}, ConverterParameter=False}" />
ToolTip="Path to a readme file." />
<TextBox
x:Name="ReadmeWebsiteSetting"
Grid.Column="0"
Height="27"
Margin="0,0,3,0"
VerticalAlignment="Center"
Text="{Binding ReadmeWebsite}"
ToolTip="Readme website"
Visibility="{Binding ReadmeIsWebsite, Converter={StaticResource bool2VisibilityConverter}}" />
ToolTip="Readme website" />
<Button
x:Name="SwapToReadmeWebsiteButton"
Grid.Column="1"
Width="27"
Command="{Binding SwapToWebsiteReadmeCommand}"
ToolTip="Set readme to be a website">
<Button.Style>
<Style BasedOn="{StaticResource IconBareButtonStyle}" TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding ReadmeIsWebsite}" Value="True">
<DataTrigger Binding="{Binding CurrentModlistSettings.ReadmeIsWebsite}" Value="True">
<Setter Property="Foreground" Value="{StaticResource SecondaryBrush}" />
</DataTrigger>
</Style.Triggers>
@ -194,14 +184,14 @@
Kind="Web" />
</Button>
<Button
x:Name="SwapToReadmeFileButton"
Grid.Column="2"
Width="27"
Command="{Binding SwapToTextReadmeCommand}"
ToolTip="Source readme from a local file (txt | html)">
<Button.Style>
<Style BasedOn="{StaticResource IconBareButtonStyle}" TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding ReadmeIsWebsite}" Value="False">
<DataTrigger Binding="{Binding CurrentModlistSettings.ReadmeIsWebsite}" Value="False">
<Setter Property="Foreground" Value="{StaticResource SecondaryBrush}" />
</DataTrigger>
</Style.Triggers>
@ -228,10 +218,10 @@
Grid.ColumnSpan="5"
MaxWidth="1000">
<Grid
x:Name="BottomCompilerSettingsGrid"
Margin="35,0,35,0"
VerticalAlignment="Center"
ClipToBounds="False"
Visibility="{Binding StartedCompilation, Converter={StaticResource bool2VisibilityConverter}, ConverterParameter=False}">
ClipToBounds="False">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
@ -254,6 +244,7 @@
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<local:ImageRadioButtonView
x:Name="MO2CompilerButton"
Grid.Row="0"
Height="35"
Margin="4"
@ -263,6 +254,7 @@
</local:ImageRadioButtonView.Image>
</local:ImageRadioButtonView>
<local:ImageRadioButtonView
x:Name="VortexCompilerButton"
Grid.Row="1"
Height="35"
Margin="4"
@ -273,9 +265,9 @@
</local:ImageRadioButtonView>
</Grid>
<ContentPresenter
x:Name="CustomCompilerSettingsPresenter"
Grid.Row="1"
Grid.Column="1"
Content="{Binding Compiler}">
Grid.Column="1">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type local:MO2CompilerVM}">
<local:MO2CompilerConfigView />
@ -286,38 +278,37 @@
</ContentPresenter.Resources>
</ContentPresenter>
<local:BeginButton
x:Name="BeginButton"
Grid.Row="0"
Grid.RowSpan="3"
Grid.Column="5"
Command="{Binding BeginCommand}" />
Grid.Column="5" />
</Grid>
</Grid>
<Grid
x:Name="MidCompilationGrid"
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="5"
Margin="5"
Visibility="{Binding StartedCompilation, Converter={StaticResource bool2VisibilityConverter}, FallbackValue=Hidden}">
Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<local:LogView Grid.Column="0" ProgressPercent="{Binding PercentCompleted, Mode=OneWay}" />
<local:LogView x:Name="LogView" Grid.Column="0" />
<local:CpuView
x:Name="CpuView"
Grid.Column="2"
ProgressPercent="{Binding PercentCompleted, Mode=OneWay}"
SettingsHook="{Binding MWVM.Settings}"
ViewModel="{Binding}"
Visibility="{Binding ActiveGlobalUserIntervention, Converter={StaticResource IsNotNullVisibilityConverter}, ConverterParameter=False}" />
<local:AttentionBorder Grid.Column="2" Visibility="{Binding ActiveGlobalUserIntervention, Converter={StaticResource IsNotNullVisibilityConverter}}">
<local:AttentionBorder.DisplayContent>
<Grid>
<local:ConfirmationInterventionView DataContext="{Binding ActiveGlobalUserIntervention}" Visibility="{Binding ActiveGlobalUserIntervention, Converter={StaticResource IsTypeVisibilityConverter}, ConverterParameter={x:Type common:ConfirmationIntervention}}" />
</Grid>
</local:AttentionBorder.DisplayContent>
ViewModel="{Binding}" />
<local:AttentionBorder x:Name="UserInterventionsControl" Grid.Column="2">
<Grid>
<local:ConfirmationInterventionView DataContext="{Binding ActiveGlobalUserIntervention}" Visibility="{Binding ActiveGlobalUserIntervention, Converter={StaticResource IsTypeVisibilityConverter}, ConverterParameter={x:Type common:ConfirmationIntervention}}" />
</Grid>
</local:AttentionBorder>
<local:CompilationCompleteView Grid.Column="2" Visibility="{Binding Completed, Converter={StaticResource IsNotNullVisibilityConverter}, FallbackValue=Collapsed}" />
<local:CompilationCompleteView
x:Name="CompilationComplete"
Grid.Column="2"
ViewModel="{Binding}" />
</Grid>
</Grid>
</UserControl>
</rxui:ReactiveUserControl>

View File

@ -1,15 +1,146 @@
using System.Windows.Controls;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Windows.Controls;
using ReactiveUI;
using System.Windows;
using Wabbajack.Common;
namespace Wabbajack
{
/// <summary>
/// Interaction logic for CompilerView.xaml
/// </summary>
public partial class CompilerView : UserControl
public partial class CompilerView : ReactiveUserControl<CompilerVM>
{
public CompilerView()
{
InitializeComponent();
this.WhenActivated(dispose =>
{
// Bind percent completed chanes
this.WhenAny(x => x.ViewModel.PercentCompleted)
.Select(f => (double)f)
.BindToStrict(this, x => x.HeatedBackground.PercentCompleted)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.PercentCompleted)
.Select(f => (double)f)
.BindToStrict(this, x => x.ModlistDetailsHeatBorder.Opacity)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.PercentCompleted)
.Select(f => (double)f)
.BindToStrict(this, x => x.TopProgressBar.ProgressPercent)
.DisposeWith(dispose);
// Bind detail image display
this.WhenAny(x => x.ViewModel.CurrentModlistSettings.ModListName)
.BindToStrict(this, x => x.DetailImage.Title)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.CurrentModlistSettings.AuthorText)
.BindToStrict(this, x => x.DetailImage.Author)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.CurrentModlistSettings.Description)
.BindToStrict(this, x => x.DetailImage.Description)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Image)
.BindToStrict(this, x => x.DetailImage.Image)
.DisposeWith(dispose);
// Top Progress Bar
this.WhenAny(x => x.ViewModel.CurrentModlistSettings.ModListName)
.BindToStrict(this, x => x.TopProgressBar.Title)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.ProgressTitle)
.BindToStrict(this, x => x.TopProgressBar.StatePrefixTitle)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.BackCommand)
.BindToStrict(this, x => x.BackButton.Command)
.DisposeWith(dispose);
// Settings Panel
this.WhenAny(x => x.ViewModel.Compiling)
.Select(x => !x)
.BindToStrict(this, x => x.SettingsScrollViewer.IsEnabled)
.DisposeWith(dispose);
this.BindStrict(this.ViewModel, x => x.CurrentModlistSettings.ModListName, x => x.ModListNameSetting.Text)
.DisposeWith(dispose);
this.BindStrict(this.ViewModel, x => x.CurrentModlistSettings.AuthorText, x => x.AuthorNameSetting.Text)
.DisposeWith(dispose);
this.BindStrict(this.ViewModel, x => x.CurrentModlistSettings.Description, x => x.DescriptionSetting.Text)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.CurrentModlistSettings.ImagePath)
.BindToStrict(this, x => x.ImageFilePicker.PickerVM)
.DisposeWith(dispose);
this.BindStrict(this.ViewModel, x => x.CurrentModlistSettings.Website, x => x.WebsiteSetting.Text)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.CurrentModlistSettings.ReadmeFilePath)
.BindToStrict(this, x => x.ReadmeFilePickerSetting.PickerVM)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.CurrentModlistSettings.ReadmeIsWebsite)
.Select(isWebsite => isWebsite ? Visibility.Collapsed : Visibility.Visible)
.BindToStrict(this, x => x.ReadmeFilePickerSetting.Visibility)
.DisposeWith(dispose);
this.BindStrict(this.ViewModel, x => x.CurrentModlistSettings.ReadmeWebsite, x => x.ReadmeWebsiteSetting.Text)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.CurrentModlistSettings.ReadmeIsWebsite)
.Select(isWebsite => isWebsite ? Visibility.Visible : Visibility.Collapsed)
.BindToStrict(this, x => x.ReadmeWebsiteSetting.Visibility)
.DisposeWith(dispose);
this.MarkAsNeeded<CompilerView, CompilerVM, bool>(this.ViewModel, x => x.CurrentModlistSettings.ReadmeIsWebsite);
this.WhenAny(x => x.ViewModel.CurrentModlistSettings.SwapToWebsiteReadmeCommand)
.BindToStrict(this, x => x.SwapToReadmeWebsiteButton.Command)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.CurrentModlistSettings.SwapToTextReadmeCommand)
.BindToStrict(this, x => x.SwapToReadmeFileButton.Command)
.DisposeWith(dispose);
// Bottom Compiler Settings
this.WhenAny(x => x.ViewModel.StartedCompilation)
.Select(started => started ? Visibility.Hidden : Visibility.Visible)
.BindToStrict(this, x => x.BottomCompilerSettingsGrid.Visibility)
.DisposeWith(dispose);
// Seems to go into an infinite loop between each other. Need to research a better radio button style pattern
//this.BindStrict(this.ViewModel, x => x.SelectedCompilerType, x => x.MO2CompilerButton.IsChecked,
// vmToViewConverter: type => type == ModManager.MO2,
// viewToVmConverter: isChecked => isChecked ? ModManager.MO2 : ModManager.Vortex);
//this.BindStrict(this.ViewModel, x => x.SelectedCompilerType, x => x.MO2CompilerButton.IsChecked,
// vmToViewConverter: type => type == ModManager.Vortex,
// viewToVmConverter: isChecked => isChecked ? ModManager.Vortex : ModManager.MO2);
this.WhenAny(x => x.ViewModel.Compiler)
.BindToStrict(this, x => x.CustomCompilerSettingsPresenter.Content)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.BeginCommand)
.BindToStrict(this, x => x.BeginButton.Command)
.DisposeWith(dispose);
// Mid-compilation panel
this.WhenAny(x => x.ViewModel.StartedCompilation)
.Select(started => started ? Visibility.Visible : Visibility.Hidden)
.BindToStrict(this, x => x.MidCompilationGrid.Visibility)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.PercentCompleted)
.Select(f => (double)f)
.BindToStrict(this, x => x.LogView.ProgressPercent)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.PercentCompleted)
.Select(f => (double)f)
.BindToStrict(this, x => x.CpuView.ProgressPercent)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.MWVM.Settings)
.BindToStrict(this, x => x.CpuView.SettingsHook)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.ActiveGlobalUserIntervention)
.Select(x => x == null ? Visibility.Visible : Visibility.Collapsed)
.BindToStrict(this, x => x.CpuView.Visibility)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.ActiveGlobalUserIntervention)
.Select(x => x != null ? Visibility.Visible : Visibility.Collapsed)
.BindToStrict(this, x => x.UserInterventionsControl.Visibility)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Completed)
.Select(x => x != null ? Visibility.Visible : Visibility.Collapsed)
.BindToStrict(this, x => x.CompilationComplete.Visibility)
.DisposeWith(dispose);
});
}
}
}

View File

@ -1,4 +1,4 @@
<UserControl
<rxui:ReactiveUserControl
x:Class="Wabbajack.InstallationCompleteView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -6,150 +6,141 @@
xmlns:icon="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:local="clr-namespace:Wabbajack"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:rxui="http://reactiveui.net"
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="local:InstallerVM"
mc:Ignorable="d">
<local:AttentionBorder ClipToBounds="True" Failure="{Binding Completed.Failed}">
<local:AttentionBorder.DisplayContent>
<Grid Margin="5">
<local:AttentionBorder x:Name="AttentionBorder" ClipToBounds="True">
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="3*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
x:Name="TitleText"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="4"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
FontFamily="Lucida Sans"
FontSize="22"
FontWeight="Black">
<TextBlock.Effect>
<DropShadowEffect BlurRadius="25" Opacity="0.5" />
</TextBlock.Effect>
</TextBlock>
<Grid
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="3*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
<Button
x:Name="BackButton"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="4"
Width="50"
Height="50"
Style="{StaticResource CircleButtonStyle}">
<icon:PackIconMaterial
Width="25"
Height="25"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Kind="ArrowLeft" />
</Button>
<TextBlock
Grid.Row="1"
Margin="0,10,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
FontFamily="Lucida Sans"
FontSize="22"
FontWeight="Black">
<TextBlock.Effect>
<DropShadowEffect BlurRadius="25" Opacity="0.5" />
</TextBlock.Effect>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="Installation Complete" />
<Style.Triggers>
<DataTrigger Binding="{Binding Completed.Failed}" Value="True">
<Setter Property="Text" Value="Installation Failed" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<Grid
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button
Grid.Row="0"
Width="50"
Height="50"
Command="{Binding BackCommand}"
Style="{StaticResource CircleButtonStyle}">
<icon:PackIconMaterial
Width="25"
Height="25"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Kind="ArrowLeft" />
</Button>
<TextBlock
Grid.Row="1"
Margin="0,10,0,0"
HorizontalAlignment="Center"
Text="Main Menu" />
</Grid>
<Grid
Grid.Row="1"
Grid.Column="1"
VerticalAlignment="Center"
Visibility="{Binding InstallerSupportsAfterInstallNavigation, Converter={StaticResource bool2VisibilityConverter}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button
Width="50"
Height="50"
Command="{Binding GoToInstallCommand}"
Style="{StaticResource CircleButtonStyle}">
<icon:PackIconMaterial
Width="23"
Height="23"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Kind="FolderMove" />
</Button>
<TextBlock
Grid.Row="1"
Margin="0,10,0,0"
HorizontalAlignment="Center"
Text="Install Folder" />
</Grid>
<Grid
Grid.Row="1"
Grid.Column="2"
VerticalAlignment="Center"
Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button
Width="50"
Height="50"
Command="{Binding OpenReadmeCommand}"
Style="{StaticResource CircleButtonStyle}">
<icon:PackIconFontAwesome
Width="25"
Height="25"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Kind="ReadmeBrands" />
</Button>
<TextBlock
Grid.Row="1"
Margin="0,10,0,0"
HorizontalAlignment="Center"
Text="Readme" />
</Grid>
<Grid
Grid.Row="1"
Grid.Column="3"
VerticalAlignment="Center"
Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button
Width="50"
Height="50"
Command="{Binding CloseWhenCompleteCommand}"
Style="{StaticResource CircleButtonStyle}">
<icon:PackIconMaterial
Width="25"
Height="25"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Kind="Check" />
</Button>
<TextBlock
Grid.Row="1"
Margin="0,10,0,0"
HorizontalAlignment="Center"
Text="Close" />
</Grid>
Text="Main Menu" />
</Grid>
</local:AttentionBorder.DisplayContent>
<Grid
Grid.Row="1"
Grid.Column="1"
VerticalAlignment="Center"
Visibility="{Binding InstallerSupportsAfterInstallNavigation, Converter={StaticResource bool2VisibilityConverter}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button
x:Name="GoToInstallButton"
Width="50"
Height="50"
Style="{StaticResource CircleButtonStyle}">
<icon:PackIconMaterial
Width="23"
Height="23"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Kind="FolderMove" />
</Button>
<TextBlock
Grid.Row="1"
Margin="0,10,0,0"
HorizontalAlignment="Center"
Text="Install Folder" />
</Grid>
<Grid
Grid.Row="1"
Grid.Column="2"
VerticalAlignment="Center"
Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button
x:Name="OpenReadmeButton"
Width="50"
Height="50"
Style="{StaticResource CircleButtonStyle}">
<icon:PackIconFontAwesome
Width="25"
Height="25"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Kind="ReadmeBrands" />
</Button>
<TextBlock
Grid.Row="1"
Margin="0,10,0,0"
HorizontalAlignment="Center"
Text="Readme" />
</Grid>
<Grid
Grid.Row="1"
Grid.Column="3"
VerticalAlignment="Center"
Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button
x:Name="CloseButton"
Width="50"
Height="50"
Style="{StaticResource CircleButtonStyle}">
<icon:PackIconMaterial
Width="25"
Height="25"
Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
Kind="Check" />
</Button>
<TextBlock
Grid.Row="1"
Margin="0,10,0,0"
HorizontalAlignment="Center"
Text="Close" />
</Grid>
</Grid>
</local:AttentionBorder>
</UserControl>
</rxui:ReactiveUserControl>

View File

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
@ -12,17 +14,45 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ReactiveUI;
namespace Wabbajack
{
/// <summary>
/// Interaction logic for InstallationCompleteView.xaml
/// </summary>
public partial class InstallationCompleteView : UserControl
public partial class InstallationCompleteView : ReactiveUserControl<InstallerVM>
{
public InstallationCompleteView()
{
InitializeComponent();
this.WhenActivated(dispose =>
{
this.WhenAny(x => x.ViewModel.Completed)
.Select(x => x?.Failed ?? false)
.BindToStrict(this, x => x.AttentionBorder.Failure)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Completed)
.Select(x => x?.Failed ?? false)
.Select(failed =>
{
return $"Installation {(failed ? "Failed" : "Complete")}";
})
.BindToStrict(this, x => x.TitleText.Text)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.BackCommand)
.BindToStrict(this, x => x.BackButton.Command)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.GoToInstallCommand)
.BindToStrict(this, x => x.GoToInstallButton.Command)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.OpenReadmeCommand)
.BindToStrict(this, x => x.OpenReadmeButton.Command)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.CloseWhenCompleteCommand)
.BindToStrict(this, x => x.CloseButton.Command)
.DisposeWith(dispose);
});
}
}
}

View File

@ -1,4 +1,4 @@
<UserControl
<rxui:ReactiveUserControl
x:Class="Wabbajack.InstallationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -9,9 +9,11 @@
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:DataContext="{d:DesignInstance local:InstallerVM}"
d:DesignHeight="500"
d:DesignWidth="800"
x:TypeArguments="local:InstallerVM"
mc:Ignorable="d">
<UserControl.Resources>
<Style
@ -41,21 +43,17 @@
</Rectangle.Fill>
</Rectangle>
<local:HeatedBackgroundView
x:Name="HeatedBackground"
Grid.Row="0"
Grid.RowSpan="3"
PercentCompleted="{Binding PercentCompleted}" />
Grid.RowSpan="3" />
<Grid
x:Name="Slideshow"
Grid.Row="1"
Margin="5,0,5,5">
<Border BorderBrush="{StaticResource BorderInterestBrush}" BorderThickness="1,0,1,1">
<Grid>
<local:DetailImageView
Title="{Binding TitleText, Mode=OneWay}"
Author="{Binding AuthorText, Mode=OneWay}"
Description="{Binding Description, Mode=OneWay}"
Image="{Binding Image, Mode=OneWay}" />
<mahapps:ProgressRing Visibility="{Binding LoadingModlist, Mode=OneWay, Converter={StaticResource bool2VisibilityHiddenConverter}}" />
<local:DetailImageView x:Name="DetailImage" />
<mahapps:ProgressRing x:Name="ModlistLoadingRing" />
</Grid>
</Border>
<Grid
@ -108,12 +106,12 @@
</Style>
</Grid.Style>
<Button
x:Name="SkipSlideButton"
Grid.Column="3"
Width="60"
Height="60"
Margin="6"
Background="{StaticResource BackgroundBrush}"
Command="{Binding Slideshow.SlideShowNextItemCommand}"
Style="{StaticResource CircleButtonStyle}"
ToolTip="Skip to the next mod">
<icon:PackIconFontAwesome
@ -126,17 +124,7 @@
Grid.Column="2"
Margin="6"
Background="{StaticResource BackgroundBrush}"
IsChecked="{Binding Slideshow.Enable}">
<ToggleButton.Style>
<Style BasedOn="{StaticResource SlideshowButton}" TargetType="ToggleButton">
<Setter Property="ToolTip" Value="Play slideshow" />
<Style.Triggers>
<DataTrigger Binding="{Binding Slideshow.Enable}" Value="True">
<Setter Property="ToolTip" Value="Pause slideshow" />
</DataTrigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
Style="{StaticResource SlideshowButton}">
<icon:PackIconMaterial>
<icon:PackIconMaterial.Style>
<Style TargetType="icon:PackIconMaterial">
@ -151,32 +139,22 @@
</icon:PackIconMaterial>
</ToggleButton>
<Button
x:Name="OpenWebsite"
Grid.Column="1"
Margin="6"
Background="{StaticResource BackgroundBrush}"
Command="{Binding Slideshow.VisitNexusSiteCommand}"
Style="{StaticResource SlideshowButton}"
ToolTip="Open Nexus Website">
ToolTip="Open mod's website">
<icon:PackIconMaterial
Width="28"
Height="28"
Kind="Web" />
</Button>
<ToggleButton
x:Name="ShowNSFWButton"
Grid.Column="0"
Background="{StaticResource BackgroundBrush}"
IsChecked="{Binding Slideshow.ShowNSFW}"
ToolTip="Show NSFW mods">
<ToggleButton.Style>
<Style BasedOn="{StaticResource SlideshowButton}" TargetType="ToggleButton">
<Setter Property="ToolTip" Value="Show NSFW mods" />
<Style.Triggers>
<DataTrigger Binding="{Binding Slideshow.ShowNSFW}" Value="True">
<Setter Property="ToolTip" Value="Hide NSFW mods" />
</DataTrigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
Style="{StaticResource SlideshowButton}">
<Grid>
<TextBlock
Margin="4"
@ -187,24 +165,22 @@
FontWeight="Bold"
Text="NSFW" />
<icon:PackIconOcticons
x:Name="NSFWSlashIcon"
Width="40"
Height="40"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="#88FFFFFF"
Kind="CircleSlash"
Visibility="{Binding Slideshow.ShowNSFW, Converter={StaticResource bool2VisibilityConverter}, ConverterParameter=False}" />
Kind="CircleSlash" />
</Grid>
</ToggleButton>
</Grid>
</Grid>
<!-- Comes after slideshow control, so that any effects/overlap goes on top -->
<local:TopProgressView
Title="{Binding ModListName}"
x:Name="TopProgressBar"
Grid.Row="0"
Grid.RowSpan="2"
ProgressPercent="{Binding PercentCompleted}"
StatePrefixTitle="{Binding ProgressTitle}">
Grid.RowSpan="2">
<!-- Readd when Pause/Stop implementations added -->
<!--<Button Grid.Column="2"
ToolTip="Pause Installation"
@ -234,17 +210,16 @@
Margin="7,5,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Command="{Binding BackCommand}"
Style="{StaticResource IconCircleButtonStyle}"
ToolTip="Back to main menu">
<icon:PackIconMaterial Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Kind="ArrowLeft" />
</Button>
<!-- Bottom Area -->
<Grid
x:Name="BottomButtonInputGrid"
Grid.Row="2"
Margin="5,0,5,5"
ClipToBounds="True"
Visibility="{Binding StartedInstallation, Converter={StaticResource bool2VisibilityConverter}, ConverterParameter=False}">
ClipToBounds="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="4" />
@ -257,9 +232,9 @@
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button
x:Name="OpenReadmePreInstallButton"
Grid.Row="0"
Margin="30,5"
Command="{Binding OpenReadmeCommand}"
FontSize="20"
Style="{StaticResource LargeButtonStyle}"
ToolTip="Open the readme for the modlist">
@ -282,9 +257,9 @@
</Grid>
</Button>
<Button
x:Name="VisitWebsitePreInstallButton"
Grid.Row="1"
Margin="30,5"
Command="{Binding VisitWebsiteCommand}"
FontSize="20"
Style="{StaticResource LargeButtonStyle}"
ToolTip="Open the webpage for the modlist">
@ -307,9 +282,9 @@
</Grid>
</Button>
<Button
x:Name="ShowManifestPreInstallButton"
Grid.Row="2"
Margin="30,5"
Command="{Binding ShowReportCommand}"
FontSize="20"
Style="{StaticResource LargeButtonStyle}"
ToolTip="Open an explicit listing of all actions this modlist will take">
@ -345,8 +320,7 @@
Grid.Column="0"
Margin="5"
VerticalAlignment="Center"
Background="Transparent"
Visibility="{Binding StartedInstallation, Converter={StaticResource bool2VisibilityConverter}, ConverterParameter=False}">
Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
@ -358,7 +332,7 @@
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle Grid.Row="0" Height="{Binding Installer.ConfigVisualVerticalOffset, Mode=OneWay}" />
<Rectangle x:Name="InstallConfigSpacer" Grid.Row="0" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
@ -368,18 +342,18 @@
Text="Target Modlist"
TextAlignment="Center" />
<local:FilePicker
x:Name="ModListLocationPicker"
Grid.Row="1"
Grid.Column="2"
Height="30"
VerticalAlignment="Center"
FontSize="14"
PickerVM="{Binding ModListLocation}" />
FontSize="14" />
<ContentPresenter
x:Name="InstallerCustomizationContent"
Grid.Row="3"
Grid.Column="0"
Grid.ColumnSpan="3"
VerticalAlignment="Top"
Content="{Binding Installer}">
VerticalAlignment="Top">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type local:MO2InstallerVM}">
<local:MO2InstallerConfigView />
@ -406,38 +380,44 @@
</ContentPresenter>
</Grid>
<local:BeginButton
x:Name="BeginButton"
Grid.Column="2"
Margin="0,0,25,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Command="{Binding BeginCommand, Mode=OneWay}" />
VerticalAlignment="Center" />
</Grid>
</Grid>
<Grid
x:Name="MidInstallDisplayGrid"
Grid.Row="2"
Margin="5,0,5,5"
Visibility="{Binding StartedInstallation, Converter={StaticResource bool2VisibilityConverter}, FallbackValue=Hidden}">
Margin="5,0,5,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<local:LogView Grid.Column="0" ProgressPercent="{Binding PercentCompleted, Mode=OneWay}" />
<local:LogView x:Name="LogView" Grid.Column="0" />
<local:CpuView
x:Name="CpuView"
Grid.Column="2"
ProgressPercent="{Binding PercentCompleted, Mode=OneWay}"
SettingsHook="{Binding MWVM.Settings}"
ViewModel="{Binding}"
Visibility="{Binding ActiveGlobalUserIntervention, Converter={StaticResource IsNotNullVisibilityConverter}, ConverterParameter=False}" />
<local:AttentionBorder Grid.Column="2" Visibility="{Binding ActiveGlobalUserIntervention, Converter={StaticResource IsNotNullVisibilityConverter}}">
<local:AttentionBorder.DisplayContent>
<Grid>
<local:ConfirmationInterventionView DataContext="{Binding ActiveGlobalUserIntervention}" Visibility="{Binding ActiveGlobalUserIntervention, Converter={StaticResource IsTypeVisibilityConverter}, ConverterParameter={x:Type common:ConfirmationIntervention}}" />
<local:ConfirmUpdateOfExistingInstallView Visibility="{Binding ActiveGlobalUserIntervention, Converter={StaticResource IsTypeVisibilityConverter}, ConverterParameter={x:Type lib:ConfirmUpdateOfExistingInstall}}" />
</Grid>
</local:AttentionBorder.DisplayContent>
ViewModel="{Binding}" />
<local:AttentionBorder
x:Name="UserInterventionsControl"
Grid.Column="2"
Content="{Binding ActiveGlobalUserIntervention}">
<local:AttentionBorder.Resources>
<DataTemplate DataType="{x:Type common:ConfirmationIntervention}">
<local:ConfirmationInterventionView ViewModel="{Binding}" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:ConfirmUpdateOfExistingInstallVM}">
<local:ConfirmUpdateOfExistingInstallView ViewModel="{Binding}" />
</DataTemplate>
</local:AttentionBorder.Resources>
</local:AttentionBorder>
<local:InstallationCompleteView Grid.Column="2" Visibility="{Binding Completed, Converter={StaticResource IsNotNullVisibilityConverter}, FallbackValue=Collapsed}" />
<local:InstallationCompleteView
x:Name="InstallComplete"
Grid.Column="2"
ViewModel="{Binding}" />
</Grid>
</Grid>
</UserControl>
</rxui:ReactiveUserControl>

View File

@ -1,15 +1,158 @@
using System.Windows.Controls;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Windows.Controls;
using ReactiveUI;
using System.Windows;
namespace Wabbajack
{
/// <summary>
/// Interaction logic for InstallationView.xaml
/// </summary>
public partial class InstallationView : UserControl
public partial class InstallationView : ReactiveUserControl<InstallerVM>
{
public InstallationView()
{
InitializeComponent();
this.WhenActivated(dispose =>
{
this.MarkAsNeeded<InstallationView, InstallerVM, bool>(this.ViewModel, x => x.Installing);
this.MarkAsNeeded<InstallationView, InstallerVM, bool>(this.ViewModel, x => x.Slideshow.Enable);
// General progress indicators
this.WhenAny(x => x.ViewModel.PercentCompleted)
.Select(x => (double)x)
.BindToStrict(this, x => x.HeatedBackground.PercentCompleted)
.DisposeWith(dispose);
// Top Progress Bar
this.WhenAny(x => x.ViewModel.ModListName)
.BindToStrict(this, x => x.TopProgressBar.Title)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.ProgressTitle)
.BindToStrict(this, x => x.TopProgressBar.StatePrefixTitle)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.PercentCompleted)
.Select(x => (double)x)
.BindToStrict(this, x => x.TopProgressBar.ProgressPercent)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.BackCommand)
.BindToStrict(this, x => x.BackButton.Command)
.DisposeWith(dispose);
// Detail Image
this.WhenAny(x => x.ViewModel.TitleText)
.BindToStrict(this, x => x.DetailImage.Title)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.AuthorText)
.BindToStrict(this, x => x.DetailImage.Author)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Description)
.BindToStrict(this, x => x.DetailImage.Description)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Image)
.BindToStrict(this, x => x.DetailImage.Image)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.LoadingModlist)
.Select(x => x ? Visibility.Visible : Visibility.Collapsed)
.BindToStrict(this, x => x.ModlistLoadingRing.Visibility)
.DisposeWith(dispose);
// Slideshow controls
this.WhenAny(x => x.ViewModel.Slideshow.SlideShowNextItemCommand)
.BindToStrict(this, x => x.SkipSlideButton.Command)
.DisposeWith(dispose);
this.BindStrict(this.ViewModel, x => x.Slideshow.Enable, x => x.PlayPauseButton.IsChecked,
vmToViewConverter: x => x,
viewToVmConverter: x => x ?? true)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Slideshow.Enable)
.Select(enabled =>
{
return $"{(enabled ? "Pause" : "Play")} slideshow";
})
.BindToStrict(this, x => x.PlayPauseButton.ToolTip)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Slideshow.VisitNexusSiteCommand)
.BindToStrict(this, x => x.OpenWebsite.Command)
.DisposeWith(dispose);
this.BindStrict(this.ViewModel, x => x.Slideshow.ShowNSFW, x => x.ShowNSFWButton.IsChecked,
vmToViewConverter: x => x,
viewToVmConverter: x => x ?? true)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Slideshow.ShowNSFW)
.Select(show =>
{
return $"{(show ? "Hide" : "Show")} NSFW mods";
})
.BindToStrict(this, x => x.ShowNSFWButton.ToolTip)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Slideshow.ShowNSFW)
.Select(show => show ? Visibility.Collapsed : Visibility.Visible)
.BindToStrict(this, x => x.NSFWSlashIcon.Visibility)
.DisposeWith(dispose);
// Bottom Input Customization
this.WhenAny(x => x.ViewModel.StartedInstallation)
.Select(started => started ? Visibility.Hidden : Visibility.Visible)
.BindToStrict(this, x => x.BottomButtonInputGrid.Visibility)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.OpenReadmeCommand)
.BindToStrict(this, x => x.OpenReadmePreInstallButton.Command)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.VisitModListWebsiteCommand)
.BindToStrict(this, x => x.VisitWebsitePreInstallButton.Command)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.ShowManifestCommand)
.BindToStrict(this, x => x.ShowManifestPreInstallButton.Command)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.StartedInstallation)
.Select(started => started ? Visibility.Collapsed : Visibility.Visible)
.BindToStrict(this, x => x.InstallationConfigurationView.Visibility)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Installer.ConfigVisualVerticalOffset)
.Select(i => (double)i)
.BindToStrict(this, x => x.InstallConfigSpacer.Height)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.ModListLocation)
.BindToStrict(this, x => x.ModListLocationPicker.PickerVM)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Installer)
.BindToStrict(this, x => x.InstallerCustomizationContent.Content)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.BeginCommand)
.BindToStrict(this, x => x.BeginButton.Command)
.DisposeWith(dispose);
// Bottom mid-install display
this.WhenAny(x => x.ViewModel.StartedInstallation)
.Select(started => started ? Visibility.Visible : Visibility.Hidden)
.BindToStrict(this, x => x.MidInstallDisplayGrid.Visibility)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.PercentCompleted)
.Select(x => (double)x)
.BindToStrict(this, x => x.LogView.ProgressPercent)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.PercentCompleted)
.Select(f => (double)f)
.BindToStrict(this, x => x.CpuView.ProgressPercent)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.MWVM.Settings)
.BindToStrict(this, x => x.CpuView.SettingsHook)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.ActiveGlobalUserIntervention)
.Select(x => x == null ? Visibility.Visible : Visibility.Collapsed)
.BindToStrict(this, x => x.CpuView.Visibility)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.ActiveGlobalUserIntervention)
.Select(x => x != null ? Visibility.Visible : Visibility.Collapsed)
.BindToStrict(this, x => x.UserInterventionsControl.Visibility)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Completed)
.Select(completed => completed != null ? Visibility.Visible : Visibility.Collapsed)
.BindToStrict(this, x => x.InstallComplete.Visibility)
.DisposeWith(dispose);
});
}
}
}

View File

@ -1,12 +1,15 @@
<UserControl
<rxui:ReactiveUserControl
x:Class="Wabbajack.ConfirmUpdateOfExistingInstallView"
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:lib="clr-namespace:Wabbajack.Lib;assembly=Wabbajack.Lib"
xmlns:local="clr-namespace:Wabbajack"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:rxui="http://reactiveui.net"
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="local:ConfirmUpdateOfExistingInstallVM"
mc:Ignorable="d">
<Grid Margin="10">
<Grid.ColumnDefinitions>
@ -21,6 +24,7 @@
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<TextBlock
x:Name="ShortDescription"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="3"
@ -28,15 +32,15 @@
FontFamily="Lucida Sans"
FontSize="14"
FontWeight="Bold"
Text="{Binding ActiveGlobalUserIntervention.ShortDescription}"
TextWrapping="WrapWithOverflow" />
<TextBlock
x:Name="ExtendedDescription"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="3"
Text="{Binding ActiveGlobalUserIntervention.ExtendedDescription}"
TextWrapping="WrapWithOverflow" />
<CheckBox
x:Name="AutoOverwriteCheckbox"
Grid.Row="2"
Grid.Column="2"
Margin="4"
@ -45,14 +49,14 @@
IsChecked="{Binding Installer.AutomaticallyOverwrite}"
ToolTip="If installing over an existing installation next time, automatically replace it without asking permission." />
<Button
x:Name="CancelButton"
Grid.Row="3"
Grid.Column="0"
Command="{Binding ActiveGlobalUserIntervention.CancelCommand}"
Content="Cancel" />
<Button
x:Name="ConfirmButton"
Grid.Row="3"
Grid.Column="2"
Command="{Binding ActiveGlobalUserIntervention.ConfirmCommand}"
Content="Confirm" />
</Grid>
</UserControl>
</rxui:ReactiveUserControl>

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
@ -12,17 +13,39 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ReactiveUI;
using Wabbajack.Lib;
namespace Wabbajack
{
/// <summary>
/// Interaction logic for ConfirmUpdateOfExistingInstallView.xaml
/// </summary>
public partial class ConfirmUpdateOfExistingInstallView : UserControl
public partial class ConfirmUpdateOfExistingInstallView : ReactiveUserControl<ConfirmUpdateOfExistingInstallVM>
{
public ConfirmUpdateOfExistingInstallView()
{
InitializeComponent();
this.WhenActivated(dispose =>
{
this.WhenAny(x => x.ViewModel.ShortDescription)
.BindToStrict(this, x => x.ShortDescription.Text)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.ExtendedDescription)
.BindToStrict(this, x => x.ExtendedDescription.Text)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Source.ConfirmCommand)
.BindToStrict(this, x => x.ConfirmButton.Command)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Source.CancelCommand)
.BindToStrict(this, x => x.CancelButton.Command)
.DisposeWith(dispose);
this.BindStrict(this.ViewModel, x => x.Installer.AutomaticallyOverwrite, x => x.AutoOverwriteCheckbox.IsChecked,
vmToViewConverter: x => x,
viewToVmConverter: x => x ?? false)
.DisposeWith(dispose);
});
}
}
}

View File

@ -1,12 +1,15 @@
<UserControl
<rxui:ReactiveUserControl
x:Class="Wabbajack.ConfirmationInterventionView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:common="clr-namespace:Wabbajack.Common;assembly=Wabbajack.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Wabbajack"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:rxui="http://reactiveui.net"
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="common:ConfirmationIntervention"
mc:Ignorable="d">
<Grid Margin="10">
<Grid.ColumnDefinitions>
@ -20,6 +23,7 @@
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock
x:Name="ShortDescription"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="3"
@ -27,23 +31,22 @@
FontFamily="Lucida Sans"
FontSize="14"
FontWeight="Bold"
Text="{Binding ShortDescription}"
TextWrapping="WrapWithOverflow" />
<TextBlock
x:Name="ExtendedDescription"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="3"
Text="{Binding ExtendedDescription}"
TextWrapping="WrapWithOverflow" />
<Button
x:Name="CancelButton"
Grid.Row="2"
Grid.Column="0"
Command="{Binding CancelCommand}"
Content="Cancel" />
<Button
x:Name="ConfirmButton"
Grid.Row="2"
Grid.Column="2"
Command="{Binding ConfirmCommand}"
Content="Confirm" />
</Grid>
</UserControl>
</rxui:ReactiveUserControl>

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
@ -12,17 +13,34 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ReactiveUI;
using Wabbajack.Common;
namespace Wabbajack
{
/// <summary>
/// Interaction logic for ConfirmationInterventionView.xaml
/// </summary>
public partial class ConfirmationInterventionView : UserControl
public partial class ConfirmationInterventionView : ReactiveUserControl<ConfirmationIntervention>
{
public ConfirmationInterventionView()
{
InitializeComponent();
this.WhenActivated(dispose =>
{
this.WhenAny(x => x.ViewModel.ShortDescription)
.BindToStrict(this, x => x.ShortDescription.Text)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.ExtendedDescription)
.BindToStrict(this, x => x.ExtendedDescription.Text)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.ConfirmCommand)
.BindToStrict(this, x => x.ConfirmButton.Command)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.CancelCommand)
.BindToStrict(this, x => x.CancelButton.Command)
.DisposeWith(dispose);
});
}
}
}

View File

@ -23,16 +23,16 @@
<ContentPresenter Content="{Binding ActivePane}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type local:CompilerVM}">
<local:CompilerView />
<local:CompilerView ViewModel="{Binding}" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:InstallerVM}">
<local:InstallationView />
<local:InstallationView ViewModel="{Binding}" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:ModeSelectionVM}">
<local:ModeSelectionView />
</DataTemplate>
<DataTemplate DataType="{x:Type local:ModListGalleryVM}">
<local:ModListGalleryView />
<local:ModListGalleryView ViewModel="{Binding}" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:WebBrowserVM}">
<local:WebBrowserView />

View File

@ -1,14 +1,17 @@
<UserControl
<rxui:ReactiveUserControl
x:Class="Wabbajack.ModListGalleryView"
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"
xmlns:system="clr-namespace:System;assembly=mscorlib"
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="local:ModListGalleryVM"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
@ -32,9 +35,9 @@
BorderThickness="1,0,1,1">
<ScrollViewer Background="Transparent" VerticalScrollBarVisibility="Auto">
<ItemsControl
x:Name="ModListGalleryControl"
Margin="0,10,0,0"
HorizontalAlignment="Center"
ItemsSource="{Binding ModLists}">
HorizontalAlignment="Center">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
@ -48,6 +51,17 @@
</ItemsControl>
</ScrollViewer>
</Border>
<mahapps:ProgressRing x:Name="LoadingRing" Grid.Row="1" />
<iconPacks:PackIconControl
x:Name="ErrorIcon"
Grid.Row="1"
Width="55"
Height="55"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="{StaticResource ErrorBrush}"
Kind="{x:Static iconPacks:PackIconMaterialKind.AlertCircle}"
ToolTip="Error loading modlist gallery" />
<local:TopProgressView
Title="Browsing Modlists"
Grid.Row="0"
@ -61,10 +75,9 @@
Margin="7,5,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Command="{Binding BackCommand}"
Style="{StaticResource IconCircleButtonStyle}"
ToolTip="Back to main menu">
<iconPacks:PackIconMaterial Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Kind="ArrowLeft" />
</Button>
</Grid>
</UserControl>
</rxui:ReactiveUserControl>

View File

@ -1,16 +1,45 @@
using System.Diagnostics;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Windows;
using System.Windows.Controls;
using MahApps.Metro.Controls;
using ReactiveUI;
using Wabbajack.Lib.ModListRegistry;
namespace Wabbajack
{
public partial class ModListGalleryView : UserControl
public partial class ModListGalleryView : ReactiveUserControl<ModListGalleryVM>
{
public ModListGalleryView()
{
InitializeComponent();
this.WhenActivated(dispose =>
{
this.WhenAny(x => x.ViewModel.BackCommand)
.BindToStrict(this, x => x.BackButton.Command)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.ModLists)
.BindToStrict(this, x => x.ModListGalleryControl.ItemsSource)
.DisposeWith(dispose);
Observable.CombineLatest(
this.WhenAny(x => x.ViewModel.ModLists.Count)
.Select(x => x > 0),
this.WhenAny(x => x.ViewModel.Error)
.Select(e => e?.Succeeded ?? true),
resultSelector: (hasContent, succeeded) =>
{
return !hasContent && succeeded;
})
.Select(x => x ? Visibility.Visible : Visibility.Collapsed)
.BindToStrict(this, x => x.LoadingRing.Visibility)
.DisposeWith(dispose);
this.WhenAny(x => x.ViewModel.Error)
.Select(e => (e?.Succeeded ?? true) ? Visibility.Collapsed : Visibility.Visible)
.BindToStrict(this, x => x.ErrorIcon.Visibility)
.DisposeWith(dispose);
});
}
}
}

View File

@ -174,6 +174,8 @@
</ApplicationDefinition>
<Compile Include="Extensions\DynamicDataExt.cs" />
<Compile Include="View Models\Settings\AuthorFilesVM.cs" />
<Compile Include="View Models\UserIntervention\ConfirmUpdateOfExistingInstallVM.cs" />
<Compile Include="Views\Common\AttentionBorder.cs" />
<Compile Include="Views\ModListTileView.xaml.cs">
<DependentUpon>ModListTileView.xaml</DependentUpon>
</Compile>
@ -202,9 +204,6 @@
<Compile Include="Views\Settings\SettingsView.xaml.cs">
<DependentUpon>SettingsView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\Common\AttentionBorder.xaml.cs">
<DependentUpon>AttentionBorder.xaml</DependentUpon>
</Compile>
<Compile Include="Converters\IsTypeVisibilityConverter.cs" />
<Compile Include="Views\Common\UnderMaintenanceOverlay.xaml.cs">
<DependentUpon>UnderMaintenanceOverlay.xaml</DependentUpon>
@ -308,6 +307,10 @@
<Compile Include="Views\WebBrowserView.xaml.cs">
<DependentUpon>WebBrowserView.xaml</DependentUpon>
</Compile>
<Page Include="Themes\CustomControls.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ModListTileView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -329,10 +332,6 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Common\AttentionBorder.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\Common\UnderMaintenanceOverlay.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@ -535,7 +534,7 @@
<Version>3.7.0</Version>
</PackageReference>
<PackageReference Include="Fody">
<Version>6.0.6</Version>
<Version>6.0.7</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
@ -569,13 +568,13 @@
<Version>3.0.0-alpha.128</Version>
</PackageReference>
<PackageReference Include="ReactiveUI.Events.WPF">
<Version>11.1.11</Version>
<Version>11.1.12</Version>
</PackageReference>
<PackageReference Include="ReactiveUI.Fody">
<Version>11.1.11</Version>
<Version>11.1.12</Version>
</PackageReference>
<PackageReference Include="ReactiveUI.WPF">
<Version>11.1.11</Version>
<Version>11.1.12</Version>
</PackageReference>
<PackageReference Include="SharpCompress">
<Version>0.24.0</Version>
@ -596,7 +595,7 @@
<Version>1.0.8</Version>
</PackageReference>
<PackageReference Include="YamlDotNet">
<Version>8.0.0</Version>
<Version>8.1.0</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>