Skip to content

Commit

Permalink
Improve UI interactivity.
Browse files Browse the repository at this point in the history
  • Loading branch information
Aetopia committed Jun 16, 2024
1 parent 5794d0b commit 2de13e8
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 31 deletions.
2 changes: 1 addition & 1 deletion src/BedrockUpdater.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<ApplicationManifest>Resources/.manifest</ApplicationManifest>
<ApplicationIcon>Resources/.ico</ApplicationIcon>

<AssemblyVersion>1.0.2.0</AssemblyVersion>
<AssemblyVersion>1.0.3.0</AssemblyVersion>
<AssemblyTitle>Bedrock Updater</AssemblyTitle>
<Product>Bedrock Updater</Product>
<Copyright>Copyright (C) 2024</Copyright>
Expand Down
22 changes: 11 additions & 11 deletions src/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class MainForm : Form

[DllImport("Shell32", CharSet = CharSet.Auto, SetLastError = true)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
static extern int ShellMessageBox(IntPtr hAppInst = default, IntPtr hWnd = default, string lpcText = default, string lpcTitle = "Error", int fuStyle = 0x00000010);
static extern int ShellMessageBox(IntPtr hAppInst = default, IntPtr hWnd = default, string lpcText = default, string lpcTitle = "Bedrock Updater", int fuStyle = 0x00000010);

internal MainForm(IEnumerable<string> args)
{
Expand Down Expand Up @@ -77,7 +77,11 @@ internal MainForm(IEnumerable<string> args)
Controls.Add(button);

using WebClient webClient = new();
webClient.DownloadProgressChanged += (sender, e) => progressBar.Value = e.ProgressPercentage;
webClient.DownloadProgressChanged += (sender, e) =>
{
label2.Text = $"Downloading... ({(float)e.BytesReceived / 1024 / 1024:0.0} MB of {(float)e.TotalBytesToReceive / 1024 / 1024:0.0} MB)";
progressBar.Value = e.ProgressPercentage;
};
webClient.DownloadFileCompleted += (sender, e) =>
{
label2.Text = "Installing...";
Expand All @@ -99,30 +103,26 @@ internal MainForm(IEnumerable<string> args)
Shown += async (sender, e) =>
{
var store = await Store.CreateAsync();
var preview = args.FirstOrDefault()?.ToLowerInvariant().Equals("/preview") ?? false;
var preview = args.FirstOrDefault()?.Equals("/preview", StringComparison.OrdinalIgnoreCase) ?? false;

foreach (var product in await store.GetProductsAsync("9wzdncrd1hkw", preview ? "9p5x4qvlc2xr" : "9nblggh2jhxj"))
{
label1.Text = $"Updating {product.Title}...";
label2.Text = "Checking...";
progressBar.Style = ProgressBarStyle.Marquee;

var updateIds = await store.SyncUpdatesAsync(product);
if (!updateIds.Any()) continue;

var count = updateIds.Count();
var identities = await store.SyncUpdatesAsync(product);
progressBar.Style = ProgressBarStyle.Blocks;

for (int i = 0; i < count; i++)
for (int i = 0; i < identities.Count; i++)
{
label1.Text = $"Updating {product.Title}... ({i + 1} of {count})";
label1.Text = $"Updating {product.Title}... ({i + 1} of {identities.Count})";
label2.Text = "Downloading...";
progressBar.Value = 0;

packageUri = new(Path.GetTempFileName());
try
{
await webClient.DownloadFileTaskAsync(await store.GetUrlAsync(updateIds.ElementAt(i)), packageUri.AbsolutePath);
await webClient.DownloadFileTaskAsync(await store.GetUrlAsync(identities[i]), packageUri.AbsolutePath);
deploymentOperation = packageManager.AddPackageAsync(packageUri, null, DeploymentOptions.ForceApplicationShutdown);
deploymentOperation.Progress += (sender, e) => progressBar.Value = (int)e.percentage;
await deploymentOperation;
Expand Down
41 changes: 22 additions & 19 deletions src/Store.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net.Http;
Expand All @@ -22,18 +23,23 @@ interface IProduct
string AppCategoryId { get; }
}

file struct Product(string title, string appCategoryId) : IProduct
file class Product(string title, string appCategoryId) : IProduct
{
public readonly string Title => title;
public string Title => title;

public readonly string AppCategoryId => appCategoryId;
public string AppCategoryId => appCategoryId;
}

file struct UpdateIdentity
interface IUpdateIdentity
{
internal string UpdateId;
string UpdateId { get; }
}

internal bool MainPackage;
file class UpdateIdentity(string updateId, bool mainPackage) : IUpdateIdentity
{
public string UpdateId => updateId;

internal bool MainPackage => mainPackage;
}

file class Update
Expand Down Expand Up @@ -96,7 +102,7 @@ class Store

static readonly string architecture = RuntimeInformation.OSArchitecture.ToString().ToLower();

internal async Task<IEnumerable<IProduct>> GetProductsAsync(params string[] productIds)
internal async Task<ReadOnlyCollection<IProduct>> GetProductsAsync(params string[] productIds)
{
await default(SynchronizationContextRemover);

Expand All @@ -115,7 +121,7 @@ internal async Task<IEnumerable<IProduct>> GetProductsAsync(params string[] prod
(string)((Dictionary<string, object>)((ArrayList)payload["Skus"])[0])["FulfillmentData"])["WuCategoryId"]));
}

return products;
return products.AsReadOnly();
}

static async Task<XmlDocument> PostAsSoapAsync(string content, bool secured = false)
Expand All @@ -137,11 +143,11 @@ internal static async Task<Store> CreateAsync()
return new((await PostAsSoapAsync(Resources.GetCookie)).GetElementsByTagName("EncryptedData")[0].InnerText);
}

internal async Task<string> GetUrlAsync(string updateId)
internal async Task<string> GetUrlAsync(IUpdateIdentity identity)
{
await default(SynchronizationContextRemover);

return (await PostAsSoapAsync(Resources.GetExtendedUpdateInfo2.Replace("{1}", updateId), true)).GetElementsByTagName("Url").Cast<XmlNode>().First(
return (await PostAsSoapAsync(Resources.GetExtendedUpdateInfo2.Replace("{1}", identity.UpdateId), true)).GetElementsByTagName("Url").Cast<XmlNode>().First(
xmlNode => xmlNode.InnerText.StartsWith("http://tlu.dl.delivery.mp.microsoft.com")).InnerText;
}

Expand All @@ -156,7 +162,7 @@ static bool CheckUpdateAvailability(string packageFullName)
new Version(packageIdentity[1]) > new Version(package.Id.Version.Major, package.Id.Version.Minor, package.Id.Version.Build, package.Id.Version.Revision));
}

internal async Task<IEnumerable<string>> SyncUpdatesAsync(IProduct product)
internal async Task<ReadOnlyCollection<IUpdateIdentity>> SyncUpdatesAsync(IProduct product)
{
await default(SynchronizationContextRemover);

Expand All @@ -181,22 +187,19 @@ internal async Task<IEnumerable<string>> SyncUpdatesAsync(IProduct product)
}
}

