Modlist gallery wired up again

This commit is contained in:
Justin Swanson
2019-11-30 03:08:04 -06:00
parent 4e9f44824c
commit d2e5aa88d3
16 changed files with 498 additions and 266 deletions

View File

@ -25,7 +25,8 @@ namespace Wabbajack
{ {
compareTo = false; compareTo = false;
} }
return value != null ? Visibility.Visible : Visibility.Collapsed; bool isNull = value != null;
return isNull == compareTo ? Visibility.Visible : Visibility.Collapsed;
} }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)

View File

@ -1,4 +1,4 @@
<ResourceDictionary <ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
@ -45,7 +45,9 @@
<Color x:Key="DarkerSecondary">#095952</Color> <Color x:Key="DarkerSecondary">#095952</Color>
<Color x:Key="OffWhiteSeconday">#cef0ed</Color> <Color x:Key="OffWhiteSeconday">#cef0ed</Color>
<Color x:Key="LightSecondary">#8cede5</Color> <Color x:Key="LightSecondary">#8cede5</Color>
<Color x:Key="IntenseSecondary">#00ffe7</Color>
<Color x:Key="Complementary">#C7FC86</Color> <Color x:Key="Complementary">#C7FC86</Color>
<Color x:Key="IntenseComplementary">#abf74d</Color>
<Color x:Key="Analogous1">#868CFC</Color> <Color x:Key="Analogous1">#868CFC</Color>
<Color x:Key="Analogous2">#F686FC</Color> <Color x:Key="Analogous2">#F686FC</Color>
<Color x:Key="Triadic1">#FC86C7</Color> <Color x:Key="Triadic1">#FC86C7</Color>
@ -115,7 +117,9 @@
<SolidColorBrush x:Key="DarkerSecondaryBrush" Color="{StaticResource DarkerSecondary}" /> <SolidColorBrush x:Key="DarkerSecondaryBrush" Color="{StaticResource DarkerSecondary}" />
<SolidColorBrush x:Key="OffWhiteSecondayBrush" Color="{StaticResource OffWhiteSeconday}" /> <SolidColorBrush x:Key="OffWhiteSecondayBrush" Color="{StaticResource OffWhiteSeconday}" />
<SolidColorBrush x:Key="LightSecondaryBrush" Color="{StaticResource LightSecondary}" /> <SolidColorBrush x:Key="LightSecondaryBrush" Color="{StaticResource LightSecondary}" />
<SolidColorBrush x:Key="IntenseSecondaryBrush" Color="{StaticResource IntenseSecondary}" />
<SolidColorBrush x:Key="ComplementaryBrush" Color="{StaticResource Complementary}" /> <SolidColorBrush x:Key="ComplementaryBrush" Color="{StaticResource Complementary}" />
<SolidColorBrush x:Key="IntenseComplementaryBrush" Color="{StaticResource IntenseComplementary}" />
<SolidColorBrush x:Key="Analogous1Brush" Color="{StaticResource Analogous1}" /> <SolidColorBrush x:Key="Analogous1Brush" Color="{StaticResource Analogous1}" />
<SolidColorBrush x:Key="Analogous2Brush" Color="{StaticResource Analogous2}" /> <SolidColorBrush x:Key="Analogous2Brush" Color="{StaticResource Analogous2}" />
<SolidColorBrush x:Key="Triadic1Brush" Color="{StaticResource Triadic1}" /> <SolidColorBrush x:Key="Triadic1Brush" Color="{StaticResource Triadic1}" />
@ -1516,9 +1520,31 @@
BasedOn="{StaticResource MahApps.Metro.Styles.MetroCircleButtonStyle}" BasedOn="{StaticResource MahApps.Metro.Styles.MetroCircleButtonStyle}"
TargetType="ButtonBase"> TargetType="ButtonBase">
<Setter Property="Focusable" Value="False" /> <Setter Property="Focusable" Value="False" />
<Setter Property="Background" Value="#333333" />
<Style.Triggers> <Style.Triggers>
<Trigger Property="IsEnabled" Value="False"> <Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource DisabledButtonForeground}" /> <Setter Property="Foreground" Value="{StaticResource DisabledButtonForeground}" />
<Setter Property="Background" Value="#222222" />
</Trigger>
</Style.Triggers>
</Style>
<Style
x:Key="IconCircleButtonStyle"
BasedOn="{StaticResource MahApps.Metro.Styles.MetroCircleButtonStyle}"
TargetType="ButtonBase">
<Setter Property="Focusable" Value="False" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="2" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource DisabledButtonForeground}" />
<Setter Property="Background" Value="#222222" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#333333" />
<Setter Property="BorderBrush" Value="{StaticResource GrayBrush7}" />
<Setter Property="Foreground" Value="{StaticResource IntenseComplementaryBrush}" />
</Trigger> </Trigger>
</Style.Triggers> </Style.Triggers>
</Style> </Style>

