Skip to content
This repository was archived by the owner on Jan 9, 2026. It is now read-only.

Commit fac0d5f

Browse files
committed
chore: bump version to 1.2.3 and improve update/UI stability
1 parent 8d787b3 commit fac0d5f

10 files changed

Lines changed: 91 additions & 81 deletions

__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""应用版本信息"""
22

3-
__version__ = "1.2.2"
3+
__version__ = "1.2.3"

core/update_manager.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def __init__(self,
3737
# UI 回调
3838
self._on_check_start: Optional[Callable[[], None]] = None
3939
self._on_check_complete: Optional[Callable[[List[Tuple[str, UpdateInfo]]], None]] = None
40+
self._on_updates_found: Optional[Callable[[List[Tuple[str, UpdateInfo]]], None]] = None
4041
self._on_download_start: Optional[Callable[[], None]] = None
4142
self._on_download_progress: Optional[Callable[[str, int, int], None]] = None
4243
self._on_download_status: Optional[Callable[[str], None]] = None
@@ -49,12 +50,21 @@ def set_callbacks(self,
4950
on_download_progress: Optional[Callable[[str, int, int], None]] = None,
5051
on_download_status: Optional[Callable[[str], None]] = None,
5152
on_download_complete: Optional[Callable[[List[str], List[Tuple[str, str]], bool], None]] = None):
52-
self._on_check_start = on_check_start
53-
self._on_check_complete = on_check_complete
54-
self._on_download_start = on_download_start
55-
self._on_download_progress = on_download_progress
56-
self._on_download_status = on_download_status
57-
self._on_download_complete = on_download_complete
53+
if on_check_start is not None:
54+
self._on_check_start = on_check_start
55+
if on_check_complete is not None:
56+
self._on_check_complete = on_check_complete
57+
if on_download_start is not None:
58+
self._on_download_start = on_download_start
59+
if on_download_progress is not None:
60+
self._on_download_progress = on_download_progress
61+
if on_download_status is not None:
62+
self._on_download_status = on_download_status
63+
if on_download_complete is not None:
64+
self._on_download_complete = on_download_complete
65+
66+
def set_updates_found_callback(self, callback: Optional[Callable[[List[Tuple[str, UpdateInfo]]], None]]):
67+
self._on_updates_found = callback
5868

5969
@property
6070
def has_updates(self) -> bool:
@@ -158,6 +168,8 @@ def _check_updates(self, versions: Dict[str, str]):
158168

159169
if updates_found:
160170
logger.info(f"发现 {len(updates_found)} 个更新: {[name for name, _ in updates_found]}")
171+
if self._on_updates_found:
172+
self._on_updates_found(updates_found)
161173
else:
162174
logger.info("所有组件已是最新版本")
163175

@@ -196,6 +208,10 @@ def _download_all_updates(self):
196208
self._is_downloading = True
197209
updates_to_download = self._updates_found.copy()
198210

211+
# 按顺序排序:LLBot → PMHQ → 管理器(管理器最后更新,避免重启弹框打断其他更新)
212+
order = {"LLBot": 0, "PMHQ": 1, "管理器": 2}
213+
updates_to_download.sort(key=lambda x: order.get(x[0], 99))
214+
199215
if self._on_download_start:
200216
self._on_download_start()
201217

lucky-lillia-desktop.spec

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,13 @@ exe = EXE(
6161
strip=False,
6262
upx=True,
6363
upx_exclude=[],
64-
runtime_tmpdir=None,
65-
console=False, # Hide console window
64+
runtime_tmpdir='C:\\LLBotTemp', # 避免中文用户名路径导致 Flutter 启动失败
65+
console=False,
6666
disable_windowed_traceback=False,
6767
argv_emulation=False,
6868
target_arch=None,
6969
codesign_identity=None,
7070
entitlements_file=None,
71-
icon='icon.ico', # Application icon
72-
uac_admin=True, # 请求管理员权限
71+
icon='icon.ico',
72+
uac_admin=True,
7373
)

main.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,9 @@ def show_startup_error(page: ft.Page, e: Exception):
689689
logger.info("="*60)
690690

691691
try:
692+
# 禁用 Flutter GPU 硬件加速,解决部分机器上 Flet View 启动失败的问题
693+
os.environ.setdefault("FLET_VIEW_ARGUMENTS", "--disable-gpu")
694+
692695
# 启动Flet应用
693696
ft.app(target=main)
694697

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "lucky-lillia-desktop-win-x64",
3-
"version": "1.2.2",
3+
"version": "1.2.3",
44
"repository": {
55
"type": "git",
66
"url": "https://github.com/LLOneBot/lucky-lillia-desktop"

ui/about_page.py

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,13 @@ def build(self, page: ft.Page):
157157
self.llbot_card.build()
158158

159159
# 检查更新/立即更新按钮
160+
self._button_text = ft.Text("检查更新")
160161
self.check_update_button = ft.ElevatedButton(
161-
"检查更新",
162-
icon=ft.Icons.CLOUD_DOWNLOAD,
162+
content=ft.Row(
163+
[ft.Icon(ft.Icons.CLOUD_DOWNLOAD), self._button_text],
164+
tight=True,
165+
spacing=8,
166+
),
163167
on_click=self._on_check_or_update_click,
164168
style=ft.ButtonStyle(
165169
color=ft.Colors.ON_PRIMARY,
@@ -168,6 +172,7 @@ def build(self, page: ft.Page):
168172
padding=ft.padding.symmetric(horizontal=24, vertical=12),
169173
)
170174
)
175+
self._button_icon = self.check_update_button.content.controls[0]
171176

172177
# 加载中指示器
173178
self.loading_indicator = ft.ProgressRing(
@@ -305,6 +310,7 @@ def load_versions_async():
305310
async def update_ui():
306311
self.pmhq_card.update_version(pmhq_version if pmhq_version else "未知")
307312
self.llbot_card.update_version(llbot_version if llbot_version else "未知")
313+
self._sync_update_status()
308314
if self.page:
309315
self.page.update()
310316

@@ -356,11 +362,11 @@ async def update_ui():
356362

357363
has_any_update = any(info.has_update for _, info in all_check_results)
358364
if has_any_update:
359-
self.check_update_button.text = "立即更新"
360-
self.check_update_button.icon = ft.Icons.DOWNLOAD
365+
self._button_text.value = "立即更新"
366+
self._button_icon.name = ft.Icons.DOWNLOAD
361367
else:
362-
self.check_update_button.text = "检查更新"
363-
self.check_update_button.icon = ft.Icons.CLOUD_DOWNLOAD
368+
self._button_text.value = "检查更新"
369+
self._button_icon.name = ft.Icons.CLOUD_DOWNLOAD
364370

365371
if self.page:
366372
self.page.update()
@@ -380,11 +386,11 @@ async def update_ui():
380386

381387
def set_updates_found(self, updates_found: list):
382388
if updates_found:
383-
self.check_update_button.text = "立即更新"
384-
self.check_update_button.icon = ft.Icons.DOWNLOAD
389+
self._button_text.value = "立即更新"
390+
self._button_icon.name = ft.Icons.DOWNLOAD
385391
else:
386-
self.check_update_button.text = "检查更新"
387-
self.check_update_button.icon = ft.Icons.CLOUD_DOWNLOAD
392+
self._button_text.value = "检查更新"
393+
self._button_icon.name = ft.Icons.CLOUD_DOWNLOAD
388394

389395
for component_name, update_info in updates_found:
390396
if component_name == "管理器":
@@ -394,11 +400,10 @@ def set_updates_found(self, updates_found: list):
394400
elif component_name == "LLBot":
395401
self.llbot_card.update_check_result(update_info)
396402

397-
if self.page:
398-
try:
399-
self.page.update()
400-
except:
401-
pass
403+
try:
404+
self.check_update_button.update()
405+
except:
406+
pass
402407

403408
def _start_all_updates(self):
404409
if not self.update_manager or not self.update_manager.has_updates:
@@ -495,8 +500,8 @@ async def on_complete():
495500
if self.page:
496501
self.page.pop_dialog()
497502

498-
self.check_update_button.text = "检查更新"
499-
self.check_update_button.icon = ft.Icons.CLOUD_DOWNLOAD
503+
self._button_text.value = "检查更新"
504+
self._button_icon.name = ft.Icons.CLOUD_DOWNLOAD
500505

501506
self.app_card.clear_update_status()
502507
self.pmhq_card.clear_update_status()
@@ -571,14 +576,14 @@ def _close_dialog(self, dialog: ft.AlertDialog):
571576
self.page.pop_dialog()
572577

573578
def refresh(self):
579+
self._sync_update_status()
574580
self._load_versions()
575-
576-
# 同步更新管理器的状态到卡片
581+
582+
def _sync_update_status(self):
577583
if self.update_manager and self.update_manager.has_updates:
578-
self.check_update_button.text = "立即更新"
579-
self.check_update_button.icon = ft.Icons.DOWNLOAD
584+
self._button_text.value = "立即更新"
585+
self._button_icon.name = ft.Icons.DOWNLOAD
580586

581-
# 同步更新状态到卡片显示
582587
for name, info in self.update_manager.updates_found:
583588
if name == "管理器":
584589
self.app_card.update_check_result(info)
@@ -587,11 +592,5 @@ def refresh(self):
587592
elif name == "LLBot":
588593
self.llbot_card.update_check_result(info)
589594
else:
590-
self.check_update_button.text = "检查更新"
591-
self.check_update_button.icon = ft.Icons.CLOUD_DOWNLOAD
592-
593-
if self.page:
594-
try:
595-
self.page.update()
596-
except:
597-
pass
595+
self._button_text.value = "检查更新"
596+
self._button_icon.name = ft.Icons.CLOUD_DOWNLOAD

ui/home_page.py

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -929,13 +929,9 @@ def _do_start_services(self):
929929
pmhq_path = config.get("pmhq_path", DEFAULT_CONFIG["pmhq_path"])
930930
llbot_path = config.get("llbot_path", DEFAULT_CONFIG["llbot_path"])
931931
node_path = config.get("node_path", DEFAULT_CONFIG["node_path"])
932-
ffmpeg_path = config.get("ffmpeg_path", DEFAULT_CONFIG["ffmpeg_path"])
933-
ffprobe_path = config.get("ffprobe_path", DEFAULT_CONFIG["ffprobe_path"])
934932
logger.info(f"PMHQ路径: {pmhq_path}")
935933
logger.info(f"LLBot路径: {llbot_path}")
936934
logger.info(f"Node.exe路径: {node_path}")
937-
logger.info(f"FFmpeg.exe路径: {ffmpeg_path}")
938-
logger.info(f"FFprobe.exe路径: {ffprobe_path}")
939935

940936
# 检查PMHQ文件是否存在
941937
pmhq_exists = self.downloader.check_file_exists(pmhq_path)
@@ -969,40 +965,24 @@ def _do_start_services(self):
969965
self.config_manager.save_config(config)
970966
logger.info(f"Node.exe可用: {node_exists}")
971967

972-
# 检查FFmpeg.exe文件是否存在(先检查配置路径,再检查环境变量,最后检查bin/llbot/ffmpeg.exe
973-
ffmpeg_exists = self.downloader.check_file_exists(ffmpeg_path)
974-
if not ffmpeg_exists:
968+
# 检查FFmpeg.exe是否存在(先检查环境变量,再检查bin/llbot/)
969+
ffmpeg_exists = self.downloader.check_ffmpeg_exists()
970+
if ffmpeg_exists:
975971
system_ffmpeg = self.downloader.check_ffmpeg_available()
976972
if system_ffmpeg:
977973
logger.info(f"在系统PATH中找到FFmpeg: {system_ffmpeg}")
978-
ffmpeg_exists = True
979-
config["ffmpeg_path"] = system_ffmpeg
980-
self.config_manager.save_config(config)
981974
else:
982-
local_ffmpeg_path = "bin/llbot/ffmpeg.exe"
983-
if self.downloader.check_file_exists(local_ffmpeg_path):
984-
logger.info(f"在本地目录找到FFmpeg: {local_ffmpeg_path}")
985-
ffmpeg_exists = True
986-
config["ffmpeg_path"] = local_ffmpeg_path
987-
self.config_manager.save_config(config)
975+
logger.info("在本地目录找到FFmpeg: bin/llbot/ffmpeg.exe")
988976
logger.info(f"FFmpeg.exe可用: {ffmpeg_exists}")
989977

990-
# 检查FFprobe.exe文件是否存在(先检查配置路径,再检查环境变量,最后检查bin/llbot/ffprobe.exe
991-
ffprobe_exists = self.downloader.check_file_exists(ffprobe_path)
992-
if not ffprobe_exists:
978+
# 检查FFprobe.exe是否存在(先检查环境变量,再检查bin/llbot/)
979+
ffprobe_exists = self.downloader.check_ffprobe_exists()
980+
if ffprobe_exists:
993981
system_ffprobe = self.downloader.check_ffprobe_available()
994982
if system_ffprobe:
995983
logger.info(f"在系统PATH中找到FFprobe: {system_ffprobe}")
996-
ffprobe_exists = True
997-
config["ffprobe_path"] = system_ffprobe
998-
self.config_manager.save_config(config)
999984
else:
1000-
local_ffprobe_path = "bin/llbot/ffprobe.exe"
1001-
if self.downloader.check_file_exists(local_ffprobe_path):
1002-
logger.info(f"在本地目录找到FFprobe: {local_ffprobe_path}")
1003-
ffprobe_exists = True
1004-
config["ffprobe_path"] = local_ffprobe_path
1005-
self.config_manager.save_config(config)
985+
logger.info("在本地目录找到FFprobe: bin/llbot/ffprobe.exe")
1006986
logger.info(f"FFprobe.exe可用: {ffprobe_exists}")
1007987

1008988
# 检查LLBot文件是否存在
@@ -1108,10 +1088,8 @@ def progress_callback(downloaded: int, total: int):
11081088
if not node_exists:
11091089
self._show_node_download_dialog()
11101090
else:
1111-
ffmpeg_path = config.get("ffmpeg_path", DEFAULT_CONFIG["ffmpeg_path"])
1112-
ffprobe_path = config.get("ffprobe_path", DEFAULT_CONFIG["ffprobe_path"])
1113-
ffmpeg_exists = self.downloader.check_file_exists(ffmpeg_path)
1114-
ffprobe_exists = self.downloader.check_file_exists(ffprobe_path)
1091+
ffmpeg_exists = self.downloader.check_ffmpeg_exists()
1092+
ffprobe_exists = self.downloader.check_ffprobe_exists()
11151093

11161094
if not ffmpeg_exists or not ffprobe_exists:
11171095
self._show_ffmpeg_download_dialog()
@@ -1311,11 +1289,8 @@ def progress_callback(downloaded: int, total: int):
13111289
if self.page:
13121290
self.page.pop_dialog()
13131291

1314-
config = self.config_manager.load_config()
1315-
ffmpeg_path = config.get("ffmpeg_path", DEFAULT_CONFIG["ffmpeg_path"])
1316-
ffprobe_path = config.get("ffprobe_path", DEFAULT_CONFIG["ffprobe_path"])
1317-
ffmpeg_exists = self.downloader.check_file_exists(ffmpeg_path)
1318-
ffprobe_exists = self.downloader.check_file_exists(ffprobe_path)
1292+
ffmpeg_exists = self.downloader.check_ffmpeg_exists()
1293+
ffprobe_exists = self.downloader.check_ffprobe_exists()
13191294

13201295
if not ffmpeg_exists or not ffprobe_exists:
13211296
self._show_ffmpeg_download_dialog()

ui/main_window.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ def build(self, page: ft.Page):
140140
self.about_page.config_manager = self.config_manager
141141
self.about_page.build(page)
142142

143+
# 注册更新发现回调,同时通知首页和关于页面
144+
self.update_manager.set_updates_found_callback(self._on_updates_found)
145+
143146
# 创建导航栏
144147
self.nav_rail = ft.NavigationRail(
145148
selected_index=0,
@@ -373,6 +376,14 @@ def _update_home_title(self, uin: str, nickname: str):
373376
def _on_about_page_update_complete(self, component: str):
374377
self.home_page.clear_update_banner(component)
375378

379+
def _on_updates_found(self, updates_found: list):
380+
if self.page:
381+
async def notify_pages():
382+
self.about_page.set_updates_found(updates_found)
383+
if self.page:
384+
self.page.update()
385+
self.page.run_task(notify_pages)
386+
376387
def _on_restart_service_after_update(self):
377388
import logging
378389
logger = logging.getLogger(__name__)

utils/constants.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
"pmhq_path": "bin/pmhq/pmhq-win-x64.exe",
2020
"llbot_path": "bin/llbot/llbot.js",
2121
"node_path": "bin/llbot/node.exe",
22-
"ffmpeg_path": "bin/llbot/ffmpeg.exe",
23-
"ffprobe_path": "bin/llbot/ffprobe.exe",
2422
"auto_start_pmhq": False,
2523
"auto_start_llbot": False,
2624
"auto_start_bot": False,

utils/downloader.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ def check_ffmpeg_available(self) -> Optional[str]:
7070
def check_ffprobe_available(self) -> Optional[str]:
7171
return self.find_in_path("ffprobe.exe") or self.find_in_path("ffprobe")
7272

73+
def check_ffmpeg_exists(self) -> bool:
74+
"""先检查环境变量,再检查 bin/llbot/"""
75+
return bool(self.check_ffmpeg_available()) or self.check_file_exists("bin/llbot/ffmpeg.exe")
76+
77+
def check_ffprobe_exists(self) -> bool:
78+
"""先检查环境变量,再检查 bin/llbot/"""
79+
return bool(self.check_ffprobe_available()) or self.check_file_exists("bin/llbot/ffprobe.exe")
80+
7381
def _get_npm_tarball_url(self, package_name: str) -> str:
7482
return get_package_tarball_url(
7583
package_name,

0 commit comments

Comments
 (0)