Merge pull request #292 from jp64k/RSL-3.0.5
Bunch of changes, look inside
This commit is contained in:
72
ADB.cs
72
ADB.cs
@@ -680,78 +680,6 @@ namespace AndroidSideloader
|
||||
|
||||
return $"Total space: {string.Format("{0:0.00}", (double)totalSize / 1000)}GB\nUsed space: {string.Format("{0:0.00}", (double)usedSize / 1000)}GB\nFree space: {string.Format("{0:0.00}", (double)freeSize / 1000)}GB";
|
||||
}
|
||||
|
||||
public static ProcessOutput Sideload(string path, string packagename = "")
|
||||
{
|
||||
ProcessOutput ret = new ProcessOutput();
|
||||
ret += RunAdbCommandToString($"install -g \"{path}\"");
|
||||
string out2 = ret.Output + ret.Error;
|
||||
|
||||
if (out2.Contains("failed"))
|
||||
{
|
||||
_ = Logger.Log(out2);
|
||||
|
||||
if (out2.Contains("offline") && !settings.NodeviceMode)
|
||||
{
|
||||
DialogResult dialogResult2 = FlexibleMessageBox.Show(Program.form, "Device is offline. Press Yes to reconnect, or if you don't wish to connect and just want to download the game (requires unchecking \"Delete games after install\" from settings menu) then press No.", "Device offline.", MessageBoxButtons.YesNoCancel);
|
||||
}
|
||||
|
||||
if (out2.Contains($"signatures do not match previously") || out2.Contains("INSTALL_FAILED_VERSION_DOWNGRADE") || out2.Contains("signatures do not match") || out2.Contains("failed to install"))
|
||||
{
|
||||
ret.Error = string.Empty;
|
||||
ret.Output = string.Empty;
|
||||
|
||||
bool cancelClicked = false;
|
||||
|
||||
if (!settings.AutoReinstall)
|
||||
{
|
||||
Program.form.Invoke((MethodInvoker)(() =>
|
||||
{
|
||||
DialogResult dialogResult1 = FlexibleMessageBox.Show(Program.form, "In place upgrade has failed. Rookie can attempt to backup your save data and reinstall the game automatically, however some games do not store their saves in an accessible location (less than 5%). Continue with reinstall?", "In place upgrade failed.", MessageBoxButtons.OKCancel);
|
||||
if (dialogResult1 == DialogResult.Cancel)
|
||||
cancelClicked = true;
|
||||
}));
|
||||
}
|
||||
|
||||
if (cancelClicked)
|
||||
return ret;
|
||||
|
||||
Program.form.changeTitle("Performing reinstall, please wait...");
|
||||
_ = RunAdbCommandToString("kill-server");
|
||||
_ = RunAdbCommandToString("devices");
|
||||
_ = RunAdbCommandToString($"pull \"/sdcard/Android/data/{MainForm.CurrPCKG}\" \"{Environment.CurrentDirectory}\"");
|
||||
Program.form.changeTitle("Uninstalling game...");
|
||||
_ = Sideloader.UninstallGame(MainForm.CurrPCKG);
|
||||
Program.form.changeTitle("Reinstalling game...");
|
||||
ret += RunAdbCommandToString($"install -g \"{path}\"");
|
||||
_ = RunAdbCommandToString($"push \"{Environment.CurrentDirectory}\\{MainForm.CurrPCKG}\" /sdcard/Android/data/");
|
||||
|
||||
string directoryToDelete = Path.Combine(Environment.CurrentDirectory, MainForm.CurrPCKG);
|
||||
if (Directory.Exists(directoryToDelete))
|
||||
{
|
||||
if (directoryToDelete != Environment.CurrentDirectory)
|
||||
{
|
||||
FileSystemUtilities.TryDeleteDirectory(directoryToDelete);
|
||||
}
|
||||
}
|
||||
|
||||
Program.form.changeTitle("");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
Program.form.changeTitle("");
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static ProcessOutput CopyOBB(string path)
|
||||
{
|
||||
string folder = Path.GetFileName(path);
|
||||
string lastFolder = Path.GetFileName(path);
|
||||
return folder.Contains(".")
|
||||
? RunAdbCommandToString($"shell rm -rf \"/sdcard/Android/obb/{lastFolder}\" && mkdir \"/sdcard/Android/obb/{lastFolder}\"") + RunAdbCommandToString($"push \"{path}\" \"/sdcard/Android/obb\"")
|
||||
: new ProcessOutput("No OBB Folder found");
|
||||
}
|
||||
}
|
||||
|
||||
internal class EtaEstimator
|
||||
|
||||
@@ -1,4 +1,21 @@
|
||||
RSL 2.34
|
||||
RSL 3.0
|
||||
|
||||
Major Rookie overhaul with modernized UI, significant performance improvements and upgraded UX.
|
||||
|
||||
- Added high-performance Gallery View with search, filters, sorting, favorites, hover animations, smooth scrolling and uninstall buttons
|
||||
- Toggle seamlessly between List and Gallery views with your preference remembered across launches
|
||||
- Complete UI redesign with new dark theme, modernized components and subtle animations throughout
|
||||
- Refined navigation, layouts, sizing and color consistency across the entire application
|
||||
- Added uninstall buttons directly in List and Gallery views for quicker app management
|
||||
- Improved startup performance through overhaul of initialization logic, removal of splash screen, parallelized async loading, batched version retrieval, optimized metadata extraction and game list initialization
|
||||
- Instant list filtering through caching and streamlined filter logic (INSTALLED / UPDATE AVAILABLE / NEWER THAN LIST)
|
||||
- Improved search speed and responsiveness
|
||||
- Fixed and improved trailer handling with faster trailer loading
|
||||
- Fixed multiple startup issues including connection errors and zombie ADB instances
|
||||
- Added local blacklist support allowing users to permanently suppress donation prompts for specific apps
|
||||
- Reduced application size by removal of now unused assets
|
||||
|
||||
RSL 2.34
|
||||
|
||||
- Feature: Allow users to favorite games (right click on game)
|
||||
- Fix: Release Notes not showing with trailers enabled
|
||||
|
||||
1209
GalleryView.cs
1209
GalleryView.cs
File diff suppressed because it is too large
Load Diff
246
MainForm.Designer.cs
generated
246
MainForm.Designer.cs
generated
@@ -90,7 +90,6 @@ namespace AndroidSideloader
|
||||
this.speedLabel_Tooltip = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.etaLabel_Tooltip = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.progressDLbtnContainer = new System.Windows.Forms.Panel();
|
||||
this.progressBar = new AndroidSideloader.ModernProgressBar();
|
||||
this.diskLabel = new System.Windows.Forms.Label();
|
||||
this.questStorageProgressBar = new System.Windows.Forms.Panel();
|
||||
this.batteryLevImg = new System.Windows.Forms.PictureBox();
|
||||
@@ -119,9 +118,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();
|
||||
@@ -130,12 +134,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();
|
||||
@@ -151,10 +151,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
|
||||
@@ -165,7 +165,7 @@ 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;
|
||||
@@ -201,7 +201,6 @@ namespace AndroidSideloader
|
||||
//
|
||||
// gamesQueListBox
|
||||
//
|
||||
this.gamesQueListBox.AllowDrop = false;
|
||||
this.gamesQueListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.gamesQueListBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(24)))), ((int)(((byte)(26)))), ((int)(((byte)(30)))));
|
||||
this.gamesQueListBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
@@ -226,7 +225,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;
|
||||
@@ -242,7 +241,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);
|
||||
@@ -336,7 +335,7 @@ namespace AndroidSideloader
|
||||
//
|
||||
// notesRichTextBox
|
||||
//
|
||||
this.notesRichTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||
this.notesRichTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.notesRichTextBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(24)))), ((int)(((byte)(26)))), ((int)(((byte)(30)))));
|
||||
this.notesRichTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
@@ -347,11 +346,12 @@ namespace AndroidSideloader
|
||||
this.notesRichTextBox.Name = "notesRichTextBox";
|
||||
this.notesRichTextBox.ReadOnly = true;
|
||||
this.notesRichTextBox.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.None;
|
||||
this.notesRichTextBox.SelectionAlignment = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
this.notesRichTextBox.ShowSelectionMargin = true;
|
||||
this.notesRichTextBox.Size = new System.Drawing.Size(265, 192);
|
||||
this.notesRichTextBox.TabIndex = 10;
|
||||
this.notesRichTextBox.Text = "\n\n\n\n\nTip: Press F1 to see all shortcuts\n\nDrag and drop APKs or folders to install";
|
||||
this.notesRichTextBox.SelectionAlignment = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
this.notesRichTextBox.Text = "\n\n\n\n\nTip: Press F1 to see all shortcuts\n\nDrag and drop APKs or folders to install" +
|
||||
"";
|
||||
this.notesRichTextBox.LinkClicked += new System.Windows.Forms.LinkClickedEventHandler(this.notesRichTextBox_LinkClicked);
|
||||
//
|
||||
// lblNotes
|
||||
@@ -458,7 +458,7 @@ namespace AndroidSideloader
|
||||
this.backupadbbutton.Padding = new System.Windows.Forms.Padding(30, 0, 0, 0);
|
||||
this.backupadbbutton.Size = new System.Drawing.Size(233, 28);
|
||||
this.backupadbbutton.TabIndex = 1;
|
||||
this.backupadbbutton.Text = "BACKUP WITH ADB";
|
||||
this.backupadbbutton.Text = "BACKUP GAMESAVE WITH ADB";
|
||||
this.backupadbbutton.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.backupadbbutton_Tooltip.SetToolTip(this.backupadbbutton, "Save game data via ADB-Backup");
|
||||
this.backupadbbutton.UseVisualStyleBackColor = false;
|
||||
@@ -478,7 +478,7 @@ namespace AndroidSideloader
|
||||
this.backupbutton.Padding = new System.Windows.Forms.Padding(30, 0, 0, 0);
|
||||
this.backupbutton.Size = new System.Drawing.Size(233, 28);
|
||||
this.backupbutton.TabIndex = 1;
|
||||
this.backupbutton.Text = "BACKUP GAMESAVES";
|
||||
this.backupbutton.Text = "BACKUP ALL GAMESAVES";
|
||||
this.backupbutton.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.backupbutton_Tooltip.SetToolTip(this.backupbutton, "Save game and apps data to the backup folder (Does not save APKs or OBBs)");
|
||||
this.backupbutton.UseVisualStyleBackColor = false;
|
||||
@@ -500,7 +500,7 @@ namespace AndroidSideloader
|
||||
this.restorebutton.TabIndex = 0;
|
||||
this.restorebutton.Text = "RESTORE GAMESAVES";
|
||||
this.restorebutton.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.restorebutton_Tooltip.SetToolTip(this.restorebutton, "Restore game and apps data to the device (Use BACKUP GAMESAVES first)");
|
||||
this.restorebutton_Tooltip.SetToolTip(this.restorebutton, "Restore game and apps data to the device");
|
||||
this.restorebutton.UseVisualStyleBackColor = false;
|
||||
this.restorebutton.Click += new System.EventHandler(this.restorebutton_Click);
|
||||
//
|
||||
@@ -759,31 +759,6 @@ namespace AndroidSideloader
|
||||
this.progressDLbtnContainer.Size = new System.Drawing.Size(984, 40);
|
||||
this.progressDLbtnContainer.TabIndex = 96;
|
||||
//
|
||||
// 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, 23);
|
||||
this.progressBar.Maximum = 100F;
|
||||
this.progressBar.Minimum = 0F;
|
||||
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 = 0F;
|
||||
//
|
||||
// diskLabel
|
||||
//
|
||||
this.diskLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
@@ -1249,35 +1224,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)))));
|
||||
@@ -1316,6 +1262,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)))));
|
||||
@@ -1499,57 +1497,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 = 100F;
|
||||
this.progressBar.Minimum = 0F;
|
||||
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 = 0F;
|
||||
//
|
||||
// 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";
|
||||
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
|
||||
//
|
||||
@@ -1600,11 +1600,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();
|
||||
|
||||
|
||||
660
MainForm.cs
660
MainForm.cs
@@ -74,6 +74,7 @@ namespace AndroidSideloader
|
||||
private static readonly Color ColorError = ColorTranslator.FromHtml("#f52f57");
|
||||
private Panel _listViewUninstallButton;
|
||||
private bool _listViewUninstallButtonHovered = false;
|
||||
private ListViewItem _hoveredItemForDeleteBtn;
|
||||
private bool isGalleryView; // Will be set from settings in constructor
|
||||
private List<ListViewItem> _galleryDataSource;
|
||||
private FastGalleryPanel _fastGallery;
|
||||
@@ -171,12 +172,10 @@ namespace AndroidSideloader
|
||||
if (_listViewUninstallButton == null)
|
||||
return;
|
||||
|
||||
// Check if we have a tagged item to track
|
||||
if (!(_listViewUninstallButton.Tag is ListViewItem item))
|
||||
return;
|
||||
var item = _hoveredItemForDeleteBtn;
|
||||
|
||||
// Verify item is still valid and selected
|
||||
if (!gamesListView.Items.Contains(item) || !item.Selected)
|
||||
// Hide if no item is hovered
|
||||
if (item == null || !gamesListView.Items.Contains(item))
|
||||
{
|
||||
_listViewUninstallButton.Visible = false;
|
||||
return;
|
||||
@@ -213,6 +212,7 @@ namespace AndroidSideloader
|
||||
if (isVisible)
|
||||
{
|
||||
_listViewUninstallButton.Location = new Point(buttonX, buttonY);
|
||||
_listViewUninstallButton.Tag = item; // Store reference for click handler
|
||||
if (!_listViewUninstallButton.Visible)
|
||||
{
|
||||
_listViewUninstallButton.Visible = true;
|
||||
@@ -225,12 +225,19 @@ namespace AndroidSideloader
|
||||
};
|
||||
uninstallButtonTimer.Start();
|
||||
|
||||
// Hide button when selection changes
|
||||
gamesListView.ItemSelectionChanged += (s, ev) =>
|
||||
gamesListView.MouseMove += (s, ev) =>
|
||||
{
|
||||
if (!ev.IsSelected && _listViewUninstallButton != null)
|
||||
var hitTest = gamesListView.HitTest(ev.Location);
|
||||
_hoveredItemForDeleteBtn = hitTest.Item;
|
||||
};
|
||||
|
||||
gamesListView.MouseLeave += (s, ev) =>
|
||||
{
|
||||
// Clear hover if mouse left the ListView bounds
|
||||
Point clientPoint = gamesListView.PointToClient(Control.MousePosition);
|
||||
if (!gamesListView.ClientRectangle.Contains(clientPoint))
|
||||
{
|
||||
_listViewUninstallButton.Visible = false;
|
||||
_hoveredItemForDeleteBtn = null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -577,28 +584,17 @@ namespace AndroidSideloader
|
||||
"Config Update Failed", MessageBoxButtons.OK);
|
||||
}
|
||||
}
|
||||
else if (settings.AutoUpdateConfig && settings.CreatePubMirrorFile)
|
||||
else if (settings.AutoUpdateConfig)
|
||||
{
|
||||
DialogResult dialogResult = FlexibleMessageBox.Show(Program.form,
|
||||
"Rookie has detected that you are missing the public config file, would you like to create it?",
|
||||
"Public Config Missing", MessageBoxButtons.YesNo);
|
||||
|
||||
if (dialogResult == DialogResult.Yes)
|
||||
// Auto-create the public config file if it doesn't exist
|
||||
Logger.Log("Public config file missing, creating automatically...");
|
||||
File.Create(configFilePath).Close();
|
||||
await GetPublicConfigAsync();
|
||||
if (!hasPublicConfig)
|
||||
{
|
||||
File.Create(configFilePath).Close();
|
||||
await GetPublicConfigAsync();
|
||||
if (!hasPublicConfig)
|
||||
{
|
||||
_ = FlexibleMessageBox.Show(Program.form,
|
||||
"Failed to fetch public mirror config, and the current one is unreadable.\r\nPlease ensure you can access https://vrpirates.wiki/ in your browser.",
|
||||
"Config Update Failed", MessageBoxButtons.OK);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.CreatePubMirrorFile = false;
|
||||
settings.AutoUpdateConfig = false;
|
||||
settings.Save();
|
||||
_ = FlexibleMessageBox.Show(Program.form,
|
||||
"Failed to fetch public mirror config, and the current one is unreadable.\r\nPlease ensure you can access https://vrpirates.wiki/ in your browser.",
|
||||
"Config Update Failed", MessageBoxButtons.OK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -876,22 +872,52 @@ namespace AndroidSideloader
|
||||
}
|
||||
ADB.DeviceID = GetDeviceID();
|
||||
|
||||
Thread t1 = new Thread(() =>
|
||||
{
|
||||
output += ADB.Sideload(path);
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
t1.Start();
|
||||
string filename = Path.GetFileName(path);
|
||||
changeTitle($"Installing {filename}...");
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.OperationType = "Installing";
|
||||
progressBar.Value = 0;
|
||||
progressBar.StatusText = "Preparing...";
|
||||
|
||||
while (t1.IsAlive)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
output = await ADB.SideloadWithProgressAsync(
|
||||
path,
|
||||
(percent, eta) => this.Invoke(() =>
|
||||
{
|
||||
if (percent == 0)
|
||||
{
|
||||
progressBar.IsIndeterminate = true;
|
||||
progressBar.OperationType = "Installing";
|
||||
}
|
||||
else
|
||||
{
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = percent;
|
||||
}
|
||||
UpdateProgressStatus("Installing", percent: (int)Math.Round(percent), eta: eta);
|
||||
progressBar.StatusText = $"Installing · {percent:0.0}%";
|
||||
}),
|
||||
status => this.Invoke(() =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(status))
|
||||
{
|
||||
if (status.Contains("Completing Installation"))
|
||||
{
|
||||
speedLabel.Text = status;
|
||||
}
|
||||
progressBar.StatusText = status;
|
||||
}
|
||||
}),
|
||||
"",
|
||||
filename);
|
||||
|
||||
// Reset UI on completion
|
||||
progressBar.Value = 0;
|
||||
progressBar.StatusText = "";
|
||||
progressBar.IsIndeterminate = false;
|
||||
speedLabel.Text = "";
|
||||
changeTitle("");
|
||||
|
||||
showAvailableSpace();
|
||||
|
||||
ShowPrcOutput(output);
|
||||
}
|
||||
|
||||
@@ -984,31 +1010,45 @@ namespace AndroidSideloader
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = 0;
|
||||
progressBar.OperationType = "Copying OBB";
|
||||
progressBar.StatusText = "Preparing...";
|
||||
|
||||
string currentStatusBase = string.Empty;
|
||||
|
||||
output = await ADB.CopyOBBWithProgressAsync(
|
||||
path,
|
||||
(progress, eta) => this.Invoke(() =>
|
||||
(percent, eta) => this.Invoke(() =>
|
||||
{
|
||||
progressBar.Value = progress;
|
||||
string etaStr = eta.HasValue && eta.Value.TotalSeconds > 0
|
||||
? $" · ETA: {eta.Value:mm\\:ss}"
|
||||
: "";
|
||||
speedLabel.Text = $"Progress: {progress}%{etaStr}";
|
||||
progressBar.Value = percent;
|
||||
UpdateProgressStatus("Copying OBB", percent: (int)Math.Round(percent), eta: eta);
|
||||
|
||||
if (!string.IsNullOrEmpty(currentStatusBase))
|
||||
{
|
||||
progressBar.StatusText = $"{currentStatusBase} · {percent:0.0}%";
|
||||
}
|
||||
else
|
||||
{
|
||||
progressBar.StatusText = $"Copying · {percent:0.0}%";
|
||||
}
|
||||
}),
|
||||
status => this.Invoke(() =>
|
||||
{
|
||||
progressBar.StatusText = status;
|
||||
currentStatusBase = status ?? string.Empty;
|
||||
if (!string.IsNullOrEmpty(status))
|
||||
{
|
||||
progressBar.StatusText = status;
|
||||
}
|
||||
}),
|
||||
folderName);
|
||||
|
||||
progressBar.Value = 100;
|
||||
// Reset UI on completion
|
||||
progressBar.Value = 0;
|
||||
progressBar.StatusText = "";
|
||||
changeTitle("Done.");
|
||||
showAvailableSpace();
|
||||
|
||||
ShowPrcOutput(output);
|
||||
changeTitle("");
|
||||
progressBar.IsIndeterminate = false;
|
||||
speedLabel.Text = "";
|
||||
changeTitle("");
|
||||
|
||||
showAvailableSpace();
|
||||
ShowPrcOutput(output);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1041,6 +1081,9 @@ namespace AndroidSideloader
|
||||
Text = "No Device Connected";
|
||||
if (!settings.NodeviceMode)
|
||||
{
|
||||
// Explicitly update sideloading UI when the dialog is shown
|
||||
UpdateSideloadingUI(true);
|
||||
|
||||
DialogResult dialogResult = FlexibleMessageBox.Show(Program.form, "No device found. Please ensure the following:\n\n - Developer mode is enabled\n - ADB drivers are installed\n - ADB connection is enabled on your device (this can reset)\n - Your device is plugged in\n\nThen press \"Retry\"", "No device found.", MessageBoxButtons.RetryCancel);
|
||||
if (dialogResult == DialogResult.Retry)
|
||||
{
|
||||
@@ -1184,8 +1227,8 @@ namespace AndroidSideloader
|
||||
string CurrBackups = Path.Combine(backupFolder, date_str);
|
||||
|
||||
DialogResult dialogResult1 = FlexibleMessageBox.Show(Program.form,
|
||||
$"Do you want to backup all gamesaves to:\n{CurrBackups}\\",
|
||||
"Backup Gamesaves",
|
||||
$"Do you want to attempt to backup all gamesaves to:\n{CurrBackups}\\",
|
||||
"Backup All Gamesaves",
|
||||
MessageBoxButtons.YesNo);
|
||||
|
||||
if (dialogResult1 == DialogResult.No || dialogResult1 == DialogResult.Cancel) return;
|
||||
@@ -1275,7 +1318,10 @@ namespace AndroidSideloader
|
||||
summary.AppendLine($" • {failed}");
|
||||
}
|
||||
|
||||
FlexibleMessageBox.Show(Program.form, summary.ToString(), "Backup Complete");
|
||||
summary.AppendLine("\nNote: Some games may not support bulk backup as they require special permissions.");
|
||||
summary.AppendLine("In this case, use 'BACKUP GAMESAVE WITH ADB' to backup the game individually.");
|
||||
|
||||
FlexibleMessageBox.Show(Program.form, summary.ToString(), "Bulk Backup Complete");
|
||||
}
|
||||
|
||||
private async void restorebutton_Click(object sender, EventArgs e)
|
||||
@@ -1715,23 +1761,49 @@ namespace AndroidSideloader
|
||||
};
|
||||
if (dialog.Show(Handle))
|
||||
{
|
||||
Thread t1 = new Thread(() =>
|
||||
{
|
||||
Sideloader.RecursiveOutput = new ProcessOutput(String.Empty, String.Empty);
|
||||
Sideloader.RecursiveCopyOBB(dialog.FileName);
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
t1.Start();
|
||||
changeTitle("Copying OBB folders to device...");
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = 0;
|
||||
progressBar.OperationType = "Copying OBB";
|
||||
progressBar.StatusText = "Preparing...";
|
||||
|
||||
Sideloader.RecursiveOutput = new ProcessOutput(String.Empty, String.Empty);
|
||||
|
||||
string currentStatusBase = string.Empty;
|
||||
|
||||
await Sideloader.RecursiveCopyOBBAsync(
|
||||
dialog.FileName,
|
||||
(percent, eta) => this.Invoke(() =>
|
||||
{
|
||||
progressBar.Value = percent;
|
||||
UpdateProgressStatus("Copying OBB", percent: (int)Math.Round(percent), eta: eta);
|
||||
|
||||
if (!string.IsNullOrEmpty(currentStatusBase))
|
||||
{
|
||||
progressBar.StatusText = $"{currentStatusBase} · {percent:0.0}%";
|
||||
}
|
||||
else
|
||||
{
|
||||
progressBar.StatusText = $"Copying · {percent:0.0}%";
|
||||
}
|
||||
}),
|
||||
status => this.Invoke(() =>
|
||||
{
|
||||
currentStatusBase = status ?? string.Empty;
|
||||
if (!string.IsNullOrEmpty(status))
|
||||
{
|
||||
changeTitle($"Copying: {status}");
|
||||
}
|
||||
}));
|
||||
|
||||
// Reset UI on completion
|
||||
progressBar.Value = 0;
|
||||
progressBar.StatusText = "";
|
||||
progressBar.IsIndeterminate = false;
|
||||
speedLabel.Text = "";
|
||||
changeTitle("");
|
||||
|
||||
showAvailableSpace();
|
||||
|
||||
while (t1.IsAlive)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
ShowPrcOutput(Sideloader.RecursiveOutput);
|
||||
}
|
||||
}
|
||||
@@ -1776,23 +1848,45 @@ namespace AndroidSideloader
|
||||
if (!data.Contains("+") && !data.Contains("_") && data.Contains("."))
|
||||
{
|
||||
_ = Logger.Log($"Copying {data} to device");
|
||||
changeTitle($"Copying {data} to device...");
|
||||
string folderName = Path.GetFileName(data);
|
||||
changeTitle($"Copying {folderName} to device...");
|
||||
|
||||
Thread t2 = new Thread(() =>
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = 0;
|
||||
progressBar.OperationType = "Copying OBB";
|
||||
progressBar.StatusText = "Preparing...";
|
||||
|
||||
{
|
||||
output += ADB.CopyOBB(data);
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
t2.Start();
|
||||
string currentStatusBase = string.Empty;
|
||||
|
||||
while (t2.IsAlive)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
output += await ADB.CopyOBBWithProgressAsync(
|
||||
data,
|
||||
(percent, eta) => this.Invoke(() =>
|
||||
{
|
||||
progressBar.Value = percent;
|
||||
UpdateProgressStatus("Copying OBB", percent: (int)Math.Round(percent), eta: eta);
|
||||
|
||||
if (!string.IsNullOrEmpty(currentStatusBase))
|
||||
{
|
||||
progressBar.StatusText = $"{currentStatusBase} · {percent:0.0}%";
|
||||
}
|
||||
else
|
||||
{
|
||||
progressBar.StatusText = $"Copying · {percent:0.0}%";
|
||||
}
|
||||
}),
|
||||
status => this.Invoke(() =>
|
||||
{
|
||||
currentStatusBase = status ?? string.Empty;
|
||||
if (!string.IsNullOrEmpty(status))
|
||||
{
|
||||
changeTitle($"Copying: {status}");
|
||||
}
|
||||
}),
|
||||
folderName);
|
||||
|
||||
// Reset UI after this operation
|
||||
progressBar.StatusText = "";
|
||||
speedLabel.Text = "";
|
||||
changeTitle("");
|
||||
settings.CurrPckg = dir;
|
||||
settings.Save();
|
||||
@@ -1827,42 +1921,88 @@ namespace AndroidSideloader
|
||||
};
|
||||
t3.Tick += timer_Tick4;
|
||||
t3.Start();
|
||||
changeTitle($"Sideloading APK ({filename})");
|
||||
|
||||
Thread t2 = new Thread(() =>
|
||||
{
|
||||
output += ADB.Sideload(file2);
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
t2.Start();
|
||||
while (t2.IsAlive)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
changeTitle($"Sideloading APK ({filename})");
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = 0;
|
||||
progressBar.OperationType = "Installing";
|
||||
progressBar.StatusText = "Preparing...";
|
||||
|
||||
output += await ADB.SideloadWithProgressAsync(
|
||||
file2,
|
||||
(percent, eta) => this.Invoke(() =>
|
||||
{
|
||||
if (percent == 0)
|
||||
{
|
||||
progressBar.IsIndeterminate = true;
|
||||
progressBar.OperationType = "Installing";
|
||||
}
|
||||
else
|
||||
{
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = percent;
|
||||
}
|
||||
UpdateProgressStatus("Installing", percent: (int)Math.Round(percent), eta: eta);
|
||||
progressBar.StatusText = $"Installing · {percent:0.0}%";
|
||||
}),
|
||||
status => this.Invoke(() =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(status))
|
||||
{
|
||||
if (status.Contains("Completing Installation"))
|
||||
{
|
||||
speedLabel.Text = status;
|
||||
}
|
||||
progressBar.StatusText = status;
|
||||
}
|
||||
}),
|
||||
cmdout,
|
||||
filename);
|
||||
|
||||
t3.Stop();
|
||||
|
||||
// Reset after APK install
|
||||
progressBar.StatusText = "";
|
||||
speedLabel.Text = "";
|
||||
|
||||
if (Directory.Exists($"{pathname}\\{cmdout}"))
|
||||
{
|
||||
_ = Logger.Log($"Copying OBB folder to device- {cmdout}");
|
||||
changeTitle($"Copying OBB folder to device...");
|
||||
Thread t1 = new Thread(() =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(cmdout))
|
||||
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = 0;
|
||||
progressBar.OperationType = "Copying OBB";
|
||||
progressBar.StatusText = "Preparing...";
|
||||
|
||||
string obbStatusBase = string.Empty;
|
||||
|
||||
output += await ADB.CopyOBBWithProgressAsync(
|
||||
$"{pathname}\\{cmdout}",
|
||||
(percent, eta) => this.Invoke(() =>
|
||||
{
|
||||
_ = ADB.RunAdbCommandToString($"shell rm -rf \"/sdcard/Android/obb/{cmdout}\" && mkdir \"/sdcard/Android/obb/{cmdout}\"");
|
||||
}
|
||||
_ = ADB.RunAdbCommandToString($"push \"{pathname}\\{cmdout}\" /sdcard/Android/obb/");
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
t1.Start();
|
||||
while (t1.IsAlive)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
progressBar.Value = percent;
|
||||
UpdateProgressStatus("Copying OBB", percent: (int)Math.Round(percent), eta: eta);
|
||||
|
||||
if (!string.IsNullOrEmpty(obbStatusBase))
|
||||
{
|
||||
progressBar.StatusText = $"{obbStatusBase} · {percent:0.0}%";
|
||||
}
|
||||
else
|
||||
{
|
||||
progressBar.StatusText = $"Copying · {percent:0.0}%";
|
||||
}
|
||||
}),
|
||||
status => this.Invoke(() =>
|
||||
{
|
||||
obbStatusBase = status ?? string.Empty;
|
||||
}),
|
||||
cmdout);
|
||||
|
||||
// Reset after OBB copy
|
||||
progressBar.StatusText = "";
|
||||
speedLabel.Text = "";
|
||||
changeTitle("");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1898,24 +2038,46 @@ namespace AndroidSideloader
|
||||
string[] folders = Directory.GetDirectories(data);
|
||||
foreach (string folder in folders)
|
||||
{
|
||||
string folderName = Path.GetFileName(folder);
|
||||
_ = Logger.Log($"Copying {folder} to device");
|
||||
changeTitle($"Copying {folder} to device...");
|
||||
changeTitle($"Copying {folderName} to device...");
|
||||
|
||||
Thread t2 = new Thread(() =>
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = 0;
|
||||
progressBar.OperationType = "Copying OBB";
|
||||
progressBar.StatusText = "Preparing...";
|
||||
|
||||
{
|
||||
output += ADB.CopyOBB(folder);
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
t2.Start();
|
||||
string folderStatusBase = string.Empty;
|
||||
|
||||
while (t2.IsAlive)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
output += await ADB.CopyOBBWithProgressAsync(
|
||||
folder,
|
||||
(percent, eta) => this.Invoke(() =>
|
||||
{
|
||||
progressBar.Value = percent;
|
||||
UpdateProgressStatus("Copying OBB", percent: (int)Math.Round(percent), eta: eta);
|
||||
|
||||
if (!string.IsNullOrEmpty(folderStatusBase))
|
||||
{
|
||||
progressBar.StatusText = $"{folderStatusBase} · {percent:0.0}%";
|
||||
}
|
||||
else
|
||||
{
|
||||
progressBar.StatusText = $"Copying · {percent:0.0}%";
|
||||
}
|
||||
}),
|
||||
status => this.Invoke(() =>
|
||||
{
|
||||
folderStatusBase = status ?? string.Empty;
|
||||
if (!string.IsNullOrEmpty(status))
|
||||
{
|
||||
changeTitle($"Copying: {status}");
|
||||
}
|
||||
}),
|
||||
folderName);
|
||||
|
||||
// Reset after folder copy
|
||||
progressBar.StatusText = "";
|
||||
speedLabel.Text = "";
|
||||
changeTitle("");
|
||||
settings.CurrPckg = dir;
|
||||
settings.Save();
|
||||
@@ -1979,43 +2141,85 @@ namespace AndroidSideloader
|
||||
timer.Start();
|
||||
|
||||
changeTitle($"Installing {dataname}...");
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = 0;
|
||||
progressBar.OperationType = "Installing";
|
||||
progressBar.StatusText = "Preparing...";
|
||||
|
||||
Thread t1 = new Thread(() =>
|
||||
{
|
||||
output += ADB.Sideload(data);
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
t1.Start();
|
||||
while (t1.IsAlive)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
output += await ADB.SideloadWithProgressAsync(
|
||||
data,
|
||||
(percent, eta) => this.Invoke(() =>
|
||||
{
|
||||
if (percent == 0)
|
||||
{
|
||||
progressBar.IsIndeterminate = true;
|
||||
progressBar.OperationType = "Installing";
|
||||
}
|
||||
else
|
||||
{
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = percent;
|
||||
}
|
||||
UpdateProgressStatus("Installing", percent: (int)Math.Round(percent), eta: eta);
|
||||
progressBar.StatusText = $"Installing · {percent:0.0}%";
|
||||
}),
|
||||
status => this.Invoke(() =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(status))
|
||||
{
|
||||
if (status.Contains("Completing Installation"))
|
||||
{
|
||||
speedLabel.Text = status;
|
||||
}
|
||||
progressBar.StatusText = status;
|
||||
}
|
||||
}),
|
||||
cmdout,
|
||||
dataname);
|
||||
|
||||
timer.Stop();
|
||||
|
||||
// Reset after APK install
|
||||
progressBar.StatusText = "";
|
||||
speedLabel.Text = "";
|
||||
|
||||
if (Directory.Exists($"{pathname}\\{cmdout}"))
|
||||
{
|
||||
_ = Logger.Log($"Copying OBB folder to device- {cmdout}");
|
||||
changeTitle($"Copying OBB folder to device...");
|
||||
Thread t2 = new Thread(() =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(cmdout))
|
||||
{
|
||||
_ = ADB.RunAdbCommandToString($"shell rm -rf \"/sdcard/Android/obb/{cmdout}\" && mkdir \"/sdcard/Android/obb/{cmdout}\"");
|
||||
}
|
||||
_ = ADB.RunAdbCommandToString($"push \"{pathname}\\{cmdout}\" /sdcard/Android/obb/");
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
t2.Start();
|
||||
while (t2.IsAlive)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = 0;
|
||||
progressBar.OperationType = "Copying OBB";
|
||||
progressBar.StatusText = "Preparing...";
|
||||
|
||||
string obbStatusBase = string.Empty;
|
||||
|
||||
output += await ADB.CopyOBBWithProgressAsync(
|
||||
$"{pathname}\\{cmdout}",
|
||||
(percent, eta) => this.Invoke(() =>
|
||||
{
|
||||
progressBar.Value = percent;
|
||||
UpdateProgressStatus("Copying OBB", percent: (int)Math.Round(percent), eta: eta);
|
||||
|
||||
if (!string.IsNullOrEmpty(obbStatusBase))
|
||||
{
|
||||
progressBar.StatusText = $"{obbStatusBase} · {percent:0.0}%";
|
||||
}
|
||||
else
|
||||
{
|
||||
progressBar.StatusText = $"Copying · {percent:0.0}%";
|
||||
}
|
||||
}),
|
||||
status => this.Invoke(() =>
|
||||
{
|
||||
obbStatusBase = status ?? string.Empty;
|
||||
}),
|
||||
cmdout);
|
||||
|
||||
// Reset after OBB copy
|
||||
progressBar.StatusText = "";
|
||||
speedLabel.Text = "";
|
||||
changeTitle("");
|
||||
}
|
||||
}
|
||||
@@ -2032,21 +2236,41 @@ namespace AndroidSideloader
|
||||
File.Copy(data, Path.Combine(foldername, filename));
|
||||
path = foldername;
|
||||
|
||||
Thread t1 = new Thread(() =>
|
||||
{
|
||||
output += ADB.CopyOBB(path);
|
||||
})
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
_ = Logger.Log($"Copying OBB folder to device- {path}");
|
||||
changeTitle($"Copying OBB folder to device ({filename})");
|
||||
t1.Start();
|
||||
|
||||
while (t1.IsAlive)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
progressBar.IsIndeterminate = false;
|
||||
progressBar.Value = 0;
|
||||
progressBar.OperationType = "Copying OBB";
|
||||
progressBar.StatusText = "Preparing...";
|
||||
|
||||
string obbStatusBase = string.Empty;
|
||||
|
||||
output += await ADB.CopyOBBWithProgressAsync(
|
||||
path,
|
||||
(percent, eta) => this.Invoke(() =>
|
||||
{
|
||||
progressBar.Value = percent;
|
||||
UpdateProgressStatus("Copying OBB", percent: (int)Math.Round(percent), eta: eta);
|
||||
|
||||
if (!string.IsNullOrEmpty(obbStatusBase))
|
||||
{
|
||||
progressBar.StatusText = $"{obbStatusBase} · {percent:0.0}%";
|
||||
}
|
||||
else
|
||||
{
|
||||
progressBar.StatusText = $"Copying · {percent:0.0}%";
|
||||
}
|
||||
}),
|
||||
status => this.Invoke(() =>
|
||||
{
|
||||
obbStatusBase = status ?? string.Empty;
|
||||
}),
|
||||
filename);
|
||||
|
||||
// Reset after OBB copy
|
||||
progressBar.StatusText = "";
|
||||
speedLabel.Text = "";
|
||||
|
||||
FileSystemUtilities.TryDeleteDirectory(foldername);
|
||||
changeTitle("");
|
||||
@@ -2104,7 +2328,11 @@ namespace AndroidSideloader
|
||||
}
|
||||
}
|
||||
|
||||
// Final reset of all UI elements
|
||||
progressBar.Value = 0;
|
||||
progressBar.StatusText = "";
|
||||
progressBar.IsIndeterminate = false;
|
||||
speedLabel.Text = "";
|
||||
|
||||
showAvailableSpace();
|
||||
ShowPrcOutput(output);
|
||||
@@ -2387,7 +2615,7 @@ namespace AndroidSideloader
|
||||
|
||||
// Check if this is a 0 MB entry that should be excluded
|
||||
bool shouldSkip = false;
|
||||
if (release.Length > 5 && StringUtilities.TryParseDouble(release[6], out double sizeInMB))
|
||||
if (release.Length > 5 && StringUtilities.TryParseDouble(release[5], out double sizeInMB))
|
||||
{
|
||||
// If size is 0 MB and this is not already an MR-Fix version
|
||||
if (sizeInMB == 0 && gameName.IndexOf("(MR-Fix)", StringComparison.OrdinalIgnoreCase) < 0)
|
||||
@@ -5846,18 +6074,17 @@ function onYouTubeIframeAPIReady() {
|
||||
return simpleMatch.Success ? simpleMatch.Groups[1].Value : string.Empty;
|
||||
}
|
||||
|
||||
// Prepare game name words for matching
|
||||
string lowerGameName = cleanedGameName.ToLowerInvariant();
|
||||
// Normalize: remove apostrophes and convert to lowercase
|
||||
string lowerGameName = cleanedGameName.ToLowerInvariant().Replace("'", "");
|
||||
var gameWords = lowerGameName
|
||||
.Split(new[] { ' ', '-', ':', '&' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.ToList();
|
||||
|
||||
int requiredMatches = Math.Max(1, gameWords.Count / 2);
|
||||
int requiredMatches = gameWords.Count;
|
||||
string bestVideoId = null;
|
||||
int bestScore = 0;
|
||||
int position = 0;
|
||||
|
||||
// Score each match
|
||||
foreach (Match match in videoMatches)
|
||||
{
|
||||
string videoId = match.Groups[1].Value;
|
||||
@@ -5866,18 +6093,20 @@ function onYouTubeIframeAPIReady() {
|
||||
title = UnicodeEscapeRegex.Replace(title, m =>
|
||||
((char)Convert.ToInt32(m.Groups[1].Value, 16)).ToString());
|
||||
|
||||
// Entry must match at least half the game name
|
||||
int matchedWords = gameWords.Count(w => title.Contains(w));
|
||||
if (matchedWords < requiredMatches)
|
||||
// Normalize title: remove apostrophes for matching
|
||||
string normalizedTitle = title.Replace("'", "");
|
||||
|
||||
// All game words must be present
|
||||
if (!gameWords.All(w => normalizedTitle.Contains(w)))
|
||||
continue;
|
||||
|
||||
position++;
|
||||
|
||||
// Only process first 5 matches
|
||||
if (position > 5)
|
||||
// Only process first 10 matches
|
||||
if (position > 10)
|
||||
break;
|
||||
|
||||
int score = matchedWords * 10;
|
||||
int score = 0;
|
||||
|
||||
// Position bonus
|
||||
if (position == 1) score += 30;
|
||||
@@ -5885,9 +6114,10 @@ function onYouTubeIframeAPIReady() {
|
||||
else if (position == 3) score += 10;
|
||||
|
||||
// Word bonus
|
||||
if (title.Contains("trailer")) score += 20;
|
||||
if (title.Contains("official") || title.Contains("launch") || title.Contains("release")) score += 15;
|
||||
if (title.Contains("announce")) score += 12; // also includes "announcement"
|
||||
if (title.Contains("trailer") || title.Contains("teaser")) score += 25;
|
||||
if (title.Contains("official")) score += 20;
|
||||
if (title.Contains("launch") || title.Contains("release")) score += 15;
|
||||
if (title.Contains("announce") || title.Contains("reveal")) score += 12; // also includes "announcement"
|
||||
if (title.Contains("gameplay") || title.Contains("vr")) score += 5;
|
||||
|
||||
// Noise penalty for extra words
|
||||
@@ -5900,6 +6130,9 @@ function onYouTubeIframeAPIReady() {
|
||||
if (title.Contains("review") ||
|
||||
title.Contains("tutorial") ||
|
||||
title.Contains("how to") ||
|
||||
title.Contains("install") ||
|
||||
title.Contains("guide") ||
|
||||
title.Contains("setup") ||
|
||||
title.Contains("reaction"))
|
||||
score -= 30;
|
||||
|
||||
@@ -5941,27 +6174,6 @@ function onYouTubeIframeAPIReady() {
|
||||
// Update the selected game label in the sidebar
|
||||
selectedGameLabel.Text = CurrentGameName;
|
||||
|
||||
// Show uninstall button only for installed games
|
||||
bool isInstalled = selectedItem.ForeColor.ToArgb() == ColorInstalled.ToArgb() ||
|
||||
selectedItem.ForeColor.ToArgb() == ColorUpdateAvailable.ToArgb() ||
|
||||
selectedItem.ForeColor.ToArgb() == ColorDonateGame.ToArgb();
|
||||
|
||||
if (isInstalled && _listViewUninstallButton != null)
|
||||
{
|
||||
// Position the button at the right side of the selected item
|
||||
Rectangle itemBounds = selectedItem.Bounds;
|
||||
int buttonX = gamesListView.ClientSize.Width - _listViewUninstallButton.Width - 5;
|
||||
int buttonY = itemBounds.Top + (itemBounds.Height - _listViewUninstallButton.Height) / 2;
|
||||
|
||||
// Ensure the button stays within visible bounds
|
||||
if (buttonY >= 0 && buttonY + _listViewUninstallButton.Height <= gamesListView.ClientSize.Height)
|
||||
{
|
||||
_listViewUninstallButton.Location = new Point(buttonX, buttonY);
|
||||
_listViewUninstallButton.Tag = selectedItem; // Store reference to the item
|
||||
_listViewUninstallButton.Visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Thumbnail
|
||||
if (!keyheld)
|
||||
{
|
||||
@@ -6014,7 +6226,7 @@ function onYouTubeIframeAPIReady() {
|
||||
var videoId = await ResolveVideoIdAsync(CurrentGameName);
|
||||
if (string.IsNullOrEmpty(videoId))
|
||||
{
|
||||
changeTitle("No Trailer found");
|
||||
changeTitle("No Trailer found", true);
|
||||
ShowVideoPlaceholder();
|
||||
}
|
||||
else
|
||||
@@ -6547,6 +6759,29 @@ function onYouTubeIframeAPIReady() {
|
||||
settings.AddFavoriteGame(packageName);
|
||||
|
||||
UpdateFavoriteMenuItemText();
|
||||
|
||||
// If currently viewing favorites, refresh the list to reflect the change
|
||||
bool isViewingFavorites = favoriteSwitcher.Text == "ALL";
|
||||
if (isViewingFavorites)
|
||||
{
|
||||
var favSet = new HashSet<string>(settings.FavoritedGames, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
var favoriteItems = _allItems
|
||||
.Where(item => item.SubItems.Count > 1 && favSet.Contains(item.SubItems[1].Text))
|
||||
.ToList();
|
||||
|
||||
gamesListView.BeginUpdate();
|
||||
gamesListView.Items.Clear();
|
||||
gamesListView.Items.AddRange(favoriteItems.ToArray());
|
||||
gamesListView.EndUpdate();
|
||||
|
||||
_galleryDataSource = favoriteItems;
|
||||
if (isGalleryView && _fastGallery != null)
|
||||
{
|
||||
_fastGallery.RefreshFavoritesCache();
|
||||
_fastGallery.UpdateItems(favoriteItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateFavoriteMenuItemText()
|
||||
@@ -7055,6 +7290,7 @@ function onYouTubeIframeAPIReady() {
|
||||
_fastGallery.TileDoubleClicked += FastGallery_TileDoubleClicked;
|
||||
_fastGallery.TileDeleteClicked += FastGallery_TileDeleteClicked;
|
||||
_fastGallery.SortChanged += FastGallery_SortChanged;
|
||||
_fastGallery.TileHovered += FastGallery_TileHovered;
|
||||
|
||||
// Apply current shared sort state to gallery
|
||||
_fastGallery.SetSortState(_sharedSortField, _sharedSortDirection);
|
||||
@@ -7088,6 +7324,14 @@ function onYouTubeIframeAPIReady() {
|
||||
SaveWindowState();
|
||||
}
|
||||
|
||||
private void FastGallery_TileHovered(object sender, string releaseName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(releaseName)) return;
|
||||
|
||||
string notePath = Path.Combine(SideloaderRCLONE.NotesFolder, $"{releaseName}.txt");
|
||||
UpdateReleaseNotes(notePath);
|
||||
}
|
||||
|
||||
private void GamesGalleryView_Resize(object sender, EventArgs e)
|
||||
{
|
||||
if (_fastGallery != null && !_fastGallery.IsDisposed)
|
||||
@@ -8500,7 +8744,7 @@ function onYouTubeIframeAPIReady() {
|
||||
UpdateSideloadingUI();
|
||||
}
|
||||
|
||||
public void UpdateSideloadingUI()
|
||||
public void UpdateSideloadingUI(bool isNoDeviceDialogShown = false)
|
||||
{
|
||||
// Update the sideload button text
|
||||
if (settings.NodeviceMode)
|
||||
@@ -8517,11 +8761,19 @@ function onYouTubeIframeAPIReady() {
|
||||
{
|
||||
sideloadingStatusLabel.Text = "Sideloading: Disabled";
|
||||
sideloadingStatusLabel.ForeColor = Color.FromArgb(255, 100, 100); // Red-ish for disabled
|
||||
downloadInstallGameButton.Text = "DOWNLOAD";
|
||||
}
|
||||
else if (isNoDeviceDialogShown || (!DeviceConnected && !isLoading))
|
||||
{
|
||||
sideloadingStatusLabel.Text = "Sideloading: No Device Connected";
|
||||
sideloadingStatusLabel.ForeColor = Color.FromArgb(240, 150, 50); // Orange for no device
|
||||
downloadInstallGameButton.Text = "DOWNLOAD";
|
||||
}
|
||||
else
|
||||
{
|
||||
sideloadingStatusLabel.Text = "Sideloading: Enabled";
|
||||
sideloadingStatusLabel.ForeColor = Color.FromArgb(93, 203, 173); // Accent green for enabled
|
||||
downloadInstallGameButton.Text = "DOWNLOAD AND INSTALL";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -193,5 +193,6 @@
|
||||
</Setting>
|
||||
<Setting Name="selectedMirror" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
@@ -1,13 +1,14 @@
|
||||
using JR.Utils.GUI.Forms;
|
||||
using AndroidSideloader.Utilities;
|
||||
using JR.Utils.GUI.Forms;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Management;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Drawing;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using AndroidSideloader.Utilities;
|
||||
|
||||
namespace AndroidSideloader
|
||||
{
|
||||
@@ -84,9 +85,12 @@ namespace AndroidSideloader
|
||||
return output;
|
||||
}
|
||||
|
||||
//Recursive sideload any apk fileD
|
||||
//Recursive sideload any apk file
|
||||
public static ProcessOutput RecursiveOutput = new ProcessOutput();
|
||||
public static void RecursiveSideload(string FolderPath)
|
||||
public static async Task RecursiveSideloadAsync(
|
||||
string FolderPath,
|
||||
Action<float, TimeSpan?> progressCallback = null,
|
||||
Action<string> statusCallback = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -94,31 +98,40 @@ namespace AndroidSideloader
|
||||
{
|
||||
if (Path.GetExtension(f) == ".apk")
|
||||
{
|
||||
RecursiveOutput += ADB.Sideload(f);
|
||||
string gameName = Path.GetFileNameWithoutExtension(f);
|
||||
statusCallback?.Invoke(gameName);
|
||||
RecursiveOutput += await ADB.SideloadWithProgressAsync(f, progressCallback, statusCallback, "", gameName);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string d in Directory.GetDirectories(FolderPath))
|
||||
{
|
||||
RecursiveSideload(d);
|
||||
await RecursiveSideloadAsync(d, progressCallback, statusCallback);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { _ = Logger.Log(ex.Message, LogLevel.ERROR); }
|
||||
}
|
||||
|
||||
//Recursive copy any obb folder
|
||||
public static void RecursiveCopyOBB(string FolderPath)
|
||||
public static async Task RecursiveCopyOBBAsync(
|
||||
string FolderPath,
|
||||
Action<float, TimeSpan?> progressCallback = null,
|
||||
Action<string> statusCallback = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (string f in Directory.GetFiles(FolderPath))
|
||||
{
|
||||
RecursiveOutput += ADB.CopyOBB(f);
|
||||
}
|
||||
|
||||
foreach (string d in Directory.GetDirectories(FolderPath))
|
||||
{
|
||||
RecursiveCopyOBB(d);
|
||||
string folderName = Path.GetFileName(d);
|
||||
if (folderName.Contains("."))
|
||||
{
|
||||
statusCallback?.Invoke(folderName);
|
||||
RecursiveOutput += await ADB.CopyOBBWithProgressAsync(d, progressCallback, statusCallback, folderName);
|
||||
}
|
||||
else
|
||||
{
|
||||
await RecursiveCopyOBBAsync(d, progressCallback, statusCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { _ = Logger.Log(ex.Message, LogLevel.ERROR); }
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace AndroidSideloader
|
||||
private static readonly string RawGitHubUrl = "https://raw.githubusercontent.com/VRPirates/rookie";
|
||||
public static readonly string GitHubUrl = "https://github.com/VRPirates/rookie";
|
||||
|
||||
public static readonly string LocalVersion = "3.0";
|
||||
public static readonly string LocalVersion = "3.0.1";
|
||||
public static string currentVersion = string.Empty;
|
||||
public static string changelog = string.Empty;
|
||||
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
RSL 3.0
|
||||
RSL 3.0.1
|
||||
|
||||
Major Rookie overhaul with modernized UI, significant performance improvements and upgraded UX.
|
||||
|
||||
- Added high-performance Gallery View with search, filters, sorting, favorites, hover animations, smooth scrolling and uninstall buttons
|
||||
- Toggle seamlessly between List and Gallery views with your preference remembered across launches
|
||||
- Complete UI redesign with new dark theme, modernized components and subtle animations throughout
|
||||
- Refined navigation, layouts, sizing and color consistency across the entire application
|
||||
- Added uninstall buttons directly in List and Gallery views for quicker app management
|
||||
- Improved startup performance through overhaul of initialization logic, removal of splash screen, parallelized async loading, batched version retrieval, optimized metadata extraction and game list initialization
|
||||
- Instant list filtering through caching and streamlined filter logic (INSTALLED / UPDATE AVAILABLE / NEWER THAN LIST)
|
||||
- Improved search speed and responsiveness
|
||||
- Fixed and improved trailer handling with faster trailer loading
|
||||
- Fixed multiple startup issues including connection errors and zombie ADB instances
|
||||
- Added local blacklist support allowing users to permanently suppress donation prompts for specific apps
|
||||
- Reduced application size by removal of now unused assets
|
||||
- Fixed popularity ranking not working on some systems
|
||||
- Fixed favorites not updating immediately when removing items
|
||||
- Improved YouTube trailer matching accuracy
|
||||
- Implemented real-time progress updates for drag and drop operations
|
||||
- Refined backup button labels and dialogs
|
||||
- Gallery View: Added grouped tiles for games with multiple versions (e.g. Beat Saber)
|
||||
- ListView: Uninstall button now shows on hover instead of click
|
||||
- Public config file is now created automatically without prompt
|
||||
- Sideloading status label now shows device connection state
|
||||
- Download button text now reflects sideloading status
|
||||
Reference in New Issue
Block a user