UNPKG

@plattar/plattar-ar-adapter

Version:

Plattar AR Adapter for interfacing with Google & Apple WebAR

290 lines (289 loc) 11.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const plattar_api_1 = require("@plattar/plattar-api"); const configurator_controller_1 = require("./controllers/configurator-controller"); const vto_controller_1 = require("./controllers/vto-controller"); const product_controller_1 = require("./controllers/product-controller"); const util_1 = require("../util/util"); const webxr_controller_1 = require("./controllers/webxr-controller"); const gallery_controller_1 = require("./controllers/gallery-controller"); const launcher_controller_1 = require("./controllers/launcher-controller"); /** * This tracks the current embed type */ var EmbedType; (function (EmbedType) { EmbedType[EmbedType["Configurator"] = 0] = "Configurator"; EmbedType[EmbedType["Legacy"] = 1] = "Legacy"; EmbedType[EmbedType["VTO"] = 2] = "VTO"; EmbedType[EmbedType["WebXR"] = 3] = "WebXR"; EmbedType[EmbedType["Gallery"] = 4] = "Gallery"; EmbedType[EmbedType["Launcher"] = 5] = "Launcher"; EmbedType[EmbedType["None"] = 6] = "None"; })(EmbedType || (EmbedType = {})); /** * Controls the state of the observer */ var ObserverState; (function (ObserverState) { ObserverState[ObserverState["Locked"] = 0] = "Locked"; ObserverState[ObserverState["Unlocked"] = 1] = "Unlocked"; })(ObserverState || (ObserverState = {})); /** * This is the primary <plattar-embed /> node that allows easy embedding * of Plattar related content */ class PlattarEmbed extends HTMLElement { constructor() { super(); // this is the current embed type, viewer by default this._currentType = EmbedType.None; this._observerState = ObserverState.Unlocked; this._controller = null; this._currentSceneID = null; this._currentServer = null; this._observer = null; } get viewer() { return this._controller ? this._controller.element : null; } /** * Begin observing all changes to this DOM element */ connectedCallback() { this.create(); } /** * creates a brand new instance of this embed */ create() { if (!this._observer) { this._observer = new MutationObserver((mutations) => { if (this._observerState === ObserverState.Unlocked) { mutations.forEach((mutation) => { if (mutation.type === "attributes") { const attributeName = mutation.attributeName ? mutation.attributeName : "none"; if (this._currentType !== EmbedType.Legacy) { this._CreateEmbed(attributeName); } else { this._OnAttributesUpdated(attributeName); } } }); } }); this._observer.observe(this, { attributes: true }); } const productID = this.hasAttribute("product-id") && !this.hasAttribute("scene-id") ? this.getAttribute("product-id") : null; if (productID) { this._currentType = EmbedType.Legacy; this._CreateLegacyEmbed(); return this._controller; } this._CreateEmbed("none"); return this._controller; } /** * Locks the observer so attribute changes do not trigger anything */ lockObserver() { this._observerState = ObserverState.Locked; } /** * Unlocks the observer so attribute changes will start to re-trigger properly */ unlockObserver() { this._observerState = ObserverState.Unlocked; } /** * Destroys the active instance of this embed and resets internal state to default */ destroy() { if (this._controller) { this._controller.removeRenderer(); this._controller = null; } this._currentType = EmbedType.None; } /** * this is only used for backwards-compatible legacy embed types typically * embedding products with variations (without a scene-id) */ _CreateLegacyEmbed() { // server cannot be changed once its set - defaults to production const server = this.hasAttribute("server") ? this.getAttribute("server") : "production"; if (util_1.Util.isValidServerLocation(server)) { plattar_api_1.Server.create(plattar_api_1.Server.match(server || "production")); this._controller = new product_controller_1.ProductController(this); const init = this.hasAttribute("init") ? this.getAttribute("init") : null; switch (init) { case "viewer": this.startViewer(); break; case "qrcode": this.startQRCode(); break; } } else { console.warn("PlattarEmbed.CreateLegacy - cannot create as server attribute " + server + " is invalid, embed status remains unchanged"); } } /** * creates the embed * this can also be called when attributes/state changes so embeds can be re-loaded */ _CreateEmbed(attributeName) { // check if controller needs to be destroyed due to server change const serverAttribute = this.hasAttribute("server") ? this.getAttribute("server") : "production"; if (this._currentServer !== serverAttribute) { this._currentServer = serverAttribute || "production"; // reset the controller if any if (this._controller) { this._controller.removeRenderer(); this._controller = null; } } if (!util_1.Util.isValidServerLocation(this._currentServer)) { console.warn("PlattarEmbed.Create - cannot create as server attribute " + this._currentServer + " is invalid, embed status remains unchanged"); return; } plattar_api_1.Server.create(plattar_api_1.Server.match(this._currentServer || "production")); const embedType = this.hasAttribute("embed-type") ? this.getAttribute("embed-type") : "configurator"; const currentEmbed = this._currentType; if (embedType) { switch (embedType.toLowerCase()) { case "vto": this._currentType = EmbedType.VTO; break; case "webxr": this._currentType = EmbedType.WebXR; break; case "gallery": this._currentType = EmbedType.Gallery; break; case "launcher": this._currentType = EmbedType.Launcher; break; case "viewer": case "configurator": default: this._currentType = EmbedType.Configurator; } } // check if the controller needs to be re-created if ((currentEmbed !== this._currentType) && this._controller) { this._controller.removeRenderer(); this._controller = null; } const sceneID = this.hasAttribute("scene-id") ? this.getAttribute("scene-id") : null; // if the provided SceneID doesn't match, we need to remove the controller if ((sceneID !== this._currentSceneID) && this._controller) { this._controller.removeRenderer(); this._controller = null; } this._currentSceneID = sceneID; // scene-id is the absolute minimum in order to initialise the embeds if (!this._currentSceneID) { return; } // if the controller was removed due to state-change, we need to re-initialise it if (!this._controller) { switch (this._currentType) { case EmbedType.Configurator: this._controller = new configurator_controller_1.ConfiguratorController(this); break; case EmbedType.WebXR: this._controller = new webxr_controller_1.WebXRController(this); break; case EmbedType.Gallery: this._controller = new gallery_controller_1.GalleryController(this); break; case EmbedType.Launcher: this._controller = new launcher_controller_1.LauncherController(this); break; case EmbedType.VTO: this._controller = new vto_controller_1.VTOController(this); break; } if (this._controller) { const init = this.hasAttribute("init") ? this.getAttribute("init") : null; switch (init) { case "viewer": this.startViewer(); break; case "qrcode": this.startQRCode(); break; } } } else { this._OnAttributesUpdated(attributeName); } } async initAR() { if (!this._controller) { throw new Error("PlattarEmbed.initAR() - cannot execute as controller has not loaded yet"); } return this._controller.initAR(); } async startAR() { if (!this._controller) { throw new Error("PlattarEmbed.startAR() - cannot execute as controller has not loaded yet"); } return this._controller.startAR(); } async startViewer() { if (!this._controller) { throw new Error("PlattarEmbed.startViewer() - cannot execute as controller has not loaded yet"); } return this._controller.startRenderer(); } async startQRCode(options = null) { if (!this._controller) { throw new Error("PlattarEmbed.startQRCode() - cannot execute as controller has not loaded yet"); } return this._controller.startQRCode(options); } /** * This will remove the currently active Renderer * * @returns - true if removed successfully, false otherwise */ removeRenderer() { if (!this._controller) { return false; } return this._controller.removeRenderer(); } /** * This is called by the observer if any of the embed attributes have changed * based on the state of the embed, we update the internal structure accordingly */ _OnAttributesUpdated(attributeName) { if (this._controller) { this._controller.onAttributesUpdated(attributeName); } } addEventListener(type, listener, options) { // add to the element event listener super.addEventListener(type, listener, options); const eventType = 'arclick'; if (type === eventType) { // automatically enable `show-ar-banner` to true if an arclick event is added this.setAttribute('show-ar-banner', 'true'); // if this is a redirect url from an AR Action - we need to fire the event listener now const url = new URL(location.href); if (url.searchParams.get('plattar_ar_action') === 'true') { setTimeout(() => { this.dispatchEvent(new Event(eventType)); }, 200); } } } } exports.default = PlattarEmbed;