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
gui
__main__.py
resources/images
.gitkeep1-country.png1024x1280_button.png1024x760.png1024x760_button.png1152x1080.png1152x1080_button.png1280x1024.png1280x1024_button.png1920x1080.png1920x1080_button.png400x50_button.png540x455.png800x600.png800x600_button.pngDark.pngDark2.pngDefault.pngMesa de trabajo 1.pngMesa de trabajo 10.pngMesa de trabajo 2.pngMesa de trabajo 3.pngMesa de trabajo 4.pngMesa de trabajo 8.pngUP_button.pngapp_off.pngapp_on.pngapply.pngarch.pngarrow-down.pngarrow.pngback.pngback_transparente.pngbackgoud800x600.pngbackground.pngbackground_connected.pngbackground_tormode.pngbilling_off.pngbilling_on.pngbitcoin.pngbitcoin_1year.pngbov_off.pngbov_on.pngbrave latest_mini.pngbrave_button.pngbrave_icon.pngbrowser only.pngbrowser-only.pngbrowser-only_button.pngbrowser_just_proxy.pngbrowser_tor.pngbrowsers_mini.pngbutton230x220.pngbutton_ch_zh.pngbutton_fi_01.pngbutton_is_1.pngbutton_md_cu.pngbutton_my.pngbutton_nl_li.pngbutton_profile.pngbutton_session_profile.pngbutton_session_tor.pngbutton_system_profile.pngbutton_us_oh.pngbutton_us_wa.pngcheck.pngcheck_icon.pngchromium latest_mini.pngchromium_button.pngchromium_icon.pngconfig.txtconnect.pngcreate_profile.pngcuadro150x50.pngcuadro400x50.pngdebian.pngdefault_location_button.pngdefault_location_mini.pngdelete_profile.pngdisconnect.pngdisconnect_system_wide.pngdisconnected.pngedit_profile.pngeditv.pngeeuu garaje.pngeeuu_button.pngeeuu_mini.pngfedora.pngfirefox latest_mini.pngfirefox_button.pngfirefox_icon.pngglobal-acces.pnghdtor_is_1.pnghdtor_md_cu.pnghdtor_mini_md_cu.pnghdtor_mini_nl_li.pnghdtor_mini_us_oh.pnghdtor_my_14.pnghdtor_nl_li.png

View file

