Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/expo/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@knocklabs/expo",
"version": "0.4.0",
"version": "0.5.0",
"author": "@knocklabs",
"license": "MIT",
"main": "dist/cjs/index.js",
Expand Down Expand Up @@ -73,6 +73,7 @@
"expo": "~53.0.22",
"expo-constants": "~17.1.7",
"expo-device": "^7.1.4",
"expo-network": "^8.0.0",
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's probably a breaking change

"expo-notifications": "^0.31.4",
"jsdom": "^27.1.0",
"react": "^19.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from "@knocklabs/react-native";
import Constants from "expo-constants";
import * as Device from "expo-device";
import * as Network from "expo-network";
import * as Notifications from "expo-notifications";
import React, {
createContext,
Expand Down Expand Up @@ -127,6 +128,7 @@ const InternalKnockExpoPushNotificationProvider: React.FC<
usePushNotifications();
const [expoPushToken, setExpoPushToken] = useState<string | null>(null);
const knockClient = useKnockClient();
const { isInternetReachable } = Network.useNetworkState();

const [notificationReceivedHandler, setNotificationReceivedHandler] =
useState<(notification: Notifications.Notification) => void>(
Expand Down Expand Up @@ -188,12 +190,56 @@ const InternalKnockExpoPushNotificationProvider: React.FC<
[knockClient],
);

useEffect(() => {
if (expoPushToken) {
return;
}

const fetchExpoTokenIfNeeded = async () => {
const { status: existingStatus } =
await Notifications.getPermissionsAsync();
if (
existingStatus === "granted" &&
Device.isDevice &&
isInternetReachable
) {
try {
const token = await getExpoPushToken();
setExpoPushToken(token ? token.data : null);
} catch (error) {
console.error(`[Knock] Error getting expo push token:`, error);
}
}
};

fetchExpoTokenIfNeeded();
}, [isInternetReachable, expoPushToken]);

useEffect(() => {
Notifications.setNotificationHandler({
handleNotification:
customNotificationHandler ?? defaultNotificationHandler,
});

const response = Notifications.getLastNotificationResponse();
if (response?.notification) {
knockClient.log(
"[Knock] Expo Push Notification was interacted with (initial)",
);
updateKnockMessageStatusFromNotification(
response.notification,
"interacted",
);
notificationTappedHandler(response);
}
}, [
customNotificationHandler,
knockClient,
notificationTappedHandler,
updateKnockMessageStatusFromNotification,
]);

useEffect(() => {
if (autoRegister) {
registerForPushNotifications()
.then(() => {
Expand Down Expand Up @@ -241,18 +287,16 @@ const InternalKnockExpoPushNotificationProvider: React.FC<
notificationReceivedSubscription.remove();
notificationResponseSubscription.remove();
};

// TODO: Remove when possible and ensure dependency array is correct
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
registerForPushNotifications,
notificationReceivedHandler,
notificationTappedHandler,
customNotificationHandler,
autoRegister,
expoPushToken,
knockExpoChannelId,
knockClient,
registerPushTokenToChannel,
updateKnockMessageStatusFromNotification,
]);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface KnockPushNotificationContextType {
registerPushTokenToChannel(
token: string,
channelId: string,
locale?: string,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the locale in our app can be overridden (not system wide) and at the moment there is no way to tell knock about the custom user's locale

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let me know if you want me to split this pr into multiple

): Promise<ChannelData | void>;
unregisterPushTokenFromChannel(
token: string,
Expand Down Expand Up @@ -44,10 +45,14 @@ export const KnockPushNotificationProvider: React.FC<

// Acts like an upsert. Inserts or updates
const registerPushTokenToChannel = useCallback(
async (token: string, channelId: string): Promise<ChannelData | void> => {
async (
token: string,
channelId: string,
locale: string = Intl.DateTimeFormat().resolvedOptions().locale,
): Promise<ChannelData | void> => {
const newDevice: Device = {
token,
locale: Intl.DateTimeFormat().resolvedOptions().locale,
locale,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
};

Expand Down
11 changes: 11 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4071,6 +4071,7 @@ __metadata:
expo: "npm:~53.0.22"
expo-constants: "npm:~17.1.7"
expo-device: "npm:^7.1.4"
expo-network: "npm:^8.0.0"
expo-notifications: "npm:^0.31.4"
jsdom: "npm:^27.1.0"
react: "npm:^19.0.0"
Expand Down Expand Up @@ -12061,6 +12062,16 @@ __metadata:
languageName: node
linkType: hard

"expo-network@npm:^8.0.0":
version: 8.0.8
resolution: "expo-network@npm:8.0.8"
peerDependencies:
expo: "*"
react: "*"
checksum: 10c0/e12e4d136dae02e22ceaf0344ed7ee053e5aed126a71e69718c91bf7161c8bc97f745eec6e794f66e60cfba44d341b4462ce2987c958671a80fc5bea85dd124d
languageName: node
linkType: hard

"expo-notifications@npm:^0.31.4":
version: 0.31.4
resolution: "expo-notifications@npm:0.31.4"
Expand Down