mirror of
https://github.com/leminlimez/Nugget.git
synced 2025-04-08 04:23:05 +08:00
add threading to applying
This commit is contained in:
@@ -40,7 +40,7 @@ def get_thumbnail_from_contents(contents: bytes, output_file: str = None):
|
|||||||
contents = get_thumbnail_from_mov(inp_file, output_file)
|
contents = get_thumbnail_from_mov(inp_file, output_file)
|
||||||
return contents
|
return contents
|
||||||
|
|
||||||
def create_caml(video_path: str, output_file: str):
|
def create_caml(video_path: str, output_file: str, update_label=lambda x: None):
|
||||||
cam = cv2.VideoCapture(video_path)
|
cam = cv2.VideoCapture(video_path)
|
||||||
assets_path = os.path.join(output_file, "assets")
|
assets_path = os.path.join(output_file, "assets")
|
||||||
try:
|
try:
|
||||||
@@ -80,7 +80,10 @@ def create_caml(video_path: str, output_file: str):
|
|||||||
if ret:
|
if ret:
|
||||||
# if video is still left continue creating images
|
# if video is still left continue creating images
|
||||||
name = 'assets/' + str(currentframe) + '.jpg'
|
name = 'assets/' + str(currentframe) + '.jpg'
|
||||||
print ('Creating...' + name)
|
if update_label:
|
||||||
|
update_label('Creating...' + name)
|
||||||
|
else:
|
||||||
|
print ('Creating...' + name)
|
||||||
|
|
||||||
# writing the extracted images
|
# writing the extracted images
|
||||||
cv2.imwrite(os.path.join(output_file, name), frame)
|
cv2.imwrite(os.path.join(output_file, name), frame)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import plistlib
|
|||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
|
|
||||||
from PySide6.QtWidgets import QMessageBox
|
from PySide6.QtWidgets import QMessageBox
|
||||||
from PySide6.QtCore import QSettings
|
from PySide6.QtCore import QSettings, QThread
|
||||||
|
|
||||||
from pymobiledevice3 import usbmux
|
from pymobiledevice3 import usbmux
|
||||||
from pymobiledevice3.lockdown import create_using_usbmux
|
from pymobiledevice3.lockdown import create_using_usbmux
|
||||||
@@ -12,37 +12,38 @@ from pymobiledevice3.exceptions import MuxException, PasswordRequiredError
|
|||||||
from devicemanagement.constants import Device, Version
|
from devicemanagement.constants import Device, Version
|
||||||
from devicemanagement.data_singleton import DataSingleton
|
from devicemanagement.data_singleton import DataSingleton
|
||||||
|
|
||||||
|
from gui.apply_worker import ApplyAlertMessage
|
||||||
from tweaks.tweaks import tweaks, FeatureFlagTweak, EligibilityTweak, AITweak, BasicPlistTweak, AdvancedPlistTweak, RdarFixTweak, NullifyFileTweak
|
from tweaks.tweaks import tweaks, FeatureFlagTweak, EligibilityTweak, AITweak, BasicPlistTweak, AdvancedPlistTweak, RdarFixTweak, NullifyFileTweak
|
||||||
from tweaks.custom_gestalt_tweaks import CustomGestaltTweaks
|
from tweaks.custom_gestalt_tweaks import CustomGestaltTweaks
|
||||||
from tweaks.posterboard_tweak import PosterboardTweak
|
from tweaks.posterboard_tweak import PosterboardTweak
|
||||||
from tweaks.basic_plist_locations import FileLocationsList, RiskyFileLocationsList
|
from tweaks.basic_plist_locations import FileLocationsList, RiskyFileLocationsList
|
||||||
from Sparserestore.restore import restore_files, FileToRestore
|
from Sparserestore.restore import restore_files, FileToRestore
|
||||||
|
|
||||||
def show_error_msg(txt: str, detailed_txt: str = None):
|
def show_error_msg(txt: str, title: str = "Error!", icon = QMessageBox.Critical, detailed_txt: str = None):
|
||||||
detailsBox = QMessageBox()
|
detailsBox = QMessageBox()
|
||||||
detailsBox.setIcon(QMessageBox.Critical)
|
detailsBox.setIcon(icon)
|
||||||
detailsBox.setWindowTitle("Error!")
|
detailsBox.setWindowTitle(title)
|
||||||
detailsBox.setText(txt)
|
detailsBox.setText(txt)
|
||||||
if detailed_txt != None:
|
if detailed_txt != None:
|
||||||
detailsBox.setDetailedText(detailed_txt)
|
detailsBox.setDetailedText(detailed_txt)
|
||||||
detailsBox.exec()
|
detailsBox.exec()
|
||||||
|
|
||||||
def show_apply_error(e: Exception, update_label=lambda x: None):
|
def show_apply_error(e: Exception, update_label=lambda x: None):
|
||||||
if "Find My" in str(e):
|
|
||||||
show_error_msg("Find My must be disabled in order to use this tool.",
|
|
||||||
detailed_txt="Disable Find My from Settings (Settings -> [Your Name] -> Find My) and then try again.")
|
|
||||||
elif "Encrypted Backup MDM" in str(e):
|
|
||||||
show_error_msg("Nugget cannot be used on this device. Click Show Details for more info.",
|
|
||||||
detailed_txt="Your device is managed and MDM backup encryption is on. This must be turned off in order for Nugget to work. Please do not use Nugget on your school/work device!")
|
|
||||||
elif "SessionInactive" in str(e):
|
|
||||||
show_error_msg("The session was terminated. Refresh the device list and try again.")
|
|
||||||
elif isinstance(e, PasswordRequiredError):
|
|
||||||
show_error_msg("Device is password protected! You must trust the computer on your device.",
|
|
||||||
detailed_txt="Unlock your device. On the popup, click \"Trust\", enter your password, then try again.")
|
|
||||||
else:
|
|
||||||
show_error_msg(type(e).__name__ + ": " + repr(e), detailed_txt=str(traceback.format_exc()))
|
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
update_label("Failed to restore")
|
update_label("Failed to restore")
|
||||||
|
if "Find My" in str(e):
|
||||||
|
return ApplyAlertMessage("Find My must be disabled in order to use this tool.",
|
||||||
|
detailed_txt="Disable Find My from Settings (Settings -> [Your Name] -> Find My) and then try again.")
|
||||||
|
elif "Encrypted Backup MDM" in str(e):
|
||||||
|
return ApplyAlertMessage("Nugget cannot be used on this device. Click Show Details for more info.",
|
||||||
|
detailed_txt="Your device is managed and MDM backup encryption is on. This must be turned off in order for Nugget to work. Please do not use Nugget on your school/work device!")
|
||||||
|
elif "SessionInactive" in str(e):
|
||||||
|
return ApplyAlertMessage("The session was terminated. Refresh the device list and try again.")
|
||||||
|
elif "PasswordRequiredError" in str(e):
|
||||||
|
return ApplyAlertMessage("Device is password protected! You must trust the computer on your device.",
|
||||||
|
detailed_txt="Unlock your device. On the popup, click \"Trust\", enter your password, then try again.")
|
||||||
|
else:
|
||||||
|
return ApplyAlertMessage(type(e).__name__ + ": " + repr(e), detailed_txt=str(traceback.format_exc()))
|
||||||
|
|
||||||
class DeviceManager:
|
class DeviceManager:
|
||||||
## Class Functions
|
## Class Functions
|
||||||
@@ -287,7 +288,7 @@ class DeviceManager:
|
|||||||
))
|
))
|
||||||
|
|
||||||
## APPLYING OR REMOVING TWEAKS AND RESTORING
|
## APPLYING OR REMOVING TWEAKS AND RESTORING
|
||||||
def apply_changes(self, resetting: bool = False, update_label=lambda x: None):
|
def apply_changes(self, resetting: bool = False, update_label=lambda x: None, show_alert=lambda x: None):
|
||||||
try:
|
try:
|
||||||
# set the tweaks and apply
|
# set the tweaks and apply
|
||||||
# first open the file in read mode
|
# first open the file in read mode
|
||||||
@@ -332,7 +333,7 @@ class DeviceManager:
|
|||||||
tmp_pb_dir = TemporaryDirectory()
|
tmp_pb_dir = TemporaryDirectory()
|
||||||
tweak.apply_tweak(
|
tweak.apply_tweak(
|
||||||
files_to_restore=files_to_restore, output_dir=tmp_pb_dir.name,
|
files_to_restore=files_to_restore, output_dir=tmp_pb_dir.name,
|
||||||
windows_path_fix=self.windows_path_fix
|
windows_path_fix=self.windows_path_fix, update_label=update_label
|
||||||
)
|
)
|
||||||
if tweak.enabled:
|
if tweak.enabled:
|
||||||
uses_domains = True
|
uses_domains = True
|
||||||
@@ -341,7 +342,7 @@ class DeviceManager:
|
|||||||
gestalt_plist = tweak.apply_tweak(gestalt_plist)
|
gestalt_plist = tweak.apply_tweak(gestalt_plist)
|
||||||
elif tweak.enabled:
|
elif tweak.enabled:
|
||||||
# no mobilegestalt file provided but applying mga tweaks, give warning
|
# no mobilegestalt file provided but applying mga tweaks, give warning
|
||||||
show_error_msg("No mobilegestalt file provided! Please select your file to apply mobilegestalt tweaks.")
|
show_alert(show_error_msg("No mobilegestalt file provided! Please select your file to apply mobilegestalt tweaks.", exec=False))
|
||||||
update_label("Failed.")
|
update_label("Failed.")
|
||||||
return
|
return
|
||||||
# set the custom gestalt keys
|
# set the custom gestalt keys
|
||||||
@@ -427,12 +428,12 @@ class DeviceManager:
|
|||||||
msg = "Your device will now restart."
|
msg = "Your device will now restart."
|
||||||
if not self.auto_reboot:
|
if not self.auto_reboot:
|
||||||
msg = "Please restart your device to see changes."
|
msg = "Please restart your device to see changes."
|
||||||
QMessageBox.information(None, "Success!", "All done! " + msg)
|
show_alert(ApplyAlertMessage(txt="All done! " + msg, title="Success!", icon=QMessageBox.Information))
|
||||||
update_label("Success!")
|
update_label("Success!")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if tmp_pb_dir != None:
|
if tmp_pb_dir != None:
|
||||||
tmp_pb_dir.cleanup()
|
tmp_pb_dir.cleanup()
|
||||||
show_apply_error(e, update_label)
|
show_alert(show_apply_error(e, update_label))
|
||||||
|
|
||||||
## RESETTING MOBILE GESTALT
|
## RESETTING MOBILE GESTALT
|
||||||
def reset_mobilegestalt(self, settings: QSettings, update_label=lambda x: None):
|
def reset_mobilegestalt(self, settings: QSettings, update_label=lambda x: None):
|
||||||
@@ -457,4 +458,4 @@ class DeviceManager:
|
|||||||
QMessageBox.information(None, "Success!", "All done! " + msg)
|
QMessageBox.information(None, "Success!", "All done! " + msg)
|
||||||
update_label("Success!")
|
update_label("Success!")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
show_apply_error(e)
|
show_error_msg(str(e))
|
||||||
|
|||||||
29
gui/apply_worker.py
Normal file
29
gui/apply_worker.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
from PySide6.QtCore import Signal, QThread
|
||||||
|
from PySide6.QtWidgets import QMessageBox
|
||||||
|
|
||||||
|
class ApplyAlertMessage:
|
||||||
|
def __init__(self, txt: str, title: str = "Error!", icon = QMessageBox.Critical, detailed_txt: str = None):
|
||||||
|
self.txt = txt
|
||||||
|
self.title = title
|
||||||
|
self.icon = icon
|
||||||
|
self.detailed_txt = detailed_txt
|
||||||
|
|
||||||
|
class ApplyThread(QThread):
|
||||||
|
progress = Signal(str)
|
||||||
|
alert = Signal(ApplyAlertMessage)
|
||||||
|
|
||||||
|
def update_label(self, txt: str):
|
||||||
|
self.progress.emit(txt)
|
||||||
|
def alert_window(self, msg: ApplyAlertMessage):
|
||||||
|
self.alert.emit(msg)
|
||||||
|
|
||||||
|
def __init__(self, manager, resetting: bool = False):
|
||||||
|
super().__init__()
|
||||||
|
self.manager = manager
|
||||||
|
self.resetting = resetting
|
||||||
|
|
||||||
|
def do_work(self):
|
||||||
|
self.manager.apply_changes(self.resetting, self.update_label, self.alert_window)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.do_work()
|
||||||
@@ -14,6 +14,7 @@ from devicemanagement.constants import Version
|
|||||||
from devicemanagement.device_manager import DeviceManager
|
from devicemanagement.device_manager import DeviceManager
|
||||||
|
|
||||||
from gui.dialogs import GestaltDialog, UpdateAppDialog, PBHelpDialog
|
from gui.dialogs import GestaltDialog, UpdateAppDialog, PBHelpDialog
|
||||||
|
from gui.apply_worker import ApplyThread, ApplyAlertMessage
|
||||||
|
|
||||||
from tweaks.tweaks import tweaks
|
from tweaks.tweaks import tweaks
|
||||||
from tweaks.custom_gestalt_tweaks import CustomGestaltTweaks, ValueTypeStrings
|
from tweaks.custom_gestalt_tweaks import CustomGestaltTweaks, ValueTypeStrings
|
||||||
@@ -43,6 +44,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
self.ui.setupUi(self)
|
self.ui.setupUi(self)
|
||||||
self.show_uuid = False
|
self.show_uuid = False
|
||||||
self.pb_mainLayout = None
|
self.pb_mainLayout = None
|
||||||
|
self.applying_in_progress = False
|
||||||
|
self.threadpool = QtCore.QThreadPool()
|
||||||
self.loadSettings()
|
self.loadSettings()
|
||||||
|
|
||||||
# Check for an update
|
# Check for an update
|
||||||
@@ -1154,12 +1157,31 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
def update_bar(self, percent):
|
def update_bar(self, percent):
|
||||||
self.ui.restoreProgressBar.setValue(int(percent))
|
self.ui.restoreProgressBar.setValue(int(percent))
|
||||||
def on_removeTweaksBtn_clicked(self):
|
def on_removeTweaksBtn_clicked(self):
|
||||||
# TODO: Add threading here
|
self.apply_changes(resetting=True)
|
||||||
self.device_manager.apply_changes(resetting=True, update_label=self.update_label)
|
|
||||||
def on_resetGestaltBtn_clicked(self):
|
def on_resetGestaltBtn_clicked(self):
|
||||||
self.device_manager.reset_mobilegestalt(self.settings, update_label=self.update_label)
|
self.device_manager.reset_mobilegestalt(self.settings, update_label=self.update_label)
|
||||||
|
|
||||||
@QtCore.Slot()
|
@QtCore.Slot()
|
||||||
def on_applyTweaksBtn_clicked(self):
|
def on_applyTweaksBtn_clicked(self):
|
||||||
# TODO: Add threading here
|
self.apply_changes()
|
||||||
self.device_manager.apply_changes(update_label=self.update_label)
|
|
||||||
|
def apply_changes(self, resetting: bool = False):
|
||||||
|
if not self.applying_in_progress:
|
||||||
|
self.applying_in_progress = True
|
||||||
|
self.worker_thread = ApplyThread(manager=self.device_manager, resetting=resetting)
|
||||||
|
self.worker_thread.progress.connect(self.ui.statusLbl.setText)
|
||||||
|
self.worker_thread.alert.connect(self.alert_message)
|
||||||
|
self.worker_thread.finished.connect(self.finish_apply_thread)
|
||||||
|
self.worker_thread.finished.connect(self.worker_thread.deleteLater)
|
||||||
|
self.worker_thread.start()
|
||||||
|
def alert_message(self, alert: ApplyAlertMessage):
|
||||||
|
print(alert.txt)
|
||||||
|
detailsBox = QtWidgets.QMessageBox()
|
||||||
|
detailsBox.setIcon(alert.icon)
|
||||||
|
detailsBox.setWindowTitle(alert.title)
|
||||||
|
detailsBox.setText(alert.txt)
|
||||||
|
if alert.detailed_txt != None:
|
||||||
|
detailsBox.setDetailedText(alert.detailed_txt)
|
||||||
|
detailsBox.exec()
|
||||||
|
def finish_apply_thread(self):
|
||||||
|
self.applying_in_progress = False
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ class PosterboardTweak(Tweak):
|
|||||||
overriding.write(thumb_contents)
|
overriding.write(thumb_contents)
|
||||||
del thumb_contents
|
del thumb_contents
|
||||||
|
|
||||||
def create_video_loop_files(self, output_dir: str):
|
def create_video_loop_files(self, output_dir: str, update_label=lambda x: None):
|
||||||
print(f"file: {self.videoFile}, looping: {self.loop_video}")
|
print(f"file: {self.videoFile}, looping: {self.loop_video}")
|
||||||
if self.videoFile and self.loop_video:
|
if self.videoFile and self.loop_video:
|
||||||
source_dir = get_bundle_files("files/posterboard/VideoCAML")
|
source_dir = get_bundle_files("files/posterboard/VideoCAML")
|
||||||
@@ -211,11 +211,11 @@ class PosterboardTweak(Tweak):
|
|||||||
copytree(source_dir, video_output_dir, dirs_exist_ok=True)
|
copytree(source_dir, video_output_dir, dirs_exist_ok=True)
|
||||||
contents_path = os.path.join(video_output_dir, "versions/1/contents/9183.Custom-810w-1080h@2x~ipad.wallpaper/9183.Custom_Floating-810w-1080h@2x~ipad.ca")
|
contents_path = os.path.join(video_output_dir, "versions/1/contents/9183.Custom-810w-1080h@2x~ipad.wallpaper/9183.Custom_Floating-810w-1080h@2x~ipad.ca")
|
||||||
print(f"path at {contents_path}, creating caml")
|
print(f"path at {contents_path}, creating caml")
|
||||||
video_handler.create_caml(video_path=self.videoFile, output_file=contents_path)
|
video_handler.create_caml(video_path=self.videoFile, output_file=contents_path, update_label=update_label)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def apply_tweak(self, files_to_restore: list[FileToRestore], output_dir: str, windows_path_fix: bool):
|
def apply_tweak(self, files_to_restore: list[FileToRestore], output_dir: str, windows_path_fix: bool, update_label=lambda x: None):
|
||||||
# unzip the file
|
# unzip the file
|
||||||
if not self.enabled:
|
if not self.enabled:
|
||||||
return
|
return
|
||||||
@@ -243,8 +243,10 @@ class PosterboardTweak(Tweak):
|
|||||||
if os.name == "nt" and windows_path_fix:
|
if os.name == "nt" and windows_path_fix:
|
||||||
# try to get past directory name limit on windows
|
# try to get past directory name limit on windows
|
||||||
output_dir = "\\\\?\\" + output_dir
|
output_dir = "\\\\?\\" + output_dir
|
||||||
|
update_label("Generating PosterBoard Video...")
|
||||||
self.create_live_photo_files(output_dir)
|
self.create_live_photo_files(output_dir)
|
||||||
self.create_video_loop_files(output_dir)
|
self.create_video_loop_files(output_dir, update_label=update_label)
|
||||||
|
update_label("Adding tendies...")
|
||||||
for tendie in self.tendies:
|
for tendie in self.tendies:
|
||||||
zip_output = os.path.join(output_dir, str(uuid.uuid4()))
|
zip_output = os.path.join(output_dir, str(uuid.uuid4()))
|
||||||
os.makedirs(zip_output)
|
os.makedirs(zip_output)
|
||||||
@@ -252,3 +254,4 @@ class PosterboardTweak(Tweak):
|
|||||||
zip_ref.extractall(zip_output)
|
zip_ref.extractall(zip_output)
|
||||||
# add the files
|
# add the files
|
||||||
self.recursive_add(files_to_restore, curr_path=output_dir)
|
self.recursive_add(files_to_restore, curr_path=output_dir)
|
||||||
|
update_label("Adding other tweaks...")
|
||||||
|
|||||||
Reference in New Issue
Block a user