diff --git a/src/Helpers.cs b/src/Helpers.cs index c84ccdd..1d98288 100644 --- a/src/Helpers.cs +++ b/src/Helpers.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.IO; using System.Management; using ByteSizeLib; @@ -117,5 +118,22 @@ public static bool IsDirectoryWritable(string folderPath) return true; } } + + public static double GetDouble(string value) + { + double result; + + // Try parsing in the current culture + if (!double.TryParse(value, NumberStyles.Any, CultureInfo.CurrentCulture, out result) && + // Then try in US english + !double.TryParse(value, NumberStyles.Any, CultureInfo.GetCultureInfo("en-US"), out result) && + // Then in neutral language + !double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out result)) + { + result = 0; + } + + return result; + } } } diff --git a/src/LegendaryDownloadManager.xaml b/src/LegendaryDownloadManager.xaml index 597ffd8..010664c 100644 --- a/src/LegendaryDownloadManager.xaml +++ b/src/LegendaryDownloadManager.xaml @@ -6,7 +6,6 @@ xmlns:local="clr-namespace:LegendaryLibraryNS" xmlns:localcon="clr-namespace:LegendaryLibraryNS.Converters" xmlns:sys="clr-namespace:System;assembly=mscorlib" - xmlns:pcmd="clr-namespace:Playnite.Commands" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="800" DataContext="{Binding RelativeSource={RelativeSource Self}}" Name="LegendaryDownloadManagerUC" PreviewKeyDown="LegendaryDownloadManagerUC_PreviewKeyDown"> @@ -18,7 +17,7 @@ - + @@ -37,26 +36,21 @@ - - - - - - - - + + + - - - - + + + + @@ -110,6 +104,18 @@ + + + + + + + + + + + + diff --git a/src/LegendaryDownloadManager.xaml.cs b/src/LegendaryDownloadManager.xaml.cs index 92acb00..756eed4 100644 --- a/src/LegendaryDownloadManager.xaml.cs +++ b/src/LegendaryDownloadManager.xaml.cs @@ -21,6 +21,7 @@ using System.ComponentModel; using LegendaryLibraryNS.Services; using System.Windows.Input; +using Playnite.SDK.Plugins; namespace LegendaryLibraryNS { @@ -34,6 +35,7 @@ public partial class LegendaryDownloadManager : UserControl private ILogger logger = LogManager.GetLogger(); private IPlayniteAPI playniteAPI = API.Instance; public DownloadManagerData.Rootobject downloadManagerData; + public SidebarItem legendaryPanel = LegendaryLibrary.GetPanel(); public LegendaryDownloadManager() { @@ -75,6 +77,11 @@ public LegendaryDownloadManager() var installSizeSplittedString = downloadItem.installSize.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); downloadItem.installSizeNumber = Helpers.ToBytes(double.Parse(installSizeSplittedString[0]), installSizeSplittedString[1].Insert(1, "i")); } + if (downloadItem.status == DownloadStatus.Completed && downloadItem.downloadedNumber == 0) + { + downloadItem.downloadedNumber = downloadItem.downloadSizeNumber; + downloadItem.progress = 100; + } downloadItem.downloadSize = ""; downloadItem.installSize = ""; } @@ -133,11 +140,11 @@ public async void DoNextJobInQueue() var queuedList = downloadManagerData.downloads.Where(i => i.status == DownloadStatus.Queued).ToList(); if (!running) { + DiskSpeedTB.Text = ""; DownloadSpeedTB.Text = ""; - DownloadedTB.Text = ""; ElapsedTB.Text = ""; EtaTB.Text = ""; - DownloadPB.Value = 0; + legendaryPanel.ProgressValue = 0; DescriptionTB.Text = ""; GameTitleTB.Text = ""; } @@ -242,7 +249,14 @@ public async Task Install(DownloadManagerData.Download taskData) var gameID = taskData.gameID; var downloadProperties = taskData.downloadProperties; var gameTitle = taskData.name; - var downloadSizeNumber = taskData.downloadSizeNumber; + double cachedDownloadSizeNumber = taskData.downloadSizeNumber; + double newDownloadSizeNumber = 0; + double downloadCache = 0; + bool downloadSpeedInBits = false; + if (settings.DisplayDownloadSpeedInBits) + { + downloadSpeedInBits = true; + } if (gameID == "eos-overlay") { var fullInstallPath = Path.Combine(downloadProperties.installPath, ".overlay"); @@ -341,7 +355,7 @@ public async Task Install(DownloadManagerData.Download taskData) case StartedCommandEvent started: wantedItem.status = DownloadStatus.Running; GameTitleTB.Text = gameTitle; - DownloadPB.Value = 0; + legendaryPanel.ProgressValue = 0; break; case StandardOutputCommandEvent stdOut: if (downloadProperties.downloadAction == DownloadAction.Repair) @@ -350,7 +364,8 @@ public async Task Install(DownloadManagerData.Download taskData) if (verificationProgressMatch.Length >= 2) { double progress = double.Parse(verificationProgressMatch.Groups[1].Value.Replace("%", ""), CultureInfo.InvariantCulture); - DownloadPB.Value = progress; + wantedItem.progress = progress; + legendaryPanel.ProgressValue = progress; } var verificationFileProgressMatch = Regex.Match(stdOut.Text, @"Verifying large file \""(.*)""\: (\d.*%) \((\d+\.\d+)\/(\d+\.\d+) (\wiB)"); if (verificationFileProgressMatch.Length >= 2) @@ -371,8 +386,13 @@ public async Task Install(DownloadManagerData.Download taskData) var downloadSizeMatch = Regex.Match(stdErr.Text, @"Download size: (\S+) (\wiB)"); if (downloadSizeMatch.Length >= 2) { - downloadSizeNumber = Helpers.ToBytes(double.Parse(downloadSizeMatch.Groups[1].Value, CultureInfo.InvariantCulture), downloadSizeMatch.Groups[2].Value); - wantedItem.downloadSizeNumber = downloadSizeNumber; + newDownloadSizeNumber = Helpers.ToBytes(Helpers.GetDouble(downloadSizeMatch.Groups[1].Value), downloadSizeMatch.Groups[2].Value); + if (newDownloadSizeNumber > cachedDownloadSizeNumber) + { + wantedItem.downloadSizeNumber = newDownloadSizeNumber; + cachedDownloadSizeNumber = newDownloadSizeNumber; + } + downloadCache = cachedDownloadSizeNumber - newDownloadSizeNumber; } var installSizeMatch = Regex.Match(stdErr.Text, @"Install size: (\S+) (\wiB)"); if (installSizeMatch.Length >= 2) @@ -388,7 +408,6 @@ public async Task Install(DownloadManagerData.Download taskData) var progressMatch = Regex.Match(stdErr.Text, @"Progress: (\d.*%)"); if (progressMatch.Length >= 2) { - double progress = double.Parse(progressMatch.Groups[1].Value.Replace("%", ""), CultureInfo.InvariantCulture); if (downloadProperties.downloadAction != DownloadAction.Update) { DescriptionTB.Text = ResourceProvider.GetString(LOC.Legendary3P_PlayniteDownloadingLabel); @@ -397,7 +416,6 @@ public async Task Install(DownloadManagerData.Download taskData) { DescriptionTB.Text = ResourceProvider.GetString(LOC.LegendaryDownloadingUpdate); } - DownloadPB.Value = progress; } var elapsedMatch = Regex.Match(stdErr.Text, @"Running for (\d\d:\d\d:\d\d)"); if (elapsedMatch.Length >= 2) @@ -412,10 +430,14 @@ public async Task Install(DownloadManagerData.Download taskData) var downloadedMatch = Regex.Match(stdErr.Text, @"Downloaded: (\S+) (\wiB)"); if (downloadedMatch.Length >= 2) { - string downloadSize = Helpers.FormatSize(downloadSizeNumber); - string downloaded = Helpers.FormatSize(double.Parse(downloadedMatch.Groups[1].Value, CultureInfo.InvariantCulture), downloadedMatch.Groups[2].Value); - DownloadedTB.Text = downloaded + " / " + downloadSize; - if (downloaded == downloadSize) + double downloadedNumber = Helpers.ToBytes(Helpers.GetDouble(downloadedMatch.Groups[1].Value), downloadedMatch.Groups[2].Value); + double totalDownloadedNumber = downloadedNumber + downloadCache; + wantedItem.downloadedNumber = totalDownloadedNumber; + double newProgress = totalDownloadedNumber / wantedItem.downloadSizeNumber * 100; + wantedItem.progress = newProgress; + legendaryPanel.ProgressValue = newProgress; + + if (totalDownloadedNumber == wantedItem.downloadSizeNumber) { switch (downloadProperties.downloadAction) { @@ -436,14 +458,15 @@ public async Task Install(DownloadManagerData.Download taskData) var downloadSpeedMatch = Regex.Match(stdErr.Text, @"Download\t- (\S+) (\wiB)"); if (downloadSpeedMatch.Length >= 2) { - bool inBits = false; - if (settings.DisplayDownloadSpeedInBits) - { - inBits = true; - } - string downloadSpeed = Helpers.FormatSize(double.Parse(downloadSpeedMatch.Groups[1].Value, CultureInfo.InvariantCulture), downloadSpeedMatch.Groups[2].Value, inBits); + string downloadSpeed = Helpers.FormatSize(Helpers.GetDouble(downloadSpeedMatch.Groups[1].Value), downloadSpeedMatch.Groups[2].Value, downloadSpeedInBits); DownloadSpeedTB.Text = downloadSpeed + "/s"; } + var diskSpeedMatch = Regex.Match(stdErr.Text, @"Disk\t- (\S+) (\wiB)"); + if (diskSpeedMatch.Length >= 2) + { + string diskSpeed = Helpers.FormatSize(Helpers.GetDouble(diskSpeedMatch.Groups[1].Value), diskSpeedMatch.Groups[2].Value, downloadSpeedInBits); + DiskSpeedTB.Text = diskSpeed + "/s"; + } var errorMessage = stdErr.Text; if (errorMessage.Contains("finished successfully") || errorMessage.Contains("already up to date")) { @@ -595,10 +618,10 @@ private void PauseBtn_Click(object sender, RoutedEventArgs e) { if (DownloadsDG.SelectedIndex != -1) { - foreach (var selectedRow in DownloadsDG.SelectedItems.Cast().ToList()) + var runningOrQueuedDownloads = DownloadsDG.SelectedItems.Cast().Where(i => i.status == DownloadStatus.Running || i.status == DownloadStatus.Queued).ToList(); + if (runningOrQueuedDownloads.Count > 0) { - if (selectedRow.status == DownloadStatus.Running || - selectedRow.status == DownloadStatus.Queued) + foreach (var selectedRow in runningOrQueuedDownloads) { if (selectedRow.status == DownloadStatus.Running) { @@ -608,8 +631,9 @@ private void PauseBtn_Click(object sender, RoutedEventArgs e) } selectedRow.status = DownloadStatus.Paused; } + legendaryPanel.ProgressValue = 0; + SaveData(); } - SaveData(); } } @@ -632,11 +656,12 @@ private void CancelDownloadBtn_Click(object sender, RoutedEventArgs e) { if (DownloadsDG.SelectedIndex != -1) { - foreach (var selectedRow in DownloadsDG.SelectedItems.Cast().ToList()) + var cancelableDownloads = DownloadsDG.SelectedItems.Cast() + .Where(i => i.status == DownloadStatus.Running || i.status == DownloadStatus.Queued || i.status == DownloadStatus.Paused) + .ToList(); + if (cancelableDownloads.Count > 0) { - if (selectedRow.status == DownloadStatus.Running || - selectedRow.status == DownloadStatus.Queued || - selectedRow.status == DownloadStatus.Paused) + foreach (var selectedRow in cancelableDownloads) { if (selectedRow.status == DownloadStatus.Running) { @@ -662,16 +687,18 @@ private void CancelDownloadBtn_Click(object sender, RoutedEventArgs e) } } selectedRow.status = DownloadStatus.Canceled; - DownloadSpeedTB.Text = ""; - DownloadedTB.Text = ""; - ElapsedTB.Text = ""; - EtaTB.Text = ""; - DownloadPB.Value = 0; - DescriptionTB.Text = ""; - GameTitleTB.Text = ""; + selectedRow.downloadedNumber = 0; + selectedRow.progress = 0; } + DownloadSpeedTB.Text = ""; + legendaryPanel.ProgressValue = 0; + ElapsedTB.Text = ""; + EtaTB.Text = ""; + DescriptionTB.Text = ""; + GameTitleTB.Text = ""; + DiskSpeedTB.Text = ""; + SaveData(); } - SaveData(); } } diff --git a/src/LegendaryLibrary.cs b/src/LegendaryLibrary.cs index f098872..0ca9a35 100644 --- a/src/LegendaryLibrary.cs +++ b/src/LegendaryLibrary.cs @@ -26,6 +26,7 @@ public class LegendaryLibrary : LibraryPluginBase GetLegendaryDownloadManager(), + ProgressValue = 0, + ProgressMaximum = 100, + }; } public static LegendaryLibrarySettings GetSettings() @@ -47,6 +57,11 @@ public static LegendaryLibrarySettings GetSettings() return Instance.SettingsViewModel?.Settings ?? null; } + public static SidebarItem GetPanel() + { + return Instance.downloadManagerSidebarItem; + } + public static LegendaryDownloadManager GetLegendaryDownloadManager() { if (Instance.LegendaryDownloadManager == null) @@ -356,13 +371,7 @@ public void LoadMenuIcons() public override IEnumerable GetSidebarItems() { - yield return new SidebarItem - { - Title = ResourceProvider.GetString(LOC.LegendaryPanel), - Icon = LegendaryLauncher.Icon, - Type = SiderbarItemType.View, - Opened = () => GetLegendaryDownloadManager() - }; + yield return downloadManagerSidebarItem; } public bool StopDownloadManager(bool displayConfirm = false) diff --git a/src/Localization/en_US.xaml b/src/Localization/en_US.xaml index aa6f6c4..ae6cf7e 100644 --- a/src/Localization/en_US.xaml +++ b/src/Localization/en_US.xaml @@ -26,9 +26,10 @@ Enable Space Available: After Installing: - Downloaded: + Downloaded ETA: Download Speed: + Disk Usage: Elapsed: Verifying... Verifying large file "{0}": {1} @@ -49,6 +50,7 @@ Failed to import game. Reason: {0}. Download Manager Status + Progress Completed Queued Running diff --git a/src/LocalizationKeys.cs b/src/LocalizationKeys.cs index c98ada9..2beb8a3 100644 --- a/src/LocalizationKeys.cs +++ b/src/LocalizationKeys.cs @@ -338,7 +338,7 @@ public static class LOC /// public const string LegendaryAfterInstalling = "LOCLegendaryAfterInstalling"; /// - /// Downloaded: + /// Downloaded /// public const string LegendaryDownloaded = "LOCLegendaryDownloaded"; /// @@ -350,6 +350,10 @@ public static class LOC /// public const string LegendaryDownloadSpeed = "LOCLegendaryDownloadSpeed"; /// + /// Disk Usage: + /// + public const string LegendaryDiskSpeed = "LOCLegendaryDiskSpeed"; + /// /// Elapsed: /// public const string LegendaryElapsed = "LOCLegendaryElapsed"; @@ -430,6 +434,10 @@ public static class LOC /// public const string LegendaryDownloadStatus = "LOCLegendaryDownloadStatus"; /// + /// Progress + /// + public const string LegendaryProgress = "LOCLegendaryProgress"; + /// /// Completed /// public const string LegendaryDownloadCompletedColumn = "LOCLegendaryDownloadCompletedColumn"; diff --git a/src/Models/DownloadManagerData.cs b/src/Models/DownloadManagerData.cs index c7e6072..96f4cbc 100644 --- a/src/Models/DownloadManagerData.cs +++ b/src/Models/DownloadManagerData.cs @@ -57,6 +57,19 @@ public DownloadStatus status set => SetValue(ref _status, value); } + private double _progress; + public double progress + { + get => _progress; + set => SetValue(ref _progress, value); + } + + private double _downloadedNumber; + public double downloadedNumber + { + get => _downloadedNumber; + set => SetValue(ref _downloadedNumber, value); + } public DownloadProperties downloadProperties { get; set; } } }