Commit cb16cd8c authored by Thibault Malbranche's avatar Thibault Malbranche Committed by GitHub

Merge pull request #4 from Titozzz/evollu-master

Update to master
parents bc7bd738 a498f921
......@@ -131,6 +131,9 @@ android {
}
dependencies {
compile(project(':react-native-maps')) {
exclude group: 'com.google.android.gms', module: 'play-services-base'
}
compile project(':react-native-fcm')
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:26.1.0"
......
package com.google.firebase.quickstart.fcm;
import android.content.Intent;
import com.facebook.react.ReactActivity;
public class MainActivity extends ReactActivity {
......@@ -12,4 +14,11 @@ public class MainActivity extends ReactActivity {
protected String getMainComponentName() {
return "SimpleFcmClient";
}
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
}
......@@ -4,6 +4,7 @@ import android.app.Application;
import android.util.Log;
import com.facebook.react.ReactApplication;
import com.airbnb.android.react.maps.MapsPackage;
import com.evollu.react.fcm.FIRMessagingPackage;
import com.facebook.react.ReactInstanceManager;
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 MapsPackage(),
new FIRMessagingPackage()
);
}
......
rootProject.name = 'SimpleFcmClient'
include ':react-native-maps'
project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/lib/android')
include ':app'
include ':react-native-fcm'
......
......@@ -11,17 +11,20 @@ import {
TouchableOpacity,
View,
Clipboard,
Platform
Platform,
ScrollView
} from 'react-native';
import FCM from "react-native-fcm";
import { StackNavigator } from 'react-navigation';
import FCM, {NotificationActionType} from "react-native-fcm";
import {registerKilledListener, registerAppListener} from "./Listeners";
import firebaseClient from "./FirebaseClient";
registerKilledListener();
export default class App extends Component {
class MainPage extends Component {
constructor(props) {
super(props);
......@@ -38,11 +41,16 @@ export default class App extends Component {
description: 'used for example',
priority: 'high'
})
registerAppListener();
registerAppListener(this.props.navigation);
FCM.getInitialNotification().then(notif => {
this.setState({
initNotif: notif
})
if(notif && notif.targetScreen === 'detail'){
setTimeout(()=>{
this.props.navigation.navigate('Detail')
}, 500)
}
});
try{
......@@ -65,17 +73,30 @@ export default class App extends Component {
showLocalNotification() {
FCM.presentLocalNotification({
vibrate: 500,
title: 'Hello',
channel: 'default',
body: 'Test Notification',
big_text: 'i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large, i am large',
priority: "high",
sound: "bell.mp3",
large_icon: "https://image.freepik.com/free-icon/small-boy-cartoon_318-38077.jpg",
show_in_foreground: true,
group: 'test',
number: 10
id: new Date().valueOf().toString(), // (optional for instant notification)
title: "Test Notification with action", // as FCM payload
body: "Force touch to reply", // as FCM payload (required)
sound: "bell.mp3", // "default" or filename
priority: "high", // as FCM payload
click_action: "com.myapp.MyCategory", // as FCM payload - this is used as category identifier on iOS.
badge: 10, // as FCM payload IOS only, set 0 to clear badges
number: 10, // Android only
ticker: "My Notification Ticker", // Android only
auto_cancel: true, // Android only (default true)
large_icon: "https://image.freepik.com/free-icon/small-boy-cartoon_318-38077.jpg", // Android only
icon: "ic_launcher", // as FCM payload, you can relace this with custom icon you put in mipmap
big_text: "Show when notification is expanded", // Android only
sub_text: "This is a subText", // Android only
color: "red", // Android only
vibrate: 300, // Android only default: 300, no vibration if you pass 0
wake_screen: true, // Android only, wake up screen when notification arrives
group: "group", // Android only
picture: "https://google.png", // Android only bigPicture style
ongoing: true, // Android only
my_custom_data:'my_custom_field_value', // extra data you want to throw
lights: true, // Android only, LED blinking (default false)
show_in_foreground: true // notification when app is in foreground (local & remote)
});
}
......@@ -91,7 +112,9 @@ export default class App extends Component {
large_icon: "https://image.freepik.com/free-icon/small-boy-cartoon_318-38077.jpg",
show_in_foreground: true,
picture: 'https://firebase.google.com/_static/af7ae4b3fc/images/firebase/lockup.png',
wake_screen: true
wake_screen: true,
extra1: {a: 1},
extra2: 1
});
}
......@@ -104,10 +127,11 @@ export default class App extends Component {
"data":{
"custom_notification": {
"title": "Simple FCM Client",
"body": "This is a notification with only NOTIFICATION.",
"body": "Click me to go to detail",
"sound": "default",
"priority": "high",
"show_in_foreground": true
"show_in_foreground": true,
targetScreen: 'detail'
}
},
"priority": 10
......@@ -117,8 +141,11 @@ export default class App extends Component {
"to": token,
"notification":{
"title": "Simple FCM Client",
"body": "This is a notification with only NOTIFICATION.",
"body": "Click me to go to detail",
"sound": "default"
},
data: {
targetScreen: 'detail'
},
"priority": 10
}
......@@ -141,21 +168,21 @@ export default class App extends Component {
firebaseClient.send(JSON.stringify(body), "data");
}
sendRemoteNotificationWithData(token) {
let body = {
"to": token,
"notification":{
"title": "Simple FCM Client",
"body": "This is a notification with NOTIFICATION and DATA (NOTIF).",
"sound": "default"
},
"data":{
"hello": "there"
},
"priority": "high"
}
firebaseClient.send(JSON.stringify(body), "notification-data");
showLocalNotificationWithAction() {
FCM.presentLocalNotification({
title: 'Test Notification with action',
body: 'Force touch to reply',
priority: "high",
show_in_foreground: true,
click_action: "com.myidentifi.fcm.text", // for ios
android_actions: JSON.stringify([{
id: "view",
title: 'view'
},{
id: "dismiss",
title: 'dismiss'
}]) // for android, take syntax similar to ios's. only buttons are supported
});
}
render() {
......@@ -163,19 +190,11 @@ export default class App extends Component {
return (
<View style={styles.container}>
<ScrollView style={{paddingHorizontal: 20}}>
<Text style={styles.welcome}>
Welcome to Simple Fcm Client!
</Text>
<Text>
Init notif: {JSON.stringify(this.state.initNotif)}
</Text>
<Text selectable={true} onPress={() => this.setClipboardContent(this.state.token)} style={styles.instructions}>
Token: {this.state.token}
</Text>
<Text style={styles.feedback}>
{this.state.tokenCopyFeedback}
</Text>
......@@ -192,17 +211,32 @@ export default class App extends Component {
<Text style={styles.buttonText}>Send Remote Data</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.sendRemoteNotificationWithData(token)} style={styles.button}>
<Text style={styles.buttonText}>Send Remote Notification With Data</Text>
<TouchableOpacity onPress={() => this.showLocalNotification()} style={styles.button}>
<Text style={styles.buttonText}>Show Local Notification</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.showLocalNotification()} style={styles.button}>
<Text style={styles.buttonText}>Send Local Notification</Text>
<TouchableOpacity onPress={() => this.showLocalNotificationWithAction(token)} style={styles.button}>
<Text style={styles.buttonText}>Show Local Notification with Action</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.scheduleLocalNotification()} style={styles.button}>
<Text style={styles.buttonText}>Schedule Notification in 5s</Text>
</TouchableOpacity>
<Text style={styles.instructions}>
Init notif:
</Text>
<Text>
{JSON.stringify(this.state.initNotif)}
</Text>
<Text style={styles.instructions}>
Token:
</Text>
<Text selectable={true} onPress={() => this.setClipboardContent(this.state.token)}>
{this.state.token}
</Text>
</ScrollView>
</View>
);
}
......@@ -218,6 +252,25 @@ export default class App extends Component {
}
}
class DetailPage extends Component {
render(){
return <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Detail page</Text>
</View>
}
}
export default StackNavigator({
Main: {
screen: MainPage,
},
Detail: {
screen: DetailPage
}
}, {
initialRouteName: 'Main',
});
const styles = StyleSheet.create({
container: {
flex: 1,
......@@ -243,8 +296,8 @@ const styles = StyleSheet.create({
button: {
backgroundColor: "teal",
paddingHorizontal: 20,
paddingVertical: 10,
marginVertical: 15,
paddingVertical: 15,
marginVertical: 10,
borderRadius: 10
},
buttonText: {
......
import { Platform, AsyncStorage } from 'react-native';
import { Platform, AsyncStorage, AppState } from 'react-native';
import FCM, {FCMEvent, RemoteNotificationResult, WillPresentNotificationResult, NotificationType} from "react-native-fcm";
import FCM, {FCMEvent, RemoteNotificationResult, WillPresentNotificationResult, NotificationType, NotificationActionType, NotificationActionOption, NotificationCategoryOption} from "react-native-fcm";
AsyncStorage.getItem('lastNotification').then(data=>{
if(data){
......@@ -10,22 +10,60 @@ AsyncStorage.getItem('lastNotification').then(data=>{
}
})
AsyncStorage.getItem('lastMessage').then(data=>{
if(data){
// if notification arrives when app is killed, it should still be logged here
console.log('last message', JSON.parse(data));
AsyncStorage.removeItem('lastMessage');
}
})
export function registerKilledListener(){
// these callback will be triggered even when app is killed
FCM.on(FCMEvent.Notification, notif => {
AsyncStorage.setItem('lastNotification', JSON.stringify(notif));
if(notif.opened_from_tray){
setTimeout(()=>{
if(notif._actionIdentifier === 'reply'){
if(AppState.currentState !== 'background'){
console.log('User replied '+ JSON.stringify(notif._userText))
alert('User replied '+ JSON.stringify(notif._userText));
} else {
AsyncStorage.setItem('lastMessage', JSON.stringify(notif._userText));
}
}
if(notif._actionIdentifier === 'view'){
alert("User clicked View in App");
}
if(notif._actionIdentifier === 'dismiss'){
alert("User clicked Dismiss");
}
}, 1000)
}
});
}
// these callback will be triggered only when app is foreground or background
export function registerAppListener(){
export function registerAppListener(navigation){
FCM.on(FCMEvent.Notification, notif => {
console.log("Notification", notif);
if(notif.local_notification){
if(Platform.OS ==='ios' && notif._notificationType === NotificationType.WillPresent && !notif.local_notification){
// this notification is only to decide if you want to show the notification when user if in forground.
// usually you can ignore it. just decide to show or not.
notif.finish(WillPresentNotificationResult.All)
return;
}
if(notif.opened_from_tray){
return;
if(notif.targetScreen === 'detail'){
setTimeout(()=>{
navigation.navigate('Detail')
}, 500)
}
setTimeout(()=>{
alert(`User tapped notification\n${JSON.stringify(notif)}`)
}, 500)
}
if(Platform.OS ==='ios'){
......@@ -51,7 +89,6 @@ export function registerAppListener(){
FCM.on(FCMEvent.RefreshToken, token => {
console.log("TOKEN (refreshUnsubscribe)", token);
this.props.onChangeToken(token);
});
FCM.enableDirectChannel();
......@@ -62,3 +99,35 @@ export function registerAppListener(){
FCM.isDirectChannelEstablished().then(d => console.log(d));
}, 1000);
}
FCM.setNotificationCategories([
{
id: 'com.myidentifi.fcm.text',
actions: [
{
type: NotificationActionType.TextInput,
id: 'reply',
title: 'Quick Reply',
textInputButtonTitle: 'Send',
textInputPlaceholder: 'Say something',
intentIdentifiers: [],
options: NotificationActionOption.AuthenticationRequired
},
{
type: NotificationActionType.Default,
id: 'view',
title: 'View in App',
intentIdentifiers: [],
options: NotificationActionOption.Foreground
},
{
type: NotificationActionType.Default,
id: 'dismiss',
title: 'Dismiss',
intentIdentifiers: [],
options: NotificationActionOption.Destructive
}
],
options: [NotificationCategoryOption.CustomDismissAction, NotificationCategoryOption.PreviewsShowTitle]
}
])
PODS:
- Firebase/Core (4.7.0):
- FirebaseAnalytics (= 4.0.5)
- FirebaseCore (= 4.0.12)
- Firebase/Messaging (4.7.0):
- Firebase/Core (4.9.0):
- FirebaseAnalytics (= 4.0.9)
- FirebaseCore (= 4.0.15)
- Firebase/Messaging (4.9.0):
- Firebase/Core
- FirebaseMessaging (= 2.0.7)
- FirebaseAnalytics (4.0.5):
- FirebaseMessaging (= 2.1.0)
- FirebaseAnalytics (4.0.9):
- FirebaseCore (~> 4.0)
- FirebaseInstanceID (~> 2.0)
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
- nanopb (~> 0.3)
- FirebaseCore (4.0.12):
- FirebaseCore (4.0.15):
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
- FirebaseInstanceID (2.0.7)
- FirebaseMessaging (2.0.7):
- FirebaseInstanceID (2.0.9):
- FirebaseCore (~> 4.0)
- FirebaseMessaging (2.1.0):
- FirebaseAnalytics (~> 4.0)
- FirebaseCore (~> 4.0)
- FirebaseInstanceID (~> 2.0)
......@@ -35,15 +36,15 @@ DEPENDENCIES:
- Firebase/Messaging
SPEC CHECKSUMS:
Firebase: dbfb98ccec2dcfcd21ab9cc1b4981a3f3c8c5e26
FirebaseAnalytics: 5b02a63ead2c3f0259cfc7f15e053e440587ecf8
FirebaseCore: 6cf108b63997bc08c04a1ffa55a3ac0d71a59ffc
FirebaseInstanceID: 148c25c986c8699e67304b114e365713dce467f2
FirebaseMessaging: 1a11d1c0a9ed9b3f75a0685bb0ae5932e1062f5f
Firebase: 632216af3ed7f31e3be34776947fdc7546cfb572
FirebaseAnalytics: 388b630c15713f5dbf364071f5f3d6077fb52f4e
FirebaseCore: 3bd047463058fa6b5d312c97502c52e45401cdfb
FirebaseInstanceID: d2058a35e9bebda1b6dd42486b84917bde552a9d
FirebaseMessaging: 2bafab2d0f3ab3dfd753101c2c32995c2051b5da
GoogleToolboxForMac: 2501e2ad72a52eb3dfe7bd9aee7dad11b858bd20
nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3
Protobuf: 8a9838fba8dae3389230e1b7f8c104aa32389c03
PODFILE CHECKSUM: 31f07bb14b00eef65c77cff51721f530ad6eb826
COCOAPODS: 1.2.1
COCOAPODS: 1.3.1
......@@ -54,6 +54,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
......@@ -83,6 +84,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
......
......@@ -9,7 +9,9 @@
"dependencies": {
"react": "16.0.0-alpha.12",
"react-native": "^0.47.2",
"react-native-fcm": "../../"
"react-native-fcm": "^14.1.0",
"react-native-maps": "^0.20.1",
"react-navigation": "^1.2.1"
},
"jest": {
"preset": "jest-react-native"
......
This diff is collapsed.
This diff is collapsed.
......@@ -37,6 +37,7 @@ import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import com.google.firebase.FirebaseApp;
import static android.content.Context.NOTIFICATION_SERVICE;
......@@ -133,6 +134,31 @@ public class FIRMessagingModule extends ReactContextBaseJavaModule implements Li
}
}
@ReactMethod
public void getEntityFCMToken(Promise promise) {
try {
String senderId = FirebaseApp.getInstance().getOptions().getGcmSenderId();
String token = FirebaseInstanceId.getInstance().getToken(senderId, "FCM");
Log.d(TAG, "Firebase token: " + token);
promise.resolve(token);
} catch (Throwable e) {
e.printStackTrace();
promise.reject(null,e.getMessage());
}
}
@ReactMethod
public void deleteEntityFCMToken(Promise promise) {
try {
String senderId = FirebaseApp.getInstance().getOptions().getGcmSenderId();
FirebaseInstanceId.getInstance().deleteToken(senderId, "FCM");
promise.resolve(null);
} catch (Throwable e) {
e.printStackTrace();
promise.reject(null,e.getMessage());
}
}
@ReactMethod
public void deleteInstanceId(Promise promise){
try {
......@@ -354,4 +380,3 @@ public class FIRMessagingModule extends ReactContextBaseJavaModule implements Li
sendEvent("FCMNotificationReceived", parseIntent(intent));
}
}
......@@ -2,9 +2,14 @@ package com.evollu.react.fcm;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
......@@ -25,11 +30,35 @@ public class InstanceIdService extends FirebaseInstanceIdService {
Log.d(TAG, "Refreshed token: " + refreshedToken);
// Broadcast refreshed token
Intent i = new Intent("com.evollu.react.fcm.FCMRefreshToken");
Bundle bundle = new Bundle();
bundle.putString("token", refreshedToken);
i.putExtras(bundle);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
final Intent message = i;
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
public void run() {
// Construct and load our normal React JS code bundle
ReactInstanceManager mReactInstanceManager = ((ReactApplication) getApplication()).getReactNativeHost().getReactInstanceManager();
ReactContext context = mReactInstanceManager.getCurrentReactContext();
// If it's constructed, send a notification
if (context != null) {
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(message);
} else {
// Otherwise wait for construction, then send the notification
mReactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
public void onReactContextInitialized(ReactContext context) {
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(message);
}
});
if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
// Construct it in the background
mReactInstanceManager.createReactContextInBackground();
}
}
}
});
}
}
package com.evollu.react.fcm;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.bridge.WritableNativeMap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Iterator;
public class ReactNativeJson {
public static WritableMap convertJsonToMap(JSONObject jsonObject) throws JSONException {
WritableMap map = new WritableNativeMap();
Iterator<String> iterator = jsonObject.keys();
while (iterator.hasNext()) {
String key = iterator.next();
Object value = jsonObject.get(key);
if (value instanceof JSONObject) {
map.putMap(key, convertJsonToMap((JSONObject) value));
} else if (value instanceof JSONArray) {
map.putArray(key, convertJsonToArray((JSONArray) value));
} else if (value instanceof Boolean) {
map.putBoolean(key, (Boolean) value);
} else if (value instanceof Integer) {
map.putInt(key, (Integer) value);
} else if (value instanceof Double) {
map.putDouble(key, (Double) value);
} else if (value instanceof String) {
map.putString(key, (String) value);
} else {
map.putString(key, value.toString());
}
}
return map;
}
public static WritableArray convertJsonToArray(JSONArray jsonArray) throws JSONException {
WritableArray array = new WritableNativeArray();
for (int i = 0; i < jsonArray.length(); i++) {
Object value = jsonArray.get(i);
if (value instanceof JSONObject) {
array.pushMap(convertJsonToMap((JSONObject) value));
} else if (value instanceof JSONArray) {
array.pushArray(convertJsonToArray((JSONArray) value));
} else if (value instanceof Boolean) {
array.pushBoolean((Boolean) value);
} else if (value instanceof Integer) {
array.pushInt((Integer) value);
} else if (value instanceof Double) {
array.pushDouble((Double) value);
} else if (value instanceof String) {
array.pushString((String) value);
} else {
array.pushString(value.toString());
}
}
return array;
}
public static JSONObject convertMapToJson(ReadableMap readableMap) throws JSONException {
JSONObject object = new JSONObject();
ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
while (iterator.hasNextKey()) {
String key = iterator.nextKey();
switch (readableMap.getType(key)) {
case Null:
object.put(key, JSONObject.NULL);
break;
case Boolean:
object.put(key, readableMap.getBoolean(key));
break;
case Number:
object.put(key, readableMap.getDouble(key));
break;
case String:
object.put(key, readableMap.getString(key));
break;
case Map:
object.put(key, convertMapToJson(readableMap.getMap(key)));
break;
case Array:
object.put(key, convertArrayToJson(readableMap.getArray(key)));
break;
}
}
return object;
}
public static JSONArray convertArrayToJson(ReadableArray readableArray) throws JSONException {
JSONArray array = new JSONArray();
for (int i = 0; i < readableArray.size(); i++) {
switch (readableArray.getType(i)) {
case Null:
break;
case Boolean:
array.put(readableArray.getBoolean(i));
break;
case Number:
array.put(readableArray.getDouble(i));
break;
case String:
array.put(readableArray.getString(i));
break;
case Map:
array.put(convertMapToJson(readableArray.getMap(i)));
break;
case Array:
array.put(convertArrayToJson(readableArray.getArray(i)));
break;
}
}
return array;
}
}
......@@ -21,6 +21,11 @@ import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
import org.json.JSONArray;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
......@@ -212,6 +217,25 @@ public class SendNotificationTask extends AsyncTask<Void, Void, Void> {
notification.setContentIntent(pendingIntent);
if (bundle.containsKey("android_actions")) {
WritableArray actions = ReactNativeJson.convertJsonToArray(new JSONArray(bundle.getString("android_actions")));
for (int a = 0; a < actions.size(); a++) {
ReadableMap action = actions.getMap(a);
String actionTitle = action.getString("title");
String actionId = action.getString("id");
Intent actionIntent = new Intent();
actionIntent.setClassName(mContext, intentClassName);
actionIntent.setAction("com.evollu.react.fcm." + actionId + "_ACTION");
actionIntent.putExtras(bundle);
actionIntent.putExtra("_actionIdentifier", actionId);
actionIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingActionIntent = PendingIntent.getActivity(mContext, notificationID, actionIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
notification.addAction(1, actionTitle, pendingActionIntent);
}
}
Notification info = notification.build();
NotificationManagerCompat.from(mContext).notify(notificationID, info);
......
......@@ -25,6 +25,26 @@ declare module "react-native-fcm" {
const Local = "local_notification";
}
export enum NotificationCategoryOption {
CustomDismissAction = 'UNNotificationCategoryOptionCustomDismissAction',
AllowInCarPlay = 'UNNotificationCategoryOptionAllowInCarPlay',
PreviewsShowTitle = 'UNNotificationCategoryOptionHiddenPreviewsShowTitle',
PreviewsShowSubtitle = 'UNNotificationCategoryOptionHiddenPreviewsShowSubtitle',
None = 'UNNotificationCategoryOptionNone'
}
export enum NotificationActionOption {
AuthenticationRequired = 'UNNotificationActionOptionAuthenticationRequired',
Destructive = 'UNNotificationActionOptionDestructive',
Foreground = 'UNNotificationActionOptionForeground',
None = 'UNNotificationActionOptionNone'
}
export enum NotificationActionType {
Default = 'UNNotificationActionTypeDefault',
TextInput = 'UNNotificationActionTypeTextInput',
}
export interface Notification {
collapse_key: string;
opened_from_tray: boolean;
......@@ -44,6 +64,8 @@ declare module "react-native-fcm" {
};
local_notification?: boolean;
_notificationType: string;
_actionIdentifier?: string;
_userText?: string;
finish(type?: string): void;
[key: string]: any;
}
......@@ -83,6 +105,23 @@ declare module "react-native-fcm" {
remove(): void;
}
export interface NotificationAction {
type: NotificationActionType;
id: string;
title?: string;
textInputButtonTitle?: string;
textInputPlaceholder?: string;
options: NotificationActionOption | NotificationActionOption[];
}
export interface NotificationCategory {
id: string;
actions: NotificationAction[];
intentIdentifiers: string[];
hiddenPreviewsBodyPlaceholder?: string;
options?: NotificationCategoryOption | NotificationCategoryOption[];
}
export class FCM {
static requestPermissions(): Promise<void>;
static getFCMToken(): Promise<string>;
......@@ -109,6 +148,8 @@ declare module "react-native-fcm" {
static enableDirectChannel(): void
static isDirectChannelEstablished(): Promise<boolean>
static getAPNSToken(): Promise<string>
static setNotificationCategories(categories: NotificationCategory[]): void;
}
export default FCM;
......
......@@ -26,6 +26,26 @@ export const NotificationType = {
Local: 'local_notification'
};
export const NotificationCategoryOption = {
CustomDismissAction: 'UNNotificationCategoryOptionCustomDismissAction',
AllowInCarPlay: 'UNNotificationCategoryOptionAllowInCarPlay',
PreviewsShowTitle: 'UNNotificationCategoryOptionHiddenPreviewsShowTitle',
PreviewsShowSubtitle: 'UNNotificationCategoryOptionHiddenPreviewsShowSubtitle',
None: 'UNNotificationCategoryOptionNone'
};
export const NotificationActionOption = {
AuthenticationRequired: 'UNNotificationActionOptionAuthenticationRequired',
Destructive: 'UNNotificationActionOptionDestructive',
Foreground: 'UNNotificationActionOptionForeground',
None: 'UNNotificationActionOptionNone',
};
export const NotificationActionType = {
Default: 'UNNotificationActionTypeDefault',
TextInput: 'UNNotificationActionTypeTextInput',
};
const RNFIRMessaging = NativeModules.RNFIRMessaging;
const FCM = {};
......@@ -48,6 +68,14 @@ FCM.getFCMToken = () => {
return RNFIRMessaging.getFCMToken();
};
FCM.getEntityFCMToken = () => {
return RNFIRMessaging.getEntityFCMToken();
}
FCM.deleteEntityFCMToken = () => {
return RNFIRMessaging.deleteEntityFCMToken();
}
FCM.deleteInstanceId = () =>{
return RNFIRMessaging.deleteInstanceId();
};
......@@ -157,7 +185,7 @@ FCM.on = (event, callback) => {
try {
await callback(data);
} catch (err) {
console.error('Notification handler err', err);
console.error('Notification handler err:\n'+err.stack);
throw err;
}
if (!data._finishCalled) {
......@@ -180,4 +208,12 @@ FCM.send = (senderId, payload) => {
RNFIRMessaging.send(senderId, payload);
};
FCM.setNotificationCategories = (categories) => {
if (Platform.OS === 'ios') {
RNFIRMessaging.setNotificationCategories(categories);
}
}
export default FCM;
export {};
#import <UIKit/UIKit.h>
@import FirebaseCore;
@import FirebaseMessaging;
@import FirebaseInstanceID;
@import Firebase;
#import <React/RCTEventEmitter.h>
@import UserNotifications;
......
This diff is collapsed.
......@@ -24,5 +24,5 @@
"type": "git",
"url": "git+https://github.com/evollu/react-native-fcm.git"
},
"version": "11.3.1"
"version": "14.1.0"
}
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