Commit c86a3d63 authored by Sébastiaan Versteeg's avatar Sébastiaan Versteeg

Add push notification functionality

parent c22cc3d8
......@@ -22,6 +22,10 @@ DerivedData
*.xcuserstate
project.xcworkspace
# Pods
#
ios/Pods
# Android/IntelliJ
#
build/
......
......@@ -141,11 +141,13 @@ android {
}
dependencies {
compile project(':react-native-fcm')
compile project(':react-native-linear-gradient')
compile project(':react-native-vector-icons')
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
compile "com.facebook.react:react-native:+" // From node_modules
compile 'com.google.firebase:firebase-core:11.4.0'
}
// Run this once to be able to run the application with BUCK
......@@ -162,3 +164,5 @@ gradle.projectsEvaluated {
processBuilder.start()
}
}
apply plugin: 'com.google.gms.google-services'
\ No newline at end of file
{
"project_info": {
"project_number": "488731759938",
"firebase_url": "https://thalia-493a0.firebaseio.com",
"project_id": "thalia-493a0",
"storage_bucket": "thalia-493a0.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:488731759938:android:ce90d9e7effcbbfb",
"android_client_info": {
"package_name": "com.thaliapp"
}
},
"oauth_client": [
{
"client_id": "488731759938-k103fp2m146qhfsf7s3to9bm43qhcous.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyApn30VsmPqjs4N5_kR68tpXzBWSyOxuoM"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 2
}
}
},
{
"client_info": {
"mobilesdk_app_id": "1:488731759938:android:e73d72886d6d4f94",
"android_client_info": {
"package_name": "com.thaliapp.dev"
}
},
"oauth_client": [
{
"client_id": "488731759938-k103fp2m146qhfsf7s3to9bm43qhcous.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyApn30VsmPqjs4N5_kR68tpXzBWSyOxuoM"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 2
}
}
}
],
"configuration_version": "1"
}
\ No newline at end of file
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.thaliapp"
android:versionCode="1"
android:versionName="1.0">
package="com.thaliapp"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="22" />
android:minSdkVersion="16"
android:targetSdkVersion="22"/>
<application
android:name=".MainApplication"
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
android:name=".MainApplication"
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
<meta-data android:name="android.max_aspect" android:value="2.1" />
<service android:name="com.evollu.react.fcm.MessagingService" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service android:name="com.evollu.react.fcm.InstanceIdService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@mipmap/ic_notification" />
<meta-data
android:name="android.max_aspect"
android:value="2.1" />
</application>
</manifest>
......@@ -3,6 +3,7 @@ package com.thaliapp;
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.evollu.react.fcm.FIRMessagingPackage;
import com.BV.LinearGradient.LinearGradientPackage;
import com.oblador.vectoricons.VectorIconsPackage;
import com.facebook.react.ReactNativeHost;
......@@ -25,6 +26,7 @@ public class MainApplication extends Application implements ReactApplication {
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new FIRMessagingPackage(),
new LinearGradientPackage(),
new VectorIconsPackage()
);
......
......@@ -6,6 +6,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.google.gms:google-services:3.1.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
......@@ -20,5 +21,8 @@ allprojects {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
maven {
url "https://maven.google.com" // Google's Maven repository
}
}
}
rootProject.name = 'ThaliApp'
include ':react-native-fcm'
project(':react-native-fcm').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fcm/android')
include ':react-native-linear-gradient'
project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android')
include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
include ':app'
include ':app'
\ No newline at end of file
export const REGISTER = 'PUSH_NOTIFICATIONS_REGISTER';
export const INVALIDATE = 'PUSH_NOTIFICATIONS_INVALIDATE';
export function register(token) {
return { type: REGISTER, payload: { token } };
}
export function invalidate() {
return { type: INVALIDATE };
}
......@@ -4,6 +4,7 @@ import { applyMiddleware, combineReducers, createStore } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';
import createSagaMiddleware from 'redux-saga';
import FCM, { FCMEvent } from 'react-native-fcm';
import Moment from 'moment';
import 'moment/locale/nl';
......@@ -11,6 +12,7 @@ import * as reducers from './reducers';
import sagas from './sagas';
import ReduxNavigator from './components/navigator';
import * as loginActions from './actions/login';
import { register } from './actions/pushNotifications';
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
const sagaMiddleware = createSagaMiddleware();
......@@ -29,6 +31,20 @@ const pairsToObject = (obj, pair) => {
return obj2;
};
FCM.on(FCMEvent.Notification, async (notif) => {
if (notif.fcm) {
FCM.presentLocalNotification({
title: notif.fcm.title,
body: notif.fcm.body,
color: notif.fcm.color,
icon: notif.fcm.icon === null ? 'ic_notification' : notif.fcm.icon,
action: notif.fcm.action,
tag: notif.fcm.tag,
show_in_foreground: true,
});
}
});
class Main extends Component {
componentDidMount() {
Moment.locale('nl');
......@@ -43,6 +59,7 @@ class Main extends Component {
if (username !== null && token !== null) {
store.dispatch(loginActions.success(username, token, displayName, photo, ''));
store.dispatch(register(token));
}
});
}
......
......@@ -5,6 +5,7 @@ import eventSaga from './event';
import profileSaga from './profile';
import welcomeSaga from './welcome';
import calendarSaga from './calendar';
import pushNotificationsSaga from './pushNotifications';
const sagas = function* sagas() {
yield all([
......@@ -13,6 +14,7 @@ const sagas = function* sagas() {
fork(profileSaga),
fork(welcomeSaga),
fork(calendarSaga),
fork(pushNotificationsSaga),
]);
};
......
......@@ -4,6 +4,7 @@ import { AsyncStorage } from 'react-native';
import { apiRequest, url } from '../url';
import * as loginActions from '../actions/login';
import * as pushNotificationsActions from '../actions/pushNotifications';
const USERNAMEKEY = '@MyStore:username';
const TOKENKEY = '@MyStore:token';
......@@ -52,6 +53,7 @@ const login = function* login(action) {
yield put(loginActions.success(
user, token, displayName, avatar,
));
yield put(pushNotificationsActions.register(token));
yield delay(2000);
yield put(loginActions.reset());
} catch (error) {
......@@ -64,6 +66,7 @@ const login = function* login(action) {
const logout = function* logout() {
yield call(AsyncStorage.multiRemove, [USERNAMEKEY, TOKENKEY]);
yield delay(2000);
yield put(pushNotificationsActions.invalidate());
yield put(loginActions.reset());
};
......
import { call, takeEvery } from 'redux-saga/effects';
import { Platform } from 'react-native';
import FCM from 'react-native-fcm';
import { apiRequest } from '../url';
import * as pushNotificationsActions from '../actions/pushNotifications';
const register = function* register(action) {
const { token } = action.payload;
let pushToken;
if (Platform.OS === 'ios') {
pushToken = yield call(FCM.getFCMToken);
} else {
yield call(FCM.requestPermissions);
pushToken = yield call(FCM.getFCMToken);
}
const data = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `Token ${token}`,
},
body: JSON.stringify({
registration_id: pushToken,
type: Platform.OS,
}),
};
yield call(apiRequest, 'devices', data);
};
const invalidate = function* invalidate() {
yield call(FCM.deleteInstanceId);
};
const pushNotificationsSaga = function* pushNotificationsSaga() {
yield takeEvery(pushNotificationsActions.REGISTER, register);
yield takeEvery(pushNotificationsActions.INVALIDATE, invalidate);
};
export default pushNotificationsSaga;
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'ThaliApp' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!
# Pods for ThaliApp
pod 'FirebaseMessaging'
target 'ThaliAppTests' do
inherit! :search_paths
# Pods for testing
end
end
PODS:
- FirebaseAnalytics (3.6.0):
- FirebaseCore (~> 3.4)
- FirebaseInstanceID (~> 1.0)
- GoogleInterchangeUtilities (~> 1.2)
- GoogleSymbolUtilities (~> 1.1)
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
- FirebaseCore (3.4.6):
- GoogleInterchangeUtilities (~> 1.2)
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
- FirebaseInstanceID (1.0.8)
- FirebaseMessaging (1.2.1):
- FirebaseAnalytics (~> 3.4)
- FirebaseInstanceID (~> 1.0)
- GoogleInterchangeUtilities (~> 1.2)
- GoogleSymbolUtilities (~> 1.1)
- GoogleToolboxForMac/Logger (~> 2.1)
- GoogleInterchangeUtilities (1.2.2):
- GoogleSymbolUtilities (~> 1.1)
- GoogleSymbolUtilities (1.1.2)
- GoogleToolboxForMac/Defines (2.1.0)
- GoogleToolboxForMac/Logger (2.1.0):
- GoogleToolboxForMac/Defines (= 2.1.0)
- GoogleToolboxForMac/NSData+zlib (2.1.0):
- GoogleToolboxForMac/Defines (= 2.1.0)
DEPENDENCIES:
- FirebaseMessaging
SPEC CHECKSUMS:
FirebaseAnalytics: 9c67af0ebeb8d2146c9b4ea2616439affa947b58
FirebaseCore: 03da1cb32615569bbc2830a22f9ad753d9a02ef5
FirebaseInstanceID: ba1e640935235e5fac39dfa816fe7660e72e1a8a
FirebaseMessaging: acf66347e43c5637c697060c3001d25c809a4131
GoogleInterchangeUtilities: d5bc4d88d5b661ab72f9d70c58d02ca8c27ad1f7
GoogleSymbolUtilities: 631ee17048aa5e9ab133470d768ea997a5ef9b96
GoogleToolboxForMac: 2b2596cbb7186865e98cadf2b1e262d851c2b168
PODFILE CHECKSUM: e96d08e64ae034c5cc5d47d35f4df47f936e7fc3
COCOAPODS: 1.2.1
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:ThaliApp.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
......@@ -4035,6 +4035,10 @@ react-native-drawer@^2.3.0:
prop-types "^15.5.8"
tween-functions "^1.0.1"
react-native-fcm@^9.6.2:
version "9.6.2"
resolved "https://registry.yarnpkg.com/react-native-fcm/-/react-native-fcm-9.6.2.tgz#df1b9b04809289eca062e399fe1b177a11267be9"
react-native-git-upgrade@^0.2.7:
version "0.2.7"
resolved "https://registry.yarnpkg.com/react-native-git-upgrade/-/react-native-git-upgrade-0.2.7.tgz#9bab5b9eabbe9f0845543feb5f1972183628aa12"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment