update: new vless and hysteria2 ui

This commit is contained in:
JOhn 2026-08-21 11:30:47 -04:00
parent d8582c8d6d
commit bd6a9a4893
29 changed files with 253 additions and 36 deletions

View file

@ -61,6 +61,7 @@ from gui.v2.actions.profile_data import (
clear_profile_data, clear_profile_data,
) )
from gui.v2.actions.database_health import GuiStorageDatabaseError from gui.v2.actions.database_health import GuiStorageDatabaseError
from gui.v2.actions.profile_status import is_profile_enabled_for_gui
from gui.v2.actions.ticket_failure import ( from gui.v2.actions.ticket_failure import (
save_ticket_verification_failure, save_ticket_verification_failure,
get_ticket_verification_failure, get_ticket_verification_failure,
@ -674,7 +675,7 @@ class CustomWindow(QMainWindow):
self.connection_manager._connected_profiles.clear() self.connection_manager._connected_profiles.clear()
for profile_id, profile in profiles.items(): for profile_id, profile in profiles.items():
try: try:
if ProfileController.is_enabled(profile): if is_profile_enabled_for_gui(profile):
connected_profiles.append(profile_id) connected_profiles.append(profile_id)
self.connection_manager.add_connected_profile(profile_id) self.connection_manager.add_connected_profile(profile_id)
except Exception: except Exception:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

View file

@ -0,0 +1,27 @@
from core.controllers.ProfileController import ProfileController
from core.controllers.SystemStateController import SystemStateController
from core.models.system.SystemProfile import SystemProfile
SINGBOX_PROTOCOLS = ("hysteria2", "vless")
def _connection_code(profile):
connection = getattr(profile, "connection", None)
return getattr(connection, "code", None)
def _system_state_profile_id():
state = SystemStateController.get()
if state is None:
return None
try:
return int(state.profile_id)
except (TypeError, ValueError):
return None
def is_profile_enabled_for_gui(profile):
if isinstance(profile, SystemProfile) and _connection_code(profile) in SINGBOX_PROTOCOLS:
return _system_state_profile_id() == int(profile.id)
return ProfileController.is_enabled(profile)

View file

@ -0,0 +1,20 @@
from core.services.helpers.install_dependencies import SUDO_SINGBOX_LOCATION
from core.services.helpers.setup_sudo_scripts import (
is_singbox_wrapper_ready,
test_if_in_sudo_folder,
)
from core.utils.basic_operations.does_file_exist import does_file_exist
def singbox_prereqs_installed():
try:
if not is_singbox_wrapper_ready():
return False
sudo_scripts = test_if_in_sudo_folder()
if not getattr(sudo_scripts, "valid", False):
return False
return does_file_exist(SUDO_SINGBOX_LOCATION)
except Exception:
return False

0
gui/v2/infrastructure/screen_size.py Normal file → Executable file
View file

View file

@ -15,6 +15,18 @@ profile_observer = ProfileObserver()
ticket_observer = TicketObserver() ticket_observer = TicketObserver()
def _format_connecting_status(event):
subject = getattr(event, 'subject', None)
if isinstance(subject, dict):
attempt_count = subject.get("attempt_count")
maximum_attempts = subject.get("maximum_number_of_attempts")
if attempt_count is not None and maximum_attempts is not None:
return f'[{attempt_count}/{maximum_attempts}] Performing connection attempt...'
if subject:
return str(subject)
return 'Connecting..'
def setup_observers(update_status): def setup_observers(update_status):
profile_observer.subscribe( profile_observer.subscribe(
'created', lambda event: update_status('Profile Created')) 'created', lambda event: update_status('Profile Created'))
@ -33,7 +45,7 @@ def setup_observers(update_status):
client_observer.subscribe( client_observer.subscribe(
'updating', lambda event: update_status('Updating client...')) 'updating', lambda event: update_status('Updating client...'))
client_observer.subscribe('update_progressing', lambda event: update_status( client_observer.subscribe('update_progressing', lambda event: update_status(
f'Current progress: {event.meta.get('progress'):.2f}%')) f"Current progress: {event.meta.get('progress'):.2f}%"))
client_observer.subscribe('updated', lambda event: update_status( client_observer.subscribe('updated', lambda event: update_status(
'Restart client to apply update.')) 'Restart client to apply update.'))
@ -58,7 +70,7 @@ def setup_observers(update_status):
# f'Downloaded {ApplicationController.get(event.subject.application_code).name}')) # f'Downloaded {ApplicationController.get(event.subject.application_code).name}'))
connection_observer.subscribe('connecting', lambda event: update_status( connection_observer.subscribe('connecting', lambda event: update_status(
f'[{event.subject.get("attempt_count")}/{event.subject.get("maximum_number_of_attempts")}] Performing connection attempt...')) _format_connecting_status(event)))
connection_observer.subscribe('tor_bootstrapping', lambda event: update_status( connection_observer.subscribe('tor_bootstrapping', lambda event: update_status(
'Establishing Tor connection...')) 'Establishing Tor connection...'))

View file

@ -94,3 +94,10 @@ class Page(QWidget):
boton.setChecked(False) boton.setChecked(False)
self.button_next.setVisible(False) self.button_next.setVisible(False)
def replace_click_handler(self, button, handler):
try:
button.clicked.disconnect()
except TypeError:
pass
button.clicked.connect(handler)

View file

@ -22,6 +22,11 @@ from gui.v2.workers.page_data_worker import PageDataWorker
class EditorPage(Page): class EditorPage(Page):
SINGBOX_PROTOCOLS = ("hysteria2", "vless")
PROTOCOL_BUTTON_ASSETS = {
"hysteria2": "hystria2",
}
def __init__(self, page_stack, main_window, prepared=None): def __init__(self, page_stack, main_window, prepared=None):
super().__init__("Editor", page_stack, main_window) super().__init__("Editor", page_stack, main_window)
self.page_stack = page_stack self.page_stack = page_stack
@ -208,6 +213,13 @@ class EditorPage(Page):
"dimentions": self.connection_manager.get_available_resolutions(data_profile.get('id', '')) "dimentions": self.connection_manager.get_available_resolutions(data_profile.get('id', ''))
}, selected_profile_str) }, selected_profile_str)
elif protocol in self.SINGBOX_PROTOCOLS:
self.process_and_show_labels(data_profile, {
"protocol": [protocol],
"connection": ['system-wide'],
"location": self.connection_manager.get_location_list(),
}, selected_profile_str)
elif protocol == "residential" or protocol == "hidetor": elif protocol == "residential" or protocol == "hidetor":
self.process_and_show_labels(data_profile, { self.process_and_show_labels(data_profile, {
"protocol": ['residential', 'wireguard', 'hidetor'], "protocol": ['residential', 'wireguard', 'hidetor'],
@ -263,6 +275,20 @@ class EditorPage(Page):
else: else:
self.brow_disp.hide() self.brow_disp.hide()
if protocol in self.SINGBOX_PROTOCOLS:
if protocol == "vless":
self.display.setGeometry(0, 90, 540, 405)
else:
self.display.setGeometry(0, 60, 540, 405)
self.display.show()
self.display.setPixmap(self._encrypted_proxy_display_pixmap(
protocol, location).scaled(
self.display.size(),
Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation))
self.garaje.hide()
self.brow_disp.hide()
if protocol == "residential": if protocol == "residential":
self.display.setGeometry(0, 60, 540, 405) self.display.setGeometry(0, 60, 540, 405)
self.brow_disp.show() self.brow_disp.show()
@ -301,7 +327,7 @@ class EditorPage(Page):
l_name = f"{location_info.country_name}, {location_info.name}" if hasattr( l_name = f"{location_info.country_name}, {location_info.name}" if hasattr(
location_info, 'country_name') else "" location_info, 'country_name') else ""
if operator_name != 'Simplified Privacy' and operator_name != "" and protocol != 'hidetor': if operator_name != 'Simplified Privacy' and operator_name != "" and protocol not in ('hidetor', *self.SINGBOX_PROTOCOLS):
text_color = "white" text_color = "white"
if profile_obj and profile_obj.is_session_profile(): if profile_obj and profile_obj.is_session_profile():
text_color = "black" text_color = "black"
@ -413,9 +439,12 @@ class EditorPage(Page):
base_image = ScreenPage.create_resolution_button_image( base_image = ScreenPage.create_resolution_button_image(
self, current_value) self, current_value)
else: else:
image_path = os.path.join(
self.btn_path, f"{data_profile.get(key, '')}_button.png")
current_value = data_profile.get(key, '') current_value = data_profile.get(key, '')
if key == 'protocol':
image_path = self._protocol_button_asset(current_value)
else:
image_path = os.path.join(
self.btn_path, f"{current_value}_button.png")
base_image = QPixmap(image_path) base_image = QPixmap(image_path)
if key == 'dimentions': if key == 'dimentions':
@ -579,7 +608,7 @@ class EditorPage(Page):
prev_button.setVisible(True) prev_button.setVisible(True)
next_button.setVisible(True) next_button.setVisible(True)
if key == 'protocol' or (protocol == 'wireguard' and key == 'connection'): if key == 'protocol' or (connection == 'system-wide' and key == 'connection'):
prev_button.setDisabled(True) prev_button.setDisabled(True)
next_button.setDisabled(True) next_button.setDisabled(True)
@ -587,6 +616,44 @@ class EditorPage(Page):
prev_button.setVisible(False) prev_button.setVisible(False)
next_button.setVisible(False) next_button.setVisible(False)
def _protocol_button_asset(self, protocol):
asset_name = self.PROTOCOL_BUTTON_ASSETS.get(protocol, protocol)
return os.path.join(self.btn_path, f"{asset_name}_button.png")
def _encrypted_proxy_display_pixmap(self, protocol, location):
pixmap = QPixmap(os.path.join(self.btn_path, f"{protocol}.png"))
if pixmap.isNull():
pixmap = QPixmap(os.path.join(self.btn_path, "system_wide_global.png"))
if pixmap.isNull():
return pixmap
location_pixmap = QPixmap(os.path.join(
self.btn_path, f"icon_mini_{location}.png"))
if location_pixmap.isNull():
location_pixmap = QPixmap(os.path.join(
self.btn_path, "default_location_mini.png"))
if location_pixmap.isNull():
return pixmap
icon_size = max(42, min(72, int(min(pixmap.width(), pixmap.height()) * 0.22)))
location_pixmap = location_pixmap.scaled(
icon_size,
icon_size,
Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation)
x = int(pixmap.width() * 0.58)
if protocol == 'hysteria2':
y = int(pixmap.height() * 0.35)
else:
y = int(pixmap.height() * 0.30)
x = min(max(0, x), max(0, pixmap.width() - location_pixmap.width()))
y = min(max(0, y), max(0, pixmap.height() - location_pixmap.height()))
painter = QPainter(pixmap)
painter.drawPixmap(x, y, location_pixmap)
painter.end()
return pixmap
def on_sync_complete_for_edit_profile(self, available_locations, available_browsers, status, is_tor, locations, all_browsers): def on_sync_complete_for_edit_profile(self, available_locations, available_browsers, status, is_tor, locations, all_browsers):
if status: if status:
self.update_status.update_status('Sync complete.') self.update_status.update_status('Sync complete.')

View file

@ -15,9 +15,9 @@ class HidetorPage(Page):
self.selected_location_icon = None self.selected_location_icon = None
self.connection_manager = main_window.connection_manager self.connection_manager = main_window.connection_manager
self.update_status = main_window self.update_status = main_window
self.button_next.clicked.connect(self.go_selected) self.replace_click_handler(self.button_next, self.go_selected)
self.button_reverse.setVisible(True) self.button_reverse.setVisible(True)
self.button_reverse.clicked.connect(self.reverse) self.replace_click_handler(self.button_reverse, self.reverse)
self.display.setGeometry(QtCore.QRect(5, 10, 390, 520)) self.display.setGeometry(QtCore.QRect(5, 10, 390, 520))
self.title.setGeometry(395, 40, 380, 40) self.title.setGeometry(395, 40, 380, 40)
self.title.setText("Pick a location") self.title.setText("Pick a location")
@ -91,7 +91,12 @@ class HidetorPage(Page):
self.update_swarp_json() self.update_swarp_json()
def reverse(self): def reverse(self):
self.custom_window.navigator.navigate("protocol") profile_data = self.update_status.read_data()
self.limpiar()
if profile_data.get("protocol") == "residential":
self.custom_window.navigator.navigate("residential")
else:
self.custom_window.navigator.navigate("protocol")
def go_selected(self): def go_selected(self):
self.custom_window.navigator.navigate("browser") self.custom_window.navigator.navigate("browser")

View file

@ -15,7 +15,8 @@ class LocationPage(Page):
self.update_status = main_window self.update_status = main_window
self.button_reverse.setVisible(True) self.button_reverse.setVisible(True)
self.connection_manager = main_window.connection_manager self.connection_manager = main_window.connection_manager
self.button_reverse.clicked.connect(self.reverse) self.replace_click_handler(self.button_reverse, self.reverse)
self.replace_click_handler(self.button_next, self.go_selected)
self.display.setGeometry(QtCore.QRect(5, 10, 390, 520)) self.display.setGeometry(QtCore.QRect(5, 10, 390, 520))
self.title.setGeometry(395, 40, 380, 40) self.title.setGeometry(395, 40, 380, 40)
self.title.setText("Pick a location") self.title.setText("Pick a location")
@ -166,7 +167,6 @@ class LocationPage(Page):
target_size, Qt.AspectRatioMode.KeepAspectRatio)) target_size, Qt.AspectRatioMode.KeepAspectRatio))
self.selected_location_icon = location self.selected_location_icon = location
self.button_next.setVisible(True) self.button_next.setVisible(True)
self.button_next.clicked.connect(self.go_selected)
self.update_swarp_json() self.update_swarp_json()
try: try:
@ -179,10 +179,19 @@ class LocationPage(Page):
self.verification_button.setEnabled(True) self.verification_button.setEnabled(True)
def reverse(self): def reverse(self):
self.custom_window.navigator.navigate("protocol") profile_data = self.update_status.read_data()
self.limpiar()
if hasattr(self, 'initial_display'):
self.initial_display.show()
if hasattr(self, 'verification_button'):
self.verification_button.setEnabled(False)
if profile_data.get("protocol") == "wireguard":
self.custom_window.navigator.navigate("wireguard")
else:
self.custom_window.navigator.navigate("protocol")
def go_selected(self): def go_selected(self):
if self.connection_type == "system-wide": if self.update_swarp_json(get_connection=True) == "system-wide":
self.custom_window.navigator.navigate("resume") self.custom_window.navigator.navigate("resume")
else: else:
self.custom_window.navigator.navigate("browser") self.custom_window.navigator.navigate("browser")

View file

@ -23,6 +23,7 @@ from core.models.system.SystemProfile import SystemProfile
from gui.v2.infrastructure.setup_observers import ticket_observer from gui.v2.infrastructure.setup_observers import ticket_observer
from gui.v2.actions.database_health import GuiStorageDatabaseError from gui.v2.actions.database_health import GuiStorageDatabaseError
from gui.v2.actions.profile_order import normalize_profile_order from gui.v2.actions.profile_order import normalize_profile_order
from gui.v2.actions.profile_status import is_profile_enabled_for_gui
from gui.v2.ui.pages.Page import Page from gui.v2.ui.pages.Page import Page
from gui.v2.ui.pages.location_verification_page import LocationVerificationPage from gui.v2.ui.pages.location_verification_page import LocationVerificationPage
from gui.v2.ui.styles.styles import SCROLLBAR_CYAN_QSS from gui.v2.ui.styles.styles import SCROLLBAR_CYAN_QSS
@ -375,7 +376,7 @@ class MenuPage(Page):
self.IsSystem = 0 self.IsSystem = 0
for profile_id, profile in profiles.items(): for profile_id, profile in profiles.items():
try: try:
is_enabled = ProfileController.is_enabled(profile) is_enabled = is_profile_enabled_for_gui(profile)
except Exception: except Exception:
is_enabled = False is_enabled = False
if is_enabled: if is_enabled:
@ -588,7 +589,7 @@ class MenuPage(Page):
elif label_name == 'browser': elif label_name == 'browser':
if connection_type == 'system-wide': if connection_type == 'system-wide':
if protocol in ('hysteria2', 'vless'): if protocol in ('hysteria2', 'vless'):
return os.path.join(self.btn_path, "system_wide_global.png") return os.path.join(self.btn_path, "wireguard_system_wide.png")
return os.path.join(self.btn_path, "wireguard_system_wide.png") return os.path.join(self.btn_path, "wireguard_system_wide.png")
else: else:
return os.path.join(self.btn_path, f"{value[label_name]} latest_mini.png") return os.path.join(self.btn_path, f"{value[label_name]} latest_mini.png")
@ -849,11 +850,12 @@ class MenuPage(Page):
elif protocol.lower() in ["wireguard", "open", "residential", "hidetor", "hysteria2", "vless"]: elif protocol.lower() in ["wireguard", "open", "residential", "hidetor", "hysteria2", "vless"]:
label_principal = QLabel(self) label_principal = QLabel(self)
label_principal.setGeometry(0, 90, 400, 300) label_principal.setGeometry(0, 90, 400, 300)
pixmap = QPixmap(os.path.join( if protocol.lower() in ["hysteria2", "vless"]:
self.btn_path, f"{protocol}_{location}.png")) pixmap = self.build_encrypted_proxy_detail_pixmap(
if pixmap.isNull() and protocol.lower() in ["hysteria2", "vless"]: protocol.lower(), location)
else:
pixmap = QPixmap(os.path.join( pixmap = QPixmap(os.path.join(
self.btn_path, f"icon_{location}.png")) self.btn_path, f"{protocol}_{location}.png"))
label_principal.setPixmap(pixmap) label_principal.setPixmap(pixmap)
label_principal.setScaledContents(True) label_principal.setScaledContents(True)
label_principal.show() label_principal.show()
@ -962,6 +964,38 @@ class MenuPage(Page):
self.current_profile_location = location self.current_profile_location = location
def build_encrypted_proxy_detail_pixmap(self, protocol, location):
pixmap = QPixmap(os.path.join(self.btn_path, f"{protocol}.png"))
if pixmap.isNull():
return pixmap
location_pixmap = QPixmap(os.path.join(
self.btn_path, f"icon_mini_{location}.png"))
if location_pixmap.isNull():
location_pixmap = QPixmap(os.path.join(
self.btn_path, "default_location_mini.png"))
if location_pixmap.isNull():
return pixmap
icon_size = max(42, min(72, int(min(pixmap.width(), pixmap.height()) * 0.22)))
location_pixmap = location_pixmap.scaled(
icon_size,
icon_size,
Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation)
x = int(pixmap.width() * 0.58)
if protocol == 'hysteria2':
y = int(pixmap.height() * 0.35)
else:
y = int(pixmap.height() * 0.30)
x = min(max(0, x), max(0, pixmap.width() - location_pixmap.width()))
y = min(max(0, y), max(0, pixmap.height() - location_pixmap.height()))
painter = QPainter(pixmap)
painter.drawPixmap(x, y, location_pixmap)
painter.end()
return pixmap
def show_profile_verification(self, profile_id): def show_profile_verification(self, profile_id):
profile = self._safe_profile(profile_id) profile = self._safe_profile(profile_id)
profile_location = getattr(profile, 'location', None) profile_location = getattr(profile, 'location', None)
@ -1092,7 +1126,10 @@ class MenuPage(Page):
def on_disconnect_done(self): def on_disconnect_done(self):
self.disconnect_button.setEnabled(True) self.disconnect_button.setEnabled(True)
self.disconnect_system_wide_button.setEnabled(True) self.disconnect_system_wide_button.setEnabled(True)
pass selected_profile_id = self.reverse_id
self.refresh_menu_buttons()
if selected_profile_id is not None and self._safe_profile(selected_profile_id):
self.print_profile_details(f"Profile_{selected_profile_id}")
def _config_flag(self, section, key, default=False): def _config_flag(self, section, key, default=False):
try: try:

