App.js 8.9 KB
Newer Older
renato's avatar
renato committed
1 2 3 4 5 6 7 8 9 10 11
/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  TouchableOpacity,
12
  View,
Libin Lu's avatar
Libin Lu committed
13
  Clipboard,
Libin Lu's avatar
Libin Lu committed
14 15
  Platform,
  ScrollView
renato's avatar
renato committed
16 17
} from 'react-native';

Libin Lu's avatar
Libin Lu committed
18 19
import { StackNavigator } from 'react-navigation';

Libin Lu's avatar
Libin Lu committed
20
import FCM, {NotificationActionType} from "react-native-fcm";
Libin Lu's avatar
Libin Lu committed
21

Libin Lu's avatar
Libin Lu committed
22
import {registerKilledListener, registerAppListener} from "./Listeners";
renato's avatar
renato committed
23 24
import firebaseClient from  "./FirebaseClient";

Libin Lu's avatar
Libin Lu committed
25 26
registerKilledListener();

Libin Lu's avatar
Libin Lu committed
27
class MainPage extends Component {
28 29 30 31
  constructor(props) {
    super(props);

    this.state = {
32 33
      token: "",
      tokenCopyFeedback: ""
34 35 36
    }
  }

Libin Lu's avatar
Libin Lu committed
37
  async componentDidMount(){
Libin Lu's avatar
Libin Lu committed
38 39 40 41 42 43
    FCM.createNotificationChannel({
      id: 'default',
      name: 'Default',
      description: 'used for example',
      priority: 'high'
    })
Libin Lu's avatar
Libin Lu committed
44
    registerAppListener(this.props.navigation);
Libin Lu's avatar
Libin Lu committed
45 46 47 48
    FCM.getInitialNotification().then(notif => {
      this.setState({
        initNotif: notif
      })
Libin Lu's avatar
Libin Lu committed
49
      if(notif && notif.targetScreen === 'detail'){
Libin Lu's avatar
Libin Lu committed
50 51 52 53
        setTimeout(()=>{
          this.props.navigation.navigate('Detail')
        }, 500)
      }
Libin Lu's avatar
Libin Lu committed
54
    });
Libin Lu's avatar
Libin Lu committed
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71

    try{
      let result = await FCM.requestPermissions({badge: false, sound: true, alert: true});
    } catch(e){
      console.error(e);
    }

    FCM.getFCMToken().then(token => {
      console.log("TOKEN (getFCMToken)", token);
      this.setState({token: token || ""})
    });

    if(Platform.OS === 'ios'){
      FCM.getAPNSToken().then(token => {
        console.log("APNS TOKEN (getFCMToken)", token);
      });
    }
Libin Lu's avatar
Libin Lu committed
72 73
  }

Libin Lu's avatar
Libin Lu committed
74 75
  showLocalNotification() {
    FCM.presentLocalNotification({
Libin Lu's avatar
Libin Lu committed
76
      channel: 'default',
Libin Lu's avatar
Libin Lu committed
77
      id: new Date().valueOf().toString(),                // (optional for instant notification)
Libin Lu's avatar
Libin Lu committed
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
      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)
Libin Lu's avatar
Libin Lu committed
100 101 102
    });
  }

Libin Lu's avatar
Libin Lu committed
103 104 105 106 107 108 109
  scheduleLocalNotification() {
    FCM.scheduleLocalNotification({
      id: 'testnotif',
      fire_date: new Date().getTime()+5000,
      vibrate: 500,
      title: 'Hello',
      body: 'Test Scheduled Notification',
Libin Lu's avatar
Libin Lu committed
110
      sub_text: 'sub text',
Libin Lu's avatar
Libin Lu committed
111
      priority: "high",
Libin Lu's avatar
Libin Lu committed
112
      large_icon: "https://image.freepik.com/free-icon/small-boy-cartoon_318-38077.jpg",
Libin Lu's avatar
Libin Lu committed
113
      show_in_foreground: true,
Libin Lu's avatar
Libin Lu committed
114
      picture: 'https://firebase.google.com/_static/af7ae4b3fc/images/firebase/lockup.png',
Libin Lu's avatar
Libin Lu committed
115 116 117
      wake_screen: true,
      extra1: {a: 1},
      extra2: 1
Libin Lu's avatar
Libin Lu committed
118 119 120
    });
  }

Libin Lu's avatar
Libin Lu committed
121 122 123 124 125 126 127 128 129
  sendRemoteNotification(token) {
    let body;

    if(Platform.OS === 'android'){
      body = {
        "to": token,
      	"data":{
					"custom_notification": {
						"title": "Simple FCM Client",
Libin Lu's avatar
Libin Lu committed
130
						"body": "Click me to go to detail",
Libin Lu's avatar
Libin Lu committed
131 132
						"sound": "default",
						"priority": "high",
Libin Lu's avatar
Libin Lu committed
133 134
            "show_in_foreground": true,
            targetScreen: 'detail'
Libin Lu's avatar
Libin Lu committed
135 136 137 138 139 140 141 142 143
        	}
    		},
    		"priority": 10
      }
    } else {
			body = {
				"to": token,
				"notification":{
					"title": "Simple FCM Client",
Libin Lu's avatar
Libin Lu committed
144
					"body": "Click me to go to detail",
Libin Lu's avatar
Libin Lu committed
145
					"sound": "default"
Libin Lu's avatar
Libin Lu committed
146 147 148 149
        },
        data: {
          targetScreen: 'detail'
        },
Libin Lu's avatar
Libin Lu committed
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
				"priority": 10
			}
		}

    firebaseClient.send(JSON.stringify(body), "notification");
  }

  sendRemoteData(token) {
    let body = {
    	"to": token,
      "data":{
    		"title": "Simple FCM Client",
    		"body": "This is a notification with only DATA.",
    		"sound": "default"
    	},
    	"priority": "normal"
    }

    firebaseClient.send(JSON.stringify(body), "data");
  }

