Add App Update checks to GUI

This commit is contained in:
Mykola Grymalyuk
2022-01-15 16:16:04 -07:00
parent 0bd3ce595d
commit 0e969ee6cd
5 changed files with 168 additions and 4 deletions
+3
View File
@@ -26,6 +26,9 @@
- Disable AirPlay to Mac/Sidecar patch set by default - Disable AirPlay to Mac/Sidecar patch set by default
- Work-around some older systems with memory instability - Work-around some older systems with memory instability
- Configurable by end user to re-enable (via FeatureUnlock setting) - Configurable by end user to re-enable (via FeatureUnlock setting)
- Add App Update checks to GUI
- If new version available, app will prompt on launch.
- Configurable in Developer Settings
## 0.3.3 ## 0.3.3
- Disable Asset Caching support with spoofless approach - Disable Asset Caching support with spoofless approach
+1 -1
View File
@@ -43,7 +43,7 @@ exe = EXE(pyz,
app = BUNDLE(exe, app = BUNDLE(exe,
name='OpenCore-Patcher.app', name='OpenCore-Patcher.app',
icon="payloads/OC-Patcher.icns", icon="payloads/OC-Patcher.icns",
bundle_identifier=None, bundle_identifier="com.dortania.opencore-legacy-patcher-wxpython",
info_plist={ info_plist={
"CFBundleShortVersionString": constants.Constants().patcher_version, "CFBundleShortVersionString": constants.Constants().patcher_version,
"NSHumanReadableCopyright": "Copyright 2020-2022 Dortania", "NSHumanReadableCopyright": "Copyright 2020-2022 Dortania",
+52 -3
View File
@@ -10,8 +10,9 @@ import time
import os import os
import wx.adv import wx.adv
from wx.lib.agw import hyperlink from wx.lib.agw import hyperlink
import threading
from resources import constants, defaults, build, install, installer, utilities, sys_patch_detect, sys_patch, run, generate_smbios from resources import constants, defaults, build, install, installer, utilities, sys_patch_detect, sys_patch, run, generate_smbios, updates
from data import model_array, os_data, smbios_data, sip_data from data import model_array, os_data, smbios_data, sip_data
from gui import menu_redirect from gui import menu_redirect
@@ -60,6 +61,8 @@ class wx_python_gui:
if current_uid == 0: if current_uid == 0:
self.file_menu.Enable(wx.ID_REDO, False) self.file_menu.Enable(wx.ID_REDO, False)
# Spawn thread to check for updates
threading.Thread(target=self.check_for_updates).start()
self.main_menu(None) self.main_menu(None)
wx.CallAfter(self.frame.Close) wx.CallAfter(self.frame.Close)
@@ -76,6 +79,36 @@ class wx_python_gui:
sys.stdout = self.stock_stdout sys.stdout = self.stock_stdout
sys.stderr = self.stock_stderr sys.stderr = self.stock_stderr
def check_for_updates(self, event=None):
ignore_updates = subprocess.run(["defaults", "read", "com.dortania.opencore-legacy-patcher-wxpython", "IgnoreAppUpdates"], capture_output=True).stdout.decode("utf-8").strip()
if ignore_updates not in ["1", "True", "TRUE"]:
self.constants.ignore_updates = False
dict = updates.check_binary_updates(self.constants).check_binary_updates()
if dict:
for entry in dict:
version = dict[entry]["Version"]
github_link = dict[entry]["Github Link"]
print(f"New version: {version}")
self.dialog = wx.MessageDialog(
parent=self.frame,
message=f"Current Version: {self.constants.patcher_version}\nNew version: {version}\nWould you like to view?",
caption="Update Available for OpenCore Legacy Patcher!",
style=wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION
)
self.dialog.SetYesNoCancelLabels("View on Github", "Ignore Always", "Ignore Once")
responce = self.dialog.ShowModal()
if responce == wx.ID_YES:
webbrowser.open(github_link)
elif responce == wx.ID_NO:
print("- Setting IgnoreAppUpdates to True")
self.constants.ignore_updates = True
subprocess.run(["defaults", "write", "com.dortania.opencore-legacy-patcher-wxpython", "IgnoreAppUpdates", "-bool", "TRUE"])
else:
print("No updates available")
else:
self.constants.ignore_updates = True
print("- Ignoring App Updates due to defaults")
def relaunch_as_root(self, event=None): def relaunch_as_root(self, event=None):
# Add Dialog Box asking if it's ok to relaunch as root # Add Dialog Box asking if it's ok to relaunch as root
@@ -1650,13 +1683,22 @@ class wx_python_gui:
if self.computer.third_party_sata_ssd is False and not self.constants.custom_model: if self.computer.third_party_sata_ssd is False and not self.constants.custom_model:
self.set_enhanced_3rd_party_ssd_checkbox.Disable() self.set_enhanced_3rd_party_ssd_checkbox.Disable()
# Set Ignore App Updates
self.set_ignore_app_updates_checkbox = wx.CheckBox(self.frame, label="Ignore App Updates")
self.set_ignore_app_updates_checkbox.SetValue(self.constants.ignore_updates)
self.set_ignore_app_updates_checkbox.Bind(wx.EVT_CHECKBOX, self.set_ignore_app_updates_click)
self.set_ignore_app_updates_checkbox.SetPosition(wx.Point(
self.set_enhanced_3rd_party_ssd_checkbox.GetPosition().x,
self.set_enhanced_3rd_party_ssd_checkbox.GetPosition().y + self.set_enhanced_3rd_party_ssd_checkbox.GetSize().height))
self.set_ignore_app_updates_checkbox.SetToolTip(wx.ToolTip("This will set whether OpenCore will ignore App Updates on launch.\nEnable this option if you do not want to be prompted for App Updates"))
# Button: Developer Debug Info # Button: Developer Debug Info
self.debug_button = wx.Button(self.frame, label="Developer Debug Info") self.debug_button = wx.Button(self.frame, label="Developer Debug Info")
self.debug_button.Bind(wx.EVT_BUTTON, self.additional_info_menu) self.debug_button.Bind(wx.EVT_BUTTON, self.additional_info_menu)
self.debug_button.SetPosition(wx.Point( self.debug_button.SetPosition(wx.Point(
self.set_enhanced_3rd_party_ssd_checkbox.GetPosition().x, self.set_ignore_app_updates_checkbox.GetPosition().x,
self.set_enhanced_3rd_party_ssd_checkbox.GetPosition().y + self.set_enhanced_3rd_party_ssd_checkbox.GetSize().height + 5)) self.set_ignore_app_updates_checkbox.GetPosition().y + self.set_ignore_app_updates_checkbox.GetSize().height + 5))
self.debug_button.Center(wx.HORIZONTAL) self.debug_button.Center(wx.HORIZONTAL)
# Button: return to main menu # Button: return to main menu
@@ -1670,6 +1712,13 @@ class wx_python_gui:
# set frame size below return to main menu button # set frame size below return to main menu button
self.frame.SetSize(wx.Size(-1, self.return_to_main_menu_button.GetPosition().y + self.return_to_main_menu_button.GetSize().height + 40)) self.frame.SetSize(wx.Size(-1, self.return_to_main_menu_button.GetPosition().y + self.return_to_main_menu_button.GetSize().height + 40))
def set_ignore_app_updates_click(self, event):
self.constants.ignore_updates = self.set_ignore_app_updates_checkbox.GetValue()
if self.constants.ignore_updates is True:
subprocess.run(["defaults", "write", "com.dortania.opencore-legacy-patcher-wxpython", "IgnoreAppUpdates", "-bool", "TRUE"])
else:
subprocess.run(["defaults", "write", "com.dortania.opencore-legacy-patcher-wxpython", "IgnoreAppUpdates", "-bool", "FALSE"])
def firewire_click(self, event=None): def firewire_click(self, event=None):
if self.firewire_boot_checkbox.GetValue(): if self.firewire_boot_checkbox.GetValue():
print("Firewire Enabled") print("Firewire Enabled")
+1
View File
@@ -98,6 +98,7 @@ class Constants:
self.recovery_status = False # Detect if booted into RecoveryOS self.recovery_status = False # Detect if booted into RecoveryOS
self.launcher_binary = None # Determine launch binary (ie. Python vs PyInstaller) self.launcher_binary = None # Determine launch binary (ie. Python vs PyInstaller)
self.launcher_script = None # Determine launch file (if run via Python) self.launcher_script = None # Determine launch file (if run via Python)
self.ignore_updates = False # Ignore OCLP updates
## Hardware ## Hardware
self.computer: device_probe.Computer = None # type: ignore self.computer: device_probe.Computer = None # type: ignore
+111
View File
@@ -0,0 +1,111 @@
# Copyright (C) 2022, Mykola Grymalyuk
# Check whether new updates are available for OpenCore Legacy Patcher binary
# Call check_binary_updates() to determine if any updates are available
# Returns dict with Link and Version of the latest binary update if available
import requests
from pathlib import Path
class check_binary_updates:
def __init__(self, constants):
self.constants = constants
self.binary_version = self.constants.patcher_version
self.binary_version_array = self.binary_version.split(".")
self.binary_version_array = [int(x) for x in self.binary_version_array]
self.binary_url = "https://api.github.com/repos/dortania/OpenCore-Legacy-Patcher/releases/latest"
self.available_binaries = {}
def verify_network_connection(self, url):
try:
response = requests.head(url, timeout=5)
if response:
return True
except (requests.exceptions.Timeout,
requests.exceptions.TooManyRedirects,
requests.exceptions.ConnectionError,
requests.exceptions.HTTPError):
return False
return False
def check_if_build_newer(self):
for i in range(0, 3):
if self.remote_version_array[i] > self.binary_version_array[i]:
return True
return False
def determine_local_build_type(self):
if self.constants.gui_mode is True:
return "GUI"
else:
return "TUI"
def determine_local_build_type_offline(self):
if (Path(self.constants.payload_path) / f"12-Monterey.zip").exists():
return True
else:
return False
def determine_remote_type(self, remote_name):
if "TUI" in remote_name:
return "TUI"
elif "GUI" in remote_name:
return "GUI"
else:
return "Unknown"
def determine_remote_offline_type(self, remote_name):
if "Offline" in remote_name:
return True
else:
return False
def check_binary_updates(self):
print("- Checking for updates...")
if self.verify_network_connection(self.binary_url):
print("- Network connection functional")
response = requests.get(self.binary_url)
data_set = response.json()
print("- Retrived latest version data")
self.remote_version = data_set["tag_name"]
print(f"- Latest version: {self.remote_version}")
self.remote_version_array = self.remote_version.split(".")
self.remote_version_array = [
int(x) for x in self.remote_version_array
]
if self.check_if_build_newer() is True:
print("- Remote version is newer")
for asset in data_set["assets"]:
print(f"- Found asset: {asset['name']}")
if self.determine_remote_type(
asset["name"]) == self.determine_local_build_type(
) and self.determine_remote_offline_type(
asset["name"]
) == self.determine_local_build_type_offline():
print(f"- Found matching asset: {asset['name']}")
self.available_binaries.update({
asset['name']: {
"Name":
asset["name"],
"Version":
self.remote_version,
"Link":
asset["browser_download_url"],
"Type":
self.determine_remote_type(asset["name"]),
"Offline":
self.determine_remote_offline_type(
asset["name"]),
"Github Link":
f"https://github.com/dortania/OpenCore-Legacy-Patcher/releases/{self.remote_version}"
}
})
break
if self.available_binaries:
return self.available_binaries
else:
print("- No matching binaries available")
return None
else:
print("- Failed to connect to GitHub API")
return None