|
|
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); require("../model/AbstractModel"); require("../model/UserModel"); require("../view/AbstractView"); require("../view/UserView"); const ChatMessageViewModel_1 = require("../viewmodel/ChatMessageViewModel"); class ChatController { constructor(model, view) { this._model = model; this._view = view; } /** * eventHandler */ eventHandler(vm) { this._model.someBusinessMethod(vm); } test() { const chatMessageViewModels = []; let chatMessageViewModelMock = new ChatMessageViewModel_1.ChatMessageViewModel(); chatMessageViewModelMock.fromUser = "user1"; chatMessageViewModelMock.toUser = "user2"; chatMessageViewModelMock.message = ""; chatMessageViewModelMock.messageTime = new Date(); chatMessageViewModels.push(chatMessageViewModelMock); } } exports.ChatController = ChatController;
},{"../model/AbstractModel":4,"../model/UserModel":8,"../view/AbstractView":12,"../view/UserView":14,"../viewmodel/ChatMessageViewModel":16}],2:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); require("../model/AbstractModel"); require("../model/UserModel"); require("../view/AbstractView"); require("../view/UserView"); const ActiveUserViewModel_1 = require("../viewmodel/ActiveUserViewModel"); class UserController { constructor(model, view) { this._model = model; this._view = view; } /** * eventHandler */ eventHandler(vm) { this._model.someBusinessMethod(vm); } test() { const activeUsersMock = []; let activeUserViewModelMock = new ActiveUserViewModel_1.ActiveUserViewModel(); activeUserViewModelMock.userName = "some user"; activeUserViewModelMock.lastActive = "3 hrs ago"; activeUserViewModelMock.online = true; activeUsersMock.push(activeUserViewModelMock); activeUserViewModelMock = new ActiveUserViewModel_1.ActiveUserViewModel(); activeUserViewModelMock.lastActive = "3 hrs ago"; activeUserViewModelMock.online = true; activeUserViewModelMock.userName = "some user 2"; activeUsersMock.push(activeUserViewModelMock); this.eventHandler(activeUsersMock); } getActiveUsers() { this._model.getActiveUsers(); } } exports.UserController = UserController;
},{"../model/AbstractModel":4,"../model/UserModel":8,"../view/AbstractView":12,"../view/UserView":14,"../viewmodel/ActiveUserViewModel":15}],3:[function(require,module,exports){ (function (global){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const UserModel_1 = require("./model/UserModel"); const UserView_1 = require("./view/UserView"); const UserController_1 = require("./controller/UserController"); const Handlebars = (typeof window !== "undefined" ? window['Handlebars'] : typeof global !== "undefined" ? global['Handlebars'] : null); const markdownit = (typeof window !== "undefined" ? window['markdownit'] : typeof global !== "undefined" ? global['markdownit'] : null); const ChatModel_1 = require("./model/ChatModel"); const ChatView_1 = require("./view/ChatView"); const ChatController_1 = require("./controller/ChatController"); const JsonAPI_1 = require("./singleton/JsonAPI"); // import log = require('loglevel')
const log = (typeof window !== "undefined" ? window['log'] : typeof global !== "undefined" ? global['log'] : null); const SJCLEncryptionService_1 = require("./service/SJCLEncryptionService"); // var markdownit = require('markdown-it');
var md = new markdownit(); const userBox = document.getElementById('contacts-box'); log.setLevel("TRACE"); const chatModel = new ChatModel_1.ChatModel(); const userModel = new UserModel_1.UserModel(); // const userModel = ModelFactory.createModel("USER");
// @ts-ignore: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'HTMLElement'. Type 'null' is not assignable to type 'HTMLElement'.
const userView = new UserView_1.UserView(userModel, chatModel, userBox); // console.log(userBox);
userModel.attach(userView); // userView.model
const userController = new UserController_1.UserController(userModel, userView); // userController.test();
// userModel.someBusinessMethod(activeUsersMock);
log.info("hello"); const chatArea = document.getElementById('chat-area-new'); // @ts-ignore: Argument of type 'HTMLElement | null' is not assignable to parameter of type 'HTMLElement'. Type 'null' is not assignable to type 'HTMLElement'.
const chatView = new ChatView_1.ChatView(chatModel, chatArea); chatModel.attach(chatView); const chatController = new ChatController_1.ChatController(chatModel, chatView); function someFunc(vm) { // log.info(vm);
// logger.info(vm)
} userController.getActiveUsers(); log.info("test"); // someFunc(activeUserViewModelMock);
// @ts-ignore: Object is possibly 'null'.
var source = document.getElementById("msg_container_template").innerHTML; var msgContainerTemplate = Handlebars.compile(source); JsonAPI_1.JsonAPI.ACTIVE_USERS_GET + 'aef'; const encryptionService = new SJCLEncryptionService_1.SJCLEncryptionService(); let ct = encryptionService.encrypt("password", "data"); console.log(encryptionService.decrypt("password", JSON.parse(ct))); Handlebars.registerHelper('avatar', function () { return '<div class="img_cont_msg"> <img src="https://static.turbosquid.com/Preview/001292/481/WV/_D.jpg" class="rounded-circle user_img_msg"> </div>'; });
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./controller/ChatController":1,"./controller/UserController":2,"./model/ChatModel":5,"./model/UserModel":8,"./service/SJCLEncryptionService":9,"./singleton/JsonAPI":10,"./view/ChatView":13,"./view/UserView":14}],4:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true });
},{}],5:[function(require,module,exports){ (function (global){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const log = (typeof window !== "undefined" ? window['log'] : typeof global !== "undefined" ? global['log'] : null); const ChatModelHelper_1 = require("./ChatModelHelper"); class ChatModel { constructor() { /** * @type {Observer[]} List of subscribers. In real life, the list of * subscribers can be stored more comprehensively (categorized by event * type, etc.). */ this._observers = []; this.state = null; this._messagesMap = new Map(); } /** * The subscription management methods. */ attach(observer) { console.log('Subject: Attached an observer.'); this._observers.push(observer); } detach(observer) { const observerIndex = this._observers.indexOf(observer); this._observers.splice(observerIndex, 1); console.log('Subject: Detached an observer.'); } setUserMessages(username, messages) { this._messagesMap.set(username, messages); } /** * Trigger an update in each subscriber. */ notify(userName) { console.log('Subject: Notifying observers...'); for (const observer of this._observers) { observer.update(this._messagesMap.get(userName)); } } someBusinessMethod(chatMessageList) { this.state = chatMessageList; this.helperMethod(); console.log(`Subject: My state has just changed`); console.log(chatMessageList); this.notify("some user"); } async getmessages(userName, passphrase, lastMessageTime) { const cVMs = await ChatModelHelper_1.ChatModelHelper.getMessages(userName, passphrase, lastMessageTime, this); if (cVMs != null) { log.info('Subject: My state has just changed'); log.debug(cVMs); this._messagesMap.set(userName, cVMs); this.notify(userName); } else { log.error('Messages were null'); } return cVMs; } helperMethod() { } populateMessages() { } } exports.ChatModel = ChatModel;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./ChatModelHelper":6}],6:[function(require,module,exports){ (function (global){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const log = (typeof window !== "undefined" ? window['log'] : typeof global !== "undefined" ? global['log'] : null); const ChatMessageViewModel_1 = require("../viewmodel/ChatMessageViewModel"); const JsonAPI_1 = require("../singleton/JsonAPI"); const FetchErrorHandler_1 = require("./FetchErrorHandler"); const SJCLEncryptionService_1 = require("../service/SJCLEncryptionService"); class ChatModelHelper { static async getMessages(userName, passphrase, lastMessageTime, chatModel) { switch (lastMessageTime) { case null: { // this.getAllMessagesAjax(userName)
// .then((data: ChatMessageDTO[]) => {
// log.debug(`Subject: received all messages`);
// // let userNames = data.map(ChatMessageViewModel => ChatMessageViewModel.fromUser)
// // let sumt = data.map(chatMessageViewModel => { return this.encryptionService.decrypt(passphrase, chatMessageViewModel.messageCipher) });
// return data.map(vm => this.toChatMessageVM(vm, passphrase));
// // chatModel.setUserMessages(userName, chatMessageVMs);
// // chatModel.notify();
// })
// break;
const data = await this.getAllMessagesAjax(userName); return data.map(vm => this.toChatMessageVM(vm, passphrase)); } default: { // this.getNewMessagesAjax(userName, lastMessageTime)
// .then((data: ChatMessageDTO[]) => {
// log.debug(`Subject: received new messages`);
// return data.map(vm => this.toChatMessageVM(vm, passphrase));
// // chatModel.setUserMessages(userName, chatMessageVMs);
// // this.state = data;
// // chatModel.notify();
// })
// break;
const data = await this.getNewMessagesAjax(userName, lastMessageTime); return data.map(vm => this.toChatMessageVM(vm, passphrase)); } } // return null;
} static toChatMessageVM(chatMessageDTO, passphrase) { const vm = new ChatMessageViewModel_1.ChatMessageViewModel(); vm.fromUser = chatMessageDTO.fromUser; vm.toUser = chatMessageDTO.toUser; vm.messageTime = chatMessageDTO.messageTime; vm.message = this.encryptionService.decrypt(passphrase, chatMessageDTO.messageCipher); return vm; } static async getAllMessagesAjax(toUser) { const headers = new Headers(); if (JsonAPI_1.JsonAPI.authToken == null) { log.error("authToken null"); return; } ; headers.append('X-AUTH-TOKEN', JsonAPI_1.JsonAPI.authToken); const response = await fetch(`${JsonAPI_1.JsonAPI.CHAT_MESSAGES_GET}/${toUser}`, { method: 'GET', headers: headers }); console.log(response.clone()); if (FetchErrorHandler_1.fetchErrorHandler(response.clone())) { return null; } const data = await response.json(); return data; } static async getNewMessagesAjax(toUser, lastMessageTimeStamp) { const headers = new Headers(); if (JsonAPI_1.JsonAPI.authToken == null) { log.error("authToken null"); return; } ; headers.append('X-AUTH-TOKEN', JsonAPI_1.JsonAPI.authToken); const response = await fetch(`${JsonAPI_1.JsonAPI.CHAT_MESSAGES_GET}/${toUser}/${lastMessageTimeStamp}`, { method: 'GET', headers: headers }); console.log(response.clone()); if (FetchErrorHandler_1.fetchErrorHandler(response.clone())) { return null; } const data = await response.json(); return data; } } exports.ChatModelHelper = ChatModelHelper; ChatModelHelper.encryptionService = new SJCLEncryptionService_1.SJCLEncryptionService();
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"../service/SJCLEncryptionService":9,"../singleton/JsonAPI":10,"../viewmodel/ChatMessageViewModel":16,"./FetchErrorHandler":7}],7:[function(require,module,exports){ (function (global){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const log = (typeof window !== "undefined" ? window['log'] : typeof global !== "undefined" ? global['log'] : null); const sprintf_js_1 = (typeof window !== "undefined" ? window['sprintf'] : typeof global !== "undefined" ? global['sprintf'] : null); // import sprintf = require('sprintf-js').sprintf;
function fetchErrorHandler(response) { // alertify.success('Current position : ' + alertify.get('notifier', 'position'));
if (!response.ok) { return response.text().catch(err => { // the status was not ok and there is no json body
// throw new Error(response.statusText);
// window.alert(sprintf('Some error occured. Http code is %s', response.status));
// alertify.error(sprintf('Some error occured. Http code is %s', response.status));
log.error(sprintf_js_1.sprintf('Some error occured. Http code is %s', response.status)); log.error(); return true; }).then(json => { // the status was not ok but there is a json body
// throw new Error(json.error.message); // example error message returned by a REST API
// window.alert(sprintf('Error: %s (Http code %s)', json, response.status));
// alertify.error(sprintf('Some error occured. Http code is %s', response.status));
log.error(sprintf_js_1.sprintf('Some error occured. Http code is %s', response.status)); log.error(json); return true; }); } } exports.fetchErrorHandler = fetchErrorHandler;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],8:[function(require,module,exports){ (function (global){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const FetchErrorHandler_1 = require("./FetchErrorHandler"); const JsonAPI_1 = require("../singleton/JsonAPI"); const log = (typeof window !== "undefined" ? window['log'] : typeof global !== "undefined" ? global['log'] : null); class UserModel { // @ts-ignore: Cannot find name 'hostAddress'.
constructor() { /** * @type {Observer[]} List of subscribers. In real life, the list of * subscribers can be stored more comprehensively (categorized by event * type, etc.). */ this.observers = []; } /** * The subscription management methods. */ attach(observer) { console.log('Subject: Attached an observer.'); this.observers.push(observer); } detach(observer) { const observerIndex = this.observers.indexOf(observer); this.observers.splice(observerIndex, 1); console.log('Subject: Detached an observer.'); } /** * Trigger an update in each subscriber. */ notify() { console.log('Subject: Notifying observers...'); for (const observer of this.observers) { observer.update(this.state); } } someBusinessMethod(activeuserList) { this.state = activeuserList; this.helperMethod(); console.log(`Subject: My state has just changed`); console.log(activeuserList); this.notify(); } /** * getActiveUsers */ getActiveUsers() { if (JsonAPI_1.JsonAPI.authToken != null) { this.getActiveUsersAjax(JsonAPI_1.JsonAPI.authToken, JsonAPI_1.JsonAPI.ACTIVE_USERS_GET) .then(data => { // // activeUsers = data;
// sessionStorage.setItem('activeUsers', JSON.stringify(data));
// console.log(sessionStorage.getItem('activeUsers'));
console.log(`Subject: received ajax active users`); this.state = data; this.notify(); }); } else { log.error('Auth token is null'); } } async getActiveUsersAjax(authToken2, URL) { let headers = new Headers(); // headers.append('Authorization', basicAuthToken);
headers.append('X-AUTH-TOKEN', authToken2); let response = await fetch(JsonAPI_1.JsonAPI.ACTIVE_USERS_GET, { method: 'GET', headers: headers }); console.log(response.clone()); if (FetchErrorHandler_1.fetchErrorHandler(response.clone())) { return null; } let data = await response.json(); // return data;
return new Promise((resolve, reject) => { if (data != null) resolve(data); else reject('Response data null'); }); } helperMethod() { } } exports.UserModel = UserModel;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"../singleton/JsonAPI":10,"./FetchErrorHandler":7}],9:[function(require,module,exports){ (function (global){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const sjcl = (typeof window !== "undefined" ? window['sjcl'] : typeof global !== "undefined" ? global['sjcl'] : null); class SJCLEncryptionService { constructor() { this.params = { mode: "gcm", ts: 128, adata: "", iter: 10000 }; } encrypt(passphrase, plainText) { return sjcl.encrypt(passphrase, plainText, this.params); } decrypt(passphrase, cipher) { // return sjcl.decrypt(passphrase, cipher as sjcl.SjclCipherEncrypted, undefined, undefined);
return sjcl.decrypt(passphrase, JSON.stringify(cipher), undefined, undefined); } } exports.SJCLEncryptionService = SJCLEncryptionService;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],10:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var JsonAPI; (function (JsonAPI) { // @ts-ignore: Cannot find name 'hostAddress'.
JsonAPI.userName = localStorage.getItem('userName'); JsonAPI.authToken = localStorage.getItem('authToken'); JsonAPI.ACTIVE_USERS_GET = `/api/chat/get/active-users`; JsonAPI.CHAT_MESSAGES_GET = `/api/chat/get/messages`; })(JsonAPI = exports.JsonAPI || (exports.JsonAPI = {}));
},{}],11:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class TemplateFactory { // static getTemplate(templateName: string): Handlebars.TemplateDelegate<any> {
// switch (templateName) {
// case "user-contact-online-template": {
// // let source = document.getElementById("user-contact-online-template").innerHTML;
// // let msgContainerTemplate = Handlebars.compile(source);
// // return msgContainerTemplate;
// return this.createTemplate(templateName);
// }
// case "msg_container_send_template": {
// // let source = document.getElementById("msg_container_send_template").innerHTML;
// // let msgContainerTemplate = Handlebars.compile(source);
// // return msgContainerTemplate;
// return this.createTemplate(templateName);
// }
// case "msg_container_template": {
// // let source = document.getElementById("msg_container_send_template").innerHTML;
// // let msgContainerTemplate = Handlebars.compile(source);
// // return msgContainerTemplate;
// return this.createTemplate(templateName);
// }
// default:
// throw new Error('invalid template name');
// }
// }
static getTemplate(templateName) { //@ts-ignore: Object is possibly 'null'.
let source = document.getElementById(templateName).innerHTML; let msgContainerTemplate = Handlebars.compile(source); return msgContainerTemplate; } } exports.TemplateFactory = TemplateFactory;
},{}],12:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true });
},{}],13:[function(require,module,exports){ (function (global){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const TemplateFactory_1 = require("../template/TemplateFactory"); const log = (typeof window !== "undefined" ? window['log'] : typeof global !== "undefined" ? global['log'] : null); const DOMPurify = (typeof window !== "undefined" ? window['DOMPurify'] : typeof global !== "undefined" ? global['DOMPurify'] : null); const markdownit = (typeof window !== "undefined" ? window['markdownit'] : typeof global !== "undefined" ? global['markdownit'] : null); var md = new markdownit(); class ChatView { constructor(model, element) { this._messageSendTemplate = TemplateFactory_1.TemplateFactory.getTemplate('msg_container_send_template'); this._model = model; this._element = element; } update(data) { log.info('ChatView: updating view'); let html = ""; data.forEach((vm) => { html += this._messageSendTemplate(vm); }); /** Very Important!!! * Sanitizing HTML before displaying on webpage to prevent XSS attacks!! */ html = DOMPurify.sanitize(md.render(html)); this._element.innerHTML = html; log.debug(this._element.innerHTML); } } exports.ChatView = ChatView;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"../template/TemplateFactory":11}],14:[function(require,module,exports){ (function (global){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const TemplateFactory_1 = require("../template/TemplateFactory"); const log = (typeof window !== "undefined" ? window['log'] : typeof global !== "undefined" ? global['log'] : null); class UserView { // private userBoxes: any[] = [];
constructor(model, chatModel, element) { this._model = model; this._chatModel = chatModel; this._element = element; } update(data) { let template = TemplateFactory_1.TemplateFactory.getTemplate('user-contact-online-template'); let html = ""; data.forEach((element) => { html += template(element); }); this._element.innerHTML = html; this.addUserCallBacks(); console.log(this._element.innerHTML); } helper() { } addUserCallBacks() { let userBoxes = document.getElementsByClassName('user-box'); for (let i = 0; i < userBoxes.length; i++) { let userBox = userBoxes[i]; userBoxes[i].addEventListener('click', this.userCallBack.bind(this, userBox)); } } userCallBack(el) { let current = document.getElementsByClassName('user-box active'); let passphrase = ''; if (current.length > 0) { let passphraseInput = document.getElementById('passphrase'); if (passphraseInput == null) { log.error('passphraseInput element reference is null'); return; } passphrase = passphraseInput.value; if (passphrase == '' || passphrase == null) { // alert('Please input passphrase')
// alertify.error('Please enter a passphrase');
log.error('passphrase is empty or null'); return; } current[0].className = current[0].className.replace(" active", ""); } // Add the active class to the current/clicked button
else if (current.length == 0) { let elem = document.getElementById('passphrase-initial'); if (elem == null) { log.error('passphraseInput element reference is null'); return; } passphrase = elem.value; if (passphrase == '' || passphrase == null) { // // alert('Please input passphrase')
// // alertify.error('Please enter a passphrase');
log.error('passphrase is empty or null'); return; } // @ts-ignore: Object is possibly 'null'.
document.getElementById('no-user-selected').hidden = true; // @ts-ignore: Object is possibly 'null'.
document.getElementById('chat-card').hidden = false; // @ts-ignore: Object is possibly 'null'.
elem.hidden = true; } // console.log(this.getElementsByClassName('to-user-span'));
let elem = el.getElementsByClassName('to-user-span')[0]; let userName = elem.innerText; // @ts-ignore: Object is possibly 'null'.
document.getElementById('user-name-span').innerText = userName; this._chatModel.getmessages(userName, passphrase, null); // populateMessages(userName, passphrase);
sessionStorage.setItem('selectedUser', userName); el.className += " active"; } } exports.UserView = UserView;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"../template/TemplateFactory":11}],15:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class ActiveUserViewModel { } exports.ActiveUserViewModel = ActiveUserViewModel;
},{}],16:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class ChatMessageViewModel { } exports.ChatMessageViewModel = ChatMessageViewModel;
},{}]},{},[3]) //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL3dhdGNoaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJ0cy9zcmMvY29udHJvbGxlci9DaGF0Q29udHJvbGxlci50cyIsInRzL3NyYy9jb250cm9sbGVyL1VzZXJDb250cm9sbGVyLnRzIiwidHMvc3JjL21haW4udHMiLCJ0cy9zcmMvbW9kZWwvQ2hhdE1vZGVsLnRzIiwidHMvc3JjL21vZGVsL0NoYXRNb2RlbEhlbHBlci50cyIsInRzL3NyYy9tb2RlbC9GZXRjaEVycm9ySGFuZGxlci50cyIsInRzL3NyYy9tb2RlbC9Vc2VyTW9kZWwudHMiLCJ0cy9zcmMvc2VydmljZS9TSkNMRW5jcnlwdGlvblNlcnZpY2UudHMiLCJ0cy9zcmMvc2luZ2xldG9uL0pzb25BUEkudHMiLCJ0cy9zcmMvdGVtcGxhdGUvVGVtcGxhdGVGYWN0b3J5LnRzIiwidHMvc3JjL3ZpZXcvQ2hhdFZpZXcudHMiLCJ0cy9zcmMvdmlldy9Vc2VyVmlldy50cyIsInRzL3NyYy92aWV3bW9kZWwvQWN0aXZlVXNlclZpZXdNb2RlbC50cyIsInRzL3NyYy92aWV3bW9kZWwvQ2hhdE1lc3NhZ2VWaWV3TW9kZWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztBQ0NBLGtDQUErQjtBQUMvQiw4QkFBMkI7QUFDM0IsZ0NBQTZCO0FBQzdCLDRCQUF5QjtBQUd6Qiw0RUFBeUU7QUFJekUsTUFBYSxjQUFjO0lBS3ZCLFlBQVksS0FBZ0IsRUFBRSxJQUFjO1FBQ3hDLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO0lBQ3RCLENBQUM7SUFHRDs7T0FFRztJQUNJLFlBQVksQ0FBQyxFQUEwQjtRQUMxQyxJQUFJLENBQUMsTUFBTSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZDLENB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
|