diff --git a/service-worker.js b/service-worker.js
index 291de24f..e48974ce 100644
--- a/service-worker.js
+++ b/service-worker.js
@@ -1,7 +1,9 @@
// Must be located at the root.
-importScripts("https://unpkg.com/firebase@5.5.5/firebase-app.js");
-importScripts("https://unpkg.com/firebase@5.5.5/firebase-messaging.js");
-importScripts("/src/firebase-init.js")
+importScripts('https://unpkg.com/firebase@5.5.5/firebase-app.js');
+importScripts('https://unpkg.com/firebase@5.5.5/firebase-messaging.js');
+importScripts('/src/firebase-init.json');
+
+console.log("FIREBASE_INIT", FIREBASE_INIT);
firebase.initializeApp(FIREBASE_INIT);
diff --git a/src/firebase-init.js b/src/firebase-init.js
deleted file mode 100644
index de1e462c..00000000
--- a/src/firebase-init.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Get these values for your project from the https://console.firebase.google.com/
-export const FIREBASE_INIT = {
- // Project Settings -> Cloud Messaging, "Sender ID".
- messagingSenderId: "114126160546",
- // Project Settings -> Cloud Messaging -> Web configuration -> Web Push certificates.
- // This value IS NOT included in the generated js config you can download from
- // the firebase console. It needs to be added separately.
- messagingVapidKey: "BOgQVPOMzIMXUpsYGpbVkZoEBc0ifKY_f2kSU5DNDGYI6i6CoKqqxDd7w7PJ3FaGRBgVGJffldETumOx831jl58"
-};
diff --git a/src/i18n/en.json b/src/i18n/en.json
new file mode 100644
index 00000000..f8fa0a2b
--- /dev/null
+++ b/src/i18n/en.json
@@ -0,0 +1,9 @@
+{
+ "login_prompt": "Login",
+ "password_prompt": "Password",
+ "stay_logged_in": "Stay logged in",
+ "forgot_password_link": "Forgot password?",
+ "sign_in_button": "Sign in",
+ "label_client": "Client:",
+ "label_server": "Server:"
+}
diff --git a/src/i18n/ru.json b/src/i18n/ru.json
new file mode 100644
index 00000000..b2802b92
--- /dev/null
+++ b/src/i18n/ru.json
@@ -0,0 +1,9 @@
+{
+ "login_prompt": "Логин",
+ "password_prompt": "Пароль",
+ "stay_logged_in": "Запомнить",
+ "forgot_password_link": "Напомнить пароль",
+ "sign_in_button": "Войти",
+ "label_client": "Клиент:",
+ "label_server": "Сервер:"
+}
diff --git a/src/index.js b/src/index.js
index bdde1523..8a49be28 100644
--- a/src/index.js
+++ b/src/index.js
@@ -3,13 +3,18 @@
import React from 'react';
import ReactDOM from 'react-dom';
-import { IntlProvider } from 'react-intl';
+import { IntlProvider, addLocaleData } from 'react-intl';
+import ruData from 'react-intl/locale-data/ru';
+addLocaleData(ruData);
+import en from './i18n/en.json';
+import ru from './i18n/ru.json';
import TinodeWeb from './views/tinode-web.jsx';
ReactDOM.render(
+ locale={navigator.language}
+ messages={en} >
,
document.getElementById('mountPoint')
diff --git a/src/lib/navigation.js b/src/lib/navigation.js
index 870aa945..4411763a 100644
--- a/src/lib/navigation.js
+++ b/src/lib/navigation.js
@@ -41,28 +41,28 @@ export default class HashNavigation {
}
static addUrlParam(hash, key, value) {
- var parsed = parseUrlHash(hash);
+ var parsed = this.parseUrlHash(hash);
parsed.params[key] = value;
- return composeUrlHash(parsed.path, parsed.params);
+ return this.composeUrlHash(parsed.path, parsed.params);
}
static removeUrlParam(hash, key) {
- var parsed = parseUrlHash(hash);
+ var parsed = this.parseUrlHash(hash);
delete parsed.params[key];
- return composeUrlHash(parsed.path, parsed.params);
+ return this.composeUrlHash(parsed.path, parsed.params);
}
static setUrlSidePanel(hash, sidepanel) {
- var parsed = parseUrlHash(hash);
+ var parsed = this.parseUrlHash(hash);
parsed.path[0] = sidepanel;
- return composeUrlHash(parsed.path, parsed.params);
+ return this.composeUrlHash(parsed.path, parsed.params);
}
static setUrlTopic(hash, topic) {
- var parsed = parseUrlHash(hash);
+ var parsed = this.parseUrlHash(hash);
parsed.path[1] = topic;
// Close InfoView on topic change.
delete parsed.params.info;
- return composeUrlHash(parsed.path, parsed.params);
+ return this.composeUrlHash(parsed.path, parsed.params);
}
}
diff --git a/src/views/login-view.jsx b/src/views/login-view.jsx
index aef390fe..5b96b727 100644
--- a/src/views/login-view.jsx
+++ b/src/views/login-view.jsx
@@ -1,5 +1,4 @@
-// Login form
-
+// Login form.
import React from 'react';
import { FormattedMessage } from 'react-intl';
@@ -50,7 +49,7 @@ export default class LoginView extends React.Component {
return (
diff --git a/src/views/logo-view.jsx b/src/views/logo-view.jsx
index ea4300f6..ca8b4904 100644
--- a/src/views/logo-view.jsx
+++ b/src/views/logo-view.jsx
@@ -1,5 +1,6 @@
/* This is just a static page to display when no conversation is selected. */
import React from 'react';
+import { FormattedMessage } from 'react-intl';
import Tinode from 'tinode-sdk';
@@ -15,8 +16,9 @@ export default class LogoView extends React.PureComponent {
Tinode Web
- Client: {version}
- Server: {this.props.serverVersion} ({this.props.serverAddress})
+ {version}
+ {this.props.serverVersion}
+ ({this.props.serverAddress})
);
diff --git a/src/views/tinode-web.jsx b/src/views/tinode-web.jsx
index 1632564a..1b8e5e12 100644
--- a/src/views/tinode-web.jsx
+++ b/src/views/tinode-web.jsx
@@ -3,7 +3,7 @@ import React from 'react';
import 'firebase/app';
import 'firebase/messaging';
-import { FIREBASE_INIT } from '../firebase-init.js'
+import { FIREBASE_INIT } from '../firebase-init.json';
import Tinode from 'tinode-sdk';
@@ -21,6 +21,8 @@ import HashNavigation from '../lib/navigation.js';
// Sound to play on message received.
export const POP_SOUND = new Audio('audio/msg.mp3');
+console.log(FIREBASE_INIT);
+
export default class TinodeWeb extends React.Component {
constructor(props) {
super(props);
diff --git a/umd/index.dev.js b/umd/index.dev.js
index bf03f47e..f7f3e7ed 100644
--- a/umd/index.dev.js
+++ b/umd/index.dev.js
@@ -525,6 +525,17 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ }),
+/***/ "./node_modules/react-intl/locale-data/ru.js":
+/*!***************************************************!*\
+ !*** ./node_modules/react-intl/locale-data/ru.js ***!
+ \***************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+eval("!function(e,a){ true?module.exports=a():undefined}(this,function(){\"use strict\";return[{locale:\"ru\",pluralRuleFunction:function(e,a){var t=String(e).split(\".\"),r=t[0],o=!t[1],n=r.slice(-1),l=r.slice(-2);return a?\"other\":o&&1==n&&11!=l?\"one\":o&&n>=2&&n<=4&&(l<12||l>14)?\"few\":o&&0==n||o&&n>=5&&n<=9||o&&l>=11&&l<=14?\"many\":\"other\"},fields:{year:{displayName:\"год\",relative:{0:\"в этом году\",1:\"в следующем году\",\"-1\":\"в прошлом году\"},relativeTime:{future:{one:\"через {0} год\",few:\"через {0} года\",many:\"через {0} лет\",other:\"через {0} года\"},past:{one:\"{0} год назад\",few:\"{0} года назад\",many:\"{0} лет назад\",other:\"{0} года назад\"}}},month:{displayName:\"месяц\",relative:{0:\"в этом месяце\",1:\"в следующем месяце\",\"-1\":\"в прошлом месяце\"},relativeTime:{future:{one:\"через {0} месяц\",few:\"через {0} месяца\",many:\"через {0} месяцев\",other:\"через {0} месяца\"},past:{one:\"{0} месяц назад\",few:\"{0} месяца назад\",many:\"{0} месяцев назад\",other:\"{0} месяца назад\"}}},day:{displayName:\"день\",relative:{0:\"сегодня\",1:\"завтра\",2:\"послезавтра\",\"-2\":\"позавчера\",\"-1\":\"вчера\"},relativeTime:{future:{one:\"через {0} день\",few:\"через {0} дня\",many:\"через {0} дней\",other:\"через {0} дня\"},past:{one:\"{0} день назад\",few:\"{0} дня назад\",many:\"{0} дней назад\",other:\"{0} дня назад\"}}},hour:{displayName:\"час\",relative:{0:\"в этом часе\"},relativeTime:{future:{one:\"через {0} час\",few:\"через {0} часа\",many:\"через {0} часов\",other:\"через {0} часа\"},past:{one:\"{0} час назад\",few:\"{0} часа назад\",many:\"{0} часов назад\",other:\"{0} часа назад\"}}},minute:{displayName:\"минута\",relative:{0:\"в эту минуту\"},relativeTime:{future:{one:\"через {0} минуту\",few:\"через {0} минуты\",many:\"через {0} минут\",other:\"через {0} минуты\"},past:{one:\"{0} минуту назад\",few:\"{0} минуты назад\",many:\"{0} минут назад\",other:\"{0} минуты назад\"}}},second:{displayName:\"секунда\",relative:{0:\"сейчас\"},relativeTime:{future:{one:\"через {0} секунду\",few:\"через {0} секунды\",many:\"через {0} секунд\",other:\"через {0} секунды\"},past:{one:\"{0} секунду назад\",few:\"{0} секунды назад\",many:\"{0} секунд назад\",other:\"{0} секунды назад\"}}}}},{locale:\"ru-BY\",parentLocale:\"ru\"},{locale:\"ru-KG\",parentLocale:\"ru\"},{locale:\"ru-KZ\",parentLocale:\"ru\"},{locale:\"ru-MD\",parentLocale:\"ru\"},{locale:\"ru-UA\",parentLocale:\"ru\"}]});\n\n\n//# sourceURL=webpack:///./node_modules/react-intl/locale-data/ru.js?");
+
+/***/ }),
+
/***/ "./node_modules/react/cjs/react.development.js":
/*!*****************************************************!*\
!*** ./node_modules/react/cjs/react.development.js ***!
@@ -665,15 +676,36 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ }),
-/***/ "./src/firebase-init.js":
-/*!******************************!*\
- !*** ./src/firebase-init.js ***!
- \******************************/
-/*! exports provided: FIREBASE_INIT */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
+/***/ "./src/firebase-init.json":
+/*!********************************!*\
+ !*** ./src/firebase-init.json ***!
+ \********************************/
+/*! exports provided: FIREBASE_INIT, default */
+/***/ (function(module) {
-"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"FIREBASE_INIT\", function() { return FIREBASE_INIT; });\n// Get these values for your project from the https://console.firebase.google.com/\nvar FIREBASE_INIT = {\n // Project Settings -> Cloud Messaging, \"Sender ID\".\n messagingSenderId: \"114126160546\",\n // Project Settings -> Cloud Messaging -> Web configuration -> Web Push certificates.\n // This value IS NOT included in the generated js config you can download from\n // the firebase console. It needs to be added separately.\n messagingVapidKey: \"BOgQVPOMzIMXUpsYGpbVkZoEBc0ifKY_f2kSU5DNDGYI6i6CoKqqxDd7w7PJ3FaGRBgVGJffldETumOx831jl58\"\n};\n\n//# sourceURL=webpack:///./src/firebase-init.js?");
+eval("module.exports = {\"FIREBASE_INIT\":{\"messagingSenderId\":\"114126160546\",\"messagingVapidKey\":\"BOgQVPOMzIMXUpsYGpbVkZoEBc0ifKY_f2kSU5DNDGYI6i6CoKqqxDd7w7PJ3FaGRBgVGJffldETumOx831jl58\"}};\n\n//# sourceURL=webpack:///./src/firebase-init.json?");
+
+/***/ }),
+
+/***/ "./src/i18n/en.json":
+/*!**************************!*\
+ !*** ./src/i18n/en.json ***!
+ \**************************/
+/*! exports provided: login_prompt, password_prompt, stay_logged_in, forgot_password_link, sign_in_button, label_client, label_server, default */
+/***/ (function(module) {
+
+eval("module.exports = {\"login_prompt\":\"Login\",\"password_prompt\":\"Password\",\"stay_logged_in\":\"Stay logged in\",\"forgot_password_link\":\"Forgot password?\",\"sign_in_button\":\"Sign in\",\"label_client\":\"Client:\",\"label_server\":\"Server:\"};\n\n//# sourceURL=webpack:///./src/i18n/en.json?");
+
+/***/ }),
+
+/***/ "./src/i18n/ru.json":
+/*!**************************!*\
+ !*** ./src/i18n/ru.json ***!
+ \**************************/
+/*! exports provided: login_prompt, password_prompt, stay_logged_in, forgot_password_link, sign_in_button, label_client, label_server, default */
+/***/ (function(module) {
+
+eval("module.exports = {\"login_prompt\":\"Логин\",\"password_prompt\":\"Пароль\",\"stay_logged_in\":\"Запомнить\",\"forgot_password_link\":\"Напомнить пароль\",\"sign_in_button\":\"Войти\",\"label_client\":\"Клиент:\",\"label_server\":\"Сервер:\"};\n\n//# sourceURL=webpack:///./src/i18n/ru.json?");
/***/ }),
@@ -685,7 +717,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-dom */ \"./node_modules/react-dom/index.js\");\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-intl */ \"./node_modules/react-intl/lib/index.es.js\");\n/* harmony import */ var _views_tinode_web_jsx__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./views/tinode-web.jsx */ \"./src/views/tinode-web.jsx\");\n// Put all packages together.\n// Used to generate umd/index.prod.js\n\n\n\n\nreact_dom__WEBPACK_IMPORTED_MODULE_1___default.a.render(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_2__[\"IntlProvider\"], {\n locale: navigator.language\n}, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_views_tinode_web_jsx__WEBPACK_IMPORTED_MODULE_3__[\"default\"], null)), document.getElementById('mountPoint'));\n\n//# sourceURL=webpack:///./src/index.js?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-dom */ \"./node_modules/react-dom/index.js\");\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-intl */ \"./node_modules/react-intl/lib/index.es.js\");\n/* harmony import */ var react_intl_locale_data_ru__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-intl/locale-data/ru */ \"./node_modules/react-intl/locale-data/ru.js\");\n/* harmony import */ var react_intl_locale_data_ru__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_intl_locale_data_ru__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _i18n_en_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./i18n/en.json */ \"./src/i18n/en.json\");\nvar _i18n_en_json__WEBPACK_IMPORTED_MODULE_4___namespace = /*#__PURE__*/__webpack_require__.t(/*! ./i18n/en.json */ \"./src/i18n/en.json\", 1);\n/* harmony import */ var _i18n_ru_json__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./i18n/ru.json */ \"./src/i18n/ru.json\");\nvar _i18n_ru_json__WEBPACK_IMPORTED_MODULE_5___namespace = /*#__PURE__*/__webpack_require__.t(/*! ./i18n/ru.json */ \"./src/i18n/ru.json\", 1);\n/* harmony import */ var _views_tinode_web_jsx__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./views/tinode-web.jsx */ \"./src/views/tinode-web.jsx\");\n// Put all packages together.\n// Used to generate umd/index.prod.js\n\n\n\n\nObject(react_intl__WEBPACK_IMPORTED_MODULE_2__[\"addLocaleData\"])(react_intl_locale_data_ru__WEBPACK_IMPORTED_MODULE_3___default.a);\n\n\n\nreact_dom__WEBPACK_IMPORTED_MODULE_1___default.a.render(react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_2__[\"IntlProvider\"], {\n locale: navigator.language,\n messages: _i18n_en_json__WEBPACK_IMPORTED_MODULE_4__\n}, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_views_tinode_web_jsx__WEBPACK_IMPORTED_MODULE_6__[\"default\"], null)), document.getElementById('mountPoint'));\n\n//# sourceURL=webpack:///./src/index.js?");
/***/ }),
@@ -721,7 +753,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return HashNavigation; });\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// Utility class for hash navigation.\n// Parse hash as in http://www.example.com/path#hash as if it were\n// path and arguments.\nvar HashNavigation =\n/*#__PURE__*/\nfunction () {\n function HashNavigation() {\n _classCallCheck(this, HashNavigation);\n }\n\n _createClass(HashNavigation, null, [{\n key: \"parseUrlHash\",\n value: function parseUrlHash(hash) {\n // Split path from args, path -> parts[0], args->path[1]\n var parts = hash.split('?', 2);\n var params = {};\n var path = [];\n\n if (parts[0]) {\n path = parts[0].substr(1).split('/');\n }\n\n if (parts[1]) {\n parts[1].split('&').forEach(function (part) {\n var item = part.split('=');\n\n if (item[0]) {\n params[decodeURIComponent(item[0])] = decodeURIComponent(item[1]);\n }\n });\n }\n\n return {\n path: path,\n params: params\n };\n }\n }, {\n key: \"navigateTo\",\n value: function navigateTo(url) {\n window.location.hash = url;\n }\n }, {\n key: \"composeUrlHash\",\n value: function composeUrlHash(path, params) {\n var url = path.join('/');\n var args = [];\n\n for (var key in params) {\n if (params.hasOwnProperty(key)) {\n args.push(key + '=' + params[key]);\n }\n }\n\n if (args.length > 0) {\n url += '?' + args.join('&');\n }\n\n return url;\n }\n }, {\n key: \"addUrlParam\",\n value: function addUrlParam(hash, key, value) {\n var parsed = parseUrlHash(hash);\n parsed.params[key] = value;\n return composeUrlHash(parsed.path, parsed.params);\n }\n }, {\n key: \"removeUrlParam\",\n value: function removeUrlParam(hash, key) {\n var parsed = parseUrlHash(hash);\n delete parsed.params[key];\n return composeUrlHash(parsed.path, parsed.params);\n }\n }, {\n key: \"setUrlSidePanel\",\n value: function setUrlSidePanel(hash, sidepanel) {\n var parsed = parseUrlHash(hash);\n parsed.path[0] = sidepanel;\n return composeUrlHash(parsed.path, parsed.params);\n }\n }, {\n key: \"setUrlTopic\",\n value: function setUrlTopic(hash, topic) {\n var parsed = parseUrlHash(hash);\n parsed.path[1] = topic; // Close InfoView on topic change.\n\n delete parsed.params.info;\n return composeUrlHash(parsed.path, parsed.params);\n }\n }]);\n\n return HashNavigation;\n}();\n\n\n\n//# sourceURL=webpack:///./src/lib/navigation.js?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return HashNavigation; });\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\n// Utility class for hash navigation.\n// Parse hash as in http://www.example.com/path#hash as if it were\n// path and arguments.\nvar HashNavigation =\n/*#__PURE__*/\nfunction () {\n function HashNavigation() {\n _classCallCheck(this, HashNavigation);\n }\n\n _createClass(HashNavigation, null, [{\n key: \"parseUrlHash\",\n value: function parseUrlHash(hash) {\n // Split path from args, path -> parts[0], args->path[1]\n var parts = hash.split('?', 2);\n var params = {};\n var path = [];\n\n if (parts[0]) {\n path = parts[0].substr(1).split('/');\n }\n\n if (parts[1]) {\n parts[1].split('&').forEach(function (part) {\n var item = part.split('=');\n\n if (item[0]) {\n params[decodeURIComponent(item[0])] = decodeURIComponent(item[1]);\n }\n });\n }\n\n return {\n path: path,\n params: params\n };\n }\n }, {\n key: \"navigateTo\",\n value: function navigateTo(url) {\n window.location.hash = url;\n }\n }, {\n key: \"composeUrlHash\",\n value: function composeUrlHash(path, params) {\n var url = path.join('/');\n var args = [];\n\n for (var key in params) {\n if (params.hasOwnProperty(key)) {\n args.push(key + '=' + params[key]);\n }\n }\n\n if (args.length > 0) {\n url += '?' + args.join('&');\n }\n\n return url;\n }\n }, {\n key: \"addUrlParam\",\n value: function addUrlParam(hash, key, value) {\n var parsed = this.parseUrlHash(hash);\n parsed.params[key] = value;\n return this.composeUrlHash(parsed.path, parsed.params);\n }\n }, {\n key: \"removeUrlParam\",\n value: function removeUrlParam(hash, key) {\n var parsed = this.parseUrlHash(hash);\n delete parsed.params[key];\n return this.composeUrlHash(parsed.path, parsed.params);\n }\n }, {\n key: \"setUrlSidePanel\",\n value: function setUrlSidePanel(hash, sidepanel) {\n var parsed = this.parseUrlHash(hash);\n parsed.path[0] = sidepanel;\n return this.composeUrlHash(parsed.path, parsed.params);\n }\n }, {\n key: \"setUrlTopic\",\n value: function setUrlTopic(hash, topic) {\n var parsed = this.parseUrlHash(hash);\n parsed.path[1] = topic; // Close InfoView on topic change.\n\n delete parsed.params.info;\n return this.composeUrlHash(parsed.path, parsed.params);\n }\n }]);\n\n return HashNavigation;\n}();\n\n\n\n//# sourceURL=webpack:///./src/lib/navigation.js?");
/***/ }),
@@ -733,7 +765,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PACKAGE_VERSION\", function() { return PACKAGE_VERSION; });\nvar PACKAGE_VERSION = \"0.15.8-rc1\";\n\n//# sourceURL=webpack:///./src/version.js?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"PACKAGE_VERSION\", function() { return PACKAGE_VERSION; });\n// This is a generated file. Don't edit.\nvar PACKAGE_VERSION = \"0.15.8-rc1\";\n\n//# sourceURL=webpack:///./src/version.js?");
/***/ }),
@@ -793,7 +825,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return LoginView; });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-intl */ \"./node_modules/react-intl/lib/index.es.js\");\n/* harmony import */ var _widgets_checkbox_jsx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../widgets/checkbox.jsx */ \"./src/widgets/checkbox.jsx\");\n/* harmony import */ var _widgets_visible_password_jsx__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../widgets/visible-password.jsx */ \"./src/widgets/visible-password.jsx\");\n/* harmony import */ var _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../lib/local-storage.js */ \"./src/lib/local-storage.js\");\nfunction _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\n// Login form\n\n\n\n\n\n\nvar LoginView =\n/*#__PURE__*/\nfunction (_React$Component) {\n _inherits(LoginView, _React$Component);\n\n function LoginView(props) {\n var _this;\n\n _classCallCheck(this, LoginView);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(LoginView).call(this, props));\n _this.state = {\n login: props.login,\n password: '',\n hostName: props.serverAddress,\n saveToken: _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"].getObject('keep-logged-in')\n };\n _this.handleLoginChange = _this.handleLoginChange.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handlePasswordChange = _this.handlePasswordChange.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleToggleSaveToken = _this.handleToggleSaveToken.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleSubmit = _this.handleSubmit.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n return _this;\n }\n\n _createClass(LoginView, [{\n key: \"handleLoginChange\",\n value: function handleLoginChange(e) {\n this.setState({\n login: e.target.value\n });\n }\n }, {\n key: \"handlePasswordChange\",\n value: function handlePasswordChange(e) {\n this.setState({\n password: e.target.value\n });\n }\n }, {\n key: \"handleToggleSaveToken\",\n value: function handleToggleSaveToken() {\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"].setObject('keep-logged-in', !this.state.saveToken);\n this.setState({\n saveToken: !this.state.saveToken\n });\n }\n }, {\n key: \"handleSubmit\",\n value: function handleSubmit(e) {\n e.preventDefault();\n this.props.onLogin(this.state.login.trim(), this.state.password.trim());\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this2 = this;\n\n var submitClasses = 'blue';\n\n if (this.props.disabled) {\n submitClasses += ' disabled';\n }\n\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"form\", {\n id: \"login-form\",\n onSubmit: this.handleSubmit\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__[\"FormattedMessage\"], {\n id: \"login.login_prompt\",\n defaultMessage: \"Login\"\n }, function (login_prompt) {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"input\", {\n type: \"text\",\n id: \"inputLogin\",\n placeholder: login_prompt,\n autoComplete: \"username\",\n value: _this2.state.login,\n onChange: _this2.handleLoginChange,\n required: true,\n autoFocus: true\n });\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__[\"FormattedMessage\"], {\n id: \"login.password_prompt\",\n defaultMessage: \"Password\"\n }, function (password_prompt) {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_widgets_visible_password_jsx__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n type: \"password\",\n id: \"inputPassword\",\n placeholder: password_prompt,\n autoComplete: \"current-password\",\n value: _this2.state.password,\n onChange: _this2.handlePasswordChange,\n required: true\n });\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"panel-form-row\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_widgets_checkbox_jsx__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n id: \"save-token\",\n name: \"save-token\",\n checked: this.state.saveToken,\n onChange: this.handleToggleSaveToken\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"label\", {\n htmlFor: \"save-token\"\n }, \"\\xA0\", react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__[\"FormattedMessage\"], {\n id: \"login.stay_logged_in\",\n defaultMessage: \"Stay logged in\"\n })), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"a\", {\n href: \"#reset\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__[\"FormattedMessage\"], {\n id: \"login.forgot_password_link\",\n defaultMessage: \"Forgot password?\"\n }))), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"dialog-buttons\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: submitClasses,\n type: \"submit\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__[\"FormattedMessage\"], {\n id: \"login.sign_in_button\",\n defaultMessage: \"Sign in\"\n }))));\n }\n }]);\n\n return LoginView;\n}(react__WEBPACK_IMPORTED_MODULE_0___default.a.Component);\n\n\n;\n/* END Login */\n\n//# sourceURL=webpack:///./src/views/login-view.jsx?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return LoginView; });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-intl */ \"./node_modules/react-intl/lib/index.es.js\");\n/* harmony import */ var _widgets_checkbox_jsx__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../widgets/checkbox.jsx */ \"./src/widgets/checkbox.jsx\");\n/* harmony import */ var _widgets_visible_password_jsx__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../widgets/visible-password.jsx */ \"./src/widgets/visible-password.jsx\");\n/* harmony import */ var _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../lib/local-storage.js */ \"./src/lib/local-storage.js\");\nfunction _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\n// Login form.\n\n\n\n\n\n\nvar LoginView =\n/*#__PURE__*/\nfunction (_React$Component) {\n _inherits(LoginView, _React$Component);\n\n function LoginView(props) {\n var _this;\n\n _classCallCheck(this, LoginView);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(LoginView).call(this, props));\n _this.state = {\n login: props.login,\n password: '',\n hostName: props.serverAddress,\n saveToken: _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"].getObject('keep-logged-in')\n };\n _this.handleLoginChange = _this.handleLoginChange.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handlePasswordChange = _this.handlePasswordChange.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleToggleSaveToken = _this.handleToggleSaveToken.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleSubmit = _this.handleSubmit.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n return _this;\n }\n\n _createClass(LoginView, [{\n key: \"handleLoginChange\",\n value: function handleLoginChange(e) {\n this.setState({\n login: e.target.value\n });\n }\n }, {\n key: \"handlePasswordChange\",\n value: function handlePasswordChange(e) {\n this.setState({\n password: e.target.value\n });\n }\n }, {\n key: \"handleToggleSaveToken\",\n value: function handleToggleSaveToken() {\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_4__[\"default\"].setObject('keep-logged-in', !this.state.saveToken);\n this.setState({\n saveToken: !this.state.saveToken\n });\n }\n }, {\n key: \"handleSubmit\",\n value: function handleSubmit(e) {\n e.preventDefault();\n this.props.onLogin(this.state.login.trim(), this.state.password.trim());\n }\n }, {\n key: \"render\",\n value: function render() {\n var _this2 = this;\n\n var submitClasses = 'blue';\n\n if (this.props.disabled) {\n submitClasses += ' disabled';\n }\n\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"form\", {\n id: \"login-form\",\n onSubmit: this.handleSubmit\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__[\"FormattedMessage\"], {\n id: \"login_prompt\",\n defaultMessage: \"Login\"\n }, function (login_prompt) {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"input\", {\n type: \"text\",\n id: \"inputLogin\",\n placeholder: login_prompt,\n autoComplete: \"username\",\n value: _this2.state.login,\n onChange: _this2.handleLoginChange,\n required: true,\n autoFocus: true\n });\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__[\"FormattedMessage\"], {\n id: \"password_prompt\",\n defaultMessage: \"Password\"\n }, function (password_prompt) {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_widgets_visible_password_jsx__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n type: \"password\",\n id: \"inputPassword\",\n placeholder: password_prompt,\n autoComplete: \"current-password\",\n value: _this2.state.password,\n onChange: _this2.handlePasswordChange,\n required: true\n });\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"panel-form-row\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_widgets_checkbox_jsx__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n id: \"save-token\",\n name: \"save-token\",\n checked: this.state.saveToken,\n onChange: this.handleToggleSaveToken\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"label\", {\n htmlFor: \"save-token\"\n }, \"\\xA0\", react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__[\"FormattedMessage\"], {\n id: \"stay_logged_in\",\n defaultMessage: \"Stay logged in\"\n })), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"a\", {\n href: \"#reset\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__[\"FormattedMessage\"], {\n id: \"forgot_password_link\",\n defaultMessage: \"Forgot password?\"\n }))), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"dialog-buttons\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"button\", {\n className: submitClasses,\n type: \"submit\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__[\"FormattedMessage\"], {\n id: \"sign_in_button\",\n defaultMessage: \"Sign in\"\n }))));\n }\n }]);\n\n return LoginView;\n}(react__WEBPACK_IMPORTED_MODULE_0___default.a.Component);\n\n\n;\n/* END Login */\n\n//# sourceURL=webpack:///./src/views/login-view.jsx?");
/***/ }),
@@ -805,7 +837,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return LogoView; });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! tinode-sdk */ \"./node_modules/tinode-sdk/umd/tinode.prod.js\");\n/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(tinode_sdk__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../config.js */ \"./src/config.js\");\nfunction _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\n/* This is just a static page to display when no conversation is selected. */\n\n\n\n\nvar LogoView =\n/*#__PURE__*/\nfunction (_React$PureComponent) {\n _inherits(LogoView, _React$PureComponent);\n\n function LogoView() {\n _classCallCheck(this, LogoView);\n\n return _possibleConstructorReturn(this, _getPrototypeOf(LogoView).apply(this, arguments));\n }\n\n _createClass(LogoView, [{\n key: \"render\",\n value: function render() {\n var version = _config_js__WEBPACK_IMPORTED_MODULE_2__[\"APP_NAME\"] + ' (' + tinode_sdk__WEBPACK_IMPORTED_MODULE_1___default.a.getLibrary() + ')';\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"dummy-view\",\n className: this.props.hideSelf ? 'nodisplay' : null\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"a\", {\n href: \"https://github.com/tinode/chat/\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"img\", {\n id: \"logo\",\n alt: \"logo\",\n src: \"img/logo.svg\"\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h2\", null, \"Tinode Web\")), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"p\", null, \"Client: \", version), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"p\", null, \"Server: \", this.props.serverVersion, \" (\", this.props.serverAddress, \")\")));\n }\n }]);\n\n return LogoView;\n}(react__WEBPACK_IMPORTED_MODULE_0___default.a.PureComponent);\n\n\n;\n\n//# sourceURL=webpack:///./src/views/logo-view.jsx?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return LogoView; });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-intl */ \"./node_modules/react-intl/lib/index.es.js\");\n/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! tinode-sdk */ \"./node_modules/tinode-sdk/umd/tinode.prod.js\");\n/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(tinode_sdk__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../config.js */ \"./src/config.js\");\nfunction _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\n/* This is just a static page to display when no conversation is selected. */\n\n\n\n\n\nvar LogoView =\n/*#__PURE__*/\nfunction (_React$PureComponent) {\n _inherits(LogoView, _React$PureComponent);\n\n function LogoView() {\n _classCallCheck(this, LogoView);\n\n return _possibleConstructorReturn(this, _getPrototypeOf(LogoView).apply(this, arguments));\n }\n\n _createClass(LogoView, [{\n key: \"render\",\n value: function render() {\n var version = _config_js__WEBPACK_IMPORTED_MODULE_3__[\"APP_NAME\"] + ' (' + tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default.a.getLibrary() + ')';\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"dummy-view\",\n className: this.props.hideSelf ? 'nodisplay' : null\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"a\", {\n href: \"https://github.com/tinode/chat/\"\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"img\", {\n id: \"logo\",\n alt: \"logo\",\n src: \"img/logo.svg\"\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h2\", null, \"Tinode Web\")), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"p\", null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__[\"FormattedMessage\"], {\n id: \"label_client\",\n defaultMessage: \"Client:\"\n }), \" \", version), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"p\", null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__[\"FormattedMessage\"], {\n id: \"label_server\",\n defaultMessage: \"Server:\"\n }), \" \", this.props.serverVersion, \"(\", this.props.serverAddress, \")\")));\n }\n }]);\n\n return LogoView;\n}(react__WEBPACK_IMPORTED_MODULE_0___default.a.PureComponent);\n\n\n;\n\n//# sourceURL=webpack:///./src/views/logo-view.jsx?");
/***/ }),
@@ -877,7 +909,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) *
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"POP_SOUND\", function() { return POP_SOUND; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return TinodeWeb; });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var firebase_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! firebase/app */ \"./node_modules/firebase/app/dist/index.cjs.js\");\n/* harmony import */ var firebase_app__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(firebase_app__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var firebase_messaging__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! firebase/messaging */ \"./node_modules/firebase/messaging/dist/index.esm.js\");\n/* harmony import */ var _firebase_init_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../firebase-init.js */ \"./src/firebase-init.js\");\n/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! tinode-sdk */ \"./node_modules/tinode-sdk/umd/tinode.prod.js\");\n/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(tinode_sdk__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _widgets_context_menu_jsx__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../widgets/context-menu.jsx */ \"./src/widgets/context-menu.jsx\");\n/* harmony import */ var _info_view_jsx__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./info-view.jsx */ \"./src/views/info-view.jsx\");\n/* harmony import */ var _messages_view_jsx__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./messages-view.jsx */ \"./src/views/messages-view.jsx\");\n/* harmony import */ var _sidepanel_view_jsx__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./sidepanel-view.jsx */ \"./src/views/sidepanel-view.jsx\");\n/* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../config.js */ \"./src/config.js\");\n/* harmony import */ var _lib_host_name_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../lib/host-name.js */ \"./src/lib/host-name.js\");\n/* harmony import */ var _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../lib/local-storage.js */ \"./src/lib/local-storage.js\");\n/* harmony import */ var _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../lib/navigation.js */ \"./src/lib/navigation.js\");\nfunction _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\n// The top-level class to hold all functionality together.\n\n\n\n\n\n\n\n\n\n\n\n\n // Sound to play on message received.\n\nvar POP_SOUND = new Audio('audio/msg.mp3');\n\nvar TinodeWeb =\n/*#__PURE__*/\nfunction (_React$Component) {\n _inherits(TinodeWeb, _React$Component);\n\n function TinodeWeb(props) {\n var _this;\n\n _classCallCheck(this, TinodeWeb);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(TinodeWeb).call(this, props));\n _this.state = _this.getBlankState();\n _this.handleResize = _this.handleResize.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleHashRoute = _this.handleHashRoute.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleOnline = _this.handleOnline.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleAppVisibility = _this.handleAppVisibility.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleReadTimer = _this.handleReadTimer.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleVisibilityEvent = _this.handleVisibilityEvent.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleError = _this.handleError.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleLoginRequest = _this.handleLoginRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleConnected = _this.handleConnected.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.doLogin = _this.doLogin.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleCredentialsRequest = _this.handleCredentialsRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleLoginSuccessful = _this.handleLoginSuccessful.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleDisconnect = _this.handleDisconnect.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.tnMeMetaDesc = _this.tnMeMetaDesc.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.tnMeContactUpdate = _this.tnMeContactUpdate.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.tnMeSubsUpdated = _this.tnMeSubsUpdated.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.resetContactList = _this.resetContactList.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.tnData = _this.tnData.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.tnInitFind = _this.tnInitFind.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.tnFndSubsUpdated = _this.tnFndSubsUpdated.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleSearchContacts = _this.handleSearchContacts.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleTopicSelected = _this.handleTopicSelected.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleHideMessagesView = _this.handleHideMessagesView.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleSendMessage = _this.handleSendMessage.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleNewAccount = _this.handleNewAccount.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleNewAccountRequest = _this.handleNewAccountRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleUpdateAccountRequest = _this.handleUpdateAccountRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleUpdateAccountTagsRequest = _this.handleUpdateAccountTagsRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleSettings = _this.handleSettings.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleGlobalSettings = _this.handleGlobalSettings.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleToggleMessageSounds = _this.handleToggleMessageSounds.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.initDesktopAlerts = _this.initDesktopAlerts.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.togglePushToken = _this.togglePushToken.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.requestPushToken = _this.requestPushToken.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleSidepanelCancel = _this.handleSidepanelCancel.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleNewTopic = _this.handleNewTopic.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleNewTopicRequest = _this.handleNewTopicRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleNewTopicCreated = _this.handleNewTopicCreated.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleTopicUpdateRequest = _this.handleTopicUpdateRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleChangePermissions = _this.handleChangePermissions.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleTagsUpdated = _this.handleTagsUpdated.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleLogout = _this.handleLogout.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleLeaveUnsubRequest = _this.handleLeaveUnsubRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleDialogCancel = _this.handleDialogCancel.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleShowContextMenu = _this.handleShowContextMenu.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.defaultTopicContextMenu = _this.defaultTopicContextMenu.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleHideContextMenu = _this.handleHideContextMenu.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleShowInfoView = _this.handleShowInfoView.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleHideInfoView = _this.handleHideInfoView.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleMemberUpdateRequest = _this.handleMemberUpdateRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleValidateCredentialsRequest = _this.handleValidateCredentialsRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handlePasswordResetRequest = _this.handlePasswordResetRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleResetPassword = _this.handleResetPassword.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n return _this;\n }\n\n _createClass(TinodeWeb, [{\n key: \"getBlankState\",\n value: function getBlankState() {\n var _ref;\n\n var settings = _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].getObject(\"settings\") || {};\n return _ref = {\n connected: false,\n transport: settings.transport || null,\n serverAddress: settings.serverAddress || detectServerAddress(),\n serverVersion: \"no connection\",\n // \"On\" is the default, so saving the \"off\" state.\n messageSounds: !settings.messageSoundsOff,\n desktopAlerts: settings.desktopAlerts,\n desktopAlertsEnabled: (Object(_lib_host_name_js__WEBPACK_IMPORTED_MODULE_10__[\"isSecureConnection\"])() || Object(_lib_host_name_js__WEBPACK_IMPORTED_MODULE_10__[\"isLocalHost\"])()) && typeof firebase != 'undefined' && typeof navigator != 'undefined' && typeof _firebase_init_js__WEBPACK_IMPORTED_MODULE_3__[\"FIREBASE_INIT\"] != 'undefined',\n firebaseToken: _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].getObject(\"firebase-token\"),\n errorText: '',\n errorLevel: null,\n sidePanelSelected: 'login',\n sidePanelTitle: null,\n sidePanelAvatar: null,\n dialogSelected: null,\n contextMenuVisible: false,\n login: '',\n password: '',\n myUserId: null,\n liveConnection: navigator.onLine,\n topicSelected: '',\n topicSelectedOnline: false,\n topicSelectedAcs: null,\n newGroupTopicParams: null,\n loginDisabled: false,\n displayMobile: window.innerWidth <= _config_js__WEBPACK_IMPORTED_MODULE_9__[\"MEDIA_BREAKPOINT\"],\n showInfoPanel: false,\n mobilePanel: 'sidepanel'\n }, _defineProperty(_ref, \"contextMenuVisible\", false), _defineProperty(_ref, \"contextMenuBounds\", null), _defineProperty(_ref, \"contextMenuClickAt\", null), _defineProperty(_ref, \"contextMenuParams\", null), _defineProperty(_ref, \"contextMenuItems\", []), _defineProperty(_ref, \"chatList\", []), _defineProperty(_ref, \"searchResults\", []), _defineProperty(_ref, \"searchableContacts\", []), _defineProperty(_ref, \"credMethod\", undefined), _defineProperty(_ref, \"credCode\", undefined), _ref;\n }\n }, {\n key: \"componentDidMount\",\n value: function componentDidMount() {\n var _this2 = this;\n\n window.addEventListener('resize', this.handleResize);\n window.addEventListener('online', function (e) {\n _this2.handleOnline(true);\n });\n window.addEventListener('offline', function (e) {\n _this2.handleOnline(false);\n });\n window.addEventListener('hashchange', this.handleHashRoute); // Window/tab visible or invisible for pausing timers.\n\n document.addEventListener('visibilitychange', this.handleVisibilityEvent);\n this.setState({\n viewportWidth: document.documentElement.clientWidth\n });\n this.tinode = TinodeWeb.tnSetup(this.state.serverAddress, this.state.transport);\n this.tinode.onConnect = this.handleConnected;\n this.tinode.onDisconnect = this.handleDisconnect; // Initialize desktop alerts.\n\n if (this.state.desktopAlertsEnabled) {\n try {\n this.fbPush = firebase.initializeApp(_firebase_init_js__WEBPACK_IMPORTED_MODULE_3__[\"FIREBASE_INIT\"], _config_js__WEBPACK_IMPORTED_MODULE_9__[\"APP_NAME\"]).messaging();\n this.fbPush.usePublicVapidKey(_firebase_init_js__WEBPACK_IMPORTED_MODULE_3__[\"FIREBASE_INIT\"].messagingVapidKey);\n navigator.serviceWorker.register('/service-worker.js').then(function (reg) {\n _this2.fbPush.useServiceWorker(reg);\n\n _this2.initDesktopAlerts();\n\n if (_this2.state.desktopAlerts) {\n if (!_this2.state.firebaseToken) {\n _this2.togglePushToken(true);\n } else {\n _this2.tinode.setDeviceToken(_this2.state.firebaseToken);\n }\n }\n }).catch(function (err) {\n // registration failed :(\n console.log(\"Failed to register service worker:\", err);\n });\n } catch (err) {\n this.handleError(\"Failed to initialize push notifications\", 'err');\n console.log(\"Failed to initialize push notifications\", err);\n this.setState({\n desktopAlertsEnabled: false\n });\n }\n }\n\n var token = _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].getObject('keep-logged-in') ? _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].getObject('auth-token') : undefined;\n var parsedNav = _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].parseUrlHash(window.location.hash);\n\n if (token) {\n // When reading from storage, date is returned as string.\n token.expires = new Date(token.expires);\n this.tinode.setAuthToken(token);\n this.tinode.connect().catch(function (err) {\n // Socket error\n _this2.handleError(err.message, 'err');\n });\n delete parsedNav.params.info;\n delete parsedNav.params.tab;\n parsedNav.path[0] = '';\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].composeUrlHash(parsedNav.path, parsedNav.params));\n } else if (!parsedNav.params.token) {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo('');\n }\n\n this.readTimer = null;\n this.readTimerCallback = null;\n this.handleHashRoute();\n }\n }, {\n key: \"componentWillUnmount\",\n value: function componentWillUnmount() {\n window.removeEventListener('resize', this.handleResize);\n window.removeEventListener('hashchange', this.handleHashRoute);\n document.removeEventListener('visibilitychange', this.handleVisibilityEvent);\n } // Setup transport (usually websocket) and server address. This will terminate connection with the server.\n\n }, {\n key: \"handleResize\",\n value: function handleResize() {\n var mobile = document.documentElement.clientWidth <= _config_js__WEBPACK_IMPORTED_MODULE_9__[\"MEDIA_BREAKPOINT\"];\n this.setState({\n viewportWidth: document.documentElement.clientWidth\n });\n\n if (this.state.displayMobile != mobile) {\n this.setState({\n displayMobile: mobile\n });\n }\n } // Handle for hashchange event: display appropriate panels.\n\n }, {\n key: \"handleHashRoute\",\n value: function handleHashRoute() {\n var hash = _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].parseUrlHash(window.location.hash);\n\n if (hash.path && hash.path.length > 0) {\n // Left-side panel selector.\n if (['register', 'settings', 'edit', 'cred', 'reset', 'newtpk', 'contacts', ''].includes(hash.path[0])) {\n this.setState({\n sidePanelSelected: hash.path[0]\n });\n } else {\n console.log(\"Unknown sidepanel view\", hash.path[0]);\n } // Topic for MessagesView selector.\n\n\n if (hash.path.length > 1 && hash.path[1] != this.state.topicSelected) {\n this.setState({\n topicSelected: tinode_sdk__WEBPACK_IMPORTED_MODULE_4___default.a.topicType(hash.path[1]) ? hash.path[1] : null\n });\n }\n } else {\n // Empty hashpath\n this.setState({\n sidePanelSelected: ''\n });\n } // Save validation credentials, if available.\n\n\n if (hash.params.method) {\n this.setState({\n credMethod: hash.params.method\n });\n }\n\n if (hash.params.code) {\n this.setState({\n credCode: hash.params.code\n });\n } // Additional parameters of panels.\n\n\n this.setState({\n showInfoPanel: hash.params.info,\n newTopicTabSelected: hash.params.tab\n });\n }\n }, {\n key: \"handleOnline\",\n value: function handleOnline(online) {\n var newState = {\n liveConnection: online\n };\n\n if (online) {\n this.handleError('', null);\n } else {\n this.handleError(\"No connection\", 'warn');\n }\n\n this.setState({\n liveConnection: online\n });\n } // Handling read notifications here to be able to pause\n // them then the window/tab is not visible.\n\n }, {\n key: \"handleAppVisibility\",\n value: function handleAppVisibility(visible, callback) {\n clearTimeout(this.readTimer);\n this.readTimerCallback = callback;\n\n if (visible && callback) {\n this.readTimer = setTimeout(callback, READ_DELAY);\n } else {\n this.readTimer = null;\n }\n }\n }, {\n key: \"handleReadTimer\",\n value: function handleReadTimer(callback) {\n this.handleAppVisibility(!document.hidden, callback);\n }\n }, {\n key: \"handleVisibilityEvent\",\n value: function handleVisibilityEvent() {\n this.handleAppVisibility(!document.hidden, this.readTimerCallback);\n }\n }, {\n key: \"handleError\",\n value: function handleError(err, level) {\n this.setState({\n errorText: err,\n errorLevel: level\n });\n } // User clicked Login button in the side panel.\n\n }, {\n key: \"handleLoginRequest\",\n value: function handleLoginRequest(login, password) {\n var _this3 = this;\n\n this.setState({\n loginDisabled: true,\n login: login,\n password: password\n });\n this.handleError('', null);\n\n if (this.tinode.isConnected()) {\n this.doLogin(login, password, {\n meth: this.state.credMethod,\n resp: this.state.credCode\n });\n } else {\n this.tinode.connect().catch(function (err) {\n // Socket error\n _this3.setState({\n loginDisabled: false\n });\n\n _this3.handleError(err.message, 'err');\n });\n }\n } // Connection succeeded.\n\n }, {\n key: \"handleConnected\",\n value: function handleConnected() {\n var params = this.tinode.getServerInfo();\n this.setState({\n serverVersion: params.ver + ' ' + (params.build ? params.build : 'none') + '; '\n });\n this.doLogin(this.state.login, this.state.password, {\n meth: this.state.credMethod,\n resp: this.state.credCode\n });\n }\n }, {\n key: \"doLogin\",\n value: function doLogin(login, password, cred) {\n var _this4 = this;\n\n if (this.tinode.isAuthenticated()) {\n // Already logged in. Go to default screen.\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo('');\n return;\n } // Sanitize and package credentail.\n\n\n cred = tinode_sdk__WEBPACK_IMPORTED_MODULE_4___default.a.credential(cred); // Try to login with login/password. If they are not available, try token. If no token, ask for login/password.\n\n var promise = null;\n var token = this.tinode.getAuthToken();\n\n if (login && password) {\n this.setState({\n password: null\n });\n promise = this.tinode.loginBasic(login, password, cred);\n } else if (token) {\n promise = this.tinode.loginToken(token.token, cred);\n }\n\n if (promise) {\n promise.then(function (ctrl) {\n if (ctrl.code >= 300 && ctrl.text === 'validate credentials') {\n if (cred) {\n _this4.handleError(\"Code does not match\", 'warn');\n }\n\n _this4.handleCredentialsRequest(ctrl.params);\n } else {\n _this4.handleLoginSuccessful();\n }\n }).catch(function (err) {\n // Login failed, report error.\n _this4.setState({\n loginDisabled: false,\n credMethod: undefined,\n credCode: undefined\n });\n\n _this4.handleError(err.message, 'err');\n\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].removeItem('auth-token');\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo('');\n });\n } else {\n // No login credentials provided.\n // Make sure we are on the login page.\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo('');\n this.setState({\n loginDisabled: false\n });\n }\n }\n }, {\n key: \"handleCredentialsRequest\",\n value: function handleCredentialsRequest(params) {\n var parsed = _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].parseUrlHash(window.location.hash);\n parsed.path[0] = 'cred';\n parsed.params['method'] = params.cred[0];\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].composeUrlHash(parsed.path, parsed.params));\n }\n }, {\n key: \"handleLoginSuccessful\",\n value: function handleLoginSuccessful() {\n var _this5 = this;\n\n this.handleError('', null); // Refresh authentication token.\n\n if (_lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].getObject('keep-logged-in')) {\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].setObject('auth-token', this.tinode.getAuthToken());\n } // Logged in fine, subscribe to 'me' attaching callbacks from the contacts view.\n\n\n var me = this.tinode.getMeTopic();\n me.onMetaDesc = this.tnMeMetaDesc;\n me.onContactUpdate = this.tnMeContactUpdate;\n me.onSubsUpdated = this.tnMeSubsUpdated;\n this.setState({\n connected: true,\n credMethod: undefined,\n credCode: undefined,\n myUserId: this.tinode.getCurrentUserID()\n }); // Subscribe, fetch topic desc, the list of subscriptions. Messages are not fetched.\n\n me.subscribe(me.startMetaQuery().withLaterSub().withDesc().build()).catch(function (err) {\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].removeItem('auth-token');\n\n _this5.handleError(err.message, 'err');\n\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo('');\n });\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlSidePanel(window.location.hash, 'contacts'));\n }\n }, {\n key: \"handleDisconnect\",\n value: function handleDisconnect(err) {\n this.setState({\n connected: false,\n topicSelectedOnline: false,\n dialogSelected: null,\n errorText: err && err.message ? err.message : \"Disconnected\",\n errorLevel: err && err.message ? 'err' : 'warn',\n loginDisabled: false,\n contextMenuVisible: false,\n serverVersion: \"no connection\"\n });\n }\n }, {\n key: \"tnMeMetaDesc\",\n value: function tnMeMetaDesc(desc) {\n if (desc && desc.public) {\n this.setState({\n sidePanelTitle: desc.public.fn,\n sidePanelAvatar: makeImageUrl(desc.public.photo)\n });\n }\n } // Reactions to updates to the contact list.\n\n }, {\n key: \"tnMeContactUpdate\",\n value: function tnMeContactUpdate(what, cont) {\n if (what == 'on' || what == 'off') {\n this.resetContactList();\n\n if (this.state.topicSelected == cont.topic) {\n this.setState({\n topicSelectedOnline: what == 'on'\n });\n }\n } else if (what == 'read') {\n this.resetContactList();\n } else if (what == 'msg') {\n // New message received\n // Skip update if the topic is currently open, otherwise the badge will annoyingly flash.\n if (this.state.topicSelected != cont.topic) {\n if (this.state.messageSounds) {\n POP_SOUND.play();\n }\n\n this.resetContactList();\n } else if (document.hidden && this.state.messageSounds) {\n POP_SOUND.play();\n }\n } else if (what == 'recv') {// Explicitly ignoring \"recv\" -- it causes no visible updates to contact list.\n } else if (what == 'gone' || what == 'unsub') {\n // Topic deleted or user unsubscribed. Remove topic from view.\n // If the currently selected topic is gone, clear the selection.\n if (this.state.topicSelected == cont.topic) {\n this.handleTopicSelected(null);\n } // Redraw without the deleted topic.\n\n\n this.resetContactList();\n } else if (what == 'acs') {\n // Permissions changed. If it's for the currently selected topic,\n // update the views.\n if (this.state.topicSelected == cont.topic) {\n this.setState({\n topicSelectedAcs: cont.acs\n });\n }\n } else if (what == 'del') {// messages deleted (hard or soft) -- update pill counter.\n } else {\n // TODO(gene): handle other types of notifications:\n // * ua -- user agent changes (maybe display a pictogram for mobile/desktop).\n // * upd -- topic 'public' updated, issue getMeta().\n console.log(\"Unsupported (yet) presence update:\" + what + \" in: \" + cont.topic);\n }\n }\n }, {\n key: \"tnMeSubsUpdated\",\n value: function tnMeSubsUpdated(unused) {\n this.resetContactList();\n } // Merge search results and contact list to create a single flat\n // list of kown contacts for GroupManager to use.\n\n }, {\n key: \"resetContactList\",\n value: function resetContactList() {\n var _this6 = this;\n\n var newState = {\n chatList: []\n };\n this.tinode.getMeTopic().contacts(function (c) {\n newState.chatList.push(c);\n\n if (_this6.state.topicSelected == c.topic) {\n newState.topicSelectedOnline = c.online;\n newState.topicSelectedAcs = c.acs;\n }\n }); // Merge search results and chat list.\n\n newState.searchableContacts = TinodeWeb.prepareSearchableContacts(newState.chatList, this.state.searchResults);\n this.setState(newState);\n } // Sending \"received\" notifications\n\n }, {\n key: \"tnData\",\n value: function tnData(data) {\n var _this7 = this;\n\n var topic = this.tinode.getTopic(data.topic);\n\n if (topic.msgStatus(data) >= tinode_sdk__WEBPACK_IMPORTED_MODULE_4___default.a.MESSAGE_STATUS_SENT) {\n clearTimeout(this.receivedTimer);\n this.receivedTimer = setTimeout(function () {\n _this7.receivedTimer = undefined;\n topic.noteRecv(data.seq);\n }, _config_js__WEBPACK_IMPORTED_MODULE_9__[\"RECEIVED_DELAY\"]);\n }\n }\n /* Fnd topic: find contacts by tokens */\n\n }, {\n key: \"tnInitFind\",\n value: function tnInitFind() {\n var _this8 = this;\n\n var fnd = this.tinode.getFndTopic();\n\n if (fnd.isSubscribed()) {\n this.tnFndSubsUpdated();\n } else {\n fnd.onSubsUpdated = this.tnFndSubsUpdated;\n fnd.subscribe(fnd.startMetaQuery().withSub().withTags().build()).catch(function (err) {\n _this8.handleError(err.message, 'err');\n });\n }\n }\n }, {\n key: \"tnFndSubsUpdated\",\n value: function tnFndSubsUpdated() {\n var foundContacts = []; // Don't attempt to create P2P topics which already exist. Server will reject the duplicates.\n\n this.tinode.getFndTopic().contacts(function (s) {\n foundContacts.push(s);\n });\n this.setState({\n searchResults: foundContacts,\n searchableContacts: TinodeWeb.prepareSearchableContacts(this.state.chatList, foundContacts)\n });\n }\n /** Called when the user enters a contact into the contact search field in the NewAccount panel\n @param query {Array} is an array of contacts to search for\n */\n\n }, {\n key: \"handleSearchContacts\",\n value: function handleSearchContacts(query) {\n var _this9 = this;\n\n var fnd = this.tinode.getFndTopic();\n fnd.setMeta({\n desc: {\n public: query\n }\n }).then(function (ctrl) {\n return fnd.getMeta(fnd.startMetaQuery().withSub().build());\n }).catch(function (err) {\n _this9.handleError(err.message, 'err');\n });\n } // User clicked on a contact in the side panel or deleted a contact.\n\n }, {\n key: \"handleTopicSelected\",\n value: function handleTopicSelected(topicName, unused_index, online, acs) {\n if (topicName) {\n this.setState({\n errorText: '',\n errorLevel: null,\n mobilePanel: 'topic-view',\n showInfoPanel: false\n }); // Different contact selected.\n\n if (this.state.topicSelected != topicName) {\n this.setState({\n topicSelectedOnline: online,\n topicSelectedAcs: acs\n });\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlTopic('', topicName));\n }\n } else {\n // Currently selected contact deleted\n this.setState({\n errorText: '',\n errorLevel: null,\n mobilePanel: 'sidepanel',\n topicSelectedOnline: false,\n topicSelectedAcs: null,\n showInfoPanel: false\n });\n\n if (this.state.topicSelected) {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlTopic('', null));\n }\n }\n } // In mobile view user requested to show sidepanel\n\n }, {\n key: \"handleHideMessagesView\",\n value: function handleHideMessagesView() {\n this.setState({\n mobilePanel: 'sidepanel'\n });\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlTopic(window.location.hash, null));\n } // User is sending a message, either plain text or a drafty object, possibly\n // with attachments.\n\n }, {\n key: \"handleSendMessage\",\n value: function handleSendMessage(msg, promise, uploader) {\n var _this10 = this;\n\n var topic = this.tinode.getTopic(this.state.topicSelected);\n msg = topic.createMessage(msg, false); // The uploader is used to show progress.\n\n msg._uploader = uploader;\n\n if (!topic.isSubscribed()) {\n if (!promise) {\n promise = Promise.resolve();\n }\n\n promise = promise.then(function () {\n return topic.subscribe();\n });\n }\n\n if (promise) {\n promise = promise.catch(function (err) {\n _this10.handleError(err.message, 'err');\n });\n }\n\n topic.publishDraft(msg, promise).catch(function (err) {\n _this10.handleError(err.message, 'err');\n });\n } // User chose a Sign Up menu item.\n\n }, {\n key: \"handleNewAccount\",\n value: function handleNewAccount() {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlSidePanel(window.location.hash, 'register'));\n } // Actual registration of a new account.\n\n }, {\n key: \"handleNewAccountRequest\",\n value: function handleNewAccountRequest(login_, password_, public_, cred_, tags_) {\n var _this11 = this;\n\n this.tinode.connect(this.state.serverAddress).then(function () {\n return _this11.tinode.createAccountBasic(login_, password_, {\n public: public_,\n tags: tags_,\n cred: tinode_sdk__WEBPACK_IMPORTED_MODULE_4___default.a.credential(cred_)\n });\n }).then(function (ctrl) {\n if (ctrl.code >= 300 && ctrl.text == 'validate credentials') {\n _this11.handleCredentialsRequest(ctrl.params);\n } else {\n _this11.handleLoginSuccessful(_this11);\n }\n }).catch(function (err) {\n _this11.handleError(err.message, 'err');\n });\n }\n }, {\n key: \"handleUpdateAccountRequest\",\n value: function handleUpdateAccountRequest(password, pub, defacs) {\n var _this12 = this;\n\n if (pub || defacs) {\n this.tinode.getMeTopic().setMeta({\n desc: {\n public: pub,\n defacs: defacs\n }\n }).catch(function (err) {\n _this12.handleError(err.message, 'err');\n });\n }\n\n if (password) {\n this.tinode.updateAccountBasic(null, this.tinode.getCurrentLogin(), password).catch(function (err) {\n _this12.handleError(err.message, 'err');\n });\n }\n }\n }, {\n key: \"handleUpdateAccountTagsRequest\",\n value: function handleUpdateAccountTagsRequest(tags) {\n var _this13 = this;\n\n this.tinode.getFndTopic().setMeta({\n tags: tags\n }).catch(function (err) {\n _this13.handleError(err.message, 'err');\n });\n } // User chose Settings menu item.\n\n }, {\n key: \"handleSettings\",\n value: function handleSettings() {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlSidePanel(window.location.hash, this.state.myUserId ? 'edit' : 'settings'));\n } // User updated global parameters.\n\n }, {\n key: \"handleGlobalSettings\",\n value: function handleGlobalSettings(settings) {\n var serverAddress = settings.serverAddress || this.state.serverAddress;\n var transport = settings.transport || this.state.transport;\n\n if (this.tinode) {\n this.tinode.onDisconnect = undefined;\n this.tinode.disconnect();\n }\n\n this.tinode = TinodeWeb.tnSetup(serverAddress, transport);\n this.tinode.onConnect = this.handleConnected;\n this.tinode.onDisconnect = this.handleDisconnect;\n this.setState({\n serverAddress: serverAddress,\n transport: transport\n });\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].setObject('settings', {\n serverAddress: serverAddress,\n transport: transport\n });\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlSidePanel(window.location.hash, ''));\n } // Initialize desktop alerts = push notifications.\n\n }, {\n key: \"initDesktopAlerts\",\n value: function initDesktopAlerts() {\n var _this14 = this;\n\n // Google could not be bothered to mention that\n // onTokenRefresh is never called.\n this.fbPush.onTokenRefresh(function () {\n _this14.requestPushToken(true);\n });\n this.fbPush.onMessage(function (payload) {// No need to do anything about it.\n // All the magic happends in the service worker.\n });\n }\n }, {\n key: \"togglePushToken\",\n value: function togglePushToken(enabled) {\n var _this15 = this;\n\n if (enabled) {\n if (!this.state.firebaseToken) {\n this.fbPush.requestPermission().then(function () {\n _this15.requestPushToken(true);\n }).catch(function (err) {\n _this15.handleError(err.message, 'err');\n\n _this15.setState({\n desktopAlerts: false,\n firebaseToken: null\n });\n\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].updateObject('settings', {\n desktopAlerts: false\n });\n console.log(\"Failed to get permission to notify.\", err);\n });\n } else {\n this.setState({\n desktopAlerts: true\n });\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].updateObject('settings', {\n desktopAlerts: true\n });\n }\n } else if (this.state.firebaseToken) {\n this.fbPush.deleteToken(this.state.firebaseToken).catch(function (err) {\n console.log(\"Unable to delete token.\", err);\n }).finally(function () {\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].updateObject('settings', {\n desktopAlerts: false\n });\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].removeItem('firebase-token');\n\n _this15.setState({\n desktopAlerts: false,\n firebaseToken: null\n });\n });\n } else {\n this.setState({\n desktopAlerts: false,\n firebaseToken: null\n });\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].updateObject('settings', {\n desktopAlerts: false\n });\n }\n }\n }, {\n key: \"requestPushToken\",\n value: function requestPushToken(sendToServer) {\n var _this16 = this;\n\n this.fbPush.getToken().then(function (refreshedToken) {\n if (refreshedToken != _this16.state.firebaseToken) {\n _this16.tinode.setDeviceToken(refreshedToken, sendToServer);\n\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].setObject('firebase-token', refreshedToken);\n }\n\n _this16.setState({\n firebaseToken: refreshedToken,\n desktopAlerts: true\n });\n\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].updateObject('settings', {\n desktopAlerts: true\n });\n }).catch(function (err) {\n _this16.handleError(err.message, 'err');\n\n console.log(\"Failed to retrieve firebase token\", err);\n });\n }\n }, {\n key: \"handleToggleMessageSounds\",\n value: function handleToggleMessageSounds(enabled) {\n this.setState({\n messageSounds: enabled\n });\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].updateObject('settings', {\n messageSoundsOff: !enabled\n });\n } // User clicked Cancel button in Setting or Sign Up panel.\n\n }, {\n key: \"handleSidepanelCancel\",\n value: function handleSidepanelCancel() {\n var parsed = _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].parseUrlHash(window.location.hash);\n parsed.path[0] = this.state.myUserId ? 'contacts' : '';\n\n if (parsed.params) {\n delete parsed.params.code;\n delete parsed.params.method;\n delete parsed.params.tab;\n }\n\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].composeUrlHash(parsed.path, parsed.params));\n this.setState({\n errorText: '',\n errorLevel: null\n });\n } // User clicked a (+) menu item.\n\n }, {\n key: \"handleNewTopic\",\n value: function handleNewTopic() {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlSidePanel(window.location.hash, 'newtpk'));\n } // Request to start a new topic. New P2P topic requires peer's name.\n\n }, {\n key: \"handleNewTopicRequest\",\n value: function handleNewTopicRequest(peerName, pub, priv, tags) {\n var _this17 = this;\n\n var topicName = peerName || this.tinode.newGroupTopicName();\n\n if (!peerName) {\n this.setState({\n newGroupTopicParams: {\n desc: {\n public: pub,\n private: {\n comment: priv\n }\n },\n tags: tags\n }\n }, function () {\n _this17.handleTopicSelected(topicName);\n });\n } else {\n this.handleTopicSelected(topicName);\n }\n } // New topic was creted, here is the new topic name.\n\n }, {\n key: \"handleNewTopicCreated\",\n value: function handleNewTopicCreated(oldName, newName) {\n if (this.state.topicSelected == oldName && oldName != newName) {\n // If the current URl contains the old topic name, replace it with new.\n // Update the name of the selected topic first so the navigator doen't clear\n // the state.\n this.setState({\n topicSelected: newName\n }, function () {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlTopic('', newName));\n });\n }\n }\n }, {\n key: \"handleTopicUpdateRequest\",\n value: function handleTopicUpdateRequest(topicName, pub, priv, permissions) {\n var _this18 = this;\n\n var topic = this.tinode.getTopic(topicName);\n\n if (topic) {\n var params = {};\n\n if (pub) {\n params.public = pub;\n }\n\n if (priv) {\n params.private = {\n comment: priv\n };\n }\n\n if (permissions) {\n params.defacs = permissions;\n }\n\n topic.setMeta({\n desc: params\n }).catch(function (err) {\n _this18.handleError(err.message, 'err');\n });\n }\n }\n }, {\n key: \"handleChangePermissions\",\n value: function handleChangePermissions(topicName, mode, uid) {\n var _this19 = this;\n\n var topic = this.tinode.getTopic(topicName);\n\n if (topic) {\n var am = topic.getAccessMode();\n\n if (uid) {\n am.updateGiven(mode);\n mode = am.getGiven();\n } else {\n am.updateWant(mode);\n mode = am.getWant();\n }\n\n topic.setMeta({\n sub: {\n user: uid,\n mode: mode\n }\n }).catch(function (err) {\n _this19.handleError(err.message, 'err');\n });\n }\n }\n }, {\n key: \"handleTagsUpdated\",\n value: function handleTagsUpdated(topicName, tags) {\n var _this20 = this;\n\n var topic = this.tinode.getTopic(topicName);\n\n if (topic) {\n var instance = this;\n topic.setMeta({\n tags: tags\n }).catch(function (err) {\n _this20.handleError(err.message, 'err');\n });\n }\n }\n }, {\n key: \"handleLogout\",\n value: function handleLogout() {\n updateFavicon(0);\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].removeItem('auth-token');\n\n if (this.tinode) {\n this.tinode.onDisconnect = undefined;\n this.tinode.disconnect();\n }\n\n this.setState(this.getBlankState());\n this.tinode = TinodeWeb.tnSetup(this.state.serverAddress, this.state.transport);\n this.tinode.onConnect = this.handleConnected;\n this.tinode.onDisconnect = this.handleDisconnect;\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo('');\n }\n }, {\n key: \"handleLeaveUnsubRequest\",\n value: function handleLeaveUnsubRequest(topicName) {\n var _this21 = this;\n\n var topic = this.tinode.getTopic(topicName);\n\n if (!topic) {\n return;\n }\n\n topic.leave(true).then(function (ctrl) {\n // Hide MessagesView and InfoView panels.\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlTopic(window.location.hash, ''));\n }).catch(function (err) {\n _this21.handleError(err.message, 'err');\n });\n }\n }, {\n key: \"handleDialogCancel\",\n value: function handleDialogCancel() {\n this.setState({\n dialogSelected: null\n });\n }\n }, {\n key: \"handleShowContextMenu\",\n value: function handleShowContextMenu(params, menuItems) {\n this.setState({\n contextMenuVisible: true,\n contextMenuClickAt: {\n x: params.x,\n y: params.y\n },\n contextMenuParams: params,\n contextMenuItems: menuItems || this.defaultTopicContextMenu(params.topicName),\n contextMenuBounds: ReactDOM.findDOMNode(this).getBoundingClientRect()\n });\n }\n }, {\n key: \"defaultTopicContextMenu\",\n value: function defaultTopicContextMenu(topicName) {\n var muted = false,\n blocked = false,\n subscribed = false,\n deleter = false;\n var topic = this.tinode.getTopic(topicName);\n\n if (topic) {\n if (topic.isSubscribed()) {\n subscribed = true;\n var acs = topic.getAccessMode();\n muted = acs && acs.isMuted();\n blocked = acs && !acs.isJoiner();\n deleter = acs && acs.isDeleter();\n }\n }\n\n return [subscribed ? {\n title: \"Info\",\n handler: this.handleShowInfoView\n } : null, subscribed ? 'messages_clear' : null, subscribed && deleter ? 'messages_clear_hard' : null, subscribed ? muted ? 'topic_unmute' : 'topic_mute' : null, subscribed ? blocked ? 'topic_unblock' : 'topic_block' : null, 'topic_delete'];\n }\n }, {\n key: \"handleHideContextMenu\",\n value: function handleHideContextMenu() {\n this.setState({\n contextMenuVisible: false,\n contextMenuClickAt: null,\n contextMenuParams: null,\n contextMenuBounds: null\n });\n }\n }, {\n key: \"handleShowInfoView\",\n value: function handleShowInfoView() {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].addUrlParam(window.location.hash, 'info', true));\n this.setState({\n showInfoPanel: true\n });\n }\n }, {\n key: \"handleHideInfoView\",\n value: function handleHideInfoView() {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].removeUrlParam(window.location.hash, 'info'));\n this.setState({\n showInfoPanel: false\n });\n }\n }, {\n key: \"handleMemberUpdateRequest\",\n value: function handleMemberUpdateRequest(topicName, added, removed) {\n var _this22 = this;\n\n if (!topicName) {\n return;\n }\n\n var topic = this.tinode.getTopic(topicName);\n\n if (!topic) {\n return;\n }\n\n if (added && added.length > 0) {\n added.map(function (uid) {\n topic.invite(uid, null).catch(function (err) {\n _this22.handleError(err.message, 'err');\n });\n });\n }\n\n if (removed && removed.length > 0) {\n removed.map(function (uid) {\n topic.delSubscription(uid).catch(function (err) {\n _this22.handleError(err.message, 'err');\n });\n });\n }\n }\n }, {\n key: \"handleValidateCredentialsRequest\",\n value: function handleValidateCredentialsRequest(cred, code) {\n this.setState({\n credMethod: cred,\n credCode: code\n });\n this.doLogin(null, null, {\n meth: cred,\n resp: code\n });\n }\n }, {\n key: \"handlePasswordResetRequest\",\n value: function handlePasswordResetRequest(method, value) {\n var _this23 = this;\n\n // If already connected, connnect() will return a resolved promise.\n this.tinode.connect().then(function () {\n return _this23.tinode.requestResetAuthSecret('basic', method, value);\n }).catch(function (err) {\n // Socket error\n _this23.handleError(err.message, 'err');\n });\n }\n }, {\n key: \"handleResetPassword\",\n value: function handleResetPassword(scheme, newPassword, token) {\n var _this24 = this;\n\n token = base64ReEncode(token);\n\n if (!token) {\n this.handleError(\"Invalid security token\", 'err');\n } else {\n this.tinode.connect().then(function () {\n return _this24.tinode.updateAccountBasic(null, null, newPassword, {\n token: token\n });\n }).catch(function (err) {\n // Socket error\n _this24.handleError(err.message, 'err');\n });\n }\n }\n }, {\n key: \"render\",\n value: function render() {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"app-container\"\n }, this.state.contextMenuVisible ? react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_widgets_context_menu_jsx__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n tinode: this.tinode,\n bounds: this.state.contextMenuBounds,\n clickAt: this.state.contextMenuClickAt,\n params: this.state.contextMenuParams,\n items: this.state.contextMenuItems,\n hide: this.handleHideContextMenu,\n onAction: this.handleContextMenuAction,\n onError: this.handleError\n }) : null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_sidepanel_view_jsx__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n tinode: this.tinode,\n connected: this.state.connected,\n displayMobile: this.state.displayMobile,\n hideSelf: this.state.displayMobile && this.state.mobilePanel !== 'sidepanel',\n state: this.state.sidePanelSelected,\n title: this.state.sidePanelTitle,\n avatar: this.state.sidePanelAvatar,\n login: this.state.login,\n myUserId: this.state.myUserId,\n loginDisabled: this.state.loginDisabled,\n errorText: this.state.errorText,\n errorLevel: this.state.errorLevel,\n topicSelected: this.state.topicSelected,\n chatList: this.state.chatList,\n credMethod: this.state.credMethod,\n credCode: this.state.credCode,\n transport: this.state.transport,\n messageSounds: this.state.messageSounds,\n desktopAlerts: this.state.desktopAlerts,\n desktopAlertsEnabled: this.state.desktopAlertsEnabled,\n serverAddress: this.state.serverAddress,\n onGlobalSettings: this.handleGlobalSettings,\n onSignUp: this.handleNewAccount,\n onSettings: this.handleSettings,\n onLoginRequest: this.handleLoginRequest,\n onCreateAccount: this.handleNewAccountRequest,\n onUpdateAccount: this.handleUpdateAccountRequest,\n onUpdateAccountTags: this.handleUpdateAccountTagsRequest,\n onTogglePushNotifications: this.togglePushToken,\n onToggleMessageSounds: this.handleToggleMessageSounds,\n onTopicSelected: this.handleTopicSelected,\n onCreateTopic: this.handleNewTopicRequest,\n onNewTopic: this.handleNewTopic,\n onLogout: this.handleLogout,\n onCancel: this.handleSidepanelCancel,\n onError: this.handleError,\n onValidateCredentials: this.handleValidateCredentialsRequest,\n onPasswordResetRequest: this.handlePasswordResetRequest,\n onResetPassword: this.handleResetPassword,\n onInitFind: this.tnInitFind,\n searchResults: this.state.searchResults,\n onSearchContacts: this.handleSearchContacts,\n showContextMenu: this.handleShowContextMenu\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_messages_view_jsx__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n tinode: this.tinode,\n connected: this.state.connected,\n online: this.state.topicSelectedOnline,\n acs: this.state.topicSelectedAcs,\n displayMobile: this.state.displayMobile,\n viewportWidth: this.state.viewportWidth,\n hideSelf: this.state.displayMobile && (this.state.mobilePanel !== 'topic-view' || this.state.showInfoPanel),\n topic: this.state.topicSelected,\n myUserId: this.state.myUserId,\n serverVersion: this.state.serverVersion,\n serverAddress: this.state.serverAddress,\n errorText: this.state.errorText,\n errorLevel: this.state.errorLevel,\n newGroupTopicParams: this.state.newGroupTopicParams,\n onHideMessagesView: this.handleHideMessagesView,\n onData: this.tnData,\n onError: this.handleError,\n onNewTopicCreated: this.handleNewTopicCreated,\n readTimerHandler: this.handleReadTimer,\n showContextMenu: this.handleShowContextMenu,\n sendMessage: this.handleSendMessage\n }), this.state.showInfoPanel ? react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_info_view_jsx__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n tinode: this.tinode,\n connected: this.state.connected,\n displayMobile: this.state.displayMobile,\n topic: this.state.topicSelected,\n searchableContacts: this.state.searchableContacts,\n myUserId: this.state.myUserId,\n errorText: this.state.errorText,\n errorLevel: this.state.errorLevel,\n onTopicDescUpdate: this.handleTopicUpdateRequest,\n onCancel: this.handleHideInfoView,\n onChangePermissions: this.handleChangePermissions,\n onMemberUpdateRequest: this.handleMemberUpdateRequest,\n onLeaveTopic: this.handleLeaveUnsubRequest,\n onAddMember: this.handleManageGroupMembers,\n onTopicTagsUpdate: this.handleTagsUpdated,\n onInitFind: this.tnInitFind,\n onError: this.handleError,\n showContextMenu: this.handleShowContextMenu\n }) : null);\n }\n }], [{\n key: \"tnSetup\",\n value: function tnSetup(serverAddress, transport) {\n var tinode = new tinode_sdk__WEBPACK_IMPORTED_MODULE_4___default.a(_config_js__WEBPACK_IMPORTED_MODULE_9__[\"APP_NAME\"], serverAddress, _config_js__WEBPACK_IMPORTED_MODULE_9__[\"API_KEY\"], transport, Object(_lib_host_name_js__WEBPACK_IMPORTED_MODULE_10__[\"isSecureConnection\"])());\n tinode.enableLogging(true, true);\n return tinode;\n }\n }, {\n key: \"prepareSearchableContacts\",\n value: function prepareSearchableContacts(chatList, foundContacts) {\n var merged = {}; // For chatList topics merge only p2p topics and convert them to the\n // same format as foundContacts.\n\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = chatList[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var c = _step.value;\n\n if (tinode_sdk__WEBPACK_IMPORTED_MODULE_4___default.a.topicType(c.topic) == 'p2p') {\n merged[c.topic] = {\n user: c.topic,\n updated: c.updated,\n public: c.public,\n private: c.private,\n acs: c.acs\n };\n }\n } // Add all foundCountacts if they have not been added already.\n\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return != null) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n\n var _iteratorNormalCompletion2 = true;\n var _didIteratorError2 = false;\n var _iteratorError2 = undefined;\n\n try {\n for (var _iterator2 = foundContacts[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {\n var _c = _step2.value;\n\n if (!merged[_c.user]) {\n merged[_c.user] = _c;\n }\n }\n } catch (err) {\n _didIteratorError2 = true;\n _iteratorError2 = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion2 && _iterator2.return != null) {\n _iterator2.return();\n }\n } finally {\n if (_didIteratorError2) {\n throw _iteratorError2;\n }\n }\n }\n\n return Object.values(merged);\n }\n }]);\n\n return TinodeWeb;\n}(react__WEBPACK_IMPORTED_MODULE_0___default.a.Component);\n\n\n;\n\n//# sourceURL=webpack:///./src/views/tinode-web.jsx?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"POP_SOUND\", function() { return POP_SOUND; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return TinodeWeb; });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var firebase_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! firebase/app */ \"./node_modules/firebase/app/dist/index.cjs.js\");\n/* harmony import */ var firebase_app__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(firebase_app__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var firebase_messaging__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! firebase/messaging */ \"./node_modules/firebase/messaging/dist/index.esm.js\");\n/* harmony import */ var _firebase_init_json__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../firebase-init.json */ \"./src/firebase-init.json\");\nvar _firebase_init_json__WEBPACK_IMPORTED_MODULE_3___namespace = /*#__PURE__*/__webpack_require__.t(/*! ../firebase-init.json */ \"./src/firebase-init.json\", 1);\n/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! tinode-sdk */ \"./node_modules/tinode-sdk/umd/tinode.prod.js\");\n/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(tinode_sdk__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _widgets_context_menu_jsx__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../widgets/context-menu.jsx */ \"./src/widgets/context-menu.jsx\");\n/* harmony import */ var _info_view_jsx__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./info-view.jsx */ \"./src/views/info-view.jsx\");\n/* harmony import */ var _messages_view_jsx__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./messages-view.jsx */ \"./src/views/messages-view.jsx\");\n/* harmony import */ var _sidepanel_view_jsx__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./sidepanel-view.jsx */ \"./src/views/sidepanel-view.jsx\");\n/* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../config.js */ \"./src/config.js\");\n/* harmony import */ var _lib_host_name_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../lib/host-name.js */ \"./src/lib/host-name.js\");\n/* harmony import */ var _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../lib/local-storage.js */ \"./src/lib/local-storage.js\");\n/* harmony import */ var _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../lib/navigation.js */ \"./src/lib/navigation.js\");\nfunction _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\n\n// The top-level class to hold all functionality together.\n\n\n\n\n\n\n\n\n\n\n\n\n // Sound to play on message received.\n\nvar POP_SOUND = new Audio('audio/msg.mp3');\nconsole.log(_firebase_init_json__WEBPACK_IMPORTED_MODULE_3__[\"FIREBASE_INIT\"]);\n\nvar TinodeWeb =\n/*#__PURE__*/\nfunction (_React$Component) {\n _inherits(TinodeWeb, _React$Component);\n\n function TinodeWeb(props) {\n var _this;\n\n _classCallCheck(this, TinodeWeb);\n\n _this = _possibleConstructorReturn(this, _getPrototypeOf(TinodeWeb).call(this, props));\n _this.state = _this.getBlankState();\n _this.handleResize = _this.handleResize.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleHashRoute = _this.handleHashRoute.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleOnline = _this.handleOnline.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleAppVisibility = _this.handleAppVisibility.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleReadTimer = _this.handleReadTimer.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleVisibilityEvent = _this.handleVisibilityEvent.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleError = _this.handleError.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleLoginRequest = _this.handleLoginRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleConnected = _this.handleConnected.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.doLogin = _this.doLogin.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleCredentialsRequest = _this.handleCredentialsRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleLoginSuccessful = _this.handleLoginSuccessful.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleDisconnect = _this.handleDisconnect.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.tnMeMetaDesc = _this.tnMeMetaDesc.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.tnMeContactUpdate = _this.tnMeContactUpdate.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.tnMeSubsUpdated = _this.tnMeSubsUpdated.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.resetContactList = _this.resetContactList.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.tnData = _this.tnData.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.tnInitFind = _this.tnInitFind.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.tnFndSubsUpdated = _this.tnFndSubsUpdated.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleSearchContacts = _this.handleSearchContacts.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleTopicSelected = _this.handleTopicSelected.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleHideMessagesView = _this.handleHideMessagesView.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleSendMessage = _this.handleSendMessage.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleNewAccount = _this.handleNewAccount.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleNewAccountRequest = _this.handleNewAccountRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleUpdateAccountRequest = _this.handleUpdateAccountRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleUpdateAccountTagsRequest = _this.handleUpdateAccountTagsRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleSettings = _this.handleSettings.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleGlobalSettings = _this.handleGlobalSettings.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleToggleMessageSounds = _this.handleToggleMessageSounds.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.initDesktopAlerts = _this.initDesktopAlerts.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.togglePushToken = _this.togglePushToken.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.requestPushToken = _this.requestPushToken.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleSidepanelCancel = _this.handleSidepanelCancel.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleNewTopic = _this.handleNewTopic.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleNewTopicRequest = _this.handleNewTopicRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleNewTopicCreated = _this.handleNewTopicCreated.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleTopicUpdateRequest = _this.handleTopicUpdateRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleChangePermissions = _this.handleChangePermissions.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleTagsUpdated = _this.handleTagsUpdated.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleLogout = _this.handleLogout.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleLeaveUnsubRequest = _this.handleLeaveUnsubRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleDialogCancel = _this.handleDialogCancel.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleShowContextMenu = _this.handleShowContextMenu.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.defaultTopicContextMenu = _this.defaultTopicContextMenu.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleHideContextMenu = _this.handleHideContextMenu.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleShowInfoView = _this.handleShowInfoView.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleHideInfoView = _this.handleHideInfoView.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleMemberUpdateRequest = _this.handleMemberUpdateRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleValidateCredentialsRequest = _this.handleValidateCredentialsRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handlePasswordResetRequest = _this.handlePasswordResetRequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n _this.handleResetPassword = _this.handleResetPassword.bind(_assertThisInitialized(_assertThisInitialized(_this)));\n return _this;\n }\n\n _createClass(TinodeWeb, [{\n key: \"getBlankState\",\n value: function getBlankState() {\n var _ref;\n\n var settings = _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].getObject(\"settings\") || {};\n return _ref = {\n connected: false,\n transport: settings.transport || null,\n serverAddress: settings.serverAddress || detectServerAddress(),\n serverVersion: \"no connection\",\n // \"On\" is the default, so saving the \"off\" state.\n messageSounds: !settings.messageSoundsOff,\n desktopAlerts: settings.desktopAlerts,\n desktopAlertsEnabled: (Object(_lib_host_name_js__WEBPACK_IMPORTED_MODULE_10__[\"isSecureConnection\"])() || Object(_lib_host_name_js__WEBPACK_IMPORTED_MODULE_10__[\"isLocalHost\"])()) && typeof firebase != 'undefined' && typeof navigator != 'undefined' && typeof _firebase_init_json__WEBPACK_IMPORTED_MODULE_3__[\"FIREBASE_INIT\"] != 'undefined',\n firebaseToken: _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].getObject(\"firebase-token\"),\n errorText: '',\n errorLevel: null,\n sidePanelSelected: 'login',\n sidePanelTitle: null,\n sidePanelAvatar: null,\n dialogSelected: null,\n contextMenuVisible: false,\n login: '',\n password: '',\n myUserId: null,\n liveConnection: navigator.onLine,\n topicSelected: '',\n topicSelectedOnline: false,\n topicSelectedAcs: null,\n newGroupTopicParams: null,\n loginDisabled: false,\n displayMobile: window.innerWidth <= _config_js__WEBPACK_IMPORTED_MODULE_9__[\"MEDIA_BREAKPOINT\"],\n showInfoPanel: false,\n mobilePanel: 'sidepanel'\n }, _defineProperty(_ref, \"contextMenuVisible\", false), _defineProperty(_ref, \"contextMenuBounds\", null), _defineProperty(_ref, \"contextMenuClickAt\", null), _defineProperty(_ref, \"contextMenuParams\", null), _defineProperty(_ref, \"contextMenuItems\", []), _defineProperty(_ref, \"chatList\", []), _defineProperty(_ref, \"searchResults\", []), _defineProperty(_ref, \"searchableContacts\", []), _defineProperty(_ref, \"credMethod\", undefined), _defineProperty(_ref, \"credCode\", undefined), _ref;\n }\n }, {\n key: \"componentDidMount\",\n value: function componentDidMount() {\n var _this2 = this;\n\n window.addEventListener('resize', this.handleResize);\n window.addEventListener('online', function (e) {\n _this2.handleOnline(true);\n });\n window.addEventListener('offline', function (e) {\n _this2.handleOnline(false);\n });\n window.addEventListener('hashchange', this.handleHashRoute); // Window/tab visible or invisible for pausing timers.\n\n document.addEventListener('visibilitychange', this.handleVisibilityEvent);\n this.setState({\n viewportWidth: document.documentElement.clientWidth\n });\n this.tinode = TinodeWeb.tnSetup(this.state.serverAddress, this.state.transport);\n this.tinode.onConnect = this.handleConnected;\n this.tinode.onDisconnect = this.handleDisconnect; // Initialize desktop alerts.\n\n if (this.state.desktopAlertsEnabled) {\n try {\n this.fbPush = firebase.initializeApp(_firebase_init_json__WEBPACK_IMPORTED_MODULE_3__[\"FIREBASE_INIT\"], _config_js__WEBPACK_IMPORTED_MODULE_9__[\"APP_NAME\"]).messaging();\n this.fbPush.usePublicVapidKey(_firebase_init_json__WEBPACK_IMPORTED_MODULE_3__[\"FIREBASE_INIT\"].messagingVapidKey);\n navigator.serviceWorker.register('/service-worker.js').then(function (reg) {\n _this2.fbPush.useServiceWorker(reg);\n\n _this2.initDesktopAlerts();\n\n if (_this2.state.desktopAlerts) {\n if (!_this2.state.firebaseToken) {\n _this2.togglePushToken(true);\n } else {\n _this2.tinode.setDeviceToken(_this2.state.firebaseToken);\n }\n }\n }).catch(function (err) {\n // registration failed :(\n console.log(\"Failed to register service worker:\", err);\n });\n } catch (err) {\n this.handleError(\"Failed to initialize push notifications\", 'err');\n console.log(\"Failed to initialize push notifications\", err);\n this.setState({\n desktopAlertsEnabled: false\n });\n }\n }\n\n var token = _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].getObject('keep-logged-in') ? _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].getObject('auth-token') : undefined;\n var parsedNav = _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].parseUrlHash(window.location.hash);\n\n if (token) {\n // When reading from storage, date is returned as string.\n token.expires = new Date(token.expires);\n this.tinode.setAuthToken(token);\n this.tinode.connect().catch(function (err) {\n // Socket error\n _this2.handleError(err.message, 'err');\n });\n delete parsedNav.params.info;\n delete parsedNav.params.tab;\n parsedNav.path[0] = '';\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].composeUrlHash(parsedNav.path, parsedNav.params));\n } else if (!parsedNav.params.token) {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo('');\n }\n\n this.readTimer = null;\n this.readTimerCallback = null;\n this.handleHashRoute();\n }\n }, {\n key: \"componentWillUnmount\",\n value: function componentWillUnmount() {\n window.removeEventListener('resize', this.handleResize);\n window.removeEventListener('hashchange', this.handleHashRoute);\n document.removeEventListener('visibilitychange', this.handleVisibilityEvent);\n } // Setup transport (usually websocket) and server address. This will terminate connection with the server.\n\n }, {\n key: \"handleResize\",\n value: function handleResize() {\n var mobile = document.documentElement.clientWidth <= _config_js__WEBPACK_IMPORTED_MODULE_9__[\"MEDIA_BREAKPOINT\"];\n this.setState({\n viewportWidth: document.documentElement.clientWidth\n });\n\n if (this.state.displayMobile != mobile) {\n this.setState({\n displayMobile: mobile\n });\n }\n } // Handle for hashchange event: display appropriate panels.\n\n }, {\n key: \"handleHashRoute\",\n value: function handleHashRoute() {\n var hash = _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].parseUrlHash(window.location.hash);\n\n if (hash.path && hash.path.length > 0) {\n // Left-side panel selector.\n if (['register', 'settings', 'edit', 'cred', 'reset', 'newtpk', 'contacts', ''].includes(hash.path[0])) {\n this.setState({\n sidePanelSelected: hash.path[0]\n });\n } else {\n console.log(\"Unknown sidepanel view\", hash.path[0]);\n } // Topic for MessagesView selector.\n\n\n if (hash.path.length > 1 && hash.path[1] != this.state.topicSelected) {\n this.setState({\n topicSelected: tinode_sdk__WEBPACK_IMPORTED_MODULE_4___default.a.topicType(hash.path[1]) ? hash.path[1] : null\n });\n }\n } else {\n // Empty hashpath\n this.setState({\n sidePanelSelected: ''\n });\n } // Save validation credentials, if available.\n\n\n if (hash.params.method) {\n this.setState({\n credMethod: hash.params.method\n });\n }\n\n if (hash.params.code) {\n this.setState({\n credCode: hash.params.code\n });\n } // Additional parameters of panels.\n\n\n this.setState({\n showInfoPanel: hash.params.info,\n newTopicTabSelected: hash.params.tab\n });\n }\n }, {\n key: \"handleOnline\",\n value: function handleOnline(online) {\n var newState = {\n liveConnection: online\n };\n\n if (online) {\n this.handleError('', null);\n } else {\n this.handleError(\"No connection\", 'warn');\n }\n\n this.setState({\n liveConnection: online\n });\n } // Handling read notifications here to be able to pause\n // them then the window/tab is not visible.\n\n }, {\n key: \"handleAppVisibility\",\n value: function handleAppVisibility(visible, callback) {\n clearTimeout(this.readTimer);\n this.readTimerCallback = callback;\n\n if (visible && callback) {\n this.readTimer = setTimeout(callback, READ_DELAY);\n } else {\n this.readTimer = null;\n }\n }\n }, {\n key: \"handleReadTimer\",\n value: function handleReadTimer(callback) {\n this.handleAppVisibility(!document.hidden, callback);\n }\n }, {\n key: \"handleVisibilityEvent\",\n value: function handleVisibilityEvent() {\n this.handleAppVisibility(!document.hidden, this.readTimerCallback);\n }\n }, {\n key: \"handleError\",\n value: function handleError(err, level) {\n this.setState({\n errorText: err,\n errorLevel: level\n });\n } // User clicked Login button in the side panel.\n\n }, {\n key: \"handleLoginRequest\",\n value: function handleLoginRequest(login, password) {\n var _this3 = this;\n\n this.setState({\n loginDisabled: true,\n login: login,\n password: password\n });\n this.handleError('', null);\n\n if (this.tinode.isConnected()) {\n this.doLogin(login, password, {\n meth: this.state.credMethod,\n resp: this.state.credCode\n });\n } else {\n this.tinode.connect().catch(function (err) {\n // Socket error\n _this3.setState({\n loginDisabled: false\n });\n\n _this3.handleError(err.message, 'err');\n });\n }\n } // Connection succeeded.\n\n }, {\n key: \"handleConnected\",\n value: function handleConnected() {\n var params = this.tinode.getServerInfo();\n this.setState({\n serverVersion: params.ver + ' ' + (params.build ? params.build : 'none') + '; '\n });\n this.doLogin(this.state.login, this.state.password, {\n meth: this.state.credMethod,\n resp: this.state.credCode\n });\n }\n }, {\n key: \"doLogin\",\n value: function doLogin(login, password, cred) {\n var _this4 = this;\n\n if (this.tinode.isAuthenticated()) {\n // Already logged in. Go to default screen.\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo('');\n return;\n } // Sanitize and package credentail.\n\n\n cred = tinode_sdk__WEBPACK_IMPORTED_MODULE_4___default.a.credential(cred); // Try to login with login/password. If they are not available, try token. If no token, ask for login/password.\n\n var promise = null;\n var token = this.tinode.getAuthToken();\n\n if (login && password) {\n this.setState({\n password: null\n });\n promise = this.tinode.loginBasic(login, password, cred);\n } else if (token) {\n promise = this.tinode.loginToken(token.token, cred);\n }\n\n if (promise) {\n promise.then(function (ctrl) {\n if (ctrl.code >= 300 && ctrl.text === 'validate credentials') {\n if (cred) {\n _this4.handleError(\"Code does not match\", 'warn');\n }\n\n _this4.handleCredentialsRequest(ctrl.params);\n } else {\n _this4.handleLoginSuccessful();\n }\n }).catch(function (err) {\n // Login failed, report error.\n _this4.setState({\n loginDisabled: false,\n credMethod: undefined,\n credCode: undefined\n });\n\n _this4.handleError(err.message, 'err');\n\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].removeItem('auth-token');\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo('');\n });\n } else {\n // No login credentials provided.\n // Make sure we are on the login page.\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo('');\n this.setState({\n loginDisabled: false\n });\n }\n }\n }, {\n key: \"handleCredentialsRequest\",\n value: function handleCredentialsRequest(params) {\n var parsed = _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].parseUrlHash(window.location.hash);\n parsed.path[0] = 'cred';\n parsed.params['method'] = params.cred[0];\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].composeUrlHash(parsed.path, parsed.params));\n }\n }, {\n key: \"handleLoginSuccessful\",\n value: function handleLoginSuccessful() {\n var _this5 = this;\n\n this.handleError('', null); // Refresh authentication token.\n\n if (_lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].getObject('keep-logged-in')) {\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].setObject('auth-token', this.tinode.getAuthToken());\n } // Logged in fine, subscribe to 'me' attaching callbacks from the contacts view.\n\n\n var me = this.tinode.getMeTopic();\n me.onMetaDesc = this.tnMeMetaDesc;\n me.onContactUpdate = this.tnMeContactUpdate;\n me.onSubsUpdated = this.tnMeSubsUpdated;\n this.setState({\n connected: true,\n credMethod: undefined,\n credCode: undefined,\n myUserId: this.tinode.getCurrentUserID()\n }); // Subscribe, fetch topic desc, the list of subscriptions. Messages are not fetched.\n\n me.subscribe(me.startMetaQuery().withLaterSub().withDesc().build()).catch(function (err) {\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].removeItem('auth-token');\n\n _this5.handleError(err.message, 'err');\n\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo('');\n });\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlSidePanel(window.location.hash, 'contacts'));\n }\n }, {\n key: \"handleDisconnect\",\n value: function handleDisconnect(err) {\n this.setState({\n connected: false,\n topicSelectedOnline: false,\n dialogSelected: null,\n errorText: err && err.message ? err.message : \"Disconnected\",\n errorLevel: err && err.message ? 'err' : 'warn',\n loginDisabled: false,\n contextMenuVisible: false,\n serverVersion: \"no connection\"\n });\n }\n }, {\n key: \"tnMeMetaDesc\",\n value: function tnMeMetaDesc(desc) {\n if (desc && desc.public) {\n this.setState({\n sidePanelTitle: desc.public.fn,\n sidePanelAvatar: makeImageUrl(desc.public.photo)\n });\n }\n } // Reactions to updates to the contact list.\n\n }, {\n key: \"tnMeContactUpdate\",\n value: function tnMeContactUpdate(what, cont) {\n if (what == 'on' || what == 'off') {\n this.resetContactList();\n\n if (this.state.topicSelected == cont.topic) {\n this.setState({\n topicSelectedOnline: what == 'on'\n });\n }\n } else if (what == 'read') {\n this.resetContactList();\n } else if (what == 'msg') {\n // New message received\n // Skip update if the topic is currently open, otherwise the badge will annoyingly flash.\n if (this.state.topicSelected != cont.topic) {\n if (this.state.messageSounds) {\n POP_SOUND.play();\n }\n\n this.resetContactList();\n } else if (document.hidden && this.state.messageSounds) {\n POP_SOUND.play();\n }\n } else if (what == 'recv') {// Explicitly ignoring \"recv\" -- it causes no visible updates to contact list.\n } else if (what == 'gone' || what == 'unsub') {\n // Topic deleted or user unsubscribed. Remove topic from view.\n // If the currently selected topic is gone, clear the selection.\n if (this.state.topicSelected == cont.topic) {\n this.handleTopicSelected(null);\n } // Redraw without the deleted topic.\n\n\n this.resetContactList();\n } else if (what == 'acs') {\n // Permissions changed. If it's for the currently selected topic,\n // update the views.\n if (this.state.topicSelected == cont.topic) {\n this.setState({\n topicSelectedAcs: cont.acs\n });\n }\n } else if (what == 'del') {// messages deleted (hard or soft) -- update pill counter.\n } else {\n // TODO(gene): handle other types of notifications:\n // * ua -- user agent changes (maybe display a pictogram for mobile/desktop).\n // * upd -- topic 'public' updated, issue getMeta().\n console.log(\"Unsupported (yet) presence update:\" + what + \" in: \" + cont.topic);\n }\n }\n }, {\n key: \"tnMeSubsUpdated\",\n value: function tnMeSubsUpdated(unused) {\n this.resetContactList();\n } // Merge search results and contact list to create a single flat\n // list of kown contacts for GroupManager to use.\n\n }, {\n key: \"resetContactList\",\n value: function resetContactList() {\n var _this6 = this;\n\n var newState = {\n chatList: []\n };\n this.tinode.getMeTopic().contacts(function (c) {\n newState.chatList.push(c);\n\n if (_this6.state.topicSelected == c.topic) {\n newState.topicSelectedOnline = c.online;\n newState.topicSelectedAcs = c.acs;\n }\n }); // Merge search results and chat list.\n\n newState.searchableContacts = TinodeWeb.prepareSearchableContacts(newState.chatList, this.state.searchResults);\n this.setState(newState);\n } // Sending \"received\" notifications\n\n }, {\n key: \"tnData\",\n value: function tnData(data) {\n var _this7 = this;\n\n var topic = this.tinode.getTopic(data.topic);\n\n if (topic.msgStatus(data) >= tinode_sdk__WEBPACK_IMPORTED_MODULE_4___default.a.MESSAGE_STATUS_SENT) {\n clearTimeout(this.receivedTimer);\n this.receivedTimer = setTimeout(function () {\n _this7.receivedTimer = undefined;\n topic.noteRecv(data.seq);\n }, _config_js__WEBPACK_IMPORTED_MODULE_9__[\"RECEIVED_DELAY\"]);\n }\n }\n /* Fnd topic: find contacts by tokens */\n\n }, {\n key: \"tnInitFind\",\n value: function tnInitFind() {\n var _this8 = this;\n\n var fnd = this.tinode.getFndTopic();\n\n if (fnd.isSubscribed()) {\n this.tnFndSubsUpdated();\n } else {\n fnd.onSubsUpdated = this.tnFndSubsUpdated;\n fnd.subscribe(fnd.startMetaQuery().withSub().withTags().build()).catch(function (err) {\n _this8.handleError(err.message, 'err');\n });\n }\n }\n }, {\n key: \"tnFndSubsUpdated\",\n value: function tnFndSubsUpdated() {\n var foundContacts = []; // Don't attempt to create P2P topics which already exist. Server will reject the duplicates.\n\n this.tinode.getFndTopic().contacts(function (s) {\n foundContacts.push(s);\n });\n this.setState({\n searchResults: foundContacts,\n searchableContacts: TinodeWeb.prepareSearchableContacts(this.state.chatList, foundContacts)\n });\n }\n /** Called when the user enters a contact into the contact search field in the NewAccount panel\n @param query {Array} is an array of contacts to search for\n */\n\n }, {\n key: \"handleSearchContacts\",\n value: function handleSearchContacts(query) {\n var _this9 = this;\n\n var fnd = this.tinode.getFndTopic();\n fnd.setMeta({\n desc: {\n public: query\n }\n }).then(function (ctrl) {\n return fnd.getMeta(fnd.startMetaQuery().withSub().build());\n }).catch(function (err) {\n _this9.handleError(err.message, 'err');\n });\n } // User clicked on a contact in the side panel or deleted a contact.\n\n }, {\n key: \"handleTopicSelected\",\n value: function handleTopicSelected(topicName, unused_index, online, acs) {\n if (topicName) {\n this.setState({\n errorText: '',\n errorLevel: null,\n mobilePanel: 'topic-view',\n showInfoPanel: false\n }); // Different contact selected.\n\n if (this.state.topicSelected != topicName) {\n this.setState({\n topicSelectedOnline: online,\n topicSelectedAcs: acs\n });\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlTopic('', topicName));\n }\n } else {\n // Currently selected contact deleted\n this.setState({\n errorText: '',\n errorLevel: null,\n mobilePanel: 'sidepanel',\n topicSelectedOnline: false,\n topicSelectedAcs: null,\n showInfoPanel: false\n });\n\n if (this.state.topicSelected) {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlTopic('', null));\n }\n }\n } // In mobile view user requested to show sidepanel\n\n }, {\n key: \"handleHideMessagesView\",\n value: function handleHideMessagesView() {\n this.setState({\n mobilePanel: 'sidepanel'\n });\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlTopic(window.location.hash, null));\n } // User is sending a message, either plain text or a drafty object, possibly\n // with attachments.\n\n }, {\n key: \"handleSendMessage\",\n value: function handleSendMessage(msg, promise, uploader) {\n var _this10 = this;\n\n var topic = this.tinode.getTopic(this.state.topicSelected);\n msg = topic.createMessage(msg, false); // The uploader is used to show progress.\n\n msg._uploader = uploader;\n\n if (!topic.isSubscribed()) {\n if (!promise) {\n promise = Promise.resolve();\n }\n\n promise = promise.then(function () {\n return topic.subscribe();\n });\n }\n\n if (promise) {\n promise = promise.catch(function (err) {\n _this10.handleError(err.message, 'err');\n });\n }\n\n topic.publishDraft(msg, promise).catch(function (err) {\n _this10.handleError(err.message, 'err');\n });\n } // User chose a Sign Up menu item.\n\n }, {\n key: \"handleNewAccount\",\n value: function handleNewAccount() {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlSidePanel(window.location.hash, 'register'));\n } // Actual registration of a new account.\n\n }, {\n key: \"handleNewAccountRequest\",\n value: function handleNewAccountRequest(login_, password_, public_, cred_, tags_) {\n var _this11 = this;\n\n this.tinode.connect(this.state.serverAddress).then(function () {\n return _this11.tinode.createAccountBasic(login_, password_, {\n public: public_,\n tags: tags_,\n cred: tinode_sdk__WEBPACK_IMPORTED_MODULE_4___default.a.credential(cred_)\n });\n }).then(function (ctrl) {\n if (ctrl.code >= 300 && ctrl.text == 'validate credentials') {\n _this11.handleCredentialsRequest(ctrl.params);\n } else {\n _this11.handleLoginSuccessful(_this11);\n }\n }).catch(function (err) {\n _this11.handleError(err.message, 'err');\n });\n }\n }, {\n key: \"handleUpdateAccountRequest\",\n value: function handleUpdateAccountRequest(password, pub, defacs) {\n var _this12 = this;\n\n if (pub || defacs) {\n this.tinode.getMeTopic().setMeta({\n desc: {\n public: pub,\n defacs: defacs\n }\n }).catch(function (err) {\n _this12.handleError(err.message, 'err');\n });\n }\n\n if (password) {\n this.tinode.updateAccountBasic(null, this.tinode.getCurrentLogin(), password).catch(function (err) {\n _this12.handleError(err.message, 'err');\n });\n }\n }\n }, {\n key: \"handleUpdateAccountTagsRequest\",\n value: function handleUpdateAccountTagsRequest(tags) {\n var _this13 = this;\n\n this.tinode.getFndTopic().setMeta({\n tags: tags\n }).catch(function (err) {\n _this13.handleError(err.message, 'err');\n });\n } // User chose Settings menu item.\n\n }, {\n key: \"handleSettings\",\n value: function handleSettings() {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlSidePanel(window.location.hash, this.state.myUserId ? 'edit' : 'settings'));\n } // User updated global parameters.\n\n }, {\n key: \"handleGlobalSettings\",\n value: function handleGlobalSettings(settings) {\n var serverAddress = settings.serverAddress || this.state.serverAddress;\n var transport = settings.transport || this.state.transport;\n\n if (this.tinode) {\n this.tinode.onDisconnect = undefined;\n this.tinode.disconnect();\n }\n\n this.tinode = TinodeWeb.tnSetup(serverAddress, transport);\n this.tinode.onConnect = this.handleConnected;\n this.tinode.onDisconnect = this.handleDisconnect;\n this.setState({\n serverAddress: serverAddress,\n transport: transport\n });\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].setObject('settings', {\n serverAddress: serverAddress,\n transport: transport\n });\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlSidePanel(window.location.hash, ''));\n } // Initialize desktop alerts = push notifications.\n\n }, {\n key: \"initDesktopAlerts\",\n value: function initDesktopAlerts() {\n var _this14 = this;\n\n // Google could not be bothered to mention that\n // onTokenRefresh is never called.\n this.fbPush.onTokenRefresh(function () {\n _this14.requestPushToken(true);\n });\n this.fbPush.onMessage(function (payload) {// No need to do anything about it.\n // All the magic happends in the service worker.\n });\n }\n }, {\n key: \"togglePushToken\",\n value: function togglePushToken(enabled) {\n var _this15 = this;\n\n if (enabled) {\n if (!this.state.firebaseToken) {\n this.fbPush.requestPermission().then(function () {\n _this15.requestPushToken(true);\n }).catch(function (err) {\n _this15.handleError(err.message, 'err');\n\n _this15.setState({\n desktopAlerts: false,\n firebaseToken: null\n });\n\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].updateObject('settings', {\n desktopAlerts: false\n });\n console.log(\"Failed to get permission to notify.\", err);\n });\n } else {\n this.setState({\n desktopAlerts: true\n });\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].updateObject('settings', {\n desktopAlerts: true\n });\n }\n } else if (this.state.firebaseToken) {\n this.fbPush.deleteToken(this.state.firebaseToken).catch(function (err) {\n console.log(\"Unable to delete token.\", err);\n }).finally(function () {\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].updateObject('settings', {\n desktopAlerts: false\n });\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].removeItem('firebase-token');\n\n _this15.setState({\n desktopAlerts: false,\n firebaseToken: null\n });\n });\n } else {\n this.setState({\n desktopAlerts: false,\n firebaseToken: null\n });\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].updateObject('settings', {\n desktopAlerts: false\n });\n }\n }\n }, {\n key: \"requestPushToken\",\n value: function requestPushToken(sendToServer) {\n var _this16 = this;\n\n this.fbPush.getToken().then(function (refreshedToken) {\n if (refreshedToken != _this16.state.firebaseToken) {\n _this16.tinode.setDeviceToken(refreshedToken, sendToServer);\n\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].setObject('firebase-token', refreshedToken);\n }\n\n _this16.setState({\n firebaseToken: refreshedToken,\n desktopAlerts: true\n });\n\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].updateObject('settings', {\n desktopAlerts: true\n });\n }).catch(function (err) {\n _this16.handleError(err.message, 'err');\n\n console.log(\"Failed to retrieve firebase token\", err);\n });\n }\n }, {\n key: \"handleToggleMessageSounds\",\n value: function handleToggleMessageSounds(enabled) {\n this.setState({\n messageSounds: enabled\n });\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].updateObject('settings', {\n messageSoundsOff: !enabled\n });\n } // User clicked Cancel button in Setting or Sign Up panel.\n\n }, {\n key: \"handleSidepanelCancel\",\n value: function handleSidepanelCancel() {\n var parsed = _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].parseUrlHash(window.location.hash);\n parsed.path[0] = this.state.myUserId ? 'contacts' : '';\n\n if (parsed.params) {\n delete parsed.params.code;\n delete parsed.params.method;\n delete parsed.params.tab;\n }\n\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].composeUrlHash(parsed.path, parsed.params));\n this.setState({\n errorText: '',\n errorLevel: null\n });\n } // User clicked a (+) menu item.\n\n }, {\n key: \"handleNewTopic\",\n value: function handleNewTopic() {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlSidePanel(window.location.hash, 'newtpk'));\n } // Request to start a new topic. New P2P topic requires peer's name.\n\n }, {\n key: \"handleNewTopicRequest\",\n value: function handleNewTopicRequest(peerName, pub, priv, tags) {\n var _this17 = this;\n\n var topicName = peerName || this.tinode.newGroupTopicName();\n\n if (!peerName) {\n this.setState({\n newGroupTopicParams: {\n desc: {\n public: pub,\n private: {\n comment: priv\n }\n },\n tags: tags\n }\n }, function () {\n _this17.handleTopicSelected(topicName);\n });\n } else {\n this.handleTopicSelected(topicName);\n }\n } // New topic was creted, here is the new topic name.\n\n }, {\n key: \"handleNewTopicCreated\",\n value: function handleNewTopicCreated(oldName, newName) {\n if (this.state.topicSelected == oldName && oldName != newName) {\n // If the current URl contains the old topic name, replace it with new.\n // Update the name of the selected topic first so the navigator doen't clear\n // the state.\n this.setState({\n topicSelected: newName\n }, function () {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlTopic('', newName));\n });\n }\n }\n }, {\n key: \"handleTopicUpdateRequest\",\n value: function handleTopicUpdateRequest(topicName, pub, priv, permissions) {\n var _this18 = this;\n\n var topic = this.tinode.getTopic(topicName);\n\n if (topic) {\n var params = {};\n\n if (pub) {\n params.public = pub;\n }\n\n if (priv) {\n params.private = {\n comment: priv\n };\n }\n\n if (permissions) {\n params.defacs = permissions;\n }\n\n topic.setMeta({\n desc: params\n }).catch(function (err) {\n _this18.handleError(err.message, 'err');\n });\n }\n }\n }, {\n key: \"handleChangePermissions\",\n value: function handleChangePermissions(topicName, mode, uid) {\n var _this19 = this;\n\n var topic = this.tinode.getTopic(topicName);\n\n if (topic) {\n var am = topic.getAccessMode();\n\n if (uid) {\n am.updateGiven(mode);\n mode = am.getGiven();\n } else {\n am.updateWant(mode);\n mode = am.getWant();\n }\n\n topic.setMeta({\n sub: {\n user: uid,\n mode: mode\n }\n }).catch(function (err) {\n _this19.handleError(err.message, 'err');\n });\n }\n }\n }, {\n key: \"handleTagsUpdated\",\n value: function handleTagsUpdated(topicName, tags) {\n var _this20 = this;\n\n var topic = this.tinode.getTopic(topicName);\n\n if (topic) {\n var instance = this;\n topic.setMeta({\n tags: tags\n }).catch(function (err) {\n _this20.handleError(err.message, 'err');\n });\n }\n }\n }, {\n key: \"handleLogout\",\n value: function handleLogout() {\n updateFavicon(0);\n _lib_local_storage_js__WEBPACK_IMPORTED_MODULE_11__[\"default\"].removeItem('auth-token');\n\n if (this.tinode) {\n this.tinode.onDisconnect = undefined;\n this.tinode.disconnect();\n }\n\n this.setState(this.getBlankState());\n this.tinode = TinodeWeb.tnSetup(this.state.serverAddress, this.state.transport);\n this.tinode.onConnect = this.handleConnected;\n this.tinode.onDisconnect = this.handleDisconnect;\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo('');\n }\n }, {\n key: \"handleLeaveUnsubRequest\",\n value: function handleLeaveUnsubRequest(topicName) {\n var _this21 = this;\n\n var topic = this.tinode.getTopic(topicName);\n\n if (!topic) {\n return;\n }\n\n topic.leave(true).then(function (ctrl) {\n // Hide MessagesView and InfoView panels.\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].setUrlTopic(window.location.hash, ''));\n }).catch(function (err) {\n _this21.handleError(err.message, 'err');\n });\n }\n }, {\n key: \"handleDialogCancel\",\n value: function handleDialogCancel() {\n this.setState({\n dialogSelected: null\n });\n }\n }, {\n key: \"handleShowContextMenu\",\n value: function handleShowContextMenu(params, menuItems) {\n this.setState({\n contextMenuVisible: true,\n contextMenuClickAt: {\n x: params.x,\n y: params.y\n },\n contextMenuParams: params,\n contextMenuItems: menuItems || this.defaultTopicContextMenu(params.topicName),\n contextMenuBounds: ReactDOM.findDOMNode(this).getBoundingClientRect()\n });\n }\n }, {\n key: \"defaultTopicContextMenu\",\n value: function defaultTopicContextMenu(topicName) {\n var muted = false,\n blocked = false,\n subscribed = false,\n deleter = false;\n var topic = this.tinode.getTopic(topicName);\n\n if (topic) {\n if (topic.isSubscribed()) {\n subscribed = true;\n var acs = topic.getAccessMode();\n muted = acs && acs.isMuted();\n blocked = acs && !acs.isJoiner();\n deleter = acs && acs.isDeleter();\n }\n }\n\n return [subscribed ? {\n title: \"Info\",\n handler: this.handleShowInfoView\n } : null, subscribed ? 'messages_clear' : null, subscribed && deleter ? 'messages_clear_hard' : null, subscribed ? muted ? 'topic_unmute' : 'topic_mute' : null, subscribed ? blocked ? 'topic_unblock' : 'topic_block' : null, 'topic_delete'];\n }\n }, {\n key: \"handleHideContextMenu\",\n value: function handleHideContextMenu() {\n this.setState({\n contextMenuVisible: false,\n contextMenuClickAt: null,\n contextMenuParams: null,\n contextMenuBounds: null\n });\n }\n }, {\n key: \"handleShowInfoView\",\n value: function handleShowInfoView() {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].addUrlParam(window.location.hash, 'info', true));\n this.setState({\n showInfoPanel: true\n });\n }\n }, {\n key: \"handleHideInfoView\",\n value: function handleHideInfoView() {\n _lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].navigateTo(_lib_navigation_js__WEBPACK_IMPORTED_MODULE_12__[\"default\"].removeUrlParam(window.location.hash, 'info'));\n this.setState({\n showInfoPanel: false\n });\n }\n }, {\n key: \"handleMemberUpdateRequest\",\n value: function handleMemberUpdateRequest(topicName, added, removed) {\n var _this22 = this;\n\n if (!topicName) {\n return;\n }\n\n var topic = this.tinode.getTopic(topicName);\n\n if (!topic) {\n return;\n }\n\n if (added && added.length > 0) {\n added.map(function (uid) {\n topic.invite(uid, null).catch(function (err) {\n _this22.handleError(err.message, 'err');\n });\n });\n }\n\n if (removed && removed.length > 0) {\n removed.map(function (uid) {\n topic.delSubscription(uid).catch(function (err) {\n _this22.handleError(err.message, 'err');\n });\n });\n }\n }\n }, {\n key: \"handleValidateCredentialsRequest\",\n value: function handleValidateCredentialsRequest(cred, code) {\n this.setState({\n credMethod: cred,\n credCode: code\n });\n this.doLogin(null, null, {\n meth: cred,\n resp: code\n });\n }\n }, {\n key: \"handlePasswordResetRequest\",\n value: function handlePasswordResetRequest(method, value) {\n var _this23 = this;\n\n // If already connected, connnect() will return a resolved promise.\n this.tinode.connect().then(function () {\n return _this23.tinode.requestResetAuthSecret('basic', method, value);\n }).catch(function (err) {\n // Socket error\n _this23.handleError(err.message, 'err');\n });\n }\n }, {\n key: \"handleResetPassword\",\n value: function handleResetPassword(scheme, newPassword, token) {\n var _this24 = this;\n\n token = base64ReEncode(token);\n\n if (!token) {\n this.handleError(\"Invalid security token\", 'err');\n } else {\n this.tinode.connect().then(function () {\n return _this24.tinode.updateAccountBasic(null, null, newPassword, {\n token: token\n });\n }).catch(function (err) {\n // Socket error\n _this24.handleError(err.message, 'err');\n });\n }\n }\n }, {\n key: \"render\",\n value: function render() {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"app-container\"\n }, this.state.contextMenuVisible ? react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_widgets_context_menu_jsx__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n tinode: this.tinode,\n bounds: this.state.contextMenuBounds,\n clickAt: this.state.contextMenuClickAt,\n params: this.state.contextMenuParams,\n items: this.state.contextMenuItems,\n hide: this.handleHideContextMenu,\n onAction: this.handleContextMenuAction,\n onError: this.handleError\n }) : null, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_sidepanel_view_jsx__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n tinode: this.tinode,\n connected: this.state.connected,\n displayMobile: this.state.displayMobile,\n hideSelf: this.state.displayMobile && this.state.mobilePanel !== 'sidepanel',\n state: this.state.sidePanelSelected,\n title: this.state.sidePanelTitle,\n avatar: this.state.sidePanelAvatar,\n login: this.state.login,\n myUserId: this.state.myUserId,\n loginDisabled: this.state.loginDisabled,\n errorText: this.state.errorText,\n errorLevel: this.state.errorLevel,\n topicSelected: this.state.topicSelected,\n chatList: this.state.chatList,\n credMethod: this.state.credMethod,\n credCode: this.state.credCode,\n transport: this.state.transport,\n messageSounds: this.state.messageSounds,\n desktopAlerts: this.state.desktopAlerts,\n desktopAlertsEnabled: this.state.desktopAlertsEnabled,\n serverAddress: this.state.serverAddress,\n onGlobalSettings: this.handleGlobalSettings,\n onSignUp: this.handleNewAccount,\n onSettings: this.handleSettings,\n onLoginRequest: this.handleLoginRequest,\n onCreateAccount: this.handleNewAccountRequest,\n onUpdateAccount: this.handleUpdateAccountRequest,\n onUpdateAccountTags: this.handleUpdateAccountTagsRequest,\n onTogglePushNotifications: this.togglePushToken,\n onToggleMessageSounds: this.handleToggleMessageSounds,\n onTopicSelected: this.handleTopicSelected,\n onCreateTopic: this.handleNewTopicRequest,\n onNewTopic: this.handleNewTopic,\n onLogout: this.handleLogout,\n onCancel: this.handleSidepanelCancel,\n onError: this.handleError,\n onValidateCredentials: this.handleValidateCredentialsRequest,\n onPasswordResetRequest: this.handlePasswordResetRequest,\n onResetPassword: this.handleResetPassword,\n onInitFind: this.tnInitFind,\n searchResults: this.state.searchResults,\n onSearchContacts: this.handleSearchContacts,\n showContextMenu: this.handleShowContextMenu\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_messages_view_jsx__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n tinode: this.tinode,\n connected: this.state.connected,\n online: this.state.topicSelectedOnline,\n acs: this.state.topicSelectedAcs,\n displayMobile: this.state.displayMobile,\n viewportWidth: this.state.viewportWidth,\n hideSelf: this.state.displayMobile && (this.state.mobilePanel !== 'topic-view' || this.state.showInfoPanel),\n topic: this.state.topicSelected,\n myUserId: this.state.myUserId,\n serverVersion: this.state.serverVersion,\n serverAddress: this.state.serverAddress,\n errorText: this.state.errorText,\n errorLevel: this.state.errorLevel,\n newGroupTopicParams: this.state.newGroupTopicParams,\n onHideMessagesView: this.handleHideMessagesView,\n onData: this.tnData,\n onError: this.handleError,\n onNewTopicCreated: this.handleNewTopicCreated,\n readTimerHandler: this.handleReadTimer,\n showContextMenu: this.handleShowContextMenu,\n sendMessage: this.handleSendMessage\n }), this.state.showInfoPanel ? react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_info_view_jsx__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n tinode: this.tinode,\n connected: this.state.connected,\n displayMobile: this.state.displayMobile,\n topic: this.state.topicSelected,\n searchableContacts: this.state.searchableContacts,\n myUserId: this.state.myUserId,\n errorText: this.state.errorText,\n errorLevel: this.state.errorLevel,\n onTopicDescUpdate: this.handleTopicUpdateRequest,\n onCancel: this.handleHideInfoView,\n onChangePermissions: this.handleChangePermissions,\n onMemberUpdateRequest: this.handleMemberUpdateRequest,\n onLeaveTopic: this.handleLeaveUnsubRequest,\n onAddMember: this.handleManageGroupMembers,\n onTopicTagsUpdate: this.handleTagsUpdated,\n onInitFind: this.tnInitFind,\n onError: this.handleError,\n showContextMenu: this.handleShowContextMenu\n }) : null);\n }\n }], [{\n key: \"tnSetup\",\n value: function tnSetup(serverAddress, transport) {\n var tinode = new tinode_sdk__WEBPACK_IMPORTED_MODULE_4___default.a(_config_js__WEBPACK_IMPORTED_MODULE_9__[\"APP_NAME\"], serverAddress, _config_js__WEBPACK_IMPORTED_MODULE_9__[\"API_KEY\"], transport, Object(_lib_host_name_js__WEBPACK_IMPORTED_MODULE_10__[\"isSecureConnection\"])());\n tinode.enableLogging(true, true);\n return tinode;\n }\n }, {\n key: \"prepareSearchableContacts\",\n value: function prepareSearchableContacts(chatList, foundContacts) {\n var merged = {}; // For chatList topics merge only p2p topics and convert them to the\n // same format as foundContacts.\n\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = chatList[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var c = _step.value;\n\n if (tinode_sdk__WEBPACK_IMPORTED_MODULE_4___default.a.topicType(c.topic) == 'p2p') {\n merged[c.topic] = {\n user: c.topic,\n updated: c.updated,\n public: c.public,\n private: c.private,\n acs: c.acs\n };\n }\n } // Add all foundCountacts if they have not been added already.\n\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return != null) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n\n var _iteratorNormalCompletion2 = true;\n var _didIteratorError2 = false;\n var _iteratorError2 = undefined;\n\n try {\n for (var _iterator2 = foundContacts[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {\n var _c = _step2.value;\n\n if (!merged[_c.user]) {\n merged[_c.user] = _c;\n }\n }\n } catch (err) {\n _didIteratorError2 = true;\n _iteratorError2 = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion2 && _iterator2.return != null) {\n _iterator2.return();\n }\n } finally {\n if (_didIteratorError2) {\n throw _iteratorError2;\n }\n }\n }\n\n return Object.values(merged);\n }\n }]);\n\n return TinodeWeb;\n}(react__WEBPACK_IMPORTED_MODULE_0___default.a.Component);\n\n\n;\n\n//# sourceURL=webpack:///./src/views/tinode-web.jsx?");
/***/ }),
diff --git a/umd/index.prod.js b/umd/index.prod.js
index 618884e1..4530303c 100644
--- a/umd/index.prod.js
+++ b/umd/index.prod.js
@@ -1 +1,45 @@
-!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Webapp=e()}}(function(){return function(){return function e(t,n,r){function i(a,s){if(!n[a]){if(!t[a]){var l="function"==typeof require&&require;if(!s&&l)return l(a,!0);if(o)return o(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var c=n[a]={exports:{}};t[a][0].call(c.exports,function(e){return i(t[a][1][e]||e)},c,c.exports,e,t,n,r)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;aa&&console.warn("This browser only supports "+a+" actions.The remaining actions will not be displayed."),[2,i.showNotification(r,n)];case 3:return this.bgMessageHandler?[4,this.bgMessageHandler(t)]:[3,5];case 4:return s.sent(),[2];case 5:return[2]}})})},t.prototype.onSubChange_=function(e){return l.__awaiter(this,void 0,void 0,function(){var e,t,n,r;return l.__generator(this,function(i){switch(i.label){case 0:return i.trys.push([0,2,,3]),[4,this.getSWRegistration_()];case 1:return e=i.sent(),[3,3];case 2:throw t=i.sent(),p.create(c.UNABLE_TO_RESUBSCRIBE,{message:t});case 3:return i.trys.push([3,5,,8]),[4,e.pushManager.getSubscription()];case 4:return i.sent(),[3,8];case 5:return n=i.sent(),[4,this.getTokenDetailsModel().getTokenDetailsFromSWScope(e.scope)];case 6:if(!(r=i.sent()))throw n;return[4,this.deleteToken(r.fcmToken)];case 7:throw i.sent(),n;case 8:return[2]}})})},t.prototype.onNotificationClick_=function(e){return l.__awaiter(this,void 0,void 0,function(){var t,n,r,i;return l.__generator(this,function(o){switch(o.label){case 0:return e.notification&&e.notification.data&&e.notification.data.FCM_MSG?e.action?[2]:(e.stopImmediatePropagation(),e.notification.close(),(t=e.notification.data.FCM_MSG).notification&&(n=t.fcmOptions&&t.fcmOptions.link||t.notification.click_action)?[4,this.getWindowClient_(n)]:[2]):[2];case 1:return(r=o.sent())?[3,3]:[4,self.clients.openWindow(n)];case 2:return r=o.sent(),[3,5];case 3:return[4,r.focus()];case 4:r=o.sent(),o.label=5;case 5:return r?(delete t.notification,delete t.fcmOptions,i=O(a.NOTIFICATION_CLICKED,t),[2,this.attemptToMessageClient_(r,i)]):[2]}})})},t.prototype.getNotificationData_=function(e){if(e&&"object"==typeof e.notification){var t,n=l.__assign({},e.notification);return n.data=l.__assign({},e.notification.data,((t={}).FCM_MSG=e,t)),n}},t.prototype.setBackgroundMessageHandler=function(e){if(!e||"function"!=typeof e)throw p.create(c.BG_HANDLER_FUNCTION_EXPECTED);this.bgMessageHandler=e},t.prototype.getWindowClient_=function(e){return l.__awaiter(this,void 0,void 0,function(){var t,n,r,i;return l.__generator(this,function(o){switch(o.label){case 0:return t=new URL(e,self.location.href).href,[4,N()];case 1:for(n=o.sent(),r=null,i=0;i0?V:z)(e)},H=Math.min,K=function(e){return e>0?H(q(e),9007199254740991):0},G=Array.isArray||function(e){return"Array"==L(e)},$=f["__core-js_shared__"]||(f["__core-js_shared__"]={}),Y=function(e){return $[e]||($[e]={})},Q=p(function(e){var t=Y("wks"),n=f.Symbol,r="function"==typeof n;(e.exports=function(e){return t[e]||(t[e]=r&&n[e]||(r?n:M)("Symbol."+e))}).store=t}),X=Q("species"),J=function(e,t){return new(function(e){var t;return G(e)&&("function"!=typeof(t=e.constructor)||t!==Array&&!G(t.prototype)||(t=void 0),m(t)&&null===(t=t[X])&&(t=void 0)),void 0===t?Array:t}(e))(t)},Z=function(e,t){var n=1==e,r=2==e,i=3==e,o=4==e,a=6==e,s=5==e||a,l=t||J;return function(t,u,c){for(var d,p,f=B(t),h=j(f),m=R(u,c,3),v=K(h.length),g=0,y=n?l(t,v):r?l(t,0):void 0;v>g;g++)if((s||g in h)&&(p=m(d=h[g],g,f),e))if(n)y[g]=p;else if(p)switch(e){case 3:return!0;case 5:return d;case 6:return g;case 2:y.push(d)}else if(o)return!1;return a?-1:i||o?o:y}},ee=Q("unscopables"),te=Array.prototype;void 0==te[ee]&&x(te,ee,{});var ne=function(e){te[ee][e]=!0},re=Z(5),ie=!0;"find"in[]&&Array(1).find(function(){ie=!1}),U(U.P+U.F*ie,"Array",{find:function(e){return re(this,e,arguments.length>1?arguments[1]:void 0)}}),ne("find");h.Array.find;var oe=Z(6),ae=!0;"findIndex"in[]&&Array(1).findIndex(function(){ae=!1}),U(U.P+U.F*ae,"Array",{findIndex:function(e){return oe(this,e,arguments.length>1?arguments[1]:void 0)}}),ne("findIndex");h.Array.findIndex;var se,le=function(e){return j(W(e))},ue=Math.max,ce=Math.min,de=Y("keys"),pe=function(e){return de[e]||(de[e]=M(e))},fe=(se=!1,function(e,t,n){var r,i=le(e),o=K(i.length),a=function(e,t){return(e=q(e))<0?ue(e+t,0):ce(e,t)}(n,o);if(se&&t!=t){for(;o>a;)if((r=i[a++])!=r)return!0}else for(;o>a;a++)if((se||a in i)&&i[a]===t)return se||a||0;return!se&&-1}),he=pe("IE_PROTO"),me=function(e,t){var n,r=le(e),i=0,o=[];for(n in r)n!=he&&N(r,n)&&o.push(n);for(;t.length>i;)N(r,n=t[i++])&&(~fe(o,n)||o.push(n));return o},ve="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(","),ge=Object.keys||function(e){return me(e,ve)},ye={f:Object.getOwnPropertySymbols},be={f:{}.propertyIsEnumerable},we=Object.assign,_e=!we||g(function(){var e={},t={},n=Symbol(),r="abcdefghijklmnopqrst";return e[n]=7,r.split("").forEach(function(e){t[e]=e}),7!=we({},e)[n]||Object.keys(we({},t)).join("")!=r})?function(e,t){for(var n=B(e),r=arguments.length,i=1,o=ye.f,a=be.f;r>i;)for(var s,l=j(arguments[i++]),u=o?ge(l).concat(o(l)):ge(l),c=u.length,d=0;c>d;)a.call(l,s=u[d++])&&(n[s]=l[s]);return n}:we;U(U.S+U.F,"Object",{assign:_e});h.Object.assign;var Ee=Q("match"),ke=function(e,t,n){if(m(r=t)&&(void 0!==(i=r[Ee])?i:"RegExp"==L(r)))throw TypeError("String#"+n+" doesn't accept regex!");var r,i;return String(W(e))},Se=Q("match"),Te="".startsWith;U(U.P+U.F*function(e){var t=/./;try{"/./"[e](t)}catch(n){try{return t[Se]=!1,!"/./"[e](t)}catch(e){}}return!0}("startsWith"),"String",{startsWith:function(e){var t=ke(this,e,"startsWith"),n=K(Math.min(arguments.length>1?arguments[1]:void 0,t.length)),r=String(e);return Te?Te.call(t,r,n):t.slice(n,n+r.length)===r}});h.String.startsWith;U(U.P,"String",{repeat:function(e){var t=String(W(this)),n="",r=q(e);if(r<0||r==1/0)throw RangeError("Count can't be negative");for(;r>0;(r>>>=1)&&(t+=t))1&r&&(n+=t);return n}});h.String.repeat;var Ce=p(function(e){var t=M("meta"),n=T.f,r=0,i=Object.isExtensible||function(){return!0},o=!g(function(){return i(Object.preventExtensions({}))}),a=function(e){n(e,t,{value:{i:"O"+ ++r,w:{}}})},s=e.exports={KEY:t,NEED:!1,fastKey:function(e,n){if(!m(e))return"symbol"==typeof e?e:("string"==typeof e?"S":"P")+e;if(!N(e,t)){if(!i(e))return"F";if(!n)return"E";a(e)}return e[t].i},getWeak:function(e,n){if(!N(e,t)){if(!i(e))return!0;if(!n)return!1;a(e)}return e[t].w},onFreeze:function(e){return o&&s.NEED&&i(e)&&!N(e,t)&&a(e),e}}}),xe=(Ce.KEY,Ce.NEED,Ce.fastKey,Ce.getWeak,Ce.onFreeze,T.f),Pe=Q("toStringTag"),Ne=function(e,t,n){e&&!N(e=n?e:e.prototype,Pe)&&xe(e,Pe,{configurable:!0,value:t})},Oe={f:Q},De=T.f,Me=function(e){var t=h.Symbol||(h.Symbol=f.Symbol||{});"_"==e.charAt(0)||e in t||De(t,e,{value:Oe.f(e)})},Ae=y?Object.defineProperties:function(e,t){v(e);for(var n,r=ge(t),i=r.length,o=0;i>o;)T.f(e,n=r[o++],t[n]);return e},Re=f.document,Ie=Re&&Re.documentElement,Ue=pe("IE_PROTO"),Fe=function(){},Le=function(){var e,t=_("iframe"),n=ve.length;for(t.style.display="none",Ie.appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("