Skip to content

Collapse engine patch/undo/status into one dynamic button#38

Merged
RobThePCGuy merged 1 commit into
masterfrom
feat/engine-single-button
Jul 9, 2026
Merged

Collapse engine patch/undo/status into one dynamic button#38
RobThePCGuy merged 1 commit into
masterfrom
feat/engine-single-button

Conversation

@RobThePCGuy

Copy link
Copy Markdown
Owner

Replaces the three engine widgets — Patch button, Undo button, and the status label — with a single button whose label, colour, tooltip, and action all reflect the live engine state:

State Button
Not patched "Patch BlueStacks Engine (required for root)" (red) → patches
Patched "✓ Engine patched — click to Undo (restore originals)" (green) → restores
Partially patched "⚠ Engine partially patched — click to finish patching" (orange) → patches
Unknown build greyed / disabled

State is re-read at click time so a stale label can't send the action the wrong way. Busy-state disabling is handled by the existing _set_busy path.

Verified live: Undo → restore → re-patch cycle works in the app; and headlessly across all four states (correct label/colour/action/enabled) plus busy-disable.

(Supersedes #37, which auto-closed when its stacked base branch was deleted on merge of #36.)

Three separate widgets (Patch button, Undo button, status label) become a
single state-driven button:

- unpatched -> "Patch BlueStacks Engine (required for root)" (red), patches
- patched   -> "Engine patched - click to Undo" (green), restores
- partial   -> "Engine partially patched - click to finish patching" (orange)
- unknown   -> disabled, greyed

The label, colour, tooltip, and click action all derive from the live engine
state, re-read at click time so a stale label can't trigger the wrong action.
@RobThePCGuy
RobThePCGuy merged commit 6d84b97 into master Jul 9, 2026
4 checks passed
@RobThePCGuy
RobThePCGuy deleted the feat/engine-single-button branch July 9, 2026 04:34

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the BlueStacks engine patching UI by consolidating the separate patch and restore buttons, along with the status label, into a single dynamic button that updates its appearance and action based on the current patch state. The review feedback highlights a potential issue where unrecognized builds (state "unknown") could accidentally be patched. To prevent this, it is recommended to set the engine action to None for unknown states and explicitly verify the action type in the click handler before executing any operations.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread main.py
Comment on lines +216 to +219
# Remember the action for the click handler; disabled only on unknown
# builds (busy-state disabling is handled by _set_busy during ops).
self._engine_action = "restore" if state == "patched" else "patch"
self.engine_button.setEnabled(enabled)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If the engine state is determined to be unknown, the button is disabled, but self._engine_action is still set to "patch". If handle_engine_button is triggered (e.g., due to a race condition or if the state becomes unknown during the click-time refresh), it will proceed to call self.handle_apply_patches(). This could attempt to patch an unrecognized build, potentially corrupting the binaries.

To prevent accidental patching of unrecognized builds, we should set self._engine_action to None when the state is unknown.

Suggested change
# Remember the action for the click handler; disabled only on unknown
# builds (busy-state disabling is handled by _set_busy during ops).
self._engine_action = "restore" if state == "patched" else "patch"
self.engine_button.setEnabled(enabled)
# Remember the action for the click handler; disabled only on unknown
# builds (busy-state disabling is handled by _set_busy during ops).
self._engine_action = "restore" if state == "patched" else ("patch" if state != "unknown" else None)
self.engine_button.setEnabled(enabled)

Comment thread main.py
Comment on lines +235 to +242
def handle_engine_button(self) -> None:
"""Patch or restore the engine, per the current (freshly-read) state."""
# Re-read state at click time so a stale label can't send us the wrong way.
self._refresh_patch_ui()
if getattr(self, "_engine_action", "patch") == "restore":
self.handle_restore_patches()
else:
self.handle_apply_patches()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Currently, if self._engine_action is not "restore", the handler defaults to calling self.handle_apply_patches(). If the state is unknown (or if there is no patch build), we should avoid executing any action.

We should explicitly check for "restore" and "patch" actions, and do nothing if the action is None.

Suggested change
def handle_engine_button(self) -> None:
"""Patch or restore the engine, per the current (freshly-read) state."""
# Re-read state at click time so a stale label can't send us the wrong way.
self._refresh_patch_ui()
if getattr(self, "_engine_action", "patch") == "restore":
self.handle_restore_patches()
else:
self.handle_apply_patches()
def handle_engine_button(self) -> None:
"""Patch or restore the engine, per the current (freshly-read) state."""
# Re-read state at click time so a stale label can't send us the wrong way.
self._refresh_patch_ui()
action = getattr(self, "_engine_action", None)
if action == "restore":
self.handle_restore_patches()
elif action == "patch":
self.handle_apply_patches()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant