From 2f12236ac8973bdfb734445bcbcb2112d96eb752 Mon Sep 17 00:00:00 2001 From: Mykola Grymalyuk Date: Mon, 15 May 2023 11:10:12 -0600 Subject: [PATCH] GUI: Implement update flow --- .../Contents/Info.plist | 2 +- resources/constants.py | 1 + resources/main.py | 4 +-- resources/utilities.py | 1 + resources/wx_gui/gui_build.py | 3 ++ resources/wx_gui/gui_install_oc.py | 28 +++++++++++++++-- resources/wx_gui/gui_main_menu.py | 31 +++++++++++++++++++ resources/wx_gui/gui_support.py | 9 ++++++ resources/wx_gui/gui_sys_patch.py | 9 +++++- 9 files changed, 81 insertions(+), 7 deletions(-) diff --git a/payloads/Tools/OpenCore-Patcher-Helper.app/Contents/Info.plist b/payloads/Tools/OpenCore-Patcher-Helper.app/Contents/Info.plist index 48c6d54f4..082a4cdf7 100644 --- a/payloads/Tools/OpenCore-Patcher-Helper.app/Contents/Info.plist +++ b/payloads/Tools/OpenCore-Patcher-Helper.app/Contents/Info.plist @@ -13,7 +13,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - OpenCore-Patcher + OpenCore-Patcher-Helper CFBundlePackageType APPL LSMinimumSystemVersion diff --git a/resources/constants.py b/resources/constants.py index f90ba79f3..0610026fa 100644 --- a/resources/constants.py +++ b/resources/constants.py @@ -131,6 +131,7 @@ class Constants: self.launcher_script: str = None # Determine launch file path (None if PyInstaller) self.booted_oc_disk: str = None # Determine current disk OCLP booted from self.unpack_thread = None # Determine if unpack thread finished (threading.Thread) + self.update_stage: int = 0 # Determine update stage (see gui_support.py) self.commit_info: tuple = (None, None, None) # Commit info (Branch, Commit Date, Commit URL) diff --git a/resources/main.py b/resources/main.py index 278d1ff33..9797cfcdf 100644 --- a/resources/main.py +++ b/resources/main.py @@ -6,7 +6,6 @@ import logging import threading from pathlib import Path -from resources.gui import gui_main from resources.wx_gui import gui_entry from resources import ( constants, @@ -39,7 +38,6 @@ class OpenCoreLegacyPatcher: self._generate_base_data() if utilities.check_cli_args() is None: - # gui_main.wx_python_gui(self.constants).main_menu(None) gui_entry.EntryPoint(self.constants).start() @@ -101,7 +99,7 @@ class OpenCoreLegacyPatcher: logging.info("- Detected arguments, switching to CLI mode") self.constants.gui_mode = True # Assumes no user interaction is required - ignore_args = ["--auto_patch", "--gui_patch", "--gui_unpatch"] + ignore_args = ["--auto_patch", "--gui_patch", "--gui_unpatch", "--update_installed"] if not any(x in sys.argv for x in ignore_args): self.constants.current_path = Path.cwd() self.constants.cli_mode = True diff --git a/resources/utilities.py b/resources/utilities.py index 186be82b1..63d3fad97 100644 --- a/resources/utilities.py +++ b/resources/utilities.py @@ -572,6 +572,7 @@ def check_cli_args(): parser.add_argument("--gui_patch", help="Starts GUI in Root Patcher", action="store_true", required=False) parser.add_argument("--gui_unpatch", help="Starts GUI in Root Unpatcher", action="store_true", required=False) parser.add_argument("--auto_patch", help="Check if patches are needed and prompt user", action="store_true", required=False) + parser.add_argument("--update_installed", help="Prompt user to finish updating via GUI", action="store_true", required=False) args = parser.parse_args() if not (args.build or args.patch_sys_vol or args.unpatch_sys_vol or args.validate or args.auto_patch): diff --git a/resources/wx_gui/gui_build.py b/resources/wx_gui/gui_build.py index e0cdc3541..d6e1d519c 100644 --- a/resources/wx_gui/gui_build.py +++ b/resources/wx_gui/gui_build.py @@ -33,6 +33,9 @@ class BuildFrame(wx.Frame): self._generate_elements(self.frame_modal) + if self.constants.update_stage != gui_support.AutoUpdateStages.INACTIVE: + self.constants.update_stage = gui_support.AutoUpdateStages.BUILDING + self.SetPosition(screen_location) if screen_location else self.Centre() self.frame_modal.ShowWindowModal() diff --git a/resources/wx_gui/gui_install_oc.py b/resources/wx_gui/gui_install_oc.py index 83f017af8..fbe117435 100644 --- a/resources/wx_gui/gui_install_oc.py +++ b/resources/wx_gui/gui_install_oc.py @@ -3,7 +3,7 @@ import threading import logging import traceback -from resources.wx_gui import gui_main_menu, gui_support +from resources.wx_gui import gui_main_menu, gui_support, gui_sys_patch from resources import constants, install @@ -27,6 +27,9 @@ class InstallOCFrame(wx.Frame): self._generate_elements() + if self.constants.update_stage != gui_support.AutoUpdateStages.INACTIVE: + self.constants.update_stage = gui_support.AutoUpdateStages.INSTALLING + self.SetPosition(screen_location) if screen_location else self.Centre() self.Show() @@ -262,7 +265,25 @@ class InstallOCFrame(wx.Frame): wx.GetApp().Yield() if self.result is True: - if not self.constants.custom_model: + if self.constants.update_stage != gui_support.AutoUpdateStages.INACTIVE: + self.constants.update_stage = gui_support.AutoUpdateStages.ROOT_PATCHING + popup_message = wx.MessageDialog( + self, + f"OpenCore has finished installing to disk.\n\nWould you like to update your root patches next?", "Success", + wx.YES_NO | wx.YES_DEFAULT + ) + popup_message.ShowModal() + if popup_message.GetReturnCode() == wx.ID_YES: + gui_sys_patch.SysPatchFrame( + parent=None, + title=self.title, + global_constants=self.constants, + screen_location=self.GetPosition() + ) + self.Destroy() + return + + elif not self.constants.custom_model: gui_support.RestartHost(self).restart(message="OpenCore has finished installing to disk.\n\nYou will need to reboot and hold the Option key and select OpenCore/Boot EFI's option.\n\nWould you like to reboot?") else: popup_message = wx.MessageDialog( @@ -271,6 +292,9 @@ class InstallOCFrame(wx.Frame): wx.OK ) popup_message.ShowModal() + else: + if self.constants.update_stage != gui_support.AutoUpdateStages.INACTIVE: + self.constants.update_stage = gui_support.AutoUpdateStages.FINISHED def _install_oc(self, partition: dict) -> None: diff --git a/resources/wx_gui/gui_main_menu.py b/resources/wx_gui/gui_main_menu.py index 5c2bd6568..23c6e663d 100644 --- a/resources/wx_gui/gui_main_menu.py +++ b/resources/wx_gui/gui_main_menu.py @@ -1,4 +1,7 @@ +# Generate GUI for main menu import wx +import sys +import time import logging import threading @@ -113,6 +116,34 @@ class MainFrame(wx.Frame): self.on_build_and_install() return + if "--update_installed" in sys.argv and self.constants.has_checked_updates is False and gui_support.CheckProperties(self.constants).host_can_build(): + # Notify user that the update has been installed + self.constants.has_checked_updates = True + pop_up = wx.MessageDialog( + self, + f"OpenCore Legacy Patcher has been updated to the latest version: {self.constants.patcher_version}\n\nWould you like to update OpenCore and your root volume patches?", + "Update successful!", + style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_INFORMATION + ) + pop_up.ShowModal() + + if pop_up.GetReturnCode() != wx.ID_YES: + print("- Skipping OpenCore and root volume patch update...") + return + + + print("- Updating OpenCore and root volume patches...") + self.constants.update_stage = gui_support.AutoUpdateStages.CHECKING + self.Hide() + pos = self.GetPosition() + gui_build.BuildFrame( + parent=None, + title=self.title, + global_constants=self.constants, + screen_location=pos + ) + self.Close() + threading.Thread(target=self._check_for_updates).start() diff --git a/resources/wx_gui/gui_support.py b/resources/wx_gui/gui_support.py index 1aea7db61..ee587de2f 100644 --- a/resources/wx_gui/gui_support.py +++ b/resources/wx_gui/gui_support.py @@ -11,6 +11,15 @@ from resources import constants from data import model_array, os_data +class AutoUpdateStages: + INACTIVE = 0 + CHECKING = 1 + BUILDING = 2 + INSTALLING = 3 + ROOT_PATCHING = 4 + FINISHED = 5 + + class GenerateMenubar: def __init__(self) -> None: diff --git a/resources/wx_gui/gui_sys_patch.py b/resources/wx_gui/gui_sys_patch.py index 5620ababa..df2ca7d53 100644 --- a/resources/wx_gui/gui_sys_patch.py +++ b/resources/wx_gui/gui_sys_patch.py @@ -39,6 +39,7 @@ class SysPatchFrame(wx.Frame): self.constants: constants.Constants = global_constants self.frame_modal: wx.Dialog = None self.return_button: wx.Button = None + self.available_patches: bool = False self.frame_modal = wx.Dialog(self, title=title, size=(360, 200)) self.SetPosition(screen_location) if screen_location else self.Centre() @@ -49,6 +50,10 @@ class SysPatchFrame(wx.Frame): self._generate_elements_display_patches(self.frame_modal, patches) self.frame_modal.ShowWindowModal() + if self.constants.update_stage != gui_support.AutoUpdateStages.INACTIVE: + if self.available_patches is False: + gui_support.RestartHost(self).restart(message="No root patch updates needed!\n\nWould you like to reboot to apply the new OpenCore build?") + def _kdk_download(self, frame: wx.Frame = None) -> bool: frame = self if not frame else frame @@ -239,12 +244,14 @@ class SysPatchFrame(wx.Frame): if not patches: start_button.Disable() else: + self.available_patches = True if patches["Validation: Patching Possible"] is False: start_button.Disable() + elif no_new_patches is False: + start_button.SetDefault() if can_unpatch is False: revert_button.Disable() - # Relaunch as root if not root uid = os.geteuid() if uid != 0: