notify.go (3683B)
1 // Package nativenotify offers a notification API that works across Windows, 2 // macOS and Linux. 3 // 4 // It provides a common subset, and is not trying to expose all underlying 5 // features. Not all fields are functional across all operating systems. 6 // 7 // Broadly, Windows likes to define buttons and text inputs separately, macOs 8 // defines them together, and Linux only supports buttons. 9 // 10 // Each operating system requires different setup data. This is handled by 11 // a call to [Setup] that accepts a fat-union containing all the data 12 // required by all operating systems. 13 // 14 // Generally each operating system will accept png icons as file paths, but 15 // other formats (eg webp) and path types (eg url) vary. 16 package nativenotify 17 18 import ( 19 "fmt" 20 21 darwinnotify "git.sr.ht/~jackmordaunt/go-notify-darwin" 22 windowsnotify "git.sr.ht/~jackmordaunt/go-toast/v2" 23 ) 24 25 // Callback is executed when the user interacts with a given notification. 26 // [action] is the activated action. 27 // [value] is any associated value for that action. 28 type Callback func(action, value string) 29 30 // Notification describes the notification. 31 type Notification struct { 32 // Callback is called upon activation. 33 Callback Callback 34 35 // Title text of the notification. 36 Title string 37 38 // Body text of the notification. 39 Body string 40 41 // Icon contains the path to an icon. Some operating systems accept url paths. 42 // All OS accept .png, other formats vary. 43 Icon string 44 45 // TextActions are for getting textual input from the user. 46 // Not supported on Linux. 47 TextActions []TextAction 48 49 // ButtonActions are for getting button input from the user. 50 ButtonActions []ButtonAction 51 52 // Windows defines windows specific options. 53 Windows WindowsOption 54 } 55 56 type WindowsOption int 57 58 const ( 59 WindowsOptionIconSquareCrop WindowsOption = iota 60 WindowsOptionIconCircleCrop 61 WindowsOptionIconHero 62 ) 63 64 // TextAction describes a text input. 65 // It might have an associated button. 66 // The user input text is passed to the callback on activation. 67 // Not all OS support this. 68 type TextAction struct { 69 // ID names the action. The user text will appear in the user data keyed by this ID. 70 ID string 71 // Title describes the title text of this action. 72 Title string 73 // PlaceholderHint will appear as the placeholder text within the text input. 74 // Not all OS support this. 75 PlaceholderHint string 76 // ButtonLabel describes the content of any related button that is associated with 77 // the text input. Not all OS support this. 78 ButtonLabel string 79 } 80 81 // ButtonAction describes a button input. 82 // [AppPayload] is passed to the callback on activation. 83 type ButtonAction struct { 84 // ID names the action. The [AppPayload] will appear in the user data keyed by this ID. 85 ID string 86 // Value is provided to the callback if this action is activated. 87 Value string 88 // LabelText describes the text content of this button action. 89 LabelText string 90 } 91 92 // Config is a fat-union of the various initialization data required by each 93 // operating system. 94 type Config struct { 95 Windows WindowsConfig 96 Linux LinuxConfig 97 Darwin DarwinConfig 98 } 99 100 type WindowsConfig = windowsnotify.AppData 101 102 type LinuxConfig struct { 103 AppName string 104 AppIcon string 105 } 106 107 type DarwinConfig struct { 108 Categories []darwinnotify.Category 109 } 110 111 // Setup initializes the notification subsystem. 112 func Setup(cfg Config) error { 113 return setup(cfg) 114 } 115 116 // Push a notification to the operating system. 117 func Push(n Notification) error { 118 for ii, a := range n.ButtonActions { 119 if a.ID == "" { 120 return fmt.Errorf("buttonaction %d requires ID", ii) 121 } 122 } 123 for ii, a := range n.TextActions { 124 if a.ID == "" { 125 return fmt.Errorf("text action %d requires ID", ii) 126 } 127 } 128 return push(n) 129 }