Răsfoiți Sursa

Enhance iOS Activation Bypass GUI for PyInstaller

Enhanced the GUI for iOS Activation Bypass with improvements for PyInstaller and user experience. Updated various UI elements, added resource path handling, and adjusted layout and styling.
Rust505 2 luni în urmă
părinte
comite
540ee13e92
1 a modificat fișierele cu 79 adăugiri și 33 ștergeri
  1. 79 33
      client/main_GUI.py

+ 79 - 33
client/main_GUI.py

@@ -1,5 +1,6 @@
 #!/usr/bin/env python3
 #!/usr/bin/env python3
-# main.py — iOS Activation Bypass GUI (macOS, PyQt6)
+# main.py — iOS Activation Bypass GUI (macOS, PyQt6) — Enhanced for PyInstaller & UX
+
 import sys
 import sys
 import os
 import os
 import re
 import re
@@ -9,10 +10,22 @@ from typing import Optional, Dict, Any
 from PyQt6.QtWidgets import (
 from PyQt6.QtWidgets import (
     QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
     QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
     QPushButton, QTextEdit, QLabel, QLineEdit, QGroupBox,
     QPushButton, QTextEdit, QLabel, QLineEdit, QGroupBox,
-    QRadioButton, QButtonGroup, QMessageBox, QProgressBar, QFrame
+    QRadioButton, QButtonGroup, QMessageBox, QProgressBar, QFrame,
+    QScrollArea, QSizePolicy
 )
 )
-from PyQt6.QtCore import Qt, QThread, pyqtSignal, QObject, QTimer, QSettings
-from PyQt6.QtGui import QFont, QTextCursor, QPalette, QColor, QPixmap, QIcon
+from PyQt6.QtCore import Qt, QThread, pyqtSignal, QObject, QTimer, QSettings, QSize
+from PyQt6.QtGui import QFont, QTextCursor, QPalette, QColor, QPixmap, QIcon, QDragEnterEvent, QDropEvent
+
+# === Resource path helper for PyInstaller ===
+def resource_path(relative_path):
+    """ Get absolute path to resource, works for dev and for PyInstaller """
+    try:
+        # PyInstaller creates a temp folder and stores path in _MEIPASS
+        base_path = Path(sys._MEIPASS)
+    except Exception:
+        base_path = Path(__file__).parent
+    return base_path / relative_path
+
 
 
 # === CLI module import ===
 # === CLI module import ===
 try:
 try:
@@ -105,34 +118,34 @@ class DeviceInfoPanel(QWidget):
         img_container.setAlignment(Qt.AlignmentFlag.AlignTop)
         img_container.setAlignment(Qt.AlignmentFlag.AlignTop)
 
 
         self.status_indicator = QLabel("●")
         self.status_indicator = QLabel("●")
-        self.status_indicator.setFont(QFont("SF Mono", 16))
+        self.status_indicator.setFont(QFont("SF Mono", 18, QFont.Weight.Bold))
         self.status_indicator.setStyleSheet("color: #999;")
         self.status_indicator.setStyleSheet("color: #999;")
         img_container.addWidget(self.status_indicator, alignment=Qt.AlignmentFlag.AlignLeft)
         img_container.addWidget(self.status_indicator, alignment=Qt.AlignmentFlag.AlignLeft)
 
 
         self.img_label = QLabel()
         self.img_label = QLabel()
-        img_path = Path("assets/iphone.png")
+        img_path = resource_path("assets/iphone.png")  # ✅ FIXED: uses resource_path
         if img_path.exists():
         if img_path.exists():
             pixmap = QPixmap(str(img_path))
             pixmap = QPixmap(str(img_path))
-            size = 128
+            size = 144  # увеличено
             screen = QApplication.primaryScreen()
             screen = QApplication.primaryScreen()
             if screen:
             if screen:
-                size = int(128 * screen.devicePixelRatio())
+                size = int(144 * screen.devicePixelRatio())
             pixmap = pixmap.scaled(size, size, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation)
             pixmap = pixmap.scaled(size, size, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation)
             self.img_label.setPixmap(pixmap)
             self.img_label.setPixmap(pixmap)
         else:
         else:
             self.img_label.setText("📱\n\niPhone\n(not found)")
             self.img_label.setText("📱\n\niPhone\n(not found)")
             self.img_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
             self.img_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
