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.
This commit is contained in:
oop7
2025-11-14 18:44:40 +02:00
parent 894f999017
commit 9d5a2460b1
16 changed files with 609 additions and 0 deletions
+17
View File
@@ -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."
}
}
+17
View File
@@ -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."
}
}
+17
View File
@@ -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."
}
}
+17
View File
@@ -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."
}
}
+17
View File
@@ -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."
}
}
+17
View File
@@ -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."
}
}
+17
View File
@@ -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."
}
}
+17
View File
@@ -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."
}
}
+17
View File
@@ -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."
}
}
+17
View File
@@ -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."
}
}
+17
View File
@@ -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."
}
}
+17
View File
@@ -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."
}
}
+17
View File
@@ -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."
}
}
+17
View File
@@ -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."
}
}
+147
View File
@@ -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"
@@ -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;"
)