View File

@ -28,6 +28,7 @@ namespace Wabbajack
public readonly Lazy<CompilerVM> Compiler; public readonly Lazy<CompilerVM> Compiler;
public readonly Lazy<InstallerVM> Installer; public readonly Lazy<InstallerVM> Installer;
public readonly Lazy<ModListGalleryVM> Gallery;
public readonly ModeSelectionVM ModeSelectionVM; public readonly ModeSelectionVM ModeSelectionVM;
public MainWindowVM(MainWindow mainWindow, MainSettings settings) public MainWindowVM(MainWindow mainWindow, MainSettings settings)
@ -36,6 +37,7 @@ namespace Wabbajack
Settings = settings; Settings = settings;
Installer = new Lazy<InstallerVM>(() => new InstallerVM(this)); Installer = new Lazy<InstallerVM>(() => new InstallerVM(this));
Compiler = new Lazy<CompilerVM>(() => new CompilerVM(this)); Compiler = new Lazy<CompilerVM>(() => new CompilerVM(this));
Gallery = new Lazy<ModListGalleryVM>(() => new ModListGalleryVM(this));
ModeSelectionVM = new ModeSelectionVM(this); ModeSelectionVM = new ModeSelectionVM(this);
// Set up logging // Set up logging
@ -74,5 +76,14 @@ namespace Wabbajack
modlistPath = args[2]; modlistPath = args[2];
return true; return true;
} }
public void OpenInstaller(string path)
{
if (path == null) return;
var installer = Installer.Value;
Settings.Installer.LastInstalledListLocation = path;
ActivePane = installer;
installer.ModListPath.TargetPath = path;
}
} }
} }

View File

@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
using DynamicData;
using DynamicData.Binding;
using ReactiveUI;
using Wabbajack.Lib;
using Wabbajack.Lib.ModListRegistry;
namespace Wabbajack
{
public class ModListGalleryVM : ViewModel
{
public MainWindowVM MWVM { get; }
public ObservableCollectionExtended<ModListMetadataVM> ModLists { get; } = new ObservableCollectionExtended<ModListMetadataVM>();
public IReactiveCommand BackCommand { get; }
public IReactiveCommand RefreshCommand { get; }
private int missingHashFallbackCounter;
public ModListGalleryVM(MainWindowVM mainWindowVM)
{
MWVM = mainWindowVM;
BackCommand = ReactiveCommand.Create(
execute: () => mainWindowVM.ActivePane = mainWindowVM.ModeSelectionVM);
RefreshCommand = ReactiveCommand.Create(() => { });
RefreshCommand.StartingExecution()
.StartWith(Unit.Default)
.ObserveOn(RxApp.TaskpoolScheduler)
.Select(_ =>
{
return ModlistMetadata.LoadFromGithub()
.AsObservableChangeSet(x => x.DownloadMetadata?.Hash ?? $"Fallback{missingHashFallbackCounter++}");
})
.Switch()
.ObserveOnGuiThread()
.Transform(m => new ModListMetadataVM(this, m))
.Bind(ModLists)
.Subscribe()
.DisposeWith(CompositeDisposable);
}
}
}

View File

