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)
|
||||
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)
|
||||
assets_path = os.path.join(output_file, "assets")
|
||||
try:
|
||||
@@ -80,6 +80,9 @@ def create_caml(video_path: str, output_file: str):
|
||||
if ret:
|
||||
# if video is still left continue creating images
|
||||
name = 'assets/' + str(currentframe) + '.jpg'
|
||||
if update_label:
|
||||
update_label('Creating...' + name)
|
||||
else:
|
||||
print ('Creating...' + name)
|
||||
|
||||
# writing the extracted images
|
||||
|
||||
@@ -3,7 +3,7 @@ import plistlib
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
from PySide6.QtWidgets import QMessageBox
|
||||
from PySide6.QtCore import QSettings
|
||||
from PySide6.QtCore import QSettings, QThread
|
||||
|
||||
from pymobiledevice3 import 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.data_singleton import DataSingleton
|
||||
|
||||
from gui.apply_worker import ApplyAlertMessage
|
||||
from tweaks.tweaks import tweaks, FeatureFlagTweak, EligibilityTweak, AITweak, BasicPlistTweak, AdvancedPlistTweak, RdarFixTweak, NullifyFileTweak
|
||||
from tweaks.custom_gestalt_tweaks import CustomGestaltTweaks
|
||||
from tweaks.posterboard_tweak import PosterboardTweak
|
||||
from tweaks.basic_plist_locations import FileLocationsList, RiskyFileLocationsList
|
||||
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.setIcon(QMessageBox.Critical)
|
||||
detailsBox.setWindowTitle("Error!")
|
||||
detailsBox.setIcon(icon)
|
||||
detailsBox.setWindowTitle(title)
|
||||
detailsBox.setText(txt)
|
||||
if detailed_txt != None:
|
||||
detailsBox.setDetailedText(detailed_txt)
|
||||
detailsBox.exec()
|
||||
|
||||
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())
|
||||
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 Functions
|
||||
@@ -287,7 +288,7 @@ class DeviceManager:
|
||||
))
|
||||
|
||||
## 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:
|
||||
# set the tweaks and apply
|
||||
# first open the file in read mode
|
||||
@@ -332,7 +333,7 @@ class DeviceManager:
|
||||
tmp_pb_dir = TemporaryDirectory()
|
||||
tweak.apply_tweak(
|
||||
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:
|
||||
uses_domains = True
|
||||
@@ -341,7 +342,7 @@ class DeviceManager:
|
||||
gestalt_plist = tweak.apply_tweak(gestalt_plist)
|
||||
elif tweak.enabled:
|
||||
# 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.")
|
||||
return
|
||||
# set the custom gestalt keys
|
||||
@@ -427,12 +428,12 @@ class DeviceManager:
|
||||
msg = "Your device will now restart."
|
||||
if not self.auto_reboot:
|
||||
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!")
|
||||
except Exception as e:
|
||||
if tmp_pb_dir != None:
|
||||
tmp_pb_dir.cleanup()
|
||||
show_apply_error(e, update_label)
|
||||
show_alert(show_apply_error(e, update_label))
|
||||
|
||||
## RESETTING MOBILE GESTALT
|
||||
def reset_mobilegestalt(self, settings: QSettings, update_label=lambda x: None):
|
||||
@@ -457,4 +458,4 @@ class DeviceManager:
|
||||
QMessageBox.information(None, "Success!", "All done! " + msg)
|
||||
update_label("Success!")
|
||||
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 gui.dialogs import GestaltDialog, UpdateAppDialog, PBHelpDialog
|
||||
from gui.apply_worker import ApplyThread, ApplyAlertMessage
|
||||
|
||||
from tweaks.tweaks import tweaks
|
||||
from tweaks.custom_gestalt_tweaks import CustomGestaltTweaks, ValueTypeStrings
|
||||
@@ -43,6 +44,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
self.ui.setupUi(self)
|
||||
self.show_uuid = False
|
||||
self.pb_mainLayout = None
|
||||
self.applying_in_progress = False
|
||||
self.threadpool = QtCore.QThreadPool()
|
||||
self.loadSettings()
|
||||
|
||||
# Check for an update
|
||||
@@ -1154,12 +1157,31 @@ class MainWindow(QtWidgets.QMainWindow):
|
||||
def update_bar(self, percent):
|
||||
self.ui.restoreProgressBar.setValue(int(percent))
|
||||
def on_removeTweaksBtn_clicked(self):
|
||||
# TODO: Add threading here
|
||||
self.device_manager.apply_changes(resetting=True, update_label=self.update_label)
|
||||
self.apply_changes(resetting=True)
|
||||
def on_resetGestaltBtn_clicked(self):
|
||||
self.device_manager.reset_mobilegestalt(self.settings, update_label=self.update_label)
|
||||
|
||||
@QtCore.Slot()
|
||||
def on_applyTweaksBtn_clicked(self):
|
||||
# TODO: Add threading here
|
||||
self.device_manager.apply_changes(update_label=self.update_label)
|
||||
self.apply_changes()
|
||||
|
||||
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)
|
||||
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}")
|
||||
if self.videoFile and self.loop_video:
|
||||
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)
|
||||
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")
|
||||
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
|
||||
if not self.enabled:
|
||||
return
|
||||
@@ -243,8 +243,10 @@ class PosterboardTweak(Tweak):
|
||||
if os.name == "nt" and windows_path_fix:
|
||||
# try to get past directory name limit on windows
|
||||
output_dir = "\\\\?\\" + output_dir
|
||||
update_label("Generating PosterBoard Video...")
|
||||
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:
|
||||
zip_output = os.path.join(output_dir, str(uuid.uuid4()))
|
||||
os.makedirs(zip_output)
|
||||
@@ -252,3 +254,4 @@ class PosterboardTweak(Tweak):
|
||||
zip_ref.extractall(zip_output)
|
||||
# add the files
|
||||
self.recursive_add(files_to_restore, curr_path=output_dir)
|
||||
update_label("Adding other tweaks...")
|
||||
|
||||
Reference in New Issue
Block a user