@thebigcrunch/sdk
Version:
The big crunch SDK library
182 lines (160 loc) • 7.01 kB
JavaScript
import io from "socket.io-client";
import "url-search-params-polyfill";
import { getConfig } from "./config";
const inputParameters = {}; // save and collect up inputs as they come in
const inputCells = {}; // The cell objects of the inputs.
const inputsOriginalOrdered = {};
const queryParams = new URLSearchParams(window.location.search);
let vizzySocket;
const customConfig = (() => {
const c = queryParams.get("customConfig");
return c ? JSON.parse(decodeURIComponent(c)) : null;
})();
const sortParametersByIndex = function sortParametersByIndex(parameters) {
return Object.keys(parameters)
.map(id => ({
id,
name: parameters[id].name,
value: parameters[id].value,
index: parameters[id].index,
cell: parameters[id].cell
}))
.sort((a, b) => a.index - b.index);
};
// Build two lists:
// 1/ the orignal list, in index order, including ids.
// 2/ the inputs[] list for vizzies to access vi array or by name and for updates individual items
const buildParameterInputsList = function buildParameterInputsList(
spaceId,
parameters
) {
sortParametersByIndex(parameters).forEach(input => {
inputsOriginalOrdered[spaceId].push(input);
// make names available by name in the input object
if (input.name) {
inputParameters[spaceId][input.name] = input.value;
inputCells[spaceId][input.name] = input.cell;
}
// make every variable (named or unnamed) available by index
inputParameters[spaceId].push(input.value);
inputCells[spaceId].push(input.cell);
});
};
// Get the positional index into the inputs array of the give param id thats stored in the origianl ordered list
const getIndexOfParam = function getIndexOfParam(spaceId, paramId) {
const input = inputsOriginalOrdered[spaceId].find(e => e.id === paramId);
return input.index;
};
const callTBCReady = function callTBCReady() {
if (window && window.tbcReady) {
window.tbcReady();
}
};
// Vizzies use this method to connect to the server for the first time and start to receive their
// initial prarameters and subsequent ones.
//
// TODO: Handle delete param
// TODO: Disconnect any existing sockets here so we don't get old update'
// TODO: pass in the same of the parameter which has been updated
//
const listenForVizzyParams = function listenForVizzyParams(spaceId, onChange) {
inputsOriginalOrdered[spaceId] = [];
inputParameters[spaceId] = [];
inputCells[spaceId] = [];
if (!vizzySocket) {
vizzySocket = io(getConfig().spacesSocketUrl);
}
vizzySocket
.on("all_params_update", (id, data) => {
if (id === spaceId) {
buildParameterInputsList(spaceId, data);
onChange(inputParameters[spaceId], inputCells[spaceId]); // tell the vizzy we have its inputs
callTBCReady();
}
})
.on("params_update", (id, input, spaceUuid) => {
// id is location tbc_x_y and spaceuuid is the uuid
if (id !== spaceId && spaceUuid !== spaceId) {
// If this update isn't for this space forget it.
return;
}
if (inputsOriginalOrdered[spaceId].length === 0) {
// We haven't received the original parameters for this space.
return;
}
// - Only poke in a few updates, no need to rebuild lists
const inputIndex = getIndexOfParam(spaceId, input.param);
inputParameters[spaceId][inputIndex] = input.value;
inputCells[spaceId][inputIndex] = input.cell;
// If this is a named parameter we also need to put it into the name because values aren't stored by reference like array params.
if (input.paramName !== null) {
inputParameters[spaceId][input.paramName] = input.value;
inputCells[spaceId][input.paramName] = input.cell;
}
onChange(inputParameters[spaceId], inputCells[spaceId]);
callTBCReady();
})
.on("array_param_update", (id, arrayValueUpdate, spaceUuid) => {
//id is location tbc_x_y and spaceuuid is the uuid
if (id !== spaceId && spaceUuid !== spaceId) {
// If this update isn't for this space forget it.
return;
}
if (inputsOriginalOrdered[spaceId].length === 0) {
// We haven't received the original parameters for this space.
return;
}
// inject the array value into its position in the parameter array
// Get the index of the parameter from the original list
const inputIndex = getIndexOfParam(spaceId, arrayValueUpdate.param);
const inputArray = inputParameters[spaceId][inputIndex];
const inputCellArray = inputCells[spaceId][inputIndex];
if (inputArray) {
inputArray[arrayValueUpdate.offset.y][
arrayValueUpdate.offset.x
] = arrayValueUpdate.value;
inputCellArray[arrayValueUpdate.offset.y][
arrayValueUpdate.offset.x
] = arrayValueUpdate.cell;
onChange(inputParameters[spaceId], inputCells[spaceId]); // Give the vizzy everything back, not just the one that was ListeningStateChangedEvent. Could change this.
} else {
inputArray[arrayValueUpdate.offset.y][
arrayValueUpdate.offset.x
] = arrayValueUpdate.value;
inputCellArray[arrayValueUpdate.offset.y][
arrayValueUpdate.offset.x
] = arrayValueUpdate.cell;
onChange(inputParameters[spaceId], inputCells[spaceId]);
}
callTBCReady();
});
vizzySocket.emit("join", spaceId);
};
export const listenToVizzy = function listenToVizzy(options = []) {
const { onChange, onConfig } = options;
if (onConfig && customConfig) onConfig(customConfig);
let spaceId;
if (options.spaceId) {
spaceId = options.spaceId;
} else if (
document.currentScript &&
document.currentScript.getAttribute("data-tbc-id")
) {
// document.currentScript is not support in IE 11.
spaceId = atob(document.currentScript.getAttribute("data-tbc-id"));
} else if (options.spaceId) {
spaceId = options.spaceId;
} else if (queryParams.get("id")) {
spaceId = queryParams.get("id");
}
if (!spaceId) {
console.error("The cell ID was not provided to TBC.vizzy");
return;
}
// Reset the input parameters for this space
inputParameters[spaceId] = {};
// Listen to changes to the vizzy parameters (if we actually do something with them)
if (onChange) {
listenForVizzyParams(spaceId, onChange);
}
};