@ -1,7 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Reactive;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -9,121 +11,86 @@ using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using Alphaleonis.Win32.Filesystem; using Alphaleonis.Win32.Filesystem;
using ReactiveUI; using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Wabbajack.Common; using Wabbajack.Common;
using Wabbajack.Lib; using Wabbajack.Lib;
using Wabbajack.Lib.Downloaders; using Wabbajack.Lib.Downloaders;
using Wabbajack.Lib.ModListRegistry; using Wabbajack.Lib.ModListRegistry;
namespace Wabbajack.View_Models namespace Wabbajack
{ {
public enum DownloadStatus
{
NotDownloaded,
Downloading,
Downloaded
}
public class ModListMetadataVM : ViewModel public class ModListMetadataVM : ViewModel
{ {
public ModlistMetadata Metadata { get; } public ModlistMetadata Metadata { get; }
private ModeSelectionVM _parent; private ModListGalleryVM _parent;
public ICommand OpenWebsiteCommand { get; }
public ICommand ExecuteCommand { get; }
public ModListMetadataVM(ModeSelectionVM parent, ModlistMetadata metadata) private readonly ObservableAsPropertyHelper<bool> _Exists;
public bool Exists => _Exists.Value;
public string Location => Path.Combine(Consts.ModListDownloadFolder, Metadata.Links.MachineURL + ExtensionManager.Extension);
[Reactive]
public double ProgressPercent { get; private set; }
public ModListMetadataVM(ModListGalleryVM parent, ModlistMetadata metadata)
{ {
_parent = parent; _parent = parent;
Metadata = metadata; Metadata = metadata;
Click = ReactiveCommand.Create(() => this.DoClick()); OpenWebsiteCommand = ReactiveCommand.Create(() => Process.Start($"https://www.wabbajack.org/modlist/{Metadata.Links.MachineURL}"));
ExecuteCommand = ReactiveCommand.CreateFromObservable<Unit, bool>((unit) =>
Observable.Return(unit)
.WithLatestFrom(
this.WhenAny(x => x.Exists),
(_, e) => e)
// Do any download work on background thread
.ObserveOn(RxApp.TaskpoolScheduler)
.SelectTask(async (exists) =>
{
if (!exists)
{
await Download();
// Return an updated check on exists
return File.Exists(Location);
}
return exists;
})
// Do any install page swap over on GUI thread
.ObserveOnGuiThread()
.Do(exists =>
{
if (exists)
{
_parent.MWVM.OpenInstaller(Path.GetFullPath(Location));
}
}));
_Exists = Observable.Interval(TimeSpan.FromSeconds(0.5))
.Unit()
.StartWith(Unit.Default)
.Select(_ => File.Exists(Location))
.ToProperty(this, nameof(Exists));
} }
private void DoClick() private Task Download()
{ {
switch (Status) ProgressPercent = 0d;
{
case DownloadStatus.NotDownloaded:
Download();
break;
case DownloadStatus.Downloading:
break;
case DownloadStatus.Downloaded:
Install();
break;
default:
throw new ArgumentOutOfRangeException();
}
}
private void Install()
{
_parent.OpenInstaller(Location);
}
private void Download()
{
IsDownloading = true;
var queue = new WorkQueue(1); var queue = new WorkQueue(1);
var sub = queue.Status.Select(i => i.ProgressPercent).ToProperty(this, x => x.DownloadProgress); var sub = queue.Status.Select(i => i.ProgressPercent)
.Subscribe(percent => ProgressPercent = percent);
TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
queue.QueueTask(() => queue.QueueTask(() =>
{ {
var downloader = DownloadDispatcher.ResolveArchive(Metadata.Links.Download); var downloader = DownloadDispatcher.ResolveArchive(Metadata.Links.Download);
downloader.Download(new Archive{ Name = Metadata.Title, Size = Metadata.DownloadMetadata?.Size ?? 0}, Location); downloader.Download(new Archive{ Name = Metadata.Title, Size = Metadata.DownloadMetadata?.Size ?? 0}, Location);
Location.FileHashCached(); Location.FileHashCached();
IsDownloading = false;
sub.Dispose(); sub.Dispose();
tcs.SetResult(true);
}); });
return tcs.Task;
} }
private void UpdateDownloadStatuses()
{
this.RaisePropertyChanged("Status");
this.RaisePropertyChanged("DownloadButtonVisibility");
this.RaisePropertyChanged("DownloadProgressVisibility");
this.RaisePropertyChanged("InstallButtonVisibility");
}
public string Location => Path.Combine(Consts.ModListDownloadFolder, Metadata.Links.MachineURL + ExtensionManager.Extension);
private bool _isDownloading = false;
public bool IsDownloading
{
get => _isDownloading;
private set
{
RaiseAndSetIfChanged(ref _isDownloading, value);
UpdateDownloadStatuses();
}
}
private float _downloadProgress;
public float DownloadProgress
{
get => _downloadProgress;
private set
{
RaiseAndSetIfChanged(ref _downloadProgress, value);
}
}
public DownloadStatus Status
{
get
{
if (IsDownloading) return DownloadStatus.Downloading;
if (!File.Exists(Location)) return DownloadStatus.NotDownloaded;
return Metadata.NeedsDownload(Location) ? DownloadStatus.NotDownloaded : DownloadStatus.Downloaded;
}
}
public Visibility DownloadButtonVisibility => Status == DownloadStatus.NotDownloaded ? Visibility.Visible : Visibility.Collapsed;
public Visibility DownloadProgressVisibility => Status == DownloadStatus.Downloading ? Visibility.Visible : Visibility.Collapsed;
public Visibility InstallButtonVisibility => Status == DownloadStatus.Downloaded ? Visibility.Visible : Visibility.Collapsed;
public ICommand Click { get; }
} }
} }

View File

