Unified DLS+ETA progress labels and implemented ETA tracking for extraction, installation, and copy operations
- Removed separate DLS+ETA labels, unified into a clearer single label - Repositioned and resized that label slightly to avoid top of label getting cut off - Added guards to prevent brief progress bar flashes during multi-file downloads - Added ETA for file extraction, APK installation, and OBB copy operations by tracking elapsed time and calculating a smoothed ETA based on the rate of progress
This commit is contained in:
151
ADB.cs
151
ADB.cs
@@ -154,13 +154,13 @@ namespace AndroidSideloader
|
||||
// Copies and installs an APK with real-time progress reporting using AdvancedSharpAdbClient
|
||||
public static async Task<ProcessOutput> SideloadWithProgressAsync(
|
||||
string path,
|
||||
Action<int> progressCallback = null,
|
||||
Action<int, TimeSpan?> progressCallback = null, // Now includes ETA
|
||||
Action<string> statusCallback = null,
|
||||
string packagename = "",
|
||||
string gameName = "")
|
||||
{
|
||||
statusCallback?.Invoke("Installing APK...");
|
||||
progressCallback?.Invoke(0);
|
||||
progressCallback?.Invoke(0, null);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -180,21 +180,81 @@ namespace AndroidSideloader
|
||||
int lastReportedPercent = -1;
|
||||
const int ThrottleMs = 100; // Update UI at most every 100ms
|
||||
|
||||
// ETA tracking with smoothing
|
||||
DateTime installStart = DateTime.UtcNow;
|
||||
int etaLastPercent = 0;
|
||||
DateTime etaLastPercentTime = DateTime.UtcNow;
|
||||
double smoothedSecondsPerPercent = 0;
|
||||
TimeSpan? lastReportedEta = null;
|
||||
const double SmoothingAlpha = 0.15; // Lower = smoother, less responsive
|
||||
const double EtaChangeThreshold = 0.10; // Only update if ETA changes by >10%
|
||||
|
||||
// Create install progress handler
|
||||
Action<InstallProgressEventArgs> installProgress = (args) =>
|
||||
{
|
||||
int percent = 0;
|
||||
string status = null;
|
||||
TimeSpan? eta = null;
|
||||
|
||||
switch (args.State)
|
||||
{
|
||||
case PackageInstallProgressState.Preparing:
|
||||
percent = 0;
|
||||
status = "Preparing...";
|
||||
installStart = DateTime.UtcNow;
|
||||
etaLastPercent = 0;
|
||||
etaLastPercentTime = installStart;
|
||||
smoothedSecondsPerPercent = 0;
|
||||
lastReportedEta = null;
|
||||
break;
|
||||
case PackageInstallProgressState.Uploading:
|
||||
percent = (int)Math.Round(args.UploadProgress);
|
||||
status = $"Installing · {args.UploadProgress:F0}%";
|
||||
|
||||
// Calculate ETA with smoothing
|
||||
if (percent > etaLastPercent && percent < 100)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
double secondsForThisChunk = (now - etaLastPercentTime).TotalSeconds;
|
||||
int percentGained = percent - etaLastPercent;
|
||||
|
||||
if (percentGained > 0 && secondsForThisChunk > 0)
|
||||
{
|
||||
double secondsPerPercent = secondsForThisChunk / percentGained;
|
||||
|
||||
// Exponential smoothing
|
||||
if (smoothedSecondsPerPercent == 0)
|
||||
smoothedSecondsPerPercent = secondsPerPercent;
|
||||
else
|
||||
smoothedSecondsPerPercent = SmoothingAlpha * secondsPerPercent + (1 - SmoothingAlpha) * smoothedSecondsPerPercent;
|
||||
|
||||
int remainingPercent = 100 - percent;
|
||||
double etaSeconds = remainingPercent * smoothedSecondsPerPercent;
|
||||
var newEta = TimeSpan.FromSeconds(Math.Max(0, etaSeconds));
|
||||
|
||||
// Only update if significant change
|
||||
if (!lastReportedEta.HasValue ||
|
||||
Math.Abs(newEta.TotalSeconds - lastReportedEta.Value.TotalSeconds) / Math.Max(1, lastReportedEta.Value.TotalSeconds) > EtaChangeThreshold)
|
||||
{
|
||||
eta = newEta;
|
||||
lastReportedEta = eta;
|
||||
}
|
||||
else
|
||||
{
|
||||
eta = lastReportedEta; // Keep previous ETA
|
||||
}
|
||||
|
||||
etaLastPercent = percent;
|
||||
etaLastPercentTime = now;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
eta = lastReportedEta;
|
||||
}
|
||||
|
||||
status = eta.HasValue && eta.Value.TotalSeconds > 0
|
||||
? $"Installing · {percent}% · ETA: {eta.Value:mm\\:ss}"
|
||||
: $"Installing · {percent}%";
|
||||
break;
|
||||
case PackageInstallProgressState.Installing:
|
||||
percent = 100;
|
||||
@@ -209,17 +269,17 @@ namespace AndroidSideloader
|
||||
break;
|
||||
}
|
||||
|
||||
// Throttle updates: only update if enough time passed or percent changed
|
||||
var now = DateTime.UtcNow;
|
||||
bool shouldUpdate = (now - lastProgressUpdate).TotalMilliseconds >= ThrottleMs
|
||||
// Throttle updates
|
||||
var updateNow = DateTime.UtcNow;
|
||||
bool shouldUpdate = (updateNow - lastProgressUpdate).TotalMilliseconds >= ThrottleMs
|
||||
|| percent != lastReportedPercent
|
||||
|| args.State != PackageInstallProgressState.Uploading;
|
||||
|
||||
if (shouldUpdate)
|
||||
{
|
||||
lastProgressUpdate = now;
|
||||
lastProgressUpdate = updateNow;
|
||||
lastReportedPercent = percent;
|
||||
progressCallback?.Invoke(percent);
|
||||
progressCallback?.Invoke(percent, eta);
|
||||
if (status != null) statusCallback?.Invoke(status);
|
||||
}
|
||||
};
|
||||
@@ -230,7 +290,7 @@ namespace AndroidSideloader
|
||||
packageManager.InstallPackage(path, installProgress);
|
||||
});
|
||||
|
||||
progressCallback?.Invoke(100);
|
||||
progressCallback?.Invoke(100, null);
|
||||
statusCallback?.Invoke("");
|
||||
|
||||
return new ProcessOutput($"{gameName}: Success\n");
|
||||
@@ -269,26 +329,22 @@ namespace AndroidSideloader
|
||||
var client = GetAdbClient();
|
||||
var packageManager = new PackageManager(client, device);
|
||||
|
||||
// Backup save data
|
||||
statusCallback?.Invoke("Backing up save data...");
|
||||
_ = RunAdbCommandToString($"pull \"/sdcard/Android/data/{MainForm.CurrPCKG}\" \"{Environment.CurrentDirectory}\"");
|
||||
|
||||
// Uninstall
|
||||
statusCallback?.Invoke("Uninstalling old version...");
|
||||
packageManager.UninstallPackage(packagename);
|
||||
|
||||
// Reinstall with progress
|
||||
statusCallback?.Invoke("Reinstalling game...");
|
||||
Action<InstallProgressEventArgs> reinstallProgress = (args) =>
|
||||
{
|
||||
if (args.State == PackageInstallProgressState.Uploading)
|
||||
{
|
||||
progressCallback?.Invoke((int)Math.Round(args.UploadProgress));
|
||||
progressCallback?.Invoke((int)Math.Round(args.UploadProgress), null);
|
||||
}
|
||||
};
|
||||
packageManager.InstallPackage(path, reinstallProgress);
|
||||
|
||||
// Restore save data
|
||||
statusCallback?.Invoke("Restoring save data...");
|
||||
_ = RunAdbCommandToString($"push \"{Environment.CurrentDirectory}\\{MainForm.CurrPCKG}\" /sdcard/Android/data/");
|
||||
|
||||
@@ -298,7 +354,7 @@ namespace AndroidSideloader
|
||||
Directory.Delete(directoryToDelete, true);
|
||||
}
|
||||
|
||||
progressCallback?.Invoke(100);
|
||||
progressCallback?.Invoke(100, null);
|
||||
return new ProcessOutput($"{gameName}: Reinstall: Success\n", "");
|
||||
}
|
||||
catch (Exception reinstallEx)
|
||||
@@ -314,7 +370,7 @@ namespace AndroidSideloader
|
||||
// Copies OBB folder with real-time progress reporting using AdvancedSharpAdbClient
|
||||
public static async Task<ProcessOutput> CopyOBBWithProgressAsync(
|
||||
string localPath,
|
||||
Action<int> progressCallback = null,
|
||||
Action<int, TimeSpan?> progressCallback = null, // Now includes ETA
|
||||
Action<string> statusCallback = null,
|
||||
string gameName = "")
|
||||
{
|
||||
@@ -337,7 +393,7 @@ namespace AndroidSideloader
|
||||
string remotePath = $"/sdcard/Android/obb/{folderName}";
|
||||
|
||||
statusCallback?.Invoke($"Preparing: {folderName}");
|
||||
progressCallback?.Invoke(0);
|
||||
progressCallback?.Invoke(0, null);
|
||||
|
||||
// Delete existing OBB folder and create new one
|
||||
ExecuteShellCommand(client, device, $"rm -rf \"{remotePath}\"");
|
||||
@@ -353,6 +409,16 @@ namespace AndroidSideloader
|
||||
int lastReportedPercent = -1;
|
||||
const int ThrottleMs = 100; // Update UI at most every 100ms
|
||||
|
||||
// ETA tracking with smoothing
|
||||
DateTime copyStart = DateTime.UtcNow;
|
||||
int etaLastPercent = 0;
|
||||
DateTime etaLastPercentTime = DateTime.UtcNow;
|
||||
double smoothedSecondsPerPercent = 0;
|
||||
TimeSpan? lastReportedEta = null;
|
||||
TimeSpan? currentEta = null;
|
||||
const double SmoothingAlpha = 0.15; // Lower = smoother, less responsive
|
||||
const double EtaChangeThreshold = 0.10; // 10% change threshold
|
||||
|
||||
statusCallback?.Invoke($"Copying: {folderName}");
|
||||
|
||||
using (var syncService = new SyncService(client, device))
|
||||
@@ -385,16 +451,54 @@ namespace AndroidSideloader
|
||||
int overallPercentInt = (int)Math.Round(overallPercent);
|
||||
overallPercentInt = Math.Max(0, Math.Min(100, overallPercentInt));
|
||||
|
||||
// Throttle updates: only update if enough time passed or percent changed
|
||||
// Calculate ETA with smoothing
|
||||
if (overallPercentInt > etaLastPercent && overallPercentInt < 100)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
bool shouldUpdate = (now - lastProgressUpdate).TotalMilliseconds >= ThrottleMs
|
||||
double secondsForThisChunk = (now - etaLastPercentTime).TotalSeconds;
|
||||
int percentGained = overallPercentInt - etaLastPercent;
|
||||
|
||||
if (percentGained > 0 && secondsForThisChunk > 0)
|
||||
{
|
||||
double secondsPerPercent = secondsForThisChunk / percentGained;
|
||||
|
||||
// Exponential smoothing
|
||||
if (smoothedSecondsPerPercent == 0)
|
||||
smoothedSecondsPerPercent = secondsPerPercent;
|
||||
else
|
||||
smoothedSecondsPerPercent = SmoothingAlpha * secondsPerPercent + (1 - SmoothingAlpha) * smoothedSecondsPerPercent;
|
||||
|
||||
int remainingPercent = 100 - overallPercentInt;
|
||||
double etaSeconds = remainingPercent * smoothedSecondsPerPercent;
|
||||
var newEta = TimeSpan.FromSeconds(Math.Max(0, etaSeconds));
|
||||
|
||||
// Only update if significant change
|
||||
if (!lastReportedEta.HasValue ||
|
||||
Math.Abs(newEta.TotalSeconds - lastReportedEta.Value.TotalSeconds) / Math.Max(1, lastReportedEta.Value.TotalSeconds) > EtaChangeThreshold)
|
||||
{
|
||||
currentEta = newEta;
|
||||
lastReportedEta = currentEta;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentEta = lastReportedEta;
|
||||
}
|
||||
|
||||
etaLastPercent = overallPercentInt;
|
||||
etaLastPercentTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
// Throttle updates
|
||||
var now2 = DateTime.UtcNow;
|
||||
bool shouldUpdate = (now2 - lastProgressUpdate).TotalMilliseconds >= ThrottleMs
|
||||
|| overallPercentInt != lastReportedPercent;
|
||||
|
||||
if (shouldUpdate)
|
||||
{
|
||||
lastProgressUpdate = now;
|
||||
lastProgressUpdate = now2;
|
||||
lastReportedPercent = overallPercentInt;
|
||||
progressCallback?.Invoke(overallPercentInt);
|
||||
progressCallback?.Invoke(overallPercentInt, currentEta);
|
||||
statusCallback?.Invoke(fileName);
|
||||
}
|
||||
};
|
||||
@@ -414,13 +518,11 @@ namespace AndroidSideloader
|
||||
});
|
||||
}
|
||||
|
||||
// Mark this file as fully transferred
|
||||
transferredBytes += fileSize;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure final 100% and clear status
|
||||
progressCallback?.Invoke(100);
|
||||
progressCallback?.Invoke(100, null);
|
||||
statusCallback?.Invoke("");
|
||||
|
||||
return new ProcessOutput($"{gameName}: OBB transfer: Success\n", "");
|
||||
@@ -428,7 +530,6 @@ namespace AndroidSideloader
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log($"CopyOBBWithProgressAsync error: {ex.Message}", LogLevel.ERROR);
|
||||
|
||||
return new ProcessOutput("", $"{gameName}: OBB transfer: Failed: {ex.Message}\n");
|
||||
}
|
||||
}
|
||||
|
||||
257
MainForm.Designer.cs
generated
257
MainForm.Designer.cs
generated
@@ -34,9 +34,7 @@ namespace AndroidSideloader
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.m_combo = new SergeUtils.EasyCompletionComboBox();
|
||||
this.progressBar = new AndroidSideloader.ModernProgressBar();
|
||||
this.speedLabel = new System.Windows.Forms.Label();
|
||||
this.etaLabel = new System.Windows.Forms.Label();
|
||||
this.freeDisclaimer = new System.Windows.Forms.Label();
|
||||
this.gamesQueListBox = new System.Windows.Forms.ListBox();
|
||||
this.devicesComboBox = new System.Windows.Forms.ComboBox();
|
||||
@@ -121,9 +119,14 @@ namespace AndroidSideloader
|
||||
this.deviceIdLabel = new System.Windows.Forms.Label();
|
||||
this.rookieStatusLabel = new System.Windows.Forms.Label();
|
||||
this.sidebarMediaPanel = new System.Windows.Forms.Panel();
|
||||
this.downloadInstallGameButton = new AndroidSideloader.RoundButton();
|
||||
this.selectedGameLabel = new System.Windows.Forms.Label();
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.webView21 = new Microsoft.Web.WebView2.WinForms.WebView2();
|
||||
this.favoriteGame = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.favoriteButton = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.gamesGalleryView = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.btnViewToggle_Tooltip = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.webViewPlaceholderPanel = new System.Windows.Forms.Panel();
|
||||
this.searchPanel = new AndroidSideloader.RoundButton();
|
||||
this.searchIconPictureBox = new System.Windows.Forms.PictureBox();
|
||||
this.searchTextBox = new System.Windows.Forms.TextBox();
|
||||
@@ -132,12 +135,8 @@ namespace AndroidSideloader
|
||||
this.btnInstalled = new AndroidSideloader.RoundButton();
|
||||
this.btnUpdateAvailable = new AndroidSideloader.RoundButton();
|
||||
this.btnNewerThanList = new AndroidSideloader.RoundButton();
|
||||
this.webView21 = new Microsoft.Web.WebView2.WinForms.WebView2();
|
||||
this.favoriteGame = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.favoriteButton = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.gamesGalleryView = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.btnViewToggle_Tooltip = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.webViewPlaceholderPanel = new System.Windows.Forms.Panel();
|
||||
this.progressBar = new AndroidSideloader.ModernProgressBar();
|
||||
this.downloadInstallGameButton = new AndroidSideloader.RoundButton();
|
||||
((System.ComponentModel.ISupportInitialize)(this.gamesPictureBox)).BeginInit();
|
||||
this.gamesPictureBox.SuspendLayout();
|
||||
this.progressDLbtnContainer.SuspendLayout();
|
||||
@@ -153,10 +152,10 @@ namespace AndroidSideloader
|
||||
this.statusInfoPanel.SuspendLayout();
|
||||
this.sidebarMediaPanel.SuspendLayout();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.searchPanel.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.searchIconPictureBox)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.webView21)).BeginInit();
|
||||
this.favoriteGame.SuspendLayout();
|
||||
this.searchPanel.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.searchIconPictureBox)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// m_combo
|
||||
@@ -167,65 +166,24 @@ namespace AndroidSideloader
|
||||
this.m_combo.ForeColor = global::AndroidSideloader.Properties.Settings.Default.FontColor;
|
||||
this.m_combo.Location = new System.Drawing.Point(253, 9);
|
||||
this.m_combo.Name = "m_combo";
|
||||
this.m_combo.Size = new System.Drawing.Size(374, 25);
|
||||
this.m_combo.Size = new System.Drawing.Size(374, 24);
|
||||
this.m_combo.TabIndex = 0;
|
||||
this.m_combo.Text = "Select an Installed App...";
|
||||
this.m_combo.Visible = false;
|
||||
//
|
||||
// progressBar
|
||||
//
|
||||
this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.progressBar.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(35)))), ((int)(((byte)(45)))));
|
||||
this.progressBar.BackgroundColor = System.Drawing.Color.FromArgb(((int)(((byte)(28)))), ((int)(((byte)(32)))), ((int)(((byte)(38)))));
|
||||
this.progressBar.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold);
|
||||
this.progressBar.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(93)))), ((int)(((byte)(203)))), ((int)(((byte)(173)))));
|
||||
this.progressBar.IndeterminateColor = System.Drawing.Color.FromArgb(((int)(((byte)(93)))), ((int)(((byte)(203)))), ((int)(((byte)(173)))));
|
||||
this.progressBar.IsIndeterminate = false;
|
||||
this.progressBar.Location = new System.Drawing.Point(1, 18);
|
||||
this.progressBar.Maximum = 100;
|
||||
this.progressBar.Minimum = 0;
|
||||
this.progressBar.MinimumSize = new System.Drawing.Size(200, 13);
|
||||
this.progressBar.Name = "progressBar";
|
||||
this.progressBar.OperationType = "";
|
||||
this.progressBar.ProgressEndColor = System.Drawing.Color.FromArgb(((int)(((byte)(50)))), ((int)(((byte)(160)))), ((int)(((byte)(130)))));
|
||||
this.progressBar.ProgressStartColor = System.Drawing.Color.FromArgb(((int)(((byte)(120)))), ((int)(((byte)(220)))), ((int)(((byte)(190)))));
|
||||
this.progressBar.Radius = 6;
|
||||
this.progressBar.Size = new System.Drawing.Size(983, 13);
|
||||
this.progressBar.StatusText = "";
|
||||
this.progressBar.TabIndex = 7;
|
||||
this.progressBar.TextColor = System.Drawing.Color.FromArgb(((int)(((byte)(230)))), ((int)(((byte)(230)))), ((int)(((byte)(230)))));
|
||||
this.progressBar.Value = 0;
|
||||
//
|
||||
// speedLabel
|
||||
//
|
||||
this.speedLabel.AutoSize = true;
|
||||
this.speedLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.speedLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold);
|
||||
this.speedLabel.ForeColor = System.Drawing.Color.White;
|
||||
this.speedLabel.Location = new System.Drawing.Point(-2, -3);
|
||||
this.speedLabel.Location = new System.Drawing.Point(-1, 3);
|
||||
this.speedLabel.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.speedLabel.Name = "speedLabel";
|
||||
this.speedLabel.Size = new System.Drawing.Size(152, 16);
|
||||
this.speedLabel.TabIndex = 76;
|
||||
this.speedLabel.Text = "DLS: Speed in MBPS";
|
||||
this.speedLabel_Tooltip.SetToolTip(this.speedLabel, "Current download speed, updates every second, in mbps");
|
||||
//
|
||||
// etaLabel
|
||||
//
|
||||
this.etaLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.etaLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.etaLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.etaLabel.ForeColor = System.Drawing.Color.White;
|
||||
this.etaLabel.Location = new System.Drawing.Point(790, -3);
|
||||
this.etaLabel.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.etaLabel.Name = "etaLabel";
|
||||
this.etaLabel.Size = new System.Drawing.Size(196, 18);
|
||||
this.etaLabel.TabIndex = 75;
|
||||
this.etaLabel.Text = "ETA: HH:MM:SS Left";
|
||||
this.etaLabel.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||
this.etaLabel_Tooltip.SetToolTip(this.etaLabel, "Estimated time when game will finish download, updates every 5 seconds, format is" +
|
||||
" HH:MM:SS");
|
||||
//
|
||||
// freeDisclaimer
|
||||
//
|
||||
@@ -272,7 +230,7 @@ namespace AndroidSideloader
|
||||
this.devicesComboBox.Location = new System.Drawing.Point(253, 39);
|
||||
this.devicesComboBox.Margin = new System.Windows.Forms.Padding(2);
|
||||
this.devicesComboBox.Name = "devicesComboBox";
|
||||
this.devicesComboBox.Size = new System.Drawing.Size(164, 25);
|
||||
this.devicesComboBox.Size = new System.Drawing.Size(164, 24);
|
||||
this.devicesComboBox.TabIndex = 1;
|
||||
this.devicesComboBox.Text = "Select your device";
|
||||
this.devicesComboBox.Visible = false;
|
||||
@@ -288,7 +246,7 @@ namespace AndroidSideloader
|
||||
this.remotesList.Location = new System.Drawing.Point(567, 40);
|
||||
this.remotesList.Margin = new System.Windows.Forms.Padding(2);
|
||||
this.remotesList.Name = "remotesList";
|
||||
this.remotesList.Size = new System.Drawing.Size(67, 25);
|
||||
this.remotesList.Size = new System.Drawing.Size(67, 24);
|
||||
this.remotesList.TabIndex = 3;
|
||||
this.remotesList.Visible = false;
|
||||
this.remotesList.SelectedIndexChanged += new System.EventHandler(this.remotesList_SelectedIndexChanged);
|
||||
@@ -808,12 +766,11 @@ namespace AndroidSideloader
|
||||
this.progressDLbtnContainer.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
|
||||
this.progressDLbtnContainer.BackColor = System.Drawing.Color.Transparent;
|
||||
this.progressDLbtnContainer.Controls.Add(this.progressBar);
|
||||
this.progressDLbtnContainer.Controls.Add(this.etaLabel);
|
||||
this.progressDLbtnContainer.Controls.Add(this.speedLabel);
|
||||
this.progressDLbtnContainer.Location = new System.Drawing.Point(258, 459);
|
||||
this.progressDLbtnContainer.Location = new System.Drawing.Point(258, 453);
|
||||
this.progressDLbtnContainer.MinimumSize = new System.Drawing.Size(600, 34);
|
||||
this.progressDLbtnContainer.Name = "progressDLbtnContainer";
|
||||
this.progressDLbtnContainer.Size = new System.Drawing.Size(984, 34);
|
||||
this.progressDLbtnContainer.Size = new System.Drawing.Size(984, 40);
|
||||
this.progressDLbtnContainer.TabIndex = 96;
|
||||
//
|
||||
// diskLabel
|
||||
@@ -1281,35 +1238,6 @@ namespace AndroidSideloader
|
||||
this.sidebarMediaPanel.Size = new System.Drawing.Size(233, 214);
|
||||
this.sidebarMediaPanel.TabIndex = 101;
|
||||
//
|
||||
// downloadInstallGameButton
|
||||
//
|
||||
this.downloadInstallGameButton.Active1 = System.Drawing.Color.FromArgb(((int)(((byte)(110)))), ((int)(((byte)(215)))), ((int)(((byte)(190)))));
|
||||
this.downloadInstallGameButton.Active2 = System.Drawing.Color.FromArgb(((int)(((byte)(110)))), ((int)(((byte)(215)))), ((int)(((byte)(190)))));
|
||||
this.downloadInstallGameButton.BackColor = System.Drawing.Color.Transparent;
|
||||
this.downloadInstallGameButton.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.downloadInstallGameButton.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||
this.downloadInstallGameButton.Disabled1 = System.Drawing.Color.FromArgb(((int)(((byte)(16)))), ((int)(((byte)(18)))), ((int)(((byte)(22)))));
|
||||
this.downloadInstallGameButton.Disabled2 = System.Drawing.Color.FromArgb(((int)(((byte)(16)))), ((int)(((byte)(18)))), ((int)(((byte)(22)))));
|
||||
this.downloadInstallGameButton.DisabledStrokeColor = System.Drawing.Color.FromArgb(((int)(((byte)(50)))), ((int)(((byte)(55)))), ((int)(((byte)(65)))));
|
||||
this.downloadInstallGameButton.Enabled = false;
|
||||
this.downloadInstallGameButton.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold);
|
||||
this.downloadInstallGameButton.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(59)))), ((int)(((byte)(67)))), ((int)(((byte)(82)))));
|
||||
this.downloadInstallGameButton.Inactive1 = System.Drawing.Color.FromArgb(((int)(((byte)(93)))), ((int)(((byte)(203)))), ((int)(((byte)(173)))));
|
||||
this.downloadInstallGameButton.Inactive2 = System.Drawing.Color.FromArgb(((int)(((byte)(93)))), ((int)(((byte)(203)))), ((int)(((byte)(173)))));
|
||||
this.downloadInstallGameButton.Location = new System.Drawing.Point(6, 177);
|
||||
this.downloadInstallGameButton.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.downloadInstallGameButton.Name = "downloadInstallGameButton";
|
||||
this.downloadInstallGameButton.Radius = 4;
|
||||
this.downloadInstallGameButton.Size = new System.Drawing.Size(238, 30);
|
||||
this.downloadInstallGameButton.Stroke = true;
|
||||
this.downloadInstallGameButton.StrokeColor = System.Drawing.Color.FromArgb(((int)(((byte)(93)))), ((int)(((byte)(203)))), ((int)(((byte)(173)))));
|
||||
this.downloadInstallGameButton.TabIndex = 94;
|
||||
this.downloadInstallGameButton.Text = "DOWNLOAD AND INSTALL";
|
||||
this.downloadInstallGameButton.Transparency = false;
|
||||
this.downloadInstallGameButton.Click += new System.EventHandler(this.downloadInstallGameButton_Click);
|
||||
this.downloadInstallGameButton.DragDrop += new System.Windows.Forms.DragEventHandler(this.Form1_DragDrop);
|
||||
this.downloadInstallGameButton.DragEnter += new System.Windows.Forms.DragEventHandler(this.Form1_DragEnter);
|
||||
//
|
||||
// selectedGameLabel
|
||||
//
|
||||
this.selectedGameLabel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(24)))), ((int)(((byte)(29)))));
|
||||
@@ -1348,6 +1276,58 @@ namespace AndroidSideloader
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(984, 34);
|
||||
this.tableLayoutPanel1.TabIndex = 97;
|
||||
//
|
||||
// webView21
|
||||
//
|
||||
this.webView21.AllowExternalDrop = true;
|
||||
this.webView21.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.webView21.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(24)))), ((int)(((byte)(26)))), ((int)(((byte)(30)))));
|
||||
this.webView21.CreationProperties = null;
|
||||
this.webView21.DefaultBackgroundColor = System.Drawing.Color.FromArgb(((int)(((byte)(24)))), ((int)(((byte)(26)))), ((int)(((byte)(30)))));
|
||||
this.webView21.Location = new System.Drawing.Point(259, 496);
|
||||
this.webView21.Name = "webView21";
|
||||
this.webView21.Size = new System.Drawing.Size(384, 216);
|
||||
this.webView21.TabIndex = 98;
|
||||
this.webView21.ZoomFactor = 1D;
|
||||
//
|
||||
// favoriteGame
|
||||
//
|
||||
this.favoriteGame.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(42)))), ((int)(((byte)(48)))));
|
||||
this.favoriteGame.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.favoriteButton});
|
||||
this.favoriteGame.Name = "favoriteGame";
|
||||
this.favoriteGame.ShowImageMargin = false;
|
||||
this.favoriteGame.Size = new System.Drawing.Size(149, 26);
|
||||
//
|
||||
// favoriteButton
|
||||
//
|
||||
this.favoriteButton.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(42)))), ((int)(((byte)(48)))));
|
||||
this.favoriteButton.ForeColor = System.Drawing.Color.White;
|
||||
this.favoriteButton.Name = "favoriteButton";
|
||||
this.favoriteButton.Size = new System.Drawing.Size(148, 22);
|
||||
this.favoriteButton.Text = "★ Add to Favorites";
|
||||
this.favoriteButton.Click += new System.EventHandler(this.favoriteButton_Click);
|
||||
//
|
||||
// gamesGalleryView
|
||||
//
|
||||
this.gamesGalleryView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.gamesGalleryView.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(15)))), ((int)(((byte)(15)))), ((int)(((byte)(15)))));
|
||||
this.gamesGalleryView.Location = new System.Drawing.Point(258, 44);
|
||||
this.gamesGalleryView.Name = "gamesGalleryView";
|
||||
this.gamesGalleryView.Size = new System.Drawing.Size(984, 409);
|
||||
this.gamesGalleryView.TabIndex = 102;
|
||||
//
|
||||
// webViewPlaceholderPanel
|
||||
//
|
||||
this.webViewPlaceholderPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.webViewPlaceholderPanel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(24)))), ((int)(((byte)(26)))), ((int)(((byte)(30)))));
|
||||
this.webViewPlaceholderPanel.Location = new System.Drawing.Point(259, 496);
|
||||
this.webViewPlaceholderPanel.Name = "webViewPlaceholderPanel";
|
||||
this.webViewPlaceholderPanel.Size = new System.Drawing.Size(384, 217);
|
||||
this.webViewPlaceholderPanel.TabIndex = 103;
|
||||
this.webViewPlaceholderPanel.Paint += new System.Windows.Forms.PaintEventHandler(this.webViewPlaceholderPanel_Paint);
|
||||
//
|
||||
// searchPanel
|
||||
//
|
||||
this.searchPanel.Active1 = System.Drawing.Color.FromArgb(((int)(((byte)(51)))), ((int)(((byte)(56)))), ((int)(((byte)(70)))));
|
||||
@@ -1531,57 +1511,59 @@ namespace AndroidSideloader
|
||||
this.btnNewerThanList.Transparency = false;
|
||||
this.btnNewerThanList.Click += new System.EventHandler(this.btnNewerThanList_Click);
|
||||
//
|
||||
// webView21
|
||||
// progressBar
|
||||
//
|
||||
this.webView21.AllowExternalDrop = true;
|
||||
this.webView21.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.webView21.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(24)))), ((int)(((byte)(26)))), ((int)(((byte)(30)))));
|
||||
this.webView21.CreationProperties = null;
|
||||
this.webView21.DefaultBackgroundColor = System.Drawing.Color.FromArgb(((int)(((byte)(24)))), ((int)(((byte)(26)))), ((int)(((byte)(30)))));
|
||||
this.webView21.Location = new System.Drawing.Point(259, 496);
|
||||
this.webView21.Name = "webView21";
|
||||
this.webView21.Size = new System.Drawing.Size(384, 216);
|
||||
this.webView21.TabIndex = 98;
|
||||
this.webView21.ZoomFactor = 1D;
|
||||
//
|
||||
// favoriteGame
|
||||
//
|
||||
this.favoriteGame.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(42)))), ((int)(((byte)(48)))));
|
||||
this.favoriteGame.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.favoriteButton});
|
||||
this.favoriteGame.Name = "favoriteGame";
|
||||
this.favoriteGame.ShowImageMargin = false;
|
||||
this.favoriteGame.Size = new System.Drawing.Size(149, 26);
|
||||
//
|
||||
// favoriteButton
|
||||
//
|
||||
this.favoriteButton.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(42)))), ((int)(((byte)(48)))));
|
||||
this.favoriteButton.ForeColor = System.Drawing.Color.White;
|
||||
this.favoriteButton.Name = "favoriteButton";
|
||||
this.favoriteButton.Size = new System.Drawing.Size(148, 22);
|
||||
this.favoriteButton.Text = "★ Add to Favorites";
|
||||
this.favoriteButton.Click += new System.EventHandler(this.favoriteButton_Click);
|
||||
//
|
||||
// gamesGalleryView
|
||||
//
|
||||
this.gamesGalleryView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.gamesGalleryView.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(15)))), ((int)(((byte)(15)))), ((int)(((byte)(15)))));
|
||||
this.gamesGalleryView.Location = new System.Drawing.Point(258, 44);
|
||||
this.gamesGalleryView.Name = "gamesGalleryView";
|
||||
this.gamesGalleryView.Size = new System.Drawing.Size(984, 409);
|
||||
this.gamesGalleryView.TabIndex = 102;
|
||||
this.progressBar.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(35)))), ((int)(((byte)(45)))));
|
||||
this.progressBar.BackgroundColor = System.Drawing.Color.FromArgb(((int)(((byte)(28)))), ((int)(((byte)(32)))), ((int)(((byte)(38)))));
|
||||
this.progressBar.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold);
|
||||
this.progressBar.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(93)))), ((int)(((byte)(203)))), ((int)(((byte)(173)))));
|
||||
this.progressBar.IndeterminateColor = System.Drawing.Color.FromArgb(((int)(((byte)(93)))), ((int)(((byte)(203)))), ((int)(((byte)(173)))));
|
||||
this.progressBar.IsIndeterminate = false;
|
||||
this.progressBar.Location = new System.Drawing.Point(1, 23);
|
||||
this.progressBar.Maximum = 100;
|
||||
this.progressBar.Minimum = 0;
|
||||
this.progressBar.MinimumSize = new System.Drawing.Size(200, 13);
|
||||
this.progressBar.Name = "progressBar";
|
||||
this.progressBar.OperationType = "";
|
||||
this.progressBar.ProgressEndColor = System.Drawing.Color.FromArgb(((int)(((byte)(50)))), ((int)(((byte)(160)))), ((int)(((byte)(130)))));
|
||||
this.progressBar.ProgressStartColor = System.Drawing.Color.FromArgb(((int)(((byte)(120)))), ((int)(((byte)(220)))), ((int)(((byte)(190)))));
|
||||
this.progressBar.Radius = 6;
|
||||
this.progressBar.Size = new System.Drawing.Size(983, 13);
|
||||
this.progressBar.StatusText = "";
|
||||
this.progressBar.TabIndex = 7;
|
||||
this.progressBar.TextColor = System.Drawing.Color.FromArgb(((int)(((byte)(230)))), ((int)(((byte)(230)))), ((int)(((byte)(230)))));
|
||||
this.progressBar.Value = 0;
|
||||
//
|
||||
// webViewPlaceholderPanel
|
||||
// downloadInstallGameButton
|
||||
//
|
||||
this.webViewPlaceholderPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.webViewPlaceholderPanel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(24)))), ((int)(((byte)(26)))), ((int)(((byte)(30)))));
|
||||
this.webViewPlaceholderPanel.Location = new System.Drawing.Point(259, 496);
|
||||
this.webViewPlaceholderPanel.Name = "webViewPlaceholderPanel";
|
||||
this.webViewPlaceholderPanel.Size = new System.Drawing.Size(384, 217);
|
||||
this.webViewPlaceholderPanel.TabIndex = 103;
|
||||
this.webViewPlaceholderPanel.Paint += new System.Windows.Forms.PaintEventHandler(this.webViewPlaceholderPanel_Paint);
|
||||
this.downloadInstallGameButton.Active1 = System.Drawing.Color.FromArgb(((int)(((byte)(110)))), ((int)(((byte)(215)))), ((int)(((byte)(190)))));
|
||||
this.downloadInstallGameButton.Active2 = System.Drawing.Color.FromArgb(((int)(((byte)(110)))), ((int)(((byte)(215)))), ((int)(((byte)(190)))));
|
||||
this.downloadInstallGameButton.BackColor = System.Drawing.Color.Transparent;
|
||||
this.downloadInstallGameButton.Cursor = System.Windows.Forms.Cursors.Hand;
|
||||
this.downloadInstallGameButton.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||
this.downloadInstallGameButton.Disabled1 = System.Drawing.Color.FromArgb(((int)(((byte)(16)))), ((int)(((byte)(18)))), ((int)(((byte)(22)))));
|
||||
this.downloadInstallGameButton.Disabled2 = System.Drawing.Color.FromArgb(((int)(((byte)(16)))), ((int)(((byte)(18)))), ((int)(((byte)(22)))));
|
||||
this.downloadInstallGameButton.DisabledStrokeColor = System.Drawing.Color.FromArgb(((int)(((byte)(50)))), ((int)(((byte)(55)))), ((int)(((byte)(65)))));
|
||||
this.downloadInstallGameButton.Enabled = false;
|
||||
this.downloadInstallGameButton.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold);
|
||||
this.downloadInstallGameButton.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(59)))), ((int)(((byte)(67)))), ((int)(((byte)(82)))));
|
||||
this.downloadInstallGameButton.Inactive1 = System.Drawing.Color.FromArgb(((int)(((byte)(93)))), ((int)(((byte)(203)))), ((int)(((byte)(173)))));
|
||||
this.downloadInstallGameButton.Inactive2 = System.Drawing.Color.FromArgb(((int)(((byte)(93)))), ((int)(((byte)(203)))), ((int)(((byte)(173)))));
|
||||
this.downloadInstallGameButton.Location = new System.Drawing.Point(6, 177);
|
||||
this.downloadInstallGameButton.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.downloadInstallGameButton.Name = "downloadInstallGameButton";
|
||||
this.downloadInstallGameButton.Radius = 4;
|
||||
this.downloadInstallGameButton.Size = new System.Drawing.Size(238, 30);
|
||||
this.downloadInstallGameButton.Stroke = true;
|
||||
this.downloadInstallGameButton.StrokeColor = System.Drawing.Color.FromArgb(((int)(((byte)(93)))), ((int)(((byte)(203)))), ((int)(((byte)(173)))));
|
||||
this.downloadInstallGameButton.TabIndex = 94;
|
||||
this.downloadInstallGameButton.Text = "DOWNLOAD AND INSTALL";
|
||||
this.downloadInstallGameButton.Transparency = false;
|
||||
this.downloadInstallGameButton.Click += new System.EventHandler(this.downloadInstallGameButton_Click);
|
||||
this.downloadInstallGameButton.DragDrop += new System.Windows.Forms.DragEventHandler(this.Form1_DragDrop);
|
||||
this.downloadInstallGameButton.DragEnter += new System.Windows.Forms.DragEventHandler(this.Form1_DragEnter);
|
||||
//
|
||||
// MainForm
|
||||
//
|
||||
@@ -1633,11 +1615,11 @@ namespace AndroidSideloader
|
||||
this.statusInfoPanel.ResumeLayout(false);
|
||||
this.sidebarMediaPanel.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.webView21)).EndInit();
|
||||
this.favoriteGame.ResumeLayout(false);
|
||||
this.searchPanel.ResumeLayout(false);
|
||||
this.searchPanel.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.searchIconPictureBox)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.webView21)).EndInit();
|
||||
this.favoriteGame.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
@@ -1646,7 +1628,6 @@ namespace AndroidSideloader
|
||||
#endregion
|
||||
private SergeUtils.EasyCompletionComboBox m_combo;
|
||||
private ModernProgressBar progressBar;
|
||||
private System.Windows.Forms.Label etaLabel;
|
||||
private System.Windows.Forms.Label speedLabel;
|
||||
private System.Windows.Forms.Label freeDisclaimer;
|
||||
private System.Windows.Forms.ComboBox devicesComboBox;
|
||||
|
||||
188
MainForm.cs
188
MainForm.cs
@@ -401,7 +401,6 @@ namespace AndroidSideloader
|
||||
gamesListView.View = View.Details;
|
||||
gamesListView.FullRowSelect = true;
|
||||
gamesListView.GridLines = false;
|
||||
etaLabel.Text = String.Empty;
|
||||
speedLabel.Text = String.Empty;
|
||||
diskLabel.Text = String.Empty;
|
||||
|
||||
@@ -965,24 +964,26 @@ namespace AndroidSideloader
|
||||
|
||||
output = await ADB.CopyOBBWithProgressAsync(
|
||||
path,
|
||||
progress => this.Invoke(() => {
|
||||
(progress, eta) => this.Invoke(() => {
|
||||
progressBar.Value = progress;
|
||||
speedLabel.Text = $"Progress: {progress}%";
|
||||
string etaStr = eta.HasValue && eta.Value.TotalSeconds > 0
|
||||
? $" · ETA: {eta.Value:mm\\:ss}"
|
||||
: "";
|
||||
speedLabel.Text = $"Progress: {progress}%{etaStr}";
|
||||
}),
|
||||
status => this.Invoke(() => {
|
||||
progressBar.StatusText = status;
|
||||
etaLabel.Text = status;
|
||||
}),
|
||||
folderName);
|
||||
|
||||
progressBar.Value = 100;
|
||||
progressBar.StatusText = "";
|
||||
changeTitle("Done.");
|
||||
showAvailableSpace();
|
||||
|
||||
ShowPrcOutput(output);
|
||||
changeTitle("");
|
||||
speedLabel.Text = "";
|
||||
etaLabel.Text = "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3047,7 +3048,6 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
public async void cleanupActiveDownloadStatus()
|
||||
{
|
||||
speedLabel.Text = String.Empty;
|
||||
etaLabel.Text = String.Empty;
|
||||
progressBar.Value = 0;
|
||||
gamesQueueList.RemoveAt(0);
|
||||
}
|
||||
@@ -3262,7 +3262,9 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
|
||||
changeTitle("Downloading game " + gameName);
|
||||
speedLabel.Text = "Starting download...";
|
||||
etaLabel.Text = "Please wait...";
|
||||
|
||||
// Track the highest valid progress to prevent brief progress bar flashes during multi-file transfers
|
||||
int highestValidPercent = 0;
|
||||
|
||||
// Download
|
||||
while (t1.IsAlive)
|
||||
@@ -3271,7 +3273,6 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
{
|
||||
HttpResponseMessage response = await client.PostAsync("http://127.0.0.1:5572/core/stats", null);
|
||||
string foo = await response.Content.ReadAsStringAsync();
|
||||
//Debug.WriteLine("RESP CONTENT " + foo);
|
||||
dynamic results = JsonConvert.DeserializeObject<dynamic>(foo);
|
||||
|
||||
if (results["transferring"] != null)
|
||||
@@ -3308,24 +3309,45 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
totalSize /= 1000000;
|
||||
downloadedSize /= 1000000;
|
||||
|
||||
// Logger.Log("Files: " + transfersComplete.ToString() + "/" + fileCount.ToString() + " (" + Convert.ToInt32((downloadedSize / totalSize) * 100).ToString() + "% Complete)");
|
||||
// Logger.Log("Downloaded: " + downloadedSize.ToString() + " of " + totalSize.ToString());
|
||||
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = Convert.ToInt32((downloadedSize / totalSize) * 100);
|
||||
|
||||
int percent = 0;
|
||||
if (totalSize > 0)
|
||||
{
|
||||
percent = Convert.ToInt32((downloadedSize / totalSize) * 100);
|
||||
}
|
||||
|
||||
// Clamp to 0-99 while download is in progress to prevent brief 100% flashes
|
||||
percent = Math.Max(0, Math.Min(99, percent));
|
||||
|
||||
// Only allow progress to increase
|
||||
if (percent >= highestValidPercent)
|
||||
{
|
||||
highestValidPercent = percent;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Progress went backwards? Keep showing the highest valid percent we've seen
|
||||
percent = highestValidPercent;
|
||||
}
|
||||
|
||||
progressBar.Value = percent;
|
||||
|
||||
TimeSpan time = TimeSpan.FromSeconds(globalEta);
|
||||
etaLabel.Text = etaLabel.Text = "ETA: " + time.ToString(@"hh\:mm\:ss") + " left";
|
||||
|
||||
speedLabel.Text = "DLS: " + transfersComplete.ToString() + "/" + fileCount.ToString() + " files - " + string.Format("{0:0.00}", downloadSpeed) + " MB/s";
|
||||
UpdateProgressStatus(
|
||||
"Downloading",
|
||||
(int)transfersComplete + 1,
|
||||
(int)fileCount,
|
||||
percent,
|
||||
time,
|
||||
downloadSpeed);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
await Task.Delay(100);
|
||||
|
||||
}
|
||||
|
||||
if (removedownloading)
|
||||
@@ -3399,18 +3421,42 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
|
||||
if (UsingPublicConfig && otherError == false && gameDownloadOutput.Output != "Download skipped.")
|
||||
{
|
||||
// ETA tracking for extraction
|
||||
DateTime extractStart = DateTime.UtcNow;
|
||||
string currentExtractFile = "";
|
||||
|
||||
Thread extractionThread = new Thread(() =>
|
||||
{
|
||||
Invoke(new Action(() =>
|
||||
{
|
||||
speedLabel.Text = "Extracting..."; etaLabel.Text = "Please wait...";
|
||||
speedLabel.Text = "Extracting...";
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = 0;
|
||||
progressBar.OperationType = "Extracting";
|
||||
isInDownloadExtract = true;
|
||||
}));
|
||||
|
||||
// Set up extraction callbacks
|
||||
Zip.ExtractionProgressCallback = (percent, eta) =>
|
||||
{
|
||||
this.Invoke(() =>
|
||||
{
|
||||
progressBar.Value = percent;
|
||||
UpdateProgressStatus("Extracting", percent: percent, eta: eta);
|
||||
|
||||
progressBar.StatusText = !string.IsNullOrEmpty(currentExtractFile)
|
||||
? $"{currentExtractFile} · {percent}%"
|
||||
: $"{percent}%";
|
||||
});
|
||||
};
|
||||
|
||||
Zip.ExtractionStatusCallback = (fileName) =>
|
||||
{
|
||||
currentExtractFile = fileName ?? "";
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
progressBar.OperationType = "Extracting";
|
||||
changeTitle("Extracting " + gameName);
|
||||
Zip.ExtractFile($"{settings.DownloadDir}\\{gameNameHash}\\{gameNameHash}.7z.001", $"{settings.DownloadDir}", PublicConfigFile.Password);
|
||||
changeTitle("");
|
||||
@@ -3425,6 +3471,12 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
this.Invoke(() => _ = FlexibleMessageBox.Show(Program.form, $"7zip error: {ex.Message}"));
|
||||
output += new ProcessOutput("", "Extract Failed");
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Clear callbacks
|
||||
Zip.ExtractionProgressCallback = null;
|
||||
Zip.ExtractionStatusCallback = null;
|
||||
}
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
@@ -3436,6 +3488,8 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
progressBar.StatusText = ""; // Clear status after extraction
|
||||
|
||||
if (Directory.Exists($"{settings.DownloadDir}\\{gameNameHash}"))
|
||||
{
|
||||
Directory.Delete($"{settings.DownloadDir}\\{gameNameHash}", true);
|
||||
@@ -3449,8 +3503,6 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
progressBar.Value = 0;
|
||||
progressBar.IsIndeterminate = false;
|
||||
changeTitle("Installing game APK " + gameName);
|
||||
etaLabel.Text = "ETA: Wait for install...";
|
||||
speedLabel.Text = "DLS: Finished";
|
||||
if (File.Exists(Path.Combine(settings.DownloadDir, gameName, "install.txt")))
|
||||
{
|
||||
isinstalltxt = true;
|
||||
@@ -3508,7 +3560,6 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
t.Start();
|
||||
|
||||
changeTitle($"Sideloading APK...");
|
||||
etaLabel.Text = "Installing APK...";
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.OperationType = "Installing";
|
||||
progressBar.Value = 0;
|
||||
@@ -3516,7 +3567,7 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
// Use async method with progress
|
||||
output += await ADB.SideloadWithProgressAsync(
|
||||
apkFile,
|
||||
progress => this.Invoke(() => {
|
||||
(progress, eta) => this.Invoke(() => {
|
||||
if (progress == 0)
|
||||
{
|
||||
progressBar.IsIndeterminate = true;
|
||||
@@ -3527,16 +3578,23 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = progress;
|
||||
}
|
||||
UpdateProgressStatus("Installing APK", percent: progress, eta: eta);
|
||||
progressBar.StatusText = $"Installing · {progress}%";
|
||||
}),
|
||||
status => this.Invoke(() => {
|
||||
if (!string.IsNullOrEmpty(status))
|
||||
{
|
||||
// "Completing Installation..."
|
||||
speedLabel.Text = status;
|
||||
progressBar.StatusText = status;
|
||||
etaLabel.Text = status;
|
||||
}
|
||||
}),
|
||||
packagename,
|
||||
Sideloader.gameNameToSimpleName(gameName));
|
||||
|
||||
t.Stop();
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.StatusText = ""; // Clear status after APK install
|
||||
|
||||
Debug.WriteLine(wrDelimiter);
|
||||
if (Directory.Exists($"{settings.DownloadDir}\\{gameName}\\{packagename}"))
|
||||
@@ -3544,7 +3602,6 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
deleteOBB(packagename);
|
||||
|
||||
changeTitle($"Copying {packagename} OBB to device...");
|
||||
etaLabel.Text = "Copying OBB...";
|
||||
progressBar.Value = 0;
|
||||
progressBar.OperationType = "Copying OBB";
|
||||
|
||||
@@ -3553,41 +3610,27 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
|
||||
output += await ADB.CopyOBBWithProgressAsync(
|
||||
$"{settings.DownloadDir}\\{gameName}\\{packagename}",
|
||||
progress => this.Invoke(() =>
|
||||
(progress, eta) => this.Invoke(() =>
|
||||
{
|
||||
progressBar.Value = progress;
|
||||
speedLabel.Text = $"OBB: {progress}%";
|
||||
UpdateProgressStatus("Copying OBB", percent: progress, eta: eta);
|
||||
|
||||
if (!string.IsNullOrEmpty(currentObbStatusBase))
|
||||
{
|
||||
if (currentObbStatusBase.StartsWith("Preparing:", StringComparison.OrdinalIgnoreCase) ||
|
||||
currentObbStatusBase.StartsWith("Copying:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
progressBar.StatusText = currentObbStatusBase;
|
||||
}
|
||||
else
|
||||
{
|
||||
// "filename · 73%"
|
||||
progressBar.StatusText = $"{currentObbStatusBase} · {progress}%";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback: just show the numeric percent in the bar
|
||||
progressBar.StatusText = $"{progress}%";
|
||||
}
|
||||
}),
|
||||
status => this.Invoke(() =>
|
||||
{
|
||||
currentObbStatusBase = status ?? string.Empty;
|
||||
if (currentObbStatusBase.StartsWith("Preparing:", StringComparison.OrdinalIgnoreCase) ||
|
||||
currentObbStatusBase.StartsWith("Copying:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
progressBar.StatusText = currentObbStatusBase;
|
||||
}
|
||||
}),
|
||||
Sideloader.gameNameToSimpleName(gameName));
|
||||
|
||||
progressBar.StatusText = ""; // Clear status after OBB copy
|
||||
changeTitle("");
|
||||
|
||||
if (!nodeviceonstart | DeviceConnected)
|
||||
@@ -3646,8 +3689,6 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
ShowPrcOutput(output);
|
||||
}
|
||||
progressBar.IsIndeterminate = false;
|
||||
etaLabel.Text = "ETA: Finished Queue";
|
||||
speedLabel.Text = "DLS: Finished Queue";
|
||||
gamesAreDownloading = false;
|
||||
isinstalling = false;
|
||||
|
||||
@@ -3768,8 +3809,6 @@ If the problem persists, visit our Telegram (https://t.me/VRPirates) or Discord
|
||||
ShowPrcOutput(output);
|
||||
}
|
||||
progressBar.IsIndeterminate = false;
|
||||
etaLabel.Text = "ETA: Finished Queue";
|
||||
speedLabel.Text = "DLS: Finished Queue";
|
||||
gamesAreDownloading = false;
|
||||
isinstalling = false;
|
||||
|
||||
@@ -7149,6 +7188,65 @@ function onYouTubeIframeAPIReady() {
|
||||
sideloadingStatusLabel.ForeColor = Color.FromArgb(93, 203, 173); // Accent green for enabled
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateProgressStatus(string operation,
|
||||
int current = 0,
|
||||
int total = 0,
|
||||
int percent = 0,
|
||||
TimeSpan? eta = null,
|
||||
double? speedMBps = null)
|
||||
{
|
||||
if (this.InvokeRequired)
|
||||
{
|
||||
this.Invoke(() => UpdateProgressStatus(operation, current, total, percent, eta, speedMBps));
|
||||
return;
|
||||
}
|
||||
|
||||
// Sync the progress bar's operation type to the current operation
|
||||
progressBar.OperationType = operation;
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
// Operation name
|
||||
sb.Append(operation);
|
||||
|
||||
// Percentage
|
||||
if (percent > 0)
|
||||
{
|
||||
sb.Append($" ({percent}%)");
|
||||
}
|
||||
|
||||
// Speed
|
||||
if (speedMBps.HasValue && speedMBps.Value > 0)
|
||||
{
|
||||
sb.Append($" @ {speedMBps.Value:F1} MB/s");
|
||||
}
|
||||
|
||||
// File count if applicable
|
||||
if (total > 1)
|
||||
{
|
||||
sb.Append($" ({current}/{total})");
|
||||
}
|
||||
|
||||
// ETA
|
||||
if (eta.HasValue && eta.Value.TotalSeconds > 0)
|
||||
{
|
||||
sb.Append($" • ETA: {eta.Value:hh\\:mm\\:ss}");
|
||||
}
|
||||
|
||||
speedLabel.Text = sb.ToString();
|
||||
}
|
||||
|
||||
public void ClearProgressStatus()
|
||||
{
|
||||
if (this.InvokeRequired)
|
||||
{
|
||||
this.Invoke(ClearProgressStatus);
|
||||
return;
|
||||
}
|
||||
|
||||
speedLabel.Text = "";
|
||||
}
|
||||
}
|
||||
|
||||
public static class ControlExtensions
|
||||
|
||||
@@ -120,9 +120,6 @@
|
||||
<metadata name="speedLabel_Tooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>1165, 17</value>
|
||||
</metadata>
|
||||
<metadata name="etaLabel_Tooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>428, 54</value>
|
||||
</metadata>
|
||||
<metadata name="startsideloadbutton_Tooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>966, 17</value>
|
||||
</metadata>
|
||||
@@ -177,6 +174,9 @@
|
||||
<metadata name="listApkButton_Tooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>1320, 17</value>
|
||||
</metadata>
|
||||
<metadata name="etaLabel_Tooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>428, 54</value>
|
||||
</metadata>
|
||||
<metadata name="favoriteGame.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>1021, 91</value>
|
||||
</metadata>
|
||||
|
||||
@@ -19,6 +19,11 @@ namespace AndroidSideloader.Utilities
|
||||
internal class Zip
|
||||
{
|
||||
private static readonly SettingsManager settings = SettingsManager.Instance;
|
||||
|
||||
// Progress callback: (percent, eta)
|
||||
public static Action<int, TimeSpan?> ExtractionProgressCallback { get; set; }
|
||||
public static Action<string> ExtractionStatusCallback { get; set; }
|
||||
|
||||
public static void ExtractFile(string sourceArchive, string destination)
|
||||
{
|
||||
string args = $"x \"{sourceArchive}\" -y -o\"{destination}\" -bsp1";
|
||||
@@ -68,6 +73,16 @@ namespace AndroidSideloader.Utilities
|
||||
|
||||
_ = Logger.Log($"Extract: 7z {string.Join(" ", args.Split(' ').Where(a => !a.StartsWith("-p")))}");
|
||||
|
||||
// ETA tracking
|
||||
DateTime extractStart = DateTime.UtcNow;
|
||||
int etaLastPercent = 0;
|
||||
DateTime etaLastPercentTime = DateTime.UtcNow;
|
||||
double smoothedSecondsPerPercent = 0;
|
||||
TimeSpan? lastReportedEta = null;
|
||||
int lastReportedPercent = -1;
|
||||
const double SmoothingAlpha = 0.15;
|
||||
const double EtaChangeThreshold = 0.10;
|
||||
|
||||
using (Process x = new Process())
|
||||
{
|
||||
x.StartInfo = pro;
|
||||
@@ -78,14 +93,76 @@ namespace AndroidSideloader.Utilities
|
||||
{
|
||||
if (e.Data != null)
|
||||
{
|
||||
var match = Regex.Match(e.Data, @"(\d+)%");
|
||||
if (match.Success)
|
||||
// Parse 7-Zip progress output (e.g., " 45% - filename")
|
||||
var match = Regex.Match(e.Data, @"^\s*(\d+)%");
|
||||
if (match.Success && int.TryParse(match.Groups[1].Value, out int percent))
|
||||
{
|
||||
int progress = int.Parse(match.Groups[1].Value);
|
||||
TimeSpan? eta = null;
|
||||
|
||||
// Calculate ETA
|
||||
if (percent > etaLastPercent && percent < 100)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
double secondsForThisChunk = (now - etaLastPercentTime).TotalSeconds;
|
||||
int percentGained = percent - etaLastPercent;
|
||||
|
||||
if (percentGained > 0 && secondsForThisChunk > 0)
|
||||
{
|
||||
double secondsPerPercent = secondsForThisChunk / percentGained;
|
||||
|
||||
if (smoothedSecondsPerPercent == 0)
|
||||
smoothedSecondsPerPercent = secondsPerPercent;
|
||||
else
|
||||
smoothedSecondsPerPercent = SmoothingAlpha * secondsPerPercent + (1 - SmoothingAlpha) * smoothedSecondsPerPercent;
|
||||
|
||||
int remainingPercent = 100 - percent;
|
||||
double etaSeconds = remainingPercent * smoothedSecondsPerPercent;
|
||||
var newEta = TimeSpan.FromSeconds(Math.Max(0, etaSeconds));
|
||||
|
||||
// Only update if significant change
|
||||
if (!lastReportedEta.HasValue ||
|
||||
Math.Abs(newEta.TotalSeconds - lastReportedEta.Value.TotalSeconds) / Math.Max(1, lastReportedEta.Value.TotalSeconds) > EtaChangeThreshold)
|
||||
{
|
||||
eta = newEta;
|
||||
lastReportedEta = eta;
|
||||
}
|
||||
else
|
||||
{
|
||||
eta = lastReportedEta;
|
||||
}
|
||||
|
||||
etaLastPercent = percent;
|
||||
etaLastPercentTime = now;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
eta = lastReportedEta;
|
||||
}
|
||||
|
||||
// Only report if percent changed
|
||||
if (percent != lastReportedPercent)
|
||||
{
|
||||
lastReportedPercent = percent;
|
||||
|
||||
MainForm mainForm = (MainForm)Application.OpenForms[0];
|
||||
if (mainForm != null)
|
||||
{
|
||||
mainForm.Invoke((Action)(() => mainForm.SetProgress(progress)));
|
||||
mainForm.Invoke((Action)(() => mainForm.SetProgress(percent)));
|
||||
}
|
||||
|
||||
ExtractionProgressCallback?.Invoke(percent, eta);
|
||||
}
|
||||
}
|
||||
|
||||
// Extract filename from output
|
||||
var fileMatch = Regex.Match(e.Data, @"- (.+)$");
|
||||
if (fileMatch.Success)
|
||||
{
|
||||
string fileName = Path.GetFileName(fileMatch.Groups[1].Value.Trim());
|
||||
if (!string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
ExtractionStatusCallback?.Invoke(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,6 +196,11 @@ namespace AndroidSideloader.Utilities
|
||||
x.BeginOutputReadLine();
|
||||
x.BeginErrorReadLine();
|
||||
x.WaitForExit();
|
||||
|
||||
// Clear callbacks
|
||||
ExtractionProgressCallback?.Invoke(100, null);
|
||||
ExtractionStatusCallback?.Invoke("");
|
||||
|
||||
errorMessageShown = false;
|
||||
|
||||
if (!string.IsNullOrEmpty(extractionError))
|
||||
|
||||
Reference in New Issue
Block a user