update: re-added core imports to ticket handling

This commit is contained in:
JOhn 2026-08-22 11:31:07 -04:00
parent 8a0a1fc74d
commit 40f0a467ab
2 changed files with 145 additions and 65 deletions

View file

@ -11,6 +11,7 @@ from PyQt6 import QtCore
from core.controllers.ProfileController import ProfileController
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.browser_page import BrowserPage
from gui.v2.ui.pages.location_page import LocationPage
@ -20,6 +21,12 @@ from gui.v2.workers.worker_thread import WorkerThread
class FastRegistrationPage(Page):
SINGBOX_PROTOCOLS = ("hysteria2", "vless")
PROTOCOLS = ("wireguard", "hysteria2", "vless", "hidetor")
PROTOCOL_BUTTON_ASSETS = {
"hysteria2": "hystria2",
}
def __init__(self, page_stack, main_window, prepared=None):
super().__init__("FastRegistration", page_stack, main_window)
self.page_stack = page_stack
@ -85,10 +92,12 @@ class FastRegistrationPage(Page):
def initialize_default_selections(self):
if not self.selected_values['location']:
locations = self.connection_manager.get_location_list()
locations = self._available_locations_for_protocol()
if locations:
random_index = random.randint(0, len(locations) - 1)
self.selected_values['location'] = locations[random_index]
else:
self._select_valid_location_for_protocol()
if not self.selected_values['browser']:
browsers = self.connection_manager.get_browser_list()
@ -167,8 +176,8 @@ class FastRegistrationPage(Page):
label = QLabel("Protocol", self)
label.setGeometry(300, 150, 185, 75)
protocol_image = QPixmap(os.path.join(
self.btn_path, f"{self.selected_values['protocol']}_button.png"))
protocol_image = QPixmap(self._protocol_button_asset(
self.selected_values['protocol']))
label.setPixmap(protocol_image)
label.setScaledContents(True)
label.show()
@ -196,6 +205,10 @@ class FastRegistrationPage(Page):
next_button.setIconSize(next_button.size())
self.buttons.append(next_button)
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 create_connection_section(self):
label = QLabel("Connection", self)
label.setGeometry(150, 250, 185, 75)
@ -227,6 +240,8 @@ class FastRegistrationPage(Page):
rotated_icon = icon.transformed(transform)
prev_button.setIcon(QIcon(rotated_icon))
prev_button.setIconSize(prev_button.size())
if self.selected_values['protocol'] in self.SINGBOX_PROTOCOLS:
prev_button.setDisabled(True)
self.buttons.append(prev_button)
next_button = QPushButton(self)
@ -236,6 +251,8 @@ class FastRegistrationPage(Page):
next_button.setIcon(
QIcon(os.path.join(self.btn_path, "UP_button.png")))
next_button.setIconSize(next_button.size())
if self.selected_values['protocol'] in self.SINGBOX_PROTOCOLS:
next_button.setDisabled(True)
self.buttons.append(next_button)
def create_location_section(self):
@ -302,7 +319,7 @@ class FastRegistrationPage(Page):
locations = self.connection_manager.get_location_info(
self.selected_values['location'])
if self.selected_values['protocol'] == 'hidetor' and locations and not (hasattr(locations, 'is_proxy_capable') and locations.is_proxy_capable):
if locations and not self._location_supports_selected_protocol(locations):
label.hide()
else:
label.show()
@ -529,46 +546,34 @@ class FastRegistrationPage(Page):
def update_ui_state_for_connection(self):
is_system_wide = self.selected_values['connection'] == 'system-wide'
is_singbox = self.selected_values['protocol'] in self.SINGBOX_PROTOCOLS
for button in self.buttons:
if hasattr(button, 'geometry'):
button_geometry = button.geometry()
if is_singbox and button_geometry.y() == 250 and button_geometry.x() in [115, 340]:
button.setEnabled(False)
if button_geometry.y() == 350:
if button_geometry.x() in [115, 340, 400, 625]:
button.setEnabled(not is_system_wide)
def show_previous_value(self, key):
if key == 'protocol':
protocols = ['wireguard', 'hidetor']
protocols = list(self.PROTOCOLS)
current_index = protocols.index(self.selected_values[key])
previous_index = (current_index - 1) % len(protocols)
self.selected_values[key] = protocols[previous_index]
if self.selected_values[key] == 'wireguard':
self.selected_values['connection'] = 'browser-only'
else:
self.selected_values['connection'] = 'tor'
loc_info = self.connection_manager.get_location_info(
self.selected_values['location'])
if not (loc_info and hasattr(loc_info, 'is_proxy_capable') and loc_info.is_proxy_capable):
locations = self.connection_manager.get_location_list()
proxy_locations = [loc for loc in locations if (l := self.connection_manager.get_location_info(
loc)) and hasattr(l, 'is_proxy_capable') and l.is_proxy_capable]
if proxy_locations:
self.selected_values['location'] = proxy_locations[0]
self._apply_protocol_defaults()
elif key == 'connection':
if self.selected_values['protocol'] == 'wireguard':
connections = ['browser-only', 'system-wide']
else:
connections = ['tor', 'just proxy']
connections = self._connections_for_protocol()
if self.selected_values[key] not in connections:
self.selected_values[key] = connections[0]
current_index = connections.index(self.selected_values[key])
previous_index = (current_index - 1) % len(connections)
self.selected_values[key] = connections[previous_index]
self.update_ui_state_for_connection()
elif key == 'location':
locations = self.connection_manager.get_location_list()
if self.selected_values['protocol'] == 'hidetor':
locations = [loc for loc in locations if (l := self.connection_manager.get_location_info(
loc)) and hasattr(l, 'is_proxy_capable') and l.is_proxy_capable]
locations = self._available_locations_for_protocol()
if locations and self.selected_values[key] in locations:
current_index = locations.index(self.selected_values[key])
@ -617,36 +622,21 @@ class FastRegistrationPage(Page):
def show_next_value(self, key):
if key == 'protocol':
protocols = ['wireguard', 'hidetor']
protocols = list(self.PROTOCOLS)
current_index = protocols.index(self.selected_values[key])
next_index = (current_index + 1) % len(protocols)
self.selected_values[key] = protocols[next_index]
if self.selected_values[key] == 'wireguard':
self.selected_values['connection'] = 'browser-only'
else:
self.selected_values['connection'] = 'tor'
loc_info = self.connection_manager.get_location_info(
self.selected_values['location'])
if not (loc_info and hasattr(loc_info, 'is_proxy_capable') and loc_info.is_proxy_capable):
locations = self.connection_manager.get_location_list()
proxy_locations = [loc for loc in locations if (l := self.connection_manager.get_location_info(
loc)) and hasattr(l, 'is_proxy_capable') and l.is_proxy_capable]
if proxy_locations:
self.selected_values['location'] = proxy_locations[0]
self._apply_protocol_defaults()
elif key == 'connection':
if self.selected_values['protocol'] == 'wireguard':
connections = ['browser-only', 'system-wide']
else:
connections = ['tor', 'just proxy']
connections = self._connections_for_protocol()
if self.selected_values[key] not in connections:
self.selected_values[key] = connections[0]
current_index = connections.index(self.selected_values[key])
next_index = (current_index + 1) % len(connections)
self.selected_values[key] = connections[next_index]
self.update_ui_state_for_connection()
elif key == 'location':
locations = self.connection_manager.get_location_list()
if self.selected_values['protocol'] == 'hidetor':
locations = [loc for loc in locations if (l := self.connection_manager.get_location_info(
loc)) and hasattr(l, 'is_proxy_capable') and l.is_proxy_capable]
locations = self._available_locations_for_protocol()
if locations and self.selected_values[key] in locations:
current_index = locations.index(self.selected_values[key])
@ -693,6 +683,57 @@ class FastRegistrationPage(Page):
self.create_interface_elements()
def _connections_for_protocol(self):
protocol = self.selected_values['protocol']
if protocol == 'wireguard':
return ['browser-only', 'system-wide']
if protocol in self.SINGBOX_PROTOCOLS:
return ['system-wide']
return ['tor', 'just proxy']
def _apply_protocol_defaults(self):
protocol = self.selected_values['protocol']
if protocol == 'wireguard':
self.selected_values['connection'] = 'browser-only'
elif protocol in self.SINGBOX_PROTOCOLS:
self.selected_values['connection'] = 'system-wide'
else:
self.selected_values['connection'] = 'tor'
self._select_valid_location_for_protocol()
def _is_enabled_capability(self, value):
return value in (True, 1, "1", "true", "True")
def _location_supports_selected_protocol(self, location_info):
protocol = self.selected_values['protocol']
if protocol == 'hidetor':
return bool(getattr(location_info, 'is_proxy_capable', False))
capability_by_protocol = {
"wireguard": "is_wireguard_capable",
"hysteria2": "is_hysteria2_capable",
"vless": "is_vless_capable",
}
capability_name = capability_by_protocol.get(protocol)
if capability_name is None:
return True
return self._is_enabled_capability(getattr(location_info, capability_name, False))
def _available_locations_for_protocol(self):
locations = self.connection_manager.get_location_list()
return [
loc for loc in locations
if (info := self.connection_manager.get_location_info(loc))
and self._location_supports_selected_protocol(info)
]
def _select_valid_location_for_protocol(self):
locations = self._available_locations_for_protocol()
if not locations:
self.selected_values['location'] = ''
return
if self.selected_values['location'] not in locations:
self.selected_values['location'] = locations[0]
def go_back(self):
menu_page = self.custom_window.navigator.get_cached("menu")
if menu_page is not None and hasattr(menu_page, 'refresh_menu_buttons'):
@ -734,6 +775,9 @@ class FastRegistrationPage(Page):
if self.selected_values['protocol'] == 'wireguard':
self.create_wireguard_profile(profile_data)
elif self.selected_values['protocol'] in self.SINGBOX_PROTOCOLS:
self.create_singbox_profile(profile_data)
return
else:
self.create_tor_profile(profile_data)
@ -778,6 +822,58 @@ class FastRegistrationPage(Page):
profile_id,
profiles.keys())
def create_singbox_profile(self, profile_data):
location_info = self.connection_manager.get_location_info(
profile_data['location'])
if not location_info:
self.update_status.update_status('Invalid location selected')
return
profiles = self._prefetched_profiles if self._prefetched_profiles is not None else ProfileController.get_all()
profile_id = self.get_next_available_profile_id(profiles)
existing_profile_ids = tuple(profiles.keys())
if not singbox_prereqs_installed():
self.show_singbox_prereq_setup(profile_data, profile_id, existing_profile_ids)
return
self.finish_singbox_profile_creation(profile_data, profile_id, existing_profile_ids)
def show_singbox_prereq_setup(self, profile_data, profile_id, existing_profile_ids):
setup_page = self.custom_window.navigator.navigate("networking_setup")
if setup_page is None:
self.update_status.update_status("Singbox prerequisite page is unavailable.")
return
setup_page.configure_for_singbox_profile(
lambda: self.finish_singbox_profile_creation(profile_data, profile_id, existing_profile_ids))
def finish_singbox_profile_creation(self, profile_data, profile_id, existing_profile_ids):
location_info = self.connection_manager.get_location_info(
profile_data['location'])
if not location_info:
self.update_status.update_status('Invalid location selected')
return
profile_data_for_resume = {
'id': profile_id,
'name': profile_data['name'],
'country_code': location_info.country_code,
'code': location_info.code,
'application': '',
'connection_type': profile_data['protocol'],
'resolution': '',
}
self._spawn_create_profile_worker(
'CREATE_SYSTEM_PROFILE', profile_data_for_resume, 'system')
if ProfileController.get(profile_id) is not None:
append_profile_to_visual_order(
getattr(self.update_status, 'gui_config_file', None),
profile_id,
existing_profile_ids)
self.go_back()
def create_tor_profile(self, profile_data):
location_info = self.connection_manager.get_location_info(
profile_data['location'])

