Rework how we download/install curated lists

This commit is contained in:
Timothy Baldridge 2019-11-28 22:52:33 -07:00
parent edcf75c28c
commit 70fead926f
6 changed files with 194 additions and 69 deletions

View File

@ -106,7 +106,7 @@ namespace Wabbajack.Lib
}
Utils.Log("Exporting ModList metadata");
var metadata = new ModlistMetadata.DownloadMetadata
var metadata = new DownloadMetadata
{
Size = File.GetSize(ModListOutputFile),
Hash = ModListOutputFile.FileHash(),

View File

@ -30,6 +30,9 @@ namespace Wabbajack.Lib.ModListRegistry
[JsonProperty("links")]
public LinksObject Links { get; set; } = new LinksObject();
[JsonProperty("download_metadata")]
public DownloadMetadata DownloadMetadata { get; set; }
public class LinksObject
{
[JsonProperty("image")]
@ -43,26 +46,13 @@ namespace Wabbajack.Lib.ModListRegistry
[JsonProperty("download")]
public string Download { get; set; }
[JsonProperty("download_metadata")]
public DownloadMetadata DownloadMetadata { get; set; }
[JsonProperty("machineURL")]
public string MachineURL { get; set; }
}
public class DownloadMetadata
{
public string Hash { get; set; }
public long Size { get; set; }
public long NumberOfArchives { get; set; }
public long SizeOfArchives { get; set; }
public long NumberOfInstalledFiles { get; set; }
public long SizeOfInstalledFiles { get; set; }
}
public static List<ModlistMetadata> LoadFromGithub()
@ -76,12 +66,24 @@ namespace Wabbajack.Lib.ModListRegistry
public bool NeedsDownload(string modlistPath)
{
if (!File.Exists(modlistPath)) return true;
if (Links.DownloadMetadata?.Hash == null)
if (DownloadMetadata?.Hash == null)
{
return true;
}
return Links.DownloadMetadata.Hash != modlistPath.FileHash();
return DownloadMetadata.Hash != modlistPath.FileHashCached();
}
}
public class DownloadMetadata
{
public string Hash { get; set; }
public long Size { get; set; }
public long NumberOfArchives { get; set; }
public long SizeOfArchives { get; set; }
public long NumberOfInstalledFiles { get; set; }
public long SizeOfInstalledFiles { get; set; }
}
}

View File

