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

View File

@@ -26,6 +26,9 @@
- Disable AirPlay to Mac/Sidecar patch set by default
- Work-around some older systems with memory instability
- 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
- Disable Asset Caching support with spoofless approach

View File

@@ -43,7 +43,7 @@ exe = EXE(pyz,
app = BUNDLE(exe,
name='OpenCore-Patcher.app',
icon="payloads/OC-Patcher.icns",
bundle_identifier=None,
bundle_identifier="com.dortania.opencore-legacy-patcher-wxpython",
info_plist={
"CFBundleShortVersionString": constants.Constants().patcher_version,
"NSHumanReadableCopyright": "Copyright 2020-2022 Dortania",

View File

@@ -10,8 +10,9 @@ import time
import os
import wx.adv
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 gui import menu_redirect
@@ -60,6 +61,8 @@ class wx_python_gui:
if current_uid == 0:
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)
wx.CallAfter(self.frame.Close)
@@ -76,6 +79,36 @@ class wx_python_gui:
sys.stdout = self.stock_stdout
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):
# Add Dialog Box asking if it's ok to relaunch as root
@@ -1649,14 +1682,23 @@ class wx_python_gui:
self.set_enhanced_3rd_party_ssd_checkbox.SetToolTip(wx.ToolTip("This will set whether OpenCore is allowed to force Apple Vendor on 3rd Party SATA SSDs\nSome benefits from this patch include better SSD performance, TRIM support and hibernation support.\nDisable this option if your SSD does not support TRIM correctly"))
if self.computer.third_party_sata_ssd is False and not self.constants.custom_model:
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
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.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 + 5))
self.set_ignore_app_updates_checkbox.GetPosition().x,
self.set_ignore_app_updates_checkbox.GetPosition().y + self.set_ignore_app_updates_checkbox.GetSize().height + 5))
self.debug_button.Center(wx.HORIZONTAL)
# Button: return to main menu
@@ -1670,6 +1712,13 @@ class wx_python_gui:
# 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))
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):
if self.firewire_boot_checkbox.GetValue():
print("Firewire Enabled")

View File

@@ -98,6 +98,7 @@ class Constants:
self.recovery_status = False # Detect if booted into RecoveryOS
self.launcher_binary = None # Determine launch binary (ie. Python vs PyInstaller)
self.launcher_script = None # Determine launch file (if run via Python)
self.ignore_updates = False # Ignore OCLP updates
## Hardware
self.computer: device_probe.Computer = None # type: ignore

111
resources/updates.py Normal file
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