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)
}
})
Managing Notifications
Removing Notification Categories
Remove a previously registered notification category:
err := runtime.RemoveNotificationCategory(a.ctx, "message-category")
Managing Notifications Lifecycle
Control notification visibility:
// Remove a specific pending notification (macOS and Linux only)
err := runtime.RemovePendingNotification(a.ctx, "notification-id")
// Remove all pending notifications (macOS and Linux only)
err = runtime.RemoveAllPendingNotifications(a.ctx)
// Remove a specific delivered notification (macOS and Linux only)
err = runtime.RemoveDeliveredNotification(a.ctx, "notification-id")
// Remove all delivered notifications (macOS and Linux only)
err = runtime.RemoveAllDeliveredNotifications(a.ctx)
// Remove a notification (Linux-specific)
err = runtime.RemoveNotification(a.ctx, "notification-id")
Platform Considerations
macOS
- Authorization Required: Apps must request notification permission
- Notarization: Required for app distribution on macOS
- Features: Supports subtitles, user text input, destructive actions, dark/light mode
- Behavior: Notifications appear in the system notification center
Windows
- No Authorization: No permission system required
- Features: Supports user text input, high DPI displays, Windows theme adaptation
- Limitations: Does not support subtitles
- Behavior: Uses Windows toast notifications
Linux
- Desktop Environment Dependent: Behavior varies by DE (GNOME, KDE, etc.)
- Features: Supports subtitles and themes
- Limitations: Does not support user text input
- Behavior: Uses native notification system when available
Best Practices
- Check Platform Support: Always verify notifications are available before using them
- Handle Authorization: Properly request and check permissions on macOS
- Use Descriptive Content: Provide clear titles, subtitles, and action button labels
- Handle Responses: Always implement proper error handling for notification responses
- Test Across Platforms: Verify functionality on your target platforms
- Clean Up: Remove old notification categories when they're no longer needed