using NHSE.Sprites; using System; using System.IO; using System.IO.Compression; using System.Threading.Tasks; using System.Windows.Forms; namespace NHSE.WinForms; public sealed partial class ImageFetcher : Form { private const string Filename = "image.zip"; private const int MaxBufferSize = 8192; private static string ZipFilePath => Path.Combine(ItemSprite.PlatformAppDataPath, Filename); private readonly string[] AllHosts; public ImageFetcher() { InitializeComponent(); L_Status.Text = L_FileSize.Text = string.Empty; var splitHosts = AllHosts = LoadHosts(); CB_HostSelect.Items.Clear(); foreach (var host in splitHosts) CB_HostSelect.Items.Add(CleanUrl(host)); CB_HostSelect.SelectedIndex = 0; // set outside of initialise to update filesize via HEAD response CheckFileStatusLabel(); } protected override void OnLoad(EventArgs e) { CenterToParent(); base.OnLoad(e); } private static string[] LoadHosts() { var hosts = Properties.Resources.hosts_images; var splitHosts = hosts.Split(["\r", "\n", "\r\n"], StringSplitOptions.RemoveEmptyEntries); return splitHosts; } private async void B_Download_Click(object sender, EventArgs e) { try { var path = ItemSprite.PlatformAppDataPath; var hostSelected = AllHosts[CB_HostSelect.SelectedIndex]; SetUIDownloadState(false); L_Status.PerformSafely(() => L_Status.Text = "Downloading..."); if (!Directory.Exists(path)) Directory.CreateDirectory(path); using var httpClient = new System.Net.Http.HttpClient(); using var response = await httpClient.GetAsync(hostSelected, System.Net.Http.HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); response.EnsureSuccessStatusCode(); var totalBytes = response.Content.Headers.ContentLength ?? -1L; var canReportProgress = totalBytes != -1 && PBar_MultiUse != null; using (var contentStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) using (var fileStream = new FileStream(ZipFilePath, FileMode.Create, FileAccess.Write, FileShare.None, MaxBufferSize, true)) { var buffer = new byte[MaxBufferSize]; long totalRead = 0; int read; while ((read = await contentStream.ReadAsync(buffer).ConfigureAwait(false)) > 0) { await fileStream.WriteAsync(buffer.AsMemory(0, read)).ConfigureAwait(false); totalRead += read; if (canReportProgress && PBar_MultiUse != null) { int progress = (int)((totalRead * 100) / totalBytes); PBar_MultiUse.PerformSafely(() => PBar_MultiUse.Value = Math.Min(progress, 100)); } } } PBar_MultiUse?.PerformSafely(() => PBar_MultiUse.Value = 100); L_Status.PerformSafely(() => L_Status.Text = "Unzipping..."); UnzipFile(); } catch (Exception ex) { WinFormsUtil.Error(ex.Message, ex.InnerException == null ? string.Empty : ex.InnerException.Message); SetUIDownloadState(true); } } private async void UnzipFile() { try { var outputFolderPath = ItemSprite.PlatformAppDataImagePath; if (Directory.Exists(outputFolderPath)) // overwrite existing Directory.Delete(outputFolderPath, true); Directory.CreateDirectory(outputFolderPath); await Task.Run(() => ZipFile.ExtractToDirectory(ZipFilePath, outputFolderPath)).ConfigureAwait(false); SetUIDownloadState(true, true); } catch (Exception ex) { WinFormsUtil.Error(ex.Message, ex.InnerException == null ? string.Empty : ex.InnerException.Message); SetUIDownloadState(true); } } private void SetUIDownloadState(bool val, bool success = false) { this.PerformSafely(() => ControlBox = val); B_Download.PerformSafely(() => B_Download.Enabled = val); PBar_MultiUse.PerformSafely(() => PBar_MultiUse.Value = 0); L_Status.PerformSafely(() => L_Status.Text = success ? "Images installed successfully." : string.Empty); CheckFileStatusLabel(); if (success) ItemSprite.Initialize(Core.GameInfo.GetStrings("en").itemlist); if (File.Exists(ZipFilePath)) File.Delete(ZipFilePath); } private void CB_HostSelect_SelectedIndexChanged(object sender, EventArgs e) { CheckNetworkFileSizeAsync(); } private async void CheckNetworkFileSizeAsync() { try { L_FileSize.PerformSafely(() => L_FileSize.Text = string.Empty); var host = AllHosts[CB_HostSelect.SelectedIndex]; using var httpClient = new System.Net.Http.HttpClient(); var httpInitialResponse = await httpClient.GetAsync(host).ConfigureAwait(false); var hdr = httpInitialResponse.Content.Headers.ContentLength; if (hdr == null) { L_FileSize.PerformSafely(() => L_FileSize.Text = "Failed."); return; } var totalSizeBytes = Convert.ToInt64(hdr); var totalSizeMb = totalSizeBytes / 1e+6; L_FileSize.PerformSafely(() => L_FileSize.Text = $"{totalSizeMb:0.##}MB"); } catch (Exception ex) { L_FileSize.PerformSafely(() => L_FileSize.Text = ex.Message); } } private static string CleanUrl(string url) { var uri = new Uri(url); return uri.Segments.Length < 2 ? url : $"{uri.Host}/{uri.Segments[1]}"; } private void CheckFileStatusLabel() => L_ImgStatus.PerformSafely(() => L_ImgStatus.Visible = ItemSprite.SingleSpriteExists); }