cobrowse-sdk-react-native 2.6.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -21,7 +21,7 @@ This will associate sessions from your mobile app with your Cobrowse account.
21
21
  ```javascript
22
22
  import CobrowseIO from 'cobrowse-sdk-react-native';
23
23
 
24
- CobrowseIO.license = "<your license key here>";
24
+ CobrowseIO.license = "put your license key here";
25
25
  CobrowseIO.start();
26
26
 
27
27
  ```
@@ -53,3 +53,11 @@ Any questions at all? Please email us directly at [hello@cobrowse.io](mailto:hel
53
53
 
54
54
  * iOS 9.0 or later
55
55
  * Android API version 19 (4.4 KitKat) or later
56
+
57
+ ## Deployment
58
+
59
+ This SDK is only available via NPM. To deploy a new version:
60
+
61
+ ```
62
+ npm publish
63
+ ```
@@ -1,3 +1,13 @@
1
+ buildscript {
2
+ repositories {
3
+ mavenCentral()
4
+ google()
5
+ }
6
+ dependencies {
7
+ classpath 'com.android.tools.build:gradle:3.1.0'
8
+ }
9
+ }
10
+
1
11
  apply plugin: 'com.android.library'
2
12
 
3
13
  android {
@@ -20,5 +30,5 @@ android {
20
30
 
21
31
  dependencies {
22
32
  implementation 'com.facebook.react:react-native:+' // support react-native-v0.22-rc+
23
- implementation 'io.cobrowse:cobrowse-sdk-android:2.11.3'
33
+ implementation 'io.cobrowse:cobrowse-sdk-android:2.16.0'
24
34
  }
@@ -20,12 +20,15 @@ import java.util.Map;
20
20
  import androidx.annotation.NonNull;
21
21
  import io.cobrowse.CobrowseIO;
22
22
  import io.cobrowse.Session;
23
+ import io.cobrowse.CobrowseAccessibilityService;
23
24
 
24
- public class CobrowseIOModule extends ReactContextBaseJavaModule implements CobrowseIO.Delegate, CobrowseIO.SessionRequestDelegate, CobrowseIO.RedactionDelegate {
25
+ public class CobrowseIOModule extends ReactContextBaseJavaModule
26
+ implements CobrowseIO.Delegate, CobrowseIO.SessionRequestDelegate,
27
+ CobrowseIO.RedactionDelegate, CobrowseIO.RemoteControlRequestDelegate {
25
28
 
26
- private static final String SESSION_UPDATED = "session_updated";
27
- private static final String SESSION_ENDED = "session_ended";
28
- private static final String SESSION_REQUESTED = "session_requested";
29
+ private static final String SESSION_UPDATED = "session.updated";
30
+ private static final String SESSION_ENDED = "session.ended";
31
+ private static final String SESSION_REQUESTED = "session.requested";
29
32
 
30
33
  CobrowseIOModule(ReactApplicationContext reactContext) {
31
34
  super(reactContext);
@@ -37,15 +40,6 @@ public class CobrowseIOModule extends ReactContextBaseJavaModule implements Cobr
37
40
  return "CobrowseIO";
38
41
  }
39
42
 
40
- @Override
41
- public Map<String, Object> getConstants() {
42
- final Map<String, Object> constants = new HashMap<>();
43
- constants.put("SESSION_UPDATED", SESSION_UPDATED);
44
- constants.put("SESSION_ENDED", SESSION_ENDED);
45
- constants.put("SESSION_REQUESTED", SESSION_REQUESTED);
46
- return constants;
47
- }
48
-
49
43
  @Override
50
44
  public void sessionDidUpdate(@NonNull Session session) {
51
45
  getReactApplicationContext()
@@ -67,6 +61,12 @@ public class CobrowseIOModule extends ReactContextBaseJavaModule implements Cobr
67
61
  .emit(SESSION_REQUESTED, Utility.convert(session));
68
62
  }
69
63
 
64
+ @Override
65
+ public void handleRemoteControlRequest(@NonNull Activity activity, @NonNull Session session) {
66
+ // no-op, this will be handed on the JS side via an "updated" event handler
67
+ // this stub just disables the default native prompt in the SDK
68
+ }
69
+
70
70
  @Override
71
71
  public List<View> redactedViews(@NonNull final Activity activity) {
72
72
  return new ArrayList<>(RedactedViewManager.redactedViews.keySet());
@@ -136,14 +136,14 @@ public class CobrowseIOModule extends ReactContextBaseJavaModule implements Cobr
136
136
  }
137
137
 
138
138
  @ReactMethod
139
- public void loadSession(final String idOrCode, final Promise promise) {
139
+ public void getSession(final String idOrCode, final Promise promise) {
140
140
  Handler handler = new Handler(getReactApplicationContext().getMainLooper());
141
141
  handler.post(new Runnable() {
142
142
  public void run() {
143
143
  CobrowseIO.instance().getSession(idOrCode, new io.cobrowse.Callback<Error, Session>() {
144
144
  @Override
145
145
  public void call(Error error, Session session) {
146
- if (error != null) promise.reject("cbio_load_session_failed", error);
146
+ if (error != null) promise.reject("cbio_get_session_failed", error);
147
147
  else promise.resolve(Utility.convert(session));
148
148
  }
149
149
  });
@@ -193,4 +193,55 @@ public class CobrowseIOModule extends ReactContextBaseJavaModule implements Cobr
193
193
  });
194
194
  }
195
195
 
196
+ @ReactMethod
197
+ public void updateSession (final ReadableMap options, final Promise promise) {
198
+ Handler handler = new Handler(getReactApplicationContext().getMainLooper());
199
+ handler.post(new Runnable() {
200
+ public void run() {
201
+ Session current = CobrowseIO.instance().currentSession();
202
+
203
+ if (current == null) {
204
+ promise.resolve(null);
205
+ return;
206
+ }
207
+
208
+ if (options.hasKey("full_device")) {
209
+ boolean fullDevice = options.getBoolean("full_device");
210
+
211
+ current.setFullDevice(fullDevice, new io.cobrowse.Callback<Error, Session>() {
212
+ @Override
213
+ public void call(Error error, Session session) {
214
+ if (error != null) promise.reject("cbio_full_device_failed", error);
215
+ else promise.resolve(null);
216
+ }
217
+ });
218
+
219
+ return;
220
+ }
221
+
222
+ if (options.hasKey("remote_control")) {
223
+ String remoteControl = options.getString("remote_control");
224
+
225
+ current.setRemoteControl(Utility.remoteControl(remoteControl), new io.cobrowse.Callback<Error, Session>() {
226
+ @Override
227
+ public void call(Error error, Session session) {
228
+ if (error != null) promise.reject("cbio_remote_control_failed", error);
229
+ else promise.resolve(null);
230
+ }
231
+ });
232
+ }
233
+ }
234
+ });
235
+ }
236
+
237
+ @ReactMethod
238
+ public void accessibilityServiceShowSetup (final Promise promise) {
239
+ CobrowseAccessibilityService.showSetup(getReactApplicationContext());
240
+ promise.resolve(null);
241
+ }
242
+
243
+ @ReactMethod
244
+ public void accessibilityServiceIsRunning(final Promise promise) {
245
+ promise.resolve(CobrowseAccessibilityService.isRunning(getReactApplicationContext()));
246
+ }
196
247
  }
@@ -5,6 +5,7 @@ import com.facebook.react.bridge.WritableMap;
5
5
 
6
6
  import io.cobrowse.Agent;
7
7
  import io.cobrowse.Session;
8
+ import io.cobrowse.Session.RemoteControlState;
8
9
 
9
10
  final class Utility {
10
11
 
@@ -15,6 +16,7 @@ final class Utility {
15
16
  map.putString("state", session.state());
16
17
  map.putString("id", session.id());
17
18
  map.putBoolean("full_device", session.fullDevice());
19
+ map.putString("remote_control", Utility.remoteControl(session.remoteControl()));
18
20
 
19
21
  Agent agent = session.agent();
20
22
  if (agent != null) {
@@ -32,4 +34,34 @@ final class Utility {
32
34
  return error.getMessage();
33
35
  }
34
36
 
37
+ static String remoteControl (RemoteControlState state) {
38
+ switch (state) {
39
+ case On:
40
+ return "on";
41
+ case Requested:
42
+ return "requested";
43
+ case Rejected:
44
+ return "rejected";
45
+ case Off:
46
+ return "off";
47
+ }
48
+
49
+ return "off";
50
+ }
51
+
52
+ static RemoteControlState remoteControl (String state) {
53
+ switch (state) {
54
+ case "on":
55
+ return RemoteControlState.On;
56
+ case "requested":
57
+ return RemoteControlState.Requested;
58
+ case "rejected":
59
+ return RemoteControlState.Rejected;
60
+ case "off":
61
+ return RemoteControlState.Off;
62
+ }
63
+
64
+ return RemoteControlState.Off;
65
+ }
66
+
35
67
  }
@@ -12,7 +12,7 @@ Pod::Spec.new do |s|
12
12
  s.source = { :git => 'https://github.com/cobrowseio/cobrowse-sdk-react-native.git' }
13
13
  s.platform = :ios, '9.0'
14
14
 
15
- s.dependency 'CobrowseIO/Framework', '2.13.3'
15
+ s.dependency 'CobrowseIO/Framework', '2.16.2'
16
16
  s.dependency 'React'
17
17
  s.source_files = 'ios/*.{h,m}'
18
18
  end
@@ -0,0 +1,8 @@
1
+ #import <Foundation/Foundation.h>
2
+ @import CobrowseIO;
3
+
4
+ @interface CBIORCTUtil : NSObject
5
+
6
+ +(NSString*) remoteControl: (CBIORemoteControlState) state;
7
+
8
+ @end
@@ -0,0 +1,15 @@
1
+ #import "CBIORCTUtil.h"
2
+
3
+ @implementation CBIORCTUtil
4
+
5
+ +(NSString *) remoteControl: (CBIORemoteControlState)state {
6
+ switch(state) {
7
+ case kCBIORemoteControlStateOn: return @"on";
8
+ case kCBIORemoteControlStateOff: return @"off";
9
+ case kCBIORemoteControlStateRejected: return @"rejected";
10
+ case kCBIORemoteControlStateRequested: return @"requested";
11
+ default: return @"off";
12
+ }
13
+ }
14
+
15
+ @end
@@ -5,3 +5,9 @@
5
5
  -(NSDictionary*) toDict;
6
6
 
7
7
  @end
8
+
9
+ @interface CBIOSession (Protected)
10
+
11
+ -(void) update:(NSDictionary*) state callback: (CBErrorSessionBlock)callback;
12
+
13
+ @end
@@ -1,4 +1,6 @@
1
1
  @import CobrowseIO;
2
+ #import "CBIORCTUtil.h"
3
+
2
4
 
3
5
  @implementation CBIOSession (Bridging)
4
6
 
@@ -8,6 +10,7 @@
8
10
  @"code": self.code ? self.code : NSNull.null,
9
11
  @"state": self.state ? self.state : NSNull.null,
10
12
  @"full_device": @(self.fullDevice),
13
+ @"remote_control": [CBIORCTUtil remoteControl: self.remoteControl],
11
14
  @"agent": self.hasAgent ? @{
12
15
  @"name": self.agent.name,
13
16
  @"id": self.agent.id
File without changes
@@ -7,9 +7,9 @@
7
7
  #import <React/RCTBridge.h>
8
8
  #import "RCTCobrowseIO.h"
9
9
 
10
- #define SESSION_UPDATED "session_updated"
11
- #define SESSION_ENDED "session_ended"
12
- #define SESSION_REQUESTED "session_requested"
10
+ #define SESSION_UPDATED "session.updated"
11
+ #define SESSION_ENDED "session.ended"
12
+ #define SESSION_REQUESTED "session.requested"
13
13
 
14
14
  @import CobrowseIO;
15
15
 
@@ -35,14 +35,6 @@ RCT_EXPORT_MODULE();
35
35
  return dispatch_get_main_queue();
36
36
  }
37
37
 
38
- -(NSDictionary *)constantsToExport {
39
- return @{
40
- @"SESSION_UPDATED": @SESSION_UPDATED,
41
- @"SESSION_ENDED": @SESSION_ENDED,
42
- @"SESSION_REQUESTED": @SESSION_REQUESTED
43
- };
44
- }
45
-
46
38
  -(void)startObserving {
47
39
  hasListeners = YES;
48
40
  }
@@ -52,7 +44,7 @@ RCT_EXPORT_MODULE();
52
44
  }
53
45
 
54
46
  -(NSArray<NSString *> *)supportedEvents {
55
- return self.constantsToExport.allValues;
47
+ return @[@SESSION_UPDATED, @SESSION_ENDED, @SESSION_REQUESTED];
56
48
  }
57
49
 
58
50
  -(void)cobrowseSessionDidUpdate:(CBIOSession *)session {
@@ -67,6 +59,11 @@ RCT_EXPORT_MODULE();
67
59
  if (hasListeners) [self sendEventWithName:@SESSION_REQUESTED body:[session toDict]];
68
60
  }
69
61
 
62
+ - (void)cobrowseHandleRemoteControlRequest:(CBIOSession *)session {
63
+ // no-op, this will be handed on the JS side via an "updated" event handler
64
+ // this stub just disables the default native prompt in the SDK
65
+ }
66
+
70
67
  -(NSArray<UIView *> *)cobrowseRedactedViewsForViewController:(UIViewController *)vc {
71
68
  NSMutableArray* views = [NSMutableArray array];
72
69
  for (UIView* v in CBIOCobrowseRedactedManager.redactedViews.allObjects) {
@@ -134,7 +131,7 @@ RCT_REMAP_METHOD(getSession,
134
131
  resolver:(RCTPromiseResolveBlock)resolve
135
132
  rejecter:(RCTPromiseRejectBlock)reject) {
136
133
  [CobrowseIO.instance getSession:idOrCode callback:^(NSError *err, CBIOSession *session) {
137
- if (err) return reject(@"cbio_load_session_failed", err.localizedDescription, err);
134
+ if (err) return reject(@"cbio_get_session_failed", err.localizedDescription, err);
138
135
  return resolve([session toDict]);
139
136
  }];
140
137
  }
@@ -161,4 +158,16 @@ RCT_REMAP_METHOD(endSession,
161
158
  }];
162
159
  }
163
160
 
161
+ RCT_REMAP_METHOD(updateSession,
162
+ updaetSession: (NSDictionary*) state
163
+ resolver:(RCTPromiseResolveBlock)resolve
164
+ rejecter:(RCTPromiseRejectBlock)reject) {
165
+ CBIOSession* current = CobrowseIO.instance.currentSession;
166
+ if (!current) return resolve(nil);
167
+ [current update: state callback: ^(NSError *err, CBIOSession *session) {
168
+ if (err) return reject(@"cbio_update_session_failed", err.localizedDescription, err);
169
+ return resolve([session toDict]);
170
+ }];
171
+ }
172
+
164
173
  @end
@@ -2,6 +2,6 @@
2
2
  <Workspace
3
3
  version = "1.0">
4
4
  <FileRef
5
- location = "self:RCTCobrowseIO.xcodeproj">
5
+ location = "self:">
6
6
  </FileRef>
7
7
  </Workspace>
File without changes
@@ -0,0 +1,11 @@
1
+ const CobrowseIONative = require('react-native').NativeModules.CobrowseIO
2
+
3
+ export default class CobrowseAccessibilityService {
4
+ static showSetup () {
5
+ return CobrowseIONative.accessibilityServiceShowSetup()
6
+ }
7
+
8
+ static isRunning () {
9
+ return CobrowseIONative.accessibilityServiceIsRunning()
10
+ }
11
+ }
package/js/CobrowseIO.js CHANGED
@@ -1,93 +1,124 @@
1
- 'use strict';
1
+ import { Alert } from 'react-native'
2
+ import Session from './Session'
3
+ const CobrowseIONative = require('react-native').NativeModules.CobrowseIO
4
+ const NativeEventEmitter = require('react-native').NativeEventEmitter
2
5
 
3
- import { Alert } from 'react-native';
4
- const CobrowseIONative = require('react-native').NativeModules.CobrowseIO;
5
- const NativeEventEmitter = require('react-native').NativeEventEmitter;
6
-
7
- const emitter = new NativeEventEmitter(CobrowseIONative);
6
+ const emitter = new NativeEventEmitter(CobrowseIONative)
8
7
 
9
8
  export default class CobrowseIO {
10
-
11
- static get SESSION_UPDATED() {
12
- return CobrowseIONative.SESSION_UPDATED;
13
- }
14
-
15
- static get SESSION_ENDED() {
16
- return CobrowseIONative.SESSION_ENDED;
17
- }
18
-
19
- static get SESSION_REQUESTED() {
20
- return CobrowseIONative.SESSION_REQUESTED;
21
- }
22
-
23
- static handleSessionRequest(session) {
24
- Alert.alert(
25
- 'Support Request',
26
- 'A support agent would like to use this app with you. Do you accept?',
27
- [
28
- {
29
- text: 'Reject',
30
- onPress: () => this.endSession(),
31
- style: 'cancel',
32
- },
33
- {
34
- text: 'Accept',
35
- onPress: () => this.activateSession()
36
- },
37
- ],
38
- {cancelable: true},
39
- );
40
- }
41
-
42
- static addListener(event, cb) {
43
- return emitter.addListener(event, cb);
44
- }
45
-
46
- static start() {
47
- return CobrowseIONative.start();
48
- }
49
-
50
- static stop() {
51
- return CobrowseIONative.stop();
52
- }
53
-
54
- static set api(api) {
55
- CobrowseIONative.api(api);
56
- }
57
-
58
- static set license(license) {
59
- CobrowseIONative.license(license);
60
- }
61
-
62
- static set customData(customData) {
63
- CobrowseIONative.customData(customData);
64
- }
65
-
66
- static set deviceToken(token) {
67
- CobrowseIONative.deviceToken(token);
68
- }
69
-
70
- static currentSession() {
71
- return CobrowseIONative.currentSession();
72
- }
73
-
74
- static createSession() {
75
- return CobrowseIONative.createSession();
76
- }
77
-
78
- static activateSession() {
79
- return CobrowseIONative.activateSession();
80
- }
81
-
82
- static getSession(codeOrId) {
83
- return CobrowseIONative.getSession(codeOrId);
84
- }
85
-
86
- static endSession() {
87
- return CobrowseIONative.endSession();
88
- }
9
+ /** @deprecated */
10
+ static get SESSION_UPDATED () {
11
+ return 'session.updated'
12
+ }
13
+
14
+ /** @deprecated */
15
+ static get SESSION_ENDED () {
16
+ return 'session.ended'
17
+ }
18
+
19
+ static handleSessionRequest (session) {
20
+ if (this._sessionRequestShown) return
21
+ this._sessionRequestShown = true
22
+ Alert.alert(
23
+ 'Support Request',
24
+ 'A support agent would like to use this app with you. Do you accept?',
25
+ [{
26
+ text: 'Reject',
27
+ onPress: () => {
28
+ this._sessionRequestShown = false
29
+ session.end()
30
+ },
31
+ style: 'cancel'
32
+ }, {
33
+ text: 'Accept',
34
+ onPress: () => {
35
+ this._sessionRequestShown = false
36
+ session.activate()
37
+ }
38
+ }], { cancelable: false })
39
+ }
40
+
41
+ static handleRemoteControlRequest (session) {
42
+ if (this._remoteControlRequestShown) return
43
+ this._remoteControlRequestShown = true
44
+ Alert.alert(
45
+ 'Remote Control Request',
46
+ 'A support agent would like to take remote control of this app. Do you accept?',
47
+ [{
48
+ text: 'Reject',
49
+ onPress: () => {
50
+ this._remoteControlRequestShown = false
51
+ session.setRemoteControl('rejected')
52
+ },
53
+ style: 'cancel'
54
+ }, {
55
+ text: 'Accept',
56
+ onPress: () => {
57
+ this._remoteControlRequestShown = false
58
+ session.setRemoteControl('on')
59
+ }
60
+ }], { cancelable: false })
61
+ }
62
+
63
+ static addListener (event, cb) {
64
+ return emitter.addListener(event, (session) => cb(new Session(session)))
65
+ }
66
+
67
+ static start () {
68
+ return CobrowseIONative.start()
69
+ }
70
+
71
+ static stop () {
72
+ return CobrowseIONative.stop()
73
+ }
74
+
75
+ static set api (api) {
76
+ CobrowseIONative.api(api)
77
+ }
78
+
79
+ static set license (license) {
80
+ CobrowseIONative.license(license)
81
+ }
82
+
83
+ static set customData (customData) {
84
+ CobrowseIONative.customData(customData)
85
+ }
86
+
87
+ static set deviceToken (token) {
88
+ CobrowseIONative.deviceToken(token)
89
+ }
90
+
91
+ static currentSession () {
92
+ return CobrowseIONative.currentSession().then((session) => session ? new Session(session) : null)
93
+ }
94
+
95
+ static createSession () {
96
+ return CobrowseIONative.createSession().then((session) => session ? new Session(session) : null)
97
+ }
98
+
99
+ static getSession (codeOrId) {
100
+ return CobrowseIONative.getSession(codeOrId).then((session) => session ? new Session(session) : null)
101
+ }
102
+
103
+ /** @deprecated */
104
+ static activateSession () {
105
+ return CobrowseIONative.activateSession().then((session) => session ? new Session(session) : null)
106
+ }
107
+
108
+ /** @deprecated */
109
+ static endSession () {
110
+ return CobrowseIONative.endSession()
111
+ }
89
112
  }
90
113
 
91
- CobrowseIO.addListener(CobrowseIO.SESSION_REQUESTED, (session) => {
92
- CobrowseIO.handleSessionRequest(session);
93
- });
114
+ // the session.requested event is considered internal, it should
115
+ // not be used outside these bindings
116
+ CobrowseIO.addListener('session.requested', (session) => {
117
+ CobrowseIO.handleSessionRequest(session)
118
+ })
119
+
120
+ CobrowseIO.addListener('session.updated', (session) => {
121
+ if (session.isActive() && session.remote_control === 'requested') {
122
+ CobrowseIO.handleRemoteControlRequest(session)
123
+ }
124
+ })
@@ -1,129 +1,128 @@
1
- import React, { Component } from 'react';
1
+ import React, { Component } from 'react'
2
2
  import {
3
- View,
4
- Text,
5
- ActivityIndicator,
6
- TouchableOpacity,
7
- StyleSheet,
8
- Linking
9
- } from 'react-native';
10
- import CobrowseIO from './CobrowseIO';
3
+ View,
4
+ Text,
5
+ ActivityIndicator,
6
+ TouchableOpacity,
7
+ StyleSheet
8
+ } from 'react-native'
9
+ import CobrowseIO from './CobrowseIO'
11
10
 
12
11
  const styles = StyleSheet.create({
13
- container: {
14
- flex: 1,
15
- justifyContent: 'flex-end'
16
- },
17
- text: {
18
- textAlign: 'center',
19
- margin: 15,
20
- fontSize: 15,
21
- lineHeight: 20
22
- },
23
- code: {
24
- fontSize: 29,
25
- padding: 20,
26
- fontWeight: 'bold',
27
- textAlign: 'center'
28
- },
29
- button: {
30
- color: 'rgb(0, 122, 255)',
31
- fontSize: 18,
32
- margin: 10
33
- }
34
- });
12
+ container: {
13
+ flex: 1,
14
+ justifyContent: 'flex-end'
15
+ },
16
+ text: {
17
+ textAlign: 'center',
18
+ margin: 15,
19
+ fontSize: 15,
20
+ lineHeight: 20
21
+ },
22
+ code: {
23
+ fontSize: 29,
24
+ padding: 20,
25
+ fontWeight: 'bold',
26
+ textAlign: 'center'
27
+ },
28
+ button: {
29
+ color: 'rgb(0, 122, 255)',
30
+ fontSize: 18,
31
+ margin: 10
32
+ }
33
+ })
35
34
 
36
35
  export default class CobrowseView extends Component {
36
+ constructor () {
37
+ super()
38
+ this.state = { error: null, session: null }
39
+ }
37
40
 
38
- constructor() {
39
- super();
40
- this.state = { error: null, session: null };
41
+ async componentDidMount () {
42
+ if (this.props.license) {
43
+ console.warn('Passing license to view is deprecated. Use CobrowseIO.license = "..." instead')
44
+ CobrowseIO.license = this.props.license
41
45
  }
42
46
 
43
- async componentDidMount() {
44
- if (this.props.license) {
45
- console.warn('Passing license to view is deprecated. Use CobrowseIO.license = "..." instead');
46
- CobrowseIO.license = this.props.license;
47
- }
48
-
49
- try {
50
- const current = await CobrowseIO.currentSession();
51
- if (current) this.setState({ session:current });
52
- else {
53
- const session = await CobrowseIO.createSession();
54
- this.setState({ session });
55
- }
56
- } catch (error) {
57
- this.setState({ error })
58
- }
59
-
60
- this.updateListener = CobrowseIO.addListener(CobrowseIO.SESSION_UPDATED, (session) => {
61
- this.setState({ session });
62
- });
63
- this.endListener = CobrowseIO.addListener(CobrowseIO.SESSION_ENDED, (session) => {
64
- if (this.props.onEnded) this.props.onEnded();
65
- });
47
+ try {
48
+ const current = await CobrowseIO.currentSession()
49
+ if (current) this.setState({ session: current })
50
+ else {
51
+ const session = await CobrowseIO.createSession()
52
+ this.setState({ session })
53
+ }
54
+ } catch (error) {
55
+ this.setState({ error })
66
56
  }
67
57
 
68
- componentWillUnmount() {
69
- if (this.updateListener) this.updateListener.remove();
70
- if (this.endListener) this.endListener.remove();
71
- }
58
+ this.updateListener = CobrowseIO.addListener('session.updated', (session) => {
59
+ this.setState({ session })
60
+ })
61
+ this.endListener = CobrowseIO.addListener('session.ended', (session) => {
62
+ if (this.props.onEnded) this.props.onEnded()
63
+ })
64
+ }
72
65
 
73
- async endSession() {
74
- try {
75
- await CobrowseIO.endSession();
76
- this.setState({session: null});
77
- } catch(error) {
78
- this.setState({error});
79
- }
80
- }
66
+ componentWillUnmount () {
67
+ if (this.updateListener) this.updateListener.remove()
68
+ if (this.endListener) this.endListener.remove()
69
+ }
81
70
 
82
- renderError() {
83
- return (
84
- <Text style={[styles.text]}>{this.state.error.message}</Text>
85
- );
71
+ async endSession () {
72
+ try {
73
+ const { session } = this.state
74
+ await session.end()
75
+ this.setState({ session: null })
76
+ } catch (error) {
77
+ this.setState({ error })
86
78
  }
79
+ }
87
80
 
88
- renderCode() {
89
- let code = this.state.session && this.state.session.code;
90
- if (code) code = code.substr(0, 3) + '-' + code.substr(3);
91
- return (
92
- <View>
93
- <Text style={[styles.code, {opacity:code?1:0.2}]}>{code || '000-000'}</Text>
94
- <Text style={[styles.text]}>Provide this code to your support agent to begin screen sharing.</Text>
95
- <ActivityIndicator/>
96
- </View>
97
- );
98
- }
81
+ renderError () {
82
+ return (
83
+ <Text style={[styles.text]}>{this.state.error.message}</Text>
84
+ )
85
+ }
99
86
 
100
- renderManageSession() {
101
- return (
102
- <View>
103
- <Text style={[styles.text]}>You{"'"}re sharing screens from this app with a support agent.</Text>
104
- <TouchableOpacity onPress={()=>this.endSession()}>
105
- <Text style={[styles.text, styles.button]}>End Session</Text>
106
- </TouchableOpacity>
107
- </View>
108
- );
109
- }
87
+ renderCode () {
88
+ let code = this.state.session && this.state.session.code
89
+ if (code) code = code.substr(0, 3) + '-' + code.substr(3)
90
+ return (
91
+ <View>
92
+ <Text style={[styles.code, { opacity: code ? 1 : 0.2 }]}>{code || '000-000'}</Text>
93
+ <Text style={[styles.text]}>Provide this code to your support agent to begin screen sharing.</Text>
94
+ <ActivityIndicator />
95
+ </View>
96
+ )
97
+ }
110
98
 
111
- renderContent() {
112
- const { error, session } = this.state;
113
- if (error) {
114
- return this.renderError();
115
- } else if ((!session) || (session.state === 'pending' || session.state === 'authorizing')) {
116
- return this.renderCode();
117
- } else {
118
- return this.renderManageSession();
119
- }
120
- }
99
+ renderManageSession () {
100
+ return (
101
+ <View>
102
+ <Text style={[styles.text]}>You{"'"}re sharing screens from this app with a support agent.</Text>
103
+ <TouchableOpacity onPress={() => this.endSession()}>
104
+ <Text style={[styles.text, styles.button]}>End Session</Text>
105
+ </TouchableOpacity>
106
+ </View>
107
+ )
108
+ }
121
109
 
122
- render() {
123
- return (
124
- <View style={styles.container}>
125
- {this.renderContent()}
126
- </View>
127
- );
110
+ renderContent () {
111
+ const { error, session } = this.state
112
+ if (error) {
113
+ return this.renderError()
114
+ } else if ((!session) || (session.state === 'pending' || session.state === 'authorizing')) {
115
+ return this.renderCode()
116
+ } else {
117
+ return this.renderManageSession()
128
118
  }
119
+ }
120
+
121
+ render () {
122
+ return (
123
+ <View style={styles.container}>
124
+ {this.renderContent()}
125
+ </View>
126
+ )
127
+ }
129
128
  }
package/js/Redacted.js CHANGED
@@ -1,17 +1,19 @@
1
- import React, { useContext } from 'react';
2
- import { View, requireNativeComponent } from 'react-native';
3
- const CBIOCobrowseRedacted = requireNativeComponent('CBIOCobrowseRedacted');
1
+ import React, { useContext } from 'react'
2
+ import { View, requireNativeComponent } from 'react-native'
3
+ const CBIOCobrowseRedacted = requireNativeComponent('CBIOCobrowseRedacted')
4
4
 
5
- const RedactionContext = React.createContext(false);
5
+ const RedactionContext = React.createContext(false)
6
6
 
7
- module.exports = function(props) {
8
- const alreadyRedacted = useContext(RedactionContext);
9
- if (!alreadyRedacted) return (
10
- <RedactionContext.Provider value={true}>
11
- <CBIOCobrowseRedacted style={props.style}>
12
- <View>{props.children}</View>
13
- </CBIOCobrowseRedacted>
14
- </RedactionContext.Provider>
15
- );
16
- return props.children;
7
+ export default function (props) {
8
+ const alreadyRedacted = useContext(RedactionContext)
9
+ if (!alreadyRedacted) {
10
+ return (
11
+ <RedactionContext.Provider value>
12
+ <CBIOCobrowseRedacted style={props.style}>
13
+ <View>{props.children}</View>
14
+ </CBIOCobrowseRedacted>
15
+ </RedactionContext.Provider>
16
+ )
17
+ }
18
+ return props.children
17
19
  }
package/js/Session.js ADDED
@@ -0,0 +1,103 @@
1
+ const CobrowseIONative = require('react-native').NativeModules.CobrowseIO
2
+ const NativeEventEmitter = require('react-native').NativeEventEmitter
3
+
4
+ const emitter = new NativeEventEmitter(CobrowseIONative)
5
+
6
+ export default class Session {
7
+ constructor (session) {
8
+ this._session = session || {}
9
+ this._listen()
10
+ }
11
+
12
+ _update (session, onMatch) {
13
+ if (this._session.id === undefined || (session && this._session.id === session.id)) {
14
+ this._session = session
15
+ if (typeof onMatch === 'function') onMatch()
16
+ }
17
+ }
18
+
19
+ _listen () {
20
+ const updates = emitter.addListener('session.updated', (session) => this._update(session))
21
+ const ended = emitter.addListener('session.ended', (session) => {
22
+ this._update(session, () => {
23
+ updates.remove()
24
+ ended.remove()
25
+ })
26
+ })
27
+ }
28
+
29
+ addListener (eventType, listener) {
30
+ // TODO: this class should extend EventEmitter and forward
31
+ // on the non-namespaced versions of these events
32
+ switch (eventType) {
33
+ case 'ended':
34
+ eventType = 'session.updated'
35
+ break
36
+ case 'updated':
37
+ eventType = 'session.ended'
38
+ break
39
+ }
40
+
41
+ return emitter.addListener(eventType, (session) => {
42
+ this._update(session, () => {
43
+ listener(this)
44
+ })
45
+ })
46
+ }
47
+
48
+ get id () {
49
+ return this._session.id
50
+ }
51
+
52
+ get code () {
53
+ return this._session.code
54
+ }
55
+
56
+ get state () {
57
+ return this._session.state
58
+ }
59
+
60
+ get full_device () {
61
+ return this._session.full_device
62
+ }
63
+
64
+ get remote_control () {
65
+ return this._session.remote_control
66
+ }
67
+
68
+ get agent () {
69
+ return this._session.agent
70
+ }
71
+
72
+ activate () {
73
+ return CobrowseIONative.activateSession().then(() => {})
74
+ }
75
+
76
+ end () {
77
+ return CobrowseIONative.endSession()
78
+ }
79
+
80
+ isActive () {
81
+ return this._session.state === 'active'
82
+ }
83
+
84
+ isAuthorizing () {
85
+ return this._session.state === 'authorizing'
86
+ }
87
+
88
+ isPending () {
89
+ return this._session.state === 'pending'
90
+ }
91
+
92
+ isEnded () {
93
+ return this._session.state === 'ended'
94
+ }
95
+
96
+ setFullDevice (state) {
97
+ return CobrowseIONative.updateSession({ full_device: state })
98
+ }
99
+
100
+ setRemoteControl (state) {
101
+ return CobrowseIONative.updateSession({ remote_control: state })
102
+ }
103
+ }
@@ -1,25 +1,26 @@
1
- import React, { Component } from 'react';
2
- import CobrowseIO from './CobrowseIO';
1
+ import React from 'react'
2
+ import CobrowseIO from './CobrowseIO'
3
3
 
4
- export default class SessionControl extends Component {
4
+ export default class SessionControl extends React.Component {
5
+ constructor () {
6
+ super()
7
+ this.state = { session: null }
8
+ }
5
9
 
6
- constructor() {
7
- super();
8
- this.state = { session: null };
9
- }
10
+ async componentDidMount () {
11
+ this.setState({ session: await CobrowseIO.currentSession() })
12
+ this.updateListener = CobrowseIO.addListener(CobrowseIO.SESSION_UPDATED, (session) => {
13
+ this.setState({ session })
14
+ })
15
+ }
10
16
 
11
- componentDidMount() {
12
- this.updateListener = CobrowseIO.addListener(CobrowseIO.SESSION_UPDATED, (session) => {
13
- this.setState({ session });
14
- });
15
- }
17
+ componentWillUnmount () {
18
+ if (this.updateListener) this.updateListener.remove()
19
+ }
16
20
 
17
- componentWillUnmount() {
18
- if (this.updateListener) this.updateListener.remove();
19
- }
20
-
21
- render() {
22
- if (this.state.session && this.state.session.state === 'active') return this.props.children;
23
- else return null;
24
- }
21
+ render () {
22
+ const { session } = this.state
23
+ if (session && session.isActive()) return this.props.children
24
+ else return null
25
+ }
25
26
  }
package/js/index.js CHANGED
@@ -1,6 +1,5 @@
1
- 'use strict';
2
-
3
- export { default as default } from './CobrowseIO'
1
+ export { default } from './CobrowseIO'
4
2
  export { default as CobrowseView } from './CobrowseView'
5
3
  export { default as Redacted } from './Redacted'
6
4
  export { default as SessionControl } from './SessionControl'
5
+ export { default as CobrowseAccessibilityService } from './CobrowseAccessibilityService'
package/package.json CHANGED
@@ -1,8 +1,14 @@
1
1
  {
2
2
  "name": "cobrowse-sdk-react-native",
3
- "version": "2.6.0",
3
+ "version": "2.10.0",
4
4
  "description": "Cobrowse SDK for React Native",
5
- "main": "./js/index.js",
5
+ "main": "js/index.js",
6
+ "types": "ts/index.d.ts",
7
+ "scripts": {
8
+ "lint-fix": "ts-standard ts/*.d.ts --fix",
9
+ "watch": "node scripts/watch.mjs",
10
+ "start:dev": "nodemon --exec ./scripts/copy.sh"
11
+ },
6
12
  "author": {
7
13
  "name": "Andy Pritchard"
8
14
  },
@@ -21,5 +27,18 @@
21
27
  "cobrowseio"
22
28
  ],
23
29
  "license": "Apache-2.0",
24
- "dependencies": {}
30
+ "optionalDependencies": {
31
+ "@types/react": "^17.0.38",
32
+ "@types/react-native": "^0.66.15"
33
+ },
34
+ "dependencies": {},
35
+ "devDependencies": {
36
+ "@types/react": "^17.0.38",
37
+ "@types/react-native": "^0.66.15",
38
+ "managed-service-daemon": "^1.2.1",
39
+ "nodemon": "^2.0.15",
40
+ "ts-standard": "^11.0.0",
41
+ "typescript": "^4.5.5",
42
+ "watchr": "^6.11.0"
43
+ }
25
44
  }
@@ -0,0 +1,6 @@
1
+ /* eslint-disable @typescript-eslint/no-extraneous-class,accessor-pairs */
2
+ export default class CobrowseAccessibilityService {
3
+ static showSetup (): Promise<void>
4
+
5
+ static isRunning (): Promise<boolean>
6
+ }
@@ -0,0 +1,29 @@
1
+ /* eslint-disable @typescript-eslint/no-extraneous-class,accessor-pairs */
2
+ import type { EmitterSubscription } from 'react-native'
3
+ import Session from './Session'
4
+
5
+ export type NativeSessionEvent = 'session.updated' | 'session.ended'
6
+
7
+ export default class CobrowseIO {
8
+ static handleSessionRequest (session?: Session): void
9
+
10
+ static addListener (eventType: NativeSessionEvent, listener: (session: Session) => void): EmitterSubscription
11
+
12
+ static start (): void
13
+
14
+ static stop (): void
15
+
16
+ static set api (api: string)
17
+
18
+ static set license (license: string)
19
+
20
+ static set customData (customData: Record<string, any>)
21
+
22
+ static set deviceToken (token: string)
23
+
24
+ static currentSession (): Promise<Session>
25
+
26
+ static createSession (): Promise<Session>
27
+
28
+ static getSession (codeOrId: string): Promise<Session>
29
+ }
@@ -0,0 +1,20 @@
1
+ import type { Component } from 'react'
2
+ import type { View, Text } from 'react-native'
3
+
4
+ export default class CobrowseView extends Component {
5
+ componentDidMount (): Promise<void>
6
+
7
+ componentWillUnmount (): void
8
+
9
+ endSession (): Promise<void>
10
+
11
+ renderError (): Text
12
+
13
+ renderCode (): View
14
+
15
+ renderManageSession (): View
16
+
17
+ renderContent (): Text | View
18
+
19
+ render (): View
20
+ }
@@ -0,0 +1,7 @@
1
+ import type { Provider, ReactNode } from 'react'
2
+
3
+ type Props = Readonly<{}> & Readonly<{
4
+ children?: ReactNode
5
+ }>
6
+
7
+ export default function (props: Props): Provider<boolean>
@@ -0,0 +1,56 @@
1
+ /* eslint-disable @typescript-eslint/no-extraneous-class,accessor-pairs */
2
+ import type { EmitterSubscription } from 'react-native'
3
+
4
+ export type SessionEvent = 'updated' | 'ended'
5
+
6
+ export type SessionState = 'active' | 'authorizing' | 'ended' | 'pending'
7
+
8
+ export type RemoteControlState = 'on' | 'requested' | 'rejected' | 'off'
9
+
10
+ export interface Agent {
11
+ id: string
12
+ name: string
13
+ }
14
+
15
+ export interface SessionLike {
16
+ id: string
17
+ code: string
18
+ state: SessionState
19
+ full_device: boolean
20
+ remote_control: RemoteControlState
21
+ agent: Agent
22
+ }
23
+
24
+ export default class Session {
25
+ constructor (sessionLike: SessionLike)
26
+
27
+ addListener (eventType: SessionEvent, listener: (session: Session) => void): EmitterSubscription
28
+
29
+ get id (): string
30
+
31
+ get code (): string
32
+
33
+ get state (): SessionState
34
+
35
+ get full_device (): boolean
36
+
37
+ get remote_control (): RemoteControlState
38
+
39
+ get agent (): Agent
40
+
41
+ activate (): Promise<void>
42
+
43
+ end (): Promise<void>
44
+
45
+ isActive (): boolean
46
+
47
+ isAuthorizing (): boolean
48
+
49
+ isPending (): boolean
50
+
51
+ isEnded (): boolean
52
+
53
+ setFullDevice (state: boolean): Promise<void>
54
+
55
+ setRemoteControl (state: RemoteControlState): Promise<void>
56
+ }
@@ -0,0 +1,9 @@
1
+ import type { Component, ReactNode } from 'react'
2
+
3
+ export default class SessionControl extends Component {
4
+ componentDidMount (): void
5
+
6
+ componentWillUnmount (): void
7
+
8
+ render (): ReactNode | null
9
+ }
package/ts/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export { default } from './CobrowseIO'
2
+ export { default as CobrowseView } from './CobrowseView'
3
+ export { default as Redacted } from './Redacted'
4
+ export { default as SessionControl } from './SessionControl'
5
+ export { default as CobrowseAccessibilityService } from './CobrowseAccessibilityService'
package/CHANGELOG.md DELETED
@@ -1,24 +0,0 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
-
5
- ## [2.6.0](https://github.com/cobrowseio/cobrowse-sdk-react-native/compare/v2.5.2...v2.6.0) (2021-06-14)
6
-
7
-
8
- ### Features
9
-
10
- * allow styling of redacted component ([614b64e](https://github.com/cobrowseio/cobrowse-sdk-react-native/commit/614b64e56a127aec693077f336935c628b609117))
11
-
12
-
13
- ### Bug Fixes
14
-
15
- * fix for Undefined symbols error (_OBJC_CLASS_$_RCTEventDispatcher) ([d66ef6d](https://github.com/cobrowseio/cobrowse-sdk-react-native/commit/d66ef6d6767b567db524865e002867718ca6301a))
16
-
17
- ## [2.1.0] - 2019-04-26
18
- - Added `handleSessionRequest` API to `CobrowseIO`
19
-
20
- ## [2.0.0] - 2019-04-24
21
- ### Changed
22
- - Switched to promises for all methods that previously took callback (e.g. `createSession`, `endSession`, `currentSession`)
23
- - Updated example project to RN 0.59
24
- - Renamed `loadSession` to `getSession` to match other SDKs