@ -1,23 +1,18 @@
using Alphaleonis.Win32.Filesystem; using Alphaleonis.Win32.Filesystem;
using ReactiveUI; using ReactiveUI;
using ReactiveUI.Fody.Helpers; using ReactiveUI.Fody.Helpers;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Windows.Input; using System.Windows.Input;
using Wabbajack.Common; using Wabbajack.Common;
using Wabbajack.Lib; using Wabbajack.Lib;
using Wabbajack.Lib.ModListRegistry;
using Wabbajack.View_Models;
namespace Wabbajack namespace Wabbajack
{ {
public class ModeSelectionVM : ViewModel public class ModeSelectionVM : ViewModel
{ {
public ObservableCollection<ModListMetadataVM> ModLists { get; }
private MainWindowVM _mainVM; private MainWindowVM _mainVM;
public ICommand DownloadAndInstallCommand { get; } public ICommand BrowseCommand { get; }
public ICommand InstallCommand { get; } public ICommand InstallCommand { get; }
public ICommand CompileCommand { get; } public ICommand CompileCommand { get; }
@ -25,8 +20,6 @@ namespace Wabbajack
{ {
_mainVM = mainVM; _mainVM = mainVM;
ModLists = new ObservableCollection<ModListMetadataVM>(ModlistMetadata.LoadFromGithub().Select(m => new ModListMetadataVM(this, m)));
InstallCommand = ReactiveCommand.Create( InstallCommand = ReactiveCommand.Create(
execute: () => execute: () =>
{ {
@ -36,23 +29,11 @@ namespace Wabbajack
{ {
path = UIUtils.OpenFileDialog($"*{ExtensionManager.Extension}|*{ExtensionManager.Extension}"); path = UIUtils.OpenFileDialog($"*{ExtensionManager.Extension}|*{ExtensionManager.Extension}");
} }
OpenInstaller(path); _mainVM.OpenInstaller(path);
}); });
CompileCommand = ReactiveCommand.Create( CompileCommand = ReactiveCommand.Create(() => mainVM.ActivePane = mainVM.Compiler.Value);
execute: () => BrowseCommand = ReactiveCommand.Create(() => mainVM.ActivePane = mainVM.Gallery.Value);
{
mainVM.ActivePane = mainVM.Compiler.Value;
});
}
internal void OpenInstaller(string path)
{
if (path == null) return;
var installer = _mainVM.Installer.Value;
_mainVM.Settings.Installer.LastInstalledListLocation = path;
_mainVM.ActivePane = installer;
installer.ModListPath.TargetPath = path;
} }
} }
} }

View File

@ -56,7 +56,7 @@
<Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Value="True" /> <Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Value="True" />
</MultiDataTrigger.Conditions> </MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters> <MultiDataTrigger.Setters>
<Setter Property="Foreground" Value="#00ffe7" /> <Setter Property="Foreground" Value="{StaticResource IntenseSecondaryBrush}" />
</MultiDataTrigger.Setters> </MultiDataTrigger.Setters>
</MultiDataTrigger> </MultiDataTrigger>
</Style.Triggers> </Style.Triggers>
@ -65,11 +65,9 @@
</icon:PackIconMaterial> </icon:PackIconMaterial>
<Button.Style> <Button.Style>
<Style BasedOn="{StaticResource CircleButtonStyle}" TargetType="Button"> <Style BasedOn="{StaticResource CircleButtonStyle}" TargetType="Button">
<Setter Property="Background" Value="#333333" />
<Style.Triggers> <Style.Triggers>
<DataTrigger Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="True"> <DataTrigger Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="BorderBrush" Value="{StaticResource SecondaryBrush}" /> <Setter Property="BorderBrush" Value="{StaticResource SecondaryBrush}" />
<Setter Property="Background" Value="#222222" />
<Setter Property="Effect"> <Setter Property="Effect">
<Setter.Value> <Setter.Value>
<DropShadowEffect <DropShadowEffect

View File