List<UpdateIdentity> updateIdentities = [];
List<IUpdateIdentity> identities = [];
foreach (XmlNode xmlNode in syncUpdatesResult.GetElementsByTagName("SecuredFragment"))
{
var xmlElement = (XmlElement)xmlNode.ParentNode.ParentNode.ParentNode;
var update = updates.Values.FirstOrDefault(update => update.Id.Equals(xmlElement["ID"].InnerText));
if (update == null) continue;

if (CheckUpdateAvailability(xmlElement.GetElementsByTagName("AppxMetadata")[0].Attributes["PackageMoniker"].InnerText))
updateIdentities.Add(new()
{
UpdateId = xmlElement.GetElementsByTagName("UpdateIdentity")[0].Attributes["UpdateID"].InnerText,
MainPackage = update.MainPackage
});
else if (update.MainPackage) return [];
identities.Add(new UpdateIdentity(xmlElement.GetElementsByTagName("UpdateIdentity")[0].Attributes["UpdateID"].InnerText, update.MainPackage));
else if (update.MainPackage) return new([]);
}
identities.Sort((a, b) => ((UpdateIdentity)a).MainPackage ? 1 : -1);

return updateIdentities.OrderBy(updateIdentity => updateIdentity.MainPackage).Select(updateIdentity => updateIdentity.UpdateId);
return identities.AsReadOnly();
}
}

0 comments on commit 2de13e8

Please sign in to comment.