Skip to content

Commit 5a66af3

Browse files
committed
feat(版本检查): 添加GitHub版本检查功能
实现自动和手动检查GitHub最新版本的功能,包括版本号比较、更新提示和下载链接。当检测到新版本时,会显示更新内容并提供下载选项。同时优化了界面显示,添加了版本检查标签和状态反馈。
1 parent c0c9c60 commit 5a66af3

File tree

2 files changed

+150
-7
lines changed

2 files changed

+150
-7
lines changed

ui/main_window.py

Lines changed: 86 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
from PySide6.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QTabWidget,
22
QGroupBox, QLineEdit, QTextEdit, QLabel, QListWidget, QPushButton,
33
QSplitter, QPlainTextEdit, QFileDialog, QMenu, QMessageBox, QFrame, QToolButton, QListView, QTabBar,
4-
QStylePainter, QStyleOptionTab, QStyle)
4+
QStylePainter, QStyleOptionTab, QStyle, QScrollArea, QListWidgetItem, QSystemTrayIcon, QApplication)
55
from PySide6.QtGui import (QIcon, QTextCursor, QColor, QMouseEvent, QPainter, QCloseEvent,
66
QPalette, QGuiApplication, QFont, QTransform, QDesktopServices)
77
from PySide6.QtCore import Qt, Slot, QTimer, QPoint, Signal, QThread, QSettings, QSize, QUrl
88
import logging
99
import os
1010
import json
11+
import re
1112
from core.file_manager import FileManager
1213
import zipfile
1314
from datetime import datetime
@@ -45,15 +46,19 @@
4546
theme_button_color, minimize_button_color, maximize_button_color, close_button_color)
4647
from utils.highlight_manager import ButtonHighlightManager
4748
from ui.glass_overlay import GlassOverlay
48-
from utils.github_utils import GithubStarFetcher
49+
from utils.github_utils import GithubStarFetcher, GithubVersionChecker
4950
import yaml
51+
import subprocess
52+
import shutil
53+
import tempfile
5054

5155
import sys,time
5256
logger = logging.getLogger(__name__)
5357

5458

5559
class MainWindow(QMainWindow):
5660
style_updated_signal = Signal()
61+
CURRENT_VERSION = "0.98"
5762

5863
def __init__(self):
5964
super().__init__()
@@ -98,7 +103,7 @@ def __init__(self):
98103
title_layout.addWidget(icon_label)
99104

100105
# 添加标题
101-
title_label = QLabel("Lovelymem Ver 0.97")
106+
title_label = QLabel(f"Lovelymem Ver {self.CURRENT_VERSION}")
102107
title_layout.addWidget(title_label)
103108

104109
# 添加 Luxe 广告
@@ -112,6 +117,17 @@ def __init__(self):
112117
self.ad_label.setCursor(Qt.PointingHandCursor)
113118
self.ad_label.mousePressEvent = lambda e: QDesktopServices.openUrl(QUrl("http://lovely.mzy0.com/lovelymemluxe.exe"))
114119
title_layout.addWidget(self.ad_label)
120+
121+
# 添加版本更新检测标签
122+
self.update_label = QLabel("🔍 检查更新")
123+
self.update_label.setStyleSheet("""
124+
color: #555555;
125+
margin-left: 15px;
126+
font-size: 11px;
127+
""")
128+
self.update_label.setCursor(Qt.PointingHandCursor)
129+
self.update_label.mousePressEvent = lambda e: self.check_for_updates(manual=True)
130+
title_layout.addWidget(self.update_label)
115131

116132
title_layout.addStretch()
117133

@@ -326,6 +342,9 @@ def __init__(self):
326342
# 异步获取GitHub星标数
327343
self.fetch_github_stars()
328344

345+
# 启动自动检查更新
346+
QTimer.singleShot(5000, lambda: self.check_for_updates(manual=False))
347+
329348
def fetch_github_stars(self):
330349
"""异步获取GitHub星标数"""
331350
try:
@@ -343,6 +362,68 @@ def fetch_github_stars(self):
343362
except Exception as e:
344363
logger.error(f"Error starting star fetcher: {e}")
345364