@ -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
@ -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;
@ -402,30 +410,55 @@ 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)
@ -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': { 'microsocks': {
'debian': 'pkexec apt -y install tor proxychains4 microsocks', 'debian': 'pkexec apt -y install microsocks',
'arch': 'pkexec pacman -S tor proxychains4 microsocks', 'arch': 'pkexec pacman -S microsocks',
'fedora': 'pkexec dnf -y install tor proxychains4' '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."'
},
'tor_sync': {
'debian': 'pkexec apt -y install tor',
'arch': 'pkexec pacman -S tor',
'fedora': 'pkexec dnf -y install tor'
}, },
'proxychains4': { 'proxychains4': {
'debian': 'pkexec apt -y install proxychains4', 'debian': 'pkexec apt -y install proxychains4',
'arch': 'pkexec pacman -S proxychains-ng', 'arch': 'pkexec pacman -S proxychains-ng',
'fedora': 'pkexec dnf -y install proxychains4' 'fedora': 'pkexec dnf -y install proxychains4'
}, },
'microsocks': { 'ratpoison': {
'debian': 'pkexec apt -y install microsocks', 'debian': 'pkexec apt -y install ratpoison',
'arch': 'pkexec pacman -S microsocks', '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 microsocks' 'fedora': 'pkexec dnf -y install ratpoison'
}, },
'xserver-xephyr': { 'tor': {
'debian': 'pkexec apt -y install xserver-xephyr bubblewrap ratpoison', 'debian': 'pkexec apt -y install tor',
'arch': 'pkexec pacman -S xorg-server-xephyr bubblewrap ratpoison', 'arch': 'pkexec pacman -S tor',
'fedora': 'pkexec dnf -y install xorg-x11-server-Xephyr bubblewrap ratpoison' 'fedora': 'pkexec dnf -y install tor'
}, },
'bubblewrap': { 'wg-quick': {
'debian': 'pkexec apt -y install bubblewrap', 'debian': 'pkexec apt -y install wireguard',
'arch': 'pkexec pacman -S bubblewrap', 'arch': 'pkexec pacman -S wireguard-tools',
'fedora': 'pkexec dnf -y install bubblewrap' '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': { 'microsocks': {
'debian': 'sudo apt -y install resolvconf', 'debian': 'sudo apt -y install microsocks',
'arch': 'sudo pacman -S resolvconf', 'arch': 'sudo pacman -S microsocks',
'fedora': 'sudo dnf -y install resolvconf' 'fedora': '# Package not available.'
},
'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': { 'proxychains4': {
'debian': 'sudo apt -y install proxychains4', 'debian': 'sudo apt -y install proxychains4',
'arch': 'sudo pacman -S proxychains-ng', 'arch': 'sudo pacman -S proxychains-ng',
'fedora': 'sudo dnf -y install proxychains4' 'fedora': 'sudo dnf -y install proxychains4'
}, },
'microsocks': { 'ratpoison': {
'debian': 'sudo apt -y install microsocks', 'debian': 'sudo apt -y install ratpoison',
'arch': 'sudo pacman -S microsocks', 'arch': '# Package not available.',
'fedora': 'sudo dnf -y install microsocks' 'fedora': 'sudo dnf -y install ratpoison'
}, },
'xserver-xephyr': { 'tor': {
'debian': 'sudo apt -y install xserver-xephyr bubblewrap ratpoison', 'debian': 'sudo apt -y install tor',
'arch': 'sudo pacman -S xorg-server-xephyr bubblewrap ratpoison', 'arch': 'sudo pacman -S tor',
'fedora': 'sudo dnf -y install xorg-x11-server-Xephyr bubblewrap ratpoison' 'fedora': 'sudo dnf -y install tor'
}, },
'bubblewrap': { 'wg-quick': {
'debian': 'sudo apt -y install bubblewrap', 'debian': 'sudo apt -y install wireguard',
'arch': 'sudo pacman -S bubblewrap', 'arch': 'sudo pacman -S wireguard-tools',
'fedora': 'sudo dnf -y install bubblewrap' '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))
@ -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

(image error) Size: 1.9 KiB

After

(image error) Size: 985 B

Binary file not shown.

Before

(image error) Size: 2.1 KiB

After

(image error) Size: 1 KiB

Binary file not shown.

Before

(image error) Size: 41 KiB

After

(image error) Size: 12 KiB

Binary file not shown.

Before

(image error) Size: 2 KiB

After

(image error) Size: 1 KiB

Binary file not shown.

Before

(image error) Size: 41 KiB

After

(image error) Size: 12 KiB

Binary file not shown.

Before

(image error) Size: 2.1 KiB

After

(image error) Size: 1,012 B

Binary file not shown.

Before

(image error) Size: 40 KiB

After

(image error) Size: 12 KiB

Binary file not shown.

Before

(image error) Size: 2.1 KiB

After

(image error) Size: 1 KiB

Binary file not shown.

Before

(image error) Size: 40 KiB

After

(image error) Size: 7.4 KiB

Binary file not shown.

Before

(image error) Size: 2 KiB

After

(image error) Size: 1,000 B

Binary file not shown.

Before

(image error) Size: 831 B

After

(image error) Size: 429 B

Binary file not shown.

Before

(image error) Size: 8.4 KiB

After

(image error) Size: 5.5 KiB

Binary file not shown.

Before

(image error) Size: 41 KiB

After

(image error) Size: 12 KiB

Binary file not shown.

Before

(image error) Size: 1.9 KiB

After

(image error) Size: 999 B

Binary file not shown.

Before

(image error) Size: 4.4 KiB

After

(image error) Size: 1.1 KiB

Binary file not shown.

Before

(image error) Size: 7 KiB

After

(image error) Size: 3.1 KiB

Binary file not shown.

Before

(image error) Size: 242 KiB

After

(image error) Size: 194 KiB

Binary file not shown.

Before

(image error) Size: 5.9 KiB

After

(image error) Size: 2.3 KiB

Binary file not shown.

Before

(image error) Size: 96 KiB

After

(image error) Size: 75 KiB

Binary file not shown.

Before

(image error) Size: 9.4 KiB

After

(image error) Size: 5.7 KiB

Binary file not shown.

Before

(image error) Size: 6 KiB

Binary file not shown.

Before

(image error) Size: 7.5 KiB

After

(image error) Size: 3.1 KiB

Binary file not shown.

Before

(image error) Size: 4.2 KiB

After

(image error) Size: 3.6 KiB

Binary file not shown.

Before

(image error) Size: 1.1 KiB

After

(image error) Size: 474 B

Binary file not shown.

Before

(image error) Size: 624 B

After

(image error) Size: 339 B

Binary file not shown.

Before

(image error) Size: 4.1 KiB

After

(image error) Size: 3.5 KiB

Binary file not shown.

Before

(image error) Size: 60 KiB

After

(image error) Size: 40 KiB

Binary file not shown.

Before

(image error) Size: 3.1 KiB

After

(image error) Size: 2.4 KiB

Binary file not shown.

Before

(image error) Size: 12 KiB

After

(image error) Size: 9.3 KiB

Binary file not shown.

Before

(image error) Size: 510 B

After

(image error) Size: 351 B

Binary file not shown.

Before

(image error) Size: 11 KiB

After

(image error) Size: 7.9 KiB

Binary file not shown.

Before

(image error) Size: 8.6 KiB

After

(image error) Size: 6.8 KiB

Binary file not shown.

Before

(image error) Size: 172 KiB

After

(image error) Size: 124 KiB

Binary file not shown.

Before

(image error) Size: 632 KiB

After

(image error) Size: 517 KiB

Binary file not shown.

Before

(image error) Size: 429 KiB

After

(image error) Size: 325 KiB

Binary file not shown.

Before

(image error) Size: 32 KiB

Binary file not shown.

Before

(image error) Size: 453 B

After

(image error) Size: 254 B

Binary file not shown.

Before

(image error) Size: 2.5 KiB

After

(image error) Size: 2.1 KiB

Binary file not shown.

Before

(image error) Size: 3.9 KiB

After

(image error) Size: 1.6 KiB

Binary file not shown.

Before

(image error) Size: 4.4 KiB

After

(image error) Size: 2.1 KiB

Binary file not shown.

Before

(image error) Size: 822 B

After

(image error) Size: 434 B

Binary file not shown.

Before

(image error) Size: 6.3 KiB

After

(image error) Size: 5.5 KiB

Binary file not shown.

Before

(image error) Size: 2.5 KiB

After

(image error) Size: 1.7 KiB

Binary file not shown.

Before

(image error) Size: 4.8 KiB

After

(image error) Size: 2.8 KiB

Binary file not shown.

Before

(image error) Size: 27 KiB

After

(image error) Size: 15 KiB

Binary file not shown.

Before

(image error) Size: 9.1 KiB

After

(image error) Size: 6.1 KiB

Binary file not shown.

Before

(image error) Size: 1.9 KiB

After

(image error) Size: 962 B

Binary file not shown.

Before

(image error) Size: 1.9 KiB

After

(image error) Size: 962 B

Binary file not shown.

Before

(image error) Size: 22 KiB

After

(image error) Size: 13 KiB

Binary file not shown.

Before

(image error) Size: 30 KiB

After

(image error) Size: 17 KiB

Binary file not shown.

Before

(image error) Size: 3.6 KiB

After

(image error) Size: 3.3 KiB

Binary file not shown.

Before

(image error) Size: 1.5 KiB

After

(image error) Size: 622 B

Binary file not shown.

Before

(image error) Size: 7.1 KiB

After

(image error) Size: 5.2 KiB

Binary file not shown.

Before

(image error) Size: 6.6 KiB

After

(image error) Size: 4.1 KiB

Binary file not shown.

Before

(image error) Size: 7.6 KiB

After

(image error) Size: 4.8 KiB

Binary file not shown.

Before

(image error) Size: 9.3 KiB

After

(image error) Size: 8.4 KiB

Binary file not shown.

Before

(image error) Size: 8.5 KiB

After

(image error) Size: 7.1 KiB

Binary file not shown.

Before

(image error) Size: 8.8 KiB

After

(image error) Size: 7.2 KiB

Binary file not shown.

Before

(image error) Size: 1.1 KiB

After

(image error) Size: 547 B

Binary file not shown.

Before

(image error) Size: 821 B

After

(image error) Size: 433 B

Binary file not shown.

Before

(image error) Size: 797 B

After

(image error) Size: 433 B

Binary file not shown.

Before

(image error) Size: 826 B

After

(image error) Size: 433 B

Binary file not shown.

Before

(image error) Size: 7.8 KiB

After

(image error) Size: 6.2 KiB

Binary file not shown.

Before

(image error) Size: 8.6 KiB

After

(image error) Size: 6.7 KiB

Binary file not shown.

Before

(image error) Size: 3.1 KiB

After

(image error) Size: 1.7 KiB

Binary file not shown.

Before

(image error) Size: 1.5 KiB

After

(image error) Size: 1.3 KiB

Binary file not shown.

Before

(image error) Size: 2.6 KiB

After

(image error) Size: 2.2 KiB

Binary file not shown.

Before

(image error) Size: 4.6 KiB

After

(image error) Size: 3.2 KiB

Binary file not shown.

Before

(image error) Size: 19 KiB

After

(image error) Size: 9.9 KiB

Binary file not shown.

Before

(image error) Size: 48 KiB

After

(image error) Size: 31 KiB

Binary file not shown.

Before

(image error) Size: 1.7 KiB

After

(image error) Size: 841 B

Binary file not shown.

Before

(image error) Size: 717 B

After

(image error) Size: 375 B

Binary file not shown.

Before

(image error) Size: 831 B

After

(image error) Size: 429 B

Binary file not shown.

Before

(image error) Size: 3.7 KiB

After

(image error) Size: 2.9 KiB

Binary file not shown.

Before

(image error) Size: 5.6 KiB

After

(image error) Size: 4.1 KiB

Binary file not shown.

Before

(image error) Size: 2.1 KiB

After

(image error) Size: 2 KiB

Binary file not shown.

Before

(image error) Size: 4.9 KiB

After

(image error) Size: 2.2 KiB

Binary file not shown.

Before

(image error) Size: 4.5 KiB

After

(image error) Size: 1.8 KiB

Binary file not shown.

Before

(image error) Size: 4.5 KiB

After

(image error) Size: 1.8 KiB

Binary file not shown.

Before

(image error) Size: 1.5 KiB

After

(image error) Size: 774 B

Binary file not shown.

Before

(image error) Size: 1.6 KiB

After

(image error) Size: 802 B

Binary file not shown.

Before

(image error) Size: 1.7 KiB

After

(image error) Size: 808 B

Binary file not shown.

Before

(image error) Size: 22 KiB

After

(image error) Size: 16 KiB

Binary file not shown.

Before

(image error) Size: 4.2 KiB

After

(image error) Size: 2.1 KiB

Binary file not shown.

Before

(image error) Size: 2.2 KiB

After

(image error) Size: 1.1 KiB

Binary file not shown.

Before

(image error) Size: 3.7 KiB

After

(image error) Size: 2.8 KiB

Binary file not shown.

Before

(image error) Size: 3.9 KiB

After

(image error) Size: 3.8 KiB

Binary file not shown.

Before

(image error) Size: 6.4 KiB

After

(image error) Size: 5.5 KiB

Binary file not shown.

Before

(image error) Size: 74 KiB

After

(image error) Size: 52 KiB

Binary file not shown.

Before

(image error) Size: 1.9 KiB

After

(image error) Size: 996 B

Binary file not shown.

Before

(image error) Size: 158 KiB

After

(image error) Size: 117 KiB

Binary file not shown.

Before

(image error) Size: 165 KiB

After

(image error) Size: 140 KiB

Binary file not shown.

Before

(image error) Size: 4.4 KiB

After

(image error) Size: 3.6 KiB

Binary file not shown.

Before

(image error) Size: 4.4 KiB

After

(image error) Size: 3.7 KiB

Binary file not shown.

Before

(image error) Size: 4.4 KiB

After

(image error) Size: 3.6 KiB

Binary file not shown.

Before

(image error) Size: 188 KiB

After

(image error) Size: 162 KiB

Binary file not shown.

Before

(image error) Size: 160 KiB

After

(image error) Size: 134 KiB

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