diff --git a/UnityLauncherPro/Data/DownloadProgress.cs b/UnityLauncherPro/Data/DownloadProgress.cs
new file mode 100644
index 0000000..cf4ba8e
--- /dev/null
+++ b/UnityLauncherPro/Data/DownloadProgress.cs
@@ -0,0 +1,14 @@
+namespace UnityLauncherPro
+{
+ public readonly struct DownloadProgress
+ {
+ public long TotalRead { get; }
+ public long TotalBytes { get; }
+
+ public DownloadProgress(long totalRead, long totalBytes)
+ {
+ TotalRead = totalRead;
+ TotalBytes = totalBytes;
+ }
+ }
+}
\ No newline at end of file
diff --git a/UnityLauncherPro/DownloadProgressWindow.xaml b/UnityLauncherPro/DownloadProgressWindow.xaml
new file mode 100644
index 0000000..538534d
--- /dev/null
+++ b/UnityLauncherPro/DownloadProgressWindow.xaml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/UnityLauncherPro/DownloadProgressWindow.xaml.cs b/UnityLauncherPro/DownloadProgressWindow.xaml.cs
new file mode 100644
index 0000000..14cde99
--- /dev/null
+++ b/UnityLauncherPro/DownloadProgressWindow.xaml.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Windows;
+using System.Windows.Input;
+
+namespace UnityLauncherPro
+{
+ public partial class DownloadProgressWindow
+ {
+ private readonly Action _cancelAction;
+ private readonly string _subjectName;
+ private static MainWindow MainWindow => Tools.mainWindow;
+
+ public DownloadProgressWindow(string subjectName, Action cancelAction = null)
+ {
+ InitializeComponent();
+ _subjectName = subjectName;
+ Title = subjectName;
+ _cancelAction = cancelAction;
+ Topmost = true;
+ Owner = MainWindow;
+ WindowStartupLocation = WindowStartupLocation.CenterOwner;
+ MainWindow.IsEnabled = false;
+ }
+
+ public void UpdateProgress(DownloadProgress downloadProgress)
+ {
+ Title = $"Downloading {_subjectName} ({downloadProgress.TotalRead / 1024d / 1024d:F1} MB / {downloadProgress.TotalBytes / 1024d / 1024d:F1} MB)";
+ var progress = downloadProgress.TotalBytes == 0 ? 0 : downloadProgress.TotalRead * 100d / downloadProgress.TotalBytes;
+ ProgressBar.Value = progress;
+ ProgressText.Text = $"{progress / 100:P1}";
+ }
+
+ private void CancelDownloadClick(object sender, RoutedEventArgs e)
+ {
+ CancelDownload();
+ }
+
+ private void CancelDownload()
+ {
+ _cancelAction?.Invoke();
+ }
+
+ private void Window_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
+ {
+ var window = (Window)sender;
+ window.Topmost = true;
+ }
+
+ protected override void OnClosed(EventArgs e)
+ {
+ base.OnClosed(e);
+ _cancelAction?.Invoke();
+ MainWindow.IsEnabled = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/UnityLauncherPro/Tools.cs b/UnityLauncherPro/Tools.cs
index 6e14e71..3bf346b 100644
--- a/UnityLauncherPro/Tools.cs
+++ b/UnityLauncherPro/Tools.cs
@@ -5,10 +5,12 @@
using System.IO;
using System.Linq;
using System.Net;
+using System.Net.Http;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
+using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
@@ -697,7 +699,7 @@ public static async void DownloadAndInstall(string version)
if (File.Exists(tempFile) == true) File.Delete(tempFile);
// TODO make async
- if (DownloadFile(exeURL, tempFile) == true)
+ if (await DownloadFileAsync(exeURL, tempFile))
{
// get base version, to use for install path
// FIXME check if have any paths?
@@ -737,7 +739,7 @@ public static async void DownloadAndInstall(string version)
static readonly string initFileDefaultURL = "https://raw.githubusercontent.com/unitycoder/UnityInitializeProject/main/Assets/Editor/InitializeProject.cs";
- public static void DownloadInitScript(string currentInitScriptFullPath, string currentInitScriptLocationOrURL)
+ public static async Task DownloadInitScript(string currentInitScriptFullPath, string currentInitScriptLocationOrURL)
{
string currentInitScriptFolder = Path.GetDirectoryName(currentInitScriptFullPath);
string currentInitScriptFile = Path.GetFileName(currentInitScriptFullPath);
@@ -750,7 +752,7 @@ public static void DownloadInitScript(string currentInitScriptFullPath, string c
if (currentInitScriptLocationOrURL.ToLower().StartsWith("http") == true)
{
// download into temp first
- if (DownloadFile(currentInitScriptLocationOrURL, tempFile) == false) return;
+ if (await DownloadFileAsync(currentInitScriptLocationOrURL, tempFile) == false) return;
}
else // file is in local folders/drives/projects
{
@@ -819,25 +821,6 @@ static void DeleteTempFile(string path)
}
}
- static bool DownloadFile(string url, string tempFile)
- {
- bool result = false;
- try
- {
- using (WebClient client = new WebClient())
- {
- client.DownloadFile(url, tempFile);
- // TODO check if actually exists
- result = true;
- }
- }
- catch (Exception e)
- {
- Console.WriteLine("Error> DownloadFile: " + e);
- }
- return result;
- }
-
public static string DownloadHTML(string url)
{
if (string.IsNullOrEmpty(url) == true) return null;
@@ -2228,6 +2211,55 @@ internal static void OpenCustomAssetPath()
}
}
}
+
+ private static async Task DownloadFileAsync(string fileUrl, string destinationPath)
+ {
+ var cancellationTokenSource = new CancellationTokenSource();
+ var fileName = Path.GetFileName(fileUrl);
+ var progressWindow = new DownloadProgressWindow(fileName, () => cancellationTokenSource.Cancel());
+ progressWindow.Show();
+ var result = false;
+ try
+ {
+ using (var client = new HttpClient())
+ using (var response = await client.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead, cancellationTokenSource.Token))
+ {
+ response.EnsureSuccessStatusCode();
+
+ var totalBytes = response.Content.Headers.ContentLength ?? 1;
+ var buffer = new byte[8192];
+ var totalRead = 0;
+
+ using (var contentStream = await response.Content.ReadAsStreamAsync())
+ using (var fileStream = new FileStream(destinationPath, FileMode.Create, FileAccess.Write,
+ FileShare.None, buffer.Length, true))
+ {
+ int bytesRead;
+ while ((bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length, cancellationTokenSource.Token)) > 0)
+ {
+ await fileStream.WriteAsync(buffer, 0, bytesRead, cancellationTokenSource.Token);
+ totalRead += bytesRead;
+ progressWindow.UpdateProgress(new DownloadProgress(totalRead, totalBytes));
+ }
+ result = true;
+ }
+ }
+ }
+ catch (TaskCanceledException)
+ {
+ Console.WriteLine("Download cancelled");
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ }
+ finally
+ {
+ DeleteTempFile(destinationPath);
+ progressWindow.Close();
+ }
+ return result;
+ }
} // class
} // namespace
diff --git a/UnityLauncherPro/UnityLauncherPro.csproj b/UnityLauncherPro/UnityLauncherPro.csproj
index 85adcb0..2be78c7 100644
--- a/UnityLauncherPro/UnityLauncherPro.csproj
+++ b/UnityLauncherPro/UnityLauncherPro.csproj
@@ -114,12 +114,16 @@
+
+
+ DownloadProgressWindow.xaml
+
@@ -141,6 +145,7 @@
UpgradeWindow.xaml
+
Designer
MSBuild:Compile