UNPKG

@gistproduct/web

Version:

Build beautiful in-app flows with no code and deliver them instantly to your app.

263 lines (240 loc) 8.61 kB
import Gist from '../gist'; import { log } from "../utilities/log"; import { logMessageView, logUserMessageView } from "../services/log-service"; import * as AnalyticsManager from "./analytics-manager"; import { v4 as uuidv4 } from 'uuid'; import { settings } from "../services/settings"; import { loadOverlayComponent, showOverlayComponent, hideOverlayComponent, removeOverlayComponent, loadEmbedComponent, showEmbedComponent, hideEmbedComponent, resizeComponent, elementHasHeight, isElementLoaded } from "./message-component-manager"; import { resolveMessageProperies } from "./gist-properties-manager"; import { positions, addPageElement } from "./page-component-manager"; import { checkMessageQueue } from "./queue-manager"; export function showMessage(message) { if (Gist.isDocumentVisible) { if (Gist.overlayInstanceId) { log(`Message ${Gist.overlayInstanceId} already showing.`); return null; } else { var properties = resolveMessageProperies(message) message.instanceId = uuidv4(); message.overlay = true; message.firstLoad = true; message.shouldResizeHeight = true; message.shouldScale = properties.shouldScale Gist.overlayInstanceId = message.instanceId; Gist.currentMessages.push(message); return loadMessageComponent(message); } } else { log("Document hidden, not showing message now."); return null; } } export function embedMessage(message, elementId) { if (Gist.isDocumentVisible) { message.instanceId = uuidv4(); message.overlay = false; message.firstLoad = true; message.shouldScale = false; message.elementId = elementId; message.shouldResizeHeight = !elementHasHeight(elementId); Gist.currentMessages.push(message); return loadMessageComponent(message, elementId); } else { log("Document hidden, not showing message now."); return null; } } export function hideMessage(instanceId) { var message = fetchMessageByInstanceId(instanceId); if (message) { AnalyticsManager.logEvent(AnalyticsManager.GIST_DISMISSED, message); Gist.messageDismissed(message); if (message.overlay) { resetOverlayState(true, message); } else { resetEmbedState(message); } } else { log(`Message with instance id: ${instanceId} not found`); } } function resetEmbedState(message) { removeMessageByInstanceId(message.instanceId); hideEmbedComponent(message.elementId); } function resetOverlayState(hideFirst, message) { removeMessageByInstanceId(message.instanceId); Gist.overlayInstanceId = null; if (hideFirst) { hideOverlayComponent(); } else { removeOverlayComponent(); } if (Gist.currentMessages.length == 0) { window.removeEventListener('message', handleGistEvents); window.removeEventListener('touchstart', {}); } } function loadMessageComponent(message, elementId = null) { if (elementId && isElementLoaded(elementId)) { log(`Message ${message.messageId} already showing in element ${elementId}.`); return null; } var options = { organizationId: Gist.config.organizationId, messageId: message.messageId, instanceId: message.instanceId, endpoint: settings.GIST_API_ENDPOINT[Gist.config.env], livePreview: false, properties: message.properties } var url = `${settings.GIST_VIEW_ENDPOINT[Gist.config.env]}/index.html?options=${encodeUnicode(JSON.stringify(options))}` window.addEventListener('message', handleGistEvents); window.addEventListener('touchstart', {}); if (elementId) { if (positions.includes(elementId)) { addPageElement(elementId); } loadEmbedComponent(elementId, url); } else { loadOverlayComponent(url, message.instanceId); } return message; } function encodeUnicode(str) { var base64Unicode = btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function toSolidBytes(match, p1) { return String.fromCharCode('0x' + p1); })); return encodeURIComponent(base64Unicode); } async function reportMessageView(message) { Gist.messageShown(message); log(`Message shown, logging view for: ${message.messageId}`); var response = {}; if (message.queueId != null) { response = await logUserMessageView(message.queueId); } else { response = await logMessageView(message.messageId); } if (response.status === 200) { log(`Message view logged`); } else { log(`Problem logging message: ${response.status}`); } } function fetchMessageByInstanceId(instanceId) { return Gist.currentMessages.find(message => message.instanceId === instanceId); } function removeMessageByInstanceId(instanceId) { Gist.currentMessages = Gist.currentMessages.filter(message => message.instanceId !== instanceId) } function updateMessageByInstanceId(instanceId, message) { removeMessageByInstanceId(instanceId); Gist.currentMessages.push(message); } function handleGistEvents(e) { if (e.data.gist) { var currentInstanceId = e.data.gist.instanceId; var currentMessage = fetchMessageByInstanceId(currentInstanceId); switch (e.data.gist.method) { case "routeLoaded": { currentMessage.currentRoute = e.data.gist.parameters.route; AnalyticsManager.logEvent(AnalyticsManager.GIST_LOADED, currentMessage); if (currentMessage.firstLoad) { if (currentMessage.overlay) { showOverlayComponent(currentMessage); } else { showEmbedComponent(currentMessage.elementId); } reportMessageView(currentMessage); currentMessage.firstLoad = false; } updateMessageByInstanceId(currentInstanceId, currentMessage); break; } case "tap": { var action = e.data.gist.parameters.action; var name = e.data.gist.parameters.name; Gist.messageAction(currentMessage, action, name); if (e.data.gist.parameters.system == true) { AnalyticsManager.logEvent(AnalyticsManager.GIST_SYSTEM_ACTION, currentMessage); hideMessage(currentInstanceId); break; } var shouldLogEvent = true; try { var url = new URL(action); if (url && url.protocol === "gist:") { var gistAction = url.href.replace("gist://", "").split('?')[0]; switch (gistAction) { case "close": hideMessage(currentInstanceId); shouldLogEvent = false; checkMessageQueue(); break; case "showMessage": var messageId = url.searchParams.get('messageId'); var properties = url.searchParams.get('properties'); if (messageId) { if (properties) { properties = JSON.parse(atob(properties)); } Gist.showMessage({ messageId: messageId, properties: properties }); } break; case "loadPage": var url = url.searchParams.get('url'); if (url) { if (url.startsWith("https://") || url.startsWith("http://") || url.startsWith("/")) { window.location.href = url; } else { window.location.href = window.location + url; } } break; } } } catch (_) {} if (shouldLogEvent) { AnalyticsManager.logEvent(AnalyticsManager.GIST_ACTION, currentMessage); } break; } case "routeChanged": { currentMessage.currentRoute = e.data.gist.parameters.route; updateMessageByInstanceId(currentInstanceId, currentMessage); log(`Route changed to: ${currentMessage.currentRoute}`); break; } case "sizeChanged": { log(`Size Changed Width: ${e.data.gist.parameters.width} - Height: ${e.data.gist.parameters.height}`) if (currentMessage.elementId && currentMessage.shouldResizeHeight) { resizeComponent(currentMessage.elementId, e.data.gist.parameters, currentMessage.shouldScale); } else { resizeComponent("gist-message", e.data.gist.parameters, currentMessage.shouldScale); } break; } case "error": case "routeError": { Gist.messageError(currentMessage); if (Gist.overlayInstanceId) { resetOverlayState(false, currentMessage); } else { resetEmbedState(currentMessage); } break; } } } }