@blockv/sdk
Version:
Allows web apps to display and interact with vatoms.
202 lines (181 loc) • 6.87 kB
JavaScript
//
// BlockV AG. Copyright (c) 2018, all rights reserved.
//
// Licensed under the BlockV SDK License (the "License"); you may not use this file or
// the BlockV SDK except in compliance with the License accompanying it. Unless
// required by applicable law or agreed to in writing, the BlockV SDK distributed under
// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
// ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
//
import BaseFace from '../BaseFace'
import BridgeV1 from './BridgeV1'
import BridgeV2 from './BridgeV2'
export default class BaseWebFace extends BaseFace {
/** @private Called on startup */
onLoad () {
// Create iframe
this.iframe = document.createElement('iframe')
this.iframe.style.cssText = 'display: block; position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; overflow: hidden; border: none; background: none; outline: none; z-index:0;'
this.iframe.setAttribute('src', this.face.properties.display_url)
this.element.appendChild(this.iframe)
this.vatom = this.vatomView.vatom
this.owner = this.vatomView.vatom.properties.owner
this.user = this.vatomView.blockv.UserManager.getPublicUserProfile(this.owner)
this.version = null
this.BridgeV1 = new BridgeV1(this.vatomView.blockv, this.vatom, this.face)
this.BridgeV2 = new BridgeV2(this.vatomView.blockv, this.vatom, this.face)
// Bind functions
this.onIncomingBridgeMessage = this.onIncomingBridgeMessage.bind(this)
// Add bridge message listener
window.addEventListener('message', this.onIncomingBridgeMessage)
// Done
return Promise.resolve()
}
/** @private Called when the view is unloaded */
onUnload () {
// Remove iframe
this.element.removeChild(this.iframe)
this.iframe.onload = null
this.iframe = null
// Remove bridge message listener
window.removeEventListener('message', this.onIncomingBridgeMessage)
}
processIncomingBridgeMessage (name, payload) {
switch (name) {
case 'vatom.init':
this.version = 1
return this.BridgeV1.init(payload)
case 'vatom.children.get':
return this.BridgeV1.getChildren(payload)
case 'vatom.rpc.call':
return this.BridgeV1.rpc()
case 'vatom.performAction':
return this.BridgeV1.performAction(payload)
case 'user.profile.fetch':
return this.BridgeV1.getUser()
case 'user.avatar.fetch':
return this.BridgeV1.getUser()
case 'vatom.patch':
return this.BridgeV1.patchVatom(payload)
case 'vatom.get':
return this.BridgeV1.getVatom(payload)
case 'core.init':
this.version = 2
return this.BridgeV2.init(payload)
case 'core.user.get':
return this.BridgeV2.getUserProfile(payload)
case 'core.vatom.get':
return this.BridgeV2.getVatom()
case 'core.vatom.children.get':
return this.BridgeV2.getVatomChildren(payload)
case 'core.action.perform':
return this.BridgeV2.performAction(payload)
case 'core.resource.encode':
return this.BridgeV2.encodeResource(payload)
case 'core.vatom.update':
this.vatom = payload.vatom
break
case 'viewer.vatom.show':
return this.BridgeV2.customMessage(payload)
case 'viewer.qr.scan':
return this.BridgeV2.customMessage(payload)
case 'viewer.view.close':
return this.BridgeV2.customMessage(payload)
case 'viewer.url.open':
return this.BridgeV2.customMessage(payload)
case 'viewer.scanner.show':
return this.BridgeV2.customMessage(payload)
default:
// Unknown event. Pass on to VatomView listener
if (this.vatomView && this.vatomView.onMessage) {
return this.vatomView.onMessage(name, payload)
}
// No listener, this is an error
return Promise.reject(new Error('Bridge message not implemented.'))
}
}
onIncomingBridgeMessage (event) {
// Get payload
let payload = event.data
// Check source is from this face's iframe
if (!payload || !this.iframe || event.source != this.iframe.contentWindow) {
return
}
// Check if there's a response ID, if so the web face is expecting a reply with that ID
let responseID = null
if (payload.responseID) {
responseID = payload.responseID
}
// Process it, get response
Promise.resolve(this.processIncomingBridgeMessage(payload.name, payload.data || payload.payload)).then(resp => {
// Done, send response back
if (payload.version === '2.0.0') {
this.sendV2Message(payload.request_id, payload.name, resp)
} else {
this.sendv1Message(responseID || resp._responseName, resp)
}
}).catch(err => {
// Failed, send error response
this.sendv1Message(responseID, {
errorCode: err.code,
errorText: err.message
})
})
}
sendv1Message (name, data) {
// Check if iframe is setup
if (!this.iframe || !this.iframe.contentWindow) {
return
}
// Send payload
this.iframe.contentWindow.postMessage({
source: 'VatomicSDK',
name: name,
data: data
}, '*')
}
sendV2Message (id, name, data, isRequest) {
// Check if iframe is setup
if (!this.iframe || !this.iframe.contentWindow) {
return
}
// Send payload
this.iframe.contentWindow.postMessage({
[ isRequest ? 'request_id' : 'response_id' ]: id,
source: 'BLOCKv SDK',
name: name,
payload: data,
version: '2.0.0'
}, '*')
}
vatomStateChanged (vatom) {
if (this.version === 1) {
if (vatom.id === this.vatom.id && this.face) {
this.vatom = vatom
var resources = {}
for (var res in this.vatomView.vatom.resources) {
resources[res] = this.vatomView.vatom.resources[res].value.value
}
var data = {
vatomInfo: {
id: this.vatomView.vatom.id,
properties: this.vatomView.vatom.properties,
resources: resources,
faceProperties: this.face.properties
}
}
this.sendv1Message('vatom.updated', data)
}
} else {
if (vatom.id === this.vatom.id && this.face) {
this.vatom = vatom
this.sendV2Message('res_1', 'core.vatom.update', { vatom: this.BridgeV2.encodeVatom(vatom) }, true)
}
}
}
onVatomUpdated () {
this.vatomStateChanged(this.vatom)
// console.log(this.vatomView.vatom);
}
}