@ -19,7 +19,6 @@
<Rectangle <Rectangle
Grid.Row="2" Grid.Row="2"
Height="25" Height="25"
Margin="6,0"
VerticalAlignment="Top" VerticalAlignment="Top"
IsHitTestVisible="False" IsHitTestVisible="False"
Visibility="{Binding OverhangShadow, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource bool2VisibilityConverter}}"> Visibility="{Binding OverhangShadow, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource bool2VisibilityConverter}}">
@ -29,6 +28,15 @@
<GradientStop Offset="1" Color="#00000000" /> <GradientStop Offset="1" Color="#00000000" />
</LinearGradientBrush> </LinearGradientBrush>
</Rectangle.Fill> </Rectangle.Fill>
<Rectangle.Style>
<Style TargetType="Rectangle">
<Style.Triggers>
<DataTrigger Binding="{Binding ShadowMargin, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Value="True">
<Setter Property="Margin" Value="6,0" />
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle> </Rectangle>
<Rectangle Grid.Row="1" Fill="{StaticResource BackgroundBrush}" /> <Rectangle Grid.Row="1" Fill="{StaticResource BackgroundBrush}" />
<mahapps:MetroProgressBar <mahapps:MetroProgressBar
@ -91,8 +99,14 @@
VerticalAlignment="Center" VerticalAlignment="Center"
FontFamily="Lucida Sans" FontFamily="Lucida Sans"
FontWeight="Black" FontWeight="Black"
Foreground="{StaticResource ComplementaryBrush}"
Text="{Binding StatePrefixTitle, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Text="{Binding StatePrefixTitle, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
TextAlignment="Right" /> TextAlignment="Right"
Visibility="{Binding StatePrefixTitle, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource IsNotNullVisibilityConverter}}" />
<Rectangle
Grid.Column="0"
Width="50"
Visibility="{Binding StatePrefixTitle, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource IsNotNullVisibilityConverter}, ConverterParameter=False}" />
<TextBlock <TextBlock
Grid.Column="1" Grid.Column="1"
Margin="15,0,0,0" Margin="15,0,0,0"

View File

@ -42,6 +42,14 @@ namespace Wabbajack
public static readonly DependencyProperty OverhangShadowProperty = DependencyProperty.Register(nameof(OverhangShadow), typeof(bool), typeof(TopProgressView), public static readonly DependencyProperty OverhangShadowProperty = DependencyProperty.Register(nameof(OverhangShadow), typeof(bool), typeof(TopProgressView),
new FrameworkPropertyMetadata(true)); new FrameworkPropertyMetadata(true));
public bool ShadowMargin
{
get => (bool)GetValue(ShadowMarginProperty);
set => SetValue(ShadowMarginProperty, value);
}
public static readonly DependencyProperty ShadowMarginProperty = DependencyProperty.Register(nameof(ShadowMargin), typeof(bool), typeof(TopProgressView),
new FrameworkPropertyMetadata(true));
private readonly ObservableAsPropertyHelper<double> _ProgressOpacityPercent; private readonly ObservableAsPropertyHelper<double> _ProgressOpacityPercent;
public double ProgressOpacityPercent => _ProgressOpacityPercent.Value; public double ProgressOpacityPercent => _ProgressOpacityPercent.Value;

View File

@ -14,7 +14,7 @@
mc:Ignorable="d"> mc:Ignorable="d">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="45" /> <RowDefinition Height="47" />
<RowDefinition Height="4*" /> <RowDefinition Height="4*" />
<RowDefinition Height="*" MinHeight="150" /> <RowDefinition Height="*" MinHeight="150" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
@ -87,9 +87,8 @@
Margin="12,5,0,0" Margin="12,5,0,0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Top" VerticalAlignment="Top"
Background="{StaticResource ButtonBackground}"
Command="{Binding BackCommand}" Command="{Binding BackCommand}"
Style="{StaticResource CircleButtonStyle}" Style="{StaticResource IconCircleButtonStyle}"
ToolTip="Back to main menu"> ToolTip="Back to main menu">
<icon:PackIconMaterial Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Kind="ArrowLeft" /> <icon:PackIconMaterial Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Kind="ArrowLeft" />
</Button> </Button>

View File

@ -22,7 +22,7 @@
</UserControl.Resources> </UserControl.Resources>
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="45" /> <RowDefinition Height="47" />
<RowDefinition Height="4*" /> <RowDefinition Height="4*" />
<RowDefinition Height="*" MinHeight="150" /> <RowDefinition Height="*" MinHeight="150" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
@ -228,9 +228,8 @@
Margin="7,5,0,0" Margin="7,5,0,0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Top" VerticalAlignment="Top"
Background="{StaticResource ButtonBackground}"
Command="{Binding BackCommand}" Command="{Binding BackCommand}"
Style="{StaticResource CircleButtonStyle}" Style="{StaticResource IconCircleButtonStyle}"
ToolTip="Back to main menu"> ToolTip="Back to main menu">
<icon:PackIconMaterial Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Kind="ArrowLeft" /> <icon:PackIconMaterial Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Kind="ArrowLeft" />
</Button> </Button>

View File

@ -30,6 +30,9 @@
<DataTemplate DataType="{x:Type local:ModeSelectionVM}"> <DataTemplate DataType="{x:Type local:ModeSelectionVM}">
<local:ModeSelectionView /> <local:ModeSelectionView />
</DataTemplate> </DataTemplate>
<DataTemplate DataType="{x:Type local:ModListGalleryVM}">
<local:ModListGalleryView />
</DataTemplate>
</ContentPresenter.Resources> </ContentPresenter.Resources>
</ContentPresenter> </ContentPresenter>
</mahapps:MetroWindow> </mahapps:MetroWindow>

View File

@ -1,116 +1,325 @@
<UserControl x:Class="Wabbajack.Views.ModListGalleryView" <UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x:Class="Wabbajack.ModListGalleryView"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mahapps="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro" xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:local="clr-namespace:Wabbajack" xmlns:local="clr-namespace:Wabbajack"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks" xmlns:mahapps="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:system="clr-namespace:System;assembly=mscorlib" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" xmlns:system="clr-namespace:System;assembly=mscorlib"
d:DesignHeight="450" d:DesignWidth="800"> d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<UserControl.Resources> <UserControl.Resources>
<Color x:Key="TextBackgroundFill">#92000000</Color> <Color x:Key="TextBackgroundFill">#92000000</Color>
<SolidColorBrush x:Key="TextBackgroundFillBrush" Color="{StaticResource TextBackgroundFill}" /> <SolidColorBrush x:Key="TextBackgroundFillBrush" Color="{StaticResource TextBackgroundFill}" />
<Style x:Key="TileStyle" TargetType="{x:Type mahapps:Tile}"> <Color x:Key="TextBackgroundHoverFill">#DF000000</Color>
<Setter Property="Background" Value="Transparent"/> <Style x:Key="BackgroundBlurStyle" TargetType="TextBlock">
</Style> <Setter Property="Background" Value="{StaticResource TextBackgroundFillBrush}" />
<Style x:Key="BackgroundBlurStyle" TargetType="{x:Type TextBlock}"> <Setter Property="Foreground" Value="Transparent" />
<Setter Property="Background" Value="{StaticResource TextBackgroundFillBrush}"/> <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> </Style>
</UserControl.Resources> </UserControl.Resources>
<Grid> <Grid>
<ScrollViewer HorizontalScrollBarVisibility="Disabled" Background="{x:Null}"> <Grid.RowDefinitions>
<ScrollViewer.Resources> <RowDefinition Height="47" />
<system:Double x:Key="{x:Static SystemParameters.VerticalScrollBarWidthKey}">8</system:Double> <RowDefinition Height="*" />
</ScrollViewer.Resources> </Grid.RowDefinitions>
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Left" Margin="8,0,8,0"> <Rectangle
<!--<Image Name="Banner"/> Grid.Row="1"
<Button Width="60" HorizontalAlignment="Left" Command="{Binding BackCommand}" Grid.RowSpan="3"
Margin="4,0,0,8"> Margin="6,0">
<StackPanel Orientation="Horizontal"> <Rectangle.Fill>
<iconPacks:PackIconMaterial Width="20" Height="20" Kind="ArrowLeft" /> <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<TextBlock FontSize="15" Text="Back" Margin="4,0,0,0"/> <GradientStop Offset="0" Color="#123700B3" />
</StackPanel> <GradientStop Offset="1" Color="#00000000" />
</Button>--> </LinearGradientBrush>
<WrapPanel HorizontalAlignment="Center"> </Rectangle.Fill>
</Rectangle>
<Border
Grid.Row="1"
BorderBrush="Transparent"
BorderThickness="1,0,1,1">
<ScrollViewer Background="Transparent" VerticalScrollBarVisibility="Auto">
<ItemsControl <ItemsControl
Name="ItemsControlElement" Margin="0,10,0,0"
Visibility="{Binding ItemsControlVisibility}"
ItemsSource="{Binding ModLists}"
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Top"> ItemsSource="{Binding ModLists}">
<ItemsControl.ItemsPanel> <ItemsControl.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<WrapPanel/> <WrapPanel />
</ItemsPanelTemplate> </ItemsPanelTemplate>
</ItemsControl.ItemsPanel> </ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate> <ItemsControl.ItemTemplate>
<DataTemplate> <DataTemplate>
<mahapps:Tile <Border
Style="{StaticResource TileStyle}" x:Name="ModListTile"
Click="Tile_OnClick" Margin="10"
Width="590" Background="Transparent"
Height="Auto"> BorderThickness="1">
<Grid <Border.Effect>
Width="590" <DropShadowEffect
Background="#222222"> BlurRadius="25"
<Grid.RowDefinitions> Opacity="0.5"
<RowDefinition Height="10*"/> ShadowDepth="5" />
<RowDefinition Height="3*"/> </Border.Effect>
<RowDefinition Height="*"/> <Border.Style>
</Grid.RowDefinitions> <Style TargetType="Border">
<Grid <Setter Property="BorderBrush" Value="{StaticResource ButtonBorder}" />
Grid.Row="0" <Style.Triggers>
Width="590" <DataTrigger Binding="{Binding IsMouseOver, ElementName=ModListTile}" Value="True">
Height="Auto"> <Setter Property="BorderBrush" Value="{StaticResource BorderInterestBrush}" />
<Grid.RowDefinitions> </DataTrigger>
<RowDefinition Height="*"/> </Style.Triggers>
</Grid.RowDefinitions> </Style>
<Viewbox Grid.Row="0" Stretch="Uniform"> </Border.Style>
<Image Source="{Binding Links.ImageUri}"/> <Grid
</Viewbox> Width="570"
<TextBlock FontSize="30" TextWrapping="Wrap" Text="{Binding Title}" Height="440"
Style="{StaticResource BackgroundBlurStyle}" Padding="4,0,4,0" Background="{StaticResource DarkBackgroundBrush}">
Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Bottom" <Grid.RowDefinitions>
FontWeight="Bold"/> <RowDefinition Height="Auto" />
</Grid> <RowDefinition Height="*" />
<Grid Grid.Row="1" Margin="4,0,2,4"> </Grid.RowDefinitions>
<Grid.RowDefinitions> <Grid.ColumnDefinitions>
<RowDefinition Height="20"/> <ColumnDefinition Width="*" />
<RowDefinition Height="*"/> <ColumnDefinition Width="Auto" />
</Grid.RowDefinitions> </Grid.ColumnDefinitions>
<TextBlock FontSize="15" FontStyle="Italic" Grid.Row="0" TextWrapping="Wrap" Text="{Binding Game}"/> <Border
<TextBlock FontSize="15" Grid.Row="1" TextWrapping="Wrap" Text="{Binding Description}"/> Grid.Row="0"
</Grid> Grid.Column="0"
<StackPanel Orientation="Horizontal" Grid.Row="2" Margin="0,0,4,4" HorizontalAlignment="Right"> Grid.ColumnSpan="2"
<Button Click="Info_OnClick" Margin="0,0,4,0"> BorderBrush="{StaticResource ButtonNormalBorder}"
<StackPanel Orientation="Horizontal"> BorderThickness="0,0,0,1">
<!--<TextBlock FontSize="13" TextWrapping="Wrap" Text="More Info" Margin="4,0,4,0"/>--> <Grid ClipToBounds="True">
<iconPacks:PackIconMaterial Width="16" Height="16" Kind="InformationOutline" Margin="0,0,4,0"/> <Viewbox
</StackPanel> Height="340"
</Button> HorizontalAlignment="Center"
<Button Click="Download_OnClick"> VerticalAlignment="Center"
<StackPanel Orientation="Horizontal"> Stretch="UniformToFill">
<!--<TextBlock FontSize="13" TextWrapping="Wrap" Text="Download" Margin="4,0,4,0"/>--> <Image Source="{Binding Metadata.Links.ImageUri}" />
<iconPacks:PackIconMaterial Width="16" Height="16" Kind="Download" /> </Viewbox>
</StackPanel> <Ellipse
</Button> Height="120"
</StackPanel> Margin="-40,0,-40,-60"
</Grid> VerticalAlignment="Bottom"
</mahapps:Tile> Fill="Black"
</DataTemplate> Opacity="0.5">
<Ellipse.Effect>
<BlurEffect Radius="55" />
</Ellipse.Effect>
<Ellipse.Style>
<Style TargetType="Ellipse">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="0.75"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
To="0.5"
Duration="0:0:0.08" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
</Grid>
</Border>
<TextBlock
x:Name="DescriptionTextShadow"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="5"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
FontFamily="Lucida Sans"
FontSize="30"
FontWeight="Bold"
Style="{StaticResource BackgroundBlurStyle}"
Text="{Binding Metadata.Title}"
TextWrapping="Wrap">
<TextBlock.Effect>
<BlurEffect Radius="25" />
</TextBlock.Effect>
</TextBlock>
<TextBlock
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="5"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
FontFamily="Lucida Sans"
FontSize="30"
FontWeight="Bold"
Text="{Binding Metadata.Title}"
TextWrapping="Wrap">
<TextBlock.Effect>
<DropShadowEffect />
</TextBlock.Effect>
</TextBlock>
<mahapps:MetroProgressBar
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
Height="3"
VerticalAlignment="Bottom"
Background="{StaticResource BackgroundBrush}"
Foreground="{StaticResource SecondaryBrush}"
Maximum="1"
Visibility="{Binding IsEnabled, ElementName=ExecuteButton, Converter={StaticResource bool2VisibilityHiddenConverter}, ConverterParameter=False}"
Value="{Binding ProgressPercent, Mode=OneWay}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="8,5"
VerticalAlignment="Center"
FontSize="14"
Text="{Binding Metadata.Description}"
TextWrapping="Wrap" />
<Grid Grid.Row="1" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.Resources>
<Style
x:Key="ModlistButtonStyle"
BasedOn="{StaticResource IconCircleButtonStyle}"
TargetType="Button">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsMouseOver, ElementName=ModListTile}" Value="True" />
<Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="True" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Foreground" Value="{StaticResource IntenseComplementaryBrush}" />
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Button
Grid.Row="0"
Width="40"
Height="40"
Margin="5,0"
VerticalAlignment="Bottom"
Command="{Binding OpenWebsiteCommand}"
Style="{StaticResource ModlistButtonStyle}">
<iconPacks:Material
Width="20"
Height="20"
Kind="Web" />
</Button>
<Button
x:Name="ExecuteButton"
Grid.Row="1"
Width="40"
Height="40"
Margin="5,0"
VerticalAlignment="Top"
Command="{Binding ExecuteCommand}">
<Button.Style>
<Style BasedOn="{StaticResource ModlistButtonStyle}" TargetType="Button">
<Setter Property="Content">
<Setter.Value>
<iconPacks:Material
Width="20"
Height="20"
Kind="Download" />
</Setter.Value>
</Setter>
<Setter Property="ToolTip" Value="Download modlist" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Exists}" Value="True" />
<Condition Binding="{Binding IsEnabled, RelativeSource={RelativeSource Self}}" Value="True" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Content">
<Setter.Value>
<iconPacks:Material
Width="20"
Height="20"
Kind="Play" />
</Setter.Value>
</Setter>
<Setter Property="ToolTip" Value="Install modlist" />
<Setter Property="Padding" Value="3,0,0,0" />
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate> </ItemsControl.ItemTemplate>
</ItemsControl> </ItemsControl>
</WrapPanel> </ScrollViewer>
<!--<Button Width="60" HorizontalAlignment="Left" Command="{Binding BackCommand}" </Border>
Margin="4,0,12,0"> <local:TopProgressView
<StackPanel Orientation="Horizontal"> Title="Browsing Modlists"
<iconPacks:PackIconMaterial Width="20" Height="20" Kind="ArrowLeft" /> Grid.Row="0"
<TextBlock FontSize="15" Text="Back" Margin="4,0,0,0"/> Grid.RowSpan="2"
</StackPanel> ShadowMargin="False" />
</Button>--> <Button
</StackPanel> x:Name="BackButton"
</ScrollViewer> Grid.Row="0"
Width="30"
Height="30"
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> </Grid>
</UserControl> </UserControl>

