ToastNotificationChangedEvent
ToastNotificationChangedEvent
Info
ToastNotificationChangedEvent is the event data interface passed to the callback registered with startListening(). It describes a single change — a notification being added or removed — in the Windows toast notification stream.
Interface Introduction
When you call startListening() and supply a callback, the system invokes that callback each time a toast notification appears or disappears. Each invocation delivers a ToastNotificationChangedEvent object so your code can identify what changed and react accordingly.
This interface is purely a data carrier; you do not instantiate it yourself. It arrives from the native listener layer.
Properties
| Property | Type | Description |
|---|---|---|
kind | ToastNotificationChangeKind | The type of change: 'added' when a new notification appears, 'removed' when one is dismissed, or 'unknown' for unclassified events. |
notificationId | number | A unique numeric identifier for the affected notification. Use this ID to correlate with snapshot data from getNotifications(). |
Note
The notificationId is assigned by the Windows notification subsystem. It is only meaningful within the current listener session — do not persist it across app restarts.
Usage
The ToastNotificationChangedEvent is delivered inside the callback you pass to startListening(). A typical workflow:
- Call requestAccess() and verify the user has granted notification access.
- Call startListening() with a callback that receives
ToastNotificationChangedEvent. - Inside the callback, branch on
event.kindto handle additions and removals. - Optionally call getNotifications() to obtain a full snapshot with rich data (title, body, app name, etc.) and match by
event.notificationId. - Call stopListening() when you no longer need events.
Tips
If you need the full notification content (title, body, app display name), do not try to extract it from this event. Call getNotifications() and look up the entry whose id matches event.notificationId.
Tips
Debounce or throttle your callback logic if you expect a burst of notifications (e.g. a chat application receiving many messages at once). The native listener fires synchronously for each event.
Example
import {
requestAccess,
startListening,
stopListening,
getNotifications,
ToastNotificationChangedEvent,
ToastNotificationSnapshot,
} from '@eisland/windows-toast-listener';
// Step 1: Request permission to read toast notifications
const status = requestAccess();
if (status !== 'allowed') {
console.error('Notification access denied:', status);
process.exit(1);
}
// Step 2: Start listening for notification changes
const started = startListening((event: ToastNotificationChangedEvent) => {
// Branch on the type of change
if (event.kind === 'added') {
// A new notification appeared — fetch full details
const snapshots: ToastNotificationSnapshot[] = getNotifications();
const match = snapshots.find((n) => n.id === event.notificationId);
if (match) {
console.log(`New notification from ${match.appDisplayName}: ${match.title}`);
}
} else if (event.kind === 'removed') {
// A notification was dismissed
console.log(`Notification dismissed — ID ${event.notificationId}`);
}
});
if (!started) {
console.error('Failed to start listener');
}
// Step 3: Stop listening when done (e.g. on app shutdown)
// stopListening();const {
requestAccess,
startListening,
stopListening,
getNotifications,
} = require('@eisland/windows-toast-listener');
// Step 1: Request permission to read toast notifications
const status = requestAccess();
if (status !== 'allowed') {
console.error('Notification access denied:', status);
process.exit(1);
}
// Step 2: Start listening for notification changes
const started = startListening((event) => {
// Branch on the type of change
if (event.kind === 'added') {
// A new notification appeared — fetch full details
const snapshots = getNotifications();
const match = snapshots.find((n) => n.id === event.notificationId);
if (match) {
console.log(`New notification from ${match.appDisplayName}: ${match.title}`);
}
} else if (event.kind === 'removed') {
// A notification was dismissed
console.log(`Notification dismissed — ID ${event.notificationId}`);
}
});
if (!started) {
console.error('Failed to start listener');
}
// Step 3: Stop listening when done (e.g. on app shutdown)
// stopListening();Notes
Note
The callback is invoked on the native event loop thread. Avoid performing heavy synchronous work inside it — offload processing to a queue or use setTimeout/setImmediate if needed.
Note
If isSuppressionEnabled() returns true, toast popups are suppressed at the OS level, but the listener still receives 'added' and 'removed' events. Suppression only hides the visual toast, not the event stream.
Tips
Call isListening() before starting a second listener. Calling startListening() while already listening returns false and does not replace the existing callback. Always stopListening() first if you need to swap callbacks.
Danger Avoidance
Caution
Never forget to call stopListening(). Each active listener holds a native handle to the Windows notification subsystem. Failing to stop the listener when it is no longer needed leaks that handle and keeps your process tethered to the OS event source. Always clean up on app exit or when the feature is disabled.
Caution
Do not assume notificationId is globally unique across sessions. The ID is assigned per listener session by Windows. Persisting it to disk and referencing it in a future session will produce incorrect matches or no match at all. Always use getNotifications() for fresh data.
Caution
Notification access is a user-granted permission. If requestAccess() returns anything other than 'allowed', the listener will not deliver events. Never call startListening() without first verifying access status — the function may appear to succeed but the callback will never fire.
Changelog
4f6b6-on

