@virtualdisplay.io/client 3.3.0 → 3.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/index.d.ts +94 -24
- package/dist/virtualdisplay.client.cjs.js +3 -3
- package/dist/virtualdisplay.client.cjs.js.map +1 -1
- package/dist/virtualdisplay.client.es.js +138 -14
- package/dist/virtualdisplay.client.es.js.map +1 -1
- package/dist/virtualdisplay.client.umd.js +3 -3
- package/dist/virtualdisplay.client.umd.js.map +1 -1
- package/package.json +1 -1
|
@@ -54,6 +54,8 @@ const EVENT_NAMES = {
|
|
|
54
54
|
IFRAME_READY: "iframe:ready",
|
|
55
55
|
// Mutation flow (Client → Server)
|
|
56
56
|
MUTATION_MESSAGE: "mutation:message",
|
|
57
|
+
// Config flow (Client → Server)
|
|
58
|
+
CONFIG_MESSAGE: "config:message",
|
|
57
59
|
// State flow (Server → Client)
|
|
58
60
|
MESSAGE_RECEIVED: "message:received",
|
|
59
61
|
STATE_CHANGED: "state:changed",
|
|
@@ -394,7 +396,6 @@ class IframeBuilder {
|
|
|
394
396
|
height: "100%",
|
|
395
397
|
border: "none"
|
|
396
398
|
});
|
|
397
|
-
iframe.setAttribute("allowfullscreen", "true");
|
|
398
399
|
iframe.setAttribute("allow", "xr-spatial-tracking; fullscreen");
|
|
399
400
|
iframe.addEventListener("load", () => {
|
|
400
401
|
logger.info("Virtualdisplay iframe loaded");
|
|
@@ -6926,7 +6927,8 @@ class MappingValidator {
|
|
|
6926
6927
|
}
|
|
6927
6928
|
const MESSAGE_TYPES = {
|
|
6928
6929
|
MUTATION: "mutation",
|
|
6929
|
-
STATE: "state"
|
|
6930
|
+
STATE: "state",
|
|
6931
|
+
CONFIG: "config"
|
|
6930
6932
|
};
|
|
6931
6933
|
function createMutationMessage(mutations) {
|
|
6932
6934
|
if (!Array.isArray(mutations)) {
|
|
@@ -6938,7 +6940,7 @@ function createMutationMessage(mutations) {
|
|
|
6938
6940
|
};
|
|
6939
6941
|
}
|
|
6940
6942
|
function isValidMessage(data) {
|
|
6941
|
-
return isMutationMessage(data) || isStateMessage(data);
|
|
6943
|
+
return isMutationMessage(data) || isStateMessage(data) || isConfigMessage(data);
|
|
6942
6944
|
}
|
|
6943
6945
|
function isMutationMessage(data) {
|
|
6944
6946
|
if (typeof data !== "object" || data === null) {
|
|
@@ -6954,6 +6956,13 @@ function isStateMessage(data) {
|
|
|
6954
6956
|
const obj = data;
|
|
6955
6957
|
return obj.type === MESSAGE_TYPES.STATE && Array.isArray(obj.nodes);
|
|
6956
6958
|
}
|
|
6959
|
+
function isConfigMessage(data) {
|
|
6960
|
+
if (typeof data !== "object" || data === null) {
|
|
6961
|
+
return false;
|
|
6962
|
+
}
|
|
6963
|
+
const obj = data;
|
|
6964
|
+
return obj.type === MESSAGE_TYPES.CONFIG && typeof obj.config === "object" && obj.config !== null;
|
|
6965
|
+
}
|
|
6957
6966
|
class AttributeService {
|
|
6958
6967
|
attributes = /* @__PURE__ */ new Map();
|
|
6959
6968
|
eventBus;
|
|
@@ -7051,8 +7060,19 @@ class EventBus {
|
|
|
7051
7060
|
this.listeners.set(event, handlers);
|
|
7052
7061
|
}
|
|
7053
7062
|
emit(event, payload) {
|
|
7054
|
-
this.listeners.get(event)
|
|
7063
|
+
const handlers = this.listeners.get(event);
|
|
7064
|
+
if (handlers === void 0 || handlers.length === 0) {
|
|
7065
|
+
return;
|
|
7066
|
+
}
|
|
7067
|
+
const handlersCopy = [...handlers];
|
|
7068
|
+
handlersCopy.forEach((listener) => {
|
|
7069
|
+
listener(payload);
|
|
7070
|
+
});
|
|
7055
7071
|
}
|
|
7072
|
+
/**
|
|
7073
|
+
* Register a listener that will be called only once
|
|
7074
|
+
* The listener is automatically removed after the first call
|
|
7075
|
+
*/
|
|
7056
7076
|
once(event, listener) {
|
|
7057
7077
|
const onceWrapper = (payload) => {
|
|
7058
7078
|
this.off(event, onceWrapper);
|
|
@@ -7060,6 +7080,9 @@ class EventBus {
|
|
|
7060
7080
|
};
|
|
7061
7081
|
this.on(event, onceWrapper);
|
|
7062
7082
|
}
|
|
7083
|
+
/**
|
|
7084
|
+
* Remove a specific listener for an event
|
|
7085
|
+
*/
|
|
7063
7086
|
off(event, listener) {
|
|
7064
7087
|
const handlers = this.listeners.get(event);
|
|
7065
7088
|
if (handlers === void 0) {
|
|
@@ -7084,16 +7107,11 @@ class MessageHandler {
|
|
|
7084
7107
|
}
|
|
7085
7108
|
setIframe(iframe) {
|
|
7086
7109
|
this.iframe = iframe;
|
|
7087
|
-
logger.debug("Message handler configured with iframe", {
|
|
7088
|
-
src: iframe.src,
|
|
7089
|
-
loaded: iframe.contentWindow !== null
|
|
7090
|
-
});
|
|
7091
7110
|
}
|
|
7092
7111
|
destroy() {
|
|
7093
7112
|
window.removeEventListener("message", this.handleWindowMessage);
|
|
7094
7113
|
this.queue.length = 0;
|
|
7095
7114
|
this.isReady = false;
|
|
7096
|
-
logger.debug("Message handler destroyed");
|
|
7097
7115
|
}
|
|
7098
7116
|
queueOrSend(message) {
|
|
7099
7117
|
if (!this.isReady) {
|
|
@@ -7118,7 +7136,7 @@ class MessageHandler {
|
|
|
7118
7136
|
payload: message
|
|
7119
7137
|
});
|
|
7120
7138
|
this.iframe.contentWindow.postMessage(message, targetOrigin);
|
|
7121
|
-
logger.
|
|
7139
|
+
logger.debug("Message sent to server", message);
|
|
7122
7140
|
}
|
|
7123
7141
|
canSend() {
|
|
7124
7142
|
return this.iframe?.contentWindow !== null && this.iframe?.contentWindow !== void 0;
|
|
@@ -7146,11 +7164,16 @@ class MessageHandler {
|
|
|
7146
7164
|
};
|
|
7147
7165
|
setupIncomingMessages() {
|
|
7148
7166
|
window.addEventListener("message", this.handleWindowMessage);
|
|
7149
|
-
logger.debug("Message handler started listening");
|
|
7150
7167
|
}
|
|
7151
7168
|
setupOutgoingMessages() {
|
|
7152
|
-
|
|
7153
|
-
|
|
7169
|
+
const outgoingEvents = [
|
|
7170
|
+
EVENT_NAMES.MUTATION_MESSAGE,
|
|
7171
|
+
EVENT_NAMES.CONFIG_MESSAGE
|
|
7172
|
+
];
|
|
7173
|
+
outgoingEvents.forEach((eventName) => {
|
|
7174
|
+
this.eventBus.on(eventName, (event) => {
|
|
7175
|
+
this.queueOrSend(event.message);
|
|
7176
|
+
});
|
|
7154
7177
|
});
|
|
7155
7178
|
}
|
|
7156
7179
|
setupReadyListener() {
|
|
@@ -7187,7 +7210,7 @@ class NodeSelector {
|
|
|
7187
7210
|
logger.warn(`Cannot toggle node ${this.nodeId}: node not found`);
|
|
7188
7211
|
return;
|
|
7189
7212
|
}
|
|
7190
|
-
if (node.isVisible
|
|
7213
|
+
if (node.isVisible) {
|
|
7191
7214
|
this.hide();
|
|
7192
7215
|
return;
|
|
7193
7216
|
}
|
|
@@ -7337,11 +7360,98 @@ class StateService {
|
|
|
7337
7360
|
this.hasReceivedInitialSync = false;
|
|
7338
7361
|
}
|
|
7339
7362
|
}
|
|
7363
|
+
class VirtualdisplayViewerService {
|
|
7364
|
+
eventBus;
|
|
7365
|
+
constructor(eventBus) {
|
|
7366
|
+
this.eventBus = eventBus;
|
|
7367
|
+
}
|
|
7368
|
+
/**
|
|
7369
|
+
* Send initial configuration based on client options
|
|
7370
|
+
* Only sends config when values are false (server defaults to true)
|
|
7371
|
+
*/
|
|
7372
|
+
sendInitialConfig(options) {
|
|
7373
|
+
const config = {};
|
|
7374
|
+
if (options.arEnabled === false) {
|
|
7375
|
+
config.arEnabled = false;
|
|
7376
|
+
}
|
|
7377
|
+
if (options.fullscreenEnabled === false) {
|
|
7378
|
+
config.fullscreenEnabled = false;
|
|
7379
|
+
}
|
|
7380
|
+
if (options.loadingIndicatorEnabled === false) {
|
|
7381
|
+
config.loadingIndicatorEnabled = false;
|
|
7382
|
+
}
|
|
7383
|
+
if (Object.keys(config).length > 0) {
|
|
7384
|
+
this.sendUIConfig(config);
|
|
7385
|
+
}
|
|
7386
|
+
}
|
|
7387
|
+
/**
|
|
7388
|
+
* Update AR button visibility
|
|
7389
|
+
*/
|
|
7390
|
+
setArEnabled(enabled) {
|
|
7391
|
+
logger.debug(`Setting AR button enabled: ${enabled}`);
|
|
7392
|
+
this.sendUIConfig({ arEnabled: enabled });
|
|
7393
|
+
}
|
|
7394
|
+
/**
|
|
7395
|
+
* Update fullscreen button visibility
|
|
7396
|
+
*/
|
|
7397
|
+
setFullscreenEnabled(enabled) {
|
|
7398
|
+
logger.debug(`Setting fullscreen button enabled: ${enabled}`);
|
|
7399
|
+
this.sendUIConfig({ fullscreenEnabled: enabled });
|
|
7400
|
+
}
|
|
7401
|
+
/**
|
|
7402
|
+
* Update loading indicator visibility
|
|
7403
|
+
*/
|
|
7404
|
+
setLoadingIndicatorEnabled(enabled) {
|
|
7405
|
+
logger.debug(`Setting loading indicator enabled: ${enabled}`);
|
|
7406
|
+
this.sendUIConfig({ loadingIndicatorEnabled: enabled });
|
|
7407
|
+
}
|
|
7408
|
+
/**
|
|
7409
|
+
* Update multiple UI settings at once
|
|
7410
|
+
*/
|
|
7411
|
+
updateUIConfig(config) {
|
|
7412
|
+
logger.debug("Updating UI configuration", config);
|
|
7413
|
+
this.sendUIConfig(config);
|
|
7414
|
+
}
|
|
7415
|
+
/**
|
|
7416
|
+
* Hide all UI elements
|
|
7417
|
+
*/
|
|
7418
|
+
hideAllUI() {
|
|
7419
|
+
logger.debug("Hiding all UI elements");
|
|
7420
|
+
this.sendUIConfig({
|
|
7421
|
+
arEnabled: false,
|
|
7422
|
+
fullscreenEnabled: false,
|
|
7423
|
+
loadingIndicatorEnabled: false
|
|
7424
|
+
});
|
|
7425
|
+
}
|
|
7426
|
+
/**
|
|
7427
|
+
* Show all UI elements
|
|
7428
|
+
*/
|
|
7429
|
+
showAllUI() {
|
|
7430
|
+
logger.debug("Showing all UI elements");
|
|
7431
|
+
this.sendUIConfig({
|
|
7432
|
+
arEnabled: true,
|
|
7433
|
+
fullscreenEnabled: true,
|
|
7434
|
+
loadingIndicatorEnabled: true
|
|
7435
|
+
});
|
|
7436
|
+
}
|
|
7437
|
+
/**
|
|
7438
|
+
* Send UI configuration to server
|
|
7439
|
+
*/
|
|
7440
|
+
sendUIConfig(uiConfig) {
|
|
7441
|
+
const config = { ui: uiConfig };
|
|
7442
|
+
const message = {
|
|
7443
|
+
type: MESSAGE_TYPES.CONFIG,
|
|
7444
|
+
config
|
|
7445
|
+
};
|
|
7446
|
+
this.eventBus.emit(EVENT_NAMES.CONFIG_MESSAGE, { message });
|
|
7447
|
+
}
|
|
7448
|
+
}
|
|
7340
7449
|
class VirtualdisplayClient {
|
|
7341
7450
|
eventBus;
|
|
7342
7451
|
attributeService;
|
|
7343
7452
|
stateService;
|
|
7344
7453
|
messageHandler;
|
|
7454
|
+
viewerService;
|
|
7345
7455
|
options;
|
|
7346
7456
|
iframe;
|
|
7347
7457
|
constructor(options) {
|
|
@@ -7350,8 +7460,10 @@ class VirtualdisplayClient {
|
|
|
7350
7460
|
this.attributeService = new AttributeService(this.eventBus);
|
|
7351
7461
|
this.stateService = new StateService(this.eventBus);
|
|
7352
7462
|
this.messageHandler = new MessageHandler(this.eventBus);
|
|
7463
|
+
this.viewerService = new VirtualdisplayViewerService(this.eventBus);
|
|
7353
7464
|
this.initializeLogging();
|
|
7354
7465
|
this.createAndConnectIframe();
|
|
7466
|
+
this.setupInitialConfig();
|
|
7355
7467
|
}
|
|
7356
7468
|
initializeLogging() {
|
|
7357
7469
|
if (this.options.debug === true) {
|
|
@@ -7370,6 +7482,11 @@ class VirtualdisplayClient {
|
|
|
7370
7482
|
logger.debug("Iframe created, setting up messaging");
|
|
7371
7483
|
this.messageHandler.setIframe(this.iframe);
|
|
7372
7484
|
}
|
|
7485
|
+
setupInitialConfig() {
|
|
7486
|
+
this.eventBus.once(EVENT_NAMES.IFRAME_READY, () => {
|
|
7487
|
+
this.viewerService.sendInitialConfig(this.options);
|
|
7488
|
+
});
|
|
7489
|
+
}
|
|
7373
7490
|
/**
|
|
7374
7491
|
* Load attribute mapping configuration
|
|
7375
7492
|
* @throws {VirtualdisplayError} When mapping configuration is invalid
|
|
@@ -7431,6 +7548,12 @@ class VirtualdisplayClient {
|
|
|
7431
7548
|
}
|
|
7432
7549
|
this.eventBus.once(EVENT_NAMES.INITIAL_STATE_RECEIVED, callback);
|
|
7433
7550
|
}
|
|
7551
|
+
/**
|
|
7552
|
+
* Get the viewer service for UI configuration
|
|
7553
|
+
*/
|
|
7554
|
+
get viewer() {
|
|
7555
|
+
return this.viewerService;
|
|
7556
|
+
}
|
|
7434
7557
|
destroy() {
|
|
7435
7558
|
logger.info("Destroying Virtualdisplay client");
|
|
7436
7559
|
this.attributeService.clear();
|
|
@@ -7456,6 +7579,7 @@ export {
|
|
|
7456
7579
|
NodeSelector,
|
|
7457
7580
|
VirtualdisplayClient,
|
|
7458
7581
|
VirtualdisplayError,
|
|
7582
|
+
VirtualdisplayViewerService,
|
|
7459
7583
|
enableDebugMode,
|
|
7460
7584
|
isDebugMode,
|
|
7461
7585
|
logger,
|