-            self.img_label.setStyleSheet("font-size: 14px; color: #888;")
+            self.img_label.setStyleSheet("font-size: 16px; color: #888; font-weight: bold;")
 
 
         img_container.addWidget(self.img_label)
         img_container.addWidget(self.img_label)
         layout.addLayout(img_container)
         layout.addLayout(img_container)
 
 
         # Right side: text
         # Right side: text
         info_layout = QVBoxLayout()
         info_layout = QVBoxLayout()
-        info_layout.setSpacing(6)
+        info_layout.setSpacing(8)
 
 
         title_label = QLabel("Device Information")
         title_label = QLabel("Device Information")
-        title_label.setFont(QFont("Segoe UI", 11, QFont.Weight.Bold))
+        title_label.setFont(QFont("Segoe UI", 14, QFont.Weight.Bold))
         info_layout.addWidget(title_label)
         info_layout.addWidget(title_label)
 
 
         self.model_label = QLabel("Model: —")
         self.model_label = QLabel("Model: —")
@@ -141,7 +154,8 @@ class DeviceInfoPanel(QWidget):
         self.udid_label = QLabel("UDID: —")
         self.udid_label = QLabel("UDID: —")
 
 
         for lbl in [self.model_label, self.ios_label, self.activation_label, self.udid_label]:
         for lbl in [self.model_label, self.ios_label, self.activation_label, self.udid_label]:
-            lbl.setFont(QFont("SF Mono, Menlo, monospace", 10))
+            lbl.setFont(QFont("SF Mono, Menlo, monospace", 12))
+            lbl.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred)
             info_layout.addWidget(lbl)
             info_layout.addWidget(lbl)
 
 
         layout.addLayout(info_layout)
         layout.addLayout(info_layout)
@@ -176,27 +190,29 @@ class DeviceInfoPanel(QWidget):
         }
         }
         code = info.get("ProductType", "Unknown")
         code = info.get("ProductType", "Unknown")
         name = model_map.get(code, code)
         name = model_map.get(code, code)
-        self.model_label.setText(f"Model: {name}")
+        self.model_label.setText(f"<b>Model:</b> {name}")
 
 
         # Other info
         # Other info
-        self.ios_label.setText(f"iOS: {info.get('ProductVersion', '—')}")
+        self.ios_label.setText(f"<b>iOS:</b> {info.get('ProductVersion', '—')}")
+
         state = info.get("ActivationState", "—")
         state = info.get("ActivationState", "—")
         color = "#4caf50" if state == "Activated" else "#ff9800"
         color = "#4caf50" if state == "Activated" else "#ff9800"
-        self.activation_label.setText(f'<span style="color:{color};">Activation: <b>{state}</b></span>')
+        self.activation_label.setText(f'<span style="color:{color};"><b>Activation:</b> <b>{state}</b></span>')
         self.activation_label.setTextFormat(Qt.TextFormat.RichText)
         self.activation_label.setTextFormat(Qt.TextFormat.RichText)
 
 
         udid = info.get("UniqueDeviceID", "—")
         udid = info.get("UniqueDeviceID", "—")
-        if len(udid) > 10:
-            udid = udid[:6] + "…" + udid[-4:]
-        self.udid_label.setText(f"UDID: {udid}")
+        # ✅ Показываем полный UDID, но делаем его переносимым
+        self.udid_label.setText(f"<b>UDID:</b> {udid}")
+        self.udid_label.setWordWrap(True)
+        self.udid_label.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop)
 
 
 
 
 # === Main window ===
 # === Main window ===
 class MainWindow(QMainWindow):
 class MainWindow(QMainWindow):
     def __init__(self):
     def __init__(self):
         super().__init__()
         super().__init__()
-        self.setWindowTitle("📱 iOS Activation Bypass (GUI)")
-        self.resize(920, 700)
+        self.setWindowTitle("📱 iOS Activation Bypass (Rust505)")
+        self.resize(1024, 768)
         self.thread = None
         self.thread = None
 
 
         # ✅ QSettings — only after QApplication
         # ✅ QSettings — only after QApplication
@@ -211,8 +227,8 @@ class MainWindow(QMainWindow):
         central = QWidget()
         central = QWidget()
         self.setCentralWidget(central)
         self.setCentralWidget(central)
         main_layout = QVBoxLayout(central)
         main_layout = QVBoxLayout(central)
-        main_layout.setContentsMargins(16, 16, 16, 16)
-        main_layout.setSpacing(12)
+        main_layout.setContentsMargins(20, 20, 20, 20)
+        main_layout.setSpacing(16)
 
 
         # Device panel
         # Device panel
         device_frame = QFrame()
         device_frame = QFrame()
@@ -226,6 +242,7 @@ class MainWindow(QMainWindow):
 
 
         # GUID mode
         # GUID mode
         mode_group = QGroupBox("GUID Input Mode")
         mode_group = QGroupBox("GUID Input Mode")
+        mode_group.setFont(QFont("Segoe UI", 12, QFont.Weight.Bold))
         mode_layout = QHBoxLayout()
         mode_layout = QHBoxLayout()
         self.radio_auto = QRadioButton("Auto-detect (recommended)")
         self.radio_auto = QRadioButton("Auto-detect (recommended)")
         self.radio_manual = QRadioButton("Manual input")
         self.radio_manual = QRadioButton("Manual input")
@@ -240,11 +257,12 @@ class MainWindow(QMainWindow):
 
 
         # GUID field
         # GUID field
         guid_layout = QHBoxLayout()
         guid_layout = QHBoxLayout()
-        guid_layout.addWidget(QLabel("GUID:"))
+        guid_layout.addWidget(QLabel("GUID:"), alignment=Qt.AlignmentFlag.AlignTop)
         self.guid_edit = QLineEdit()
         self.guid_edit = QLineEdit()
         self.guid_edit.setPlaceholderText("e.g. 1A2B3C4D-1234-4123-8888-ABCDEF012345")
         self.guid_edit.setPlaceholderText("e.g. 1A2B3C4D-1234-4123-8888-ABCDEF012345")
         self.guid_edit.textChanged.connect(self._validate_guid)
         self.guid_edit.textChanged.connect(self._validate_guid)
-        self.guid_edit.setMaximumWidth(500)
+        self.guid_edit.setMaximumWidth(600)
+        self.guid_edit.setFont(QFont("SF Mono, Menlo, monospace", 12))
         guid_layout.addWidget(self.guid_edit)
         guid_layout.addWidget(self.guid_edit)
         main_layout.addLayout(guid_layout)
         main_layout.addLayout(guid_layout)
 
 
@@ -255,6 +273,8 @@ class MainWindow(QMainWindow):
         self.stop_btn.setEnabled(False)
         self.stop_btn.setEnabled(False)
         self.start_btn.clicked.connect(self.start_activation)
         self.start_btn.clicked.connect(self.start_activation)
         self.stop_btn.clicked.connect(self.stop_activation)
         self.stop_btn.clicked.connect(self.stop_activation)
+        self.start_btn.setFont(QFont("Segoe UI", 12, QFont.Weight.Bold))
+        self.stop_btn.setFont(QFont("Segoe UI", 12, QFont.Weight.Bold))
         btn_layout.addWidget(self.start_btn)
         btn_layout.addWidget(self.start_btn)
         btn_layout.addWidget(self.stop_btn)
         btn_layout.addWidget(self.stop_btn)
         main_layout.addLayout(btn_layout)
         main_layout.addLayout(btn_layout)
@@ -263,15 +283,36 @@ class MainWindow(QMainWindow):
         self.progress = QProgressBar()
         self.progress = QProgressBar()
         self.progress.setRange(0, 100)
         self.progress.setRange(0, 100)
         self.progress.setValue(0)
         self.progress.setValue(0)
+        self.progress.setFont(QFont("Segoe UI", 12))
+        self.progress.setStyleSheet("""
+            QProgressBar {
+                border: 2px solid #bbb;
+                border-radius: 5px;
+                text-align: center;
+                height: 24px;
+            }
+            QProgressBar::chunk {
+                background-color: #4caf50;
+                width: 20px;
+            }
+        """)
         main_layout.addWidget(self.progress)
         main_layout.addWidget(self.progress)
 
 
         # Logs
         # Logs
         log_group = QGroupBox("Logs")
         log_group = QGroupBox("Logs")
+        log_group.setFont(QFont("Segoe UI", 12, QFont.Weight.Bold))
         log_layout = QVBoxLayout()
         log_layout = QVBoxLayout()
         self.log_view = QTextEdit()
         self.log_view = QTextEdit()
         self.log_view.setReadOnly(True)
         self.log_view.setReadOnly(True)
-        self.log_view.setFont(QFont("SF Mono, Menlo, Monaco, monospace", 10))
-        self.log_view.setStyleSheet("background: #1e1e1e; color: #e0e0e0;")
+        self.log_view.setFont(QFont("SF Mono, Menlo, Monaco, monospace", 11))
+        self.log_view.setStyleSheet("""
+            background: #1e1e1e;
+            color: #e0e0e0;
+            border: 1px solid #444;
+            padding: 8px;
+            font-size: 11pt;
+        """)
+        self.log_view.setLineWrapMode(QTextEdit.LineWrapMode.WidgetWidth)
         log_layout.addWidget(self.log_view)
         log_layout.addWidget(self.log_view)
         log_group.setLayout(log_layout)
         log_group.setLayout(log_layout)
         main_layout.addWidget(log_group)
         main_layout.addWidget(log_group)
@@ -287,7 +328,6 @@ class MainWindow(QMainWindow):
         # Load last GUID (if exists)
         # Load last GUID (if exists)
         last_guid = self.settings.value("last_guid", "")
         last_guid = self.settings.value("last_guid", "")
         if last_guid and validate_guid(last_guid):
         if last_guid and validate_guid(last_guid):
-            self.radio_manual.setChecked(True)
             self.guid_edit.setText(last_guid.upper())
             self.guid_edit.setText(last_guid.upper())
 
 
         # Check dependencies and update device
         # Check dependencies and update device
@@ -300,8 +340,8 @@ class MainWindow(QMainWindow):
             msg = (
             msg = (
                 f"⚠ Missing tools: {', '.join(missing)}\n\n"
                 f"⚠ Missing tools: {', '.join(missing)}\n\n"
                 "Install with:\n"
                 "Install with:\n"
-                "  brew install libimobiledevice usbmuxd\n"
-                "  pip3 install -U pymobiledevice3"
+                "  brew install libimobiledevice\n"
+                "  pip3 install pymobiledevice3"
             )
             )
             QMessageBox.critical(self, "Dependency Error", msg)
             QMessageBox.critical(self, "Dependency Error", msg)
             self.start_btn.setEnabled(False)
             self.start_btn.setEnabled(False)
@@ -382,8 +422,14 @@ class MainWindow(QMainWindow):
         self.stop_btn.setEnabled(False)
         self.stop_btn.setEnabled(False)
 
 
     def append_log(self, msg: str, level='info'):
     def append_log(self, msg: str, level='info'):
-        colors = {'success': '#4caf50', 'error': '#f44336', 'warn': '#ff9800',
-                  'step': '#2196f3', 'info': '#64b5f6', 'detail': '#90a4ae'}
+        colors = {
+            'success': '#4caf50',
+            'error': '#f44336',
+            'warn': '#ff9800',
+            'step': '#2196f3',
+            'info': '#64b5f6',
+            'detail': '#90a4ae'
+        }
         color = colors.get(level, '#e0e0e0')
         color = colors.get(level, '#e0e0e0')
         ts = time.strftime("%H:%M:%S")
         ts = time.strftime("%H:%M:%S")
         html = f'<span style="color:#78909c;">[{ts}]</span> <span style="color:{color};">{msg}</span><br>'
         html = f'<span style="color:#78909c;">[{ts}]</span> <span style="color:{color};">{msg}</span><br>'
@@ -398,7 +444,7 @@ class MainWindow(QMainWindow):
         if guid and validate_guid(guid):
         if guid and validate_guid(guid):
             self.settings.setValue("last_guid", guid)
             self.settings.setValue("last_guid", guid)
         QMessageBox.information(self, "Success", "✅ Activation bypass completed!\n\n"
         QMessageBox.information(self, "Success", "✅ Activation bypass completed!\n\n"
-                                                 "Check Settings → General → About.")
+                                                 "📌 Thanks Rust505 and rhcp011235")
         self.detect_device()
         self.detect_device()
 
 
     def on_error(self, err: str):
     def on_error(self, err: str):
@@ -436,7 +482,7 @@ def enable_dark_mode(app: QApplication):
 
 
 
 
 def set_app_icon(app: QApplication):
 def set_app_icon(app: QApplication):
-    icon_path = Path("assets/app_icon.png")
+    icon_path = resource_path("assets/app_icon.icns")  # ✅ FIXED: uses resource_path
     if icon_path.exists():
     if icon_path.exists():
         app.setWindowIcon(QIcon(str(icon_path)))
         app.setWindowIcon(QIcon(str(icon_path)))