新增: 自动升级体系 + WorkerW重建检测 + 知识卡片优化

自动升级:
- 版本变量注入 (-ldflags -X main.version)
- 远程 version.json 检查 + 弹窗提示(非强制右下角/强制居中)
- updater.exe 嵌入主程序, 运行时释放到临时目录
- 下载+SHA256校验+备份+替换+回滚 全流程
- 托盘菜单"检查更新"

稳定性:
- WorkerW 重建自动检测(每10s)并重新嵌入
- 左键托盘点击防抖
- 设置窗口已打开时正确前置

优化:
- 知识卡片prompt改为面向开发者的硬核内容
- 配置目录统一到 ~/.u-desktop/
- 设置窗口WebView2数据目录改为configDir下
This commit is contained in:
2026-05-28 19:06:26 +08:00
parent aee7997195
commit f5a473c4b8
23 changed files with 859 additions and 90 deletions

View File

@@ -18,10 +18,35 @@ func onSystrayReady() {
systray.SetIcon(trayIcon)
systray.SetTooltip("动态壁纸引擎")
// 左键点击托盘图标 → 打开设置(防抖: 连续点击只响应一次)
go func() {
for range systray.TrayClickCh {
openSettingsWindow()
// 消费后续积压的点击
for {
select {
case <-systray.TrayClickCh:
default:
goto done
}
}
done:
}
}()
mSettings := systray.AddMenuItem("桌面设置", "打开设置窗口")
mCheckUpdate := systray.AddMenuItem("检查更新", "检查是否有新版本")
mRestart := systray.AddMenuItem("重启", "重启程序")
mQuit := systray.AddMenuItem("退出", "退出程序")
// 检查更新
go func() {
for {
<-mCheckUpdate.ClickedCh
manualCheckUpdate()
}
}()
// 设置窗口
go func() {
for {
@@ -53,6 +78,7 @@ func onSystrayReady() {
go bingWallpaperLoop()
go knowledgeLoop()
go startPhotoLoop()
go runAutoUpdateCheck()
}
func startWebView() {
@@ -89,10 +115,10 @@ func startWebView() {
wvHwnd = uintptr(wv.Window())
procShowWindow.Call(wvHwnd, 0) // SW_HIDE
procSetWindowLongPtrW.Call(wvHwnd, gwlStyle, wsPopup|wsVisible|wsChild)
procSetWindowLongPtrW.Call(wvHwnd, gwlExStyle, wsExTransparent|wsExLayered)
// 立即嵌入 WorkerW
procSetParent.Call(wvHwnd, workerw)
procMoveWindow.Call(wvHwnd, uintptr(^uint(0)), uintptr(^uint(0)), uintptr(screenW+2), uintptr(screenH+2), 1)
embedWorkerW(workerw, screenW, screenH)
log.Printf("已嵌入 WorkerW: HWND=0x%x, %dx%d", wvHwnd, screenW, screenH)
wv.Bind("setZodiacFromGo", func(zodiac string) error {
@@ -158,11 +184,35 @@ func startWebView() {
}
}
func embedWorkerW(workerw uintptr, screenW, screenH int32) {
procSetParent.Call(wvHwnd, workerw)
procMoveWindow.Call(wvHwnd, uintptr(^uint(0)), uintptr(^uint(0)), uintptr(screenW+2), uintptr(screenH+2), 1)
}
func fullscreenMonitor() {
type rect struct{ Left, Top, Right, Bottom int32 }
var lastState string
var lastParent uintptr
var parentTick int
for {
if atomic.LoadInt32(&paused) == 0 && wv != nil {
// 每 5 轮(10s)检测一次父窗口,极轻量系统调用
parentTick++
if parentTick >= 5 {
parentTick = 0
parent, _, _ := procGetParent.Call(wvHwnd)
if parent != lastParent {
lastParent = parent
ww := findWorkerW()
if ww != 0 && ww != parent {
screenW, screenH := getScreenSize()
embedWorkerW(ww, screenW, screenH)
procShowWindow.Call(wvHwnd, 5)
log.Printf("WorkerW 变更,已重新嵌入: 0x%x → 0x%x", parent, ww)
}
}
}
fg, _, _ := procGetForegroundWindow.Call()
if fg != 0 {
var r rect