View file

@ -10,6 +10,7 @@ from core.models.Result import Result, ResultError
import sys import sys
from gui.v2.actions.singbox_prereqs import singbox_prereqs_installed
from gui.v2.ui.pages.Page import Page from gui.v2.ui.pages.Page import Page
from gui.v2.workers.worker_thread import WorkerThread from gui.v2.workers.worker_thread import WorkerThread
@ -190,6 +191,10 @@ class NetworkingSetupPage(Page):
def prepare_singbox_prereqs(self): def prepare_singbox_prereqs(self):
if not self._is_singbox_mode(): if not self._is_singbox_mode():
return return
if singbox_prereqs_installed():
self._set_status("Singbox prerequisites are already installed. Creating profile...", "#2ecc71")
QTimer.singleShot(200, self.finish_singbox_prereq_flow)
return
if not self._sudo_scripts_ready_for_singbox(): if not self._sudo_scripts_ready_for_singbox():
self.manual_button.setDisabled(False) self.manual_button.setDisabled(False)
self.auto_button.setDisabled(False) self.auto_button.setDisabled(False)

View file

@ -23,7 +23,8 @@ class ProtocolPage(Page):
self.connection_manager = main_window.connection_manager self.connection_manager = main_window.connection_manager
self.button_back.setVisible(True) self.button_back.setVisible(True)
self.update_status = main_window self.update_status = main_window
self.button_go.clicked.connect(self.go_selected) self.replace_click_handler(self.button_back, self.reverse)
self.replace_click_handler(self.button_go, self.go_selected)
self.coming_soon_label = QLabel("Coming soon", self) self.coming_soon_label = QLabel("Coming soon", self)
self.coming_soon_label.setGeometry(210, 50, 200, 40) self.coming_soon_label.setGeometry(210, 50, 200, 40)
self.coming_soon_label.setStyleSheet("font-size: 22px;") self.coming_soon_label.setStyleSheet("font-size: 22px;")
@ -104,3 +105,10 @@ class ProtocolPage(Page):
def find_menu_page(self): def find_menu_page(self):
return self.custom_window.navigator.get_cached("menu") return self.custom_window.navigator.get_cached("menu")
def reverse(self):
self.display.clear()
for boton in self.buttons:
boton.setChecked(False)
self.button_go.setVisible(False)
self.custom_window.navigator.navigate("menu")

