diff --git a/gui/__main__.py b/gui/__main__.py index 0bc6e4f..1fca2fa 100644 --- a/gui/__main__.py +++ b/gui/__main__.py @@ -1,5 +1,5 @@ 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 -from PyQt6.QtGui import QIcon, QPixmap,QIcon, QPixmap, QTransform, QPainter, QColor, QFont +from PyQt6.QtGui import QIcon, QPixmap,QIcon, QPixmap, QTransform, QPainter, QColor, QFont, QPen from PyQt6 import QtGui from PyQt6 import QtCore from PyQt6.QtCore import Qt,QSize,QThread,pyqtSignal, QTimer, QPointF, QRect, QMutex, QMutexLocker, QObject @@ -12,7 +12,7 @@ import traceback import random import subprocess from typing import Union -from core.Errors import CommandNotFoundError, MissingSubscriptionError, InvalidSubscriptionError, ProfileActivationError, UnsupportedApplicationVersionError, FileIntegrityError, ProfileModificationError, ProfileStateConflictError +from core.Errors import UnknownConnectionTypeError, CommandNotFoundError, MissingSubscriptionError, InvalidSubscriptionError, ProfileActivationError, UnsupportedApplicationVersionError, FileIntegrityError, ProfileModificationError, ProfileStateConflictError from core.controllers.ApplicationVersionController import ApplicationVersionController from core.controllers.ApplicationController import ApplicationController from core.controllers.ClientController import ClientController @@ -77,10 +77,8 @@ class WorkerThread(QThread): self.get_subscription() elif self.action == 'DISABLE_PROFILE': self.disable_profile() - elif self.action == 'SYNC': + elif self.action == 'SYNC' or self.action == 'SYNC_TOR': self.sync() - elif self.action == 'SYNC_TOR': - self.tor_sync() elif self.action == 'GET_CONNECTION': self.get_connection() elif self.action == 'SET_CONNECTION': @@ -116,7 +114,7 @@ class WorkerThread(QThread): def download_update(self): self.text_output.emit("Starting update process...") - ClientController.__update(client_observer=client_observer) + ClientController.update(client_observer=client_observer) client_observer.subscribe('update_progressing', lambda event: self.text_output.emit(f"Downloading: {event.meta.get('progress'):.1f}%")) client_observer.subscribe('updated', lambda event: self.text_output.emit("Update process completed")) @@ -230,7 +228,10 @@ class WorkerThread(QThread): def sync(self): try: - ConfigurationController.set_connection('system') + if self.action == 'SYNC_TOR': + ConfigurationController.set_connection('tor') + else: + ConfigurationController.set_connection('system') ClientController.sync(client_observer=client_observer, connection_observer=connection_observer) locations = LocationController.get_all() print(locations) @@ -240,18 +241,6 @@ class WorkerThread(QThread): print(e) self.sync_output.emit([], False, False, [], False) - def tor_sync(self): - try: - ConfigurationController.set_connection('tor') - self.text_output.emit('Syncing in progress...') - ClientController.sync(client_observer=client_observer, connection_observer=connection_observer) - locations = LocationController.get_all() - all_location_codes = [location.country_name for location in locations] - self.sync_output.emit(all_location_codes, True, True, locations, False) - except ConnectionError: - self.sync_output.emit([], False, False, [], False) - except CommandNotFoundError: - self.sync_output.emit([], False, False, [], True) def get_connection(self): @@ -336,8 +325,11 @@ class CustomWindow(QMainWindow): self.is_downloading = False self.current_profile_id = None self.connection_manager = ConnectionManager() - - current_connection = ConfigurationController.get_connection() + + current_connection = self.get_current_connection() + if current_connection is None: + ConfigurationController.set_connection('system') + current_connection = 'system' self.is_tor_mode = current_connection == 'tor' self.is_animating = False self.animation_step = 0 @@ -416,6 +408,13 @@ class CustomWindow(QMainWindow): self.check_logging() self.init_ui() + + def get_current_connection(self): + try: + return ConfigurationController.get_connection() + except UnknownConnectionTypeError: + return None + def _setup_gui_directory(self): os.makedirs(self.gui_dir, exist_ok=True) @@ -739,26 +738,24 @@ class CustomWindow(QMainWindow): self.menu_page = MenuPage(self.page_stack, self) self.editor_page = EditorPage(self.page_stack, self) self.pages = [MenuPage(self.page_stack, self), - ProtocolPage(self.page_stack, self), - WireGuardPage(self.page_stack, self), - ResidentialPage(self.page_stack, self), - HidetorPage(self.page_stack, self), - lokinetPage(self.page_stack, self), - OpenPage(self.page_stack, self), - TorPage(self.page_stack, self), - TorLocationPage(self.page_stack, self), - PaymentPage(self.page_stack, self), - LocationPage(self.page_stack, self), - BrowserPage(self.page_stack, self), - ScreenPage(self.page_stack, self), - ResumePage(self.page_stack, self), - IdPage(self.page_stack, self), - InstallSystemPackage(self.page_stack, self), - WelcomePage(self.page_stack, self), - PaymentConfirmed(self.page_stack, self), - EditorPage(self.page_stack, self), - Settings(self.page_stack, self), - ConnectionPage(self.page_stack, self)] + ProtocolPage(self.page_stack, self), + LocationPage(self.page_stack, self), + BrowserPage(self.page_stack, self), + ScreenPage(self.page_stack, self), + ResumePage(self.page_stack, self), + WireGuardPage(self.page_stack, self), + ResidentialPage(self.page_stack, self), + HidetorPage(self.page_stack, self), + InstallSystemPackage(self.page_stack, self), + WelcomePage(self.page_stack, self), + PaymentPage(self.page_stack, self), + PaymentConfirmed(self.page_stack, self), + IdPage(self.page_stack, self), + TorPage(self.page_stack, self), + EditorPage(self.page_stack, self), + Settings(self.page_stack, self), + ConnectionPage(self.page_stack, self), + SyncScreen(self.page_stack, self)] for page in self.pages: self.page_stack.addWidget(page) # Conectar la señal currentChanged al método page_changed @@ -801,7 +798,7 @@ class CustomWindow(QMainWindow): self.disable_marquee() def check_first_launch(self): - config_file = os.path.join(Constants.HV_CONFIG_HOME, '.first_launch') + config_file = os.path.join(self.gui_dir, "first_launch.txt") os.makedirs(Constants.HV_CONFIG_HOME, exist_ok=True) @@ -875,9 +872,7 @@ class CustomWindow(QMainWindow): elif isinstance(current_page, ResumePage): self.update_status('Choose a name for your profile') current_page.eliminacion() - elif isinstance(current_page, ProtocolPage): - if not self.connection_manager.is_synced(): - self.update_status('Choose a sync method') + elif isinstance(current_page, IdPage): pass elif isinstance(current_page, LocationPage): @@ -1026,8 +1021,6 @@ class Worker(QObject): self.update_signal.emit("Application version file integrity could not be verified.", False, None, None, None) except ProfileModificationError: self.update_signal.emit("WireGuard configuration could not be attached.", False, None, None, None) - #except OSError: - # self.update_signal.emit("Connection could not be established.", False, None, None, None) except ProfileStateConflictError: self.update_signal.emit("The profile is already being enabled...", False, None, None, None) except CommandNotFoundError as e : @@ -1111,79 +1104,23 @@ class MenuPage(Page): self.is_system_connected = False self.profile_button_map = {} - self.update_button = QPushButton(self) - self.update_button.setGeometry(750, 530, 25, 25) - self.update_button.setObjectName("update_button") - update_icon = QtGui.QIcon(os.path.join(self.btn_path, "available-updates.png")) - self.update_button.setIcon(update_icon) - self.update_button.setIconSize(self.update_button.size()) - self.update_button.clicked.connect(self.check_updates) #self.label.setStyleSheet("background-color: rgba(0, 255, 0, 51);") self.create_interface_elements() # Establecer el color de fondo y el color del texto utilizando hojas de estilo - - - - def check_updates(self): - self.update_status.update_status("Checking for updates...") - self.worker = WorkerThread('CHECK_FOR_UPDATE') - self.worker.text_output.connect(self.update_status.update_status) - self.worker.finished.connect(self.on_update_check_finished) - self.worker.start() - - def on_update_check_finished(self, result): - if result: + def on_update_check_finished(self): reply = QMessageBox.question(self, 'Update Available', 'An update is available. Would you like to download it?', QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No) if reply == QMessageBox.StandardButton.Yes: self.worker = WorkerThread('DOWNLOAD_UPDATE') - self.worker.text_output.connect(self.update_status.update_status) - self.worker.update_finished.connect(self.on_update_download_finished) self.worker.start() else: self.update_status.update_status("Update cancelled by user.") - else: - self.update_status.update_status("No updates available.") - def on_update_download_finished(self, result: dict): - if result["status"] and result["path"]: - self.countdown_timer = QTimer() - self.countdown_timer.setInterval(1000) - self.countdown_seconds = 3 - self.new_app_path = result["path"] - - def update_countdown(): - if self.countdown_seconds > 0: - self.update_status.update_status(f"New version downloaded. Restarting in {self.countdown_seconds} second{'s' if self.countdown_seconds > 1 else ''}...") - self.countdown_seconds -= 1 - else: - self.countdown_timer.stop() - self.restart_application() - - def restart_application(): - QApplication.quit() - current_app = Constants.APPIMAGE_PATH - - if os.path.exists(self.new_app_path): - try: - os.remove(current_app) - os.execv(self.new_app_path, [self.new_app_path] + sys.argv[1:]) - except PermissionError: - self.update_status.update_status(f"Permission denied: Unable to remove {current_app}") - else: - self.update_status.update_status(f"Error: New application not found at {self.new_app_path}") - - self.restart_application = restart_application - self.countdown_timer.timeout.connect(update_countdown) - self.countdown_timer.start() - - atexit.register(restart_application) - else: - self.update_status.update_status("Failed to download update.") + def create_interface_elements(self): for icon_name, function, position in [ @@ -1579,11 +1516,6 @@ class MenuPage(Page): editar_profile = {"profile_number": profile_number, "name": name, "protocol": protocol} self.page_stack.currentWidget().add_selected_profile(editar_profile) - - - - - def launch(self): pass @@ -1648,7 +1580,10 @@ class MenuPage(Page): if len(self.profile_info) == 6: self.update_status.update_status('Maximum number of profiles reached!') return - self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(ProtocolPage))) + if not self.connection_manager.is_synced(): + self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(SyncScreen))) + else: + self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(ProtocolPage))) @@ -2517,138 +2452,12 @@ class ProtocolPage(Page): self.coming_soon_label.setGeometry(210, 50, 200, 40) self.coming_soon_label.setStyleSheet("font-size: 22px;") - self.sync_label = QLabel("Sync finds out what plans, countries, \n& browsers are available", self) - self.sync_label.setGeometry(100, 120,500,60) - self.sync_label.setStyleSheet("font-size: 20px;") - - self.button_sync = QPushButton(self) - self.button_sync.setObjectName("sync_button") - self.button_sync.setGeometry(100, 250,150,60) - self.button_sync.setIconSize(self.button_sync.size()) - icon = QIcon(os.path.join(self.btn_path, "sync_button.png")) - self.button_sync.setIcon(icon) - self.button_sync.clicked.connect(self.handle_core_action_sync_button) - - self.tor_button_sync = QPushButton(self) - self.tor_button_sync.setObjectName("tor_sync") - self.tor_button_sync.setGeometry(300, 250,150,60) - self.tor_button_sync.setIconSize(self.tor_button_sync.size()) - tor_icon = QIcon(os.path.join(self.btn_path, "tor_sync.png")) - self.tor_button_sync.setIcon(tor_icon) - self.tor_button_sync.clicked.connect(lambda: self.handle_core_action_sync_button(True)) - - self.button_sync.setVisible(True) - self.tor_button_sync.setVisible(True) - - self.coming_soon_label.setVisible(False) self.title.setGeometry(585, 40, 185, 40); self.title.setText("Pick a Protocol") self.display.setGeometry(QtCore.QRect(0, 50, 580, 435))#relacion 4:3 self.create_interface_elements() - def sync_button(self, toggle: bool, sync_complete: bool=False): - self.button_sync.setDisabled(toggle) - self.tor_button_sync.setDisabled(toggle) - - - if sync_complete: - for button in self.buttons: - button.setDisabled(toggle) - self.button_sync.setVisible(False) - self.tor_button_sync.setVisible(False) - self.sync_label.setVisible(False) - - def handle_core_action_sync_button(self, tor: bool = False): - self.sync_button(True) - - if tor: - self.main_window.set_toggle_state(True) - self.sync_button(True) - self.update_status.update_status('Syncing through Tor in progress...') - self.worker_thread = WorkerThread('SYNC_TOR') - self.worker_thread.sync_output.connect(self.update_output) - self.worker_thread.text_output.connect(self.update_text_output) - self.worker_thread.start() - return - - self.update_status.update_status('Syncing in progress...') - self.worker_thread = WorkerThread('SYNC') - self.worker_thread.sync_output.connect(self.update_output) - self.worker_thread.start() - - - def update_text_output(self, text): - self.update_status.update_status(text) - - def update_output(self, available_locations, status, is_tor, locations, is_os_error): - if is_os_error: - install_page = self.page_stack.findChild(InstallSystemPackage) - install_page.configure(package_name='tor', distro='debian', is_sync=True) - self.page_stack.setCurrentIndex(self.page_stack.indexOf(install_page)) - self.sync_button(False) - return - - if status is False: - self.sync_button(False) - self.update_status.update_status('An error occurred during sync') - return - - - - - self.update_status.update_status('Sync complete') - self.connection_manager.set_synced(True) - - available_locations_list = [] - self.connection_manager.store_locations(locations) - - grid_positions = [ - (395, 90, 185, 75), - (585, 90, 185, 75), - (395, 195, 185, 75), - (585, 195, 185, 75), - (395, 300, 185, 75), - (585, 300, 185, 75), - (395, 405, 185, 75), - (585, 405, 185, 75) - ] - - list1 = [] - for i, location in enumerate(available_locations): - position_index = i % len(grid_positions) - list1.append((QPushButton, location, grid_positions[position_index])) - - for item in list1: - available_locations_list.append(item) - - self.sync_button(False, True) - location_page = self.find_location_page() - hidetor_page = self.find_hidetor_page() - print(f' the available locations list is {available_locations_list}') - - if location_page: - location_page.create_interface_elements(available_locations_list) - if hidetor_page: - hidetor_page.create_interface_elements(available_locations_list) - - - - def find_location_page(self): - for i in range(self.page_stack.count()): - page = self.page_stack.widget(i) - if isinstance(page, LocationPage): - return page - return None - - def find_hidetor_page(self): - for i in range(self.page_stack.count()): - page = self.page_stack.widget(i) - if isinstance(page, HidetorPage): - return page - return None - - def create_interface_elements(self): self.buttonGroup = QButtonGroup(self) self.buttons = [] @@ -2667,6 +2476,10 @@ class ProtocolPage(Page): self.buttons.append(boton) self.buttonGroup.addButton(boton, j) boton.clicked.connect(lambda _, page=page_class, protocol=icon_name: self.show_protocol(page, protocol)) + + def enable_protocol_buttons(self): + for button in self.buttons: + button.setDisabled(False) def update_swarp_json(self): self.update_status.write_data({"protocol": self.selected_protocol_icon}) @@ -5724,6 +5537,252 @@ class ClickableValueLabel(QLabel): self.setStyleSheet(self.default_style) +class SyncScreen(Page): + def __init__(self, page_stack, main_window=None, parent=None): + super().__init__("SyncScreen", page_stack, main_window, parent) + self.main_window = main_window + self.btn_path = main_window.btn_path + self.update_status = main_window + self.connection_manager = main_window.connection_manager + self.is_tor_mode = main_window.is_tor_mode + + + + self.heading_label = QLabel("You're about to fetch data from\nSimplified Privacy.", self) + self.heading_label.setGeometry(15, 80, 750, 80) + self.heading_label.setStyleSheet("font-size: 36px; font-weight: bold; color: white;") + + self.data_description = QLabel("This data includes what plans, countries,\nbrowsers, and version upgrades are\navailable. As well as coordinating billing.", self) + self.data_description.setGeometry(22, 190, 750, 90) + self.data_description.setStyleSheet("font-size: 26px; font-weight: bold; color: #ffff00;") + + self.instructions = QLabel("Use the toggle in the bottom right to\ndecide if you want to use Tor or not.\nThen hit \"Next\"", self) + self.instructions.setGeometry(22, 345, 750, 100) + self.instructions.setStyleSheet("font-size: 30px; font-weight: bold; color: white;") + + self.arrow_label = QLabel(self) + self.arrow_label.setGeometry(520, 400, 180, 130) + arrow_pixmap = QPixmap(os.path.join(self.btn_path, "arrow-down.png")) + + self.arrow_label.setPixmap(arrow_pixmap) + self.arrow_label.raise_() + + self.button_go.setVisible(True) + self.button_back.setVisible(True) + self.button_go.clicked.connect(self.perform_sync) + self.button_back.clicked.connect(self.go_back) + + def go_back(self): + self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(MenuPage))) + + def perform_sync(self): + self.button_go.setEnabled(False) + self.button_back.setEnabled(False) + self.update_status.update_status('Syncing in progress...') + if self.main_window.get_current_connection() == 'tor': + self.worker_thread = WorkerThread('SYNC_TOR') + else: + self.worker_thread = WorkerThread('SYNC') + + self.worker_thread.sync_output.connect(self.update_output) + self.worker_thread.start() + + def update_output(self, available_locations, status, is_tor, locations, is_os_error): + if is_os_error: + install_page = self.page_stack.findChild(InstallSystemPackage) + install_page.configure(package_name='tor', distro='debian', is_sync=True) + self.page_stack.setCurrentIndex(self.page_stack.indexOf(install_page)) + self.button_go.setEnabled(True) + self.button_back.setEnabled(True) + return + + if status is False: + self.button_go.setEnabled(True) + self.button_back.setEnabled(True) + self.update_status.update_status('An error occurred during sync') + return + + self.update_status.update_status('Sync complete') + self.connection_manager.set_synced(True) + + update_available = ClientController.can_be_updated() + + if not update_available: + menu_page = self.page_stack.findChild(MenuPage) + menu_page.on_update_check_finished() + + + available_locations_list = [] + self.connection_manager.store_locations(locations) + + grid_positions = [ + (395, 90, 185, 75), + (585, 90, 185, 75), + (395, 195, 185, 75), + (585, 195, 185, 75), + (395, 300, 185, 75), + (585, 300, 185, 75), + (395, 405, 185, 75), + (585, 405, 185, 75) + ] + + list1 = [] + for i, location in enumerate(available_locations): + position_index = i % len(grid_positions) + list1.append((QPushButton, location, grid_positions[position_index])) + + for item in list1: + available_locations_list.append(item) + + location_page = self.find_location_page() + hidetor_page = self.find_hidetor_page() + protocol_page = self.find_protocol_page() + + if location_page: + location_page.create_interface_elements(available_locations_list) + if hidetor_page: + hidetor_page.create_interface_elements(available_locations_list) + if protocol_page: + protocol_page.enable_protocol_buttons() + + self.page_stack.setCurrentIndex(self.page_stack.indexOf(self.page_stack.findChild(ProtocolPage))) + + def find_location_page(self): + for i in range(self.page_stack.count()): + page = self.page_stack.widget(i) + if isinstance(page, LocationPage): + return page + return None + + def find_hidetor_page(self): + for i in range(self.page_stack.count()): + page = self.page_stack.widget(i) + if isinstance(page, HidetorPage): + return page + return None + + def find_protocol_page(self): + for i in range(self.page_stack.count()): + page = self.page_stack.widget(i) + if isinstance(page, ProtocolPage): + return page + return None + +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)) + + if __name__ == "__main__": app = QApplication(sys.argv) window = CustomWindow() diff --git a/gui/resources/images/arrow-down.png b/gui/resources/images/arrow-down.png new file mode 100644 index 0000000..86c64b5 Binary files /dev/null and b/gui/resources/images/arrow-down.png differ diff --git a/gui/resources/images/original.png b/gui/resources/images/original.png index 162b3a8..fdfbfbd 100644 Binary files a/gui/resources/images/original.png and b/gui/resources/images/original.png differ