diff --git a/chatto/.gitignore b/chatto/.gitignore index 5814f2f..a1c42da 100644 --- a/chatto/.gitignore +++ b/chatto/.gitignore @@ -37,4 +37,5 @@ bundle.js bundle.min.js src/main/javascript/node/ dist -out \ No newline at end of file +out +yarn-error.log \ No newline at end of file diff --git a/chatto/src/main/javascript/app.css b/chatto/src/main/javascript/app.css deleted file mode 100644 index 059d217..0000000 --- a/chatto/src/main/javascript/app.css +++ /dev/null @@ -1,3 +0,0 @@ -@import url("node_modules/alertifyjs/build/css/alertify.css"); -@import url("node_modules/alertifyjs/build/css/themes/bootstrap.min.css"); -@import url("node_modules/alertifyjs/build/css/themes/default.min.css"); \ No newline at end of file diff --git a/chatto/src/main/javascript/chat.js b/chatto/src/main/javascript/chat.js deleted file mode 100644 index c408dae..0000000 --- a/chatto/src/main/javascript/chat.js +++ /dev/null @@ -1,560 +0,0 @@ -// import { sprintf } from 'sprintf-js'; -// import { vsprintf } from 'sprintf-js'; -/*var off_payment_method = document.getElementsByName('offline_payment_method'); -var ischecked_method = false; -for ( var i = 0; i < off_payment_method.length; i++) { - if(off_payment_method[i].checked) { - ischecked_method = true; - break; - } -} -if(!ischecked_method) { //payment method button is not checked - alert("Please choose Offline Payment Method"); -}*/ -// var css = require('./app.css'); -// console.log(css); -// var alertify = require('alertifyjs'); -var log = require('loglevel'); -var sjcl = require('sjcl'); -var markdownit = require('markdown-it'); -var md = new markdownit(); -var Handlebars = require('handlebars'); -var DOMPurify = require('dompurify'); -var Fuse = require('fuse.js'); - -require('./test.js'); - -var toUserRadios = document.getElementsByName('toUser'); -var isCheckedUser = false; -var chatTextArea = document.getElementById('chatTextArea'); - -var postNewMessageUrl = `http://${hostAddress}/api/chat/post/message`; //hostAddress variable is set in the thymeleaf head fragment -var getAllMessagesUrl = `http://${hostAddress}/api/chat/get/messages/`; -var getNewMessagesUrl = `http://${hostAddress}/api/chat/get/messages/`; -var getActiveUsersUrl = `http://${hostAddress}/api/chat/get/active-users/`; -// var postNewMessageUrl = "http://localhost:8080/api/chat/post/message"; -// var getAllMessagesUrl = "http://localhost:8080/api/chat/get/messages/"; -// var getNewMessagesUrl = "http://localhost:8080/api/chat/get/messages/"; -// var messageLog = []; -var username = localStorage.getItem('username'); -var authToken = localStorage.getItem('authToken'); - -var passphraseInput = document.getElementById('passphrase'); -var iterations = 100000; - -var source = document.getElementById("msg_container_template").innerHTML; -var msgContainerTemplate = Handlebars.compile(source); -var source = document.getElementById("msg_container_send_template").innerHTML; -var msgContainerSendTemplate = Handlebars.compile(source); -var source = document.getElementById("user-contact-online-template").innerHTML; -var userContactOnlineTemplate = Handlebars.compile(source); -var source = document.getElementById("user-contact-offline-template").innerHTML; -var userContactOfflineTemplate = Handlebars.compile(source); - -var chatAreaNew = document.getElementById('chat_area_new'); - -var userBoxes = document.getElementsByName('user-box'); - - - -var activeUsers = {}; - -var fuseOptions = { - shouldSort: true, - threshold: 0.01, - location: 0, - distance: 100, - maxPatternLength: 32, - minMatchCharLength: 1, - keys: [ - "userName", - ] -}; - -log.setLevel('TRACE'); - -alertify.set('notifier', 'position', 'top-center'); - -// Loop through the buttons and add the active class to the current/clicked button -// for (var i = 0; i < btns.length; i++) { -// btns[i].addEventListener("click", function() { -// var current = document.getElementsByClassName("active"); - -// // If there's no active class -// if (current.length > 0) { -// current[0].className = current[0].className.replace(" active", ""); -// } - -// // Add the active class to the current/clicked button -// this.className += " active"; -// }); -// } - -getActiveUsers(authToken) - .then(data => { - // activeUsers = data; - sessionStorage.setItem('activeUsers', JSON.stringify(data)); - log.log(sessionStorage.getItem('activeUsers')); - }) - -for (let i = 0; i < userBoxes.length; i++) { - userBoxes[i].addEventListener('click', userCallBack) -} - -function addUserCallBacks() { - for (let i = 0; i < userBoxes.length; i++) { - userBoxes[i].addEventListener('click', userCallBack) - } -} - -function userCallBack() { - let current = document.getElementsByClassName('user-box active'); - let passphrase = passphraseInput.value; - if (current.length > 0) { - if (passphrase == '') { - // alert('Please input passphrase') - alertify.error('Please enter a passphrase'); - 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'); - passphrase = elem.value; - if (passphrase == '') { - // alert('Please input passphrase') - alertify.error('Please enter a passphrase'); - return; - } - document.getElementById('no-user-selected').hidden = true; - document.getElementById('chat-card').hidden = false; - elem.hidden = true; - } - // console.log(this.getElementsByClassName('to-user-span')); - let userName = this.getElementsByClassName('to-user-span')[0].innerText; - document.getElementById('user-name-span').innerText = userName; - populateMessages(userName, passphrase); - sessionStorage.setItem('selectedUser', userName); - this.className += " active"; -} - -function populateMessages(userName, passphrase) { - console.log('Selected user = ' + userName); - if (passphrase == '') { - alert('Please input passphrase') - return; - } - // console.log(userName); - if (sessionStorage.getItem(userName) == null) { - chatTextArea.textContent = ''; - chatAreaNew.innerHTML = ''; - getAllMessages(userName) - .then(json => { - if (json == null) return; - console.log(json); - let i = 0; - let messageLog = []; - let messageLogNew = []; - let lastMessageTimeStamp; - - if (json.length > 0) { - json.forEach(function(obj) { - // console.log(obj.toUser); - messageCipher = JSON.stringify(obj.messageCipher); - console.log(messageCipher); - // let message = sjcl.decrypt("password", messageCipher); - let message = md.render(sjcl.decrypt(passphrase, messageCipher)); - let utcDate = obj.messageTime; - lastMessageTimeStamp = utcDate; - let localDate = new Date(utcDate); - let messageLine = sprintf('%s %s: %s ', localDate, obj.fromUser, message); - - - // localDate.`` - // console.log('localDate = ' + localDate); - console.log(messageLine); - // chatTextArea.append(obj.fromUser + ": " + message + "\n"); - chatTextArea.append(messageLine + '\n'); - messageLog[i++] = messageLine; - chatTextArea.scrollTop = chatTextArea.scrollHeight; - // console.log('Message log = ' + messageLog); - - let context = { fromUser: obj.fromUser, message: message, time: localDate.toLocaleString() }; - let msgContainer; - if (obj.fromUser == username) { - msgContainer = msgContainerSendTemplate(context); - } else { - msgContainer = msgContainerTemplate(context); - } - - messageLogNew.push(JSON.stringify(context)); - $(chatAreaNew).append(DOMPurify.sanitize(msgContainer)); - - - }); - sessionStorage.setItem(userName, JSON.stringify(messageLog)); - sessionStorage.setItem(userName + username + 'new', JSON.stringify(messageLogNew)); - // console.log() - // sessionStorage.clear(); - console.log('Last message time = ' + lastMessageTimeStamp); - sessionStorage.setItem(userName + '-time', lastMessageTimeStamp); - - - } - }); - } else { - - - console.log("Stored messages = " + sessionStorage.getItem(userName)); - let storedMessages = JSON.parse(sessionStorage.getItem(userName)); - let storedMessagesNew = JSON.parse(sessionStorage.getItem(userName + username + 'new')); - let lastMessageTime = sessionStorage.getItem(userName + '-time'); - console.log("last message time stamp = " + lastMessageTime); - if (lastMessageTime != null) { - getNewMessages(userName, lastMessageTime) - .then(json => { - if (json == null) return; - console.log(json) - if (json.length > 0) { - json.forEach(function(obj) { - let messageCipher = JSON.stringify(obj.messageCipher); - let message = md.render(sjcl.decrypt(passphrase, messageCipher)); - // console.log(message); - // chatTextArea.append(message + "\n"); - let utcDate = obj.messageTime; - lastMessageTimeStamp = utcDate; - let localDate = new Date(utcDate); - let messageLine = sprintf('%s %s: %s', localDate, obj.fromUser, message); - - // localDate.`` - // console.log('localDate = ' + localDate); - console.log(messageLine); - // chatTextArea.append(obj.fromUser + ": " + message + "\n"); - chatTextArea.append(messageLine + '\n'); - chatTextArea.scrollTop = chatTextArea.scrollHeight; - storedMessages.push(messageLine); - - let context = { fromUser: obj.fromUser, message: message, time: localDate.toLocaleString() }; - let msgContainer; - if (obj.fromUser == username) { - msgContainer = msgContainerSendTemplate(context); - } else { - msgContainer = msgContainerTemplate(context); - } - - storedMessagesNew.push(JSON.stringify(context)); - $(chatAreaNew).append(DOMPurify.sanitize(msgContainer)); - - }) - sessionStorage.setItem(userName + '-time', lastMessageTimeStamp); - sessionStorage.setItem(userName, JSON.stringify(storedMessages)); - sessionStorage.setItem(userName + username + 'new', JSON.stringify(storedMessagesNew)); - console.log("this value stored" + sessionStorage.getItem(userName)) - console.log("last message time stamp = " + lastMessageTimeStamp); - console.log(sessionStorage.getItem(userName + '-time')); - - } - chatTextArea.textContent = ''; - chatAreaNew.innerHTML = ''; - console.log("Stored messages 2 = " + storedMessages); - storedMessages.forEach(function(messageLine) { - chatTextArea.append(messageLine + '\n'); - chatTextArea.scrollTop = chatTextArea.scrollHeight; - - // let context = {message: messageLine}; - // let msgContainer; - // if(obj.fromUser == username) - // { - // msgContainer = msgContainerSendTemplate(context); - // } - // else{ - // msgContainer = msgContainerTemplate(context); - // } - - // $(chatAreaNew).append(msgContainer); - }) - - storedMessagesNew.forEach(function(contextString) { - let context = JSON.parse(contextString); - let msgContainer; - if (context.fromUser == username) { - msgContainer = msgContainerSendTemplate(context); - } else { - msgContainer = msgContainerTemplate(context); - } - - $(chatAreaNew).append(DOMPurify.sanitize(msgContainer)); - scrollChatAreaAnimated(2400); - }) - - - }); - - - } - // chatTextArea.append(JSON.stringify(storedMessages)); - - } - // sessionStorage.setItem('status', 'ready'); - // sessionStorage.setItem('userName', messageLog); - // console.log('Message log = ' + messageLog); - // } - - // let passphraseKey = userName + '-passphrase'; - // sessionStorage.setItem(passphraseKey, passphrase); - // console.log(sessionStorage.getItem(passphraseKey)); -} - -// var lastMessageTimeStamp; - -// console.log(authToken); -// 'Basic ' + btoa("hmm" + ":" + "hmm") - -Handlebars.registerHelper('avatar', function() { - return '
'; -}); - - -// var user; -function getSelectedUser() { - for (var i = 0; i < toUserRadios.length; i++) { - if (toUserRadios[i].checked) { - let user = toUserRadios[i].value; - console.log('sending to user = ' + user); - isCheckedUser = true; - return user; - } - } - -} - -function getSelectedUserNew() { - return sessionStorage.getItem('selectedUser'); -} - -document.getElementById('chatMessageForm').addEventListener('submit', function(e) { - let chatInput = document.getElementById('chatInput'); - e.preventDefault(); - let user = getSelectedUserNew(); - - if (!this.checkValidity()) { - console.log("error"); - this.classList.add('was-validated'); - return; - } - this.classList.add('was-validated'); - - if (user == null) { - // window.alert('please select a user'); - alertify.error('Please select a user'); - return; - } - let messageContent = chatInput.value; - let context = { fromUser: username, message: md.render(messageContent), time: new Date().toLocaleString() }; - let msgContainer = msgContainerSendTemplate(context); - $(chatAreaNew).append(DOMPurify.sanitize(msgContainer)); - scrollChatAreaAnimated(2400); - let messageCipher = sjcl.encrypt(passphraseInput.value, messageContent, { mode: "gcm", ts: 128, adata: "", iter: iterations }); - let messageCipherJson = JSON.parse(messageCipher); - let chatMessageDTO = { - "toUser": user, - "messageCipher": messageCipherJson - } - messageSend(JSON.stringify(chatMessageDTO)); -}) - -document.getElementById('user-search').addEventListener('submit', function(e) { - e.preventDefault(); - let contactsBox = document.getElementById('contacts-box'); - let temp = contactsBox.innerHTML; - // log.trace(temp); - let searchTerm = document.getElementById('user-search-term').value; - log.debug("search term value = " + searchTerm); - let list = JSON.parse(sessionStorage.getItem('activeUsers')); - log.debug("active users"); - log.debug(list); - let fuse = new Fuse(list, fuseOptions); - let searchResult = fuse.search(searchTerm); - populateContactsBox(contactsBox, searchResult); - addUserCallBacks(); - log.debug(searchResult); -}) -document.getElementById('user-search-term').addEventListener('input', function(e) { - e.preventDefault(); - if (this.value.length < 2) { - log.debug("inputted") - let cancelButton = document.getElementById('user-search-cancel'); - cancelButton.hidden = false; - } -}) -document.getElementById('user-search-cancel').addEventListener('click', function(e) { - e.preventDefault(); - let list = JSON.parse(sessionStorage.getItem('activeUsers')); - let contactsBox = document.getElementById('contacts-box'); - populateContactsBox(contactsBox,list); - addUserCallBacks(); - document.getElementById('user-search-term').value = ""; - this.hidden = true; -}) - -function populateContactsBox(contactsBox, list) -{ - let userContactBoxList = ""; - list.forEach(function(activeUser) { - log.debug(activeUser); - if (activeUser.online) { - userContactBoxList += userContactOnlineTemplate(activeUser); - } else { - userContactBoxList += userContactOfflineTemplate(activeUser); - } - }) - contactsBox.innerHTML = userContactBoxList; -} - - - -// console.log('Credentials = ' + JSON.parse(sessionStorage.getItem('credentials'))); - - -function messageSend(chatMessageDTO) { - let headers = new Headers(); - // console.log("Token = " + btoa("hmm" + ":" + "hmm")) - - // headers.append('Accept','application/json') - headers.append('Content-Type', 'application/json'); - // headers.append('Authorization', basicAuthToken); - headers.append('X-AUTH-TOKEN', authToken); - fetch(postNewMessageUrl, { - method: 'POST', - headers: headers, - body: chatMessageDTO - }) - .then(response => { - console.log(response); - return response.clone(); - }) - .then(response => fetchHandler(response)); -} - - -async function getAllMessages(toUser) { - let headers = new Headers(); - // headers.append('Accept','application/json') - // headers.append('Content-Type', 'application/json'); - // headers.append('Authorization', basicAuthToken); - headers.append('X-AUTH-TOKEN', authToken); - let response = await fetch(getAllMessagesUrl + toUser, { - method: 'GET', - headers: headers - }); - console.log(response); - if (fetchErrorHandler(response.clone())) { - return null; - } - // if (response.status == 440) { - // window.alert('Token has expired. Please login again'); - // return null; - // } - let data = await response.json(); - return data; -} - -async function getNewMessages(toUser, lastMessageTimeStamp) { - let headers = new Headers(); - // headers.append('Authorization', basicAuthToken); - headers.append('X-AUTH-TOKEN', authToken); - let response = await fetch(`${getNewMessagesUrl}${toUser}/${lastMessageTimeStamp}`, { - method: 'GET', - headers: headers - }); - console.log(response.clone()); - if (fetchErrorHandler(response.clone())) { - return null; - } - let data = await response.json(); - return data; -} - - -async function getActiveUsers(authToken2) { - let headers = new Headers(); - // headers.append('Authorization', basicAuthToken); - headers.append('X-AUTH-TOKEN', authToken2); - let response = await fetch(getActiveUsersUrl, { - method: 'GET', - headers: headers - }); - console.log(response.clone()); - if (fetchErrorHandler(response.clone())) { - return null; - } - let data = await response.json(); - return data; -} - -$(document).ready(function() { - $('#action_menu_btn').click(function() { - $('.action_menu').toggle(); - }); -}); - -function fetchHandler(response) { - if (response.ok) { - return response.json().then(json => { - // the status was ok and there is a json body - // return Promise.resolve({ json: json, response: response }); - alertify.success('Message sent succesfully' + sprintf(" (http code %d)", response.status)); - }).catch(err => { - // the status was ok but there is no json body - // return Promise.resolve({ response: response }); - alertify.success('Message sent succesfully' + sprintf(" (http code %d)", response.status)); - }); - - } else { - return response.json().catch(err => { - // the status was not ok and there is no json body - // throw new Error(response.statusText); - alertify.error('Some error occured. Please try again.'); - }).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 - let delay = alertify.get('notifier', 'delay'); - alertify.set('notifier', 'delay', 30); - let errorMessage = ""; - json.errors.forEach(function(data) { - errorMessage += sprintf("Field Name: %s \n Rejected value: %s \n Reason: %s \n", data.field_name, data.rejected_value, data.error_message); - }); - alertify.error(sprintf('There were errors in your message - %s', errorMessage)); - alertify.set('notifier', 'delay', delay); - }); - } -} - - -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)); - 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)); - console.log(json); - return true; - }); - } -} - -function scrollChatAreaAnimated(delay) { - $(chatAreaNew).stop().animate({ - scrollTop: $(chatAreaNew)[0].scrollHeight - }, delay); -} \ No newline at end of file diff --git a/chatto/src/main/javascript/index.html b/chatto/src/main/javascript/index.html deleted file mode 100644 index e69de29..0000000 diff --git a/chatto/src/main/javascript/test.js b/chatto/src/main/javascript/test.js deleted file mode 100644 index 9e75acd..0000000 --- a/chatto/src/main/javascript/test.js +++ /dev/null @@ -1 +0,0 @@ -log.info("test success"); \ No newline at end of file diff --git a/chatto/src/main/javascript/ts/bundle.js b/chatto/src/main/javascript/ts/bundle.js deleted file mode 100644 index 40d668d..0000000 --- a/chatto/src/main/javascript/ts/bundle.js +++ /dev/null @@ -1,794 +0,0 @@ -(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 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var FetchErrorHandler_1 = require("./FetchErrorHandler"); -var ChatModel = /** @class */ (function () { - function ChatModel() { - /** - * @type {Observer[]} List of subscribers. In real life, the list of - * subscribers can be stored more comprehensively (categorized by event - * type, etc.). - */ - this.observers = []; - // @ts-ignore: Cannot find name 'hostAddress'. - this.getActiveUsersUrl = ""; - } - /** - * The subscription management methods. - */ - ChatModel.prototype.attach = function (observer) { - console.log('Subject: Attached an observer.'); - this.observers.push(observer); - }; - ChatModel.prototype.detach = function (observer) { - var observerIndex = this.observers.indexOf(observer); - this.observers.splice(observerIndex, 1); - console.log('Subject: Detached an observer.'); - }; - /** - * Trigger an update in each subscriber. - */ - ChatModel.prototype.notify = function () { - console.log('Subject: Notifying observers...'); - for (var _i = 0, _a = this.observers; _i < _a.length; _i++) { - var observer = _a[_i]; - observer.update(this.state); - } - }; - ChatModel.prototype.someBusinessMethod = function (activeuserList) { - this.state = activeuserList; - this.helperMethod(); - console.log("Subject: My state has just changed"); - console.log(activeuserList); - this.notify(); - }; - /** - * getActiveUsers - */ - ChatModel.prototype.getActiveUsers = function () { - var _this = this; - this.getActiveUsersAjax(":") - .then(function (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(); - }); - }; - ChatModel.prototype.getActiveUsersAjax = function (authToken2) { - return __awaiter(this, void 0, void 0, function () { - var headers, response, data; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - headers = new Headers(); - // headers.append('Authorization', basicAuthToken); - headers.append('X-AUTH-TOKEN', authToken2); - return [4 /*yield*/, fetch(this.getActiveUsersUrl, { - method: 'GET', - headers: headers - })]; - case 1: - response = _a.sent(); - console.log(response.clone()); - if (FetchErrorHandler_1.fetchErrorHandler(response.clone())) { - return [2 /*return*/, null]; - } - return [4 /*yield*/, response.json()]; - case 2: - data = _a.sent(); - return [2 /*return*/, data]; - } - }); - }); - }; - ChatModel.prototype.helperMethod = function () { }; - return ChatModel; -}()); -exports.ChatModel = ChatModel; - -},{"./FetchErrorHandler":6}],6:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function fetchErrorHandler(response) { - // alertify.success('Current position : ' + alertify.get('notifier', 'position')); - if (!response.ok) { - return response.text().catch(function (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)); - return true; - }).then(function (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)); - console.log(json); - return true; - }); - } -} -exports.fetchErrorHandler = fetchErrorHandler; - -},{}],7:[function(require,module,exports){ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var FetchErrorHandler_1 = require("./FetchErrorHandler"); -var UserModel = /** @class */ (function () { - function UserModel() { - /** - * @type {Observer[]} List of subscribers. In real life, the list of - * subscribers can be stored more comprehensively (categorized by event - * type, etc.). - */ - this.observers = []; - // @ts-ignore: Cannot find name 'hostAddress'. - this.getActiveUsersUrl = ""; - } - /** - * The subscription management methods. - */ - UserModel.prototype.attach = function (observer) { - console.log('Subject: Attached an observer.'); - this.observers.push(observer); - }; - UserModel.prototype.detach = function (observer) { - var observerIndex = this.observers.indexOf(observer); - this.observers.splice(observerIndex, 1); - console.log('Subject: Detached an observer.'); - }; - /** - * Trigger an update in each subscriber. - */ - UserModel.prototype.notify = function () { - console.log('Subject: Notifying observers...'); - for (var _i = 0, _a = this.observers; _i < _a.length; _i++) { - var observer = _a[_i]; - observer.update(this.state); - } - }; - UserModel.prototype.someBusinessMethod = function (activeuserList) { - this.state = activeuserList; - this.helperMethod(); - console.log("Subject: My state has just changed"); - console.log(activeuserList); - this.notify(); - }; - /** - * getActiveUsers - */ - UserModel.prototype.getActiveUsers = function () { - var _this = this; - this.getActiveUsersAjax(":") - .then(function (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(); - }); - }; - UserModel.prototype.getActiveUsersAjax = function (authToken2) { - return __awaiter(this, void 0, void 0, function () { - var headers, response, data; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - headers = new Headers(); - // headers.append('Authorization', basicAuthToken); - headers.append('X-AUTH-TOKEN', authToken2); - return [4 /*yield*/, fetch(this.getActiveUsersUrl, { - method: 'GET', - headers: headers - })]; - case 1: - response = _a.sent(); - console.log(response.clone()); - if (FetchErrorHandler_1.fetchErrorHandler(response.clone())) { - return [2 /*return*/, null]; - } - return [4 /*yield*/, response.json()]; - case 2: - data = _a.sent(); - return [2 /*return*/, data]; - } - }); - }); - }; - UserModel.prototype.helperMethod = function () { }; - return UserModel; -}()); -exports.UserModel = UserModel; - -},{"./FetchErrorHandler":6}],8:[function(require,module,exports){ -(function (global){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var loglevel_1 = __importDefault((typeof window !== "undefined" ? window['log'] : typeof global !== "undefined" ? global['log'] : null)); -var LogLevelLogger = /** @class */ (function () { - function LogLevelLogger() { - loglevel_1.default.setLevel("DEBUG"); - } - LogLevelLogger.prototype.info = function (message) { - loglevel_1.default.info(message); - }; - LogLevelLogger.prototype.warn = function (message) { - loglevel_1.default.warn(message); - }; - LogLevelLogger.prototype.error = function (message) { - loglevel_1.default.error(message); - }; - LogLevelLogger.prototype.debug = function (message) { - loglevel_1.default.debug(message); - }; - return LogLevelLogger; -}()); -exports.LogLevelLogger = LogLevelLogger; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - -},{}],9:[function(require,module,exports){ -(function (global){ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var sjcl_1 = __importDefault((typeof window !== "undefined" ? window['sjcl'] : typeof global !== "undefined" ? global['sjcl'] : null)); -var SJCLEncryptionService = /** @class */ (function () { - function SJCLEncryptionService() { - this.params = { mode: "gcm", ts: 128, adata: "", iter: 10000 }; - } - SJCLEncryptionService.prototype.encrypt = function (passphrase, plainText) { - return sjcl_1.default.encrypt(passphrase, plainText, this.params); - }; - SJCLEncryptionService.prototype.decrypt = function (passphrase, cipher) { - return sjcl_1.default.decrypt(passphrase, cipher, undefined, undefined); - }; - return SJCLEncryptionService; -}()); -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.ActiveUsersGET = "/api/chat/get/active-users/"; -})(JsonAPI = exports.JsonAPI || (exports.JsonAPI = {})); - -},{}],11:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var TemplateFactory = /** @class */ (function () { - function TemplateFactory() { - } - TemplateFactory.getTemplate = function () { - // @ts-ignore: Object is possibly 'null'. - var source = document.getElementById("user-contact-online-template").innerHTML; - var msgContainerTemplate = Handlebars.compile(source); - return msgContainerTemplate; - }; - return TemplateFactory; -}()); -exports.TemplateFactory = TemplateFactory; - -},{}],12:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); - -},{}],13:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var TemplateFactory_1 = require("../template/TemplateFactory"); -var ChatView = /** @class */ (function () { - // private userBoxes: any[] = []; - function ChatView(model, element) { - this._model = model; - this._element = element; - } - Object.defineProperty(ChatView.prototype, "model", { - /** - * Getter model - * @return {Model} - */ - get: function () { - return this._model; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(ChatView.prototype, "element", { - /** - * Getter element - * @return {any} - */ - get: function () { - return this._element; - }, - enumerable: true, - configurable: true - }); - // /** - // * Setter model - // * @param {Model} value - // */ - // public set model(value: Model) { - // this._model = value; - // } - // /** - // * Setter element - // * @param {any} value - // */ - // public set element(value: any) { - // this._element = value; - // } - ChatView.prototype.update = function (data) { - var template = TemplateFactory_1.TemplateFactory.getTemplate(); - var html = ""; - data.forEach(function (element) { - html += template(element); - }); - this.element.innerHTML = html; - this.addUserCallBacks(); - console.log(this.element.innerHTML); - }; - ChatView.prototype.helper = function () { - }; - ChatView.prototype.addUserCallBacks = function () { - var userBoxes = document.getElementsByClassName('user-box'); - for (var i = 0; i < userBoxes.length; i++) { - var userBox = userBoxes[i]; - userBoxes[i].addEventListener('click', this.userCallBack.bind(this, userBox)); - } - }; - ChatView.prototype.userCallBack = function (el) { - var current = document.getElementsByClassName('user-box active'); - var passphrase = ""; - if (current.length > 0) { - if (passphrase == '') { - // alert('Please input passphrase') - // alertify.error('Please enter a passphrase'); - // return; - } - current[0].className = current[0].className.replace(" active", ""); - } - // Add the active class to the current/clicked button - else if (current.length == 0) { - var elem_1 = document.getElementById('passphrase-initial'); - passphrase = ""; - if (passphrase == '') { - // // alert('Please input passphrase') - // // alertify.error('Please enter a passphrase'); - // 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_1.hidden = true; - } - // console.log(this.getElementsByClassName('to-user-span')); - var elem = el.getElementsByClassName('to-user-span')[0]; - var userName = elem.innerText; - // @ts-ignore: Object is possibly 'null'. - document.getElementById('user-name-span').innerText = userName; - // populateMessages(userName, passphrase); - sessionStorage.setItem('selectedUser', userName); - el.className += " active"; - }; - return ChatView; -}()); -exports.ChatView = ChatView; - -},{"../template/TemplateFactory":11}],14:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var TemplateFactory_1 = require("../template/TemplateFactory"); -var UserView = /** @class */ (function () { - // private userBoxes: any[] = []; - function UserView(model, element) { - this._model = model; - this._element = element; - } - Object.defineProperty(UserView.prototype, "model", { - /** - * Getter model - * @return {Model} - */ - get: function () { - return this._model; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(UserView.prototype, "element", { - /** - * Getter element - * @return {any} - */ - get: function () { - return this._element; - }, - enumerable: true, - configurable: true - }); - // /** - // * Setter model - // * @param {Model} value - // */ - // public set model(value: Model) { - // this._model = value; - // } - // /** - // * Setter element - // * @param {any} value - // */ - // public set element(value: any) { - // this._element = value; - // } - UserView.prototype.update = function (data) { - var template = TemplateFactory_1.TemplateFactory.getTemplate(); - var html = ""; - data.forEach(function (element) { - html += template(element); - }); - this.element.innerHTML = html; - this.addUserCallBacks(); - console.log(this.element.innerHTML); - }; - UserView.prototype.helper = function () { - }; - UserView.prototype.addUserCallBacks = function () { - var userBoxes = document.getElementsByClassName('user-box'); - for (var i = 0; i < userBoxes.length; i++) { - var userBox = userBoxes[i]; - userBoxes[i].addEventListener('click', this.userCallBack.bind(this, userBox)); - } - }; - UserView.prototype.userCallBack = function (el) { - var current = document.getElementsByClassName('user-box active'); - var passphrase = ""; - if (current.length > 0) { - if (passphrase == '') { - // alert('Please input passphrase') - // alertify.error('Please enter a passphrase'); - // return; - } - current[0].className = current[0].className.replace(" active", ""); - } - // Add the active class to the current/clicked button - else if (current.length == 0) { - var elem_1 = document.getElementById('passphrase-initial'); - passphrase = ""; - if (passphrase == '') { - // // alert('Please input passphrase') - // // alertify.error('Please enter a passphrase'); - // 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_1.hidden = true; - } - // console.log(this.getElementsByClassName('to-user-span')); - var elem = el.getElementsByClassName('to-user-span')[0]; - var userName = elem.innerText; - // @ts-ignore: Object is possibly 'null'. - document.getElementById('user-name-span').innerText = userName; - // populateMessages(userName, passphrase); - sessionStorage.setItem('selectedUser', userName); - el.className += " active"; - }; - return UserView; -}()); -exports.UserView = UserView; - -},{"../template/TemplateFactory":11}],15:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var ActiveUserViewModel = /** @class */ (function () { - function ActiveUserViewModel() { - } - return ActiveUserViewModel; -}()); -exports.ActiveUserViewModel = ActiveUserViewModel; - -},{}],16:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var ChatMessageViewModel = /** @class */ (function () { - function ChatMessageViewModel() { - } - return ChatMessageViewModel; -}()); -exports.ChatMessageViewModel = ChatMessageViewModel; - -},{}]},{},[3]) -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL3dhdGNoaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJzcmMvY29udHJvbGxlci9DaGF0Q29udHJvbGxlci50cyIsInNyYy9jb250cm9sbGVyL1VzZXJDb250cm9sbGVyLnRzIiwic3JjL21haW4udHMiLCJzcmMvbW9kZWwvQ2hhdE1vZGVsLnRzIiwic3JjL21vZGVsL0ZldGNoRXJyb3JIYW5kbGVyLnRzIiwic3JjL21vZGVsL1VzZXJNb2RlbC50cyIsInNyYy9zZXJ2aWNlL0xvZ0xldmVsTG9nZ2VyU2VydmljZS50cyIsInNyYy9zZXJ2aWNlL1NKQ0xFbmNyeXB0aW9uU2VydmljZS50cyIsInNyYy9zaW5nbGV0b24vSnNvbkFQSS50cyIsInNyYy90ZW1wbGF0ZS9UZW1wbGF0ZUZhY3RvcnkudHMiLCJzcmMvdmlldy9DaGF0Vmlldy50cyIsInNyYy92aWV3L1VzZXJWaWV3LnRzIiwic3JjL3ZpZXdtb2RlbC9BY3RpdmVVc2VyVmlld01vZGVsLnRzIiwic3JjL3ZpZXdtb2RlbC9DaGF0TWVzc2FnZVZpZXdNb2RlbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0FDQ0Esa0NBQStCO0FBQy9CLDhCQUEyQjtBQUMzQixnQ0FBNkI7QUFDN0IsNEJBQXlCO0FBR3pCLDBFQUF5RTtBQUV6RTtJQUtJLHdCQUFZLEtBQVksRUFBRSxJQUFVO1FBQ2hDLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO0lBQ3RCLENBQUM7SUFNRCxzQkFBVyxpQ0FBSztRQUpoQjs7O1dBR0c7YUFDSDtZQUNJLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUN2QixDQUFDO1FBVUQ7OztXQUdHO2FBQ0gsVUFBaUIsS0FBWTtZQUN6QixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUss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SUFBSSxDQUFDO1lBQzFELHlDQUF5QztZQUN6QyxRQUFRLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7WUFDcEQseUNBQXlDO1lBQ3pDLE1BQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1NBQ3RCO1FBQ0QsNERBQTREO1FBQzVELElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQWdCLENBQUM7UUFDdkUsSUFBSSxRQUFRLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztRQUM5Qix5Q0FBeUM7UUFDekMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUM7UUFDL0QsMENBQTBDO1FBQzFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ2pELEVBQUUsQ0FBQyxTQUFTLElBQUksU0FBUyxDQUFDO0lBQzlCLENBQUM7SUFFTCxlQUFDO0FBQUQsQ0FqSEEsQUFpSEMsSUFBQTtBQWpIWSw0QkFBUTs7Ozs7QUNSckI7SUFBQTtJQUlBLENBQUM7SUFBRCwwQkFBQztBQUFELENBSkEsQUFJQyxJQUFBO0FBSlksa0RBQW1COzs7OztBQ0FoQztJQUFBO0lBT0EsQ0FBQztJQUFELDJCQUFDO0FBQUQsQ0FQQSxBQU9DLElBQUE7QUFQWSxvREFBb0IiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCJpbXBvcnQgeyBDb250cm9sbGVyIH0gZnJvbSBcIi4vQWJzdHJhY3RDb250cm9sbGVyXCI7XG5pbXBvcnQgXCIuLi9tb2RlbC9BYnN0cmFjdE1vZGVsXCJcbmltcG9ydCBcIi4uL21vZGVsL1VzZXJNb2RlbFwiXG5pbXBvcnQgXCIuLi92aWV3L0Fic3RyYWN0Vmlld1wiXG5pbXBvcnQgXCIuLi92aWV3L1VzZXJWaWV3XCJcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL0Fic3RyYWN0TW9kZWxcIjtcbmltcG9ydCB7IFZpZXcgfSBmcm9tIFwiLi4vdmlldy9BYnN0cmFjdFZpZXdcIjtcbmltcG9ydCB7IENoYXRNZXNzYWdlVmlld01vZGVsIH0gZnJvbSBcIi4uL3ZpZXdtb2RlbC9DaGF0TWVzc2FnZVZpZXdNb2RlbFwiO1xuXG5leHBvcnQgY2xhc3MgQ2hhdENvbnRyb2xsZXIgaW1wbGVtZW50cyBDb250cm9sbGVye1xuICAgIHByaXZhdGUgX21vZGVsOiBNb2RlbDtcbiAgICBwcml2YXRlIF92aWV3OiBWaWV3O1xuXG5cbiAgICBjb25zdHJ1Y3Rvcihtb2RlbDogTW9kZWwsIHZpZXc6IFZpZXcpIHtcbiAgICAgICAgdGhpcy5fbW9kZWwgPSBtb2RlbDtcbiAgICAgICAgdGhpcy5fdmlldyA9IHZpZXc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0dGVyIG1vZGVsXG4gICAgICogQHJldHVybiB7TW9kZWx9XG4gICAgICovXG4gICAgcHVibGljIGdldCBtb2RlbCgpOiBNb2RlbCB7XG4gICAgICAgIHJldHVybiB0aGlzLl9tb2RlbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXR0ZXIgdmlld1xuICAgICAqIEByZXR1cm4ge1ZpZXd9XG4gICAgICovXG4gICAgcHVibGljIGdldCB2aWV3KCk6IFZpZXcge1xuICAgICAgICByZXR1cm4gdGhpcy5fdmlldztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXR0ZXIgbW9kZWxcbiAgICAgKiBAcGFyYW0ge01vZGVsfSB2YWx1ZVxuICAgICAqL1xuICAgIHB1YmxpYyBzZXQgbW9kZWwodmFsdWU6IE1vZGVsKSB7XG4gICAgICAgIHRoaXMuX21vZGVsID0gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0dGVyIHZpZXdcbiAgICAgKiBAcGFyYW0ge1ZpZXd9IHZhbHVlXG4gICAgICovXG4gICAgcHVibGljIHNldCB2aWV3KHZhbHVlOiBWaWV3KSB7XG4gICAgICAgIHRoaXMuX3ZpZXcgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBldmVudEhhbmRsZXJcbiAgICAgKi9cbiAgICBwdWJsaWMgZXZlbnRIYW5kbGVyKHZtOiBDaGF0TWVzc2FnZVZpZXdNb2RlbFtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMubW9kZWwuc29tZUJ1c2luZXNzTWV0aG9kKHZtKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgdGVzdCgpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY2hhdE1lc3NhZ2VWaWV3TW9kZWxzOiBDaGF0TWVzc2FnZVZpZXdNb2RlbFtdID0gW107XG4gICAgICAgIGxldCBjaGF0TWVzc2FnZVZpZXdNb2RlbE1vY2sgPSBuZXcgQ2hhdE1lc3NhZ2VWaWV3TW9kZWwoKTtcbiAgICAgICAgY2hhdE1lc3NhZ2VWaWV3TW9kZWxNb2NrLmZyb21Vc2VyID0gXCJ1c2VyMVwiO1xuICAgICAgICBjaGF0TWVzc2FnZVZpZXdNb2RlbE1vY2sudG9Vc2VyID0gXCJ1c2VyMlwiO1xuICAgICAgICBjaGF0TWVzc2FnZVZpZXdNb2RlbE1vY2subWVzc2FnZUNpcGhlciA9IFwiXCI7XG4gICAgICAgIGNoYXRNZXNzYWdlVmlld01vZGVsTW9jay5tZXNzYWdlVGltZSA9IG5ldyBEYXRlKCk7XG4gICAgICAgIGNoYXRNZXNzYWdlVmlld01vZGVscy5wdXNoKGNoYXRNZXNzYWdlVmlld01vZGVsTW9jayk7XG4gICAgfVxuXG4gICAgXG59IiwiaW1wb3J0IHsgQ29udHJvbGxlciB9IGZyb20gXCIuL0Fic3RyYWN0Q29udHJvbGxlclwiO1xuaW1wb3J0IFwiLi4vbW9kZWwvQWJzdHJhY3RNb2RlbFwiXG5pbXBvcnQgXCIuLi9tb2RlbC9Vc2VyTW9kZWxcIlxuaW1wb3J0IFwiLi4vdmlldy9BYnN0cmFjdFZpZXdcIlxuaW1wb3J0IFwiLi4vdmlldy9Vc2VyVmlld1wiXG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCIuLi9tb2RlbC9BYnN0cmFjdE1vZGVsXCI7XG5pbXBvcnQgeyBWaWV3IH0gZnJvbSBcIi4uL3ZpZXcvQWJzdHJhY3RWaWV3XCI7XG5pbXBvcnQgeyBBY3RpdmVVc2VyVmlld01vZGVsIH0gZnJvbSBcIi4uL3ZpZXdtb2RlbC9BY3RpdmVVc2VyVmlld01vZGVsXCI7XG5cbmV4cG9ydCBjbGFzcyBVc2VyQ29udHJvbGxlciBpbXBsZW1lbnRzIENvbnRyb2xsZXJ7XG4gICAgcHJpdmF0ZSBfbW9kZWw6IE1vZGVsO1xuICAgIHByaXZhdGUgX3ZpZXc6IFZpZXc7XG5cblxuICAgIGNvbnN0cnVjdG9yKG1vZGVsOiBNb2RlbCwgdmlldzogVmlldykge1xuICAgICAgICB0aGlzLl9tb2RlbCA9IG1vZGVsO1xuICAgICAgICB0aGlzLl92aWV3ID0gdmlldztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXR0ZXIgbW9kZWxcbiAgICAgKiBAcmV0dXJuIHtNb2RlbH1cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IG1vZGVsKCk6IE1vZGVsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21vZGVsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHRlciB2aWV3XG4gICAgICogQHJldHVybiB7Vmlld31cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IHZpZXcoKTogVmlldyB7XG4gICAgICAgIHJldHVybiB0aGlzLl92aWV3O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHRlciBtb2RlbFxuICAgICAqIEBwYXJhbSB7TW9kZWx9IHZhbHVlXG4gICAgICovXG4gICAgcHVibGljIHNldCBtb2RlbCh2YWx1ZTogTW9kZWwpIHtcbiAgICAgICAgdGhpcy5fbW9kZWwgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXR0ZXIgdmlld1xuICAgICAqIEBwYXJhbSB7Vmlld30gdmFsdWVcbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0IHZpZXcodmFsdWU6IFZpZXcpIHtcbiAgICAgICAgdGhpcy5fdmlldyA9IHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIGV2ZW50SGFuZGxlclxuICAgICAqL1xuICAgIHB1YmxpYyBldmVudEhhbmRsZXIodm06IEFjdGl2ZVVzZXJWaWV3TW9kZWxbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLm1vZGVsLnNvbWVCdXNpbmVzc01ldGhvZCh2bSk7XG4gICAgfVxuXG4gICAgcHVibGljIHRlc3QoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGFjdGl2ZVVzZXJzTW9jazogQWN0aXZlVXNlclZpZXdNb2RlbFtdID0gW107XG4gICAgICAgIGxldCBhY3RpdmVVc2VyVmlld01vZGVsTW9jayA9IG5ldyBBY3RpdmVVc2VyVmlld01vZGVsKCk7XG4gICAgICAgIGFjdGl2ZVVzZXJWaWV3TW9kZWxNb2NrLnVzZXJOYW1lID0gXCJzb21lIHVzZXJcIjtcbiAgICAgICAgYWN0aXZlVXNlclZpZXdNb2RlbE1vY2subGFzdEFjdGl2ZSA9IFwiMyBocnMgYWdvXCI7XG4gICAgICAgIGFjdGl2ZVVzZXJWaWV3TW9kZWxNb2NrLm9ubGluZSA9IHRydWU7XG4gICAgICAgIGFjdGl2ZVVzZXJzTW9jay5wdXNoKGFjdGl2ZVVzZXJWaWV3TW9kZWxNb2NrKTtcbiAgICAgICAgYWN0aXZlVXNlclZpZXdNb2RlbE1vY2sgPSBuZXcgQWN0aXZlVXNlclZpZXdNb2RlbCgpO1xuICAgICAgICBhY3RpdmVVc2VyVmlld01vZGVsTW9jay5sYXN0QWN0aXZlID0gXCIzIGhycyBhZ29cIjtcbiAgICAgICAgYWN0aXZlVXNlclZpZXdNb2RlbE1vY2sub25saW5lID0gdHJ1ZTtcbiAgICAgICAgYWN0aXZlVXNlclZpZXdNb2RlbE1vY2sudXNlck5hbWUgPSBcInNvbWUgdXNlciAyXCI7XG4gICAgICAgIGFjdGl2ZVVzZXJzTW9jay5wdXNoKGFjdGl2ZVVzZXJWaWV3TW9kZWxNb2NrKTtcbiAgICAgICAgdGhpcy5ldmVudEhhbmRsZXIoYWN0aXZlVXNlcnNNb2NrKTtcbiAgICB9XG5cbiAgICBcbn0iLCJpbXBvcnQgeyBDb250cm9sbGVyIH0gZnJvbSBcIi4vY29udHJvbGxlci9BYnN0cmFjdENvbnRyb2xsZXJcIjtcbmltcG9ydCB7IFVzZXJNb2RlbCB9IGZyb20gXCIuL21vZGVsL1VzZXJNb2RlbFwiXG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCIuL21vZGVsL0Fic3RyYWN0TW9kZWxcIjtcbmltcG9ydCB7IFZpZXcgfSBmcm9tIFwiLi92aWV3L0Fic3RyYWN0Vmlld1wiO1xuaW1wb3J0IHsgVXNlclZpZXcgfSBmcm9tIFwiLi92aWV3L1VzZXJWaWV3XCI7XG5pbXBvcnQgeyBVc2VyQ29udHJvbGxlciB9IGZyb20gXCIuL2NvbnRyb2xsZXIvVXNlckNvbnRyb2xsZXJcIjtcbmltcG9ydCBsb2cgZnJvbSBcImxvZ2xldmVsXCI7XG5pbXBvcnQgeyBNb2RlbEZhY3RvcnkgfSBmcm9tIFwiLi9tb2RlbC9Nb2RlbEZhY3RvcnlcIjtcbmltcG9ydCB7IEFjdGl2ZVVzZXJWaWV3TW9kZWwgfSBmcm9tIFwiLi92aWV3bW9kZWwvQWN0aXZlVXNlclZpZXdNb2RlbFwiO1xuaW1wb3J0IHsgQ2hhdE1lc3NhZ2VWaWV3TW9kZWwgfSBmcm9tIFwiLi92aWV3bW9kZWwvQ2hhdE1lc3NhZ2VWaWV3TW9kZWxcIjtcbmltcG9ydCBIYW5kbGViYXJzIGZyb20gXCJoYW5kbGViYXJzXCI7XG5pbXBvcnQgbWFya2Rvd25pdCBmcm9tIFwibWFya2Rvd24taXRcIjtcbmltcG9ydCB7IENoYXRNb2RlbCB9IGZyb20gXCIuL21vZGVsL0NoYXRNb2RlbFwiO1xuaW1wb3J0IHsgQ2hhdFZpZXcgfSBmcm9tIFwiLi92aWV3L0NoYXRWaWV3XCI7XG5pbXBvcnQgeyBDaGF0Q29udHJvbGxlciB9IGZyb20gXCIuL2NvbnRyb2xsZXIvQ2hhdENvbnRyb2xsZXJcIjtcbmltcG9ydCB7IEpzb25BUEkgfSBmcm9tIFwiLi9zaW5nbGV0b24vSnNvbkFQSVwiO1xuaW1wb3J0IHsgU0pDTEVuY3J5cHRpb25TZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZS9TSkNMRW5jcnlwdGlvblNlcnZpY2VcIjtcbmltcG9ydCB7IEVuY3J5cHRpb25TZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZS9FbmNyeXB0aW9uU2VydmljZVwiO1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSBcIi4vc2VydmljZS9Mb2dnZXJTZXJ2aWNlXCI7XG5pbXBvcnQgeyBMb2dMZXZlbExvZ2dlciB9IGZyb20gXCIuL3NlcnZpY2UvTG9nTGV2ZWxMb2dnZXJTZXJ2aWNlXCI7XG4vLyBpbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwiLi9zaW5nbGV0b24vTG9nZ2VyXCI7XG4vLyB2YXIgbWFya2Rvd25pdCA9IHJlcXVpcmUoJ21hcmtkb3duLWl0Jyk7XG52YXIgbWQgPSBuZXcgbWFya2Rvd25pdCgpO1xuXG5jb25zdCBsb2dnZXI6IExvZ2dlciA9IG5ldyBMb2dMZXZlbExvZ2dlcigpO1xuXG5sZXQgdXNlckJveCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdjb250YWN0cy1ib3gnKTtcblxubG9nLnNldExldmVsKFwiVFJBQ0VcIilcbmxldCB1c2VyTW9kZWwgPSBuZXcgVXNlck1vZGVsKCk7XG4vLyBjb25zdCB1c2VyTW9kZWwgPSBNb2RlbEZhY3RvcnkuY3JlYXRlTW9kZWwoXCJVU0VSXCIpO1xuLy8gQHRzLWlnbm9yZTogQXJndW1lbnQgb2YgdHlwZSAnSFRNTEVsZW1lbnQgfCBudWxsJyBpcyBub3QgYXNzaWduYWJsZSB0byBwYXJhbWV0ZXIgb2YgdHlwZSAnSFRNTEVsZW1lbnQnLiBUeXBlICdudWxsJyBpcyBub3QgYXNzaWduYWJsZSB0byB0eXBlICdIVE1MRWxlbWVudCcuXG5jb25zdCB1c2VyVmlldyA9IG5ldyBVc2VyVmlldyh1c2VyTW9kZWwsIHVzZXJCb3gpO1xuXG4vLyBjb25zb2xlLmxvZyh1c2VyQm94KTtcblxudXNlck1vZGVsLmF0dGFjaCh1c2VyVmlldyk7XG4vLyB1c2VyVmlldy5tb2RlbFxuY29uc3QgdXNlckNvbnRyb2xsZXIgPSBuZXcgVXNlckNvbnRyb2xsZXIodXNlck1vZGVsLCB1c2VyVmlldyk7XG51c2VyQ29udHJvbGxlci50ZXN0KCk7XG5cblxuXG4vLyB1c2VyTW9kZWwuc29tZUJ1c2luZXNzTWV0aG9kKGFjdGl2ZVVzZXJzTW9jayk7XG5sb2cuaW5mbyhcImhlbGxvXCIpO1xuXG5jb25zdCBjaGF0TW9kZWwgPSBuZXcgQ2hhdE1vZGVsKCk7XG4vLyBAdHMtaWdub3JlOiBBcmd1bWVudCBvZiB0eXBlICdIVE1MRWxlbWVudCB8IG51bGwnIGlzIG5vdCBhc3NpZ25hYmxlIHRvIHBhcmFtZXRlciBvZiB0eXBlICdIVE1MRWxlbWVudCcuIFR5cGUgJ251bGwnIGlzIG5vdCBhc3NpZ25hYmxlIHRvIHR5cGUgJ0hUTUxFbGVtZW50Jy5cbmNvbnN0IGNoYXRWaWV3ID0gbmV3IENoYXRWaWV3KGNoYXRNb2RlbCwgdXNlckJveCk7XG5jb25zdCBjaGF0Q29udHJvbGxlciA9IG5ldyBDaGF0Q29udHJvbGxlcihjaGF0TW9kZWwsIGNoYXRWaWV3KTtcblxuXG5mdW5jdGlvbiBzb21lRnVuYyh2bTogQWN0aXZlVXNlclZpZXdNb2RlbCk6IHZvaWQge1xuICAgIC8vIGxvZy5pbmZvKHZtKTtcbiAgICAvLyBsb2dnZXIuaW5mbyh2bSlcbn1cblxubG9nZ2VyLmluZm8oXCJ0ZXN0XCIpO1xuLy8gc29tZUZ1bmMoYWN0aXZlVXNlclZpZXdNb2RlbE1vY2spO1xuXG4vLyBAdHMtaWdub3JlOiBPYmplY3QgaXMgcG9zc2libHkgJ251bGwnLlxudmFyIHNvdXJjZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwibXNnX2NvbnRhaW5lcl90ZW1wbGF0ZVwiKS5pbm5lckhUTUw7XG5cbnZhciBtc2dDb250YWluZXJUZW1wbGF0ZSA9IEhhbmRsZWJhcnMuY29tcGlsZShzb3VyY2UpO1xuXG5Kc29uQVBJLkFjdGl2ZVVzZXJzR0VUXG5cbmxldCBlbmNyeXB0aW9uU2VydmljZTogRW5jcnlwdGlvblNlcnZpY2UgPSBuZXcgU0pDTEVuY3J5cHRpb25TZXJ2aWNlKCk7XG5sZXQgY3QgPSBlbmNyeXB0aW9uU2VydmljZS5lbmNyeXB0KFwicGFzc3dvcmRcIixcImRhdGFcIik7XG5jb25zb2xlLmxvZyhlbmNyeXB0aW9uU2VydmljZS5kZWNyeXB0KFwicGFzc3dvcmRcIiwgY3QpKTsiLCJpbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSBcIi4uL29ic2VydmUvT2JzZXJ2YWJsZVwiO1xuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiLi9BYnN0cmFjdE1vZGVsXCI7XG5pbXBvcnQgeyBPYnNlcnZlciB9IGZyb20gXCIuLi9vYnNlcnZlL09ic2VydmVyXCI7XG5pbXBvcnQgeyBmZXRjaEVycm9ySGFuZGxlciB9IGZyb20gXCIuL0ZldGNoRXJyb3JIYW5kbGVyXCI7XG5pbXBvcnQgeyBBY3RpdmVVc2VyVmlld01vZGVsIH0gZnJvbSBcIi4uL3ZpZXdtb2RlbC9BY3RpdmVVc2VyVmlld01vZGVsXCI7XG5pbXBvcnQgeyBDaGF0TWVzc2FnZVZpZXdNb2RlbCB9IGZyb20gXCIuLi92aWV3bW9kZWwvQ2hhdE1lc3NhZ2VWaWV3TW9kZWxcIjtcblxuZXhwb3J0IGNsYXNzIENoYXRNb2RlbCBpbXBsZW1lbnRzIE1vZGVsLCBTdWJqZWN0IHtcbiAgICAvKipcbiAgKiBAdHlwZSB7T2JzZXJ2ZXJbXX0gTGlzdCBvZiBzdWJzY3JpYmVycy4gSW4gcmVhbCBsaWZlLCB0aGUgbGlzdCBvZlxuICAqIHN1YnNjcmliZXJzIGNhbiBiZSBzdG9yZWQgbW9yZSBjb21wcmVoZW5zaXZlbHkgKGNhdGVnb3JpemVkIGJ5IGV2ZW50XG4gICogdHlwZSwgZXRjLikuXG4gICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBvYnNlcnZlcnM6IE9ic2VydmVyW10gPSBbXTtcbiAgICBwcml2YXRlIHN0YXRlOiBDaGF0TWVzc2FnZVZpZXdNb2RlbFtdIHwgdW5kZWZpbmVkO1xuICAgIC8vIEB0cy1pZ25vcmU6IENhbm5vdCBmaW5kIG5hbWUgJ2hvc3RBZGRyZXNzJy5cbiAgICBnZXRBY3RpdmVVc2Vyc1VybCA9IFwiXCI7XG5cbiAgICBjb25zdHJ1Y3RvcigpIHsgfVxuICAgIC8qKlxuICAgICAqIFRoZSBzdWJzY3JpcHRpb24gbWFuYWdlbWVudCBtZXRob2RzLlxuICAgICAqL1xuICAgIHB1YmxpYyBhdHRhY2gob2JzZXJ2ZXI6IE9ic2VydmVyKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdTdWJqZWN0OiBBdHRhY2hlZCBhbiBvYnNlcnZlci4nKTtcbiAgICAgICAgdGhpcy5vYnNlcnZlcnMucHVzaChvYnNlcnZlcik7XG4gICAgfVxuXG4gICAgcHVibGljIGRldGFjaChvYnNlcnZlcjogT2JzZXJ2ZXIpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgb2JzZXJ2ZXJJbmRleCA9IHRoaXMub2JzZXJ2ZXJzLmluZGV4T2Yob2JzZXJ2ZXIpO1xuICAgICAgICB0aGlzLm9ic2VydmVycy5zcGxpY2Uob2JzZXJ2ZXJJbmRleCwgMSk7XG4gICAgICAgIGNvbnNvbGUubG9nKCdTdWJqZWN0OiBEZXRhY2hlZCBhbiBvYnNlcnZlci4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcmlnZ2VyIGFuIHVwZGF0ZSBpbiBlYWNoIHN1YnNjcmliZXIuXG4gICAgICovXG4gICAgcHVibGljIG5vdGlmeSgpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5sb2coJ1N1YmplY3Q6IE5vdGlmeWluZyBvYnNlcnZlcnMuLi4nKTtcbiAgICAgICAgZm9yIChjb25zdCBvYnNlcnZlciBvZiB0aGlzLm9ic2VydmVycykge1xuICAgICAgICAgICAgb2JzZXJ2ZXIudXBkYXRlKHRoaXMuc3RhdGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHNvbWVCdXNpbmVzc01ldGhvZChhY3RpdmV1c2VyTGlzdDogQ2hhdE1lc3NhZ2VWaWV3TW9kZWxbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLnN0YXRlID0gYWN0aXZldXNlckxpc3Q7XG4gICAgICAgIHRoaXMuaGVscGVyTWV0aG9kKCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGBTdWJqZWN0OiBNeSBzdGF0ZSBoYXMganVzdCBjaGFuZ2VkYCk7XG4gICAgICAgIGNvbnNvbGUubG9nKGFjdGl2ZXVzZXJMaXN0KTtcbiAgICAgICAgdGhpcy5ub3RpZnkoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBnZXRBY3RpdmVVc2Vyc1xuICAgICAqL1xuICAgIHB1YmxpYyBnZXRBY3RpdmVVc2VycygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRBY3RpdmVVc2Vyc0FqYXgoXCI6XCIpXG4gICAgICAgIC50aGVuKGRhdGEgPT4ge1xuICAgICAgICAgICAgLy8gLy8gYWN0aXZlVXNlcnMgPSBkYXRhO1xuICAgICAgICAgICAgLy8gc2Vzc2lvblN0b3JhZ2Uuc2V0SXRlbSgnYWN0aXZlVXNlcnMnLCBKU09OLnN0cmluZ2lmeShkYXRhKSk7XG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhzZXNzaW9uU3RvcmFnZS5nZXRJdGVtKCdhY3RpdmVVc2VycycpKTtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBTdWJqZWN0OiByZWNlaXZlZCBhamF4IGFjdGl2ZSB1c2Vyc2ApO1xuICAgICAgICAgICAgdGhpcy5zdGF0ZSA9IGRhdGE7XG4gICAgICAgICAgICB0aGlzLm5vdGlmeSgpO1xuICAgICAgICB9KVxuICAgIH1cblxuICAgIGFzeW5jIGdldEFjdGl2ZVVzZXJzQWpheChhdXRoVG9rZW4yOiBzdHJpbmcpIHtcbiAgICAgICAgbGV0IGhlYWRlcnMgPSBuZXcgSGVhZGVycygpO1xuICAgICAgICAvLyBoZWFkZXJzLmFwcGVuZCgnQXV0aG9yaXphdGlvbicsIGJhc2ljQXV0aFRva2VuKTtcbiAgICAgICAgaGVhZGVycy5hcHBlbmQoJ1gtQVVUSC1UT0tFTicsIGF1dGhUb2tlbjIpO1xuICAgICAgICBsZXQgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh0aGlzLmdldEFjdGl2ZVVzZXJzVXJsLCB7XG4gICAgICAgICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgICAgICAgaGVhZGVyczogaGVhZGVyc1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5sb2cocmVzcG9uc2UuY2xvbmUoKSk7XG4gICAgICAgIGlmIChmZXRjaEVycm9ySGFuZGxlcihyZXNwb25zZS5jbG9uZSgpKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGRhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cbiAgICBcbiAgICBwcml2YXRlIGhlbHBlck1ldGhvZCgpIHt9XG5cbn0iLCJleHBvcnQgZnVuY3Rpb24gZmV0Y2hFcnJvckhhbmRsZXIocmVzcG9uc2U6IFJlc3BvbnNlKSB7XG4gICAgLy8gYWxlcnRpZnkuc3VjY2VzcygnQ3VycmVudCBwb3NpdGlvbiA6ICcgKyBhbGVydGlmeS5nZXQoJ25vdGlmaWVyJywgJ3Bvc2l0aW9uJykpO1xuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLnRleHQoKS5jYXRjaChlcnIgPT4ge1xuICAgICAgICAgICAgLy8gdGhlIHN0YXR1cyB3YXMgbm90IG9rIGFuZCB0aGVyZSBpcyBubyBqc29uIGJvZHlcbiAgICAgICAgICAgIC8vIHRocm93IG5ldyBFcnJvcihyZXNwb25zZS5zdGF0dXNUZXh0KTtcbiAgICAgICAgICAgIC8vIHdpbmRvdy5hbGVydChzcHJpbnRmKCdTb21lIGVycm9yIG9jY3VyZWQuIEh0dHAgY29kZSBpcyAlcycsIHJlc3BvbnNlLnN0YXR1cykpO1xuICAgICAgICAgICAgLy8gYWxlcnRpZnkuZXJyb3Ioc3ByaW50ZignU29tZSBlcnJvciBvY2N1cmVkLiBIdHRwIGNvZGUgaXMgJXMnLCByZXNwb25zZS5zdGF0dXMpKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KS50aGVuKGpzb24gPT4ge1xuICAgICAgICAgICAgLy8gdGhlIHN0YXR1cyB3YXMgbm90IG9rIGJ1dCB0aGVyZSBpcyBhIGpzb24gYm9keVxuICAgICAgICAgICAgLy8gdGhyb3cgbmV3IEVycm9yKGpzb24uZXJyb3IubWVzc2FnZSk7IC8vIGV4YW1wbGUgZXJyb3IgbWVzc2FnZSByZXR1cm5lZCBieSBhIFJFU1QgQVBJXG4gICAgICAgICAgICAvLyB3aW5kb3cuYWxlcnQoc3ByaW50ZignRXJyb3I6ICVzIChIdHRwIGNvZGUgJXMpJywganNvbiwgcmVzcG9uc2Uuc3RhdHVzKSk7XG4gICAgICAgICAgICAvLyBhbGVydGlmeS5lcnJvcihzcHJpbnRmKCdTb21lIGVycm9yIG9jY3VyZWQuIEh0dHAgY29kZSBpcyAlcycsIHJlc3BvbnNlLnN0YXR1cykpO1xuICAgICAgICAgICAgY29uc29sZS5sb2coanNvbik7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgfVxufSIsImltcG9ydCB7IFN1YmplY3QgfSBmcm9tIFwiLi4vb2JzZXJ2ZS9PYnNlcnZhYmxlXCI7XG5pbXBvcnQgeyBNb2RlbCB9IGZyb20gXCIuL0Fic3RyYWN0TW9kZWxcIjtcbmltcG9ydCB7IE9ic2VydmVyIH0gZnJvbSBcIi4uL29ic2VydmUvT2JzZXJ2ZXJcIjtcbmltcG9ydCB7IGZldGNoRXJyb3JIYW5kbGVyIH0gZnJvbSBcIi4vRmV0Y2hFcnJvckhhbmRsZXJcIjtcbmltcG9ydCB7IEFjdGl2ZVVzZXJWaWV3TW9kZWwgfSBmcm9tIFwiLi4vdmlld21vZGVsL0FjdGl2ZVVzZXJWaWV3TW9kZWxcIjtcblxuZXhwb3J0IGNsYXNzIFVzZXJNb2RlbCBpbXBsZW1lbnRzIE1vZGVsLCBTdWJqZWN0IHtcbiAgICAvKipcbiAgKiBAdHlwZSB7T2JzZXJ2ZXJbXX0gTGlzdCBvZiBzdWJzY3JpYmVycy4gSW4gcmVhbCBsaWZlLCB0aGUgbGlzdCBvZlxuICAqIHN1YnNjcmliZXJzIGNhbiBiZSBzdG9yZWQgbW9yZSBjb21wcmVoZW5zaXZlbHkgKGNhdGVnb3JpemVkIGJ5IGV2ZW50XG4gICogdHlwZSwgZXRjLikuXG4gICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBvYnNlcnZlcnM6IE9ic2VydmVyW10gPSBbXTtcbiAgICBwcml2YXRlIHN0YXRlOiBBY3RpdmVVc2VyVmlld01vZGVsW10gfCB1bmRlZmluZWQ7XG4gICAgLy8gQHRzLWlnbm9yZTogQ2Fubm90IGZpbmQgbmFtZSAnaG9zdEFkZHJlc3MnLlxuICAgIGdldEFjdGl2ZVVzZXJzVXJsID0gYGA7XG5cbiAgICBjb25zdHJ1Y3RvcigpIHsgfVxuICAgIC8qKlxuICAgICAqIFRoZSBzdWJzY3JpcHRpb24gbWFuYWdlbWVudCBtZXRob2RzLlxuICAgICAqL1xuICAgIHB1YmxpYyBhdHRhY2gob2JzZXJ2ZXI6IE9ic2VydmVyKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdTdWJqZWN0OiBBdHRhY2hlZCBhbiBvYnNlcnZlci4nKTtcbiAgICAgICAgdGhpcy5vYnNlcnZlcnMucHVzaChvYnNlcnZlcik7XG4gICAgfVxuXG4gICAgcHVibGljIGRldGFjaChvYnNlcnZlcjogT2JzZXJ2ZXIpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgb2JzZXJ2ZXJJbmRleCA9IHRoaXMub2JzZXJ2ZXJzLmluZGV4T2Yob2JzZXJ2ZXIpO1xuICAgICAgICB0aGlzLm9ic2VydmVycy5zcGxpY2Uob2JzZXJ2ZXJJbmRleCwgMSk7XG4gICAgICAgIGNvbnNvbGUubG9nKCdTdWJqZWN0OiBEZXRhY2hlZCBhbiBvYnNlcnZlci4nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcmlnZ2VyIGFuIHVwZGF0ZSBpbiBlYWNoIHN1YnNjcmliZXIuXG4gICAgICovXG4gICAgcHVibGljIG5vdGlmeSgpOiB2b2lkIHtcbiAgICAgICAgY29uc29sZS5sb2coJ1N1YmplY3Q6IE5vdGlmeWluZyBvYnNlcnZlcnMuLi4nKTtcbiAgICAgICAgZm9yIChjb25zdCBvYnNlcnZlciBvZiB0aGlzLm9ic2VydmVycykge1xuICAgICAgICAgICAgb2JzZXJ2ZXIudXBkYXRlKHRoaXMuc3RhdGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIHNvbWVCdXNpbmVzc01ldGhvZChhY3RpdmV1c2VyTGlzdDogQWN0aXZlVXNlclZpZXdNb2RlbFtdKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBhY3RpdmV1c2VyTGlzdDtcbiAgICAgICAgdGhpcy5oZWxwZXJNZXRob2QoKTtcbiAgICAgICAgY29uc29sZS5sb2coYFN1YmplY3Q6IE15IHN0YXRlIGhhcyBqdXN0IGNoYW5nZWRgKTtcbiAgICAgICAgY29uc29sZS5sb2coYWN0aXZldXNlckxpc3QpO1xuICAgICAgICB0aGlzLm5vdGlmeSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIGdldEFjdGl2ZVVzZXJzXG4gICAgICovXG4gICAgcHVibGljIGdldEFjdGl2ZVVzZXJzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmdldEFjdGl2ZVVzZXJzQWpheChcIjpcIilcbiAgICAgICAgLnRoZW4oZGF0YSA9PiB7XG4gICAgICAgICAgICAvLyAvLyBhY3RpdmVVc2VycyA9IGRhdGE7XG4gICAgICAgICAgICAvLyBzZXNzaW9uU3RvcmFnZS5zZXRJdGVtKCdhY3RpdmVVc2VycycsIEpTT04uc3RyaW5naWZ5KGRhdGEpKTtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKHNlc3Npb25TdG9yYWdlLmdldEl0ZW0oJ2FjdGl2ZVVzZXJzJykpO1xuICAgICAgICAgICAgY29uc29sZS5sb2coYFN1YmplY3Q6IHJlY2VpdmVkIGFqYXggYWN0aXZlIHVzZXJzYCk7XG4gICAgICAgICAgICB0aGlzLnN0YXRlID0gZGF0YTtcbiAgICAgICAgICAgIHRoaXMubm90aWZ5KCk7XG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgYXN5bmMgZ2V0QWN0aXZlVXNlcnNBamF4KGF1dGhUb2tlbjI6IHN0cmluZykge1xuICAgICAgICBsZXQgaGVhZGVycyA9IG5ldyBIZWFkZXJzKCk7XG4gICAgICAgIC8vIGhlYWRlcnMuYXBwZW5kKCdBdXRob3JpemF0aW9uJywgYmFzaWNBdXRoVG9rZW4pO1xuICAgICAgICBoZWFkZXJzLmFwcGVuZCgnWC1BVVRILVRPS0VOJywgYXV0aFRva2VuMik7XG4gICAgICAgIGxldCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHRoaXMuZ2V0QWN0aXZlVXNlcnNVcmwsIHtcbiAgICAgICAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICAgICAgICBoZWFkZXJzOiBoZWFkZXJzXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zb2xlLmxvZyhyZXNwb25zZS5jbG9uZSgpKTtcbiAgICAgICAgaWYgKGZldGNoRXJyb3JIYW5kbGVyKHJlc3BvbnNlLmNsb25lKCkpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBsZXQgZGF0YSA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuICAgIFxuICAgIHByaXZhdGUgaGVscGVyTWV0aG9kKCkge31cblxufSIsImltcG9ydCB7IExvZ2dlciB9IGZyb20gXCIuL0xvZ2dlclNlcnZpY2VcIjtcbmltcG9ydCBsb2cgZnJvbSBcImxvZ2xldmVsXCJcblxuZXhwb3J0IGNsYXNzIExvZ0xldmVsTG9nZ2VyIGltcGxlbWVudHMgTG9nZ2Vye1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBsb2cuc2V0TGV2ZWwoXCJERUJVR1wiKTtcbiAgICB9XG4gICAgaW5mbyhtZXNzYWdlOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgbG9nLmluZm8obWVzc2FnZSlcbiAgICB9XG4gICAgd2FybihtZXNzYWdlOiBhbnkpXG4gICAge1xuICAgICAgICBsb2cud2FybihtZXNzYWdlKVxuICAgIH1cbiAgICBlcnJvcihtZXNzYWdlOiBhbnkpXG4gICAge1xuICAgICAgICBsb2cuZXJyb3IobWVzc2FnZSlcbiAgICB9XG4gICAgZGVidWcobWVzc2FnZTogYW55KVxuICAgIHtcbiAgICAgICAgbG9nLmRlYnVnKG1lc3NhZ2UpXG4gICAgfVxufSIsImltcG9ydCB7IEVuY3J5cHRpb25TZXJ2aWNlIH0gZnJvbSBcIi4vRW5jcnlwdGlvblNlcnZpY2VcIjtcbmltcG9ydCBzamNsIGZyb20gXCJzamNsXCI7XG5cbmV4cG9ydCBjbGFzcyBTSkNMRW5jcnlwdGlvblNlcnZpY2UgaW1wbGVtZW50cyBFbmNyeXB0aW9uU2VydmljZSB7XG4gICAgcHVibGljIHBhcmFtczogYW55ID0geyBtb2RlOiBcImdjbVwiLCB0czogMTI4LCBhZGF0YTogXCJcIiwgaXRlcjogMTAwMDB9XG4gICAgcHVibGljIGVuY3J5cHQocGFzc3BocmFzZTogc3RyaW5nLCBwbGFpblRleHQ6IHN0cmluZyk6IE9iamVjdCB7XG4gICAgICAgIHJldHVybiBzamNsLmVuY3J5cHQocGFzc3BocmFzZSwgcGxhaW5UZXh0LCB0aGlzLnBhcmFtcyk7XG4gICAgfSBcbiAgICBcbiAgICBwdWJsaWMgZGVjcnlwdChwYXNzcGhyYXNlOiBzdHJpbmcsIGNpcGhlcjogT2JqZWN0KTogT2JqZWN0IHtcbiAgICAgICAgcmV0dXJuIHNqY2wuZGVjcnlwdChwYXNzcGhyYXNlLCBjaXBoZXIgYXMgc2pjbC5TamNsQ2lwaGVyRW5jcnlwdGVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCk7XG4gICAgfVxufSIsImV4cG9ydCBuYW1lc3BhY2UgSnNvbkFQSSB7XG4gICAgLy8gQHRzLWlnbm9yZTogQ2Fubm90IGZpbmQgbmFtZSAnaG9zdEFkZHJlc3MnLlxuICAgIGV4cG9ydCBjb25zdCBBY3RpdmVVc2Vyc0dFVCA9IGAvYXBpL2NoYXQvZ2V0L2FjdGl2ZS11c2Vycy9gO1xuICAgIFxufSIsImV4cG9ydCBjbGFzcyBUZW1wbGF0ZUZhY3Rvcnkge1xuICAgIHN0YXRpYyBnZXRUZW1wbGF0ZSgpOiBIYW5kbGViYXJzLlRlbXBsYXRlRGVsZWdhdGU8YW55PiB7XG4gICAgICAgIC8vIEB0cy1pZ25vcmU6IE9iamVjdCBpcyBwb3NzaWJseSAnbnVsbCcuXG4gICAgICAgIHZhciBzb3VyY2UgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInVzZXItY29udGFjdC1vbmxpbmUtdGVtcGxhdGVcIikuaW5uZXJIVE1MOyBcbiAgICAgICAgdmFyIG1zZ0NvbnRhaW5lclRlbXBsYXRlID0gSGFuZGxlYmFycy5jb21waWxlKHNvdXJjZSk7XG4gICAgICAgIHJldHVybiBtc2dDb250YWluZXJUZW1wbGF0ZTtcbiAgICB9XG59IiwiaW1wb3J0IHsgT2JzZXJ2ZXIgfSBmcm9tIFwiLi4vb2JzZXJ2ZS9PYnNlcnZlclwiO1xuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvQWJzdHJhY3RNb2RlbFwiO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gXCIuLi9vYnNlcnZlL09ic2VydmFibGVcIjtcbmltcG9ydCB7IFZpZXcgfSBmcm9tIFwiLi9BYnN0cmFjdFZpZXdcIjtcbmltcG9ydCB7IENvbnRyb2xsZXIgfSBmcm9tIFwiLi4vY29udHJvbGxlci9BYnN0cmFjdENvbnRyb2xsZXJcIjtcbmltcG9ydCB7IFRlbXBsYXRlRmFjdG9yeSB9IGZyb20gXCIuLi90ZW1wbGF0ZS9UZW1wbGF0ZUZhY3RvcnlcIjtcbmltcG9ydCB7IEFjdGl2ZVVzZXJWaWV3TW9kZWwgfSBmcm9tIFwiLi4vdmlld21vZGVsL0FjdGl2ZVVzZXJWaWV3TW9kZWxcIjtcblxuZXhwb3J0IGNsYXNzIENoYXRWaWV3IGltcGxlbWVudHMgT2JzZXJ2ZXIsIFZpZXcge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX21vZGVsOiBNb2RlbDtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9lbGVtZW50OiBIVE1MRWxlbWVudDtcbiAgICAvLyBwcml2YXRlIHVzZXJCb3hlczogYW55W10gPSAgW107XG5cblxuICAgIGNvbnN0cnVjdG9yKG1vZGVsOiBNb2RlbCwgZWxlbWVudDogSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5fbW9kZWwgPSBtb2RlbDtcbiAgICAgICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgfVxuXG5cblxuICAgIC8qKlxuICAgICAqIEdldHRlciBtb2RlbFxuICAgICAqIEByZXR1cm4ge01vZGVsfVxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgbW9kZWwoKTogTW9kZWwge1xuICAgICAgICByZXR1cm4gdGhpcy5fbW9kZWw7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBHZXR0ZXIgZWxlbWVudFxuICAgICAqIEByZXR1cm4ge2FueX1cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IGVsZW1lbnQoKTogSFRNTEVsZW1lbnQge1xuICAgICAgICByZXR1cm4gdGhpcy5fZWxlbWVudDtcbiAgICB9XG5cbiAgICAvLyAvKipcbiAgICAvLyAgKiBTZXR0ZXIgbW9kZWxcbiAgICAvLyAgKiBAcGFyYW0ge01vZGVsfSB2YWx1ZVxuICAgIC8vICAqL1xuICAgIC8vIHB1YmxpYyBzZXQgbW9kZWwodmFsdWU6IE1vZGVsKSB7XG4gICAgLy8gICAgIHRoaXMuX21vZGVsID0gdmFsdWU7XG4gICAgLy8gfVxuXG5cbiAgICAvLyAvKipcbiAgICAvLyAgKiBTZXR0ZXIgZWxlbWVudFxuICAgIC8vICAqIEBwYXJhbSB7YW55fSB2YWx1ZVxuICAgIC8vICAqL1xuICAgIC8vIHB1YmxpYyBzZXQgZWxlbWVudCh2YWx1ZTogYW55KSB7XG4gICAgLy8gICAgIHRoaXMuX2VsZW1lbnQgPSB2YWx1ZTtcbiAgICAvLyB9XG5cblxuXG5cblxuICAgIHVwZGF0ZShkYXRhOiBBY3RpdmVVc2VyVmlld01vZGVsW10pOiB2b2lkIHtcbiAgICAgICAgbGV0IHRlbXBsYXRlID0gVGVtcGxhdGVGYWN0b3J5LmdldFRlbXBsYXRlKCk7XG4gICAgICAgIGxldCBodG1sOiBzdHJpbmcgPSBcIlwiO1xuICAgICAgICBkYXRhLmZvckVhY2goKGVsZW1lbnQ6IEFjdGl2ZVVzZXJWaWV3TW9kZWwpID0+IHtcbiAgICAgICAgICAgIGh0bWwgKz0gdGVtcGxhdGUoZWxlbWVudCk7XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmVsZW1lbnQuaW5uZXJIVE1MID0gaHRtbDtcbiAgICAgICAgdGhpcy5hZGRVc2VyQ2FsbEJhY2tzKCk7XG4gICAgICAgIGNvbnNvbGUubG9nKHRoaXMuZWxlbWVudC5pbm5lckhUTUwpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaGVscGVyKCk6IHZvaWQge1xuICAgICAgICBcbiAgICB9XG5cbiAgICBwcml2YXRlIGFkZFVzZXJDYWxsQmFja3MoKTogdm9pZCB7XG4gICAgICAgIGxldCB1c2VyQm94ZXMgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCd1c2VyLWJveCcpO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHVzZXJCb3hlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgbGV0IHVzZXJCb3ggPSB1c2VyQm94ZXNbaV07XG4gICAgICAgICAgICB1c2VyQm94ZXNbaV0uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLnVzZXJDYWxsQmFjay5iaW5kKHRoaXMsIHVzZXJCb3gpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBcblxuICAgIHByaXZhdGUgdXNlckNhbGxCYWNrKGVsOiBFbGVtZW50KTogdm9pZCB7XG4gICAgICAgIGxldCBjdXJyZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgndXNlci1ib3ggYWN0aXZlJyk7XG4gICAgICAgIGxldCBwYXNzcGhyYXNlID0gXCJcIlxuICAgICAgICBpZiAoY3VycmVudC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBpZiAocGFzc3BocmFzZSA9PSAnJykge1xuICAgICAgICAgICAgICAgIC8vIGFsZXJ0KCdQbGVhc2UgaW5wdXQgcGFzc3BocmFzZScpXG4gICAgICAgICAgICAgICAgLy8gYWxlcnRpZnkuZXJyb3IoJ1BsZWFzZSBlbnRlciBhIHBhc3NwaHJhc2UnKTtcbiAgICAgICAgICAgICAgICAvLyByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjdXJyZW50WzBdLmNsYXNzTmFtZSA9IGN1cnJlbnRbMF0uY2xhc3NOYW1lLnJlcGxhY2UoXCIgYWN0aXZlXCIsIFwiXCIpO1xuICAgIFxuICAgICAgICB9XG4gICAgICAgIC8vIEFkZCB0aGUgYWN0aXZlIGNsYXNzIHRvIHRoZSBjdXJyZW50L2NsaWNrZWQgYnV0dG9uXG4gICAgICAgIGVsc2UgaWYgKGN1cnJlbnQubGVuZ3RoID09IDApIHtcbiAgICAgICAgICAgIGxldCBlbGVtID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3Bhc3NwaHJhc2UtaW5pdGlhbCcpO1xuICAgICAgICAgICAgcGFzc3BocmFzZSA9IFwiXCI7XG4gICAgICAgICAgICBpZiAocGFzc3BocmFzZSA9PSAnJykge1xuICAgICAgICAgICAgLy8gICAgIC8vIGFsZXJ0KCdQbGVhc2UgaW5wdXQgcGFzc3BocmFzZScpXG4gICAgICAgICAgICAvLyAgICAgLy8gYWxlcnRpZnkuZXJyb3IoJ1BsZWFzZSBlbnRlciBhIHBhc3NwaHJhc2UnKTtcbiAgICAgICAgICAgIC8vICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBAdHMtaWdub3JlOiBPYmplY3QgaXMgcG9zc2libHkgJ251bGwnLlxuICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ25vLXVzZXItc2VsZWN0ZWQnKS5oaWRkZW4gPSB0cnVlO1xuICAgICAgICAgICAgLy8gQHRzLWlnbm9yZTogT2JqZWN0IGlzIHBvc3NpYmx5ICdudWxsJy5cbiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdjaGF0LWNhcmQnKS5oaWRkZW4gPSBmYWxzZTtcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmU6IE9iamVjdCBpcyBwb3NzaWJseSAnbnVsbCcuXG4gICAgICAgICAgICBlbGVtLmhpZGRlbiA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgLy8gY29uc29sZS5sb2codGhpcy5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCd0by11c2VyLXNwYW4nKSk7XG4gICAgICAgIGxldCBlbGVtID0gZWwuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgndG8tdXNlci1zcGFuJylbMF0gYXMgSFRNTEVsZW1lbnQ7XG4gICAgICAgIGxldCB1c2VyTmFtZSA9IGVsZW0uaW5uZXJUZXh0O1xuICAgICAgICAvLyBAdHMtaWdub3JlOiBPYmplY3QgaXMgcG9zc2libHkgJ251bGwnLlxuICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndXNlci1uYW1lLXNwYW4nKS5pbm5lclRleHQgPSB1c2VyTmFtZTtcbiAgICAgICAgLy8gcG9wdWxhdGVNZXNzYWdlcyh1c2VyTmFtZSwgcGFzc3BocmFzZSk7XG4gICAgICAgIHNlc3Npb25TdG9yYWdlLnNldEl0ZW0oJ3NlbGVjdGVkVXNlcicsIHVzZXJOYW1lKTtcbiAgICAgICAgZWwuY2xhc3NOYW1lICs9IFwiIGFjdGl2ZVwiO1xuICAgIH1cblxufSIsImltcG9ydCB7IE9ic2VydmVyIH0gZnJvbSBcIi4uL29ic2VydmUvT2JzZXJ2ZXJcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIi4uL21vZGVsL0Fic3RyYWN0TW9kZWxcIjtcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tIFwiLi4vb2JzZXJ2ZS9PYnNlcnZhYmxlXCI7XG5pbXBvcnQgeyBWaWV3IH0gZnJvbSBcIi4vQWJzdHJhY3RWaWV3XCI7XG5pbXBvcnQgeyBDb250cm9sbGVyIH0gZnJvbSBcIi4uL2NvbnRyb2xsZXIvQWJzdHJhY3RDb250cm9sbGVyXCI7XG5pbXBvcnQgeyBUZW1wbGF0ZUZhY3RvcnkgfSBmcm9tIFwiLi4vdGVtcGxhdGUvVGVtcGxhdGVGYWN0b3J5XCI7XG5pbXBvcnQgeyBBY3RpdmVVc2VyVmlld01vZGVsIH0gZnJvbSBcIi4uL3ZpZXdtb2RlbC9BY3RpdmVVc2VyVmlld01vZGVsXCI7XG5cbmV4cG9ydCBjbGFzcyBVc2VyVmlldyBpbXBsZW1lbnRzIE9ic2VydmVyLCBWaWV3IHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9tb2RlbDogTW9kZWw7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfZWxlbWVudDogSFRNTEVsZW1lbnQ7XG4gICAgLy8gcHJpdmF0ZSB1c2VyQm94ZXM6IGFueVtdID0gIFtdO1xuXG5cbiAgICBjb25zdHJ1Y3Rvcihtb2RlbDogTW9kZWwsIGVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG4gICAgICAgIHRoaXMuX21vZGVsID0gbW9kZWw7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgIH1cblxuXG5cbiAgICAvKipcbiAgICAgKiBHZXR0ZXIgbW9kZWxcbiAgICAgKiBAcmV0dXJuIHtNb2RlbH1cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IG1vZGVsKCk6IE1vZGVsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21vZGVsO1xuICAgIH1cblxuXG4gICAgLyoqXG4gICAgICogR2V0dGVyIGVsZW1lbnRcbiAgICAgKiBAcmV0dXJuIHthbnl9XG4gICAgICovXG4gICAgcHVibGljIGdldCBlbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VsZW1lbnQ7XG4gICAgfVxuXG4gICAgLy8gLyoqXG4gICAgLy8gICogU2V0dGVyIG1vZGVsXG4gICAgLy8gICogQHBhcmFtIHtNb2RlbH0gdmFsdWVcbiAgICAvLyAgKi9cbiAgICAvLyBwdWJsaWMgc2V0IG1vZGVsKHZhbHVlOiBNb2RlbCkge1xuICAgIC8vICAgICB0aGlzLl9tb2RlbCA9IHZhbHVlO1xuICAgIC8vIH1cblxuXG4gICAgLy8gLyoqXG4gICAgLy8gICogU2V0dGVyIGVsZW1lbnRcbiAgICAvLyAgKiBAcGFyYW0ge2FueX0gdmFsdWVcbiAgICAvLyAgKi9cbiAgICAvLyBwdWJsaWMgc2V0IGVsZW1lbnQodmFsdWU6IGFueSkge1xuICAgIC8vICAgICB0aGlzLl9lbGVtZW50ID0gdmFsdWU7XG4gICAgLy8gfVxuXG5cblxuXG5cbiAgICB1cGRhdGUoZGF0YTogQWN0aXZlVXNlclZpZXdNb2RlbFtdKTogdm9pZCB7XG4gICAgICAgIGxldCB0ZW1wbGF0ZSA9IFRlbXBsYXRlRmFjdG9yeS5nZXRUZW1wbGF0ZSgpO1xuICAgICAgICBsZXQgaHRtbDogc3RyaW5nID0gXCJcIjtcbiAgICAgICAgZGF0YS5mb3JFYWNoKChlbGVtZW50OiBBY3RpdmVVc2VyVmlld01vZGVsKSA9PiB7XG4gICAgICAgICAgICBodG1sICs9IHRlbXBsYXRlKGVsZW1lbnQpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5lbGVtZW50LmlubmVySFRNTCA9IGh0bWw7XG4gICAgICAgIHRoaXMuYWRkVXNlckNhbGxCYWNrcygpO1xuICAgICAgICBjb25zb2xlLmxvZyh0aGlzLmVsZW1lbnQuaW5uZXJIVE1MKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGhlbHBlcigpOiB2b2lkIHtcbiAgICAgICAgXG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhZGRVc2VyQ2FsbEJhY2tzKCk6IHZvaWQge1xuICAgICAgICBsZXQgdXNlckJveGVzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgndXNlci1ib3gnKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB1c2VyQm94ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGxldCB1c2VyQm94ID0gdXNlckJveGVzW2ldO1xuICAgICAgICAgICAgdXNlckJveGVzW2ldLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy51c2VyQ2FsbEJhY2suYmluZCh0aGlzLCB1c2VyQm94KSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgXG5cbiAgICBwcml2YXRlIHVzZXJDYWxsQmFjayhlbDogRWxlbWVudCk6IHZvaWQge1xuICAgICAgICBsZXQgY3VycmVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ3VzZXItYm94IGFjdGl2ZScpO1xuICAgICAgICBsZXQgcGFzc3BocmFzZSA9IFwiXCJcbiAgICAgICAgaWYgKGN1cnJlbnQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgaWYgKHBhc3NwaHJhc2UgPT0gJycpIHtcbiAgICAgICAgICAgICAgICAvLyBhbGVydCgnUGxlYXNlIGlucHV0IHBhc3NwaHJhc2UnKVxuICAgICAgICAgICAgICAgIC8vIGFsZXJ0aWZ5LmVycm9yKCdQbGVhc2UgZW50ZXIgYSBwYXNzcGhyYXNlJyk7XG4gICAgICAgICAgICAgICAgLy8gcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudFswXS5jbGFzc05hbWUgPSBjdXJyZW50WzBdLmNsYXNzTmFtZS5yZXBsYWNlKFwiIGFjdGl2ZVwiLCBcIlwiKTtcbiAgICBcbiAgICAgICAgfVxuICAgICAgICAvLyBBZGQgdGhlIGFjdGl2ZSBjbGFzcyB0byB0aGUgY3VycmVudC9jbGlja2VkIGJ1dHRvblxuICAgICAgICBlbHNlIGlmIChjdXJyZW50Lmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgICBsZXQgZWxlbSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdwYXNzcGhyYXNlLWluaXRpYWwnKTtcbiAgICAgICAgICAgIHBhc3NwaHJhc2UgPSBcIlwiO1xuICAgICAgICAgICAgaWYgKHBhc3NwaHJhc2UgPT0gJycpIHtcbiAgICAgICAgICAgIC8vICAgICAvLyBhbGVydCgnUGxlYXNlIGlucHV0IHBhc3NwaHJhc2UnKVxuICAgICAgICAgICAgLy8gICAgIC8vIGFsZXJ0aWZ5LmVycm9yKCdQbGVhc2UgZW50ZXIgYSBwYXNzcGhyYXNlJyk7XG4gICAgICAgICAgICAvLyAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQHRzLWlnbm9yZTogT2JqZWN0IGlzIHBvc3NpYmx5ICdudWxsJy5cbiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCduby11c2VyLXNlbGVjdGVkJykuaGlkZGVuID0gdHJ1ZTtcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmU6IE9iamVjdCBpcyBwb3NzaWJseSAnbnVsbCcuXG4gICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnY2hhdC1jYXJkJykuaGlkZGVuID0gZmFsc2U7XG4gICAgICAgICAgICAvLyBAdHMtaWdub3JlOiBPYmplY3QgaXMgcG9zc2libHkgJ251bGwnLlxuICAgICAgICAgICAgZWxlbS5oaWRkZW4gPSB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKHRoaXMuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgndG8tdXNlci1zcGFuJykpO1xuICAgICAgICBsZXQgZWxlbSA9IGVsLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ3RvLXVzZXItc3BhbicpWzBdIGFzIEhUTUxFbGVtZW50O1xuICAgICAgICBsZXQgdXNlck5hbWUgPSBlbGVtLmlubmVyVGV4dDtcbiAgICAgICAgLy8gQHRzLWlnbm9yZTogT2JqZWN0IGlzIHBvc3NpYmx5ICdudWxsJy5cbiAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3VzZXItbmFtZS1zcGFuJykuaW5uZXJUZXh0ID0gdXNlck5hbWU7XG4gICAgICAgIC8vIHBvcHVsYXRlTWVzc2FnZXModXNlck5hbWUsIHBhc3NwaHJhc2UpO1xuICAgICAgICBzZXNzaW9uU3RvcmFnZS5zZXRJdGVtKCdzZWxlY3RlZFVzZXInLCB1c2VyTmFtZSk7XG4gICAgICAgIGVsLmNsYXNzTmFtZSArPSBcIiBhY3RpdmVcIjtcbiAgICB9XG5cbn0iLCJleHBvcnQgY2xhc3MgQWN0aXZlVXNlclZpZXdNb2RlbCB7XG4gICAgdXNlck5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBvbmxpbmU6IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG4gICAgbGFzdEFjdGl2ZTogc3RyaW5nfCB1bmRlZmluZWQ7XG59IiwiZXhwb3J0IGNsYXNzIENoYXRNZXNzYWdlVmlld01vZGVsIHtcbiAgICBwdWJsaWMgdG9Vc2VyOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgcHVibGljIGZyb21Vc2VyOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgcHVibGljIG1lc3NhZ2VDaXBoZXI6IGFueTtcbiAgICBwdWJsaWMgbWVzc2FnZVRpbWUhOiBEYXRlO1xuXG4gICAgXG59Il19 diff --git a/chatto/src/main/javascript/ts/test.html b/chatto/src/main/javascript/ts/test.html deleted file mode 100644 index f34efaf..0000000 --- a/chatto/src/main/javascript/ts/test.html +++ /dev/null @@ -1,311 +0,0 @@ - - - - - - - - -
- - Chat -
- - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
-

