Applied patch files

This commit is contained in:
Your Name 2025-05-16 23:20:04 +01:00
parent ff6826b0d9
commit 2b52907e05
240 changed files with 201 additions and 250 deletions

View file

@ -1,6 +1,6 @@
from PyQt6.QtWidgets import QComboBox,QButtonGroup, QLineEdit,QMainWindow, QLabel, QWidget, QVBoxLayout, QStackedWidget, QApplication, QPushButton, QTextEdit, QFrame, QHBoxLayout, QVBoxLayout, QScrollArea, QSystemTrayIcon, QMessageBox, QGridLayout, QCheckBox, QStackedLayout, QGroupBox, QDialog from PyQt6.QtWidgets import QComboBox,QButtonGroup, QLineEdit,QMainWindow, QLabel, QWidget, QVBoxLayout, QStackedWidget, QApplication, QPushButton, QTextEdit, QFrame, QHBoxLayout, QVBoxLayout, QScrollArea, QSystemTrayIcon, QMessageBox, QGridLayout, QCheckBox, QStackedLayout, QGroupBox, QDialog
from PyQt6.QtGui import QIcon, QPixmap,QIcon, QPixmap, QTransform, QPainter, QColor, QFont, QFontDatabase from PyQt6.QtGui import QIcon, QPixmap,QIcon, QPixmap, QTransform, QPainter, QColor, QFont, QFontDatabase
from PyQt6 import QtGui from PyQt6 import QtGui
from PyQt6 import QtCore from PyQt6 import QtCore
from PyQt6.QtCore import Qt,QSize,QThread,pyqtSignal, QTimer, QPointF, QRect, QMutex, QMutexLocker, QObject from PyQt6.QtCore import Qt,QSize,QThread,pyqtSignal, QTimer, QPointF, QRect, QMutex, QMutexLocker, QObject
import os import os
@ -9,7 +9,7 @@ import functools
import threading import threading
import logging import logging
import traceback import traceback
import random import random
import subprocess import subprocess
from typing import Union from typing import Union
from core.Errors import UnknownConnectionTypeError, CommandNotFoundError, MissingSubscriptionError, InvalidSubscriptionError, ProfileActivationError, UnsupportedApplicationVersionError, FileIntegrityError, ProfileModificationError, ProfileStateConflictError from core.Errors import UnknownConnectionTypeError, CommandNotFoundError, MissingSubscriptionError, InvalidSubscriptionError, ProfileActivationError, UnsupportedApplicationVersionError, FileIntegrityError, ProfileModificationError, ProfileStateConflictError
@ -35,6 +35,7 @@ from datetime import datetime, timezone, timedelta
from core.Constants import Constants from core.Constants import Constants
import atexit import atexit
import json import json
import shlex
@ -119,7 +120,7 @@ class WorkerThread(QThread):
self.text_output.emit("Checking for updates...") self.text_output.emit("Checking for updates...")
ClientController.sync(client_observer=client_observer, connection_observer=connection_observer) ClientController.sync(client_observer=client_observer, connection_observer=connection_observer)
update_available = ClientController.can_be_updated() update_available = ClientController.can_be_updated()
if update_available: if update_available:
self.text_output.emit("An update is available. Downloading...") self.text_output.emit("An update is available. Downloading...")
self.finished.emit(True) self.finished.emit(True)
else: else:
@ -130,7 +131,7 @@ class WorkerThread(QThread):
def install_package(self): def install_package(self):
try: try:
self.text_output.emit(f"Installing {self.package_name}...") self.text_output.emit(f"Installing {self.package_name}...")
subprocess.run(self.package_command.split(), check=True) subprocess.run(shlex.split(self.package_command), check=True)
self.text_output.emit(f"{self.package_name} installed!") self.text_output.emit(f"{self.package_name} installed!")
self.finished.emit(True) self.finished.emit(True)
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
@ -227,7 +228,7 @@ class WorkerThread(QThread):
ConfigurationController.set_connection('tor') ConfigurationController.set_connection('tor')
else: else:
ConfigurationController.set_connection('system') ConfigurationController.set_connection('system')
ClientController.sync(client_observer=client_observer, connection_observer=connection_observer) self.check_for_update()
locations = LocationController.get_all() locations = LocationController.get_all()
all_location_codes = [f"{location.country_code}_{location.code}" for location in locations] all_location_codes = [f"{location.country_code}_{location.code}" for location in locations]
self.sync_output.emit(all_location_codes, True, False, locations, False) self.sync_output.emit(all_location_codes, True, False, locations, False)
@ -317,12 +318,15 @@ class CustomWindow(QMainWindow):
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
self.setAttribute(Qt.WidgetAttribute.WA_NoSystemBackground) self.setAttribute(Qt.WidgetAttribute.WA_NoSystemBackground)
self.setWindowTitle("HydraVeil VPN") self.setWindowTitle('HydraVeil')
self._data = {"Profile_1": {}} self._data = {"Profile_1": {}}
self.gui_dir = os.path.join(Constants.HV_DATA_HOME, "gui") self.gui_config_home = os.path.join(Constants.HV_CONFIG_HOME, 'gui')
self.gui_config_file = os.path.join(self.gui_dir, "config.json") self.gui_config_file = os.path.join(self.gui_config_home, 'config.json')
self.gui_log_file = os.path.join(self.gui_dir, "gui.log")
self.gui_cache_home = os.path.join(Constants.HV_CACHE_HOME, 'gui')
self.gui_log_file = os.path.join(self.gui_cache_home, 'gui.log')
self._setup_gui_directory() self._setup_gui_directory()
current_dir = os.path.dirname(os.path.abspath(__file__)) current_dir = os.path.dirname(os.path.abspath(__file__))
@ -330,10 +334,8 @@ class CustomWindow(QMainWindow):
self.btn_path = os.getenv('BTN_PATH', os.path.join(current_dir, 'resources', 'images')) self.btn_path = os.getenv('BTN_PATH', os.path.join(current_dir, 'resources', 'images'))
self.css_path = os.getenv('CSS_PATH', os.path.join(current_dir, 'resources', 'styles')) self.css_path = os.getenv('CSS_PATH', os.path.join(current_dir, 'resources', 'styles'))
icon_base = os.getenv('SYSTEM_TRAY_ICON', '')
self.tray = None self.tray = None
self.init_system_tray(icon_base) self.init_system_tray(self.btn_path)
self.is_downloading = False self.is_downloading = False
self.current_profile_id = None self.current_profile_id = None
@ -351,6 +353,12 @@ class CustomWindow(QMainWindow):
profile_observer.subscribe('created', lambda event: self.update_status('Profile Created')) profile_observer.subscribe('created', lambda event: self.update_status('Profile Created'))
profile_observer.subscribe('destroyed', lambda event: self.update_status('Profile destroyed')) profile_observer.subscribe('destroyed', lambda event: self.update_status('Profile destroyed'))
client_observer.subscribe('synchronizing', lambda event: self.update_status('Sync in progress...'))
client_observer.subscribe('synchronized', lambda event: self.update_status('Sync complete'))
client_observer.subscribe('updating', lambda event: self.update_status('Updating client...'))
client_observer.subscribe('update_progressing', lambda event: self.update_status(f'Current progress: {event.meta.get('progress'):.2f}%'))
client_observer.subscribe('updated', lambda event: self.update_status('Restart client to apply update.'))
application_version_observer.subscribe('downloading', lambda event: self.update_status(f'Downloading {ApplicationController.get(event.subject.application_code).name}')) application_version_observer.subscribe('downloading', lambda event: self.update_status(f'Downloading {ApplicationController.get(event.subject.application_code).name}'))
application_version_observer.subscribe('download_progressing', lambda event: self.update_status(f'Downloading {ApplicationController.get(event.subject.application_code).name} {event.meta.get('progress'):.2f}%')) application_version_observer.subscribe('download_progressing', lambda event: self.update_status(f'Downloading {ApplicationController.get(event.subject.application_code).name} {event.meta.get('progress'):.2f}%'))
@ -389,7 +397,7 @@ class CustomWindow(QMainWindow):
self.scroll_speed = 1 self.scroll_speed = 1
self.tor_text = QLabel("Billing & Browsers", self) self.tor_text = QLabel("Billing & Browsers", self)
self.tor_text.setGeometry(515, 542, 150, 20) self.tor_text.setGeometry(532, 541, 150, 20)
self.tor_text.setStyleSheet(""" self.tor_text.setStyleSheet("""
QLabel { QLabel {
color: cyan; color: cyan;
@ -401,31 +409,56 @@ class CustomWindow(QMainWindow):
self.set_scroll_speed(7) self.set_scroll_speed(7)
self.tor_icon = QLabel(self)
self.tor_icon.setGeometry(705, 537, 25, 25)
self.set_tor_icon()
self.toggle_button = QPushButton(self) self.toggle_button = QPushButton(self)
self.toggle_button.setGeometry(645, 541, 50, 22) self.toggle_button.setGeometry(670, 541, 50, 22)
self.toggle_button.setCheckable(True) self.toggle_button.setCheckable(True)
self.toggle_button.clicked.connect(self.toggle_mode) self.toggle_button.clicked.connect(self.toggle_mode)
self.tor_icon = QLabel(self)
self.tor_icon.setGeometry(730, 537, 25, 25)
self.set_tor_icon()
self.create_toggle(self.is_tor_mode) self.create_toggle(self.is_tor_mode)
self.animation_timer = QTimer() self.animation_timer = QTimer()
self.animation_timer.timeout.connect(self.animate_toggle) self.animation_timer.timeout.connect(self.animate_toggle)
self.check_logging() self.check_logging()
self.sync_button = QPushButton(self)
self.sync_button.setGeometry(771, 541, 22, 22)
self.sync_button.setObjectName('sync_button')
if CustomWindow.should_be_synchronized():
sync_icon = QtGui.QIcon(os.path.join(self.btn_path, 'icon_sync_urgent.png'))
else:
sync_icon = QtGui.QIcon(os.path.join(self.btn_path, 'icon_sync.png'))
self.sync_button.setToolTip('Sync')
self.sync_button.setIcon(sync_icon)
self.sync_button.setIconSize(self.sync_button.size())
self.sync_button.clicked.connect(self.sync)
self.init_ui() self.init_ui()
current_connection = self.get_current_connection() current_connection = self.get_current_connection()
self.is_tor_mode = current_connection == 'tor' self.is_tor_mode = current_connection == 'tor'
self.set_toggle_state(self.is_tor_mode) self.set_toggle_state(self.is_tor_mode)
def perform_update_check(self):
update_available = ClientController.can_be_updated()
if update_available:
menu_page = self.page_stack.findChild(MenuPage)
menu_page.on_update_check_finished()
def sync(self):
if ConfigurationController.get_connection() == 'tor':
self.worker_thread = WorkerThread('SYNC_TOR')
else:
self.worker_thread = WorkerThread('SYNC')
self.sync_button.setIcon(QtGui.QIcon(os.path.join(self.btn_path, 'icon_sync.png')))
self.worker_thread.finished.connect(lambda: self.perform_update_check())
self.worker_thread.start()
def _handle_exception(self, identifier, message, trace): def _handle_exception(self, identifier, message, trace):
if issubclass(identifier, UnknownConnectionTypeError): if issubclass(identifier, UnknownConnectionTypeError):
@ -515,7 +548,8 @@ class CustomWindow(QMainWindow):
return ConfigurationController.get_connection() return ConfigurationController.get_connection()
def _setup_gui_directory(self): def _setup_gui_directory(self):
os.makedirs(self.gui_dir, exist_ok=True) os.makedirs(self.gui_cache_home, exist_ok=True)
os.makedirs(self.gui_config_home, exist_ok=True)
if not os.path.exists(self.gui_config_file): if not os.path.exists(self.gui_config_file):
default_config = { default_config = {
@ -562,7 +596,7 @@ class CustomWindow(QMainWindow):
def _setup_gui_logging(self): def _setup_gui_logging(self):
os.makedirs(self.gui_dir, exist_ok=True) os.makedirs(self.gui_cache_home, exist_ok=True)
formatter = logging.Formatter( formatter = logging.Formatter(
'%(asctime)s - %(levelname)s - %(message)s', '%(asctime)s - %(levelname)s - %(message)s',
@ -734,24 +768,25 @@ class CustomWindow(QMainWindow):
def init_system_tray(self, icon_base): def init_system_tray(self, icon_base_path):
if QSystemTrayIcon.isSystemTrayAvailable(): if QSystemTrayIcon.isSystemTrayAvailable():
tray_icon = QIcon() tray_icon = QIcon()
window_icon = QIcon() window_icon = QIcon()
tray_sizes = [22, 24] tray_sizes = [22, 24]
for size in tray_sizes: for size in tray_sizes:
icon_path = os.path.join(icon_base, f"{size}x{size}/apps/simplified-privacy.png") icon_path = os.path.join(icon_base_path, f"hv-icon-{size}x{size}.png")
if os.path.exists(icon_path): if os.path.exists(icon_path):
tray_icon.addFile(icon_path, QSize(size, size)) tray_icon.addFile(icon_path, QSize(size, size))
window_sizes = [32, 48, 64, 128] window_sizes = [32, 48, 64, 128]
for size in window_sizes: for size in window_sizes:
icon_path = os.path.join(icon_base, f"{size}x{size}/apps/simplified-privacy.png") icon_path = os.path.join(icon_base_path, f"hv-icon-{size}x{size}.png")
if os.path.exists(icon_path): if os.path.exists(icon_path):
window_icon.addFile(icon_path, QSize(size, size)) window_icon.addFile(icon_path, QSize(size, size))
self.tray = QSystemTrayIcon(self) self.tray = QSystemTrayIcon(self)
self.tray.setToolTip('HydraVeil')
self.tray.setIcon(tray_icon) self.tray.setIcon(tray_icon)
self.tray.setVisible(True) self.tray.setVisible(True)
self.setWindowIcon(window_icon) self.setWindowIcon(window_icon)
@ -828,13 +863,13 @@ class CustomWindow(QMainWindow):
self.editor_page = EditorPage(self.page_stack, self) self.editor_page = EditorPage(self.page_stack, self)
self.pages = [MenuPage(self.page_stack, self), self.pages = [MenuPage(self.page_stack, self),
ProtocolPage(self.page_stack, self), ProtocolPage(self.page_stack, self),
WireGuardPage(self.page_stack, self),
HidetorPage(self.page_stack, self),
LocationPage(self.page_stack, self), LocationPage(self.page_stack, self),
BrowserPage(self.page_stack, self), BrowserPage(self.page_stack, self),
ScreenPage(self.page_stack, self), ScreenPage(self.page_stack, self),
ResumePage(self.page_stack, self), ResumePage(self.page_stack, self),
WireGuardPage(self.page_stack, self),
ResidentialPage(self.page_stack, self), ResidentialPage(self.page_stack, self),
HidetorPage(self.page_stack, self),
InstallSystemPackage(self.page_stack, self), InstallSystemPackage(self.page_stack, self),
WelcomePage(self.page_stack, self), WelcomePage(self.page_stack, self),
PaymentPage(self.page_stack, self), PaymentPage(self.page_stack, self),
@ -878,8 +913,8 @@ class CustomWindow(QMainWindow):
self.disable_marquee() self.disable_marquee()
def check_first_launch(self): def check_first_launch(self):
config_file = os.path.join(self.gui_dir, "first_launch.txt")
config_file = os.path.join(self.gui_config_home, '.first-run')
os.makedirs(Constants.HV_CONFIG_HOME, exist_ok=True) os.makedirs(Constants.HV_CONFIG_HOME, exist_ok=True)
is_first_launch = not os.path.exists(config_file) is_first_launch = not os.path.exists(config_file)
@ -936,7 +971,23 @@ class CustomWindow(QMainWindow):
def set_scroll_speed(self, speed): def set_scroll_speed(self, speed):
self.scroll_speed = speed self.scroll_speed = speed
@staticmethod
def should_be_synchronized():
current_datetime = datetime.today().astimezone(timezone.utc)
last_synced_at = ConfigurationController.get_last_synced_at()
return last_synced_at is None or (current_datetime - last_synced_at) >= timedelta(days=30)
def page_changed(self, index): def page_changed(self, index):
if CustomWindow.should_be_synchronized():
sync_icon = QtGui.QIcon(os.path.join(self.btn_path, 'icon_sync_urgent.png'))
else:
sync_icon = QtGui.QIcon(os.path.join(self.btn_path, 'icon_sync.png'))
self.sync_button.setIcon(sync_icon)
current_page = self.page_stack.widget(index) current_page = self.page_stack.widget(index)
if self.page_history: if self.page_history:
previous_page = self.page_history[-1] previous_page = self.page_history[-1]
@ -958,15 +1009,17 @@ class CustomWindow(QMainWindow):
elif isinstance(current_page, LocationPage): elif isinstance(current_page, LocationPage):
self.update_status(None, clear=True) self.update_status(None, clear=True)
elif isinstance(current_page, InstallSystemPackage): elif isinstance(current_page, InstallSystemPackage):
self.update_status("Required tools are not installed. Please install them.") self.update_status('Please check package availability.')
else: else:
self.update_status(None) self.update_status(None)
if isinstance(current_page, MenuPage): if isinstance(current_page, MenuPage):
self.sync_button.setVisible(True)
self.tor_text.setVisible(True) self.tor_text.setVisible(True)
self.toggle_button.setGeometry(645, 541, 50, 22) self.toggle_button.setGeometry(670, 541, 50, 22)
self.tor_icon.setGeometry(705, 537, 25, 25) self.tor_icon.setGeometry(730, 537, 25, 25)
else: else:
self.sync_button.setVisible(False)
self.tor_text.setVisible(False) self.tor_text.setVisible(False)
self.toggle_button.setGeometry(540, 541, 50, 22) self.toggle_button.setGeometry(540, 541, 50, 22)
self.tor_icon.setGeometry(600, 537, 25, 25) self.tor_icon.setGeometry(600, 537, 25, 25)
@ -1104,7 +1157,7 @@ class Worker(QObject):
except ProfileStateConflictError: except ProfileStateConflictError:
self.update_signal.emit("The profile is already being enabled...", False, None, None, None) self.update_signal.emit("The profile is already being enabled...", False, None, None, None)
except CommandNotFoundError as e : except CommandNotFoundError as e :
self.update_signal.emit(str(e), False, -1, None, None) self.update_signal.emit(str(e.subject), False, -1, None, None)
except Exception as e: except Exception as e:
print(e) print(e)
self.update_signal.emit("An unknown error occurred", False, None, None, None) self.update_signal.emit("An unknown error occurred", False, None, None, None)
@ -1198,7 +1251,7 @@ class MenuPage(Page):
self.worker = WorkerThread('DOWNLOAD_UPDATE') self.worker = WorkerThread('DOWNLOAD_UPDATE')
self.worker.start() self.worker.start()
else: else:
self.update_status.update_status("Update cancelled by user.") self.update_status.update_status('Update canceled')
@ -1328,6 +1381,9 @@ class MenuPage(Page):
return new_dict return new_dict
def create(self): def create(self):
self.boton_just.setEnabled(False)
self.boton_just_session.setEnabled(False)
self.boton_edit.setEnabled(False)
self.profiles_data = self.match_core_profiles(ProfileController.get_all()) self.profiles_data = self.match_core_profiles(ProfileController.get_all())
self.number_of_profiles = len(self.profiles_data) self.number_of_profiles = len(self.profiles_data)
self.profile_info.update(self.profiles_data) self.profile_info.update(self.profiles_data)
@ -1933,7 +1989,7 @@ class ConnectionManager:
def get_is_profile_being_enabled(self, profile_id: int) -> bool: def get_is_profile_being_enabled(self, profile_id: int) -> bool:
return self._is_profile_being_enabled.get(profile_id, False) return self._is_profile_being_enabled.get(profile_id, False)
class InstallSystemPackage(Page): class InstallSystemPackage(Page):
def __init__(self, page_stack, main_window=None, parent=None): def __init__(self, page_stack, main_window=None, parent=None):
super().__init__("InstallPackage", page_stack, main_window, parent) super().__init__("InstallPackage", page_stack, main_window, parent)
@ -1953,110 +2009,104 @@ class InstallSystemPackage(Page):
self.auto_install_package_commands = { self.auto_install_package_commands = {
'all': { 'all': {
'debian': 'pkexec apt install -y bubblewrap iproute2 microsocks proxychains4 ratpoison tor wireguard xserver-xephyr resolvconf', 'debian': 'pkexec apt install -y bubblewrap iproute2 microsocks proxychains4 ratpoison tor wireguard xserver-xephyr',
'arch': 'pkexec pacman -S bubblewrap iproute2 microsocks proxychains-ng tor wireguard-tools xorg-server-xephyr resolvconf', 'arch': 'pkexec pacman -S bubblewrap iproute2 microsocks proxychains-ng tor wireguard-tools xorg-server-xephyr',
'fedora': 'pkexec dnf -y install bubblewrap iproute-doc proxychains4 ratpoison tor wireguard xorg-x11-server-Xephyr resolvconf' 'fedora': 'pkexec dnf -y install bubblewrap iproute proxychains4 ratpoison tor wireguard-tools xorg-x11-server-Xephyr'
}, },
'bwrap': {
'wireguard': { 'debian': 'pkexec apt -y install bubblewrap',
'debian': 'pkexec apt -y install wireguard resolvconf', 'arch': 'pkexec pacman -S bubblewrap',
'arch': 'pkexec pacman -S wireguard-tools resolvconf', 'fedora': 'pkexec dnf -y install bubblewrap'
'fedora': 'pkexec dnf -y install wireguard-tools resolvconf'
}, },
'resolvconf': { 'ip': {
'debian': 'pkexec apt -y install resolvconf', 'debian': 'pkexec apt -y install iproute2',
'arch': 'pkexec pacman -S resolvconf', 'arch': 'pkexec pacman -S iproute2',
'fedora': 'pkexec dnf -y install resolvconf' 'fedora': 'pkexec dnf -y install iproute'
},
'tor': {
'debian': 'pkexec apt -y install tor proxychains4 microsocks',
'arch': 'pkexec pacman -S tor proxychains4 microsocks',
'fedora': 'pkexec dnf -y install tor proxychains4'
},
'tor_sync': {
'debian': 'pkexec apt -y install tor',
'arch': 'pkexec pacman -S tor',
'fedora': 'pkexec dnf -y install tor'
},
'proxychains4': {
'debian': 'pkexec apt -y install proxychains4',
'arch': 'pkexec pacman -S proxychains-ng',
'fedora': 'pkexec dnf -y install proxychains4'
}, },
'microsocks': { 'microsocks': {
'debian': 'pkexec apt -y install microsocks', 'debian': 'pkexec apt -y install microsocks',
'arch': 'pkexec pacman -S microsocks', 'arch': 'pkexec pacman -S microsocks',
'fedora': 'pkexec dnf -y install microsocks' 'fedora': 'zenity --warning --text="An essential dependency (microsocks) is not included in your distribution\'s default repository. Please build it from source or contact support."'
}, },
'xserver-xephyr': { 'proxychains4': {
'debian': 'pkexec apt -y install xserver-xephyr bubblewrap ratpoison', 'debian': 'pkexec apt -y install proxychains4',
'arch': 'pkexec pacman -S xorg-server-xephyr bubblewrap ratpoison', 'arch': 'pkexec pacman -S proxychains-ng',
'fedora': 'pkexec dnf -y install xorg-x11-server-Xephyr bubblewrap ratpoison' 'fedora': 'pkexec dnf -y install proxychains4'
}, },
'bubblewrap': { 'ratpoison': {
'debian': 'pkexec apt -y install bubblewrap', 'debian': 'pkexec apt -y install ratpoison',
'arch': 'pkexec pacman -S bubblewrap', 'arch': 'zenity --warning --text="An essential dependency (ratpoison) is not included in your distribution\'s default repository. Please build it from source or contact support."',
'fedora': 'pkexec dnf -y install bubblewrap' 'fedora': 'pkexec dnf -y install ratpoison'
},
'tor': {
'debian': 'pkexec apt -y install tor',
'arch': 'pkexec pacman -S tor',
'fedora': 'pkexec dnf -y install tor'
},
'wg-quick': {
'debian': 'pkexec apt -y install wireguard',
'arch': 'pkexec pacman -S wireguard-tools',
'fedora': 'pkexec dnf -y install wireguard-tools'
},
'Xephyr': {
'debian': 'pkexec apt -y install xserver-xephyr',
'arch': 'pkexec pacman -S xorg-server-xephyr',
'fedora': 'pkexec dnf -y install xorg-x11-server-Xephyr'
} }
} }
self.manual_install_package_commands = { self.manual_install_package_commands = {
'all': { 'all': {
'debian': 'sudo apt install -y bubblewrap iproute2 microsocks proxychains4 ratpoison tor wireguard xserver-xephyr resolvconf', 'debian': 'sudo apt install -y bubblewrap iproute2 microsocks proxychains4 ratpoison tor wireguard xserver-xephyr',
'arch': 'sudo pacman -S bubblewrap iproute2 microsocks proxychains-ng tor wireguard-tools xorg-server-xephyr resolvconf', 'arch': 'sudo pacman -S bubblewrap iproute2 microsocks proxychains-ng tor wireguard-tools xorg-server-xephyr',
'fedora': 'sudo dnf -y install bubblewrap iproute-doc proxychains4 ratpoison tor wireguard xorg-x11-server-Xephyr resolvconf' 'fedora': 'sudo dnf -y install bubblewrap iproute proxychains4 ratpoison tor wireguard-tools xorg-x11-server-Xephyr'
}, },
'polkit': { 'bwrap': {
'debian': 'sudo apt -y install policykit-1', 'debian': 'sudo apt -y install bubblewrap',
'arch': 'sudo pacman -S polkit', 'arch': 'sudo pacman -S bubblewrap',
'fedora': 'sudo dnf -y install polkit' 'fedora': 'sudo dnf -y install bubblewrap'
}, },
'wireguard': { 'ip': {
'debian': 'sudo apt -y install wireguard resolvconf', 'debian': 'sudo apt -y install iproute2',
'arch': 'sudo pacman -S wireguard-tools resolvconf', 'arch': 'sudo pacman -S iproute2',
'fedora': 'sudo dnf -y install wireguard-tools resolvconf' 'fedora': 'sudo dnf -y install iproute'
},
'resolvconf': {
'debian': 'sudo apt -y install resolvconf',
'arch': 'sudo pacman -S resolvconf',
'fedora': 'sudo dnf -y install resolvconf'
},
'tor': {
'debian': 'sudo apt -y install tor proxychains4 microsocks',
'arch': 'sudo pacman -S tor proxychains-ng microsocks',
'fedora': 'sudo dnf -y install tor proxychains4'
},
'tor_sync': {
'debian': 'sudo apt -y install tor',
'arch': 'sudo pacman -S tor',
'fedora': 'sudo dnf -y install tor'
},
'proxychains4': {
'debian': 'sudo apt -y install proxychains4',
'arch': 'sudo pacman -S proxychains-ng',
'fedora': 'sudo dnf -y install proxychains4'
}, },
'microsocks': { 'microsocks': {
'debian': 'sudo apt -y install microsocks', 'debian': 'sudo apt -y install microsocks',
'arch': 'sudo pacman -S microsocks', 'arch': 'sudo pacman -S microsocks',
'fedora': 'sudo dnf -y install microsocks' 'fedora': '# Package not available.'
}, },
'xserver-xephyr': { 'proxychains4': {
'debian': 'sudo apt -y install xserver-xephyr bubblewrap ratpoison', 'debian': 'sudo apt -y install proxychains4',
'arch': 'sudo pacman -S xorg-server-xephyr bubblewrap ratpoison', 'arch': 'sudo pacman -S proxychains-ng',
'fedora': 'sudo dnf -y install xorg-x11-server-Xephyr bubblewrap ratpoison' 'fedora': 'sudo dnf -y install proxychains4'
}, },
'bubblewrap': { 'ratpoison': {
'debian': 'sudo apt -y install bubblewrap', 'debian': 'sudo apt -y install ratpoison',
'arch': 'sudo pacman -S bubblewrap', 'arch': '# Package not available.',
'fedora': 'sudo dnf -y install bubblewrap' 'fedora': 'sudo dnf -y install ratpoison'
},
'tor': {
'debian': 'sudo apt -y install tor',
'arch': 'sudo pacman -S tor',
'fedora': 'sudo dnf -y install tor'
},
'wg-quick': {
'debian': 'sudo apt -y install wireguard',
'arch': 'sudo pacman -S wireguard-tools',
'fedora': 'sudo dnf -y install wireguard-tools'
},
'Xephyr': {
'debian': 'sudo apt -y install xserver-xephyr',
'arch': 'sudo pacman -S xorg-server-xephyr',
'fedora': 'sudo dnf -y install xorg-x11-server-Xephyr'
} }
} }
def _setup_permanent_ui(self): def _setup_permanent_ui(self):
self.title.setGeometry(20, 50, 300, 60) self.title.setGeometry(20, 50, 300, 60)
self.title.setText("Package Installation") self.title.setText("Package Installation")
self.title.setStyleSheet("font-size: 24px; font-weight: bold;") self.title.setStyleSheet("font-size: 22px; font-weight: bold;")
self.permanent_elements.append(self.title) self.permanent_elements.append(self.title)
self.display.setGeometry(QtCore.QRect(100, 160, 580, 435)) self.display.setGeometry(QtCore.QRect(100, 160, 580, 435))
@ -2147,6 +2197,7 @@ class InstallSystemPackage(Page):
self.ui_elements.append(auto_install_label) self.ui_elements.append(auto_install_label)
auto_install_desc = QLabel("Click the button below to automatically install the missing packages:", self) auto_install_desc = QLabel("Click the button below to automatically install the missing packages:", self)
auto_install_desc.setStyleSheet("font-size: 14px; font-weight: bold;")
auto_install_desc.setGeometry(80, 170, 650, 30) auto_install_desc.setGeometry(80, 170, 650, 30)
auto_install_desc.setVisible(True) auto_install_desc.setVisible(True)
self.ui_elements.append(auto_install_desc) self.ui_elements.append(auto_install_desc)
@ -2182,6 +2233,7 @@ class InstallSystemPackage(Page):
self.ui_elements.append(manual_install_label) self.ui_elements.append(manual_install_label)
manual_install_desc = QLabel("Run this command in your terminal:", self) manual_install_desc = QLabel("Run this command in your terminal:", self)
manual_install_desc.setStyleSheet("font-size: 14px; font-weight: bold;")
manual_install_desc.setGeometry(80, 330, 380, 30) manual_install_desc.setGeometry(80, 330, 380, 30)
manual_install_desc.setVisible(True) manual_install_desc.setVisible(True)
@ -2368,7 +2420,7 @@ class InstallSystemPackage(Page):
def check_package(self): def check_package(self):
try: try:
if self.package_name.lower() == 'all': if self.package_name.lower() == 'all':
packages = ['bwrap', 'ip', 'microsocks', 'proxychains4', 'ratpoison', 'tor', 'Xephyr', 'wg', 'resolvconf'] packages = ['bwrap', 'ip', 'microsocks', 'proxychains4', 'ratpoison', 'tor', 'Xephyr', 'wg']
for package in packages: for package in packages:
if subprocess.getstatusoutput(f'{package} --help')[0] == 127: if subprocess.getstatusoutput(f'{package} --help')[0] == 127:
self.status_label.setText(f"{package} is not installed") self.status_label.setText(f"{package} is not installed")
@ -2397,120 +2449,6 @@ class InstallSystemPackage(Page):
def go_next(self): def go_next(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)))
class WelcomePage(Page):
def __init__(self, page_stack, main_window=None, parent=None):
super().__init__("Welcome", page_stack, main_window, parent)
self.btn_path = main_window.btn_path
self.update_status = main_window
self.ui_elements = []
self.button_next.clicked.connect(self.go_to_install)
self.button_next.setVisible(True)
self._setup_welcome_ui()
self._setup_stats_display()
def _setup_welcome_ui(self):
welcome_title = QLabel("Welcome to HydraVeilVPN", self)
welcome_title.setGeometry(20, 45, 760, 60)
welcome_title.setStyleSheet("""
font-size: 32px;
font-weight: bold;
color: cyan;
""")
welcome_title.setAlignment(Qt.AlignmentFlag.AlignCenter)
welcome_msg = QLabel(
"Before we begin your journey, we need to set up a few essential components. "
"Click 'Next' to take you to the installation page.", self)
welcome_msg.setGeometry(40, 100, 720, 80)
welcome_msg.setWordWrap(True)
welcome_msg.setStyleSheet("""
font-size: 16px;
color: cyan;
""")
welcome_msg.setAlignment(Qt.AlignmentFlag.AlignCenter)
def _setup_stats_display(self):
stats_container = QWidget(self)
stats_container.setGeometry(70, 200, 730, 240)
stats_title = QLabel(stats_container)
stats_title.setText("Features & Services")
stats_title.setGeometry(190, 10, 300, 30)
stats_title.setStyleSheet("""
font-size: 22px;
font-weight: bold;
color: cyan;
""")
grid_widget = QWidget(stats_container)
grid_widget.setGeometry(0, 70, 700, 190)
grid_layout = QGridLayout(grid_widget)
grid_layout.setSpacing(30)
stats = [
("Browsers", "browsers_mini.png", "10 Supported Browsers", True),
("WireGuard", "wireguard_mini.png", "6 Global Locations", True),
("Proxy", "just proxy_mini.png", "5 Proxy Locations", True),
("Tor", "toricon_mini.png", "Tor Network Access", True)
]
for i, (title, icon_name, count, available) in enumerate(stats):
row = i // 2
col = i % 2
stat_widget = QWidget()
stat_layout = QHBoxLayout(stat_widget)
stat_layout.setContentsMargins(20, 10, 2, 10)
stat_layout.setSpacing(15)
icon_label = QLabel()
icon_path = os.path.join(self.btn_path, icon_name)
icon_label.setPixmap(QPixmap(icon_path).scaled(30, 30, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation))
icon_label.setFixedSize(30, 30)
stat_layout.addWidget(icon_label)
text_widget = QWidget()
text_layout = QVBoxLayout(text_widget)
text_layout.setSpacing(5)
text_layout.setContentsMargins(0, 0, 30, 0)
title_widget = QWidget()
title_layout = QHBoxLayout(title_widget)
title_layout.setContentsMargins(0, 0, 0, 0)
title_layout.setSpacing(10)
title_label = QLabel(title)
title_label.setStyleSheet("font-size: 16px; font-weight: bold; color: #2c3e50;")
title_layout.addWidget(title_label)
status_indicator = QLabel("")
status_indicator.setStyleSheet("color: #2ecc71; font-size: 16px;")
title_layout.addWidget(status_indicator)
title_layout.addStretch()
text_layout.addWidget(title_widget)
count_label = QLabel(count)
count_label.setStyleSheet("color: #34495e;")
text_layout.addWidget(count_label)
stat_layout.addWidget(text_widget, stretch=1)
stat_widget.setStyleSheet("""
QWidget {
background-color: transparent;
border-radius: 10px;
}
""")
grid_layout.addWidget(stat_widget, row, col)
def go_to_install(self):
install_page = self.page_stack.findChild(InstallSystemPackage)
install_page.configure(package_name='all', distro='debian')
self.page_stack.setCurrentIndex(self.page_stack.indexOf(install_page))
class ProtocolPage(Page): class ProtocolPage(Page):
def __init__(self, page_stack, main_window=None, parent=None): def __init__(self, page_stack, main_window=None, parent=None):
super().__init__("Protocol", page_stack,main_window, parent) super().__init__("Protocol", page_stack,main_window, parent)
@ -2538,8 +2476,7 @@ class ProtocolPage(Page):
for j, (object_type,icon_name, page_class, geometry) in enumerate([ for j, (object_type,icon_name, page_class, geometry) in enumerate([
(QPushButton,"wireguard", WireGuardPage, (585, 90,185,75)), (QPushButton,"wireguard", WireGuardPage, (585, 90,185,75)),
(QPushButton,"residential", ResidentialPage, (585, 90+30+75,185,75)), (QPushButton,"residential", ResidentialPage, (585, 90+30+75,185,75)),
(QPushButton,"hidetor", HidetorPage, (585, 90+30+75+30+75,185,75)), (QPushButton,"hidetor", HidetorPage, (585, 90+30+75+30+75,185,75))
(QPushButton,"open", LocationPage, (585, 90+30+75+30+75+30+75,185,75))
]): ]):
boton = object_type(self) boton = object_type(self)
boton.setGeometry(*geometry) boton.setGeometry(*geometry)
@ -2559,6 +2496,7 @@ class ProtocolPage(Page):
self.update_status.write_data({"protocol": self.selected_protocol_icon}) self.update_status.write_data({"protocol": self.selected_protocol_icon})
def show_protocol(self, page_class, protocol): def show_protocol(self, page_class, protocol):
self.update_status.clear_data()
self.display.setPixmap(QPixmap(os.path.join(self.btn_path, f"{protocol}.png")).scaled(self.display.size(), Qt.AspectRatioMode.KeepAspectRatio)) self.display.setPixmap(QPixmap(os.path.join(self.btn_path, f"{protocol}.png")).scaled(self.display.size(), Qt.AspectRatioMode.KeepAspectRatio))
self.selected_protocol_icon = protocol self.selected_protocol_icon = protocol
self.selected_page_class = page_class self.selected_page_class = page_class
@ -2767,7 +2705,7 @@ class HidetorPage(Page):
boton.setVisible(False) boton.setVisible(False)
boton.setIcon(QIcon(os.path.join(self.btn_path, f"button_{icon_name}.png"))) boton.setIcon(QIcon(os.path.join(self.btn_path, f"button_{icon_name}.png")))
if boton.icon().isNull(): if boton.icon().isNull():
boton.setPixmap(QPixmap(os.path.join(self.btn_path, "default_location_button.png"))) boton.setIcon(QIcon(os.path.join(self.btn_path, "default_location_button.png")))
self.buttons.append(boton) self.buttons.append(boton)
self.buttonGroup.addButton(boton, j) self.buttonGroup.addButton(boton, j)
boton.clicked.connect(lambda _, location=icon_name: self.show_location(location)) boton.clicked.connect(lambda _, location=icon_name: self.show_location(location))
@ -3075,7 +3013,7 @@ class LocationPage(Page):
def show_location(self, location): def show_location(self, location):
self.initial_display.hide() self.initial_display.hide()
self.display.setPixmap(QPixmap(os.path.join(self.btn_path, f"icon_{location}.png")).scaled(self.display.size(), Qt.AspectRatioMode.KeepAspectRatio)) self.display.setPixmap(QPixmap(os.path.join(self.btn_path, f"icon_{location}.png")).scaled(self.display.size(), Qt.AspectRatioMode.KeepAspectRatio))
self.selected_location_icon = location self.selected_location_icon = location
self.button_next.setVisible(True) self.button_next.setVisible(True)
@ -3356,7 +3294,7 @@ class ResumePage(Page):
def create_interface_elements(self): def create_interface_elements(self):
for j, (object_type, icon_name, geometry) in enumerate([ for j, (object_type, icon_name, geometry) in enumerate([
(QLineEdit, None, (130, 70, 300, 30)), (QLineEdit, None, (130, 73, 300, 24)),
(QLabel, None, (0,0,0,0)) (QLabel, None, (0,0,0,0))
]): ]):
@ -3373,8 +3311,8 @@ class ResumePage(Page):
self.line_edit.setGeometry(*geometry) self.line_edit.setGeometry(*geometry)
self.line_edit.setMaxLength(13) self.line_edit.setMaxLength(13)
self.line_edit.textChanged.connect(self.toggle_button_visibility) self.line_edit.textChanged.connect(self.toggle_button_visibility)
self.line_edit.setStyleSheet("background-color: rgba(22, 10, 30, 0.5);") self.line_edit.setStyleSheet("background-color: transparent; border: none; color: cyan;")
self.line_edit.setPlaceholderText("Type a name here") self.line_edit.setPlaceholderText("Enter profile name")
self.line_edit.setAlignment(Qt.AlignmentFlag.AlignCenter) self.line_edit.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.create() self.create()
@ -3644,13 +3582,14 @@ class EditorPage(Page):
self.button_back.clicked.connect(self.go_back) self.button_back.clicked.connect(self.go_back)
self.name_handle = QLabel(self) self.name_handle = QLabel(self)
self.name_handle.setGeometry(125, 70, 400, 30) self.name_handle.setGeometry(134, 70, 400, 30)
self.name_handle.setStyleSheet('color: #cacbcb;')
self.name_handle.setText("Profile Name:") self.name_handle.setText("Profile Name:")
self.name = QLineEdit(self) self.name = QLineEdit(self)
self.name.setGeometry(275, 70, 400, 30) self.name.setGeometry(288, 70, 190, 30)
self.name.setStyleSheet("border: transparent;") self.name.setStyleSheet("color: cyan; border: transparent;")
self.temp_changes = {} self.temp_changes = {}
self.original_values = {} self.original_values = {}
@ -4144,7 +4083,7 @@ class Settings(Page):
border: none; border: none;
background: transparent; background: transparent;
color: #808080; color: #808080;
font-size: 15px; font-size: 14px;
{self.font_style} {self.font_style}
}} }}
QPushButton:checked {{ QPushButton:checked {{
@ -4477,7 +4416,7 @@ class Settings(Page):
value_label = ClickableValueLabel("N/A", stat_widget) value_label = ClickableValueLabel("N/A", stat_widget)
value_label.setObjectName("value_label") value_label.setObjectName("value_label")
value_label.setStyleSheet(f"color: #00ffff; font-size: 13px; font-weight: bold; {self.font_style}") value_label.setStyleSheet(f"color: #00ffff; font-size: 12px; font-family: 'Retro Gaming', sans-serif;")
value_label.setAlignment(Qt.AlignmentFlag.AlignCenter) value_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
stat_widget.layout().insertWidget(0, value_label) stat_widget.layout().insertWidget(0, value_label)
@ -4639,15 +4578,21 @@ class Settings(Page):
layout.setSpacing(10) layout.setSpacing(10)
config_path = Constants.HV_CONFIG_HOME config_path = Constants.HV_CONFIG_HOME
current_connection = self.update_status.get_current_connection();
if current_connection is not None:
current_connection = current_connection.capitalize()
stats = [ stats = [
("Config Path", config_path), ("Config Path", config_path),
("Client Version", Constants.HV_CLIENT_VERSION_NUMBER), ("Client Version", Constants.HV_CLIENT_VERSION_NUMBER),
("Connection", self.update_status.get_current_connection()), ("Connection", current_connection),
] ]
for i, (label, value) in enumerate(stats): for i, (label, value) in enumerate(stats):
info_widget = QLabel(f"{label}: {value}") info_widget = QLabel(f"{label}: {value}")
info_widget.setStyleSheet(f"color: white; padding: 5px; {self.font_style}") info_widget.setStyleSheet(f"font-size: 14px; color: white; padding: 5px; {self.font_style}")
info_widget.setWordWrap(True) info_widget.setWordWrap(True)
layout.addWidget(info_widget, i, 0) layout.addWidget(info_widget, i, 0)
@ -4667,7 +4612,7 @@ class Settings(Page):
value_label = QLabel(str(value)) value_label = QLabel(str(value))
value_label.setObjectName("value_label") value_label.setObjectName("value_label")
value_label.setStyleSheet("color: #00ffff; font-size: 24px; font-weight: bold") value_label.setStyleSheet("font-family: 'Retro Gaming', sans-serif; color: #00ffff; font-size: 22px; font-weight: bold")
value_label.setAlignment(Qt.AlignmentFlag.AlignCenter) value_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
desc_label = QLabel(label) desc_label = QLabel(label)
@ -4744,7 +4689,7 @@ class Settings(Page):
title.setStyleSheet(f"color: #808080; font-size: 12px; font-weight: bold; {self.font_style}") title.setStyleSheet(f"color: #808080; font-size: 12px; font-weight: bold; {self.font_style}")
layout.addWidget(title) layout.addWidget(title)
log_text = QLabel(f"If enabled, these Error Logs would be stored locally on your computer\nat {Constants.HV_DATA_HOME}/gui") log_text = QLabel(f"Enabling this feature means error logs will be stored on your local\nmachine at: '{Constants.HV_CACHE_HOME}/gui'.")
log_text.setStyleSheet(f"color: white; font-size: 14px; {self.font_style}") log_text.setStyleSheet(f"color: white; font-size: 14px; {self.font_style}")
layout.addWidget(log_text) layout.addWidget(log_text)
@ -4818,7 +4763,7 @@ class IdPage(Page):
self.btn_path = main_window.btn_path self.btn_path = main_window.btn_path
self.buttonGroup = QButtonGroup(self) self.buttonGroup = QButtonGroup(self)
self.display.setGeometry(QtCore.QRect(-10, 50, 550, 460)) self.display.setGeometry(QtCore.QRect(-10, 50, 550, 460))
self.display.setPixmap(QPixmap(os.path.join(self.btn_path, "wireguardx.png")).scaled(self.display.size(), Qt.AspectRatioMode.KeepAspectRatio)) # self.display.setPixmap(QPixmap(os.path.join(self.btn_path, "wireguardx.png")).scaled(self.display.size(), Qt.AspectRatioMode.KeepAspectRatio))
self.create_interface_elements() self.create_interface_elements()
@ -5336,7 +5281,7 @@ class PaymentConfirmed(Page):
self.update_status = main_window self.update_status = main_window
self.buttonGroup = QButtonGroup(self) self.buttonGroup = QButtonGroup(self)
self.display.setGeometry(QRect(-10, 50, 550, 460)) self.display.setGeometry(QRect(-10, 50, 550, 460))
self.display.setPixmap(QPixmap(os.path.join(self.btn_path, f"wireguardx.png")).scaled(self.display.size(), Qt.AspectRatioMode.KeepAspectRatio)) # self.display.setPixmap(QPixmap(os.path.join(self.btn_path, f"wireguardx.png")).scaled(self.display.size(), Qt.AspectRatioMode.KeepAspectRatio))
self.button_reverse.setVisible(False) self.button_reverse.setVisible(False)
@ -5652,7 +5597,7 @@ class SyncScreen(Page):
def perform_sync(self): def perform_sync(self):
self.button_go.setEnabled(False) self.button_go.setEnabled(False)
self.button_back.setEnabled(False) self.button_back.setEnabled(False)
self.update_status.update_status('Syncing in progress...') self.update_status.update_status('Sync in progress...')
if self.main_window.get_current_connection() == 'tor': if self.main_window.get_current_connection() == 'tor':
self.worker_thread = WorkerThread('SYNC_TOR') self.worker_thread = WorkerThread('SYNC_TOR')
else: else:
@ -5754,7 +5699,7 @@ class WelcomePage(Page):
self._setup_stats_display() self._setup_stats_display()
def _setup_welcome_ui(self): def _setup_welcome_ui(self):
welcome_title = QLabel("Welcome to HydraVeilVPN", self) welcome_title = QLabel('Welcome to HydraVeil', self)
welcome_title.setGeometry(20, 45, 760, 60) welcome_title.setGeometry(20, 45, 760, 60)
welcome_title.setStyleSheet(""" welcome_title.setStyleSheet("""
font-size: 32px; font-size: 32px;
@ -5836,7 +5781,7 @@ class WelcomePage(Page):
text_layout.addWidget(title_widget) text_layout.addWidget(title_widget)
count_label = QLabel(count) count_label = QLabel(count)
count_label.setStyleSheet("color: #34495e;") count_label.setStyleSheet("font-size: 16px; color: #34495e;")
text_layout.addWidget(count_label) text_layout.addWidget(count_label)
stat_layout.addWidget(text_widget, stretch=1) stat_layout.addWidget(text_widget, stretch=1)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 985 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1,012 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 1,000 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 831 B

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 999 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 474 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 624 B

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 510 B

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 632 KiB

After

Width:  |  Height:  |  Size: 517 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 429 KiB

After

Width:  |  Height:  |  Size: 325 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 453 B

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 822 B

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 962 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 962 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 547 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 821 B

After

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 797 B

After

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 826 B

After

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 841 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 717 B

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 831 B

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 774 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 802 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 808 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 996 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Some files were not shown because too many files have changed in this diff Show more