@plattar/plattar-ar-adapter 2.7.2 → 2.7.3
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/build/es2015/plattar-ar-adapter.js +1307 -1155
- package/build/es2015/plattar-ar-adapter.min.js +1 -1
- package/build/es2019/plattar-ar-adapter.js +303 -150
- package/build/es2019/plattar-ar-adapter.min.js +1 -1
- package/dist/ar/configurator-ar.js +2 -0
- package/dist/ar/model-ar.js +2 -0
- package/dist/ar/product-ar.js +2 -2
- package/dist/ar/raw-ar.js +2 -0
- package/dist/ar/scene-ar.js +2 -1
- package/dist/ar/scene-graph-ar.d.ts +1 -0
- package/dist/ar/scene-graph-ar.js +31 -25
- package/dist/embed/controllers/configurator-controller.d.ts +5 -0
- package/dist/embed/controllers/configurator-controller.js +50 -18
- package/dist/embed/controllers/gallery-controller.js +3 -9
- package/dist/embed/controllers/launcher-controller.js +9 -4
- package/dist/embed/controllers/plattar-controller.d.ts +9 -2
- package/dist/embed/controllers/plattar-controller.js +30 -12
- package/dist/embed/controllers/vto-controller.js +4 -10
- package/dist/embed/controllers/webxr-controller.js +4 -10
- package/dist/embed/plattar-embed.d.ts +6 -0
- package/dist/embed/plattar-embed.js +12 -0
- package/dist/util/configurator-state.d.ts +13 -1
- package/dist/util/configurator-state.js +74 -35
- package/dist/util/util.d.ts +1 -0
- package/dist/util/util.js +74 -22
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +14 -4
|
@@ -31,6 +31,8 @@ class ConfiguratorAR extends launcher_ar_1.LauncherAR {
|
|
|
31
31
|
this._ar = null;
|
|
32
32
|
}
|
|
33
33
|
_SetupAnalytics() {
|
|
34
|
+
if (this._analytics !== null)
|
|
35
|
+
return;
|
|
34
36
|
const scene = this._options.state.scene;
|
|
35
37
|
let analytics = null;
|
|
36
38
|
// setup scene stuff (if any)
|
|
@@ -240,6 +242,8 @@ class ModelAR extends launcher_ar_1.LauncherAR {
|
|
|
240
242
|
return this._options.modelID;
|
|
241
243
|
}
|
|
242
244
|
_SetupAnalytics(model) {
|
|
245
|
+
if (this._analytics !== null)
|
|
246
|
+
return;
|
|
243
247
|
let analytics = null;
|
|
244
248
|
const project = model.relationships.find(plattar_api_1.Project);
|
|
245
249
|
// setup scene stuff (if any)
|
|
@@ -387,6 +391,8 @@ class ProductAR extends launcher_ar_1.LauncherAR {
|
|
|
387
391
|
return this._options.variationSKU;
|
|
388
392
|
}
|
|
389
393
|
_SetupAnalytics(product, variation) {
|
|
394
|
+
if (this._analytics !== null)
|
|
395
|
+
return;
|
|
390
396
|
let analytics = null;
|
|
391
397
|
const scene = product.relationships.find(plattar_api_1.Scene);
|
|
392
398
|
// setup scene stuff (if any)
|
|
@@ -436,9 +442,7 @@ class ProductAR extends launcher_ar_1.LauncherAR {
|
|
|
436
442
|
return reject(new Error("ProductAR.init() - cannot proceed as AR not available in context"));
|
|
437
443
|
}
|
|
438
444
|
const product = new plattar_api_1.Product(this.productID);
|
|
439
|
-
product.include(plattar_api_1.ProductVariation);
|
|
440
445
|
product.include(plattar_api_1.ProductVariation.include(plattar_api_1.FileModel));
|
|
441
|
-
product.include(plattar_api_1.Scene);
|
|
442
446
|
product.include(plattar_api_1.Scene.include(plattar_api_1.Project));
|
|
443
447
|
product.get().then((product) => {
|
|
444
448
|
// find the required variation from our product
|
|
@@ -594,6 +598,8 @@ class RawAR extends launcher_ar_1.LauncherAR {
|
|
|
594
598
|
}
|
|
595
599
|
_SetupAnalytics() {
|
|
596
600
|
return new Promise((accept, _reject) => {
|
|
601
|
+
if (this._analytics !== null)
|
|
602
|
+
return accept();
|
|
597
603
|
const sceneID = this._options.sceneID;
|
|
598
604
|
if (!sceneID) {
|
|
599
605
|
return accept();
|
|
@@ -746,6 +752,8 @@ class SceneAR extends launcher_ar_1.LauncherAR {
|
|
|
746
752
|
return this._options.sceneID;
|
|
747
753
|
}
|
|
748
754
|
_SetupAnalytics(scene) {
|
|
755
|
+
if (this._analytics !== null)
|
|
756
|
+
return;
|
|
749
757
|
let analytics = null;
|
|
750
758
|
// setup scene stuff (if any)
|
|
751
759
|
if (scene) {
|
|
@@ -871,7 +879,6 @@ class SceneAR extends launcher_ar_1.LauncherAR {
|
|
|
871
879
|
}
|
|
872
880
|
const scene = new plattar_api_1.Scene(this.sceneID);
|
|
873
881
|
scene.include(plattar_api_1.Project);
|
|
874
|
-
scene.include(plattar_api_1.SceneProduct);
|
|
875
882
|
scene.include(plattar_api_1.SceneProduct.include(plattar_api_1.Product));
|
|
876
883
|
scene.include(plattar_api_1.SceneModel);
|
|
877
884
|
scene.get().then((scene) => {
|
|
@@ -973,6 +980,7 @@ const version_1 = __importDefault(require("../version"));
|
|
|
973
980
|
class SceneGraphAR extends launcher_ar_1.LauncherAR {
|
|
974
981
|
// analytics instance
|
|
975
982
|
_analytics = null;
|
|
983
|
+
_analyticsSetup = null;
|
|
976
984
|
_options;
|
|
977
985
|
// this thing controls the actual AR view
|
|
978
986
|
// this is setup via .init() function
|
|
@@ -982,32 +990,37 @@ class SceneGraphAR extends launcher_ar_1.LauncherAR {
|
|
|
982
990
|
this._options = options;
|
|
983
991
|
this._ar = null;
|
|
984
992
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
if (
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
993
|
+
_SetupAnalytics() {
|
|
994
|
+
if (this._analyticsSetup !== null)
|
|
995
|
+
return this._analyticsSetup;
|
|
996
|
+
this._analyticsSetup = (async () => {
|
|
997
|
+
const scene = new plattar_api_1.Scene(this._options.sceneID);
|
|
998
|
+
scene.include(plattar_api_1.Project);
|
|
999
|
+
const fetchedScene = await scene.get();
|
|
1000
|
+
let analytics = null;
|
|
1001
|
+
analytics = new plattar_analytics_1.Analytics(fetchedScene.attributes.application_id);
|
|
1002
|
+
analytics.origin = plattar_api_1.Server.location().type;
|
|
1003
|
+
this._analytics = analytics;
|
|
1004
|
+
analytics.data.push("type", "scene-graph-ar");
|
|
1005
|
+
analytics.data.push("sdkVersion", version_1.default);
|
|
1006
|
+
analytics.data.push("sceneId", fetchedScene.id);
|
|
1007
|
+
analytics.data.push("sceneTitle", fetchedScene.attributes.title);
|
|
1008
|
+
const application = fetchedScene.relationships.find(plattar_api_1.Project);
|
|
1009
|
+
// setup application stuff (if any)
|
|
1010
|
+
if (application) {
|
|
1011
|
+
analytics.data.push("applicationId", application.id);
|
|
1012
|
+
analytics.data.push("applicationTitle", application.attributes.title);
|
|
1013
|
+
if (this._options.useARBanner) {
|
|
1014
|
+
this.options.banner = {
|
|
1015
|
+
title: application.attributes.title,
|
|
1016
|
+
subtitle: fetchedScene.attributes.title,
|
|
1017
|
+
button: 'Visit'
|
|
1018
|
+
};
|
|
1019
|
+
}
|
|
1008
1020
|
}
|
|
1009
|
-
|
|
1010
|
-
|
|
1021
|
+
return fetchedScene;
|
|
1022
|
+
})();
|
|
1023
|
+
return this._analyticsSetup;
|
|
1011
1024
|
}
|
|
1012
1025
|
/**
|
|
1013
1026
|
* Composes a Scene into an AR Model (remote operation) that can be used to launch
|
|
@@ -1176,6 +1189,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
1176
1189
|
exports.ConfiguratorController = void 0;
|
|
1177
1190
|
const plattar_api_1 = require("@plattar/plattar-api");
|
|
1178
1191
|
const scene_product_ar_1 = require("../../ar/scene-product-ar");
|
|
1192
|
+
const configurator_state_1 = require("../../util/configurator-state");
|
|
1179
1193
|
const util_1 = require("../../util/util");
|
|
1180
1194
|
const plattar_controller_1 = require("./plattar-controller");
|
|
1181
1195
|
const configurator_ar_1 = require("../../ar/configurator-ar");
|
|
@@ -1254,6 +1268,11 @@ class ConfiguratorController extends plattar_controller_1.PlattarController {
|
|
|
1254
1268
|
}
|
|
1255
1269
|
return Promise.reject(new Error("ConfiguratorController.startARQRCode() - legacy product transition failed"));
|
|
1256
1270
|
}
|
|
1271
|
+
// Kick off scene-graph encoding immediately while we proceed to the base
|
|
1272
|
+
// implementation — the result is Promise-cached so no duplicate request is fired
|
|
1273
|
+
if (!this.getAttribute("scene-graph-id")) {
|
|
1274
|
+
dState.state.encodeSceneGraphID().catch(() => null);
|
|
1275
|
+
}
|
|
1257
1276
|
}
|
|
1258
1277
|
catch (_err) {
|
|
1259
1278
|
}
|
|
@@ -1375,28 +1394,38 @@ class ConfiguratorController extends plattar_controller_1.PlattarController {
|
|
|
1375
1394
|
// optional attributes
|
|
1376
1395
|
let configState = null;
|
|
1377
1396
|
this._state = plattar_controller_1.ControllerState.Renderer;
|
|
1378
|
-
|
|
1379
|
-
|
|
1397
|
+
const suppliedState = this.getAttribute("config-state");
|
|
1398
|
+
if (suppliedState) {
|
|
1399
|
+
// the state was supplied by the host page — decode it locally
|
|
1400
|
+
// rather than paying for the scene fetch getConfiguratorState()
|
|
1401
|
+
// performs before the renderer iframe can even be created. The
|
|
1402
|
+
// renderer only needs the re-encoded state; the flows that do
|
|
1403
|
+
// need the scene (QR/AR) decode on demand and reuse this same
|
|
1404
|
+
// instance via _bootConfigState, keeping user mutations.
|
|
1405
|
+
configState = configurator_state_1.ConfiguratorState.decode(suppliedState);
|
|
1406
|
+
this._bootConfigState = configState;
|
|
1380
1407
|
// if this is declared, we have a furniture scene that we need to re-create the embed
|
|
1381
1408
|
// with new attributes
|
|
1382
|
-
const product =
|
|
1409
|
+
const product = configState.firstOfType("product");
|
|
1383
1410
|
if (product) {
|
|
1384
|
-
this.
|
|
1385
|
-
this.parent.destroy();
|
|
1386
|
-
this.setAttribute("product-id", product.scene_product_id);
|
|
1387
|
-
this.removeAttribute("scene-id");
|
|
1388
|
-
this.parent.unlockObserver();
|
|
1389
|
-
const controller = this.parent.create();
|
|
1390
|
-
if (controller) {
|
|
1391
|
-
return controller.startRenderer();
|
|
1392
|
-
}
|
|
1393
|
-
return Promise.reject(new Error("ConfiguratorController.startRenderer() - legacy product transition failed"));
|
|
1411
|
+
return this._transitionLegacyProduct(product);
|
|
1394
1412
|
}
|
|
1395
|
-
configState = dState;
|
|
1396
1413
|
}
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1414
|
+
else {
|
|
1415
|
+
try {
|
|
1416
|
+
const dState = await this.getConfiguratorState();
|
|
1417
|
+
// if this is declared, we have a furniture scene that we need to re-create the embed
|
|
1418
|
+
// with new attributes
|
|
1419
|
+
const product = dState.state.firstOfType("product");
|
|
1420
|
+
if (product) {
|
|
1421
|
+
return this._transitionLegacyProduct(product);
|
|
1422
|
+
}
|
|
1423
|
+
configState = dState.state;
|
|
1424
|
+
}
|
|
1425
|
+
catch (_err) {
|
|
1426
|
+
// config state is not available
|
|
1427
|
+
configState = null;
|
|
1428
|
+
}
|
|
1400
1429
|
}
|
|
1401
1430
|
// required attributes with defaults for plattar-configurator node
|
|
1402
1431
|
const width = this.getAttribute("width") || "500px";
|
|
@@ -1411,7 +1440,7 @@ class ConfiguratorController extends plattar_controller_1.PlattarController {
|
|
|
1411
1440
|
const showAR = this.getAttribute("show-ar");
|
|
1412
1441
|
const showUI = this.getAttribute("show-ui");
|
|
1413
1442
|
if (configState) {
|
|
1414
|
-
const encodedState = configState.
|
|
1443
|
+
const encodedState = configState.encode();
|
|
1415
1444
|
if (encodedState.length < 6000) {
|
|
1416
1445
|
viewer.setAttribute("config-state", encodedState);
|
|
1417
1446
|
}
|
|
@@ -1430,6 +1459,22 @@ class ConfiguratorController extends plattar_controller_1.PlattarController {
|
|
|
1430
1459
|
return accept(viewer);
|
|
1431
1460
|
});
|
|
1432
1461
|
}
|
|
1462
|
+
/**
|
|
1463
|
+
* Legacy furniture scenes carry a "product" state entry — the embed is
|
|
1464
|
+
* re-created with product attributes and rendering restarts there
|
|
1465
|
+
*/
|
|
1466
|
+
async _transitionLegacyProduct(product) {
|
|
1467
|
+
this.parent.lockObserver();
|
|
1468
|
+
this.parent.destroy();
|
|
1469
|
+
this.setAttribute("product-id", product.scene_product_id);
|
|
1470
|
+
this.removeAttribute("scene-id");
|
|
1471
|
+
this.parent.unlockObserver();
|
|
1472
|
+
const controller = this.parent.create();
|
|
1473
|
+
if (controller) {
|
|
1474
|
+
return controller.startRenderer();
|
|
1475
|
+
}
|
|
1476
|
+
return Promise.reject(new Error("ConfiguratorController.startRenderer() - legacy product transition failed"));
|
|
1477
|
+
}
|
|
1433
1478
|
async initAR() {
|
|
1434
1479
|
if (!util_1.Util.canAugment()) {
|
|
1435
1480
|
throw new Error("ConfiguratorController.initAR() - cannot proceed as AR not available in context");
|
|
@@ -1513,7 +1558,7 @@ class ConfiguratorController extends plattar_controller_1.PlattarController {
|
|
|
1513
1558
|
}
|
|
1514
1559
|
exports.ConfiguratorController = ConfiguratorController;
|
|
1515
1560
|
|
|
1516
|
-
},{"../../ar/configurator-ar":1,"../../ar/scene-graph-ar":7,"../../ar/scene-product-ar":8,"../../util/util":19,"./plattar-controller":12,"@plattar/plattar-api":48}],10:[function(require,module,exports){
|
|
1561
|
+
},{"../../ar/configurator-ar":1,"../../ar/scene-graph-ar":7,"../../ar/scene-product-ar":8,"../../util/configurator-state":18,"../../util/util":19,"./plattar-controller":12,"@plattar/plattar-api":48}],10:[function(require,module,exports){
|
|
1517
1562
|
"use strict";
|
|
1518
1563
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1519
1564
|
exports.GalleryController = void 0;
|
|
@@ -1598,16 +1643,10 @@ class GalleryController extends plattar_controller_1.PlattarController {
|
|
|
1598
1643
|
this._prevQROpt = opt;
|
|
1599
1644
|
if (!opt.detached) {
|
|
1600
1645
|
this._state = plattar_controller_1.ControllerState.QRCode;
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
return accept(viewer);
|
|
1604
|
-
};
|
|
1605
|
-
this.append(viewer);
|
|
1606
|
-
});
|
|
1646
|
+
this.append(viewer);
|
|
1647
|
+
return this._awaitLoad(viewer);
|
|
1607
1648
|
}
|
|
1608
|
-
return
|
|
1609
|
-
return accept(viewer);
|
|
1610
|
-
});
|
|
1649
|
+
return Promise.resolve(viewer);
|
|
1611
1650
|
}
|
|
1612
1651
|
async startRenderer() {
|
|
1613
1652
|
// remove the old renderer instance if any
|
|
@@ -1704,6 +1743,11 @@ class LauncherController extends plattar_controller_1.PlattarController {
|
|
|
1704
1743
|
}
|
|
1705
1744
|
return Promise.reject(new Error("LauncherController.startARQRCode() - legacy product transition failed"));
|
|
1706
1745
|
}
|
|
1746
|
+
// Kick off scene-graph encoding immediately while we proceed to the base
|
|
1747
|
+
// implementation — the result is Promise-cached so no duplicate request is fired
|
|
1748
|
+
if (!this.getAttribute("scene-graph-id")) {
|
|
1749
|
+
dState.state.encodeSceneGraphID().catch(() => null);
|
|
1750
|
+
}
|
|
1707
1751
|
}
|
|
1708
1752
|
catch (_err) {
|
|
1709
1753
|
}
|
|
@@ -1766,10 +1810,10 @@ class LauncherController extends plattar_controller_1.PlattarController {
|
|
|
1766
1810
|
if (sceneGraphID) {
|
|
1767
1811
|
viewer.setAttribute("scene-graph-id", sceneGraphID);
|
|
1768
1812
|
}
|
|
1769
|
-
else {
|
|
1813
|
+
else if (configState) {
|
|
1770
1814
|
try {
|
|
1771
|
-
const
|
|
1772
|
-
viewer.setAttribute("scene-graph-id",
|
|
1815
|
+
const encodedID = await configState.state.encodeSceneGraphID();
|
|
1816
|
+
viewer.setAttribute("scene-graph-id", encodedID);
|
|
1773
1817
|
}
|
|
1774
1818
|
catch (_err) {
|
|
1775
1819
|
// scene graph ID not available for some reason
|
|
@@ -1780,7 +1824,7 @@ class LauncherController extends plattar_controller_1.PlattarController {
|
|
|
1780
1824
|
return new Promise((accept, reject) => {
|
|
1781
1825
|
this.append(viewer);
|
|
1782
1826
|
if (configState) {
|
|
1783
|
-
this.setupMessengerObservers(viewer, configState);
|
|
1827
|
+
this.setupMessengerObservers(viewer, configState.state);
|
|
1784
1828
|
}
|
|
1785
1829
|
return accept(viewer);
|
|
1786
1830
|
});
|
|
@@ -1903,6 +1947,11 @@ class PlattarController {
|
|
|
1903
1947
|
_state = ControllerState.None;
|
|
1904
1948
|
_element = null;
|
|
1905
1949
|
_prevQROpt = null;
|
|
1950
|
+
// when the renderer was booted from a supplied config-state attribute the
|
|
1951
|
+
// state is decoded locally without the scene fetch — this keeps that live
|
|
1952
|
+
// instance (mutated by the messenger observers as the user configures) so
|
|
1953
|
+
// a later full decode for QR/AR reuses it instead of losing those changes
|
|
1954
|
+
_bootConfigState = null;
|
|
1906
1955
|
_selectVariationObserver = null;
|
|
1907
1956
|
_selectVariationIDObserver = null;
|
|
1908
1957
|
_selectVariationSKUObserver = null;
|
|
@@ -1924,7 +1973,7 @@ class PlattarController {
|
|
|
1924
1973
|
// get a list of variation SKU's to use for initialising
|
|
1925
1974
|
const variationSKUs = this.getAttribute("variation-sku");
|
|
1926
1975
|
// generate the decoded configurator state
|
|
1927
|
-
const decodedState = configState ? await configurator_state_1.ConfiguratorState.decodeState(sceneID, configState) : await configurator_state_1.ConfiguratorState.decodeScene(sceneID);
|
|
1976
|
+
const decodedState = configState ? await configurator_state_1.ConfiguratorState.decodeState(sceneID, configState, this._bootConfigState) : await configurator_state_1.ConfiguratorState.decodeScene(sceneID);
|
|
1928
1977
|
// change the ID's and SKU's (if any) of the default configuration state
|
|
1929
1978
|
const variationIDList = variationIDs ? variationIDs.split(",") : [];
|
|
1930
1979
|
const variationSKUList = variationSKUs ? variationSKUs.split(",") : [];
|
|
@@ -1947,7 +1996,7 @@ class PlattarController {
|
|
|
1947
1996
|
const args = cd.data[0];
|
|
1948
1997
|
const variations = args ? (Array.isArray(args) ? args : [args]) : [];
|
|
1949
1998
|
variations.forEach((variationID) => {
|
|
1950
|
-
configState.
|
|
1999
|
+
configState.setVariationID(variationID);
|
|
1951
2000
|
});
|
|
1952
2001
|
}
|
|
1953
2002
|
});
|
|
@@ -1956,7 +2005,7 @@ class PlattarController {
|
|
|
1956
2005
|
const args = cd.data[0];
|
|
1957
2006
|
const variations = args ? (Array.isArray(args) ? args : [args]) : [];
|
|
1958
2007
|
variations.forEach((variationID) => {
|
|
1959
|
-
configState.
|
|
2008
|
+
configState.setVariationID(variationID);
|
|
1960
2009
|
});
|
|
1961
2010
|
}
|
|
1962
2011
|
});
|
|
@@ -1965,7 +2014,7 @@ class PlattarController {
|
|
|
1965
2014
|
const args = cd.data[0];
|
|
1966
2015
|
const variations = args ? (Array.isArray(args) ? args : [args]) : [];
|
|
1967
2016
|
variations.forEach((variationSKU) => {
|
|
1968
|
-
configState.
|
|
2017
|
+
configState.setVariationSKU(variationSKU);
|
|
1969
2018
|
});
|
|
1970
2019
|
}
|
|
1971
2020
|
});
|
|
@@ -2087,8 +2136,9 @@ class PlattarController {
|
|
|
2087
2136
|
}
|
|
2088
2137
|
else {
|
|
2089
2138
|
try {
|
|
2090
|
-
const
|
|
2091
|
-
|
|
2139
|
+
const configState = await this.getConfiguratorState();
|
|
2140
|
+
const encodedID = await configState.state.encodeSceneGraphID();
|
|
2141
|
+
dst += "&scene_graph_id=" + encodedID;
|
|
2092
2142
|
}
|
|
2093
2143
|
catch (_err) {
|
|
2094
2144
|
// scene graph ID not available for some reason
|
|
@@ -2100,17 +2150,29 @@ class PlattarController {
|
|
|
2100
2150
|
this._prevQROpt = opt;
|
|
2101
2151
|
if (!opt.detached) {
|
|
2102
2152
|
this._state = ControllerState.QRCode;
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
viewer.onload = () => {
|
|
2106
|
-
return accept(viewer);
|
|
2107
|
-
};
|
|
2108
|
-
});
|
|
2153
|
+
this.append(viewer);
|
|
2154
|
+
return this._awaitLoad(viewer);
|
|
2109
2155
|
}
|
|
2110
2156
|
return new Promise((accept, reject) => {
|
|
2111
2157
|
return accept(viewer);
|
|
2112
2158
|
});
|
|
2113
2159
|
}
|
|
2160
|
+
/**
|
|
2161
|
+
* Appends the viewer to the shadow DOM and waits for its onload event.
|
|
2162
|
+
* Rejects if onload does not fire within timeoutMs (default 30 s) so
|
|
2163
|
+
* callers are never left with a permanently-pending Promise.
|
|
2164
|
+
*/
|
|
2165
|
+
_awaitLoad(viewer, timeoutMs = 30000) {
|
|
2166
|
+
return new Promise((accept, reject) => {
|
|
2167
|
+
const timeout = setTimeout(() => {
|
|
2168
|
+
reject(new Error("PlattarController._awaitLoad() - element did not fire onload within " + timeoutMs + "ms"));
|
|
2169
|
+
}, timeoutMs);
|
|
2170
|
+
viewer.onload = () => {
|
|
2171
|
+
clearTimeout(timeout);
|
|
2172
|
+
accept(viewer);
|
|
2173
|
+
};
|
|
2174
|
+
});
|
|
2175
|
+
}
|
|
2114
2176
|
/**
|
|
2115
2177
|
* Removes the currently active renderer view from the DOM
|
|
2116
2178
|
*/
|
|
@@ -2587,16 +2649,10 @@ class VTOController extends plattar_controller_1.PlattarController {
|
|
|
2587
2649
|
this._prevQROpt = opt;
|
|
2588
2650
|
if (!opt.detached) {
|
|
2589
2651
|
this._state = plattar_controller_1.ControllerState.QRCode;
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
return accept(viewer);
|
|
2593
|
-
};
|
|
2594
|
-
this.append(viewer);
|
|
2595
|
-
});
|
|
2652
|
+
this.append(viewer);
|
|
2653
|
+
return this._awaitLoad(viewer);
|
|
2596
2654
|
}
|
|
2597
|
-
return
|
|
2598
|
-
return accept(viewer);
|
|
2599
|
-
});
|
|
2655
|
+
return Promise.resolve(viewer);
|
|
2600
2656
|
}
|
|
2601
2657
|
async startRenderer() {
|
|
2602
2658
|
// remove the old renderer instance if any
|
|
@@ -2647,7 +2703,7 @@ class VTOController extends plattar_controller_1.PlattarController {
|
|
|
2647
2703
|
return new Promise((accept, reject) => {
|
|
2648
2704
|
this.append(viewer);
|
|
2649
2705
|
if (configState) {
|
|
2650
|
-
this.setupMessengerObservers(viewer, configState);
|
|
2706
|
+
this.setupMessengerObservers(viewer, configState.state);
|
|
2651
2707
|
}
|
|
2652
2708
|
return accept(viewer);
|
|
2653
2709
|
});
|
|
@@ -2805,12 +2861,8 @@ class WebXRController extends plattar_controller_1.PlattarController {
|
|
|
2805
2861
|
viewer.setAttribute("url", opt.url || dst);
|
|
2806
2862
|
this._state = plattar_controller_1.ControllerState.QRCode;
|
|
2807
2863
|
this._prevQROpt = opt;
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
return accept(viewer);
|
|
2811
|
-
};
|
|
2812
|
-
this.append(viewer);
|
|
2813
|
-
});
|
|
2864
|
+
this.append(viewer);
|
|
2865
|
+
return this._awaitLoad(viewer);
|
|
2814
2866
|
}
|
|
2815
2867
|
async startRenderer() {
|
|
2816
2868
|
// remove the old renderer instance if any
|
|
@@ -2840,10 +2892,8 @@ class WebXRController extends plattar_controller_1.PlattarController {
|
|
|
2840
2892
|
if (showUI) {
|
|
2841
2893
|
viewer.setAttribute("show-ui", showUI);
|
|
2842
2894
|
}
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
return accept(viewer);
|
|
2846
|
-
});
|
|
2895
|
+
this.append(viewer);
|
|
2896
|
+
return Promise.resolve(viewer);
|
|
2847
2897
|
}
|
|
2848
2898
|
async initAR() {
|
|
2849
2899
|
throw new Error("WebXRController.initAR() - cannot proceed as AR not available in webxr");
|
|
@@ -2907,6 +2957,18 @@ class PlattarEmbed extends HTMLElement {
|
|
|
2907
2957
|
connectedCallback() {
|
|
2908
2958
|
this.create();
|
|
2909
2959
|
}
|
|
2960
|
+
/**
|
|
2961
|
+
* Clean up when the element is removed from the DOM.
|
|
2962
|
+
* Disconnects the MutationObserver and removes all messenger subscriptions
|
|
2963
|
+
* to prevent memory leaks from dangling closures.
|
|
2964
|
+
*/
|
|
2965
|
+
disconnectedCallback() {
|
|
2966
|
+
if (this._observer) {
|
|
2967
|
+
this._observer.disconnect();
|
|
2968
|
+
this._observer = null;
|
|
2969
|
+
}
|
|
2970
|
+
this.destroy();
|
|
2971
|
+
}
|
|
2910
2972
|
/**
|
|
2911
2973
|
* creates a brand new instance of this embed
|
|
2912
2974
|
*/
|
|
@@ -3225,6 +3287,16 @@ class ConfiguratorState {
|
|
|
3225
3287
|
_mappedVariationIDValues;
|
|
3226
3288
|
// This maps Variation SKU against a Variation ID - populated by decodeScene() function
|
|
3227
3289
|
_mappedVariationSKUValues;
|
|
3290
|
+
// Cache for encodeSceneGraphID() - keyed by serialised scene graph JSON so state
|
|
3291
|
+
// changes automatically bust the cache, and concurrent in-flight calls share one fetch
|
|
3292
|
+
_cachedSceneGraphID = null;
|
|
3293
|
+
_cachedSceneGraphJSON = null;
|
|
3294
|
+
// Memoised result of the sceneGraph getter - cleared whenever state is mutated
|
|
3295
|
+
_cachedSceneGraph = null;
|
|
3296
|
+
// Static page-lifetime cache for Scene API responses, keyed by sceneID.
|
|
3297
|
+
// Shared across all controller instances so that multiple <plattar-embed>
|
|
3298
|
+
// elements with the same scene-id (or a recreated controller) reuse one fetch.
|
|
3299
|
+
static _sceneAPICache = new Map();
|
|
3228
3300
|
constructor(state = null) {
|
|
3229
3301
|
this._mappedVariationIDValues = new Map();
|
|
3230
3302
|
this._mappedVariationSKUValues = new Map();
|
|
@@ -3321,6 +3393,7 @@ class ConfiguratorState {
|
|
|
3321
3393
|
newData[meta.scene_product_index] = SceneModelID;
|
|
3322
3394
|
newData[meta.product_variation_index] = null;
|
|
3323
3395
|
newData[meta.meta_index] = metaData;
|
|
3396
|
+
this._cachedSceneGraph = null;
|
|
3324
3397
|
}
|
|
3325
3398
|
}
|
|
3326
3399
|
/**
|
|
@@ -3348,6 +3421,7 @@ class ConfiguratorState {
|
|
|
3348
3421
|
newData[meta.product_index] = productID;
|
|
3349
3422
|
newData[meta.product_variation_index] = productVariationID;
|
|
3350
3423
|
newData[meta.meta_index] = metaData;
|
|
3424
|
+
this._cachedSceneGraph = null;
|
|
3351
3425
|
}
|
|
3352
3426
|
}
|
|
3353
3427
|
/**
|
|
@@ -3376,6 +3450,7 @@ class ConfiguratorState {
|
|
|
3376
3450
|
newData[meta.scene_product_index] = sceneProductID;
|
|
3377
3451
|
newData[meta.product_variation_index] = productVariationID;
|
|
3378
3452
|
newData[meta.meta_index] = metaData;
|
|
3453
|
+
this._cachedSceneGraph = null;
|
|
3379
3454
|
}
|
|
3380
3455
|
}
|
|
3381
3456
|
/**
|
|
@@ -3560,24 +3635,43 @@ class ConfiguratorState {
|
|
|
3560
3635
|
static decode(state) {
|
|
3561
3636
|
return new ConfiguratorState(state);
|
|
3562
3637
|
}
|
|
3638
|
+
/**
|
|
3639
|
+
* Returns a cached Promise<Scene> for the given sceneID, firing at most one
|
|
3640
|
+
* API request per sceneID per page lifetime. Both decodeState() and
|
|
3641
|
+
* decodeScene() share this cache so they never race each other.
|
|
3642
|
+
*/
|
|
3643
|
+
static _fetchScene(sceneID) {
|
|
3644
|
+
const cached = ConfiguratorState._sceneAPICache.get(sceneID);
|
|
3645
|
+
if (cached) {
|
|
3646
|
+
return cached;
|
|
3647
|
+
}
|
|
3648
|
+
const fscene = new plattar_api_1.Scene(sceneID);
|
|
3649
|
+
fscene.include(plattar_api_1.Project);
|
|
3650
|
+
fscene.include(plattar_api_1.SceneModel);
|
|
3651
|
+
fscene.include(plattar_api_1.Product);
|
|
3652
|
+
fscene.include(plattar_api_1.SceneProduct.include(plattar_api_1.Product.include(plattar_api_1.ProductVariation)));
|
|
3653
|
+
const promise = fscene.get();
|
|
3654
|
+
ConfiguratorState._sceneAPICache.set(sceneID, promise);
|
|
3655
|
+
// Bust the cache on failure so the next call retries
|
|
3656
|
+
promise.catch(() => {
|
|
3657
|
+
ConfiguratorState._sceneAPICache.delete(sceneID);
|
|
3658
|
+
});
|
|
3659
|
+
return promise;
|
|
3660
|
+
}
|
|
3563
3661
|
/**
|
|
3564
3662
|
* Decodes a previously generated state
|
|
3565
3663
|
* @param sceneID
|
|
3566
3664
|
* @param state
|
|
3665
|
+
* @param existingState - (optional) reuse this already-decoded instance instead of
|
|
3666
|
+
* parsing a fresh one, so mutations applied to it before this call are preserved
|
|
3567
3667
|
* @returns
|
|
3568
3668
|
*/
|
|
3569
|
-
static async decodeState(sceneID = null, state = null) {
|
|
3669
|
+
static async decodeState(sceneID = null, state = null, existingState = null) {
|
|
3570
3670
|
if (!sceneID || !state) {
|
|
3571
3671
|
throw new Error("ConfiguratorState.decodeState(sceneID, state) - sceneID and state must be defined");
|
|
3572
3672
|
}
|
|
3573
|
-
const configState = new ConfiguratorState(state);
|
|
3574
|
-
const
|
|
3575
|
-
fscene.include(plattar_api_1.Project);
|
|
3576
|
-
fscene.include(plattar_api_1.Product);
|
|
3577
|
-
fscene.include(plattar_api_1.SceneProduct);
|
|
3578
|
-
fscene.include(plattar_api_1.SceneModel);
|
|
3579
|
-
fscene.include(plattar_api_1.SceneProduct.include(plattar_api_1.Product.include(plattar_api_1.ProductVariation)));
|
|
3580
|
-
const scene = await fscene.get();
|
|
3673
|
+
const configState = existingState ?? new ConfiguratorState(state);
|
|
3674
|
+
const scene = await ConfiguratorState._fetchScene(sceneID);
|
|
3581
3675
|
return {
|
|
3582
3676
|
scene: scene,
|
|
3583
3677
|
state: configState
|
|
@@ -3594,13 +3688,7 @@ class ConfiguratorState {
|
|
|
3594
3688
|
throw new Error("ConfiguratorState.decodeScene(sceneID) - sceneID must be defined");
|
|
3595
3689
|
}
|
|
3596
3690
|
const configState = new ConfiguratorState();
|
|
3597
|
-
const
|
|
3598
|
-
fscene.include(plattar_api_1.Project);
|
|
3599
|
-
fscene.include(plattar_api_1.SceneProduct);
|
|
3600
|
-
fscene.include(plattar_api_1.SceneModel);
|
|
3601
|
-
fscene.include(plattar_api_1.Product);
|
|
3602
|
-
fscene.include(plattar_api_1.SceneProduct.include(plattar_api_1.Product.include(plattar_api_1.ProductVariation)));
|
|
3603
|
-
const scene = await fscene.get();
|
|
3691
|
+
const scene = await ConfiguratorState._fetchScene(sceneID);
|
|
3604
3692
|
const sceneProducts = scene.relationships.filter(plattar_api_1.SceneProduct);
|
|
3605
3693
|
const sceneModels = scene.relationships.filter(plattar_api_1.SceneModel);
|
|
3606
3694
|
const products = scene.relationships.filter(plattar_api_1.Product);
|
|
@@ -3658,42 +3746,54 @@ class ConfiguratorState {
|
|
|
3658
3746
|
encode() {
|
|
3659
3747
|
return btoa(JSON.stringify(this._state));
|
|
3660
3748
|
}
|
|
3661
|
-
|
|
3749
|
+
encodeSceneGraphID() {
|
|
3662
3750
|
const graph = this.sceneGraph;
|
|
3751
|
+
const graphJSON = JSON.stringify(graph);
|
|
3752
|
+
// Return cached promise if the scene graph state hasn't changed.
|
|
3753
|
+
// Caching the Promise (not the resolved value) means concurrent in-flight
|
|
3754
|
+
// calls also share a single fetch rather than firing multiple requests.
|
|
3755
|
+
if (this._cachedSceneGraphID !== null && this._cachedSceneGraphJSON === graphJSON) {
|
|
3756
|
+
return this._cachedSceneGraphID;
|
|
3757
|
+
}
|
|
3663
3758
|
// some scene-graphs are very large in size, we store it remotely
|
|
3664
3759
|
// this storage will expire in 10 minutes so this is a non-permanent version
|
|
3665
3760
|
// and is designed for quick ar
|
|
3666
3761
|
const url = plattar_api_1.Server.location().type === 'staging' ? 'https://c.plattar.space/v3/redir/store' : 'https://c.plattar.com/v3/redir/store';
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
data: graph
|
|
3678
|
-
}
|
|
3762
|
+
this._cachedSceneGraphJSON = graphJSON;
|
|
3763
|
+
this._cachedSceneGraphID = fetch(url, {
|
|
3764
|
+
method: "POST",
|
|
3765
|
+
headers: {
|
|
3766
|
+
"Content-Type": "application/json"
|
|
3767
|
+
},
|
|
3768
|
+
body: JSON.stringify({
|
|
3769
|
+
data: {
|
|
3770
|
+
attributes: {
|
|
3771
|
+
data: graph
|
|
3679
3772
|
}
|
|
3680
|
-
}
|
|
3681
|
-
})
|
|
3773
|
+
}
|
|
3774
|
+
})
|
|
3775
|
+
}).then(async (response) => {
|
|
3682
3776
|
if (!response.ok) {
|
|
3683
3777
|
throw new Error(`ConfiguratorState.encodeSceneGraphID() - network response was not ok ${response.status}`);
|
|
3684
3778
|
}
|
|
3685
3779
|
const data = await response.json();
|
|
3686
3780
|
return data.data.id;
|
|
3687
|
-
}
|
|
3688
|
-
|
|
3781
|
+
}).catch((error) => {
|
|
3782
|
+
// Bust the cache on failure so the next call retries
|
|
3783
|
+
this._cachedSceneGraphID = null;
|
|
3784
|
+
this._cachedSceneGraphJSON = null;
|
|
3689
3785
|
throw new Error(`ConfiguratorState.encodeSceneGraphID() - there was a request error to ${url}, error was ${error.message}`);
|
|
3690
|
-
}
|
|
3786
|
+
});
|
|
3787
|
+
return this._cachedSceneGraphID;
|
|
3691
3788
|
}
|
|
3692
3789
|
/**
|
|
3693
3790
|
* Compiles and returns the Dynamic Scene Graph (Updated for 2025 for DynamicAR)
|
|
3694
3791
|
* NOTE: Eventually this structure should replace ConfiguratorState
|
|
3695
3792
|
*/
|
|
3696
3793
|
get sceneGraph() {
|
|
3794
|
+
if (this._cachedSceneGraph !== null) {
|
|
3795
|
+
return this._cachedSceneGraph;
|
|
3796
|
+
}
|
|
3697
3797
|
const objects = this.array();
|
|
3698
3798
|
// in here we need to generate the schema input to be sent to the backend service
|
|
3699
3799
|
const schema = {
|
|
@@ -3720,7 +3820,8 @@ class ConfiguratorState {
|
|
|
3720
3820
|
schema.inputs.push(data);
|
|
3721
3821
|
}
|
|
3722
3822
|
});
|
|
3723
|
-
|
|
3823
|
+
this._cachedSceneGraph = schema;
|
|
3824
|
+
return this._cachedSceneGraph;
|
|
3724
3825
|
}
|
|
3725
3826
|
}
|
|
3726
3827
|
exports.ConfiguratorState = ConfiguratorState;
|
|
@@ -3733,6 +3834,7 @@ exports.Util = void 0;
|
|
|
3733
3834
|
* Static Utility Functions
|
|
3734
3835
|
*/
|
|
3735
3836
|
class Util {
|
|
3837
|
+
static _cache = new Map();
|
|
3736
3838
|
static isValidServerLocation(server) {
|
|
3737
3839
|
if (!server) {
|
|
3738
3840
|
return false;
|
|
@@ -3758,67 +3860,118 @@ class Util {
|
|
|
3758
3860
|
return false;
|
|
3759
3861
|
}
|
|
3760
3862
|
static canAugment() {
|
|
3761
|
-
|
|
3863
|
+
if (Util._cache.has('canAugment'))
|
|
3864
|
+
return Util._cache.get('canAugment');
|
|
3865
|
+
const result = Util.canQuicklook() || Util.canSceneViewer();
|
|
3866
|
+
Util._cache.set('canAugment', result);
|
|
3867
|
+
return result;
|
|
3762
3868
|
}
|
|
3763
3869
|
static canQuicklook() {
|
|
3870
|
+
if (Util._cache.has('canQuicklook'))
|
|
3871
|
+
return Util._cache.get('canQuicklook');
|
|
3872
|
+
let result = false;
|
|
3764
3873
|
if (Util.isIOS()) {
|
|
3765
3874
|
const isWKWebView = Boolean((window && window).webkit && window.webkit.messageHandlers);
|
|
3766
3875
|
if (isWKWebView) {
|
|
3767
|
-
|
|
3876
|
+
result = Boolean(/CriOS\/|EdgiOS\/|FxiOS\/|GSA\/|DuckDuckGo\//.test(navigator.userAgent));
|
|
3877
|
+
}
|
|
3878
|
+
else {
|
|
3879
|
+
const tempAnchor = document.createElement("a");
|
|
3880
|
+
result = Boolean(tempAnchor.relList && tempAnchor.relList.supports && tempAnchor.relList.supports("ar"));
|
|
3768
3881
|
}
|
|
3769
|
-
const tempAnchor = document.createElement("a");
|
|
3770
|
-
return tempAnchor.relList && tempAnchor.relList.supports && tempAnchor.relList.supports("ar");
|
|
3771
3882
|
}
|
|
3772
|
-
|
|
3883
|
+
Util._cache.set('canQuicklook', result);
|
|
3884
|
+
return result;
|
|
3773
3885
|
}
|
|
3774
3886
|
static canSceneViewer() {
|
|
3775
|
-
|
|
3887
|
+
if (Util._cache.has('canSceneViewer'))
|
|
3888
|
+
return Util._cache.get('canSceneViewer');
|
|
3889
|
+
const result = Util.isAndroid() && !Util.isFirefox() && !Util.isOculus();
|
|
3890
|
+
Util._cache.set('canSceneViewer', result);
|
|
3891
|
+
return result;
|
|
3776
3892
|
}
|
|
3777
3893
|
static canRealityViewer() {
|
|
3778
|
-
|
|
3894
|
+
if (Util._cache.has('canRealityViewer'))
|
|
3895
|
+
return Util._cache.get('canRealityViewer');
|
|
3896
|
+
const result = Util.isIOS() && Util.getIOSVersion()[0] >= 13;
|
|
3897
|
+
Util._cache.set('canRealityViewer', result);
|
|
3898
|
+
return result;
|
|
3779
3899
|
}
|
|
3780
3900
|
static isSafariOnIOS() {
|
|
3781
|
-
|
|
3901
|
+
if (Util._cache.has('isSafariOnIOS'))
|
|
3902
|
+
return Util._cache.get('isSafariOnIOS');
|
|
3903
|
+
const result = Util.isIOS() && Util.isSafari();
|
|
3904
|
+
Util._cache.set('isSafariOnIOS', result);
|
|
3905
|
+
return result;
|
|
3782
3906
|
}
|
|
3783
3907
|
static isChromeOnIOS() {
|
|
3784
|
-
|
|
3908
|
+
if (Util._cache.has('isChromeOnIOS'))
|
|
3909
|
+
return Util._cache.get('isChromeOnIOS');
|
|
3910
|
+
const result = Util.isIOS() && /CriOS\//.test(navigator.userAgent);
|
|
3911
|
+
Util._cache.set('isChromeOnIOS', result);
|
|
3912
|
+
return result;
|
|
3785
3913
|
}
|
|
3786
3914
|
static isIOS() {
|
|
3787
|
-
|
|
3915
|
+
if (Util._cache.has('isIOS'))
|
|
3916
|
+
return Util._cache.get('isIOS');
|
|
3917
|
+
const result = (/iPad|iPhone|iPod/.test(navigator.userAgent) && !self.MSStream) || (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
|
|
3918
|
+
Util._cache.set('isIOS', result);
|
|
3919
|
+
return result;
|
|
3788
3920
|
}
|
|
3789
3921
|
static isAndroid() {
|
|
3790
|
-
|
|
3922
|
+
if (Util._cache.has('isAndroid'))
|
|
3923
|
+
return Util._cache.get('isAndroid');
|
|
3924
|
+
const result = /android/i.test(navigator.userAgent);
|
|
3925
|
+
Util._cache.set('isAndroid', result);
|
|
3926
|
+
return result;
|
|
3791
3927
|
}
|
|
3792
3928
|
static isFirefox() {
|
|
3793
|
-
|
|
3929
|
+
if (Util._cache.has('isFirefox'))
|
|
3930
|
+
return Util._cache.get('isFirefox');
|
|
3931
|
+
const result = /firefox/i.test(navigator.userAgent);
|
|
3932
|
+
Util._cache.set('isFirefox', result);
|
|
3933
|
+
return result;
|
|
3794
3934
|
}
|
|
3795
3935
|
static isOculus() {
|
|
3796
|
-
|
|
3936
|
+
if (Util._cache.has('isOculus'))
|
|
3937
|
+
return Util._cache.get('isOculus');
|
|
3938
|
+
const result = /OculusBrowser/.test(navigator.userAgent);
|
|
3939
|
+
Util._cache.set('isOculus', result);
|
|
3940
|
+
return result;
|
|
3797
3941
|
}
|
|
3798
3942
|
static isSafari() {
|
|
3799
|
-
|
|
3943
|
+
if (Util._cache.has('isSafari'))
|
|
3944
|
+
return Util._cache.get('isSafari');
|
|
3945
|
+
const result = Util.isIOS() && /Safari\//.test(navigator.userAgent);
|
|
3946
|
+
Util._cache.set('isSafari', result);
|
|
3947
|
+
return result;
|
|
3800
3948
|
}
|
|
3801
3949
|
static getIOSVersion() {
|
|
3950
|
+
if (Util._cache.has('getIOSVersion'))
|
|
3951
|
+
return Util._cache.get('getIOSVersion');
|
|
3952
|
+
let result = [-1, -1, -1];
|
|
3802
3953
|
if (/iP(hone|od|ad)/.test(navigator.platform)) {
|
|
3803
3954
|
const v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/);
|
|
3804
3955
|
if (v !== null) {
|
|
3805
|
-
|
|
3956
|
+
result = [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3], 10)];
|
|
3806
3957
|
}
|
|
3807
3958
|
}
|
|
3808
|
-
if (/Mac/.test(navigator.platform)) {
|
|
3959
|
+
else if (/Mac/.test(navigator.platform)) {
|
|
3809
3960
|
const v = (navigator.appVersion).match(/Version\/(\d+)\.(\d+)\.?(\d+)?/);
|
|
3810
3961
|
if (v !== null) {
|
|
3811
|
-
|
|
3962
|
+
result = [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3], 10)];
|
|
3812
3963
|
}
|
|
3813
3964
|
}
|
|
3814
|
-
|
|
3965
|
+
Util._cache.set('getIOSVersion', result);
|
|
3966
|
+
return result;
|
|
3815
3967
|
}
|
|
3816
3968
|
static getChromeVersion() {
|
|
3969
|
+
if (Util._cache.has('getChromeVersion'))
|
|
3970
|
+
return Util._cache.get('getChromeVersion');
|
|
3817
3971
|
const raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
return 1;
|
|
3972
|
+
const result = raw !== null ? parseInt(raw[2], 10) : 1;
|
|
3973
|
+
Util._cache.set('getChromeVersion', result);
|
|
3974
|
+
return result;
|
|
3822
3975
|
}
|
|
3823
3976
|
}
|
|
3824
3977
|
exports.Util = Util;
|
|
@@ -3826,7 +3979,7 @@ exports.Util = Util;
|
|
|
3826
3979
|
},{}],20:[function(require,module,exports){
|
|
3827
3980
|
"use strict";
|
|
3828
3981
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3829
|
-
exports.default = "2.7.
|
|
3982
|
+
exports.default = "2.7.3";
|
|
3830
3983
|
|
|
3831
3984
|
},{}],21:[function(require,module,exports){
|
|
3832
3985
|
"use strict";
|