Skip to content
Merged
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
69 changes: 31 additions & 38 deletions docs/pages/push-notifications/push-notifications-setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ If you need finer-grained control over your notifications, communicating directl
</Collapsible>

<Prerequisites>
<Requirement title="A physical Android or iOS device">
Push notifications are not supported on Android Emulators or iOS Simulators. You will need a
real device to test.
<Requirement title="A device or emulator/simulator that supports push">
You can test push notifications on a physical Android or iOS device, on an Android Emulator with
Google Play services, or on an iOS Simulator running on Xcode 14 or later (macOS 13+, iOS 16+).
</Requirement>
</Prerequisites>

Expand All @@ -48,12 +48,11 @@ The following steps in this guide use [EAS Build](/build/introduction/). This is

## Install libraries

Run the following command to install the `expo-notifications`, `expo-device` and `expo-constants` libraries:
Run the following command to install the `expo-notifications` and `expo-constants` libraries:

<Terminal cmd={['$ npx expo install expo-notifications expo-device expo-constants']} />
<Terminal cmd={['$ npx expo install expo-notifications expo-constants']} />

- [`expo-notifications`](/versions/latest/sdk/notifications) library is used to request a user's permission and to obtain the `ExpoPushToken` for sending push notifications.
- [`expo-device`](/versions/latest/sdk/device) is used to check whether the app is running on a physical device.
- [`expo-constants`](/versions/latest/sdk/constants) is used to get the `projectId` value from the app config.

</Step>
Expand Down Expand Up @@ -88,7 +87,6 @@ The code below shows a working example of how to register for, send, and receive
```tsx App.tsx
import { useState, useEffect } from 'react';
import { Text, View, Button, Platform } from 'react-native';
import * as Device from 'expo-device';
import * as Notifications from 'expo-notifications';
import Constants from 'expo-constants';

Expand Down Expand Up @@ -140,37 +138,32 @@ async function registerForPushNotificationsAsync() {
});
}

if (Device.isDevice) {
const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== 'granted') {
handleRegistrationError('Permission not granted to get push token for push notification!');
return;
}
const projectId =
Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId;
if (!projectId) {
handleRegistrationError('Project ID not found');
}
try {
/* @info This fetches the Expo push token (if not previously fetched), which is unique to this device and projectID. */
const pushTokenString = (
await Notifications.getExpoPushTokenAsync({
projectId,
})
).data;
/* @end */
console.log(pushTokenString);
return pushTokenString;
} catch (e: unknown) {
handleRegistrationError(`${e}`);
}
} else {
handleRegistrationError('Must use physical device for push notifications');
const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== 'granted') {
handleRegistrationError('Permission not granted to get push token for push notification!');
return;
}
const projectId = Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId;
if (!projectId) {
handleRegistrationError('Project ID not found');
}
try {
/* @info This fetches the Expo push token (if not previously fetched), which is unique to this device and projectID. */
const pushTokenString = (
await Notifications.getExpoPushTokenAsync({
projectId,
})
).data;
/* @end */
console.log(pushTokenString);
return pushTokenString;
} catch (e: unknown) {
handleRegistrationError(`${e}`);
}
}

Expand Down
63 changes: 29 additions & 34 deletions docs/pages/versions/unversioned/sdk/notifications.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: A library that provides an API to fetch push notification tokens an
sourceCodeUrl: 'https://github.com/expo/expo/tree/main/packages/expo-notifications'
packageName: 'expo-notifications'
iconUrl: '/static/images/packages/expo-notifications.png'
platforms: ['android*', 'ios*']
platforms: ['android', 'ios']
---

import { NotificationBoxIcon } from '@expo/styleguide-icons/outline/NotificationBoxIcon';
Expand Down Expand Up @@ -65,14 +65,13 @@ This issue only affects debug builds and does not occur in release builds. To wo

## Usage

Check out the example Snack below to see Notifications in action, make sure to use a physical device to test it. Push notifications don't work on emulators/simulators.
Check out the example Snack below to see Notifications in action. Push notifications work on physical devices, Android emulators with Google Play services, and iOS simulators on Xcode 14 or later (macOS 13+, iOS 16+).

<SnackInline label='Push Notifications' dependencies={['expo-device', 'expo-constants', 'expo-notifications']}>
<SnackInline label='Push Notifications' dependencies={['expo-constants', 'expo-notifications']}>

```tsx
import { useState, useEffect } from 'react';
import { Text, View, Button, Platform } from 'react-native';
import * as Device from 'expo-device';
import * as Notifications from 'expo-notifications';
import Constants from 'expo-constants';

Expand Down Expand Up @@ -166,37 +165,33 @@ async function registerForPushNotificationsAsync() {
});
}

