feat: 统一 Commilitia Drop 全客户端命名与分发

This commit is contained in:
2026-07-31 22:56:10 +08:00
parent f7b0f04c9c
commit c480f0d1c2
77 changed files with 861 additions and 263 deletions
+34 -9
View File
@@ -4,14 +4,18 @@ package platform
import (
"os"
"path/filepath"
"sync"
toast "git.sr.ht/~jackmordaunt/go-toast/v2"
"golang.org/x/sys/windows/registry"
)
const (
// toastAppID 是 Windows Action Center 里显示的应用标识,与 macOS bundle id 对齐。
toastAppID = "net.commilitia.cdrop"
// toastAppID 是稳定的内部 AppUserModelIDWindows 通知设置中的用户可见名称由
// toastDisplayName 单独写入 DisplayName,避免为了改显示名破坏系统身份。
toastAppID = "net.commilitia.cdrop"
toastDisplayName = "Commilitia Drop"
// toastGUID 固定不变——它把通知归属到注册表里的本应用条目;更换会让既有通知
// 失去归属。
toastGUID = "{c4d8e2a1-6b3f-4e7a-9c2d-1f5b8a0e3d6c}"
@@ -19,20 +23,41 @@ const (
var toastInit sync.Once
// 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. SetAppData registers the app identity once so the toast
// shows "cdrop" rather than the PowerShell host.
func Notify(title, body string) {
// 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,