View File

@ -4,7 +4,7 @@ using System.Windows.Controls;
using MahApps.Metro.Controls; using MahApps.Metro.Controls;
using Wabbajack.Lib.ModListRegistry; using Wabbajack.Lib.ModListRegistry;
namespace Wabbajack.Views namespace Wabbajack
{ {
public partial class ModListGalleryView : UserControl public partial class ModListGalleryView : UserControl
{ {
@ -12,41 +12,5 @@ namespace Wabbajack.Views
{ {
InitializeComponent(); InitializeComponent();
} }
public void Info_OnClick(object sender, RoutedEventArgs e)
{
if (!(sender is Button b)) return;
if (!(b.DataContext is ModlistMetadata mm)) return;
var link = mm.Links.MachineURL;
Process.Start($"https://www.wabbajack.org/modlist/{link}");
}
public void Download_OnClick(object sender, RoutedEventArgs routedEventArgs)
{
/* unsure about this since the downloader changed
if (!(sender is Button b)) return;
if (!(b.DataContext is ModlistMetadata mm)) return;
var link = mm.Links.Download;
if (!Directory.Exists(Consts.ModListDownloadFolder))
Directory.CreateDirectory(Consts.ModListDownloadFolder);
var dest = Path.Combine(Consts.ModListDownloadFolder, mm.Links.MachineURL + ExtensionManager.Extension);
var downloadWindow = new DownloadWindow(link, mm.Title, mm.,dest);
downloadWindow.ShowDialog();*/
}
private void Tile_OnClick(object sender, RoutedEventArgs e)
{
if (!(sender is Tile t)) return;
if (!t.IsFocused) return;
if (!t.IsMouseOver) return;
if (!(t.DataContext is ModlistMetadata mm)) return;
var link = mm.Links.MachineURL;
Process.Start($"https://www.wabbajack.org/modlist/{link}");
}
} }
} }