View file

@ -1,12 +1,11 @@
import os
import shutil
from PyQt6.QtWidgets import QButtonGroup, QMessageBox, QPushButton
from PyQt6.QtGui import QIcon
from PyQt6.QtCore import QSize
from PyQt6 import QtCore
from core.Constants import Constants
from core.services.prepare_tickets.ticket_tracker import delete_ticket_data
from gui.v2.ui.pages.Page import Page
from gui.v2.ui.popups.message_box import style_message_box, mark_confirm_button
@ -135,29 +134,14 @@ class TicketCryptoPickerPage(Page):
self.update_status.update_status("Cancelled.")
def _restart_payment_after_wipe(self):
if not self._delete_ticket_data():
if not delete_ticket_data():
self.update_status.update_status("Could not wipe ticket data.")
return
self.bypass_existing = False
currency_btn = self.buttonGroup.checkedButton()
if currency_btn:
self.start_initiate_payment(currency_btn.property('currency'))
def _delete_ticket_data(self):
paths = [
Constants.TICKET_TRACKER_PATH,
os.path.join(Constants.HV_TICKETING_CONFIG_HOME, "billing_choices.json"),
]
try:
for path in paths:
if os.path.exists(path):
os.remove(path)
if os.path.isdir(Constants.HV_TICKETING_DATA_HOME):
shutil.rmtree(Constants.HV_TICKETING_DATA_HOME)
return True
except OSError as error:
self.update_status.update_status(f"Could not wipe ticket data: {error}")
return False
def on_error(self, msg):
self.update_status.update_status(f"Payment error: {msg}")