View file

@ -15,8 +15,8 @@ class ResidentialPage(Page):
self.update_status = main_window self.update_status = main_window
self.connection_choice = None self.connection_choice = None
self.button_reverse.setVisible(True) self.button_reverse.setVisible(True)
self.button_reverse.clicked.connect(self.reverse) self.replace_click_handler(self.button_reverse, self.reverse)
self.button_go.clicked.connect(self.go_selected) self.replace_click_handler(self.button_go, self.go_selected)
self.display_1 = QLabel(self) self.display_1 = QLabel(self)
self.display_1.setGeometry(QtCore.QRect( self.display_1.setGeometry(QtCore.QRect(
@ -98,4 +98,5 @@ class ResidentialPage(Page):
self.update_status.write_data(inserted_data) self.update_status.write_data(inserted_data)
def reverse(self): def reverse(self):
self.button_go.setVisible(False)
self.custom_window.navigator.navigate("protocol") self.custom_window.navigator.navigate("protocol")

View file

@ -10,6 +10,7 @@ from PyQt6 import QtCore, QtGui
from core.controllers.ProfileController import ProfileController from core.controllers.ProfileController import ProfileController
from gui.v2.actions.profile_order import append_profile_to_visual_order from gui.v2.actions.profile_order import append_profile_to_visual_order
from gui.v2.actions.singbox_prereqs import singbox_prereqs_installed
from gui.v2.ui.pages.Page import Page from gui.v2.ui.pages.Page import Page
from gui.v2.ui.pages.location_page import LocationPage from gui.v2.ui.pages.location_page import LocationPage
from gui.v2.ui.pages.screen_page import ScreenPage from gui.v2.ui.pages.screen_page import ScreenPage
@ -28,13 +29,13 @@ class ResumePage(Page):
self.btn_path = main_window.btn_path self.btn_path = main_window.btn_path
self.labels_creados = [] self.labels_creados = []
self.additional_labels = [] self.additional_labels = []
self.button_go.clicked.connect(self.copy_profile) self.replace_click_handler(self.button_go, self.copy_profile)
self.button_back.setVisible(True) self.button_back.setVisible(True)
self.title.setGeometry(585, 40, 185, 40) self.title.setGeometry(585, 40, 185, 40)
self.title.setText("Profile Summary") self.title.setText("Profile Summary")
self.display.setGeometry(QtCore.QRect(5, 50, 580, 435)) self.display.setGeometry(QtCore.QRect(5, 50, 580, 435))
self.buttonGroup = QButtonGroup(self) self.buttonGroup = QButtonGroup(self)
self.button_back.clicked.connect(self.reverse) self.replace_click_handler(self.button_back, self.reverse)
self.create_arrow() self.create_arrow()
self.create_interface_elements() self.create_interface_elements()
@ -382,7 +383,7 @@ class ResumePage(Page):
new_profile = profile_data new_profile = profile_data
existing_profile_ids = tuple(profiles.keys()) existing_profile_ids = tuple(profiles.keys())
if new_profile.get('protocol') in self.SINGBOX_PROTOCOLS: if new_profile.get('protocol') in self.SINGBOX_PROTOCOLS and not singbox_prereqs_installed():
self.show_singbox_prereq_setup(new_profile, profile_id, existing_profile_ids) self.show_singbox_prereq_setup(new_profile, profile_id, existing_profile_ids)
return return

View file

@ -345,3 +345,6 @@ class ScreenPage(Page):
def gestionar_next(self): def gestionar_next(self):
self.custom_window.navigator.navigate("resume") self.custom_window.navigator.navigate("resume")
def gestionar_back(self):
self.custom_window.navigator.navigate("browser")

View file

@ -24,10 +24,11 @@ class TorPage(Page):
QPixmap(os.path.join(self.btn_path, "browser only.png"))) QPixmap(os.path.join(self.btn_path, "browser only.png")))
self.display0.lower() self.display0.lower()
self.button_go.clicked.connect(self.go_selected) self.replace_click_handler(self.button_go, self.go_selected)
self.button_reverse.setVisible(True) self.button_reverse.setVisible(True)
self.button_reverse.clicked.connect(self.reverse_selected) self.replace_click_handler(self.button_reverse, self.reverse_selected)
self.replace_click_handler(self.button_back, self.reverse_selected)
self.label = QLabel(self) self.label = QLabel(self)
self.label.setGeometry(440, 370, 86, 130) self.label.setGeometry(440, 370, 86, 130)
@ -72,6 +73,8 @@ class TorPage(Page):
self.update_status.write_data(inserted_data) self.update_status.write_data(inserted_data)
def reverse_selected(self): def reverse_selected(self):
self.limpiar()
self.button_go.setVisible(False)
self.custom_window.navigator.navigate("residential") self.custom_window.navigator.navigate("residential")
def go_selected(self): def go_selected(self):

View file

@ -19,7 +19,8 @@ class WireGuardPage(Page):
self.selected_protocol = None self.selected_protocol = None
self.selected_protocol_icon = None self.selected_protocol_icon = None
self.button_back.setVisible(True) self.button_back.setVisible(True)
self.button_go.clicked.connect(self.go_selected) self.replace_click_handler(self.button_back, self.reverse)
self.replace_click_handler(self.button_go, self.go_selected)
self.additional_labels = [] self.additional_labels = []
self.title.setGeometry(585, 40, 185, 40) self.title.setGeometry(585, 40, 185, 40)
self.title.setText("Pick a Protocol") self.title.setText("Pick a Protocol")

View file

@ -1,5 +1,6 @@
import shlex import shlex
import subprocess import subprocess
import inspect
from PyQt6.QtCore import QThread, pyqtSignal from PyQt6.QtCore import QThread, pyqtSignal
@ -52,6 +53,18 @@ class WorkerThread(QThread):
self.is_running = True self.is_running = True
self.is_disabling = False self.is_disabling = False
def _disable_profile(self, profile):
kwargs = {
'profile_observer': profile_observer,
'ticket_observer': ticket_observer,
'connection_observer': connection_observer,
}
supported = inspect.signature(ProfileController.disable).parameters
ProfileController.disable(
profile,
**{key: value for key, value in kwargs.items() if key in supported}
)
def run(self): def run(self):
if self.action == 'LIST_PROFILES': if self.action == 'LIST_PROFILES':
self.list_profiles() self.list_profiles()
@ -167,13 +180,11 @@ class WorkerThread(QThread):
for profile_id in self.profile_data: for profile_id in self.profile_data:
profile = ProfileController.get(int(profile_id)) profile = ProfileController.get(int(profile_id))
if isinstance(profile, SessionProfile): if isinstance(profile, SessionProfile):
ProfileController.disable( self._disable_profile(profile)
profile, ignore=True, profile_observer=profile_observer, ticket_observer=ticket_observer, connection_observer=connection_observer)
for profile_id in self.profile_data: for profile_id in self.profile_data:
profile = ProfileController.get(int(profile_id)) profile = ProfileController.get(int(profile_id))
if isinstance(profile, SystemProfile): if isinstance(profile, SystemProfile):
ProfileController.disable( self._disable_profile(profile)
profile, ignore=True, profile_observer=profile_observer, ticket_observer=ticket_observer, connection_observer=connection_observer)
self.text_output.emit("All profiles were successfully disabled") self.text_output.emit("All profiles were successfully disabled")
except SudoScript as e: except SudoScript as e:
self.text_output.emit(str(e)) self.text_output.emit(str(e))
@ -282,8 +293,7 @@ class WorkerThread(QThread):
try: try:
profile = ProfileController.get(int(self.profile_data['id'])) profile = ProfileController.get(int(self.profile_data['id']))
if profile: if profile:
ProfileController.disable( self._disable_profile(profile)
profile, profile_observer=profile_observer, ticket_observer=ticket_observer, connection_observer=connection_observer, wipe_assassin=True)
else: else:
self.text_output.emit( self.text_output.emit(
f"No profile found with ID: {self.profile_data['id']}") f"No profile found with ID: {self.profile_data['id']}")