View File

@ -5,9 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:icon="http://metro.mahapps.com/winfx/xaml/iconpacks" xmlns:icon="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:local="clr-namespace:Wabbajack" xmlns:local="clr-namespace:Wabbajack"
xmlns:ms="clr-namespace:Wabbajack.View_Models"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
d:DataContext="{d:DesignInstance local:ModeSelectionVM}" d:DataContext="{d:DesignInstance local:ModeSelectionVM}"
d:DesignHeight="700" d:DesignHeight="700"
d:DesignWidth="1000" d:DesignWidth="1000"
@ -47,7 +45,8 @@
Margin="15,0" Margin="15,0"
Background="Transparent" Background="Transparent"
BorderBrush="Transparent" BorderBrush="Transparent"
ClipToBounds="False"> ClipToBounds="False"
Command="{Binding BrowseCommand}">
<Button.Template> <Button.Template>
<ControlTemplate TargetType="Button"> <ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"> <Border Background="{TemplateBinding Background}">

View File

@ -169,6 +169,7 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
</ApplicationDefinition> </ApplicationDefinition>
<Compile Include="Converters\EqualsToBoolConverter.cs" /> <Compile Include="Converters\EqualsToBoolConverter.cs" />
<Compile Include="View Models\ModListGalleryVM.cs" />
<Compile Include="View Models\ModListMetadataVM.cs" /> <Compile Include="View Models\ModListMetadataVM.cs" />
<Compile Include="Views\Common\HeatedBackgroundView.xaml.cs"> <Compile Include="Views\Common\HeatedBackgroundView.xaml.cs">
<DependentUpon>HeatedBackgroundView.xaml</DependentUpon> <DependentUpon>HeatedBackgroundView.xaml</DependentUpon>