Chat with your friends

-
-
- -
-
- - Lorem ipsum dolor sit, amet consectetur adipisicing elit. Laboriosam dolorem nostrum consequatur eos voluptates. Ipsam ullam quos illo qui. Quaerat corrupti nisi numquam rerum quasi nesciunt deserunt fugit commodi consequatur! - -
-
-
-
- -
-
-
-
-
-
-
-
- -
-
- -
  • -
    -
    - - -
    - -
    -
  • -
    - - -
  • -
    -
    - - -
    - -
    -
    Dec 25
    -
    Hello how are you
    -
    -
    -
  • -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -

    Please select a user

    - -
    -
    -
    -
    - -
    -
    -
    - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/chatto/src/main/javascript/yarn-error.log b/chatto/src/main/javascript/yarn-error.log deleted file mode 100644 index b0f8a26..0000000 --- a/chatto/src/main/javascript/yarn-error.log +++ /dev/null @@ -1,157 +0,0 @@ -Arguments: - /home/rohan/.nvm/versions/node/v12.10.0/bin/node /home/rohan/.nvm/versions/node/v12.10.0/bin/yarn add handlebars.js - -PATH: - /home/rohan/.sdkman/candidates/maven/current/bin:/home/rohan/.sdkman/candidates/java/current/bin:/home/rohan/.nvm/versions/node/v12.10.0/bin:/home/rohan/miniconda3/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/rohan/.cargo/bin:/home/rohan/.platformio/penv/bin - -Yarn version: - 1.19.2 - -Node version: - 12.10.0 - -Platform: - linux x64 - -Trace: - Error: https://registry.yarnpkg.com/handlebars.js: Not found - at Request.params.callback [as _callback] (/home/rohan/.nvm/versions/node/v12.10.0/lib/node_modules/yarn/lib/cli.js:66927:18) - at Request.self.callback (/home/rohan/.nvm/versions/node/v12.10.0/lib/node_modules/yarn/lib/cli.js:140586:22) - at Request.emit (events.js:209:13) - at Request. (/home/rohan/.nvm/versions/node/v12.10.0/lib/node_modules/yarn/lib/cli.js:141558:10) - at Request.emit (events.js:209:13) - at IncomingMessage. (/home/rohan/.nvm/versions/node/v12.10.0/lib/node_modules/yarn/lib/cli.js:141480:12) - at Object.onceWrapper (events.js:298:28) - at IncomingMessage.emit (events.js:214:15) - at endReadableNT (_stream_readable.js:1178:12) - at processTicksAndRejections (internal/process/task_queues.js:80:21) - -npm manifest: - { - "dependencies": { - "alertifyjs": "^1.12.0", - "chart.js": "^2.9.3", - "dompurify": "^2.0.7", - "fuse.js": "^3.4.6", - "loglevel": "^1.6.6", - "markdown-it": "^10.0.0" - } - } - -yarn manifest: - No manifest - -Lockfile: - # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. - # yarn lockfile v1 - - - alertifyjs@^1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/alertifyjs/-/alertifyjs-1.12.0.tgz#75be1eac23e059d3b990ab076979d36a45aa21ac" - integrity sha512-BWEFsLhPM1MBEAQ6jFATNO8ESCh1LDZzUslJ2g/E6NnI3QfyfIvpCuw07SiUQy59E6HSsdb8c5RgqiOwTcRQ2Q== - - argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - - chart.js@^2.9.3: - version "2.9.3" - resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.3.tgz#ae3884114dafd381bc600f5b35a189138aac1ef7" - integrity sha512-+2jlOobSk52c1VU6fzkh3UwqHMdSlgH1xFv9FKMqHiNCpXsGPQa/+81AFa+i3jZ253Mq9aAycPwDjnn1XbRNNw== - dependencies: - chartjs-color "^2.1.0" - moment "^2.10.2" - - chartjs-color-string@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz#1df096621c0e70720a64f4135ea171d051402f71" - integrity sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A== - dependencies: - color-name "^1.0.0" - - chartjs-color@^2.1.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.4.1.tgz#6118bba202fe1ea79dd7f7c0f9da93467296c3b0" - integrity sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w== - dependencies: - chartjs-color-string "^0.6.0" - color-convert "^1.9.3" - - color-convert@^1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - - color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - - color-name@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - - dompurify@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.0.7.tgz#f8266ad38fe1602fb5b3222f31eedbf5c16c4fd5" - integrity sha512-S3O0lk6rFJtO01ZTzMollCOGg+WAtCwS3U5E2WSDY/x/sy7q70RjEC4Dmrih5/UqzLLB9XoKJ8KqwBxaNvBu4A== - - entities@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" - integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== - - fuse.js@^3.4.6: - version "3.4.6" - resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-3.4.6.tgz#545c3411fed88bf2e27c457cab6e73e7af697a45" - integrity sha512-H6aJY4UpLFwxj1+5nAvufom5b2BT2v45P1MkPvdGIK8fWjQx/7o6tTT1+ALV0yawQvbmvCF0ufl2et8eJ7v7Cg== - - linkify-it@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" - integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== - dependencies: - uc.micro "^1.0.1" - - loglevel@^1.6.6: - version "1.6.6" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.6.tgz#0ee6300cc058db6b3551fa1c4bf73b83bb771312" - integrity sha512-Sgr5lbboAUBo3eXCSPL4/KoVz3ROKquOjcctxmHIt+vol2DrqTQe3SwkKKuYhEiWB5kYa13YyopJ69deJ1irzQ== - - markdown-it@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc" - integrity sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg== - dependencies: - argparse "^1.0.7" - entities "~2.0.0" - linkify-it "^2.0.0" - mdurl "^1.0.1" - uc.micro "^1.0.5" - - mdurl@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= - - moment@^2.10.2: - version "2.24.0" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" - integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== - - sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - - uc.micro@^1.0.1, uc.micro@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" - integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== diff --git a/chatto/src/main/resources/static/js/chat.js b/chatto/src/main/resources/static/js/chat.js deleted file mode 100644 index 33ba6a6..0000000 --- a/chatto/src/main/resources/static/js/chat.js +++ /dev/null @@ -1,547 +0,0 @@ -// import { sprintf } from 'sprintf-js'; -// import { vsprintf } from 'sprintf-js'; -/*var off_payment_method = document.getElementsByName('offline_payment_method'); -var ischecked_method = false; -for ( var i = 0; i < off_payment_method.length; i++) { - if(off_payment_method[i].checked) { - ischecked_method = true; - break; - } -} -if(!ischecked_method) { //payment method button is not checked - alert("Please choose Offline Payment Method"); -}*/ -var toUserRadios = document.getElementsByName('toUser'); -var isCheckedUser = false; -var chatTextArea = document.getElementById('chatTextArea'); - -var postNewMessageUrl = `http://${hostAddress}/api/chat/post/message`; //hostAddress variable is set in the thymeleaf head fragment -var getAllMessagesUrl = `http://${hostAddress}/api/chat/get/messages/`; -var getNewMessagesUrl = `http://${hostAddress}/api/chat/get/messages/`; -var getActiveUsersUrl = `http://${hostAddress}/api/chat/get/active-users/`; -// var postNewMessageUrl = "http://localhost:8080/api/chat/post/message"; -// var getAllMessagesUrl = "http://localhost:8080/api/chat/get/messages/"; -// var getNewMessagesUrl = "http://localhost:8080/api/chat/get/messages/"; -// var messageLog = []; -var username = localStorage.getItem('username'); -var authToken = localStorage.getItem('authToken'); - -var passphraseInput = document.getElementById('passphrase'); -var iterations = 100000; - -var source = document.getElementById("msg_container_template").innerHTML; -var msgContainerTemplate = Handlebars.compile(source); -var source = document.getElementById("msg_container_send_template").innerHTML; -var msgContainerSendTemplate = Handlebars.compile(source); -var source = document.getElementById("user-contact-online-template").innerHTML; -var userContactOnlineTemplate = Handlebars.compile(source); -var source = document.getElementById("user-contact-offline-template").innerHTML; -var userContactOfflineTemplate = Handlebars.compile(source); - -var chatAreaNew = document.getElementById('chat_area_new'); - -var userBoxes = document.getElementsByName('user-box'); - -var md = window.markdownit(); - -var activeUsers = {}; - -var fuseOptions = { - shouldSort: true, - threshold: 0.01, - location: 0, - distance: 100, - maxPatternLength: 32, - minMatchCharLength: 1, - keys: [ - "userName", - ] -}; - -log.setLevel('TRACE'); - -alertify.set('notifier', 'position', 'top-center'); - -// Loop through the buttons and add the active class to the current/clicked button -// for (var i = 0; i < btns.length; i++) { -// btns[i].addEventListener("click", function() { -// var current = document.getElementsByClassName("active"); - -// // If there's no active class -// if (current.length > 0) { -// current[0].className = current[0].className.replace(" active", ""); -// } - -// // Add the active class to the current/clicked button -// this.className += " active"; -// }); -// } - -getActiveUsers(authToken) - .then(data => { - // activeUsers = data; - sessionStorage.setItem('activeUsers', JSON.stringify(data)); - log.log(sessionStorage.getItem('activeUsers')); - }) - -for (let i = 0; i < userBoxes.length; i++) { - userBoxes[i].addEventListener('click', userCallBack) -} - -function addUserCallBacks() { - for (let i = 0; i < userBoxes.length; i++) { - userBoxes[i].addEventListener('click', userCallBack) - } -} - -function userCallBack() { - let current = document.getElementsByClassName('user-box active'); - let passphrase = passphraseInput.value; - if (current.length > 0) { - if (passphrase == '') { - // alert('Please input passphrase') - alertify.error('Please enter a passphrase'); - 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'); - passphrase = elem.value; - if (passphrase == '') { - // alert('Please input passphrase') - alertify.error('Please enter a passphrase'); - return; - } - document.getElementById('no-user-selected').hidden = true; - document.getElementById('chat-card').hidden = false; - elem.hidden = true; - } - // console.log(this.getElementsByClassName('to-user-span')); - let userName = this.getElementsByClassName('to-user-span')[0].innerText; - document.getElementById('user-name-span').innerText = userName; - populateMessages(userName, passphrase); - sessionStorage.setItem('selectedUser', userName); - this.className += " active"; -} - -function populateMessages(userName, passphrase) { - console.log('Selected user = ' + userName); - if (passphrase == '') { - alert('Please input passphrase') - return; - } - // console.log(userName); - if (sessionStorage.getItem(userName) == null) { - chatTextArea.textContent = ''; - chatAreaNew.innerHTML = ''; - getAllMessages(userName) - .then(json => { - if (json == null) return; - console.log(json); - let i = 0; - let messageLog = []; - let messageLogNew = []; - let lastMessageTimeStamp; - - if (json.length > 0) { - json.forEach(function(obj) { - // console.log(obj.toUser); - messageCipher = JSON.stringify(obj.messageCipher); - console.log(messageCipher); - // let message = sjcl.decrypt("password", messageCipher); - let message = md.render(sjcl.decrypt(passphrase, messageCipher)); - let utcDate = obj.messageTime; - lastMessageTimeStamp = utcDate; - let localDate = new Date(utcDate); - let messageLine = sprintf('%s %s: %s ', localDate, obj.fromUser, message); - - - // localDate.`` - // console.log('localDate = ' + localDate); - console.log(messageLine); - // chatTextArea.append(obj.fromUser + ": " + message + "\n"); - chatTextArea.append(messageLine + '\n'); - messageLog[i++] = messageLine; - chatTextArea.scrollTop = chatTextArea.scrollHeight; - // console.log('Message log = ' + messageLog); - - let context = { fromUser: obj.fromUser, message: message, time: localDate.toLocaleString() }; - let msgContainer; - if (obj.fromUser == username) { - msgContainer = msgContainerSendTemplate(context); - } else { - msgContainer = msgContainerTemplate(context); - } - - messageLogNew.push(JSON.stringify(context)); - $(chatAreaNew).append(DOMPurify.sanitize(msgContainer)); - - - }); - sessionStorage.setItem(userName, JSON.stringify(messageLog)); - sessionStorage.setItem(userName + username + 'new', JSON.stringify(messageLogNew)); - // console.log() - // sessionStorage.clear(); - console.log('Last message time = ' + lastMessageTimeStamp); - sessionStorage.setItem(userName + '-time', lastMessageTimeStamp); - - - } - }); - } else { - - - console.log("Stored messages = " + sessionStorage.getItem(userName)); - let storedMessages = JSON.parse(sessionStorage.getItem(userName)); - let storedMessagesNew = JSON.parse(sessionStorage.getItem(userName + username + 'new')); - let lastMessageTime = sessionStorage.getItem(userName + '-time'); - console.log("last message time stamp = " + lastMessageTime); - if (lastMessageTime != null) { - getNewMessages(userName, lastMessageTime) - .then(json => { - if (json == null) return; - console.log(json) - if (json.length > 0) { - json.forEach(function(obj) { - let messageCipher = JSON.stringify(obj.messageCipher); - let message = md.render(sjcl.decrypt(passphrase, messageCipher)); - // console.log(message); - // chatTextArea.append(message + "\n"); - let utcDate = obj.messageTime; - lastMessageTimeStamp = utcDate; - let localDate = new Date(utcDate); - let messageLine = sprintf('%s %s: %s', localDate, obj.fromUser, message); - - // localDate.`` - // console.log('localDate = ' + localDate); - console.log(messageLine); - // chatTextArea.append(obj.fromUser + ": " + message + "\n"); - chatTextArea.append(messageLine + '\n'); - chatTextArea.scrollTop = chatTextArea.scrollHeight; - storedMessages.push(messageLine); - - let context = { fromUser: obj.fromUser, message: message, time: localDate.toLocaleString() }; - let msgContainer; - if (obj.fromUser == username) { - msgContainer = msgContainerSendTemplate(context); - } else { - msgContainer = msgContainerTemplate(context); - } - - storedMessagesNew.push(JSON.stringify(context)); - $(chatAreaNew).append(DOMPurify.sanitize(msgContainer)); - - }) - sessionStorage.setItem(userName + '-time', lastMessageTimeStamp); - sessionStorage.setItem(userName, JSON.stringify(storedMessages)); - sessionStorage.setItem(userName + username + 'new', JSON.stringify(storedMessagesNew)); - console.log("this value stored" + sessionStorage.getItem(userName)) - console.log("last message time stamp = " + lastMessageTimeStamp); - console.log(sessionStorage.getItem(userName + '-time')); - - } - chatTextArea.textContent = ''; - chatAreaNew.innerHTML = ''; - console.log("Stored messages 2 = " + storedMessages); - storedMessages.forEach(function(messageLine) { - chatTextArea.append(messageLine + '\n'); - chatTextArea.scrollTop = chatTextArea.scrollHeight; - - // let context = {message: messageLine}; - // let msgContainer; - // if(obj.fromUser == username) - // { - // msgContainer = msgContainerSendTemplate(context); - // } - // else{ - // msgContainer = msgContainerTemplate(context); - // } - - // $(chatAreaNew).append(msgContainer); - }) - - storedMessagesNew.forEach(function(contextString) { - let context = JSON.parse(contextString); - let msgContainer; - if (context.fromUser == username) { - msgContainer = msgContainerSendTemplate(context); - } else { - msgContainer = msgContainerTemplate(context); - } - - $(chatAreaNew).append(DOMPurify.sanitize(msgContainer)); - scrollChatAreaAnimated(2400); - }) - - - }); - - - } - // chatTextArea.append(JSON.stringify(storedMessages)); - - } - // sessionStorage.setItem('status', 'ready'); - // sessionStorage.setItem('userName', messageLog); - // console.log('Message log = ' + messageLog); - // } - - // let passphraseKey = userName + '-passphrase'; - // sessionStorage.setItem(passphraseKey, passphrase); - // console.log(sessionStorage.getItem(passphraseKey)); -} - -// var lastMessageTimeStamp; - -// console.log(authToken); -// 'Basic ' + btoa("hmm" + ":" + "hmm") - -Handlebars.registerHelper('avatar', function() { - return '
    '; -}); - - -// var user; -function getSelectedUser() { - for (var i = 0; i < toUserRadios.length; i++) { - if (toUserRadios[i].checked) { - let user = toUserRadios[i].value; - console.log('sending to user = ' + user); - isCheckedUser = true; - return user; - } - } - -} - -function getSelectedUserNew() { - return sessionStorage.getItem('selectedUser'); -} - -document.getElementById('chatMessageForm').addEventListener('submit', function(e) { - let chatInput = document.getElementById('chatInput'); - e.preventDefault(); - let user = getSelectedUserNew(); - - if (!this.checkValidity()) { - console.log("error"); - this.classList.add('was-validated'); - return; - } - this.classList.add('was-validated'); - - if (user == null) { - // window.alert('please select a user'); - alertify.error('Please select a user'); - return; - } - let messageContent = chatInput.value; - let context = { fromUser: username, message: md.render(messageContent), time: new Date().toLocaleString() }; - let msgContainer = msgContainerSendTemplate(context); - $(chatAreaNew).append(DOMPurify.sanitize(msgContainer)); - scrollChatAreaAnimated(2400); - let messageCipher = sjcl.encrypt(passphraseInput.value, messageContent, { mode: "gcm", ts: 128, adata: "", iter: iterations }); - let messageCipherJson = JSON.parse(messageCipher); - let chatMessageDTO = { - "toUser": user, - "messageCipher": messageCipherJson - } - messageSend(JSON.stringify(chatMessageDTO)); -}) - -document.getElementById('user-search').addEventListener('submit', function(e) { - e.preventDefault(); - let contactsBox = document.getElementById('contacts-box'); - let temp = contactsBox.innerHTML; - // log.trace(temp); - let searchTerm = document.getElementById('user-search-term').value; - log.debug("search term value = " + searchTerm); - let list = JSON.parse(sessionStorage.getItem('activeUsers')); - log.debug("active users"); - log.debug(list); - let fuse = new Fuse(list, fuseOptions); - let searchResult = fuse.search(searchTerm); - populateContactsBox(contactsBox, searchResult); - addUserCallBacks(); - log.debug(searchResult); -}) -document.getElementById('user-search-term').addEventListener('input', function(e) { - e.preventDefault(); - if (this.value.length < 2) { - log.debug("inputted") - let cancelButton = document.getElementById('user-search-cancel'); - cancelButton.hidden = false; - } -}) -document.getElementById('user-search-cancel').addEventListener('click', function(e) { - e.preventDefault(); - let list = JSON.parse(sessionStorage.getItem('activeUsers')); - let contactsBox = document.getElementById('contacts-box'); - populateContactsBox(contactsBox,list); - addUserCallBacks(); - document.getElementById('user-search-term').value = ""; - this.hidden = true; -}) - -function populateContactsBox(contactsBox, list) -{ - let userContactBoxList = ""; - list.forEach(function(activeUser) { - log.debug(activeUser); - if (activeUser.online) { - userContactBoxList += userContactOnlineTemplate(activeUser); - } else { - userContactBoxList += userContactOfflineTemplate(activeUser); - } - }) - contactsBox.innerHTML = userContactBoxList; -} - - - -// console.log('Credentials = ' + JSON.parse(sessionStorage.getItem('credentials'))); - - -function messageSend(chatMessageDTO) { - let headers = new Headers(); - // console.log("Token = " + btoa("hmm" + ":" + "hmm")) - - // headers.append('Accept','application/json') - headers.append('Content-Type', 'application/json'); - // headers.append('Authorization', basicAuthToken); - headers.append('X-AUTH-TOKEN', authToken); - fetch(postNewMessageUrl, { - method: 'POST', - headers: headers, - body: chatMessageDTO - }) - .then(response => { - console.log(response); - return response.clone(); - }) - .then(response => fetchHandler(response)); -} - - -async function getAllMessages(toUser) { - let headers = new Headers(); - // headers.append('Accept','application/json') - // headers.append('Content-Type', 'application/json'); - // headers.append('Authorization', basicAuthToken); - headers.append('X-AUTH-TOKEN', authToken); - let response = await fetch(getAllMessagesUrl + toUser, { - method: 'GET', - headers: headers - }); - console.log(response); - if (fetchErrorHandler(response.clone())) { - return null; - } - // if (response.status == 440) { - // window.alert('Token has expired. Please login again'); - // return null; - // } - let data = await response.json(); - return data; -} - -async function getNewMessages(toUser, lastMessageTimeStamp) { - let headers = new Headers(); - // headers.append('Authorization', basicAuthToken); - headers.append('X-AUTH-TOKEN', authToken); - let response = await fetch(`${getNewMessagesUrl}${toUser}/${lastMessageTimeStamp}`, { - method: 'GET', - headers: headers - }); - console.log(response.clone()); - if (fetchErrorHandler(response.clone())) { - return null; - } - let data = await response.json(); - return data; -} - - -async function getActiveUsers(authToken2) { - let headers = new Headers(); - // headers.append('Authorization', basicAuthToken); - headers.append('X-AUTH-TOKEN', authToken2); - let response = await fetch(getActiveUsersUrl, { - method: 'GET', - headers: headers - }); - console.log(response.clone()); - if (fetchErrorHandler(response.clone())) { - return null; - } - let data = await response.json(); - return data; -} - -$(document).ready(function() { - $('#action_menu_btn').click(function() { - $('.action_menu').toggle(); - }); -}); - -function fetchHandler(response) { - if (response.ok) { - return response.json().then(json => { - // the status was ok and there is a json body - // return Promise.resolve({ json: json, response: response }); - alertify.success('Message sent succesfully' + sprintf(" (http code %d)", response.status)); - }).catch(err => { - // the status was ok but there is no json body - // return Promise.resolve({ response: response }); - alertify.success('Message sent succesfully' + sprintf(" (http code %d)", response.status)); - }); - - } else { - return response.json().catch(err => { - // the status was not ok and there is no json body - // throw new Error(response.statusText); - alertify.error('Some error occured. Please try again.'); - }).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 - let delay = alertify.get('notifier', 'delay'); - alertify.set('notifier', 'delay', 30); - let errorMessage = ""; - json.errors.forEach(function(data) { - errorMessage += sprintf("Field Name: %s \n Rejected value: %s \n Reason: %s \n", data.field_name, data.rejected_value, data.error_message); - }); - alertify.error(sprintf('There were errors in your message - %s', errorMessage)); - alertify.set('notifier', 'delay', delay); - }); - } -} - - -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)); - 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)); - console.log(json); - return true; - }); - } -} - -function scrollChatAreaAnimated(delay) { - $(chatAreaNew).stop().animate({ - scrollTop: $(chatAreaNew)[0].scrollHeight - }, delay); -} \ No newline at end of file diff --git a/chatto/src/main/resources/static/js/my_Crypto.js b/chatto/src/main/resources/static/js/my_Crypto.js deleted file mode 100644 index 9ef7b37..0000000 --- a/chatto/src/main/resources/static/js/my_Crypto.js +++ /dev/null @@ -1,57 +0,0 @@ -var cipherText = sjcl.encrypt("password", "data"); -console.log(cipherText); -var plainText = sjcl.decrypt("password", cipherText); -console.log(plainText); - -var field = document.getElementById('crypt'); -// field.innerText = plainText; - -var jsonString = "{\"iv\":\"2rtnuXaJXFuQGO9ncaVkmA==\",\"v\":1,\"iter\":10000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"H1z7o3f6qlQ=\",\"ct\":\"lF9Uno7ihjVv01M8\"}"; - -var myJSON = JSON.parse(jsonString); -console.log(myJSON); - -// let base64 = require('base-64'); - -let headers = new Headers(); -console.log("Token = " + btoa("hmm" + ":" + "hmm")) - -// headers.append('Accept','application/json') -// headers.append('Content-Type', 'application/json'); -headers.append('Authorization', 'Basic ' + btoa("hmm" + ":" + "hmm")); -// headers.append('Authorization', 'Basic aG1tOmhtbQ=='); - - -// aG1tOmhtbQ== -var messageCipher; -fetch('http://localhost:8080/api/messages', { - method: 'GET', - headers: headers - // credentials: 'include' -}).then(response => response.json()) - .then(json => { - // console.log('parsed json', JSON.stringify(json)) // access json.body here - // console.log('parsed json', json[0].messageCipher); - messageCipher = JSON.stringify(json[0].messageCipher); - console.log(messageCipher); - console.log(sjcl.decrypt("password", messageCipher)); - - }); - // console.log("New message = " + messageCipher); - - // [{"messageID":5,"fromUser":{"userID":3,"userName":"user2","joinDate":1569224699000},"toUser":{"userID":6,"userName":"novo","joinDate":1569224706000},"messageCipher":{"iv":"2rtnuXaJXFuQGO9ncaVkmA==","v":1,"mode":"ccm","adata":"","cipher":"aes","salt":"H1z7o3f6qlQ=","iter":10000,"ks":128,"ts":64,"ct":"lF9Uno7ihjVv01M8"},"messageTime":1569685335000}] - -var url = 'http://localhost:8080/api/users' -xml = new XMLHttpRequest(); -xml.onreadystatechange = function () { - if (xml.readyState == XMLHttpRequest.DONE) { - // alert(xhr.responseText); - console.log(xml.responseText); - // console.log(xml.getResponseHeader('X-CSRF-TOKEN')); - } -} -xml.open('GET', url) -xml.setRequestHeader('Authorization', 'Basic aG1tOmhtbQ=='); -xml.setRequestHeader("X-CSRF-TOKEN", "fetch"); -xml.send(null); -