edge-core-js
Version:
Edge account & wallet management library
108 lines (87 loc) • 2.97 kB
JavaScript
import '../../client-side'
import { findNodeHandle, UIManager } from 'react-native'
import { Bridge, onMethod } from 'yaob'
import { hideProperties } from '../hidden-properties'
import {
YAOB_THROTTLE_MS
} from './react-native-types'
/**
* Sets up a YAOB bridge for use with a React Native WebView.
* The returned callbacks should be passed to the `onMessage` and `ref`
* properties of the WebView. Handles WebView reloads and related
* race conditions.
* @param {*} onRoot Called when the inner HTML sends a root object.
* May be called multiple times if the inner HTML reloads.
* @param {*} debug Provide a message prefix to enable debugging.
*/
export function makeYaobCallbacks(
onRoot,
debug
) {
let bridge
let gatedRoot
let webview = null
// Gate the root object on the WebView being ready:
function tryReleasingRoot() {
if (gatedRoot != null && webview != null) {
onRoot(gatedRoot)
gatedRoot = undefined
}
}
// Feed incoming messages into the YAOB bridge (if any):
function handleMessage(event) {
const message = JSON.parse(event.nativeEvent.message)
if (debug != null) console.info(`${debug} →`, message)
// This is a terrible hack. We are using our inside knowledge
// of YAOB's message format to determine when the client has restarted.
if (
bridge != null &&
message.events != null &&
message.events.find((event) => event.localId === 0) != null
) {
bridge.close(new Error('edge-core: The WebView has been unmounted.'))
bridge = undefined
}
// If we have no bridge, start one:
if (bridge == null) {
let firstMessage = true
bridge = new Bridge({
hideProperties,
sendMessage: message => {
if (debug != null) console.info(`${debug} ←`, message)
if (webview == null) return
const messageJs = JSON.stringify(message)
.replace(/\u2028/g, '\\u2028')
.replace(/\u2029/g, '\\u2029')
const js = `if (window.reactBridge != null) {${
firstMessage
? 'window.reactBridge.inSync = true;'
: 'window.reactBridge.inSync && '
} window.reactBridge.handleMessage(${messageJs})}`
firstMessage = false
UIManager.dispatchViewManagerCommand(
findNodeHandle(webview),
'runJs',
[js]
)
},
throttleMs: YAOB_THROTTLE_MS
})
// Use our inside knowledge of YAOB to directly
// subscribe to the root object appearing:
// @ts-expect-error
onMethod.call(bridge._state, 'root', root => {
gatedRoot = root
tryReleasingRoot()
})
}
// Finally, pass the message to the bridge:
bridge.handleMessage(message)
}
// Listen for the WebView component to mount:
function setRef(element) {
webview = element
tryReleasingRoot()
}
return { handleMessage, setRef }
}