Libin Lu's avatar
Libin Lu committed
171 172 173 174 175 176
  showLocalNotificationWithAction() {
    FCM.presentLocalNotification({
      title: 'Test Notification with action',
      body: 'Force touch to reply',
      priority: "high",
      show_in_foreground: true,
Libin Lu's avatar
Libin Lu committed
177 178 179 180 181 182 183 184
      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
Libin Lu's avatar
Libin Lu committed
185
    });
Libin Lu's avatar
Libin Lu committed
186 187
  }

renato's avatar
renato committed
188
  render() {
189
    let { token, tokenCopyFeedback } = this.state;
190

renato's avatar
renato committed
191 192
    return (
      <View style={styles.container}>
Libin Lu's avatar
Libin Lu committed
193
      <ScrollView style={{paddingHorizontal: 20}}>
renato's avatar
renato committed
194 195 196 197
        <Text style={styles.welcome}>
          Welcome to Simple Fcm Client!
        </Text>

198 199 200 201
        <Text style={styles.feedback}>
          {this.state.tokenCopyFeedback}
        </Text>

Libin Lu's avatar
Libin Lu committed
202 203 204 205
        <Text style={styles.feedback}>
          Remote notif won't be available to iOS emulators
        </Text>

Libin Lu's avatar
Libin Lu committed
206
        <TouchableOpacity onPress={() => this.sendRemoteNotification(token)} style={styles.button}>
Libin Lu's avatar
Libin Lu committed
207
          <Text style={styles.buttonText}>Send Remote Notification</Text>
renato's avatar
renato committed
208 209
        </TouchableOpacity>

Libin Lu's avatar
Libin Lu committed
210
        <TouchableOpacity onPress={() => this.sendRemoteData(token)} style={styles.button}>
Libin Lu's avatar
Libin Lu committed
211
          <Text style={styles.buttonText}>Send Remote Data</Text>
renato's avatar
renato committed
212
        </TouchableOpacity>
renato's avatar
renato committed
213

Libin Lu's avatar
Libin Lu committed
214 215
        <TouchableOpacity onPress={() => this.showLocalNotification()} style={styles.button}>
          <Text style={styles.buttonText}>Show Local Notification</Text>
renato's avatar
renato committed
216
        </TouchableOpacity>
Libin Lu's avatar
Libin Lu committed
217

Libin Lu's avatar
Libin Lu committed
218
        <TouchableOpacity onPress={() => this.showLocalNotificationWithAction(token)} style={styles.button}>
Libin Lu's avatar
Libin Lu committed
219
          <Text style={styles.buttonText}>Show Local Notification with Action</Text>
Libin Lu's avatar
Libin Lu committed
220
        </TouchableOpacity>
Libin Lu's avatar
Libin Lu committed
221 222 223 224

        <TouchableOpacity onPress={() => this.scheduleLocalNotification()} style={styles.button}>
          <Text style={styles.buttonText}>Schedule Notification in 5s</Text>
        </TouchableOpacity>
Libin Lu's avatar
Libin Lu committed
225

Libin Lu's avatar
Libin Lu committed
226 227 228
        <Text style={styles.instructions}>
          Init notif:
        </Text>
Libin Lu's avatar
Libin Lu committed
229
        <Text>
Libin Lu's avatar
Libin Lu committed
230
          {JSON.stringify(this.state.initNotif)}
Libin Lu's avatar
Libin Lu committed
231 232
        </Text>

Libin Lu's avatar
Libin Lu committed
233 234
        <Text style={styles.instructions}>
          Token:
Libin Lu's avatar
Libin Lu committed
235
        </Text>
Libin Lu's avatar
Libin Lu committed
236 237 238 239
        <Text selectable={true} onPress={() => this.setClipboardContent(this.state.token)}>
          {this.state.token}
        </Text>
        </ScrollView>
renato's avatar
renato committed
240 241 242
      </View>
    );
  }
243 244 245 246 247 248 249 250 251 252

  setClipboardContent(text) {
    Clipboard.setString(text);
    this.setState({tokenCopyFeedback: "Token copied to clipboard."});
    setTimeout(() => {this.clearTokenCopyFeedback()}, 2000);
  }

  clearTokenCopyFeedback() {
    this.setState({tokenCopyFeedback: ""});
  }
renato's avatar
renato committed
253 254
}

Libin Lu's avatar
Libin Lu committed
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
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',
});

renato's avatar
renato committed
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
289 290 291 292 293 294
    marginBottom: 2,
  },
  feedback: {
    textAlign: 'center',
    color: '#996633',
    marginBottom: 3,
renato's avatar
renato committed
295 296 297 298
  },
  button: {
    backgroundColor: "teal",
    paddingHorizontal: 20,
Libin Lu's avatar
Libin Lu committed
299 300
    paddingVertical: 15,
    marginVertical: 10,
renato's avatar
renato committed
301 302 303 304 305 306 307
    borderRadius: 10
  },
  buttonText: {
    color: "white",
    backgroundColor: "transparent"
  },
});