@glance-networks/reactnative-bridge
TypeScript icon, indicating that this package has built-in type declarations

0.1.3 • Public • Published

@glance-networks/reactnative-bridge

Android/iOS Native modules for hosting the GlanceSDK RN support layer

Getting started

  1. Run yarn install to install the dependencies.
  2. Run yarn example <android/ios> to run the internal app where we test the bridge

PS.: we didn't move all methods to the src/index.tsx yet, but those that were moved already work. The ones accessed directly by the GlanceBridge too, but that should change once we publish it to the NPM registry.

Usage

Due to framework/language limitations and also aiming to build a smooth use between platforms, we need to send all the method's arguments as key-value pairs in a single map in all methods. To make it even easier, we have a set of constants available through the GlanceBridge.getConstants() method where you can get any key name before creating the map, avoiding hardcoded strings. To see the full list, check the appendix.

PS.: the ReadableMap being received by some methods offers the same flexibility we have in the native calls, by using overloading to provide several method variations with different arguments. Required fields and data type rules are the same.

We also tried to simulate the same data types by creating sub-maps when needed. For example, DisplayParams in StartParams would look like:

{
 "key" : "1234",
 "displayParams" : {
    "displayName": "somename",
    "scale": 1.0,
    ...
 }
 ...  
}

Here's a list of the available methods (for more details, please check the native docs - Android and iOS):

