added row level AES encryption.
This commit is contained in:
parent
d6941fd1bf
commit
3d3f73c259
29
package-lock.json
generated
29
package-lock.json
generated
@ -32,7 +32,9 @@
|
|||||||
"earcut": "^2.2.4",
|
"earcut": "^2.2.4",
|
||||||
"events": "^3.3.0",
|
"events": "^3.3.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
|
"hash-wasm": "4.11.0",
|
||||||
"hls.js": "^1.1.4",
|
"hls.js": "^1.1.4",
|
||||||
|
"js-crypto-aes": "1.0.6",
|
||||||
"loglevel": "^1.9.1",
|
"loglevel": "^1.9.1",
|
||||||
"niceware": "^4.0.0",
|
"niceware": "^4.0.0",
|
||||||
"peer-lite": "2.0.2",
|
"peer-lite": "2.0.2",
|
||||||
@ -43,6 +45,7 @@
|
|||||||
"recordrtc": "^5.6.0",
|
"recordrtc": "^5.6.0",
|
||||||
"rfc4648": "^1.5.3",
|
"rfc4648": "^1.5.3",
|
||||||
"round": "^2.0.1",
|
"round": "^2.0.1",
|
||||||
|
"uint8-to-b64": "^1.0.2",
|
||||||
"uuid": "^9.0.1"
|
"uuid": "^9.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -1702,6 +1705,11 @@
|
|||||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/hash-wasm": {
|
||||||
|
"version": "4.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hash-wasm/-/hash-wasm-4.11.0.tgz",
|
||||||
|
"integrity": "sha512-HVusNXlVqHe0fzIzdQOGolnFN6mX/fqcrSAOcTBXdvzrXVHwTz11vXeKRmkR5gTuwVpvHZEIyKoePDvuAR+XwQ=="
|
||||||
|
},
|
||||||
"node_modules/hls.js": {
|
"node_modules/hls.js": {
|
||||||
"version": "1.5.8",
|
"version": "1.5.8",
|
||||||
"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.5.8.tgz",
|
"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.5.8.tgz",
|
||||||
@ -1826,6 +1834,19 @@
|
|||||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/js-crypto-aes": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-crypto-aes/-/js-crypto-aes-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-E2hu9z5+YtpDg9Un/bDfmH+I5dv/8aN+ozxv9L0ybZldcQ9T5iYDbBKdlKGBUKI3IvzoWSBSdnZnhwZaRIN46w==",
|
||||||
|
"dependencies": {
|
||||||
|
"js-crypto-env": "^1.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/js-crypto-env": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-crypto-env/-/js-crypto-env-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-8/UNN3sG8J+yMzqwSNVaobaWhIz4MqZFoOg5OB0DFXqS8eFjj2YvdmLJqIWXPl57Yw10SvYx0DQOtkfsWIV9Aw=="
|
||||||
|
},
|
||||||
"node_modules/js-tokens": {
|
"node_modules/js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
@ -3029,6 +3050,14 @@
|
|||||||
"integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==",
|
"integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/uint8-to-b64": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uint8-to-b64/-/uint8-to-b64-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-V2mVc9Mu398c1aXz55K3NHMFyLk8g0AP/tUNXqv0SGrSn9nCzkiUlNWFH5H0yJkH4Me/RAX7+u9xZuXgp/YV2A==",
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "1.5.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/undici-types": {
|
"node_modules/undici-types": {
|
||||||
"version": "5.26.5",
|
"version": "5.26.5",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||||
|
|||||||
16
package.json
16
package.json
@ -22,36 +22,28 @@
|
|||||||
"@babylonjs/inspector": "^7.9.0",
|
"@babylonjs/inspector": "^7.9.0",
|
||||||
"@babylonjs/loaders": "^7.9.0",
|
"@babylonjs/loaders": "^7.9.0",
|
||||||
"@babylonjs/materials": "^7.9.0",
|
"@babylonjs/materials": "^7.9.0",
|
||||||
"@babylonjs/procedural-textures": "^7.9.0",
|
|
||||||
"@babylonjs/serializers": "^7.9.0",
|
"@babylonjs/serializers": "^7.9.0",
|
||||||
"@maptiler/client": "1.8.1",
|
"@maptiler/client": "1.8.1",
|
||||||
"@picovoice/cobra-web": "^2.0.3",
|
"@picovoice/cobra-web": "^2.0.3",
|
||||||
"@picovoice/eagle-web": "^1.0.0",
|
"@picovoice/eagle-web": "^1.0.0",
|
||||||
"@picovoice/web-voice-processor": "^4.0.9",
|
"@picovoice/web-voice-processor": "^4.0.9",
|
||||||
"@typed-mxgraph/typed-mxgraph": "^1.0.8",
|
|
||||||
"@types/dom-to-image": "^2.6.7",
|
|
||||||
"@types/file-saver": "^2.0.6",
|
|
||||||
"@types/node": "^18.14.0",
|
"@types/node": "^18.14.0",
|
||||||
"@types/react": "^18.2.72",
|
"@types/react": "^18.2.72",
|
||||||
"@types/react-dom": "^18.2.22",
|
"@types/react-dom": "^18.2.22",
|
||||||
"axios": "^1.6.8",
|
"axios": "^1.6.8",
|
||||||
"canvas-hypertxt": "1.0.3",
|
"canvas-hypertxt": "1.0.3",
|
||||||
"dom-to-image-more": "^3.3.0",
|
|
||||||
"earcut": "^2.2.4",
|
|
||||||
"events": "^3.3.0",
|
|
||||||
"file-saver": "^2.0.5",
|
|
||||||
"hls.js": "^1.1.4",
|
"hls.js": "^1.1.4",
|
||||||
"loglevel": "^1.9.1",
|
"loglevel": "^1.9.1",
|
||||||
"niceware": "^4.0.0",
|
|
||||||
"peer-lite": "2.0.2",
|
"peer-lite": "2.0.2",
|
||||||
"pouchdb": "^8.0.1",
|
"pouchdb": "^8.0.1",
|
||||||
"pouchdb-find": "^8.0.1",
|
|
||||||
"query-string": "^8.1.0",
|
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"recordrtc": "^5.6.0",
|
"recordrtc": "^5.6.0",
|
||||||
"rfc4648": "^1.5.3",
|
"rfc4648": "^1.5.3",
|
||||||
"round": "^2.0.1",
|
"round": "^2.0.1",
|
||||||
"uuid": "^9.0.1"
|
"uuid": "^9.0.1",
|
||||||
|
"js-crypto-aes": "1.0.6",
|
||||||
|
"hash-wasm": "4.11.0",
|
||||||
|
"uint8-to-b64": "^1.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/dom-to-image": "^2.6.7",
|
"@types/dom-to-image": "^2.6.7",
|
||||||
|
|||||||
@ -162,6 +162,11 @@ h1 {
|
|||||||
height: 210px;
|
height: 210px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#password {
|
||||||
|
display: none;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
}
|
||||||
#diagramList {
|
#diagramList {
|
||||||
left: 340px;
|
left: 340px;
|
||||||
top: 400px;
|
top: 400px;
|
||||||
|
|||||||
@ -162,10 +162,8 @@ export class Rigplatform {
|
|||||||
|
|
||||||
|
|
||||||
private initializeControllers() {
|
private initializeControllers() {
|
||||||
|
|
||||||
this.xr.input.onControllerAddedObservable.add((source) => {
|
this.xr.input.onControllerAddedObservable.add((source) => {
|
||||||
this.registerObserver();
|
this.registerObserver();
|
||||||
let controller;
|
|
||||||
switch (source.inputSource.handedness) {
|
switch (source.inputSource.handedness) {
|
||||||
case RIGHT:
|
case RIGHT:
|
||||||
if (!this.rightController) {
|
if (!this.rightController) {
|
||||||
@ -179,9 +177,6 @@ export class Rigplatform {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//this.xr.baseExperience.camera.position = new Vector3(0, 0, 0);
|
//this.xr.baseExperience.camera.position = new Vector3(0, 0, 0);
|
||||||
if (controller) {
|
|
||||||
controller.setRig(this);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
this.xr.input.onControllerRemovedObservable.add((source) => {
|
this.xr.input.onControllerRemovedObservable.add((source) => {
|
||||||
switch (source.inputSource.handedness) {
|
switch (source.inputSource.handedness) {
|
||||||
|
|||||||
@ -94,13 +94,13 @@ export class DiagramManager {
|
|||||||
|
|
||||||
|
|
||||||
private onDiagramEvent(event: DiagramEvent) {
|
private onDiagramEvent(event: DiagramEvent) {
|
||||||
|
let diagramObject = this._diagramObjects.get(event.entity.id);
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case DiagramEventType.ADD:
|
case DiagramEventType.ADD:
|
||||||
let diagramObject = this._diagramObjects.get(event.entity.id);
|
|
||||||
if (diagramObject) {
|
if (diagramObject) {
|
||||||
diagramObject.fromDiagramEntity(event.entity);
|
diagramObject.fromDiagramEntity(event.entity);
|
||||||
} else {
|
} else {
|
||||||
diagramObject = new DiagramObject(this._scene,
|
diagramObject = DiagramObject.CreateObject(this._scene,
|
||||||
this.onDiagramEventObservable,
|
this.onDiagramEventObservable,
|
||||||
{diagramEntity: event.entity, actionManager: this._diagramEntityActionManager});
|
{diagramEntity: event.entity, actionManager: this._diagramEntityActionManager});
|
||||||
}
|
}
|
||||||
@ -111,18 +111,20 @@ export class DiagramManager {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DiagramEventType.REMOVE:
|
case DiagramEventType.REMOVE:
|
||||||
const object = this._diagramObjects.get(event.entity.id);
|
if (diagramObject) {
|
||||||
if (object) {
|
diagramObject.dispose();
|
||||||
object.dispose();
|
|
||||||
}
|
}
|
||||||
this._diagramObjects.delete(event.entity.id);
|
this._diagramObjects.delete(event.entity.id);
|
||||||
break;
|
break;
|
||||||
case DiagramEventType.MODIFY:
|
case DiagramEventType.MODIFY:
|
||||||
console.log(event);
|
console.log(event);
|
||||||
if (event.entity.text) {
|
//diagramObject = this._diagramObjects.get(event.entity.id);
|
||||||
const diagramObject = this._diagramObjects.get(event.entity.id);
|
if (diagramObject && event.entity.text) {
|
||||||
diagramObject.text = event.entity.text;
|
diagramObject.text = event.entity.text;
|
||||||
}
|
}
|
||||||
|
if (event.entity.position) {
|
||||||
|
//diagramObject.position = event.entity.position;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,7 +42,7 @@ export class DiagramMenuManager {
|
|||||||
if (viewOnly()) {
|
if (viewOnly()) {
|
||||||
this.toolbox.handleMesh.setEnabled(false);
|
this.toolbox.handleMesh.setEnabled(false);
|
||||||
//this.scaleMenu.handleMesh.setEnabled(false)
|
//this.scaleMenu.handleMesh.setEnabled(false)
|
||||||
this.configMenu.handleMesh.setEnabled(false);
|
this.configMenu.handleTransformNode.setEnabled(false);
|
||||||
}
|
}
|
||||||
controllers.controllerObservable.add((event: ControllerEvent) => {
|
controllers.controllerObservable.add((event: ControllerEvent) => {
|
||||||
if (event.type == ControllerEventType.B_BUTTON) {
|
if (event.type == ControllerEventType.B_BUTTON) {
|
||||||
@ -65,7 +65,7 @@ export class DiagramMenuManager {
|
|||||||
}
|
}
|
||||||
const configY = this._inputTextView.handleMesh.absolutePosition.y;
|
const configY = this._inputTextView.handleMesh.absolutePosition.y;
|
||||||
if (configY > (cameraPos.y - .2)) {
|
if (configY > (cameraPos.y - .2)) {
|
||||||
this.configMenu.handleMesh.position.y = localCamera.y - .2;
|
this.configMenu.handleTransformNode.position.y = localCamera.y - .2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,12 +26,12 @@ type DiagramObjectOptionsType = {
|
|||||||
export class DiagramObject {
|
export class DiagramObject {
|
||||||
private readonly _logger: Logger = log.getLogger('DiagramObject');
|
private readonly _logger: Logger = log.getLogger('DiagramObject');
|
||||||
private _scene: Scene;
|
private _scene: Scene;
|
||||||
|
public grabbed: boolean = false;
|
||||||
private _from: string;
|
private _from: string;
|
||||||
private _to: string;
|
private _to: string;
|
||||||
private _observingStart: number;
|
private _observingStart: number;
|
||||||
private _sceneObserver: Observer<Scene>;
|
private _sceneObserver: Observer<Scene>;
|
||||||
private _eventObservable: Observable<DiagramEvent>;
|
private _eventObservable: Observable<DiagramEvent>;
|
||||||
private _mesh: AbstractMesh;
|
|
||||||
private _label: AbstractMesh;
|
private _label: AbstractMesh;
|
||||||
private _meshesPresent: boolean = false;
|
private _meshesPresent: boolean = false;
|
||||||
private _positionHash: string;
|
private _positionHash: string;
|
||||||
@ -39,12 +39,6 @@ export class DiagramObject {
|
|||||||
private _toMesh: AbstractMesh;
|
private _toMesh: AbstractMesh;
|
||||||
private _meshRemovedObserver: Observer<AbstractMesh>;
|
private _meshRemovedObserver: Observer<AbstractMesh>;
|
||||||
|
|
||||||
public grabbed: boolean = false;
|
|
||||||
|
|
||||||
public get mesh(): AbstractMesh {
|
|
||||||
return this._mesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(scene: Scene, eventObservable: Observable<DiagramEvent>, options?: DiagramObjectOptionsType) {
|
constructor(scene: Scene, eventObservable: Observable<DiagramEvent>, options?: DiagramObjectOptionsType) {
|
||||||
this._eventObservable = eventObservable;
|
this._eventObservable = eventObservable;
|
||||||
this._scene = scene;
|
this._scene = scene;
|
||||||
@ -58,7 +52,7 @@ export class DiagramObject {
|
|||||||
const myEntity = this.fromDiagramEntity(options.diagramEntity);
|
const myEntity = this.fromDiagramEntity(options.diagramEntity);
|
||||||
if (!myEntity) {
|
if (!myEntity) {
|
||||||
this._logger.warn('DiagramObject constructor called with invalid diagramEntity', options.diagramEntity);
|
this._logger.warn('DiagramObject constructor called with invalid diagramEntity', options.diagramEntity);
|
||||||
return null;
|
this._valid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (options.mesh) {
|
if (options.mesh) {
|
||||||
@ -69,6 +63,28 @@ export class DiagramObject {
|
|||||||
this._mesh.actionManager = options.actionManager;
|
this._mesh.actionManager = options.actionManager;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this._valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _mesh: AbstractMesh;
|
||||||
|
|
||||||
|
public get mesh(): AbstractMesh {
|
||||||
|
return this._mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _valid: boolean = false;
|
||||||
|
|
||||||
|
public get valid(): boolean {
|
||||||
|
return this._valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CreateObject(scene: Scene, eventObservable: Observable<DiagramEvent>, options: DiagramObjectOptionsType): DiagramObject {
|
||||||
|
const newObj = new DiagramObject(scene, eventObservable, options);
|
||||||
|
if (newObj.valid) {
|
||||||
|
return newObj;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _baseTransform: TransformNode;
|
private _baseTransform: TransformNode;
|
||||||
@ -216,9 +232,18 @@ export class DiagramObject {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this._mesh.setParent(this._baseTransform);
|
this._mesh.setParent(this._baseTransform);
|
||||||
this._baseTransform.position = xyztovec(entity.position);
|
if (entity.position) {
|
||||||
this._baseTransform.rotation = xyztovec(entity.rotation);
|
this._baseTransform.position = xyztovec(entity.position)
|
||||||
this._mesh.scaling = xyztovec(entity.scale);
|
}
|
||||||
|
;
|
||||||
|
if (entity.rotation) {
|
||||||
|
this._baseTransform.rotation = xyztovec(entity.rotation)
|
||||||
|
}
|
||||||
|
;
|
||||||
|
if (entity.scale) {
|
||||||
|
this._mesh.scaling = xyztovec(entity.scale)
|
||||||
|
}
|
||||||
|
;
|
||||||
this._mesh.position = Vector3.Zero();
|
this._mesh.position = Vector3.Zero();
|
||||||
this._mesh.rotation = Vector3.Zero();
|
this._mesh.rotation = Vector3.Zero();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import {AbstractMesh, MeshBuilder, Observable, Scene, Vector3} from "@babylonjs/core";
|
import {AbstractMesh, MeshBuilder, Observable, Scene, TransformNode, Vector3} from "@babylonjs/core";
|
||||||
import log, {Logger} from "loglevel";
|
import log, {Logger} from "loglevel";
|
||||||
import {AdvancedDynamicTexture, Control, InputText, VirtualKeyboard} from "@babylonjs/gui";
|
import {AdvancedDynamicTexture, Control, InputText, VirtualKeyboard} from "@babylonjs/gui";
|
||||||
import {ControllerEventType, Controllers} from "../controllers/controllers";
|
import {ControllerEventType, Controllers} from "../controllers/controllers";
|
||||||
@ -33,8 +33,12 @@ export class InputTextView {
|
|||||||
this.createKeyboard();
|
this.createKeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get handleMesh(): TransformNode {
|
||||||
|
return this.handle.transformNode;
|
||||||
|
}
|
||||||
|
|
||||||
public show(mesh: AbstractMesh) {
|
public show(mesh: AbstractMesh) {
|
||||||
this.handle.mesh.setEnabled(true);
|
this.handle.transformNode.setEnabled(true);
|
||||||
if (mesh.metadata?.text) {
|
if (mesh.metadata?.text) {
|
||||||
this.inputText.text = mesh.metadata?.text;
|
this.inputText.text = mesh.metadata?.text;
|
||||||
} else {
|
} else {
|
||||||
@ -46,15 +50,6 @@ export class InputTextView {
|
|||||||
this.logger.debug(mesh.metadata);
|
this.logger.debug(mesh.metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get handleMesh(): AbstractMesh {
|
|
||||||
return this.handle.mesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
private hide() {
|
|
||||||
this.handle.mesh.setEnabled(false);
|
|
||||||
this.diagramMesh = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public createKeyboard() {
|
public createKeyboard() {
|
||||||
const platform = this.scene.getMeshById('platform');
|
const platform = this.scene.getMeshById('platform');
|
||||||
const position = new Vector3(0, 1.66, .53);
|
const position = new Vector3(0, 1.66, .53);
|
||||||
@ -70,18 +65,18 @@ export class InputTextView {
|
|||||||
this.scene.onNewMeshAddedObservable.add((mesh) => {
|
this.scene.onNewMeshAddedObservable.add((mesh) => {
|
||||||
if (mesh.id == 'platform') {
|
if (mesh.id == 'platform') {
|
||||||
this.logger.debug("platform added");
|
this.logger.debug("platform added");
|
||||||
handle.mesh.parent = mesh;
|
handle.transformNode.parent = mesh;
|
||||||
if (!handle.idStored) {
|
if (!handle.idStored) {
|
||||||
handle.mesh.position = position;
|
handle.transformNode.position = position;
|
||||||
handle.mesh.rotation = rotation;
|
handle.transformNode.rotation = rotation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, -1, false, this, false);
|
}, -1, false, this, false);
|
||||||
} else {
|
} else {
|
||||||
handle.mesh.setParent(platform);
|
handle.transformNode.setParent(platform);
|
||||||
if (!handle.idStored) {
|
if (!handle.idStored) {
|
||||||
handle.mesh.position = position;
|
handle.transformNode.position = position;
|
||||||
handle.mesh.rotation = rotation;
|
handle.transformNode.rotation = rotation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +138,11 @@ export class InputTextView {
|
|||||||
}
|
}
|
||||||
}, -1, false, this, false);
|
}, -1, false, this, false);
|
||||||
this.keyboard = keyboard;
|
this.keyboard = keyboard;
|
||||||
this.handle.mesh.setEnabled(false);
|
this.handle.transformNode.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private hide() {
|
||||||
|
this.handle.transformNode.setEnabled(false);
|
||||||
|
this.diagramMesh = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
90
src/integration/encryption.ts
Normal file
90
src/integration/encryption.ts
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import {createSHA256, pbkdf2} from "hash-wasm";
|
||||||
|
import aes from 'js-crypto-aes';
|
||||||
|
import {decode, encode} from "uint8-to-b64";
|
||||||
|
|
||||||
|
export class Encryption {
|
||||||
|
private _key: Uint8Array | null = null;
|
||||||
|
private _salt: Uint8Array | null = null;
|
||||||
|
private _iv: Uint8Array | null = null;
|
||||||
|
private _encrypted: Uint8Array | null = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private _ready: boolean = false;
|
||||||
|
|
||||||
|
public get ready() {
|
||||||
|
return this._ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async setPassword(password: string, saltString?: string) {
|
||||||
|
if (saltString) {
|
||||||
|
this._salt = decode(saltString);
|
||||||
|
} else {
|
||||||
|
const salt = new Uint8Array(16);
|
||||||
|
window.crypto.getRandomValues(salt);
|
||||||
|
this._salt = salt;
|
||||||
|
}
|
||||||
|
this._key = await pbkdf2({
|
||||||
|
password: password,
|
||||||
|
salt: this._salt,
|
||||||
|
iterations: 10000,
|
||||||
|
hashLength: 32,
|
||||||
|
hashFunction: createSHA256(),
|
||||||
|
outputType: "binary"
|
||||||
|
});
|
||||||
|
this._ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async encryptObject(obj: any) {
|
||||||
|
return await this.encrypt(JSON.stringify(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async decryptToObject(msg: string, iv: string) {
|
||||||
|
return JSON.parse(await this.decrypt(msg, iv));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async encrypt(msg: string) {
|
||||||
|
if (!this._key) {
|
||||||
|
throw new Error('No password key set');
|
||||||
|
}
|
||||||
|
|
||||||
|
const iv = new Uint8Array(12);
|
||||||
|
window.crypto.getRandomValues(iv);
|
||||||
|
this._iv = iv;
|
||||||
|
|
||||||
|
const arr: Uint8Array = await aes.encrypt(
|
||||||
|
new TextEncoder().encode(msg), this._key, {name: 'AES-GCM', iv: this._iv, tagLength: 16});
|
||||||
|
this._encrypted = arr;
|
||||||
|
return this._encrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async decrypt(msg: string, iv: string) {
|
||||||
|
if (!this._key) {
|
||||||
|
throw new Error('No key set');
|
||||||
|
}
|
||||||
|
this._iv = decode(iv);
|
||||||
|
const msgArray = decode(msg);
|
||||||
|
//Uint8Array.from(atob(decode(msg)), c => c.charCodeAt(0));
|
||||||
|
const output = await aes.decrypt(msgArray, this._key, {name: 'AES-GCM', iv: this._iv, tagLength: 16});
|
||||||
|
return new TextDecoder().decode(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getEncrypted() {
|
||||||
|
if (
|
||||||
|
!this._encrypted ||
|
||||||
|
!this._iv ||
|
||||||
|
!this._salt
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
encrypted: encode(this._encrypted),
|
||||||
|
salt: encode(this._salt),
|
||||||
|
iv: encode(this._iv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
export function hex_to_ascii(input) {
|
export function hex_to_ascii(input) {
|
||||||
var hex = input.toString();
|
const hex = input.toString();
|
||||||
let output = '';
|
let output = '';
|
||||||
for (let n = 0; n < hex.length; n += 2) {
|
for (let n = 0; n < hex.length; n += 2) {
|
||||||
output += String.fromCharCode(parseInt(hex.substr(n, 2), 16));
|
output += String.fromCharCode(parseInt(hex.substr(n, 2), 16));
|
||||||
@ -10,7 +10,7 @@ export function hex_to_ascii(input) {
|
|||||||
export function ascii_to_hex(str) {
|
export function ascii_to_hex(str) {
|
||||||
const arr1 = [];
|
const arr1 = [];
|
||||||
for (let n = 0, l = str.length; n < l; n++) {
|
for (let n = 0, l = str.length; n < l; n++) {
|
||||||
var hex = Number(str.charCodeAt(n)).toString(16);
|
const hex = Number(str.charCodeAt(n)).toString(16);
|
||||||
arr1.push(hex);
|
arr1.push(hex);
|
||||||
}
|
}
|
||||||
return arr1.join('');
|
return arr1.join('');
|
||||||
|
|||||||
@ -2,22 +2,44 @@ import log from "loglevel";
|
|||||||
import {DiagramEntity} from "../../diagram/types/diagramEntity";
|
import {DiagramEntity} from "../../diagram/types/diagramEntity";
|
||||||
import {Observable} from "@babylonjs/core";
|
import {Observable} from "@babylonjs/core";
|
||||||
import {UserModelType} from "../../users/userTypes";
|
import {UserModelType} from "../../users/userTypes";
|
||||||
|
import {Encryption} from "../encryption";
|
||||||
|
|
||||||
export function syncDoc(info: any, onDBRemoveObservable: Observable<DiagramEntity>, onDBUpdateObservable: Observable<DiagramEntity>, onUserObservable: Observable<UserModelType>) {
|
export async function syncDoc(info: any, onDBRemoveObservable: Observable<DiagramEntity>, onDBUpdateObservable: Observable<DiagramEntity>, onUserObservable: Observable<UserModelType>,
|
||||||
|
encryption: Encryption, key: string) {
|
||||||
const logger = log.getLogger('syncDoc');
|
const logger = log.getLogger('syncDoc');
|
||||||
logger.debug(info);
|
logger.debug(info);
|
||||||
if (info.direction == 'pull') {
|
if (info.direction == 'pull') {
|
||||||
const docs = info.change.docs;
|
const docs = info.change.docs;
|
||||||
|
let salt = null;
|
||||||
for (const doc of docs) {
|
for (const doc of docs) {
|
||||||
if (doc.type == 'user') {
|
if (doc.encrypted) {
|
||||||
//onUserObservable.notifyObservers(doc, -1);
|
if (salt != doc.encrypted.salt || (key && !encryption.ready)) {
|
||||||
} else {
|
await encryption.setPassword(key, doc.encrypted.salt);
|
||||||
logger.debug(doc);
|
salt = doc.encrypted.salt
|
||||||
if (doc._deleted) {
|
}
|
||||||
logger.debug('Delete', doc);
|
const decrypted = await encryption.decryptToObject(doc.encrypted.encrypted, doc.encrypted.iv);
|
||||||
onDBRemoveObservable.notifyObservers({id: doc._id, template: doc.template}, 1);
|
if (decrypted.type == 'user') {
|
||||||
|
//onUserObservable.notifyObservers(doc, -1);
|
||||||
} else {
|
} else {
|
||||||
onDBUpdateObservable.notifyObservers(doc, 1);
|
logger.debug(decrypted);
|
||||||
|
if (doc._deleted) {
|
||||||
|
logger.debug('Delete', doc);
|
||||||
|
onDBRemoveObservable.notifyObservers({id: doc._id, template: decrypted.template}, 1);
|
||||||
|
} else {
|
||||||
|
onDBUpdateObservable.notifyObservers(decrypted, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (doc.type == 'user') {
|
||||||
|
//onUserObservable.notifyObservers(doc, -1);
|
||||||
|
} else {
|
||||||
|
logger.debug(doc);
|
||||||
|
if (doc._deleted) {
|
||||||
|
logger.debug('Delete', doc);
|
||||||
|
onDBRemoveObservable.notifyObservers({id: doc._id, template: doc.template}, 1);
|
||||||
|
} else {
|
||||||
|
onDBUpdateObservable.notifyObservers(doc, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,7 +53,7 @@ export class NewRelicQuery {
|
|||||||
const plane = MeshBuilder.CreatePlane("plane", {width: .5, height: .25}, this.scene);
|
const plane = MeshBuilder.CreatePlane("plane", {width: .5, height: .25}, this.scene);
|
||||||
plane.billboardMode = Mesh.BILLBOARDMODE_ALL;
|
plane.billboardMode = Mesh.BILLBOARDMODE_ALL;
|
||||||
const advancedTexture = AdvancedDynamicTexture.CreateForMesh(plane, 1024, 512, false);
|
const advancedTexture = AdvancedDynamicTexture.CreateForMesh(plane, 1024, 512, false);
|
||||||
var text1 = new TextBlock();
|
const text1 = new TextBlock();
|
||||||
text1.text = text;
|
text1.text = text;
|
||||||
advancedTexture.background = "#000000";
|
advancedTexture.background = "#000000";
|
||||||
text1.color = "white";
|
text1.color = "white";
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import {syncDoc} from "./functions/syncDoc";
|
|||||||
import {checkDb} from "./functions/checkDb";
|
import {checkDb} from "./functions/checkDb";
|
||||||
import {UserModelType} from "../users/userTypes";
|
import {UserModelType} from "../users/userTypes";
|
||||||
import {getMe} from "../util/me";
|
import {getMe} from "../util/me";
|
||||||
|
import {Encryption} from "./encryption";
|
||||||
|
|
||||||
export class PouchdbPersistenceManager {
|
export class PouchdbPersistenceManager {
|
||||||
private _logger: Logger = log.getLogger('PouchdbPersistenceManager');
|
private _logger: Logger = log.getLogger('PouchdbPersistenceManager');
|
||||||
@ -20,10 +21,16 @@ export class PouchdbPersistenceManager {
|
|||||||
private db: PouchDB;
|
private db: PouchDB;
|
||||||
private remote: PouchDB;
|
private remote: PouchDB;
|
||||||
private user: string;
|
private user: string;
|
||||||
|
private _encryption = new Encryption();
|
||||||
|
private _encKey = null;
|
||||||
constructor() {
|
constructor() {
|
||||||
|
document.addEventListener('passwordset', (evt) => {
|
||||||
|
this._encKey = evt.detail || null;
|
||||||
|
if (this._encKey && typeof (this._encKey) == 'string') {
|
||||||
|
this.initialize();
|
||||||
|
}
|
||||||
|
console.log(evt);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
public setDiagramManager(diagramManager: DiagramManager) {
|
public setDiagramManager(diagramManager: DiagramManager) {
|
||||||
diagramManager.onDiagramEventObservable.add((evt) => {
|
diagramManager.onDiagramEventObservable.add((evt) => {
|
||||||
@ -80,10 +87,7 @@ export class PouchdbPersistenceManager {
|
|||||||
} else {
|
} else {
|
||||||
this._logger.error(err);
|
this._logger.error(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
public async remove(id: string) {
|
public async remove(id: string) {
|
||||||
if (!id) {
|
if (!id) {
|
||||||
@ -101,17 +105,41 @@ export class PouchdbPersistenceManager {
|
|||||||
if (!entity) {
|
if (!entity) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this._encKey && !this._encryption.ready) {
|
||||||
|
await this._encryption.setPassword(this._encKey);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const doc = await this.db.get(entity.id);
|
const doc = await this.db.get(entity.id);
|
||||||
if (doc) {
|
if (this._encKey) {
|
||||||
const newDoc = {...doc, ...entity};
|
|
||||||
this.db.put(newDoc);
|
await this._encryption.encryptObject(entity);
|
||||||
|
const newDoc = {
|
||||||
|
_id: doc._id,
|
||||||
|
_rev: doc._rev,
|
||||||
|
encrypted: this._encryption.getEncrypted()
|
||||||
|
}
|
||||||
|
this.db.put(newDoc)
|
||||||
|
} else {
|
||||||
|
if (doc) {
|
||||||
|
const newDoc = {...doc, ...entity};
|
||||||
|
this.db.put(newDoc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.status == 404) {
|
if (err.status == 404) {
|
||||||
try {
|
try {
|
||||||
const newEntity = {...entity, _id: entity.id};
|
if (this._encKey) {
|
||||||
this.db.put(newEntity);
|
await this._encryption.encryptObject(entity);
|
||||||
|
const newDoc = {
|
||||||
|
_id: entity.id,
|
||||||
|
encrypted: this._encryption.getEncrypted()
|
||||||
|
}
|
||||||
|
this.db.put(newDoc);
|
||||||
|
} else {
|
||||||
|
const newEntity = {...entity, _id: entity.id};
|
||||||
|
this.db.put(newEntity);
|
||||||
|
}
|
||||||
} catch (err2) {
|
} catch (err2) {
|
||||||
this._logger.error(err2);
|
this._logger.error(err2);
|
||||||
}
|
}
|
||||||
@ -128,28 +156,52 @@ export class PouchdbPersistenceManager {
|
|||||||
await this.sendLocalDataToScene();
|
await this.sendLocalDataToScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async setupMetadata(current: string) {
|
private async setupMetadata(current: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const doc = await this.db.get('metadata');
|
const doc = await this.db.get('metadata');
|
||||||
if (doc && doc.friendly) {
|
if (doc.encrypted) {
|
||||||
localStorage.setItem(current, doc.friendly);
|
if (!this._encKey) {
|
||||||
}
|
const promptPassword = new CustomEvent('promptpassword', {detail: 'Please enter password'});
|
||||||
if (doc && doc.camera) {
|
document.dispatchEvent(promptPassword);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!this._encryption.ready) {
|
||||||
|
await this._encryption.setPassword(this._encKey, doc.encrypted.salt);
|
||||||
|
}
|
||||||
|
const decrypted = await this._encryption.decryptToObject(doc.encrypted.encrypted, doc.encrypted.iv);
|
||||||
|
if (decrypted.friendly) {
|
||||||
|
localStorage.setItem(current, decrypted.friendly);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (doc && doc.friendly) {
|
||||||
|
localStorage.setItem(current, doc.friendly);
|
||||||
|
}
|
||||||
|
if (doc && doc.camera) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.status == 404) {
|
if (err.status == 404) {
|
||||||
this._logger.debug('no metadata found');
|
this._logger.debug('no metadata found');
|
||||||
const friendly = localStorage.getItem(current);
|
const friendly = localStorage.getItem(current);
|
||||||
if (friendly) {
|
if (friendly) {
|
||||||
this._logger.debug('local friendly name found ', friendly, ' setting metadata');
|
if (this._encKey) {
|
||||||
const newDoc = {_id: 'metadata', id: 'metadata', friendly: friendly};
|
if (!this._encryption.ready) {
|
||||||
await this.db.put(newDoc);
|
await this._encryption.setPassword(this._encKey);
|
||||||
|
}
|
||||||
|
await this._encryption.encryptObject({friendly: friendly});
|
||||||
|
await this.db.put({_id: 'metadata', id: 'metadata', encrypted: this._encryption.getEncrypted()})
|
||||||
|
} else {
|
||||||
|
this._logger.debug('local friendly name found ', friendly, ' setting metadata');
|
||||||
|
const newDoc = {_id: 'metadata', id: 'metadata', friendly: friendly};
|
||||||
|
await this.db.put(newDoc);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this._logger.debug('no friendly name found');
|
this._logger.debug('no friendly name found');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async initLocal(): Promise<boolean> {
|
private async initLocal(): Promise<boolean> {
|
||||||
@ -165,8 +217,9 @@ export class PouchdbPersistenceManager {
|
|||||||
this.db = new PouchDB(current, {auto_compaction: true});
|
this.db = new PouchDB(current, {auto_compaction: true});
|
||||||
//await this.db.compact();
|
//await this.db.compact();
|
||||||
if (sync) {
|
if (sync) {
|
||||||
await this.setupMetadata(current);
|
if (await this.setupMetadata(current)) {
|
||||||
await this.beginSync(current);
|
await this.beginSync(current);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -177,20 +230,38 @@ export class PouchdbPersistenceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async sendLocalDataToScene() {
|
private async sendLocalDataToScene() {
|
||||||
|
|
||||||
|
let salt = null;
|
||||||
|
|
||||||
const clear = localStorage.getItem('clearLocal');
|
const clear = localStorage.getItem('clearLocal');
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const all = await this.db.allDocs({include_docs: true});
|
const all = await this.db.allDocs({include_docs: true});
|
||||||
for (const entity of all.rows) {
|
for (const dbEntity of all.rows) {
|
||||||
this._logger.debug(entity.doc);
|
this._logger.debug(dbEntity.doc);
|
||||||
if (clear) {
|
if (clear) {
|
||||||
this.remove(entity.id);
|
this.remove(dbEntity.id);
|
||||||
} else {
|
} else {
|
||||||
if (entity.type == 'user') {
|
if (dbEntity.doc.encrypted) {
|
||||||
this.onUserObservable.notifyObservers(entity.doc);
|
if (!salt || salt != dbEntity.doc.encrypted.salt) {
|
||||||
|
await this._encryption.setPassword(this._encKey, dbEntity.doc.encrypted.salt);
|
||||||
|
salt = dbEntity.doc.encrypted.salt;
|
||||||
|
}
|
||||||
|
const decrypted = await this._encryption.decryptToObject(dbEntity.doc.encrypted.encrypted, dbEntity.doc.encrypted.iv);
|
||||||
|
if (decrypted.type == 'user') {
|
||||||
|
this.onUserObservable.notifyObservers(decrypted);
|
||||||
|
} else {
|
||||||
|
if (decrypted.id != 'metadata') {
|
||||||
|
this.onDBEntityUpdateObservable.notifyObservers(decrypted, DiagramEventObserverMask.FROM_DB);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (entity.id != 'metadata') {
|
if (dbEntity.type == 'user') {
|
||||||
this.onDBEntityUpdateObservable.notifyObservers(entity.doc, DiagramEventObserverMask.FROM_DB);
|
this.onUserObservable.notifyObservers(dbEntity.doc);
|
||||||
|
} else {
|
||||||
|
if (dbEntity.id != 'metadata') {
|
||||||
|
this.onDBEntityUpdateObservable.notifyObservers(dbEntity.doc, DiagramEventObserverMask.FROM_DB);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,6 +270,12 @@ export class PouchdbPersistenceManager {
|
|||||||
localStorage.removeItem('clearLocal');
|
localStorage.removeItem('clearLocal');
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
switch (err.message) {
|
||||||
|
case 'WebCrypto_DecryptionFailure: ':
|
||||||
|
case 'Invalid data type!':
|
||||||
|
const promptPassword = new CustomEvent('promptpassword', {detail: 'Please enter password'});
|
||||||
|
document.dispatchEvent(promptPassword);
|
||||||
|
}
|
||||||
this._logger.error(err);
|
this._logger.error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,9 +319,10 @@ export class PouchdbPersistenceManager {
|
|||||||
{auth: {username: remoteUserName, password: password}, skip_setup: true});
|
{auth: {username: remoteUserName, password: password}, skip_setup: true});
|
||||||
const dbInfo = await this.remote.info();
|
const dbInfo = await this.remote.info();
|
||||||
this._logger.debug(dbInfo);
|
this._logger.debug(dbInfo);
|
||||||
|
|
||||||
this.db.sync(this.remote, {live: true, retry: true})
|
this.db.sync(this.remote, {live: true, retry: true})
|
||||||
.on('change', (info) => {
|
.on('change', (info) => {
|
||||||
syncDoc(info, this.onDBEntityRemoveObservable, this.onDBEntityUpdateObservable, this.onUserObservable);
|
syncDoc(info, this.onDBEntityRemoveObservable, this.onDBEntityUpdateObservable, this.onUserObservable, this._encryption, this._encKey);
|
||||||
})
|
})
|
||||||
.on('active', (info) => {
|
.on('active', (info) => {
|
||||||
this._logger.debug('sync active', info)
|
this._logger.debug('sync active', info)
|
||||||
|
|||||||
@ -3,7 +3,7 @@ export function tile2long(x, z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function tile2lat(y, z) {
|
export function tile2lat(y, z) {
|
||||||
var n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
|
const n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
|
||||||
return (180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))));
|
return (180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import {AdvancedDynamicTexture, CheckboxGroup, RadioGroup, SelectionPanel, StackPanel} from "@babylonjs/gui";
|
import {AdvancedDynamicTexture, CheckboxGroup, RadioGroup, SelectionPanel, StackPanel} from "@babylonjs/gui";
|
||||||
import {AbstractMesh, MeshBuilder, Scene, TransformNode, Vector3} from "@babylonjs/core";
|
import {MeshBuilder, Scene, TransformNode, Vector3} from "@babylonjs/core";
|
||||||
import {AppConfig} from "../util/appConfig";
|
import {AppConfig} from "../util/appConfig";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import {DefaultScene} from "../defaultScene";
|
import {DefaultScene} from "../defaultScene";
|
||||||
@ -35,8 +35,8 @@ export class ConfigMenu {
|
|||||||
this.buildMenu();
|
this.buildMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get handleMesh(): AbstractMesh {
|
public get handleTransformNode(): TransformNode {
|
||||||
return this._handle.mesh;
|
return this._handle.transformNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private adjustRadio(radio: RadioGroup | CheckboxGroup) {
|
private adjustRadio(radio: RadioGroup | CheckboxGroup) {
|
||||||
@ -167,20 +167,20 @@ export class ConfigMenu {
|
|||||||
|
|
||||||
const platform = this._scene.getMeshById('platform');
|
const platform = this._scene.getMeshById('platform');
|
||||||
if (platform) {
|
if (platform) {
|
||||||
this._handle.mesh.parent = platform;
|
this._handle.transformNode.parent = platform;
|
||||||
if (!this._handle.idStored) {
|
if (!this._handle.idStored) {
|
||||||
this._handle.mesh.position = offset;
|
this._handle.transformNode.position = offset;
|
||||||
this._handle.mesh.rotation = rotation;
|
this._handle.transformNode.rotation = rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const handler = this._scene.onNewMeshAddedObservable.add((mesh) => {
|
const handler = this._scene.onNewMeshAddedObservable.add((mesh) => {
|
||||||
if (mesh && mesh.id == 'platform') {
|
if (mesh && mesh.id == 'platform') {
|
||||||
this._handle.mesh.parent = mesh;
|
this._handle.transformNode.parent = mesh;
|
||||||
|
|
||||||
if (!this._handle.idStored) {
|
if (!this._handle.idStored) {
|
||||||
this._handle.mesh.position = offset;
|
this._handle.transformNode.position = offset;
|
||||||
this._handle.mesh.rotation = rotation;
|
this._handle.transformNode.rotation = rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export class NewRelicMenu extends AbstractMenu {
|
|||||||
|
|
||||||
buildMenu() {
|
buildMenu() {
|
||||||
this.logger.debug('buildMenu');
|
this.logger.debug('buildMenu');
|
||||||
this.makeButton("credentials", "credentials");
|
//this.makeButton("credentials", "credentials");
|
||||||
const grid = new Grid("grid");
|
const grid = new Grid("grid");
|
||||||
grid.addColumnDefinition(.5);
|
grid.addColumnDefinition(.5);
|
||||||
grid.addColumnDefinition(.5);
|
grid.addColumnDefinition(.5);
|
||||||
@ -22,12 +22,6 @@ export class NewRelicMenu extends AbstractMenu {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
makeButton(name: string, id: string) {
|
|
||||||
const button = super.makeButton(name, id);
|
|
||||||
button.onPointerClickObservable.add(this.handleClick, -1, false, this);
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleClick(_info, state) {
|
private handleClick(_info, state) {
|
||||||
this.logger.debug("clicked " + state.currentTarget.name);
|
this.logger.debug("clicked " + state.currentTarget.name);
|
||||||
switch (state.currentTarget.name) {
|
switch (state.currentTarget.name) {
|
||||||
|
|||||||
@ -37,8 +37,8 @@ export class Button {
|
|||||||
public onPointerObservable: Observable<ActionEvent> = new Observable<ActionEvent>();
|
public onPointerObservable: Observable<ActionEvent> = new Observable<ActionEvent>();
|
||||||
private _scene: Scene;
|
private _scene: Scene;
|
||||||
private _mesh: AbstractMesh;
|
private _mesh: AbstractMesh;
|
||||||
private _width: number;
|
private readonly _width: number;
|
||||||
private _height: number;
|
private readonly _height: number;
|
||||||
private _background: Color3;
|
private _background: Color3;
|
||||||
private _color: Color3;
|
private _color: Color3;
|
||||||
private _hoverBackground: Color3;
|
private _hoverBackground: Color3;
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import log, {Logger} from "loglevel";
|
|||||||
import {split} from "canvas-hypertxt";
|
import {split} from "canvas-hypertxt";
|
||||||
|
|
||||||
export class Handle {
|
export class Handle {
|
||||||
public mesh: TransformNode;
|
public transformNode: TransformNode;
|
||||||
private readonly _menuItem: TransformNode;
|
private readonly _menuItem: TransformNode;
|
||||||
private _isStored: boolean = false;
|
private _isStored: boolean = false;
|
||||||
private _offset: Vector3;
|
private _offset: Vector3;
|
||||||
@ -75,7 +75,7 @@ export class Handle {
|
|||||||
handle.rotation = this._rotation;
|
handle.rotation = this._rotation;
|
||||||
}
|
}
|
||||||
handle.metadata = {handle: true};
|
handle.metadata = {handle: true};
|
||||||
this.mesh = handle;
|
this.transformNode = handle;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,33 @@ function MainMenu({onClick}) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function PasswordDialog() {
|
||||||
|
const onsubmitClick = (evt) => {
|
||||||
|
evt.preventDefault();
|
||||||
|
const password = (document.querySelector('#passwordInput') as HTMLInputElement).value;
|
||||||
|
if (password.length < 4) {
|
||||||
|
window.alert('Password must be longer than 4 characters');
|
||||||
|
} else {
|
||||||
|
const event = new CustomEvent('passwordset', {detail: password});
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
document.querySelector('#password').style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const onCancelClick = (evt) => {
|
||||||
|
evt.preventDefault();
|
||||||
|
document.querySelector('#password').style.display = 'none';
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="overlay" id="password">
|
||||||
|
<div>
|
||||||
|
<div><input autoComplete="on" id="passwordInput" placeholder="Enter password" type="password"/></div>
|
||||||
|
<div><a href="#" id="passwordActionLink" onClick={onsubmitClick}>Enter</a></div>
|
||||||
|
<div><a className="cancel" href="#" onClick={onCancelClick} id="cancelPasswordLink">Cancel</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function CreateMenu({display, toggleCreateMenu}) {
|
function CreateMenu({display, toggleCreateMenu}) {
|
||||||
const onCreateClick = (evt) => {
|
const onCreateClick = (evt) => {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
@ -152,13 +179,21 @@ function Menu() {
|
|||||||
<CreateMenu display={createState} toggleCreateMenu={handleCreateClick}/>
|
<CreateMenu display={createState} toggleCreateMenu={handleCreateClick}/>
|
||||||
<DiagramList onClick={handleCreateClick} display={diagramListState}/>
|
<DiagramList onClick={handleCreateClick} display={diagramListState}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function WebApp() {
|
export default function WebApp() {
|
||||||
|
document.addEventListener('promptpassword', (evt) => {
|
||||||
|
const password = document.querySelector('#password');
|
||||||
|
if (password) {
|
||||||
|
password.style.display = 'block';
|
||||||
|
}
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Menu/>
|
<Menu/>
|
||||||
|
<PasswordDialog/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,8 +38,8 @@ export class Toolbox {
|
|||||||
return Toolbox._instance;
|
return Toolbox._instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get handleMesh(): AbstractMesh {
|
public get handleMesh(): TransformNode {
|
||||||
return this._handle.mesh;
|
return this._handle.transformNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public isTool(mesh: AbstractMesh) {
|
public isTool(mesh: AbstractMesh) {
|
||||||
@ -113,10 +113,10 @@ export class Toolbox {
|
|||||||
const rotation = new Vector3(.5, -.6, .18);
|
const rotation = new Vector3(.5, -.6, .18);
|
||||||
|
|
||||||
const handle = this._handle;
|
const handle = this._handle;
|
||||||
handle.mesh.parent = mesh;
|
handle.transformNode.parent = mesh;
|
||||||
if (!handle.idStored) {
|
if (!handle.idStored) {
|
||||||
handle.mesh.position = offset;
|
handle.transformNode.position = offset;
|
||||||
handle.mesh.rotation = rotation;
|
handle.transformNode.rotation = rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import {DefaultScene} from "../../defaultScene";
|
import {DefaultScene} from "../../defaultScene";
|
||||||
|
|
||||||
|
|
||||||
export function addSceneInspector() {
|
export function addSceneInspector() {
|
||||||
const scene = DefaultScene.Scene;
|
const scene = DefaultScene.Scene;
|
||||||
window.addEventListener("keydown", (ev) => {
|
window.addEventListener("keydown", (ev) => {
|
||||||
@ -10,6 +11,10 @@ export function addSceneInspector() {
|
|||||||
//voiceManager.stopRecording();
|
//voiceManager.stopRecording();
|
||||||
}
|
}
|
||||||
if (ev.shiftKey && ev.ctrlKey && ev.altKey && ev.keyCode === 73) {
|
if (ev.shiftKey && ev.ctrlKey && ev.altKey && ev.keyCode === 73) {
|
||||||
|
|
||||||
|
const web = document.querySelector('#webApp');
|
||||||
|
(web as HTMLDivElement).style.display = 'none';
|
||||||
|
|
||||||
import ("@babylonjs/inspector").then((inspector) => {
|
import ("@babylonjs/inspector").then((inspector) => {
|
||||||
inspector.Inspector.Show(DefaultScene.Scene, {
|
inspector.Inspector.Show(DefaultScene.Scene, {
|
||||||
overlay: true,
|
overlay: true,
|
||||||
|
|||||||
@ -6,7 +6,15 @@ export default defineConfig({
|
|||||||
test: {},
|
test: {},
|
||||||
define: {},
|
define: {},
|
||||||
build: {
|
build: {
|
||||||
sourcemap: "inline"
|
sourcemap: true,
|
||||||
|
rollupOptions: {
|
||||||
|
output: {
|
||||||
|
manualChunks: {
|
||||||
|
'babylon': ['@babylonjs/core'],
|
||||||
|
'crypto': ["js-crypto-aes", "hash-wasm", "uint8-to-b64"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
esbuildOptions: {
|
esbuildOptions: {
|
||||||
@ -31,6 +39,24 @@ export default defineConfig({
|
|||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
preview: {
|
||||||
|
port: 3001,
|
||||||
|
proxy: {
|
||||||
|
'^/sync/.*': {
|
||||||
|
target: 'https://www.deepdiagram.com/',
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
'^/create-db': {
|
||||||
|
target: 'https://www.deepdiagram.com/',
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
'^/api/images': {
|
||||||
|
target: 'https://www.deepdiagram.com/',
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
base: "/"
|
base: "/"
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user