if (Device.isDevice) {
const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== 'granted') {
alert('Failed to get push token for push notification!');
return;
}
// Learn more about projectId:
// https://docs.expo.dev/push-notifications/push-notifications-setup/#configure-projectid
// EAS projectId is used here.
try {
const projectId =
Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId;
if (!projectId) {
throw new Error('Project ID not found');
}
token = (
await Notifications.getExpoPushTokenAsync({
projectId,
})
).data;
console.log(token);
} catch (e) {
token = `${e}`;
const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== 'granted') {
alert('Failed to get push token for push notification!');
return;
}
// Learn more about projectId:
// https://docs.expo.dev/push-notifications/push-notifications-setup/#configure-projectid
// EAS projectId is used here.
try {
const projectId =
Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId;
if (!projectId) {
throw new Error('Project ID not found');
}
} else {
alert('Must use physical device for Push Notifications');
token = (
await Notifications.getExpoPushTokenAsync({
projectId,
})
).data;
console.log(token);
} catch (e) {
token = `${e}`;
}

return token;
Expand Down
69 changes: 10 additions & 59 deletions docs/pages/versions/unversioned/sdk/ui/swift-ui/datepicker.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,12 @@ export default function GraphicalDatePickerExample() {

## Disabled picker

You can make the picker non-interactive using the `disabled` modifier.

```tsx DisabledDatePickerExample.tsx
import { useState } from 'react';
import { Host, DatePicker } from '@expo/ui/swift-ui';
import { disabled } from '@expo/ui/swift-ui/modifiers';

export default function DisabledDatePickerExample() {
const [selectedDate, setSelectedDate] = useState(new Date());
Expand All @@ -185,61 +188,7 @@ export default function DisabledDatePickerExample() {
onDateChange={date => {
setSelectedDate(date);
}}
disabled
/>
</Host>
);
}
```

## Custom locale

Use the `locale` prop to display the picker in a specific locale.

```tsx LocaleDatePickerExample.tsx
import { useState } from 'react';
import { Host, DatePicker } from '@expo/ui/swift-ui';

export default function LocaleDatePickerExample() {
const [selectedDate, setSelectedDate] = useState(new Date());

return (
<Host matchContents>
<DatePicker
title="Sélectionner la date"
selection={selectedDate}
displayedComponents={['date']}
onDateChange={date => {
setSelectedDate(date);
}}
locale="fr_FR"
/>
</Host>
);
}
```

## Custom time zone

Use the `timeZone` prop to display the picker in a specific IANA time zone.

```tsx TimeZoneDatePickerExample.tsx
import { useState } from 'react';
import { Host, DatePicker } from '@expo/ui/swift-ui';

export default function TimeZoneDatePickerExample() {
const [selectedDate, setSelectedDate] = useState(new Date());

return (
<Host matchContents>
<DatePicker
title="Tokyo time"
selection={selectedDate}
displayedComponents={['date', 'hourAndMinute']}
onDateChange={date => {
setSelectedDate(date);
}}
timeZone="Asia/Tokyo"
modifiers={[disabled()]}
/>
</Host>
);
Expand All @@ -248,11 +197,12 @@ export default function TimeZoneDatePickerExample() {

## Custom locale

Use the `locale` prop to display the picker in a specific locale.
Apply the `environment` modifier with the `locale` key to display the picker in a specific locale.

```tsx LocaleDatePickerExample.tsx
import { useState } from 'react';
import { Host, DatePicker } from '@expo/ui/swift-ui';
import { environment } from '@expo/ui/swift-ui/modifiers';

export default function LocaleDatePickerExample() {
const [selectedDate, setSelectedDate] = useState(new Date());
Expand All @@ -266,7 +216,7 @@ export default function LocaleDatePickerExample() {
onDateChange={date => {
setSelectedDate(date);
}}
locale="fr_FR"
modifiers={[environment('locale', 'fr_FR')]}
/>
</Host>
);
Expand All @@ -275,11 +225,12 @@ export default function LocaleDatePickerExample() {

## Custom time zone

Use the `timeZone` prop to display the picker in a specific IANA time zone.
Apply the `environment` modifier with the `timeZone` key to display the picker in a specific IANA time zone.

```tsx TimeZoneDatePickerExample.tsx
import { useState } from 'react';
import { Host, DatePicker } from '@expo/ui/swift-ui';
import { environment } from '@expo/ui/swift-ui/modifiers';

export default function TimeZoneDatePickerExample() {
const [selectedDate, setSelectedDate] = useState(new Date());
Expand All @@ -293,7 +244,7 @@ export default function TimeZoneDatePickerExample() {
onDateChange={date => {
setSelectedDate(date);
}}
timeZone="Asia/Tokyo"
modifiers={[environment('timeZone', 'Asia/Tokyo')]}
/>
</Host>
);
Expand Down
Loading
Loading