Method Sync? Android iOS ReadableMap structure¹
getVersion(Callback callback) : void -
init(ReadableMap readableMap) : void { "timeout": 1000, "attempts": 3, "glanceServer": "www.glance.net", "groupID" : 0000, "visitorID": "someid", "site": "somesite", "token": "sometoken", "name": "some name", "email": "some@email", "phone": "12345678", "allowedCameras": "\"front\"}
addMaskedViewId(Integer reactTag, String label, Promise promise) : void -
removeMaskedViewId(Integer viewId) : void -
getVisitorCallId(Promise promise) : void -
isInSession(Promise promise) : void -
isVideoAvailable(Promise promise) : void -
isAgentVideoEnabled(Promise promise) : void -
pause(Boolean isPaused) : Boolean -
togglePause() : void -
release() : void -
updateVisitorVideoSize(int width, int height, String stringMode) : void -
updateVisitorVideoStatus(boolean isPaused) : void -
updateWidgetVisibility(String stringVisibility) : void -
updateWidgetLocation(String stringVisibility) : void -
setUserState(String state, String value) : void -
sendUserMessage(String messageType, String value) : void -
startSession(ReadableMap readableMap) : void { "groupID" : 0000, "maskKeyboard": true, "timeout": 1000, "attempts": 3,"skipDialog": false, "displayParams" : {"displayName": "somename", "scale": 1.0, "displayCaptureWidth": 0, "displayCaptureHeight": 0, "displayVideo": false }, "key": "1234", "videoMode": "smallmultiway", "captureEntireScreen": false, "mediaProjectionEnabled": false, "mainCallId": 0, "maxGuests": 0, "show": false, "guestInfoFlags": 0, "encrypt": false, "requestRC": false, "instantJoin": false, "forceTunnel": false, "viewerCloseable": false, "reportErrors": false, "persist": false, "showTerms": true, "presenceStart": false, "paused": false, "termsUrl": null }
endSession() : void -
addVisitorVideo(ReadableMap readableMap) : void { "videoMode": "smallmultiway", "invokeShowWidget": true}
getVisitorId(Promise promise) : void -
getVisitorStartParams(Callback callback) : void -
setPresenceStartParams(ReadableMap readableMap) : void { "displayParams" : {"displayName": "somename", "scale": 1.0, "displayCaptureWidth": 0, "displayCaptureHeight": 0, "displayVideo": false }, "key": null, "videoMode": "smallmultiway", "captureEntireScreen": false, "mediaProjectionEnabled": false, "mainCallId": 0, "maxGuests": 0, "show": false, "guestInfoFlags": 0, "encrypt": false, "requestRC": false, "instantJoin": false, "forceTunnel": false, "viewerCloseable": false, "reportErrors": false, "persist": false, "showTerms": true, "presenceStart": false, "paused": false, "termsUrl": null }
getPresenceVideoMode(Callback callback) : void -
arePresenceTermsDisplayed(Promise promise) : void -
connectToPresence(ReadableMap readableMap) : void { "timeout": 1000, "attempts": 3, "registerNotifications": false }
sendToPresenceSession(ReadableMap readableMap) : void { "presenceEvent": "presence", "presenceDataMap": { "url": "someurl"}}
sendPresenceTermsAccepted(boolean isAccepted) : void -
disconnectPresence() : void -
sendPresenceTermsDisplayed() : void -
isPresenceConnected(Promise promise) : void -
getApplicationName() : String -
maskKeyboard(boolean maskKeyboard) : void -
restartAgentVideo() : void -
getCapturedScreenSize(Callback callback) : void -
openWebView() : void -
setGlanceGroupID(String groupID) : void -
setGlanceServer(String server) : void -

¹ This represents what the method can expect to have in its ReadbableMap argument. This doesn't mean that you need to always send everything. For more details, please refer to the native docs.

Masking

To achieve masking we use react tags to identify the views in the native level so we can remove the mask later. Basic steps to make it work:

  1. Create a variable to hold a react tag reference that will be used later:
import React from 'react';
...

    constructor(props: any) {
        super(props);

        this.viewRef = React.createRef();

        ....
    }

...    
  1. Once the component is loaded, find the native view reference and save it in the state so we can use it to call GlanceBridge.addMaskedViewId:
import { findNodeHandle } from 'react-native';
...

async componentDidMount() {
    const reactTag = findNodeHandle(this.vewRef.current);
    this.setState({logoViewId : await GlanceBridge.addMaskedViewId(reactTag, "MASKED 1")});

    ....
}

...
  1. Use the viewRef in the desired view.
render() {
    return (
      <View style={styles.container}>
        <Text style={styles.text} ref={this.viewRef}>Some view to be masked</Text>
      </View>
    );
  }

Examples

Sync methods

const dataMap = {
    groupID: <YOUR GROUP ID>,
    visitorID: "",
    site: "",
    token: "",
    name: "",
    email: "",
    phone: "",
    allowedCameras: '"front","back"'
};
dataMap[VISITOR_ID_MAP_KEY] = visitorID;

GlanceBridge.init(dataMap);

Async methods

const callId = await GlanceBridge.getVisitorCallId();
console.log('Call ID:', `${callId}`);

How to listen to Events

import { NativeModules, NativeEventEmitter } from 'react-native';

const { GlanceBridge } = NativeModules;
const eventEmitter = new NativeEventEmitter(GlanceBridge);

const GlanceBridge = NativeModules.GlanceBridge;
const {
  GLANCE_EVENT_LISTENER_KEY,
  SESSION_KEY_MAP_KEY,
  EventVisitorInitialized,
  EventConnectedToSession,
  EventSessionEnded
} = GlanceBridge.getConstants();

export default class MyComponent extends Component {

    ...

    onGlanceEvent = eventEmitter.addListener(GLANCE_EVENT_LISTENER_KEY, async (event) => {
        console.log("RECEIVED EVENT >>>", event);

        if (event.code == EventConnectedToSession) {
            // update any status view/variable/etc

            Alert.alert(
                `Session key:`,
                event[SESSION_KEY_MAP_KEY]
            );
        } else if (event.code == EventSessionEnded) {
            // update any status view/variable/etc
        }
    });

    componentWillUnmount() {
        this.onGlanceEvent.remove(); // don't forget to unregister it
    }

    ....
}

Constants

In order to make things easier, we reused the same variable names/constants from the native code as much as possible. Along with the following list, you'll also have access to the VideoMode and EventCode constant values.

---------------TODO: maybe those are different for Android and iOS

Key Value
SDK_VERSION_MAP_KEY "version"
SESSION_KEY_MAP_KEY "sessionkey"
MASK_KEYBOARD_MAP_KEY "maskKeyboard"
VIDEO_MODE_MAP_KEY "videoMode"
GLANCE_TIMEOUT_MAP_KEY "timeout"
GLANCE_ATTEMPTS_MAP_KEY "attempts"
GROUP_ID_MAP_KEY "groupID"
VISITOR_ID_MAP_KEY "visitorID"
GLANCE_SERVER_MAP_KEY "glanceServer"
TOKEN_MAP_KEY "token"
NAME_MAP_KEY "name"
EMAIL_MAP_KEY "email"
PHONE_MAP_KEY "phone"
SKIP_DIALOG_MAP_KEY "skipDialog"
INVOKE_SHOW_WIDGET_MAP_KEY "invokeShowWidget"
SITE_MAP_KEY "site"
ALLOWED_CAMERAS_MAP_KEY "allowedCameras"
REGISTER_PRESENCE_NOTIFICATIONS_MAP_KEY "registerNotifications"
SCREEN_X_VALUE "screenX"
SCREEN_Y_VALUE "screenY"
DISPLAY_PARAMS_MAP_KEY "displayParams"
DISPLAY_PARAMS_NAME_MAP_KEY "displayName"
DISPLAY_PARAMS_SCALE_MAP_KEY "displayScale"
DISPLAY_PARAMS_WIDTH_MAP_KEY "displayCaptureWidth"
DISPLAY_PARAMS_HEIGHT_MAP_KEY "displayCaptureHeight"
DISPLAY_PARAMS_VIDEO_MAP_KEY "displayVideo"
START_PARAMS_CAPTURE_ENTIRE_SCREEN_MAP_KEY "captureEntireScreen"
START_PARAMS_MEDIA_PROJECTION_MAP_KEY "mediaProjectionEnabled"
START_PARAMS_MAIN_CALL_ID_MAP_KEY "mainCallId"
START_PARAMS_MAX_GUESTS_MAP_KEY "maxGuests"
START_PARAMS_SHOW_MAP_KEY "show"
START_PARAMS_GUEST_INFO_FLAGS_MAP_KEY "guestInfoFlags"
START_PARAMS_ENCRYPT_MAP_KEY "encrypt"
START_PARAMS_REQUEST_RC_MAP_KEY "requestRC"
START_PARAMS_INSTANT_JOIN_MAP_KEY "instantJoin"
START_PARAMS_FORCE_TUNNEL_MAP_KEY "forceTunnel"
START_PARAMS_VIEWER_CLOSEABLE_MAP_KEY "viewerCloseable"
START_PARAMS_REPORT_ERRORS_MAP_KEY "reportErrors"
START_PARAMS_PERSIST_MAP_KEY "persist"
START_PARAMS_SHOW_TERMS_MAP_KEY "showTerms"
START_PARAMS_PRESENCE_START_MAP_KEY "presenceStart"
START_PARAMS_PAUSED_MAP_KEY "paused"
START_PARAMS_TERMS_URL_MAP_KEY "termsUrl"
GLANCE_EVENT_LISTENER_KEY "GlanceEvent"
GUEST_COUNT_MAP_KEY "guestCount"
EVENT_RECEIVED_MESSAGE_MAP_KEY "receivedMessage"
EVENT_RECEIVED_MESSAGE_VALUE_MAP_KEY "receivedMessageValue"
EVENT_WARNING_MESSAGE_MAP_KEY "warningMsg"
EVENT_CODE_MAP_KEY "code"
EVENT_TYPE_MAP_KEY "type"
PRESENCE_EVENT_MAP_KEY "presenceEvent"
PRESENCE_DATA_MAP_KEY "presenceDataMap"

License

See License file and https://ww2.glance.net/terms/ for Glance terms of service.

Package Sidebar

Install

npm i @glance-networks/reactnative-bridge

Weekly Downloads

138

Version

0.1.3

License

SEE LICENSE IN LICENSE.TXT

Unpacked Size

24 MB

Total Files

116

Last publish

Collaborators

  • ehardebeck
  • jonathanfink
  • tomkraft
  • veronika.makurina
  • dperezglance
  • glima_glance
  • robbyketchell