| 1 | //go:build windows |
| 2 | |
| 3 | package notify |
| 4 | |
| 5 | import ( |
| 6 | "path/filepath" |
| 7 | |
| 8 | "git.sr.ht/~jackmordaunt/go-toast/v2" |
| 9 | "golang.org/x/sys/windows/registry" |
| 10 | |
| 11 | "reasonix/internal/appidentity" |
| 12 | ) |
| 13 | |
| 14 | // PlatformSender delivers notifications through the Windows Toast API. |
| 15 | type PlatformSender struct{} |
| 16 | |
| 17 | // NewPlatformSender returns the best-effort sender for the current platform. |
| 18 | func NewPlatformSender() PlatformSender { |
| 19 | _ = registerDesktopNotifications(toast.SetAppData, setNotificationDisplayName) |
| 20 | return PlatformSender{} |
| 21 | } |
| 22 | |
| 23 | func (PlatformSender) Send(m Message) error { |
| 24 | notification := desktopNotification(m) |
| 25 | return notification.Push() |
| 26 | } |
| 27 | |
| 28 | func desktopNotification(m Message) toast.Notification { |
| 29 | return toast.Notification{ |
| 30 | AppID: appidentity.AppUserModelID, |
| 31 | Title: m.Title, |
| 32 | Body: m.Body, |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | func registerDesktopNotifications(register func(toast.AppData) error, displayName func(string, string) error) error { |
| 37 | if err := register(toast.AppData{AppID: appidentity.AppUserModelID}); err != nil { |
| 38 | return err |
| 39 | } |
| 40 | return displayName(appidentity.AppUserModelID, appidentity.DisplayName) |
| 41 | } |
| 42 | |
| 43 | // go-toast defaults DisplayName to the ID. Change only our new registration; |
| 44 | // the old "Reasonix" registration still belongs to installed Studio releases. |
| 45 | func setNotificationDisplayName(id, name string) error { |
| 46 | path := filepath.Join("Software", "Classes", "AppUserModelId", id) |
| 47 | key, err := registry.OpenKey(registry.CURRENT_USER, path, registry.SET_VALUE) |
| 48 | if err != nil { |
| 49 | return err |
| 50 | } |
| 51 | defer key.Close() |
| 52 | return key.SetStringValue("DisplayName", name) |
| 53 | } |
| 54 |