diff --git a/Wabbajack.Lib/ACompiler.cs b/Wabbajack.Lib/ACompiler.cs index 59d2c751..ee166b94 100644 --- a/Wabbajack.Lib/ACompiler.cs +++ b/Wabbajack.Lib/ACompiler.cs @@ -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(), diff --git a/Wabbajack.Lib/ModListRegistry/ModListMetadata.cs b/Wabbajack.Lib/ModListRegistry/ModListMetadata.cs index 9604ded5..191d1cd2 100644 --- a/Wabbajack.Lib/ModListRegistry/ModListMetadata.cs +++ b/Wabbajack.Lib/ModListRegistry/ModListMetadata.cs @@ -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 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; } + + } + } diff --git a/Wabbajack/View Models/ModListMetadataVM.cs b/Wabbajack/View Models/ModListMetadataVM.cs new file mode 100644 index 00000000..ccaf4026 --- /dev/null +++ b/Wabbajack/View Models/ModListMetadataVM.cs @@ -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; } + + } +} diff --git a/Wabbajack/View Models/ModeSelectionVM.cs b/Wabbajack/View Models/ModeSelectionVM.cs index 7f090b43..7e52dbd4 100644 --- a/Wabbajack/View Models/ModeSelectionVM.cs +++ b/Wabbajack/View Models/ModeSelectionVM.cs @@ -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 ModLists { get; } = new ObservableCollection(ModlistMetadata.LoadFromGithub()); - - [Reactive] - public ModlistMetadata SelectedModList { get; set; } + public ObservableCollection ModLists { get; } private MainWindowVM _mainVM; public ICommand DownloadAndInstallCommand { get; } @@ -26,6 +24,9 @@ namespace Wabbajack public ModeSelectionVM(MainWindowVM mainVM) { _mainVM = mainVM; + + ModLists = new ObservableCollection(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; - } } } diff --git a/Wabbajack/Views/ModeSelectionView.xaml b/Wabbajack/Views/ModeSelectionView.xaml index e0f2cb20..41829ae1 100644 --- a/Wabbajack/Views/ModeSelectionView.xaml +++ b/Wabbajack/Views/ModeSelectionView.xaml @@ -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 @@ - + ScrollViewer.HorizontalScrollBarVisibility="Disabled"> @@ -50,27 +50,27 @@ - + + Source="{Binding Metadata.Links.ImageUri}" /> + Text="{Binding Metadata.Title}" /> + Text="{Binding Metadata.Author}" /> - + + + + + + + -