From 9d5a2460b1c72872dd5c87bf8950952c734dafcc Mon Sep 17 00:00:00 2001 From: oop7 <110548351+oop7@users.noreply.github.com> Date: Fri, 14 Nov 2025 18:44:40 +0200 Subject: [PATCH] Add Deno version check and update UI Introduces a Deno version checker and updater section to the updater tab, with localized strings in all supported languages. Adds backend functions for fetching the latest Deno version, comparing versions, and upgrading Deno, along with corresponding GUI logic for checking and updating Deno from the interface. --- languages/ar.json | 17 ++ languages/de.json | 17 ++ languages/en.json | 17 ++ languages/es.json | 17 ++ languages/fr.json | 17 ++ languages/hi.json | 17 ++ languages/id.json | 17 ++ languages/it.json | 17 ++ languages/ja.json | 17 ++ languages/pl.json | 17 ++ languages/pt.json | 17 ++ languages/ru.json | 17 ++ languages/tr.json | 17 ++ languages/zh.json | 17 ++ src/core/ytsage_deno.py | 147 ++++++++++++ .../ytsage_dialogs_updater.py | 224 ++++++++++++++++++ 16 files changed, 609 insertions(+) diff --git a/languages/ar.json b/languages/ar.json index 8ddb6fc..219b56c 100644 --- a/languages/ar.json +++ b/languages/ar.json @@ -503,5 +503,22 @@ "verification_failed": "SHA256 verification failed. The downloaded file may be corrupted or tampered with.", "setup_failed": "Failed to set up Deno. Some features may not work correctly.", "setup_error": "Setup Error" + }, + "deno_updater": { + "title": "Deno Version Checker & Updater", + "description": "Check your Deno version and update to the latest release.", + "current_version": "Current Version:", + "latest_version": "Latest Version:", + "status_idle": "Click 'Check for Updates' to get started", + "status_checking": "🔄 Checking for updates...", + "status_up_to_date": "✓ Up to date", + "status_update_available": "⚠ Update available", + "status_not_installed": "✗ Not installed", + "check_updates": "Check for Updates", + "update_now": "Update Deno", + "updating": "🔄 Updating Deno...", + "update_success": "✅ Deno has been successfully updated!", + "update_failed": "❌ Update failed: {error}", + "check_failed": "Failed to check for updates. Please check your internet connection." } } \ No newline at end of file diff --git a/languages/de.json b/languages/de.json index e2c064e..87bd810 100644 --- a/languages/de.json +++ b/languages/de.json @@ -503,5 +503,22 @@ "verification_failed": "SHA256 verification failed. The downloaded file may be corrupted or tampered with.", "setup_failed": "Failed to set up Deno. Some features may not work correctly.", "setup_error": "Setup Error" + }, + "deno_updater": { + "title": "Deno Version Checker & Updater", + "description": "Check your Deno version and update to the latest release.", + "current_version": "Current Version:", + "latest_version": "Latest Version:", + "status_idle": "Click 'Check for Updates' to get started", + "status_checking": "🔄 Checking for updates...", + "status_up_to_date": "✓ Up to date", + "status_update_available": "⚠ Update available", + "status_not_installed": "✗ Not installed", + "check_updates": "Check for Updates", + "update_now": "Update Deno", + "updating": "🔄 Updating Deno...", + "update_success": "✅ Deno has been successfully updated!", + "update_failed": "❌ Update failed: {error}", + "check_failed": "Failed to check for updates. Please check your internet connection." } } \ No newline at end of file diff --git a/languages/en.json b/languages/en.json index 9ce6965..cc0a24c 100644 --- a/languages/en.json +++ b/languages/en.json @@ -503,5 +503,22 @@ "verification_failed": "SHA256 verification failed. The downloaded file may be corrupted or tampered with.", "setup_failed": "Failed to set up Deno. Some features may not work correctly.", "setup_error": "Setup Error" + }, + "deno_updater": { + "title": "Deno Version Checker & Updater", + "description": "Check your Deno version and update to the latest release.", + "current_version": "Current Version:", + "latest_version": "Latest Version:", + "status_idle": "Click 'Check for Updates' to get started", + "status_checking": "🔄 Checking for updates...", + "status_up_to_date": "✓ Up to date", + "status_update_available": "⚠ Update available", + "status_not_installed": "✗ Not installed", + "check_updates": "Check for Updates", + "update_now": "Update Deno", + "updating": "🔄 Updating Deno...", + "update_success": "✅ Deno has been successfully updated!", + "update_failed": "❌ Update failed: {error}", + "check_failed": "Failed to check for updates. Please check your internet connection." } } \ No newline at end of file diff --git a/languages/es.json b/languages/es.json index 3bbd6bf..88c2627 100644 --- a/languages/es.json +++ b/languages/es.json @@ -486,5 +486,22 @@ "verification_failed": "SHA256 verification failed. The downloaded file may be corrupted or tampered with.", "setup_failed": "Failed to set up Deno. Some features may not work correctly.", "setup_error": "Setup Error" + }, + "deno_updater": { + "title": "Deno Version Checker & Updater", + "description": "Check your Deno version and update to the latest release.", + "current_version": "Current Version:", + "latest_version": "Latest Version:", + "status_idle": "Click 'Check for Updates' to get started", + "status_checking": "🔄 Checking for updates...", + "status_up_to_date": "✓ Up to date", + "status_update_available": "⚠ Update available", + "status_not_installed": "✗ Not installed", + "check_updates": "Check for Updates", + "update_now": "Update Deno", + "updating": "🔄 Updating Deno...", + "update_success": "✅ Deno has been successfully updated!", + "update_failed": "❌ Update failed: {error}", + "check_failed": "Failed to check for updates. Please check your internet connection." } } \ No newline at end of file diff --git a/languages/fr.json b/languages/fr.json index 41679e5..6546a71 100644 --- a/languages/fr.json +++ b/languages/fr.json @@ -503,5 +503,22 @@ "verification_failed": "SHA256 verification failed. The downloaded file may be corrupted or tampered with.", "setup_failed": "Failed to set up Deno. Some features may not work correctly.", "setup_error": "Setup Error" + }, + "deno_updater": { + "title": "Deno Version Checker & Updater", + "description": "Check your Deno version and update to the latest release.", + "current_version": "Current Version:", + "latest_version": "Latest Version:", + "status_idle": "Click 'Check for Updates' to get started", + "status_checking": "🔄 Checking for updates...", + "status_up_to_date": "✓ Up to date", + "status_update_available": "⚠ Update available", + "status_not_installed": "✗ Not installed", + "check_updates": "Check for Updates", + "update_now": "Update Deno", + "updating": "🔄 Updating Deno...", + "update_success": "✅ Deno has been successfully updated!", + "update_failed": "❌ Update failed: {error}", + "check_failed": "Failed to check for updates. Please check your internet connection." } } \ No newline at end of file diff --git a/languages/hi.json b/languages/hi.json index e7de12a..858980d 100644 --- a/languages/hi.json +++ b/languages/hi.json @@ -503,5 +503,22 @@ "verification_failed": "SHA256 verification failed. The downloaded file may be corrupted or tampered with.", "setup_failed": "Failed to set up Deno. Some features may not work correctly.", "setup_error": "Setup Error" + }, + "deno_updater": { + "title": "Deno Version Checker & Updater", + "description": "Check your Deno version and update to the latest release.", + "current_version": "Current Version:", + "latest_version": "Latest Version:", + "status_idle": "Click 'Check for Updates' to get started", + "status_checking": "🔄 Checking for updates...", + "status_up_to_date": "✓ Up to date", + "status_update_available": "⚠ Update available", + "status_not_installed": "✗ Not installed", + "check_updates": "Check for Updates", + "update_now": "Update Deno", + "updating": "🔄 Updating Deno...", + "update_success": "✅ Deno has been successfully updated!", + "update_failed": "❌ Update failed: {error}", + "check_failed": "Failed to check for updates. Please check your internet connection." } } \ No newline at end of file diff --git a/languages/id.json b/languages/id.json index 3cc9ed4..fe3e9ac 100644 --- a/languages/id.json +++ b/languages/id.json @@ -503,5 +503,22 @@ "verification_failed": "SHA256 verification failed. The downloaded file may be corrupted or tampered with.", "setup_failed": "Failed to set up Deno. Some features may not work correctly.", "setup_error": "Setup Error" + }, + "deno_updater": { + "title": "Deno Version Checker & Updater", + "description": "Check your Deno version and update to the latest release.", + "current_version": "Current Version:", + "latest_version": "Latest Version:", + "status_idle": "Click 'Check for Updates' to get started", + "status_checking": "🔄 Checking for updates...", + "status_up_to_date": "✓ Up to date", + "status_update_available": "⚠ Update available", + "status_not_installed": "✗ Not installed", + "check_updates": "Check for Updates", + "update_now": "Update Deno", + "updating": "🔄 Updating Deno...", + "update_success": "✅ Deno has been successfully updated!", + "update_failed": "❌ Update failed: {error}", + "check_failed": "Failed to check for updates. Please check your internet connection." } } \ No newline at end of file diff --git a/languages/it.json b/languages/it.json index 6613b42..36b46a8 100644 --- a/languages/it.json +++ b/languages/it.json @@ -503,5 +503,22 @@ "verification_failed": "SHA256 verification failed. The downloaded file may be corrupted or tampered with.", "setup_failed": "Failed to set up Deno. Some features may not work correctly.", "setup_error": "Setup Error" + }, + "deno_updater": { + "title": "Deno Version Checker & Updater", + "description": "Check your Deno version and update to the latest release.", + "current_version": "Current Version:", + "latest_version": "Latest Version:", + "status_idle": "Click 'Check for Updates' to get started", + "status_checking": "🔄 Checking for updates...", + "status_up_to_date": "✓ Up to date", + "status_update_available": "⚠ Update available", + "status_not_installed": "✗ Not installed", + "check_updates": "Check for Updates", + "update_now": "Update Deno", + "updating": "🔄 Updating Deno...", + "update_success": "✅ Deno has been successfully updated!", + "update_failed": "❌ Update failed: {error}", + "check_failed": "Failed to check for updates. Please check your internet connection." } } \ No newline at end of file diff --git a/languages/ja.json b/languages/ja.json index 1223f74..49fd581 100644 --- a/languages/ja.json +++ b/languages/ja.json @@ -503,5 +503,22 @@ "verification_failed": "SHA256 verification failed. The downloaded file may be corrupted or tampered with.", "setup_failed": "Failed to set up Deno. Some features may not work correctly.", "setup_error": "Setup Error" + }, + "deno_updater": { + "title": "Deno Version Checker & Updater", + "description": "Check your Deno version and update to the latest release.", + "current_version": "Current Version:", + "latest_version": "Latest Version:", + "status_idle": "Click 'Check for Updates' to get started", + "status_checking": "🔄 Checking for updates...", + "status_up_to_date": "✓ Up to date", + "status_update_available": "⚠ Update available", + "status_not_installed": "✗ Not installed", + "check_updates": "Check for Updates", + "update_now": "Update Deno", + "updating": "🔄 Updating Deno...", + "update_success": "✅ Deno has been successfully updated!", + "update_failed": "❌ Update failed: {error}", + "check_failed": "Failed to check for updates. Please check your internet connection." } } \ No newline at end of file diff --git a/languages/pl.json b/languages/pl.json index 606a076..47a7875 100644 --- a/languages/pl.json +++ b/languages/pl.json @@ -503,5 +503,22 @@ "verification_failed": "SHA256 verification failed. The downloaded file may be corrupted or tampered with.", "setup_failed": "Failed to set up Deno. Some features may not work correctly.", "setup_error": "Setup Error" + }, + "deno_updater": { + "title": "Deno Version Checker & Updater", + "description": "Check your Deno version and update to the latest release.", + "current_version": "Current Version:", + "latest_version": "Latest Version:", + "status_idle": "Click 'Check for Updates' to get started", + "status_checking": "🔄 Checking for updates...", + "status_up_to_date": "✓ Up to date", + "status_update_available": "⚠ Update available", + "status_not_installed": "✗ Not installed", + "check_updates": "Check for Updates", + "update_now": "Update Deno", + "updating": "🔄 Updating Deno...", + "update_success": "✅ Deno has been successfully updated!", + "update_failed": "❌ Update failed: {error}", + "check_failed": "Failed to check for updates. Please check your internet connection." } } \ No newline at end of file diff --git a/languages/pt.json b/languages/pt.json index c8a30fe..4963d1b 100644 --- a/languages/pt.json +++ b/languages/pt.json @@ -503,5 +503,22 @@ "verification_failed": "SHA256 verification failed. The downloaded file may be corrupted or tampered with.", "setup_failed": "Failed to set up Deno. Some features may not work correctly.", "setup_error": "Setup Error" + }, + "deno_updater": { + "title": "Deno Version Checker & Updater", + "description": "Check your Deno version and update to the latest release.", + "current_version": "Current Version:", + "latest_version": "Latest Version:", + "status_idle": "Click 'Check for Updates' to get started", + "status_checking": "🔄 Checking for updates...", + "status_up_to_date": "✓ Up to date", + "status_update_available": "⚠ Update available", + "status_not_installed": "✗ Not installed", + "check_updates": "Check for Updates", + "update_now": "Update Deno", + "updating": "🔄 Updating Deno...", + "update_success": "✅ Deno has been successfully updated!", + "update_failed": "❌ Update failed: {error}", + "check_failed": "Failed to check for updates. Please check your internet connection." } } \ No newline at end of file diff --git a/languages/ru.json b/languages/ru.json index bc92200..0af313e 100644 --- a/languages/ru.json +++ b/languages/ru.json @@ -503,5 +503,22 @@ "verification_failed": "SHA256 verification failed. The downloaded file may be corrupted or tampered with.", "setup_failed": "Failed to set up Deno. Some features may not work correctly.", "setup_error": "Setup Error" + }, + "deno_updater": { + "title": "Deno Version Checker & Updater", + "description": "Check your Deno version and update to the latest release.", + "current_version": "Current Version:", + "latest_version": "Latest Version:", + "status_idle": "Click 'Check for Updates' to get started", + "status_checking": "🔄 Checking for updates...", + "status_up_to_date": "✓ Up to date", + "status_update_available": "⚠ Update available", + "status_not_installed": "✗ Not installed", + "check_updates": "Check for Updates", + "update_now": "Update Deno", + "updating": "🔄 Updating Deno...", + "update_success": "✅ Deno has been successfully updated!", + "update_failed": "❌ Update failed: {error}", + "check_failed": "Failed to check for updates. Please check your internet connection." } } \ No newline at end of file diff --git a/languages/tr.json b/languages/tr.json index b06145d..4a5a2f7 100644 --- a/languages/tr.json +++ b/languages/tr.json @@ -503,5 +503,22 @@ "verification_failed": "SHA256 verification failed. The downloaded file may be corrupted or tampered with.", "setup_failed": "Failed to set up Deno. Some features may not work correctly.", "setup_error": "Setup Error" + }, + "deno_updater": { + "title": "Deno Version Checker & Updater", + "description": "Check your Deno version and update to the latest release.", + "current_version": "Current Version:", + "latest_version": "Latest Version:", + "status_idle": "Click 'Check for Updates' to get started", + "status_checking": "🔄 Checking for updates...", + "status_up_to_date": "✓ Up to date", + "status_update_available": "⚠ Update available", + "status_not_installed": "✗ Not installed", + "check_updates": "Check for Updates", + "update_now": "Update Deno", + "updating": "🔄 Updating Deno...", + "update_success": "✅ Deno has been successfully updated!", + "update_failed": "❌ Update failed: {error}", + "check_failed": "Failed to check for updates. Please check your internet connection." } } \ No newline at end of file diff --git a/languages/zh.json b/languages/zh.json index f5fe7e2..13eaacf 100644 --- a/languages/zh.json +++ b/languages/zh.json @@ -503,5 +503,22 @@ "verification_failed": "SHA256 verification failed. The downloaded file may be corrupted or tampered with.", "setup_failed": "Failed to set up Deno. Some features may not work correctly.", "setup_error": "Setup Error" + }, + "deno_updater": { + "title": "Deno Version Checker & Updater", + "description": "Check your Deno version and update to the latest release.", + "current_version": "Current Version:", + "latest_version": "Latest Version:", + "status_idle": "Click 'Check for Updates' to get started", + "status_checking": "🔄 Checking for updates...", + "status_up_to_date": "✓ Up to date", + "status_update_available": "⚠ Update available", + "status_not_installed": "✗ Not installed", + "check_updates": "Check for Updates", + "update_now": "Update Deno", + "updating": "🔄 Updating Deno...", + "update_success": "✅ Deno has been successfully updated!", + "update_failed": "❌ Update failed: {error}", + "check_failed": "Failed to check for updates. Please check your internet connection." } } \ No newline at end of file diff --git a/src/core/ytsage_deno.py b/src/core/ytsage_deno.py index 5d6d137..7444cfd 100644 --- a/src/core/ytsage_deno.py +++ b/src/core/ytsage_deno.py @@ -595,3 +595,150 @@ def setup_deno(parent_widget=None): # User cancelled or setup failed, return the fallback command logger.debug("Returning fallback command 'deno'") return "deno" + + +def get_latest_deno_version() -> Optional[str]: + """ + Fetch the latest Deno version from GitHub API. + + Returns: + str: Version string (e.g., "2.5.6") or None if fetch failed + """ + try: + response = requests.get( + "https://api.github.com/repos/denoland/deno/releases/latest", + timeout=10 + ) + response.raise_for_status() + data = response.json() + + # Get tag_name (e.g., "v2.5.6") and remove 'v' prefix + tag_name = data.get("tag_name", "") + if tag_name.startswith("v"): + version = tag_name[1:] + else: + version = tag_name + + logger.info(f"Latest Deno version: {version}") + return version + + except requests.RequestException as e: + logger.error(f"Failed to fetch latest Deno version: {e}") + return None + except Exception as e: + logger.exception(f"Unexpected error fetching Deno version: {e}") + return None + + +def compare_deno_versions(current: str, latest: str) -> bool: + """ + Compare two Deno version strings. + + Args: + current: Current version string (e.g., "2.5.6") + latest: Latest version string (e.g., "2.5.7") + + Returns: + bool: True if update is needed (latest > current), False otherwise + """ + try: + import re + + def parse_version(version_str: str) -> tuple: + """Parse version string into tuple of integers.""" + # Remove 'v' prefix if present + if version_str.startswith('v'): + version_str = version_str[1:] + + # Extract version numbers + match = re.search(r'(\d+\.\d+\.\d+)', version_str) + if match: + version_str = match.group(1) + + parts = version_str.split('.') + return tuple(int(p) for p in parts if p.isdigit()) + + current_tuple = parse_version(current) + latest_tuple = parse_version(latest) + + logger.debug(f"Comparing Deno versions: {current_tuple} vs {latest_tuple}") + return latest_tuple > current_tuple + + except (ValueError, AttributeError) as e: + logger.warning(f"Could not compare Deno versions: {e}") + return False + + +def upgrade_deno() -> tuple[bool, str]: + """ + Upgrade Deno to the latest version using 'deno upgrade' command. + + Returns: + tuple: (success: bool, output: str) - Success status and command output + """ + try: + deno_path = DENO_APP_BIN_PATH + + if not deno_path.exists(): + error_msg = f"Deno binary not found at: {deno_path}" + logger.error(error_msg) + return False, error_msg + + logger.info(f"Upgrading Deno using: {deno_path}") + + # Run deno upgrade command + result = subprocess.run( + [str(deno_path), "upgrade"], + capture_output=True, + text=True, + timeout=300, # 5 minutes timeout + creationflags=SUBPROCESS_CREATIONFLAGS + ) + + output = result.stdout + result.stderr + + if result.returncode == 0: + logger.info("Deno upgrade successful") + logger.debug(f"Upgrade output: {output}") + return True, output + else: + logger.error(f"Deno upgrade failed with code {result.returncode}") + logger.error(f"Output: {output}") + return False, output + + except subprocess.TimeoutExpired: + error_msg = "Deno upgrade timed out after 5 minutes" + logger.error(error_msg) + return False, error_msg + except Exception as e: + error_msg = f"Error upgrading Deno: {str(e)}" + logger.exception(error_msg) + return False, error_msg + + +def check_deno_update() -> tuple[bool, str, str]: + """ + Check if a Deno update is available. + + Returns: + tuple: (update_needed: bool, current_version: str, latest_version: str) + """ + try: + # Get current version + current_version = get_deno_version_direct() + if current_version in ["Not found", "Error getting version"]: + return False, current_version, "Unknown" + + # Get latest version + latest_version = get_latest_deno_version() + if not latest_version: + return False, current_version, "Error" + + # Compare versions + update_needed = compare_deno_versions(current_version, latest_version) + + return update_needed, current_version, latest_version + + except Exception as e: + logger.exception(f"Error checking Deno update: {e}") + return False, "Error", "Error" diff --git a/src/gui/ytsage_gui_dialogs/ytsage_dialogs_updater.py b/src/gui/ytsage_gui_dialogs/ytsage_dialogs_updater.py index c0a67b2..c86d1ba 100644 --- a/src/gui/ytsage_gui_dialogs/ytsage_dialogs_updater.py +++ b/src/gui/ytsage_gui_dialogs/ytsage_dialogs_updater.py @@ -29,6 +29,7 @@ from src.core.ytsage_utils import ( update_auto_update_settings, ) from src.core.ytsage_yt_dlp import get_yt_dlp_path +from src.core.ytsage_deno import check_deno_update, upgrade_deno from src.gui.ytsage_gui_dialogs.ytsage_dialogs_update import YTDLPUpdateDialog from src.utils.ytsage_config_manager import ConfigManager from src.utils.ytsage_localization import _ @@ -290,6 +291,116 @@ class UpdaterTabWidget(QWidget): layout.addWidget(ffmpeg_group) + # === Deno Version Check & Update Section === + deno_group = QGroupBox(_('deno_updater.title')) + deno_layout = QVBoxLayout(deno_group) + + # Description + deno_desc = QLabel(_('deno_updater.description')) + deno_desc.setWordWrap(True) + deno_desc.setStyleSheet("color: #999999; padding: 10px;") + deno_layout.addWidget(deno_desc) + + # Version information layout + deno_version_layout = QVBoxLayout() + + # Current version + deno_current_layout = QHBoxLayout() + deno_current_label = QLabel(_('deno_updater.current_version')) + deno_current_label.setStyleSheet("font-weight: bold; color: #ffffff;") + deno_current_layout.addWidget(deno_current_label) + + self.deno_current_version_label = QLabel("...") + self.deno_current_version_label.setStyleSheet("color: #cccccc;") + deno_current_layout.addWidget(self.deno_current_version_label) + deno_current_layout.addStretch() + deno_version_layout.addLayout(deno_current_layout) + + # Latest version + deno_latest_layout = QHBoxLayout() + deno_latest_label = QLabel(_('deno_updater.latest_version')) + deno_latest_label.setStyleSheet("font-weight: bold; color: #ffffff;") + deno_latest_layout.addWidget(deno_latest_label) + + self.deno_latest_version_label = QLabel("...") + self.deno_latest_version_label.setStyleSheet("color: #cccccc;") + deno_latest_layout.addWidget(self.deno_latest_version_label) + deno_latest_layout.addStretch() + deno_version_layout.addLayout(deno_latest_layout) + + deno_layout.addLayout(deno_version_layout) + + # Status label + self.deno_status_label = QLabel(_('deno_updater.status_idle')) + self.deno_status_label.setWordWrap(True) + self.deno_status_label.setStyleSheet( + "color: #888888; font-size: 12px; padding: 8px; " + "background-color: #2a2d36; border-radius: 4px; margin: 5px 0;" + ) + deno_layout.addWidget(self.deno_status_label) + + # Buttons layout + deno_button_layout = QHBoxLayout() + + # Check for updates button + self.deno_check_button = QPushButton(_('deno_updater.check_updates')) + self.deno_check_button.clicked.connect(self.check_deno_updates) + self.deno_check_button.setStyleSheet( + """ + QPushButton { + padding: 8px 15px; + background-color: #444444; + border: none; + border-radius: 4px; + color: white; + font-weight: bold; + min-width: 120px; + } + QPushButton:hover { + background-color: #555555; + } + QPushButton:disabled { + background-color: #2a2a2a; + color: #666666; + } + """ + ) + deno_button_layout.addWidget(self.deno_check_button) + + # Update button (initially hidden) + self.deno_update_button = QPushButton(_('deno_updater.update_now')) + self.deno_update_button.clicked.connect(self.update_deno) + self.deno_update_button.setVisible(False) + self.deno_update_button.setStyleSheet( + """ + QPushButton { + padding: 8px 15px; + background-color: #c90000; + border: none; + border-radius: 4px; + color: white; + font-weight: bold; + min-width: 120px; + } + QPushButton:hover { + background-color: #a50000; + } + QPushButton:pressed { + background-color: #800000; + } + QPushButton:disabled { + background-color: #2a2a2a; + color: #666666; + } + """ + ) + deno_button_layout.addWidget(self.deno_update_button) + + deno_button_layout.addStretch() + deno_layout.addLayout(deno_button_layout) + + layout.addWidget(deno_group) + # === yt-dlp Release Channel Section === ytdlp_channel_group = QGroupBox(_("settings.ytdlp_channel")) ytdlp_channel_layout = QVBoxLayout() @@ -697,3 +808,116 @@ class UpdaterTabWidget(QWidget): "color: #ff6666; font-size: 12px; padding: 8px; " "background-color: #2a2d36; border-radius: 4px; margin: 5px 0;" ) + + def check_deno_updates(self) -> None: + """Check for Deno updates.""" + self.deno_check_button.setEnabled(False) + self.deno_update_button.setVisible(False) + self.deno_status_label.setText(_('deno_updater.status_checking')) + self.deno_status_label.setStyleSheet( + "color: #ffaa00; font-size: 12px; padding: 8px; " + "background-color: #2a2d36; border-radius: 4px; margin: 5px 0;" + ) + + # Run check in background thread + def check_thread(): + try: + update_available, current_version, latest_version = check_deno_update() + + # Update UI in main thread + self.deno_check_button.setEnabled(True) + self._update_deno_check_results(update_available, current_version, latest_version) + + except Exception as e: + logger.exception(f"Error checking Deno version: {e}") + self.deno_check_button.setEnabled(True) + self._show_deno_check_error(str(e)) + + thread = threading.Thread(target=check_thread, daemon=True) + thread.start() + + def _update_deno_check_results(self, update_available: bool, current_version: str, latest_version: str) -> None: + """Handle completion of Deno version check.""" + # Update version labels + self.deno_current_version_label.setText(current_version) + self.deno_latest_version_label.setText(latest_version) + + # Update status + if current_version in ["Not found", "Error getting version"]: + self.deno_status_label.setText(_('deno_updater.status_not_installed')) + self.deno_status_label.setStyleSheet( + "color: #ff6666; font-size: 12px; padding: 8px; " + "background-color: #2a2d36; border-radius: 4px; margin: 5px 0;" + ) + elif update_available: + self.deno_status_label.setText(_('deno_updater.status_update_available')) + self.deno_status_label.setStyleSheet( + "color: #ffaa00; font-size: 12px; padding: 8px; " + "background-color: #2a2d36; border-radius: 4px; margin: 5px 0;" + ) + # Show update button + self.deno_update_button.setVisible(True) + else: + self.deno_status_label.setText(_('deno_updater.status_up_to_date')) + self.deno_status_label.setStyleSheet( + "color: #00cc00; font-size: 12px; padding: 8px; " + "background-color: #2a2d36; border-radius: 4px; margin: 5px 0;" + ) + + def _show_deno_check_error(self, error: str) -> None: + """Handle error during Deno version check.""" + self.deno_status_label.setText(_('deno_updater.check_failed')) + self.deno_status_label.setStyleSheet( + "color: #ff6666; font-size: 12px; padding: 8px; " + "background-color: #2a2d36; border-radius: 4px; margin: 5px 0;" + ) + + def update_deno(self) -> None: + """Update Deno to the latest version.""" + self.deno_check_button.setEnabled(False) + self.deno_update_button.setEnabled(False) + self.deno_status_label.setText(_('deno_updater.updating')) + self.deno_status_label.setStyleSheet( + "color: #ffaa00; font-size: 12px; padding: 8px; " + "background-color: #2a2d36; border-radius: 4px; margin: 5px 0;" + ) + + # Run update in background thread + def update_thread(): + try: + success, output = upgrade_deno() + + # Update UI in main thread + self.deno_check_button.setEnabled(True) + self.deno_update_button.setEnabled(True) + self._handle_deno_update_result(success, output) + + except Exception as e: + logger.exception(f"Error updating Deno: {e}") + self.deno_check_button.setEnabled(True) + self.deno_update_button.setEnabled(True) + self._handle_deno_update_result(False, str(e)) + + thread = threading.Thread(target=update_thread, daemon=True) + thread.start() + + def _handle_deno_update_result(self, success: bool, output: str) -> None: + """Handle Deno update completion.""" + if success: + self.deno_status_label.setText(_('deno_updater.update_success')) + self.deno_status_label.setStyleSheet( + "color: #00cc00; font-size: 12px; padding: 8px; " + "background-color: #2a2d36; border-radius: 4px; margin: 5px 0;" + ) + self.deno_update_button.setVisible(False) + + # Re-check version to update display + self.check_deno_updates() + else: + # Extract meaningful error from output + error_msg = output if output else "Unknown error" + self.deno_status_label.setText(_('deno_updater.update_failed', error=error_msg)) + self.deno_status_label.setStyleSheet( + "color: #ff6666; font-size: 12px; padding: 8px; " + "background-color: #2a2d36; border-radius: 4px; margin: 5px 0;" + )