aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShravya Ramesh <37447613+shravyaramesh@users.noreply.github.com>2020-12-29 11:41:57 -0800
committerGitHub <noreply@github.com>2020-12-29 14:41:57 -0500
commit05cd91206a6ce3361097d9eb408a447eae3d120e (patch)
tree1b8c5ba82358c3f9b393ea42d03b6c9c7219ce7f /src
parentefaa41884b5aa4b4704380eb3615d3801958a775 (diff)
[TMA-288] notifications frontend infra (#154)
* Configured settings to enable remote notifications * Added FCM services * Added background message handler + api calls * minor fixes * minor changes requested from pr
Diffstat (limited to 'src')
-rw-r--r--src/App.tsx8
-rw-r--r--src/constants/api.ts4
-rw-r--r--src/screens/onboarding/CategorySelection.tsx3
-rw-r--r--src/screens/onboarding/Login.tsx3
-rw-r--r--src/services/FCMService.ts177
-rw-r--r--src/services/index.ts1
6 files changed, 193 insertions, 3 deletions
diff --git a/src/App.tsx b/src/App.tsx
index e1cd83cc..92d26ba7 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,10 +1,16 @@
-import React from 'react';
+import React, {useEffect} from 'react';
import {NavigationContainer} from '@react-navigation/native';
import Routes from './routes';
import {Provider} from 'react-redux';
import store from './store/configureStore';
+import {fcmService} from './services/FCMService';
const App = () => {
+ useEffect(() => {
+ fcmService.setUpPushNotifications();
+ //If permissions are not there, deactivateFcmService
+ });
+
return (
/**
* This is the provider from the redux store, it acts as the root provider for our application
diff --git a/src/constants/api.ts b/src/constants/api.ts
index 890ef102..e1658993 100644
--- a/src/constants/api.ts
+++ b/src/constants/api.ts
@@ -1,5 +1,6 @@
// const BASE_URL: string = 'http://3.22.188.127/'; // prod server
const BASE_URL: string = 'http://127.0.0.1:8000/'; // local server
+
const API_URL: string = BASE_URL + 'api/';
export const LOGIN_ENDPOINT: string = API_URL + 'login/';
export const LOGOUT_ENDPOINT: string = API_URL + 'logout/';
@@ -28,6 +29,9 @@ export const BLOCK_USER_ENDPOINT: string = API_URL + 'block/';
export const PASSWORD_RESET_ENDPOINT: string = API_URL + 'password-reset/';
export const MOMENT_CATEGORY_ENDPOINT: string = API_URL + 'moment-category/';
+// Register as FCM device
+export const FCM_ENDPOINT: string = API_URL + 'fcm/';
+
// Register Social Link (Non-integrated)
export const LINK_SNAPCHAT_ENDPOINT: string = API_URL + 'link-sc/';
export const LINK_TIKTOK_ENDPOINT: string = API_URL + 'link-tt/';
diff --git a/src/screens/onboarding/CategorySelection.tsx b/src/screens/onboarding/CategorySelection.tsx
index f92b7e39..b9677ed4 100644
--- a/src/screens/onboarding/CategorySelection.tsx
+++ b/src/screens/onboarding/CategorySelection.tsx
@@ -21,7 +21,7 @@ import {MOMENT_CATEGORIES} from '../../constants';
import {OnboardingStackParams} from '../../routes';
import {StackNavigationProp} from '@react-navigation/stack';
import {getTokenOrLogout, userLogin} from '../../utils';
-import {postMomentCategories} from '../../services';
+import {fcmService, postMomentCategories} from '../../services';
import {updateMomentCategories} from '../../store/actions/momentCategories';
import {ScrollView} from 'react-native-gesture-handler';
@@ -135,6 +135,7 @@ const CategorySelection: React.FC<CategorySelectionProps> = ({
const token = await getTokenOrLogout(dispatch);
await postMomentCategories(selectedCategories, token);
userLogin(dispatch, {userId: userId, username: username});
+ fcmService.sendFcmTokenToServer();
} else {
dispatch(updateMomentCategories(selectedCategories, true, userId));
navigation.goBack();
diff --git a/src/screens/onboarding/Login.tsx b/src/screens/onboarding/Login.tsx
index 1315fdf5..3e59b00e 100644
--- a/src/screens/onboarding/Login.tsx
+++ b/src/screens/onboarding/Login.tsx
@@ -12,7 +12,7 @@ import {
KeyboardAvoidingView,
Platform,
} from 'react-native';
-
+import {fcmService} from '../../services';
import {OnboardingStackParams} from '../../routes/onboarding';
import {Background, TaggInput, SubmitButton} from '../../components';
import {usernameRegex, LOGIN_ENDPOINT} from '../../constants';
@@ -164,6 +164,7 @@ const Login: React.FC<LoginProps> = ({navigation}: LoginProps) => {
await AsyncStorage.setItem('userId', data.UserID);
await AsyncStorage.setItem('username', username);
userLogin(dispatch, {userId: data.UserID, username});
+ fcmService.sendFcmTokenToServer();
} catch (err) {
setUser(NO_USER);
console.log(data);
diff --git a/src/services/FCMService.ts b/src/services/FCMService.ts
new file mode 100644
index 00000000..11cb7510
--- /dev/null
+++ b/src/services/FCMService.ts
@@ -0,0 +1,177 @@
+import AsyncStorage from '@react-native-community/async-storage';
+import messaging from '@react-native-firebase/messaging';
+import {Platform} from 'react-native';
+import {getDeviceId, getDeviceName} from 'react-native-device-info';
+import {FCM_ENDPOINT} from '../constants';
+
+class FCMService {
+ setUpPushNotifications = () => {
+ // Requesting user to permit notifications
+ this.checkPermission();
+
+ // Registering with FCM to receive unique device/app token
+ this.registerAppWithFCM();
+
+ //Store registration_id/device token to AsyncStorage
+ this.getToken();
+
+ // Receive a notification
+ this.createNotificationListeners();
+
+ // // Schedule a local notification
+ // PushNotification.localNotificationSchedule({
+ // //... You can use all the options from localNotifications
+ // message: 'My Notification Message', // (required)
+ // date: new Date(Date.now() + 60 * 1000), // in 60 secs
+ // allowWhileIdle: false, // (optional) set notification to work while on doze, default: false
+ // });
+
+ // // Send local notification when app in foreground since remote notifications
+ // // aren't displayed when app is in the foreground
+ // PushNotification.localNotification({
+ // //... You can use all the options from localNotifications
+ // message: 'My Notification Message', // (required)
+ // date: new Date(Date.now() + 60 * 1000), // in 60 secs
+ // allowWhileIdle: false, // (optional) set notification to work while on doze, default: false
+ //});
+ };
+
+ registerAppWithFCM = async () => {
+ if (Platform.OS === 'ios') {
+ if (!messaging().isDeviceRegisteredForRemoteMessages) {
+ await messaging().registerDeviceForRemoteMessages();
+ }
+ await messaging().setAutoInitEnabled(true);
+ }
+ };
+
+ checkPermission = async () => {
+ try {
+ const permission = await messaging().hasPermission();
+ // Permission might be 0 (not allowed), 1 (allowed), -1(unknown)
+ if (permission !== 1) {
+ await messaging().requestPermission({
+ sound: true,
+ announcement: true,
+ badge: true,
+ alert: true,
+ });
+ }
+ } catch (error) {
+ console.log('[FCMService] Permission Rejected ', error);
+ }
+ };
+
+ // Receiving fcm unique device token to receive remote messages through fcm
+ getToken = async () => {
+ messaging()
+ .getToken()
+ .then(async (fcmToken) => {
+ if (fcmToken) {
+ await AsyncStorage.setItem('@fcmToken', fcmToken);
+ return fcmToken;
+ }
+ })
+ .catch((error) => {
+ console.log('[FCMService] getToken rejected', error);
+ });
+ return '';
+ };
+
+ sendFcmTokenToServer = async () => {
+ const registration_id: string | null = await AsyncStorage.getItem(
+ '@fcmToken',
+ );
+ const device_id = getDeviceId();
+ const type = Platform.OS;
+ let active: boolean = false;
+ let name: string = '';
+ await getDeviceName().then((deviceName) => {
+ name = deviceName;
+ });
+
+ await messaging()
+ .hasPermission()
+ .then((hasPermission) => {
+ active = hasPermission === 1;
+ });
+ const token = await AsyncStorage.getItem('token');
+
+ if (registration_id && type) {
+ let response = await fetch(FCM_ENDPOINT, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: 'Token ' + token,
+ },
+ body: JSON.stringify({
+ registration_id,
+ type,
+ device_id,
+ name,
+ active,
+ }),
+ });
+
+ if (response.status === 201) {
+ console.log('Successfully stored device token!');
+ } else {
+ console.log('Failed to store device token!');
+ console.log(response);
+ }
+ }
+ };
+
+ deactivateFcmService = async () => {
+ //Make PATCH call to deactivate device
+ console.log('Deactivating FCM device');
+ };
+
+ createNotificationListeners = () => {
+ // messaging().onNotificationOpenedApp((remoteMessage) => {
+ // console.log(
+ // '[FCMService] onNotificationOpenedApp Notification caused app to open',
+ // );
+ // if (remoteMessage) {
+ // const notification = remoteMessage.notification;
+ // onOpenNotification(notification);
+ // }
+ // });
+
+ // messaging()
+ // .getInitialNotification()
+ // .then((remoteMessage) => {
+ // console.log(
+ // '[FCMService] getInitialNotification Notification caused app to open',
+ // );
+
+ // if (remoteMessage) {
+ // const notification = remoteMessage.notification;
+ // onOpenNotification(notification);
+ // }
+ // });
+
+ messaging().onMessage((remoteMessage) => {
+ console.log('Received a remote notification!!');
+ if (remoteMessage) {
+ let notification = remoteMessage.notification;
+ let notificationId = remoteMessage.messageId;
+ console.log(
+ 'notificationsId: ',
+ notificationId,
+ ' notification: ',
+ notification,
+ );
+ }
+ });
+
+ messaging().onTokenRefresh((fcmToken) => {
+ AsyncStorage.setItem('@fcmToken', fcmToken).catch((err) => {
+ console.log('Failed to store new token!');
+ console.log(err);
+ });
+ });
+ };
+}
+
+export const fcmService = new FCMService();
diff --git a/src/services/index.ts b/src/services/index.ts
index d98996ba..81a09b92 100644
--- a/src/services/index.ts
+++ b/src/services/index.ts
@@ -6,3 +6,4 @@ export * from './UserFollowServices';
export * from './ReportingService';
export * from './BlockUserService';
export * from './MomentCategoryService';
+export * from './FCMService';