@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Alphaleonis.Win32.Filesystem;
using ReactiveUI;
using Wabbajack.Common;
using Wabbajack.Lib;
using Wabbajack.Lib.Downloaders;
using Wabbajack.Lib.ModListRegistry;
namespace Wabbajack.View_Models
{
public enum DownloadStatus
{
NotDownloaded,
Downloading,
Downloaded
}
public class ModListMetadataVM : ViewModel
{
public ModlistMetadata Metadata { get; }
private ModeSelectionVM _parent;
public ModListMetadataVM(ModeSelectionVM parent, ModlistMetadata metadata)
{
_parent = parent;
Metadata = metadata;
Click = ReactiveCommand.Create(() => this.DoClick());
}
private void DoClick()
{
switch (Status)
{
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 sub = queue.Status.Select(i => i.ProgressPercent).ToProperty(this, x => x.DownloadProgress);
queue.QueueTask(() =>
{
var downloader = DownloadDispatcher.ResolveArchive(Metadata.Links.Download);
downloader.Download(new Archive{ Name = Metadata.Title, Size = Metadata.DownloadMetadata?.Size ?? 0}, Location);
Location.FileHashCached();
IsDownloading = false;
sub.Dispose();
});
}
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

@ -8,15 +8,13 @@ using System.Windows.Input;
using Wabbajack.Common;
using Wabbajack.Lib;
using Wabbajack.Lib.ModListRegistry;
using Wabbajack.View_Models;
namespace Wabbajack
{
public class ModeSelectionVM : ViewModel
{
public ObservableCollection<ModlistMetadata> ModLists { get; } = new ObservableCollection<ModlistMetadata>(ModlistMetadata.LoadFromGithub());
[Reactive]
public ModlistMetadata SelectedModList { get; set; }
public ObservableCollection<ModListMetadataVM> ModLists { get; }
private MainWindowVM _mainVM;
public ICommand DownloadAndInstallCommand { get; }
@ -26,6 +24,9 @@ namespace Wabbajack
public ModeSelectionVM(MainWindowVM mainVM)
{
_mainVM = mainVM;
ModLists = new ObservableCollection<ModListMetadataVM>(ModlistMetadata.LoadFromGithub().Select(m => new ModListMetadataVM(this, m)));
InstallCommand = ReactiveCommand.Create(
execute: () =>
{
@ -43,18 +44,9 @@ namespace Wabbajack
{
mainVM.ActivePane = mainVM.Compiler.Value;
});
DownloadAndInstallCommand = ReactiveCommand.Create(
canExecute: this.WhenAny(x => x.SelectedModList)
.Select(x => x != null)
.ObserveOnGuiThread(),
execute: () =>
{
OpenInstaller(Download());
});
}
private void OpenInstaller(string path)
internal void OpenInstaller(string path)
{
if (path == null) return;
var installer = _mainVM.Installer.Value;
@ -62,23 +54,5 @@ namespace Wabbajack
_mainVM.ActivePane = installer;
installer.ModListPath.TargetPath = path;
}
private string Download()
{
if (!Directory.Exists(Consts.ModListDownloadFolder))
Directory.CreateDirectory(Consts.ModListDownloadFolder);
string dest = Path.Combine(Consts.ModListDownloadFolder, SelectedModList.Links.MachineURL + ExtensionManager.Extension);
var window = new DownloadWindow(SelectedModList.Links.Download,
SelectedModList.Title,
SelectedModList.Links.DownloadMetadata?.Size ?? 0,
dest);
window.ShowDialog();
if (window.Result == DownloadWindow.WindowResult.Completed)
return dest;
return null;
}
}
}

View File

@ -4,7 +4,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Wabbajack"
xmlns:ms="clr-namespace:Wabbajack.View_Models"
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:DesignHeight="450"
d:DesignWidth="800"
@ -15,7 +17,6 @@
<RowDefinition Height="*" />
<RowDefinition Height="70" />
<RowDefinition Height="70" />
<RowDefinition Height="70" />
</Grid.RowDefinitions>
<Image
Name="Banner"
@ -34,8 +35,7 @@
Grid.ColumnSpan="3"
ItemsSource="{Binding ModLists}"
ScrollViewer.CanContentScroll="False"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectedItem="{Binding Path=SelectedModList, Mode=TwoWay}">
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="10">
@ -50,27 +50,27 @@
<RowDefinition Height="20" />
<RowDefinition Height="15" />
<RowDefinition Height="150" />
<RowDefinition Height="20" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Image
Grid.Row="0"
Grid.RowSpan="4"
Grid.Column="0"
Source="{Binding Links.ImageUri}" />
Source="{Binding Metadata.Links.ImageUri}" />
<TextBlock
Grid.Row="0"
Grid.Column="2"
FontSize="20"
Text="{Binding Title}" />
Text="{Binding Metadata.Title}" />
<TextBlock
Grid.Row="1"
Grid.Column="2"
Text="{Binding Author}" />
Text="{Binding Metadata.Author}" />
<TextBlock
Grid.Row="1"
Grid.Column="4"
HorizontalAlignment="Right"
Text="{Binding GameName}"
Text="{Binding Metadata.GameName}"
TextAlignment="Right" />
<TextBlock
Grid.Row="2"
@ -78,24 +78,43 @@
Grid.ColumnSpan="3"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Text="{Binding Description}"
Text="{Binding Metadata.Description}"
TextWrapping="Wrap" />
<Button Grid.Row="3" Grid.Column="2">More Info</Button>
<Button Grid.Row="3" Grid.ColumnSpan="5" Content="Download" Visibility="{Binding DownloadButtonVisibility}" Command="{Binding Click}" ></Button>
<mah:MetroProgressBar
Grid.Row="3"
Grid.ColumnSpan="5"
Background="{StaticResource WindowBackgroundBrush}"
BorderThickness="0"
Foreground="Transparent"
Maximum="1"
Value="{Binding DownloadProgress, Mode=OneWay}"
Visibility="{Binding DownloadProgressVisibility}" />
<mah:MetroProgressBar
Grid.Row="3"
Grid.ColumnSpan="5"
Background="Transparent"
BorderThickness="0"
Foreground="{StaticResource PrimaryVariantBrush}"
Maximum="1"
Opacity="{Binding DownloadProgress, Mode=OneWay}"
Value="{Binding DownloadProgress, Mode=OneWay}"
Visibility="{Binding DownloadProgressVisibility}" />
<Label Grid.Row="3"
Grid.ColumnSpan="5"
Content="Downloading..."
HorizontalContentAlignment="Center"
Visibility="{Binding DownloadProgressVisibility}" ></Label>
<Button Grid.Row="3" Grid.ColumnSpan ="5" Content="Install" Visibility="{Binding InstallButtonVisibility}" Command="{Binding Click}"></Button>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button
Name="InstallModlist"
Grid.Row="2"
Grid.ColumnSpan="3"
Margin="2"
Command="{Binding DownloadAndInstallCommand}">
<TextBlock FontSize="40">Download and Install</TextBlock>
</Button>
<Button
Name="InstallFromList"
Grid.Row="3"
Grid.Row="2"
Grid.ColumnSpan="3"
Margin="2"
Command="{Binding InstallCommand}">
@ -103,7 +122,7 @@
</Button>
<Button
Name="CreateModlist"
Grid.Row="4"
Grid.Row="3"
Grid.ColumnSpan="3"
Margin="2"
Command="{Binding CompileCommand}">

View File

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