diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/App.tsx | 8 | ||||
-rw-r--r-- | src/constants/api.ts | 4 | ||||
-rw-r--r-- | src/screens/onboarding/CategorySelection.tsx | 3 | ||||
-rw-r--r-- | src/screens/onboarding/Login.tsx | 3 | ||||
-rw-r--r-- | src/services/FCMService.ts | 177 | ||||
-rw-r--r-- | src/services/index.ts | 1 |
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'; |