Move update check to background thread
Refactored the update checking logic into a QThread subclass to prevent blocking the UI during network requests. The update check now runs asynchronously, and the dialog is shown via a signal when an update is available.
This commit is contained in:
+49
-34
@@ -8,7 +8,7 @@ import markdown
|
|||||||
import pyglet
|
import pyglet
|
||||||
import requests
|
import requests
|
||||||
from packaging import version
|
from packaging import version
|
||||||
from PySide6.QtCore import Q_ARG, QMetaObject, Qt, QTimer, Slot
|
from PySide6.QtCore import Q_ARG, QMetaObject, Qt, QTimer, Slot, QThread, Signal
|
||||||
from PySide6.QtGui import QIcon
|
from PySide6.QtGui import QIcon
|
||||||
from PySide6.QtWidgets import (
|
from PySide6.QtWidgets import (
|
||||||
QApplication,
|
QApplication,
|
||||||
@@ -53,7 +53,51 @@ from src.utils.ytsage_localization import LocalizationManager, _
|
|||||||
from src.utils.ytsage_history_manager import HistoryManager
|
from src.utils.ytsage_history_manager import HistoryManager
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateCheckThread(QThread):
|
||||||
|
update_available = Signal(str, str, str) # version, url, changelog
|
||||||
|
|
||||||
|
def __init__(self, current_version):
|
||||||
|
super().__init__()
|
||||||
|
self.current_version = current_version
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
# Get the latest version info from PyPI (no rate limiting unlike GitHub API)
|
||||||
|
response = requests.get(
|
||||||
|
"https://pypi.org/pypi/ytsage/json",
|
||||||
|
timeout=10,
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
pypi_data = response.json()
|
||||||
|
latest_version = pypi_data["info"]["version"]
|
||||||
|
|
||||||
|
# Compare versions
|
||||||
|
if version.parse(latest_version) > version.parse(self.current_version):
|
||||||
|
release_url = "https://github.com/oop7/YTSage/releases/latest"
|
||||||
|
|
||||||
|
# Try to fetch changelog from GitHub (with fallback if rate-limited)
|
||||||
|
changelog = "View the full changelog on the [GitHub Releases](https://github.com/oop7/YTSage/releases) page."
|
||||||
|
try:
|
||||||
|
gh_response = requests.get(
|
||||||
|
"https://api.github.com/repos/oop7/YTSage/releases/latest",
|
||||||
|
headers={"Accept": "application/vnd.github.v3+json"},
|
||||||
|
timeout=5,
|
||||||
|
)
|
||||||
|
if gh_response.status_code == 200:
|
||||||
|
gh_data = gh_response.json()
|
||||||
|
changelog = gh_data.get("body", changelog)
|
||||||
|
except Exception:
|
||||||
|
# Silently fallback to static message if GitHub API fails
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.update_available.emit(latest_version, release_url, changelog)
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"Failed to check for updates: {e}")
|
||||||
|
|
||||||
|
|
||||||
class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin): # Inherit from mixins
|
class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin): # Inherit from mixins
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
@@ -1161,39 +1205,10 @@ class YTSageApp(QMainWindow, FormatTableMixin, VideoInfoMixin): # Inherit from
|
|||||||
self.signals.update_status.emit(_("download.resumed"))
|
self.signals.update_status.emit(_("download.resumed"))
|
||||||
|
|
||||||
def check_for_updates(self) -> None:
|
def check_for_updates(self) -> None:
|
||||||
try:
|
"""Starts the update check in a background thread."""
|
||||||
# Get the latest version info from PyPI (no rate limiting unlike GitHub API)
|
self.update_thread = UpdateCheckThread(self.version)
|
||||||
response = requests.get(
|
self.update_thread.update_available.connect(self.show_update_dialog)
|
||||||
"https://pypi.org/pypi/ytsage/json",
|
self.update_thread.start()
|
||||||
timeout=10,
|
|
||||||
)
|
|
||||||
response.raise_for_status()
|
|
||||||
|
|
||||||
pypi_data = response.json()
|
|
||||||
latest_version = pypi_data["info"]["version"]
|
|
||||||
|
|
||||||
# Compare versions
|
|
||||||
if version.parse(latest_version) > version.parse(self.version):
|
|
||||||
release_url = "https://github.com/oop7/YTSage/releases/latest"
|
|
||||||
|
|
||||||
# Try to fetch changelog from GitHub (with fallback if rate-limited)
|
|
||||||
changelog = "View the full changelog on the [GitHub Releases](https://github.com/oop7/YTSage/releases) page."
|
|
||||||
try:
|
|
||||||
gh_response = requests.get(
|
|
||||||
"https://api.github.com/repos/oop7/YTSage/releases/latest",
|
|
||||||
headers={"Accept": "application/vnd.github.v3+json"},
|
|
||||||
timeout=5,
|
|
||||||
)
|
|
||||||
if gh_response.status_code == 200:
|
|
||||||
gh_data = gh_response.json()
|
|
||||||
changelog = gh_data.get("body", changelog)
|
|
||||||
except Exception:
|
|
||||||
# Silently fallback to static message if GitHub API fails (rate limit, etc.)
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.show_update_dialog(latest_version, release_url, changelog)
|
|
||||||
except Exception as e:
|
|
||||||
logger.exception(f"Failed to check for updates: {e}")
|
|
||||||
|
|
||||||
def show_update_dialog(self, latest_version, release_url, changelog) -> None: # Added changelog parameter
|
def show_update_dialog(self, latest_version, release_url, changelog) -> None: # Added changelog parameter
|
||||||
msg = QDialog(self)
|
msg = QDialog(self)
|
||||||
|
|||||||
Reference in New Issue
Block a user