UNPKG

@nota/nativescript-webview-ext

Version:

Extended WebView for NativeScript which adds 'x-local' scheme for local-files. events between WebView and native-layer, javascript execution, injecting CSS and JS-files.

678 lines 98.7 kB
"use strict"; function __export(m) { for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; } Object.defineProperty(exports, "__esModule", { value: true }); var fs = require("tns-core-modules/file-system"); var platform = require("tns-core-modules/platform"); var view_1 = require("tns-core-modules/ui/core/view"); var nativescript_webview_bridge_loader_1 = require("./nativescript-webview-bridge-loader"); __export(require("tns-core-modules/ui//core/view")); var isAndroid = platform.isAndroid, isIOS = platform.isIOS; exports.androidSDK = isAndroid && Number(platform.device.sdkVersion); exports.useWKWebView = isIOS && typeof CustomUrlSchemeHandler !== "undefined"; exports.autoInjectJSBridgeProperty = new view_1.Property({ name: "autoInjectJSBridge", defaultValue: true }); exports.builtInZoomControlsProperty = new view_1.Property({ name: "builtInZoomControls", defaultValue: false }); exports.cacheModeProperty = new view_1.Property({ name: "cacheMode", defaultValue: "default", }); exports.databaseStorageProperty = new view_1.Property({ name: "databaseStorage", defaultValue: false, }); exports.domStorageProperty = new view_1.Property({ name: "domStorage", defaultValue: false, }); exports.debugModeProperty = new view_1.Property({ name: "debugMode", defaultValue: false, }); exports.displayZoomControlsProperty = new view_1.Property({ name: "displayZoomControls", defaultValue: false }); exports.supportZoomProperty = new view_1.Property({ name: "supportZoom", defaultValue: false, }); exports.srcProperty = new view_1.Property({ name: "src", }); exports.scrollBounceProperty = new view_1.Property({ name: "scrollBounce", defaultValue: true, }); var EventNames; (function (EventNames) { EventNames["LoadFinished"] = "loadFinished"; EventNames["LoadStarted"] = "loadStarted"; EventNames["ShouldOverrideUrlLoading"] = "shouldOverideUrlLoading"; })(EventNames = exports.EventNames || (exports.EventNames = {})); var UnsupportSDKError = (function (_super) { __extends(UnsupportSDKError, _super); function UnsupportSDKError(minSdk) { var _this = _super.call(this, "Android API < " + minSdk + " not supported") || this; Object.setPrototypeOf(_this, UnsupportSDKError.prototype); return _this; } return UnsupportSDKError; }(Error)); exports.UnsupportSDKError = UnsupportSDKError; var WebViewExtBase = (function (_super) { __extends(WebViewExtBase, _super); function WebViewExtBase() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.autoInjectJSBridge = true; _this.autoInjectScriptFiles = []; _this.autoInjectStyleSheetFiles = []; _this.autoInjectJavaScriptBlocks = []; _this.tempSuspendSrcLoading = false; return _this; } WebViewExtBase_1 = WebViewExtBase; Object.defineProperty(WebViewExtBase.prototype, "interceptScheme", { get: function () { return "x-local"; }, enumerable: true, configurable: true }); Object.defineProperty(WebViewExtBase, "loadStartedEvent", { get: function () { return EventNames.LoadStarted; }, enumerable: true, configurable: true }); Object.defineProperty(WebViewExtBase, "loadFinishedEvent", { get: function () { return EventNames.LoadFinished; }, enumerable: true, configurable: true }); Object.defineProperty(WebViewExtBase, "shouldOverrideUrlLoadingEvent", { get: function () { return EventNames.ShouldOverrideUrlLoading; }, enumerable: true, configurable: true }); WebViewExtBase.prototype._onLoadFinished = function (url, error) { return __awaiter(this, void 0, void 0, function () { var args, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!error) { try { this.tempSuspendSrcLoading = true; this.src = url; this.tempSuspendSrcLoading = false; } finally { this.tempSuspendSrcLoading = false; } } args = { error: error, eventName: WebViewExtBase_1.loadFinishedEvent, navigationType: undefined, object: this, url: url, }; if (error) { this.notify(args); return [2, Promise.reject(args)]; } this.writeTrace("WebViewExt._onLoadFinished(\"" + url + "\", " + (error || void 0) + ") - > Injecting webview-bridge JS code"); if (!this.autoInjectJSBridge) { return [2, Promise.resolve(args)]; } _a.label = 1; case 1: _a.trys.push([1, 6, , 7]); return [4, this.injectWebViewBridge()]; case 2: _a.sent(); return [4, this.loadJavaScriptFiles(this.autoInjectScriptFiles)]; case 3: _a.sent(); return [4, this.loadStyleSheetFiles(this.autoInjectStyleSheetFiles)]; case 4: _a.sent(); return [4, this.executePromises(this.autoInjectJavaScriptBlocks.map(function (data) { return data.scriptCode; }), -1)]; case 5: _a.sent(); return [3, 7]; case 6: error_1 = _a.sent(); args.error = error_1; return [3, 7]; case 7: this.notify(args); return [2, args]; } }); }); }; WebViewExtBase.prototype._onLoadStarted = function (url, navigationType) { var args = { eventName: WebViewExtBase_1.loadStartedEvent, navigationType: navigationType, object: this, url: url, }; this.notify(args); }; WebViewExtBase.prototype._onShouldOverrideUrlLoading = function (url, httpMethod, navigationType) { var args = { eventName: WebViewExtBase_1.shouldOverrideUrlLoadingEvent, httpMethod: httpMethod, navigationType: navigationType, object: this, url: url, }; this.notify(args); return args.cancel; }; WebViewExtBase.prototype._loadUrl = function (src) { throw new Error("Method not implemented."); }; WebViewExtBase.prototype._loadData = function (src) { throw new Error("Method not implemented."); }; WebViewExtBase.prototype.stopLoading = function () { throw new Error("Method not implemented."); }; Object.defineProperty(WebViewExtBase.prototype, "canGoBack", { get: function () { throw new Error("This member is abstract."); }, enumerable: true, configurable: true }); Object.defineProperty(WebViewExtBase.prototype, "canGoForward", { get: function () { throw new Error("This member is abstract."); }, enumerable: true, configurable: true }); WebViewExtBase.prototype.goBack = function () { throw new Error("Method not implemented."); }; WebViewExtBase.prototype.goForward = function () { throw new Error("Method not implemented."); }; WebViewExtBase.prototype.reload = function () { throw new Error("Method not implemented."); }; WebViewExtBase.prototype[exports.srcProperty.getDefault] = function () { return ""; }; WebViewExtBase.prototype[exports.srcProperty.setNative] = function (src) { if (!src || this.tempSuspendSrcLoading) { return; } var originSrc = src; this.stopLoading(); if (src.startsWith("~/")) { src = "file://" + fs.knownFolders.currentApp().path + "/" + src.substr(2); this.writeTrace("WebViewExt.src = \"" + originSrc + "\" startsWith ~/ resolved to \"" + src + "\""); } else if (src.startsWith("/")) { src = "file://" + src; this.writeTrace("WebViewExt.src = \"" + originSrc + "\" startsWith \"/\" resolved to " + src); } var lcSrc = src.toLowerCase(); if (lcSrc.startsWith("file:///")) { src = encodeURI(src); if (lcSrc !== src) { this.writeTrace("WebViewExt.src = \"" + originSrc + "\" escaped to \"" + src + "\""); } } if (lcSrc.startsWith(this.interceptScheme) || lcSrc.startsWith("http://") || lcSrc.startsWith("https://") || lcSrc.startsWith("file:///")) { this._loadUrl(src); this.writeTrace("WebViewExt.src = \"" + originSrc + "\" - LoadUrl(\"" + src + "\")"); } else { this._loadData(src); this.writeTrace("WebViewExt.src = \"" + originSrc + "\" - LoadData(\"" + src + "\")"); } }; WebViewExtBase.prototype[exports.debugModeProperty.getDefault] = function () { return false; }; WebViewExtBase.prototype.resolveLocalResourceFilePath = function (filepath) { if (!filepath) { this.writeTrace("WebViewExt.resolveLocalResourceFilePath() no filepath", view_1.traceMessageType.error); return; } if (filepath.startsWith("~")) { filepath = fs.path.normalize(fs.knownFolders.currentApp().path + filepath.substr(1)); } if (filepath.startsWith("file://")) { filepath = filepath.replace(/^file:\/\//, ""); } if (!fs.File.exists(filepath)) { this.writeTrace("WebViewExt.resolveLocalResourceFilePath(\"" + filepath + "\") - no such file", view_1.traceMessageType.error); return; } return filepath; }; WebViewExtBase.prototype.registerLocalResource = function (name, filepath) { throw new Error("Method not implemented."); }; WebViewExtBase.prototype.unregisterLocalResource = function (name) { throw new Error("Method not implemented."); }; WebViewExtBase.prototype.getRegisteredLocalResource = function (name) { throw new Error("Method not implemented."); }; WebViewExtBase.prototype.loadUrl = function (src) { var _this = this; if (!src) { return this._onLoadFinished(src, "empty src"); } return new Promise(function (resolve, reject) { var loadFinishedEvent = function (args) { _this.off(WebViewExtBase_1.loadFinishedEvent, loadFinishedEvent); if (args.error) { reject(args); } else { resolve(args); } }; _this.on(WebViewExtBase_1.loadFinishedEvent, loadFinishedEvent); _this.src = src; }); }; WebViewExtBase.prototype.loadJavaScriptFile = function (scriptName, filepath) { return this.loadJavaScriptFiles([ { resourceName: scriptName, filepath: filepath, }, ]); }; WebViewExtBase.prototype.loadJavaScriptFiles = function (files) { return __awaiter(this, void 0, void 0, function () { var promiseScriptCodes, _i, files_1, _a, resourceName, filepath, fixedResourceName, href, scriptCode; return __generator(this, function (_b) { switch (_b.label) { case 0: if (!files || !files.length) { return [2]; } promiseScriptCodes = []; for (_i = 0, files_1 = files; _i < files_1.length; _i++) { _a = files_1[_i], resourceName = _a.resourceName, filepath = _a.filepath; fixedResourceName = this.fixLocalResourceName(resourceName); if (filepath) { this.registerLocalResource(fixedResourceName, filepath); } href = this.interceptScheme + "://" + fixedResourceName; scriptCode = this.generateLoadJavaScriptFileScriptCode(href); promiseScriptCodes.push(scriptCode); this.writeTrace("WebViewExt.loadJavaScriptFiles() - > Loading javascript file: \"" + href + "\""); } if (promiseScriptCodes.length !== files.length) { this.writeTrace("WebViewExt.loadJavaScriptFiles() - > Num of generated scriptCodes " + promiseScriptCodes.length + " differ from num files " + files.length, view_1.traceMessageType.error); } if (!promiseScriptCodes.length) { this.writeTrace("WebViewExt.loadJavaScriptFiles() - > No files"); return [2]; } if (!promiseScriptCodes.length) { return [2]; } return [4, this.executePromises(promiseScriptCodes)]; case 1: _b.sent(); return [2]; } }); }); }; WebViewExtBase.prototype.loadStyleSheetFile = function (stylesheetName, filepath, insertBefore) { if (insertBefore === void 0) { insertBefore = true; } return this.loadStyleSheetFiles([ { resourceName: stylesheetName, filepath: filepath, insertBefore: insertBefore, }, ]); }; WebViewExtBase.prototype.loadStyleSheetFiles = function (files) { return __awaiter(this, void 0, void 0, function () { var promiseScriptCodes, _i, files_2, _a, resourceName, filepath, insertBefore, fixedResourceName, href, scriptCode; return __generator(this, function (_b) { switch (_b.label) { case 0: if (!files || !files.length) { return [2]; } promiseScriptCodes = []; for (_i = 0, files_2 = files; _i < files_2.length; _i++) { _a = files_2[_i], resourceName = _a.resourceName, filepath = _a.filepath, insertBefore = _a.insertBefore; fixedResourceName = this.fixLocalResourceName(resourceName); if (filepath) { this.registerLocalResource(fixedResourceName, filepath); } href = this.interceptScheme + "://" + fixedResourceName; scriptCode = this.generaateLoadCSSFileScriptCode(href, insertBefore); promiseScriptCodes.push(scriptCode); this.writeTrace("WebViewExt.loadStyleSheetFiles() - > Loading stylesheet file: " + href); } if (promiseScriptCodes.length !== files.length) { this.writeTrace("WebViewExt.loadStyleSheetFiles() - > Num of generated scriptCodes " + promiseScriptCodes.length + " differ from num files " + files.length, view_1.traceMessageType.error); } if (!promiseScriptCodes.length) { this.writeTrace("WebViewExt.loadStyleSheetFiles() - > No files"); return [2]; } return [4, this.executePromises(promiseScriptCodes)]; case 1: _b.sent(); return [2]; } }); }); }; WebViewExtBase.prototype.autoLoadJavaScriptFile = function (resourceName, filepath) { if (this.src) { this.loadJavaScriptFile(resourceName, filepath).catch(function () { return void 0; }); } this.autoInjectScriptFiles.push({ resourceName: resourceName, filepath: filepath }); }; WebViewExtBase.prototype.removeAutoLoadJavaScriptFile = function (resourceName) { this.autoInjectScriptFiles = this.autoInjectScriptFiles.filter(function (data) { return data.resourceName !== resourceName; }); }; WebViewExtBase.prototype.autoLoadStyleSheetFile = function (resourceName, filepath, insertBefore) { if (this.src) { this.loadStyleSheetFile(resourceName, filepath, insertBefore).catch(function () { return void 0; }); } this.autoInjectStyleSheetFiles.push({ resourceName: resourceName, filepath: filepath, insertBefore: insertBefore, }); }; WebViewExtBase.prototype.removeAutoLoadStyleSheetFile = function (resourceName) { this.autoInjectStyleSheetFiles = this.autoInjectStyleSheetFiles.filter(function (data) { return data.resourceName !== resourceName; }); }; WebViewExtBase.prototype.autoExecuteJavaScript = function (scriptCode, name) { if (this.src) { this.executePromise(scriptCode).catch(function () { return void 0; }); } this.removeAutoExecuteJavaScript(name); var fixedCodeBlock = scriptCode.trim(); this.autoInjectJavaScriptBlocks.push({ scriptCode: fixedCodeBlock, name: name, }); }; WebViewExtBase.prototype.removeAutoExecuteJavaScript = function (name) { this.autoInjectJavaScriptBlocks = this.autoInjectJavaScriptBlocks.filter(function (data) { return data.name !== name; }); }; WebViewExtBase.prototype.ensureFetchSupport = function () { return __awaiter(this, void 0, void 0, function () { var _a; return __generator(this, function (_b) { switch (_b.label) { case 0: if (WebViewExtBase_1.isFetchSupported) { return [2, Promise.resolve()]; } if (!(typeof WebViewExtBase_1.isFetchSupported === "undefined")) return [3, 2]; this.writeTrace("WebViewExtBase.ensureFetchSupport() - need to check for fetch support."); _a = WebViewExtBase_1; return [4, this.executeJavaScript("typeof fetch !== 'undefined'")]; case 1: _a.isFetchSupported = _b.sent(); _b.label = 2; case 2: if (WebViewExtBase_1.isFetchSupported) { this.writeTrace("WebViewExtBase.ensureFetchSupport() - fetch is supported - polyfill not needed."); return [2]; } this.writeTrace("WebViewExtBase.ensureFetchSupport() - fetch is not supported - polyfill needed."); return [4, this.loadFetchPolyfill()]; case 3: return [2, _b.sent()]; } }); }); }; WebViewExtBase.prototype.loadFetchPolyfill = function () { return __awaiter(this, void 0, void 0, function () { var scriptCode; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, nativescript_webview_bridge_loader_1.fetchPolyfill]; case 1: scriptCode = _a.sent(); return [4, this.executeJavaScript(scriptCode, false)]; case 2: _a.sent(); return [2]; } }); }); }; WebViewExtBase.prototype.ensurePromiseSupport = function () { return __awaiter(this, void 0, void 0, function () { var _a; return __generator(this, function (_b) { switch (_b.label) { case 0: if (exports.androidSDK >= 21 || WebViewExtBase_1.isPromiseSupported) { return [2]; } if (!(typeof WebViewExtBase_1.isPromiseSupported === "undefined")) return [3, 2]; this.writeTrace("WebViewExtBase.ensurePromiseSupport() - need to check for promise support."); _a = WebViewExtBase_1; return [4, this.executeJavaScript("typeof Promise !== 'undefined'")]; case 1: _a.isPromiseSupported = _b.sent(); _b.label = 2; case 2: if (WebViewExtBase_1.isPromiseSupported) { this.writeTrace("WebViewExtBase.ensurePromiseSupport() - promise is supported - polyfill not needed."); return [2]; } this.writeTrace("WebViewExtBase.ensurePromiseSupport() - promise is not supported - polyfill needed."); return [4, this.loadPromisePolyfill()]; case 3: _b.sent(); return [2]; } }); }); }; WebViewExtBase.prototype.loadPromisePolyfill = function () { return __awaiter(this, void 0, void 0, function () { var scriptCode; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, nativescript_webview_bridge_loader_1.promisePolyfill]; case 1: scriptCode = _a.sent(); return [4, this.executeJavaScript(scriptCode, false)]; case 2: _a.sent(); return [2]; } }); }); }; WebViewExtBase.prototype.ensurePolyfills = function () { var _this = this; return this.ensurePromiseSupport().then(function () { return _this.ensureFetchSupport(); }); }; WebViewExtBase.prototype.executeJavaScript = function (scriptCode, stringifyResult) { throw new Error("Method not implemented."); }; WebViewExtBase.prototype.executePromise = function (scriptCode, timeout) { if (timeout === void 0) { timeout = 2000; } return __awaiter(this, void 0, void 0, function () { var results; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, this.executePromises([scriptCode], timeout)]; case 1: results = _a.sent(); return [2, results && results[0]]; } }); }); }; WebViewExtBase.prototype.executePromises = function (scriptCodes, timeout) { if (timeout === void 0) { timeout = 2000; } return __awaiter(this, void 0, void 0, function () { var reqId, eventName, scriptHeader, scriptBody, _i, scriptCodes_1, scriptCode_1, scriptFooter, scriptCode, promiseScriptCode; var _this = this; return __generator(this, function (_a) { if (scriptCodes.length === 0) { return [2]; } reqId = "" + Math.round(Math.random() * 1000); eventName = "tmp-promise-event-" + reqId; scriptHeader = "\n var promises = [];\n var p = Promise.resolve();\n ".trim(); scriptBody = []; for (_i = 0, scriptCodes_1 = scriptCodes; _i < scriptCodes_1.length; _i++) { scriptCode_1 = scriptCodes_1[_i]; scriptBody.push(("\n p = p.then(function() {\n return " + scriptCode_1.trim() + ";\n });\n\n promises.push(p);\n ").trim()); } scriptFooter = "\n return Promise.all(promises);\n ".trim(); scriptCode = ("(function() {\n " + scriptHeader + "\n " + scriptBody.join(";") + "\n " + scriptFooter + "\n })()").trim(); promiseScriptCode = ("\n (function() {\n var eventName = " + JSON.stringify(eventName) + ";\n try {\n var promise = (function() {return " + scriptCode + "})();\n window.nsWebViewBridge.executePromise(promise, eventName);\n } catch (err) {\n window.nsWebViewBridge.emitError(err, eventName);\n }\n })();\n ").trim(); return [2, new Promise(function (resolve, reject) { var timer; var tmpPromiseEvent = function (args) { clearTimeout(timer); _this.off(eventName); var _a = args.data || {}, data = _a.data, err = _a.err; if (typeof err === "undefined") { resolve(data); return; } if (err && typeof err === "object") { var error = new Error(err.message || err); if (err.stack) { error.webStack = err.stack; } reject(error); return; } reject(new Error(err)); }; _this.on(eventName, tmpPromiseEvent); _this.executeJavaScript(promiseScriptCode, false); if (timeout > 0) { timer = setTimeout(function () { reject(new Error("Timed out after: " + timeout)); _this.off(eventName); }, timeout); } })]; }); }); }; WebViewExtBase.prototype.generateLoadJavaScriptFileScriptCode = function (scriptHref) { return "window.nsWebViewBridge.injectJavaScriptFile(" + JSON.stringify(scriptHref) + ");"; }; WebViewExtBase.prototype.generaateLoadCSSFileScriptCode = function (stylesheetHref, insertBefore) { if (insertBefore === void 0) { insertBefore = false; } return "window.nsWebViewBridge.injectStyleSheetFile(" + JSON.stringify(stylesheetHref) + ", " + !!insertBefore + ");"; }; WebViewExtBase.prototype.injectWebViewBridge = function () { return __awaiter(this, void 0, void 0, function () { var scriptCode; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, nativescript_webview_bridge_loader_1.webViewBridge]; case 1: scriptCode = _a.sent(); return [4, this.executeJavaScript(scriptCode, false)]; case 2: _a.sent(); return [4, this.ensurePolyfills()]; case 3: _a.sent(); return [2]; } }); }); }; WebViewExtBase.prototype.parseWebViewJavascriptResult = function (result) { if (result === undefined) { return; } if (typeof result !== "string") { return result; } try { return JSON.parse(result); } catch (err) { return result; } }; WebViewExtBase.prototype.writeTrace = function (message, type) { if (type === void 0) { type = view_1.traceMessageType.info; } if (view_1.traceEnabled()) { view_1.traceWrite(message, "NOTA", type); } }; WebViewExtBase.prototype.emitToWebView = function (eventName, data) { var scriptCode = "\n window.nsWebViewBridge && nsWebViewBridge.onNativeEvent(" + JSON.stringify(eventName) + ", " + JSON.stringify(data) + ");\n "; this.executeJavaScript(scriptCode, false); }; WebViewExtBase.prototype.onWebViewEvent = function (eventName, data) { this.notify({ eventName: eventName, object: this, data: data, }); }; WebViewExtBase.prototype.getTitle = function () { throw new Error("Method not implemented."); }; WebViewExtBase.prototype.onUIWebViewEvent = function (url) { throw new Error("WebViewExt.onUIWebViewEvent() only available on iOS"); }; WebViewExtBase.prototype.zoomIn = function () { throw new Error("Method not implemented."); }; WebViewExtBase.prototype.zoomOut = function () { throw new Error("Method not implemented."); }; WebViewExtBase.prototype.zoomBy = function (zoomFactor) { throw new Error("Method not implemented."); }; WebViewExtBase.prototype.fixLocalResourceName = function (resourceName) { if (resourceName.startsWith(this.interceptScheme)) { return resourceName.substr(this.interceptScheme.length + 3); } return resourceName; }; var WebViewExtBase_1; WebViewExtBase = WebViewExtBase_1 = __decorate([ view_1.CSSType("WebView") ], WebViewExtBase); return WebViewExtBase; }(view_1.ContainerView)); exports.WebViewExtBase = WebViewExtBase; exports.autoInjectJSBridgeProperty.register(WebViewExtBase); exports.builtInZoomControlsProperty.register(WebViewExtBase); exports.cacheModeProperty.register(WebViewExtBase); exports.databaseStorageProperty.register(WebViewExtBase); exports.debugModeProperty.register(WebViewExtBase); exports.displayZoomControlsProperty.register(WebViewExtBase); exports.domStorageProperty.register(WebViewExtBase); exports.srcProperty.register(WebViewExtBase); exports.supportZoomProperty.register(WebViewExtBase); exports.scrollBounceProperty.register(WebViewExtBase); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2Vidmlldy1leHQtY29tbW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsid2Vidmlldy1leHQtY29tbW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsaURBQW1EO0FBQ25ELG9EQUFzRDtBQUN0RCxzREFBd0k7QUFDeEksMkZBQXFHO0FBRXJHLG9EQUErQztBQUl2QyxJQUFBLDhCQUFTLEVBQUUsc0JBQUssQ0FBYztBQUV6QixRQUFBLFVBQVUsR0FBRyxTQUFTLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7QUFDN0QsUUFBQSxZQUFZLEdBQUcsS0FBSyxJQUFJLE9BQU8sc0JBQXNCLEtBQUssV0FBVyxDQUFDO0FBRXRFLFFBQUEsMEJBQTBCLEdBQUcsSUFBSSxlQUFRLENBQTBCLEVBQUUsSUFBSSxFQUFFLG9CQUFvQixFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQ3ZILFFBQUEsMkJBQTJCLEdBQUcsSUFBSSxlQUFRLENBQTBCLEVBQUUsSUFBSSxFQUFFLHFCQUFxQixFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0FBQzFILFFBQUEsaUJBQWlCLEdBQUcsSUFBSSxlQUFRLENBQXlCO0lBQ2xFLElBQUksRUFBRSxXQUFXO0lBQ2pCLFlBQVksRUFBRSxTQUFTO0NBQzFCLENBQUMsQ0FBQztBQUNVLFFBQUEsdUJBQXVCLEdBQUcsSUFBSSxlQUFRLENBQTBCO0lBQ3pFLElBQUksRUFBRSxpQkFBaUI7SUFDdkIsWUFBWSxFQUFFLEtBQUs7Q0FDdEIsQ0FBQyxDQUFDO0FBQ1UsUUFBQSxrQkFBa0IsR0FBRyxJQUFJLGVBQVEsQ0FBMEI7SUFDcEUsSUFBSSxFQUFFLFlBQVk7SUFDbEIsWUFBWSxFQUFFLEtBQUs7Q0FDdEIsQ0FBQyxDQUFDO0FBQ1UsUUFBQSxpQkFBaUIsR0FBRyxJQUFJLGVBQVEsQ0FBMEI7SUFDbkUsSUFBSSxFQUFFLFdBQVc7SUFD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