What changed in native-notify v5 and how to upgrade, including the breaking change to the five follow helpers.
Breaking change: the follow helpers
v5 is a drop-in upgrade except for registerFollowMasterID, registerFollowerID, postFollowingID, unfollowMasterID and updateFollowersList. They now return a NativeNotifyActionResult object instead of a string:
interface NativeNotifyActionResult {
success: boolean;
status:
| 'registered'
| 'already_registered'
| 'posted'
| 'already_posted'
| 'unfollowed'
| 'not_following'
| 'removed'
| 'not_found'
| 'error';
message: string; // the string the previous versions returned
error?: any; // the underlying failure, when status is 'error'
}
Before v5, the result was a plain string:
const result = await registerFollowMasterID('master-id', appId, appToken);
if (result === 'Follow Master Indie ID already registered.') {
// ...
}
In v5 it's an object:
const result = await registerFollowMasterID('master-id', appId, appToken);
if (result.success || result.status === 'already_registered') {
// registered now, or it already was — branch on result.status for details
}
if (result.status === 'error') {
console.warn(result.message, result.error);
}
message still holds the text previous versions returned, so most upgrades replace string checks with result.status or result.success. Network failures now surface as status: 'error' with the error attached, instead of being misreported as "already registered".
What's new in v5
| Export | What it does |
|---|---|
NativeNotify.init({ appId, appToken }) | Sets your credentials once at module scope. appId and appToken are then optional everywhere: plain functions (registerIndieID, the follow, inbox and send functions) read it. |
<NativeNotifyProvider appId appToken> | The same for hooks and components, as a React provider. They read it first, then NativeNotify.init(). |
useNativeNotify() | Reads the active { appId, appToken } config inside a component. |
useNativeNotifyPress<T>() | Cold-start-safe notification tap handling. See Push data & taps. |
registerForPushNotificationsAsync() | The raw token flow, exported. It never throws and reports { status, reason, expoPushToken, ... }. |
getNotificationInboxPage() / getIndieNotificationInboxPage() | One page of inbox rows plus the server's total row count: { rows, total }. |
Also new, and not breaking:
registerNNPushToken(appId, appToken, options)takes an optional third argument:{ onRegistered, onError, watchTokenRotation }.- The notification inbox syncs the unread count to the app icon badge (
syncBadge, defaulttrue), and both inboxes support exact pagination through the new page functions.
v5.1: analytics
Adds opt-in analytics: trackScreen and useNativeNotifyScreenTracking (screen views), session tracking, push-open reporting, the stable deviceId option, and the analytics flags on NativeNotify.init and registerNNPushToken. Everything is off by default. See Analytics.
v5.1.1: token-rotation stability
The token-rotation listener skips no-op same-token events, checks at most once per minute, never overlaps, and re-registers only when the token payload changed. There are no API changes. Upgrade if you're on 5.0.x or 5.1.0.
v5.2: inbox read state, rich fields, Android channels
Every change is additive: existing calls make the same requests.
npm install native-notify@^5.2.0
-
Per-notification inbox read state. The prebuilt inbox accepts
perNotificationRead(off by default), anduseNotificationInbox()also returnsperNotificationReadandmarkNotificationRead(). For custom UIs, the page functions take{ perNotification: true }aftertakeandskip, and two new helpers mark one row read. They resolvefalsewithout sending anything whennotificationIdis missing. See the indie and mass inbox pages.getNotificationInboxPage(appId, appToken, take, skip, { perNotification: true }) getIndieNotificationInboxPage(subId, appId, appToken, take, skip, { perNotification: true }) markMassNotificationRead(notificationId, appId?, appToken?) markIndieNotificationRead(notificationId, subId, appId?, appToken?) -
Rich-field send helpers.
sendMassNotification,sendIndieNotification,sendIndieGroupNotificationandsendNotificationToFollowerspasssubtitle,badge,ttl,interruptionLevel,categoryId,channelId,collapseId,contentAvailable,mutableContentandsoundto every send path.setAndroidNotificationChannel()creates the channel achannelIdrefers to. See Rich notifications. -
New types:
RichPushFields,SendNotificationOptions,AndroidNotificationChannelOptionsandPerNotificationReadOptions.
Fixes in 5.2 only change requests for apps that turned analytics on, which now send the events they asked for:
- Analytics reports (screens, sessions, opens) work when the ids are passed only to
registerNNPushToken(appId, appToken, { analytics }). 5.1 dropped them unlessNativeNotify.init()had the ids. That call's flags and ids now apply before the components under it mount, so a cold-start tap or the first tracked screen isn't lost. useNativeNotifyScreenTracking(() => currentRouteName)(React Navigation, or any navigator other than Expo Router) tracks every screen change. 5.1 tracked only the first.sendMassNotificationstamps the inbox date.
v5.3: paired-token registration
Additive. Registrations send a device's Expo and native tokens together as an optional devicePair, and you change no code. See Paired-token registration.