import { onProjectVersionsPreviewGeneratedSubscription } from "/_nuxt/lib/projects/graphql/subscriptions.ts"; import { useSubscription } from "/_nuxt/node_modules/@vue/apollo-composable/dist/index.mjs?v=e4f18c29"; import { useLock } from "/_nuxt/lib/common/composables/singleton.ts"; import PreviewPlaceholder from "/_nuxt/assets/images/preview_placeholder.png?import"; import { isValidBase64Image } from "/_nuxt/@fs/D:/speckle-server/packages/shared/dist/esm/images/base64.js"; import { nanoid } from "/_nuxt/node_modules/.cache/vite/client/deps/nanoid.js?v=e4f18c29"; import { useState } from "/_nuxt/node_modules/nuxt/dist/app/composables/state.js?v=e4f18c29"; import { useNuxtApp } from "/_nuxt/node_modules/nuxt/dist/app/nuxt.js?v=e4f18c29"; import { unref, ref, computed, watch } from "/_nuxt/node_modules/vue/dist/vue.runtime.esm-bundler.js?v=e4f18c29"; import { useLogger } from "/_nuxt/composables/logging.ts"; import { useHead } from "/_nuxt/node_modules/nuxt/dist/app/composables/head.js?v=e4f18c29"; const PREVIEWS_EAGER_LOAD_COUNT = 20; const previewUrlProjectIdRegexp = /\/preview\/([\w\d]+)\//i; const previewUrlCommitIdRegexp = /\/commits\/([\w\d]+)/i; const previewUrlObjectIdRegexp = /\/commits\/([\w\d]+)/i; class AngleNotFoundError extends Error { } const usePreviewsState = () => useState("preview_images_load_state", () => ({ /** * How many previews have already been eager loaded */ eagerLoadedKeys: /* @__PURE__ */ new Set() })); export function usePreviewImageBlob(previewUrl, options) { const { $isAppHydrated } = useNuxtApp(); const state = usePreviewsState(); const eagerLoadKey = unref(previewUrl) || nanoid(); const eagerLoad = options?.eagerLoad && !$isAppHydrated.value && (state.value.eagerLoadedKeys.size < PREVIEWS_EAGER_LOAD_COUNT || state.value.eagerLoadedKeys.has(eagerLoadKey)); if (eagerLoad) { state.value.eagerLoadedKeys.add(eagerLoadKey); } const { enabled = ref(true) } = options || {}; const logger = useLogger(); const lazyLoad = !eagerLoad; const url = ref(PreviewPlaceholder); const hasDoneFirstLoad = ref(false); const panoramaUrl = ref(null); const isLoadingPanorama = ref(false); const shouldLoadPanorama = ref(false); const basePanoramaUrl = computed(() => unref(previewUrl) + "/all"); const isEnabled = computed(() => { if (false) return true; return unref(enabled); }); const cacheBust = ref(0); const isPanoramaPlaceholder = ref(false); const ret = { previewUrl: computed(() => url.value), panoramaPreviewUrl: computed(() => panoramaUrl.value), isLoadingPanorama, shouldLoadPanorama, hasDoneFirstLoad: computed(() => hasDoneFirstLoad.value), isPanoramaPlaceholder: computed(() => isPanoramaPlaceholder.value), wasEagerLoaded: eagerLoad }; const previewUrlPath = computed(() => { const basePreviewUrl = unref(previewUrl); if (!basePreviewUrl) return null; const urlObj = new URL(basePreviewUrl); return urlObj.pathname; }); const projectId = computed(() => { const path = previewUrlPath.value; if (!path) return null; const [, val] = previewUrlProjectIdRegexp.exec(path) || [null, null]; return val; }); const versionId = computed(() => { const path = previewUrlPath.value; if (!path) return null; const [, val] = previewUrlCommitIdRegexp.exec(path) || [null, null]; return val; }); const objectId = computed(() => { const path = previewUrlPath.value; if (!path) return null; const [, val] = previewUrlObjectIdRegexp.exec(path) || [null, null]; return val; }); const isPreviewServiceUrl = computed(() => !!projectId.value); const { hasLock } = useLock( computed(() => `useProjectModelUpdateTracking-${unref(previewUrl) || ""}`) ); const { onResult: onProjectPreviewGenerated } = useSubscription( onProjectVersionsPreviewGeneratedSubscription, () => ({ id: projectId.value || "" }), () => ({ enabled: !!projectId.value && hasLock.value && isEnabled.value && !false, errorPolicy: "all" }) ); onProjectPreviewGenerated((res) => { const message = res.data?.projectVersionsPreviewGenerated; if (!message) return; let regenerate = false; if (objectId.value && objectId.value === message.objectId) { regenerate = true; } else if (versionId.value && versionId.value === message.versionId) { regenerate = true; } if (regenerate) { void regeneratePreviews(); } }); async function processBasePreviewUrl() { if (!isEnabled.value) return; const basePreviewUrl = unref(previewUrl); try { if (!basePreviewUrl) { url.value = PreviewPlaceholder; hasDoneFirstLoad.value = true; return; } if (isValidBase64Image(basePreviewUrl)) { url.value = basePreviewUrl; hasDoneFirstLoad.value = true; return; } const blobUrlConfig = new URL(basePreviewUrl); blobUrlConfig.searchParams.set("v", cacheBust.value.toString()); const blobUrl = blobUrlConfig.toString(); if (true && lazyLoad) { const img = new Image(); img.src = blobUrl; await new Promise((resolve, reject) => { img.onload = resolve; img.onerror = reject; }); } url.value = blobUrl; } catch (e) { logger.error("Preview image load error", e); url.value = PreviewPlaceholder; } finally { hasDoneFirstLoad.value = true; } } async function processPanoramaPreviewUrl() { if (!isEnabled.value || false) return; const basePreviewUrl = unref(previewUrl); try { isLoadingPanorama.value = true; if (!basePreviewUrl) { url.value = PreviewPlaceholder; return; } if (isValidBase64Image(basePreviewUrl)) { panoramaUrl.value = null; return; } const blobUrlConfig = new URL(basePanoramaUrl.value); blobUrlConfig.searchParams.set("v", cacheBust.value.toString()); const blobUrl = blobUrlConfig.toString(); if (true) { const img = new Image(); img.src = blobUrl; await new Promise((resolve, reject) => { img.onload = resolve; img.onerror = reject; }); isPanoramaPlaceholder.value = img.naturalWidth <= 700; } panoramaUrl.value = blobUrl; } catch (e) { if (!(e instanceof AngleNotFoundError)) { logger.error("Panorama preview image load error:", e); } panoramaUrl.value = null; } finally { isLoadingPanorama.value = false; } } const regeneratePreviews = async () => { cacheBust.value++; await Promise.all([ processBasePreviewUrl(), ...shouldLoadPanorama.value ? [processPanoramaPreviewUrl()] : [] ]); }; if (true) { watch(shouldLoadPanorama, (newVal) => { if (newVal) processPanoramaPreviewUrl(); }); watch( () => unref(previewUrl), () => { void regeneratePreviews(); } ); watch( () => isEnabled.value, (newVal) => { if (!newVal) return; void regeneratePreviews(); } ); } else { useHead({ link: computed(() => [ ...url.value?.length && isPreviewServiceUrl.value ? [{ rel: "preload", as: "image", href: url.value }] : [] ]) }); } const init = () => { if (!eagerLoad && false) { return; } void regeneratePreviews(); }; init(); return ret; } export function useCommentScreenshotImage(screenshotData) { const backgroundImage = computed(() => { const screenshot = unref(screenshotData) || "data:null"; return `url("${screenshot}")`; }); return { backgroundImage, screenshot: unref(screenshotData) }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJtYXBwaW5ncyI6IkFBRUEsU0FBUyxxREFBcUQ7QUFDOUQsU0FBUyx1QkFBdUI7QUFDaEMsU0FBUyxlQUFlO0FBQ3hCLE9BQU8sd0JBQXdCO0FBQy9CLFNBQVMsMEJBQTBCO0FBQ25DLFNBQVMsY0FBYzs7Ozs7OztBQWF2QixNQUFNLDRCQUE0QjtBQUVsQyxNQUFNLDRCQUE0QjtBQUNsQyxNQUFNLDJCQUEyQjtBQUNqQyxNQUFNLDJCQUEyQjtBQUVqQyxNQUFNLDJCQUEyQixNQUFNO0FBQUM7QUFFeEMsTUFBTSxtQkFBbUIsTUFDdkIsU0FBUyw2QkFBNkIsT0FBTztBQUFBO0FBQUE7QUFBQTtBQUFBLEVBSTNDLGlCQUFpQixvQkFBSSxJQUFZO0FBQ25DLEVBQUU7QUFRRyxnQkFBUyxvQkFDZCxZQUNBLFNBYUE7QUFFQSxRQUFNLEVBQUUsZUFBZSxJQUFJLFdBQVc7QUFDdEMsUUFBTSxRQUFRLGlCQUFpQjtBQUMvQixRQUFNLGVBQWUsTUFBTSxVQUFVLEtBQUssT0FBTztBQUNqRCxRQUFNLFlBQ0osU0FBUyxhQUNULENBQUMsZUFBZSxVQUNmLE1BQU0sTUFBTSxnQkFBZ0IsT0FBTyw2QkFDbEMsTUFBTSxNQUFNLGdCQUFnQixJQUFJLFlBQVk7QUFFaEQsTUFBSSxXQUFXO0FBQ2IsVUFBTSxNQUFNLGdCQUFnQixJQUFJLFlBQVk7QUFBQSxFQUM5QztBQUdBLFFBQU0sRUFBRSxVQUFVLElBQUksSUFBSSxFQUFFLElBQUksV0FBVyxDQUFDO0FBQzVDLFFBQU0sU0FBUyxVQUFVO0FBQ3pCLFFBQU0sV0FBVyxDQUFDO0FBRWxCLFFBQU0sTUFBTSxJQUFzQixrQkFBa0I7QUFDcEQsUUFBTSxtQkFBbUIsSUFBSSxLQUFLO0FBQ2xDLFFBQU0sY0FBYyxJQUFJLElBQXdCO0FBQ2hELFFBQU0sb0JBQW9CLElBQUksS0FBSztBQUNuQyxRQUFNLHFCQUFxQixJQUFJLEtBQUs7QUFDcEMsUUFBTSxrQkFBa0IsU0FBUyxNQUFNLE1BQU0sVUFBVSxJQUFJLE1BQU07QUFDakUsUUFBTSxZQUFZLFNBQVMsTUFBTTtBQUMvQixRQUFJLEtBQVksQ0FBUSxRQUFPO0FBQy9CLFdBQU8sTUFBTSxPQUFPO0FBQUEsRUFDdEIsQ0FBQztBQUNELFFBQU0sWUFBWSxJQUFJLENBQUM7QUFDdkIsUUFBTSx3QkFBd0IsSUFBSSxLQUFLO0FBRXZDLFFBQU0sTUFBTTtBQUFBLElBQ1YsWUFBWSxTQUFTLE1BQU0sSUFBSSxLQUFLO0FBQUEsSUFDcEMsb0JBQW9CLFNBQVMsTUFBTSxZQUFZLEtBQUs7QUFBQSxJQUNwRDtBQUFBLElBQ0E7QUFBQSxJQUNBLGtCQUFrQixTQUFTLE1BQU0saUJBQWlCLEtBQUs7QUFBQSxJQUN2RCx1QkFBdUIsU0FBUyxNQUFNLHNCQUFzQixLQUFLO0FBQUEsSUFDakUsZ0JBQWdCO0FBQUEsRUFDbEI7QUFFQSxRQUFNLGlCQUFpQixTQUFTLE1BQU07QUFDcEMsVUFBTSxpQkFBaUIsTUFBTSxVQUFVO0FBQ3ZDLFFBQUksQ0FBQyxlQUFnQixRQUFPO0FBRTVCLFVBQU0sU0FBUyxJQUFJLElBQUksY0FBYztBQUNyQyxXQUFPLE9BQU87QUFBQSxFQUNoQixDQUFDO0FBRUQsUUFBTSxZQUFZLFNBQVMsTUFBTTtBQUMvQixVQUFNLE9BQU8sZUFBZTtBQUM1QixRQUFJLENBQUMsS0FBTSxRQUFPO0FBQ2xCLFVBQU0sQ0FBQyxFQUFFLEdBQUcsSUFBSSwwQkFBMEIsS0FBSyxJQUFJLEtBQUssQ0FBQyxNQUFNLElBQUk7QUFDbkUsV0FBTztBQUFBLEVBQ1QsQ0FBQztBQUVELFFBQU0sWUFBWSxTQUFTLE1BQU07QUFDL0IsVUFBTSxPQUFPLGVBQWU7QUFDNUIsUUFBSSxDQUFDLEtBQU0sUUFBTztBQUNsQixVQUFNLENBQUMsRUFBRSxHQUFHLElBQUkseUJBQXlCLEtBQUssSUFBSSxLQUFLLENBQUMsTUFBTSxJQUFJO0FBQ2xFLFdBQU87QUFBQSxFQUNULENBQUM7QUFFRCxRQUFNLFdBQVcsU0FBUyxNQUFNO0FBQzlCLFVBQU0sT0FBTyxlQUFlO0FBQzVCLFFBQUksQ0FBQyxLQUFNLFFBQU87QUFDbEIsVUFBTSxDQUFDLEVBQUUsR0FBRyxJQUFJLHlCQUF5QixLQUFLLElBQUksS0FBSyxDQUFDLE1BQU0sSUFBSTtBQUNsRSxXQUFPO0FBQUEsRUFDVCxDQUFDO0FBRUQsUUFBTSxzQkFBc0IsU0FBUyxNQUFNLENBQUMsQ0FBQyxVQUFVLEtBQUs7QUFFNUQsUUFBTSxFQUFFLFFBQVEsSUFBSTtBQUFBLElBQ2xCLFNBQVMsTUFBTSxpQ0FBaUMsTUFBTSxVQUFVLEtBQUssRUFBRSxFQUFFO0FBQUEsRUFDM0U7QUFDQSxRQUFNLEVBQUUsVUFBVSwwQkFBMEIsSUFBSTtBQUFBLElBQzlDO0FBQUEsSUFDQSxPQUFPO0FBQUEsTUFDTCxJQUFJLFVBQVUsU0FBUztBQUFBLElBQ3pCO0FBQUEsSUFDQSxPQUFPO0FBQUEsTUFDTCxTQUNFLENBQUMsQ0FBQyxVQUFVLFNBQVMsUUFBUSxTQUFTLFVBQVUsU0FBUyxDQUFDLEtBQVk7QUFBQSxNQUN4RSxhQUFhO0FBQUEsSUFDZjtBQUFBLEVBQ0Y7QUFFQSw0QkFBMEIsQ0FBQyxRQUFRO0FBQ2pDLFVBQU0sVUFBVSxJQUFJLE1BQU07QUFDMUIsUUFBSSxDQUFDLFFBQVM7QUFFZCxRQUFJLGFBQWE7QUFDakIsUUFBSSxTQUFTLFNBQVMsU0FBUyxVQUFVLFFBQVEsVUFBVTtBQUN6RCxtQkFBYTtBQUFBLElBQ2YsV0FBVyxVQUFVLFNBQVMsVUFBVSxVQUFVLFFBQVEsV0FBVztBQUNuRSxtQkFBYTtBQUFBLElBQ2Y7QUFFQSxRQUFJLFlBQVk7QUFDZCxXQUFLLG1CQUFtQjtBQUFBLElBQzFCO0FBQUEsRUFDRixDQUFDO0FBRUQsaUJBQWUsd0JBQXdCO0FBQ3JDLFFBQUksQ0FBQyxVQUFVLE1BQU87QUFFdEIsVUFBTSxpQkFBaUIsTUFBTSxVQUFVO0FBQ3ZDLFFBQUk7QUFDRixVQUFJLENBQUMsZ0JBQWdCO0FBQ25CLFlBQUksUUFBUTtBQUNaLHlCQUFpQixRQUFRO0FBQ3pCO0FBQUEsTUFDRjtBQUVBLFVBQUksbUJBQW1CLGNBQWMsR0FBRztBQUV0QyxZQUFJLFFBQVE7QUFDWix5QkFBaUIsUUFBUTtBQUN6QjtBQUFBLE1BQ0Y7QUFFQSxZQUFNLGdCQUFnQixJQUFJLElBQUksY0FBYztBQUM1QyxvQkFBYyxhQUFhLElBQUksS0FBSyxVQUFVLE1BQU0sU0FBUyxDQUFDO0FBQzlELFlBQU0sVUFBVSxjQUFjLFNBQVM7QUFHdkMsVUFBSSxJQUFZLElBQVUsVUFBVTtBQUNsQyxjQUFNLE1BQU0sSUFBSSxNQUFNO0FBQ3RCLFlBQUksTUFBTTtBQUNWLGNBQU0sSUFBSSxRQUFRLENBQUMsU0FBUyxXQUFXO0FBQ3JDLGNBQUksU0FBUztBQUNiLGNBQUksVUFBVTtBQUFBLFFBQ2hCLENBQUM7QUFBQSxNQUNIO0FBRUEsVUFBSSxRQUFRO0FBQUEsSUFDZCxTQUFTLEdBQUc7QUFDVixhQUFPLE1BQU0sNEJBQTRCLENBQUM7QUFDMUMsVUFBSSxRQUFRO0FBQUEsSUFDZCxVQUFFO0FBQ0EsdUJBQWlCLFFBQVE7QUFBQSxJQUMzQjtBQUFBLEVBQ0Y7QUFFQSxpQkFBZSw0QkFBNEI7QUFDekMsUUFBSSxDQUFDLFVBQVUsU0FBUyxLQUFZLENBQVE7QUFFNUMsVUFBTSxpQkFBaUIsTUFBTSxVQUFVO0FBQ3ZDLFFBQUk7QUFDRix3QkFBa0IsUUFBUTtBQUMxQixVQUFJLENBQUMsZ0JBQWdCO0FBQ25CLFlBQUksUUFBUTtBQUNaO0FBQUEsTUFDRjtBQUVBLFVBQUksbUJBQW1CLGNBQWMsR0FBRztBQUN0QyxvQkFBWSxRQUFRO0FBQ3BCO0FBQUEsTUFDRjtBQUVBLFlBQU0sZ0JBQWdCLElBQUksSUFBSSxnQkFBZ0IsS0FBSztBQUNuRCxvQkFBYyxhQUFhLElBQUksS0FBSyxVQUFVLE1BQU0sU0FBUyxDQUFDO0FBQzlELFlBQU0sVUFBVSxjQUFjLFNBQVM7QUFHdkMsVUFBSSxJQUFZLEVBQVE7QUFDdEIsY0FBTSxNQUFNLElBQUksTUFBTTtBQUN0QixZQUFJLE1BQU07QUFDVixjQUFNLElBQUksUUFBUSxDQUFDLFNBQVMsV0FBVztBQUNyQyxjQUFJLFNBQVM7QUFDYixjQUFJLFVBQVU7QUFBQSxRQUNoQixDQUFDO0FBR0QsOEJBQXNCLFFBQVEsSUFBSSxnQkFBZ0I7QUFBQSxNQUNwRDtBQUVBLGtCQUFZLFFBQVE7QUFBQSxJQUN0QixTQUFTLEdBQUc7QUFDVixVQUFJLEVBQUUsYUFBYSxxQkFBcUI7QUFDdEMsZUFBTyxNQUFNLHNDQUFzQyxDQUFDO0FBQUEsTUFDdEQ7QUFFQSxrQkFBWSxRQUFRO0FBQUEsSUFDdEIsVUFBRTtBQUNBLHdCQUFrQixRQUFRO0FBQUEsSUFDNUI7QUFBQSxFQUNGO0FBRUEsUUFBTSxxQkFBcUIsWUFBWTtBQUNyQyxjQUFVO0FBQ1YsVUFBTSxRQUFRLElBQUk7QUFBQSxNQUNoQixzQkFBc0I7QUFBQSxNQUN0QixHQUFJLG1CQUFtQixRQUFRLENBQUMsMEJBQTBCLENBQUMsSUFBSSxDQUFDO0FBQUEsSUFDbEUsQ0FBQztBQUFBLEVBQ0g7QUFFQSxNQUFJLElBQVksRUFBUTtBQUN0QixVQUFNLG9CQUFvQixDQUFDLFdBQVc7QUFDcEMsVUFBSSxPQUFRLDJCQUEwQjtBQUFBLElBQ3hDLENBQUM7QUFFRDtBQUFBLE1BQ0UsTUFBTSxNQUFNLFVBQVU7QUFBQSxNQUN0QixNQUFNO0FBQ0osYUFBSyxtQkFBbUI7QUFBQSxNQUMxQjtBQUFBLElBQ0Y7QUFFQTtBQUFBLE1BQ0UsTUFBTSxVQUFVO0FBQUEsTUFDaEIsQ0FBQyxXQUFXO0FBQ1YsWUFBSSxDQUFDLE9BQVE7QUFFYixhQUFLLG1CQUFtQjtBQUFBLE1BQzFCO0FBQUEsSUFDRjtBQUFBLEVBQ0YsT0FBTztBQUNMLFlBQVE7QUFBQSxNQUNOLE1BQU0sU0FBUyxNQUFNO0FBQUEsUUFDbkIsR0FBSSxJQUFJLE9BQU8sVUFBVSxvQkFBb0IsUUFDekMsQ0FBQyxFQUFFLEtBQUssV0FBVyxJQUFXLFNBQVMsTUFBTSxJQUFJLE1BQU0sQ0FBQyxJQUN4RCxDQUFDO0FBQUEsTUFDUCxDQUFDO0FBQUEsSUFDSCxDQUFDO0FBQUEsRUFDSDtBQUVBLFFBQU0sT0FBTyxNQUFNO0FBQ2pCLFFBQUksQ0FBQyxhQUFhLEtBQVksRUFBUTtBQUNwQztBQUFBLElBQ0Y7QUFFQSxTQUFLLG1CQUFtQjtBQUFBLEVBQzFCO0FBQ0EsT0FBSztBQUVMLFNBQU87QUFDVDtBQUVPLGdCQUFTLDBCQUNkLGdCQUNBO0FBQ0EsUUFBTSxrQkFBa0IsU0FBUyxNQUFNO0FBQ3JDLFVBQU0sYUFBYSxNQUFNLGNBQWMsS0FBSztBQUM1QyxXQUFPLFFBQVEsVUFBVTtBQUFBLEVBQzNCLENBQUM7QUFFRCxTQUFPLEVBQUUsaUJBQWlCLFlBQVksTUFBTSxjQUFjLEVBQUU7QUFDOUQiLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VzIjpbInByZXZpZXdJbWFnZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IE1heWJlUmVmIH0gZnJvbSAnQHZ1ZXVzZS9jb3JlJ1xyXG5pbXBvcnQgdHlwZSB7IE51bGxhYmxlIH0gZnJvbSAnQHNwZWNrbGUvc2hhcmVkJ1xyXG5pbXBvcnQgeyBvblByb2plY3RWZXJzaW9uc1ByZXZpZXdHZW5lcmF0ZWRTdWJzY3JpcHRpb24gfSBmcm9tICd+fi9saWIvcHJvamVjdHMvZ3JhcGhxbC9zdWJzY3JpcHRpb25zJ1xyXG5pbXBvcnQgeyB1c2VTdWJzY3JpcHRpb24gfSBmcm9tICdAdnVlL2Fwb2xsby1jb21wb3NhYmxlJ1xyXG5pbXBvcnQgeyB1c2VMb2NrIH0gZnJvbSAnfn4vbGliL2NvbW1vbi9jb21wb3NhYmxlcy9zaW5nbGV0b24nXHJcbmltcG9ydCBQcmV2aWV3UGxhY2Vob2xkZXIgZnJvbSAnfn4vYXNzZXRzL2ltYWdlcy9wcmV2aWV3X3BsYWNlaG9sZGVyLnBuZydcclxuaW1wb3J0IHsgaXNWYWxpZEJhc2U2NEltYWdlIH0gZnJvbSAnQHNwZWNrbGUvc2hhcmVkL2ltYWdlcy9iYXNlNjQnXHJcbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gJ25hbm9pZCdcclxuXHJcbi8qKlxyXG4gKiBFYWdlciBsb2FkaW5nIHByZXZpZXdzIGVuc3VyZXMgYSBiZXR0ZXIgTENQIHNjb3JlLCBidXQgYWxzbyBoaXRzIHRoZSBwcmV2aWV3IGVuZHBvaW50IG1vcmUgb2Z0ZW4uXHJcbiAqIFNpbmNlIHdlIGRvbid0IGtub3cgdGhlIHZpZXdwb3J0IHNpemUgaW4gU1NSLCB3ZSBjYW4ganVzdCBzZXQgYSBsaW1pdCBvZiBob3cgbWFueSBwcmV2aWV3cyB0byBlYWdlclxyXG4gKiBsb2FkIGFmdGVyIHdoaWNoIHRoZXkgc2hvdWxkIHVzZSBzcGlubmVycy5cclxuICpcclxuICogVGhlb3JldGljYWxseSBldmVuIDEgZWFnZXIgbG9hZCB3aWxsIGZpeCB0aGUgTENQIGlzc3VlLCBidXQgaXQgd2lsbCBsb29rIG9kZCBpZiBhbGwgb2YgdGhlIG90aGVyIG9uZXNcclxuICogc2hvdyB1cCBhcyBzcGlubmVycy4gU28gaWRlYWxseSBqdXN0IHNldCBlbm91Z2ggZm9yIDEgcGFnZSBsb2FkLlxyXG4gKlxyXG4gKiBBc3N1bWluZyBhIGxhcmdlIHNjcmVlbiB3LyB0aGUgYnVzaWVzdCBwcmV2aWV3IHBhZ2UgKHByb2plY3QgcGFnZSB3LyBtb2RlbCBncmlkKSwgdGhlcmUgd291bGQgYmVcclxuICogYWJvdXQgMjAgcHJldmlld3NcclxuICovXHJcbmNvbnN0IFBSRVZJRVdTX0VBR0VSX0xPQURfQ09VTlQgPSAyMFxyXG5cclxuY29uc3QgcHJldmlld1VybFByb2plY3RJZFJlZ2V4cCA9IC9cXC9wcmV2aWV3XFwvKFtcXHdcXGRdKylcXC8vaVxyXG5jb25zdCBwcmV2aWV3VXJsQ29tbWl0SWRSZWdleHAgPSAvXFwvY29tbWl0c1xcLyhbXFx3XFxkXSspL2lcclxuY29uc3QgcHJldmlld1VybE9iamVjdElkUmVnZXhwID0gL1xcL2NvbW1pdHNcXC8oW1xcd1xcZF0rKS9pXHJcblxyXG5jbGFzcyBBbmdsZU5vdEZvdW5kRXJyb3IgZXh0ZW5kcyBFcnJvciB7fVxyXG5cclxuY29uc3QgdXNlUHJldmlld3NTdGF0ZSA9ICgpID0+XHJcbiAgdXNlU3RhdGUoJ3ByZXZpZXdfaW1hZ2VzX2xvYWRfc3RhdGUnLCAoKSA9PiAoe1xyXG4gICAgLyoqXHJcbiAgICAgKiBIb3cgbWFueSBwcmV2aWV3cyBoYXZlIGFscmVhZHkgYmVlbiBlYWdlciBsb2FkZWRcclxuICAgICAqL1xyXG4gICAgZWFnZXJMb2FkZWRLZXlzOiBuZXcgU2V0PHN0cmluZz4oKVxyXG4gIH0pKVxyXG5cclxuLyoqXHJcbiAqIEdldCBhdXRoZW50aWNhdGVkIHByZXZpZXcgaW1hZ2UgVVJMIGFuZCBzdWJzY3JpYmVzIHRvIHByZXZpZXcgaW1hZ2UgZ2VuZXJhdGlvbiBldmVudHMgc28gdGhhdCB0aGUgcHJldmlldyBpbWFnZSBVUkxcclxuICogaXMgdXBkYXRlZCB3aGVuZXZlciBnZW5lcmF0aW9uIGZpbmlzaGVzXHJcbiAqXHJcbiAqIFRPRE86IFJlZmFjdG9yLCB0aGUgaW50ZXJuYWxzIGhhdmUgZ290dGVuIHZlcnkgbWVzc3kgYW5kIG92ZXJseSBjb21wbGljYXRlZFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHVzZVByZXZpZXdJbWFnZUJsb2IoXHJcbiAgcHJldmlld1VybDogTWF5YmVSZWY8c3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZD4sXHJcbiAgb3B0aW9ucz86IFBhcnRpYWw8e1xyXG4gICAgLyoqXHJcbiAgICAgKiBBbGxvd3MgZGlzYWJsaW5nIHRoZSBtZWNoYW5pc20gY29uZGl0aW9uYWxseSAoZS5nLiBpZiBpbWFnZSBub3QgaW4gdmlld3BvcnQpXHJcbiAgICAgKi9cclxuICAgIGVuYWJsZWQ6IE1heWJlUmVmPGJvb2xlYW4+XHJcbiAgICAvKipcclxuICAgICAqIFdoZXRoZXIgdG8gYXZvaWQgc3Bpbm5lcnMgYW5kIGp1c3QgZW1iZWQgdGhlIGltYWdlIGltbWVkaWF0ZWx5LiBNZWFucyB3ZSB3aWxsIGxpa2VseVxyXG4gICAgICogbG9hZCBhIGxvdCBtb3JlIHRoYW4gbmVlZGVkLCBidXQgYWxzbyBnZXQgYSB3YXkgYmV0dGVyIExDUCBzY29yZSAobm8gc3Bpbm5lcnMpLlxyXG4gICAgICpcclxuICAgICAqIElmIGVuYWJsZWQsIG92ZXJyaWRlcyBgZW5hYmxlZGAgdG8gYmUgdHJ1ZS5cclxuICAgICAqL1xyXG4gICAgZWFnZXJMb2FkOiBib29sZWFuXHJcbiAgfT5cclxuKSB7XHJcbiAgLy8gQ2hlY2tpbmcgaWYgd2UncmUgYWxsb3dlZCB0byBlYWdlciBsb2FkXHJcbiAgY29uc3QgeyAkaXNBcHBIeWRyYXRlZCB9ID0gdXNlTnV4dEFwcCgpXHJcbiAgY29uc3Qgc3RhdGUgPSB1c2VQcmV2aWV3c1N0YXRlKClcclxuICBjb25zdCBlYWdlckxvYWRLZXkgPSB1bnJlZihwcmV2aWV3VXJsKSB8fCBuYW5vaWQoKVxyXG4gIGNvbnN0IGVhZ2VyTG9hZCA9XHJcbiAgICBvcHRpb25zPy5lYWdlckxvYWQgJiZcclxuICAgICEkaXNBcHBIeWRyYXRlZC52YWx1ZSAmJlxyXG4gICAgKHN0YXRlLnZhbHVlLmVhZ2VyTG9hZGVkS2V5cy5zaXplIDwgUFJFVklFV1NfRUFHRVJfTE9BRF9DT1VOVCB8fFxyXG4gICAgICBzdGF0ZS52YWx1ZS5lYWdlckxvYWRlZEtleXMuaGFzKGVhZ2VyTG9hZEtleSkpXHJcblxyXG4gIGlmIChlYWdlckxvYWQpIHtcclxuICAgIHN0YXRlLnZhbHVlLmVhZ2VyTG9hZGVkS2V5cy5hZGQoZWFnZXJMb2FkS2V5KVxyXG4gIH1cclxuXHJcbiAgLy8gQ29udGludWUgb24gd2l0aCBub3JtYWwgb3BlcmF0aW9uXHJcbiAgY29uc3QgeyBlbmFibGVkID0gcmVmKHRydWUpIH0gPSBvcHRpb25zIHx8IHt9XHJcbiAgY29uc3QgbG9nZ2VyID0gdXNlTG9nZ2VyKClcclxuICBjb25zdCBsYXp5TG9hZCA9ICFlYWdlckxvYWRcclxuXHJcbiAgY29uc3QgdXJsID0gcmVmPE51bGxhYmxlPHN0cmluZz4+KFByZXZpZXdQbGFjZWhvbGRlcilcclxuICBjb25zdCBoYXNEb25lRmlyc3RMb2FkID0gcmVmKGZhbHNlKVxyXG4gIGNvbnN0IHBhbm9yYW1hVXJsID0gcmVmKG51bGwgYXMgTnVsbGFibGU8c3RyaW5nPilcclxuICBjb25zdCBpc0xvYWRpbmdQYW5vcmFtYSA9IHJlZihmYWxzZSlcclxuICBjb25zdCBzaG91bGRMb2FkUGFub3JhbWEgPSByZWYoZmFsc2UpXHJcbiAgY29uc3QgYmFzZVBhbm9yYW1hVXJsID0gY29tcHV0ZWQoKCkgPT4gdW5yZWYocHJldmlld1VybCkgKyAnL2FsbCcpXHJcbiAgY29uc3QgaXNFbmFibGVkID0gY29tcHV0ZWQoKCkgPT4ge1xyXG4gICAgaWYgKGltcG9ydC5tZXRhLnNlcnZlcikgcmV0dXJuIHRydWUgLy8gYWx3YXlzIHRydWUgb24gc2VydmVyXHJcbiAgICByZXR1cm4gdW5yZWYoZW5hYmxlZClcclxuICB9KVxyXG4gIGNvbnN0IGNhY2hlQnVzdCA9IHJlZigwKVxyXG4gIGNvbnN0IGlzUGFub3JhbWFQbGFjZWhvbGRlciA9IHJlZihmYWxzZSlcclxuXHJcbiAgY29uc3QgcmV0ID0ge1xyXG4gICAgcHJldmlld1VybDogY29tcHV0ZWQoKCkgPT4gdXJsLnZhbHVlKSxcclxuICAgIHBhbm9yYW1hUHJldmlld1VybDogY29tcHV0ZWQoKCkgPT4gcGFub3JhbWFVcmwudmFsdWUpLFxyXG4gICAgaXNMb2FkaW5nUGFub3JhbWEsXHJcbiAgICBzaG91bGRMb2FkUGFub3JhbWEsXHJcbiAgICBoYXNEb25lRmlyc3RMb2FkOiBjb21wdXRlZCgoKSA9PiBoYXNEb25lRmlyc3RMb2FkLnZhbHVlKSxcclxuICAgIGlzUGFub3JhbWFQbGFjZWhvbGRlcjogY29tcHV0ZWQoKCkgPT4gaXNQYW5vcmFtYVBsYWNlaG9sZGVyLnZhbHVlKSxcclxuICAgIHdhc0VhZ2VyTG9hZGVkOiBlYWdlckxvYWRcclxuICB9XHJcblxyXG4gIGNvbnN0IHByZXZpZXdVcmxQYXRoID0gY29tcHV0ZWQoKCkgPT4ge1xyXG4gICAgY29uc3QgYmFzZVByZXZpZXdVcmwgPSB1bnJlZihwcmV2aWV3VXJsKVxyXG4gICAgaWYgKCFiYXNlUHJldmlld1VybCkgcmV0dXJuIG51bGxcclxuXHJcbiAgICBjb25zdCB1cmxPYmogPSBuZXcgVVJMKGJhc2VQcmV2aWV3VXJsKVxyXG4gICAgcmV0dXJuIHVybE9iai5wYXRobmFtZVxyXG4gIH0pXHJcblxyXG4gIGNvbnN0IHByb2plY3RJZCA9IGNvbXB1dGVkKCgpID0+IHtcclxuICAgIGNvbnN0IHBhdGggPSBwcmV2aWV3VXJsUGF0aC52YWx1ZVxyXG4gICAgaWYgKCFwYXRoKSByZXR1cm4gbnVsbFxyXG4gICAgY29uc3QgWywgdmFsXSA9IHByZXZpZXdVcmxQcm9qZWN0SWRSZWdleHAuZXhlYyhwYXRoKSB8fCBbbnVsbCwgbnVsbF1cclxuICAgIHJldHVybiB2YWxcclxuICB9KVxyXG5cclxuICBjb25zdCB2ZXJzaW9uSWQgPSBjb21wdXRlZCgoKSA9PiB7XHJcbiAgICBjb25zdCBwYXRoID0gcHJldmlld1VybFBhdGgudmFsdWVcclxuICAgIGlmICghcGF0aCkgcmV0dXJuIG51bGxcclxuICAgIGNvbnN0IFssIHZhbF0gPSBwcmV2aWV3VXJsQ29tbWl0SWRSZWdleHAuZXhlYyhwYXRoKSB8fCBbbnVsbCwgbnVsbF1cclxuICAgIHJldHVybiB2YWxcclxuICB9KVxyXG5cclxuICBjb25zdCBvYmplY3RJZCA9IGNvbXB1dGVkKCgpID0+IHtcclxuICAgIGNvbnN0IHBhdGggPSBwcmV2aWV3VXJsUGF0aC52YWx1ZVxyXG4gICAgaWYgKCFwYXRoKSByZXR1cm4gbnVsbFxyXG4gICAgY29uc3QgWywgdmFsXSA9IHByZXZpZXdVcmxPYmplY3RJZFJlZ2V4cC5leGVjKHBhdGgpIHx8IFtudWxsLCBudWxsXVxyXG4gICAgcmV0dXJuIHZhbFxyXG4gIH0pXHJcblxyXG4gIGNvbnN0IGlzUHJldmlld1NlcnZpY2VVcmwgPSBjb21wdXRlZCgoKSA9PiAhIXByb2plY3RJZC52YWx1ZSlcclxuXHJcbiAgY29uc3QgeyBoYXNMb2NrIH0gPSB1c2VMb2NrKFxyXG4gICAgY29tcHV0ZWQoKCkgPT4gYHVzZVByb2plY3RNb2RlbFVwZGF0ZVRyYWNraW5nLSR7dW5yZWYocHJldmlld1VybCkgfHwgJyd9YClcclxuICApXHJcbiAgY29uc3QgeyBvblJlc3VsdDogb25Qcm9qZWN0UHJldmlld0dlbmVyYXRlZCB9ID0gdXNlU3Vic2NyaXB0aW9uKFxyXG4gICAgb25Qcm9qZWN0VmVyc2lvbnNQcmV2aWV3R2VuZXJhdGVkU3Vic2NyaXB0aW9uLFxyXG4gICAgKCkgPT4gKHtcclxuICAgICAgaWQ6IHByb2plY3RJZC52YWx1ZSB8fCAnJ1xyXG4gICAgfSksXHJcbiAgICAoKSA9PiAoe1xyXG4gICAgICBlbmFibGVkOlxyXG4gICAgICAgICEhcHJvamVjdElkLnZhbHVlICYmIGhhc0xvY2sudmFsdWUgJiYgaXNFbmFibGVkLnZhbHVlICYmICFpbXBvcnQubWV0YS5zZXJ2ZXIsXHJcbiAgICAgIGVycm9yUG9saWN5OiAnYWxsJ1xyXG4gICAgfSlcclxuICApXHJcblxyXG4gIG9uUHJvamVjdFByZXZpZXdHZW5lcmF0ZWQoKHJlcykgPT4ge1xyXG4gICAgY29uc3QgbWVzc2FnZSA9IHJlcy5kYXRhPy5wcm9qZWN0VmVyc2lvbnNQcmV2aWV3R2VuZXJhdGVkXHJcbiAgICBpZiAoIW1lc3NhZ2UpIHJldHVyblxyXG5cclxuICAgIGxldCByZWdlbmVyYXRlID0gZmFsc2VcclxuICAgIGlmIChvYmplY3RJZC52YWx1ZSAmJiBvYmplY3RJZC52YWx1ZSA9PT0gbWVzc2FnZS5vYmplY3RJZCkge1xyXG4gICAgICByZWdlbmVyYXRlID0gdHJ1ZVxyXG4gICAgfSBlbHNlIGlmICh2ZXJzaW9uSWQudmFsdWUgJiYgdmVyc2lvbklkLnZhbHVlID09PSBtZXNzYWdlLnZlcnNpb25JZCkge1xyXG4gICAgICByZWdlbmVyYXRlID0gdHJ1ZVxyXG4gICAgfVxyXG5cclxuICAgIGlmIChyZWdlbmVyYXRlKSB7XHJcbiAgICAgIHZvaWQgcmVnZW5lcmF0ZVByZXZpZXdzKClcclxuICAgIH1cclxuICB9KVxyXG5cclxuICBhc3luYyBmdW5jdGlvbiBwcm9jZXNzQmFzZVByZXZpZXdVcmwoKSB7XHJcbiAgICBpZiAoIWlzRW5hYmxlZC52YWx1ZSkgcmV0dXJuXHJcblxyXG4gICAgY29uc3QgYmFzZVByZXZpZXdVcmwgPSB1bnJlZihwcmV2aWV3VXJsKVxyXG4gICAgdHJ5IHtcclxuICAgICAgaWYgKCFiYXNlUHJldmlld1VybCkge1xyXG4gICAgICAgIHVybC52YWx1ZSA9IFByZXZpZXdQbGFjZWhvbGRlclxyXG4gICAgICAgIGhhc0RvbmVGaXJzdExvYWQudmFsdWUgPSB0cnVlXHJcbiAgICAgICAgcmV0dXJuXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmIChpc1ZhbGlkQmFzZTY0SW1hZ2UoYmFzZVByZXZpZXdVcmwpKSB7XHJcbiAgICAgICAgLy8gcmV0dXJuIGFzIGlzXHJcbiAgICAgICAgdXJsLnZhbHVlID0gYmFzZVByZXZpZXdVcmxcclxuICAgICAgICBoYXNEb25lRmlyc3RMb2FkLnZhbHVlID0gdHJ1ZVxyXG4gICAgICAgIHJldHVyblxyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCBibG9iVXJsQ29uZmlnID0gbmV3IFVSTChiYXNlUHJldmlld1VybClcclxuICAgICAgYmxvYlVybENvbmZpZy5zZWFyY2hQYXJhbXMuc2V0KCd2JywgY2FjaGVCdXN0LnZhbHVlLnRvU3RyaW5nKCkpXHJcbiAgICAgIGNvbnN0IGJsb2JVcmwgPSBibG9iVXJsQ29uZmlnLnRvU3RyaW5nKClcclxuXHJcbiAgICAgIC8vIExvYWQgaW1nIGluIGJyb3dzZXIgZmlyc3QsIGJlZm9yZSB3ZSBzZXQgdGhlIHVybFxyXG4gICAgICBpZiAoaW1wb3J0Lm1ldGEuY2xpZW50ICYmIGxhenlMb2FkKSB7XHJcbiAgICAgICAgY29uc3QgaW1nID0gbmV3IEltYWdlKClcclxuICAgICAgICBpbWcuc3JjID0gYmxvYlVybFxyXG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgICAgIGltZy5vbmxvYWQgPSByZXNvbHZlXHJcbiAgICAgICAgICBpbWcub25lcnJvciA9IHJlamVjdFxyXG4gICAgICAgIH0pXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHVybC52YWx1ZSA9IGJsb2JVcmxcclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgbG9nZ2VyLmVycm9yKCdQcmV2aWV3IGltYWdlIGxvYWQgZXJyb3InLCBlKVxyXG4gICAgICB1cmwudmFsdWUgPSBQcmV2aWV3UGxhY2Vob2xkZXJcclxuICAgIH0gZmluYWxseSB7XHJcbiAgICAgIGhhc0RvbmVGaXJzdExvYWQudmFsdWUgPSB0cnVlXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBmdW5jdGlvbiBwcm9jZXNzUGFub3JhbWFQcmV2aWV3VXJsKCkge1xyXG4gICAgaWYgKCFpc0VuYWJsZWQudmFsdWUgfHwgaW1wb3J0Lm1ldGEuc2VydmVyKSByZXR1cm5cclxuXHJcbiAgICBjb25zdCBiYXNlUHJldmlld1VybCA9IHVucmVmKHByZXZpZXdVcmwpXHJcbiAgICB0cnkge1xyXG4gICAgICBpc0xvYWRpbmdQYW5vcmFtYS52YWx1ZSA9IHRydWVcclxuICAgICAgaWYgKCFiYXNlUHJldmlld1VybCkge1xyXG4gICAgICAgIHVybC52YWx1ZSA9IFByZXZpZXdQbGFjZWhvbGRlclxyXG4gICAgICAgIHJldHVyblxyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoaXNWYWxpZEJhc2U2NEltYWdlKGJhc2VQcmV2aWV3VXJsKSkge1xyXG4gICAgICAgIHBhbm9yYW1hVXJsLnZhbHVlID0gbnVsbCAvLyBwYW5vcmFtYSB1bnN1cHBvcnRlZFxyXG4gICAgICAgIHJldHVyblxyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCBibG9iVXJsQ29uZmlnID0gbmV3IFVSTChiYXNlUGFub3JhbWFVcmwudmFsdWUpXHJcbiAgICAgIGJsb2JVcmxDb25maWcuc2VhcmNoUGFyYW1zLnNldCgndicsIGNhY2hlQnVzdC52YWx1ZS50b1N0cmluZygpKVxyXG4gICAgICBjb25zdCBibG9iVXJsID0gYmxvYlVybENvbmZpZy50b1N0cmluZygpXHJcblxyXG4gICAgICAvLyBMb2FkIGltZyBpbiBicm93c2VyIGZpcnN0LCBiZWZvcmUgd2Ugc2V0IHRoZSB1cmxcclxuICAgICAgaWYgKGltcG9ydC5tZXRhLmNsaWVudCkge1xyXG4gICAgICAgIGNvbnN0IGltZyA9IG5ldyBJbWFnZSgpXHJcbiAgICAgICAgaW1nLnNyYyA9IGJsb2JVcmxcclxuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgICBpbWcub25sb2FkID0gcmVzb2x2ZVxyXG4gICAgICAgICAgaW1nLm9uZXJyb3IgPSByZWplY3RcclxuICAgICAgICB9KVxyXG5cclxuICAgICAgICAvLyBJZiB3aWR0aCBpcyA3MDBweCBvciBsZXNzLCBpdCdzIHRoZSBwbGFjZWhvbGRlciBub3QgdGhlIGFjdHVhbCBwYW5vcmFtYVxyXG4gICAgICAgIGlzUGFub3JhbWFQbGFjZWhvbGRlci52YWx1ZSA9IGltZy5uYXR1cmFsV2lkdGggPD0gNzAwXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHBhbm9yYW1hVXJsLnZhbHVlID0gYmxvYlVybFxyXG4gICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgQW5nbGVOb3RGb3VuZEVycm9yKSkge1xyXG4gICAgICAgIGxvZ2dlci5lcnJvcignUGFub3JhbWEgcHJldmlldyBpbWFnZSBsb2FkIGVycm9yOicsIGUpXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHBhbm9yYW1hVXJsLnZhbHVlID0gbnVsbFxyXG4gICAgfSBmaW5hbGx5IHtcclxuICAgICAgaXNMb2FkaW5nUGFub3JhbWEudmFsdWUgPSBmYWxzZVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgY29uc3QgcmVnZW5lcmF0ZVByZXZpZXdzID0gYXN5bmMgKCkgPT4ge1xyXG4gICAgY2FjaGVCdXN0LnZhbHVlKytcclxuICAgIGF3YWl0IFByb21pc2UuYWxsKFtcclxuICAgICAgcHJvY2Vzc0Jhc2VQcmV2aWV3VXJsKCksXHJcbiAgICAgIC4uLihzaG91bGRMb2FkUGFub3JhbWEudmFsdWUgPyBbcHJvY2Vzc1Bhbm9yYW1hUHJldmlld1VybCgpXSA6IFtdKVxyXG4gICAgXSlcclxuICB9XHJcblxyXG4gIGlmIChpbXBvcnQubWV0YS5jbGllbnQpIHtcclxuICAgIHdhdGNoKHNob3VsZExvYWRQYW5vcmFtYSwgKG5ld1ZhbCkgPT4ge1xyXG4gICAgICBpZiAobmV3VmFsKSBwcm9jZXNzUGFub3JhbWFQcmV2aWV3VXJsKClcclxuICAgIH0pXHJcblxyXG4gICAgd2F0Y2goXHJcbiAgICAgICgpID0+IHVucmVmKHByZXZpZXdVcmwpLFxyXG4gICAgICAoKSA9PiB7XHJcbiAgICAgICAgdm9pZCByZWdlbmVyYXRlUHJldmlld3MoKVxyXG4gICAgICB9XHJcbiAgICApXHJcblxyXG4gICAgd2F0Y2goXHJcbiAgICAgICgpID0+IGlzRW5hYmxlZC52YWx1ZSxcclxuICAgICAgKG5ld1ZhbCkgPT4ge1xyXG4gICAgICAgIGlmICghbmV3VmFsKSByZXR1cm5cclxuXHJcbiAgICAgICAgdm9pZCByZWdlbmVyYXRlUHJldmlld3MoKVxyXG4gICAgICB9XHJcbiAgICApXHJcbiAgfSBlbHNlIHtcclxuICAgIHVzZUhlYWQoe1xyXG4gICAgICBsaW5rOiBjb21wdXRlZCgoKSA9PiBbXHJcbiAgICAgICAgLi4uKHVybC52YWx1ZT8ubGVuZ3RoICYmIGlzUHJldmlld1NlcnZpY2VVcmwudmFsdWVcclxuICAgICAgICAgID8gW3sgcmVsOiAncHJlbG9hZCcsIGFzOiA8Y29uc3Q+J2ltYWdlJywgaHJlZjogdXJsLnZhbHVlIH1dXHJcbiAgICAgICAgICA6IFtdKVxyXG4gICAgICBdKVxyXG4gICAgfSlcclxuICB9XHJcblxyXG4gIGNvbnN0IGluaXQgPSAoKSA9PiB7XHJcbiAgICBpZiAoIWVhZ2VyTG9hZCAmJiBpbXBvcnQubWV0YS5zZXJ2ZXIpIHtcclxuICAgICAgcmV0dXJuIC8vIGRvbid0IGRvIGFueXRoaW5nIC0gc2hvdyBzcGlubmVyXHJcbiAgICB9XHJcblxyXG4gICAgdm9pZCByZWdlbmVyYXRlUHJldmlld3MoKVxyXG4gIH1cclxuICBpbml0KClcclxuXHJcbiAgcmV0dXJuIHJldFxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gdXNlQ29tbWVudFNjcmVlbnNob3RJbWFnZShcclxuICBzY3JlZW5zaG90RGF0YTogTWF5YmVSZWY8c3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZD5cclxuKSB7XHJcbiAgY29uc3QgYmFja2dyb3VuZEltYWdlID0gY29tcHV0ZWQoKCkgPT4ge1xyXG4gICAgY29uc3Qgc2NyZWVuc2hvdCA9IHVucmVmKHNjcmVlbnNob3REYXRhKSB8fCAnZGF0YTpudWxsJ1xyXG4gICAgcmV0dXJuIGB1cmwoXCIke3NjcmVlbnNob3R9XCIpYFxyXG4gIH0pXHJcblxyXG4gIHJldHVybiB7IGJhY2tncm91bmRJbWFnZSwgc2NyZWVuc2hvdDogdW5yZWYoc2NyZWVuc2hvdERhdGEpIH1cclxufVxyXG4iXSwiZmlsZSI6IkQ6L3NwZWNrbGUtc2VydmVyL3BhY2thZ2VzL2Zyb250ZW5kLTIvbGliL3Byb2plY3RzL2NvbXBvc2FibGVzL3ByZXZpZXdJbWFnZS50cyJ9