1import React from 'react';
2import { Alert, ScrollView } from 'react-native';
3import { Notifications } from 'expo';
4import * as Permissions from 'expo-permissions';
5import HeadingText from '../components/HeadingText';
6import ListButton from '../components/ListButton';
7
8import registerForPushNotificationsAsync from '../api/registerForPushNotificationsAsync';
9
10export default class NotificationScreen extends React.Component {
11  static navigationOptions = {
12    title: 'Notifications',
13  };
14
15  render() {
16    return (
17      <ScrollView style={{ padding: 10 }}>
18        <HeadingText>Local Notifications</HeadingText>
19        <ListButton
20          onPress={this._presentLocalNotificationAsync}
21          title="Present a notification immediately"
22        />
23        <ListButton
24          onPress={this._scheduleLocalNotificationAsync}
25          title="Schedule notification for 10 seconds from now"
26        />
27        <ListButton
28          onPress={this._scheduleLocalNotificationAndCancelAsync}
29          title="Schedule notification for 10 seconds from now and then cancel it immediately"
30        />
31        <ListButton
32          onPress={Notifications.cancelAllScheduledNotificationsAsync}
33          title="Cancel all scheduled notifications"
34        />
35        <ListButton
36          onPress={this._scheduleLegacyNotificationAsync}
37          title="Schedule a notification with both `time` and `repeat` (deprecated on iOS)"
38        />
39        <ListButton
40          onPress={this._scheduleAndCancelLegacyNotificationAsync}
41          title="Schedule and immediately cancel notification with both `time` and `repeat` (deprecated on iOS)"
42        />
43
44        <HeadingText>Push Notifications</HeadingText>
45        <ListButton
46          onPress={this._sendNotificationAsync}
47          title="Send me a push notification"
48        />
49
50        <HeadingText>Custom notification categories</HeadingText>
51        <ListButton
52          onPress={this._createCategoryAsync}
53          title="Create a custom 'message' category"
54        />
55        <ListButton
56          onPress={this._scheduleLocalNotificationWithCategoryAsync}
57          title="Schedule notification for 10 seconds from now with a 'message' category"
58        />
59        <ListButton
60          onPress={this._deleteCategoryAsync}
61          title="Delete the custom 'message' category"
62        />
63
64        <HeadingText>Badge Number</HeadingText>
65        <ListButton
66          onPress={this._incrementIconBadgeNumberAsync}
67          title="Increment the app icon's badge number"
68        />
69        <ListButton
70          onPress={this._clearIconBadgeAsync}
71          title="Clear the app icon's badge number"
72        />
73      </ScrollView>
74    );
75  }
76
77  _obtainUserFacingNotifPermissionsAsync = async () => {
78    let permission = await Permissions.getAsync(
79      Permissions.USER_FACING_NOTIFICATIONS
80    );
81    if (permission.status !== 'granted') {
82      permission = await Permissions.askAsync(
83        Permissions.USER_FACING_NOTIFICATIONS
84      );
85      if (permission.status !== 'granted') {
86        Alert.alert(`We don't have permission to present notifications.`);
87      }
88    }
89    return permission;
90  }
91
92  _obtainRemoteNotifPermissionsAsync = async () => {
93    let permission = await Permissions.getAsync(Permissions.NOTIFICATIONS);
94    if (permission.status !== 'granted') {
95      permission = await Permissions.askAsync(Permissions.NOTIFICATIONS);
96      if (permission.status !== 'granted') {
97        Alert.alert(
98          `We don't have permission to receive remote notifications.`
99        );
100      }
101    }
102    return permission;
103  }
104
105  _presentLocalNotificationAsync = async () => {
106    await this._obtainUserFacingNotifPermissionsAsync();
107    Notifications.presentLocalNotificationAsync({
108      title: 'Here is a local notification!',
109      body: 'This is the body',
110      data: {
111        hello: 'there',
112      },
113      ios: {
114        sound: true,
115      },
116    });
117  }
118
119  _scheduleLocalNotificationAsync = async () => {
120    await this._obtainUserFacingNotifPermissionsAsync();
121    Notifications.scheduleLocalNotificationAsync(
122      {
123        title: 'Here is a scheduled notifiation!',
124        body: 'This is the body',
125        data: {
126          hello: 'there',
127          future: 'self',
128        },
129        ios: {
130          sound: true,
131        },
132      },
133      {
134        time: new Date().getTime() + 10000,
135      }
136    );
137  }
138
139  _createCategoryAsync = () =>
140    Notifications.createCategoryAsync('message', [
141      {
142        actionId: 'dismiss',
143        buttonTitle: 'Dismiss notification',
144        isDestructive: true,
145        isAuthenticationRequired: false,
146      },
147      {
148        actionId: 'respond',
149        buttonTitle: 'Respond',
150        isDestructive: false,
151        isAuthenticationRequired: true,
152        textInput: {
153          submitButtonTitle: 'Send',
154          placeholder: 'Response',
155        },
156      },
157    ])
158
159  _deleteCategoryAsync = () => Notifications.deleteCategoryAsync('message');
160
161  _scheduleLocalNotificationWithCategoryAsync = async () => {
162    await this._obtainUserFacingNotifPermissionsAsync();
163
164    await Notifications.scheduleLocalNotificationAsync(
165      {
166        title: 'Expo sent you a message!',
167        body: 'Howdy, fella!',
168        ios: {
169          sound: true,
170        },
171        categoryId: 'message',
172      },
173      {
174        time: new Date().getTime() + 10000,
175      }
176    );
177  }
178
179  _scheduleLocalNotificationAndCancelAsync = async () => {
180    await this._obtainUserFacingNotifPermissionsAsync();
181    const notificationId = await Notifications.scheduleLocalNotificationAsync(
182      {
183        title: 'This notification should not appear',
184        body: 'It should have been cancelled. :(',
185        ios: {
186          sound: true,
187        },
188      },
189      {
190        time: new Date().getTime() + 10000,
191      }
192    );
193    await Notifications.cancelScheduledNotificationAsync(notificationId);
194  }
195
196  _scheduleLegacyNotificationAsync = async () => {
197    await this._obtainUserFacingNotifPermissionsAsync();
198    return Notifications.scheduleLocalNotificationAsync(
199      {
200        title: 'Repeating notification',
201        body: `I repeat every minute starting from ${new Date().toLocaleTimeString()}`,
202        data: {
203          repeatingEvery: 'minute',
204          scheduledAt: new Date().toLocaleTimeString(),
205        },
206        ios: {
207          sound: true,
208        },
209      },
210      {
211        time: new Date().getTime() + 2000,
212        repeat: 'minute',
213      }
214    );
215  }
216
217  _scheduleAndCancelLegacyNotificationAsync = async () => {
218    const notificationId = await this._scheduleLegacyNotificationAsync();
219    await Notifications.cancelScheduledNotificationAsync(notificationId);
220  }
221
222  _incrementIconBadgeNumberAsync = async () => {
223    const currentNumber = await Notifications.getBadgeNumberAsync();
224    await Notifications.setBadgeNumberAsync(currentNumber + 1);
225    const actualNumber = await Notifications.getBadgeNumberAsync();
226    Alert.alert(`Set the badge number to ${actualNumber}`);
227  }
228
229  _clearIconBadgeAsync = async () => {
230    await Notifications.setBadgeNumberAsync(0);
231    Alert.alert(`Cleared the badge`);
232  }
233
234  _sendNotificationAsync = async () => {
235    const permission = await this._obtainRemoteNotifPermissionsAsync();
236    if (permission.status === 'granted') {
237      registerForPushNotificationsAsync();
238    }
239  }
240}
241