update: added systemwide tab in settings
This commit is contained in:
parent
fc944b0cb5
commit
043f1fd2b0
2 changed files with 248 additions and 37 deletions
279
gui/__main__.py
279
gui/__main__.py
|
|
@ -14,7 +14,7 @@ import subprocess
|
||||||
import qrcode
|
import qrcode
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import Union
|
from typing import Union
|
||||||
from core.Errors import UnknownConnectionTypeError, CommandNotFoundError, MissingSubscriptionError, InvalidSubscriptionError, ProfileActivationError, UnsupportedApplicationVersionError, FileIntegrityError, ProfileModificationError, ProfileStateConflictError, EndpointVerificationError
|
from core.Errors import UnknownConnectionTypeError, CommandNotFoundError, MissingSubscriptionError, InvalidSubscriptionError, ProfileActivationError, UnsupportedApplicationVersionError, FileIntegrityError, ProfileModificationError, ProfileStateConflictError, EndpointVerificationError, PolicyAssignmentError, PolicyInstatementError, PolicyRevocationError
|
||||||
from core.controllers.ApplicationVersionController import ApplicationVersionController
|
from core.controllers.ApplicationVersionController import ApplicationVersionController
|
||||||
from core.controllers.ApplicationController import ApplicationController
|
from core.controllers.ApplicationController import ApplicationController
|
||||||
from core.controllers.ClientController import ClientController
|
from core.controllers.ClientController import ClientController
|
||||||
|
|
@ -24,6 +24,7 @@ from core.controllers.LocationController import LocationController
|
||||||
from core.controllers.ProfileController import ProfileController
|
from core.controllers.ProfileController import ProfileController
|
||||||
from core.controllers.SubscriptionController import SubscriptionController
|
from core.controllers.SubscriptionController import SubscriptionController
|
||||||
from core.controllers.SubscriptionPlanController import SubscriptionPlanController
|
from core.controllers.SubscriptionPlanController import SubscriptionPlanController
|
||||||
|
from core.controllers.PrivilegePolicyController import PrivilegePolicyController
|
||||||
from core.models.session.SessionConnection import SessionConnection
|
from core.models.session.SessionConnection import SessionConnection
|
||||||
from core.models.session.SessionProfile import SessionProfile
|
from core.models.session.SessionProfile import SessionProfile
|
||||||
from core.models.system.SystemConnection import SystemConnection
|
from core.models.system.SystemConnection import SystemConnection
|
||||||
|
|
@ -608,6 +609,21 @@ class CustomWindow(QMainWindow):
|
||||||
if config["logging"]["gui_logging_enabled"]:
|
if config["logging"]["gui_logging_enabled"]:
|
||||||
self._setup_gui_logging()
|
self._setup_gui_logging()
|
||||||
|
|
||||||
|
def has_shown_systemwide_prompt(self):
|
||||||
|
config = self._load_gui_config()
|
||||||
|
if not config:
|
||||||
|
return False
|
||||||
|
return config.get("systemwide", {}).get("prompt_shown", False)
|
||||||
|
|
||||||
|
def mark_systemwide_prompt_shown(self):
|
||||||
|
config = self._load_gui_config()
|
||||||
|
if config is None:
|
||||||
|
config = {"logging": {"gui_logging_enabled": False, "log_level": "INFO"}}
|
||||||
|
if "systemwide" not in config:
|
||||||
|
config["systemwide"] = {}
|
||||||
|
config["systemwide"]["prompt_shown"] = True
|
||||||
|
self._save_gui_config(config)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def stop_gui_logging(self):
|
def stop_gui_logging(self):
|
||||||
|
|
@ -895,6 +911,7 @@ class CustomWindow(QMainWindow):
|
||||||
ResidentialPage(self.page_stack, self),
|
ResidentialPage(self.page_stack, self),
|
||||||
InstallSystemPackage(self.page_stack, self),
|
InstallSystemPackage(self.page_stack, self),
|
||||||
WelcomePage(self.page_stack, self),
|
WelcomePage(self.page_stack, self),
|
||||||
|
SystemwidePromptPage(self.page_stack, self),
|
||||||
PaymentDetailsPage(self.page_stack, self),
|
PaymentDetailsPage(self.page_stack, self),
|
||||||
DurationSelectionPage(self.page_stack, self),
|
DurationSelectionPage(self.page_stack, self),
|
||||||
CurrencySelectionPage(self.page_stack, self),
|
CurrencySelectionPage(self.page_stack, self),
|
||||||
|
|
@ -2841,6 +2858,13 @@ class InstallSystemPackage(Page):
|
||||||
self.status_label.setStyleSheet("color: red;")
|
self.status_label.setStyleSheet("color: red;")
|
||||||
|
|
||||||
def go_next(self):
|
def go_next(self):
|
||||||
|
if not self.update_status.has_shown_systemwide_prompt():
|
||||||
|
system_page = self.page_stack.findChild(SystemwidePromptPage)
|
||||||
|
if system_page is None:
|
||||||
|
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(MenuPage)))
|
||||||
|
return
|
||||||
|
self.page_stack.setCurrentIndex(self.page_stack.indexOf(system_page))
|
||||||
|
else:
|
||||||
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(MenuPage)))
|
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(MenuPage)))
|
||||||
|
|
||||||
class ProtocolPage(Page):
|
class ProtocolPage(Page):
|
||||||
|
|
@ -5308,6 +5332,7 @@ class Settings(Page):
|
||||||
("Subscriptions", self.show_subscription_page),
|
("Subscriptions", self.show_subscription_page),
|
||||||
("Create/Edit", self.show_registrations_page),
|
("Create/Edit", self.show_registrations_page),
|
||||||
("Verification", self.show_verification_page),
|
("Verification", self.show_verification_page),
|
||||||
|
("Systemwide", self.show_systemwide_page),
|
||||||
("Delete Profile", self.show_delete_page),
|
("Delete Profile", self.show_delete_page),
|
||||||
("Error Logs", self.show_logs_page),
|
("Error Logs", self.show_logs_page),
|
||||||
("Debug Help", self.show_debug_page)
|
("Debug Help", self.show_debug_page)
|
||||||
|
|
@ -6101,39 +6126,6 @@ class Settings(Page):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def show_account_page(self):
|
|
||||||
self.content_layout.setCurrentWidget(self.account_page)
|
|
||||||
self.update_button_states(0)
|
|
||||||
|
|
||||||
|
|
||||||
def show_subscription_page(self):
|
|
||||||
self.content_layout.setCurrentWidget(self.subscription_page)
|
|
||||||
self.update_button_states(1)
|
|
||||||
|
|
||||||
def show_registrations_page(self):
|
|
||||||
self.content_layout.setCurrentWidget(self.registrations_page)
|
|
||||||
self.update_button_states(2)
|
|
||||||
|
|
||||||
def show_verification_page(self):
|
|
||||||
self.content_layout.setCurrentWidget(self.verification_page)
|
|
||||||
self.update_button_states(3)
|
|
||||||
|
|
||||||
def show_delete_page(self):
|
|
||||||
self.content_layout.setCurrentWidget(self.delete_page)
|
|
||||||
self.update_button_states(4)
|
|
||||||
|
|
||||||
def show_logs_page(self):
|
|
||||||
self.content_layout.setCurrentWidget(self.logs_page)
|
|
||||||
self.update_button_states(5)
|
|
||||||
|
|
||||||
def show_debug_page(self):
|
|
||||||
self.content_layout.setCurrentWidget(self.debug_page)
|
|
||||||
self.update_button_states(6)
|
|
||||||
|
|
||||||
def update_button_states(self, active_index):
|
|
||||||
for i, btn in enumerate(self.menu_buttons):
|
|
||||||
btn.setChecked(i == active_index)
|
|
||||||
|
|
||||||
def reverse(self):
|
def reverse(self):
|
||||||
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(MenuPage)))
|
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(MenuPage)))
|
||||||
|
|
||||||
|
|
@ -6547,6 +6539,10 @@ class Settings(Page):
|
||||||
self.verification_page = self.create_verification_page()
|
self.verification_page = self.create_verification_page()
|
||||||
self.content_layout.addWidget(self.verification_page)
|
self.content_layout.addWidget(self.verification_page)
|
||||||
|
|
||||||
|
self.content_layout.removeWidget(self.systemwide_page)
|
||||||
|
self.systemwide_page = self.create_systemwide_page()
|
||||||
|
self.content_layout.addWidget(self.systemwide_page)
|
||||||
|
|
||||||
self.content_layout.removeWidget(self.logs_page)
|
self.content_layout.removeWidget(self.logs_page)
|
||||||
self.logs_page = self.create_logs_page()
|
self.logs_page = self.create_logs_page()
|
||||||
self.content_layout.addWidget(self.logs_page)
|
self.content_layout.addWidget(self.logs_page)
|
||||||
|
|
@ -6751,6 +6747,7 @@ class Settings(Page):
|
||||||
self.subscription_page = self.create_subscription_page()
|
self.subscription_page = self.create_subscription_page()
|
||||||
self.registrations_page = self.create_registrations_page()
|
self.registrations_page = self.create_registrations_page()
|
||||||
self.verification_page = self.create_verification_page()
|
self.verification_page = self.create_verification_page()
|
||||||
|
self.systemwide_page = self.create_systemwide_page()
|
||||||
self.logs_page = self.create_logs_page()
|
self.logs_page = self.create_logs_page()
|
||||||
self.delete_page = self.create_delete_page()
|
self.delete_page = self.create_delete_page()
|
||||||
self.debug_page = self.create_debug_page()
|
self.debug_page = self.create_debug_page()
|
||||||
|
|
@ -6759,6 +6756,7 @@ class Settings(Page):
|
||||||
self.content_layout.addWidget(self.subscription_page)
|
self.content_layout.addWidget(self.subscription_page)
|
||||||
self.content_layout.addWidget(self.registrations_page)
|
self.content_layout.addWidget(self.registrations_page)
|
||||||
self.content_layout.addWidget(self.verification_page)
|
self.content_layout.addWidget(self.verification_page)
|
||||||
|
self.content_layout.addWidget(self.systemwide_page)
|
||||||
self.content_layout.addWidget(self.logs_page)
|
self.content_layout.addWidget(self.logs_page)
|
||||||
self.content_layout.addWidget(self.delete_page)
|
self.content_layout.addWidget(self.delete_page)
|
||||||
self.content_layout.addWidget(self.debug_page)
|
self.content_layout.addWidget(self.debug_page)
|
||||||
|
|
@ -6766,6 +6764,45 @@ class Settings(Page):
|
||||||
self.content_layout.setCurrentIndex(0)
|
self.content_layout.setCurrentIndex(0)
|
||||||
self.show_account_page()
|
self.show_account_page()
|
||||||
|
|
||||||
|
def show_account_page(self):
|
||||||
|
self.content_layout.setCurrentWidget(self.account_page)
|
||||||
|
self._select_menu_button("Overview")
|
||||||
|
|
||||||
|
def show_subscription_page(self):
|
||||||
|
self.content_layout.setCurrentWidget(self.subscription_page)
|
||||||
|
self._select_menu_button("Subscriptions")
|
||||||
|
|
||||||
|
def show_registrations_page(self):
|
||||||
|
self.content_layout.setCurrentWidget(self.registrations_page)
|
||||||
|
self._select_menu_button("Create/Edit")
|
||||||
|
|
||||||
|
def show_verification_page(self):
|
||||||
|
self.content_layout.setCurrentWidget(self.verification_page)
|
||||||
|
self._select_menu_button("Verification")
|
||||||
|
|
||||||
|
def show_systemwide_page(self):
|
||||||
|
self.content_layout.setCurrentWidget(self.systemwide_page)
|
||||||
|
self._select_menu_button("Systemwide")
|
||||||
|
|
||||||
|
def show_logs_page(self):
|
||||||
|
self.content_layout.setCurrentWidget(self.logs_page)
|
||||||
|
self._select_menu_button("Error Logs")
|
||||||
|
|
||||||
|
def show_delete_page(self):
|
||||||
|
self.content_layout.setCurrentWidget(self.delete_page)
|
||||||
|
self._select_menu_button("Delete Profile")
|
||||||
|
|
||||||
|
def show_debug_page(self):
|
||||||
|
self.content_layout.setCurrentWidget(self.debug_page)
|
||||||
|
self._select_menu_button("Debug Help")
|
||||||
|
|
||||||
|
def _select_menu_button(self, label):
|
||||||
|
for btn in self.menu_buttons:
|
||||||
|
if btn.text() == label:
|
||||||
|
btn.setChecked(True)
|
||||||
|
else:
|
||||||
|
btn.setChecked(False)
|
||||||
|
|
||||||
def create_logs_page(self):
|
def create_logs_page(self):
|
||||||
page = QWidget()
|
page = QWidget()
|
||||||
layout = QVBoxLayout(page)
|
layout = QVBoxLayout(page)
|
||||||
|
|
@ -6879,6 +6916,87 @@ class Settings(Page):
|
||||||
self.load_registrations_settings()
|
self.load_registrations_settings()
|
||||||
return page
|
return page
|
||||||
|
|
||||||
|
def create_systemwide_page(self):
|
||||||
|
page = QWidget()
|
||||||
|
layout = QVBoxLayout(page)
|
||||||
|
layout.setSpacing(20)
|
||||||
|
layout.setContentsMargins(20, 20, 20, 20)
|
||||||
|
|
||||||
|
title = QLabel("SYSTEM-WIDE PROFILES")
|
||||||
|
title.setStyleSheet(f"color: #808080; font-size: 12px; font-weight: bold; {self.font_style}")
|
||||||
|
layout.addWidget(title)
|
||||||
|
|
||||||
|
description = QLabel("Control whether HydraVeil configures a sudo policy so system-wide WireGuard profiles can be started without entering your sudo password.")
|
||||||
|
description.setWordWrap(True)
|
||||||
|
description.setStyleSheet(f"color: white; font-size: 14px; {self.font_style}")
|
||||||
|
layout.addWidget(description)
|
||||||
|
|
||||||
|
status_layout = QHBoxLayout()
|
||||||
|
status_label = QLabel("Current status:")
|
||||||
|
status_label.setStyleSheet(f"color: white; font-size: 14px; {self.font_style}")
|
||||||
|
self.systemwide_status_value = QLabel("")
|
||||||
|
self.systemwide_status_value.setStyleSheet(f"color: #e67e22; font-size: 14px; {self.font_style}")
|
||||||
|
status_layout.addWidget(status_label)
|
||||||
|
status_layout.addWidget(self.systemwide_status_value)
|
||||||
|
status_layout.addStretch()
|
||||||
|
layout.addLayout(status_layout)
|
||||||
|
|
||||||
|
toggle_layout = QHBoxLayout()
|
||||||
|
self.systemwide_toggle = QCheckBox("Enable system-wide policy")
|
||||||
|
self.systemwide_toggle.setStyleSheet(self.get_checkbox_style())
|
||||||
|
toggle_layout.addWidget(self.systemwide_toggle)
|
||||||
|
toggle_layout.addStretch()
|
||||||
|
layout.addLayout(toggle_layout)
|
||||||
|
|
||||||
|
save_button = QPushButton()
|
||||||
|
save_button.setFixedSize(75, 46)
|
||||||
|
save_button.setIcon(QIcon(os.path.join(self.btn_path, "save.png")))
|
||||||
|
save_button.setIconSize(QSize(75, 46))
|
||||||
|
save_button.clicked.connect(self.save_systemwide_settings)
|
||||||
|
|
||||||
|
button_layout = QHBoxLayout()
|
||||||
|
button_layout.addWidget(save_button)
|
||||||
|
button_layout.addStretch()
|
||||||
|
layout.addLayout(button_layout)
|
||||||
|
|
||||||
|
layout.addStretch()
|
||||||
|
self.load_systemwide_settings()
|
||||||
|
return page
|
||||||
|
|
||||||
|
def load_systemwide_settings(self):
|
||||||
|
enabled = False
|
||||||
|
try:
|
||||||
|
enabled = PrivilegePolicyController.is_instated()
|
||||||
|
except Exception:
|
||||||
|
enabled = False
|
||||||
|
self.systemwide_toggle.setChecked(enabled)
|
||||||
|
if enabled:
|
||||||
|
self.systemwide_status_value.setText("Enabled")
|
||||||
|
self.systemwide_status_value.setStyleSheet(f"color: #2ecc71; font-size: 14px; {self.font_style}")
|
||||||
|
else:
|
||||||
|
self.systemwide_status_value.setText("Disabled")
|
||||||
|
self.systemwide_status_value.setStyleSheet(f"color: #e67e22; font-size: 14px; {self.font_style}")
|
||||||
|
|
||||||
|
def save_systemwide_settings(self):
|
||||||
|
enable = self.systemwide_toggle.isChecked()
|
||||||
|
try:
|
||||||
|
if enable:
|
||||||
|
PrivilegePolicyController.instate()
|
||||||
|
else:
|
||||||
|
if PrivilegePolicyController.is_instated():
|
||||||
|
PrivilegePolicyController.revoke()
|
||||||
|
self.load_systemwide_settings()
|
||||||
|
self.update_status.update_status("System-wide policy settings updated")
|
||||||
|
except CommandNotFoundError as e:
|
||||||
|
self.systemwide_status_value.setText(str(e))
|
||||||
|
self.systemwide_status_value.setStyleSheet(f"color: red; font-size: 14px; {self.font_style}")
|
||||||
|
except (PolicyAssignmentError, PolicyInstatementError, PolicyRevocationError) as e:
|
||||||
|
self.systemwide_status_value.setText(str(e))
|
||||||
|
self.systemwide_status_value.setStyleSheet(f"color: red; font-size: 14px; {self.font_style}")
|
||||||
|
except Exception:
|
||||||
|
self.systemwide_status_value.setText("Failed to update policy")
|
||||||
|
self.systemwide_status_value.setStyleSheet(f"color: red; font-size: 14px; {self.font_style}")
|
||||||
|
|
||||||
def load_registrations_settings(self) -> None:
|
def load_registrations_settings(self) -> None:
|
||||||
try:
|
try:
|
||||||
config = self.update_status._load_gui_config()
|
config = self.update_status._load_gui_config()
|
||||||
|
|
@ -7855,6 +7973,99 @@ class WelcomePage(Page):
|
||||||
self.page_stack.setCurrentIndex(self.page_stack.indexOf(install_page))
|
self.page_stack.setCurrentIndex(self.page_stack.indexOf(install_page))
|
||||||
|
|
||||||
|
|
||||||
|
class SystemwidePromptPage(Page):
|
||||||
|
def __init__(self, page_stack, main_window=None, parent=None):
|
||||||
|
super().__init__("Systemwide", page_stack, main_window, parent)
|
||||||
|
self.btn_path = main_window.btn_path
|
||||||
|
self.update_status = main_window
|
||||||
|
self.button_back.setVisible(True)
|
||||||
|
self.button_back.clicked.connect(self.back_to_install)
|
||||||
|
self.button_next.setVisible(False)
|
||||||
|
self.button_go.setVisible(False)
|
||||||
|
self.status_label = QLabel(self)
|
||||||
|
self.status_label.setGeometry(80, 430, 640, 40)
|
||||||
|
self.status_label.setStyleSheet("font-size: 14px; color: cyan;")
|
||||||
|
self.setup_ui()
|
||||||
|
|
||||||
|
def setup_ui(self):
|
||||||
|
self.title.setGeometry(20, 50, 760, 40)
|
||||||
|
self.title.setText("Enable system-wide WireGuard profiles")
|
||||||
|
description = QLabel(self)
|
||||||
|
description.setGeometry(80, 100, 640, 80)
|
||||||
|
description.setWordWrap(True)
|
||||||
|
description.setStyleSheet("font-size: 14px; color: cyan;")
|
||||||
|
description.setText("You can enable system-wide WireGuard profiles so they can be started without entering your sudo password each time. This uses a secure sudo policy tailored to your user.")
|
||||||
|
icon_label = QLabel(self)
|
||||||
|
icon_label.setGeometry(80, 200, 64, 64)
|
||||||
|
icon_pix = QPixmap(os.path.join(self.btn_path, "wireguard_system_wide.png"))
|
||||||
|
icon_label.setPixmap(icon_pix.scaled(64, 64, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation))
|
||||||
|
yes_button = QPushButton("Yes, enable system-wide profiles", self)
|
||||||
|
yes_button.setGeometry(170, 200, 300, 50)
|
||||||
|
yes_button.setStyleSheet("""
|
||||||
|
QPushButton {
|
||||||
|
background: #007AFF;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background: #0056CC;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
yes_button.clicked.connect(self.enable_systemwide)
|
||||||
|
no_button = QPushButton("Not now", self)
|
||||||
|
no_button.setGeometry(170, 270, 120, 40)
|
||||||
|
no_button.setStyleSheet("""
|
||||||
|
QPushButton {
|
||||||
|
background: #007AFF;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
QPushButton:hover {
|
||||||
|
background: #0056CC;
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
no_button.clicked.connect(self.skip_systemwide)
|
||||||
|
self.refresh_status()
|
||||||
|
|
||||||
|
def refresh_status(self):
|
||||||
|
if PrivilegePolicyController.is_instated():
|
||||||
|
self.status_label.setText("Current status: system-wide policy is enabled.")
|
||||||
|
self.status_label.setStyleSheet("font-size: 14px; color: #2ecc71;")
|
||||||
|
else:
|
||||||
|
self.status_label.setText("Current status: system-wide policy is disabled.")
|
||||||
|
self.status_label.setStyleSheet("font-size: 14px; color: #e67e22;")
|
||||||
|
|
||||||
|
def enable_systemwide(self):
|
||||||
|
try:
|
||||||
|
PrivilegePolicyController.instate()
|
||||||
|
self.update_status.mark_systemwide_prompt_shown()
|
||||||
|
self.refresh_status()
|
||||||
|
self.update_status.update_status("System-wide policy enabled")
|
||||||
|
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(MenuPage)))
|
||||||
|
except CommandNotFoundError as e:
|
||||||
|
self.status_label.setText(str(e))
|
||||||
|
self.status_label.setStyleSheet("font-size: 14px; color: red;")
|
||||||
|
except (PolicyAssignmentError, PolicyInstatementError) as e:
|
||||||
|
self.status_label.setText(str(e))
|
||||||
|
self.status_label.setStyleSheet("font-size: 14px; color: red;")
|
||||||
|
except Exception:
|
||||||
|
self.status_label.setText("Failed to enable system-wide policy")
|
||||||
|
self.status_label.setStyleSheet("font-size: 14px; color: red;")
|
||||||
|
|
||||||
|
def skip_systemwide(self):
|
||||||
|
self.update_status.mark_systemwide_prompt_shown()
|
||||||
|
self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(MenuPage)))
|
||||||
|
|
||||||
|
def back_to_install(self):
|
||||||
|
install_page = self.page_stack.findChild(InstallSystemPackage)
|
||||||
|
if install_page:
|
||||||
|
self.page_stack.setCurrentIndex(self.page_stack.indexOf(install_page))
|
||||||
class DurationSelectionPage(Page):
|
class DurationSelectionPage(Page):
|
||||||
def __init__(self, page_stack, main_window=None, parent=None):
|
def __init__(self, page_stack, main_window=None, parent=None):
|
||||||
super().__init__("Select Duration", page_stack, main_window, parent)
|
super().__init__("Select Duration", page_stack, main_window, parent)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[project]
|
[project]
|
||||||
name = "sp-hydra-veil-gui"
|
name = "sp-hydra-veil-gui"
|
||||||
version = "1.1.7"
|
version = "1.1.8"
|
||||||
authors = [
|
authors = [
|
||||||
{ name = "Simplified Privacy" },
|
{ name = "Simplified Privacy" },
|
||||||
]
|
]
|
||||||
|
|
@ -12,7 +12,7 @@ classifiers = [
|
||||||
"Operating System :: POSIX :: Linux",
|
"Operating System :: POSIX :: Linux",
|
||||||
]
|
]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"sp-hydra-veil-core == 1.1.7",
|
"sp-hydra-veil-core == 1.1.8-a2",
|
||||||
"pyperclip ~= 1.9.0",
|
"pyperclip ~= 1.9.0",
|
||||||
"pyqt6 ~= 6.7.1",
|
"pyqt6 ~= 6.7.1",
|
||||||
"qrcode[pil] ~= 8.2"
|
"qrcode[pil] ~= 8.2"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue