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

Libin Lu's avatar
Libin Lu committed
7
import React, { Component } from "react";
renato's avatar
renato committed
8 9 10 11
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
Libin Lu's avatar
Libin Lu committed
16
} from "react-native";
renato's avatar
renato committed
17

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

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 23
import { registerKilledListener, registerAppListener } from "./Listeners";
import firebaseClient from "./FirebaseClient";
renato's avatar
renato committed
24

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: ""
Libin Lu's avatar
Libin Lu committed
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
    FCM.getInitialNotification().then(notif => {
      this.setState({
        initNotif: notif
Libin Lu's avatar
Libin Lu committed
48 49 50 51 52
      });
      if (notif && notif.targetScreen === "detail") {
        setTimeout(() => {
          this.props.navigation.navigate("Detail");
        }, 500);
Libin Lu's avatar
Libin Lu committed
53
      }
Libin Lu's avatar
Libin Lu committed
54
    });
Libin Lu's avatar
Libin Lu committed
55

Libin Lu's avatar
Libin Lu committed
56 57 58 59 60 61 62
    try {
      let result = await FCM.requestPermissions({
        badge: false,
        sound: true,
        alert: true
      });
    } catch (e) {
Libin Lu's avatar
Libin Lu committed
63 64 65 66 67
      console.error(e);
    }

    FCM.getFCMToken().then(token => {
      console.log("TOKEN (getFCMToken)", token);
Libin Lu's avatar
Libin Lu committed
68
      this.setState({ token: token || "" });
Libin Lu's avatar
Libin Lu committed
69 70
    });

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

    // topic example
    // FCM.subscribeToTopic('sometopic')
    // FCM.unsubscribeFromTopic('sometopic')
Libin Lu's avatar
Libin Lu committed
80 81
  }

Libin Lu's avatar
Libin Lu committed
82 83
  showLocalNotification() {
    FCM.presentLocalNotification({
Libin Lu's avatar
Libin Lu committed
84
      channel: 'default',
Libin Lu's avatar
Libin Lu committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
      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://www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.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
110 111 112
    });
  }

Libin Lu's avatar
Libin Lu committed
113 114
  scheduleLocalNotification() {
    FCM.scheduleLocalNotification({
Libin Lu's avatar
Libin Lu committed
115 116
      id: "testnotif",
      fire_date: new Date().getTime() + 5000,
Libin Lu's avatar
Libin Lu committed
117
      vibrate: 500,
Libin Lu's avatar
Libin Lu committed
118 119 120
      title: "Hello",
      body: "Test Scheduled Notification",
      sub_text: "sub text",
Libin Lu's avatar
Libin Lu committed
121
      priority: "high",
Libin Lu's avatar
Libin Lu committed
122 123
      large_icon:
        "https://image.freepik.com/free-icon/small-boy-cartoon_318-38077.jpg",
Libin Lu's avatar
Libin Lu committed
124
      show_in_foreground: true,
Libin Lu's avatar
Libin Lu committed
125 126
      picture:
        "https://firebase.google.com/_static/af7ae4b3fc/images/firebase/lockup.png",
Libin Lu's avatar
Libin Lu committed
127
      wake_screen: true,
Libin Lu's avatar
Libin Lu committed
128
      extra1: { a: 1 },
Libin Lu's avatar
Libin Lu committed
129
      extra2: 1
Libin Lu's avatar
Libin Lu committed
130 131 132
    });
  }

