68 lines
1.9 KiB
Go
68 lines
1.9 KiB
Go
//go:build windows
|
||
|
||
package platform
|
||
|
||
import (
|
||
"os"
|
||
"path/filepath"
|
||
"sync"
|
||
|
||
toast "git.sr.ht/~jackmordaunt/go-toast/v2"
|
||
"golang.org/x/sys/windows/registry"
|
||
)
|
||
|
||
const (
|
||
// toastAppID 是稳定的内部 AppUserModelID;Windows 通知设置中的用户可见名称由
|
||
// toastDisplayName 单独写入 DisplayName,避免为了改显示名破坏系统身份。
|
||
toastAppID = "net.commilitia.cdrop"
|
||
toastDisplayName = "Commilitia Drop"
|
||
// toastGUID 固定不变——它把通知归属到注册表里的本应用条目;更换会让既有通知
|
||
// 失去归属。
|
||
toastGUID = "{c4d8e2a1-6b3f-4e7a-9c2d-1f5b8a0e3d6c}"
|
||
)
|
||
|
||
var toastInit sync.Once
|
||
|
||
// InitializeNotifications registers the stable Windows notification identity
|
||
// and corrects its user-visible name. It is safe to call repeatedly.
|
||
func InitializeNotifications() {
|
||
toastInit.Do(func() {
|
||
data := toast.AppData{AppID: toastAppID, GUID: toastGUID}
|
||
if exe, err := os.Executable(); err == nil {
|
||
data.ActivationExe = exe
|
||
}
|
||
_ = toast.SetAppData(data)
|
||
|
||
// go-toast v2.0.3 没有独立 DisplayName 字段,会把 AppID 写进
|
||
// DisplayName,且已有值时不更新;在同一稳定键上显式覆盖显示名。
|
||
appKey := filepath.Join(
|
||
"SOFTWARE",
|
||
"Classes",
|
||
"AppUserModelId",
|
||
toastAppID,
|
||
)
|
||
if key, err := registry.OpenKey(
|
||
registry.CURRENT_USER,
|
||
appKey,
|
||
registry.SET_VALUE,
|
||
); err == nil {
|
||
_ = key.SetStringValue("DisplayName", toastDisplayName)
|
||
_ = key.Close()
|
||
}
|
||
})
|
||
}
|
||
|
||
// Notify shows a native Windows toast. go-toast renders via the WinRT/COM path
|
||
// (PowerShell fallback when the AppID isn't registered), so it works without code
|
||
// signing — SmartScreen only gates the installer, not notifications. Best-effort:
|
||
// errors are swallowed.
|
||
func Notify(title, body string) {
|
||
InitializeNotifications()
|
||
n := toast.Notification{
|
||
AppID: toastAppID,
|
||
Title: title,
|
||
Body: body,
|
||
}
|
||
_ = n.Push()
|
||
}
|