UNPKG

3.98 kBJavaScriptView Raw
1import { NativeModules, NativeEventEmitter, DeviceEventEmitter, Platform } from 'react-native'
2
3const { RNBranch, RNBranchEventEmitter } = NativeModules
4
5/**
6 * Utility class to encapsulate the logic of subscription to native events.
7 */
8export default class BranchSubscriber {
9 /**
10 * Native event emitter (private)
11 */
12 _nativeEventEmitter = Platform.select({
13 android: DeviceEventEmitter,
14 ios: new NativeEventEmitter(RNBranchEventEmitter),
15 })
16
17 /**
18 * Tracks whether cached events should be checked on the next
19 * call to subscribe(). Initialized by options.checkCachedEvents
20 * if present, true otherwise.
21 */
22 _checkCachedEvents = true
23
24 /**
25 * Keep track of whether subscription is active.
26 */
27 _subscribed = false
28
29 /**
30 * The options Object passed to the constructor
31 * @type {Object}
32 */
33 options = {}
34
35 /**
36 * Creates a new BranchSubscriber object with options.
37 *
38 * @param {!Object} options an Object containing options
39 */
40 constructor(options) {
41 this.options = options || {}
42 if ('checkCachedEvents' in this.options) {
43 this._checkCachedEvents = this.options.checkCachedEvents
44 }
45
46 this.initSessionStart = null
47 this.initSessionSuccess = null
48 this.initSessionError = null
49 }
50
51 subscribe() {
52 if (this._subscribed) return
53
54 this._subscribed = true
55
56 if (this._checkCachedEvents) {
57 /*
58 * Only check for events from the native layer on the first call to
59 * subscribe().
60 */
61 this._checkCachedEvents = false
62 RNBranch.redeemInitSessionResult().then((result) => {
63 if (result) {
64 /*** Cached value is returned, so set it as cached. ***/
65 if('params' in result && !!result['params']) {
66 result['params']['+rn_cached_initial_event'] = true
67 }
68
69 /*
70 * TODO: There can easily be a race here on cold launch from a link.
71 * An INIT_SESSION_START event can be emitted by the native layer
72 * before the subscribe() method is called in JS. Then subscribe() is
73 * called before a cached response is available, so here we get
74 * result == null. Then the live INIT_SESSION_SUCCESS event is
75 * transmitted to JS, and onOpenComplete is called with a non-null
76 * URI, but onOpenStart was never called. This can be addressed
77 * by caching the pending URI in the native layers.
78 */
79 if (this.options.onOpenStart && 'uri' in result) {
80 this.options.onOpenStart({uri: result.uri, cachedInitialEvent: true})
81 }
82 if (this.options.onOpenComplete) {
83 // result includes uri and +rn_cached_initial_event.
84 this.options.onOpenComplete(result)
85 }
86 }
87
88 this._subscribe()
89 })
90 }
91 else {
92 this._subscribe()
93 }
94 }
95
96 /**
97 * Activates subscription to native events. Private. Use
98 * subscribe() and set checkCachedEvents true or false in
99 * constructor.
100 */
101 _subscribe() {
102 if (this.options.onOpenStart) {
103 this.initSessionStart = this._nativeEventEmitter.addListener(RNBranch.INIT_SESSION_START, this.options.onOpenStart)
104 }
105
106 if (this.options.onOpenComplete) {
107 this.initSessionSuccess = this._nativeEventEmitter.addListener(RNBranch.INIT_SESSION_SUCCESS, this.options.onOpenComplete)
108 this.initSessionError = this._nativeEventEmitter.addListener(RNBranch.INIT_SESSION_ERROR, this.options.onOpenComplete)
109 }
110 }
111
112 /**
113 * Deactivates subscription to native events
114 */
115 unsubscribe() {
116 if (!this._subscribed) return
117
118 this._subscribed = false
119
120 if (this.options.onOpenStart) {
121 if (this.initSessionStart) {
122 this.initSessionStart.remove()
123 };
124 }
125
126 if (this.options.onOpenComplete) {
127 if (this.initSessionSuccess) {
128 this.initSessionSuccess.remove();
129 }
130 if (this.initSessionError) {
131 this.initSessionError.remove()
132 }
133 }
134 }
135}