Libin Lu's avatar
Libin Lu committed
133 134 135
  sendRemoteNotification(token) {
    let body;

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

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

  sendRemoteData(token) {
    let body = {
Libin Lu's avatar
Libin Lu committed
171 172 173 174 175 176 177 178
      to: token,
      data: {
        title: "Simple FCM Client",
        body: "This is a notification with only DATA.",
        sound: "default"
      },
      priority: "normal"
    };
Libin Lu's avatar
Libin Lu committed
179 180 181 182

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

Libin Lu's avatar
Libin Lu committed
183 184
  showLocalNotificationWithAction() {
    FCM.presentLocalNotification({
Libin Lu's avatar
Libin Lu committed
185 186
      title: "Test Notification with action",
      body: "Force touch to reply",
Libin Lu's avatar
Libin Lu committed
187 188
      priority: "high",
      show_in_foreground: true,
Libin Lu's avatar
Libin Lu committed
189
      click_action: "com.myidentifi.fcm.text", // for ios
Libin Lu's avatar
Libin Lu committed
190 191 192 193 194 195 196 197 198 199
      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
200
    });
Libin Lu's avatar
Libin Lu committed
201 202
  }

renato's avatar
renato committed
203
  render() {
204
    let { token, tokenCopyFeedback } = this.state;
205

renato's avatar
renato committed
206 207
    return (
      <View style={styles.container}>
Libin Lu's avatar
Libin Lu committed
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
        <ScrollView style={{ paddingHorizontal: 20 }}>
          <Text style={styles.welcome}>Welcome to Simple Fcm Client!</Text>

          <Text style={styles.feedback}>{this.state.tokenCopyFeedback}</Text>

          <Text style={styles.feedback}>
            Remote notif won't be available to iOS emulators
          </Text>

          <TouchableOpacity
            onPress={() => this.sendRemoteNotification(token)}
            style={styles.button}
          >
            <Text style={styles.buttonText}>Send Remote Notification</Text>
          </TouchableOpacity>

          <TouchableOpacity
            onPress={() => this.sendRemoteData(token)}
            style={styles.button}
          >
            <Text style={styles.buttonText}>Send Remote Data</Text>
          </TouchableOpacity>

          <TouchableOpacity
            onPress={() => this.showLocalNotification()}
            style={styles.button}
          >
            <Text style={styles.buttonText}>Show Local Notification</Text>
          </TouchableOpacity>

          <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>
Libin Lu's avatar
Libin Lu committed
264
        </ScrollView>
renato's avatar
renato committed
265 266 267
      </View>
    );
  }
268 269 270

  setClipboardContent(text) {
    Clipboard.setString(text);
Libin Lu's avatar
Libin Lu committed
271 272 273 274
    this.setState({ tokenCopyFeedback: "Token copied to clipboard." });
    setTimeout(() => {
      this.clearTokenCopyFeedback();
    }, 2000);
275 276 277
  }

  clearTokenCopyFeedback() {
Libin Lu's avatar
Libin Lu committed
278
    this.setState({ tokenCopyFeedback: "" });
279
  }
renato's avatar
renato committed
280 281
}

Libin Lu's avatar
Libin Lu committed
282
class DetailPage extends Component {
Libin Lu's avatar
Libin Lu committed
283 284 285 286 287 288
  render() {
    return (
      <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
        <Text>Detail page</Text>
      </View>
    );
Libin Lu's avatar
Libin Lu committed
289 290 291
  }
}

Libin Lu's avatar
Libin Lu committed
292 293 294 295 296 297 298 299
export default StackNavigator(
  {
    Main: {
      screen: MainPage
    },
    Detail: {
      screen: DetailPage
    }
Libin Lu's avatar
Libin Lu committed
300
  },
Libin Lu's avatar
Libin Lu committed
301 302
  {
    initialRouteName: "Main"
Libin Lu's avatar
Libin Lu committed
303
  }
Libin Lu's avatar
Libin Lu committed
304
);
Libin Lu's avatar
Libin Lu committed
305

renato's avatar
renato committed
306 307 308
const styles = StyleSheet.create({
  container: {
    flex: 1,
Libin Lu's avatar
Libin Lu committed
309 310 311
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#F5FCFF"
renato's avatar
renato committed
312 313 314
  },
  welcome: {
    fontSize: 20,
Libin Lu's avatar
Libin Lu committed
315 316
    textAlign: "center",
    margin: 10
renato's avatar
renato committed
317 318
  },
  instructions: {
Libin Lu's avatar
Libin Lu committed
319 320 321
    textAlign: "center",
    color: "#333333",
    marginBottom: 2
322 323
  },
  feedback: {
Libin Lu's avatar
Libin Lu committed
324 325 326
    textAlign: "center",
    color: "#996633",
    marginBottom: 3
renato's avatar
renato committed
327 328 329 330
  },
  button: {
    backgroundColor: "teal",
    paddingHorizontal: 20,
Libin Lu's avatar
Libin Lu committed
331 332
    paddingVertical: 15,
    marginVertical: 10,
renato's avatar
renato committed
333 334 335 336 337
    borderRadius: 10
  },
  buttonText: {
    color: "white",
    backgroundColor: "transparent"
Libin Lu's avatar
Libin Lu committed
338
  }
renato's avatar
renato committed
339
});