Notifications
Wails provides a comprehensive cross-platform notification system for desktop applications. This runtime allows you to display native system notifications with support for interactive elements like action buttons and text input fields.
Notifications are currently unsupported in the JS runtime.
Basic Usage
Initializing Notifications
First, initialize the notification system. This should be called during app startup (typically in OnStartup):
err := runtime.InitializeNotifications(a.ctx)
if err != nil {
// Handle initialization error
// On macOS, this may fail if bundle identifier is not set
}
Then, check if notifications are available on the current platform:
if runtime.IsNotificationAvailable(a.ctx) {
// Notifications are supported
// On macOS, this checks for macOS 10.14+
// On Windows and Linux, this always returns true
}
On macOS, you'll need to request permission before sending notifications:
authorized, err := runtime.CheckNotificationAuthorization(a.ctx)
if err != nil {
// Handle authorization error
}
if !authorized {
authorized, err = runtime.RequestNotificationAuthorization(a.ctx)
if err != nil || !authorized {
// Handle permission denial
}
}
On Windows and Linux, authorization is not required as these platforms don't have permission systems.
Sending Basic Notifications
Send a basic notification with a unique ID, title, optional subtitle (macOS and Linux), and body text:
err := runtime.SendNotification(a.ctx, runtime.NotificationOptions{
ID: "calendar-invite-001",
Title: "New Calendar Invite",
Subtitle: "From: Jane Doe", // Optional - macOS and Linux only
Body: "Tap to view the event",
})
if err != nil {
// Handle error
}
Interactive Notifications
Interactive notifications allow users to respond with button actions or text input. You must first register a notification category that defines the available actions.
Creating Notification Categories
Define a category with action buttons and optional text input:
categoryID := "message-category"
category := runtime.NotificationCategory{
ID: categoryID,
Actions: []runtime.NotificationAction{
{
ID: "OPEN",
Title: "Open",
},
{
ID: "ARCHIVE",
Title: "Archive",
Destructive: true, // macOS-specific - shows as red button
},
},
HasReplyField: true,
ReplyPlaceholder: "Type your reply...",
ReplyButtonTitle: "Reply",
}
err := runtime.RegisterNotificationCategory(a.ctx, category)
if err != nil {
// Handle error
}
Sending Interactive Notifications
Send an interactive notification using the registered category. If the category is not found or CategoryID is empty, a basic notification will be sent instead:
err := runtime.SendNotificationWithActions(a.ctx, runtime.NotificationOptions{
ID: "message-001",
Title: "New Message",
Subtitle: "From: John Smith", // Optional - macOS and Linux only
Body: "Hey, are you free for lunch?",
CategoryID: categoryID,
})
if err != nil {
// Handle error
}
Handling Notification Responses
Listen for user interactions with notifications by registering a callback:
runtime.OnNotificationResponse(a.ctx, func(result runtime.NotificationResult) {
if result.Error != nil {
// Handle response error
return
}
response := result.Response
fmt.Printf("Notification %s was actioned with: %s\n",
response.ID, response.ActionIdentifier)
if response.ActionIdentifier == "TEXT_REPLY" {
fmt.Printf("User replied: %s\n", response.UserText)
}
// You can also emit events to the frontend
runtime.EventsEmit(a.ctx, "notification", response)
})
Adding Custom Data
Basic and interactive notifications can include custom data that will be returned in the response:
err := runtime.SendNotification(a.ctx, runtime.NotificationOptions{
ID: "event-001",
Title: "Team Meeting",
Subtitle: "In 30 minutes",
Body: "Don't forget your presentation materials!",
Data: map[string]interface{}{
"eventId": "meeting-123",
"startTime": "2024-01-15T14:00:00Z",
"attendees": []string{"john@company.com", "jane@company.com"},
"priority": "high",
},
})
// In the response handler:
runtime.OnNotificationResponse(a.ctx, func(result runtime.NotificationResult) {
response := result.Response
if eventId, ok := response.UserInfo["eventId"].(string); ok {
fmt.Printf("Event ID: %s\n", eventId)
}
})