365+
def check_for_updates(self, manual=False):
366+
"""检查版本更新"""
367+
if manual:
368+
self.update_label.setText("🔄 正在检查...")
369+
370+
try:
371+
# 加载代理配置
372+
config_path = os.path.join(os.getcwd(), "config", "base_config.yaml")
373+
proxy_url = None
374+
if os.path.exists(config_path):
375+
with open(config_path, 'r', encoding='utf-8') as f:
376+
config = yaml.safe_load(f)
377+
proxy_url = config.get("base_config", {}).get("proxy", {}).get("url")
378+
379+
self.version_checker = GithubVersionChecker("https://github.com/Tokeii0/LovelyMem", proxy_url)
380+
self.version_checker.version_checked.connect(lambda v, u, b: self.on_version_checked(v, u, b, manual))
381+
self.version_checker.start()
382+
except Exception as e:
383+
logger.error(f"Error starting version checker: {e}")
384+
if manual:
385+
self.update_label.setText("❌ 检查失败")
386+
QTimer.singleShot(3000, lambda: self.update_label.setText("🔍 检查更新"))
387+
388+
def on_version_checked(self, latest_version, download_url, body, manual):
389+
"""版本检查完成的回调"""
390+
if not latest_version:
391+
if manual:
392+
self.update_label.setText("❌ 检查失败")
393+
QTimer.singleShot(3000, lambda: self.update_label.setText("🔍 检查更新"))
394+
return
395+
396+
# 版本号对比
397+
try:
398+
current = float(re.sub(r'[^0-9.]', '', self.CURRENT_VERSION))
399+
latest = float(re.sub(r'[^0-9.]', '', latest_version))
400+
401+
if latest > current:
402+
self.update_label.setText(f"🎁 新版本 v{latest_version}")
403+
self.update_label.setStyleSheet("color: #FF4500; font-weight: bold; margin-left: 15px; font-size: 11px;")
404+
405+
# 弹窗提示
406+
reply = QMessageBox.information(
407+
self,
408+
"发现新版本",
409+
f"检测到新版本: v{latest_version}\n\n更新内容:\n{body}\n\n是否立即前往下载?",
410+
QMessageBox.Yes | QMessageBox.No,
411+
QMessageBox.Yes
412+
)
413+
if reply == QMessageBox.Yes:
414+
QDesktopServices.openUrl(QUrl(download_url))
415+
else:
416+
if manual:
417+
self.update_label.setText("✅ 已是最新")
418+
QMessageBox.information(self, "检查更新", f"当前版本 v{self.CURRENT_VERSION} 已是最新版本。")
419+
QTimer.singleShot(3000, lambda: self.update_label.setText("🔍 检查更新"))
420+
else:
421+
self.update_label.setText("🔍 检查更新")
422+
except Exception as e:
423+
logger.error(f"Version comparison error: {e}")
424+
if manual:
425+
self.update_label.setText("🔍 检查更新")
426+
346427
def update_star_label(self, stars):
347428
"""更新星标数显示"""
348429
self.star_label.setText(f"⭐ {stars}")
@@ -422,7 +503,7 @@ def load_image(self, image_path=None):
422503
self.quick_check_area.set_image_path(image_path)
423504
title_label = self.findChild(QLabel, "title_label")
424505
if title_label:
425-
title_label.setText(f"Lovelymem Ver 0.97 - {image_path}")
506+
title_label.setText(f"Lovelymem Ver {self.CURRENT_VERSION} - {image_path}")
426507
self.current_mem_path = image_path # 更新当前内存镜像路径
427508
self.mem_image_loader.load_mem_image(image_path)
428509
self.cmd_output.append("正在加载内存镜像,请稍候...")
@@ -490,7 +571,7 @@ def unload_image(self):
490571
# 更新标题
491572
title_label = self.findChild(QLabel, "title_label")
492573
if title_label:
493-
title_label.setText("Lovelymem Ver 0.97")
574+
title_label.setText(f"Lovelymem Ver {self.CURRENT_VERSION}")
494575

495576
# profile 清空
496577
self.vol2_area.profile = None

utils/github_utils.py

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import logging
33
from PySide6.QtCore import QThread, Signal
44
import urllib3
5+
import re
56

67
# 禁用不安全请求警告
78
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
@@ -69,11 +70,72 @@ def _make_request(self, url, proxies=None, verify=True):
6970
)
7071
if response.status_code == 200:
7172
data = response.json()
72-
# 格式化数字:如果是 1590 -> 1,590
7373
count = data.get("stargazers_count", 0)
7474
if count >= 1000:
7575
return f"{count/1000:.1f}k" if count < 10000 else f"{count//1000}k"
7676
return str(count)
7777
elif response.status_code == 403:
78-
return "Limit" # API 速率限制
78+
return "Limit"
7979
return "Err"
80+
81+
class GithubVersionChecker(QThread):
82+
"""
83+
检查 GitHub 上的最新版本
84+
返回 (latest_version, download_url, release_notes)
85+
"""
86+
version_checked = Signal(str, str, str)
87+
88+
def __init__(self, repo_url, proxy=None):
89+
super().__init__()
90+
self.repo_url = repo_url
91+
self.proxy = proxy
92+
self.headers = {
93+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
94+
"Accept": "application/vnd.github.v3+json"
95+
}
96+
97+
def run(self):
98+
try:
99+
parts = self.repo_url.rstrip('/').split('/')
100+
if len(parts) < 2:
101+
self.version_checked.emit("", "", "")
102+
return
103+
104+
owner = parts[-2]
105+
repo = parts[-1]
106+
# 获取最新 release
107+
api_url = f"https://api.github.com/repos/{owner}/{repo}/releases/latest"
108+
109+
proxies = None
110+
if self.proxy:
111+
proxies = {"http": self.proxy, "https": self.proxy}
112+
113+
# 尝试获取
114+
data = self._fetch_data(api_url, proxies)
115+
if data:
116+
tag_name = data.get("tag_name", "")
117+
# 提取版本号 (如 v0.98 -> 0.98)
118+
version = re.sub(r'[^0-9.]', '', tag_name)
119+
download_url = data.get("html_url", self.repo_url)
120+
body = data.get("body", "无更新说明")
121+
self.version_checked.emit(version, download_url, body)
122+
else:
123+
self.version_checked.emit("", "", "")
124+
except Exception as e:
125+
logger.error(f"Version check failed: {e}")
126+
self.version_checked.emit("", "", "")
127+
128+
def _fetch_data(self, url, proxies=None):
129+
try:
130+
# 策略1: 正常请求
131+
response = requests.get(url, proxies=proxies, timeout=10, headers=self.headers)
132+
if response.status_code == 200:
133+
return response.json()
134+
135+
# 策略2: 忽略 SSL
136+
response = requests.get(url, proxies=proxies, timeout=10, headers=self.headers, verify=False)
137+
if response.status_code == 200:
138+
return response.json()
139+
except:
140+
pass
141+
return None

0 commit comments

Comments
 (0)