('service', 'Service', errors);\n *\n * ...\n * throw error.create(Err.GENERIC);\n * ...\n * throw error.create(Err.FILE_NOT_FOUND, {'file': fileName});\n * ...\n * // Service: Could not file file: foo.txt (service/file-not-found).\n *\n * catch (e) {\n * assert(e.message === \"Could not find file: foo.txt.\");\n * if ((e as FirebaseError)?.code === 'service/file-not-found') {\n * console.log(\"Could not read file: \" + e['file']);\n * }\n * }\n */\nconst ERROR_NAME = 'FirebaseError';\n// Based on code from:\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types\nclass FirebaseError extends Error {\n constructor(\n /** The error code for this error. */\n code, message, \n /** Custom data for this error. */\n customData) {\n super(message);\n this.code = code;\n this.customData = customData;\n /** The custom name for all FirebaseErrors. */\n this.name = ERROR_NAME;\n // Fix For ES5\n // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n // TODO(dlarocque): Replace this with `new.target`: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget\n // which we can now use since we no longer target ES5.\n Object.setPrototypeOf(this, FirebaseError.prototype);\n // Maintains proper stack trace for where our error was thrown.\n // Only available on V8.\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ErrorFactory.prototype.create);\n }\n }\n}\nclass ErrorFactory {\n constructor(service, serviceName, errors) {\n this.service = service;\n this.serviceName = serviceName;\n this.errors = errors;\n }\n create(code, ...data) {\n const customData = data[0] || {};\n const fullCode = `${this.service}/${code}`;\n const template = this.errors[code];\n const message = template ? replaceTemplate(template, customData) : 'Error';\n // Service Name: Error message (service/code).\n const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`;\n const error = new FirebaseError(fullCode, fullMessage, customData);\n return error;\n }\n}\nfunction replaceTemplate(template, data) {\n return template.replace(PATTERN, (_, key) => {\n const value = data[key];\n return value != null ? String(value) : `<${key}?>`;\n });\n}\nconst PATTERN = /\\{\\$([^}]+)}/g;\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Evaluates a JSON string into a javascript object.\n *\n * @param {string} str A string containing JSON.\n * @return {*} The javascript object representing the specified JSON.\n */\nfunction jsonEval(str) {\n return JSON.parse(str);\n}\n/**\n * Returns JSON representing a javascript object.\n * @param {*} data JavaScript object to be stringified.\n * @return {string} The JSON contents of the object.\n */\nfunction stringify(data) {\n return JSON.stringify(data);\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Decodes a Firebase auth. token into constituent parts.\n *\n * Notes:\n * - May return with invalid / incomplete claims if there's no native base64 decoding support.\n * - Doesn't check if the token is actually valid.\n */\nconst decode = function (token) {\n let header = {}, claims = {}, data = {}, signature = '';\n try {\n const parts = token.split('.');\n header = jsonEval(base64Decode(parts[0]) || '');\n claims = jsonEval(base64Decode(parts[1]) || '');\n signature = parts[2];\n data = claims['d'] || {};\n delete claims['d'];\n }\n catch (e) { }\n return {\n header,\n claims,\n data,\n signature\n };\n};\n/**\n * Decodes a Firebase auth. token and checks the validity of its time-based claims. Will return true if the\n * token is within the time window authorized by the 'nbf' (not-before) and 'iat' (issued-at) claims.\n *\n * Notes:\n * - May return a false negative if there's no native base64 decoding support.\n * - Doesn't check if the token is actually valid.\n */\nconst isValidTimestamp = function (token) {\n const claims = decode(token).claims;\n const now = Math.floor(new Date().getTime() / 1000);\n let validSince = 0, validUntil = 0;\n if (typeof claims === 'object') {\n if (claims.hasOwnProperty('nbf')) {\n validSince = claims['nbf'];\n }\n else if (claims.hasOwnProperty('iat')) {\n validSince = claims['iat'];\n }\n if (claims.hasOwnProperty('exp')) {\n validUntil = claims['exp'];\n }\n else {\n // token will expire after 24h by default\n validUntil = validSince + 86400;\n }\n }\n return (!!now &&\n !!validSince &&\n !!validUntil &&\n now >= validSince &&\n now <= validUntil);\n};\n/**\n * Decodes a Firebase auth. token and returns its issued at time if valid, null otherwise.\n *\n * Notes:\n * - May return null if there's no native base64 decoding support.\n * - Doesn't check if the token is actually valid.\n */\nconst issuedAtTime = function (token) {\n const claims = decode(token).claims;\n if (typeof claims === 'object' && claims.hasOwnProperty('iat')) {\n return claims['iat'];\n }\n return null;\n};\n/**\n * Decodes a Firebase auth. token and checks the validity of its format. Expects a valid issued-at time.\n *\n * Notes:\n * - May return a false negative if there's no native base64 decoding support.\n * - Doesn't check if the token is actually valid.\n */\nconst isValidFormat = function (token) {\n const decoded = decode(token), claims = decoded.claims;\n return !!claims && typeof claims === 'object' && claims.hasOwnProperty('iat');\n};\n/**\n * Attempts to peer into an auth token and determine if it's an admin auth token by looking at the claims portion.\n *\n * Notes:\n * - May return a false negative if there's no native base64 decoding support.\n * - Doesn't check if the token is actually valid.\n */\nconst isAdmin = function (token) {\n const claims = decode(token).claims;\n return typeof claims === 'object' && claims['admin'] === true;\n};\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction contains(obj, key) {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\nfunction safeGet(obj, key) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n return obj[key];\n }\n else {\n return undefined;\n }\n}\nfunction isEmpty(obj) {\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n return false;\n }\n }\n return true;\n}\nfunction map(obj, fn, contextObj) {\n const res = {};\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n res[key] = fn.call(contextObj, obj[key], key, obj);\n }\n }\n return res;\n}\n/**\n * Deep equal two objects. Support Arrays and Objects.\n */\nfunction deepEqual(a, b) {\n if (a === b) {\n return true;\n }\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n for (const k of aKeys) {\n if (!bKeys.includes(k)) {\n return false;\n }\n const aProp = a[k];\n const bProp = b[k];\n if (isObject(aProp) && isObject(bProp)) {\n if (!deepEqual(aProp, bProp)) {\n return false;\n }\n }\n else if (aProp !== bProp) {\n return false;\n }\n }\n for (const k of bKeys) {\n if (!aKeys.includes(k)) {\n return false;\n }\n }\n return true;\n}\nfunction isObject(thing) {\n return thing !== null && typeof thing === 'object';\n}\n\n/**\n * @license\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Rejects if the given promise doesn't resolve in timeInMS milliseconds.\n * @internal\n */\nfunction promiseWithTimeout(promise, timeInMS = 2000) {\n const deferredPromise = new Deferred();\n setTimeout(() => deferredPromise.reject('timeout!'), timeInMS);\n promise.then(deferredPromise.resolve, deferredPromise.reject);\n return deferredPromise.promise;\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Returns a querystring-formatted string (e.g. &arg=val&arg2=val2) from a\n * params object (e.g. {arg: 'val', arg2: 'val2'})\n * Note: You must prepend it with ? when adding it to a URL.\n */\nfunction querystring(querystringParams) {\n const params = [];\n for (const [key, value] of Object.entries(querystringParams)) {\n if (Array.isArray(value)) {\n value.forEach(arrayVal => {\n params.push(encodeURIComponent(key) + '=' + encodeURIComponent(arrayVal));\n });\n }\n else {\n params.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n }\n }\n return params.length ? '&' + params.join('&') : '';\n}\n/**\n * Decodes a querystring (e.g. ?arg=val&arg2=val2) into a params object\n * (e.g. {arg: 'val', arg2: 'val2'})\n */\nfunction querystringDecode(querystring) {\n const obj = {};\n const tokens = querystring.replace(/^\\?/, '').split('&');\n tokens.forEach(token => {\n if (token) {\n const [key, value] = token.split('=');\n obj[decodeURIComponent(key)] = decodeURIComponent(value);\n }\n });\n return obj;\n}\n/**\n * Extract the query string part of a URL, including the leading question mark (if present).\n */\nfunction extractQuerystring(url) {\n const queryStart = url.indexOf('?');\n if (!queryStart) {\n return '';\n }\n const fragmentStart = url.indexOf('#', queryStart);\n return url.substring(queryStart, fragmentStart > 0 ? fragmentStart : undefined);\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * @fileoverview SHA-1 cryptographic hash.\n * Variable names follow the notation in FIPS PUB 180-3:\n * http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.\n *\n * Usage:\n * var sha1 = new sha1();\n * sha1.update(bytes);\n * var hash = sha1.digest();\n *\n * Performance:\n * Chrome 23: ~400 Mbit/s\n * Firefox 16: ~250 Mbit/s\n *\n */\n/**\n * SHA-1 cryptographic hash constructor.\n *\n * The properties declared here are discussed in the above algorithm document.\n * @constructor\n * @final\n * @struct\n */\nclass Sha1 {\n constructor() {\n /**\n * Holds the previous values of accumulated variables a-e in the compress_\n * function.\n * @private\n */\n this.chain_ = [];\n /**\n * A buffer holding the partially computed hash result.\n * @private\n */\n this.buf_ = [];\n /**\n * An array of 80 bytes, each a part of the message to be hashed. Referred to\n * as the message schedule in the docs.\n * @private\n */\n this.W_ = [];\n /**\n * Contains data needed to pad messages less than 64 bytes.\n * @private\n */\n this.pad_ = [];\n /**\n * @private {number}\n */\n this.inbuf_ = 0;\n /**\n * @private {number}\n */\n this.total_ = 0;\n this.blockSize = 512 / 8;\n this.pad_[0] = 128;\n for (let i = 1; i < this.blockSize; ++i) {\n this.pad_[i] = 0;\n }\n this.reset();\n }\n reset() {\n this.chain_[0] = 0x67452301;\n this.chain_[1] = 0xefcdab89;\n this.chain_[2] = 0x98badcfe;\n this.chain_[3] = 0x10325476;\n this.chain_[4] = 0xc3d2e1f0;\n this.inbuf_ = 0;\n this.total_ = 0;\n }\n /**\n * Internal compress helper function.\n * @param buf Block to compress.\n * @param offset Offset of the block in the buffer.\n * @private\n */\n compress_(buf, offset) {\n if (!offset) {\n offset = 0;\n }\n const W = this.W_;\n // get 16 big endian words\n if (typeof buf === 'string') {\n for (let i = 0; i < 16; i++) {\n // TODO(user): [bug 8140122] Recent versions of Safari for Mac OS and iOS\n // have a bug that turns the post-increment ++ operator into pre-increment\n // during JIT compilation. We have code that depends heavily on SHA-1 for\n // correctness and which is affected by this bug, so I've removed all uses\n // of post-increment ++ in which the result value is used. We can revert\n // this change once the Safari bug\n // (https://bugs.webkit.org/show_bug.cgi?id=109036) has been fixed and\n // most clients have been updated.\n W[i] =\n (buf.charCodeAt(offset) << 24) |\n (buf.charCodeAt(offset + 1) << 16) |\n (buf.charCodeAt(offset + 2) << 8) |\n buf.charCodeAt(offset + 3);\n offset += 4;\n }\n }\n else {\n for (let i = 0; i < 16; i++) {\n W[i] =\n (buf[offset] << 24) |\n (buf[offset + 1] << 16) |\n (buf[offset + 2] << 8) |\n buf[offset + 3];\n offset += 4;\n }\n }\n // expand to 80 words\n for (let i = 16; i < 80; i++) {\n const t = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];\n W[i] = ((t << 1) | (t >>> 31)) & 0xffffffff;\n }\n let a = this.chain_[0];\n let b = this.chain_[1];\n let c = this.chain_[2];\n let d = this.chain_[3];\n let e = this.chain_[4];\n let f, k;\n // TODO(user): Try to unroll this loop to speed up the computation.\n for (let i = 0; i < 80; i++) {\n if (i < 40) {\n if (i < 20) {\n f = d ^ (b & (c ^ d));\n k = 0x5a827999;\n }\n else {\n f = b ^ c ^ d;\n k = 0x6ed9eba1;\n }\n }\n else {\n if (i < 60) {\n f = (b & c) | (d & (b | c));\n k = 0x8f1bbcdc;\n }\n else {\n f = b ^ c ^ d;\n k = 0xca62c1d6;\n }\n }\n const t = (((a << 5) | (a >>> 27)) + f + e + k + W[i]) & 0xffffffff;\n e = d;\n d = c;\n c = ((b << 30) | (b >>> 2)) & 0xffffffff;\n b = a;\n a = t;\n }\n this.chain_[0] = (this.chain_[0] + a) & 0xffffffff;\n this.chain_[1] = (this.chain_[1] + b) & 0xffffffff;\n this.chain_[2] = (this.chain_[2] + c) & 0xffffffff;\n this.chain_[3] = (this.chain_[3] + d) & 0xffffffff;\n this.chain_[4] = (this.chain_[4] + e) & 0xffffffff;\n }\n update(bytes, length) {\n // TODO(johnlenz): tighten the function signature and remove this check\n if (bytes == null) {\n return;\n }\n if (length === undefined) {\n length = bytes.length;\n }\n const lengthMinusBlock = length - this.blockSize;\n let n = 0;\n // Using local instead of member variables gives ~5% speedup on Firefox 16.\n const buf = this.buf_;\n let inbuf = this.inbuf_;\n // The outer while loop should execute at most twice.\n while (n < length) {\n // When we have no data in the block to top up, we can directly process the\n // input buffer (assuming it contains sufficient data). This gives ~25%\n // speedup on Chrome 23 and ~15% speedup on Firefox 16, but requires that\n // the data is provided in large chunks (or in multiples of 64 bytes).\n if (inbuf === 0) {\n while (n <= lengthMinusBlock) {\n this.compress_(bytes, n);\n n += this.blockSize;\n }\n }\n if (typeof bytes === 'string') {\n while (n < length) {\n buf[inbuf] = bytes.charCodeAt(n);\n ++inbuf;\n ++n;\n if (inbuf === this.blockSize) {\n this.compress_(buf);\n inbuf = 0;\n // Jump to the outer loop so we use the full-block optimization.\n break;\n }\n }\n }\n else {\n while (n < length) {\n buf[inbuf] = bytes[n];\n ++inbuf;\n ++n;\n if (inbuf === this.blockSize) {\n this.compress_(buf);\n inbuf = 0;\n // Jump to the outer loop so we use the full-block optimization.\n break;\n }\n }\n }\n }\n this.inbuf_ = inbuf;\n this.total_ += length;\n }\n /** @override */\n digest() {\n const digest = [];\n let totalBits = this.total_ * 8;\n // Add pad 0x80 0x00*.\n if (this.inbuf_ < 56) {\n this.update(this.pad_, 56 - this.inbuf_);\n }\n else {\n this.update(this.pad_, this.blockSize - (this.inbuf_ - 56));\n }\n // Add # bits.\n for (let i = this.blockSize - 1; i >= 56; i--) {\n this.buf_[i] = totalBits & 255;\n totalBits /= 256; // Don't use bit-shifting here!\n }\n this.compress_(this.buf_);\n let n = 0;\n for (let i = 0; i < 5; i++) {\n for (let j = 24; j >= 0; j -= 8) {\n digest[n] = (this.chain_[i] >> j) & 255;\n ++n;\n }\n }\n return digest;\n }\n}\n\n/**\n * Helper to make a Subscribe function (just like Promise helps make a\n * Thenable).\n *\n * @param executor Function which can make calls to a single Observer\n * as a proxy.\n * @param onNoObservers Callback when count of Observers goes to zero.\n */\nfunction createSubscribe(executor, onNoObservers) {\n const proxy = new ObserverProxy(executor, onNoObservers);\n return proxy.subscribe.bind(proxy);\n}\n/**\n * Implement fan-out for any number of Observers attached via a subscribe\n * function.\n */\nclass ObserverProxy {\n /**\n * @param executor Function which can make calls to a single Observer\n * as a proxy.\n * @param onNoObservers Callback when count of Observers goes to zero.\n */\n constructor(executor, onNoObservers) {\n this.observers = [];\n this.unsubscribes = [];\n this.observerCount = 0;\n // Micro-task scheduling by calling task.then().\n this.task = Promise.resolve();\n this.finalized = false;\n this.onNoObservers = onNoObservers;\n // Call the executor asynchronously so subscribers that are called\n // synchronously after the creation of the subscribe function\n // can still receive the very first value generated in the executor.\n this.task\n .then(() => {\n executor(this);\n })\n .catch(e => {\n this.error(e);\n });\n }\n next(value) {\n this.forEachObserver((observer) => {\n observer.next(value);\n });\n }\n error(error) {\n this.forEachObserver((observer) => {\n observer.error(error);\n });\n this.close(error);\n }\n complete() {\n this.forEachObserver((observer) => {\n observer.complete();\n });\n this.close();\n }\n /**\n * Subscribe function that can be used to add an Observer to the fan-out list.\n *\n * - We require that no event is sent to a subscriber synchronously to their\n * call to subscribe().\n */\n subscribe(nextOrObserver, error, complete) {\n let observer;\n if (nextOrObserver === undefined &&\n error === undefined &&\n complete === undefined) {\n throw new Error('Missing Observer.');\n }\n // Assemble an Observer object when passed as callback functions.\n if (implementsAnyMethods(nextOrObserver, [\n 'next',\n 'error',\n 'complete'\n ])) {\n observer = nextOrObserver;\n }\n else {\n observer = {\n next: nextOrObserver,\n error,\n complete\n };\n }\n if (observer.next === undefined) {\n observer.next = noop;\n }\n if (observer.error === undefined) {\n observer.error = noop;\n }\n if (observer.complete === undefined) {\n observer.complete = noop;\n }\n const unsub = this.unsubscribeOne.bind(this, this.observers.length);\n // Attempt to subscribe to a terminated Observable - we\n // just respond to the Observer with the final error or complete\n // event.\n if (this.finalized) {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.task.then(() => {\n try {\n if (this.finalError) {\n observer.error(this.finalError);\n }\n else {\n observer.complete();\n }\n }\n catch (e) {\n // nothing\n }\n return;\n });\n }\n this.observers.push(observer);\n return unsub;\n }\n // Unsubscribe is synchronous - we guarantee that no events are sent to\n // any unsubscribed Observer.\n unsubscribeOne(i) {\n if (this.observers === undefined || this.observers[i] === undefined) {\n return;\n }\n delete this.observers[i];\n this.observerCount -= 1;\n if (this.observerCount === 0 && this.onNoObservers !== undefined) {\n this.onNoObservers(this);\n }\n }\n forEachObserver(fn) {\n if (this.finalized) {\n // Already closed by previous event....just eat the additional values.\n return;\n }\n // Since sendOne calls asynchronously - there is no chance that\n // this.observers will become undefined.\n for (let i = 0; i < this.observers.length; i++) {\n this.sendOne(i, fn);\n }\n }\n // Call the Observer via one of it's callback function. We are careful to\n // confirm that the observe has not been unsubscribed since this asynchronous\n // function had been queued.\n sendOne(i, fn) {\n // Execute the callback asynchronously\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.task.then(() => {\n if (this.observers !== undefined && this.observers[i] !== undefined) {\n try {\n fn(this.observers[i]);\n }\n catch (e) {\n // Ignore exceptions raised in Observers or missing methods of an\n // Observer.\n // Log error to console. b/31404806\n if (typeof console !== 'undefined' && console.error) {\n console.error(e);\n }\n }\n }\n });\n }\n close(err) {\n if (this.finalized) {\n return;\n }\n this.finalized = true;\n if (err !== undefined) {\n this.finalError = err;\n }\n // Proxy is no longer needed - garbage collect references\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.task.then(() => {\n this.observers = undefined;\n this.onNoObservers = undefined;\n });\n }\n}\n/** Turn synchronous function into one called asynchronously. */\n// eslint-disable-next-line @typescript-eslint/ban-types\nfunction async(fn, onError) {\n return (...args) => {\n Promise.resolve(true)\n .then(() => {\n fn(...args);\n })\n .catch((error) => {\n if (onError) {\n onError(error);\n }\n });\n };\n}\n/**\n * Return true if the object passed in implements any of the named methods.\n */\nfunction implementsAnyMethods(obj, methods) {\n if (typeof obj !== 'object' || obj === null) {\n return false;\n }\n for (const method of methods) {\n if (method in obj && typeof obj[method] === 'function') {\n return true;\n }\n }\n return false;\n}\nfunction noop() {\n // do nothing\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Check to make sure the appropriate number of arguments are provided for a public function.\n * Throws an error if it fails.\n *\n * @param fnName The function name\n * @param minCount The minimum number of arguments to allow for the function call\n * @param maxCount The maximum number of argument to allow for the function call\n * @param argCount The actual number of arguments provided.\n */\nconst validateArgCount = function (fnName, minCount, maxCount, argCount) {\n let argError;\n if (argCount < minCount) {\n argError = 'at least ' + minCount;\n }\n else if (argCount > maxCount) {\n argError = maxCount === 0 ? 'none' : 'no more than ' + maxCount;\n }\n if (argError) {\n const error = fnName +\n ' failed: Was called with ' +\n argCount +\n (argCount === 1 ? ' argument.' : ' arguments.') +\n ' Expects ' +\n argError +\n '.';\n throw new Error(error);\n }\n};\n/**\n * Generates a string to prefix an error message about failed argument validation\n *\n * @param fnName The function name\n * @param argName The name of the argument\n * @return The prefix to add to the error thrown for validation.\n */\nfunction errorPrefix(fnName, argName) {\n return `${fnName} failed: ${argName} argument `;\n}\n/**\n * @param fnName\n * @param argumentNumber\n * @param namespace\n * @param optional\n */\nfunction validateNamespace(fnName, namespace, optional) {\n if (optional && !namespace) {\n return;\n }\n if (typeof namespace !== 'string') {\n //TODO: I should do more validation here. We only allow certain chars in namespaces.\n throw new Error(errorPrefix(fnName, 'namespace') + 'must be a valid firebase namespace.');\n }\n}\nfunction validateCallback(fnName, argumentName, \n// eslint-disable-next-line @typescript-eslint/ban-types\ncallback, optional) {\n if (optional && !callback) {\n return;\n }\n if (typeof callback !== 'function') {\n throw new Error(errorPrefix(fnName, argumentName) + 'must be a valid function.');\n }\n}\nfunction validateContextObject(fnName, argumentName, context, optional) {\n if (optional && !context) {\n return;\n }\n if (typeof context !== 'object' || context === null) {\n throw new Error(errorPrefix(fnName, argumentName) + 'must be a valid context object.');\n }\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// Code originally came from goog.crypt.stringToUtf8ByteArray, but for some reason they\n// automatically replaced '\\r\\n' with '\\n', and they didn't handle surrogate pairs,\n// so it's been modified.\n// Note that not all Unicode characters appear as single characters in JavaScript strings.\n// fromCharCode returns the UTF-16 encoding of a character - so some Unicode characters\n// use 2 characters in JavaScript. All 4-byte UTF-8 characters begin with a first\n// character in the range 0xD800 - 0xDBFF (the first character of a so-called surrogate\n// pair).\n// See http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3\n/**\n * @param {string} str\n * @return {Array}\n */\nconst stringToByteArray = function (str) {\n const out = [];\n let p = 0;\n for (let i = 0; i < str.length; i++) {\n let c = str.charCodeAt(i);\n // Is this the lead surrogate in a surrogate pair?\n if (c >= 0xd800 && c <= 0xdbff) {\n const high = c - 0xd800; // the high 10 bits.\n i++;\n assert(i < str.length, 'Surrogate pair missing trail surrogate.');\n const low = str.charCodeAt(i) - 0xdc00; // the low 10 bits.\n c = 0x10000 + (high << 10) + low;\n }\n if (c < 128) {\n out[p++] = c;\n }\n else if (c < 2048) {\n out[p++] = (c >> 6) | 192;\n out[p++] = (c & 63) | 128;\n }\n else if (c < 65536) {\n out[p++] = (c >> 12) | 224;\n out[p++] = ((c >> 6) & 63) | 128;\n out[p++] = (c & 63) | 128;\n }\n else {\n out[p++] = (c >> 18) | 240;\n out[p++] = ((c >> 12) & 63) | 128;\n out[p++] = ((c >> 6) & 63) | 128;\n out[p++] = (c & 63) | 128;\n }\n }\n return out;\n};\n/**\n * Calculate length without actually converting; useful for doing cheaper validation.\n * @param {string} str\n * @return {number}\n */\nconst stringLength = function (str) {\n let p = 0;\n for (let i = 0; i < str.length; i++) {\n const c = str.charCodeAt(i);\n if (c < 128) {\n p++;\n }\n else if (c < 2048) {\n p += 2;\n }\n else if (c >= 0xd800 && c <= 0xdbff) {\n // Lead surrogate of a surrogate pair. The pair together will take 4 bytes to represent.\n p += 4;\n i++; // skip trail surrogate.\n }\n else {\n p += 3;\n }\n }\n return p;\n};\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * The amount of milliseconds to exponentially increase.\n */\nconst DEFAULT_INTERVAL_MILLIS = 1000;\n/**\n * The factor to backoff by.\n * Should be a number greater than 1.\n */\nconst DEFAULT_BACKOFF_FACTOR = 2;\n/**\n * The maximum milliseconds to increase to.\n *\n * Visible for testing\n */\nconst MAX_VALUE_MILLIS = 4 * 60 * 60 * 1000; // Four hours, like iOS and Android.\n/**\n * The percentage of backoff time to randomize by.\n * See\n * http://go/safe-client-behavior#step-1-determine-the-appropriate-retry-interval-to-handle-spike-traffic\n * for context.\n *\n *
Visible for testing\n */\nconst RANDOM_FACTOR = 0.5;\n/**\n * Based on the backoff method from\n * https://github.com/google/closure-library/blob/master/closure/goog/math/exponentialbackoff.js.\n * Extracted here so we don't need to pass metadata and a stateful ExponentialBackoff object around.\n */\nfunction calculateBackoffMillis(backoffCount, intervalMillis = DEFAULT_INTERVAL_MILLIS, backoffFactor = DEFAULT_BACKOFF_FACTOR) {\n // Calculates an exponentially increasing value.\n // Deviation: calculates value from count and a constant interval, so we only need to save value\n // and count to restore state.\n const currBaseValue = intervalMillis * Math.pow(backoffFactor, backoffCount);\n // A random \"fuzz\" to avoid waves of retries.\n // Deviation: randomFactor is required.\n const randomWait = Math.round(\n // A fraction of the backoff value to add/subtract.\n // Deviation: changes multiplication order to improve readability.\n RANDOM_FACTOR *\n currBaseValue *\n // A random float (rounded to int by Math.round above) in the range [-1, 1]. Determines\n // if we add or subtract.\n (Math.random() - 0.5) *\n 2);\n // Limits backoff to max to avoid effectively permanent backoff.\n return Math.min(MAX_VALUE_MILLIS, currBaseValue + randomWait);\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Provide English ordinal letters after a number\n */\nfunction ordinal(i) {\n if (!Number.isFinite(i)) {\n return `${i}`;\n }\n return i + indicator(i);\n}\nfunction indicator(i) {\n i = Math.abs(i);\n const cent = i % 100;\n if (cent >= 10 && cent <= 20) {\n return 'th';\n }\n const dec = i % 10;\n if (dec === 1) {\n return 'st';\n }\n if (dec === 2) {\n return 'nd';\n }\n if (dec === 3) {\n return 'rd';\n }\n return 'th';\n}\n\n/**\n * @license\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction getModularInstance(service) {\n if (service && service._delegate) {\n return service._delegate;\n }\n else {\n return service;\n }\n}\n\nexport { CONSTANTS, DecodeBase64StringError, Deferred, ErrorFactory, FirebaseError, MAX_VALUE_MILLIS, RANDOM_FACTOR, Sha1, areCookiesEnabled, assert, assertionError, async, base64, base64Decode, base64Encode, base64urlEncodeWithoutPadding, calculateBackoffMillis, contains, createMockUserToken, createSubscribe, decode, deepCopy, deepEqual, deepExtend, errorPrefix, extractQuerystring, getDefaultAppConfig, getDefaultEmulatorHost, getDefaultEmulatorHostnameAndPort, getDefaults, getExperimentalSetting, getGlobal, getModularInstance, getUA, isAdmin, isBrowser, isBrowserExtension, isCloudWorkstation, isCloudflareWorker, isElectron, isEmpty, isIE, isIndexedDBAvailable, isMobileCordova, isNode, isNodeSdk, isReactNative, isSafari, isSafariOrWebkit, isUWP, isValidFormat, isValidTimestamp, isWebWorker, issuedAtTime, jsonEval, map, ordinal, pingServer, promiseWithTimeout, querystring, querystringDecode, safeGet, stringLength, stringToByteArray, stringify, updateEmulatorBanner, validateArgCount, validateCallback, validateContextObject, validateIndexedDBOpenable, validateNamespace };\n//# sourceMappingURL=index.esm2017.js.map\n","import { Deferred } from '@firebase/util';\n\n/**\n * Component for service name T, e.g. `auth`, `auth-internal`\n */\nclass Component {\n /**\n *\n * @param name The public service name, e.g. app, auth, firestore, database\n * @param instanceFactory Service factory responsible for creating the public interface\n * @param type whether the service provided by the component is public or private\n */\n constructor(name, instanceFactory, type) {\n this.name = name;\n this.instanceFactory = instanceFactory;\n this.type = type;\n this.multipleInstances = false;\n /**\n * Properties to be added to the service namespace\n */\n this.serviceProps = {};\n this.instantiationMode = \"LAZY\" /* InstantiationMode.LAZY */;\n this.onInstanceCreated = null;\n }\n setInstantiationMode(mode) {\n this.instantiationMode = mode;\n return this;\n }\n setMultipleInstances(multipleInstances) {\n this.multipleInstances = multipleInstances;\n return this;\n }\n setServiceProps(props) {\n this.serviceProps = props;\n return this;\n }\n setInstanceCreatedCallback(callback) {\n this.onInstanceCreated = callback;\n return this;\n }\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst DEFAULT_ENTRY_NAME = '[DEFAULT]';\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Provider for instance for service name T, e.g. 'auth', 'auth-internal'\n * NameServiceMapping[T] is an alias for the type of the instance\n */\nclass Provider {\n constructor(name, container) {\n this.name = name;\n this.container = container;\n this.component = null;\n this.instances = new Map();\n this.instancesDeferred = new Map();\n this.instancesOptions = new Map();\n this.onInitCallbacks = new Map();\n }\n /**\n * @param identifier A provider can provide multiple instances of a service\n * if this.component.multipleInstances is true.\n */\n get(identifier) {\n // if multipleInstances is not supported, use the default name\n const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);\n if (!this.instancesDeferred.has(normalizedIdentifier)) {\n const deferred = new Deferred();\n this.instancesDeferred.set(normalizedIdentifier, deferred);\n if (this.isInitialized(normalizedIdentifier) ||\n this.shouldAutoInitialize()) {\n // initialize the service if it can be auto-initialized\n try {\n const instance = this.getOrInitializeService({\n instanceIdentifier: normalizedIdentifier\n });\n if (instance) {\n deferred.resolve(instance);\n }\n }\n catch (e) {\n // when the instance factory throws an exception during get(), it should not cause\n // a fatal error. We just return the unresolved promise in this case.\n }\n }\n }\n return this.instancesDeferred.get(normalizedIdentifier).promise;\n }\n getImmediate(options) {\n var _a;\n // if multipleInstances is not supported, use the default name\n const normalizedIdentifier = this.normalizeInstanceIdentifier(options === null || options === void 0 ? void 0 : options.identifier);\n const optional = (_a = options === null || options === void 0 ? void 0 : options.optional) !== null && _a !== void 0 ? _a : false;\n if (this.isInitialized(normalizedIdentifier) ||\n this.shouldAutoInitialize()) {\n try {\n return this.getOrInitializeService({\n instanceIdentifier: normalizedIdentifier\n });\n }\n catch (e) {\n if (optional) {\n return null;\n }\n else {\n throw e;\n }\n }\n }\n else {\n // In case a component is not initialized and should/cannot be auto-initialized at the moment, return null if the optional flag is set, or throw\n if (optional) {\n return null;\n }\n else {\n throw Error(`Service ${this.name} is not available`);\n }\n }\n }\n getComponent() {\n return this.component;\n }\n setComponent(component) {\n if (component.name !== this.name) {\n throw Error(`Mismatching Component ${component.name} for Provider ${this.name}.`);\n }\n if (this.component) {\n throw Error(`Component for ${this.name} has already been provided`);\n }\n this.component = component;\n // return early without attempting to initialize the component if the component requires explicit initialization (calling `Provider.initialize()`)\n if (!this.shouldAutoInitialize()) {\n return;\n }\n // if the service is eager, initialize the default instance\n if (isComponentEager(component)) {\n try {\n this.getOrInitializeService({ instanceIdentifier: DEFAULT_ENTRY_NAME });\n }\n catch (e) {\n // when the instance factory for an eager Component throws an exception during the eager\n // initialization, it should not cause a fatal error.\n // TODO: Investigate if we need to make it configurable, because some component may want to cause\n // a fatal error in this case?\n }\n }\n // Create service instances for the pending promises and resolve them\n // NOTE: if this.multipleInstances is false, only the default instance will be created\n // and all promises with resolve with it regardless of the identifier.\n for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {\n const normalizedIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);\n try {\n // `getOrInitializeService()` should always return a valid instance since a component is guaranteed. use ! to make typescript happy.\n const instance = this.getOrInitializeService({\n instanceIdentifier: normalizedIdentifier\n });\n instanceDeferred.resolve(instance);\n }\n catch (e) {\n // when the instance factory throws an exception, it should not cause\n // a fatal error. We just leave the promise unresolved.\n }\n }\n }\n clearInstance(identifier = DEFAULT_ENTRY_NAME) {\n this.instancesDeferred.delete(identifier);\n this.instancesOptions.delete(identifier);\n this.instances.delete(identifier);\n }\n // app.delete() will call this method on every provider to delete the services\n // TODO: should we mark the provider as deleted?\n async delete() {\n const services = Array.from(this.instances.values());\n await Promise.all([\n ...services\n .filter(service => 'INTERNAL' in service) // legacy services\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n .map(service => service.INTERNAL.delete()),\n ...services\n .filter(service => '_delete' in service) // modularized services\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n .map(service => service._delete())\n ]);\n }\n isComponentSet() {\n return this.component != null;\n }\n isInitialized(identifier = DEFAULT_ENTRY_NAME) {\n return this.instances.has(identifier);\n }\n getOptions(identifier = DEFAULT_ENTRY_NAME) {\n return this.instancesOptions.get(identifier) || {};\n }\n initialize(opts = {}) {\n const { options = {} } = opts;\n const normalizedIdentifier = this.normalizeInstanceIdentifier(opts.instanceIdentifier);\n if (this.isInitialized(normalizedIdentifier)) {\n throw Error(`${this.name}(${normalizedIdentifier}) has already been initialized`);\n }\n if (!this.isComponentSet()) {\n throw Error(`Component ${this.name} has not been registered yet`);\n }\n const instance = this.getOrInitializeService({\n instanceIdentifier: normalizedIdentifier,\n options\n });\n // resolve any pending promise waiting for the service instance\n for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {\n const normalizedDeferredIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);\n if (normalizedIdentifier === normalizedDeferredIdentifier) {\n instanceDeferred.resolve(instance);\n }\n }\n return instance;\n }\n /**\n *\n * @param callback - a function that will be invoked after the provider has been initialized by calling provider.initialize().\n * The function is invoked SYNCHRONOUSLY, so it should not execute any longrunning tasks in order to not block the program.\n *\n * @param identifier An optional instance identifier\n * @returns a function to unregister the callback\n */\n onInit(callback, identifier) {\n var _a;\n const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);\n const existingCallbacks = (_a = this.onInitCallbacks.get(normalizedIdentifier)) !== null && _a !== void 0 ? _a : new Set();\n existingCallbacks.add(callback);\n this.onInitCallbacks.set(normalizedIdentifier, existingCallbacks);\n const existingInstance = this.instances.get(normalizedIdentifier);\n if (existingInstance) {\n callback(existingInstance, normalizedIdentifier);\n }\n return () => {\n existingCallbacks.delete(callback);\n };\n }\n /**\n * Invoke onInit callbacks synchronously\n * @param instance the service instance`\n */\n invokeOnInitCallbacks(instance, identifier) {\n const callbacks = this.onInitCallbacks.get(identifier);\n if (!callbacks) {\n return;\n }\n for (const callback of callbacks) {\n try {\n callback(instance, identifier);\n }\n catch (_a) {\n // ignore errors in the onInit callback\n }\n }\n }\n getOrInitializeService({ instanceIdentifier, options = {} }) {\n let instance = this.instances.get(instanceIdentifier);\n if (!instance && this.component) {\n instance = this.component.instanceFactory(this.container, {\n instanceIdentifier: normalizeIdentifierForFactory(instanceIdentifier),\n options\n });\n this.instances.set(instanceIdentifier, instance);\n this.instancesOptions.set(instanceIdentifier, options);\n /**\n * Invoke onInit listeners.\n * Note this.component.onInstanceCreated is different, which is used by the component creator,\n * while onInit listeners are registered by consumers of the provider.\n */\n this.invokeOnInitCallbacks(instance, instanceIdentifier);\n /**\n * Order is important\n * onInstanceCreated() should be called after this.instances.set(instanceIdentifier, instance); which\n * makes `isInitialized()` return true.\n */\n if (this.component.onInstanceCreated) {\n try {\n this.component.onInstanceCreated(this.container, instanceIdentifier, instance);\n }\n catch (_a) {\n // ignore errors in the onInstanceCreatedCallback\n }\n }\n }\n return instance || null;\n }\n normalizeInstanceIdentifier(identifier = DEFAULT_ENTRY_NAME) {\n if (this.component) {\n return this.component.multipleInstances ? identifier : DEFAULT_ENTRY_NAME;\n }\n else {\n return identifier; // assume multiple instances are supported before the component is provided.\n }\n }\n shouldAutoInitialize() {\n return (!!this.component &&\n this.component.instantiationMode !== \"EXPLICIT\" /* InstantiationMode.EXPLICIT */);\n }\n}\n// undefined should be passed to the service factory for the default instance\nfunction normalizeIdentifierForFactory(identifier) {\n return identifier === DEFAULT_ENTRY_NAME ? undefined : identifier;\n}\nfunction isComponentEager(component) {\n return component.instantiationMode === \"EAGER\" /* InstantiationMode.EAGER */;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * ComponentContainer that provides Providers for service name T, e.g. `auth`, `auth-internal`\n */\nclass ComponentContainer {\n constructor(name) {\n this.name = name;\n this.providers = new Map();\n }\n /**\n *\n * @param component Component being added\n * @param overwrite When a component with the same name has already been registered,\n * if overwrite is true: overwrite the existing component with the new component and create a new\n * provider with the new component. It can be useful in tests where you want to use different mocks\n * for different tests.\n * if overwrite is false: throw an exception\n */\n addComponent(component) {\n const provider = this.getProvider(component.name);\n if (provider.isComponentSet()) {\n throw new Error(`Component ${component.name} has already been registered with ${this.name}`);\n }\n provider.setComponent(component);\n }\n addOrOverwriteComponent(component) {\n const provider = this.getProvider(component.name);\n if (provider.isComponentSet()) {\n // delete the existing provider from the container, so we can register the new component\n this.providers.delete(component.name);\n }\n this.addComponent(component);\n }\n /**\n * getProvider provides a type safe interface where it can only be called with a field name\n * present in NameServiceMapping interface.\n *\n * Firebase SDKs providing services should extend NameServiceMapping interface to register\n * themselves.\n */\n getProvider(name) {\n if (this.providers.has(name)) {\n return this.providers.get(name);\n }\n // create a Provider for a service that hasn't registered with Firebase\n const provider = new Provider(name, this);\n this.providers.set(name, provider);\n return provider;\n }\n getProviders() {\n return Array.from(this.providers.values());\n }\n}\n\nexport { Component, ComponentContainer, Provider };\n//# sourceMappingURL=index.esm2017.js.map\n","/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * A container for all of the Logger instances\n */\nconst instances = [];\n/**\n * The JS SDK supports 5 log levels and also allows a user the ability to\n * silence the logs altogether.\n *\n * The order is a follows:\n * DEBUG < VERBOSE < INFO < WARN < ERROR\n *\n * All of the log types above the current log level will be captured (i.e. if\n * you set the log level to `INFO`, errors will still be logged, but `DEBUG` and\n * `VERBOSE` logs will not)\n */\nvar LogLevel;\n(function (LogLevel) {\n LogLevel[LogLevel[\"DEBUG\"] = 0] = \"DEBUG\";\n LogLevel[LogLevel[\"VERBOSE\"] = 1] = \"VERBOSE\";\n LogLevel[LogLevel[\"INFO\"] = 2] = \"INFO\";\n LogLevel[LogLevel[\"WARN\"] = 3] = \"WARN\";\n LogLevel[LogLevel[\"ERROR\"] = 4] = \"ERROR\";\n LogLevel[LogLevel[\"SILENT\"] = 5] = \"SILENT\";\n})(LogLevel || (LogLevel = {}));\nconst levelStringToEnum = {\n 'debug': LogLevel.DEBUG,\n 'verbose': LogLevel.VERBOSE,\n 'info': LogLevel.INFO,\n 'warn': LogLevel.WARN,\n 'error': LogLevel.ERROR,\n 'silent': LogLevel.SILENT\n};\n/**\n * The default log level\n */\nconst defaultLogLevel = LogLevel.INFO;\n/**\n * By default, `console.debug` is not displayed in the developer console (in\n * chrome). To avoid forcing users to have to opt-in to these logs twice\n * (i.e. once for firebase, and once in the console), we are sending `DEBUG`\n * logs to the `console.log` function.\n */\nconst ConsoleMethod = {\n [LogLevel.DEBUG]: 'log',\n [LogLevel.VERBOSE]: 'log',\n [LogLevel.INFO]: 'info',\n [LogLevel.WARN]: 'warn',\n [LogLevel.ERROR]: 'error'\n};\n/**\n * The default log handler will forward DEBUG, VERBOSE, INFO, WARN, and ERROR\n * messages on to their corresponding console counterparts (if the log method\n * is supported by the current log level)\n */\nconst defaultLogHandler = (instance, logType, ...args) => {\n if (logType < instance.logLevel) {\n return;\n }\n const now = new Date().toISOString();\n const method = ConsoleMethod[logType];\n if (method) {\n console[method](`[${now}] ${instance.name}:`, ...args);\n }\n else {\n throw new Error(`Attempted to log a message with an invalid logType (value: ${logType})`);\n }\n};\nclass Logger {\n /**\n * Gives you an instance of a Logger to capture messages according to\n * Firebase's logging scheme.\n *\n * @param name The name that the logs will be associated with\n */\n constructor(name) {\n this.name = name;\n /**\n * The log level of the given Logger instance.\n */\n this._logLevel = defaultLogLevel;\n /**\n * The main (internal) log handler for the Logger instance.\n * Can be set to a new function in internal package code but not by user.\n */\n this._logHandler = defaultLogHandler;\n /**\n * The optional, additional, user-defined log handler for the Logger instance.\n */\n this._userLogHandler = null;\n /**\n * Capture the current instance for later use\n */\n instances.push(this);\n }\n get logLevel() {\n return this._logLevel;\n }\n set logLevel(val) {\n if (!(val in LogLevel)) {\n throw new TypeError(`Invalid value \"${val}\" assigned to \\`logLevel\\``);\n }\n this._logLevel = val;\n }\n // Workaround for setter/getter having to be the same type.\n setLogLevel(val) {\n this._logLevel = typeof val === 'string' ? levelStringToEnum[val] : val;\n }\n get logHandler() {\n return this._logHandler;\n }\n set logHandler(val) {\n if (typeof val !== 'function') {\n throw new TypeError('Value assigned to `logHandler` must be a function');\n }\n this._logHandler = val;\n }\n get userLogHandler() {\n return this._userLogHandler;\n }\n set userLogHandler(val) {\n this._userLogHandler = val;\n }\n /**\n * The functions below are all based on the `console` interface\n */\n debug(...args) {\n this._userLogHandler && this._userLogHandler(this, LogLevel.DEBUG, ...args);\n this._logHandler(this, LogLevel.DEBUG, ...args);\n }\n log(...args) {\n this._userLogHandler &&\n this._userLogHandler(this, LogLevel.VERBOSE, ...args);\n this._logHandler(this, LogLevel.VERBOSE, ...args);\n }\n info(...args) {\n this._userLogHandler && this._userLogHandler(this, LogLevel.INFO, ...args);\n this._logHandler(this, LogLevel.INFO, ...args);\n }\n warn(...args) {\n this._userLogHandler && this._userLogHandler(this, LogLevel.WARN, ...args);\n this._logHandler(this, LogLevel.WARN, ...args);\n }\n error(...args) {\n this._userLogHandler && this._userLogHandler(this, LogLevel.ERROR, ...args);\n this._logHandler(this, LogLevel.ERROR, ...args);\n }\n}\nfunction setLogLevel(level) {\n instances.forEach(inst => {\n inst.setLogLevel(level);\n });\n}\nfunction setUserLogHandler(logCallback, options) {\n for (const instance of instances) {\n let customLogLevel = null;\n if (options && options.level) {\n customLogLevel = levelStringToEnum[options.level];\n }\n if (logCallback === null) {\n instance.userLogHandler = null;\n }\n else {\n instance.userLogHandler = (instance, level, ...args) => {\n const message = args\n .map(arg => {\n if (arg == null) {\n return null;\n }\n else if (typeof arg === 'string') {\n return arg;\n }\n else if (typeof arg === 'number' || typeof arg === 'boolean') {\n return arg.toString();\n }\n else if (arg instanceof Error) {\n return arg.message;\n }\n else {\n try {\n return JSON.stringify(arg);\n }\n catch (ignored) {\n return null;\n }\n }\n })\n .filter(arg => arg)\n .join(' ');\n if (level >= (customLogLevel !== null && customLogLevel !== void 0 ? customLogLevel : instance.logLevel)) {\n logCallback({\n level: LogLevel[level].toLowerCase(),\n message,\n args,\n type: instance.name\n });\n }\n };\n }\n }\n}\n\nexport { LogLevel, Logger, setLogLevel, setUserLogHandler };\n//# sourceMappingURL=index.esm2017.js.map\n","const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);\n\nlet idbProxyableTypes;\nlet cursorAdvanceMethods;\n// This is a function to prevent it throwing up in node environments.\nfunction getIdbProxyableTypes() {\n return (idbProxyableTypes ||\n (idbProxyableTypes = [\n IDBDatabase,\n IDBObjectStore,\n IDBIndex,\n IDBCursor,\n IDBTransaction,\n ]));\n}\n// This is a function to prevent it throwing up in node environments.\nfunction getCursorAdvanceMethods() {\n return (cursorAdvanceMethods ||\n (cursorAdvanceMethods = [\n IDBCursor.prototype.advance,\n IDBCursor.prototype.continue,\n IDBCursor.prototype.continuePrimaryKey,\n ]));\n}\nconst cursorRequestMap = new WeakMap();\nconst transactionDoneMap = new WeakMap();\nconst transactionStoreNamesMap = new WeakMap();\nconst transformCache = new WeakMap();\nconst reverseTransformCache = new WeakMap();\nfunction promisifyRequest(request) {\n const promise = new Promise((resolve, reject) => {\n const unlisten = () => {\n request.removeEventListener('success', success);\n request.removeEventListener('error', error);\n };\n const success = () => {\n resolve(wrap(request.result));\n unlisten();\n };\n const error = () => {\n reject(request.error);\n unlisten();\n };\n request.addEventListener('success', success);\n request.addEventListener('error', error);\n });\n promise\n .then((value) => {\n // Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval\n // (see wrapFunction).\n if (value instanceof IDBCursor) {\n cursorRequestMap.set(value, request);\n }\n // Catching to avoid \"Uncaught Promise exceptions\"\n })\n .catch(() => { });\n // This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This\n // is because we create many promises from a single IDBRequest.\n reverseTransformCache.set(promise, request);\n return promise;\n}\nfunction cacheDonePromiseForTransaction(tx) {\n // Early bail if we've already created a done promise for this transaction.\n if (transactionDoneMap.has(tx))\n return;\n const done = new Promise((resolve, reject) => {\n const unlisten = () => {\n tx.removeEventListener('complete', complete);\n tx.removeEventListener('error', error);\n tx.removeEventListener('abort', error);\n };\n const complete = () => {\n resolve();\n unlisten();\n };\n const error = () => {\n reject(tx.error || new DOMException('AbortError', 'AbortError'));\n unlisten();\n };\n tx.addEventListener('complete', complete);\n tx.addEventListener('error', error);\n tx.addEventListener('abort', error);\n });\n // Cache it for later retrieval.\n transactionDoneMap.set(tx, done);\n}\nlet idbProxyTraps = {\n get(target, prop, receiver) {\n if (target instanceof IDBTransaction) {\n // Special handling for transaction.done.\n if (prop === 'done')\n return transactionDoneMap.get(target);\n // Polyfill for objectStoreNames because of Edge.\n if (prop === 'objectStoreNames') {\n return target.objectStoreNames || transactionStoreNamesMap.get(target);\n }\n // Make tx.store return the only store in the transaction, or undefined if there are many.\n if (prop === 'store') {\n return receiver.objectStoreNames[1]\n ? undefined\n : receiver.objectStore(receiver.objectStoreNames[0]);\n }\n }\n // Else transform whatever we get back.\n return wrap(target[prop]);\n },\n set(target, prop, value) {\n target[prop] = value;\n return true;\n },\n has(target, prop) {\n if (target instanceof IDBTransaction &&\n (prop === 'done' || prop === 'store')) {\n return true;\n }\n return prop in target;\n },\n};\nfunction replaceTraps(callback) {\n idbProxyTraps = callback(idbProxyTraps);\n}\nfunction wrapFunction(func) {\n // Due to expected object equality (which is enforced by the caching in `wrap`), we\n // only create one new func per func.\n // Edge doesn't support objectStoreNames (booo), so we polyfill it here.\n if (func === IDBDatabase.prototype.transaction &&\n !('objectStoreNames' in IDBTransaction.prototype)) {\n return function (storeNames, ...args) {\n const tx = func.call(unwrap(this), storeNames, ...args);\n transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);\n return wrap(tx);\n };\n }\n // Cursor methods are special, as the behaviour is a little more different to standard IDB. In\n // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the\n // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense\n // with real promises, so each advance methods returns a new promise for the cursor object, or\n // undefined if the end of the cursor has been reached.\n if (getCursorAdvanceMethods().includes(func)) {\n return function (...args) {\n // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n // the original object.\n func.apply(unwrap(this), args);\n return wrap(cursorRequestMap.get(this));\n };\n }\n return function (...args) {\n // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n // the original object.\n return wrap(func.apply(unwrap(this), args));\n };\n}\nfunction transformCachableValue(value) {\n if (typeof value === 'function')\n return wrapFunction(value);\n // This doesn't return, it just creates a 'done' promise for the transaction,\n // which is later returned for transaction.done (see idbObjectHandler).\n if (value instanceof IDBTransaction)\n cacheDonePromiseForTransaction(value);\n if (instanceOfAny(value, getIdbProxyableTypes()))\n return new Proxy(value, idbProxyTraps);\n // Return the same value back if we're not going to transform it.\n return value;\n}\nfunction wrap(value) {\n // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because\n // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.\n if (value instanceof IDBRequest)\n return promisifyRequest(value);\n // If we've already transformed this value before, reuse the transformed value.\n // This is faster, but it also provides object equality.\n if (transformCache.has(value))\n return transformCache.get(value);\n const newValue = transformCachableValue(value);\n // Not all types are transformed.\n // These may be primitive types, so they can't be WeakMap keys.\n if (newValue !== value) {\n transformCache.set(value, newValue);\n reverseTransformCache.set(newValue, value);\n }\n return newValue;\n}\nconst unwrap = (value) => reverseTransformCache.get(value);\n\nexport { reverseTransformCache as a, instanceOfAny as i, replaceTraps as r, unwrap as u, wrap as w };\n","import { w as wrap, r as replaceTraps } from './wrap-idb-value.js';\nexport { u as unwrap, w as wrap } from './wrap-idb-value.js';\n\n/**\n * Open a database.\n *\n * @param name Name of the database.\n * @param version Schema version.\n * @param callbacks Additional callbacks.\n */\nfunction openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {\n const request = indexedDB.open(name, version);\n const openPromise = wrap(request);\n if (upgrade) {\n request.addEventListener('upgradeneeded', (event) => {\n upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);\n });\n }\n if (blocked) {\n request.addEventListener('blocked', (event) => blocked(\n // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n event.oldVersion, event.newVersion, event));\n }\n openPromise\n .then((db) => {\n if (terminated)\n db.addEventListener('close', () => terminated());\n if (blocking) {\n db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));\n }\n })\n .catch(() => { });\n return openPromise;\n}\n/**\n * Delete a database.\n *\n * @param name Name of the database.\n */\nfunction deleteDB(name, { blocked } = {}) {\n const request = indexedDB.deleteDatabase(name);\n if (blocked) {\n request.addEventListener('blocked', (event) => blocked(\n // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n event.oldVersion, event));\n }\n return wrap(request).then(() => undefined);\n}\n\nconst readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];\nconst writeMethods = ['put', 'add', 'delete', 'clear'];\nconst cachedMethods = new Map();\nfunction getMethod(target, prop) {\n if (!(target instanceof IDBDatabase &&\n !(prop in target) &&\n typeof prop === 'string')) {\n return;\n }\n if (cachedMethods.get(prop))\n return cachedMethods.get(prop);\n const targetFuncName = prop.replace(/FromIndex$/, '');\n const useIndex = prop !== targetFuncName;\n const isWrite = writeMethods.includes(targetFuncName);\n if (\n // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.\n !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||\n !(isWrite || readMethods.includes(targetFuncName))) {\n return;\n }\n const method = async function (storeName, ...args) {\n // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(\n const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');\n let target = tx.store;\n if (useIndex)\n target = target.index(args.shift());\n // Must reject if op rejects.\n // If it's a write operation, must reject if tx.done rejects.\n // Must reject with op rejection first.\n // Must resolve with op value.\n // Must handle both promises (no unhandled rejections)\n return (await Promise.all([\n target[targetFuncName](...args),\n isWrite && tx.done,\n ]))[0];\n };\n cachedMethods.set(prop, method);\n return method;\n}\nreplaceTraps((oldTraps) => ({\n ...oldTraps,\n get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),\n has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),\n}));\n\nexport { deleteDB, openDB };\n","import { Component, ComponentContainer } from '@firebase/component';\nimport { Logger, setUserLogHandler, setLogLevel as setLogLevel$1 } from '@firebase/logger';\nimport { ErrorFactory, base64Decode, getDefaultAppConfig, deepEqual, isBrowser, isWebWorker, FirebaseError, base64urlEncodeWithoutPadding, isIndexedDBAvailable, validateIndexedDBOpenable } from '@firebase/util';\nexport { FirebaseError } from '@firebase/util';\nimport { openDB } from 'idb';\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nclass PlatformLoggerServiceImpl {\n constructor(container) {\n this.container = container;\n }\n // In initial implementation, this will be called by installations on\n // auth token refresh, and installations will send this string.\n getPlatformInfoString() {\n const providers = this.container.getProviders();\n // Loop through providers and get library/version pairs from any that are\n // version components.\n return providers\n .map(provider => {\n if (isVersionServiceProvider(provider)) {\n const service = provider.getImmediate();\n return `${service.library}/${service.version}`;\n }\n else {\n return null;\n }\n })\n .filter(logString => logString)\n .join(' ');\n }\n}\n/**\n *\n * @param provider check if this provider provides a VersionService\n *\n * NOTE: Using Provider<'app-version'> is a hack to indicate that the provider\n * provides VersionService. The provider is not necessarily a 'app-version'\n * provider.\n */\nfunction isVersionServiceProvider(provider) {\n const component = provider.getComponent();\n return (component === null || component === void 0 ? void 0 : component.type) === \"VERSION\" /* ComponentType.VERSION */;\n}\n\nconst name$q = \"@firebase/app\";\nconst version$1 = \"0.13.2\";\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst logger = new Logger('@firebase/app');\n\nconst name$p = \"@firebase/app-compat\";\n\nconst name$o = \"@firebase/analytics-compat\";\n\nconst name$n = \"@firebase/analytics\";\n\nconst name$m = \"@firebase/app-check-compat\";\n\nconst name$l = \"@firebase/app-check\";\n\nconst name$k = \"@firebase/auth\";\n\nconst name$j = \"@firebase/auth-compat\";\n\nconst name$i = \"@firebase/database\";\n\nconst name$h = \"@firebase/data-connect\";\n\nconst name$g = \"@firebase/database-compat\";\n\nconst name$f = \"@firebase/functions\";\n\nconst name$e = \"@firebase/functions-compat\";\n\nconst name$d = \"@firebase/installations\";\n\nconst name$c = \"@firebase/installations-compat\";\n\nconst name$b = \"@firebase/messaging\";\n\nconst name$a = \"@firebase/messaging-compat\";\n\nconst name$9 = \"@firebase/performance\";\n\nconst name$8 = \"@firebase/performance-compat\";\n\nconst name$7 = \"@firebase/remote-config\";\n\nconst name$6 = \"@firebase/remote-config-compat\";\n\nconst name$5 = \"@firebase/storage\";\n\nconst name$4 = \"@firebase/storage-compat\";\n\nconst name$3 = \"@firebase/firestore\";\n\nconst name$2 = \"@firebase/ai\";\n\nconst name$1 = \"@firebase/firestore-compat\";\n\nconst name = \"firebase\";\nconst version = \"11.10.0\";\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * The default app name\n *\n * @internal\n */\nconst DEFAULT_ENTRY_NAME = '[DEFAULT]';\nconst PLATFORM_LOG_STRING = {\n [name$q]: 'fire-core',\n [name$p]: 'fire-core-compat',\n [name$n]: 'fire-analytics',\n [name$o]: 'fire-analytics-compat',\n [name$l]: 'fire-app-check',\n [name$m]: 'fire-app-check-compat',\n [name$k]: 'fire-auth',\n [name$j]: 'fire-auth-compat',\n [name$i]: 'fire-rtdb',\n [name$h]: 'fire-data-connect',\n [name$g]: 'fire-rtdb-compat',\n [name$f]: 'fire-fn',\n [name$e]: 'fire-fn-compat',\n [name$d]: 'fire-iid',\n [name$c]: 'fire-iid-compat',\n [name$b]: 'fire-fcm',\n [name$a]: 'fire-fcm-compat',\n [name$9]: 'fire-perf',\n [name$8]: 'fire-perf-compat',\n [name$7]: 'fire-rc',\n [name$6]: 'fire-rc-compat',\n [name$5]: 'fire-gcs',\n [name$4]: 'fire-gcs-compat',\n [name$3]: 'fire-fst',\n [name$1]: 'fire-fst-compat',\n [name$2]: 'fire-vertex',\n 'fire-js': 'fire-js', // Platform identifier for JS SDK.\n [name]: 'fire-js-all'\n};\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * @internal\n */\nconst _apps = new Map();\n/**\n * @internal\n */\nconst _serverApps = new Map();\n/**\n * Registered components.\n *\n * @internal\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst _components = new Map();\n/**\n * @param component - the component being added to this app's container\n *\n * @internal\n */\nfunction _addComponent(app, component) {\n try {\n app.container.addComponent(component);\n }\n catch (e) {\n logger.debug(`Component ${component.name} failed to register with FirebaseApp ${app.name}`, e);\n }\n}\n/**\n *\n * @internal\n */\nfunction _addOrOverwriteComponent(app, component) {\n app.container.addOrOverwriteComponent(component);\n}\n/**\n *\n * @param component - the component to register\n * @returns whether or not the component is registered successfully\n *\n * @internal\n */\nfunction _registerComponent(component) {\n const componentName = component.name;\n if (_components.has(componentName)) {\n logger.debug(`There were multiple attempts to register component ${componentName}.`);\n return false;\n }\n _components.set(componentName, component);\n // add the component to existing app instances\n for (const app of _apps.values()) {\n _addComponent(app, component);\n }\n for (const serverApp of _serverApps.values()) {\n _addComponent(serverApp, component);\n }\n return true;\n}\n/**\n *\n * @param app - FirebaseApp instance\n * @param name - service name\n *\n * @returns the provider for the service with the matching name\n *\n * @internal\n */\nfunction _getProvider(app, name) {\n const heartbeatController = app.container\n .getProvider('heartbeat')\n .getImmediate({ optional: true });\n if (heartbeatController) {\n void heartbeatController.triggerHeartbeat();\n }\n return app.container.getProvider(name);\n}\n/**\n *\n * @param app - FirebaseApp instance\n * @param name - service name\n * @param instanceIdentifier - service instance identifier in case the service supports multiple instances\n *\n * @internal\n */\nfunction _removeServiceInstance(app, name, instanceIdentifier = DEFAULT_ENTRY_NAME) {\n _getProvider(app, name).clearInstance(instanceIdentifier);\n}\n/**\n *\n * @param obj - an object of type FirebaseApp or FirebaseOptions.\n *\n * @returns true if the provide object is of type FirebaseApp.\n *\n * @internal\n */\nfunction _isFirebaseApp(obj) {\n return obj.options !== undefined;\n}\n/**\n *\n * @param obj - an object of type FirebaseApp.\n *\n * @returns true if the provided object is of type FirebaseServerAppImpl.\n *\n * @internal\n */\nfunction _isFirebaseServerApp(obj) {\n if (obj === null || obj === undefined) {\n return false;\n }\n return obj.settings !== undefined;\n}\n/**\n * Test only\n *\n * @internal\n */\nfunction _clearComponents() {\n _components.clear();\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst ERRORS = {\n [\"no-app\" /* AppError.NO_APP */]: \"No Firebase App '{$appName}' has been created - \" +\n 'call initializeApp() first',\n [\"bad-app-name\" /* AppError.BAD_APP_NAME */]: \"Illegal App name: '{$appName}'\",\n [\"duplicate-app\" /* AppError.DUPLICATE_APP */]: \"Firebase App named '{$appName}' already exists with different options or config\",\n [\"app-deleted\" /* AppError.APP_DELETED */]: \"Firebase App named '{$appName}' already deleted\",\n [\"server-app-deleted\" /* AppError.SERVER_APP_DELETED */]: 'Firebase Server App has been deleted',\n [\"no-options\" /* AppError.NO_OPTIONS */]: 'Need to provide options, when not being deployed to hosting via source.',\n [\"invalid-app-argument\" /* AppError.INVALID_APP_ARGUMENT */]: 'firebase.{$appName}() takes either no argument or a ' +\n 'Firebase App instance.',\n [\"invalid-log-argument\" /* AppError.INVALID_LOG_ARGUMENT */]: 'First argument to `onLog` must be null or a function.',\n [\"idb-open\" /* AppError.IDB_OPEN */]: 'Error thrown when opening IndexedDB. Original error: {$originalErrorMessage}.',\n [\"idb-get\" /* AppError.IDB_GET */]: 'Error thrown when reading from IndexedDB. Original error: {$originalErrorMessage}.',\n [\"idb-set\" /* AppError.IDB_WRITE */]: 'Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.',\n [\"idb-delete\" /* AppError.IDB_DELETE */]: 'Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.',\n [\"finalization-registry-not-supported\" /* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */]: 'FirebaseServerApp deleteOnDeref field defined but the JS runtime does not support FinalizationRegistry.',\n [\"invalid-server-app-environment\" /* AppError.INVALID_SERVER_APP_ENVIRONMENT */]: 'FirebaseServerApp is not for use in browser environments.'\n};\nconst ERROR_FACTORY = new ErrorFactory('app', 'Firebase', ERRORS);\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nclass FirebaseAppImpl {\n constructor(options, config, container) {\n this._isDeleted = false;\n this._options = Object.assign({}, options);\n this._config = Object.assign({}, config);\n this._name = config.name;\n this._automaticDataCollectionEnabled =\n config.automaticDataCollectionEnabled;\n this._container = container;\n this.container.addComponent(new Component('app', () => this, \"PUBLIC\" /* ComponentType.PUBLIC */));\n }\n get automaticDataCollectionEnabled() {\n this.checkDestroyed();\n return this._automaticDataCollectionEnabled;\n }\n set automaticDataCollectionEnabled(val) {\n this.checkDestroyed();\n this._automaticDataCollectionEnabled = val;\n }\n get name() {\n this.checkDestroyed();\n return this._name;\n }\n get options() {\n this.checkDestroyed();\n return this._options;\n }\n get config() {\n this.checkDestroyed();\n return this._config;\n }\n get container() {\n return this._container;\n }\n get isDeleted() {\n return this._isDeleted;\n }\n set isDeleted(val) {\n this._isDeleted = val;\n }\n /**\n * This function will throw an Error if the App has already been deleted -\n * use before performing API actions on the App.\n */\n checkDestroyed() {\n if (this.isDeleted) {\n throw ERROR_FACTORY.create(\"app-deleted\" /* AppError.APP_DELETED */, { appName: this._name });\n }\n }\n}\n\n/**\n * @license\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// Parse the token and check to see if the `exp` claim is in the future.\n// Reports an error to the console if the token or claim could not be parsed, or if `exp` is in\n// the past.\nfunction validateTokenTTL(base64Token, tokenName) {\n const secondPart = base64Decode(base64Token.split('.')[1]);\n if (secondPart === null) {\n console.error(`FirebaseServerApp ${tokenName} is invalid: second part could not be parsed.`);\n return;\n }\n const expClaim = JSON.parse(secondPart).exp;\n if (expClaim === undefined) {\n console.error(`FirebaseServerApp ${tokenName} is invalid: expiration claim could not be parsed`);\n return;\n }\n const exp = JSON.parse(secondPart).exp * 1000;\n const now = new Date().getTime();\n const diff = exp - now;\n if (diff <= 0) {\n console.error(`FirebaseServerApp ${tokenName} is invalid: the token has expired.`);\n }\n}\nclass FirebaseServerAppImpl extends FirebaseAppImpl {\n constructor(options, serverConfig, name, container) {\n // Build configuration parameters for the FirebaseAppImpl base class.\n const automaticDataCollectionEnabled = serverConfig.automaticDataCollectionEnabled !== undefined\n ? serverConfig.automaticDataCollectionEnabled\n : true;\n // Create the FirebaseAppSettings object for the FirebaseAppImp constructor.\n const config = {\n name,\n automaticDataCollectionEnabled\n };\n if (options.apiKey !== undefined) {\n // Construct the parent FirebaseAppImp object.\n super(options, config, container);\n }\n else {\n const appImpl = options;\n super(appImpl.options, config, container);\n }\n // Now construct the data for the FirebaseServerAppImpl.\n this._serverConfig = Object.assign({ automaticDataCollectionEnabled }, serverConfig);\n // Ensure that the current time is within the `authIdtoken` window of validity.\n if (this._serverConfig.authIdToken) {\n validateTokenTTL(this._serverConfig.authIdToken, 'authIdToken');\n }\n // Ensure that the current time is within the `appCheckToken` window of validity.\n if (this._serverConfig.appCheckToken) {\n validateTokenTTL(this._serverConfig.appCheckToken, 'appCheckToken');\n }\n this._finalizationRegistry = null;\n if (typeof FinalizationRegistry !== 'undefined') {\n this._finalizationRegistry = new FinalizationRegistry(() => {\n this.automaticCleanup();\n });\n }\n this._refCount = 0;\n this.incRefCount(this._serverConfig.releaseOnDeref);\n // Do not retain a hard reference to the dref object, otherwise the FinalizationRegistry\n // will never trigger.\n this._serverConfig.releaseOnDeref = undefined;\n serverConfig.releaseOnDeref = undefined;\n registerVersion(name$q, version$1, 'serverapp');\n }\n toJSON() {\n return undefined;\n }\n get refCount() {\n return this._refCount;\n }\n // Increment the reference count of this server app. If an object is provided, register it\n // with the finalization registry.\n incRefCount(obj) {\n if (this.isDeleted) {\n return;\n }\n this._refCount++;\n if (obj !== undefined && this._finalizationRegistry !== null) {\n this._finalizationRegistry.register(obj, this);\n }\n }\n // Decrement the reference count.\n decRefCount() {\n if (this.isDeleted) {\n return 0;\n }\n return --this._refCount;\n }\n // Invoked by the FinalizationRegistry callback to note that this app should go through its\n // reference counts and delete itself if no reference count remain. The coordinating logic that\n // handles this is in deleteApp(...).\n automaticCleanup() {\n void deleteApp(this);\n }\n get settings() {\n this.checkDestroyed();\n return this._serverConfig;\n }\n /**\n * This function will throw an Error if the App has already been deleted -\n * use before performing API actions on the App.\n */\n checkDestroyed() {\n if (this.isDeleted) {\n throw ERROR_FACTORY.create(\"server-app-deleted\" /* AppError.SERVER_APP_DELETED */);\n }\n }\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * The current SDK version.\n *\n * @public\n */\nconst SDK_VERSION = version;\nfunction initializeApp(_options, rawConfig = {}) {\n let options = _options;\n if (typeof rawConfig !== 'object') {\n const name = rawConfig;\n rawConfig = { name };\n }\n const config = Object.assign({ name: DEFAULT_ENTRY_NAME, automaticDataCollectionEnabled: true }, rawConfig);\n const name = config.name;\n if (typeof name !== 'string' || !name) {\n throw ERROR_FACTORY.create(\"bad-app-name\" /* AppError.BAD_APP_NAME */, {\n appName: String(name)\n });\n }\n options || (options = getDefaultAppConfig());\n if (!options) {\n throw ERROR_FACTORY.create(\"no-options\" /* AppError.NO_OPTIONS */);\n }\n const existingApp = _apps.get(name);\n if (existingApp) {\n // return the existing app if options and config deep equal the ones in the existing app.\n if (deepEqual(options, existingApp.options) &&\n deepEqual(config, existingApp.config)) {\n return existingApp;\n }\n else {\n throw ERROR_FACTORY.create(\"duplicate-app\" /* AppError.DUPLICATE_APP */, { appName: name });\n }\n }\n const container = new ComponentContainer(name);\n for (const component of _components.values()) {\n container.addComponent(component);\n }\n const newApp = new FirebaseAppImpl(options, config, container);\n _apps.set(name, newApp);\n return newApp;\n}\nfunction initializeServerApp(_options, _serverAppConfig) {\n if (isBrowser() && !isWebWorker()) {\n // FirebaseServerApp isn't designed to be run in browsers.\n throw ERROR_FACTORY.create(\"invalid-server-app-environment\" /* AppError.INVALID_SERVER_APP_ENVIRONMENT */);\n }\n if (_serverAppConfig.automaticDataCollectionEnabled === undefined) {\n _serverAppConfig.automaticDataCollectionEnabled = true;\n }\n let appOptions;\n if (_isFirebaseApp(_options)) {\n appOptions = _options.options;\n }\n else {\n appOptions = _options;\n }\n // Build an app name based on a hash of the configuration options.\n const nameObj = Object.assign(Object.assign({}, _serverAppConfig), appOptions);\n // However, Do not mangle the name based on releaseOnDeref, since it will vary between the\n // construction of FirebaseServerApp instances. For example, if the object is the request headers.\n if (nameObj.releaseOnDeref !== undefined) {\n delete nameObj.releaseOnDeref;\n }\n const hashCode = (s) => {\n return [...s].reduce((hash, c) => (Math.imul(31, hash) + c.charCodeAt(0)) | 0, 0);\n };\n if (_serverAppConfig.releaseOnDeref !== undefined) {\n if (typeof FinalizationRegistry === 'undefined') {\n throw ERROR_FACTORY.create(\"finalization-registry-not-supported\" /* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */, {});\n }\n }\n const nameString = '' + hashCode(JSON.stringify(nameObj));\n const existingApp = _serverApps.get(nameString);\n if (existingApp) {\n existingApp.incRefCount(_serverAppConfig.releaseOnDeref);\n return existingApp;\n }\n const container = new ComponentContainer(nameString);\n for (const component of _components.values()) {\n container.addComponent(component);\n }\n const newApp = new FirebaseServerAppImpl(appOptions, _serverAppConfig, nameString, container);\n _serverApps.set(nameString, newApp);\n return newApp;\n}\n/**\n * Retrieves a {@link @firebase/app#FirebaseApp} instance.\n *\n * When called with no arguments, the default app is returned. When an app name\n * is provided, the app corresponding to that name is returned.\n *\n * An exception is thrown if the app being retrieved has not yet been\n * initialized.\n *\n * @example\n * ```javascript\n * // Return the default app\n * const app = getApp();\n * ```\n *\n * @example\n * ```javascript\n * // Return a named app\n * const otherApp = getApp(\"otherApp\");\n * ```\n *\n * @param name - Optional name of the app to return. If no name is\n * provided, the default is `\"[DEFAULT]\"`.\n *\n * @returns The app corresponding to the provided app name.\n * If no app name is provided, the default app is returned.\n *\n * @public\n */\nfunction getApp(name = DEFAULT_ENTRY_NAME) {\n const app = _apps.get(name);\n if (!app && name === DEFAULT_ENTRY_NAME && getDefaultAppConfig()) {\n return initializeApp();\n }\n if (!app) {\n throw ERROR_FACTORY.create(\"no-app\" /* AppError.NO_APP */, { appName: name });\n }\n return app;\n}\n/**\n * A (read-only) array of all initialized apps.\n * @public\n */\nfunction getApps() {\n return Array.from(_apps.values());\n}\n/**\n * Renders this app unusable and frees the resources of all associated\n * services.\n *\n * @example\n * ```javascript\n * deleteApp(app)\n * .then(function() {\n * console.log(\"App deleted successfully\");\n * })\n * .catch(function(error) {\n * console.log(\"Error deleting app:\", error);\n * });\n * ```\n *\n * @public\n */\nasync function deleteApp(app) {\n let cleanupProviders = false;\n const name = app.name;\n if (_apps.has(name)) {\n cleanupProviders = true;\n _apps.delete(name);\n }\n else if (_serverApps.has(name)) {\n const firebaseServerApp = app;\n if (firebaseServerApp.decRefCount() <= 0) {\n _serverApps.delete(name);\n cleanupProviders = true;\n }\n }\n if (cleanupProviders) {\n await Promise.all(app.container\n .getProviders()\n .map(provider => provider.delete()));\n app.isDeleted = true;\n }\n}\n/**\n * Registers a library's name and version for platform logging purposes.\n * @param library - Name of 1p or 3p library (e.g. firestore, angularfire)\n * @param version - Current version of that library.\n * @param variant - Bundle variant, e.g., node, rn, etc.\n *\n * @public\n */\nfunction registerVersion(libraryKeyOrName, version, variant) {\n var _a;\n // TODO: We can use this check to whitelist strings when/if we set up\n // a good whitelist system.\n let library = (_a = PLATFORM_LOG_STRING[libraryKeyOrName]) !== null && _a !== void 0 ? _a : libraryKeyOrName;\n if (variant) {\n library += `-${variant}`;\n }\n const libraryMismatch = library.match(/\\s|\\//);\n const versionMismatch = version.match(/\\s|\\//);\n if (libraryMismatch || versionMismatch) {\n const warning = [\n `Unable to register library \"${library}\" with version \"${version}\":`\n ];\n if (libraryMismatch) {\n warning.push(`library name \"${library}\" contains illegal characters (whitespace or \"/\")`);\n }\n if (libraryMismatch && versionMismatch) {\n warning.push('and');\n }\n if (versionMismatch) {\n warning.push(`version name \"${version}\" contains illegal characters (whitespace or \"/\")`);\n }\n logger.warn(warning.join(' '));\n return;\n }\n _registerComponent(new Component(`${library}-version`, () => ({ library, version }), \"VERSION\" /* ComponentType.VERSION */));\n}\n/**\n * Sets log handler for all Firebase SDKs.\n * @param logCallback - An optional custom log handler that executes user code whenever\n * the Firebase SDK makes a logging call.\n *\n * @public\n */\nfunction onLog(logCallback, options) {\n if (logCallback !== null && typeof logCallback !== 'function') {\n throw ERROR_FACTORY.create(\"invalid-log-argument\" /* AppError.INVALID_LOG_ARGUMENT */);\n }\n setUserLogHandler(logCallback, options);\n}\n/**\n * Sets log level for all Firebase SDKs.\n *\n * All of the log types above the current log level are captured (i.e. if\n * you set the log level to `info`, errors are logged, but `debug` and\n * `verbose` logs are not).\n *\n * @public\n */\nfunction setLogLevel(logLevel) {\n setLogLevel$1(logLevel);\n}\n\n/**\n * @license\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst DB_NAME = 'firebase-heartbeat-database';\nconst DB_VERSION = 1;\nconst STORE_NAME = 'firebase-heartbeat-store';\nlet dbPromise = null;\nfunction getDbPromise() {\n if (!dbPromise) {\n dbPromise = openDB(DB_NAME, DB_VERSION, {\n upgrade: (db, oldVersion) => {\n // We don't use 'break' in this switch statement, the fall-through\n // behavior is what we want, because if there are multiple versions between\n // the old version and the current version, we want ALL the migrations\n // that correspond to those versions to run, not only the last one.\n // eslint-disable-next-line default-case\n switch (oldVersion) {\n case 0:\n try {\n db.createObjectStore(STORE_NAME);\n }\n catch (e) {\n // Safari/iOS browsers throw occasional exceptions on\n // db.createObjectStore() that may be a bug. Avoid blocking\n // the rest of the app functionality.\n console.warn(e);\n }\n }\n }\n }).catch(e => {\n throw ERROR_FACTORY.create(\"idb-open\" /* AppError.IDB_OPEN */, {\n originalErrorMessage: e.message\n });\n });\n }\n return dbPromise;\n}\nasync function readHeartbeatsFromIndexedDB(app) {\n try {\n const db = await getDbPromise();\n const tx = db.transaction(STORE_NAME);\n const result = await tx.objectStore(STORE_NAME).get(computeKey(app));\n // We already have the value but tx.done can throw,\n // so we need to await it here to catch errors\n await tx.done;\n return result;\n }\n catch (e) {\n if (e instanceof FirebaseError) {\n logger.warn(e.message);\n }\n else {\n const idbGetError = ERROR_FACTORY.create(\"idb-get\" /* AppError.IDB_GET */, {\n originalErrorMessage: e === null || e === void 0 ? void 0 : e.message\n });\n logger.warn(idbGetError.message);\n }\n }\n}\nasync function writeHeartbeatsToIndexedDB(app, heartbeatObject) {\n try {\n const db = await getDbPromise();\n const tx = db.transaction(STORE_NAME, 'readwrite');\n const objectStore = tx.objectStore(STORE_NAME);\n await objectStore.put(heartbeatObject, computeKey(app));\n await tx.done;\n }\n catch (e) {\n if (e instanceof FirebaseError) {\n logger.warn(e.message);\n }\n else {\n const idbGetError = ERROR_FACTORY.create(\"idb-set\" /* AppError.IDB_WRITE */, {\n originalErrorMessage: e === null || e === void 0 ? void 0 : e.message\n });\n logger.warn(idbGetError.message);\n }\n }\n}\nfunction computeKey(app) {\n return `${app.name}!${app.options.appId}`;\n}\n\n/**\n * @license\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst MAX_HEADER_BYTES = 1024;\nconst MAX_NUM_STORED_HEARTBEATS = 30;\nclass HeartbeatServiceImpl {\n constructor(container) {\n this.container = container;\n /**\n * In-memory cache for heartbeats, used by getHeartbeatsHeader() to generate\n * the header string.\n * Stores one record per date. This will be consolidated into the standard\n * format of one record per user agent string before being sent as a header.\n * Populated from indexedDB when the controller is instantiated and should\n * be kept in sync with indexedDB.\n * Leave public for easier testing.\n */\n this._heartbeatsCache = null;\n const app = this.container.getProvider('app').getImmediate();\n this._storage = new HeartbeatStorageImpl(app);\n this._heartbeatsCachePromise = this._storage.read().then(result => {\n this._heartbeatsCache = result;\n return result;\n });\n }\n /**\n * Called to report a heartbeat. The function will generate\n * a HeartbeatsByUserAgent object, update heartbeatsCache, and persist it\n * to IndexedDB.\n * Note that we only store one heartbeat per day. So if a heartbeat for today is\n * already logged, subsequent calls to this function in the same day will be ignored.\n */\n async triggerHeartbeat() {\n var _a, _b;\n try {\n const platformLogger = this.container\n .getProvider('platform-logger')\n .getImmediate();\n // This is the \"Firebase user agent\" string from the platform logger\n // service, not the browser user agent.\n const agent = platformLogger.getPlatformInfoString();\n const date = getUTCDateString();\n if (((_a = this._heartbeatsCache) === null || _a === void 0 ? void 0 : _a.heartbeats) == null) {\n this._heartbeatsCache = await this._heartbeatsCachePromise;\n // If we failed to construct a heartbeats cache, then return immediately.\n if (((_b = this._heartbeatsCache) === null || _b === void 0 ? void 0 : _b.heartbeats) == null) {\n return;\n }\n }\n // Do not store a heartbeat if one is already stored for this day\n // or if a header has already been sent today.\n if (this._heartbeatsCache.lastSentHeartbeatDate === date ||\n this._heartbeatsCache.heartbeats.some(singleDateHeartbeat => singleDateHeartbeat.date === date)) {\n return;\n }\n else {\n // There is no entry for this date. Create one.\n this._heartbeatsCache.heartbeats.push({ date, agent });\n // If the number of stored heartbeats exceeds the maximum number of stored heartbeats, remove the heartbeat with the earliest date.\n // Since this is executed each time a heartbeat is pushed, the limit can only be exceeded by one, so only one needs to be removed.\n if (this._heartbeatsCache.heartbeats.length > MAX_NUM_STORED_HEARTBEATS) {\n const earliestHeartbeatIdx = getEarliestHeartbeatIdx(this._heartbeatsCache.heartbeats);\n this._heartbeatsCache.heartbeats.splice(earliestHeartbeatIdx, 1);\n }\n }\n return this._storage.overwrite(this._heartbeatsCache);\n }\n catch (e) {\n logger.warn(e);\n }\n }\n /**\n * Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.\n * It also clears all heartbeats from memory as well as in IndexedDB.\n *\n * NOTE: Consuming product SDKs should not send the header if this method\n * returns an empty string.\n */\n async getHeartbeatsHeader() {\n var _a;\n try {\n if (this._heartbeatsCache === null) {\n await this._heartbeatsCachePromise;\n }\n // If it's still null or the array is empty, there is no data to send.\n if (((_a = this._heartbeatsCache) === null || _a === void 0 ? void 0 : _a.heartbeats) == null ||\n this._heartbeatsCache.heartbeats.length === 0) {\n return '';\n }\n const date = getUTCDateString();\n // Extract as many heartbeats from the cache as will fit under the size limit.\n const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats);\n const headerString = base64urlEncodeWithoutPadding(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend }));\n // Store last sent date to prevent another being logged/sent for the same day.\n this._heartbeatsCache.lastSentHeartbeatDate = date;\n if (unsentEntries.length > 0) {\n // Store any unsent entries if they exist.\n this._heartbeatsCache.heartbeats = unsentEntries;\n // This seems more likely than emptying the array (below) to lead to some odd state\n // since the cache isn't empty and this will be called again on the next request,\n // and is probably safest if we await it.\n await this._storage.overwrite(this._heartbeatsCache);\n }\n else {\n this._heartbeatsCache.heartbeats = [];\n // Do not wait for this, to reduce latency.\n void this._storage.overwrite(this._heartbeatsCache);\n }\n return headerString;\n }\n catch (e) {\n logger.warn(e);\n return '';\n }\n }\n}\nfunction getUTCDateString() {\n const today = new Date();\n // Returns date format 'YYYY-MM-DD'\n return today.toISOString().substring(0, 10);\n}\nfunction extractHeartbeatsForHeader(heartbeatsCache, maxSize = MAX_HEADER_BYTES) {\n // Heartbeats grouped by user agent in the standard format to be sent in\n // the header.\n const heartbeatsToSend = [];\n // Single date format heartbeats that are not sent.\n let unsentEntries = heartbeatsCache.slice();\n for (const singleDateHeartbeat of heartbeatsCache) {\n // Look for an existing entry with the same user agent.\n const heartbeatEntry = heartbeatsToSend.find(hb => hb.agent === singleDateHeartbeat.agent);\n if (!heartbeatEntry) {\n // If no entry for this user agent exists, create one.\n heartbeatsToSend.push({\n agent: singleDateHeartbeat.agent,\n dates: [singleDateHeartbeat.date]\n });\n if (countBytes(heartbeatsToSend) > maxSize) {\n // If the header would exceed max size, remove the added heartbeat\n // entry and stop adding to the header.\n heartbeatsToSend.pop();\n break;\n }\n }\n else {\n heartbeatEntry.dates.push(singleDateHeartbeat.date);\n // If the header would exceed max size, remove the added date\n // and stop adding to the header.\n if (countBytes(heartbeatsToSend) > maxSize) {\n heartbeatEntry.dates.pop();\n break;\n }\n }\n // Pop unsent entry from queue. (Skipped if adding the entry exceeded\n // quota and the loop breaks early.)\n unsentEntries = unsentEntries.slice(1);\n }\n return {\n heartbeatsToSend,\n unsentEntries\n };\n}\nclass HeartbeatStorageImpl {\n constructor(app) {\n this.app = app;\n this._canUseIndexedDBPromise = this.runIndexedDBEnvironmentCheck();\n }\n async runIndexedDBEnvironmentCheck() {\n if (!isIndexedDBAvailable()) {\n return false;\n }\n else {\n return validateIndexedDBOpenable()\n .then(() => true)\n .catch(() => false);\n }\n }\n /**\n * Read all heartbeats.\n */\n async read() {\n const canUseIndexedDB = await this._canUseIndexedDBPromise;\n if (!canUseIndexedDB) {\n return { heartbeats: [] };\n }\n else {\n const idbHeartbeatObject = await readHeartbeatsFromIndexedDB(this.app);\n if (idbHeartbeatObject === null || idbHeartbeatObject === void 0 ? void 0 : idbHeartbeatObject.heartbeats) {\n return idbHeartbeatObject;\n }\n else {\n return { heartbeats: [] };\n }\n }\n }\n // overwrite the storage with the provided heartbeats\n async overwrite(heartbeatsObject) {\n var _a;\n const canUseIndexedDB = await this._canUseIndexedDBPromise;\n if (!canUseIndexedDB) {\n return;\n }\n else {\n const existingHeartbeatsObject = await this.read();\n return writeHeartbeatsToIndexedDB(this.app, {\n lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,\n heartbeats: heartbeatsObject.heartbeats\n });\n }\n }\n // add heartbeats\n async add(heartbeatsObject) {\n var _a;\n const canUseIndexedDB = await this._canUseIndexedDBPromise;\n if (!canUseIndexedDB) {\n return;\n }\n else {\n const existingHeartbeatsObject = await this.read();\n return writeHeartbeatsToIndexedDB(this.app, {\n lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,\n heartbeats: [\n ...existingHeartbeatsObject.heartbeats,\n ...heartbeatsObject.heartbeats\n ]\n });\n }\n }\n}\n/**\n * Calculate bytes of a HeartbeatsByUserAgent array after being wrapped\n * in a platform logging header JSON object, stringified, and converted\n * to base 64.\n */\nfunction countBytes(heartbeatsCache) {\n // base64 has a restricted set of characters, all of which should be 1 byte.\n return base64urlEncodeWithoutPadding(\n // heartbeatsCache wrapper properties\n JSON.stringify({ version: 2, heartbeats: heartbeatsCache })).length;\n}\n/**\n * Returns the index of the heartbeat with the earliest date.\n * If the heartbeats array is empty, -1 is returned.\n */\nfunction getEarliestHeartbeatIdx(heartbeats) {\n if (heartbeats.length === 0) {\n return -1;\n }\n let earliestHeartbeatIdx = 0;\n let earliestHeartbeatDate = heartbeats[0].date;\n for (let i = 1; i < heartbeats.length; i++) {\n if (heartbeats[i].date < earliestHeartbeatDate) {\n earliestHeartbeatDate = heartbeats[i].date;\n earliestHeartbeatIdx = i;\n }\n }\n return earliestHeartbeatIdx;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction registerCoreComponents(variant) {\n _registerComponent(new Component('platform-logger', container => new PlatformLoggerServiceImpl(container), \"PRIVATE\" /* ComponentType.PRIVATE */));\n _registerComponent(new Component('heartbeat', container => new HeartbeatServiceImpl(container), \"PRIVATE\" /* ComponentType.PRIVATE */));\n // Register `app` package.\n registerVersion(name$q, version$1, variant);\n // BUILD_TARGET will be replaced by values like esm2017, cjs2017, etc during the compilation\n registerVersion(name$q, version$1, 'esm2017');\n // Register platform SDK identifier (no version).\n registerVersion('fire-js', '');\n}\n\n/**\n * Firebase App\n *\n * @remarks This package coordinates the communication between the different Firebase components\n * @packageDocumentation\n */\nregisterCoreComponents('');\n\nexport { SDK_VERSION, DEFAULT_ENTRY_NAME as _DEFAULT_ENTRY_NAME, _addComponent, _addOrOverwriteComponent, _apps, _clearComponents, _components, _getProvider, _isFirebaseApp, _isFirebaseServerApp, _registerComponent, _removeServiceInstance, _serverApps, deleteApp, getApp, getApps, initializeApp, initializeServerApp, onLog, registerVersion, setLogLevel };\n//# sourceMappingURL=index.esm2017.js.map\n","import { registerVersion } from '@firebase/app';\nexport * from '@firebase/app';\n\nvar name = \"firebase\";\nvar version = \"11.10.0\";\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nregisterVersion(name, version, 'app');\n//# sourceMappingURL=index.esm.js.map\n","import { _getProvider, getApp, _registerComponent, registerVersion } from '@firebase/app';\nimport { Component } from '@firebase/component';\nimport { ErrorFactory, FirebaseError } from '@firebase/util';\nimport { openDB } from 'idb';\n\nconst name = \"@firebase/installations\";\nconst version = \"0.6.18\";\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst PENDING_TIMEOUT_MS = 10000;\nconst PACKAGE_VERSION = `w:${version}`;\nconst INTERNAL_AUTH_VERSION = 'FIS_v2';\nconst INSTALLATIONS_API_URL = 'https://firebaseinstallations.googleapis.com/v1';\nconst TOKEN_EXPIRATION_BUFFER = 60 * 60 * 1000; // One hour\nconst SERVICE = 'installations';\nconst SERVICE_NAME = 'Installations';\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst ERROR_DESCRIPTION_MAP = {\n [\"missing-app-config-values\" /* ErrorCode.MISSING_APP_CONFIG_VALUES */]: 'Missing App configuration value: \"{$valueName}\"',\n [\"not-registered\" /* ErrorCode.NOT_REGISTERED */]: 'Firebase Installation is not registered.',\n [\"installation-not-found\" /* ErrorCode.INSTALLATION_NOT_FOUND */]: 'Firebase Installation not found.',\n [\"request-failed\" /* ErrorCode.REQUEST_FAILED */]: '{$requestName} request failed with error \"{$serverCode} {$serverStatus}: {$serverMessage}\"',\n [\"app-offline\" /* ErrorCode.APP_OFFLINE */]: 'Could not process request. Application offline.',\n [\"delete-pending-registration\" /* ErrorCode.DELETE_PENDING_REGISTRATION */]: \"Can't delete installation while there is a pending registration request.\"\n};\nconst ERROR_FACTORY = new ErrorFactory(SERVICE, SERVICE_NAME, ERROR_DESCRIPTION_MAP);\n/** Returns true if error is a FirebaseError that is based on an error from the server. */\nfunction isServerError(error) {\n return (error instanceof FirebaseError &&\n error.code.includes(\"request-failed\" /* ErrorCode.REQUEST_FAILED */));\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction getInstallationsEndpoint({ projectId }) {\n return `${INSTALLATIONS_API_URL}/projects/${projectId}/installations`;\n}\nfunction extractAuthTokenInfoFromResponse(response) {\n return {\n token: response.token,\n requestStatus: 2 /* RequestStatus.COMPLETED */,\n expiresIn: getExpiresInFromResponseExpiresIn(response.expiresIn),\n creationTime: Date.now()\n };\n}\nasync function getErrorFromResponse(requestName, response) {\n const responseJson = await response.json();\n const errorData = responseJson.error;\n return ERROR_FACTORY.create(\"request-failed\" /* ErrorCode.REQUEST_FAILED */, {\n requestName,\n serverCode: errorData.code,\n serverMessage: errorData.message,\n serverStatus: errorData.status\n });\n}\nfunction getHeaders({ apiKey }) {\n return new Headers({\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n 'x-goog-api-key': apiKey\n });\n}\nfunction getHeadersWithAuth(appConfig, { refreshToken }) {\n const headers = getHeaders(appConfig);\n headers.append('Authorization', getAuthorizationHeader(refreshToken));\n return headers;\n}\n/**\n * Calls the passed in fetch wrapper and returns the response.\n * If the returned response has a status of 5xx, re-runs the function once and\n * returns the response.\n */\nasync function retryIfServerError(fn) {\n const result = await fn();\n if (result.status >= 500 && result.status < 600) {\n // Internal Server Error. Retry request.\n return fn();\n }\n return result;\n}\nfunction getExpiresInFromResponseExpiresIn(responseExpiresIn) {\n // This works because the server will never respond with fractions of a second.\n return Number(responseExpiresIn.replace('s', '000'));\n}\nfunction getAuthorizationHeader(refreshToken) {\n return `${INTERNAL_AUTH_VERSION} ${refreshToken}`;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function createInstallationRequest({ appConfig, heartbeatServiceProvider }, { fid }) {\n const endpoint = getInstallationsEndpoint(appConfig);\n const headers = getHeaders(appConfig);\n // If heartbeat service exists, add the heartbeat string to the header.\n const heartbeatService = heartbeatServiceProvider.getImmediate({\n optional: true\n });\n if (heartbeatService) {\n const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader();\n if (heartbeatsHeader) {\n headers.append('x-firebase-client', heartbeatsHeader);\n }\n }\n const body = {\n fid,\n authVersion: INTERNAL_AUTH_VERSION,\n appId: appConfig.appId,\n sdkVersion: PACKAGE_VERSION\n };\n const request = {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n };\n const response = await retryIfServerError(() => fetch(endpoint, request));\n if (response.ok) {\n const responseValue = await response.json();\n const registeredInstallationEntry = {\n fid: responseValue.fid || fid,\n registrationStatus: 2 /* RequestStatus.COMPLETED */,\n refreshToken: responseValue.refreshToken,\n authToken: extractAuthTokenInfoFromResponse(responseValue.authToken)\n };\n return registeredInstallationEntry;\n }\n else {\n throw await getErrorFromResponse('Create Installation', response);\n }\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/** Returns a promise that resolves after given time passes. */\nfunction sleep(ms) {\n return new Promise(resolve => {\n setTimeout(resolve, ms);\n });\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction bufferToBase64UrlSafe(array) {\n const b64 = btoa(String.fromCharCode(...array));\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_');\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst VALID_FID_PATTERN = /^[cdef][\\w-]{21}$/;\nconst INVALID_FID = '';\n/**\n * Generates a new FID using random values from Web Crypto API.\n * Returns an empty string if FID generation fails for any reason.\n */\nfunction generateFid() {\n try {\n // A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5\n // bytes. our implementation generates a 17 byte array instead.\n const fidByteArray = new Uint8Array(17);\n const crypto = self.crypto || self.msCrypto;\n crypto.getRandomValues(fidByteArray);\n // Replace the first 4 random bits with the constant FID header of 0b0111.\n fidByteArray[0] = 0b01110000 + (fidByteArray[0] % 0b00010000);\n const fid = encode(fidByteArray);\n return VALID_FID_PATTERN.test(fid) ? fid : INVALID_FID;\n }\n catch (_a) {\n // FID generation errored\n return INVALID_FID;\n }\n}\n/** Converts a FID Uint8Array to a base64 string representation. */\nfunction encode(fidByteArray) {\n const b64String = bufferToBase64UrlSafe(fidByteArray);\n // Remove the 23rd character that was added because of the extra 4 bits at the\n // end of our 17 byte array, and the '=' padding.\n return b64String.substr(0, 22);\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/** Returns a string key that can be used to identify the app. */\nfunction getKey(appConfig) {\n return `${appConfig.appName}!${appConfig.appId}`;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst fidChangeCallbacks = new Map();\n/**\n * Calls the onIdChange callbacks with the new FID value, and broadcasts the\n * change to other tabs.\n */\nfunction fidChanged(appConfig, fid) {\n const key = getKey(appConfig);\n callFidChangeCallbacks(key, fid);\n broadcastFidChange(key, fid);\n}\nfunction addCallback(appConfig, callback) {\n // Open the broadcast channel if it's not already open,\n // to be able to listen to change events from other tabs.\n getBroadcastChannel();\n const key = getKey(appConfig);\n let callbackSet = fidChangeCallbacks.get(key);\n if (!callbackSet) {\n callbackSet = new Set();\n fidChangeCallbacks.set(key, callbackSet);\n }\n callbackSet.add(callback);\n}\nfunction removeCallback(appConfig, callback) {\n const key = getKey(appConfig);\n const callbackSet = fidChangeCallbacks.get(key);\n if (!callbackSet) {\n return;\n }\n callbackSet.delete(callback);\n if (callbackSet.size === 0) {\n fidChangeCallbacks.delete(key);\n }\n // Close broadcast channel if there are no more callbacks.\n closeBroadcastChannel();\n}\nfunction callFidChangeCallbacks(key, fid) {\n const callbacks = fidChangeCallbacks.get(key);\n if (!callbacks) {\n return;\n }\n for (const callback of callbacks) {\n callback(fid);\n }\n}\nfunction broadcastFidChange(key, fid) {\n const channel = getBroadcastChannel();\n if (channel) {\n channel.postMessage({ key, fid });\n }\n closeBroadcastChannel();\n}\nlet broadcastChannel = null;\n/** Opens and returns a BroadcastChannel if it is supported by the browser. */\nfunction getBroadcastChannel() {\n if (!broadcastChannel && 'BroadcastChannel' in self) {\n broadcastChannel = new BroadcastChannel('[Firebase] FID Change');\n broadcastChannel.onmessage = e => {\n callFidChangeCallbacks(e.data.key, e.data.fid);\n };\n }\n return broadcastChannel;\n}\nfunction closeBroadcastChannel() {\n if (fidChangeCallbacks.size === 0 && broadcastChannel) {\n broadcastChannel.close();\n broadcastChannel = null;\n }\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst DATABASE_NAME = 'firebase-installations-database';\nconst DATABASE_VERSION = 1;\nconst OBJECT_STORE_NAME = 'firebase-installations-store';\nlet dbPromise = null;\nfunction getDbPromise() {\n if (!dbPromise) {\n dbPromise = openDB(DATABASE_NAME, DATABASE_VERSION, {\n upgrade: (db, oldVersion) => {\n // We don't use 'break' in this switch statement, the fall-through\n // behavior is what we want, because if there are multiple versions between\n // the old version and the current version, we want ALL the migrations\n // that correspond to those versions to run, not only the last one.\n // eslint-disable-next-line default-case\n switch (oldVersion) {\n case 0:\n db.createObjectStore(OBJECT_STORE_NAME);\n }\n }\n });\n }\n return dbPromise;\n}\n/** Assigns or overwrites the record for the given key with the given value. */\nasync function set(appConfig, value) {\n const key = getKey(appConfig);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n const objectStore = tx.objectStore(OBJECT_STORE_NAME);\n const oldValue = (await objectStore.get(key));\n await objectStore.put(value, key);\n await tx.done;\n if (!oldValue || oldValue.fid !== value.fid) {\n fidChanged(appConfig, value.fid);\n }\n return value;\n}\n/** Removes record(s) from the objectStore that match the given key. */\nasync function remove(appConfig) {\n const key = getKey(appConfig);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n await tx.objectStore(OBJECT_STORE_NAME).delete(key);\n await tx.done;\n}\n/**\n * Atomically updates a record with the result of updateFn, which gets\n * called with the current value. If newValue is undefined, the record is\n * deleted instead.\n * @return Updated value\n */\nasync function update(appConfig, updateFn) {\n const key = getKey(appConfig);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n const store = tx.objectStore(OBJECT_STORE_NAME);\n const oldValue = (await store.get(key));\n const newValue = updateFn(oldValue);\n if (newValue === undefined) {\n await store.delete(key);\n }\n else {\n await store.put(newValue, key);\n }\n await tx.done;\n if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) {\n fidChanged(appConfig, newValue.fid);\n }\n return newValue;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Updates and returns the InstallationEntry from the database.\n * Also triggers a registration request if it is necessary and possible.\n */\nasync function getInstallationEntry(installations) {\n let registrationPromise;\n const installationEntry = await update(installations.appConfig, oldEntry => {\n const installationEntry = updateOrCreateInstallationEntry(oldEntry);\n const entryWithPromise = triggerRegistrationIfNecessary(installations, installationEntry);\n registrationPromise = entryWithPromise.registrationPromise;\n return entryWithPromise.installationEntry;\n });\n if (installationEntry.fid === INVALID_FID) {\n // FID generation failed. Waiting for the FID from the server.\n return { installationEntry: await registrationPromise };\n }\n return {\n installationEntry,\n registrationPromise\n };\n}\n/**\n * Creates a new Installation Entry if one does not exist.\n * Also clears timed out pending requests.\n */\nfunction updateOrCreateInstallationEntry(oldEntry) {\n const entry = oldEntry || {\n fid: generateFid(),\n registrationStatus: 0 /* RequestStatus.NOT_STARTED */\n };\n return clearTimedOutRequest(entry);\n}\n/**\n * If the Firebase Installation is not registered yet, this will trigger the\n * registration and return an InProgressInstallationEntry.\n *\n * If registrationPromise does not exist, the installationEntry is guaranteed\n * to be registered.\n */\nfunction triggerRegistrationIfNecessary(installations, installationEntry) {\n if (installationEntry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {\n if (!navigator.onLine) {\n // Registration required but app is offline.\n const registrationPromiseWithError = Promise.reject(ERROR_FACTORY.create(\"app-offline\" /* ErrorCode.APP_OFFLINE */));\n return {\n installationEntry,\n registrationPromise: registrationPromiseWithError\n };\n }\n // Try registering. Change status to IN_PROGRESS.\n const inProgressEntry = {\n fid: installationEntry.fid,\n registrationStatus: 1 /* RequestStatus.IN_PROGRESS */,\n registrationTime: Date.now()\n };\n const registrationPromise = registerInstallation(installations, inProgressEntry);\n return { installationEntry: inProgressEntry, registrationPromise };\n }\n else if (installationEntry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) {\n return {\n installationEntry,\n registrationPromise: waitUntilFidRegistration(installations)\n };\n }\n else {\n return { installationEntry };\n }\n}\n/** This will be executed only once for each new Firebase Installation. */\nasync function registerInstallation(installations, installationEntry) {\n try {\n const registeredInstallationEntry = await createInstallationRequest(installations, installationEntry);\n return set(installations.appConfig, registeredInstallationEntry);\n }\n catch (e) {\n if (isServerError(e) && e.customData.serverCode === 409) {\n // Server returned a \"FID cannot be used\" error.\n // Generate a new ID next time.\n await remove(installations.appConfig);\n }\n else {\n // Registration failed. Set FID as not registered.\n await set(installations.appConfig, {\n fid: installationEntry.fid,\n registrationStatus: 0 /* RequestStatus.NOT_STARTED */\n });\n }\n throw e;\n }\n}\n/** Call if FID registration is pending in another request. */\nasync function waitUntilFidRegistration(installations) {\n // Unfortunately, there is no way of reliably observing when a value in\n // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),\n // so we need to poll.\n let entry = await updateInstallationRequest(installations.appConfig);\n while (entry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) {\n // createInstallation request still in progress.\n await sleep(100);\n entry = await updateInstallationRequest(installations.appConfig);\n }\n if (entry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {\n // The request timed out or failed in a different call. Try again.\n const { installationEntry, registrationPromise } = await getInstallationEntry(installations);\n if (registrationPromise) {\n return registrationPromise;\n }\n else {\n // if there is no registrationPromise, entry is registered.\n return installationEntry;\n }\n }\n return entry;\n}\n/**\n * Called only if there is a CreateInstallation request in progress.\n *\n * Updates the InstallationEntry in the DB based on the status of the\n * CreateInstallation request.\n *\n * Returns the updated InstallationEntry.\n */\nfunction updateInstallationRequest(appConfig) {\n return update(appConfig, oldEntry => {\n if (!oldEntry) {\n throw ERROR_FACTORY.create(\"installation-not-found\" /* ErrorCode.INSTALLATION_NOT_FOUND */);\n }\n return clearTimedOutRequest(oldEntry);\n });\n}\nfunction clearTimedOutRequest(entry) {\n if (hasInstallationRequestTimedOut(entry)) {\n return {\n fid: entry.fid,\n registrationStatus: 0 /* RequestStatus.NOT_STARTED */\n };\n }\n return entry;\n}\nfunction hasInstallationRequestTimedOut(installationEntry) {\n return (installationEntry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */ &&\n installationEntry.registrationTime + PENDING_TIMEOUT_MS < Date.now());\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function generateAuthTokenRequest({ appConfig, heartbeatServiceProvider }, installationEntry) {\n const endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry);\n const headers = getHeadersWithAuth(appConfig, installationEntry);\n // If heartbeat service exists, add the heartbeat string to the header.\n const heartbeatService = heartbeatServiceProvider.getImmediate({\n optional: true\n });\n if (heartbeatService) {\n const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader();\n if (heartbeatsHeader) {\n headers.append('x-firebase-client', heartbeatsHeader);\n }\n }\n const body = {\n installation: {\n sdkVersion: PACKAGE_VERSION,\n appId: appConfig.appId\n }\n };\n const request = {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n };\n const response = await retryIfServerError(() => fetch(endpoint, request));\n if (response.ok) {\n const responseValue = await response.json();\n const completedAuthToken = extractAuthTokenInfoFromResponse(responseValue);\n return completedAuthToken;\n }\n else {\n throw await getErrorFromResponse('Generate Auth Token', response);\n }\n}\nfunction getGenerateAuthTokenEndpoint(appConfig, { fid }) {\n return `${getInstallationsEndpoint(appConfig)}/${fid}/authTokens:generate`;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Returns a valid authentication token for the installation. Generates a new\n * token if one doesn't exist, is expired or about to expire.\n *\n * Should only be called if the Firebase Installation is registered.\n */\nasync function refreshAuthToken(installations, forceRefresh = false) {\n let tokenPromise;\n const entry = await update(installations.appConfig, oldEntry => {\n if (!isEntryRegistered(oldEntry)) {\n throw ERROR_FACTORY.create(\"not-registered\" /* ErrorCode.NOT_REGISTERED */);\n }\n const oldAuthToken = oldEntry.authToken;\n if (!forceRefresh && isAuthTokenValid(oldAuthToken)) {\n // There is a valid token in the DB.\n return oldEntry;\n }\n else if (oldAuthToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */) {\n // There already is a token request in progress.\n tokenPromise = waitUntilAuthTokenRequest(installations, forceRefresh);\n return oldEntry;\n }\n else {\n // No token or token expired.\n if (!navigator.onLine) {\n throw ERROR_FACTORY.create(\"app-offline\" /* ErrorCode.APP_OFFLINE */);\n }\n const inProgressEntry = makeAuthTokenRequestInProgressEntry(oldEntry);\n tokenPromise = fetchAuthTokenFromServer(installations, inProgressEntry);\n return inProgressEntry;\n }\n });\n const authToken = tokenPromise\n ? await tokenPromise\n : entry.authToken;\n return authToken;\n}\n/**\n * Call only if FID is registered and Auth Token request is in progress.\n *\n * Waits until the current pending request finishes. If the request times out,\n * tries once in this thread as well.\n */\nasync function waitUntilAuthTokenRequest(installations, forceRefresh) {\n // Unfortunately, there is no way of reliably observing when a value in\n // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),\n // so we need to poll.\n let entry = await updateAuthTokenRequest(installations.appConfig);\n while (entry.authToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */) {\n // generateAuthToken still in progress.\n await sleep(100);\n entry = await updateAuthTokenRequest(installations.appConfig);\n }\n const authToken = entry.authToken;\n if (authToken.requestStatus === 0 /* RequestStatus.NOT_STARTED */) {\n // The request timed out or failed in a different call. Try again.\n return refreshAuthToken(installations, forceRefresh);\n }\n else {\n return authToken;\n }\n}\n/**\n * Called only if there is a GenerateAuthToken request in progress.\n *\n * Updates the InstallationEntry in the DB based on the status of the\n * GenerateAuthToken request.\n *\n * Returns the updated InstallationEntry.\n */\nfunction updateAuthTokenRequest(appConfig) {\n return update(appConfig, oldEntry => {\n if (!isEntryRegistered(oldEntry)) {\n throw ERROR_FACTORY.create(\"not-registered\" /* ErrorCode.NOT_REGISTERED */);\n }\n const oldAuthToken = oldEntry.authToken;\n if (hasAuthTokenRequestTimedOut(oldAuthToken)) {\n return Object.assign(Object.assign({}, oldEntry), { authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ } });\n }\n return oldEntry;\n });\n}\nasync function fetchAuthTokenFromServer(installations, installationEntry) {\n try {\n const authToken = await generateAuthTokenRequest(installations, installationEntry);\n const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), { authToken });\n await set(installations.appConfig, updatedInstallationEntry);\n return authToken;\n }\n catch (e) {\n if (isServerError(e) &&\n (e.customData.serverCode === 401 || e.customData.serverCode === 404)) {\n // Server returned a \"FID not found\" or a \"Invalid authentication\" error.\n // Generate a new ID next time.\n await remove(installations.appConfig);\n }\n else {\n const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), { authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ } });\n await set(installations.appConfig, updatedInstallationEntry);\n }\n throw e;\n }\n}\nfunction isEntryRegistered(installationEntry) {\n return (installationEntry !== undefined &&\n installationEntry.registrationStatus === 2 /* RequestStatus.COMPLETED */);\n}\nfunction isAuthTokenValid(authToken) {\n return (authToken.requestStatus === 2 /* RequestStatus.COMPLETED */ &&\n !isAuthTokenExpired(authToken));\n}\nfunction isAuthTokenExpired(authToken) {\n const now = Date.now();\n return (now < authToken.creationTime ||\n authToken.creationTime + authToken.expiresIn < now + TOKEN_EXPIRATION_BUFFER);\n}\n/** Returns an updated InstallationEntry with an InProgressAuthToken. */\nfunction makeAuthTokenRequestInProgressEntry(oldEntry) {\n const inProgressAuthToken = {\n requestStatus: 1 /* RequestStatus.IN_PROGRESS */,\n requestTime: Date.now()\n };\n return Object.assign(Object.assign({}, oldEntry), { authToken: inProgressAuthToken });\n}\nfunction hasAuthTokenRequestTimedOut(authToken) {\n return (authToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */ &&\n authToken.requestTime + PENDING_TIMEOUT_MS < Date.now());\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Creates a Firebase Installation if there isn't one for the app and\n * returns the Installation ID.\n * @param installations - The `Installations` instance.\n *\n * @public\n */\nasync function getId(installations) {\n const installationsImpl = installations;\n const { installationEntry, registrationPromise } = await getInstallationEntry(installationsImpl);\n if (registrationPromise) {\n registrationPromise.catch(console.error);\n }\n else {\n // If the installation is already registered, update the authentication\n // token if needed.\n refreshAuthToken(installationsImpl).catch(console.error);\n }\n return installationEntry.fid;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Returns a Firebase Installations auth token, identifying the current\n * Firebase Installation.\n * @param installations - The `Installations` instance.\n * @param forceRefresh - Force refresh regardless of token expiration.\n *\n * @public\n */\nasync function getToken(installations, forceRefresh = false) {\n const installationsImpl = installations;\n await completeInstallationRegistration(installationsImpl);\n // At this point we either have a Registered Installation in the DB, or we've\n // already thrown an error.\n const authToken = await refreshAuthToken(installationsImpl, forceRefresh);\n return authToken.token;\n}\nasync function completeInstallationRegistration(installations) {\n const { registrationPromise } = await getInstallationEntry(installations);\n if (registrationPromise) {\n // A createInstallation request is in progress. Wait until it finishes.\n await registrationPromise;\n }\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function deleteInstallationRequest(appConfig, installationEntry) {\n const endpoint = getDeleteEndpoint(appConfig, installationEntry);\n const headers = getHeadersWithAuth(appConfig, installationEntry);\n const request = {\n method: 'DELETE',\n headers\n };\n const response = await retryIfServerError(() => fetch(endpoint, request));\n if (!response.ok) {\n throw await getErrorFromResponse('Delete Installation', response);\n }\n}\nfunction getDeleteEndpoint(appConfig, { fid }) {\n return `${getInstallationsEndpoint(appConfig)}/${fid}`;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Deletes the Firebase Installation and all associated data.\n * @param installations - The `Installations` instance.\n *\n * @public\n */\nasync function deleteInstallations(installations) {\n const { appConfig } = installations;\n const entry = await update(appConfig, oldEntry => {\n if (oldEntry && oldEntry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {\n // Delete the unregistered entry without sending a deleteInstallation request.\n return undefined;\n }\n return oldEntry;\n });\n if (entry) {\n if (entry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) {\n // Can't delete while trying to register.\n throw ERROR_FACTORY.create(\"delete-pending-registration\" /* ErrorCode.DELETE_PENDING_REGISTRATION */);\n }\n else if (entry.registrationStatus === 2 /* RequestStatus.COMPLETED */) {\n if (!navigator.onLine) {\n throw ERROR_FACTORY.create(\"app-offline\" /* ErrorCode.APP_OFFLINE */);\n }\n else {\n await deleteInstallationRequest(appConfig, entry);\n await remove(appConfig);\n }\n }\n }\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Sets a new callback that will get called when Installation ID changes.\n * Returns an unsubscribe function that will remove the callback when called.\n * @param installations - The `Installations` instance.\n * @param callback - The callback function that is invoked when FID changes.\n * @returns A function that can be called to unsubscribe.\n *\n * @public\n */\nfunction onIdChange(installations, callback) {\n const { appConfig } = installations;\n addCallback(appConfig, callback);\n return () => {\n removeCallback(appConfig, callback);\n };\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Returns an instance of {@link Installations} associated with the given\n * {@link @firebase/app#FirebaseApp} instance.\n * @param app - The {@link @firebase/app#FirebaseApp} instance.\n *\n * @public\n */\nfunction getInstallations(app = getApp()) {\n const installationsImpl = _getProvider(app, 'installations').getImmediate();\n return installationsImpl;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction extractAppConfig(app) {\n if (!app || !app.options) {\n throw getMissingValueError('App Configuration');\n }\n if (!app.name) {\n throw getMissingValueError('App Name');\n }\n // Required app config keys\n const configKeys = [\n 'projectId',\n 'apiKey',\n 'appId'\n ];\n for (const keyName of configKeys) {\n if (!app.options[keyName]) {\n throw getMissingValueError(keyName);\n }\n }\n return {\n appName: app.name,\n projectId: app.options.projectId,\n apiKey: app.options.apiKey,\n appId: app.options.appId\n };\n}\nfunction getMissingValueError(valueName) {\n return ERROR_FACTORY.create(\"missing-app-config-values\" /* ErrorCode.MISSING_APP_CONFIG_VALUES */, {\n valueName\n });\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst INSTALLATIONS_NAME = 'installations';\nconst INSTALLATIONS_NAME_INTERNAL = 'installations-internal';\nconst publicFactory = (container) => {\n const app = container.getProvider('app').getImmediate();\n // Throws if app isn't configured properly.\n const appConfig = extractAppConfig(app);\n const heartbeatServiceProvider = _getProvider(app, 'heartbeat');\n const installationsImpl = {\n app,\n appConfig,\n heartbeatServiceProvider,\n _delete: () => Promise.resolve()\n };\n return installationsImpl;\n};\nconst internalFactory = (container) => {\n const app = container.getProvider('app').getImmediate();\n // Internal FIS instance relies on public FIS instance.\n const installations = _getProvider(app, INSTALLATIONS_NAME).getImmediate();\n const installationsInternal = {\n getId: () => getId(installations),\n getToken: (forceRefresh) => getToken(installations, forceRefresh)\n };\n return installationsInternal;\n};\nfunction registerInstallations() {\n _registerComponent(new Component(INSTALLATIONS_NAME, publicFactory, \"PUBLIC\" /* ComponentType.PUBLIC */));\n _registerComponent(new Component(INSTALLATIONS_NAME_INTERNAL, internalFactory, \"PRIVATE\" /* ComponentType.PRIVATE */));\n}\n\n/**\n * The Firebase Installations Web SDK.\n * This SDK does not work in a Node.js environment.\n *\n * @packageDocumentation\n */\nregisterInstallations();\nregisterVersion(name, version);\n// BUILD_TARGET will be replaced by values like esm2017, cjs2017, etc during the compilation\nregisterVersion(name, version, 'esm2017');\n\nexport { deleteInstallations, getId, getInstallations, getToken, onIdChange };\n//# sourceMappingURL=index.esm2017.js.map\n","import '@firebase/installations';\nimport { Component } from '@firebase/component';\nimport { openDB, deleteDB } from 'idb';\nimport { ErrorFactory, validateIndexedDBOpenable, isIndexedDBAvailable, areCookiesEnabled, getModularInstance } from '@firebase/util';\nimport { _registerComponent, registerVersion, _getProvider, getApp } from '@firebase/app';\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst DEFAULT_SW_PATH = '/firebase-messaging-sw.js';\nconst DEFAULT_SW_SCOPE = '/firebase-cloud-messaging-push-scope';\nconst DEFAULT_VAPID_KEY = 'BDOU99-h67HcA6JeFXHbSNMu7e2yNNu3RzoMj8TM4W88jITfq7ZmPvIM1Iv-4_l2LxQcYwhqby2xGpWwzjfAnG4';\nconst ENDPOINT = 'https://fcmregistrations.googleapis.com/v1';\nconst CONSOLE_CAMPAIGN_ID = 'google.c.a.c_id';\nconst CONSOLE_CAMPAIGN_NAME = 'google.c.a.c_l';\nconst CONSOLE_CAMPAIGN_TIME = 'google.c.a.ts';\n/** Set to '1' if Analytics is enabled for the campaign */\nconst CONSOLE_CAMPAIGN_ANALYTICS_ENABLED = 'google.c.a.e';\nconst DEFAULT_REGISTRATION_TIMEOUT = 10000;\nvar MessageType$1;\n(function (MessageType) {\n MessageType[MessageType[\"DATA_MESSAGE\"] = 1] = \"DATA_MESSAGE\";\n MessageType[MessageType[\"DISPLAY_NOTIFICATION\"] = 3] = \"DISPLAY_NOTIFICATION\";\n})(MessageType$1 || (MessageType$1 = {}));\n\n/**\n * @license\n * Copyright 2018 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under the License\n * is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\n * or implied. See the License for the specific language governing permissions and limitations under\n * the License.\n */\nvar MessageType;\n(function (MessageType) {\n MessageType[\"PUSH_RECEIVED\"] = \"push-received\";\n MessageType[\"NOTIFICATION_CLICKED\"] = \"notification-clicked\";\n})(MessageType || (MessageType = {}));\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction arrayToBase64(array) {\n const uint8Array = new Uint8Array(array);\n const base64String = btoa(String.fromCharCode(...uint8Array));\n return base64String.replace(/=/g, '').replace(/\\+/g, '-').replace(/\\//g, '_');\n}\nfunction base64ToArray(base64String) {\n const padding = '='.repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding)\n .replace(/\\-/g, '+')\n .replace(/_/g, '/');\n const rawData = atob(base64);\n const outputArray = new Uint8Array(rawData.length);\n for (let i = 0; i < rawData.length; ++i) {\n outputArray[i] = rawData.charCodeAt(i);\n }\n return outputArray;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst OLD_DB_NAME = 'fcm_token_details_db';\n/**\n * The last DB version of 'fcm_token_details_db' was 4. This is one higher, so that the upgrade\n * callback is called for all versions of the old DB.\n */\nconst OLD_DB_VERSION = 5;\nconst OLD_OBJECT_STORE_NAME = 'fcm_token_object_Store';\nasync function migrateOldDatabase(senderId) {\n if ('databases' in indexedDB) {\n // indexedDb.databases() is an IndexedDB v3 API and does not exist in all browsers. TODO: Remove\n // typecast when it lands in TS types.\n const databases = await indexedDB.databases();\n const dbNames = databases.map(db => db.name);\n if (!dbNames.includes(OLD_DB_NAME)) {\n // old DB didn't exist, no need to open.\n return null;\n }\n }\n let tokenDetails = null;\n const db = await openDB(OLD_DB_NAME, OLD_DB_VERSION, {\n upgrade: async (db, oldVersion, newVersion, upgradeTransaction) => {\n var _a;\n if (oldVersion < 2) {\n // Database too old, skip migration.\n return;\n }\n if (!db.objectStoreNames.contains(OLD_OBJECT_STORE_NAME)) {\n // Database did not exist. Nothing to do.\n return;\n }\n const objectStore = upgradeTransaction.objectStore(OLD_OBJECT_STORE_NAME);\n const value = await objectStore.index('fcmSenderId').get(senderId);\n await objectStore.clear();\n if (!value) {\n // No entry in the database, nothing to migrate.\n return;\n }\n if (oldVersion === 2) {\n const oldDetails = value;\n if (!oldDetails.auth || !oldDetails.p256dh || !oldDetails.endpoint) {\n return;\n }\n tokenDetails = {\n token: oldDetails.fcmToken,\n createTime: (_a = oldDetails.createTime) !== null && _a !== void 0 ? _a : Date.now(),\n subscriptionOptions: {\n auth: oldDetails.auth,\n p256dh: oldDetails.p256dh,\n endpoint: oldDetails.endpoint,\n swScope: oldDetails.swScope,\n vapidKey: typeof oldDetails.vapidKey === 'string'\n ? oldDetails.vapidKey\n : arrayToBase64(oldDetails.vapidKey)\n }\n };\n }\n else if (oldVersion === 3) {\n const oldDetails = value;\n tokenDetails = {\n token: oldDetails.fcmToken,\n createTime: oldDetails.createTime,\n subscriptionOptions: {\n auth: arrayToBase64(oldDetails.auth),\n p256dh: arrayToBase64(oldDetails.p256dh),\n endpoint: oldDetails.endpoint,\n swScope: oldDetails.swScope,\n vapidKey: arrayToBase64(oldDetails.vapidKey)\n }\n };\n }\n else if (oldVersion === 4) {\n const oldDetails = value;\n tokenDetails = {\n token: oldDetails.fcmToken,\n createTime: oldDetails.createTime,\n subscriptionOptions: {\n auth: arrayToBase64(oldDetails.auth),\n p256dh: arrayToBase64(oldDetails.p256dh),\n endpoint: oldDetails.endpoint,\n swScope: oldDetails.swScope,\n vapidKey: arrayToBase64(oldDetails.vapidKey)\n }\n };\n }\n }\n });\n db.close();\n // Delete all old databases.\n await deleteDB(OLD_DB_NAME);\n await deleteDB('fcm_vapid_details_db');\n await deleteDB('undefined');\n return checkTokenDetails(tokenDetails) ? tokenDetails : null;\n}\nfunction checkTokenDetails(tokenDetails) {\n if (!tokenDetails || !tokenDetails.subscriptionOptions) {\n return false;\n }\n const { subscriptionOptions } = tokenDetails;\n return (typeof tokenDetails.createTime === 'number' &&\n tokenDetails.createTime > 0 &&\n typeof tokenDetails.token === 'string' &&\n tokenDetails.token.length > 0 &&\n typeof subscriptionOptions.auth === 'string' &&\n subscriptionOptions.auth.length > 0 &&\n typeof subscriptionOptions.p256dh === 'string' &&\n subscriptionOptions.p256dh.length > 0 &&\n typeof subscriptionOptions.endpoint === 'string' &&\n subscriptionOptions.endpoint.length > 0 &&\n typeof subscriptionOptions.swScope === 'string' &&\n subscriptionOptions.swScope.length > 0 &&\n typeof subscriptionOptions.vapidKey === 'string' &&\n subscriptionOptions.vapidKey.length > 0);\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// Exported for tests.\nconst DATABASE_NAME = 'firebase-messaging-database';\nconst DATABASE_VERSION = 1;\nconst OBJECT_STORE_NAME = 'firebase-messaging-store';\nlet dbPromise = null;\nfunction getDbPromise() {\n if (!dbPromise) {\n dbPromise = openDB(DATABASE_NAME, DATABASE_VERSION, {\n upgrade: (upgradeDb, oldVersion) => {\n // We don't use 'break' in this switch statement, the fall-through behavior is what we want,\n // because if there are multiple versions between the old version and the current version, we\n // want ALL the migrations that correspond to those versions to run, not only the last one.\n // eslint-disable-next-line default-case\n switch (oldVersion) {\n case 0:\n upgradeDb.createObjectStore(OBJECT_STORE_NAME);\n }\n }\n });\n }\n return dbPromise;\n}\n/** Gets record(s) from the objectStore that match the given key. */\nasync function dbGet(firebaseDependencies) {\n const key = getKey(firebaseDependencies);\n const db = await getDbPromise();\n const tokenDetails = (await db\n .transaction(OBJECT_STORE_NAME)\n .objectStore(OBJECT_STORE_NAME)\n .get(key));\n if (tokenDetails) {\n return tokenDetails;\n }\n else {\n // Check if there is a tokenDetails object in the old DB.\n const oldTokenDetails = await migrateOldDatabase(firebaseDependencies.appConfig.senderId);\n if (oldTokenDetails) {\n await dbSet(firebaseDependencies, oldTokenDetails);\n return oldTokenDetails;\n }\n }\n}\n/** Assigns or overwrites the record for the given key with the given value. */\nasync function dbSet(firebaseDependencies, tokenDetails) {\n const key = getKey(firebaseDependencies);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n await tx.objectStore(OBJECT_STORE_NAME).put(tokenDetails, key);\n await tx.done;\n return tokenDetails;\n}\n/** Removes record(s) from the objectStore that match the given key. */\nasync function dbRemove(firebaseDependencies) {\n const key = getKey(firebaseDependencies);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n await tx.objectStore(OBJECT_STORE_NAME).delete(key);\n await tx.done;\n}\nfunction getKey({ appConfig }) {\n return appConfig.appId;\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst ERROR_MAP = {\n [\"missing-app-config-values\" /* ErrorCode.MISSING_APP_CONFIG_VALUES */]: 'Missing App configuration value: \"{$valueName}\"',\n [\"only-available-in-window\" /* ErrorCode.AVAILABLE_IN_WINDOW */]: 'This method is available in a Window context.',\n [\"only-available-in-sw\" /* ErrorCode.AVAILABLE_IN_SW */]: 'This method is available in a service worker context.',\n [\"permission-default\" /* ErrorCode.PERMISSION_DEFAULT */]: 'The notification permission was not granted and dismissed instead.',\n [\"permission-blocked\" /* ErrorCode.PERMISSION_BLOCKED */]: 'The notification permission was not granted and blocked instead.',\n [\"unsupported-browser\" /* ErrorCode.UNSUPPORTED_BROWSER */]: \"This browser doesn't support the API's required to use the Firebase SDK.\",\n [\"indexed-db-unsupported\" /* ErrorCode.INDEXED_DB_UNSUPPORTED */]: \"This browser doesn't support indexedDb.open() (ex. Safari iFrame, Firefox Private Browsing, etc)\",\n [\"failed-service-worker-registration\" /* ErrorCode.FAILED_DEFAULT_REGISTRATION */]: 'We are unable to register the default service worker. {$browserErrorMessage}',\n [\"token-subscribe-failed\" /* ErrorCode.TOKEN_SUBSCRIBE_FAILED */]: 'A problem occurred while subscribing the user to FCM: {$errorInfo}',\n [\"token-subscribe-no-token\" /* ErrorCode.TOKEN_SUBSCRIBE_NO_TOKEN */]: 'FCM returned no token when subscribing the user to push.',\n [\"token-unsubscribe-failed\" /* ErrorCode.TOKEN_UNSUBSCRIBE_FAILED */]: 'A problem occurred while unsubscribing the ' +\n 'user from FCM: {$errorInfo}',\n [\"token-update-failed\" /* ErrorCode.TOKEN_UPDATE_FAILED */]: 'A problem occurred while updating the user from FCM: {$errorInfo}',\n [\"token-update-no-token\" /* ErrorCode.TOKEN_UPDATE_NO_TOKEN */]: 'FCM returned no token when updating the user to push.',\n [\"use-sw-after-get-token\" /* ErrorCode.USE_SW_AFTER_GET_TOKEN */]: 'The useServiceWorker() method may only be called once and must be ' +\n 'called before calling getToken() to ensure your service worker is used.',\n [\"invalid-sw-registration\" /* ErrorCode.INVALID_SW_REGISTRATION */]: 'The input to useServiceWorker() must be a ServiceWorkerRegistration.',\n [\"invalid-bg-handler\" /* ErrorCode.INVALID_BG_HANDLER */]: 'The input to setBackgroundMessageHandler() must be a function.',\n [\"invalid-vapid-key\" /* ErrorCode.INVALID_VAPID_KEY */]: 'The public VAPID key must be a string.',\n [\"use-vapid-key-after-get-token\" /* ErrorCode.USE_VAPID_KEY_AFTER_GET_TOKEN */]: 'The usePublicVapidKey() method may only be called once and must be ' +\n 'called before calling getToken() to ensure your VAPID key is used.'\n};\nconst ERROR_FACTORY = new ErrorFactory('messaging', 'Messaging', ERROR_MAP);\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function requestGetToken(firebaseDependencies, subscriptionOptions) {\n const headers = await getHeaders(firebaseDependencies);\n const body = getBody(subscriptionOptions);\n const subscribeOptions = {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n };\n let responseData;\n try {\n const response = await fetch(getEndpoint(firebaseDependencies.appConfig), subscribeOptions);\n responseData = await response.json();\n }\n catch (err) {\n throw ERROR_FACTORY.create(\"token-subscribe-failed\" /* ErrorCode.TOKEN_SUBSCRIBE_FAILED */, {\n errorInfo: err === null || err === void 0 ? void 0 : err.toString()\n });\n }\n if (responseData.error) {\n const message = responseData.error.message;\n throw ERROR_FACTORY.create(\"token-subscribe-failed\" /* ErrorCode.TOKEN_SUBSCRIBE_FAILED */, {\n errorInfo: message\n });\n }\n if (!responseData.token) {\n throw ERROR_FACTORY.create(\"token-subscribe-no-token\" /* ErrorCode.TOKEN_SUBSCRIBE_NO_TOKEN */);\n }\n return responseData.token;\n}\nasync function requestUpdateToken(firebaseDependencies, tokenDetails) {\n const headers = await getHeaders(firebaseDependencies);\n const body = getBody(tokenDetails.subscriptionOptions);\n const updateOptions = {\n method: 'PATCH',\n headers,\n body: JSON.stringify(body)\n };\n let responseData;\n try {\n const response = await fetch(`${getEndpoint(firebaseDependencies.appConfig)}/${tokenDetails.token}`, updateOptions);\n responseData = await response.json();\n }\n catch (err) {\n throw ERROR_FACTORY.create(\"token-update-failed\" /* ErrorCode.TOKEN_UPDATE_FAILED */, {\n errorInfo: err === null || err === void 0 ? void 0 : err.toString()\n });\n }\n if (responseData.error) {\n const message = responseData.error.message;\n throw ERROR_FACTORY.create(\"token-update-failed\" /* ErrorCode.TOKEN_UPDATE_FAILED */, {\n errorInfo: message\n });\n }\n if (!responseData.token) {\n throw ERROR_FACTORY.create(\"token-update-no-token\" /* ErrorCode.TOKEN_UPDATE_NO_TOKEN */);\n }\n return responseData.token;\n}\nasync function requestDeleteToken(firebaseDependencies, token) {\n const headers = await getHeaders(firebaseDependencies);\n const unsubscribeOptions = {\n method: 'DELETE',\n headers\n };\n try {\n const response = await fetch(`${getEndpoint(firebaseDependencies.appConfig)}/${token}`, unsubscribeOptions);\n const responseData = await response.json();\n if (responseData.error) {\n const message = responseData.error.message;\n throw ERROR_FACTORY.create(\"token-unsubscribe-failed\" /* ErrorCode.TOKEN_UNSUBSCRIBE_FAILED */, {\n errorInfo: message\n });\n }\n }\n catch (err) {\n throw ERROR_FACTORY.create(\"token-unsubscribe-failed\" /* ErrorCode.TOKEN_UNSUBSCRIBE_FAILED */, {\n errorInfo: err === null || err === void 0 ? void 0 : err.toString()\n });\n }\n}\nfunction getEndpoint({ projectId }) {\n return `${ENDPOINT}/projects/${projectId}/registrations`;\n}\nasync function getHeaders({ appConfig, installations }) {\n const authToken = await installations.getToken();\n return new Headers({\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n 'x-goog-api-key': appConfig.apiKey,\n 'x-goog-firebase-installations-auth': `FIS ${authToken}`\n });\n}\nfunction getBody({ p256dh, auth, endpoint, vapidKey }) {\n const body = {\n web: {\n endpoint,\n auth,\n p256dh\n }\n };\n if (vapidKey !== DEFAULT_VAPID_KEY) {\n body.web.applicationPubKey = vapidKey;\n }\n return body;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// UpdateRegistration will be called once every week.\nconst TOKEN_EXPIRATION_MS = 7 * 24 * 60 * 60 * 1000; // 7 days\nasync function getTokenInternal(messaging) {\n const pushSubscription = await getPushSubscription(messaging.swRegistration, messaging.vapidKey);\n const subscriptionOptions = {\n vapidKey: messaging.vapidKey,\n swScope: messaging.swRegistration.scope,\n endpoint: pushSubscription.endpoint,\n auth: arrayToBase64(pushSubscription.getKey('auth')),\n p256dh: arrayToBase64(pushSubscription.getKey('p256dh'))\n };\n const tokenDetails = await dbGet(messaging.firebaseDependencies);\n if (!tokenDetails) {\n // No token, get a new one.\n return getNewToken(messaging.firebaseDependencies, subscriptionOptions);\n }\n else if (!isTokenValid(tokenDetails.subscriptionOptions, subscriptionOptions)) {\n // Invalid token, get a new one.\n try {\n await requestDeleteToken(messaging.firebaseDependencies, tokenDetails.token);\n }\n catch (e) {\n // Suppress errors because of #2364\n console.warn(e);\n }\n return getNewToken(messaging.firebaseDependencies, subscriptionOptions);\n }\n else if (Date.now() >= tokenDetails.createTime + TOKEN_EXPIRATION_MS) {\n // Weekly token refresh\n return updateToken(messaging, {\n token: tokenDetails.token,\n createTime: Date.now(),\n subscriptionOptions\n });\n }\n else {\n // Valid token, nothing to do.\n return tokenDetails.token;\n }\n}\n/**\n * This method deletes the token from the database, unsubscribes the token from FCM, and unregisters\n * the push subscription if it exists.\n */\nasync function deleteTokenInternal(messaging) {\n const tokenDetails = await dbGet(messaging.firebaseDependencies);\n if (tokenDetails) {\n await requestDeleteToken(messaging.firebaseDependencies, tokenDetails.token);\n await dbRemove(messaging.firebaseDependencies);\n }\n // Unsubscribe from the push subscription.\n const pushSubscription = await messaging.swRegistration.pushManager.getSubscription();\n if (pushSubscription) {\n return pushSubscription.unsubscribe();\n }\n // If there's no SW, consider it a success.\n return true;\n}\nasync function updateToken(messaging, tokenDetails) {\n try {\n const updatedToken = await requestUpdateToken(messaging.firebaseDependencies, tokenDetails);\n const updatedTokenDetails = Object.assign(Object.assign({}, tokenDetails), { token: updatedToken, createTime: Date.now() });\n await dbSet(messaging.firebaseDependencies, updatedTokenDetails);\n return updatedToken;\n }\n catch (e) {\n throw e;\n }\n}\nasync function getNewToken(firebaseDependencies, subscriptionOptions) {\n const token = await requestGetToken(firebaseDependencies, subscriptionOptions);\n const tokenDetails = {\n token,\n createTime: Date.now(),\n subscriptionOptions\n };\n await dbSet(firebaseDependencies, tokenDetails);\n return tokenDetails.token;\n}\n/**\n * Gets a PushSubscription for the current user.\n */\nasync function getPushSubscription(swRegistration, vapidKey) {\n const subscription = await swRegistration.pushManager.getSubscription();\n if (subscription) {\n return subscription;\n }\n return swRegistration.pushManager.subscribe({\n userVisibleOnly: true,\n // Chrome <= 75 doesn't support base64-encoded VAPID key. For backward compatibility, VAPID key\n // submitted to pushManager#subscribe must be of type Uint8Array.\n applicationServerKey: base64ToArray(vapidKey)\n });\n}\n/**\n * Checks if the saved tokenDetails object matches the configuration provided.\n */\nfunction isTokenValid(dbOptions, currentOptions) {\n const isVapidKeyEqual = currentOptions.vapidKey === dbOptions.vapidKey;\n const isEndpointEqual = currentOptions.endpoint === dbOptions.endpoint;\n const isAuthEqual = currentOptions.auth === dbOptions.auth;\n const isP256dhEqual = currentOptions.p256dh === dbOptions.p256dh;\n return isVapidKeyEqual && isEndpointEqual && isAuthEqual && isP256dhEqual;\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction externalizePayload(internalPayload) {\n const payload = {\n from: internalPayload.from,\n // eslint-disable-next-line camelcase\n collapseKey: internalPayload.collapse_key,\n // eslint-disable-next-line camelcase\n messageId: internalPayload.fcmMessageId\n };\n propagateNotificationPayload(payload, internalPayload);\n propagateDataPayload(payload, internalPayload);\n propagateFcmOptions(payload, internalPayload);\n return payload;\n}\nfunction propagateNotificationPayload(payload, messagePayloadInternal) {\n if (!messagePayloadInternal.notification) {\n return;\n }\n payload.notification = {};\n const title = messagePayloadInternal.notification.title;\n if (!!title) {\n payload.notification.title = title;\n }\n const body = messagePayloadInternal.notification.body;\n if (!!body) {\n payload.notification.body = body;\n }\n const image = messagePayloadInternal.notification.image;\n if (!!image) {\n payload.notification.image = image;\n }\n const icon = messagePayloadInternal.notification.icon;\n if (!!icon) {\n payload.notification.icon = icon;\n }\n}\nfunction propagateDataPayload(payload, messagePayloadInternal) {\n if (!messagePayloadInternal.data) {\n return;\n }\n payload.data = messagePayloadInternal.data;\n}\nfunction propagateFcmOptions(payload, messagePayloadInternal) {\n var _a, _b, _c, _d, _e;\n // fcmOptions.link value is written into notification.click_action. see more in b/232072111\n if (!messagePayloadInternal.fcmOptions &&\n !((_a = messagePayloadInternal.notification) === null || _a === void 0 ? void 0 : _a.click_action)) {\n return;\n }\n payload.fcmOptions = {};\n const link = (_c = (_b = messagePayloadInternal.fcmOptions) === null || _b === void 0 ? void 0 : _b.link) !== null && _c !== void 0 ? _c : (_d = messagePayloadInternal.notification) === null || _d === void 0 ? void 0 : _d.click_action;\n if (!!link) {\n payload.fcmOptions.link = link;\n }\n // eslint-disable-next-line camelcase\n const analyticsLabel = (_e = messagePayloadInternal.fcmOptions) === null || _e === void 0 ? void 0 : _e.analytics_label;\n if (!!analyticsLabel) {\n payload.fcmOptions.analyticsLabel = analyticsLabel;\n }\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction isConsoleMessage(data) {\n // This message has a campaign ID, meaning it was sent using the Firebase Console.\n return typeof data === 'object' && !!data && CONSOLE_CAMPAIGN_ID in data;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n_mergeStrings('AzSCbw63g1R0nCw85jG8', 'Iaya3yLKwmgvh7cF0q4');\nfunction _mergeStrings(s1, s2) {\n const resultArray = [];\n for (let i = 0; i < s1.length; i++) {\n resultArray.push(s1.charAt(i));\n if (i < s2.length) {\n resultArray.push(s2.charAt(i));\n }\n }\n return resultArray.join('');\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction extractAppConfig(app) {\n if (!app || !app.options) {\n throw getMissingValueError('App Configuration Object');\n }\n if (!app.name) {\n throw getMissingValueError('App Name');\n }\n // Required app config keys\n const configKeys = [\n 'projectId',\n 'apiKey',\n 'appId',\n 'messagingSenderId'\n ];\n const { options } = app;\n for (const keyName of configKeys) {\n if (!options[keyName]) {\n throw getMissingValueError(keyName);\n }\n }\n return {\n appName: app.name,\n projectId: options.projectId,\n apiKey: options.apiKey,\n appId: options.appId,\n senderId: options.messagingSenderId\n };\n}\nfunction getMissingValueError(valueName) {\n return ERROR_FACTORY.create(\"missing-app-config-values\" /* ErrorCode.MISSING_APP_CONFIG_VALUES */, {\n valueName\n });\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nclass MessagingService {\n constructor(app, installations, analyticsProvider) {\n // logging is only done with end user consent. Default to false.\n this.deliveryMetricsExportedToBigQueryEnabled = false;\n this.onBackgroundMessageHandler = null;\n this.onMessageHandler = null;\n this.logEvents = [];\n this.isLogServiceStarted = false;\n const appConfig = extractAppConfig(app);\n this.firebaseDependencies = {\n app,\n appConfig,\n installations,\n analyticsProvider\n };\n }\n _delete() {\n return Promise.resolve();\n }\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function registerDefaultSw(messaging) {\n try {\n messaging.swRegistration = await navigator.serviceWorker.register(DEFAULT_SW_PATH, {\n scope: DEFAULT_SW_SCOPE\n });\n // The timing when browser updates sw when sw has an update is unreliable from experiment. It\n // leads to version conflict when the SDK upgrades to a newer version in the main page, but sw\n // is stuck with the old version. For example,\n // https://github.com/firebase/firebase-js-sdk/issues/2590 The following line reliably updates\n // sw if there was an update.\n messaging.swRegistration.update().catch(() => {\n /* it is non blocking and we don't care if it failed */\n });\n await waitForRegistrationActive(messaging.swRegistration);\n }\n catch (e) {\n throw ERROR_FACTORY.create(\"failed-service-worker-registration\" /* ErrorCode.FAILED_DEFAULT_REGISTRATION */, {\n browserErrorMessage: e === null || e === void 0 ? void 0 : e.message\n });\n }\n}\n/**\n * Waits for registration to become active. MDN documentation claims that\n * a service worker registration should be ready to use after awaiting\n * navigator.serviceWorker.register() but that doesn't seem to be the case in\n * practice, causing the SDK to throw errors when calling\n * swRegistration.pushManager.subscribe() too soon after register(). The only\n * solution seems to be waiting for the service worker registration `state`\n * to become \"active\".\n */\nasync function waitForRegistrationActive(registration) {\n return new Promise((resolve, reject) => {\n const rejectTimeout = setTimeout(() => reject(new Error(`Service worker not registered after ${DEFAULT_REGISTRATION_TIMEOUT} ms`)), DEFAULT_REGISTRATION_TIMEOUT);\n const incomingSw = registration.installing || registration.waiting;\n if (registration.active) {\n clearTimeout(rejectTimeout);\n resolve();\n }\n else if (incomingSw) {\n incomingSw.onstatechange = ev => {\n var _a;\n if (((_a = ev.target) === null || _a === void 0 ? void 0 : _a.state) === 'activated') {\n incomingSw.onstatechange = null;\n clearTimeout(rejectTimeout);\n resolve();\n }\n };\n }\n else {\n clearTimeout(rejectTimeout);\n reject(new Error('No incoming service worker found.'));\n }\n });\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function updateSwReg(messaging, swRegistration) {\n if (!swRegistration && !messaging.swRegistration) {\n await registerDefaultSw(messaging);\n }\n if (!swRegistration && !!messaging.swRegistration) {\n return;\n }\n if (!(swRegistration instanceof ServiceWorkerRegistration)) {\n throw ERROR_FACTORY.create(\"invalid-sw-registration\" /* ErrorCode.INVALID_SW_REGISTRATION */);\n }\n messaging.swRegistration = swRegistration;\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function updateVapidKey(messaging, vapidKey) {\n if (!!vapidKey) {\n messaging.vapidKey = vapidKey;\n }\n else if (!messaging.vapidKey) {\n messaging.vapidKey = DEFAULT_VAPID_KEY;\n }\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function getToken$1(messaging, options) {\n if (!navigator) {\n throw ERROR_FACTORY.create(\"only-available-in-window\" /* ErrorCode.AVAILABLE_IN_WINDOW */);\n }\n if (Notification.permission === 'default') {\n await Notification.requestPermission();\n }\n if (Notification.permission !== 'granted') {\n throw ERROR_FACTORY.create(\"permission-blocked\" /* ErrorCode.PERMISSION_BLOCKED */);\n }\n await updateVapidKey(messaging, options === null || options === void 0 ? void 0 : options.vapidKey);\n await updateSwReg(messaging, options === null || options === void 0 ? void 0 : options.serviceWorkerRegistration);\n return getTokenInternal(messaging);\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function logToScion(messaging, messageType, data) {\n const eventType = getEventType(messageType);\n const analytics = await messaging.firebaseDependencies.analyticsProvider.get();\n analytics.logEvent(eventType, {\n /* eslint-disable camelcase */\n message_id: data[CONSOLE_CAMPAIGN_ID],\n message_name: data[CONSOLE_CAMPAIGN_NAME],\n message_time: data[CONSOLE_CAMPAIGN_TIME],\n message_device_time: Math.floor(Date.now() / 1000)\n /* eslint-enable camelcase */\n });\n}\nfunction getEventType(messageType) {\n switch (messageType) {\n case MessageType.NOTIFICATION_CLICKED:\n return 'notification_open';\n case MessageType.PUSH_RECEIVED:\n return 'notification_foreground';\n default:\n throw new Error();\n }\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function messageEventListener(messaging, event) {\n const internalPayload = event.data;\n if (!internalPayload.isFirebaseMessaging) {\n return;\n }\n if (messaging.onMessageHandler &&\n internalPayload.messageType === MessageType.PUSH_RECEIVED) {\n if (typeof messaging.onMessageHandler === 'function') {\n messaging.onMessageHandler(externalizePayload(internalPayload));\n }\n else {\n messaging.onMessageHandler.next(externalizePayload(internalPayload));\n }\n }\n // Log to Scion if applicable\n const dataPayload = internalPayload.data;\n if (isConsoleMessage(dataPayload) &&\n dataPayload[CONSOLE_CAMPAIGN_ANALYTICS_ENABLED] === '1') {\n await logToScion(messaging, internalPayload.messageType, dataPayload);\n }\n}\n\nconst name = \"@firebase/messaging\";\nconst version = \"0.12.22\";\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst WindowMessagingFactory = (container) => {\n const messaging = new MessagingService(container.getProvider('app').getImmediate(), container.getProvider('installations-internal').getImmediate(), container.getProvider('analytics-internal'));\n navigator.serviceWorker.addEventListener('message', e => messageEventListener(messaging, e));\n return messaging;\n};\nconst WindowMessagingInternalFactory = (container) => {\n const messaging = container\n .getProvider('messaging')\n .getImmediate();\n const messagingInternal = {\n getToken: (options) => getToken$1(messaging, options)\n };\n return messagingInternal;\n};\nfunction registerMessagingInWindow() {\n _registerComponent(new Component('messaging', WindowMessagingFactory, \"PUBLIC\" /* ComponentType.PUBLIC */));\n _registerComponent(new Component('messaging-internal', WindowMessagingInternalFactory, \"PRIVATE\" /* ComponentType.PRIVATE */));\n registerVersion(name, version);\n // BUILD_TARGET will be replaced by values like esm2017, cjs2017, etc during the compilation\n registerVersion(name, version, 'esm2017');\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Checks if all required APIs exist in the browser.\n * @returns a Promise that resolves to a boolean.\n *\n * @public\n */\nasync function isWindowSupported() {\n try {\n // This throws if open() is unsupported, so adding it to the conditional\n // statement below can cause an uncaught error.\n await validateIndexedDBOpenable();\n }\n catch (e) {\n return false;\n }\n // firebase-js-sdk/issues/2393 reveals that idb#open in Safari iframe and Firefox private browsing\n // might be prohibited to run. In these contexts, an error would be thrown during the messaging\n // instantiating phase, informing the developers to import/call isSupported for special handling.\n return (typeof window !== 'undefined' &&\n isIndexedDBAvailable() &&\n areCookiesEnabled() &&\n 'serviceWorker' in navigator &&\n 'PushManager' in window &&\n 'Notification' in window &&\n 'fetch' in window &&\n ServiceWorkerRegistration.prototype.hasOwnProperty('showNotification') &&\n PushSubscription.prototype.hasOwnProperty('getKey'));\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function deleteToken$1(messaging) {\n if (!navigator) {\n throw ERROR_FACTORY.create(\"only-available-in-window\" /* ErrorCode.AVAILABLE_IN_WINDOW */);\n }\n if (!messaging.swRegistration) {\n await registerDefaultSw(messaging);\n }\n return deleteTokenInternal(messaging);\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction onMessage$1(messaging, nextOrObserver) {\n if (!navigator) {\n throw ERROR_FACTORY.create(\"only-available-in-window\" /* ErrorCode.AVAILABLE_IN_WINDOW */);\n }\n messaging.onMessageHandler = nextOrObserver;\n return () => {\n messaging.onMessageHandler = null;\n };\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Retrieves a Firebase Cloud Messaging instance.\n *\n * @returns The Firebase Cloud Messaging instance associated with the provided firebase app.\n *\n * @public\n */\nfunction getMessagingInWindow(app = getApp()) {\n // Conscious decision to make this async check non-blocking during the messaging instance\n // initialization phase for performance consideration. An error would be thrown latter for\n // developer's information. Developers can then choose to import and call `isSupported` for\n // special handling.\n isWindowSupported().then(isSupported => {\n // If `isWindowSupported()` resolved, but returned false.\n if (!isSupported) {\n throw ERROR_FACTORY.create(\"unsupported-browser\" /* ErrorCode.UNSUPPORTED_BROWSER */);\n }\n }, _ => {\n // If `isWindowSupported()` rejected.\n throw ERROR_FACTORY.create(\"indexed-db-unsupported\" /* ErrorCode.INDEXED_DB_UNSUPPORTED */);\n });\n return _getProvider(getModularInstance(app), 'messaging').getImmediate();\n}\n/**\n * Subscribes the {@link Messaging} instance to push notifications. Returns a Firebase Cloud\n * Messaging registration token that can be used to send push messages to that {@link Messaging}\n * instance.\n *\n * If notification permission isn't already granted, this method asks the user for permission. The\n * returned promise rejects if the user does not allow the app to show notifications.\n *\n * @param messaging - The {@link Messaging} instance.\n * @param options - Provides an optional vapid key and an optional service worker registration.\n *\n * @returns The promise resolves with an FCM registration token.\n *\n * @public\n */\nasync function getToken(messaging, options) {\n messaging = getModularInstance(messaging);\n return getToken$1(messaging, options);\n}\n/**\n * Deletes the registration token associated with this {@link Messaging} instance and unsubscribes\n * the {@link Messaging} instance from the push subscription.\n *\n * @param messaging - The {@link Messaging} instance.\n *\n * @returns The promise resolves when the token has been successfully deleted.\n *\n * @public\n */\nfunction deleteToken(messaging) {\n messaging = getModularInstance(messaging);\n return deleteToken$1(messaging);\n}\n/**\n * When a push message is received and the user is currently on a page for your origin, the\n * message is passed to the page and an `onMessage()` event is dispatched with the payload of\n * the push message.\n *\n *\n * @param messaging - The {@link Messaging} instance.\n * @param nextOrObserver - This function, or observer object with `next` defined,\n * is called when a message is received and the user is currently viewing your page.\n * @returns To stop listening for messages execute this returned function.\n *\n * @public\n */\nfunction onMessage(messaging, nextOrObserver) {\n messaging = getModularInstance(messaging);\n return onMessage$1(messaging, nextOrObserver);\n}\n\n/**\n * The Firebase Cloud Messaging Web SDK.\n * This SDK does not work in a Node.js environment.\n *\n * @packageDocumentation\n */\nregisterMessagingInWindow();\n\nexport { deleteToken, getMessagingInWindow as getMessaging, getToken, isWindowSupported as isSupported, onMessage };\n//# sourceMappingURL=index.esm2017.js.map\n","import React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nexport default class Alert extends React.PureComponent {\n render() {\n return (
\n
\n
{this.props.title}
\n
{this.props.content}
\n
\n {this.props.onReject ?\n \n {this.props.reject || }\n \n :\n null\n }\n {this.props.onConfirm ?\n \n {this.props.confirm || }\n \n :\n null\n }\n
\n
\n
);\n }\n};\n","// Context Menu: popup/dropdown menu.\nimport React from 'react';\nimport { injectIntl, defineMessages } from 'react-intl';\n\nimport { REM_SIZE } from '../config.js';\n\nconst messages = defineMessages({\n info: {\n id: 'menu_item_info',\n defaultMessage: 'Info',\n description: 'Show extended topic information'\n },\n clear_messages: {\n id: 'menu_item_clear_messages',\n defaultMessage: 'Clear messages',\n description: 'Delete all messages'\n },\n clear_for_all: {\n id: 'menu_item_clear_messages_for_all',\n defaultMessage: 'Clear for All',\n description: 'Delete all message(s) for all members'\n },\n delete: {\n id: 'menu_item_delete',\n defaultMessage: 'Delete',\n description: 'Delete selected messages'\n },\n delete_for_all: {\n id: 'menu_item_delete_for_all',\n defaultMessage: 'Delete for All',\n description: 'Delete selected message(s) for all members'\n },\n send_retry: {\n id: 'menu_item_send_retry',\n defaultMessage: 'Retry',\n description: 'Retry sending message'\n },\n mute: {\n id: 'menu_item_mute',\n defaultMessage: 'Mute',\n description: 'Turn off notifications'\n },\n unmute: {\n id: 'menu_item_unmute',\n defaultMessage: 'Unmute',\n description: 'Turn notifications on'\n },\n reply: {\n id: 'menu_item_reply',\n defaultMessage: 'Reply',\n description: 'Reply to message'\n },\n forward: {\n id: 'menu_item_forward',\n defaultMessage: 'Forward',\n description: 'Forward message'\n },\n edit: {\n id: 'menu_item_edit',\n defaultMessage: 'Edit',\n description: 'Edit message'\n },\n topic_delete: {\n id: 'menu_item_delete_topic',\n defaultMessage: 'Delete',\n description: 'Delete entire topic'\n },\n topic_delete_warning: {\n id: 'topic_delete_warning',\n defaultMessage: 'Are you sure you want to delete this conversation? It cannot be undone.',\n description: 'Alert warning when deleting entire topic'\n },\n delete_messages_warning: {\n id: 'delete_messages_warning',\n defaultMessage: 'Are you sure you want to delete all messages for everyone? It cannot be undone.',\n description: 'Alert dialog warning when hard-deleting all messages.'\n },\n unblock: {\n id: 'menu_item_unblock',\n defaultMessage: 'Unblock',\n description: 'Unblock topic or user'\n },\n // Generic string suitable for either topic or user.\n block: {\n id: 'menu_item_block',\n defaultMessage: 'Block',\n description: 'Block topic or user'\n },\n topic_block_warning: {\n id: 'topic_block_warning',\n defaultMessage: 'Are you sure you want to block this conversation?',\n description: 'Alert warning when blocking a topic.'\n },\n member_delete: {\n id: 'menu_item_member_delete',\n defaultMessage: 'Remove',\n description: 'Remove user from topic'\n },\n archive: {\n id: 'menu_item_archive_topic',\n defaultMessage: 'Archive',\n description: 'Move topic from the list of active chats to archive'\n },\n unarchive: {\n id: 'menu_item_restore_topic',\n defaultMessage: 'Restore',\n description: 'Restore topic from archive'\n },\n edit_permissions: {\n id: 'menu_item_edit_permissions',\n defaultMessage: 'Edit permissions',\n description: 'Menu item [Edit permissions]'\n },\n clear_messages_warning: {\n id: 'clear_messages_warning',\n defaultMessage: 'Are you sure you want to clear all messages? It cannot be undone.',\n description: 'Alert dialog warning when deleting all messages.'\n },\n pin_message: {\n id: 'pin_message',\n defaultMessage: 'Pin',\n description: 'Menu item [Pin] for pinning message to the top.'\n },\n unpin_message: {\n id: 'unpin_message',\n defaultMessage: 'Unpin',\n description: 'Menu item [Unpin] for un-pinning the message.'\n },\n});\n\nclass ContextMenu extends React.Component {\n constructor(props) {\n super(props);\n\n this.selfRef = React.createRef();\n\n const {formatMessage} = props.intl;\n\n this.handlePageClick = this.handlePageClick.bind(this);\n this.handleEscapeKey = this.handleEscapeKey.bind(this);\n this.handleClick = this.handleClick.bind(this);\n\n // Preconfigured menu items.\n this.MenuItems = {\n 'topic_info': {\n id: 'topic_info',\n title: formatMessage(messages.info),\n handler: null\n },\n 'messages_clear': {\n id: 'messages_clear',\n title: formatMessage(messages.clear_messages),\n handler: (params, errorHandler) => {\n return props.onShowAlert(\n formatMessage(messages.clear_messages), // title\n formatMessage(messages.clear_messages_warning), // content\n (_ => { this.deleteMessages(true, false, params, errorHandler); }), // onConfirm\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n },\n 'messages_clear_hard': {\n id: 'messages_clear_hard',\n title: formatMessage(messages.clear_for_all),\n handler: (params, errorHandler) => {\n return props.onShowAlert(\n formatMessage(messages.clear_for_all), // title\n formatMessage(messages.delete_messages_warning), // content\n (_ => { return this.deleteMessages(true, true, params, errorHandler); }),\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n },\n 'message_delete': {\n id: 'message_delete',\n title: formatMessage(messages.delete),\n handler: (params, errorHandler) => {\n return this.deleteMessages(false, false, params, errorHandler);\n }\n },\n 'message_delete_hard': {\n id: 'message_delete_hard',\n title: formatMessage(messages.delete_for_all),\n handler: (params, errorHandler) => {\n return this.deleteMessages(false, true, params, errorHandler);\n }\n },\n // Hard-delete but with just 'Delete' title.\n 'message_delete_generic': {\n id: 'message_delete_generic',\n title: formatMessage(messages.delete),\n handler: (params, errorHandler) => {\n return this.deleteMessages(false, true, params, errorHandler);\n }\n },\n 'menu_item_send_retry': {\n id: 'menu_item_send_retry',\n title: formatMessage(messages.send_retry),\n handler: (params, errorHandler) => {\n return this.retryMessage(params, errorHandler);\n }\n },\n 'menu_item_reply': {\n id: 'menu_item_reply',\n title: formatMessage(messages.reply),\n handler: (params, errorHandler) => {\n return this.replyToMessage(params, errorHandler);\n }\n },\n 'menu_item_forward': {\n id: 'menu_item_forward',\n title: formatMessage(messages.forward),\n handler: _ => {} /* the action is taken directly in tinode-web */\n },\n 'menu_item_edit': {\n id: 'menu_item_edit',\n title: formatMessage(messages.edit),\n handler: (params, errorHandler) => {\n return this.editMessage(params, errorHandler);\n }\n },\n 'menu_item_pin': {\n id: 'menu_item_pin',\n title: formatMessage(messages.pin_message),\n handler: (params, errorHandler) => {\n return this.pinMessage(true, params, errorHandler);\n }\n },\n 'menu_item_unpin': {\n id: 'menu_item_unpin',\n title: formatMessage(messages.unpin_message),\n handler: (params, errorHandler) => {\n return this.pinMessage(false, params, errorHandler);\n }\n },\n 'topic_unmute': {\n id: 'topic_unmute',\n title: formatMessage(messages.unmute),\n handler: this.topicPermissionSetter.bind(this, '+P')\n },\n 'topic_mute': {\n id: 'topic_mute',\n title: formatMessage(messages.mute),\n handler: this.topicPermissionSetter.bind(this, '-P')\n },\n 'topic_unblock': {\n id: 'topic_unblock',\n title: formatMessage(messages.unblock),\n handler: this.topicPermissionSetter.bind(this, '+JP')\n },\n 'topic_block': {\n id: 'topic_block',\n title: formatMessage(messages.block),\n handler: (params, errorHandler) => {\n return props.onShowAlert(\n formatMessage(messages.block), // title\n formatMessage(messages.topic_block_warning), // content\n (_ => this.topicPermissionSetter('-JP', params, errorHandler).then(ctrl => {\n this.props.onTopicRemoved(params.topicName);\n return ctrl;\n })),\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n },\n 'topic_delete': {\n id: 'topic_delete',\n title: formatMessage(messages.topic_delete),\n handler: (params, errorHandler) => {\n return props.onShowAlert(\n formatMessage(messages.topic_delete), // title\n formatMessage(messages.topic_delete_warning), // content\n (_ => {\n const topic = this.props.tinode.getTopic(params.topicName);\n if (!topic) {\n console.warn(\"Topic not found: \", params.topicName);\n return;\n }\n return topic.delTopic(true).catch(err => {\n if (errorHandler) {\n errorHandler(err.message, 'err');\n }\n });\n }),\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n },\n 'topic_archive': {\n id: 'topic_archive',\n title: formatMessage(messages.archive),\n handler: (params, errorHandler) => {\n const topic = this.props.tinode.getTopic(params.topicName);\n if (!topic) {\n console.warn(\"Topic not found: \", params.topicName);\n return;\n }\n return topic.archive(true).catch(err => {\n if (errorHandler) {\n errorHandler(err.message, 'err');\n }\n });\n }\n },\n 'topic_restore': {\n id: 'topic_restore',\n title: formatMessage(messages.unarchive),\n handler: (params, errorHandler) => {\n const topic = this.props.tinode.getTopic(params.topicName);\n if (!topic) {\n console.warn(\"Topic not found: \", params.topicName);\n return;\n }\n return topic.archive(false).catch(err => {\n if (errorHandler) {\n errorHandler(err.message, 'err');\n }\n });\n }\n },\n // menu_item_edit_permissions is defined elsewhere.\n 'permissions': {\n id: 'permissions',\n title: formatMessage(messages.edit_permissions),\n handler: null\n },\n 'member_delete': {\n id: 'member_delete',\n title: formatMessage(messages.member_delete),\n handler: (params, errorHandler) => {\n const topic = this.props.tinode.getTopic(params.topicName);\n if (!topic || !params.user) {\n console.warn(\"Topic or user not found: '\" + params.topicName + \"', '\" + params.user + \"'\");\n return;\n }\n return topic.delSubscription(params.user).catch(err => {\n if (errorHandler) {\n errorHandler(err.message, 'err');\n }\n });\n }\n },\n 'member_mute': {\n id: 'member_mute',\n title: formatMessage(messages.mute),\n handler: this.topicPermissionSetter.bind(this, '-P')\n },\n 'member_unmute': {\n id: 'member_unmute',\n title: formatMessage(messages.unmute),\n handler: this.topicPermissionSetter.bind(this, '+P')\n },\n 'member_block': {\n id: 'member_block',\n title: formatMessage(messages.block),\n handler: this.topicPermissionSetter.bind(this, '-JP')\n },\n 'member_unblock': {\n id: 'member_unblock',\n title: formatMessage(messages.unblock),\n handler: this.topicPermissionSetter.bind(this, '+JP')\n },\n };\n }\n\n componentDidMount() {\n document.addEventListener('mousedown', this.handlePageClick, false);\n document.addEventListener('keyup', this.handleEscapeKey, false);\n }\n\n componentWillUnmount() {\n document.removeEventListener('mousedown', this.handlePageClick, false);\n document.removeEventListener('keyup', this.handleEscapeKey, false);\n }\n\n handlePageClick(e) {\n if (this.selfRef.current.contains(e.target)) {\n return;\n }\n e.preventDefault();\n e.stopPropagation();\n this.props.hide();\n }\n\n handleEscapeKey(e) {\n if (e.keyCode === 27) {\n this.props.hide();\n }\n }\n\n handleClick(e) {\n e.preventDefault();\n e.stopPropagation();\n this.props.hide();\n let item = this.props.items[e.currentTarget.dataset.id];\n if (typeof item == 'string') {\n item = this.MenuItems[item];\n }\n\n if (!item) {\n console.error(\"Invalid menu item ID\", e.currentTarget.dataset.id);\n } else {\n this.props.onAction(\n item.id,\n item.handler(this.props.params, this.props.onError),\n this.props.params);\n }\n }\n\n // Menu Actions\n\n deleteMessages(all, hard, params, errorHandler) {\n const topic = this.props.tinode.getTopic(params.topicName);\n if (!topic) {\n console.warn(\"Topic not found: \", params.topicName);\n return;\n }\n\n // We don't know if the message is still pending (e.g. attachment is being uploaded),\n // so try cancelling first. No harm if we can't cancel.\n // The message can be cancelled if transmission to the server has not\n // started yet or if the message send has failed.\n if (!all && topic.cancelSend(params.seq)) {\n return;\n }\n\n const promise = all ?\n topic.delMessagesAll(hard) :\n params.replace > 0 ?\n topic.delMessagesEdits(params.replace, hard) :\n topic.delMessagesList([params.seq], hard);\n\n return promise.catch(err => {\n if (errorHandler) {\n errorHandler(err.message, 'err');\n }\n });\n }\n\n // Retries sending failed message.\n retryMessage(params, errorHandler) {\n const topic = this.props.tinode.getTopic(params.topicName);\n // Remove the existing message entry.\n if (!topic || !topic.flushMessage(params.seq)) {\n return;\n }\n const msg = topic.createMessage(params.content, false);\n return topic.publishDraft(msg).catch(err => {\n if (errorHandler) {\n errorHandler(err.message, 'err');\n }\n });\n }\n\n // Pin or unpin the message.\n pinMessage(pin, params, errorHandler) {\n const topic = this.props.tinode.getTopic(params.topicName);\n if (!topic) {\n return;\n }\n topic.pinMessage(params.seq, pin)\n .catch(err => errorHandler ? errorHandler(err.message, 'err') : null);\n }\n\n // Function is used by context menu to set permissions.\n topicPermissionSetter(mode, params, errorHandler) {\n const topic = this.props.tinode.getTopic(params.topicName);\n if (!topic) {\n console.warn(\"Topic not found\", params.topicName);\n return;\n }\n\n let result = topic.updateMode(params.user, mode);\n if (errorHandler) {\n result = result.catch(err => errorHandler(err.message, 'err'));\n }\n return result;\n }\n\n replyToMessage(params, errorHandler) {\n params.pickReply(params.seq, params.content, params.userFrom, params.userName, errorHandler);\n }\n\n editMessage(params, errorHandler) {\n params.editMessage(params.replace || params.seq, params.content, errorHandler);\n }\n\n render() {\n const menu = [];\n let count = 0;\n this.props.items.forEach(item => {\n if (typeof item == 'string') {\n item = this.MenuItems[item];\n }\n if (item && item.title) {\n const className = item.disabled ? 'disabled' : undefined;\n menu.push(\n item.title == '-' ?\n \n :\n {item.title} \n );\n }\n count++;\n });\n\n // Ensure that menu is inside the app-container.\n const hSize = 12 * REM_SIZE;\n const vSize = REM_SIZE * (0.7 + menu.length * 2.5);\n const left = (this.props.bounds.right - this.props.clickAt.x < hSize) ?\n (this.props.clickAt.x - this.props.bounds.left - hSize) :\n (this.props.clickAt.x - this.props.bounds.left);\n const top = (this.props.bounds.bottom - this.props.clickAt.y < vSize) ?\n (this.props.clickAt.y - this.props.bounds.top - vSize) :\n (this.props.clickAt.y - this.props.bounds.top);\n\n const position = {\n left: left + 'px',\n top: top + 'px'\n };\n\n return (\n \n );\n }\n}\n\nexport default injectIntl(ContextMenu);\n","import React from 'react';\n\nconst icon_mapping = {'muted': 'notifications_off', 'banned': 'block', 'staff': 'verified_user'};\n\n/* Contact's labels: [you], or icons [muted], [blocked] */\nexport default class ContactBadges extends React.PureComponent {\n render() {\n let badges = null;\n if (this.props.badges && this.props.badges.length > 0) {\n badges = [];\n this.props.badges.forEach(b => {\n const color = (b.color ? ' ' + b.color : '');\n if (b.icon) {\n badges.push({icon_mapping[b.icon] || b.icon} );\n } else {\n badges.push({b.name} );\n }\n });\n return <>{badges}>;\n }\n return null;\n }\n};\n","// The counter of unread messages in the topic.\nimport React from 'react';\n\nexport default class UnreadBadge extends React.PureComponent {\n render() {\n return (this.props.count > 0 ?\n {this.props.count > 9 ? \"9+\" : this.props.count} \n : null);\n }\n};\n","// Chat message describing a video or voice call.\n\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { secondsToTime } from '../lib/strformat.js';\n\nexport default class CallMessage extends React.PureComponent {\n render() {\n const isCallDropped = ['busy', 'declined', 'disconnected', 'missed'].includes(this.props.callState);\n const successClass = 'material-icons medium ' + (isCallDropped ? 'red' : 'green');\n const callIcon = this.props.incoming ?\n (isCallDropped ? 'call_missed' : 'call_received') :\n (isCallDropped ? 'call_missed_outgoing' : 'call_made');\n const title = this.props.incoming ?\n :\n ;\n let duration;\n if (isCallDropped) {\n switch (this.props.callState) {\n case 'busy':\n duration = ;\n break;\n case 'declined':\n duration = ;\n break;\n case 'missed':\n duration = this.props.incoming ?\n :\n ;\n break;\n default:\n duration = ;\n break;\n }\n } else {\n duration = {secondsToTime(this.props.duration / 1000)} ;\n }\n return \n
call
\n
\n
{title}
\n
{callIcon} {duration}
\n
\n
;\n }\n}\n","// The counter of unread messages in the topic.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { secondsToTime } from '../lib/strformat.js';\n\n// Props:\n// incoming: true | false.\n// callState: 'busy' | 'declined' | 'disconnected' | 'missed'.\n// duration: (call duration in milliseconds).\nexport default class CallStatus extends React.PureComponent {\n render() {\n const isCallDropped = ['busy', 'declined', 'disconnected', 'missed'].includes(this.props.callState);\n const icon2 = this.props.incoming ?\n (isCallDropped ? 'call_missed' : 'call_received') :\n (isCallDropped ? 'call_missed_outgoing' : 'call_made');\n let duration;\n if (isCallDropped) {\n switch (this.props.callState) {\n case 'busy':\n duration = ;\n break;\n case 'declined':\n duration = ;\n break;\n case 'missed':\n duration = this.props.incoming ?\n :\n ;\n break;\n default:\n duration = ;\n break;\n }\n } else if (['accepted', 'started'].includes(this.props.callState) && !this.props.duration) {\n duration = \n } else {\n duration = {secondsToTime(this.props.duration / 1000)} ;\n }\n return (\n <>\n \n call {icon2} \n
{duration}\n >\n );\n }\n};\n","// Element which shows static video preview:\n// an image with duration and a play button in the middle.\n\nimport React from 'react';\n\nimport { secondsToTime } from '../lib/strformat.js'\n\nexport default class InlineVideo extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.videoRef = React.createRef();\n\n this.handleClick = this.handleClick.bind(this);\n }\n\n handleClick(e) {\n if (this.props.onClick) {\n // the click target has to be the image element.\n this.props.onClick(e);\n }\n }\n\n render() {\n const duration = secondsToTime(this.props['data-duration'] / 1000);\n const className = 'inline-video' + (this.props.onClick ? ' image-clickable' : '');\n return (\n \n {React.createElement('img', this.props)}\n
\n {this.props.onClick ?\n
play_arrow \n :\n
}\n
\n {duration ?
{duration}
: null}\n
\n );\n }\n};\n","// Image with a placeholder which is replaced when the promise is resolved.\nimport React from 'react';\n\nexport default class LazyImage extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n src: this.props.isvideo ? 'img/blankvid.png' : 'img/blankimg.png',\n style: Object.assign({padding: '4px'}, this.props.style),\n className: this.props.className,\n alt: this.props.alt,\n onClick: this.props.onClick,\n };\n }\n\n componentDidMount() {\n // whenDone is a wrapper around an actual promise to be able to cancel it.\n this.props.whenDone\n .promise\n .then(data => this.setState({src: data.src, style: {...this.state.style, padding: 0}}))\n .catch(_ => this.setState({src: this.props.isvideo ? 'img/broken_video.png' : 'img/broken_image.png'}));\n }\n\n componentWillUnmount() {\n this.props.whenDone.cancel();\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.whenDone != this.props.whenDone) {\n this.setState({src: this.props.isvideo ? 'img/blankvid.png' : 'img/blankimg.png', style: {...this.state.style, padding: '4px'}});\n this.props.whenDone\n .promise\n .then(data => this.setState({src: data.src, style: {...this.state.style, padding: 0}}))\n .catch(_ => this.setState({src: this.props.isvideo ? 'img/broken_video.png' : 'img/broken_image.png'}));\n }\n }\n\n render() {\n return React.createElement('img', this.state);\n }\n};\n","// File uload/download progress indicator with a cancel inside.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nexport default class FileProgress extends React.PureComponent {\n render() {\n return (\n \n );\n }\n}\n","// Image view with progress bar and a cancel button.\nimport React from 'react';\n\nimport FileProgress from './file-progress.jsx';\n\nexport default class UploadingImage extends React.PureComponent {\n constructor(props) {\n super(props);\n }\n\n render() {\n return (\n \n {React.createElement('img', this.props)}\n
\n \n
\n
\n );\n }\n};\n","import React from 'react';\nimport { defineMessages } from 'react-intl';\n\nimport { Drafty } from 'tinode-sdk';\n\nimport AudioPlayer from '../widgets/audio-player.jsx'\nimport CallMessage from '../widgets/call-message.jsx'\nimport CallStatus from '../widgets/call-status.jsx';\nimport InlineVideo from '../widgets/inline-video.jsx';\nimport LazyImage from '../widgets/lazy-image.jsx'\nimport UploadingImage from '../widgets/uploading-image.jsx'\n\nimport { BROKEN_IMAGE_SIZE, CLICKABLE_URL_SCHEMES, IMAGE_THUMBNAIL_DIM, NO_DIMENSIONS_VIDEO, REM_SIZE,\n VIDEO_THUMBNAIL_WIDTH } from '../config.js';\nimport { base64ToBlob, blobToBase64, fitImageSize, imageScaled } from './blob-helpers.js';\nimport { idToColorClass, secondsToTime, shortenFileName } from './strformat.js';\nimport { cancelablePromise, sanitizeUrl, sanitizeUrlForMime } from './utils.js';\n\nconst messages = defineMessages({\n drafty_form: {\n id: 'drafty_form',\n defaultMessage: 'Form: ',\n description: 'Comment for form in Drafty'\n },\n drafty_attachment: {\n id: 'drafty_attachment',\n defaultMessage: 'Attachment',\n description: 'Comment for attachment in Drafty'\n },\n drafty_image: {\n id: 'drafty_image',\n defaultMessage: 'Picture',\n description: 'Comment for embedded images in Drafty'\n },\n drafty_video: {\n id: 'drafty_video',\n defaultMessage: 'Video recording',\n description: 'Comment for videos embedded in Drafty'\n },\n drafty_unknown: {\n id: 'drafty_unknown',\n defaultMessage: 'Unsupported',\n description: 'Unsupported entity in drafty'\n }\n});\n\nconst JSON_MIME_TYPE = 'application/json+drafty';\nconst JSON_MIME_TYPE_LEGACY = 'application/json'; // Remove in 2026.\n\n// The main Drafty formatter: converts Drafty elements into React classes. 'this' is set by the caller.\n// 'this' must contain:\n// viewportWidth:\n// authorizeURL:\n// onImagePreview:\n// onVideoPreview:\n// onFormButtonClick:\n// onQuoteClick:\nexport function fullFormatter(style, data, values, key, stack) {\n if (stack.includes('QQ')) {\n return quoteFormatter.call(this, style, data, values, key);\n }\n\n if (!style) {\n // Unformatted.\n return values;\n }\n\n let el = Drafty.tagName(style);\n let attr = Drafty.attrValue(style, data) || {};\n attr.key = key;\n switch (style) {\n case 'AU':\n // Show audio player.\n if (attr.src) {\n attr.src = this.authorizeURL(sanitizeUrlForMime(attr.src, 'audio'));\n attr.duration = data.duration > 0 ? (data.duration | 0) : undefined;\n attr.preview = data.preview;\n attr.loading = 'lazy';\n }\n el = AudioPlayer;\n // Audio element cannot have content.\n values = null;\n break;\n case 'BR':\n values = null;\n break;\n case 'EX':\n // Ignore.\n break;\n case 'HL':\n // Highlighted text. Assign class name.\n attr.className = 'highlight';\n break;\n case 'HD':\n el = null;\n values = null;\n break;\n case 'IM':\n // Additional processing for images\n el = handleImageData.call(this, el, data, attr);\n // Image element cannot have content.\n values = null;\n break;\n case 'BN':\n // Button\n attr.onClick = this.onFormButtonClick;\n let inner = React.Children.map(values, (child) => {\n return typeof child == 'string' ? child : undefined;\n });\n if (!inner || inner.length == 0) {\n inner = [attr.name]\n }\n // Get text which will be sent back when the button is clicked.\n attr['data-title'] = inner.join('');\n break;\n case 'LN':\n if (attr) {\n // Ensure only safe URL schemes are clickable.\n attr.href = typeof attr.href == 'string' ? sanitizeUrl(attr.href, CLICKABLE_URL_SCHEMES) : '';\n }\n break;\n case 'MN':\n // Mention\n attr.className = 'mention'\n if (data) {\n attr.className += ' ' + idToColorClass(data.val, false, true);\n }\n break;\n case 'FM':\n // Form\n attr.className = 'bot-form';\n break;\n case 'RW':\n // Form element formatting is dependent on element content.\n break;\n case 'QQ':\n // Quote/citation.\n attr.className = 'reply-quote'\n attr.onClick = this.onQuoteClick;\n break;\n case 'VC':\n el = CallMessage;\n // Video call messages do not have content.\n values = null;\n if (data) {\n attr.callState = data.state;\n attr.incoming = data.incoming;\n attr.duration = data.duration;\n }\n break;\n case 'VD':\n // Additional processing for videos.\n el = handleVideoData.call(this, el, data, attr);\n // Video element cannot have content.\n values = null;\n break;\n default:\n if (!el) {\n // Unknown element.\n el = React.Fragment;\n attr = {key: key};\n // Generate comment for unknown element.\n let body = values;\n if (!Array.isArray(values) || !values.join('').trim()) {\n body = [{this.formatMessage(messages.drafty_unknown)} ];\n }\n values = [extension , ' '].concat(body);\n }\n break;\n }\n if (!el) {\n return values;\n }\n return React.createElement(el, attr, values);\n}\n\n// Additional processing of image data.\nfunction handleImageData(el, data, attr) {\n if (!data) {\n attr.src = 'img/broken_image.png';\n attr.style = {\n width: IMAGE_THUMBNAIL_DIM + 'px',\n height: IMAGE_THUMBNAIL_DIM + 'px',\n };\n return el;\n }\n\n attr.className = 'inline-image';\n const dim = fitImageSize(data.width, data.height,\n this.viewportWidth > 0 ? Math.min(this.viewportWidth - REM_SIZE * 6.5, REM_SIZE * 34.5) :\n REM_SIZE * 34.5, REM_SIZE * 24, false) ||\n {dstWidth: BROKEN_IMAGE_SIZE, dstHeight: BROKEN_IMAGE_SIZE};\n attr.style = {\n width: dim.dstWidth + 'px',\n height: dim.dstHeight + 'px',\n // Looks like a Chrome bug: broken image does not respect 'width' and 'height'.\n minWidth: dim.dstWidth + 'px',\n minHeight: dim.dstHeight + 'px'\n };\n if (!Drafty.isProcessing(data)) {\n attr.src = this.authorizeURL(sanitizeUrlForMime(attr.src, 'image'));\n attr.alt = data.name;\n if (attr.src) {\n if (Math.max(data.width || 0, data.height || 0) > IMAGE_THUMBNAIL_DIM) {\n // Allow previews for large enough images.\n attr.onClick = this.onImagePreview;\n attr.className += ' image-clickable';\n }\n attr.loading = 'lazy';\n } else {\n attr.src = null;\n }\n } else {\n // Use custom element instead of or .\n el = UploadingImage;\n }\n\n return el;\n}\n\n// Additional processing of attached video data.\nfunction handleVideoData(el, data, attr) {\n if (!data) {\n attr.src = 'img/broken_video.png';\n attr.style = {\n width: IMAGE_THUMBNAIL_DIM + 'px',\n height: IMAGE_THUMBNAIL_DIM + 'px',\n };\n return el;\n }\n attr.className = 'inline-image';\n const dim = fitImageSize(data.width, data.height,\n this.viewportWidth > 0 ? Math.min(this.viewportWidth - REM_SIZE * 6.5, REM_SIZE * 34.5) :\n REM_SIZE * 34.5, REM_SIZE * 24, false) ||\n {dstWidth: NO_DIMENSIONS_VIDEO, dstHeight: NO_DIMENSIONS_VIDEO};\n attr.style = {\n width: dim.dstWidth + 'px',\n height: dim.dstHeight + 'px',\n // Looks like a Chrome bug: broken image does not respect 'width' and 'height'.\n minWidth: dim.dstWidth + 'px',\n minHeight: dim.dstHeight + 'px'\n };\n if (!Drafty.isProcessing(data)) {\n attr.src = this.authorizeURL(sanitizeUrlForMime(attr.src, 'image'));\n attr.alt = data.name;\n if (data.ref || data.val) {\n attr.onClick = this.onVideoPreview;\n attr.loading = 'lazy';\n }\n el = InlineVideo;\n } else {\n // Use custom element instead of or .\n el = UploadingImage;\n }\n\n return el;\n}\n\n// Converts Drafty object into a one-line preview. 'this' is set by the caller.\n// 'this' must contain:\n// formatMessage: this.props.intl.formatMessage\n// messages: formatjs messages defined with defineMessages.\nexport function previewFormatter(style, data, values, key) {\n if (!style) {\n // Unformatted.\n return values;\n }\n\n let el = Drafty.tagName(style);\n const attr = { key: key };\n switch (style) {\n case 'AU':\n // Voicemail as '[mic] 0:00'.\n el = React.Fragment;\n values = [mic , ' ', secondsToTime(data.duration/1000)];\n break;\n case 'BR':\n // Replace new line with a space.\n el = React.Fragment;\n values = [' '];\n break;\n case 'HL':\n // Make highlight less prominent in preview.\n attr.className = 'highlight preview';\n break;\n case 'LN':\n case 'MN':\n // Disable links in previews.\n el = 'span';\n break;\n case 'IM':\n // Replace image with '[icon] Image'.\n el = React.Fragment;\n values = [photo , ' ', this.formatMessage(messages.drafty_image)];\n break;\n case 'BN':\n el = 'span';\n attr.className = 'flat-button faux';\n break;\n case 'FM':\n el = React.Fragment;\n values = [dashboard ,\n this.formatMessage(messages.drafty_form)].concat(' ', values || []);\n break;\n case 'RW':\n el = React.Fragment;\n break;\n case 'EX':\n if (data) {\n if (data.mime == JSON_MIME_TYPE || data.mime == JSON_MIME_TYPE_LEGACY) {\n // Ignore JSON attachments: they are form response payloads.\n return null;\n }\n // Clear payload.\n delete data.val;\n delete data.ref;\n }\n el = React.Fragment;\n values = [attachment , ' ', this.formatMessage(messages.drafty_attachment)];\n break;\n case 'VC':\n el = CallStatus;\n if (data) {\n attr.callState = data.state;\n attr.incoming = data.incoming;\n attr.duration = data.duration;\n }\n values = null;\n break;\n case 'QQ':\n case 'HD':\n el = null;\n values = null;\n break;\n case 'VD':\n // Replace image with '[icon] Video'.\n el = React.Fragment;\n values = [play_circle_outline , ' ', this.formatMessage(messages.drafty_video)];\n break;\n default:\n if (!el) {\n // Unknown element.\n el = React.Fragment;\n values = [extension , ' ', this.formatMessage(messages.drafty_unknown)];\n }\n break;\n }\n if (!el) {\n return values;\n }\n return React.createElement(el, attr, values);\n};\n\n// Converts Drafty object into a quoted reply; 'this' is set by the caller.\nfunction inlineImageAttr(attr, data) {\n attr.style = {\n width: IMAGE_THUMBNAIL_DIM + 'px',\n height: IMAGE_THUMBNAIL_DIM + 'px',\n maxWidth: IMAGE_THUMBNAIL_DIM + 'px',\n maxHeight: IMAGE_THUMBNAIL_DIM + 'px',\n }\n attr.className = 'inline-image';\n attr.alt = this.formatMessage(messages.drafty_image);\n if (!data) {\n attr.src = 'img/broken_image.png';\n } else {\n attr.src = attr.src || 'img/broken_image.png';\n }\n attr.title = attr.alt;\n return attr;\n}\n\n// Converts Drafty object into a quoted reply; 'this' is set by the caller.\nfunction inlineVideoAttr(attr, data) {\n const dim = fitImageSize(data.width, data.height, VIDEO_THUMBNAIL_WIDTH, IMAGE_THUMBNAIL_DIM);\n attr.style = {\n width: dim.width + 'px',\n height: dim.height + 'px',\n maxWidth: VIDEO_THUMBNAIL_WIDTH + 'px',\n maxHeight: IMAGE_THUMBNAIL_DIM + 'px',\n }\n attr.className = 'inline-image';\n attr.alt = this.formatMessage(messages.drafty_video);\n attr.title = attr.alt;\n if (!data) {\n attr.src = 'img/broken_video.png';\n } else {\n attr.src = attr.src || 'img/broken_video.png';\n }\n return attr;\n}\n\n// Displays a portion of Drafty within 'QQ' quotes. 'this' is set by the caller.\n// 'this' must contain:\n// formatMessage: this.props.intl.formatMessage\n// messages: formatjs messages defined with defineMessages.\n// authorizeURL: this.props.tinode.authorizeURL\n// onQuoteClick: this.handleQuoteClick (optional)\nfunction quoteFormatter(style, data, values, key) {\n if (['BR', 'EX', 'IM', 'MN', 'VD'].includes(style)) {\n let el = Drafty.tagName(style);\n let attr = Drafty.attrValue(style, data) || {};\n attr.key = key;\n switch(style) {\n case 'BR':\n values = null;\n break;\n case 'IM':\n attr = inlineImageAttr.call(this, attr, data);\n values = [React.createElement('img', attr, null), ' ', attr.alt];\n el = React.Fragment;\n // Fragment attributes.\n attr = {key: key};\n break;\n case 'VD':\n attr = inlineVideoAttr.call(this, attr, data);\n values = [React.createElement('img', attr, null), ' ', attr.alt];\n el = React.Fragment;\n // Fragment attributes.\n attr = {key: key};\n break;\n case 'MN':\n el = 'span';\n attr.className = 'mention'\n if (data) {\n attr.className += ' ' + idToColorClass(data.val, false, true);\n }\n break;\n case 'EX':\n let fname;\n if (data) {\n if (data.mime == JSON_MIME_TYPE || data.mime == JSON_MIME_TYPE_LEGACY) {\n // Ignore JSON attachments: they are form response payloads.\n return null;\n }\n fname = data.name;\n // Clear payload.\n delete data.val;\n delete data.ref;\n }\n el = React.Fragment;\n values = [attachment ,\n shortenFileName(fname, 16) || this.formatMessage(messages.drafty_attachment)];\n break;\n }\n return React.createElement(el, attr, values);\n }\n return previewFormatter.call(this, style, data, values, key);\n}\n\n// Create image thumbnail suitable for inclusion in a quote.\nfunction quoteImageOrVideo(data, isVideo) {\n let promise;\n let bits, ref, mime;\n if (isVideo) {\n bits = data.preview;\n mime = data.premime || 'image/jpeg';\n ref = data.preref;\n } else {\n bits = data.val;\n mime = data.mime;\n ref = data.ref;\n }\n // Get the blob from the image data.\n if (bits) {\n const blob = base64ToBlob(bits, mime);\n if (!blob) {\n throw new Error(\"Invalid image\");\n }\n promise = Promise.resolve(blob);\n } else if (ref) {\n promise = fetch(this.authorizeURL(sanitizeUrlForMime(ref, 'image')))\n .then(evt => {\n if (evt.ok) {\n return evt.blob();\n } else {\n throw new Error(`Image fetch unsuccessful: ${evt.status} ${evt.statusText}`);\n }\n });\n } else {\n throw new Error(\"Missing image data\");\n }\n\n // Scale the blob.\n return promise\n .then(blob => {\n // If it's an image, cut the square from the center of the image and shrink it.\n // If it's a video, allow it to be rectantular.\n return imageScaled(blob, isVideo ? VIDEO_THUMBNAIL_WIDTH : IMAGE_THUMBNAIL_DIM, IMAGE_THUMBNAIL_DIM, -1, !isVideo)\n }).then(scaled => {\n if (isVideo) {\n data.premime = scaled.mime;\n } else {\n data.mime = scaled.mime;\n }\n data.size = scaled.blob.size;\n data.width = scaled.width;\n data.height = scaled.height;\n delete data.ref;\n delete data.preref;\n // Keeping the original file name, if provided: ex.data.name;\n\n data.src = URL.createObjectURL(scaled.blob);\n return blobToBase64(scaled.blob);\n }).then(b64 => {\n if (isVideo) {\n data.preview = b64.bits;\n } else {\n data.val = b64.bits;\n }\n return data;\n }).catch(err => {\n delete data.val;\n delete data.preview;\n delete data.src;\n data.width = IMAGE_THUMBNAIL_DIM;\n data.height = IMAGE_THUMBNAIL_DIM;\n // Rethrow.\n throw err;\n });\n}\n\n// Create a preview of a reply.\nexport function replyFormatter(style, data, values, key, stack) {\n if (style == 'IM' || style == 'VD') {\n const isImage = style == 'IM';\n const attr = isImage ? inlineImageAttr.call(this, {key: key}, data) :\n inlineVideoAttr.call(this, {key: key}, data);\n\n let loadedPromise;\n try {\n loadedPromise = cancelablePromise(quoteImageOrVideo.call(this, data, style == 'VD'));\n } catch (error) {\n console.warn(\"Failed to quote image:\", error.message);\n loadedPromise = cancelablePromise(error);\n }\n attr.whenDone = loadedPromise;\n values = [React.createElement(LazyImage, attr, null), ' ', attr.alt];\n return React.createElement(React.Fragment, {key: key}, values);\n } else if (style == 'QQ') {\n if (stack.includes('QQ')) {\n // Quote inside quote when forwarding a message.\n return React.createElement('span', {key: key},\n [format_quote , ' ']);\n }\n\n const attr = Drafty.attrValue('QQ', data) || {};\n attr.key = key;\n attr.className = 'reply-quote'\n return React.createElement(Drafty.tagName('QQ'), attr, values);\n }\n return quoteFormatter.call(this, style, data, values, key);\n}\n","// A single topic or user.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport ContactBadges from './contact-badges.jsx';\nimport LetterTile from './letter-tile.jsx';\nimport UnreadBadge from './unread-badge.jsx';\n\nimport { Drafty } from 'tinode-sdk';\n\nimport { previewFormatter } from '../lib/formatters.js';\nimport { deliveryMarker } from '../lib/utils.js';\n\nconst messages = defineMessages({\n self_topic_name: {\n id: 'self_topic_name',\n defaultMessage: 'Saved messages',\n description: 'Name of self topic for UI'\n },\n self_topic_comment: {\n id: 'self_topic_comment',\n defaultMessage: 'Notes, messages, links, files saved for posterity',\n description: 'Comment for self topic for UI'\n }\n});\n\nclass Contact extends React.Component {\n constructor(props) {\n super(props);\n\n this.handleClick = this.handleClick.bind(this);\n this.handleContextClick = this.handleContextClick.bind(this);\n }\n\n handleClick(e) {\n e.preventDefault();\n e.stopPropagation();\n if (this.props.onSelected) {\n // Index this.props.index is used by GroupManager.\n this.props.onSelected(this.props.item, this.props.index);\n }\n }\n\n handleContextClick(e) {\n e.preventDefault();\n e.stopPropagation();\n this.props.showContextMenu({ topicName: this.props.item, y: e.pageY, x: e.pageX });\n }\n\n render() {\n let title = this.props.title;\n const self = Tinode.isSelfTopicName(this.props.item);\n if (!title) {\n if (self) {\n title = this.props.intl.formatMessage(messages.self_topic_name);\n } else {\n title = ;\n }\n } else if (title.length > 30) {\n // FIXME: this is probably wrong for RTL languages.\n title = title.substring(0, 28) + '…';\n }\n const online = this.props.now ? 'online' : 'offline';\n const avatar = this.props.avatar ? this.props.avatar : true;\n const badges = this.props.badges ? this.props.badges.slice() : [];\n const icon_badges = [];\n if (this.props.isVerified) {\n icon_badges.push({icon: 'verified', color: 'verified-color'});\n }\n if (this.props.isStaff) {\n icon_badges.push({icon: 'staff', color: 'staff-color'});\n }\n if (this.props.isDangerous) {\n icon_badges.push({icon: 'dangerous', color: 'danger-color'});\n }\n if (this.props.acs) {\n if (this.props.showMode) {\n badges.push({name: this.props.acs.getMode(), key: 'mode'});\n }\n if (this.props.acs.isMuted()) {\n icon_badges.push({icon: 'muted'});\n }\n if (!this.props.acs.isJoiner()) {\n icon_badges.push({icon: 'banned'});\n }\n }\n\n // The this.props.preview contains alreay shortened Drafty or string.\n let preview;\n if (typeof this.props.preview == 'string') {\n preview = this.props.preview;\n } else if (Drafty.isValid(this.props.preview)) {\n preview = React.createElement(React.Fragment, null, Drafty.format(this.props.preview, previewFormatter,\n {formatMessage: this.props.intl.formatMessage, previewIsResponse: this.props.previewIsResponse}));\n } else if (this.props.preview) {\n preview =\n <>warning_amber \n \n >;\n }\n\n const icon = deliveryMarker(this.props.received);\n const marker = icon ? {icon.name} : null;\n const titleClass = 'contact-title' + (this.props.deleted ? ' deleted' : '');\n\n const comment = preview || this.props.comment ||\n (self ? this.props.intl.formatMessage(messages.self_topic_comment) : '\\u00A0');\n return (\n \n \n \n {this.props.deleted ? cancel :\n (!self && this.props.showOnline) ? :\n (this.props.showCheckmark && this.props.selected) ?\n check_circle \n : null}\n
\n \n
{title} \n {this.props.isGroup ?
group : null}\n {this.props.isChannel ?
: null}\n {!self ?
: null}\n {!this.props.deleted ?
: null}\n
\n {this.props.showMode ?\n
:\n this.props.small ? null :
{marker}{comment}
}\n
\n {this.props.showContextMenu ?\n \n \n expand_more \n \n : null}\n \n );\n }\n};\n\nexport default injectIntl(Contact);\n","// A panel included into a list of contacts with an action text.\nimport React from 'react';\nimport { injectIntl } from 'react-intl';\n\nclass ContactAction extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleClick = this.handleClick.bind(this);\n }\n\n handleClick(e) {\n e.preventDefault();\n e.stopPropagation();\n this.props.onAction(this.props.action);\n }\n\n render() {\n const {formatMessage} = this.props.intl;\n return (\n \n {formatMessage(this.props.title, this.props.values)}
\n \n );\n }\n};\n\nexport default injectIntl(ContactAction);\n","// ContactList: component for showing a list of contacts,\n// such as a list of group members in a group chat.\nimport React from 'react';\nimport { defineMessages, injectIntl } from 'react-intl';\n\nimport { Drafty, Tinode } from 'tinode-sdk';\n\nimport Contact from './contact.jsx';\nimport ContactAction from './contact-action.jsx';\n\nimport { makeImageUrl } from '../lib/blob-helpers.js';\n\nimport { MESSAGE_PREVIEW_LENGTH } from '../config.js';\n\nconst messages = defineMessages({\n badge_you: {\n id: 'badge_you',\n defaultMessage: 'you',\n description: 'Badge for indicating the current user'\n },\n badge_owner: {\n id: 'badge_owner',\n defaultMessage: 'owner',\n description: 'Badge for indicating the owner'\n }\n});\n\nclass ContactList extends React.Component {\n render() {\n const { formatMessage } = this.props.intl;\n const showCheckmark = Array.isArray(this.props.topicSelected);\n const contactNodes = [];\n\n // Count of contacts, excluding action items.\n let contactsCount = 0;\n if (this.props.showSelfTopic) {\n const selected = showCheckmark ?\n (this.props.topicSelected.indexOf('slf') > -1) :\n (this.props.topicSelected === 'slf');\n contactNodes.push(\n \n );\n contactsCount ++;\n }\n if (this.props.contacts && this.props.contacts.length > 0) {\n this.props.contacts.forEach(c => {\n if (c.action) {\n // Action item\n contactNodes.push(\n );\n } else {\n // Normal contact\n const key = this.props.showMode ? c.user : (c.topic || c.user);\n // If filter function is provided, filter out the items\n // which don't satisfy the condition.\n if (this.props.filterFunc && this.props.filter) {\n const filterOn = [key];\n if (c.private && c.private.comment) {\n filterOn.push(('' + c.private.comment).toLowerCase());\n }\n if (c.public && c.public.fn) {\n filterOn.push(('' + c.public.fn).toLowerCase());\n }\n if (!this.props.filterFunc(this.props.filter, filterOn)) {\n return;\n }\n }\n\n const isChannel = Tinode.isChannelTopicName(key);\n const isGroup = !isChannel && Tinode.isGroupTopicName(key);\n const selected = showCheckmark ?\n (this.props.topicSelected.indexOf(key) > -1) :\n (this.props.topicSelected === key);\n const badges = [];\n if (this.props.showMode) {\n if (key == this.props.myUserId) {\n badges.push({name: formatMessage(messages.badge_you), color: 'green'});\n }\n if (c.acs && c.acs.isOwner()) {\n badges.push({name: formatMessage(messages.badge_owner), color: 'blue'});\n }\n }\n\n const comment = Array.isArray(c.private) ?\n c.private.join(',') : (c.private ? c.private.comment : null);\n let preview;\n let forwarded;\n let previewIsResponse;\n let deliveryStatus;\n if (!this.props.showMode && c.latestMessage) {\n const msg = c.latestMessage();\n if (msg) {\n forwarded = msg.head ? msg.head.forwarded : null;\n deliveryStatus = msg._status || c.msgStatus(msg, true);\n previewIsResponse = msg.from != this.props.myUserId;\n if (msg.content) {\n preview = typeof msg.content == 'string' ?\n msg.content.substr(0, MESSAGE_PREVIEW_LENGTH) :\n Drafty.preview(msg.content, MESSAGE_PREVIEW_LENGTH);\n }\n }\n }\n\n contactNodes.push(\n \n );\n contactsCount ++;\n }\n }, this);\n }\n\n return (\n \n {contactsCount == 0 ?\n
\n :\n null\n }\n {contactNodes.length > 0 ?\n
\n :\n null\n }\n
\n );\n }\n};\n\nexport default injectIntl(ContactList);\n","import React from 'react';\n\nimport { Tinode } from 'tinode-sdk';\n\nexport default class SearchContacts extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n edited: false,\n search: ''\n };\n\n this.handleSearchChange = this.handleSearchChange.bind(this);\n this.handleSearch = this.handleSearch.bind(this);\n this.handleClear = this.handleClear.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n }\n\n componentWillUnmount() {\n if (this.state.edited) {\n this.setState({search: '', edited: false});\n this.props.onSearchContacts(Tinode.DEL_CHAR);\n }\n }\n\n handleSearchChange(e) {\n this.setState({search: e.target.value});\n }\n\n handleSearch(e) {\n e.preventDefault();\n const query = this.state.search.trim();\n this.setState({edited: (query.length > 0)});\n this.props.onSearchContacts(query.length > 0 ? query : Tinode.DEL_CHAR);\n }\n\n handleClear(e) {\n e.preventDefault();\n if (this.state.edited) {\n this.props.onSearchContacts(Tinode.DEL_CHAR);\n }\n this.setState({search: '', edited: false});\n }\n\n handleKeyDown(e) {\n if (e.key === 'Enter') {\n this.handleSearch(e);\n } else if (e.key === 'Escape') {\n this.handleClear();\n }\n }\n\n render() {\n return (\n \n );\n }\n};\n","// Forward Menu: message forwarding popup/dropdown menu.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport ContactList from './contact-list.jsx';\nimport SearchContacts from './search-contacts.jsx';\n\nexport default class ForwardDialog extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n query: null\n };\n\n this.handleEscapeKey = this.handleEscapeKey.bind(this);\n this.handleClose = this.handleClose.bind(this);\n\n this.handleSearchContacts = this.handleSearchContacts.bind(this);\n this.handleContactSelected = this.handleContactSelected.bind(this);\n }\n\n componentDidMount() {\n this.props.onInitFind();\n }\n\n handleEscapeKey(e) {\n if (e.keyCode === 27) {\n // Not forwarding the message.\n this.props.hide(false);\n }\n }\n\n handleClose(e) {\n e.preventDefault();\n this.props.hide(false);\n }\n\n handleSearchContacts(query) {\n this.setState({ query: Tinode.isNullValue(query) ? null : query });\n this.props.onSearchContacts(query);\n }\n\n handleContactSelected(uid) {\n this.props.onTopicSelected(uid);\n this.props.hide(true);\n }\n\n render() {\n let contacts = this.state.query != null ? this.props.searchResults : this.props.contacts;\n // Filter out contacts without a 'W' or 'J' permissions as well as the current topic.\n contacts = contacts.filter((c) => {\n return (c.name != this.props.topicSelected) && c.acs.isJoiner() && c.acs.isWriter();\n });\n\n return (\n \n
\n
\n
{\n (search_placeholder) => \n } \n
{\n (not_found_placeholder) => \n } \n
\n
\n );\n }\n}\n","// Video call states.\nexport const CALL_STATE_NONE = 0;\nexport const CALL_STATE_OUTGOING_INITATED = 1;\nexport const CALL_STATE_INCOMING_RECEIVED = 2;\nexport const CALL_STATE_IN_PROGRESS = 3;\n\n// Video call message headers representing call state.\nexport const CALL_HEAD_STARTED = 'started';\n\n","// IncomingCall: displays Accept & Reject buttons for incoming calls.\nimport React from 'react';\n\nimport BadgeList from './badge-list.jsx';\nimport LetterTile from './letter-tile.jsx';\n\nimport { MAX_TITLE_LENGTH, MAX_PEER_TITLE_LENGTH } from '../config.js';\nimport { CALL_STATE_INCOMING_RECEIVED } from '../constants.js';\n\nimport { makeImageUrl } from '../lib/blob-helpers.js';\nimport { clipStr } from '../lib/utils.js'\n\nconst RING_SOUND = new Audio('audio/call-in.m4a');\n\nexport default class CallIncoming extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n topic: null,\n fullName: undefined,\n avatar: null,\n trustedBadges: [],\n previousMetaDesc: undefined,\n };\n\n this.resetDesc = this.resetDesc.bind(this);\n this.onMetaDesc = this.onMetaDesc.bind(this);\n this.handleRejectCall = this.handleRejectCall.bind(this);\n this.handleAcceptCall = this.handleAcceptCall.bind(this);\n this.ringTimer = null;\n }\n\n componentDidMount() {\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n\n this.resetDesc(topic);\n if (this.props.callState == CALL_STATE_INCOMING_RECEIVED) {\n // play() throws if the user did not click the app first: https://goo.gl/xX8pDD.\n RING_SOUND.play().catch(_ => {});\n this.ringTimer = setInterval(_ => {RING_SOUND.play().catch(_ => {})}, 2000);\n this.props.onRinging(this.props.topic, this.props.seq);\n }\n }\n\n // No need to separately handle component mount.\n componentDidUpdate(props) {\n const topic = this.props.tinode.getTopic(props.topic);\n if (!topic) {\n return;\n }\n\n if (this.onMetaDesc != topic.onMetaDesc) {\n this.previousMetaDesc = topic.onMetaDesc;\n topic.onMetaDesc = this.onMetaDesc;\n }\n\n if (this.state.topic != props.topic) {\n this.setState({topic: props.topic});\n this.resetDesc(topic, props);\n }\n }\n\n componentWillUnmount() {\n if (this.ringTimer != null) {\n clearInterval(this.ringTimer);\n RING_SOUND.pause();\n }\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n this.setState({topic: null});\n topic.onMetaDesc = this.previousMetaDesc;\n }\n\n resetDesc(topic) {\n const badges = [];\n if (topic.trusted) {\n for (const [key, val] of Object.entries(topic.trusted)) {\n if (val) {\n badges.push(key);\n }\n }\n }\n\n this.setState({\n fullName: clipStr(topic.public ? topic.public.fn : undefined, MAX_TITLE_LENGTH),\n avatar: makeImageUrl(topic.public ? topic.public.photo : null),\n trustedBadges: badges,\n });\n }\n\n onMetaDesc(desc) {\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n this.resetDesc(topic);\n\n if (this.previousMetaDesc && this.previousMetaDesc != this.onMetaDesc) {\n this.previousMetaDesc(desc);\n }\n }\n\n handleAcceptCall() {\n this.props.onAcceptCall(this.props.topic);\n }\n\n handleRejectCall() {\n this.props.onReject(this.props.topic, this.props.seq);\n this.props.onClose();\n }\n\n render() {\n return (\n \n
\n
\n
\n \n
\n
{clipStr(this.state.fullName, MAX_PEER_TITLE_LENGTH)}\n
\n
\n
\n {this.props.callState == CALL_STATE_INCOMING_RECEIVED ?\n <>\n \n call_end \n \n \n call \n \n >\n :\n null\n }\n
\n
\n
\n );\n }\n};\n","// The X menu to be displayed in title bars.\nimport React from 'react';\n\nexport default class MenuCancel extends React.PureComponent {\n render() {\n return (\n {e.preventDefault(); this.props.onCancel();}}>\n close \n \n );\n }\n}\n","import React from 'react';\n\nimport MenuCancel from './menu-cancel.jsx';\n\nexport default class ErrorPanel extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n show: false,\n };\n\n this.hide = this.hide.bind(this);\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.level !== this.props.level) {\n this.setState({\n show: !(!this.props.level)\n });\n }\n }\n\n hide() {\n this.setState({show: false});\n if (this.props.onClearError) {\n this.props.onClearError();\n }\n }\n\n render() {\n const icons = {err: 'error', warn: 'warning', info: 'info'}\n const level = icons[this.props.level] || '';\n const className = 'info-box ' + level;\n return (\n \n );\n }\n};\n","import React from 'react';\n\nimport LetterTile from './letter-tile.jsx';\n\nexport default class Chip extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleCancel = this.handleCancel.bind(this);\n }\n\n handleCancel(e) {\n e.preventDefault();\n this.props.onCancel(this.props.topic, this.props.index);\n }\n\n render() {\n const title = this.props.title || this.props.topic;\n const className = this.props.invalid ? 'chip invalid' : 'chip';\n return (\n \n {this.props.noAvatar ?\n
:\n
\n \n
\n }\n
{title} \n {this.props.onCancel && !this.props.required ?\n
× \n :
}\n
\n );\n }\n};\n","import React from 'react';\n\nimport Chip from './chip.jsx';\n\nimport { makeImageUrl } from '../lib/blob-helpers.js';\n\n/* BEGIN ChipInput: group membership widget */\nexport default class ChipInput extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = ChipInput.deriveStateFromProps(props);\n this.state.input = '';\n this.state.focused = false;\n\n this.handleTextInput = this.handleTextInput.bind(this);\n this.removeChipAt = this.removeChipAt.bind(this);\n this.handleChipCancel = this.handleChipCancel.bind(this);\n this.handleFocusGained = this.handleFocusGained.bind(this);\n this.handleFocusLost = this.handleFocusLost.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n }\n\n static deriveStateFromProps(props) {\n return {\n placeholder: props.chips ? '' : props.prompt,\n sortedChips: ChipInput.sortChips(props.chips, props.staticMembers),\n chipIndex: ChipInput.indexChips(props.chips)\n };\n }\n\n componentDidUpdate(prevProps, prevState) {\n if (prevProps.chips != this.props.chips ||\n prevProps.staticMembers != this.props.staticMembers ||\n prevProps.prompt != this.props.prompt) {\n this.setState(ChipInput.deriveStateFromProps(this.props));\n }\n if (!prevState || this.props.chips.length > prevState.sortedChips.length) {\n this.setState({input: ''});\n }\n }\n\n // Map chip index to user name\n static indexChips(chips) {\n const index = {};\n let count = 0;\n chips.forEach(item => {\n index[item.user] = count;\n count ++;\n });\n return index;\n }\n\n // Have non-removable chips appear before all other chips.\n static sortChips(chips, keep) {\n const required = [];\n const normal = [];\n chips.forEach(item => {\n if (keep && keep.includes(item.user)) {\n required.push(item);\n } else {\n normal.push(item);\n }\n });\n return required.concat(normal);\n }\n\n handleTextInput(e) {\n this.setState({input: e.target.value});\n if (this.props.filterFunc) {\n this.props.filterFunc(e.target.value);\n }\n }\n\n removeChipAt(idx) {\n const removed = this.state.sortedChips[idx];\n this.props.onChipRemoved(removed.user, this.state.chipIndex[removed.user]);\n }\n\n handleChipCancel(item, idx) {\n this.removeChipAt(idx);\n }\n\n handleFocusGained() {\n this.setState({focused: true});\n }\n\n handleFocusLost() {\n this.setState({focused: false});\n if (this.props.onFocusLost) {\n this.props.onFocusLost(this.state.input);\n }\n }\n\n handleKeyDown(e) {\n if (e.key === 'Backspace') {\n if (this.state.input.length == 0 && this.state.sortedChips.length > 0) {\n const at = this.state.sortedChips.length - 1;\n if (this.state.sortedChips[at].user !== this.props.staticMembers) {\n this.removeChipAt(at);\n }\n }\n } else if (e.key === 'Enter') {\n if (this.props.onEnter) {\n this.props.onEnter(this.state.input);\n }\n } else if (e.key === 'Escape') {\n if (this.props.onCancel) {\n this.props.onCancel();\n }\n }\n }\n\n render() {\n const chips = [];\n let count = 0;\n const staticMembers = this.props.staticMembers || [];\n this.state.sortedChips.forEach(item => {\n chips.push(\n \n );\n count++;\n });\n const className = \"chip-input\" + (this.state.focused ? ' focused' : '');\n const autoFocus = !(this.props.tabIndex > 0);\n return (\n \n {chips}\n \n
\n );\n }\n};\n","// GroupMembers: control for managing a list of group members.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport ChipInput from './chip-input.jsx';\nimport ContactList from './contact-list.jsx';\n\nconst messages = defineMessages({\n no_contacts: {\n id: 'no_contacts',\n defaultMessage: 'You have no contacts :-(',\n description: 'Shown in ContactsView when the user has no contacts'\n },\n contacts_not_found_short: {\n id: 'contacts_not_found_short',\n defaultMessage: \"No contacts match ''{query}''\",\n description: 'Shown in ContactsView when search returned no results'\n }\n});\n\nclass GroupManager extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n // Array of topic members\n members: props.members,\n index: GroupManager.indexMembers(props.members),\n staticMembers: GroupManager.staticMembers(props.members, props.keepInitialMembers, props.requiredMember),\n contactFilter: '',\n noContactsMessage: props.intl.formatMessage(messages.no_contacts),\n selectedContacts: GroupManager.selectedContacts(props.members)\n };\n\n this.handleContactSelected = this.handleContactSelected.bind(this);\n this.handleMemberRemoved = this.handleMemberRemoved.bind(this);\n this.handleContactFilter = this.handleContactFilter.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n }\n\n static indexMembers(members) {\n let index = {};\n members.forEach(m => {\n index[m.user] = {delta: 0, present: true}; // Delta: 0 unchanged, +1 added, -1 removed\n });\n return index;\n }\n\n static staticMembers(members, keepInitial, requiredMember) {\n let stat = [];\n members.forEach(m => {\n if (keepInitial || m.user == requiredMember) {\n stat.push(m.user);\n }\n });\n return stat;\n }\n\n static selectedContacts(members) {\n let sel = [];\n members.forEach(m => {\n sel.push(m.user);\n });\n return sel;\n }\n\n handleContactSelected(userId, index) {\n let status = this.state.index[userId];\n if (status) {\n if (status.present) {\n // Prevent duplicate members\n return;\n }\n status.delta += 1;\n status.present = true;\n } else {\n status = {delta: 1, present: true};\n }\n\n let m = this.state.members.slice();\n m.push(this.props.contacts[index]);\n\n const sel = GroupManager.selectedContacts(m);\n\n const i = this.state.index;\n i[userId] = status;\n\n this.setState({members: m, index: i, selectedContacts: sel});\n }\n\n handleMemberRemoved(userId, index) {\n const status = this.state.index[userId];\n if (!status || !status.present) {\n return;\n }\n status.present = false;\n status.delta -= 1;\n\n let m = this.state.members.slice();\n m.splice(index, 1);\n\n const sel = GroupManager.selectedContacts(m);\n\n const i = this.state.index;\n i[userId] = status;\n\n this.setState({members: m, index: i, selectedContacts: sel});\n }\n\n handleContactFilter(val) {\n const {formatMessage} = this.props.intl;\n const msg = !val ?\n formatMessage(messages.no_contacts) :\n formatMessage(messages.contacts_not_found_short, {query: val});\n\n this.setState({contactFilter: val, noContactsMessage: msg});\n }\n\n static doContactFiltering(filter, values) {\n if (filter) {\n for (let i=0; i= 0) {\n return true;\n }\n }\n return false;\n }\n return true;\n }\n\n handleSubmit() {\n const members = [];\n const added = [];\n const removed = [];\n\n const keys = Object.keys(this.state.index);\n keys.forEach(k => {\n if (this.state.index[k].present) {\n members.push(k);\n }\n\n if (this.state.index[k].delta > 0) {\n added.push(k);\n } else if (this.state.index[k].delta < 0) {\n removed.push(k);\n }\n });\n this.props.onSubmit(members, added, removed);\n }\n\n handleCancel() {\n this.props.onCancel();\n }\n\n render() {\n return (\n \n
\n \n \n \n
\n
\n \n
\n
\n \n \n \n
\n
\n
\n \n \n \n \n \n \n
\n
\n );\n }\n};\n\nexport default injectIntl(GroupManager);\n","// PermissionsEditor: Component for editing permissions\n// \nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport CheckBox from './checkbox.jsx';\nimport Contact from './contact.jsx';\n\nimport { makeImageUrl } from '../lib/blob-helpers.js';\n\n// Translatable permission names.\nconst messages = defineMessages({\n joiner: {\n id: 'permission_join',\n defaultMessage: \"Join ({val})\",\n description: 'Name of J permission'\n },\n reader: {\n id: 'permission_read',\n defaultMessage: \"Read ({val})\",\n description: 'Name of R permission'\n },\n writer: {\n id: 'permission_write',\n defaultMessage: \"Write ({val})\",\n description: 'Name of W permission'\n },\n preser: {\n id: 'permission_pres',\n defaultMessage: \"Get notified ({val})\",\n description: 'Name of P permission'\n },\n approver: {\n id: 'permission_admin',\n defaultMessage: \"Approve ({val})\",\n description: 'Name of A permission'\n },\n sharer: {\n id: 'permission_share',\n defaultMessage: \"Share ({val})\",\n description: 'Name of S permission'\n },\n deleter: {\n id: 'permission_delete',\n defaultMessage: \"Delete ({val})\",\n description: 'Name of D permission'\n },\n owner: {\n id: 'permission_owner',\n defaultMessage: \"Owner ({val})\",\n description: 'Name of O permission'\n }\n});\n\nclass PermissionsEditor extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n mode: (props.mode || '').replace('N', '')\n };\n\n this.handleChange = this.handleChange.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n }\n\n handleChange(val) {\n let mode = this.state.mode;\n const idx = mode.indexOf(val);\n if (idx == -1) {\n mode += val;\n } else {\n mode = mode.replace(val, '');\n }\n this.setState({mode: mode});\n }\n\n handleSubmit() {\n // Normalize string, otherwise cannot check if mode has changed.\n const mode = (this.state.mode || 'N').split('').sort().join('');\n const before = (this.props.mode || 'N').split('').sort().join('')\n if (mode !== before) {\n this.props.onSubmit(mode);\n } else {\n this.props.onCancel();\n }\n }\n\n handleCancel() {\n this.props.onCancel();\n }\n\n render() {\n const {formatMessage} = this.props.intl;\n const all = 'JRWPASDO';\n const names = {\n 'J': formatMessage(messages.joiner, {val: 'J'}),\n 'R': formatMessage(messages.reader, {val: 'R'}),\n 'W': formatMessage(messages.writer, {val: 'W'}),\n 'P': formatMessage(messages.preser, {val: 'P'}),\n 'A': formatMessage(messages.approver, {val: 'A'}),\n 'S': formatMessage(messages.sharer, {val: 'S'}),\n 'D': formatMessage(messages.deleter, {val: 'D'}),\n 'O': formatMessage(messages.owner, {val: 'O'})\n };\n\n let skip = this.props.skip || '';\n let mode = this.state.mode;\n let compare = (this.props.compare || '').replace('N', '');\n let items = [];\n for (let i=0; i= 0 && mode.indexOf(c) < 0) {\n // Permission is marked as inactive: hide unchecked permissions, disable checked permissions\n continue;\n }\n items.push(\n \n {names[c]} \n {skip.indexOf(c) < 0 ?\n = 0)} onChange={this.handleChange}/>\n :\n = 0)} />\n } {this.props.compare ? \n = 0)}/>\n : null}\n \n );\n }\n\n return (\n \n {this.props.userTitle ?\n
: null}\n
\n
\n {this.props.compare ?\n \n {this.props.modeTitle} \n {this.props.compareTitle} \n :\n null}\n \n {items}\n
\n
\n
\n \n \n \n \n \n \n
\n
\n );\n }\n};\n\nexport default injectIntl(PermissionsEditor);\n","var __WEBPACK_NAMESPACE_OBJECT__ = QRCode;","import QRCode from 'qrcodejs';\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { QRCODE_SIZE } from '../config';\n\nexport default class ShowQRCode extends React.PureComponent {\n constructor(props) {\n super(props);\n this.qrCodeRef = React.createRef();\n }\n\n componentDidMount() {\n new QRCode(this.qrCodeRef.current, {\n text: this.props.uri,\n width: QRCODE_SIZE,\n height: QRCODE_SIZE,\n });\n }\n\n render() {\n return (\n \n );\n }\n};\n","// In-place text editor. Shows text with an icon which toggles it into an input field.\nimport React from 'react';\n\nimport VisiblePassword from './visible-password.jsx';\n\nexport default class InPlaceEdit extends React.Component {\n constructor(props) {\n super(props);\n\n this.selfRef = React.createRef();\n\n this.state = {\n active: props.active,\n initialValue: props.value || '',\n value: props.value || '',\n valid: true\n };\n\n this.handeTextChange = this.handeTextChange.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleStartEditing = this.handleStartEditing.bind(this);\n this.handleEditingFinished = this.handleEditingFinished.bind(this);\n this.handlePasswordFinished = this.handlePasswordFinished.bind(this);\n }\n\n componentDidUpdate(prevProps, prevState) {\n // If text has changed while in read mode, update text and discard changes.\n // Ignore update if in edit mode.\n const newValue = this.props.value || '';\n if (prevState.initialValue != newValue && !prevState.active) {\n this.setState({\n initialValue: newValue,\n value: newValue\n });\n }\n }\n\n handeTextChange(e) {\n this.setState({value: e.target.value || ''});\n if (this.props.validator) {\n Promise.resolve(this.props.validator(e.target.value))\n .then(valid => {\n this.setState({valid: valid});\n })\n .catch(err => {\n // If it's interrupted, then the err is undefined. Ignore it.\n if (err) {\n this.setState({valid: false});\n }\n });\n }\n }\n\n handleKeyDown(e) {\n if (e.keyCode === 27) {\n // Escape pressed\n this.setState({value: this.props.value, active: false});\n } else if (e.keyCode === 13) {\n // Enter pressed\n this.handleEditingFinished(e);\n }\n }\n\n handleStartEditing() {\n if (!this.props.readOnly) {\n this.setState({active: true}, _ => {\n if (this.selfRef.current) {\n this.selfRef.current.focus();\n }\n });\n }\n }\n\n handleEditingFinished(event) {\n const value = this.state.value.trim();\n if (this.props.required && (!event.target.checkValidity() || !value)) {\n // Empty input\n this.setState({value: this.props.value, active: false});\n return;\n }\n this.setState({active: false});\n if ((value || this.props.value) && (value !== this.props.value) && this.state.valid) {\n this.props.onFinished(value);\n }\n }\n\n handlePasswordFinished(value) {\n this.setState({active: false});\n if (value && (value !== this.props.value)) {\n this.props.onFinished(value);\n }\n }\n\n render() {\n if (!this.state.active) {\n let spanText = this.props.type == 'password' ? '••••••••' : this.state.value;\n let spanClass = 'in-place-edit' + (this.props.readOnly ? ' disabled' : '');\n if (!spanText) {\n spanText = this.props.placeholder;\n spanClass += ' placeholder';\n }\n if (!this.props.multiline || this.props.multiline == 1) {\n spanClass += ' short';\n }\n\n return (\n {this.props.iconLeft && {this.props.iconLeft} }\n {spanText} \n {this.props.iconRight && {this.props.iconRight} }\n );\n }\n\n let element;\n const attr = {};\n if (this.props.type == 'password') {\n element = VisiblePassword;\n attr.onFinished = this.handlePasswordFinished;\n } else {\n if (this.props.multiline > 1) {\n element = 'textarea';\n attr.rows = this.props.multiline;\n attr.className = 'in-place-edit';\n } else {\n element = 'input';\n attr.type = this.props.type || 'text';\n attr.className = 'in-place-edit' + (this.props.iconLeft ? ' with-icon-left'\n : this.props.iconRight ? ' with-icon-right' : '');\n if (this.props.maxLength) {\n attr.maxLength=this.props.maxLength;\n }\n }\n attr.value = this.state.value;\n attr.className += this.state.valid ? '' : ' invalid';\n attr.ref = this.selfRef;\n attr.onChange = this.handeTextChange;\n attr.onKeyDown = this.handleKeyDown;\n attr.onBlur = this.handleEditingFinished;\n }\n attr.placeholder = this.props.placeholder;\n attr.required = this.props.required ? 'required' : '';\n attr.autoComplete = this.props.autoComplete;\n attr.autoFocus = true;\n if (this.props.spellCheck !== undefined) {\n attr.spellCheck = this.props.spellCheck ? 'true' : 'false';\n }\n\n if (this.props.iconLeft || this.props.iconRight) {\n return (\n <>\n {this.props.iconLeft && {this.props.iconLeft} }\n {React.createElement(element, attr, null)}\n {this.props.iconRight && {this.props.iconRight} }\n >\n );\n }\n return React.createElement(element, attr, null);\n }\n};\n","// TagManager: edit topic or user tags.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport ChipInput from './chip-input.jsx';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport { MAX_TAG_COUNT, MAX_TAG_LENGTH, MIN_TAG_LENGTH } from '../config.js';\nimport { arrayEqual } from '../lib/utils.js';\n\nexport default class TagManager extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n tags: this.props.tags || [],\n alias: Tinode.tagByPrefix(this.props.tags, Tinode.TAG_ALIAS) || '',\n tagInput: '',\n activated: this.props.activated\n };\n\n this.handleTagInput = this.handleTagInput.bind(this);\n this.handleAddTag = this.handleAddTag.bind(this);\n this.handleRemoveTag = this.handleRemoveTag.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n }\n\n static getDerivedStateFromProps(nextProps, prevState) {\n const tags = nextProps.tags || [];\n if (!arrayEqual(tags, prevState.tags) && !prevState.activated) {\n return {\n tags: tags || [],\n alias: Tinode.tagByPrefix(tags, Tinode.TAG_ALIAS) || '',\n };\n }\n return null;\n }\n\n handleTagInput(text) {\n this.setState({tagInput: text});\n if (text.length > 0) {\n const last = text[text.length-1];\n if (text[0] == '\"') {\n // This is a quoted string.\n if (text.length > 1 && last == '\"') {\n this.handleAddTag(text.substring(1, text.length-1));\n }\n } else if (last == ',' || last == ' ' || last == ';' || last == '\"') {\n // User entered ',', ' ' or ';'\n this.handleAddTag(text.substring(0, text.length-1).trim());\n }\n }\n }\n\n handleAddTag(tag) {\n const maxTagCount = this.props.tinode.getServerParam(Tinode.MAX_TAG_COUNT, MAX_TAG_COUNT);\n\n if (tag.length > 0 && this.state.tags.length < maxTagCount) {\n const tags = this.state.tags.slice(0);\n tags.push(tag);\n\n this.setState({tags: tags, tagInput: ''});\n if (this.props.onTagsChanged) {\n this.props.onTagsChanged(tags);\n }\n return tags;\n }\n return this.state.tags;\n }\n\n handleRemoveTag(tag, index) {\n const tags = this.state.tags.slice(0);\n tags.splice(index, 1);\n this.setState({tags: tags});\n if (this.props.onTagsChanged) {\n this.props.onTagsChanged(tags);\n }\n }\n\n handleSubmit() {\n // Add unprocessed input to tags.\n let tags = this.handleAddTag(this.state.tagInput.trim());\n // Add back the alias (and overwrite one possibly added by hand).\n tags = Tinode.setUniqueTag(tags, this.state.alias);\n // Submit the updated list.\n this.props.onSubmit(tags);\n this.setState({activated: false, tags: this.props.tags || []});\n }\n\n handleCancel() {\n this.setState({activated: false, tagInput: '', tags: this.props.tags || []});\n if (this.props.onCancel) {\n this.props.onCancel();\n }\n }\n\n render() {\n const minTagLength = this.props.tinode.getServerParam(Tinode.MIN_TAG_LENGTH, MIN_TAG_LENGTH);\n const maxTagLength = this.props.tinode.getServerParam(Tinode.MAX_TAG_LENGTH, MAX_TAG_LENGTH);\n\n let tags = [];\n if (this.state.activated) {\n this.state.tags.forEach(tag => {\n if (tag != this.state.alias) {\n tags.push({user: tag, invalid: (tag.length < minTagLength || tag.length > maxTagLength)});\n }\n });\n\n } else {\n this.state.tags.forEach(tag => {\n if (tag != this.state.alias) {\n tags.push({tag} );\n }\n });\n if (tags.length == 0) {\n tags = (\n \n \n \n );\n }\n }\n return (\n \n
\n {this.props.title} \n
\n {this.state.activated ?\n
\n
{\n (add_tags_prompt) => \n } \n {this.props.onSubmit || this.props.onCancel ?\n
\n \n \n \n \n \n \n
\n : null}\n
\n :\n
\n }\n
\n );\n }\n};\n","// Widget for editing topic description.\n\nimport React from 'react';\nimport { defineMessages, FormattedMessage, injectIntl } from 'react-intl';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport AvatarCrop from './avatar-crop.jsx';\nimport AvatarUpload from './avatar-upload.jsx';\nimport InPlaceEdit from './in-place-edit.jsx';\nimport TagManager from './tag-manager.jsx';\n\nimport { AVATAR_SIZE, MAX_AVATAR_BYTES, MAX_EXTERN_ATTACHMENT_SIZE, MAX_TITLE_LENGTH,\n MAX_TOPIC_DESCRIPTION_LENGTH } from '../config.js';\nimport { imageScaled, blobToBase64, makeImageUrl } from '../lib/blob-helpers.js';\nimport { arrayEqual, theCard } from '../lib/utils.js';\n\nconst messages = defineMessages({\n alias_invalid: {\n id: 'alias_invalid',\n defaultMessage: '(invalid)',\n description: 'Error message for invalid alias'\n },\n alias_already_taken: {\n id: 'alias_already_taken',\n defaultMessage: '(already taken)',\n description: 'Error message for alias already taken'\n },\n self_topic_name: {\n id: 'self_topic_name',\n defaultMessage: 'Saved messages',\n description: 'Name of self topic for UI'\n },\n self_topic_comment: {\n id: 'self_topic_comment',\n defaultMessage: 'Notes, messages, links, files saved for posterity',\n description: 'Comment for self topic for UI'\n }\n});\n\nconst ALIAS_AVAILABILITY_CHECK_DELAY = 1000; // milliseconds\n\nclass TopicDescEdit extends React.Component {\n constructor(props) {\n super(props);\n\n const topic = this.props.tinode.getTopic(this.props.topic);\n const acs = topic.getAccessMode();\n const isSelf = Tinode.isSelfTopicName(this.props.topic);\n this.state = {\n isMe: Tinode.isMeTopicName(this.props.topic),\n isSelf: isSelf,\n owner: acs && acs.isOwner(),\n fullName: topic.public ? topic.public.fn :\n isSelf ? this.props.intl.formatMessage(messages.self_topic_name) : null,\n private: topic.private ? topic.private.comment : null,\n description: topic.public ? topic.public.note :\n isSelf ? this.props.intl.formatMessage(messages.self_topic_comment) : null,\n avatar: makeImageUrl(topic.public ? topic.public.photo : null),\n tags: topic.tags() || [],\n newAvatar: null,\n newAvatarMime: null,\n aliasError: ''\n };\n\n this.previousOnTags = null;\n this.aliasCheckTimer = null;\n this.aliasCheckPromise = null;\n\n this.tnNewTags = this.tnNewTags.bind(this);\n this.handleFullNameUpdate = this.handleFullNameUpdate.bind(this);\n this.handleImageUpdated = this.handleImageUpdated.bind(this);\n this.handleAvatarCropped = this.handleAvatarCropped.bind(this);\n this.handleAvatarCropCancel = this.handleAvatarCropCancel.bind(this);\n this.uploadAvatar = this.uploadAvatar.bind(this);\n this.handlePrivateUpdate = this.handlePrivateUpdate.bind(this);\n this.handleAliasUpdate = this.handleAliasUpdate.bind(this);\n this.handleDescriptionUpdate = this.handleDescriptionUpdate.bind(this);\n this.handleTagsUpdated = this.handleTagsUpdated.bind(this);\n this.validateAlias = this.validateAlias.bind(this);\n this.cancelValidator = this.cancelValidator.bind(this);\n }\n\n componentDidMount() {\n const topic = this.props.tinode.getTopic(this.props.topic);\n this.previousOnTags = topic.onTagsUpdated;\n topic.onTagsUpdated = this.tnNewTags;\n }\n\n componentWillUnmount() {\n const topic = this.props.tinode.getTopic(this.props.topic);\n topic.onTagsUpdated = this.previousOnTags;\n this.cancelValidator();\n }\n\n tnNewTags(tags) {\n this.setState({tags: tags});\n }\n\n handleFullNameUpdate(fn) {\n fn = fn.trim().substring(0, MAX_TITLE_LENGTH);\n if (fn && this.state.fullName !== fn) {\n this.setState({fullName: fn});\n this.props.onUpdateTopicDesc(this.props.topic, theCard(fn, null));\n }\n }\n\n handlePrivateUpdate(comment) {\n comment = comment.trim().substring(0, MAX_TITLE_LENGTH);\n if (this.state.private !== comment) {\n this.setState({private: comment});\n this.props.onUpdateTopicDesc(this.props.topic, null, comment || Tinode.DEL_CHAR);\n }\n }\n\n handleDescriptionUpdate(desc) {\n desc = desc.trim().substring(0, MAX_TOPIC_DESCRIPTION_LENGTH);\n if (desc) {\n this.setState({description: desc});\n this.props.onUpdateTopicDesc(this.props.topic, theCard(null, null, null, desc));\n }\n }\n\n // AvatarUpload widget has changed the avatar: received a new file or deleted the avatar.\n handleImageUpdated(mime, img) {\n // This will show the AvatarCropView is img is not null.\n this.setState({newAvatar: img, newAvatarMime: mime});\n if (!img) {\n // Deleting the avatar.\n this.setState({avatar: null});\n this.props.onUpdateTopicDesc(this.props.topic, theCard(null, Tinode.DEL_CHAR));\n }\n }\n\n // AvatarCropView calls this method when the user has cropped the image.\n handleAvatarCropped(mime, blob, width, height) {\n const url = blob ? URL.createObjectURL(blob) : null;\n this.setState({avatar: url, newAvatar: null, newAvatarMime: null});\n if (blob) {\n this.uploadAvatar(mime, blob, width, height);\n }\n }\n\n // Utility method for converting cropped avatar blob to bytes for sending inband or\n // for uploading it to the server out of band.\n uploadAvatar(mime, blob, width, height) {\n const readyToUpload = image => {\n let {mime, blob} = image;\n if (blob.size > MAX_AVATAR_BYTES) {\n // Too large to send inband - uploading out of band and sending as a link.\n const uploader = this.props.tinode.getLargeFileHelper();\n uploader.upload(blob)\n .then(url => this.props.onUpdateTopicDesc(this.props.topic, theCard(null, url)))\n .catch(err => this.props.onError(err.message, 'err'));\n } else {\n // Convert blob to base64-encoded bits.\n blobToBase64(blob)\n .then(b64 => {\n const du = makeImageUrl({data: b64.bits, type: mime});\n this.setState({source: du});\n this.props.onUpdateTopicDesc(this.props.topic, theCard(null, du));\n });\n }\n };\n\n if (width > AVATAR_SIZE || height > AVATAR_SIZE || width != height) {\n // Avatar is not square or too large even after cropping. Shrink it and make square.\n imageScaled(blob, AVATAR_SIZE, AVATAR_SIZE, MAX_EXTERN_ATTACHMENT_SIZE, true)\n .then(scaled => readyToUpload(scaled))\n .catch(err => this.props.onError(err.message, 'err'));\n } else {\n readyToUpload({mime: mime, blob: blob, width: width, height: height});\n }\n }\n\n handleAvatarCropCancel() {\n this.setState({newAvatar: null, newAvatarMime: null});\n }\n\n handleAliasUpdate(alias) {\n alias = (alias || '').trim();\n const tags = alias ?\n Tinode.setUniqueTag(this.state.tags, Tinode.TAG_ALIAS + alias.toLowerCase()) :\n Tinode.clearTagPrefix(this.state.tags, Tinode.TAG_ALIAS);\n this.handleTagsUpdated(tags);\n }\n\n validateAlias(alias) {\n // Reset pending delayed check.\n this.cancelValidator();\n\n alias = alias.trim();\n if (!alias) {\n this.setState({aliasError: ''});\n return true;\n }\n\n const valid = Tinode.isValidTagValue(alias);\n if (!valid) {\n this.setState({aliasError: this.props.intl.formatMessage(messages.alias_invalid)});\n return false;\n }\n this.setState({aliasError: ''});\n\n // Setup a delayed check for alias availability.\n const fnd = this.props.tinode.getFndTopic();\n if (!fnd) {\n // Unable to check alias availability.\n this.setState({aliasError: ''});\n return true;\n }\n this.aliasCheckPromise = {};\n const validationPromise = new Promise((resolve, reject) => {\n this.aliasCheckPromise.resolve = resolve;\n this.aliasCheckPromise.reject = reject;\n });\n this.aliasCheckTimer = setTimeout(_ => {\n this.aliasCheckTimer = null;\n fnd.checkTagUniqueness(`${Tinode.TAG_ALIAS}${alias}`, this.props.topic)\n .then(ok => {\n this.aliasCheckPromise.resolve(ok)\n this.setState({aliasError: ok ? '' : this.props.intl.formatMessage(messages.alias_already_taken)});\n })\n .catch(err => {\n this.aliasCheckPromise.reject(err);\n this.setState({aliasError: err.message});\n });\n }, ALIAS_AVAILABILITY_CHECK_DELAY);\n return validationPromise;\n }\n\n cancelValidator() {\n // Reset pending delayed check.\n if (this.aliasCheckTimer) {\n clearTimeout(this.aliasCheckTimer);\n this.aliasCheckTimer = null;\n this.aliasCheckPromise.reject(null);\n }\n }\n\n handleTagsUpdated(tags) {\n // Check if tags have actually changed.\n if (arrayEqual(this.state.tags.slice(0), tags.slice(0))) {\n return;\n }\n this.props.onUpdateTags(tags);\n }\n\n render() {\n if (this.state.newAvatar) {\n return (\n \n );\n }\n\n const editable = this.state.isMe || (this.state.owner && !this.state.isSelf);\n let alias = this.state.tags && this.state.tags.find(t => t.startsWith('alias:'));\n if (alias) {\n // Remove 'alias:' prefix.\n alias = alias.substring(6);\n }\n\n return (\n <>\n \n
\n \n \n {this.state.isMe ?\n
\n
\n \n \n
\n {\n (full_name_placeholder) => \n } \n
\n
\n :\n <>\n
\n
\n \n
\n
\n {\n (group_name_placeholder) => \n } \n
\n
\n
\n
\n \n \n \n
\n
\n {\n (private_placeholder) => \n } \n
\n
\n >\n }\n {editable || alias ?\n
\n
\n {this.state.aliasError}\n
\n
\n {\n (private_placeholder) => \n } \n
\n
\n : null\n }\n {editable || this.state.description ?\n
\n
\n \n
\n
\n {\n (private_placeholder) => \n } \n
\n
\n : null\n }\n
\n {editable && !this.state.isMe ?\n <>\n
\n {\n (title_tag_manager) => \n } \n >\n : null\n }\n >\n );\n }\n};\n\nexport default injectIntl(TopicDescEdit);\n","// View for editing topic parameters (including 'me' topic).\n\nimport React from 'react';\n\nimport TopicDescEdit from '../widgets/topic-desc-edit.jsx';\n\nimport { arrayEqual } from '../lib/utils.js';\n\nexport default class TopicCommonView extends React.Component {\n constructor(props) {\n super(props);\n\n const topic = this.props.tinode.getTopic(this.props.topic);\n const acs = topic.getAccessMode();\n this.state = {\n tags: []\n };\n\n this.previousTagsUpdated = undefined;\n\n this.onTagsUpdated = this.onTagsUpdated.bind(this);\n this.handleTagsUpdated = this.handleTagsUpdated.bind(this);\n }\n\n // No need to separately handle component mount.\n componentDidUpdate(props) {\n const topic = this.props.tinode.getTopic(props.topic);\n if (!topic) {\n return;\n }\n\n if (topic.onTagsUpdated != this.onTagsUpdated) {\n if (topic.getType() == 'grp') {\n this.previousTagsUpdated = topic.onTagsUpdated;\n topic.onTagsUpdated = this.onTagsUpdated;\n } else {\n this.previousTagsUpdated = undefined;\n }\n }\n\n if (this.state.topic != props.topic) {\n this.setState({topic: props.topic});\n }\n }\n\n componentWillUnmount() {\n const topic = this.props.tinode.getTopic(this.props.topic);\n topic.onTagsUpdated = this.previousTagsUpdated;\n }\n\n // Server informs that the tags have been updated.\n onTagsUpdated(tags) {\n this.setState({tags: tags});\n\n if (this.previousTagsUpdated && this.previousTagsUpdated != this.onTagsUpdated) {\n this.previousTagsUpdated(tags);\n }\n }\n\n // Request server to change tags.\n handleTagsUpdated(tags) {\n if (!arrayEqual(this.state.tags.slice(0), tags.slice(0))) {\n this.props.onUpdateTagsRequest(this.props.topic, tags);\n }\n }\n\n render() {\n return (\n \n \n
\n );\n }\n};\n","// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nconst messages = defineMessages({\n clear_messages: {\n id: 'action_clear_messages',\n defaultMessage: 'Clear Messages',\n description: 'Flat button [Clear Messages] (soft-delete messages)'\n },\n clear_messages_warning: {\n id: 'clear_messages_warning',\n defaultMessage: 'Are you sure you want to clear all messages? It cannot be undone.',\n description: 'Alert dialog warning when deleting all messages.'\n },\n delete_messages: {\n id: 'action_delete_messages',\n defaultMessage: 'Clear Messages for All',\n description: 'Flat button [Clear for All] (hard-delete all messages)'\n },\n delete_messages_warning: {\n id: 'delete_messages_warning',\n defaultMessage: 'Are you sure you want to delete all messages for everyone? It cannot be undone.',\n description: 'Alert dialog warning when hard-deleting all messages.'\n },\n topic_delete: {\n id: 'topic_delete',\n defaultMessage: 'Delete Conversation',\n description: 'Alert title when deleting the topic.'\n },\n topic_delete_warning: {\n id: 'topic_delete_warning',\n defaultMessage: 'Are you sure you want to delete this conversation? It cannot be undone.',\n description: 'Alert warning when deleting entire topic'\n },\n leave_chat: {\n id: 'action_leave_chat',\n defaultMessage: 'Leave Conversation',\n description: 'Flat button [Leave Conversation]'\n },\n leave_chat_warning: {\n id: 'leave_chat_warning',\n defaultMessage: 'Are you sure you want to leave this conversation?',\n description: 'Alert dialog warning when unsubscribing from a chat.'\n },\n block_contact: {\n id: 'action_block_contact',\n defaultMessage: \"Block Contact\",\n description: \"Flat button [Block Contact]\"\n },\n block_contact_warning: {\n id: 'block_contact_warning',\n defaultMessage: 'Are you sure you want to block this contact?',\n description: 'Alert dialog warning when blocking a contact.'\n },\n report_chat: {\n id: 'action_report_chat',\n defaultMessage: 'Report Conversation',\n description: 'Flat button [Report Group]'\n },\n report_chat_warning: {\n id: 'report_chat_warning',\n defaultMessage: 'Are you sure you want to block and report this conversation?',\n description: 'Alert dialog warning when reporting a conversation for abuse'\n },\n other_user: {\n id: 'label_other_user',\n defaultMessage: 'Other',\n description: 'Label for the other user when the user is unnamed'\n },\n});\n\nclass TopicSecurity extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleDeleteTopic = this.handleDeleteTopic.bind(this);\n this.handleDeleteMessages = this.handleDeleteMessages.bind(this);\n this.handleLeave = this.handleLeave.bind(this);\n this.handleBlock = this.handleBlock.bind(this);\n this.handleReport = this.handleReport.bind(this);\n }\n\n handleDeleteTopic(e) {\n e.preventDefault();\n const {formatMessage} = this.props.intl;\n this.props.onShowAlert(\n formatMessage(messages.topic_delete), // title\n formatMessage(messages.topic_delete_warning), // content\n _ => this.props.onDeleteTopic(this.props.topic), // onConfirm\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n\n handleDeleteMessages(e) {\n e.preventDefault();\n const {formatMessage} = this.props.intl;\n this.props.onShowAlert(\n formatMessage(this.props.deleter ? messages.delete_messages : messages.clear_messages), // title\n formatMessage(this.props.deleter ? messages.delete_messages_warning : messages.clear_messages_warning), // content\n _ => this.props.onDeleteMessages(this.props.topic), // onConfirm\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n\n handleLeave(e) {\n e.preventDefault();\n const {formatMessage} = this.props.intl;\n this.props.onShowAlert(\n formatMessage(messages.leave_chat), // title\n formatMessage(messages.leave_chat_warning), // content\n _ => this.props.onLeaveTopic(this.props.topic), // onConfirm\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n\n handleBlock(e) {\n e.preventDefault();\n const {formatMessage} = this.props.intl;\n this.props.onShowAlert(\n formatMessage(messages.block_contact), // title\n formatMessage(messages.block_contact_warning), // content\n _ => this.props.onBlockTopic(this.props.topic), // onConfirm\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n\n handleReport(e) {\n e.preventDefault();\n const {formatMessage} = this.props.intl;\n this.props.onShowAlert(\n formatMessage(messages.report_chat), // title\n formatMessage(messages.report_chat_warning), // content\n (_ => { this.props.onReportTopic(this.props.topic); }), // onConfirm\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n\n render() {\n const {formatMessage} = this.props.intl;\n return (\n \n
\n
\n
\n {this.props.groupTopic ?\n <>\n
\n \n \n {e.preventDefault(); this.props.onLaunchPermissionsEditor('want')}}>\n {this.props.access}\n \n
\n {!this.props.channel ?\n
\n
\n \n \n \n
\n
\n
Auth: {\n e.preventDefault();\n if (this.props.owner) {\n this.props.onLaunchPermissionsEditor('auth');\n }\n }}>{this.props.auth} \n
\n
Anon: {\n e.preventDefault();\n if (this.props.owner) {\n this.props.onLaunchPermissionsEditor('anon');\n }\n }}>{this.props.anon} \n
\n
\n
\n :\n null\n }\n >\n :\n
\n
\n \n \n \n
\n
\n
\n {e.preventDefault(); this.props.onLaunchPermissionsEditor('want')}}>\n {this.props.access}\n \n
\n
{this.props.fullName ? this.props.fullName : formatMessage(messages.other_user)}:\n {e.preventDefault(); this.props.onLaunchPermissionsEditor('given')}}>\n {this.props.modeGiven2}\n \n
\n
\n
\n }\n
\n
\n );\n }\n};\n\nexport default injectIntl(TopicSecurity);\n","// InfoView: panel with topic/user info.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport { AccessMode, Tinode } from 'tinode-sdk';\n\nimport AvatarUpload from '../widgets/avatar-upload.jsx';\nimport BadgeList from '../widgets/badge-list.jsx';\nimport CheckBox from '../widgets/checkbox.jsx';\nimport ContactList from '../widgets/contact-list.jsx';\nimport ErrorPanel from '../widgets/error-panel.jsx';\nimport GroupManager from '../widgets/group-manager.jsx';\nimport MenuCancel from '../widgets/menu-cancel.jsx';\nimport PermissionsEditor from '../widgets/permissions-editor.jsx';\nimport ShowQRCode from '../widgets/show-qrcode.jsx';\nimport TopicCommonView from './topic-common-view.jsx';\nimport TopicSecurity from '../widgets/topic-security.jsx';\n\nimport { MAX_TITLE_LENGTH, MAX_TOPIC_DESCRIPTION_LENGTH,\n NO_ACCESS_MODE, TOAST_DURATION } from '../config.js';\n\nimport { makeImageUrl } from '../lib/blob-helpers.js';\nimport { theCard, clipStr } from '../lib/utils.js';\n\nconst messages = defineMessages({\n info: {\n id: 'panel_title_info',\n description: 'Title for InfoView',\n defaultMessage: 'Info'\n },\n general: {\n id: 'panel_title_general',\n description: 'Title for TopicCommon.',\n defaultMessage: 'General'\n },\n security: {\n id: 'panel_title_security',\n description: 'Title for TopicSecirity and AccSecurity.',\n defaultMessage: 'Security'\n },\n members: {\n id: 'panel_title_members',\n description: 'Title for managing group members view.',\n defaultMessage: 'Members'\n },\n crop: {\n id: 'panel_title_crop',\n description: 'Title for AvatarCropView.',\n defaultMessage: 'Drag to Adjust'\n },\n perm_want: {\n id: 'requested_permissions',\n defaultMessage: 'Requested',\n description: 'Title for permissions'\n },\n perm_given: {\n id: 'granted_permissions',\n defaultMessage: 'Granted',\n description: 'Title for permissions'\n },\n perm_auth: {\n id: 'permissions_authenticated',\n defaultMessage: 'Authenticated',\n description: 'Title for editing default authenticated permissions'\n },\n perm_anon: {\n id: 'permissions_anonymous',\n defaultMessage: 'Anonymous',\n description: 'Title for editing default anonymous permissions'\n },\n perm_user: {\n id: 'permissions_user',\n defaultMessage: 'User\\'s Permissions',\n description: 'Title for editing user\\'s permissions'\n },\n edit_permissions: {\n id: 'menu_item_edit_permissions',\n defaultMessage: 'Edit permissions',\n description: 'Menu item [Edit permissions]'\n },\n qrcode: {\n id: 'scan_qr_code',\n defaultMessage: 'Scan QR Code',\n description: 'Title for scanning QR code'\n },\n text_copied: {\n id: 'text_copied',\n defaultMessage: 'Copied to clipboard',\n description: 'Notification that text has been copied to clipboard'\n },\n self_topic_name: {\n id: 'self_topic_name',\n defaultMessage: 'Saved messages',\n description: 'Name of self topic for UI',\n },\n self_topic_comment: {\n id: 'self_topic_comment',\n defaultMessage: 'Notes, messages, links, files saved for posterity',\n description: 'Comment for self topic for UI',\n },\n});\n\nclass InfoView extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n topic: null,\n owner: false,\n admin: false,\n sharer: false,\n deleter: false,\n muted: false,\n address: null,\n groupTopic: undefined,\n isSelf: false,\n channel: undefined,\n fullName: undefined,\n description: undefined,\n avatar: null,\n private: null,\n selectedContact: null,\n access: null,\n modeGiven: null,\n modeWant: null,\n modeGiven2: null, // P2P topic, the other user mode given\n modeWant2: null, // P2P topic, the other user mode want\n auth: null,\n anon: null,\n contactList: [],\n trustedBadges: [],\n previousMetaDesc: undefined,\n previousSubsUpdated: undefined,\n };\n\n this.resetSubs = this.resetSubs.bind(this);\n this.resetDesc = this.resetDesc.bind(this);\n this.resetTags = this.resetTags.bind(this);\n this.onMetaDesc = this.onMetaDesc.bind(this);\n this.onSubsUpdated = this.onSubsUpdated.bind(this);\n this.handleImageChanged = this.handleImageChanged.bind(this);\n this.handleMuted = this.handleMuted.bind(this);\n this.handleUnarchive = this.handleUnarchive.bind(this);\n this.handlePermissionsChanged = this.handlePermissionsChanged.bind(this);\n this.handleLaunchPermissionsEditor = this.handleLaunchPermissionsEditor.bind(this);\n this.handleShowQRCode = this.handleShowQRCode.bind(this);\n this.handleCopyToClipboard = this.handleCopyToClipboard.bind(this);\n this.handleShowAddMembers = this.handleShowAddMembers.bind(this);\n this.handleMemberUpdateRequest = this.handleMemberUpdateRequest.bind(this);\n this.handleMemberSelected = this.handleMemberSelected.bind(this);\n this.handleContextMenu = this.handleContextMenu.bind(this);\n this.handleBackNavigate = this.handleBackNavigate.bind(this);\n }\n\n // No need to separately handle component mount.\n componentDidUpdate(props) {\n const topic = this.props.tinode.getTopic(props.topic);\n if (!topic) {\n return;\n }\n\n if (this.onMetaDesc != topic.onMetaDesc) {\n this.previousMetaDesc = topic.onMetaDesc;\n topic.onMetaDesc = this.onMetaDesc;\n\n this.previousSubsUpdated = topic.onSubsUpdated;\n topic.onSubsUpdated = this.onSubsUpdated;\n }\n\n if (this.state.topic != props.topic) {\n this.setState({topic: props.topic});\n this.resetDesc(topic, props);\n this.resetSubs(topic, props);\n this.resetTags(topic);\n }\n }\n\n componentWillUnmount() {\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n this.setState({topic: null});\n topic.onMetaDesc = this.previousMetaDesc;\n topic.onSubsUpdated = this.previousSubsUpdated;\n }\n\n resetSubs(topic, props) {\n const newState = {contactList: []};\n if (topic.getType() == 'p2p') {\n // Fetch the other party in the p2p conversation.\n // Topic may not be ready yet, so check if user is found.\n const user2 = topic.subscriber(props.topic);\n if (user2) {\n newState.modeGiven2 = user2.acs.getGiven();\n newState.modeWant2 = user2.acs.getWant();\n } else {\n newState.modeGiven2 = NO_ACCESS_MODE;\n newState.modeWant2 = NO_ACCESS_MODE;\n }\n } else {\n topic.subscribers((sub) => {\n newState.contactList.push(sub);\n }, this);\n }\n\n this.setState(newState);\n }\n\n resetDesc(topic, props) {\n const defacs = topic.getDefaultAccess() || {};\n const acs = topic.getAccessMode();\n\n const badges = [];\n if (topic.trusted) {\n for (const [key, val] of Object.entries(topic.trusted)) {\n if (val) {\n badges.push(key);\n }\n }\n }\n\n const isSelf = topic.isSelfType();\n\n this.setState({\n owner: acs && acs.isOwner(),\n admin: acs && acs.isAdmin(),\n sharer: acs && acs.isSharer(),\n deleter: acs && acs.isDeleter(),\n muted: acs && acs.isMuted(),\n\n fullName: isSelf ?\n props.intl.formatMessage(messages.self_topic_name) :\n clipStr(topic.public && topic.public.fn, MAX_TITLE_LENGTH),\n description: isSelf ?\n props.intl.formatMessage(messages.self_topic_comment) :\n clipStr(topic.public && topic.public.note, MAX_TOPIC_DESCRIPTION_LENGTH),\n avatar: makeImageUrl(topic.public ? topic.public.photo : null),\n trustedBadges: badges,\n private: clipStr(topic.private && topic.private.comment, MAX_TITLE_LENGTH),\n archived: topic.isArchived(),\n address: topic.name,\n groupTopic: topic.isGroupType(),\n isSelf: isSelf,\n channel: topic.isChannelType() || topic.chan,\n access: acs ? acs.getMode() : undefined,\n modeGiven: acs ? acs.getGiven() : undefined,\n modeWant: acs ? acs.getWant() : undefined,\n auth: defacs.auth,\n anon: defacs.anon\n });\n }\n\n resetTags(topic) {\n if (topic.getType() != 'grp') {\n return;\n }\n\n const acs = topic.getAccessMode();\n if (acs && acs.isOwner()) {\n // Requesting tags: owner is editing the topic.\n topic.getMeta(topic.startMetaQuery().withTags().build());\n }\n }\n\n onMetaDesc(desc) {\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n this.resetDesc(topic, this.props);\n\n if (this.previousMetaDesc && this.previousMetaDesc != this.onMetaDesc) {\n this.previousMetaDesc(desc);\n }\n }\n\n onSubsUpdated(subs) {\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n this.resetSubs(topic, this.props);\n\n if (this.previousSubsUpdated && this.previousSubsUpdated != this.onSubsUpdated) {\n this.previousSubsUpdated(subs);\n }\n }\n\n handleImageChanged(mime, img) {\n this.setState({avatar: img});\n this.props.onTopicDescUpdate(this.props.topic, theCard(null, img || Tinode.DEL_CHAR), null);\n }\n\n handleMuted(ignored, checked) {\n this.setState({muted: checked});\n this.props.onChangePermissions(this.props.topic, checked ? '-P' : '+P');\n }\n\n handleUnarchive(ignored, ignored2) {\n this.props.onTopicUnArchive(this.props.topic);\n }\n\n handlePermissionsChanged(which, perm) {\n switch (which) {\n case 'auth':\n this.props.onTopicDescUpdateRequest(this.props.topic, null, null, {auth: perm});\n break;\n case 'anon':\n this.props.onTopicDescUpdateRequest(this.props.topic, null, null, {anon: perm});\n break;\n case 'mode':\n case 'want':\n this.props.onChangePermissions(this.props.topic, perm);\n break;\n case 'given':\n this.props.onChangePermissions(this.props.topic, perm, this.props.topic);\n break;\n case 'user':\n this.props.onChangePermissions(this.props.topic, perm, this.state.userPermissionsEdited);\n break;\n }\n\n this.handleBackNavigate();\n }\n\n handleLaunchPermissionsEditor(which, uid) {\n const {formatMessage} = this.props.intl;\n let toEdit, toCompare, toSkip, titleEdit, titleCompare, userTitle, userAvatar;\n switch (which) {\n case 'mode':\n toEdit = this.state.access;\n break;\n case 'want':\n toEdit = this.state.modeWant;\n toCompare = this.state.modeGiven;\n if (this.state.owner) {\n // Don't allow owner to unset 'O' permission. All other permissions are OK.\n toSkip = 'O';\n } else {\n // Allow accepting any of 'ASDO' permissions but don't allow asking for them.\n toSkip = AccessMode.encode(AccessMode.diff('ASDO', this.state.modeGiven));\n if (this.state.channel) {\n // Channels are read-only.\n toSkip += 'W';\n }\n }\n titleEdit = formatMessage(messages.perm_want);\n titleCompare = formatMessage(messages.perm_given);\n break;\n case 'given':\n toEdit = this.state.modeGiven2;\n toCompare = this.state.modeWant2;\n toSkip = this.state.groupTopic ? (this.state.owner ? '' : 'O') : 'ASDO';\n titleEdit = formatMessage(messages.perm_given);\n titleCompare = formatMessage(messages.perm_want);\n break;\n case 'auth':\n toEdit = this.state.auth;\n toSkip = 'O';\n break;\n case 'anon':\n toEdit = this.state.anon;\n toSkip = 'O';\n break;\n case 'user': {\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n const user = topic.subscriber(uid);\n if (!user || !user.acs) {\n return;\n }\n toEdit = user.acs.getGiven();\n toCompare = user.acs.getWant();\n toSkip = this.state.owner ? '' : 'O';\n titleEdit = formatMessage(messages.perm_given);\n titleCompare = formatMessage(messages.perm_want);\n if (user.public) {\n userTitle = user.public.fn;\n userAvatar = user.public.photo;\n }\n break;\n }\n default:\n console.error(\"Unknown permission editing mode '\" + which + \"'\");\n return;\n }\n this.setState({\n userPermissionsEdited: uid,\n userPermissionsTitle: userTitle,\n userPermissionsAvatar: userAvatar,\n editedPermissions: toEdit,\n immutablePermissions: toCompare,\n editedPermissionsTitle: titleEdit,\n immutablePermissionsTitle: titleCompare,\n editedPermissionsSkipped: toSkip,\n });\n this.props.onNavigate(`perm/${which}`);\n }\n\n handleShowQRCode(e) {\n e.preventDefault();\n this.props.onNavigate('qrcode');\n }\n\n handleCopyToClipboard(e, text) {\n e.preventDefault();\n navigator.clipboard.writeText(text).then(_ => {\n this.setState({toast: this.props.intl.formatMessage(messages.text_copied)});\n setTimeout(_ => { this.setState({toast: ''}); }, TOAST_DURATION);\n });\n\n }\n\n handleShowAddMembers(e) {\n e.preventDefault();\n this.props.onInitFind();\n this.props.onNavigate('members');\n }\n\n handleMemberUpdateRequest(members, added, removed) {\n this.props.onMemberUpdateRequest(this.props.topic, added, removed);\n this.props.onNavigate('info');\n }\n\n handleMemberSelected(uid) {\n this.setState({selectedContact: uid});\n }\n\n handleBackNavigate() {\n const args = (this.props.panel || 'info').split('/');\n if (args[0] == 'info') {\n this.props.onNavigate(null);\n } else if (args[0] == 'perm') {\n if (args[1] == 'user') {\n this.props.onNavigate('info');\n } else {\n this.props.onNavigate('security');\n }\n } else {\n this.props.onNavigate('info');\n }\n }\n\n handleContextMenu(params) {\n const {formatMessage} = this.props.intl;\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n const user = topic.subscriber(params.topicName);\n if (!user || !user.acs) {\n return;\n }\n\n const isMe = this.props.tinode.isMe(params.topicName);\n const menuItems = [{\n title: formatMessage(messages.edit_permissions),\n handler: _ => this.handleLaunchPermissionsEditor(isMe ? 'want' : 'user', params.topicName)\n }];\n if (!isMe) {\n menuItems.push('member_delete');\n }\n menuItems.push(user.acs.isMuted() ? 'member_unmute' : 'member_mute');\n if (!isMe) {\n menuItems.push(user.acs.isJoiner() ? 'member_block' : 'member_unblock');\n }\n this.props.showContextMenu({\n topicName: this.props.topic,\n x: params.x,\n y: params.y,\n user: params.topicName}, menuItems);\n }\n\n render() {\n const args = (this.props.panel || 'info').split('/');\n const view = args[0];\n args.shift();\n\n const {formatMessage} = this.props.intl;\n const panelTitle = formatMessage((view == 'perm' ? messages['perm_' + args[0]] : messages[view])\n || messages['info']);\n\n const topic = this.props.tinode.getTopic(this.state.topic);\n const alias = topic && topic.alias();\n\n return (\n \n
{this.state.toast}
\n
\n
{panelTitle}
\n
\n \n
\n
\n {this.props.displayMobile ?\n
: null}\n {view == 'members' ?\n
\n :\n view == 'perm' && args.length > 0 ?\n
this.handlePermissionsChanged(args[0], mode)}\n onCancel={this.handleBackNavigate} />\n :\n view == 'general' ?\n \n :\n view == 'security' ?\n \n :\n view == 'qrcode' ?\n \n :\n \n
\n {!this.state.isSelf ?\n
{e.preventDefault(); this.props.onNavigate('general');}}>\n edit \n \n \n : null\n }\n
\n \n \n
\n
\n \n
\n
{this.state.fullName}\n {this.state.channel ?
: null}
\n
\n {this.state.private ?\n
\n
\n \n
\n
{this.state.private}
\n
\n : null\n }\n {!this.state.isSelf ?\n <>\n
\n
\n \n {this.state.address} \n
\n
\n
\n {alias ?\n
\n : null}\n >\n : null\n }\n {this.state.trustedBadges.length > 0 ?\n
\n \n
\n : null\n }\n {this.state.description ?\n
\n
\n \n \n
{this.state.description}
\n
: null}\n
\n {!this.state.isSelf ?\n <>
\n
\n \n \n \n \n
>\n : null\n }\n {this.state.archived ?\n
\n \n \n \n \n
\n :\n null\n }\n {!this.state.isSelf ?\n <>
\n
>\n : null\n }\n {this.state.groupTopic && this.state.sharer ?\n <>\n
\n
\n \n \n \n
\n
\n
{\n (no_members) => \n } \n >\n :\n null\n }\n
\n }\n \n );\n }\n};\n\nexport default injectIntl(InfoView);\n","// CallPanel displays call in progress: local and remote viewports and controls.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport LetterTile from './letter-tile.jsx';\n\nimport { MAX_PEER_TITLE_LENGTH } from '../config.js';\nimport { CALL_STATE_OUTGOING_INITATED, CALL_STATE_IN_PROGRESS } from '../constants.js';\n\nimport { clipStr } from '../lib/utils.js'\n\nconst RING_SOUND = new Audio('audio/call-out.m4a');\nRING_SOUND.loop = true;\nconst CALL_ENDED_SOUND = new Audio('audio/call-end.m4a');\nCALL_ENDED_SOUND.loop = true;\nconst DIALING_SOUND = new Audio('audio/dialing.m4a');\n\nconst VIDEO_MUTED_EVENT = 'video:muted';\nconst VIDEO_UNMUTED_EVENT = 'video:unmuted';\n\nconst messages = defineMessages({\n already_in_call: {\n id: 'already_in_call',\n defaultMessage: 'You already in an ongoing call!',\n description: 'Error message when the user tried to accept a new call without finishing pervious one',\n }\n});\n\nclass CallPanel extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n localStream: undefined,\n remoteStream: undefined,\n pc: undefined,\n dataChannel: undefined,\n\n previousOnInfo: undefined,\n waitingForPeer: false,\n // If true, the client has received a remote SDP from the peer and has sent a local SDP to the peer.\n callInitialSetupComplete: false,\n audioOnly: props.callAudioOnly,\n // Video mute/unmute in progress.\n videoToggleInProgress: false,\n // Indicates if the remote peer has informed us that their camera is on.\n remoteVideoLive: false,\n };\n\n this.localStreamConstraints = {\n audio: true,\n video: !props.callAudioOnly\n };\n this.isOutgoingCall = props.callState == CALL_STATE_OUTGOING_INITATED;\n\n this.localRef = React.createRef();\n this.remoteRef = React.createRef();\n // Cache for remote ice candidates until initial setup gets completed.\n this.remoteIceCandidatesCache = [];\n\n this.onInfo = this.onInfo.bind(this);\n this.start = this.start.bind(this);\n this.stop = this.stop.bind(this);\n\n this.createPeerConnection = this.createPeerConnection.bind(this);\n this.canSendOffer = this.canSendOffer.bind(this);\n this.drainRemoteIceCandidatesCache = this.drainRemoteIceCandidatesCache.bind(this);\n\n this.handleNegotiationNeededEvent = this.handleNegotiationNeededEvent.bind(this);\n this.handleICECandidateEvent = this.handleICECandidateEvent.bind(this);\n this.handleNewICECandidateMsg = this.handleNewICECandidateMsg.bind(this);\n this.handleICEConnectionStateChangeEvent = this.handleICEConnectionStateChangeEvent.bind(this);\n this.handleSignalingStateChangeEvent = this.handleSignalingStateChangeEvent.bind(this);\n this.handleICEGatheringStateChangeEvent = this.handleICEGatheringStateChangeEvent.bind(this);\n this.handleIceCandidateErrorEvent = this.handleIceCandidateErrorEvent.bind(this);\n this.handleTrackEvent = this.handleTrackEvent.bind(this);\n\n this.handleVideoOfferMsg = this.handleVideoOfferMsg.bind(this);\n this.handleVideoAnswerMsg = this.handleVideoAnswerMsg.bind(this);\n this.handleNewICECandidateMsg = this.handleNewICECandidateMsg.bind(this);\n\n this.reportError = this.reportError.bind(this);\n this.handleGetUserMediaError = this.handleGetUserMediaError.bind(this);\n\n this.stopTracks = this.stopTracks.bind(this);\n this.disconnectMedia = this.disconnectMedia.bind(this);\n\n this.handleCloseClick = this.handleCloseClick.bind(this);\n this.handleToggleCameraClick = this.handleToggleCameraClick.bind(this);\n this.handleToggleMicClick = this.handleToggleMicClick.bind(this);\n\n this.handleRemoteHangup = this.handleRemoteHangup.bind(this);\n this.handleVideoCallAccepted = this.handleVideoCallAccepted.bind(this);\n\n this.muteVideo = this.muteVideo.bind(this);\n this.unmuteVideo = this.unmuteVideo.bind(this);\n this.emptyVideoTrack = this.emptyVideoTrack.bind(this);\n\n this.handleDataChannelEvent = this.handleDataChannelEvent.bind(this);\n this.handleDataChannelError = this.handleDataChannelError.bind(this);\n this.handleDataChannelMessage = this.handleDataChannelMessage.bind(this);\n this.handleDataChannelOpen = this.handleDataChannelOpen.bind(this);\n this.handleDataChannelClose = this.handleDataChannelClose.bind(this);\n }\n\n componentDidMount() {\n const topic = this.props.tinode.getTopic(this.props.topic);\n this.previousOnInfo = topic.onInfo;\n topic.onInfo = this.onInfo;\n if ((this.props.callState == CALL_STATE_OUTGOING_INITATED ||\n this.props.callState == CALL_STATE_IN_PROGRESS) && this.localRef.current) {\n this.start();\n }\n }\n\n componentWillUnmount() {\n const topic = this.props.tinode.getTopic(this.props.topic);\n topic.onInfo = this.previousOnInfo;\n this.stop();\n }\n\n handleVideoCallAccepted(info) {\n RING_SOUND.pause();\n // Create peer connection with a data channel.\n const pc = this.createPeerConnection(true);\n const stream = this.state.localStream;\n stream.getTracks().forEach(track => {\n pc.addTrack(track, stream);\n\n if (track.kind == 'video' && this.state.audioOnly) {\n // This is an audio-only call.\n // Remove dummy video track (placeholder remains).\n track.enabled = false;\n track.stop();\n stream.removeTrack(track);\n }\n });\n }\n\n onInfo(info) {\n if (info.what != 'call') {\n return;\n }\n switch (info.event) {\n case 'accept':\n this.handleVideoCallAccepted(info);\n break;\n case 'answer':\n this.handleVideoAnswerMsg(info);\n break;\n case 'ice-candidate':\n this.handleNewICECandidateMsg(info);\n break;\n case 'hang-up':\n this.handleRemoteHangup(info);\n break;\n case 'offer':\n this.handleVideoOfferMsg(info);\n break;\n case 'ringing':\n // play() throws if the user did not click the app first: https://goo.gl/xX8pDD.\n RING_SOUND.play().catch(_ => {});\n break;\n default:\n console.warn(\"Unknown call event\", info.event);\n break;\n }\n }\n\n // Creates an empty video track placeholder.\n emptyVideoTrack() {\n const width = 640;\n const height = 480;\n const canvas = Object.assign(document.createElement(\"canvas\"), {width, height});\n canvas.getContext('2d').fillRect(0, 0, width, height);\n const stream = canvas.captureStream(0);\n return Object.assign(stream.getVideoTracks()[0], {enabled: false});\n }\n\n start() {\n if (this.state.localStream) {\n this.props.onError(this.props.intl.formatMessage(messages.already_in_call), 'info');\n return;\n }\n\n if (this.props.callState == CALL_STATE_IN_PROGRESS) {\n // We apparently just accepted the call.\n this.props.onInvite(this.props.topic, this.props.seq, CALL_STATE_IN_PROGRESS, this.props.callAudioOnly);\n return;\n }\n\n // This is an outgoing call waiting for the other side to pick up.\n // Start local video.\n navigator.mediaDevices.getUserMedia(this.localStreamConstraints)\n .then(stream => {\n if (!this.localStreamConstraints.video) {\n // Starting an audio-only call. Create a dummy video track\n // (so video can be enabled during the call if the user desires).\n stream.addTrack(this.emptyVideoTrack());\n }\n this.setState({localStream: stream, waitingForPeer: true});\n this.localRef.current.srcObject = stream;\n\n DIALING_SOUND.play();\n\n // Send call invitation.\n this.props.onInvite(this.props.topic, this.props.seq, this.props.callState, this.props.callAudioOnly);\n })\n .catch(this.handleGetUserMediaError);\n }\n\n stop() {\n CALL_ENDED_SOUND.pause();\n CALL_ENDED_SOUND.currentTime = 0;\n RING_SOUND.pause();\n RING_SOUND.currentTime = 0;\n\n this.stopTracks(this.state.localStream);\n this.stopTracks(this.state.remoteStream);\n this.disconnectMedia(this.localRef.current);\n this.disconnectMedia(this.remoteRef.current);\n if (this.state.pc) {\n this.state.pc.ontrack = null;\n this.state.pc.onremovetrack = null;\n this.state.pc.onremovestream = null;\n this.state.pc.onicecandidate = null;\n this.state.pc.oniceconnectionstatechange = null;\n this.state.pc.onsignalingstatechange = null;\n this.state.pc.onicegatheringstatechange = null;\n this.state.pc.onnegotiationneeded = null;\n this.state.pc.onicecandidateerror = null;\n this.state.pc.ondatachannel = null;\n\n if (this.state.dataChannel && (this.state.dataChannel.readyState == 'open' || this.state.dataChannel.readyState == 'connecting')) {\n this.state.dataChannel.close();\n }\n this.state.pc.close();\n }\n this.setState({pc: null, waitingForPeer: false});\n }\n\n disconnectMedia(el) {\n if (!el) {\n return;\n }\n\n el.srcObject = null;\n el.src = '';\n }\n\n stopTracks(stream) {\n if (!stream) {\n return;\n }\n\n let tracks = stream.getTracks();\n if (tracks) {\n tracks.forEach(track => {\n track.stop();\n track.enabled = false;\n });\n }\n }\n\n handleDataChannelError(error) {\n console.error('data channel error', error);\n }\n\n handleDataChannelMessage(event) {\n switch (event.data) {\n case VIDEO_MUTED_EVENT:\n this.setState({remoteVideoLive: false}, _ => { this.remoteRef.current.srcObject = this.state.remoteStream; });\n break;\n case VIDEO_UNMUTED_EVENT:\n this.setState({remoteVideoLive: true}, _ => { this.remoteRef.current.srcObject = this.state.remoteStream; });\n break;\n default:\n break;\n }\n }\n\n handleDataChannelOpen(event) {\n if (!this.state.audioOnly) {\n event.target.send(VIDEO_UNMUTED_EVENT);\n }\n }\n\n handleDataChannelClose(event) {\n console.log('close data channel:', event);\n }\n\n handleDataChannelEvent(event) {\n console.log('data channel event:', event);\n const channel = event.channel;\n channel.onerror = this.handleDataChannelError;\n channel.onmessage = this.handleDataChannelMessage;\n channel.onopen = this.handleDataChannelOpen;\n channel.onclose = this.handleDataChannelClose;\n this.setState({dataChannel: channel});\n }\n\n createPeerConnection(withDataChannel) {\n const iceServers = this.props.tinode.getServerParam('iceServers', null);\n const pc = iceServers ? new RTCPeerConnection({iceServers: iceServers}) : new RTCPeerConnection();\n\n pc.onicecandidate = this.handleICECandidateEvent;\n pc.oniceconnectionstatechange = this.handleICEConnectionStateChangeEvent;\n pc.onicegatheringstatechange = this.handleICEGatheringStateChangeEvent;\n pc.onsignalingstatechange = this.handleSignalingStateChangeEvent;\n pc.onnegotiationneeded = this.handleNegotiationNeededEvent;\n pc.onicecandidateerror = this.handleIceCandidateErrorEvent;\n pc.ontrack = this.handleTrackEvent;\n pc.ondatachannel = this.handleDataChannelEvent;\n\n let stateUpdate = {pc: pc, waitingForPeer: false};\n if (withDataChannel) {\n // Create data channel for exchanging events.\n const channel = pc.createDataChannel(\"events\", {ordered: true});\n channel.onerror = this.handleDataChannelError;\n channel.onmessage = this.handleDataChannelMessage;\n channel.onopen = this.handleDataChannelOpen;\n channel.onclose = this.handleDataChannelClose;\n stateUpdate.dataChannel = channel;\n }\n this.setState(stateUpdate);\n return pc;\n }\n\n handleVideoAnswerMsg(info) {\n // Configure the remote description, which is the SDP payload\n // in 'info' message.\n const desc = new RTCSessionDescription(info.payload);\n this.state.pc.setRemoteDescription(desc)\n .then(_ => {\n this.setState({ callInitialSetupComplete: true }, _ => this.drainRemoteIceCandidatesCache());\n })\n .catch(err => this.reportError(err));\n }\n\n reportError(err) {\n this.props.onError(err.message, 'err');\n }\n\n canSendOffer() {\n return this.isOutgoingCall || this.state.callInitialSetupComplete;\n }\n\n handleNegotiationNeededEvent(event) {\n const pc = event.target;\n if (!this.canSendOffer()) {\n return;\n }\n pc.createOffer().then(offer => {\n return pc.setLocalDescription(offer);\n })\n .then(_ => {\n this.props.onSendOffer(this.props.topic, this.props.seq, pc.localDescription.toJSON());\n })\n .catch(err => this.reportError(err));\n }\n\n handleIceCandidateErrorEvent(event) {\n console.warn(\"ICE candidate error:\", event);\n }\n\n handleICECandidateEvent(event) {\n if (event.candidate) {\n this.props.onIceCandidate(this.props.topic, this.props.seq, event.candidate.toJSON());\n }\n }\n\n handleNewICECandidateMsg(info) {\n const candidate = new RTCIceCandidate(info.payload);\n if (this.state.callInitialSetupComplete) {\n this.state.pc.addIceCandidate(candidate)\n .catch(err => {\n if (candidate.candidate) {\n this.reportError(err);\n }\n console.warn(\"Error adding new ice candidate\", candidate, err);\n });\n } else {\n this.remoteIceCandidatesCache.push(candidate);\n }\n }\n\n drainRemoteIceCandidatesCache() {\n this.remoteIceCandidatesCache.forEach(candidate => {\n this.state.pc.addIceCandidate(candidate)\n .catch(err => {\n if (candidate.candidate) {\n this.reportError(err);\n }\n console.warn(\"Error adding cached ice candidate\", candidate, err);\n });\n });\n this.remoteIceCandidatesCache = [];\n }\n\n handleICEConnectionStateChangeEvent(event) {\n switch (event.target.iceConnectionState) {\n case 'closed':\n case 'failed':\n this.handleCloseClick();\n break;\n }\n }\n\n handleSignalingStateChangeEvent(event) {\n if (event.target.signalingState == 'closed') {\n this.handleCloseClick();\n }\n }\n\n handleICEGatheringStateChangeEvent(event) {\n // ICE gathering change state\n }\n\n handleTrackEvent(event) {\n // Remote video becomes available.\n this.remoteRef.current.srcObject = event.streams[0];\n this.setState({remoteStream: event.streams[0]});\n }\n\n handleGetUserMediaError(e) {\n console.error(\"Error opening camera and/or microphone\", e);\n switch(e.name) {\n case 'NotFoundError':\n // Cannot start the call b/c no camera and/or microphone found.\n this.reportError(e);\n break;\n case 'SecurityError':\n case 'PermissionDeniedError':\n // Do nothing; this is the same as the user canceling the call.\n break;\n default:\n this.reportError(e);\n break;\n }\n\n // Make sure we shut down our end of the RTCPeerConnection so we're\n // ready to try again.\n this.handleCloseClick();\n }\n\n handleVideoOfferMsg(info) {\n let localStream = null;\n // If needed, create peer connection.\n // Not creating data channel since it should be created by the peer.\n const pc = this.state.pc ? this.state.pc : this.createPeerConnection(false);\n const desc = new RTCSessionDescription(info.payload);\n\n pc.setRemoteDescription(desc).then(_ => {\n return navigator.mediaDevices.getUserMedia(this.localStreamConstraints);\n })\n .then(stream => {\n let dummyVideo;\n if (!this.localStreamConstraints.video) {\n // Starting an audio-only call. Create an empty video track so\n // so the user can enable the video during the call.\n dummyVideo = this.emptyVideoTrack();\n stream.addTrack(dummyVideo);\n }\n localStream = stream;\n this.localRef.current.srcObject = stream;\n this.setState({localStream: stream});\n\n localStream.getTracks().forEach(track => {\n pc.addTrack(track, localStream);\n });\n\n if (dummyVideo) {\n dummyVideo.enabled = false;\n dummyVideo.stop();\n stream.removeTrack(dummyVideo);\n }\n })\n .then(_ => {\n return pc.createAnswer();\n })\n .then(answer => {\n return pc.setLocalDescription(answer);\n })\n .then(_ => {\n this.props.onSendAnswer(this.props.topic, this.props.seq, pc.localDescription.toJSON());\n this.setState({ callInitialSetupComplete: true }, _ => this.drainRemoteIceCandidatesCache());\n })\n .catch(this.handleGetUserMediaError);\n }\n\n // Call disconnected by remote.\n handleRemoteHangup() {\n if (!this.state.waitingForPeer) {\n // This is live call, just hang up.\n this.handleCloseClick();\n } else {\n // This is a call which is not yet connected.\n // Stop pulse animation.\n this.setState({waitingForPeer: false});\n // Change sound and wait a bit before ending it.\n RING_SOUND.pause();\n RING_SOUND.currentTime = 0;\n CALL_ENDED_SOUND.loop = true;\n CALL_ENDED_SOUND.play().catch(_ => {});\n setTimeout(_ => {\n this.handleCloseClick();\n }, 2000);\n }\n }\n\n handleCloseClick() {\n this.stop();\n this.props.onHangup(this.props.topic, this.props.seq);\n }\n\n // Ends video track and turns off the camera.\n muteVideo() {\n if (!this.state.pc || !this.state.dataChannel) {\n return;\n }\n\n const stream = this.state.localStream;\n const t = stream.getVideoTracks()[0];\n t.enabled = false;\n t.stop();\n\n stream.removeTrack(t);\n this.state.dataChannel.send(VIDEO_MUTED_EVENT);\n this.setState({videoToggleInProgress: false});\n }\n\n unmuteVideo() {\n if (!this.state.pc || !this.state.dataChannel) {\n return;\n }\n navigator.mediaDevices.getUserMedia({ video: true })\n .then(stream => {\n // Will extract video track from stream and throw stream away,\n // and replace video track in the media sender.\n this.localRef.current.srcObject = null;\n const sender = this.state.pc.getSenders().find(s => s.track.kind == 'video');\n const track = stream.getVideoTracks()[0];\n // Remote track from new stream.\n stream.removeTrack(track);\n // Add this track to the existing local stream.\n this.state.localStream.addTrack(track);\n return sender.replaceTrack(track);\n })\n .then(_ => {\n this.localRef.current.srcObject = this.state.localStream;\n this.state.dataChannel.send(VIDEO_UNMUTED_EVENT);\n })\n .catch(err => this.handleGetUserMediaError(err))\n .finally(_ => { this.setState({videoToggleInProgress: false}); }); // Make sure we redraw the mute/unmute icons (e.g. camera -> camera_off).\n }\n\n handleToggleCameraClick() {\n if (this.state.videoToggleInProgress) {\n // Toggle currently in progress.\n return;\n }\n const tracks = this.state.localStream.getVideoTracks();\n this.setState({videoToggleInProgress: true}, _ => {\n if (tracks && tracks.length > 0 && tracks[0].enabled && tracks[0].readyState == 'live') {\n this.muteVideo();\n } else {\n this.unmuteVideo();\n }\n this.setState({audioOnly: !this.state.audioOnly});\n });\n }\n\n handleToggleMicClick() {\n const stream = this.state.localStream;\n const t = stream.getAudioTracks()[0];\n t.enabled = !t.enabled;\n // Make sure we redraw the mute/unmute icons (e.g. mic -> mic_off).\n this.forceUpdate();\n }\n\n render() {\n const audioTracks = this.state.localStream && this.state.localStream.getAudioTracks();\n const videoTracks = !this.state.audioOnly && this.state.localStream && this.state.localStream.getVideoTracks();\n const disabled = !this.state.pc || !this.state.dataChannel || !(audioTracks && audioTracks[0]);\n const audioIcon = audioTracks && audioTracks[0] && audioTracks[0].enabled ? 'mic' : 'mic_off';\n const videoIcon = videoTracks && videoTracks[0] && videoTracks[0].enabled && videoTracks[0].readyState == 'live' ? 'videocam' : 'videocam_off';\n const peerTitle = clipStr(this.props.title, MAX_PEER_TITLE_LENGTH);\n const pulseAnimation = this.state.waitingForPeer ? ' pulse' : '';\n\n let remoteActive = false;\n if (this.remoteRef.current && this.remoteRef.current.srcObject && this.state.remoteVideoLive) {\n const rstream = this.remoteRef.current.srcObject;\n if (rstream.getVideoTracks().length > 0) {\n const t = rstream.getVideoTracks()[0];\n remoteActive = t.enabled && t.readyState == 'live';\n }\n }\n\n return (\n <>\n \n
\n
\n
\n {remoteActive ?\n <>\n
\n
{peerTitle}
\n > :\n <>\n
\n
\n
\n \n
\n
{peerTitle}
\n
\n >\n }\n
\n
\n
\n \n call_end \n \n \n {videoIcon} \n \n \n {audioIcon} \n \n
\n
\n >\n );\n }\n};\n\nexport default injectIntl(CallPanel);\n","import React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport FileProgress from './file-progress.jsx';\nimport { bytesToHumanSize } from '../lib/strformat.js';\nimport { isUrlRelative, sanitizeUrl } from '../lib/utils.js';\n\nexport default class Attachment extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n downloader: null,\n progress: 0\n };\n\n this.downloadFile = this.downloadFile.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n }\n\n downloadFile(url, filename, mimetype) {\n if (!url) {\n this.props.onError(\"Invalid download URL '\" + url + \"'\");\n return;\n }\n\n const downloader = this.props.tinode.getLargeFileHelper();\n this.setState({downloader: downloader});\n downloader.download(url, filename, mimetype,\n loaded => this.setState({progress: loaded / this.props.size}),\n err => this.props.onError(err, 'err')\n )\n .then(_ => this.setState({downloader: null, progress: 0}))\n .catch(err => {\n if (err) {\n this.props.onError(\"Error downloading file: \" + err.message, 'err');\n }\n this.setState({downloader: null, progress: 0});\n });\n }\n\n handleCancel() {\n if (this.props.uploading) {\n this.props.onCancelUpload();\n } else if (this.state.downloader) {\n this.state.downloader.cancel();\n }\n }\n\n render() {\n let filename = this.props.filename || 'file_attachment';\n if (filename.length > 36) {\n filename = filename.substr(0, 16) + '...' + filename.substr(-16);\n }\n let size = this.props.size > 0 ?\n ({bytesToHumanSize(this.props.size)}) :\n null;\n\n // Detect if the download URL is relative or absolute.\n // If the URL is relative use LargeFileHelper to attach authentication\n // credentials to the request.\n let url, helperFunc;\n if (!this.props.uploading && !this.state.downloader && isUrlRelative(this.props.downloadUrl)) {\n // Relative URL. Use download helper.\n url = '#';\n helperFunc = (e) => {\n e.preventDefault();\n this.downloadFile(this.props.downloadUrl, this.props.filename, this.props.mimetype);\n };\n } else {\n url = sanitizeUrl(this.props.downloadUrl);\n helperFunc = null;\n }\n const downloadWidget = <>file_download >;\n return (\n \n
insert_drive_file
\n
\n
{filename} {size}
\n {this.props.uploading || this.state.downloader ?\n
\n :\n
\n }\n
\n
\n );\n }\n};\n","// Received/read indicator.\nimport React from 'react';\nimport { defineMessages, injectIntl } from 'react-intl';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport { deliveryMarker } from '../lib/utils.js';\n\nconst messages = defineMessages({\n message_sending: {\n id: 'message_sending',\n defaultMessage: 'sending...',\n description: 'Message being sent, in place of time stamp'\n },\n message_sending_failed: {\n id: 'message_sending_failed',\n defaultMessage: 'failed',\n description: 'Failed to send message, in place of time stamp'\n },\n message_edited_marker: {\n id: 'message_edited_marker',\n defaultMessage: ', edited',\n description: 'Marker indicating that the message was edited'\n }\n});\n\nclass ReceivedMarker extends React.PureComponent {\n render() {\n const {formatMessage} = this.props.intl;\n let timestamp;\n if (this.props.received <= Tinode.MESSAGE_STATUS_SENDING) {\n timestamp = formatMessage(messages.message_sending);\n } else if (this.props.received == Tinode.MESSAGE_STATUS_FAILED ||\n this.props.received == Tinode.MESSAGE_STATUS_FATAL) {\n timestamp = formatMessage(messages.message_sending_failed);\n } else {\n timestamp = this.props.timestamp.toLocaleTimeString(this.props.intl.locale, { timeStyle: 'short' });\n }\n\n const icon = deliveryMarker(this.props.received);\n const marker = icon ? {icon.name} : null;\n const edited = this.props.edited ? formatMessage(messages.message_edited_marker) : null;\n\n return (\n \n {timestamp}{edited}{'\\u00a0'}{marker}\n \n );\n }\n};\n\nexport default injectIntl(ReceivedMarker);\n","// Single chat message bubble, sent or received.\n\nimport React from 'react';\nimport { FormattedMessage, injectIntl } from 'react-intl';\nimport { Drafty, Tinode } from 'tinode-sdk';\n\nimport Attachment from './attachment.jsx';\nimport LetterTile from './letter-tile.jsx';\nimport ReceivedMarker from './received-marker.jsx'\n\nimport { fullFormatter } from '../lib/formatters.js';\nimport { sanitizeUrl } from '../lib/utils.js';\n\nclass BaseChatMessage extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n progress: 0\n };\n\n if (props.uploader) {\n props.uploader.onProgress = this.handleProgress.bind(this);\n }\n\n this.handleExpandImage = this.handleExpandImage.bind(this);\n this.handlePlayVideo = this.handlePlayVideo.bind(this);\n this.handleFormButtonClick = this.handleFormButtonClick.bind(this);\n this.handleContextClick = this.handleContextClick.bind(this);\n this.handleCancelUpload = this.handleCancelUpload.bind(this);\n this.handleQuoteClick = this.handleQuoteClick.bind(this);\n\n this.formatterContext = {\n formatMessage: props.intl.formatMessage.bind(props.intl),\n viewportWidth: props.viewportWidth,\n authorizeURL: props.tinode.authorizeURL.bind(props.tinode),\n\n onImagePreview: this.handleExpandImage,\n onVideoPreview: this.handlePlayVideo,\n onFormButtonClick: this.handleFormButtonClick,\n onQuoteClick: this.handleQuoteClick\n };\n }\n\n handleExpandImage(e) {\n e.preventDefault();\n this.props.onExpandMedia({\n url: e.target.src,\n filename: e.target.dataset.name,\n width: e.target.dataset.width,\n height: e.target.dataset.height,\n size: e.target.dataset.size,\n type: e.target.dataset.mime\n });\n }\n\n handlePlayVideo(e) {\n e.preventDefault();\n this.props.onExpandMedia({\n video: true,\n url: e.target.dataset.src,\n preview: e.target.src,\n filename: e.target.dataset.name,\n width: e.target.dataset.width,\n height: e.target.dataset.height,\n duration: e.target.dataset.duration,\n size: e.target.dataset.size,\n type: e.target.dataset.mime\n });\n }\n\n handleFormButtonClick(e) {\n e.preventDefault();\n const data = {\n seq: this.props.seq\n };\n data.resp = {};\n if (e.target.dataset.name) {\n data.resp[e.target.dataset.name] = e.target.dataset.val ? e.target.dataset.val :\n e.target.dataset.val === undefined ? 1 : '' + e.target.dataset.val;\n }\n if (e.target.dataset.act == 'url') {\n data.ref = sanitizeUrl(e.target.dataset.ref) || 'about:blank';\n }\n const text = e.target.dataset.title || 'unknown';\n this.props.onFormResponse(e.target.dataset.act, text, data);\n }\n\n handleContextClick(e) {\n e.preventDefault();\n e.stopPropagation();\n const menuItems = [];\n if (this.props.received == Tinode.MESSAGE_STATUS_FAILED) {\n menuItems.push('menu_item_send_retry');\n }\n if (this.props.received > Tinode.MESSAGE_STATUS_FATAL) {\n if (this.props.userIsWriter) {\n menuItems.push('menu_item_reply');\n if (!this.props.response) {\n let immutable = false;\n Drafty.entities(this.props.content, (_0, _1, tp) => {\n immutable = ['AU', 'EX', 'FM', 'IM', 'VC', 'VD'].includes(tp);\n return immutable;\n });\n if (!immutable) {\n Drafty.styles(this.props.content, tp => {\n immutable = ['QQ'].includes(tp);\n return immutable;\n });\n }\n if (!immutable) {\n menuItems.push('menu_item_edit');\n }\n }\n }\n if (this.props.userIsAdmin) {\n menuItems.push(this.props.pinned ? 'menu_item_unpin' : 'menu_item_pin');\n }\n }\n menuItems.push('menu_item_forward');\n\n this.props.showContextMenu({\n seq: this.props.seq,\n replace: this.props.edited ? parseInt(this.props.edited.split(':')[1]) : 0,\n content: this.props.content,\n userFrom: this.props.userFrom,\n userName: this.props.userName,\n y: e.pageY,\n x: e.pageX,\n pickReply: this.props.pickReply,\n editMessage: this.props.editMessage,\n timestamp: this.props.timestamp,\n }, menuItems);\n }\n\n handleProgress(ratio) {\n this.setState({progress: ratio});\n }\n\n handleCancelUpload() {\n this.props.onCancelUpload(this.props.seq, this.props.uploader);\n }\n\n handleQuoteClick(e) {\n e.preventDefault();\n e.stopPropagation();\n const replyToSeq = this.props.replyToSeq;\n if (replyToSeq) {\n this.props.onQuoteClick(replyToSeq);\n }\n }\n\n render() {\n const sideClass = this.props.sequence + ' ' + (this.props.response ? 'left' : 'right');\n const bubbleClass = (this.props.sequence == 'single' || this.props.sequence == 'last') ? 'bubble tip' : 'bubble';\n const avatar = this.props.userAvatar || true;\n let textSizeClass = 'message-content';\n const fullDisplay = (this.props.isGroup && this.props.response &&\n (this.props.sequence == 'single' || this.props.sequence == 'last'));\n\n let content = this.props.content;\n const attachments = [];\n if (this.props.mimeType == Drafty.getContentType() && Drafty.isValid(content)) {\n Drafty.attachments(content, (att, i) => {\n if (att.mime == 'application/json+drafty' ||\n att.mime == 'application/json') {\n // Don't show json drafty form response objects as attachments.\n // They are not meant for users.\n return;\n }\n attachments.push( );\n }, this);\n const tree = Drafty.format(content, fullFormatter, this.formatterContext);\n content = React.createElement(React.Fragment, null, tree);\n } else if (typeof content == 'string') {\n // Make font bigger for emoji-only messages.\n // Must use 'new RegExp(...)' because React does not like /{1-5}/.\n if (new RegExp('^\\\\p{RGI_Emoji}{1,5}$', 'v').test(content || '')) {\n // Content consists of 1-5 emoji characters. Count how many and use it to increase the font size.\n textSizeClass += ' emoji-' + (content || '').match(/\\p{RGI_Emoji}/vg).length;\n }\n } else {\n content = <>warning_amber \n >\n }\n\n return (\n \n {this.props.isGroup && this.props.response ?\n \n {fullDisplay ?\n :\n null}\n
:\n null}\n \n
\n
\n
\n {content}\n {attachments}\n
\n {this.props.timestamp ?\n
\n : null}\n
\n {this.props.showContextMenu ?\n
\n \n expand_more \n \n : null\n }\n
\n {fullDisplay ?\n
\n {this.props.userName ||\n \n }\n
\n : null\n }\n
\n \n );\n }\n};\n\nconst IntlChatMessage = injectIntl(BaseChatMessage);\nconst ChatMessage = React.forwardRef((props, ref) => );\n\nexport default ChatMessage;\n","// Send message form.\nimport React, { Suspense } from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\nimport { Drafty } from 'tinode-sdk';\n\n// Lazy-loading AudioRecorder because it's quite large due to\n// a dependency on webm-duration-fix.\nconst AudioRecorder = React.lazy(_ => import('./audio-recorder.jsx'));\n\nimport { KEYPRESS_DELAY } from '../config.js';\nimport { filePasted } from '../lib/blob-helpers.js';\nimport { replyFormatter } from '../lib/formatters.js';\n\nconst messages = defineMessages({\n messaging_disabled: {\n id: 'messaging_disabled_prompt',\n defaultMessage: 'Messaging disabled',\n description: 'Prompt in SendMessage in read-only topic'\n },\n type_new_message: {\n id: 'new_message_prompt',\n defaultMessage: 'New message',\n description: 'Prompt in send message field'\n },\n add_image_caption: {\n id: 'image_caption_prompt',\n defaultMessage: 'Image caption',\n description: 'Prompt in SendMessage for attached image'\n },\n file_attachment_too_large: {\n id: 'file_attachment_too_large',\n defaultMessage: 'The file size {size} exceeds the {limit} limit.',\n description: 'Error message when attachment is too large'\n },\n cannot_initiate_upload: {\n id: 'cannot_initiate_file_upload',\n defaultMessage: 'Cannot initiate file upload.',\n description: 'Generic error messagewhen attachment fails'\n },\n icon_title_record_voice: {\n id: 'icon_title_record_voice',\n defaultMessage: 'Record voice message',\n description: 'Icon tool tip for recording a voice message'\n },\n icon_title_attach_file: {\n id: 'icon_title_attach_file',\n defaultMessage: 'Attach file',\n description: 'Icon tool tip for attaching a file'\n },\n icon_title_add_image: {\n id: 'icon_title_add_image',\n defaultMessage: 'Add image',\n description: 'Icon tool tip for attaching an image'\n },\n icon_title_send: {\n id: 'icon_title_send',\n defaultMessage: 'Send message',\n description: 'Icon tool tip for sending a message'\n },\n});\n\nclass SendMessage extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n quote: null,\n message: '',\n audioRec: false,\n audioAvailable: !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia),\n };\n\n // Timestamp when the previous key press was sent to the server.\n this.keypressTimestamp = 0;\n\n this.handlePasteEvent = this.handlePasteEvent.bind(this);\n this.handleAttachImage = this.handleAttachImage.bind(this);\n this.handleAttachFile = this.handleAttachFile.bind(this);\n this.handleAttachAudio = this.handleAttachAudio.bind(this);\n this.handleSend = this.handleSend.bind(this);\n this.handleKeyPress = this.handleKeyPress.bind(this);\n this.handleMessageTyping = this.handleMessageTyping.bind(this);\n this.handleDropAttach = this.handleDropAttach.bind(this);\n\n this.handleQuoteClick = this.handleQuoteClick.bind(this);\n\n this.formatReply = this.formatReply.bind(this);\n }\n\n componentDidMount() {\n if (this.messageEditArea) {\n this.messageEditArea.addEventListener('paste', this.handlePasteEvent, false);\n if (window.getComputedStyle(this.messageEditArea).getPropertyValue('transition-property') == 'all') {\n // Set focus on desktop, but not on mobile: focus causes soft keyboard to pop up.\n this.messageEditArea.focus();\n }\n }\n\n this.setState({quote: this.formatReply()});\n }\n\n componentWillUnmount() {\n if (this.messageEditArea) {\n this.messageEditArea.removeEventListener('paste', this.handlePasteEvent, false);\n }\n }\n\n componentDidUpdate(prevProps) {\n if (this.messageEditArea) {\n if (window.getComputedStyle(this.messageEditArea).getPropertyValue('transition-property') == 'all') {\n // Set focus on desktop, but not on mobile: focus causes soft keyboard to pop up.\n this.messageEditArea.focus();\n }\n\n // Adjust height of the message area for the amount of text.\n this.messageEditArea.style.height = '0px';\n this.messageEditArea.style.height = this.messageEditArea.scrollHeight + 'px';\n }\n\n if (prevProps.topicName != this.props.topicName) {\n this.setState({message: this.props.initMessage || '', audioRec: false, quote: null});\n } else if (prevProps.initMessage != this.props.initMessage) {\n const msg = this.props.initMessage || '';\n this.setState({message: msg}, _ => {\n // If there is text, scroll to bottom and set caret to the end.\n this.messageEditArea.scrollTop = this.messageEditArea.scrollHeight;\n this.messageEditArea.setSelectionRange(msg.length, msg.length);\n });\n }\n if (prevProps.reply != this.props.reply) {\n this.setState({quote: this.formatReply()});\n }\n }\n\n formatReply() {\n return this.props.reply ?\n Drafty.format(this.props.reply.content, replyFormatter, {\n formatMessage: this.props.intl.formatMessage.bind(this.props.intl),\n authorizeURL: this.props.tinode.authorizeURL.bind(this.props.tinode)\n }) : null;\n }\n\n handlePasteEvent(e) {\n if (this.props.disabled) {\n return;\n }\n // FIXME: handle large files too.\n if (filePasted(e,\n file => { this.props.onAttachImage(file); },\n file => { this.props.onAttachFile(file); },\n this.props.onError)) {\n\n // If a file was pasted, don't paste base64 data into input field.\n e.preventDefault();\n }\n }\n\n handleAttachImage(e) {\n if (e.target.files && e.target.files.length > 0) {\n this.props.onAttachImage(e.target.files[0]);\n }\n // Clear the value so the same file can be uploaded again.\n e.target.value = '';\n }\n\n handleAttachFile(e) {\n if (e.target.files && e.target.files.length > 0) {\n this.props.onAttachFile(e.target.files[0]);\n }\n // Clear the value so the same file can be uploaded again.\n e.target.value = '';\n }\n\n handleDropAttach(files) {\n if (files && files.length > 0) {\n this.props.onAttachFile(files[0]);\n }\n }\n\n handleAttachAudio(url, preview, duration) {\n this.setState({audioRec: false});\n this.props.onAttachAudio(url, preview, duration);\n }\n\n handleSend(e) {\n e.preventDefault();\n const message = this.state.message.trim();\n if (message || this.props.acceptBlank || this.props.noInput) {\n this.props.onSendMessage(message);\n this.setState({message: ''});\n }\n }\n\n /* Send on Enter key */\n handleKeyPress(e) {\n if (this.state.audioRec) {\n // Ignore key presses while audio is being recorded.\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n // Remove this if you don't want Enter to trigger send\n if (e.key === 'Enter') {\n // Have Shift-Enter insert a line break instead\n if (!e.shiftKey) {\n e.preventDefault();\n e.stopPropagation();\n\n this.handleSend(e);\n }\n }\n }\n\n handleMessageTyping(e) {\n this.setState({message: e.target.value});\n if (this.props.onKeyPress) {\n const now = new Date().getTime();\n if (now - this.keypressTimestamp > KEYPRESS_DELAY) {\n this.props.onKeyPress();\n this.keypressTimestamp = now;\n }\n }\n }\n\n handleQuoteClick(e) {\n e.preventDefault();\n e.stopPropagation();\n if (this.props.reply && this.props.onQuoteClick) {\n const replyToSeq = this.props.reply.seq;\n this.props.onQuoteClick(replyToSeq);\n }\n }\n\n render() {\n const { formatMessage } = this.props.intl;\n const prompt = this.props.disabled ?\n formatMessage(messages.messaging_disabled) :\n (this.props.messagePrompt ?\n formatMessage(messages[this.props.messagePrompt]) :\n formatMessage(messages.type_new_message));\n\n const sendIcon = (this.props.reply && this.props.reply.editing) ?\n 'check_circle' : 'send';\n\n const quote = this.state.quote ?\n (\n
\n {this.state.quote}\n
) : null;\n const audioEnabled = this.state.audioAvailable && this.props.onAttachAudio;\n return (\n \n {!this.props.noInput ? quote : null}\n
}>\n
this.props.onKeyPress(true)}\n onDeleted={_ => this.setState({audioRec: false})}\n onFinished={this.handleAttachAudio}/>\n ) :\n \n \n );\n }\n};\n\nexport default injectIntl(SendMessage);\n","import React from 'react';\nimport { FormattedMessage } from 'react-intl';\nimport SendMessage from '../widgets/send-message.jsx';\n\nimport { bytesToHumanSize, shortenFileName } from '../lib/strformat.js';\n\n// Get material icon name from mime type.\nfunction iconFromMime(mime) {\n // If more icons become available in material icons, add them to this mime-to-icon mapping.\n const mimeToIcon = {default: 'insert_drive_file', image: 'image', text: 'description', video: 'theaters'};\n\n return mimeToIcon[mime] || mimeToIcon[(mime || '').split('/')[0]] || mimeToIcon['default'];\n}\n\nexport default class DocPreview extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleSendDoc = this.handleSendDoc.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n }\n\n componentDidMount() {\n document.addEventListener('keydown', this.handleKeyDown);\n }\n\n componentWillUnmount() {\n document.removeEventListener('keydown', this.handleKeyDown);\n }\n\n handleKeyDown(e) {\n e.preventDefault();\n if (e.key === 'Escape') {\n this.props.onClose();\n }\n }\n\n handleSendDoc(caption) {\n this.props.onClose();\n this.props.onSendMessage(this.props.content.file);\n }\n\n render() {\n if (!this.props.content) {\n return null;\n }\n return (\n \n
\n
\n
\n
{iconFromMime(this.props.content.type)} \n
{shortenFileName(this.props.content.name, 24) || '-'}
\n
{this.props.content.type || 'application/octet-stream'}
\n
{bytesToHumanSize(this.props.content.size)}
\n
\n
\n
\n
\n );\n }\n};\n","// GroupSubs: a list of group subscribers currently online.\n// Show in the topic title bar\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { MAX_ONLINE_IN_TOPIC } from '../config.js'\n\nimport LetterTile from './letter-tile.jsx';\nimport { makeImageUrl } from '../lib/blob-helpers.js';\n\nexport default class GroupSubs extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n const usersOnline = [];\n const totalCount = (this.props.subscribers || []).length;\n const countToShow = Math.min(MAX_ONLINE_IN_TOPIC, totalCount);\n\n (this.props.subscribers || []).some((sub) => {\n usersOnline.push(\n \n \n
\n );\n return usersOnline.length == countToShow;\n });\n if (usersOnline.length == 0) {\n return null;\n }\n return (\n {usersOnline} {totalCount > countToShow ?\n \n \n : null}\n
\n );\n }\n};\n","import React from 'react';\nimport { FormattedMessage } from 'react-intl';\nimport SendMessage from './send-message.jsx';\n\nimport { REM_SIZE } from '../config.js';\nimport { fitImageSize } from '../lib/blob-helpers.js';\nimport { bytesToHumanSize, shortenFileName } from '../lib/strformat.js';\nimport { urlAsAttachment } from '../lib/utils.js';\n\nexport default class ImagePreview extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n width: 0,\n height: 0\n };\n\n this.handleSendImage = this.handleSendImage.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n }\n\n componentDidMount() {\n document.addEventListener('keydown', this.handleKeyDown);\n }\n\n componentWillUnmount() {\n document.removeEventListener('keydown', this.handleKeyDown);\n }\n\n handleKeyDown(e) {\n if (this.props.onSendMessage) {\n return;\n }\n\n e.preventDefault();\n if (e.key === 'Escape') {\n this.props.onClose();\n }\n }\n\n assignWidth(node) {\n if (node && !this.state.width) {\n const bounds = node.getBoundingClientRect();\n this.setState({\n width: bounds.width | 0,\n height: bounds.height | 0\n });\n }\n }\n\n handleSendImage(caption) {\n this.props.onClose();\n this.props.onSendMessage(caption, this.props.content.blob);\n }\n\n render() {\n if (!this.props.content) {\n return null;\n }\n\n const dim = fitImageSize(this.props.content.width, this.props.content.height,\n this.state.width, this.state.height, false);\n const size = dim ? { width: dim.dstWidth + 'px', height: dim.dstHeight + 'px' } :\n ((this.props.content.width > this.props.content.height) ? {width: '100%'} : {height: '100%'});\n size.maxWidth = '100%';\n size.maxHeight = '100%';\n\n // Average font aspect ratio is ~0.5; File name takes 1/3 of the viewport width.\n const maxlength = Math.max(((this.state.width / REM_SIZE / 1.5) | 0) - 2, 12);\n const fname = shortenFileName(this.props.content.filename, maxlength) || '-';\n\n const width = this.props.content.width || '-';\n const height = this.props.content.height || '-';\n\n const download_url = urlAsAttachment(this.props.content.url);\n\n return (\n \n
\n
this.assignWidth(node)}>\n
\n
\n {this.props.onSendMessage ?\n
\n :\n }\n
\n );\n }\n};\n","// A single topic or user.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nexport default class Invitation extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleButtonAction = this.handleButtonAction.bind(this);\n }\n\n handleButtonAction(evt, data) {\n evt.preventDefault();\n this.props.onAction(data);\n }\n\n render() {\n return (\n \n
\n \n
\n
\n { this.handleButtonAction(event, \"accept\"); }}>\n \n \n { this.handleButtonAction(event, \"delete\"); }}>\n \n \n { this.handleButtonAction(event, \"block\"); }}>\n \n \n
\n
\n );\n }\n};\n","/* This is just a static page to display when no conversation is selected. */\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport { APP_NAME } from '../config.js';\n\nexport default class LogoView extends React.PureComponent {\n render() {\n const version = APP_NAME + ' (' + Tinode.getLibrary() + ')';\n return (\n \n
\n
\n \n Tinode Web \n \n
{version}
\n
{this.props.serverVersion} ({this.props.serverAddress})
\n
\n
\n );\n }\n};\n","// Message bubble with non-payload content, such as an indicator of deleted content or a date stamp.\n\nimport React from 'react';\n\nexport default class MetaMessage extends React.PureComponent {\n constructor(props) {\n super(props);\n }\n\n render() {\n let content = null;\n let bubbleClass = 'bubble';\n if (this.props.date) {\n // A date badge.\n content = <>{this.props.date}>\n bubbleClass += ' date';\n }\n\n if (!content) {\n return <>{null}>\n }\n\n return (\n \n \n \n );\n }\n};\n","// Send message form.\nimport React from 'react';\nimport { defineMessages, injectIntl } from 'react-intl';\nimport { Drafty } from 'tinode-sdk';\n\nimport { previewFormatter } from '../lib/formatters.js';\nimport { MIN_SWIPE_DISTANCE } from '../config.js';\n\nconst messages = defineMessages({\n message_not_found: {\n id: 'message_not_found',\n defaultMessage: 'message not found',\n description: 'Pinned message is not found'\n },\n message_deleted: {\n id: 'message_deleted',\n defaultMessage: 'message deleted',\n description: 'Pinned message is deleted'\n }\n});\n\nclass PinnedMessages extends React.PureComponent {\n constructor(props) {\n super(props);\n\n // Starting location of the touch gesture.\n this.touchX = null;\n this.touchY = null;\n\n this.touchSurface = React.createRef();\n\n this.getSelectedIndex = this.getSelectedIndex.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n this.handleSelected = this.handleSelected.bind(this);\n this.handleMoveNext = this.handleMoveNext.bind(this);\n this.handleMovePrev = this.handleMovePrev.bind(this);\n this.handleTouchEventStart = this.handleTouchEventStart.bind(this);\n this.handleTouchEventEnd = this.handleTouchEventEnd.bind(this);\n this.handleTouchCancel = this.handleTouchCancel.bind(this);\n }\n\n componentDidMount() {\n this.touchSurface.current.addEventListener('touchstart', this.handleTouchEventStart, {passive: true});\n this.touchSurface.current.addEventListener('touchend', this.handleTouchEventEnd, {passive: true});\n this.touchSurface.current.addEventListener('touchcancel', this.handleTouchCancel, {passive: true});\n }\n\n componentWillUnmount() {\n this.touchSurface.current.removeEventListener('touchstart', this.handleTouchEventStart);\n this.touchSurface.current.removeEventListener('touchend', this.handleTouchEventEnd);\n this.touchSurface.current.removeEventListener('touchcancel', this.handleTouchCancel);\n }\n getSelectedIndex() {\n const list = (this.props.pins || []);\n return list.length - this.props.selected - 1;\n }\n\n handleCancel(e) {\n e.preventDefault();\n this.props.onCancel(this.props.pins[this.getSelectedIndex()]);\n }\n\n handleSelected(e) {\n e.preventDefault();\n this.props.onSelected(this.props.pins[this.getSelectedIndex()]);\n }\n\n handleMoveNext(e, isTouch) {\n // Don't call preventDefault for touch events.\n isTouch || e.preventDefault();\n e.stopPropagation();\n const idx = Math.max(this.props.selected - 1, 0);\n if (idx != this.props.selected) {\n this.props.setSelected(idx);\n }\n }\n\n handleMovePrev(e, isTouch) {\n // Don't call preventDefault for touch events.\n isTouch || e.preventDefault();\n e.stopPropagation();\n const idx = Math.min(this.props.selected + 1, (this.props.pins || []).length - 1);\n if (idx != this.props.selected) {\n this.props.setSelected(idx);\n }\n }\n\n handleTouchEventStart(e) {\n if (e.touches.length == 1) {\n this.touchX = e.touches[0].clientX;\n this.touchY = e.touches[0].clientY;\n }\n }\n\n handleTouchEventEnd(e) {\n if (this.touchX === null || e.changedTouches.length != 1) {\n this.touchX = null;\n return;\n }\n\n const dX = this.touchX - e.changedTouches[0].clientX;\n const dY = this.touchY - e.changedTouches[0].clientY;\n this.touchX = null;\n\n if (Math.abs(dX) > Math.abs(dY) || Math.abs(dY) < MIN_SWIPE_DISTANCE) {\n // Horizontal swipe or too short vertical swipe.\n return;\n }\n\n if (dY > 0) {\n this.handleMovePrev(e, true);\n } else {\n this.handleMoveNext(e, true);\n }\n }\n\n handleTouchCancel() {\n this.touchX = null;\n }\n\n render() {\n const selected = this.getSelectedIndex();\n let messageShown = (this.props.messages || [])[selected];\n messageShown = messageShown ?\n messageShown._deleted ?\n {this.props.intl.formatMessage(messages.message_deleted)} \n :\n Drafty.format(messageShown.content, previewFormatter, {\n formatMessage: this.props.intl.formatMessage.bind(this.props.intl),\n authorizeURL: this.props.tinode.authorizeURL.bind(this.props.tinode)\n })\n :\n {this.props.intl.formatMessage(messages.message_not_found)} ;\n\n const dots = [];\n this.props.pins.forEach(seq => {\n const cn = dots.length == selected ? 'adot' : 'dot';\n dots.push(
);\n });\n\n return (\n \n {this.props.isAdmin ?\n
:\n
push_pin
\n }\n
{dots}
\n
\n
\n
\n );\n }\n}\n\nexport default injectIntl(PinnedMessages);\n","import React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\nimport SendMessage from './send-message.jsx';\n\nimport { bytesToHumanSize } from '../lib/strformat.js';\n\nconst messages = defineMessages({\n unrecognized_video_format: {\n id: 'unrecognized_video_format',\n defaultMessage: 'Format of this video is not recognized',\n description: 'Error message when uploaded video is invalid',\n }\n});\n\nclass VideoPreview extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.videoRef = React.createRef();\n\n this.handleSendVideo = this.handleSendVideo.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n }\n\n componentDidMount() {\n document.addEventListener('keydown', this.handleKeyDown);\n }\n\n componentWillUnmount() {\n document.removeEventListener('keydown', this.handleKeyDown);\n }\n\n handleKeyDown(e) {\n if (this.props.onSendMessage) {\n return;\n }\n\n e.preventDefault();\n if (e.key === 'Escape') {\n this.props.onClose();\n }\n }\n\n handleSendVideo(caption) {\n this.props.onClose();\n const params = {\n width: this.videoRef.current.videoWidth,\n height: this.videoRef.current.videoHeight,\n duration: (this.videoRef.current.duration * 1000) | 0,\n mime: this.props.content.mime,\n name: this.props.content.filename\n }\n\n if (params.width == 0 || params.height == 0) {\n this.props.onError(this.props.intl.formatMessage(messages.unrecognized_video_format), 'err');\n return;\n }\n\n // Capture screen from a video.\n const canvas = document.createElement('canvas');\n canvas.width = params.width;\n canvas.height = params.height;\n const ctx = canvas.getContext('2d');\n ctx.drawImage(this.videoRef.current, 0, 0, canvas.width, canvas.height);\n ctx.canvas.toBlob(\n preview => this.props.onSendMessage(caption, this.props.content.blob, preview, params),\n 'image/jpeg', 0.75\n );\n }\n\n render() {\n if (!this.props.content) {\n return null;\n }\n\n const width = this.props.content.width || '-';\n const height = this.props.content.height || '-';\n\n const controlist = this.props.onSendMessage ? 'nodownload' : '';\n const autoPlay = !this.props.onSendMessage;\n\n return (\n \n
\n
\n \n
\n {this.props.onSendMessage ?\n
\n :\n }\n
\n );\n }\n};\n\nexport default injectIntl(VideoPreview);\n","// Panel with a chat.\n\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport { Drafty, Tinode } from 'tinode-sdk';\n\nimport CallPanel from '../widgets/call-panel.jsx';\nimport ChatMessage from '../widgets/chat-message.jsx';\nimport ContactBadges from '../widgets/contact-badges.jsx';\nimport DocPreview from '../widgets/doc-preview.jsx';\nimport ErrorPanel from '../widgets/error-panel.jsx';\nimport GroupSubs from '../widgets/group-subs.jsx';\nimport ImagePreview from '../widgets/image-preview.jsx';\nimport Invitation from '../widgets/invitation.jsx';\nimport LetterTile from '../widgets/letter-tile.jsx';\nimport LoadSpinner from '../widgets/load-spinner.jsx';\nimport LogoView from './logo-view.jsx';\nimport MetaMessage from '../widgets/meta-message.jsx';\nimport PinnedMessages from '../widgets/pinned-messages.jsx';\nimport SendMessage from '../widgets/send-message.jsx';\nimport VideoPreview from '../widgets/video-preview.jsx';\n\nimport { DEFAULT_P2P_ACCESS_MODE, EDIT_PREVIEW_LENGTH, IMAGE_PREVIEW_DIM, IMMEDIATE_P2P_SUBSCRIPTION,\n KEYPRESS_DELAY, MESSAGES_PAGE, MAX_EXTERN_ATTACHMENT_SIZE, MAX_IMAGE_DIM, MAX_INBAND_ATTACHMENT_SIZE,\n READ_DELAY, QUOTED_REPLY_LENGTH, VIDEO_PREVIEW_DIM } from '../config.js';\nimport { CALL_STATE_OUTGOING_INITATED, CALL_STATE_IN_PROGRESS } from '../constants.js';\nimport { blobToBase64, fileToBase64, imageScaled, makeImageUrl } from '../lib/blob-helpers.js';\nimport HashNavigation from '../lib/navigation.js';\nimport { bytesToHumanSize, relativeDateFormat, shortDateFormat } from '../lib/strformat.js';\n\n// Run timer with this frequency (ms) for checking notification queue.\nconst NOTIFICATION_EXEC_INTERVAL = 300;\n// Scroll distance before [go to latest message] button is shown.\nconst SHOW_GO_TO_LAST_DIST = 100;\n// Sctoll distance from the top when fetching the page of earlier messages is triggered.\nconst FETCH_PAGE_TRIGGER = 40;\n\nconst messages = defineMessages({\n online_now: {\n id: 'online_now',\n defaultMessage: 'online now',\n description: 'Indicator that the user or topic is currently online',\n },\n last_seen: {\n id: 'last_seen_timestamp',\n defaultMessage: 'Last seen',\n description: 'Label for the timestamp of when the user or topic was last online'\n },\n not_found: {\n id: 'title_not_found',\n defaultMessage: 'Not found',\n description: 'Title shown when topic is not found'\n },\n channel: {\n id: 'channel',\n defaultMessage: 'channel',\n description: 'Subtitle shown for channels in MessagesView instead of last seen'\n },\n file_attachment_too_large: {\n id: 'file_attachment_too_large',\n defaultMessage: 'The file size {size} exceeds the {limit} limit.',\n description: 'Error message when attachment is too large'\n },\n invalid_content: {\n id: 'invalid_content',\n defaultMessage: 'invalid content',\n description: 'Shown when the message is unreadable'\n },\n editing_message: {\n id: 'editing_message',\n defaultMessage: 'Editing',\n description: 'Title over message editing preview'\n },\n drag_file: {\n id: 'drag_file',\n defaultMessage: 'Drag file here',\n description: 'Prompt on the file drag-n-drop overlay banner'\n },\n self_topic_name: {\n id: 'self_topic_name',\n defaultMessage: 'Saved messages',\n description: 'Name of self topic for UI'\n },\n});\n\n// Checks if the access permissions are granted but not yet accepted.\nfunction isUnconfirmed(acs) {\n if (acs) {\n const ex = acs.getExcessive() || '';\n return acs.isJoiner('given') && (ex.includes('R') || ex.includes('W'));\n }\n return false;\n}\n\nfunction isPeerRestricted(acs) {\n if (acs) {\n const ms = acs.getMissing() || '';\n return acs.isJoiner('want') && (ms.includes('R') || ms.includes('W'));\n }\n return false;\n}\n\nfunction shouldPresentCallPanel(callState) {\n // Show call panel if either:\n // - call is outgoing (and the client is waiting for the other side to pick up) or,\n // - call is already in progress.\n return callState == CALL_STATE_OUTGOING_INITATED || callState == CALL_STATE_IN_PROGRESS;\n}\n\nclass MessagesView extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = MessagesView.getDerivedStateFromProps(props, {});\n\n this.componentSetup = this.componentSetup.bind(this);\n this.leave = this.leave.bind(this);\n this.sendMessage = this.sendMessage.bind(this);\n this.retrySend = this.retrySend.bind(this);\n this.sendImageAttachment = this.sendImageAttachment.bind(this);\n this.sendVideoAttachment = this.sendVideoAttachment.bind(this);\n this.sendFileAttachment = this.sendFileAttachment.bind(this);\n this.sendAudioAttachment = this.sendAudioAttachment.bind(this);\n this.sendKeyPress = this.sendKeyPress.bind(this);\n this.subscribe = this.subscribe.bind(this);\n this.handleScrollReference = this.handleScrollReference.bind(this);\n this.mountDnDEvents = this.mountDnDEvents.bind(this);\n this.handleScrollEvent = this.handleScrollEvent.bind(this);\n this.handleDescChange = this.handleDescChange.bind(this);\n this.handleSubsUpdated = this.handleSubsUpdated.bind(this);\n this.handleMessageUpdate = this.handleMessageUpdate.bind(this);\n this.handleAuxUpdate = this.handleAuxUpdate.bind(this);\n this.handleAllMessagesReceived = this.handleAllMessagesReceived.bind(this);\n this.handleInfoReceipt = this.handleInfoReceipt.bind(this);\n this.handleExpandMedia = this.handleExpandMedia.bind(this);\n this.handleClosePreview = this.handleClosePreview.bind(this);\n this.handleFormResponse = this.handleFormResponse.bind(this);\n this.handleContextClick = this.handleContextClick.bind(this);\n this.handleShowMessageContextMenu = this.handleShowMessageContextMenu.bind(this);\n this.handleNewChatAcceptance = this.handleNewChatAcceptance.bind(this);\n this.handleEnablePeer = this.handleEnablePeer.bind(this);\n this.handleAttachFile = this.handleAttachFile.bind(this);\n this.handleAttachImageOrVideo = this.handleAttachImageOrVideo.bind(this);\n this.handleCancelUpload = this.handleCancelUpload.bind(this);\n this.postReadNotification = this.postReadNotification.bind(this);\n this.clearNotificationQueue = this.clearNotificationQueue.bind(this);\n this.goToLatestMessage = this.goToLatestMessage.bind(this);\n this.handleFileDrop = this.handleFileDrop.bind(this);\n\n this.handlePickReply = this.handlePickReply.bind(this);\n this.handleEditMessage = this.handleEditMessage.bind(this);\n this.handleCancelReply = this.handleCancelReply.bind(this);\n this.handleQuoteClick = this.handleQuoteClick.bind(this);\n this.handleUnpinMessage = this.handleUnpinMessage.bind(this);\n this.handleCallHangup = this.handleCallHangup.bind(this);\n\n this.isDragEnabled = this.isDragEnabled.bind(this);\n this.handleDragStart = this.handleDragStart.bind(this);\n this.handleDragIn = this.handleDragIn.bind(this);\n this.handleDragOut = this.handleDragOut.bind(this);\n this.handleDrag = this.handleDrag.bind(this);\n this.handleDrop = this.handleDrop.bind(this);\n\n this.chatMessageRefs = [];\n this.getOrCreateMessageRef = this.getOrCreateMessageRef.bind(this);\n this.getVisibleMessageRange = this.getVisibleMessageRange.bind(this);\n\n // Keeps track of the drag event.\n // Need a counter b/c the browser's 'drag' events may fire multiple times\n // when the user takes the mouse pointer over the container:\n // for the component itself and for all nested/child elements.\n this.dragCounter = 0;\n this.dndRef = null;\n\n this.readNotificationQueue = [];\n this.readNotificationTimer = null;\n\n this.keyPressTimer = null;\n }\n\n getOrCreateMessageRef(seqId) {\n if (this.chatMessageRefs[seqId]) {\n return this.chatMessageRefs[seqId];\n }\n const ref = React.createRef();\n this.chatMessageRefs[seqId] = ref;\n return ref;\n }\n\n getVisibleMessageRange(holderRect) {\n let min = Number.MAX_SAFE_INTEGER, max = -1;\n let visibilityStatus = false;\n this.chatMessageRefs.every((ref, seq) => {\n if (ref.current) {\n const { top, bottom, height } = ref.current.getBoundingClientRect();\n const visible = top <= holderRect.top ? holderRect.top - top <= height : bottom - holderRect.bottom <= height;\n if (visible) {\n visibilityStatus = true;\n min = Math.min(min, seq);\n max = Math.max(max, seq);\n } else if (visibilityStatus) {\n // The remaining elements are no longer visible, no need to iterate them.\n return false;\n }\n }\n return true;\n });\n\n return max >= min ? {min: min, max: max} : {min: 0, max: 0};\n }\n\n componentDidMount() {\n if (this.messagesScroller) {\n this.messagesScroller.addEventListener('scroll', this.handleScrollEvent);\n }\n\n // Drag and drop events\n this.mountDnDEvents(this.dndRef);\n\n this.componentSetup({}, {});\n }\n\n componentWillUnmount() {\n if (this.messagesScroller) {\n this.messagesScroller.removeEventListener('scroll', this.handleScrollEvent);\n }\n\n // Flush all notifications.\n this.clearNotificationQueue();\n\n // Drag and drop events\n if (this.dndRef) {\n this.dndRef.removeEventListener('dragstart', this.handleDragStart);\n this.dndRef.removeEventListener('dragenter', this.handleDragIn);\n this.dndRef.removeEventListener('dragleave', this.handleDragOut);\n this.dndRef.removeEventListener('dragover', this.handleDrag);\n this.dndRef.removeEventListener('drop', this.handleDrop);\n }\n }\n\n componentDidUpdate(prevProps, prevState) {\n // Scroll last message into view on component update e.g. on message received\n // or vertical shrinking.\n if (this.messagesScroller &&\n (prevState.topic != this.state.topic || prevState.maxSeqId != this.state.maxSeqId ||\n prevState.minSeqId != this.state.minSeqId)) {\n // New message.\n if (this.state.scrollPosition < SHOW_GO_TO_LAST_DIST) {\n this.messagesScroller.scrollTop = this.messagesScroller.scrollHeight -\n this.state.scrollPosition - this.messagesScroller.offsetHeight;\n }\n }\n\n if (!this.props.applicationVisible) {\n // If application is not visible, flush all unsent 'read' notifications.\n this.clearNotificationQueue();\n } else {\n // Otherwise assume there are unread messages.\n this.postReadNotification(0);\n }\n\n this.componentSetup(prevProps, prevState);\n }\n\n componentSetup(prevProps, prevState) {\n const topic = this.props.tinode ? this.props.tinode.getTopic(this.state.topic) : undefined;\n if (this.state.topic != prevState.topic) {\n if (prevState.topic && !Tinode.isNewGroupTopicName(prevState.topic)) {\n this.leave(prevState.topic);\n if (prevState.rtcPanel) {\n this.handleCallHangup(prevState.topic, prevProps.callSeq);\n }\n }\n\n if (topic) {\n topic.onData = this.handleMessageUpdate;\n topic.onAllMessagesReceived = this.handleAllMessagesReceived;\n topic.onInfo = this.handleInfoReceipt;\n topic.onMetaDesc = this.handleDescChange;\n topic.onSubsUpdated = this.handleSubsUpdated;\n topic.onPres = this.handleSubsUpdated;\n topic.onAuxUpdated = this.handleAuxUpdate;\n }\n }\n\n if (topic) {\n if ((this.state.topic != prevState.topic) || (this.props.myUserId && !prevProps.myUserId)) {\n // Don't immediately subscribe to a new p2p topic, wait for the first message.\n const newTopic = (this.props.newTopicParams && this.props.newTopicParams._topicName == this.props.topic);\n if (topic.isP2PType() && newTopic && !IMMEDIATE_P2P_SUBSCRIPTION) {\n topic.getMeta(topic.startMetaQuery().withDesc().build());\n } else if (this.props.myUserId) {\n this.subscribe(topic);\n }\n } else if (topic.isSubscribed() && this.state.isReader && !prevState.isReader) {\n // If reader status has changed and data became available.\n topic.getMeta(topic.startMetaQuery().withLaterData().build());\n }\n }\n }\n\n static getDerivedStateFromProps(nextProps, prevState) {\n let nextState = {};\n if (!nextProps.topic) {\n // Default state: no topic.\n nextState = {\n minSeqId: -1,\n maxSeqId: -1,\n latestClearId: -1,\n onlineSubs: [],\n topic: null,\n title: '',\n avatar: null,\n isVerified: false,\n isStaff: false,\n isDangerous: false,\n deleted: false,\n docPreview: null,\n imagePreview: null,\n imagePostview: null,\n videoPreview: null,\n videoPostview: null,\n rtcPanel: null,\n typingIndicator: false,\n scrollPosition: 0,\n fetchingMessages: false,\n peerMessagingDisabled: false,\n channel: false,\n reply: null,\n contentToEdit: null,\n showGoToLastButton: false,\n dragging: false,\n pins: [],\n pinsLoaded: false,\n selectedPin: 0,\n subsVersion: 0\n };\n } else if (nextProps.topic != prevState.topic) {\n const topic = nextProps.tinode.getTopic(nextProps.topic);\n\n nextState = {\n topic: nextProps.topic,\n deleted: topic._deleted,\n docPreview: null,\n imagePreview: null,\n imagePostview: null,\n videoPreview: null,\n videoPostview: null,\n rtcPanel: null,\n typingIndicator: false,\n scrollPosition: 0,\n fetchingMessages: false,\n showGoToLastButton: false,\n contentToEdit: null,\n dragging: false,\n selectedPin: 0\n };\n\n if (nextProps.forwardMessage) {\n // We are forwarding a message. Show preview.\n nextState.reply = {\n content: nextProps.forwardMessage.preview,\n seq: null\n };\n } else {\n nextState.reply = null;\n }\n\n if (topic) {\n // Topic exists.\n const subs = [];\n\n if (nextProps.connected) {\n topic.subscribers((sub) => {\n if (sub.online && sub.user != nextProps.myUserId) {\n subs.push(sub);\n }\n });\n }\n\n Object.assign(nextState, {\n onlineSubs: subs\n });\n\n if (topic.isSelfType()) {\n Object.assign(nextState, {\n title: nextProps.intl.formatMessage(messages.self_topic_name),\n avatar: true\n });\n } else if (topic.public) {\n Object.assign(nextState, {\n title: topic.public.fn,\n avatar: makeImageUrl(topic.public.photo)\n });\n } else {\n Object.assign(nextState, {\n title: '',\n avatar: null\n });\n }\n\n const peer = topic.p2pPeerDesc();\n if (peer) {\n Object.assign(nextState, {\n peerMessagingDisabled: isPeerRestricted(peer.acs)\n });\n } else if (prevState.peerMessagingDisabled) {\n Object.assign(nextState, {\n peerMessagingDisabled: false\n });\n }\n Object.assign(nextState, {\n minSeqId: topic.minMsgSeq(),\n maxSeqId: topic.maxMsgSeq(),\n latestClearId: topic.maxClearId(),\n channel: topic.isChannelType(),\n pins: (topic.aux('pins') || []).slice(),\n pinsLoaded: false\n });\n\n if (nextProps.callTopic == topic.name && shouldPresentCallPanel(nextProps.callState)) {\n nextState.rtcPanel = nextProps.callTopic;\n }\n } else {\n // Invalid topic.\n Object.assign(nextState, {\n minSeqId: -1,\n maxSeqId: -1,\n latestClearId: -1,\n onlineSubs: [],\n title: '',\n avatar: null,\n peerMessagingDisabled: false,\n channel: false,\n pins: [],\n pinsLoaded: false\n });\n }\n } else {\n // We are still in same topic. Show the call panel if necessary.\n if (nextProps.callTopic == prevState.topic && !prevState.rtcPanel &&\n shouldPresentCallPanel(nextProps.callState)) {\n nextState.rtcPanel = nextProps.callTopic;\n }\n }\n\n if (nextProps.acs) {\n if (nextProps.acs.isWriter() != prevState.isWriter) {\n nextState.isWriter = !prevState.isWriter;\n }\n if (nextProps.acs.isReader() != prevState.isReader) {\n nextState.isReader = !prevState.isReader;\n }\n if (nextProps.acs.isAdmin() != prevState.isAdmin) {\n nextState.isAdmin = !prevState.isAdmin;\n }\n if (!nextProps.acs.isReader('given') != prevState.readingBlocked) {\n nextState.readingBlocked = !prevState.readingBlocked;\n }\n if (nextProps.acs.isSharer() != prevState.isSharer) {\n nextState.isSharer = !prevState.isSharer;\n }\n } else {\n if (prevState.isWriter) {\n nextState.isWriter = false;\n }\n if (prevState.isReader) {\n nextState.isReader = false;\n }\n if (prevState.isAdmin) {\n nextState.isAdmin = false;\n }\n if (!prevState.readingBlocked) {\n prevState.readingBlocked = true;\n }\n if (prevState.isSharer) {\n nextState.isSharer = false;\n }\n }\n\n if (isUnconfirmed(nextProps.acs) == !prevState.unconformed) {\n nextState.unconfirmed = !prevState.unconformed;\n }\n\n // Clear subscribers online when there is no connection.\n if (!nextProps.connected && prevState.onlineSubs && prevState.onlineSubs.length > 0) {\n nextState.onlineSubs = [];\n }\n\n return nextState;\n }\n\n subscribe(topic) {\n if (topic.isSubscribed() || !this.props.ready) {\n return;\n }\n\n // Is this a new topic?\n const newTopic = (this.props.newTopicParams && this.props.newTopicParams._topicName == this.props.topic);\n // Don't request the tags. They are useless unless the user\n // is the owner and is editing the topic.\n let getQuery = topic.startMetaQuery().withLaterDesc().withLaterSub().withAux();\n if (this.state.isReader || newTopic) {\n // Reading is either permitted or we don't know because it's a new topic. Ask for messages.\n getQuery = getQuery.withLaterData(MESSAGES_PAGE);\n if (this.state.isReader) {\n getQuery = getQuery.withLaterDel();\n }\n // And show \"loading\" spinner.\n this.setState({ fetchingMessages: true });\n }\n\n const setQuery = newTopic ? this.props.newTopicParams : undefined;\n topic.subscribe(getQuery.build(), setQuery)\n .then(ctrl => {\n if (ctrl.code == 303) {\n // Redirect to another topic requested.\n HashNavigation.navigateTo(HashNavigation.setUrlTopic('', ctrl.params.topic));\n return;\n }\n if (this.state.topic != ctrl.topic) {\n this.setState({topic: ctrl.topic});\n }\n if (this.state.deleted) {\n this.setState({deleted: false});\n }\n this.props.onNewTopicCreated(this.props.topic, ctrl.topic);\n // If there are unsent messages (except hard-failed and video call messages),\n // try sending them now. Hard-failed and unsent video call messages will be dropped.\n let discard = [];\n topic.queuedMessages(pub => {\n if (pub._sending) {\n return;\n }\n if (pub._fatal || (pub.head && pub.head.webrtc)) {\n // Filter out unsent failed & video call messages.\n discard.push(pub.seq);\n return;\n }\n if (topic.isSubscribed()) {\n this.retrySend(pub);\n }\n });\n if (discard.length > 0) {\n topic.delMessagesList(discard, true);\n }\n })\n .catch(err => {\n console.error(\"Failed subscription to\", this.state.topic, err);\n this.props.onError(err.message, 'err');\n const blankState = MessagesView.getDerivedStateFromProps({}, {});\n blankState.title = this.props.intl.formatMessage(messages.not_found);\n this.setState(blankState);\n });\n }\n\n leave(oldTopicName) {\n if (!oldTopicName || !this.props.tinode.isTopicCached(oldTopicName)) {\n return;\n }\n\n const oldTopic = this.props.tinode.getTopic(oldTopicName);\n if (oldTopic && oldTopic.isSubscribed()) {\n oldTopic.leave(false)\n .catch(_ => { /* do nothing here */ })\n .finally(_ => {\n // We don't care if the request succeeded or failed.\n // The topic is dead regardless.\n this.setState({fetchingMessages: false});\n oldTopic.onData = undefined;\n oldTopic.onAllMessagesReceived = undefined;\n oldTopic.onInfo = undefined;\n oldTopic.onMetaDesc = undefined;\n oldTopic.onSubsUpdated = undefined;\n oldTopic.onPres = undefined;\n oldTopic.onAuxUpdated = undefined;\n });\n }\n }\n\n // Don't use React.createRef as the ref.current is not available in componentDidMount in this component.\n handleScrollReference(node) {\n if (node) {\n node.addEventListener('scroll', this.handleScrollEvent);\n this.messagesScroller = node;\n this.messagesScroller.scrollTop = this.messagesScroller.scrollHeight -\n this.state.scrollPosition - this.messagesScroller.offsetHeight;\n }\n }\n\n // Get older messages and show/hide [go to latest message] button.\n handleScrollEvent(event) {\n const pos = event.target.scrollHeight - event.target.scrollTop - event.target.offsetHeight;\n this.setState({\n scrollPosition: pos,\n // Show [go to latest message] if far enough from bottom and scrolling down.\n showGoToLastButton: (pos > SHOW_GO_TO_LAST_DIST) && (pos < this.state.scrollPosition),\n });\n\n if (this.state.fetchingMessages || this.processingScrollEvent) {\n return;\n }\n\n if (event.target.scrollTop <= FETCH_PAGE_TRIGGER) {\n const topic = this.props.tinode.getTopic(this.state.topic);\n if (topic && topic.isSubscribed()) {\n this.processingScrollEvent = true;\n const {min, max} = this.getVisibleMessageRange(event.target.getBoundingClientRect());\n const gaps = topic.msgHasMoreMessages(min, max, false);\n if (gaps.length > 0) {\n this.setState({fetchingMessages: true}, _ => {\n topic.getMessagesPage(MESSAGES_PAGE, gaps, min, max)\n .catch(err => this.props.onError(err.message, 'err'))\n .finally(_ => this.setState({fetchingMessages: false}));\n });\n }\n }\n }\n this.processingScrollEvent = false;\n }\n\n /* Mount drag and drop events */\n mountDnDEvents(dnd) {\n if (dnd) {\n dnd.addEventListener('dragstart', this.handleDragStart);\n dnd.addEventListener('dragenter', this.handleDragIn);\n dnd.addEventListener('dragleave', this.handleDragOut);\n dnd.addEventListener('dragover', this.handleDrag);\n dnd.addEventListener('drop', this.handleDrop);\n this.dndRef = dnd;\n }\n }\n\n goToLatestMessage() {\n this.setState({scrollPosition: 0});\n if (this.messagesScroller) {\n this.messagesScroller.scrollTop = this.messagesScroller.scrollHeight - this.messagesScroller.offsetHeight;\n }\n }\n\n handleDescChange(desc) {\n if (Tinode.isSelfTopicName(this.props.topic)) {\n this.setState({\n title: this.props.intl.formatMessage(messages.self_topic_name),\n avatar: true\n });\n } else if (desc.public) {\n this.setState({\n title: desc.public.fn,\n avatar: makeImageUrl(desc.public.photo)\n });\n } else {\n this.setState({\n title: '',\n avatar: null\n });\n }\n\n if (desc.acs) {\n this.setState({\n isWriter: desc.acs.isWriter(),\n isReader: desc.acs.isReader(),\n isAdmin: desc.acs.isAdmin(),\n readingBlocked: !desc.acs.isReader('given'),\n unconfirmed: isUnconfirmed(desc.acs),\n });\n }\n }\n\n postReadNotification(seq) {\n // Ignore notifications if the app is invisible or topic is not yet available.\n if (!this.props.applicationVisible || !this.state.topic) {\n return;\n }\n\n // Set up the timer if it's not running already.\n if (!this.readNotificationTimer) {\n this.readNotificationTimer = setInterval(_ => {\n if (this.readNotificationQueue.length == 0) {\n // Shut down the timer if the queue is empty.\n clearInterval(this.readNotificationTimer);\n this.readNotificationTimer = null;\n return;\n }\n\n let seq = -1;\n while (this.readNotificationQueue.length > 0) {\n const n = this.readNotificationQueue[0];\n if (n.topicName != this.state.topic) {\n // Topic has changed. Drop the notification.\n this.readNotificationQueue.shift();\n continue;\n }\n\n const now = new Date();\n if (n.sendAt <= now) {\n // Remove expired notification from queue.\n this.readNotificationQueue.shift();\n if (n.seq == 0 || Tinode.isServerAssignedSeq(n.seq)) {\n seq = Math.max(seq, n.seq);\n }\n } else {\n break;\n }\n }\n\n // Send only one notification for the whole batch of messages.\n if (seq >= 0) {\n const topic = this.props.tinode.getTopic(this.state.topic);\n if (topic) {\n try {\n topic.noteRead(seq);\n } catch (err) {\n console.error(\"Failed to send read notification\", err);\n }\n }\n }\n }, NOTIFICATION_EXEC_INTERVAL);\n }\n\n const now = new Date();\n this.readNotificationQueue.push({\n topicName: this.state.topic,\n seq: seq,\n sendAt: now.setMilliseconds(now.getMilliseconds() + READ_DELAY)\n });\n }\n\n // Clear notification queue and timer.\n clearNotificationQueue() {\n this.readNotificationQueue = [];\n if (this.readNotificationTimer) {\n clearInterval(this.readNotificationTimer);\n this.readNotificationTimer = null;\n }\n }\n\n handleSubsUpdated() {\n if (this.state.topic) {\n const subs = [];\n const topic = this.props.tinode.getTopic(this.state.topic);\n topic.subscribers(sub => {\n if (sub.online && sub.user != this.props.myUserId) {\n subs.push(sub);\n }\n });\n const newState = {onlineSubs: subs, subsVersion: this.state.subsVersion + 1};\n const peer = topic.p2pPeerDesc();\n if (peer) {\n Object.assign(newState, {\n peerMessagingDisabled: isPeerRestricted(peer.acs)\n });\n } else if (this.state.peerMessagingDisabled) {\n Object.assign(newState, {\n peerMessagingDisabled: false\n });\n }\n this.setState(newState);\n }\n }\n\n // The 'msg' could be false-ish if some message ranges were deleted.\n handleMessageUpdate(msg) {\n if (!this.state.topic) {\n return;\n }\n const topic = this.props.tinode.getTopic(this.state.topic);\n if (!msg) {\n // msg could be null if one or more messages were deleted.\n // Updating state to force redraw.\n this.setState({latestClearId: topic.maxClearId()});\n return;\n }\n\n clearTimeout(this.keyPressTimer)\n this.setState({maxSeqId: topic.maxMsgSeq(), minSeqId: topic.minMsgSeq(), typingIndicator: false}, _ => {\n // Scroll to the bottom if the message is added to the end of the message\n // list if already at the bottom, otherwise show [go to latest] button.\n // Implemented as a callback to be sure the scroll height has been updated.\n if (topic.isNewMessage(msg.seq)) {\n if (this.state.scrollPosition > SHOW_GO_TO_LAST_DIST) {\n this.setState({showGoToLastButton: true});\n } else {\n this.goToLatestMessage();\n }\n } else {\n if (this.messagesScroller) {\n this.messagesScroller.scrollTop = this.messagesScroller.scrollHeight - this.state.scrollPosition -\n this.messagesScroller.offsetHeight;\n }\n }\n });\n\n // Aknowledge messages except own messages. They are\n // automatically assumed to be read and recived.\n const status = topic.msgStatus(msg, true);\n if (status >= Tinode.MESSAGE_STATUS_SENT && msg.from != this.props.myUserId) {\n this.postReadNotification(msg.seq);\n }\n }\n\n handleAllMessagesReceived(count) {\n this.setState({fetchingMessages: false});\n if (!count) {\n // All messages received. Nothing left to receive.\n const topic = this.props.tinode.getTopic(this.state.topic);\n if (topic) {\n // Send read notification for the absolute last message.\n this.postReadNotification(topic.seq);\n }\n return;\n }\n\n // Load pinned message too (if any);\n if (!this.state.pinsLoaded) {\n // This needs to be guarded to avoid an infinite loop.\n // The loop may happen if some pinned messages are deleted.\n const topic = this.props.tinode.getTopic(this.state.topic);\n this.setState({pinsLoaded: true}, _ => {\n topic.getPinnedMessages();\n });\n } else {\n this.setState({pinsLoaded: false});\n }\n }\n\n handleAuxUpdate(aux) {\n const pins = (aux['pins'] || []).slice();\n let selectedPin = this.state.selectedPin;\n if (pins.length > this.state.pins.length) {\n // New pins added, show the latest.\n selectedPin = 0;\n } else if (selectedPin >= pins.length) {\n selectedPin = Math.max(0, pins.length - 1);\n }\n this.setState({pins: pins, selectedPin: selectedPin});\n }\n\n handleInfoReceipt(info) {\n switch (info.what) {\n case 'kp': {\n clearTimeout(this.keyPressTimer);\n this.keyPressTimer = setTimeout(_ => this.setState({typingIndicator: false}), KEYPRESS_DELAY + 1000);\n if (!this.state.typingIndicator) {\n this.setState({typingIndicator: true});\n }\n break;\n }\n case 'read':\n case 'recv':\n // Redraw due to changed recv/read status.\n this.forceUpdate();\n break;\n default:\n console.info(\"Other change in topic: \", info.what);\n }\n }\n\n handleExpandMedia(content) {\n if (!content) {\n return;\n }\n\n if (content.video) {\n this.setState({videoPostview: content});\n } else {\n this.setState({imagePostview: content});\n }\n }\n\n handleClosePreview() {\n if (this.state.imagePreview && this.state.imagePreview.url) {\n URL.revokeObjectURL(this.state.imagePreview.url);\n }\n if (this.state.videoPreview && this.state.videoPreview.url) {\n URL.revokeObjectURL(this.state.videoPreview.url);\n }\n this.setState({ imagePostview: null, imagePreview: null, docPreview: null, videoPreview: null, videoPostview: null});\n }\n\n handleFormResponse(action, text, data) {\n if (action == 'pub') {\n this.sendMessage(Drafty.attachJSON(Drafty.parse(text), data));\n } else if (action == 'url') {\n const url = new URL(data.ref);\n const params = url.searchParams;\n for (let key in data.resp) {\n if (data.resp.hasOwnProperty(key)) {\n params.set(key, data.resp[key]);\n }\n }\n ['name', 'seq'].forEach(key => {\n if (data[key]) {\n params.set(key, data[key]);\n }\n });\n params.set('uid', this.props.myUserId);\n params.set('topic', this.state.topic);\n url.search = params;\n window.open(url, '_blank');\n } else {\n console.info(\"Unknown action in form\", action);\n }\n }\n\n handleContextClick(e) {\n e.preventDefault();\n e.stopPropagation();\n this.props.showContextMenu({ topicName: this.state.topic, y: e.pageY, x: e.pageX });\n }\n\n handleShowMessageContextMenu(params, messageSpecificMenuItems) {\n if (params.userFrom == 'chan') {\n params.userFrom = this.state.topic;\n params.userName = this.state.title;\n }\n params.topicName = this.state.topic;\n const menuItems = messageSpecificMenuItems || [];\n const topic = this.props.tinode.getTopic(params.topicName);\n if (topic) {\n // Self -> (1) always hard-delete with [Delete] title.\n // P2P -> (1) hard-delete if allowed and not too old, (2) always soft-delete.\n // Group -> (1) hard-delete if allowed and not too old or owner, (2) always soft-delete.\n if (topic.isSelfType()) {\n // Hard-delete with plain [Delete] title.\n menuItems.push('message_delete_generic');\n } else {\n if (!topic.isChannelType()) {\n // P2P or normal group: always allow to soft-delete.\n menuItems.push('message_delete');\n }\n\n const acs = topic.getAccessMode();\n if (acs && acs.isDeleter()) {\n // Owner can always hard-delete regardless of age.\n let canDelete = acs.isOwner();\n if (!canDelete) {\n // Not owner: check message age if configured on the server.\n const maxDelAge = this.props.tinode.getServerParam(Tinode.MSG_DELETE_AGE, 0) | 0;\n // Make sure the message is not too old. This check is here just to make the UI\n // more user-friendly. The server will enforce the limit regardless of this.\n canDelete = maxDelAge == 0 || (maxDelAge > 0 && params.timestamp ?\n params.timestamp.getTime() > (new Date().getTime() - maxDelAge * 1000) : false);\n }\n if (canDelete) {\n // [Delete for All] title.\n menuItems.push('message_delete_hard');\n }\n }\n }\n }\n this.props.showContextMenu(params, menuItems);\n }\n\n handleNewChatAcceptance(action) {\n this.props.onNewChat(this.state.topic, action);\n }\n\n handleEnablePeer(e) {\n e.preventDefault();\n this.props.onChangePermissions(this.state.topic, DEFAULT_P2P_ACCESS_MODE, this.state.topic);\n }\n\n sendKeyPress(audio) {\n const topic = this.props.tinode.getTopic(this.state.topic);\n if (topic.isSubscribed()) {\n if (audio) {\n topic.noteRecording(true);\n } else {\n topic.noteKeyPress();\n }\n }\n }\n\n // sendMessage sends the message with an optional subscription to topic first.\n sendMessage(msg, uploadCompletionPromise, uploader) {\n let head;\n if (this.props.forwardMessage) {\n // We are forwarding a message.\n msg = this.props.forwardMessage.msg;\n head = this.props.forwardMessage.head;\n this.handleCancelReply();\n } else if (this.state.reply) {\n if (this.state.reply.editing) {\n if (msg == this.state.contentToEdit) {\n // Message unchanged.\n this.handleCancelReply();\n return;\n }\n // Editing an existing message.\n head = {replace: ':' + this.state.reply.seq};\n } else if (this.state.reply.content) {\n // Replying to a message in this topic.\n // Turn it into Drafty so we can make a quoted Drafty object later.\n head = {reply: '' + this.state.reply.seq};\n if (typeof msg == 'string') {\n msg = Drafty.parse(msg);\n }\n msg = Drafty.append(Drafty.sanitizeEntities(this.state.reply.content), msg);\n }\n this.handleCancelReply();\n }\n this.props.sendMessage(msg, uploadCompletionPromise, uploader, head);\n }\n\n // Retry sending a message.\n retrySend(pub) {\n this.props.sendMessage(pub.content, undefined, undefined, pub.head)\n .then(_ => {\n // All good. Remove the original message draft from the cache.\n const topic = this.props.tinode.getTopic(this.state.topic);\n topic.delMessagesList([pub.seq], true);\n });\n }\n\n // Send attachment as Drafty message:\n // - if file is too large, upload it and send a s link.\n // - if file is small enough, just send it in-band.\n sendFileAttachment(file) {\n // Server-provided limit reduced for base64 encoding and overhead.\n const maxInbandAttachmentSize = (this.props.tinode.getServerParam('maxMessageSize',\n MAX_INBAND_ATTACHMENT_SIZE) * 0.75 - 1024) | 0;\n\n if (file.size > maxInbandAttachmentSize) {\n // Too large to send inband - uploading out of band and sending as a link.\n const uploader = this.props.tinode.getLargeFileHelper();\n if (!uploader) {\n this.props.onError(this.props.intl.formatMessage(messages.cannot_initiate_upload));\n return;\n }\n const uploadCompletionPromise = uploader.upload(file);\n const msg = Drafty.attachFile(null, {\n mime: file.type,\n filename: file.name,\n size: file.size,\n urlPromise: uploadCompletionPromise\n });\n // Pass data and the uploader to the TinodeWeb.\n this.sendMessage(msg, uploadCompletionPromise, uploader);\n } else {\n // Small enough to send inband.\n fileToBase64(file)\n .then(b64 => this.sendMessage(Drafty.attachFile(null, {\n mime: b64.mime,\n data: b64.bits,\n filename: b64.name,\n size: file.size\n })))\n .catch(err => this.props.onError(err.message, 'err'));\n }\n }\n\n // handleAttachFile method is called when [Attach file] button is clicked: launch attachment preview.\n handleAttachFile(file) {\n const maxExternAttachmentSize = this.props.tinode.getServerParam('maxFileUploadSize', MAX_EXTERN_ATTACHMENT_SIZE);\n\n if (file.size > maxExternAttachmentSize) {\n // Too large.\n this.props.onError(this.props.intl.formatMessage(messages.file_attachment_too_large,\n {size: bytesToHumanSize(file.size), limit: bytesToHumanSize(maxExternAttachmentSize)}), 'err');\n } else {\n this.setState({\n docPreview: {\n file: file,\n name: file.name,\n size: file.size,\n type: file.type\n }\n });\n }\n }\n\n handleCallHangup(topic, seq) {\n this.props.onVideoCallClosed();\n this.setState({\n rtcPanel: null\n });\n this.props.onCallHangup(topic, seq);\n }\n\n // sendImageAttachment sends the image bits as Drafty message.\n sendImageAttachment(caption, blob) {\n const mime = this.state.imagePreview.mime;\n const width = this.state.imagePreview.width;\n const height = this.state.imagePreview.height;\n const fname = this.state.imagePreview.filename;\n\n // Server-provided limit reduced for base64 encoding and overhead.\n const maxInbandAttachmentSize = (this.props.tinode.getServerParam('maxMessageSize',\n MAX_INBAND_ATTACHMENT_SIZE) * 0.75 - 1024) | 0;\n\n if (blob.size > maxInbandAttachmentSize) {\n // Too large to send inband - uploading out of band and sending as a link.\n const uploader = this.props.tinode.getLargeFileHelper();\n if (!uploader) {\n this.props.onError(this.props.intl.formatMessage(messages.cannot_initiate_upload));\n return;\n }\n const uploadCompletionPromise = uploader.upload(blob);\n\n // Make small preview to show while uploading.\n imageScaled(blob, IMAGE_PREVIEW_DIM, IMAGE_PREVIEW_DIM, -1, false)\n // Convert tiny image into base64 for serialization and previewing.\n .then(scaled => blobToBase64(scaled.blob))\n .then(b64 => {\n let msg = Drafty.insertImage(null, 0, {\n mime: mime,\n _tempPreview: b64.bits, // This preview will not be serialized.\n bits: b64.bits, // Image thumbnail.\n width: width,\n height: height,\n filename: fname,\n size: blob.size,\n urlPromise: uploadCompletionPromise\n });\n if (caption) {\n msg = Drafty.appendLineBreak(msg);\n msg = Drafty.append(msg, Drafty.parse(caption));\n }\n // Pass data and the uploader to the TinodeWeb.\n this.sendMessage(msg, uploadCompletionPromise, uploader);\n })\n .catch(err => this.props.onError(err, 'err'));\n return;\n }\n\n // Send the image inband if it's not too big. The image has been scaled already\n // in image preview.\n blobToBase64(blob)\n .then(b64 => {\n let msg = Drafty.insertImage(null, 0, {\n mime: b64.mime,\n bits: b64.bits,\n width: width,\n height: height,\n filename: fname,\n size: blob.size\n });\n if (caption) {\n msg = Drafty.appendLineBreak(msg);\n msg = Drafty.append(msg, Drafty.parse(caption));\n }\n this.sendMessage(msg);\n });\n }\n\n // sendVideoAttachment sends the video bits as Drafty message.\n sendVideoAttachment(caption, videoBlob, previewBlob, params) {\n const width = params.width;\n const height = params.height;\n\n // Server-provided limit reduced for base64 encoding and overhead.\n const maxInbandAttachmentSize = (this.props.tinode.getServerParam('maxMessageSize',\n MAX_INBAND_ATTACHMENT_SIZE) * 0.75 - 1024) | 0;\n\n const uploads = [];\n let uploader;\n if ((videoBlob.size + previewBlob.size) > maxInbandAttachmentSize) {\n // One or both are too large to send inband. Uploading out of band and sending as a link.\n uploader = this.props.tinode.getLargeFileHelper();\n if (!uploader) {\n this.props.onError(this.props.intl.formatMessage(messages.cannot_initiate_upload));\n return;\n }\n\n uploads[0] = videoBlob.size > maxInbandAttachmentSize * 0.675 ? uploader.upload(videoBlob) : null;\n uploads[1] = previewBlob.size > maxInbandAttachmentSize * 0.275 ? uploader.upload(previewBlob) : null;\n }\n\n if (uploads.length == 0) {\n // Both video and preview are small enough to send inband.\n Promise.all([blobToBase64(videoBlob), blobToBase64(previewBlob)])\n .then(b64s => {\n const [v64, i64] = b64s;\n let msg = Drafty.insertVideo(null, 0, {\n mime: v64.mime,\n bits: v64.bits,\n preview: i64.bits,\n premime: i64.mime,\n width: width,\n height: height,\n duration: params.duration,\n filename: params.name,\n size: videoBlob.size\n });\n if (caption) {\n msg = Drafty.appendLineBreak(msg);\n msg = Drafty.append(msg, Drafty.parse(caption));\n }\n this.sendMessage(msg);\n });\n return;\n }\n\n const uploadCompletionPromise = Promise.all(uploads);\n\n const b64conv = [];\n // Small video converted to base64.\n b64conv[0] = uploads[0] ? null : blobToBase64(videoBlob);\n // Full-size preview fits inline.\n b64conv[1] = uploads[1] ? null : imageScaled(previewBlob, MAX_IMAGE_DIM, MAX_IMAGE_DIM, -1, false)\n .then(scaled => blobToBase64(scaled.blob));\n // Small preview to show while uploading.\n b64conv[2] = imageScaled(previewBlob, VIDEO_PREVIEW_DIM, VIDEO_PREVIEW_DIM, -1, false)\n .then(scaled => blobToBase64(scaled.blob));\n // Convert tiny image into base64 for serialization and previewing.\n Promise.all(b64conv)\n .then(b64s => {\n const [video, img, preview] = b64s;\n let msg = Drafty.insertVideo(null, 0, {\n mime: params.mime,\n bits: video ? video.bits : null,\n _tempPreview: preview.bits,\n preview: img ? img.bits : preview.bits,\n premime: img ? img.mime : preview.mime,\n width: width,\n height: height,\n duration: params.duration,\n filename: params.name,\n size: videoBlob.size,\n urlPromise: uploadCompletionPromise\n });\n\n if (caption) {\n msg = Drafty.appendLineBreak(msg);\n msg = Drafty.append(msg, Drafty.parse(caption));\n }\n // Pass data and the uploader to the TinodeWeb.\n this.sendMessage(msg, uploadCompletionPromise, uploader);\n })\n .catch(err => this.props.onError(err.message, 'err'));\n }\n\n // handleAttachImageOrVideo method is called when [Attach image or video] button is clicked: launch image or video preview.\n handleAttachImageOrVideo(file) {\n const maxExternAttachmentSize = this.props.tinode.getServerParam('maxFileUploadSize', MAX_EXTERN_ATTACHMENT_SIZE);\n\n if (file.type.startsWith('video/')) {\n this.setState({videoPreview: {\n url: URL.createObjectURL(file),\n blob: file,\n filename: file.name,\n size: file.size,\n mime: file.type\n }});\n return;\n }\n\n // Get image dimensions and size, optionally scale it down.\n imageScaled(file, MAX_IMAGE_DIM, MAX_IMAGE_DIM, maxExternAttachmentSize, false)\n .then(scaled => {\n this.setState({imagePreview: {\n url: URL.createObjectURL(scaled.blob),\n blob: scaled.blob,\n filename: scaled.name,\n width: scaled.width,\n height: scaled.height,\n size: scaled.blob.size,\n mime: scaled.mime\n }});\n }).catch(err => {\n this.props.onError(err.message, 'err');\n });\n }\n\n // handleFileDrop is called when the user drags & drops a file upon the message view.\n handleFileDrop(files) {\n if (!files || files.length == 0) {\n return;\n }\n const file = files[0];\n if (file.type && file.type.startsWith('image/')) {\n this.handleAttachImageOrVideo(file);\n } else {\n this.handleAttachFile(file);\n }\n }\n\n // sendAudioAttachment sends audio bits inband as Drafty message (no preview).\n sendAudioAttachment(url, preview, duration) {\n fetch(url)\n .then(result => result.blob())\n .then(blob => {\n // Server-provided limit reduced for base64 encoding and overhead.\n const maxInbandAttachmentSize = this.props.tinode.getServerParam('maxMessageSize', MAX_INBAND_ATTACHMENT_SIZE) * 0.75 - 1024;\n if (blob.size > maxInbandAttachmentSize) {\n // Too large to send inband - uploading out of band and sending as a link.\n const uploader = this.props.tinode.getLargeFileHelper();\n if (!uploader) {\n this.props.onError(this.props.intl.formatMessage(messages.cannot_initiate_upload));\n return;\n }\n const uploadCompletionPromise = uploader.upload(blob);\n const msg = Drafty.appendAudio(null, {\n mime: blob.type,\n size: blob.size,\n duration: duration,\n preview: preview,\n urlPromise: uploadCompletionPromise\n });\n // Pass data and the uploader to the TinodeWeb.\n this.sendMessage(msg, uploadCompletionPromise, uploader);\n } else {\n // Small enough to send inband.\n blobToBase64(blob)\n .then(b64 => {\n this.sendMessage(Drafty.appendAudio(null, {\n mime: b64.mime,\n bits: b64.bits,\n size: blob.size,\n duration: duration,\n preview: preview,\n }))\n })\n }\n })\n .catch(err => {this.props.onError(err.message, 'err')});;\n }\n\n handleCancelUpload(seq, uploader) {\n const topic = this.props.tinode.getTopic(this.state.topic);\n const found = topic.findMessage(seq);\n if (found) {\n found._cancelled = true;\n }\n uploader.cancel();\n }\n\n // seq: seq ID of the source message\n // context: message content.\n // senderId: UID of the sender of the source message.\n // senderName: full name of the sender of the original message.\n handlePickReply(seq, content, senderId, senderName) {\n if (!seq || !content) {\n this.setState({reply: null});\n return;\n }\n\n content = typeof content == 'string' ? Drafty.init(content) : content;\n if (Drafty.isValid(content)) {\n content = Drafty.replyContent(content, QUOTED_REPLY_LENGTH);\n } else {\n // /!\\ invalid content.\n content = Drafty.append(Drafty.init('\\u26A0 '),\n Drafty.wrapInto(this.props.intl.formatMessage(messages.invalid_content), 'EM'));\n }\n\n this.setState({\n reply: {\n content: Drafty.quote(senderName, senderId, content),\n seq: seq\n }\n });\n this.props.onCancelForwardMessage();\n }\n\n // seq: seq ID of the message to edit.\n // context: message content.\n handleEditMessage(seq, content) {\n if (!seq || !content) {\n this.setState({reply: null});\n return;\n }\n\n content = typeof content == 'string' ? Drafty.init(content) : content;\n const editable = Drafty.toMarkdown(content);\n if (Drafty.isValid(content)) {\n content = Drafty.replyContent(content, EDIT_PREVIEW_LENGTH);\n } else {\n // /!\\ invalid content.\n content = Drafty.append(Drafty.init('\\u26A0 '),\n Drafty.wrapInto(this.props.intl.formatMessage(messages.invalid_content), 'EM'));\n }\n\n this.setState({\n reply: {\n content: Drafty.quote(this.props.intl.formatMessage(messages.editing_message), null, content),\n seq: seq,\n editing: true\n },\n contentToEdit: editable\n });\n this.props.onCancelForwardMessage();\n }\n\n\n handleCancelReply() {\n this.setState({reply: null, contentToEdit: null});\n this.props.onCancelForwardMessage();\n }\n\n handleQuoteClick(replyToSeq) {\n const ref = this.getOrCreateMessageRef(replyToSeq);\n if (ref && ref.current) {\n ref.current.scrollIntoView({block: \"center\", behavior: \"smooth\"});\n ref.current.classList.add('flash');\n setTimeout(_ => {ref.current.classList.remove('flash')} , 1000);\n } else {\n console.error(\"Unresolved message ref\", replyToSeq);\n }\n }\n\n handleUnpinMessage(seq) {\n const topic = this.props.tinode.getTopic(this.state.topic);\n topic.pinMessage(seq, false);\n }\n\n isDragEnabled() {\n return this.state.isWriter && !this.state.unconfirmed && !this.props.forwardMessage && !this.state.peerMessagingDisabled;\n }\n\n handleDragStart(e) {\n e.preventDefault();\n e.stopPropagation();\n e.dataTransfer.clearData();\n }\n\n handleDragIn(e) {\n e.preventDefault();\n e.stopPropagation();\n this.dragCounter++;\n if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {\n this.setState({dragging: true});\n }\n }\n\n handleDragOut(e) {\n e.preventDefault();\n e.stopPropagation();\n this.dragCounter--;\n if (this.dragCounter <= 0) {\n this.setState({dragging: false});\n }\n }\n\n handleDrag(e) {\n e.preventDefault();\n e.stopPropagation();\n }\n\n handleDrop(e) {\n e.preventDefault();\n e.stopPropagation();\n this.setState({dragging: false});\n if (this.isDragEnabled() && e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n this.handleFileDrop(e.dataTransfer.files);\n this.dragCounter = 0;\n }\n }\n\n render() {\n const {formatMessage} = this.props.intl;\n\n let component;\n if (!this.state.topic) {\n component = (\n \n );\n } else {\n let component2;\n if (this.state.imagePreview) {\n // Preview image before sending.\n component2 = (\n \n );\n } else if (this.state.videoPreview) {\n // Preview video.\n component2 = (\n \n );\n } else if (this.state.imagePostview) {\n // Expand received image.\n component2 = (\n \n );\n } else if (this.state.videoPostview) {\n // Play received video.\n component2 = (\n \n );\n } else if (this.state.docPreview) {\n // Preview attachment before sending.\n component2 = (\n \n );\n } else if (this.state.rtcPanel) {\n // P2P call.\n component2 = (\n \n );\n } else {\n const topic = this.props.tinode.getTopic(this.state.topic);\n const isChannel = topic.isChannelType();\n const groupTopic = topic.isGroupType() && !isChannel;\n const icon_badges = [];\n if (topic.trusted) {\n if (topic.trusted.verified) {\n icon_badges.push({icon: 'verified', color: 'badge-inv'});\n }\n if (topic.trusted.staff) {\n icon_badges.push({icon: 'staff', color: 'badge-inv'});\n }\n if (topic.trusted.danger) {\n icon_badges.push({icon: 'dangerous', color: 'badge-inv'});\n }\n }\n\n const pinnedMessages = [];\n this.state.pins.forEach(seq => pinnedMessages.push(topic.latestMsgVersion(seq) || topic.findMessage(seq)));\n\n const messageNodes = [];\n let previousFrom = null;\n let prevDate = null;\n let chatBoxClass = null;\n topic.messages((msg, prev, next, i) => {\n let nextFrom = next ? (next.from || 'chan') : null;\n\n let sequence = 'single';\n let thisFrom = msg.from || 'chan';\n if (thisFrom == previousFrom) {\n if (thisFrom == nextFrom) {\n sequence = 'middle';\n } else {\n sequence = 'last';\n }\n } else if (thisFrom == nextFrom) {\n sequence = 'first';\n }\n previousFrom = thisFrom;\n\n const isReply = !(thisFrom == this.props.myUserId);\n const deliveryStatus = topic.msgStatus(msg, true);\n\n let userFrom = thisFrom, userName, userAvatar;\n const user = topic.userDesc(thisFrom);\n if (user && user.public) {\n userName = user.public.fn;\n userAvatar = makeImageUrl(user.public.photo);\n }\n chatBoxClass = groupTopic ? 'chat-box group' : 'chat-box';\n\n // Ref for this chat message.\n const ref = this.getOrCreateMessageRef(msg.seq);\n let replyToSeq = msg.head ? parseInt(msg.head.reply) : null;\n if (!replyToSeq || isNaN(replyToSeq)) {\n replyToSeq = null;\n }\n\n if (msg.hi) {\n // Deleted message.\n messageNodes.push(\n \n );\n } else {\n const thisDate = new Date(msg.ts);\n // This message was sent on a different date than the previous.\n if (!prevDate || prevDate.toDateString() != thisDate.toDateString()) {\n messageNodes.push(\n \n );\n prevDate = thisDate;\n }\n messageNodes.push(\n \n );\n }\n });\n\n let lastSeen = null;\n if (isChannel) {\n lastSeen = formatMessage(messages.channel);\n } else {\n const cont = this.props.tinode.getMeTopic().getContact(this.state.topic);\n if (cont && Tinode.isP2PTopicName(cont.topic)) {\n if (cont.online) {\n lastSeen = formatMessage(messages.online_now);\n } else if (cont.seen) {\n lastSeen = formatMessage(messages.last_seen) + \": \" +\n shortDateFormat(cont.seen.when, this.props.intl.locale);\n // TODO: also handle user agent in c.seen.ua\n }\n }\n }\n const avatar = this.state.avatar || true;\n const online = this.state.deleted || topic.isSelfType() ? null :\n this.props.online ? 'online' + (this.state.typingIndicator ? ' typing' : '') : 'offline';\n\n const titleClass = 'panel-title' + (this.state.deleted ? ' deleted' : '');\n\n let messagesComponent = (\n <>\n \n
\n arrow_downward \n \n
\n {!this.state.isReader ?\n
\n {this.state.readingBlocked ?\n
\n \n
\n : null }\n
\n : null }\n
\n {this.state.peerMessagingDisabled && !this.state.unconfirmed ?\n : null}\n {this.state.unconfirmed ?\n \n :\n }\n >\n );\n\n component2 = (\n <>\n \n {this.props.displayMobile ?\n <>\n {this.state.pins.length > 0 ?\n this.setState({selectedPin: index})}\n onSelected={this.handleQuoteClick}\n onCancel={this.handleUnpinMessage} />\n : null\n }\n \n >\n : null}\n \n {messagesComponent}\n {this.state.dragging && this.isDragEnabled() ?\n {formatMessage(messages.drag_file)}
\n : null}\n >\n );\n }\n component = {component2}
\n }\n return component;\n }\n};\n\nexport default injectIntl(MessagesView);\n","// The <- button to be displayed in title bars.\nimport React from 'react';\n\nexport default class ButtonBack extends React.PureComponent {\n render() {\n return (\n {e.preventDefault(); this.props.onBack();}}>\n arrow_back \n \n );\n }\n}\n","import React from 'react';\n\nexport default class MenuContacts extends React.PureComponent {\n render() {\n return (\n \n );\n }\n};\n","import React from 'react';\n\nexport default class MenuStart extends React.PureComponent {\n render() {\n return (\n \n );\n }\n};\n","import React from 'react';\n\nimport LetterTile from './letter-tile.jsx';\nimport ButtonBack from './button-back.jsx';\nimport ContactBadges from './contact-badges.jsx';\nimport MenuContacts from './menu-contacts.jsx';\nimport MenuStart from './menu-start.jsx';\n\nimport { sanitizeUrlForMime } from '../lib/utils.js';\n\nexport default class SideNavbar extends React.PureComponent {\n render() {\n const icon_badges = [];\n if (this.props.trustedBadges) {\n this.props.trustedBadges.forEach(b => {\n icon_badges.push({icon: b, color: 'badge-inv'});\n });\n }\n let avatar = null;\n if (this.props.tinode) {\n avatar = this.props.tinode.authorizeURL(sanitizeUrlForMime(this.props.avatar, 'image'));\n }\n return (\n \n {this.props.onCancel ?
: null}\n {avatar ?\n
\n \n
\n :\n null}\n
{this.props.title}
\n {this.props.state === 'login' ?\n
:\n this.props.state === 'contacts' ?\n
:\n null}\n
\n );\n }\n};\n","/* ContactsView holds all contacts-related stuff */\nimport React from 'react';\nimport { FormattedMessage, defineMessages } from 'react-intl';\n\nimport ContactList from '../widgets/contact-list.jsx';\n\nimport { updateFavicon } from '../lib/utils.js';\n\nconst messages = defineMessages({\n archived_contacts_title: {\n id: \"archived_contacts\",\n defaultMessage: \"Archived contacts ({count})\",\n description: \"Label for archived chats\"\n }\n});\n\nexport default class ContactsView extends React.Component {\n constructor(props) {\n super(props);\n\n this.handleAction = this.handleAction.bind(this);\n\n this.state = ContactsView.deriveStateFromProps(props);\n }\n\n static deriveStateFromProps(props) {\n const contacts = [];\n let unreadThreads = 0;\n let archivedCount = 0;\n props.chatList.forEach(c => {\n const blocked = c.acs && !c.acs.isJoiner();\n // Show only blocked contacts only when props.blocked == true.\n if (blocked && props.blocked) {\n contacts.push(c);\n }\n if (blocked || props.blocked) {\n return;\n }\n\n if (c.private && c.private.arch) {\n if (props.archive) {\n contacts.push(c);\n } else {\n archivedCount ++;\n }\n } else if (!props.archive) {\n contacts.push(c);\n unreadThreads += c.unread > 0 ? 1 : 0;\n }\n });\n\n contacts.sort((a, b) => {\n return (b.touched || 0) - (a.touched || 0);\n });\n\n if (archivedCount > 0) {\n contacts.push({\n action: 'archive',\n title: messages.archived_contacts_title,\n values: {count: archivedCount}\n });\n }\n\n return {\n contactList: contacts,\n unreadThreads: unreadThreads\n };\n }\n\n componentDidUpdate(prevProps, prevState) {\n if (prevProps.chatList != this.props.chatList ||\n prevProps.archive != this.props.archive ||\n prevProps.blocked != this.props.blocked) {\n const newState = ContactsView.deriveStateFromProps(this.props);\n this.setState(newState);\n if (newState.unreadThreads != prevState.unreadThreads) {\n updateFavicon(newState.unreadThreads);\n }\n }\n }\n\n handleAction(action_ignored) {\n this.props.onShowArchive();\n }\n\n render() {\n return (\n ¯∖_(ツ)_/¯\"\n description=\"HTML message shown in ContactList when no contacts are found\">{\n (no_contacts) => \n }\n );\n }\n};\n","// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport CheckBox from '../widgets/checkbox.jsx';\n\nexport default class EditAccountView extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleCheckboxClick = this.handleCheckboxClick.bind(this);\n }\n\n handleCheckboxClick(what, checked) {\n if (what == 'sound') {\n this.props.onToggleMessageSounds(checked);\n } else if (what == 'alert') {\n this.props.onTogglePushNotifications(checked);\n } else if (what == 'incognito') {\n this.props.onToggleIncognitoMode(checked);\n }\n }\n\n render() {\n return (\n \n
\n \n \n \n \n
\n
\n \n {this.props.desktopAlertsEnabled ?\n \n :\n \n }\n \n \n
\n
\n \n \n \n \n
\n
\n );\n }\n};\n","// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport InPlaceEdit from '../widgets/in-place-edit.jsx';\nimport PermissionsEditor from '../widgets/permissions-editor.jsx';\n\nconst messages = defineMessages({\n delete_account: {\n id: 'delete_account',\n defaultMessage: 'Delete account',\n description: 'Title for delete account warning'\n },\n delete_account_warning: {\n id: 'delete_account_warning',\n defaultMessage: 'Are you sure you want to delete your account? It cannot be undone.',\n description: 'Warning message when deleting an account'\n }\n});\n\nclass AccSecurityView extends React.Component {\n constructor(props) {\n super(props);\n\n const me = this.props.tinode.getMeTopic();\n let blockedCount = 0;\n me.contacts((c) => {\n if (c.acs && !c.acs.isJoiner()) {\n blockedCount ++;\n }\n });\n const defacs = me.getDefaultAccess();\n this.state = {\n auth: defacs ? defacs.auth : null,\n anon: defacs ? defacs.anon : null,\n showPermissionEditorFor: undefined,\n blockedCount: blockedCount,\n };\n\n this.handlePasswordUpdate = this.handlePasswordUpdate.bind(this);\n this.handleLaunchPermissionsEditor = this.handleLaunchPermissionsEditor.bind(this);\n this.handleHidePermissionsEditor = this.handleHidePermissionsEditor.bind(this);\n this.handlePermissionsChanged = this.handlePermissionsChanged.bind(this);\n this.handleDeleteAccount = this.handleDeleteAccount.bind(this);\n }\n\n handlePasswordUpdate(pwd) {\n this.setState({password: pwd});\n this.props.onUpdatePassword(pwd);\n }\n\n handleLaunchPermissionsEditor(which) {\n this.setState({\n showPermissionEditorFor: which,\n editedPermissions: this.state[which]\n });\n }\n\n handleHidePermissionsEditor() {\n this.setState({showPermissionEditorFor: undefined});\n }\n\n handlePermissionsChanged(perm) {\n let defacs = {};\n defacs[this.state.showPermissionEditorFor] = perm;\n this.props.onUpdateAccountDesc('me', undefined, undefined, defacs);\n\n let newState = {showPermissionEditorFor: undefined};\n newState[this.state.showPermissionEditorFor] = perm;\n this.setState(newState);\n }\n\n handleDeleteAccount(e) {\n e.preventDefault();\n const {formatMessage} = this.props.intl;\n this.props.onShowAlert(\n formatMessage(messages.delete_account), // title\n formatMessage(messages.delete_account_warning), // content\n (_ => this.props.onDeleteAccount()), // onConfirm\n null, // use default text \"OK\"\n true, // Show Reject button\n null // use default text \"Cancel\"\n );\n }\n\n render() {\n return (\n <>{this.state.showPermissionEditorFor ?\n \n :\n \n
\n
\n \n \n
\n {\n (password_unchanged) => \n } \n
\n
\n
\n
\n
\n
\n
\n \n \n \n
\n
\n
Auth: {this.state.auth}
\n
Anon: {this.state.anon}
\n
\n
\n {this.state.blockedCount > 0 ?\n <>\n
\n
\n >\n : null }\n
\n }>\n );\n }\n};\n\nexport default injectIntl(AccSecurityView);\n","// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport { APP_NAME, LINK_CONTACT_US, LINK_PRIVACY_POLICY, LINK_TERMS_OF_SERVICE } from '../config.js';\n\nexport default class AccSupportView extends React.PureComponent {\n render() {\n return (\n \n
\n
\n
\n
\n \n {APP_NAME}\n
\n
\n \n {Tinode.getLibrary()}\n
\n
\n \n {this.props.serverVersion}\n
\n
\n \n {this.props.serverAddress}\n
\n
\n
\n );\n }\n};\n","// Login form.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport CheckBox from '../widgets/checkbox.jsx';\nimport VisiblePassword from '../widgets/visible-password.jsx';\n\nexport default class LoginView extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n login: props.login,\n password: '',\n hostName: props.serverAddress,\n saveToken: props.persist\n };\n this.handleLoginChange = this.handleLoginChange.bind(this);\n this.handlePasswordChange = this.handlePasswordChange.bind(this);\n this.handleToggleSaveToken = this.handleToggleSaveToken.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n }\n\n handleLoginChange(e) {\n this.setState({login: e.target.value});\n }\n\n handlePasswordChange(e) {\n this.setState({password: e.target.value});\n }\n\n handleToggleSaveToken() {\n this.props.onPersistenceChange(!this.state.saveToken);\n this.setState({saveToken: !this.state.saveToken});\n }\n\n handleSubmit(e) {\n e.preventDefault();\n this.props.onLogin(this.state.login.trim(), this.state.password.trim());\n }\n\n render() {\n let submitClasses = 'primary';\n if (this.props.disabled) {\n submitClasses += ' disabled';\n }\n\n return (\n \n );\n }\n};\n","import QRCode from 'qrcodejs';\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport { QRCODE_SIZE } from '../config';\n\nconst messages = defineMessages({\n invalid_id: {\n id: 'error_invalid_id',\n defaultMessage: 'Invalid ID',\n description: 'Error message'\n }\n});\n\nclass NewTopicById extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.qrCodeRef = React.createRef();\n\n this.state = {\n groupId: '',\n };\n\n this.handleChange = this.handleChange.bind(this);\n this.handleKeyPress = this.handleKeyPress.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n }\n\n componentDidMount() {\n new QRCode(this.qrCodeRef.current, {\n text: this.props.myURI,\n width: QRCODE_SIZE,\n height: QRCODE_SIZE,\n });\n }\n\n handleChange(e) {\n this.setState({groupId: e.target.value});\n }\n\n handleKeyPress(e) {\n if (e.key === 'Enter') {\n this.handleSubmit(e);\n }\n }\n\n handleSubmit(e) {\n e.preventDefault();\n if (this.state.groupId) {\n const name = this.state.groupId.trim();\n const prefix = name.substring(0, 3);\n if (name.length > 3 && ['usr', 'grp', 'chn'].includes(prefix)) {\n this.props.onSubmit(name);\n } else {\n this.props.onError(this.props.intl.formatMessage(messages.invalid_id), 'err');\n }\n }\n }\n\n render() {\n return (\n \n
\n {\n (prompt) => \n } \n
\n
\n \n \n \n
\n
\n
\n
\n );\n }\n};\n\nexport default injectIntl(NewTopicById);\n","import React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport AvatarCrop from './avatar-crop.jsx';\nimport AvatarUpload from './avatar-upload.jsx';\nimport CheckBox from './checkbox.jsx';\nimport TagManager from './tag-manager.jsx';\n\nimport { AVATAR_SIZE, MAX_AVATAR_BYTES, MAX_EXTERN_ATTACHMENT_SIZE, MAX_TITLE_LENGTH,\n MAX_TOPIC_DESCRIPTION_LENGTH } from '../config.js';\nimport { imageScaled, blobToBase64, makeImageUrl } from '../lib/blob-helpers.js';\n\nexport default class NewTopicGroup extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.fullName = React.createRef();\n\n this.state = {\n fullName: '', // full/formatted name\n private: '',\n description: '',\n imageUrl: null,\n tags: [],\n isChannel: false,\n newAvatar: null,\n newAvatarMime: null\n };\n\n this.handleFieldEdit = this.handleFieldEdit.bind(this);\n this.handleImageChanged = this.handleImageChanged.bind(this);\n this.handleAvatarCropped = this.handleAvatarCropped.bind(this);\n this.handleAvatarCropCancel = this.handleAvatarCropCancel.bind(this);\n this.uploadAvatar = this.uploadAvatar.bind(this);\n this.handleTagsChanged = this.handleTagsChanged.bind(this);\n this.handleChannelToggle = this.handleChannelToggle.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n }\n\n componentDidMount() {\n // this.fullName.current.focus();\n }\n\n handleFieldEdit(name, e) {\n this.setState({[name]: e.target.value || ''});\n }\n\n handleImageChanged(mime, img) {\n this.setState({newAvatar: img, newAvatarMime: mime});\n }\n\n handleAvatarCropped(mime, blob, width, height) {\n const url = blob ? URL.createObjectURL(blob) : null;\n this.setState({imageUrl: url, newAvatar: null, newAvatarMime: null});\n if (blob) {\n this.uploadAvatar(mime, blob, width, height);\n }\n }\n\n handleAvatarCropCancel() {\n this.setState({newAvatar: null, newAvatarMime: null});\n }\n\n // Utility method for converting cropped avatar blob to bytes for sending inband or\n // for uploading it to the server out of band.\n uploadAvatar(mime, blob, width, height) {\n const readyToUpload = image => {\n let {mime, blob} = image;\n if (blob.size > MAX_AVATAR_BYTES) {\n // Too large to send inband - uploading out of band and sending as a link.\n const uploader = this.props.tinode.getLargeFileHelper();\n uploader.upload(blob)\n .then(url => this.setState({imageUrl: url}))\n .catch(err => this.props.onError(err.message, 'err'));\n } else {\n // Convert blob to base64-encoded bits.\n blobToBase64(blob)\n .then(b64 => this.setState({imageUrl: makeImageUrl({data: b64.bits, type: mime})}));\n }\n };\n\n if (width > AVATAR_SIZE || height > AVATAR_SIZE || width != height) {\n // Avatar is not square or too large even after cropping. Shrink it and make square.\n imageScaled(blob, AVATAR_SIZE, AVATAR_SIZE, MAX_EXTERN_ATTACHMENT_SIZE, true)\n .then(scaled => readyToUpload(scaled))\n .catch(err => this.props.onError(err.message, 'err'));\n } else {\n readyToUpload({mime: mime, blob: blob, width: width, height: height});\n }\n }\n\n handleTagsChanged(tags) {\n this.setState({tags: tags});\n }\n\n handleChannelToggle() {\n this.setState({isChannel: !this.state.isChannel});\n }\n\n handleSubmit(e) {\n e.preventDefault();\n\n const fn = this.state.fullName.trim().substring(0, MAX_TITLE_LENGTH);\n const comment = this.state.private.trim().substring(0, MAX_TITLE_LENGTH);\n const description = this.state.description.trim().substring(0, MAX_TOPIC_DESCRIPTION_LENGTH);\n if (fn) {\n this.props.onSubmit(fn, description, this.state.imageUrl, comment, this.state.tags, this.state.isChannel);\n }\n }\n\n render() {\n if (this.state.newAvatar) {\n return (\n \n );\n }\n\n let submitClasses = 'primary';\n if (this.props.disabled) {\n submitClasses += ' disabled';\n }\n return (\n \n );\n }\n};\n","// Create new topic and invite users or send an invite.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport ContactList from '../widgets/contact-list.jsx';\nimport NewTopicById from '../widgets/new-topic-by-id.jsx';\nimport NewTopicGroup from '../widgets/new-topic-group.jsx';\nimport SearchContacts from '../widgets/search-contacts.jsx';\n\nimport HashNavigation from '../lib/navigation.js';\nimport { asEmail, asPhone, theCard } from '../lib/utils.js';\n\nconst messages = defineMessages({\n search_for_contacts: {\n id: \"search_for_contacts\",\n defaultMessage: \"Use search to find contacts\",\n description: \"Text shown in contacts view when user entered no search query.\"\n },\n search_no_results: {\n id: \"search_no_results\",\n defaultMessage: \"Search returned no results\",\n description: \"Text shown in contacts view when query returned no results.\"\n },\n search_placeholder: {\n id: \"search_placeholder\",\n defaultMessage: \"List like alice@example.com, +17025550003...\",\n description: \"Placeholder in contacts search field\"\n },\n});\n\nclass NewTopicView extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n tabSelected: 'find',\n searchQuery: null\n };\n\n this.handleTabClick = this.handleTabClick.bind(this);\n this.handleSearchContacts = this.handleSearchContacts.bind(this);\n this.handleSearchResultSelected = this.handleSearchResultSelected.bind(this);\n this.handleNewGroupSubmit = this.handleNewGroupSubmit.bind(this);\n this.handleGroupByID = this.handleGroupByID.bind(this);\n }\n\n componentDidMount() {\n this.props.onInitFind();\n }\n\n handleTabClick(e) {\n e.preventDefault();\n HashNavigation.navigateTo(HashNavigation.addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id));\n this.setState({tabSelected: e.currentTarget.dataset.id});\n }\n\n handleSearchContacts(query) {\n query = query.trim() || Tinode.DEL_CHAR;\n if (!/[\\s,:]/.test(query) && query != Tinode.DEL_CHAR) {\n // No colons, spaces or commas, not DEL char. Try as email, phone, or alias.\n const email = asEmail(query);\n if (email) {\n query = `${Tinode.TAG_EMAIL}${email}`;\n } else {\n const tel = asPhone(query);\n if (tel) {\n query = `${Tinode.TAG_PHONE}${tel}`;\n } else {\n if (query[0] == '@') {\n // Strip the leading '@' sign if present.\n query = query.substring(1);\n }\n // 'alice' -> 'alias:alice,alice'\n query = `${Tinode.TAG_ALIAS}${query},${query}`;\n }\n }\n }\n this.props.onSearchContacts(query);\n this.setState({searchQuery: Tinode.isNullValue(query) ? null : query});\n }\n\n handleSearchResultSelected(topicName) {\n if (this.state.tabSelected == 'find') {\n HashNavigation.navigateTo(HashNavigation.removeUrlParam(window.location.hash, 'tab'));\n this.props.onCreateTopic(topicName);\n }\n }\n\n handleNewGroupSubmit(name, description, dataUrl, priv, tags, isChannel) {\n HashNavigation.navigateTo(HashNavigation.removeUrlParam(window.location.hash, 'tab'));\n this.props.onCreateTopic(undefined,\n {public: theCard(name, dataUrl, null, description), private: priv, tags: tags}, isChannel);\n }\n\n handleGroupByID(topicName) {\n HashNavigation.navigateTo(HashNavigation.removeUrlParam(window.location.hash, 'tab'));\n this.props.onCreateTopic(topicName);\n }\n\n render() {\n const {formatMessage} = this.props.intl;\n const no_contacts_placeholder = formatMessage(this.state.searchQuery ?\n messages.search_no_results : messages.search_for_contacts);\n const search_placeholder = formatMessage(messages.search_placeholder);\n return (\n \n
\n {this.state.tabSelected === 'grp' ?\n
:\n this.state.tabSelected === 'byid' ?\n
:\n
\n \n \n
}\n
\n );\n }\n};\n\nexport default injectIntl(NewTopicView);\n","import React from 'react';\n\nimport { KNOWN_HOSTS } from '../config.js';\n\n/* Combobox for selecting host name */\n\nexport default class HostSelector extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n hostName: props.serverAddress,\n changed: false\n };\n\n this.handleHostNameChange = this.handleHostNameChange.bind(this);\n this.handleEditingFinished = this.handleEditingFinished.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n }\n\n handleHostNameChange(e) {\n this.setState({hostName: e.target.value, changed: true});\n }\n\n handleEditingFinished() {\n if (this.state.changed) {\n this.setState({changed: false});\n this.props.onServerAddressChange(this.state.hostName.trim());\n }\n }\n\n handleKeyDown(e) {\n if (e.key == 'Enter') {\n this.handleEditingFinished();\n }\n }\n\n render() {\n const hostOptions = [];\n for (let key in KNOWN_HOSTS) {\n let item = KNOWN_HOSTS[key];\n hostOptions.push(\n \n );\n }\n return (\n \n \n \n {hostOptions}\n \n
\n );\n }\n}\n","// Tinode config panel.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport CheckBox from '../widgets/checkbox.jsx';\n\nimport HostSelector from '../widgets/host-selector.jsx';\n\nexport default class SettingsView extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n transport: props.transport || 'def',\n serverAddress: props.serverAddress,\n secureConnection: props.secureConnection,\n };\n\n this.handleSubmit = this.handleSubmit.bind(this);\n this.handleTransportSelected = this.handleTransportSelected.bind(this);\n this.handleServerAddressChange = this.handleServerAddressChange.bind(this);\n this.handleToggleSecure = this.handleToggleSecure.bind(this);\n }\n\n handleSubmit(e) {\n e.preventDefault();\n this.props.onUpdate({\n transport: this.state.transport,\n serverAddress: this.state.serverAddress,\n secureConnection: this.state.secureConnection,\n });\n }\n\n handleTransportSelected(e) {\n this.setState({transport: e.currentTarget.value});\n }\n\n handleServerAddressChange(name) {\n this.setState({serverAddress: name});\n }\n\n handleToggleSecure(e) {\n this.setState({secureConnection: !this.state.secureConnection});\n }\n\n render() {\n const names = {def: \"default\", ws: \"websocket\", lp: \"long polling\"};\n const transportOptions = [];\n ['def', 'ws', 'lp'].forEach(item => {\n const id = 'transport-' + item;\n const name = names[item];\n transportOptions.push(\n \n \n {name} \n \n );\n });\n\n return (\n \n );\n }\n};\n","// ValidationView: panel for confirming credentials, like email or phone.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nconst messages = defineMessages({\n phone: {\n id: 'phone_dative',\n defaultMessage: 'phone',\n description: \"Dative case of 'phone', i.e. 'phone' in 'by phone'\",\n },\n email: {\n id: 'email_dative',\n defaultMessage: 'email',\n description: \"Dative case of 'email', i.e. 'email' in 'by email'\",\n }\n});\n\nclass ValidationView extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n code: props.credCode || '',\n codeReceived: props.credCode\n };\n\n this.handleCodeChange = this.handleCodeChange.bind(this);\n this.handleKeyPress = this.handleKeyPress.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n }\n\n static getDerivedStateFromProps(nextProps, prevState) {\n if (nextProps.credCode != prevState.codeReceived) {\n return {\n code: nextProps.credCode || '',\n codeReceived: nextProps.credCode\n };\n }\n\n return prevState;\n }\n\n componentDidMount() {\n // Submit code automatically if it's received from the parent.\n if (this.props.credCode) {\n this.props.onSubmit(this.props.credMethod, this.props.credCode, this.props.credToken);\n }\n }\n\n componentDidUpdate(prevProps, prevState) {\n // Submit code automatically if it's received from the parent.\n if (this.state.codeReceived && this.state.code && this.state.code != prevState.code) {\n this.props.onSubmit(this.props.credMethod, this.state.code, this.props.credToken);\n }\n }\n\n\n handleCodeChange(e) {\n this.setState({code: e.target.value.replace(/[^\\d]/g, '')});\n }\n\n handleKeyPress(e) {\n if (e.key === 'Enter') {\n this.handleSubmit(e);\n } else if (e.key == 'Escape') {\n this.handleCancel(e);\n }\n }\n\n handleSubmit(e) {\n e.preventDefault();\n if (this.state.code && this.state.code.trim()) {\n this.props.onSubmit(this.props.credMethod, this.state.code.trim(), this.props.credToken);\n }\n }\n\n handleCancel(e) {\n e.preventDefault();\n this.props.onCancel();\n }\n\n render() {\n const { formatMessage } = this.props.intl;\n const methods = {'email': formatMessage(messages.email), 'tel': formatMessage(messages.phone)};\n const method = methods[this.props.credMethod] || this.props.credMethod;\n return (\n \n
\n \n \n \n
\n
\n {\n (numbers_only) => \n } \n
\n
\n \n \n \n \n \n \n
\n
\n );\n }\n};\n\nexport default injectIntl(ValidationView);\n","import React, { Suspense } from 'react';\nimport { defineMessages, FormattedMessage, injectIntl } from 'react-intl';\n\nimport ErrorPanel from '../widgets/error-panel.jsx';\nimport LoadSpinner from '../widgets/load-spinner.jsx';\nimport SideNavbar from '../widgets/side-navbar.jsx';\nimport TopicCommonView from './topic-common-view.jsx';\n\nconst AccountSettingsView = React.lazy(_ => import('./account-settings-view.jsx'));\nimport ContactsView from './contacts-view.jsx';\nconst CreateAccountView = React.lazy(_ => import('./create-account-view.jsx'));\nimport AccNotificationsView from './acc-notifications-view.jsx';\nimport AccSecurityView from './acc-security-view.jsx';\nimport AccSupportView from './acc-support-view.jsx';\nimport LoginView from './login-view.jsx';\nimport NewTopicView from './new-topic-view.jsx';\nconst PasswordResetView = React.lazy(_ => import('./password-reset-view.jsx'));\nimport SettingsView from './settings-view.jsx';\nimport ValidationView from './validation-view.jsx';\n\n// Panel titles for translation.\nconst messages = defineMessages({\n login: {\n id: 'sidepanel_title_login',\n description: 'Sidepanel title for LoginView.',\n defaultMessage: 'Sign In'\n },\n register: {\n id: 'sidepanel_title_register',\n description: 'Sidepanel title for CreateAccountView.',\n defaultMessage: 'Create Account'\n },\n settings: {\n id: 'sidepanel_title_settings',\n description: 'Sidepanel title for SettingsView.',\n defaultMessage: 'Settings'\n },\n edit: {\n id: 'sidepanel_title_account_settings',\n description: 'Sidepanel title for AccountSettingsView.',\n defaultMessage: 'Account Settings'\n },\n general: {\n id: 'panel_title_general',\n description: 'Title for TopicCommon.',\n defaultMessage: 'General'\n },\n security: {\n id: 'panel_title_security',\n description: 'Title for TopicSecirity and AccSecurity.',\n defaultMessage: 'Security'\n },\n crop: {\n id: 'panel_title_crop',\n description: 'Title for AvatarCropView.',\n defaultMessage: 'Drag to Adjust'\n },\n notif: {\n id: 'sidepanel_title_acc_notifications',\n description: 'Sidepanel title for AccNotificationsView.',\n defaultMessage: 'Notifications'\n },\n support: {\n id: 'sidepanel_title_acc_support',\n description: 'Sidepanel title for AccSupportView.',\n defaultMessage: 'Support'\n },\n newtpk: {\n id: 'sidepanel_title_newtpk',\n description: 'Sidepanel title for NewTopicView.',\n defaultMessage: 'Start New Chat'\n },\n cred: {\n id: 'sidepanel_title_cred',\n description: 'Sidepanel title for ValidationView.',\n defaultMessage: 'Confirm Credentials'\n },\n reset: {\n id: 'sidepanel_title_reset',\n description: 'Sidepanel title for PasswordResetView.',\n defaultMessage: 'Reset Password'\n },\n archive: {\n id: 'sidepanel_title_archive',\n description: 'Sidepanel title for ContactsView-Archive.',\n defaultMessage: 'Archived Chats'\n },\n blocked: {\n id: 'sidepanel_title_blocked',\n description: 'Sidepanel title for ContactsView-Blocked.',\n defaultMessage: 'Blocked Chats'\n }\n});\n\nclass SidepanelView extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleNewTopic = this.handleNewTopic.bind(this);\n }\n\n handleNewTopic() {\n this.props.onNavigate('newtpk');\n }\n\n render() {\n const {formatMessage} = this.props.intl;\n const view = this.props.state || (this.props.myUserId ? 'contacts' : 'login');\n\n let title, avatar, badges;\n if (view == 'contacts') {\n title = this.props.title;\n avatar = this.props.avatar ? this.props.avatar : true;\n badges = this.props.trustedBadges;\n } else {\n title = formatMessage(messages[view]);\n avatar = false;\n badges = null;\n }\n\n let onCancel;\n if (['login', 'contacts'].indexOf(view) == -1) {\n onCancel = this.props.onCancel;\n }\n\n return (\n \n \n\n \n\n \n\n {view === 'login' ?\n :\n\n view === 'register' ?\n
}>\n \n :\n\n view === 'settings' ?\n :\n\n view === 'edit' ?\n }>\n \n :\n\n (view === 'general' || view === 'crop') ?\n :\n\n view === 'notif' ?\n :\n\n view === 'security' ?\n :\n\n view === 'support' ?\n :\n\n (view === 'contacts' || view == 'archive' || view == 'blocked') ?\n :\n\n view === 'newtpk' ?\n :\n\n view === 'cred' ?\n :\n\n view === 'reset' ?\n }>\n \n :\n null}\n \n );\n }\n};\n\nexport default injectIntl(SidepanelView);\n","import { KNOWN_HOSTS, DEFAULT_HOST } from '../config.js';\n\n// Detect server address from the URL\nexport function detectServerAddress() {\n let host = DEFAULT_HOST;\n if (typeof window.location == 'object') {\n if (window.location.protocol == 'file:' || window.location.hostname == 'localhost') {\n host = KNOWN_HOSTS.local;\n } else if (window.location.hostname) {\n host = window.location.hostname + (window.location.port ? ':' + window.location.port : '');\n }\n }\n return host;\n}\n\n// Detect if the page is served over HTTPS.\nexport function isSecureConnection() {\n if (typeof window.location == 'object') {\n return window.location.protocol == 'https:';\n }\n return false;\n}\n\nexport function isLocalHost() {\n if (typeof window.location == 'object') {\n return window.location.hostname == 'localhost';\n }\n return false;\n}\n","// The top-level class to hold all functionality together.\nimport React, { Suspense } from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport { initializeApp as firebaseInitApp } from 'firebase/app';\nimport { getMessaging as firebaseGetMessaging, getToken as firebaseGetToken,\n deleteToken as firebaseDelToken, onMessage as firebaseOnMessage } from 'firebase/messaging';\n\nimport { Drafty, Tinode } from 'tinode-sdk';\n\nimport Alert from '../widgets/alert.jsx';\nimport ContextMenu from '../widgets/context-menu.jsx';\nimport ForwardDialog from '../widgets/forward-dialog.jsx';\nimport CallIncoming from '../widgets/call-incoming.jsx';\nconst PhoneCountrySelector = React.lazy(_ => import('../widgets/phone-country-selector.jsx'));\n\nimport InfoView from './info-view.jsx';\nimport MessagesView from './messages-view.jsx';\nimport SidepanelView from './sidepanel-view.jsx';\n\nimport { API_KEY, APP_NAME, DEFAULT_P2P_ACCESS_MODE, FORWARDED_PREVIEW_LENGTH, LOGGING_ENABLED,\n MEDIA_BREAKPOINT, WAKE_UP_TICK, WAKE_UP_TIMEOUT } from '../config.js';\nimport { CALL_STATE_NONE, CALL_STATE_OUTGOING_INITATED,\n CALL_STATE_INCOMING_RECEIVED, CALL_STATE_IN_PROGRESS,\n CALL_HEAD_STARTED } from '../constants.js';\nimport { PACKAGE_VERSION } from '../version.js';\nimport { base64ReEncode, makeImageUrl } from '../lib/blob-helpers.js';\nimport { detectServerAddress, isLocalHost, isSecureConnection } from '../lib/host-name.js';\nimport LocalStorageUtil from '../lib/local-storage.js';\nimport HashNavigation from '../lib/navigation.js';\nimport { secondsToTime } from '../lib/strformat.js'\nimport { updateFavicon } from '../lib/utils.js';\n\n// Sound to play on message received.\nconst POP_SOUND = new Audio('audio/msg.m4a');\n\nconst messages = defineMessages({\n reconnect_countdown: {\n id: 'reconnect_countdown',\n defaultMessage: 'Disconnected. Reconnecting in {seconds}…',\n description: 'Message shown when an app update is available.'\n },\n reconnect_now: {\n id: 'reconnect_now',\n defaultMessage: 'Try now',\n description: 'Prompt for reconnecting now'\n },\n push_init_failed: {\n id: 'push_init_failed',\n defaultMessage: 'Failed to initialize push notifications',\n description: 'Error message when push notifications have failed to initialize.'\n },\n invalid_security_token: {\n id: 'invalid_security_token',\n defaultMessage: 'Invalid security token',\n description: 'Error message when resetting password.'\n },\n no_connection: {\n id: 'no_connection',\n defaultMessage: 'No connection',\n description: 'Warning that the user is offline.'\n },\n code_doesnot_match: {\n id: 'code_doesnot_match',\n defaultMessage: 'Code does not match',\n description: 'Error message when the credential validation code is incorrect.'\n },\n menu_item_info: {\n id: 'menu_item_info',\n defaultMessage: 'Info',\n description: 'Show extended topic information'\n },\n menu_item_audio_call: {\n id: 'menu_item_audio_call',\n defaultMessage: 'Call',\n description: 'Start audio call'\n },\n menu_item_video_call: {\n id: 'menu_item_video_call',\n defaultMessage: 'Video call',\n description: 'Start video call'\n },\n cred_confirmed_successfully: {\n id: 'cred_confirmed_successfully',\n defaultMessage: 'Confirmed successfully',\n description: 'Notification message that the credential was successfully validated.'\n },\n password_reset_success: {\n id: 'password_reset_success',\n defaultMessage: 'Password reset successfully',\n description: 'Notification message that the password was successfully reset.'\n },\n select_country: {\n id: 'select_country',\n defaultMessage: 'Select country',\n description: 'Placeholder for the country selector'\n }\n});\n\nclass TinodeWeb extends React.Component {\n constructor(props) {\n super(props);\n\n this.selfRef = React.createRef();\n\n this.state = this.getBlankState();\n\n this.handleResize = this.handleResize.bind(this);\n this.handleHashRoute = this.handleHashRoute.bind(this);\n this.handleOnline = this.handleOnline.bind(this);\n this.checkForAppUpdate = this.checkForAppUpdate.bind(this);\n this.handleVisibilityEvent = this.handleVisibilityEvent.bind(this);\n this.handleError = this.handleError.bind(this);\n this.handleLoginRequest = this.handleLoginRequest.bind(this);\n this.handlePersistenceChange = this.handlePersistenceChange.bind(this);\n this.handleConnected = this.handleConnected.bind(this);\n this.handleAutoreconnectIteration = this.handleAutoreconnectIteration.bind(this);\n this.doLogin = this.doLogin.bind(this);\n this.handleLoginSuccessful = this.handleLoginSuccessful.bind(this);\n this.handleDisconnect = this.handleDisconnect.bind(this);\n this.tnMeMetaDesc = this.tnMeMetaDesc.bind(this);\n this.tnMeContactUpdate = this.tnMeContactUpdate.bind(this);\n this.tnMeSubsUpdated = this.tnMeSubsUpdated.bind(this);\n this.resetContactList = this.resetContactList.bind(this);\n this.tnInitFind = this.tnInitFind.bind(this);\n this.tnFndSubsUpdated = this.tnFndSubsUpdated.bind(this);\n this.handleSearchContacts = this.handleSearchContacts.bind(this);\n this.handleTopicSelected = this.handleTopicSelected.bind(this);\n this.handleHideMessagesView = this.handleHideMessagesView.bind(this);\n this.handleSendMessage = this.handleSendMessage.bind(this);\n this.handleNewChatInvitation = this.handleNewChatInvitation.bind(this);\n this.handleNewAccount = this.handleNewAccount.bind(this);\n this.handleNewAccountRequest = this.handleNewAccountRequest.bind(this);\n this.handleUpdatePasswordRequest = this.handleUpdatePasswordRequest.bind(this);\n this.handleUpdateAccountTagsRequest = this.handleUpdateAccountTagsRequest.bind(this);\n this.handleToggleIncognitoMode = this.handleToggleIncognitoMode.bind(this);\n this.handleSettings = this.handleSettings.bind(this);\n this.handleGlobalSettings = this.handleGlobalSettings.bind(this);\n this.handleShowArchive = this.handleShowArchive.bind(this);\n this.handleShowBlocked = this.handleShowBlocked.bind(this);\n this.handleToggleMessageSounds = this.handleToggleMessageSounds.bind(this);\n this.handleCredAdd = this.handleCredAdd.bind(this);\n this.handleCredDelete = this.handleCredDelete.bind(this);\n this.handleCredConfirm = this.handleCredConfirm.bind(this);\n this.initFCMessaging = this.initFCMessaging.bind(this);\n this.toggleFCMToken = this.toggleFCMToken.bind(this);\n this.handlePushMessage = this.handlePushMessage.bind(this);\n this.handleSidepanelCancel = this.handleSidepanelCancel.bind(this);\n this.handleStartTopicRequest = this.handleStartTopicRequest.bind(this);\n this.handleNewTopicCreated = this.handleNewTopicCreated.bind(this);\n this.handleTopicUpdateRequest = this.handleTopicUpdateRequest.bind(this);\n this.handleUnarchive = this.handleUnarchive.bind(this);\n this.handleChangePermissions = this.handleChangePermissions.bind(this);\n this.handleTagsUpdateRequest = this.handleTagsUpdateRequest.bind(this);\n this.handleLogout = this.handleLogout.bind(this);\n this.handleDeleteAccount = this.handleDeleteAccount.bind(this);\n this.handleDeleteTopicRequest = this.handleDeleteTopicRequest.bind(this);\n this.handleDeleteMessagesRequest = this.handleDeleteMessagesRequest.bind(this);\n this.handleLeaveUnsubRequest = this.handleLeaveUnsubRequest.bind(this);\n this.handleBlockTopicRequest = this.handleBlockTopicRequest.bind(this);\n this.handleReportTopic = this.handleReportTopic.bind(this);\n this.handleShowContextMenu = this.handleShowContextMenu.bind(this);\n this.defaultTopicContextMenu = this.defaultTopicContextMenu.bind(this);\n this.handleHideContextMenu = this.handleHideContextMenu.bind(this);\n this.handleShowAlert = this.handleShowAlert.bind(this);\n this.handleShowInfoView = this.handleShowInfoView.bind(this);\n this.handleMemberUpdateRequest = this.handleMemberUpdateRequest.bind(this);\n this.handleValidateCredentialsRequest = this.handleValidateCredentialsRequest.bind(this);\n this.handlePasswordResetRequest = this.handlePasswordResetRequest.bind(this);\n this.handleResetPassword = this.handleResetPassword.bind(this);\n this.handleContextMenuAction = this.handleContextMenuAction.bind(this);\n this.handleShowCountrySelector = this.handleShowCountrySelector.bind(this);\n\n this.handleShowForwardDialog = this.handleShowForwardDialog.bind(this);\n this.handleHideForwardDialog = this.handleHideForwardDialog.bind(this);\n\n this.handleStartVideoCall = this.handleStartVideoCall.bind(this);\n this.handleStartAudioCall = this.handleStartAudioCall.bind(this);\n this.handleInfoMessage = this.handleInfoMessage.bind(this);\n this.handleDataMessage = this.handleDataMessage.bind(this);\n this.handleCallClose = this.handleCallClose.bind(this);\n\n this.handleCallInvite = this.handleCallInvite.bind(this);\n this.handleCallRinging = this.handleCallRinging.bind(this);\n this.handleCallHangup = this.handleCallHangup.bind(this);\n this.handleCallSendOffer = this.handleCallSendOffer.bind(this);\n this.handleCallIceCandidate = this.handleCallIceCandidate.bind(this);\n this.handleCallSendAnswer = this.handleCallSendAnswer.bind(this);\n\n this.handleCallAccept = this.handleCallAccept.bind(this);\n\n this.sendMessageToTopic = this.sendMessageToTopic.bind(this);\n\n // FIXME: this is unused.\n this.callTimeoutTimer = null;\n }\n\n getBlankState() {\n const settings = LocalStorageUtil.getObject('settings') || {};\n const persist = !!LocalStorageUtil.getObject('keep-logged-in');\n\n return {\n connected: false,\n // Connected and subscribed to 'me'\n ready: false,\n // Try to re-login on new connection.\n autoLogin: false,\n transport: settings.transport || null,\n serverAddress: settings.serverAddress || detectServerAddress(),\n secureConnection: settings.secureConnection === undefined ?\n isSecureConnection() : settings.secureConnection,\n serverVersion: \"no connection\",\n // \"On\" is the default, so saving the \"off\" state.\n messageSounds: !settings.messageSoundsOff,\n incognitoMode: false,\n // Persistent request to enable alerts.\n desktopAlerts: persist && !!settings.desktopAlerts,\n // Enable / disable checkbox.\n desktopAlertsEnabled: (isSecureConnection() || isLocalHost()) &&\n (typeof firebaseInitApp != 'undefined') && (typeof navigator != 'undefined') &&\n (typeof FIREBASE_INIT != 'undefined'),\n firebaseToken: persist ? LocalStorageUtil.getObject('firebase-token') : null,\n\n applicationVisible: !document.hidden,\n\n errorText: '',\n errorLevel: null,\n errorAction: undefined,\n errorActionText: null,\n\n sidePanelSelected: 'login',\n sidePanelTitle: null,\n sidePanelAvatar: null,\n myTrustedBadges: [],\n loadSpinnerVisible: false,\n\n login: '',\n password: '',\n persist: persist,\n myUserId: null,\n liveConnection: navigator.onLine,\n topicSelected: '',\n topicSelectedOnline: false,\n topicSelectedAcs: null,\n newTopicParams: null,\n loginDisabled: false,\n displayMobile: (window.innerWidth <= MEDIA_BREAKPOINT),\n infoPanel: undefined,\n mobilePanel: 'sidepanel',\n\n // Video calls.\n callTopic: undefined,\n callState: CALL_STATE_NONE,\n callAudioOnly: undefined,\n // If true, call state should be transitioned to CALL_STATE_IN_PROGRESS upon\n // switching to the call topic.\n callShouldStart: false,\n\n contextMenuVisible: false,\n contextMenuBounds: null,\n contextMenuClickAt: null,\n contextMenuParams: null,\n contextMenuItems: [],\n\n forwardDialogVisible: false,\n forwardMessage: null,\n\n // Modal alert dialog.\n alertVisible: false,\n alertParams: {},\n\n // Chats as shown in the ContactsView\n chatList: [],\n // Contacts returned by a search query.\n searchResults: [],\n // Merged results of a search query and p2p chats.\n searchableContacts: [],\n // Credential validation.\n reqCredMethod: undefined,\n credMethod: undefined,\n credCode: undefined,\n credToken: undefined,\n // Topic to go to after login.\n requestedTopic: undefined\n };\n }\n\n componentDidMount() {\n window.addEventListener('resize', this.handleResize);\n this.handleOnlineOn = _ => { this.handleOnline(true); }\n window.addEventListener('online', this.handleOnlineOn);\n this.handleOnlineOff = _ => { this.handleOnline(false); }\n window.addEventListener('offline', this.handleOnlineOff);\n window.addEventListener('hashchange', this.handleHashRoute);\n\n // Process background notifications from the service worker.\n if (typeof BroadcastChannel == 'function') {\n const serviceWorkerChannel = new BroadcastChannel('tinode-sw');\n serviceWorkerChannel.addEventListener('message', this.handlePushMessage);\n } else {\n // Safari is broken by design.\n console.warn(\"Your browser does not support BroadcastChannel. Some features will not be available\");\n }\n\n // Detect if computer just woke up from sleep. Checks how much time has passed since the last tick.\n // If too much time has passed then the computer was asleep.\n this.lastWakeUpCheck = new Date().getTime();\n this.wakeUpTicker = setInterval(_ => {\n const now = new Date().getTime();\n if (now - this.lastWakeUpCheck > WAKE_UP_TIMEOUT) {\n // Trigger reconnect.\n this.handleOnlineOn();\n }\n this.lastWakeUpCheck = now;\n }, WAKE_UP_TICK);\n\n // Window/tab visible or invisible for pausing timers.\n document.addEventListener('visibilitychange', this.handleVisibilityEvent);\n\n this.setState({\n viewportWidth: document.documentElement.clientWidth,\n viewportHeight: document.documentElement.clientHeight\n });\n\n new Promise((resolve, reject) => {\n this.tinode = TinodeWeb.tnSetup(this.state.serverAddress, isSecureConnection(), this.state.transport,\n this.props.intl.locale, this.state.persist, resolve);\n this.tinode.onConnect = this.handleConnected;\n this.tinode.onDisconnect = this.handleDisconnect;\n this.tinode.onAutoreconnectIteration = this.handleAutoreconnectIteration;\n this.tinode.onInfoMessage = this.handleInfoMessage;\n this.tinode.onDataMessage = this.handleDataMessage;\n }).then(_ => {\n // Initialize desktop alerts.\n if (this.state.desktopAlertsEnabled) {\n this.initFCMessaging().catch(_ => {\n // do nothing: handled earlier.\n // catch needed to pervent unnecessary logging of error.\n });\n }\n\n // Read contacts from cache.\n this.resetContactList();\n\n const token = this.state.persist ? LocalStorageUtil.getObject('auth-token') : undefined;\n if (token) {\n this.setState({autoLogin: true});\n\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(err => {\n // Socket error\n this.handleError(err.message, 'err');\n });\n }\n\n // Parse the hash navigation params.\n const parsedNav = HashNavigation.parseUrlHash(window.location.hash);\n // Maybe navigate to home screen.\n if (!['cred', 'reset', 'register'].includes(parsedNav.path[0])) {\n // Save possible topic name.\n this.setState({requestedTopic: parsedNav.path[1]});\n const path = parsedNav.params && parsedNav.params.cred_done ?\n HashNavigation.addUrlParam('', 'cred_done', parsedNav.params.cred_done):\n '';\n HashNavigation.navigateTo(path);\n } else {\n this.handleHashRoute();\n }\n });\n }\n\n componentWillUnmount() {\n window.removeEventListener('resize', this.handleResize);\n window.removeEventListener('hashchange', this.handleHashRoute);\n window.removeEventListener('online', this.handleOnlineOn);\n window.removeEventListener('offline', this.handleOnlineOff);\n document.removeEventListener('visibilitychange', this.handleVisibilityEvent);\n\n clearInterval(this.wakeUpTicker);\n }\n\n // Setup transport (usually websocket) and server address. This will terminate connection with the server.\n static tnSetup(serverAddress, secureConnection, transport, locale, persistentCache, onSetupCompleted) {\n const tinode = new Tinode({appName: APP_NAME, host: serverAddress, apiKey: API_KEY, transport: transport,\n secure: secureConnection, persist: persistentCache}, onSetupCompleted);\n tinode.setHumanLanguage(locale);\n tinode.enableLogging(LOGGING_ENABLED, true);\n return tinode;\n }\n\n // Tinode received a push notification from the server.\n handlePushMessage(payload) {\n this.tinode.oobNotification(payload.data || {});\n }\n\n initFCMessaging() {\n const {formatMessage, locale} = this.props.intl;\n const onError = (msg, err) => {\n console.error(msg, err);\n this.handleError(formatMessage(messages.push_init_failed), 'err');\n this.setState({firebaseToken: null});\n LocalStorageUtil.updateObject('settings', {desktopAlerts: false});\n }\n\n try {\n this.fcm = firebaseGetMessaging(firebaseInitApp(FIREBASE_INIT, APP_NAME));\n return navigator.serviceWorker.getRegistration('/service-worker.js').then(reg => {\n return reg || navigator.serviceWorker.register('/service-worker.js').then(reg => {\n this.checkForAppUpdate(reg);\n return reg;\n });\n }).then(reg => {\n // Pass locale and version config to the service worker.\n (reg.active || reg.installing).postMessage(JSON.stringify({locale: locale, version: PACKAGE_VERSION}));\n // Request token.\n return TinodeWeb.requestFCMToken(this.fcm, reg);\n }).then(token => {\n const persist = LocalStorageUtil.getObject('keep-logged-in');\n if (token != this.state.firebaseToken) {\n this.tinode.setDeviceToken(token);\n if (persist) {\n LocalStorageUtil.setObject('firebase-token', token);\n }\n }\n this.setState({firebaseToken: token, desktopAlerts: true});\n if (persist) {\n LocalStorageUtil.updateObject('settings', {desktopAlerts: true});\n }\n\n // Handhe FCM pushes\n // (a) for channels always,\n // (b) pushes when the app is in foreground but has no focus.\n firebaseOnMessage(this.fcm, payload => { this.handlePushMessage(payload); });\n }).catch(err => {\n // SW registration or FCM has failed :(\n onError(err);\n throw err;\n });\n } catch (err) {\n onError(err);\n return Promise.reject(err);\n }\n }\n\n // Google's FCM API is idiotic.\n static requestFCMToken(fcm, sw) {\n return firebaseGetToken(fcm, {\n serviceWorkerRegistration: sw,\n vapidKey: FIREBASE_INIT.messagingVapidKey\n }).then(token => {\n if (token) {\n return token;\n } else if (typeof Notification != 'undefined') {\n // Try to request permissions.\n return Notification.requestPermission().then(permission => {\n if (permission === 'granted') {\n return firebaseGetToken(fcm, {\n serviceWorkerRegistration: reg,\n vapidKey: FIREBASE_INIT.messagingVapidKey\n }).then(token => {\n if (token) {\n return token;\n } else {\n throw new Error(\"Failed to initialize notifications\");\n }\n });\n } else {\n throw new Error(\"No permission to send notifications: \" + permission);\n }\n });\n }\n throw new Error(\"Notifications are not supported\");\n });\n }\n\n handleResize() {\n const mobile = document.documentElement.clientWidth <= MEDIA_BREAKPOINT;\n this.setState({\n viewportWidth: document.documentElement.clientWidth,\n viewportHeight: document.documentElement.clientHeight\n });\n if (this.state.displayMobile != mobile) {\n this.setState({displayMobile: mobile});\n }\n }\n\n // Check if a newer version of TinodeWeb app is available at the server.\n checkForAppUpdate(reg) {\n reg.onupdatefound = _ => {\n const installingWorker = reg.installing;\n installingWorker.onstatechange = _ => {\n if (installingWorker.state == 'installed' && navigator.serviceWorker.controller) {\n const msg = <>\n \n \n .>;\n this.handleError(msg, 'info');\n }\n }\n }\n }\n\n // Handle for hash navigation (hashchange) event: update state.\n handleHashRoute() {\n const hash = HashNavigation.parseUrlHash(window.location.hash);\n // Start with panel parameters.\n const newState = {\n infoPanel: hash.params.info,\n newTopicTabSelected: hash.params.tab\n };\n\n if (hash.path && hash.path.length > 0) {\n // Left-side panel selector.\n if (['register','settings','edit','notif','security','support','general','crop',\n 'cred','reset','newtpk','archive','blocked','contacts',''].includes(hash.path[0])) {\n newState.sidePanelSelected = hash.path[0];\n } else {\n console.warn(\"Unknown sidepanel view\", hash.path[0]);\n }\n\n // Topic for MessagesView selector.\n let topicName = hash.path[1] || null;\n if (topicName != this.state.topicSelected) {\n if (!Tinode.topicType(topicName)) {\n // Clear invalid topic name and hide messages view on mobile.\n topicName = null;\n newState.mobilePanel = 'sidepanel';\n } else {\n // Topic valid: show messages view on mobile.\n newState.mobilePanel = 'topic-view';\n }\n Object.assign(newState, {\n topicSelected: topicName,\n topicSelectedAcs: this.tinode.getTopicAccessMode(topicName)\n });\n }\n } else {\n // Empty hashpath\n Object.assign(newState, {sidePanelSelected: '', topicSelected: null});\n }\n\n // Save credential validation parameters, if available.\n if (hash.params.method) {\n newState.credMethod = hash.params.method;\n }\n if (hash.params.code) {\n newState.credCode = hash.params.code;\n }\n if (hash.params.token) {\n newState.credToken = hash.params.token;\n }\n\n // Show a message if validation was successful.\n if (hash.params.cred_done) {\n Object.assign(newState,\n TinodeWeb.stateForError(this.props.intl.formatMessage(messages.cred_confirmed_successfully), 'info'));\n }\n\n this.setState(newState);\n }\n\n handleOnline(online) {\n if (online) {\n this.handleError();\n clearInterval(this.reconnectCountdown);\n this.tinode.reconnect();\n } else {\n this.handleError(this.props.intl.formatMessage(messages.no_connection), 'warn');\n }\n this.setState({liveConnection: online});\n }\n\n handleVisibilityEvent() {\n this.setState({applicationVisible: !document.hidden});\n }\n\n static stateForError(err, level, action, actionText) {\n return {\n errorText: err,\n errorLevel: level,\n errorAction: action,\n errorActionText: actionText,\n callShouldStart: false,\n };\n }\n\n handleError(err, level, action, actionText) {\n this.setState(TinodeWeb.stateForError(err, level, action, actionText));\n }\n\n // User clicked Login button in the side panel.\n handleLoginRequest(login, password) {\n this.setState({\n loginDisabled: true,\n login: login,\n password: password,\n loadSpinnerVisible: true,\n autoLogin: true\n });\n this.handleError('', null);\n\n if (this.tinode.isConnected()) {\n this.doLogin(login, password, null, {meth: this.state.credMethod, resp: this.state.credCode});\n } else {\n this.tinode.connect().catch(err => {\n // Socket error\n this.setState({loginDisabled: false, autoLogin: false, loadSpinnerVisible: false});\n this.handleError(err.message, 'err');\n });\n }\n\n if (this.state.desktopAlertsEnabled && !this.state.firebaseToken) {\n // Firefox and Safari: \"The Notification permission may only be requested from inside a\n // short running user-generated event handler\".\n this.initFCMessaging();\n }\n }\n\n // Enable or disable saving the password and IndexedDB.\n handlePersistenceChange(persist) {\n if (persist) {\n this.tinode.initStorage().then(_ => {\n LocalStorageUtil.setObject('keep-logged-in', true);\n this.setState({persist: true});\n });\n } else {\n this.tinode.clearStorage().then(_ => {\n LocalStorageUtil.setObject('keep-logged-in', false);\n this.setState({persist: false});\n });\n }\n }\n\n // Connection succeeded.\n handleConnected() {\n // Just to be sure.\n clearInterval(this.reconnectCountdown);\n this.handleError();\n\n const params = this.tinode.getServerInfo();\n this.setState({\n serverVersion: params.ver + ' ' + (params.build ? params.build : 'none'),\n // \"reqCred\":{\"auth\":[\"email\"]}\n reqCredMethod: ((params.reqCred || {}).auth || [])[0] || 'email'\n });\n\n if (this.state.autoLogin) {\n this.doLogin(this.state.login, this.state.password, null,\n {meth: this.state.credMethod, resp: this.state.credCode});\n }\n }\n\n // Called for each auto-reconnect iteration.\n handleAutoreconnectIteration(sec, prom) {\n clearInterval(this.reconnectCountdown);\n\n if (sec < 0) {\n // Clear error\n this.handleError();\n return;\n }\n\n if (prom) {\n // Reconnecting now\n prom.then(_ => {\n // Reconnected: clear error\n this.handleError();\n }).catch(err => {\n this.handleError(err.message, 'err');\n });\n return;\n }\n\n const {formatMessage} = this.props.intl;\n let count = sec / 1000;\n count = count | count;\n this.reconnectCountdown = setInterval(_ => {\n if (count < -10) {\n // Count could go to negative if computer woke up from sleep.\n clearInterval(this.reconnectCountdown);\n this.tinode.reconnect();\n return;\n }\n\n const fmtTime = (count > 99) ? secondsToTime(count) : count;\n this.handleError(\n formatMessage(messages.reconnect_countdown, {seconds: fmtTime}),\n 'warn',\n _ => {\n clearInterval(this.reconnectCountdown);\n this.tinode.reconnect();\n },\n formatMessage(messages.reconnect_now)\n );\n count -= 1;\n }, 1000);\n }\n\n // Connection lost\n handleDisconnect(err) {\n this.setState({\n connected: false,\n ready: false,\n topicSelectedOnline: false,\n errorText: err && err.message ? err.message : \"Disconnected\",\n errorLevel: err && err.message ? 'err' : 'warn',\n loginDisabled: false,\n contextMenuVisible: false,\n forwardDialogVisible: false,\n serverVersion: \"no connection\"\n });\n }\n\n doLogin(login, password, tmpToken, cred) {\n if (this.tinode.isAuthenticated()) {\n // Already logged in. Go to default screen.\n HashNavigation.navigateTo('');\n return;\n }\n\n let token = tmpToken || (this.tinode.getAuthToken() || {}).token;\n if (!(login && password) && !token) {\n // No login credentials provided.\n // Make sure we are on the login page.\n HashNavigation.navigateTo('');\n this.setState({loginDisabled: false});\n return;\n }\n\n // Sanitize and package credentail.\n cred = Tinode.credential(cred);\n // May be disconnected.\n let connectionPromise = this.tinode.isConnected() ? Promise.resolve() : this.tinode.connect();\n // Try to login with login/password. If they are not available, try token; if no token, ask for login/password.\n let loginPromise;\n if (login && password) {\n token = null;\n this.setState({password: null});\n loginPromise = connectionPromise.then(_ => this.tinode.loginBasic(login, password, cred));\n } else {\n loginPromise = connectionPromise.then(_ => this.tinode.loginToken(token, cred));\n }\n\n loginPromise.then(ctrl => {\n if (ctrl.code >= 300 && ctrl.text === 'validate credentials') {\n this.setState({loadSpinnerVisible: false});\n if (cred) {\n this.handleError(this.props.intl.formatMessage(messages.code_doesnot_match), 'warn');\n }\n TinodeWeb.navigateToCredentialsView(ctrl.params);\n } else {\n this.handleLoginSuccessful();\n }\n }).catch(err => {\n const autoLogin = err.code >= 500;\n // Connection or login failed, report error.\n this.setState({\n loginDisabled: false,\n credMethod: undefined,\n credCode: undefined,\n loadSpinnerVisible: false,\n autoLogin: autoLogin\n });\n this.handleError(err.message, 'err');\n console.warn(\"Login failed\", err);\n if (!autoLogin) {\n if (token) {\n this.handleLogout();\n }\n HashNavigation.navigateTo('');\n }\n });\n }\n\n static navigateToCredentialsView(params) {\n const parsed = HashNavigation.parseUrlHash(window.location.hash);\n parsed.path[0] = 'cred';\n parsed.params['method'] = params.cred[0];\n parsed.params['token'] = params.token;\n parsed.params['code'] = params.code;\n HashNavigation.navigateTo(HashNavigation.composeUrlHash(parsed.path, parsed.params));\n }\n\n handleLoginSuccessful() {\n this.handleError();\n\n // Refresh authentication token.\n if (LocalStorageUtil.getObject('keep-logged-in')) {\n LocalStorageUtil.setObject('auth-token', this.tinode.getAuthToken());\n }\n\n const goToTopic = this.state.requestedTopic;\n // Logged in fine, subscribe to 'me' attaching callbacks from the contacts view.\n const 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 credToken: undefined,\n myUserId: this.tinode.getCurrentUserID(),\n autoLogin: true,\n requestedTopic: undefined,\n });\n // Subscribe, fetch topic desc, the list of subscriptions. Messages are not fetched.\n me.subscribe(\n me.startMetaQuery().\n withLaterSub().\n withDesc().\n withTags().\n withCred().\n build()\n ).catch(err => {\n this.tinode.disconnect();\n localStorage.removeItem('auth-token');\n this.handleError(err.message, 'err');\n HashNavigation.navigateTo('');\n }).finally(_ => {\n this.setState({loadSpinnerVisible: false});\n });\n let urlHash = HashNavigation.setUrlSidePanel(window.location.hash, 'contacts');\n if (goToTopic) {\n urlHash = HashNavigation.setUrlTopic(urlHash, goToTopic);\n }\n HashNavigation.navigateTo(urlHash);\n }\n\n tnMeMetaDesc(desc) {\n if (desc) {\n if (desc.public) {\n this.setState({\n sidePanelTitle: desc.public.fn,\n sidePanelAvatar: makeImageUrl(desc.public.photo)\n });\n }\n if (desc.trusted) {\n const badges = [];\n for (const [key, val] of Object.entries(desc.trusted)) {\n if (val) {\n badges.push(key);\n }\n }\n this.setState({\n myTrustedBadges: badges,\n });\n }\n if (desc.acs) {\n this.setState({\n incognitoMode: !desc.acs.isPresencer()\n });\n }\n }\n }\n\n // Reactions to updates to the contact list.\n tnMeContactUpdate(what, cont) {\n if (what == 'on' || what == 'off') {\n this.resetContactList();\n if (this.state.topicSelected == cont.topic) {\n this.setState({topicSelectedOnline: (what == 'on')});\n }\n } else if (what == 'read') {\n this.resetContactList();\n } else if (what == 'msg' && cont) {\n // Check if the topic is archived. If so, don't play a sound.\n const topic = this.tinode.getTopic(cont.topic);\n const archived = topic && topic.isArchived();\n\n // New message received. Maybe the message is from the current user, then unread is 0.\n if (cont.unread > 0 && this.state.messageSounds && !archived) {\n // Skip update if the topic is currently open, otherwise the badge will annoyingly flash.\n if (document.hidden || this.state.topicSelected != cont.topic) {\n POP_SOUND.play().catch(_ => {\n // play() throws if the user did not click the app first: https://goo.gl/xX8pDD.\n });\n }\n }\n // Reorder contact list to use possibly updated 'touched'.\n this.resetContactList();\n } else if (what == 'recv') {\n // 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 }\n // Redraw without the deleted topic.\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({topicSelectedAcs: cont.acs});\n }\n } else if (what == 'del') {\n // TODO: messages deleted (hard or soft) -- update pill counter.\n } else if (what == 'upd' || what == 'call') {\n // upd, call - handled by the SDK. Explicitly ignoring here.\n } else {\n // TODO(gene): handle other types of notifications:\n // * ua -- user agent changes (maybe display a pictogram for mobile/desktop).\n console.info(\"Unsupported (yet) presence update:\", what, \"in\", (cont || {}).topic);\n }\n }\n\n tnMeSubsUpdated(unused) {\n this.resetContactList();\n }\n\n // Merge search results and contact list to create a single flat\n // list of known contacts for GroupManager to use.\n static prepareSearchableContacts(chatList, foundContacts) {\n const merged = {};\n\n // For chatList topics merge only p2p topics and convert them to the\n // same format as foundContacts.\n for (const c of chatList) {\n if (Tinode.isP2PTopicName(c.topic)) {\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 }\n\n // Add all foundCountacts if they have not been added already.\n for (const c of foundContacts) {\n if (!merged[c.user]) {\n merged[c.user] = c;\n }\n }\n\n return Object.values(merged);\n }\n\n resetContactList() {\n const newState = {\n chatList: []\n };\n\n if (!this.state.ready) {\n newState.ready = true;\n }\n\n this.tinode.getMeTopic().contacts(c => {\n if (!c.topic && !c.user) {\n // Contacts expect c.topic to be set.\n c.topic = c.name;\n }\n\n newState.chatList.push(c);\n if (this.state.topicSelected == c.topic) {\n newState.topicSelectedOnline = c.online;\n newState.topicSelectedAcs = c.acs;\n }\n });\n\n const past = new Date(0);\n newState.chatList.sort((a, b) => {\n return (a.touched || past).getTime() - (b.touched || past).getTime();\n });\n\n // Merge search results and chat list.\n newState.searchableContacts = TinodeWeb.prepareSearchableContacts(newState.chatList, this.state.searchResults);\n this.setState(newState);\n }\n\n /* Fnd topic: find contacts by tokens */\n tnInitFind() {\n const fnd = this.tinode.getFndTopic();\n fnd.onSubsUpdated = this.tnFndSubsUpdated;\n if (fnd.isSubscribed()) {\n this.tnFndSubsUpdated();\n } else {\n fnd.subscribe(fnd.startMetaQuery().withSub().build()).catch(err => {\n this.handleError(err.message, 'err');\n });\n }\n }\n\n tnFndSubsUpdated() {\n const foundContacts = [];\n // Don't attempt to create P2P topics which already exist. Server will reject the duplicates.\n this.tinode.getFndTopic().contacts((s) => {\n foundContacts.push(s);\n });\n this.setState({\n searchResults: foundContacts,\n searchableContacts: TinodeWeb.prepareSearchableContacts(this.state.chatList, foundContacts)\n });\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 handleSearchContacts(query) {\n const fnd = this.tinode.getFndTopic();\n fnd.setMeta({desc: {public: query}})\n .then(_ => fnd.getMeta(fnd.startMetaQuery().withSub().build()))\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n // User clicked on a topic in the side panel or deleted a topic.\n handleTopicSelected(topicName) {\n // Clear newTopicParams after use.\n if (this.state.newTopicParams && this.state.newTopicParams._topicName != topicName) {\n this.setState({\n newTopicParams: null\n });\n }\n\n if (topicName) {\n this.setState({\n errorText: '',\n errorLevel: null,\n mobilePanel: 'topic-view',\n infoPanel: undefined\n });\n // Different topic selected.\n if (this.state.topicSelected != topicName) {\n this.setState({\n topicSelectedOnline: this.tinode.isTopicOnline(topicName),\n topicSelectedAcs: this.tinode.getTopicAccessMode(topicName),\n forwardMessage: null\n });\n HashNavigation.navigateTo(HashNavigation.setUrlTopic('', topicName));\n }\n } else {\n // Currently selected contact deleted\n this.setState({\n topicSelected: null,\n errorText: '',\n errorLevel: null,\n mobilePanel: 'sidepanel',\n topicSelectedOnline: false,\n topicSelectedAcs: null,\n infoPanel: undefined,\n forwardMessage: null\n });\n\n HashNavigation.navigateTo(HashNavigation.setUrlTopic('', null));\n }\n }\n\n // In mobile view user requested to show sidepanel\n handleHideMessagesView() {\n this.setState({\n mobilePanel: 'sidepanel'\n });\n HashNavigation.navigateTo(HashNavigation.setUrlTopic(window.location.hash, null));\n }\n\n // User is sending a message, either plain text or a drafty object, possibly\n // with attachments.\n // - msg - Drafty message with content\n // - promise - Promise to be resolved when the upload is completed\n // - uploadCompletionPromise - for tracking progress\n // - head - head dictionary to be attached to the message\n handleSendMessage(msg, uploadCompletionPromise, uploader, head) {\n const topic = this.tinode.getTopic(this.state.topicSelected);\n /* TODO: check if return is required */\n return this.sendMessageToTopic(topic, msg, uploadCompletionPromise, uploader, head);\n }\n\n sendMessageToTopic(topic, msg, uploadCompletionPromise, uploader, head) {\n msg = topic.createMessage(msg, false);\n // The uploader is used to show progress.\n msg._uploader = uploader;\n\n if (head) {\n msg.head = Object.assign(msg.head || {}, head);\n }\n\n const completion = [];\n if (uploadCompletionPromise) {\n completion.push(uploadCompletionPromise);\n }\n\n if (!topic.isSubscribed()) {\n // Topic is not subscribed yet. Subscribe.\n const subscribePromise =\n topic.subscribe()\n .then(_ => {\n // If there are unsent messages (except video call messages),\n // try sending them now. Unsent video call messages will be dropped.\n let calls = [];\n topic.queuedMessages(pub => {\n if (pub._sending || pub.seq == msg.seq) {\n return;\n }\n if (pub.head && pub.head.webrtc) {\n // Filter out unsent video call messages.\n calls.push(pub.seq);\n return;\n }\n if (topic.isSubscribed()) {\n topic.publishMessage(pub);\n }\n });\n if (calls.length > 0) {\n topic.delMessagesList(calls, true);\n }\n });\n completion.push(subscribePromise);\n }\n\n // TODO: check if return is required.\n return topic.publishDraft(msg, Promise.all(completion))\n .then(ctrl => {\n if (topic.isArchived()) {\n topic.archive(false);\n }\n return ctrl;\n })\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n handleNewChatInvitation(topicName, action) {\n const topic = this.tinode.getTopic(topicName);\n let response = null;\n switch (action) {\n case 'accept':\n // Accept given permissions.\n const mode = topic.getAccessMode().getGiven();\n response = topic.setMeta({sub: {mode: mode}});\n if (topic.isP2PType()) {\n // For P2P topics change 'given' permission of the peer too.\n // In p2p topics the other user has the same name as the topic.\n response = response.then(_ => topic.setMeta({sub: {user: topicName, mode: mode}}));\n }\n break;\n case 'delete':\n // Ignore invitation by deleting it.\n response = topic.delTopic(true);\n break;\n case 'block':\n // Ban the topic making futher invites impossible.\n // Just self-ban.\n const am = topic.getAccessMode().updateWant('-JP').getWant();\n response = topic.setMeta({sub: {mode: am}}).then(_ => this.handleTopicSelected(null));\n break;\n default:\n console.warn(\"Unknown invitation action\", '\"' + action + '\"\"');\n }\n\n if (response != null) {\n response.catch(err => this.handleError(err.message, 'err'));\n }\n }\n\n // User chose a Sign Up menu item.\n handleNewAccount() {\n this.handleError();\n\n HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, 'register'));\n }\n\n // Actual registration of a new account.\n handleNewAccountRequest(login_, password_, public_, cred_, tags_) {\n // Clear old error, if any.\n this.handleError();\n\n this.tinode.connect(this.state.serverAddress)\n .then(_ => {\n let attachments;\n if (public_ && public_.photo && public_.photo.ref) {\n attachments = [public_.photo.ref];\n }\n return this.tinode.createAccountBasic(login_, password_,\n {public: public_, tags: tags_, cred: Tinode.credential(cred_), attachments: attachments});\n }).then(ctrl => {\n if (ctrl.code >= 300 && ctrl.text == 'validate credentials') {\n TinodeWeb.navigateToCredentialsView(ctrl.params);\n } else {\n this.handleLoginSuccessful(this);\n }\n }).catch(err => {\n this.handleError(err.message, 'err');\n });\n }\n\n handleToggleIncognitoMode(on) {\n // Make state undefined.\n this.setState({incognitoMode: null});\n\n const me = this.tinode.getMeTopic();\n const am = me.getAccessMode().updateWant(on ? '-P' : '+P').getWant();\n me.setMeta({sub: {mode: am}}).catch(err => {\n // Request failed, keep existing state.\n this.setState({incognitoMode: !on});\n this.handleError(err.message, 'err');\n });\n }\n\n handleUpdateAccountTagsRequest(_, tags) {\n this.tinode.getMeTopic().setMeta({tags: tags})\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n // User chose Settings menu item.\n handleSettings() {\n this.handleError();\n\n HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash,\n this.state.myUserId ? 'edit' : 'settings'));\n }\n\n // User updated global parameters.\n handleGlobalSettings(settings) {\n const serverAddress = settings.serverAddress || this.state.serverAddress;\n const transport = settings.transport || this.state.transport;\n const secureConnection = settings.secureConnection === undefined ?\n this.state.secureConnection : settings.secureConnection;\n if (this.tinode) {\n this.tinode.clearStorage();\n this.tinode.onDisconnect = undefined;\n this.tinode.disconnect();\n }\n this.tinode = TinodeWeb.tnSetup(serverAddress, secureConnection, transport,\n this.props.intl.locale, LocalStorageUtil.getObject('keep-logged-in'));\n this.tinode.onConnect = this.handleConnected;\n this.tinode.onDisconnect = this.handleDisconnect;\n this.tinode.onAutoreconnectIteration = this.handleAutoreconnectIteration;\n this.tinode.onInfoMessage = this.handleInfoMessage;\n this.tinode.onDataMessage = this.handleDataMessage;\n\n this.setState({\n serverAddress: serverAddress,\n transport: transport,\n secureConnection: secureConnection,\n });\n LocalStorageUtil.setObject('settings', {\n serverAddress: serverAddress,\n transport: transport,\n secureConnection: secureConnection,\n });\n\n HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, ''));\n }\n\n // User chose 'Archived chats'.\n handleShowArchive() {\n HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash,\n this.state.myUserId ? 'archive' : ''));\n }\n\n // User viewes 'Blocked chats'.\n handleShowBlocked() {\n HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash,\n this.state.myUserId ? 'blocked' : ''));\n }\n\n toggleFCMToken(enabled) {\n if (enabled) {\n this.setState({desktopAlerts: null});\n if (!this.state.firebaseToken) {\n this.initFCMessaging();\n } else {\n this.setState({desktopAlerts: true});\n if (LocalStorageUtil.getObject('keep-logged-in')) {\n LocalStorageUtil.updateObject('settings', {desktopAlerts: true});\n }\n }\n } else if (this.state.firebaseToken && this.fcm) {\n firebaseDelToken(this.fcm).catch(err => {\n console.error(\"Unable to delete token.\", err);\n }).finally(_ => {\n LocalStorageUtil.updateObject('settings', {desktopAlerts: false});\n localStorage.removeItem('firebase-token');\n this.setState({desktopAlerts: false, firebaseToken: null});\n // Inform the server that the token was deleted.\n this.tinode.setDeviceToken(null);\n });\n } else {\n this.setState({desktopAlerts: false, firebaseToken: null});\n LocalStorageUtil.updateObject('settings', {desktopAlerts: false});\n }\n }\n\n handleToggleMessageSounds(enabled) {\n this.setState({messageSounds: enabled});\n LocalStorageUtil.updateObject('settings', {\n messageSoundsOff: !enabled\n });\n }\n\n handleCredAdd(method, value) {\n const me = this.tinode.getMeTopic();\n me.setMeta({cred: {meth: method, val: value}})\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n handleCredDelete(method, value) {\n const me = this.tinode.getMeTopic();\n me.delCredential(method, value)\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n handleCredConfirm(method, response) {\n TinodeWeb.navigateToCredentialsView({cred: [method], code: response});\n }\n\n // User clicked Cancel button in Setting or Sign Up panel.\n handleSidepanelCancel() {\n const parsed = HashNavigation.parseUrlHash(window.location.hash);\n let path = '';\n if (['security','support','general','notif'].includes(parsed.path[0])) {\n path = 'edit';\n } else if ('crop' == parsed.path[0]) {\n path = 'general';\n } else if ('blocked' == parsed.path[0]) {\n path = 'security';\n } else if (this.state.myUserId) {\n path = 'contacts';\n }\n parsed.path[0] = path;\n if (parsed.params) {\n delete parsed.params.code;\n delete parsed.params.method;\n delete parsed.params.tab;\n delete parsed.params.scheme;\n delete parsed.params.token;\n }\n HashNavigation.navigateTo(HashNavigation.composeUrlHash(parsed.path, parsed.params));\n this.setState({errorText: '', errorLevel: null});\n }\n\n // Sidepanel navigator. No need to bind to 'this'.\n basicNavigator(hash) {\n HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, hash));\n }\n\n // Topic info navigator. No need to bind to 'this'.\n infoNavigator(hash) {\n HashNavigation.navigateTo(HashNavigation.setUrlInfoPanel(window.location.hash, hash));\n }\n\n // Request to start a topic, new or selected from search results, or \"by ID\".\n handleStartTopicRequest(topicName, newTopicParams, isChannel) {\n // Check if topic is indeed new. If not, launch it.\n if (topicName && this.tinode.isTopicCached(topicName)) {\n this.handleTopicSelected(topicName);\n return;\n }\n\n const params = {};\n if (Tinode.isP2PTopicName(topicName)) {\n // Because we are initiating the subscription, set 'want' to all permissions.\n params.sub = {mode: DEFAULT_P2P_ACCESS_MODE};\n // Give the other user all permissions too.\n params.desc = {defacs: {auth: DEFAULT_P2P_ACCESS_MODE}};\n } else {\n topicName = topicName || this.tinode.newGroupTopicName(isChannel);\n if (newTopicParams) {\n params.desc = {public: newTopicParams.public, private: {comment: newTopicParams.private}};\n params.tags = newTopicParams.tags;\n }\n }\n params._topicName = topicName;\n this.setState({newTopicParams: params}, _ => {this.handleTopicSelected(topicName)});\n }\n\n // New topic was created, here is the new topic name.\n handleNewTopicCreated(oldName, newName) {\n let nextState = {};\n if (this.state.callShouldStart) {\n nextState = {callState: CALL_STATE_IN_PROGRESS, callShouldStart: false};\n }\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 nextState.topicSelected = newName;\n }\n this.setState(nextState, _ => {\n HashNavigation.navigateTo(HashNavigation.setUrlTopic('', newName));\n });\n }\n\n handleTopicUpdateRequest(topicName, pub, priv, defacs) {\n this.handleError();\n\n const topic = this.tinode.getTopic(topicName);\n if (topic) {\n const params = {};\n let attachments;\n if (pub) {\n if (pub.photo) {\n if (pub.photo.ref && pub.photo.ref != Tinode.DEL_CHAR) {\n attachments = [pub.photo.ref];\n } else if (!pub.photo.data || pub.photo.data == Tinode.DEL_CHAR) {\n pub.photo = Tinode.DEL_CHAR;\n }\n }\n params.public = pub;\n }\n\n if (typeof priv == 'string') {\n params.private = (priv === Tinode.DEL_CHAR) ?\n Tinode.DEL_CHAR : {comment: priv};\n }\n if (defacs) {\n params.defacs = defacs;\n }\n topic.setMeta({desc: params, attachments: attachments})\n .catch(err => this.handleError(err.message, 'err'));\n }\n }\n\n handleUnarchive(topicName) {\n const topic = this.tinode.getTopic(topicName);\n if (topic) {\n topic.archive(false).catch(err => this.handleError(err.message, 'err'));\n }\n }\n\n handleUpdatePasswordRequest(password) {\n this.handleError();\n\n if (password) {\n this.tinode.updateAccountBasic(null, this.tinode.getCurrentLogin(), password)\n .catch(err => this.handleError(err.message, 'err'));\n }\n }\n\n handleChangePermissions(topicName, mode, uid) {\n const topic = this.tinode.getTopic(topicName);\n if (topic) {\n const am = topic.getAccessMode();\n if (uid) {\n am.updateGiven(mode);\n mode = am.getGiven();\n } else {\n am.updateWant(mode);\n mode = am.getWant();\n }\n topic.setMeta({sub: {user: uid, mode: mode}})\n .catch(err => this.handleError(err.message, 'err'));\n }\n }\n\n handleTagsUpdateRequest(topicName, tags) {\n const topic = this.tinode.getTopic(topicName);\n if (topic) {\n topic.setMeta({tags: tags})\n .catch(err => this.handleError(err.message, 'err'));\n }\n }\n\n handleLogout() {\n updateFavicon(0);\n\n // Remove stored data.\n localStorage.removeItem('auth-token');\n localStorage.removeItem('firebase-token');\n localStorage.removeItem('settings');\n if (this.state.firebaseToken) {\n firebaseDelToken(this.fcm);\n }\n\n clearInterval(this.reconnectCountdown);\n\n let cleared;\n if (this.tinode) {\n cleared = this.tinode.clearStorage();\n this.tinode.onDisconnect = undefined;\n this.tinode.disconnect();\n } else {\n cleared = Promose.resolve();\n }\n this.setState(this.getBlankState());\n\n cleared.then(_ => {\n this.tinode = TinodeWeb.tnSetup(this.state.serverAddress, isSecureConnection(),\n this.state.transport, this.props.intl.locale, LocalStorageUtil.getObject('keep-logged-in'), _ => {\n this.tinode.onConnect = this.handleConnected;\n this.tinode.onDisconnect = this.handleDisconnect;\n this.tinode.onAutoreconnectIteration = this.handleAutoreconnectIteration;\n this.tinode.onInfoMessage = this.handleInfoMessage;\n this.tinode.onDataMessage = this.handleDataMessage;\n HashNavigation.navigateTo('');\n })\n });\n }\n\n handleDeleteAccount() {\n this.tinode.delCurrentUser(true).then(_ => {\n this.handleLogout();\n });\n }\n\n handleDeleteTopicRequest(topicName) {\n const topic = this.tinode.getTopic(topicName);\n if (!topic) {\n return;\n }\n\n // Request to hard-delete topic.\n topic.delTopic(true).then(_ => {\n // Hide MessagesView and InfoView panels.\n HashNavigation.navigateTo(HashNavigation.setUrlTopic(window.location.hash, ''));\n }).catch(err => {\n this.handleError(err.message, 'err');\n });\n }\n\n handleDeleteMessagesRequest(topicName) {\n const topic = this.tinode.getTopic(topicName);\n if (!topic) {\n return;\n }\n\n // Request hard-delete all messages.\n topic.delMessagesAll(true)\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n handleLeaveUnsubRequest(topicName) {\n const topic = this.tinode.getTopic(topicName);\n if (!topic) {\n return;\n }\n\n topic.leave(true).then(_ => {\n // Hide MessagesView and InfoView panels.\n HashNavigation.navigateTo(HashNavigation.setUrlTopic(window.location.hash, ''));\n }).catch(err => {\n this.handleError(err.message, 'err');\n });\n }\n\n handleBlockTopicRequest(topicName) {\n const topic = this.tinode.getTopic(topicName);\n if (!topic) {\n return;\n }\n\n topic.updateMode(null, '-JP')\n .then(_ => {\n // Hide MessagesView and InfoView panels.\n HashNavigation.navigateTo(HashNavigation.setUrlTopic(window.location.hash, ''));\n })\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n handleReportTopic(topicName) {\n const topic = this.tinode.getTopic(topicName);\n if (!topic) {\n return;\n }\n\n // Publish spam report.\n this.tinode.report('report', topicName);\n\n // Remove J and P permissions.\n topic.updateMode(null, '-JP')\n .then(_ => {\n // Hide MessagesView and InfoView panels.\n HashNavigation.navigateTo(HashNavigation.setUrlTopic(window.location.hash, ''));\n })\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n handleShowContextMenu(params, menuItems) {\n this.setState({\n contextMenuVisible: true,\n contextMenuClickAt: {x: params.x, y: params.y},\n contextMenuParams: params,\n contextMenuItems: menuItems || this.defaultTopicContextMenu(params.topicName),\n contextMenuBounds: this.selfRef.current.getBoundingClientRect()\n });\n }\n\n //\n handleShowForwardDialog(params) {\n if (this.state.sidePanelSelected == 'newtpk') {\n // If the Find panel is active, close it.\n this.handleSidepanelCancel();\n }\n const header = '➦ ' + params.userName;\n const content = typeof params.content == 'string' ? Drafty.init(params.content) : Drafty.forwardedContent(params.content);\n const preview = Drafty.preview(content, FORWARDED_PREVIEW_LENGTH, true);\n const msg = Drafty.append(Drafty.appendLineBreak(Drafty.mention(header, params.userFrom)), content);\n const msgPreview = Drafty.quote(header, params.userFrom, preview);\n\n const head = {\n forwarded: params.topicName + ':' + params.seq\n };\n this.setState({\n forwardDialogVisible: true,\n forwardMessage: { head: head, msg: msg, preview: msgPreview }\n });\n }\n\n defaultTopicContextMenu(topicName) {\n const topic = this.tinode.getTopic(topicName);\n\n if (topic._deleted) {\n return [\n 'topic_delete'\n ];\n }\n\n let muted = false, blocked = false, self_blocked = false, subscribed = false, deleter = false,\n archived = false, webrtc = false, writer = false, p2p = false, self = false;\n if (topic) {\n subscribed = topic.isSubscribed();\n archived = topic.isArchived();\n\n const acs = topic.getAccessMode();\n if (acs) {\n muted = acs.isMuted();\n blocked = !acs.isJoiner();\n self_blocked = !acs.isJoiner('want');\n deleter = acs.isDeleter();\n writer = acs.isWriter();\n }\n }\n\n webrtc = writer && !!this.tinode.getServerParam('iceServers');\n p2p = Tinode.isP2PTopicName(topicName);\n self = Tinode.isSelfTopicName(topicName);\n\n return [\n subscribed ? {\n title: this.props.intl.formatMessage(messages.menu_item_info),\n handler: this.handleShowInfoView\n } : null,\n subscribed && p2p && webrtc ? {\n title: this.props.intl.formatMessage(messages.menu_item_audio_call),\n handler: this.handleStartAudioCall\n } : null,\n subscribed && p2p && webrtc ? {\n title: this.props.intl.formatMessage(messages.menu_item_video_call),\n handler: this.handleStartVideoCall\n } : null,\n subscribed ? 'messages_clear' : null,\n subscribed && deleter && !self ? 'messages_clear_hard' : null,\n self ? null : (muted ? (blocked ? null : 'topic_unmute') : 'topic_mute'),\n self ? null : (self_blocked ? 'topic_unblock' : 'topic_block'),\n archived ? 'topic_restore' : 'topic_archive',\n 'topic_delete'\n ];\n }\n\n handleHideContextMenu() {\n this.setState({\n contextMenuVisible: false,\n contextMenuClickAt: null,\n contextMenuParams: null,\n contextMenuBounds: null\n });\n }\n\n handleHideForwardDialog(keepForwardedMessage) {\n this.setState({\n forwardDialogVisible: false,\n forwardMessage: keepForwardedMessage ? this.state.forwardMessage : null\n });\n }\n\n handleContextMenuAction(action, promise, params) {\n if (action == 'topic_archive') {\n if (promise && params.topicName && params.topicName == this.state.topicSelected) {\n promise.then(_ => {\n this.handleTopicSelected(null);\n });\n }\n } else if (action == 'menu_item_forward') {\n this.handleShowForwardDialog(params);\n }\n }\n\n handleShowAlert(title, content, onConfirm, confirmText, onReject, rejectText) {\n this.setState({\n alertVisible: true,\n alertParams: {\n title: title,\n content: content,\n onConfirm: onConfirm,\n confirm: confirmText,\n onReject: onReject,\n reject: rejectText\n }\n });\n }\n\n handleShowInfoView() {\n HashNavigation.navigateTo(HashNavigation.addUrlParam(window.location.hash, 'info', 'info'));\n this.setState({infoPanel: 'info'});\n }\n\n handleMemberUpdateRequest(topicName, added, removed) {\n if (!topicName) {\n return;\n }\n\n const topic = this.tinode.getTopic(topicName);\n if (!topic) {\n return;\n }\n\n if (added && added.length > 0) {\n added.forEach(uid => {\n topic.invite(uid, null)\n .catch(err => this.handleError(err.message, 'err'));\n });\n }\n\n if (removed && removed.length > 0) {\n removed.forEach(uid => {\n topic.delSubscription(uid)\n .catch(err => this.handleError(err.message, 'err'));\n });\n }\n }\n\n handleValidateCredentialsRequest(cred, code, token) {\n if (this.tinode.isAuthenticated()) {\n // Adding new email or phone number in account setting.\n this.tinode.getMeTopic().setMeta({cred: {meth: cred, resp: code}})\n .then(_ => HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, 'contacts')))\n .catch(err => this.handleError(err.message, 'err'));\n } else {\n // Credential validation on signup.\n this.setState({credMethod: cred, credCode: code, credToken: token});\n this.doLogin(null, null, token, {meth: cred, resp: code});\n }\n }\n\n handlePasswordResetRequest(method, value) {\n // If already connected, connnect() will return a resolved promise.\n return this.tinode.connect()\n .then(_ => this.tinode.requestResetAuthSecret('basic', method, value))\n .catch(err => {\n // Socket error\n this.handleError(err.message, 'err');\n });\n }\n\n handleResetPassword(newPassword, tempAuth) {\n const secret = base64ReEncode(tempAuth.secret);\n if (!secret || !tempAuth.scheme) {\n this.handleError(this.props.intl.formatMessage(messages.invalid_security_token), 'err');\n } else {\n this.tinode.connect()\n .then(_ => this.tinode.updateAccountBasic(null, null, newPassword, {scheme: tempAuth.scheme, secret: secret}))\n .then(_ => {\n this.handleError(this.props.intl.formatMessage(messages.password_reset_success), 'info');\n HashNavigation.navigateTo('');\n })\n .catch(err => {\n this.handleError(err.message, 'err');\n });\n }\n }\n\n handleShowCountrySelector(code, dial, selectedCallback) {\n this.handleShowAlert(this.props.intl.formatMessage(messages.select_country),\n }>\n {\n this.setState({alertVisible: false});\n selectedCallback(c, d);\n }} />\n ,\n null, null, _ => {}, null);\n }\n\n handleStartVideoCall() {\n this.setState({\n callTopic: this.state.topicSelected,\n callState: CALL_STATE_OUTGOING_INITATED,\n callAudioOnly: false\n });\n }\n\n handleStartAudioCall() {\n this.setState({\n callTopic: this.state.topicSelected,\n callState: CALL_STATE_OUTGOING_INITATED,\n callAudioOnly: true\n });\n }\n\n handleCallInvite(callTopic, callSeq, callState, audioOnly) {\n switch (callState) {\n case CALL_STATE_OUTGOING_INITATED:\n const head = { webrtc: CALL_HEAD_STARTED, aonly: !!audioOnly };\n return this.handleSendMessage(Drafty.videoCall(audioOnly), undefined, undefined, head)\n .then(ctrl => {\n if (ctrl.code < 200 || ctrl.code >= 300 || !ctrl.params || !ctrl.params.seq) {\n this.handleCallClose();\n return ctrl;\n }\n this.setState({callSeq: ctrl.params['seq']});\n return ctrl\n });\n case CALL_STATE_IN_PROGRESS:\n const topic = this.tinode.getTopic(callTopic);\n if (!topic) {\n return;\n }\n // We've accepted the call. Let the other side know.\n topic.videoCall('accept', callSeq);\n break;\n }\n }\n\n handleCallRinging(callTopic, callSeq) {\n const topic = this.tinode.getTopic(callTopic);\n if (!topic) {\n return;\n }\n\n topic.videoCall('ringing', callSeq);\n }\n\n handleCallHangup(callTopic, callSeq) {\n const topic = this.tinode.getTopic(callTopic);\n if (!topic) {\n return;\n }\n\n topic.videoCall('hang-up', callSeq);\n }\n\n handleCallSendOffer(callTopic, callSeq, sdp) {\n const topic = this.tinode.getTopic(callTopic);\n if (!topic) {\n return;\n }\n\n topic.videoCall('offer', callSeq, sdp);\n }\n\n handleCallIceCandidate(callTopic, callSeq, candidate) {\n const topic = this.tinode.getTopic(callTopic);\n if (!topic) {\n return;\n }\n\n topic.videoCall('ice-candidate', callSeq, candidate);\n }\n handleCallSendAnswer(callTopic, callSeq, sdp) {\n const topic = this.tinode.getTopic(callTopic);\n if (!topic) {\n return;\n }\n\n topic.videoCall('answer', callSeq, sdp);\n }\n\n handleCallClose() {\n if (this.callTimeoutTimer) {\n clearTimeout(this.callTimeoutTimer);\n }\n this.setState({\n callTopic: undefined,\n callState: CALL_STATE_NONE,\n callAudioOnly: undefined\n });\n }\n\n handleCallAccept(topicName, setCallTopic, callSeq) {\n const topic = this.tinode.getTopic(topicName);\n if (!topic) {\n return;\n }\n if (topic.isSubscribed()) {\n this.handleTopicSelected(setCallTopic ? topicName : this.state.callTopic);\n const upd = {\n callState: CALL_STATE_IN_PROGRESS\n };\n if (setCallTopic) {\n upd.callTopic = topicName;\n upd.callSeq = callSeq;\n }\n this.setState(upd);\n } else {\n // We need to switch and subscribe to callTopic first.\n this.setState({\n callShouldStart: true,\n }, _ => this.handleTopicSelected(this.state.callTopic));\n }\n }\n\n handleInfoMessage(info) {\n if (info.what != 'call') {\n return;\n }\n switch (info.event) {\n case 'accept':\n // If another my session has accepted the call.\n if (Tinode.isMeTopicName(info.topic) && this.tinode.isMe(info.from)) {\n this.setState({\n callTopic: null,\n callState: CALL_STATE_NONE,\n callSeq: null,\n callAudioOnly: undefined\n });\n return;\n }\n if (info.topic == this.state.callTopic) {\n // Update state.\n this.setState({callState: CALL_STATE_IN_PROGRESS});\n }\n break;\n case 'hang-up':\n // Remote hangup.\n this.handleCallClose();\n break;\n }\n }\n\n handleDataMessage(data) {\n if (data.head && data.head.webrtc && data.head.webrtc == CALL_HEAD_STARTED && Tinode.isP2PTopicName(data.topic)) {\n // If it's a video call invite message.\n // See if we need to display incoming call UI.\n const topic = this.tinode.getTopic(data.topic);\n if (topic) {\n // Check if a later version of the message exists (which means the call\n // has been either accepted or finished already).\n const msg = topic.latestMsgVersion(data.seq) || data;\n if (msg.head && msg.head.webrtc && msg.head.webrtc == CALL_HEAD_STARTED) {\n // This is a legit new call.\n if (data.from != this.state.myUserId) {\n if (this.state.callState == CALL_STATE_NONE) {\n // Incoming call.\n this.setState({\n callTopic: data.topic,\n callState: CALL_STATE_INCOMING_RECEIVED,\n callSeq: data.seq,\n callAudioOnly: !!msg.head.aonly\n });\n } else {\n // Another call is either in progress or being established.\n // Reject the incoming call.\n this.handleCallHangup(data.topic, data.seq);\n }\n }\n }\n } else {\n console.warn(\"Received vc data message from unknown topic\", data.topic);\n }\n }\n }\n\n render() {\n return (\n \n {this.state.contextMenuVisible ?\n
{\n if (topicName == this.state.topicSelected) {\n this.handleTopicSelected(null);\n }\n }}\n onError={this.handleError} />\n :\n null\n }\n {this.state.forwardDialogVisible ?\n \n :\n null\n }\n {this.state.callTopic && this.state.callState == CALL_STATE_INCOMING_RECEIVED ?\n \n :\n null\n }\n {this.state.alertVisible ?\n this.setState({alertVisible: false})) : null}\n reject={this.state.alertParams.reject}\n onConfirm={this.state.alertParams.onConfirm ?\n (_ => {this.setState({alertVisible: false}); this.state.alertParams.onConfirm();}) : null}\n confirm={this.state.alertParams.confirm}\n /> : null}\n\n {!this.state.displayMobile || this.state.mobilePanel == 'sidepanel' ?\n \n : null}\n\n {!this.state.displayMobile || (this.state.mobilePanel == 'topic-view' && !this.state.infoPanel) ?\n \n : null}\n\n {this.state.infoPanel ?\n \n :\n null\n }\n \n );\n }\n};\n\nexport default injectIntl(TinodeWeb);\n","// Put all packages together.\n// Used to generate umd/index.prod.js\n\nimport React from 'react';\nimport { createRoot } from 'react-dom/client';\n\nimport { IntlProvider } from 'react-intl';\n\nimport TinodeWeb from './views/tinode-web.jsx';\nimport HashNavigation from './lib/navigation.js';\n\n// Insert google analytics script and tag if configured.\nif (typeof FIREBASE_INIT != 'undefined' && FIREBASE_INIT && FIREBASE_INIT.measurementId) {\n const head = document.getElementsByTagName('head')[0];\n let script = document.createElement('script');\n script.src = 'https://www.googletagmanager.com/gtag/js?id=' + FIREBASE_INIT.measurementId;\n script.async = true;\n head.prepend(script);\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', FIREBASE_INIT.measurementId);\n}\n\n// Allow loading translation strings for just one language.\nconst messageLoader = {\n 'ar': _ => import('./i18n.min/ar.json'),\n 'de': _ => import('./i18n.min/de.json'),\n 'en': _ => import('./i18n.min/en.json'),\n 'es': _ => import('./i18n.min/es.json'),\n 'fr': _ => import('./i18n.min/fr.json'),\n 'ko': _ => import('./i18n.min/ko.json'),\n 'ro': _ => import('./i18n.min/ro.json'),\n 'ru': _ => import('./i18n.min/ru.json'),\n 'th': _ => import('./i18n.min/th.json'),\n 'uk': _ => import('./i18n.min/uk.json'),\n 'zh': _ => import('./i18n.min/zh.json'),\n 'zh-TW': _ => import('./i18n.min/zh-TW.json')\n};\n\n// List of languages that are written right-to-left.\nconst rtl = ['ar', 'fa', 'he', 'ur'];\n\n// Detect human language to use in the UI:\n// Check parameters from URL hash #?hl=ru, then browser, then use 'en' as a fallback.\nconst { params } = HashNavigation.parseUrlHash(window.location.hash);\nconst language = (params && params.hl) ||\n (navigator.languages && navigator.languages[0]) ||\n navigator.language ||\n navigator.userLanguage ||\n 'en';\n\n// Make sure names like 'en_GB' and 'en-GB' consistently use '-'.\nconst normalized = language.replace('_', '-');\n// Get the base language 'en' from a more specific 'en-US' as a partial fallback.\nconst baseLanguage = normalized.split('-')[0].toLowerCase();\n\n// Try the full locale first, then the locale without the region code, fallback to 'en'.\nconst htmlLang = messageLoader[normalized] ? language : messageLoader[baseLanguage] ? baseLanguage : 'en';\n\nconst html = document.getElementsByTagName('html')[0];\n// Set lang attribute of the HTML element: \nhtml.setAttribute('lang', htmlLang);\nif (rtl.includes(baseLanguage)) {\n // Set right-to-left dir attribute of the HTML element: \n html.setAttribute('dir', 'rtl');\n}\n// Render the app.\nconst root = createRoot(document.getElementById('mountPoint'));\nmessageLoader[htmlLang]().then(messages =>\n root.render(\n \n \n \n));\n"],"names":["leafPrototypes","getProto","inProgress","dataWebpackPrefix","Cropper","React","constructor","props","super","this","state","panX","panY","originX","originY","zoom","minZoom","maxZoom","overlay","cutout","preview","boundingBox","imageWidth","imageHeight","mouseX","mouseY","prevDistance","cutoutRect","bBoxRect","initScaling","bind","onZoom","handleZoom","mouseDown","mouseUp","mouseMove","mouseTouch","positionAll","translate","componentDidMount","current","addEventListener","passive","getBoundingClientRect","width","height","componentWillUnmount","removeEventListener","setState","left","top","onChange","checkBound","currPan","img","delta","nextDiff","Math","min","imgRect","max","e","target","value","imgLeft","imgRight","coLeft","coRight","imgTop","imgBottom","coTop","coBottom","touches","pageX","pageY","window","document","body","style","dX","dY","right","bottom","preventDefault","length","touch0","touch1","distance","sqrt","scale","render","t3d","orig","className","ref","src","source","alt","transform","transformOrigin","onLoad","type","step","AvatarCrop","handleSubmit","handleChange","imageCrop","mime","avatar","then","onSubmit","blob","catch","err","onError","onCancel","onClick","FormattedMessage","id","defaultMessage","PACKAGE_VERSION","icon_mapping","messages","defineMessages","badge_verified","badge_staff","badge_danger","BadgeList","formatMessage","intl","badges","trustedBadges","forEach","b","comment","short","push","key","injectIntl","LoadSpinner","large","clear","centered","show","CheckBox","name","checked","iconName","classList","Array","isArray","attrs","join","module","exports","updateFavicon","count","oldIcon","getElementById","head","getElementsByTagName","newIcon","createElement","rel","href","removeChild","appendChild","title","theCard","fn","imageUrl","imageMimeType","note","card","trim","Tinode","DEL_CHAR","mimeType","matches","exec","photo","data","substring","indexOf","arrayEqual","a","sort","i","l","asPhone","val","test","replaceAll","asEmail","isUrlRelative","url","replace","sanitizeUrl","allowedSchemes","schemes","RegExp","sanitizeUrlForMime","mimeMajor","sanitizedUrl","urlAsAttachment","startsWith","query","fragment","idxF","idxQ","params","URLSearchParams","append","toString","deliveryMarker","received","MESSAGE_STATUS_SENDING","MESSAGE_STATUS_FAILED","MESSAGE_STATUS_FATAL","color","MESSAGE_STATUS_SENT","MESSAGE_STATUS_RECEIVED","MESSAGE_STATUS_READ","cancelablePromise","promise","hasCanceled","Error","Promise","reject","resolve","result","isCanceled","error","cancel","clipStr","str","tinode","BAR_COLOR_DARK","icon_title_play","AudioPlayer","base64ToIntArray","canPlay","playing","currentTime","duration","secondsToTime","longMin","initAudio","initCanvas","resampleBars","visualize","handlePlay","handleSeek","handleError","audioPlayer","viewBuffer","canvasRef","onloadedmetadata","ontimeupdate","onended","pause","componentDidUpdate","prevProps","Audio","_","offsetWidth","offsetHeight","canvasContext","getContext","lineCap","effectiveWidth","lineWidth","drawFrame","clearRect","requestAnimationFrame","thumbAt","LINE_WIDTH","beginPath","strokeStyle","x","y","stroke","moveTo","lineTo","arc","PI","fillStyle","fill","original","dstCount","apply","map","factor","amps","maxAmp","lo","hi","amp","j","readyState","play","console","rect","offset","clientX","playClass","ReactDOM","m","createRoot","hydrateRoot","SUPPORTED_IMAGE_FORMATS","MIME_EXTENSIONS","makeImageUrl","fitImageSize","maxWidth","maxHeight","forceSquare","size","dstWidth","dstHeight","srcWidth","srcHeight","xoffset","yoffset","fileNameForMime","fname","idx","ext","at","lastIndexOf","imageScaled","fileOrBlob","maxSize","Image","crossOrigin","onerror","onload","async","URL","revokeObjectURL","dim","canvas","ctx","imageSmoothingEnabled","drawImage","includes","toBlob","createObjectURL","objURL","fileToBase64","file","reader","FileReader","bits","split","readAsDataURL","blobToBase64","filePasted","event","onImageSuccess","onAttachmentSuccess","items","clipboardData","originalEvent","item","kind","getAsFile","base64ReEncode","btoa","atob","base64ToBlob","bin","buf","ArrayBuffer","arr","Uint8Array","charCodeAt","Blob","intArrayToBase64","String","fromCharCode","b64","c","VisiblePassword","inputRef","visible","handleVisibility","handeTextChange","handleKeyDown","handleEditingFinished","autoFocus","focus","keyCode","onFinished","currentTarget","setTimeout","contains","activeElement","tabIndex","onBlur","placeholder","maxLength","required","autoComplete","onKeyDown","LetterTile","isSelfTopicName","topic","SELF_AVATAR_URI","isGroup","isGroupTopicName","iconColor","idToColorClass","letter","charAt","deleted","authorizeURL","HashNavigation","parseUrlHash","hash","parts","path","arg","eq","slice","decodeURIComponent","navigateTo","location","composeUrlHash","args","hasOwnProperty","undefined","encodeURIComponent","addUrlParam","parsed","removeUrlParam","setUrlSidePanel","sidepanel","setUrlInfoPanel","infopanel","info","setUrlTopic","ReactIntl","LocalStorageUtil","setObject","localStorage","setItem","JSON","stringify","getObject","getItem","parse","updateObject","oldVal","Object","assign","removeItem","shortDateFormat","locale","navigator","userLanguage","language","now","Date","getFullYear","getMonth","getDate","toLocaleTimeString","hour12","hour","minute","toLocaleDateString","month","day","year","relativeDateFormat","diff","floor","getTime","getTimezoneOffset","abs","Intl","RelativeTimeFormat","numeric","format","DateTimeFormat","seconds","fixedMin","hours","sec","bytesToHumanSize","bytes","sizes","bucket","log2","pow","round","toFixed","shortenFileName","filename","light","fg","userId","stringToColorHash","flagEmoji","countryCode","codePoints","toUpperCase","char","fromCodePoint","APP_NAME","API_KEY","KNOWN_HOSTS","hosted","local","DEFAULT_HOST","LOGGING_ENABLED","KEYPRESS_DELAY","READ_DELAY","MIN_TAG_LENGTH","MAX_TAG_LENGTH","MAX_TAG_COUNT","DEFAULT_P2P_ACCESS_MODE","NO_ACCESS_MODE","MEDIA_BREAKPOINT","REM_SIZE","AVATAR_SIZE","MAX_AVATAR_BYTES","BROKEN_IMAGE_SIZE","NO_DIMENSIONS_VIDEO","MESSAGES_PAGE","MAX_INBAND_ATTACHMENT_SIZE","MAX_EXTERN_ATTACHMENT_SIZE","MAX_IMAGE_DIM","IMAGE_PREVIEW_DIM","VIDEO_PREVIEW_DIM","IMAGE_THUMBNAIL_DIM","VIDEO_THUMBNAIL_WIDTH","MAX_ONLINE_IN_TOPIC","MAX_TITLE_LENGTH","MAX_TOPIC_DESCRIPTION_LENGTH","MAX_PEER_TITLE_LENGTH","MESSAGE_PREVIEW_LENGTH","QUOTED_REPLY_LENGTH","FORWARDED_PREVIEW_LENGTH","EDIT_PREVIEW_LENGTH","MIN_DURATION","MAX_DURATION","LINK_CONTACT_US","LINK_PRIVACY_POLICY","LINK_TERMS_OF_SERVICE","IMMEDIATE_P2P_SUBSCRIPTION","CLICKABLE_URL_SCHEMES","QRCODE_SIZE","WAKE_UP_TIMEOUT","WAKE_UP_TICK","MIN_SWIPE_DISTANCE","TOAST_DURATION","AvatarUpload","handleFileReceived","image","files","onImageUpdated","randId","random","readOnly","uid","accept","htmlFor","uploading","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","call","n","getter","__esModule","d","getPrototypeOf","obj","__proto__","t","mode","ns","create","r","def","getOwnPropertyNames","definition","o","defineProperty","enumerable","get","f","chunkId","all","keys","reduce","promises","u","g","globalThis","Function","prop","prototype","done","script","needAttach","scripts","s","getAttribute","charset","timeout","nc","setAttribute","onScriptComplete","prev","clearTimeout","doneFns","parentNode","Symbol","toStringTag","p","installedChunks","installedChunkData","errorType","realSrc","message","request","webpackJsonpCallback","parentChunkLoadingFunction","chunkIds","moreModules","runtime","some","chunkLoadingGlobal","self","stringToByteArray$1","out","base64","byteToCharMap_","charToByteMap_","byteToCharMapWebSafe_","charToByteMapWebSafe_","ENCODED_VALS_BASE","ENCODED_VALS","ENCODED_VALS_WEBSAFE","HAS_NATIVE_SUPPORT","encodeByteArray","input","webSafe","init_","byteToCharMap","output","byte1","haveByte2","byte2","haveByte3","byte3","outByte1","outByte2","outByte3","outByte4","encodeString","decodeString","pos","c1","c2","c3","byteArrayToString","decodeStringToByteArray","charToByteMap","byte4","DecodeBase64StringError","arguments","base64urlEncodeWithoutPadding","utf8Bytes","base64Encode","base64Decode","getDefaultsFromGlobal","getGlobal","__FIREBASE_DEFAULTS__","getDefaults","process","env","defaultsJsonString","getDefaultsFromEnvVariable","match","cookie","decoded","getDefaultsFromCookie","getDefaultAppConfig","_a","config","Deferred","wrapCallback","callback","isIndexedDBAvailable","indexedDB","validateIndexedDBOpenable","preExist","DB_CHECK_NAME","open","onsuccess","close","deleteDatabase","onupgradeneeded","FirebaseError","code","customData","setPrototypeOf","captureStackTrace","ErrorFactory","service","serviceName","errors","fullCode","template","PATTERN","replaceTemplate","fullMessage","deepEqual","aKeys","bKeys","k","aProp","bProp","isObject","thing","getModularInstance","_delegate","Component","instanceFactory","multipleInstances","serviceProps","instantiationMode","onInstanceCreated","setInstantiationMode","setMultipleInstances","setServiceProps","setInstanceCreatedCallback","DEFAULT_ENTRY_NAME","Provider","container","component","instances","Map","instancesDeferred","instancesOptions","onInitCallbacks","identifier","normalizedIdentifier","normalizeInstanceIdentifier","has","deferred","set","isInitialized","shouldAutoInitialize","instance","getOrInitializeService","instanceIdentifier","getImmediate","options","optional","getComponent","setComponent","isComponentEager","instanceDeferred","entries","clearInstance","delete","services","from","values","filter","INTERNAL","_delete","isComponentSet","getOptions","initialize","opts","onInit","existingCallbacks","Set","add","existingInstance","invokeOnInitCallbacks","callbacks","providers","addComponent","provider","getProvider","addOrOverwriteComponent","getProviders","LogLevel","levelStringToEnum","DEBUG","VERBOSE","INFO","WARN","ERROR","SILENT","defaultLogLevel","ConsoleMethod","defaultLogHandler","logType","logLevel","toISOString","method","idbProxyableTypes","cursorAdvanceMethods","cursorRequestMap","WeakMap","transactionDoneMap","transactionStoreNamesMap","transformCache","reverseTransformCache","idbProxyTraps","receiver","IDBTransaction","objectStoreNames","objectStore","wrap","wrapFunction","func","IDBDatabase","transaction","IDBCursor","advance","continue","continuePrimaryKey","unwrap","storeNames","tx","transformCachableValue","unlisten","complete","DOMException","cacheDonePromiseForTransaction","object","IDBObjectStore","IDBIndex","Proxy","IDBRequest","success","promisifyRequest","newValue","openDB","version","blocked","upgrade","blocking","terminated","openPromise","oldVersion","newVersion","db","deleteDB","readMethods","writeMethods","cachedMethods","getMethod","targetFuncName","useIndex","isWrite","storeName","store","index","shift","oldTraps","PlatformLoggerServiceImpl","getPlatformInfoString","isVersionServiceProvider","library","logString","name$q","version$1","logger","_logLevel","_logHandler","_userLogHandler","TypeError","setLogLevel","logHandler","userLogHandler","debug","log","warn","name$p","name$o","name$n","name$m","name$l","name$k","name$j","name$i","name$h","name$g","name$f","name$e","name$d","name$c","name$b","name$a","name$9","name$8","name$7","name$6","name$5","name$4","name$3","name$2","name$1","PLATFORM_LOG_STRING","_apps","_serverApps","_components","_addComponent","app","_registerComponent","componentName","serverApp","heartbeatController","triggerHeartbeat","ERROR_FACTORY","FirebaseAppImpl","_isDeleted","_options","_config","_name","_automaticDataCollectionEnabled","automaticDataCollectionEnabled","_container","checkDestroyed","isDeleted","appName","initializeApp","rawConfig","existingApp","newApp","registerVersion","libraryKeyOrName","variant","libraryMismatch","versionMismatch","warning","STORE_NAME","dbPromise","getDbPromise","createObjectStore","originalErrorMessage","writeHeartbeatsToIndexedDB","heartbeatObject","put","computeKey","idbGetError","appId","HeartbeatServiceImpl","_heartbeatsCache","_storage","HeartbeatStorageImpl","_heartbeatsCachePromise","read","_b","agent","date","getUTCDateString","heartbeats","lastSentHeartbeatDate","singleDateHeartbeat","earliestHeartbeatIdx","earliestHeartbeatDate","getEarliestHeartbeatIdx","splice","overwrite","getHeartbeatsHeader","heartbeatsToSend","unsentEntries","heartbeatsCache","heartbeatEntry","find","hb","dates","countBytes","pop","extractHeartbeatsForHeader","headerString","_canUseIndexedDBPromise","runIndexedDBEnvironmentCheck","idbHeartbeatObject","readHeartbeatsFromIndexedDB","heartbeatsObject","existingHeartbeatsObject","PENDING_TIMEOUT_MS","INTERNAL_AUTH_VERSION","TOKEN_EXPIRATION_BUFFER","isServerError","getInstallationsEndpoint","projectId","extractAuthTokenInfoFromResponse","response","token","requestStatus","expiresIn","responseExpiresIn","Number","creationTime","getErrorFromResponse","requestName","errorData","json","serverCode","serverMessage","serverStatus","status","getHeaders","apiKey","Headers","Accept","getHeadersWithAuth","appConfig","refreshToken","headers","getAuthorizationHeader","retryIfServerError","sleep","ms","VALID_FID_PATTERN","generateFid","fidByteArray","crypto","msCrypto","getRandomValues","fid","b64String","array","substr","encode","getKey","fidChangeCallbacks","fidChanged","callFidChangeCallbacks","channel","getBroadcastChannel","postMessage","closeBroadcastChannel","broadcastFidChange","broadcastChannel","BroadcastChannel","onmessage","OBJECT_STORE_NAME","oldValue","remove","update","updateFn","getInstallationEntry","installations","registrationPromise","installationEntry","oldEntry","entry","registrationStatus","clearTimedOutRequest","updateOrCreateInstallationEntry","entryWithPromise","onLine","inProgressEntry","registrationTime","registeredInstallationEntry","heartbeatServiceProvider","endpoint","heartbeatService","heartbeatsHeader","authVersion","sdkVersion","fetch","ok","responseValue","authToken","createInstallationRequest","registerInstallation","waitUntilFidRegistration","triggerRegistrationIfNecessary","updateInstallationRequest","generateAuthTokenRequest","getGenerateAuthTokenEndpoint","installation","refreshAuthToken","forceRefresh","tokenPromise","isEntryRegistered","oldAuthToken","isAuthTokenExpired","isAuthTokenValid","updateAuthTokenRequest","waitUntilAuthTokenRequest","inProgressAuthToken","requestTime","makeAuthTokenRequestInProgressEntry","updatedInstallationEntry","fetchAuthTokenFromServer","getToken","installationsImpl","completeInstallationRegistration","getMissingValueError","valueName","INSTALLATIONS_NAME","internalFactory","getId","configKeys","keyName","extractAppConfig","DEFAULT_VAPID_KEY","CONSOLE_CAMPAIGN_ID","DEFAULT_REGISTRATION_TIMEOUT","MessageType$1","MessageType","arrayToBase64","uint8Array","base64ToArray","base64String","repeat","rawData","outputArray","OLD_DB_NAME","OLD_OBJECT_STORE_NAME","upgradeDb","dbGet","firebaseDependencies","tokenDetails","oldTokenDetails","senderId","dbNames","databases","upgradeTransaction","oldDetails","auth","p256dh","fcmToken","createTime","subscriptionOptions","swScope","vapidKey","checkTokenDetails","migrateOldDatabase","dbSet","requestDeleteToken","unsubscribeOptions","getEndpoint","responseData","errorInfo","getBody","web","applicationPubKey","getTokenInternal","messaging","pushSubscription","swRegistration","subscription","pushManager","getSubscription","subscribe","userVisibleOnly","applicationServerKey","getPushSubscription","scope","dbOptions","currentOptions","isVapidKeyEqual","isEndpointEqual","isAuthEqual","isP256dhEqual","isTokenValid","updatedToken","updateOptions","requestUpdateToken","updatedTokenDetails","updateToken","getNewToken","deleteTokenInternal","dbRemove","unsubscribe","subscribeOptions","requestGetToken","externalizePayload","internalPayload","payload","collapseKey","collapse_key","messageId","fcmMessageId","messagePayloadInternal","notification","icon","propagateNotificationPayload","propagateDataPayload","_c","_d","_e","fcmOptions","click_action","link","analyticsLabel","analytics_label","propagateFcmOptions","s1","s2","resultArray","_mergeStrings","MessagingService","analyticsProvider","deliveryMetricsExportedToBigQueryEnabled","onBackgroundMessageHandler","onMessageHandler","logEvents","isLogServiceStarted","messagingSenderId","registerDefaultSw","serviceWorker","register","registration","rejectTimeout","incomingSw","installing","waiting","active","onstatechange","ev","waitForRegistrationActive","browserErrorMessage","getToken$1","Notification","permission","requestPermission","updateVapidKey","ServiceWorkerRegistration","updateSwReg","serviceWorkerRegistration","logToScion","messageType","eventType","NOTIFICATION_CLICKED","PUSH_RECEIVED","getEventType","logEvent","message_id","message_name","message_time","message_device_time","messageEventListener","isFirebaseMessaging","next","dataPayload","WindowMessagingInternalFactory","isWindowSupported","cookieEnabled","PushSubscription","getMessagingInWindow","isSupported","deleteToken","deleteToken$1","onMessage","nextOrObserver","onMessage$1","Alert","content","onReject","onConfirm","confirm","clear_messages","clear_for_all","delete_for_all","send_retry","mute","unmute","reply","forward","edit","topic_delete","topic_delete_warning","delete_messages_warning","unblock","block","topic_block_warning","member_delete","archive","unarchive","edit_permissions","clear_messages_warning","pin_message","unpin_message","ContextMenu","selfRef","handlePageClick","handleEscapeKey","handleClick","MenuItems","handler","errorHandler","onShowAlert","deleteMessages","retryMessage","replyToMessage","editMessage","pinMessage","topicPermissionSetter","ctrl","onTopicRemoved","topicName","getTopic","delTopic","user","delSubscription","stopPropagation","hide","dataset","onAction","hard","cancelSend","seq","delMessagesAll","delMessagesEdits","delMessagesList","flushMessage","msg","createMessage","publishDraft","pin","updateMode","pickReply","userFrom","userName","menu","disabled","hSize","vSize","position","bounds","clickAt","ContactBadges","UnreadBadge","CallMessage","isCallDropped","callState","successClass","callIcon","incoming","CallStatus","icon2","InlineVideo","videoRef","LazyImage","isvideo","padding","whenDone","FileProgress","progress","UploadingImage","onCancelUpload","drafty_form","drafty_attachment","drafty_image","drafty_video","drafty_unknown","JSON_MIME_TYPE","JSON_MIME_TYPE_LEGACY","fullFormatter","stack","quoteFormatter","el","Drafty","tagName","attr","attrValue","loading","handleImageData","onFormButtonClick","inner","child","onQuoteClick","handleVideoData","concat","viewportWidth","minWidth","minHeight","isProcessing","onImagePreview","onVideoPreview","previewFormatter","inlineImageAttr","inlineVideoAttr","quoteImageOrVideo","isVideo","premime","preref","evt","statusText","scaled","replyFormatter","loadedPromise","self_topic_name","self_topic_comment","Contact","handleContextClick","onSelected","showContextMenu","online","icon_badges","isVerified","isStaff","isDangerous","acs","showMode","getMode","isMuted","isJoiner","isValid","previewIsResponse","marker","titleClass","showCheckmark","selected","showOnline","isChannel","unread","small","ContactAction","action","badge_you","badge_owner","ContactList","topicSelected","contactNodes","contactsCount","showSelfTopic","onTopicSelected","contacts","filterFunc","filterOn","private","toLowerCase","public","isChannelTopicName","myUserId","isOwner","forwarded","deliveryStatus","latestMessage","_status","msgStatus","showUnread","connected","trusted","verified","staff","danger","_deleted","noScroll","dangerouslySetInnerHTML","__html","emptyListMessage","SearchContacts","edited","search","handleSearchChange","handleSearch","handleClear","onSearchContacts","ForwardDialog","handleClose","handleSearchContacts","handleContactSelected","onInitFind","isNullValue","searchResults","isWriter","desription","search_placeholder","not_found_placeholder","CALL_HEAD_STARTED","RING_SOUND","CallIncoming","fullName","previousMetaDesc","resetDesc","onMetaDesc","handleRejectCall","handleAcceptCall","ringTimer","setInterval","onRinging","clearInterval","desc","onAcceptCall","onClose","MenuCancel","ErrorPanel","level","onClearError","text","whiteSpace","actionText","Chip","handleCancel","invalid","noAvatar","ChipInput","deriveStateFromProps","focused","handleTextInput","removeChipAt","handleChipCancel","handleFocusGained","handleFocusLost","chips","prompt","sortedChips","sortChips","staticMembers","chipIndex","indexChips","prevState","keep","normal","removed","onChipRemoved","onFocusLost","onEnter","avatarDisabled","onFocus","no_contacts","contacts_not_found_short","GroupManager","members","indexMembers","keepInitialMembers","requiredMember","contactFilter","noContactsMessage","selectedContacts","handleMemberRemoved","handleContactFilter","present","keepInitial","stat","sel","doContactFiltering","added","joiner","writer","preser","approver","sharer","deleter","owner","PermissionsEditor","names","skip","compare","userTitle","userAvatar","modeTitle","compareTitle","QRCode","ShowQRCode","qrCodeRef","uri","InPlaceEdit","initialValue","valid","handleStartEditing","handlePasswordFinished","validator","checkValidity","spanText","spanClass","multiline","iconLeft","iconRight","element","rows","spellCheck","TagManager","tags","alias","tagByPrefix","TAG_ALIAS","tagInput","activated","handleTagInput","handleAddTag","handleRemoveTag","getDerivedStateFromProps","nextProps","last","tag","maxTagCount","getServerParam","onTagsChanged","setUniqueTag","minTagLength","maxTagLength","add_tags_prompt","alias_invalid","alias_already_taken","TopicDescEdit","getAccessMode","isSelf","isMe","isMeTopicName","description","newAvatar","newAvatarMime","aliasError","previousOnTags","aliasCheckTimer","aliasCheckPromise","tnNewTags","handleFullNameUpdate","handleImageUpdated","handleAvatarCropped","handleAvatarCropCancel","uploadAvatar","handlePrivateUpdate","handleAliasUpdate","handleDescriptionUpdate","handleTagsUpdated","validateAlias","cancelValidator","onTagsUpdated","onUpdateTopicDesc","readyToUpload","getLargeFileHelper","upload","du","clearTagPrefix","isValidTagValue","fnd","getFndTopic","validationPromise","checkTagUniqueness","onUpdateTags","editable","full_name_placeholder","group_name_placeholder","private_placeholder","title_tag_manager","TopicCommonView","previousTagsUpdated","getType","onUpdateTagsRequest","delete_messages","leave_chat","leave_chat_warning","block_contact","block_contact_warning","report_chat","report_chat_warning","other_user","TopicSecurity","handleDeleteTopic","handleDeleteMessages","handleLeave","handleBlock","handleReport","onDeleteTopic","onDeleteMessages","onLeaveTopic","onBlockTopic","onReportTopic","groupTopic","onLaunchPermissionsEditor","access","anon","modeGiven2","general","security","crop","perm_want","perm_given","perm_auth","perm_anon","perm_user","qrcode","text_copied","InfoView","admin","muted","address","selectedContact","modeGiven","modeWant","modeWant2","contactList","previousSubsUpdated","resetSubs","resetTags","onSubsUpdated","handleImageChanged","handleMuted","handleUnarchive","handlePermissionsChanged","handleLaunchPermissionsEditor","handleShowQRCode","handleCopyToClipboard","handleShowAddMembers","handleMemberUpdateRequest","handleMemberSelected","handleContextMenu","handleBackNavigate","newState","user2","subscriber","getGiven","getWant","subscribers","sub","defacs","getDefaultAccess","isSelfType","isAdmin","isSharer","isDeleter","archived","isArchived","isGroupType","isChannelType","chan","getMeta","startMetaQuery","withTags","build","subs","onTopicDescUpdate","ignored","onChangePermissions","ignored2","onTopicUnArchive","which","perm","onTopicDescUpdateRequest","userPermissionsEdited","toEdit","toCompare","toSkip","titleEdit","titleCompare","AccessMode","userPermissionsTitle","userPermissionsAvatar","editedPermissions","immutablePermissions","editedPermissionsTitle","immutablePermissionsTitle","editedPermissionsSkipped","onNavigate","clipboard","writeText","toast","onMemberUpdateRequest","panel","menuItems","view","panelTitle","displayMobile","errorLevel","errorText","searchableContacts","reqCredMethod","onCredAdd","onTopicTagsUpdateRequest","onCredConfirm","onCredDelete","URI_TOPIC_ID_PREFIX","marginLeft","opacity","no_members","loop","CALL_ENDED_SOUND","DIALING_SOUND","VIDEO_MUTED_EVENT","VIDEO_UNMUTED_EVENT","already_in_call","CallPanel","localStream","remoteStream","pc","dataChannel","previousOnInfo","waitingForPeer","callInitialSetupComplete","audioOnly","callAudioOnly","videoToggleInProgress","remoteVideoLive","localStreamConstraints","audio","video","isOutgoingCall","localRef","remoteRef","remoteIceCandidatesCache","onInfo","start","stop","createPeerConnection","canSendOffer","drainRemoteIceCandidatesCache","handleNegotiationNeededEvent","handleICECandidateEvent","handleNewICECandidateMsg","handleICEConnectionStateChangeEvent","handleSignalingStateChangeEvent","handleICEGatheringStateChangeEvent","handleIceCandidateErrorEvent","handleTrackEvent","handleVideoOfferMsg","handleVideoAnswerMsg","reportError","handleGetUserMediaError","stopTracks","disconnectMedia","handleCloseClick","handleToggleCameraClick","handleToggleMicClick","handleRemoteHangup","handleVideoCallAccepted","muteVideo","unmuteVideo","emptyVideoTrack","handleDataChannelEvent","handleDataChannelError","handleDataChannelMessage","handleDataChannelOpen","handleDataChannelClose","stream","getTracks","track","addTrack","enabled","removeTrack","what","fillRect","captureStream","getVideoTracks","mediaDevices","getUserMedia","srcObject","onInvite","ontrack","onremovetrack","onremovestream","onicecandidate","oniceconnectionstatechange","onsignalingstatechange","onicegatheringstatechange","onnegotiationneeded","onicecandidateerror","ondatachannel","tracks","send","onopen","onclose","withDataChannel","iceServers","RTCPeerConnection","stateUpdate","createDataChannel","ordered","RTCSessionDescription","setRemoteDescription","createOffer","offer","setLocalDescription","onSendOffer","localDescription","toJSON","candidate","onIceCandidate","RTCIceCandidate","addIceCandidate","iceConnectionState","signalingState","streams","dummyVideo","createAnswer","answer","onSendAnswer","onHangup","sender","getSenders","replaceTrack","finally","getAudioTracks","forceUpdate","audioTracks","videoTracks","audioIcon","videoIcon","peerTitle","pulseAnimation","remoteActive","rstream","autoPlay","playsInline","Attachment","downloader","downloadFile","mimetype","download","loaded","helperFunc","downloadUrl","downloadWidget","message_sending","message_sending_failed","message_edited_marker","ReceivedMarker","timestamp","timeStyle","BaseChatMessage","uploader","onProgress","handleProgress","handleExpandImage","handlePlayVideo","handleFormButtonClick","handleCancelUpload","handleQuoteClick","formatterContext","onExpandMedia","resp","act","onFormResponse","userIsWriter","immutable","entities","_0","_1","tp","styles","userIsAdmin","pinned","parseInt","ratio","replyToSeq","sideClass","sequence","bubbleClass","textSizeClass","fullDisplay","attachments","getContentType","att","getDownloadUrl","getEntitySize","tree","innerRef","IntlChatMessage","_extends","AudioRecorder","messaging_disabled","type_new_message","add_image_caption","file_attachment_too_large","cannot_initiate_upload","icon_title_record_voice","icon_title_attach_file","icon_title_add_image","icon_title_send","SendMessage","quote","audioRec","audioAvailable","keypressTimestamp","handlePasteEvent","handleAttachImage","handleAttachFile","handleAttachAudio","handleSend","handleKeyPress","handleMessageTyping","handleDropAttach","formatReply","messageEditArea","getComputedStyle","getPropertyValue","scrollHeight","initMessage","scrollTop","setSelectionRange","onAttachImage","onAttachFile","onAttachAudio","acceptBlank","noInput","onSendMessage","shiftKey","onKeyPress","messagePrompt","sendIcon","editing","onCancelReply","audioEnabled","attachImage","click","attachFile","Suspense","fallback","onRecordingProgress","onDeleted","display","DocPreview","handleSendDoc","caption","mimeToIcon","default","iconFromMime","GroupSubs","usersOnline","totalCount","countToShow","overflow","ImagePreview","handleSendImage","assignWidth","node","maxlength","download_url","Invitation","handleButtonAction","LogoView","getLibrary","serverVersion","serverAddress","MetaMessage","message_not_found","message_deleted","PinnedMessages","touchX","touchY","touchSurface","getSelectedIndex","handleSelected","handleMoveNext","handleMovePrev","handleTouchEventStart","handleTouchEventEnd","handleTouchCancel","pins","isTouch","setSelected","clientY","changedTouches","messageShown","dots","cn","unrecognized_video_format","VideoPreview","handleSendVideo","videoWidth","videoHeight","controlist","controls","controlsList","disablePictureInPicture","poster","online_now","last_seen","not_found","invalid_content","editing_message","drag_file","isUnconfirmed","ex","getExcessive","isPeerRestricted","getMissing","shouldPresentCallPanel","MessagesView","componentSetup","leave","sendMessage","retrySend","sendImageAttachment","sendVideoAttachment","sendFileAttachment","sendAudioAttachment","sendKeyPress","handleScrollReference","mountDnDEvents","handleScrollEvent","handleDescChange","handleSubsUpdated","handleMessageUpdate","handleAuxUpdate","handleAllMessagesReceived","handleInfoReceipt","handleExpandMedia","handleClosePreview","handleFormResponse","handleShowMessageContextMenu","handleNewChatAcceptance","handleEnablePeer","handleAttachImageOrVideo","postReadNotification","clearNotificationQueue","goToLatestMessage","handleFileDrop","handlePickReply","handleEditMessage","handleCancelReply","handleUnpinMessage","handleCallHangup","isDragEnabled","handleDragStart","handleDragIn","handleDragOut","handleDrag","handleDrop","chatMessageRefs","getOrCreateMessageRef","getVisibleMessageRange","dragCounter","dndRef","readNotificationQueue","readNotificationTimer","keyPressTimer","seqId","holderRect","MAX_SAFE_INTEGER","visibilityStatus","every","messagesScroller","maxSeqId","minSeqId","scrollPosition","applicationVisible","isNewGroupTopicName","rtcPanel","callSeq","onData","onAllMessagesReceived","onPres","onAuxUpdated","newTopic","newTopicParams","_topicName","isP2PType","withDesc","isSubscribed","isReader","withLaterData","nextState","docPreview","imagePreview","imagePostview","videoPreview","videoPostview","typingIndicator","fetchingMessages","showGoToLastButton","contentToEdit","dragging","selectedPin","forwardMessage","onlineSubs","peer","p2pPeerDesc","peerMessagingDisabled","minMsgSeq","maxMsgSeq","latestClearId","maxClearId","aux","pinsLoaded","callTopic","subsVersion","readingBlocked","unconformed","unconfirmed","ready","getQuery","withLaterDesc","withLaterSub","withAux","withLaterDel","setQuery","onNewTopicCreated","discard","queuedMessages","pub","_sending","_fatal","webrtc","blankState","oldTopicName","isTopicCached","oldTopic","processingScrollEvent","gaps","msgHasMoreMessages","getMessagesPage","dnd","sendAt","isServerAssignedSeq","noteRead","setMilliseconds","getMilliseconds","isNewMessage","getPinnedMessages","attachJSON","searchParams","messageSpecificMenuItems","canDelete","maxDelAge","MSG_DELETE_AGE","onNewChat","noteRecording","noteKeyPress","uploadCompletionPromise","sanitizeEntities","maxInbandAttachmentSize","urlPromise","maxExternAttachmentSize","limit","onVideoCallClosed","onCallHangup","insertImage","_tempPreview","appendLineBreak","videoBlob","previewBlob","uploads","b64s","v64","i64","insertVideo","b64conv","appendAudio","found","findMessage","_cancelled","senderName","init","replyContent","wrapInto","onCancelForwardMessage","toMarkdown","scrollIntoView","behavior","dataTransfer","clearData","component2","onCallInvite","onCallSendOffer","onCallIceCandidate","onCallSendAnswer","pinnedMessages","latestMsgVersion","messageNodes","previousFrom","prevDate","chatBoxClass","nextFrom","thisFrom","isReply","userDesc","isNaN","thisDate","ts","toDateString","ChatMessage","isChan","_uploader","lastSeen","cont","getMeTopic","getContact","isP2PTopicName","seen","when","messagesComponent","onHideMessagesView","ButtonBack","onBack","MenuContacts","onNewTopic","onSettings","MenuStart","onSignUp","SideNavbar","archived_contacts_title","ContactsView","handleAction","unreadThreads","archivedCount","chatList","arch","touched","action_ignored","onShowArchive","EditAccountView","handleCheckboxClick","onToggleMessageSounds","onTogglePushNotifications","onToggleIncognitoMode","messageSounds","desktopAlertsEnabled","desktopAlerts","incognitoMode","delete_account","delete_account_warning","AccSecurityView","me","blockedCount","showPermissionEditorFor","handlePasswordUpdate","handleHidePermissionsEditor","handleDeleteAccount","pwd","password","onUpdatePassword","onUpdateAccountDesc","onDeleteAccount","password_unchanged","onLogout","onShowBlocked","AccSupportView","LoginView","login","hostName","saveToken","persist","handleLoginChange","handlePasswordChange","handleToggleSaveToken","onPersistenceChange","onLogin","submitClasses","login_prompt","autoCorrect","autoCapitalize","password_prompt","invalid_id","NewTopicById","groupId","myURI","prefix","NewTopicGroup","handleFieldEdit","handleTagsChanged","handleChannelToggle","search_for_contacts","search_no_results","NewTopicView","tabSelected","searchQuery","handleTabClick","handleSearchResultSelected","handleNewGroupSubmit","handleGroupByID","email","TAG_EMAIL","tel","TAG_PHONE","onCreateTopic","dataUrl","priv","no_contacts_placeholder","getCurrentUserID","HostSelector","changed","handleHostNameChange","onServerAddressChange","hostOptions","list","SettingsView","transport","secureConnection","handleTransportSelected","handleServerAddressChange","handleToggleSecure","onUpdate","ws","lp","transportOptions","phone","ValidationView","credCode","codeReceived","handleCodeChange","credMethod","credToken","numbers_only","AccountSettingsView","CreateAccountView","PasswordResetView","settings","notif","support","newtpk","cred","reset","SidepanelView","handleNewTopic","errorAction","errorActionText","loadSpinnerVisible","loginDisabled","onLoginRequest","onShowCountrySelector","onCreateAccount","onGlobalSettings","onUpdateAccountTags","AccNotificationsView","onValidateCredentials","onRequest","onPasswordResetRequest","onReset","onResetPassword","detectServerAddress","host","protocol","hostname","port","isSecureConnection","PhoneCountrySelector","POP_SOUND","reconnect_countdown","reconnect_now","push_init_failed","invalid_security_token","no_connection","code_doesnot_match","menu_item_info","menu_item_audio_call","menu_item_video_call","cred_confirmed_successfully","password_reset_success","select_country","TinodeWeb","getBlankState","handleResize","handleHashRoute","handleOnline","checkForAppUpdate","handleVisibilityEvent","handleLoginRequest","handlePersistenceChange","handleConnected","handleAutoreconnectIteration","doLogin","handleLoginSuccessful","handleDisconnect","tnMeMetaDesc","tnMeContactUpdate","tnMeSubsUpdated","resetContactList","tnInitFind","tnFndSubsUpdated","handleTopicSelected","handleHideMessagesView","handleSendMessage","handleNewChatInvitation","handleNewAccount","handleNewAccountRequest","handleUpdatePasswordRequest","handleUpdateAccountTagsRequest","handleToggleIncognitoMode","handleSettings","handleGlobalSettings","handleShowArchive","handleShowBlocked","handleToggleMessageSounds","handleCredAdd","handleCredDelete","handleCredConfirm","initFCMessaging","toggleFCMToken","handlePushMessage","handleSidepanelCancel","handleStartTopicRequest","handleNewTopicCreated","handleTopicUpdateRequest","handleChangePermissions","handleTagsUpdateRequest","handleLogout","handleDeleteTopicRequest","handleDeleteMessagesRequest","handleLeaveUnsubRequest","handleBlockTopicRequest","handleReportTopic","handleShowContextMenu","defaultTopicContextMenu","handleHideContextMenu","handleShowAlert","handleShowInfoView","handleValidateCredentialsRequest","handlePasswordResetRequest","handleResetPassword","handleContextMenuAction","handleShowCountrySelector","handleShowForwardDialog","handleHideForwardDialog","handleStartVideoCall","handleStartAudioCall","handleInfoMessage","handleDataMessage","handleCallClose","handleCallInvite","handleCallRinging","handleCallSendOffer","handleCallIceCandidate","handleCallSendAnswer","handleCallAccept","sendMessageToTopic","callTimeoutTimer","autoLogin","messageSoundsOff","firebaseInitApp","FIREBASE_INIT","firebaseToken","hidden","sidePanelSelected","sidePanelTitle","sidePanelAvatar","myTrustedBadges","liveConnection","topicSelectedOnline","topicSelectedAcs","innerWidth","infoPanel","mobilePanel","callShouldStart","contextMenuVisible","contextMenuBounds","contextMenuClickAt","contextMenuParams","contextMenuItems","forwardDialogVisible","alertVisible","alertParams","requestedTopic","handleOnlineOn","handleOnlineOff","lastWakeUpCheck","wakeUpTicker","documentElement","clientWidth","viewportHeight","clientHeight","tnSetup","onConnect","onDisconnect","onAutoreconnectIteration","onInfoMessage","onDataMessage","expires","setAuthToken","connect","parsedNav","cred_done","persistentCache","onSetupCompleted","secure","setHumanLanguage","enableLogging","oobNotification","fcm","firebaseGetMessaging","getRegistration","reg","requestFCMToken","setDeviceToken","firebaseOnMessage","sw","firebaseGetToken","messagingVapidKey","mobile","onupdatefound","installingWorker","controller","newTopicTabSelected","tab","topicType","getTopicAccessMode","stateForError","reconnectCountdown","reconnect","isConnected","meth","initStorage","clearStorage","getServerInfo","ver","reqCred","prom","fmtTime","tmpToken","isAuthenticated","getAuthToken","credential","loginPromise","connectionPromise","loginBasic","loginToken","navigateToCredentialsView","goToTopic","onContactUpdate","withCred","disconnect","urlHash","isPresencer","unused","prepareSearchableContacts","foundContacts","merged","updated","past","withSub","setMeta","isTopicOnline","completion","subscribePromise","calls","publishMessage","am","updateWant","login_","password_","public_","cred_","tags_","createAccountBasic","on","firebaseDelToken","delCredential","scheme","basicNavigator","infoNavigator","newGroupTopicName","oldName","newName","updateAccountBasic","getCurrentLogin","updateGiven","cleared","Promose","delCurrentUser","report","header","forwardedContent","mention","msgPreview","self_blocked","subscribed","p2p","keepForwardedMessage","confirmText","rejectText","invite","requestResetAuthSecret","newPassword","tempAuth","secret","dial","selectedCallback","aonly","videoCall","sdp","setCallTopic","upd","myUserName","onAddMember","handleManageGroupMembers","measurementId","gtag","dataLayer","prepend","messageLoader","hl","languages","normalized","baseLanguage","htmlLang","html","root","IntlProvider","textComponent"],"sourceRoot":""}
\ No newline at end of file
+{"version":3,"file":"index.prod.js","mappings":"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","sources":["webpack://tinode-webapp/webpack/runtime/create fake namespace object","webpack://tinode-webapp/webpack/runtime/load script","webpack://tinode-webapp/./src/widgets/cropper.jsx","webpack://tinode-webapp/./src/widgets/avatar-crop.jsx","webpack://tinode-webapp/./src/version.js","webpack://tinode-webapp/./src/widgets/badge-list.jsx","webpack://tinode-webapp/./src/widgets/load-spinner.jsx","webpack://tinode-webapp/./src/widgets/checkbox.jsx","webpack://tinode-webapp/external var \"React\"","webpack://tinode-webapp/./src/lib/utils.js","webpack://tinode-webapp/external var \"tinode\"","webpack://tinode-webapp/./src/widgets/audio-player.jsx","webpack://tinode-webapp/external var \"ReactDOM\"","webpack://tinode-webapp/./node_modules/react-dom/client.js","webpack://tinode-webapp/./src/lib/blob-helpers.js","webpack://tinode-webapp/./src/widgets/visible-password.jsx","webpack://tinode-webapp/./src/widgets/letter-tile.jsx","webpack://tinode-webapp/./src/lib/navigation.js","webpack://tinode-webapp/external var \"ReactIntl\"","webpack://tinode-webapp/./src/lib/local-storage.js","webpack://tinode-webapp/./src/lib/strformat.js","webpack://tinode-webapp/./src/config.js","webpack://tinode-webapp/./src/widgets/avatar-upload.jsx","webpack://tinode-webapp/webpack/bootstrap","webpack://tinode-webapp/webpack/runtime/compat get default export","webpack://tinode-webapp/webpack/runtime/define property getters","webpack://tinode-webapp/webpack/runtime/ensure chunk","webpack://tinode-webapp/webpack/runtime/get javascript chunk filename","webpack://tinode-webapp/webpack/runtime/global","webpack://tinode-webapp/webpack/runtime/hasOwnProperty shorthand","webpack://tinode-webapp/webpack/runtime/make namespace object","webpack://tinode-webapp/webpack/runtime/publicPath","webpack://tinode-webapp/webpack/runtime/jsonp chunk loading","webpack://tinode-webapp/./node_modules/@firebase/util/dist/postinstall.mjs","webpack://tinode-webapp/./node_modules/@firebase/util/dist/index.esm2017.js","webpack://tinode-webapp/./node_modules/@firebase/component/dist/esm/index.esm2017.js","webpack://tinode-webapp/./node_modules/@firebase/logger/dist/esm/index.esm2017.js","webpack://tinode-webapp/./node_modules/idb/build/wrap-idb-value.js","webpack://tinode-webapp/./node_modules/idb/build/index.js","webpack://tinode-webapp/./node_modules/@firebase/app/dist/esm/index.esm2017.js","webpack://tinode-webapp/./node_modules/firebase/app/dist/esm/index.esm.js","webpack://tinode-webapp/./node_modules/@firebase/installations/dist/esm/index.esm2017.js","webpack://tinode-webapp/./node_modules/@firebase/messaging/dist/esm/index.esm2017.js","webpack://tinode-webapp/./src/widgets/alert.jsx","webpack://tinode-webapp/./src/widgets/context-menu.jsx","webpack://tinode-webapp/./src/widgets/contact-badges.jsx","webpack://tinode-webapp/./src/widgets/unread-badge.jsx","webpack://tinode-webapp/./src/widgets/call-message.jsx","webpack://tinode-webapp/./src/widgets/call-status.jsx","webpack://tinode-webapp/./src/widgets/inline-video.jsx","webpack://tinode-webapp/./src/widgets/lazy-image.jsx","webpack://tinode-webapp/./src/widgets/file-progress.jsx","webpack://tinode-webapp/./src/widgets/uploading-image.jsx","webpack://tinode-webapp/./src/lib/formatters.js","webpack://tinode-webapp/./src/widgets/contact.jsx","webpack://tinode-webapp/./src/widgets/contact-action.jsx","webpack://tinode-webapp/./src/widgets/contact-list.jsx","webpack://tinode-webapp/./src/widgets/search-contacts.jsx","webpack://tinode-webapp/./src/widgets/forward-dialog.jsx","webpack://tinode-webapp/./src/constants.js","webpack://tinode-webapp/./src/widgets/call-incoming.jsx","webpack://tinode-webapp/./src/widgets/menu-cancel.jsx","webpack://tinode-webapp/./src/widgets/error-panel.jsx","webpack://tinode-webapp/./src/widgets/chip.jsx","webpack://tinode-webapp/./src/widgets/chip-input.jsx","webpack://tinode-webapp/./src/widgets/group-manager.jsx","webpack://tinode-webapp/./src/widgets/permissions-editor.jsx","webpack://tinode-webapp/external var \"QRCode\"","webpack://tinode-webapp/./src/widgets/show-qrcode.jsx","webpack://tinode-webapp/./src/widgets/in-place-edit.jsx","webpack://tinode-webapp/./src/widgets/tag-manager.jsx","webpack://tinode-webapp/./src/widgets/topic-desc-edit.jsx","webpack://tinode-webapp/./src/views/topic-common-view.jsx","webpack://tinode-webapp/./src/widgets/topic-security.jsx","webpack://tinode-webapp/./src/views/info-view.jsx","webpack://tinode-webapp/./src/widgets/call-panel.jsx","webpack://tinode-webapp/./src/widgets/attachment.jsx","webpack://tinode-webapp/./src/widgets/received-marker.jsx","webpack://tinode-webapp/./src/widgets/chat-message.jsx","webpack://tinode-webapp/./src/widgets/send-message.jsx","webpack://tinode-webapp/./src/widgets/doc-preview.jsx","webpack://tinode-webapp/./src/widgets/group-subs.jsx","webpack://tinode-webapp/./src/widgets/image-preview.jsx","webpack://tinode-webapp/./src/widgets/invitation.jsx","webpack://tinode-webapp/./src/views/logo-view.jsx","webpack://tinode-webapp/./src/widgets/meta-message.jsx","webpack://tinode-webapp/./src/widgets/pinned-messages.jsx","webpack://tinode-webapp/./src/widgets/video-preview.jsx","webpack://tinode-webapp/./src/views/messages-view.jsx","webpack://tinode-webapp/./src/widgets/button-back.jsx","webpack://tinode-webapp/./src/widgets/menu-contacts.jsx","webpack://tinode-webapp/./src/widgets/menu-start.jsx","webpack://tinode-webapp/./src/widgets/side-navbar.jsx","webpack://tinode-webapp/./src/views/contacts-view.jsx","webpack://tinode-webapp/./src/views/acc-notifications-view.jsx","webpack://tinode-webapp/./src/views/acc-security-view.jsx","webpack://tinode-webapp/./src/views/acc-support-view.jsx","webpack://tinode-webapp/./src/views/login-view.jsx","webpack://tinode-webapp/./src/widgets/new-topic-by-id.jsx","webpack://tinode-webapp/./src/widgets/new-topic-group.jsx","webpack://tinode-webapp/./src/views/new-topic-view.jsx","webpack://tinode-webapp/./src/widgets/host-selector.jsx","webpack://tinode-webapp/./src/views/settings-view.jsx","webpack://tinode-webapp/./src/views/validation-view.jsx","webpack://tinode-webapp/./src/views/sidepanel-view.jsx","webpack://tinode-webapp/./src/lib/host-name.js","webpack://tinode-webapp/./src/views/tinode-web.jsx","webpack://tinode-webapp/./src/index.js"],"sourcesContent":["var getProto = Object.getPrototypeOf ? function(obj) { return Object.getPrototypeOf(obj); } : function(obj) { return obj.__proto__; };\nvar leafPrototypes;\n// create a fake namespace object\n// mode & 1: value is a module id, require it\n// mode & 2: merge all properties of value into the ns\n// mode & 4: return value when already ns object\n// mode & 16: return value when it's Promise-like\n// mode & 8|1: behave like require\n__webpack_require__.t = function(value, mode) {\n\tif(mode & 1) value = this(value);\n\tif(mode & 8) return value;\n\tif(typeof value === 'object' && value) {\n\t\tif((mode & 4) && value.__esModule) return value;\n\t\tif((mode & 16) && typeof value.then === 'function') return value;\n\t}\n\tvar ns = Object.create(null);\n\t__webpack_require__.r(ns);\n\tvar def = {};\n\tleafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)];\n\tfor(var current = mode & 2 && value; (typeof current == 'object' || typeof current == 'function') && !~leafPrototypes.indexOf(current); current = getProto(current)) {\n\t\tObject.getOwnPropertyNames(current).forEach(function(key) { def[key] = function() { return value[key]; }; });\n\t}\n\tdef['default'] = function() { return value; };\n\t__webpack_require__.d(ns, def);\n\treturn ns;\n};","var inProgress = {};\nvar dataWebpackPrefix = \"tinode-webapp:\";\n// loadScript function to load a script via script tag\n__webpack_require__.l = function(url, done, key, chunkId) {\n\tif(inProgress[url]) { inProgress[url].push(done); return; }\n\tvar script, needAttach;\n\tif(key !== undefined) {\n\t\tvar scripts = document.getElementsByTagName(\"script\");\n\t\tfor(var i = 0; i < scripts.length; i++) {\n\t\t\tvar s = scripts[i];\n\t\t\tif(s.getAttribute(\"src\") == url || s.getAttribute(\"data-webpack\") == dataWebpackPrefix + key) { script = s; break; }\n\t\t}\n\t}\n\tif(!script) {\n\t\tneedAttach = true;\n\t\tscript = document.createElement('script');\n\n\t\tscript.charset = 'utf-8';\n\t\tscript.timeout = 120;\n\t\tif (__webpack_require__.nc) {\n\t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n\t\t}\n\t\tscript.setAttribute(\"data-webpack\", dataWebpackPrefix + key);\n\n\t\tscript.src = url;\n\t}\n\tinProgress[url] = [done];\n\tvar onScriptComplete = function(prev, event) {\n\t\t// avoid mem leaks in IE.\n\t\tscript.onerror = script.onload = null;\n\t\tclearTimeout(timeout);\n\t\tvar doneFns = inProgress[url];\n\t\tdelete inProgress[url];\n\t\tscript.parentNode && script.parentNode.removeChild(script);\n\t\tdoneFns && doneFns.forEach(function(fn) { return fn(event); });\n\t\tif(prev) return prev(event);\n\t}\n\tvar timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);\n\tscript.onerror = onScriptComplete.bind(null, script.onerror);\n\tscript.onload = onScriptComplete.bind(null, script.onload);\n\tneedAttach && document.head.appendChild(script);\n};","// Image zoom and crop widget.\n\nimport React from 'react';\n\nconst DEFAULT_MAX_ZOOM = 2.5;\n\nexport default class Cropper extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n // Coordinates of the top left corner of the image in container coordinates.\n panX: 0,\n panY: 0,\n // Origin of the zoom in image coordinates.\n originX: 0,\n originY: 0,\n // Zoom scale.\n zoom: 1,\n // Zoom min and max.\n minZoom: 0,\n maxZoom: DEFAULT_MAX_ZOOM,\n };\n\n // References to DOM elements for hooking up events and getting screen dimensions.\n // The transparent element which captures mouse moves (moves with the image).\n this.overlay = React.createRef();\n // The image cutout window or view port (static).\n this.cutout = React.createRef();\n // Scaled and translated image preview.\n this.preview = React.createRef();\n // The main container (static).\n this.boundingBox = React.createRef();\n\n // The original image width and height before any scaling.\n this.imageWidth = 0;\n this.imageHeight = 0;\n\n // Mouse position when dragging.\n this.mouseX = 0\n this.mouseY = 0;\n // Length of the previous mouse move when dragging.\n this.prevDistance = 0;\n\n // Bounding rectangles of static elements.\n this.cutoutRect = {};\n this.bBoxRect = {};\n // Center of the bounding box.\n this.originX = 0;\n this.originY = 0;\n\n this.initScaling = this.initScaling.bind(this);\n this.onZoom = this.onZoom.bind(this);\n this.handleZoom = this.handleZoom.bind(this);\n this.mouseDown = this.mouseDown.bind(this);\n this.mouseUp = this.mouseUp.bind(this);\n this.mouseMove = this.mouseMove.bind(this);\n this.mouseTouch = this.mouseTouch.bind(this);\n this.positionAll = this.positionAll.bind(this);\n this.translate = this.translate.bind(this);\n }\n\n componentDidMount() {\n this.overlay.current.addEventListener('mousedown', this.mouseDown, { passive: true });\n this.overlay.current.addEventListener('touchstart', this.mouseDown, { passive: true });\n\n // The rectangle position is in viewport coordinates.\n this.bBoxRect = this.boundingBox.current.getBoundingClientRect();\n // Center of the bounding box in container coordinates.\n this.originX = this.bBoxRect.width / 2;\n this.originY = this.bBoxRect.height / 2;\n\n // The rectangle position is in viewport coordinates.\n this.cutoutRect = this.cutout.current.getBoundingClientRect();\n }\n\n componentWillUnmount() {\n if (this.overlay.current) {\n this.overlay.current.removeEventListener('mousedown', this.mouseDown);\n this.overlay.current.removeEventListener('touchstart', this.mouseDown);\n }\n }\n\n // Position all elements.\n positionAll(panX, panY, zoom) {\n // Zoom origin in image preview coordinates.\n this.setState({\n panX: panX,\n panY: panY,\n zoom: zoom,\n originX: this.originX - panX,\n originY: this.originY - panY,\n });\n\n // Pass cut out coordinates to caller.\n const left = (this.originX - panX) * zoom - this.originX;\n const top = (this.originY - panY) * zoom - this.originY;\n this.props.onChange(\n (left + this.cutoutRect.left - this.bBoxRect.left) / zoom,\n (top + this.cutoutRect.top - this.bBoxRect.top) / zoom,\n this.cutoutRect.width / zoom,\n this.cutoutRect.height / zoom,\n zoom);\n }\n\n // Check if new location is within the limits.\n static checkBound(currPan, img, cutout, delta) {\n let nextDiff = Math.min(0, cutout[0] - img[0] - delta, img[1] - cutout[1] + delta);\n if (nextDiff == 0) {\n // Cutout is completely within the image.\n currPan += delta;\n } else if (Math.min(0, cutout[0] - img[0], img[1] - cutout[1]) < nextDiff) {\n // Cutout is outside of the range but closer to the bound.\n currPan += delta;\n }\n return currPan;\n }\n\n initScaling() {\n // Initialize components.\n const imgRect = this.preview.current.getBoundingClientRect();\n\n this.imageWidth = imgRect.width;\n this.imageHeight = imgRect.height;\n\n // Set zoom slider's min and max values. Make sure the scaled image cannot be smaller than the cutout.\n const minZoom = Math.max(this.cutoutRect.width / imgRect.width, this.cutoutRect.height / imgRect.height);\n this.setState({\n minZoom: minZoom,\n maxZoom: Math.max(DEFAULT_MAX_ZOOM, minZoom + 1)\n });\n\n // Initial zoom level fills the bounding box at the smallest image dimension and overflows the largest, i.e. \"fill\" not \"fit\".\n const zoom = Math.max(this.bBoxRect.width / imgRect.width, this.bBoxRect.height / imgRect.height);\n // Converting from viewport coordinates to container, then panning.\n const panX = this.cutoutRect.left - this.bBoxRect.left -\n (imgRect.width - this.cutoutRect.width) / 2;\n const panY = this.cutoutRect.top - this.bBoxRect.top -\n (imgRect.height - this.cutoutRect.height) / 2;\n\n this.positionAll(panX, panY, zoom);\n }\n\n onZoom(e) {\n this.handleZoom(e.target.value);\n }\n\n handleZoom(zoom) {\n let panX = this.state.panX;\n let panY = this.state.panY;\n\n // Ensure that the image at the new zoom is not outside of the cutout boundaries.\n // Calculate image coordinates at the new zoom.\n const imgLeft = this.originX - (this.originX - panX) * zoom;\n const imgRight = imgLeft + this.imageWidth * zoom;\n // Cutout in the same coordinates as the image.\n const coLeft = this.cutoutRect.left - this.bBoxRect.left;\n const coRight = coLeft + this.cutoutRect.width;\n if (coLeft < imgLeft) {\n panX -= imgLeft - coLeft;\n } else if (coRight > imgRight) {\n panX += coRight - imgRight;\n }\n const imgTop = this.originY - (this.originY - panY) * zoom;\n const imgBottom = imgTop + this.imageHeight * zoom;\n const coTop = this.cutoutRect.top - this.bBoxRect.top;\n const coBottom = coTop + this.cutoutRect.height;\n if (coTop < imgTop) {\n panY -= imgTop - coTop;\n } else if (coBottom > imgBottom) {\n panY += coBottom - imgBottom;\n }\n\n this.positionAll(panX, panY, zoom);\n }\n\n mouseDown(e) {\n if (e.touches) {\n this.mouseX = e.touches[0].pageX;\n this.mouseY = e.touches[0].pageY;\n } else {\n this.mouseX = e.pageX;\n this.mouseY = e.pageY;\n }\n\n window.addEventListener('mousemove', this.mouseMove, { passive: false });\n window.addEventListener('touchmove', this.mouseTouch, { passive: false });\n window.addEventListener('mouseup', this.mouseUp, { passive: true });\n window.addEventListener('touchend', this.mouseUp, { passive: true });\n // Disable text selection in the entire document.\n document.body.style['userSelect'] = 'none';\n }\n\n // Perform image panning.\n translate(pageX, pageY) {\n const dX = pageX - this.mouseX;\n const dY = pageY - this.mouseY;\n\n this.mouseX = pageX;\n this.mouseY = pageY;\n\n // Make sure the image is within the cutout window.\n const imgRect = this.preview.current.getBoundingClientRect();\n\n // Check if the new position is within the boundaries, and if not if it's closer to them.\n let panX = Cropper.checkBound(this.state.panX, [imgRect.left, imgRect.right],\n [this.cutoutRect.left, this.cutoutRect.right], dX);\n let panY = Cropper.checkBound(this.state.panY, [imgRect.top, imgRect.bottom],\n [this.cutoutRect.top, this.cutoutRect.bottom], dY);\n\n this.positionAll(panX, panY, this.state.zoom);\n }\n\n // Image panning.\n mouseMove(e) {\n e.preventDefault();\n this.translate(e.pageX, e.pageY);\n }\n\n mouseTouch(e) {\n e.preventDefault();\n\n if (e.touches.length == 1) {\n this.translate(e.touches[0].pageX, e.touches[0].pageY);\n return;\n }\n\n // Image zooming by pinching.\n const [touch0, touch1] = e.touches;\n const distance = Math.sqrt((touch0.pageX - touch1.pageX) * (touch0.pageX - touch1.pageX) +\n (touch0.pageY - touch1.pageY) * (touch0.pageY - touch1.pageY));\n\n if (!this.prevDistance) {\n this.prevDistance = distance / this.state.zoom;\n }\n\n let scale = (distance / this.prevDistance);\n this.handleZoom(Math.max(this.minZoom, Math.min(this.maxZoom, scale)));\n }\n\n mouseUp(e) {\n window.removeEventListener('mousemove', this.mouseMove);\n window.removeEventListener('touchmove', this.mouseTouch);\n window.removeEventListener('mouseup', this.mouseUp);\n window.removeEventListener('touchend', this.mouseUp);\n // Re-enable text selection.\n document.body.style['userSelect'] = '';\n\n this.positionAll(this.state.panX, this.state.panY, this.state.zoom);\n }\n\n render() {\n // transform3d: position and scale.\n const t3d = `translate3d(${this.state.panX}px, ${this.state.panY}px, 0) scale(${this.state.zoom})`;\n // transformOrigin: zoom origin.\n const orig = `${this.state.originX}px ${this.state.originY}px`;\n\n // Overlay position and size are exactly equal to the position and size of the transformed image\n // except it uses different coordinates.\n const overlay = {\n top: `${this.originY - this.state.originY * this.state.zoom}px`,\n left: `${this.originX - this.state.originX * this.state.zoom}px`,\n width: `${this.imageWidth * this.state.zoom}px`,\n height: `${this.imageHeight * this.state.zoom}px`\n };\n return (\n \n
\n
\n
\n
\n
\n
\n \n
\n
\n );\n }\n}\n","// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport Cropper from './cropper.jsx';\nimport { imageCrop } from '../lib/blob-helpers.js';\n\nexport default class AvatarCrop extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n top: 0,\n left: 0,\n width: 0,\n height: 0,\n scale: 1\n };\n\n this.handleSubmit = this.handleSubmit.bind(this);\n this.handleChange = this.handleChange.bind(this);\n }\n\n // Cut out in image coordinates and desired scale factor.\n handleChange(left, top, width, height, scale) {\n this.setState({\n left: left,\n top: top,\n width: width,\n height: height,\n scale: scale\n });\n }\n\n handleSubmit() {\n imageCrop(this.props.mime, this.props.avatar,\n this.state.left, this.state.top, this.state.width, this.state.height,\n this.state.scale)\n .then(img => {\n this.props.onSubmit(img.mime, img.blob, img.width, img.height);\n })\n .catch(err => {\n this.props.onError(err);\n });\n }\n\n render() {\n return (\n \n
\n \n
\n
\n {this.props.onCancel ?\n \n \n \n : null}\n \n \n \n
\n
\n );\n }\n};\n","// This is a generated file. Don't edit.\n\nexport const PACKAGE_VERSION = \"0.24.3\";\n","import React from 'react';\nimport { defineMessages, injectIntl } from 'react-intl';\n\nconst icon_mapping = {'staff': 'verified_user'};\n\nconst messages = defineMessages({\n badge_verified: {\n id: 'badge_verified',\n defaultMessage: 'Verified/official',\n description: 'Explanation of a verified account or topic badge'\n },\n badge_staff: {\n id: 'badge_staff',\n defaultMessage: 'Staff-managed',\n description: 'Explanation of a staff-managed account or topic badge'\n },\n badge_danger: {\n id: 'badge_danger',\n defaultMessage: 'Untrustworthy',\n description: 'Suspicious or untrustworthy account or topic badge'\n },\n});\n\n\n/* Trusted badges with labels: verified, staff, danger */\nclass BadgeList extends React.PureComponent {\n render() {\n const {formatMessage} = this.props.intl;\n let badges = null;\n if (this.props.trustedBadges && this.props.trustedBadges.length > 0) {\n badges = [];\n this.props.trustedBadges.forEach(b => {\n const comment = this.props.short ? null : formatMessage(messages['badge_' + b]);\n const style = 'material-icons ' + b + '-color';\n badges.push({icon_mapping[b] || b} {comment}
);\n });\n return <>{badges}>;\n }\n return null;\n }\n};\n\nexport default injectIntl(BadgeList);\n","import React from 'react';\n\nexport default class LoadSpinner extends React.PureComponent {\n render() {\n const className = 'load-spinner-box' + (this.props.large ? ' large' : '')\n + (this.props.clear ? ' clear' : '') + (this.props.centered ? ' centered' : '');\n return (this.props.show ?\n : null);\n }\n}\n","import React from 'react';\n\n/* CheckBox: styled three-state checkbox, either clickable or static */\nexport default class CheckBox extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleChange = this.handleChange.bind(this);\n }\n\n handleChange() {\n this.props.onChange(this.props.name, !this.props.checked);\n }\n\n render() {\n let classList = ['material-icons'];\n let iconName;\n if (Array.isArray(this.props.className)) {\n classList.push(...this.props.className);\n } else if (this.props.className) {\n classList.push(this.props.className);\n }\n if (this.props.onChange) {\n if (this.props.checked) {\n classList.push('blue', 'clickable');\n iconName = 'check_box';\n } else if (this.props.checked === false) {\n classList.push('blue', 'clickable');\n iconName = 'check_box_outline_blank';\n } else {\n classList.push('lt-blue');\n iconName = 'indeterminate_check_box';\n }\n } else {\n if (this.props.checked) {\n iconName = 'check_box';\n } else {\n iconName = 'check_box_outline_blank';\n }\n }\n let attrs = {\n className: classList.join(' '),\n id: this.props.id,\n };\n if (this.props.onChange) {\n attrs.onClick = this.handleChange;\n }\n return React.createElement('i', attrs, iconName);\n }\n}\n","module.exports = React;","// Odds and ends\n\nimport { Tinode } from 'tinode-sdk';\n\n// Make shortcut icon appear with a green dot + show unread count in title.\nexport function updateFavicon(count) {\n const oldIcon = document.getElementById('shortcut-icon');\n const head = document.head || document.getElementsByTagName('head')[0];\n const newIcon = document.createElement('link');\n newIcon.type = 'image/png';\n newIcon.id = 'shortcut-icon';\n newIcon.rel = 'shortcut icon';\n newIcon.href = 'img/logo32x32' + (count > 0 ? 'a' : '') + '.png';\n if (oldIcon) {\n head.removeChild(oldIcon);\n }\n head.appendChild(newIcon);\n\n document.title = (count > 0 ? '('+count+') ' : '') + 'Tinode';\n}\n\n// Create theCard which represents user's or topic's \"public\" info.\nexport function theCard(fn, imageUrl, imageMimeType, note) {\n let card = null;\n fn = fn && fn.trim();\n note = note && note.trim();\n\n if (fn) {\n card = {\n fn: fn\n };\n }\n\n if (typeof note == 'string') {\n card = card || {};\n card.note = note ? note : Tinode.DEL_CHAR;\n }\n\n if (imageUrl) {\n card = card || {};\n let mimeType = imageMimeType;\n // Is this a data URL \"data:[][;base64],\"?\n const matches = /^data:(image\\/[-a-z0-9+.]+)?(;base64)?,/i.exec(imageUrl);\n if (matches) {\n mimeType = matches[1];\n card.photo = {\n data: imageUrl.substring(imageUrl.indexOf(',') + 1),\n ref: Tinode.DEL_CHAR\n };\n } else {\n card.photo = {\n data: Tinode.DEL_CHAR,\n ref: imageUrl\n };\n }\n card.photo.type = (mimeType || 'image/jpeg').substring('image/'.length);\n }\n\n return card;\n}\n\n// Deep-shallow compare two arrays: shallow compare each element.\nexport function arrayEqual(a, b) {\n if (a === b) {\n return true;\n }\n\n if (!Array.isArray(a) || !Array.isArray(b)) {\n return false;\n }\n\n // Compare lengths first.\n if (a.length != b.length) {\n return false;\n }\n // Order of elements is ignored.\n a.sort();\n b.sort();\n for (let i = 0, l = a.length; i < l; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n return true;\n}\n\n// Checks (loosely) if the given string is a phone. If so, returns the phone number in a format\n// as close to E.164 as possible.\nexport function asPhone(val) {\n val = val.trim();\n if (/^(?:\\+?(\\d{1,3}))?[- (.]*(\\d{3})[- ).]*(\\d{3})[- .]*(\\d{2})[- .]*(\\d{2})?$/.test(val)) {\n return val.replaceAll(/[- ().]*/g, '');\n }\n return null;\n}\n\n// Checks (loosely) if the given string is an email. If so returns the email.\nexport function asEmail(val) {\n val = val.trim();\n if (/^[a-z0-9_.+-]+@[a-z0-9-]+(\\.[a-z0-9-]+)+$/i.test(val)) {\n return val;\n }\n return null;\n}\n\n// Checks if URL is a relative url, i.e. has no 'scheme://', including the case of missing scheme '//'.\n// The scheme is expected to be RFC-compliant, e.g. [a-z][a-z0-9+.-]*\n// example.html - ok\n// https:example.com - not ok.\n// http:/example.com - not ok.\n// //example.com or \\\\example.com - not ok.\n// ' ↲ https://example.com' - not ok. (↲ means carriage return)\nexport function isUrlRelative(url) {\n // Replacing backslashes with forward slashes to mimic JS URL parser then testing for\n // 'scheme:' and '//' with optional space at the start.\n return url && !/^\\s*([a-z][a-z0-9+.-]*:|\\/\\/)/im.test(url.replace(/\\\\/g, '/'));\n}\n\n// Ensure URL does not present an XSS risk. Optional allowedSchemes may contain an array of\n// strings with permitted URL schemes, such as ['ftp', 'ftps']; otherwise accept http and https only.\nexport function sanitizeUrl(url, allowedSchemes) {\n if (typeof url != 'string') {\n return url;\n }\n\n // Strip control characters and whitespace. They are not valid URL characters anyway.\n url = url.replace(/[^\\x21-\\x7E]/gmi, '').trim();\n\n // Replace backslashes with forward slashes. They will be replaced in the URL parser anyway.\n url = url.replace(/\\\\/g, '/');\n\n // Relative URLs are safe.\n // Relative URL does not start with ':', abcd123: or '//'.\n if (!/^([a-z][a-z0-9+.-]*:|\\/\\/)/i.test(url)) {\n return url;\n }\n\n // Blob URLs are safe.\n if (/^blob:http/.test(url)) {\n return url;\n }\n\n // Absolute URL. Accept only safe schemes, or no scheme.\n const schemes = Array.isArray(allowedSchemes) ? allowedSchemes.join('|') : 'http|https';\n const re = new RegExp('^((' + schemes + '):|//)', 'i');\n if (!re.test(url)) {\n return null;\n }\n\n return url;\n}\n\n// Ensure URL is suitable as a source like field: the URL must be a relative URL or\n// have http:, https:, blob: or data: scheme.\n// In case of data: scheme, the URL must must be of the right MIME type such as 'data:{mimeMajor}/XXXX;base64,'.\nexport function sanitizeUrlForMime(url, mimeMajor) {\n if (!url) {\n return null;\n }\n\n const sanitizedUrl = sanitizeUrl(url);\n if (sanitizedUrl) {\n return sanitizedUrl;\n }\n\n // Is this a data: URL of the appropriate mime type?\n const re = new RegExp(`data:${mimeMajor}\\/[-+.a-z0-9]+;base64,`, 'i');\n if (re.test(url.trim())) {\n return url;\n }\n\n return null;\n}\n\n// Append query parameter 'asatt=1' to the URL.\n// It will cause Tinode server to add 'Content-Disposition: attachment' header when serving it.\n// The URL is a string. The URL here is always absolute.\nexport function urlAsAttachment(url) {\n // TODO: check if URL is local or remote, i.e. compare to window.location.origin.\n /*\n if (typeof window.location == 'object') {\n if (!url.startsWith(window.location.origin)) {\n return url;\n }\n }\n */\n // Check if the URL is a data or blob. Do not alter such URLs.\n if (url.startsWith('data:') || url.startsWith('blob:')) {\n return url;\n }\n\n // Split URL into host+path, query, fragment.\n let query = '', fragment = '';\n const idxF = url.indexOf('#');\n if (idxF > 0) {\n fragment = url.substring(idxF+1);\n url = url.substring(0, idxF);\n }\n const idxQ = url.indexOf('?');\n if (idxQ > 0) {\n query = url.substring(idxQ+1);\n url = url.substring(0, idxQ);\n }\n // Add parameter and reassemble.\n const params = new URLSearchParams(query);\n params.append('asatt', '1');\n return `${url}?${params.toString()}` + (fragment ? `#${fragment}` : '');\n}\n\n// Given message's received status, return name and color of a delivery indicator icon.\nexport function deliveryMarker(received) {\n switch (received) {\n case Tinode.MESSAGE_STATUS_SENDING:\n return { name: 'access_time' }; // watch face\n case Tinode.MESSAGE_STATUS_FAILED:\n case Tinode.MESSAGE_STATUS_FATAL:\n return { name: 'warning', color: 'danger-color' }; // yellow icon /!\\\n case Tinode.MESSAGE_STATUS_SENT:\n return { name: 'done' }; // checkmark\n case Tinode.MESSAGE_STATUS_RECEIVED:\n return { name: 'done_all' }; // double checkmark\n case Tinode.MESSAGE_STATUS_READ:\n return { name: 'done_all', color: 'blue' }; // blue double checkmark\n }\n return null;\n}\n\n// Wraps a promise to make it cancelable.\n// The parameter can be either a promise or an error. If it's an error, the wrapped promise is\n// created in a rejected state.\nexport function cancelablePromise(promise) {\n let hasCanceled = false;\n\n const wrappedPromise = promise instanceof Error ?\n Promise.reject(promise) :\n new Promise((resolve, reject) => {\n promise.then(\n result => hasCanceled ? reject({isCanceled: true}) : resolve(result),\n error => hasCanceled ? reject({isCanceled: true}) : reject(error)\n );\n });\n\n return {\n promise: wrappedPromise,\n cancel() {\n hasCanceled = true;\n },\n };\n};\n\n// Clips string to the specified length.\nexport function clipStr(str, length) {\n return str && str.substring(0, length);\n}\n","module.exports = tinode;","// Audio recorder widget.\n\nimport React from 'react';\nimport { defineMessages, injectIntl } from 'react-intl';\n\nimport { secondsToTime } from '../lib/strformat';\nimport { base64ToIntArray } from '../lib/blob-helpers';\n\n// Make canvas bigger than the element size to reduce blurring.\nconst CANVAS_UPSCALING = 2.0;\n// Thickness of a visualization bar.\nconst LINE_WIDTH = 3 * CANVAS_UPSCALING;\n// Spacing between two visualization bars.\nconst SPACING = 2 * CANVAS_UPSCALING;\n// Color of histogram bars.\nconst BAR_COLOR = '#888A';\nconst BAR_COLOR_DARK = '#666C';\nconst THUMB_COLOR = '#444E';\n// Minimum number of amplitude bars to draw.\nconst MIN_PREVIEW_LENGTH = 16;\n\nconst messages = defineMessages({\n icon_title_play: {\n id: 'icon_title_play',\n defaultMessage: 'Play recording',\n description: 'Icon tool tip for starting audio playback'\n }\n});\n\nclass AudioPlayer extends React.PureComponent {\n constructor(props) {\n super(props);\n\n let preview = base64ToIntArray(this.props.preview);\n if (!Array.isArray(preview) || preview.length < MIN_PREVIEW_LENGTH) {\n preview = null;\n }\n\n this.state = {\n canPlay: false,\n playing: false,\n currentTime: '0:00',\n duration: this.props.duration > 0 ? secondsToTime(this.props.duration / 1000) : '-:--',\n longMin: this.props.duration >= 600000,\n preview: preview\n };\n\n this.initAudio = this.initAudio.bind(this);\n this.initCanvas = this.initCanvas.bind(this);\n this.resampleBars = this.resampleBars.bind(this);\n this.visualize = this.visualize.bind(this);\n\n this.handlePlay = this.handlePlay.bind(this);\n this.handleSeek = this.handleSeek.bind(this);\n this.handleError = this.handleError.bind(this);\n\n this.audioPlayer = null;\n\n this.viewBuffer = [];\n this.canvasRef = React.createRef();\n }\n\n componentDidMount() {\n if (this.props.src) {\n this.initAudio();\n }\n\n this.initCanvas();\n }\n\n componentWillUnmount() {\n if (this.audioPlayer) {\n this.audioPlayer.onloadedmetadata = null;\n this.audioPlayer.ontimeupdate = null;\n this.audioPlayer.onended = null;\n this.audioPlayer.pause();\n this.audioPlayer = null;\n }\n }\n\n componentDidUpdate(prevProps) {\n if (this.props.src != prevProps.src) {\n this.initAudio();\n }\n\n if (this.props.preview != prevProps.preview) {\n let preview = base64ToIntArray(this.props.preview);\n if (!Array.isArray(preview) || preview.length < MIN_PREVIEW_LENGTH) {\n preview = null;\n }\n this.setState({preview: preview}, this.initCanvas);\n }\n }\n\n initAudio() {\n this.audioPlayer = new Audio(this.props.src);\n this.audioPlayer.onloadedmetadata = _ => this.setState({canPlay: true});\n this.audioPlayer.ontimeupdate = _ => this.setState({\n currentTime: secondsToTime(this.audioPlayer.currentTime, this.state.longMin)\n });\n this.audioPlayer.onended = _ => {\n this.audioPlayer.currentTime = 0;\n this.setState({playing: false, currentTime: secondsToTime(0, this.state.longMin)})\n }\n }\n\n initCanvas() {\n // Force canvas aspect ratio to match one of the element + upscale canvas to reduce blurring.\n this.canvasRef.current.width = this.canvasRef.current.offsetWidth * CANVAS_UPSCALING;\n this.canvasRef.current.height = this.canvasRef.current.offsetHeight * CANVAS_UPSCALING;\n\n this.canvasContext = this.canvasRef.current.getContext('2d');\n this.canvasContext.lineCap = 'round';\n\n this.viewBuffer = this.resampleBars(this.state.preview);\n this.visualize();\n }\n\n // Draw amplitude of sound.\n visualize() {\n if (!this.canvasRef.current) {\n return;\n }\n\n const width = this.effectiveWidth;\n const height = this.canvasRef.current.height;\n\n this.canvasContext.lineWidth = LINE_WIDTH;\n\n const drawFrame = _ => {\n if (!this.canvasRef.current || !this.audioPlayer) {\n // The component is unmounted.\n return;\n }\n\n this.canvasContext.clearRect(0, 0, this.canvasRef.current.width, height);\n\n if (this.viewBuffer) {\n if (this.state.playing) {\n window.requestAnimationFrame(drawFrame);\n }\n\n // Current playback position.\n const thumbAt = this.props.duration ?\n Math.max(0, Math.min(this.audioPlayer.currentTime * 1000 / this.props.duration, 1)) * (width - LINE_WIDTH * 2) : -1;\n\n // Draw amplitude bars.\n this.canvasContext.beginPath();\n this.canvasContext.strokeStyle = BAR_COLOR_DARK;\n for (let i = 0; i < this.viewBuffer.length; i++) {\n let x = 1 + i * (LINE_WIDTH + SPACING) + LINE_WIDTH * 0.5;\n let y = Math.max(this.viewBuffer[i] * height * 0.9, 1);\n\n const color = x < thumbAt ? BAR_COLOR_DARK : BAR_COLOR;\n if (this.canvasContext.strokeStyle != color) {\n this.canvasContext.stroke();\n this.canvasContext.beginPath();\n this.canvasContext.strokeStyle = color;\n }\n\n this.canvasContext.moveTo(x, (height - y) * 0.5);\n this.canvasContext.lineTo(x, (height + y) * 0.5);\n }\n // Actually draw the bars on canvas.\n this.canvasContext.stroke();\n\n // Draw thumb.\n if (this.props.duration) {\n this.canvasContext.beginPath();\n this.canvasContext.arc(thumbAt + LINE_WIDTH * 2, height * 0.5, LINE_WIDTH * 2, 0, 2 * Math.PI);\n this.canvasContext.fillStyle = THUMB_COLOR;\n this.canvasContext.fill();\n }\n }\n }\n\n drawFrame();\n }\n\n // Quick and dirty downsampling of the original preview bars into a smaller (or equal) number of bars we can display here.\n resampleBars(original) {\n const dstCount = ((this.canvasRef.current.width - SPACING) / (LINE_WIDTH + SPACING)) | 0;\n // Remove extra padding on the right due to fractional bar which is not drawn.\n this.effectiveWidth = dstCount * (LINE_WIDTH + SPACING) + SPACING;\n\n if (!Array.isArray(original) || original.length == 0) {\n return Array.apply(null, Array(dstCount)).map(_ => 0.01);\n }\n\n const factor = original.length / dstCount;\n let amps = [];\n let maxAmp = -1;\n for (let i=0; i 0) {\n return amps.map(a => a / maxAmp);\n }\n return Array.apply(null, Array(dstCount)).map(_ => 0.01);\n }\n\n handlePlay(e) {\n e.preventDefault();\n if (!this.state.canPlay) {\n return;\n }\n\n if (this.state.playing) {\n this.audioPlayer.pause();\n this.setState({playing: false});\n } else if (this.audioPlayer.readyState >= 2) {\n this.audioPlayer.play();\n this.setState({playing: true}, this.visualize);\n }\n }\n\n handleError(err) {\n console.error(err);\n }\n\n handleSeek(e) {\n e.preventDefault();\n if (e.target && this.props.duration) {\n const rect = e.target.getBoundingClientRect();\n const offset = (e.clientX - rect.left) / this.effectiveWidth * CANVAS_UPSCALING;\n this.audioPlayer.currentTime = this.props.duration * offset / 1000;\n this.setState({currentTime: secondsToTime(this.audioPlayer.currentTime, this.state.longMin)});\n if (!this.state.playing) {\n this.visualize();\n }\n }\n }\n\n render() {\n const playClass = 'material-icons' +\n (this.props.short ? '' : ' large') +\n (this.state.canPlay ? '' : ' disabled');\n const play = (\n {this.state.playing ? 'pause_circle' :\n (this.state.canPlay ? 'play_circle' : 'not_interested')} \n );\n return ({this.props.short ?\n <>\n
\n {play}\n >\n :\n <>\n {play}\n
\n
\n
{this.state.currentTime}/{this.state.duration}
\n
\n >\n }\n
);\n }\n}\n\nexport default injectIntl(AudioPlayer);\n","module.exports = ReactDOM;","'use strict';\n\nvar m = require('react-dom');\nif (process.env.NODE_ENV === 'production') {\n exports.createRoot = m.createRoot;\n exports.hydrateRoot = m.hydrateRoot;\n} else {\n var i = m.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n exports.createRoot = function(c, o) {\n i.usingClientEntryPoint = true;\n try {\n return m.createRoot(c, o);\n } finally {\n i.usingClientEntryPoint = false;\n }\n };\n exports.hydrateRoot = function(c, h, o) {\n i.usingClientEntryPoint = true;\n try {\n return m.hydrateRoot(c, h, o);\n } finally {\n i.usingClientEntryPoint = false;\n }\n };\n}\n","// File and image helper functions.\n\n// Supported image MIME types and corresponding file extensions.\nexport const SUPPORTED_IMAGE_FORMATS = ['image/jpeg', 'image/gif', 'image/png', 'image/svg', 'image/svg+xml'];\nexport const MIME_EXTENSIONS = ['jpg', 'gif', 'png', 'svg', 'svg'];\n\n// Get an URL from a theCard photo: either create a data: URL or return reference URL.\nexport function makeImageUrl(photo) {\n if (photo && typeof photo == 'object') {\n if (photo.ref) {\n return photo.ref\n }\n if (photo.data && photo.type) {\n const mime = photo.type.startsWith('image/') ? photo.type : ('image/' + photo.type);\n return 'data:' + mime + ';base64,' + photo.data;\n }\n }\n return null;\n}\n\n// Calculate linear dimensions for scaling image down to fit under a certain size.\n// Returns an object which contains destination sizes, source sizes, and offsets\n// into source (when making square images).\nexport function fitImageSize(width, height, maxWidth, maxHeight, forceSquare) {\n // Sanitize input\n width = width | 0;\n height = height | 0;\n maxWidth = maxWidth | 0;\n maxHeight = maxHeight | 0;\n\n if (width <= 0 || height <= 0 || maxWidth <= 0 || maxHeight <= 0) {\n return null;\n }\n\n if (forceSquare) {\n maxWidth = maxHeight = Math.min(maxWidth, maxHeight);\n }\n\n const scale = Math.min(\n Math.min(width, maxWidth) / width,\n Math.min(height, maxHeight) / height\n );\n\n const size = {\n dstWidth: (width * scale) | 0,\n dstHeight: (height * scale) | 0,\n };\n\n if (forceSquare) {\n // Also calculate parameters for making the image square.\n size.dstWidth = size.dstHeight = Math.min(size.dstWidth, size.dstHeight);\n size.srcWidth = size.srcHeight = Math.min(width, height);\n size.xoffset = ((width - size.srcWidth) / 2) | 0;\n size.yoffset = ((height - size.srcWidth) / 2) | 0;\n } else {\n size.xoffset = size.yoffset = 0;\n size.srcWidth = width;\n size.srcHeight = height;\n }\n return size;\n}\n\n// Ensure file's extension matches mime content type\nexport function fileNameForMime(fname, mime) {\n const idx = SUPPORTED_IMAGE_FORMATS.indexOf(mime);\n if (idx < 0 || !fname) {\n // Unknown mime or empty name.\n return fname;\n }\n const ext = MIME_EXTENSIONS[idx];\n\n const at = fname.lastIndexOf('.');\n if (at >= 0) {\n fname = fname.substring(0, at);\n }\n return fname + '.' + ext;\n}\n\n// Scale uploaded image to fit under certain dimensions and byte size, optionally constraining to a square.\n// Returns a promise which is resolven on success or rejected on failure.\nexport function imageScaled(fileOrBlob, maxWidth, maxHeight, maxSize, forceSquare) {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.crossOrigin = 'Anonymous';\n img.onerror = function(err) {\n reject(new Error(\"Image format unrecognized\"));\n }\n img.onload = async function() {\n // Once the image is loaded, the URL is no longer needed.\n URL.revokeObjectURL(img.src);\n\n // Calculate the desired image dimensions.\n const dim = fitImageSize(img.width, img.height, maxWidth, maxHeight, forceSquare);\n if (!dim) {\n reject(new Error(\"Invalid image\"));\n return;\n }\n let canvas = document.createElement('canvas');\n canvas.width = dim.dstWidth;\n canvas.height = dim.dstHeight;\n let ctx = canvas.getContext('2d');\n ctx.imageSmoothingEnabled = true;\n ctx.drawImage(img, dim.xoffset, dim.yoffset, dim.srcWidth, dim.srcHeight,\n 0, 0, dim.dstWidth, dim.dstHeight);\n\n const mime = SUPPORTED_IMAGE_FORMATS.includes(fileOrBlob.type) ? fileOrBlob.type : 'image/jpeg';\n // Generate blob to check size of the image.\n let blob = await new Promise(resolve => canvas.toBlob(resolve, mime));\n if (!blob) {\n reject(new Error(\"Unsupported image format\"));\n return;\n }\n // Ensure the image is not too large. Shrink the image keeping the aspect ratio.\n // Do nothing if maxsize is <= 0.\n while (maxSize > 0 && blob.length > maxSize) {\n dim.dstWidth = (dim.dstWidth * 0.70710678118) | 0;\n dim.dstHeight = (dim.dstHeight * 0.70710678118) | 0;\n canvas.width = dim.dstWidth;\n canvas.height = dim.dstHeight;\n ctx = canvas.getContext('2d');\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.drawImage(img, dim.xoffset, dim.yoffset, dim.srcWidth, dim.srcHeight,\n 0, 0, dim.dstWidth, dim.dstHeight);\n blob = await new Promise(resolve => canvas.toBlob(resolve, mime));\n }\n\n canvas = null;\n resolve({mime: mime, blob: blob, width: dim.dstWidth, height: dim.dstHeight, name: fileNameForMime(fileOrBlob.name, mime)});\n };\n img.src = URL.createObjectURL(fileOrBlob);\n });\n}\n\n// Scale and crop image according to specified dimensions.\n// The coordinates are in unscaled image pixels, i.e. cut the rectangle first then scale it.\n// returns a promise.\nexport function imageCrop(mime, objURL, left, top, width, height, scale) {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.crossOrigin = 'Anonymous';\n img.onerror = _ => {\n reject(new Error(\"Image format unrecognized\"));\n };\n img.onload = _ => {\n // Once the image is loaded, the URL is no longer needed.\n URL.revokeObjectURL(img.src);\n\n let canvas = document.createElement('canvas');\n canvas.width = width * scale;\n canvas.height = height * scale;\n let ctx = canvas.getContext('2d');\n ctx.imageSmoothingEnabled = true;\n ctx.drawImage(img, left, top, width, height, 0, 0, canvas.width, canvas.height);\n\n mime = SUPPORTED_IMAGE_FORMATS.includes(mime) ? mime : 'image/jpeg';\n // Generate blob to check size of the image.\n canvas.toBlob((blob) => {\n // Allow GC.\n canvas = null;\n if (blob) {\n resolve({mime: mime, blob: blob, width: width, height: height});\n } else {\n reject(new Error(\"Unsupported image format\"));\n }\n }, mime);\n };\n img.src = objURL;\n });\n}\n\n// Convert file to base64 string.\nexport function fileToBase64(file) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = _ => {\n reject(reader.error);\n };\n reader.onload = _ => {\n resolve({mime: file.type, bits: reader.result.split(',')[1], name: file.name});\n };\n reader.readAsDataURL(file);\n });\n}\n\n// Convert Blob to base64 string. Returns a promise resolved with the base64 string and mime.\nexport function blobToBase64(blob) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onerror = _ => {\n reject(reader.error);\n };\n reader.onload = _ => {\n resolve({mime: blob.type, bits: reader.result.split(',')[1]});\n };\n reader.readAsDataURL(blob);\n });\n}\n\n// File pasted from the clipboard. It's either an inline image or a file attachment.\nexport function filePasted(event, onImageSuccess, onAttachmentSuccess, onError) {\n const items = (event.clipboardData || event.originalEvent.clipboardData || {}).items;\n if (!items || !items.length) {\n return false;\n }\n\n for (let i in items) {\n const item = items[i];\n if (item.kind === 'file') {\n const file = item.getAsFile();\n if (!file) {\n console.error(\"Failed to get file object from pasted file item\", item.kind, item.type);\n onError(\"Failed to get file object from pasted file item\");\n continue;\n }\n if (file.type && file.type.split('/')[0] == 'image') {\n onImageSuccess(file);\n } else {\n onAttachmentSuccess(file);\n }\n // Indicate that the pasted data contains a file.\n return true;\n }\n }\n // No file found.\n return false;\n}\n\n// Get mime type from data URL header.\nexport function getMimeType(header) {\n const mime = /^data:(image\\/[-+a-z0-9.]+);base64/.exec(header);\n return (mime && mime.length > 1) ? mime[1] : null;\n}\n\n// Given length of a binary object in bytes, calculate the length after\n// base64 encoding.\nexport function base64EncodedLen(n) {\n return Math.floor((n + 2) / 3) * 4;\n}\n\n// Given length of a base64-encoded object, calculate decoded size of the\n// pbject in bytes.\nexport function base64DecodedLen(n) {\n return Math.floor(n / 4) * 3;\n}\n\n// Re-encode string to standard base64 encoding with padding.\n// The string may be base64-URL encoded without the padding.\nexport function base64ReEncode(str) {\n if (str) {\n str = str.replace(/-/g, '+').replace(/_/g, '/');\n try {\n str = btoa(atob(str));\n } catch(err) {\n console.error(\"Failed to base64 re-encode string.\", err);\n str = null;\n }\n }\n return str;\n}\n\n// Convert a base64 encoded string with the provided mime type into a Blob.\nexport function base64ToBlob(str, mime) {\n if (!str) {\n return null;\n }\n\n try {\n // Make blob.\n const bin = atob(str);\n const length = bin.length;\n const buf = new ArrayBuffer(length);\n const arr = new Uint8Array(buf);\n for (let i = 0; i < length; i++) {\n arr[i] = bin.charCodeAt(i);\n }\n\n return new Blob([buf], { type: mime });\n } catch(err) {\n console.error(\"Failed to convert base64 to blob: \", err);\n }\n\n return null;\n}\n\nexport function intArrayToBase64(arr) {\n if (!Array.isArray(arr)) {\n return null;\n }\n try {\n let bin = '';\n new Uint8Array(arr).forEach(b => bin += String.fromCharCode(b));\n return window.btoa(bin);\n } catch (err) {}\n return null;\n}\n\nexport function base64ToIntArray(b64) {\n const arr = [];\n try {\n const bin = window.atob(b64);\n [...bin].forEach(c => {\n arr.push(c.charCodeAt(0));\n });\n return arr;\n } catch (err) {}\n return null;\n}\n","// Password with a visiblity toggle.\nimport React from 'react';\n\nexport default class VisiblePassword extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.inputRef = React.createRef();\n\n this.state = {\n value: this.props.value || '',\n visible: false\n };\n\n this.handleVisibility = this.handleVisibility.bind(this);\n this.handeTextChange = this.handeTextChange.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleEditingFinished = this.handleEditingFinished.bind(this);\n }\n\n componentDidMount() {\n if (this.props.autoFocus) {\n this.inputRef.current.focus();\n }\n }\n\n handeTextChange(e) {\n this.setState({value: e.target.value});\n if (this.props.onChange) {\n this.props.onChange(e);\n }\n }\n\n handleVisibility(e) {\n e.preventDefault();\n this.setState({visible: !this.state.visible});\n }\n\n handleKeyDown(e) {\n if (e.keyCode == 27) {\n // Escape pressed\n this.setState({value: this.props.value || '', visible: false});\n if (this.props.onFinished) {\n this.props.onFinished();\n }\n } else if (e.keyCode == 13) {\n // Enter pressed\n this.handleEditingFinished();\n }\n }\n\n handleEditingFinished(e) {\n if (e) {\n let currentTarget = e.currentTarget;\n setTimeout(_ => {\n if (!currentTarget.contains(document.activeElement)) {\n if (this.props.onFinished) {\n this.props.onFinished(this.state.value);\n }\n }\n }, 0);\n } else if (this.props.onFinished) {\n this.props.onFinished(this.state.value.trim());\n }\n }\n\n render() {\n return (\n \n \n \n \n {this.state.visible ? 'visibility' : 'visibility_off'}\n \n \n
\n );\n }\n}\n","import React from 'react';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport { idToColorClass } from '../lib/strformat.js';\nimport { sanitizeUrlForMime } from '../lib/utils.js';\n\nimport { SELF_AVATAR_URI } from '../config.js';\n\nexport default class LetterTile extends React.PureComponent {\n render() {\n let avatar;\n if (this.props.avatar === true) {\n if (Tinode.isSelfTopicName(this.props.topic)) {\n avatar = \n } else {\n const isGroup = Tinode.isGroupTopicName(this.props.topic);\n const iconColor = idToColorClass(this.props.topic, isGroup);\n\n if (this.props.topic && this.props.title && this.props.title.trim()) {\n const letter = this.props.title.trim().charAt(0);\n const className = 'lettertile ' + iconColor + (this.props.deleted ? ' disabled' : '');\n avatar = ()\n } else {\n const className = 'material-icons ' + iconColor + (this.props.deleted ? ' disabled' : '');\n avatar = isGroup ? group : person ;\n }\n }\n } else if (this.props.avatar) {\n const url = this.props.tinode.authorizeURL(sanitizeUrlForMime(this.props.avatar, 'image'));\n // If avatar image is invalid, show a placeholder.\n const className = 'avatar' + (this.props.deleted ? ' deleted' : '');\n avatar = {e.target.onerror = null; e.target.src=\"../img/broken_image.png\"}} />;\n } else {\n avatar = null;\n }\n return avatar;\n }\n}\n","// Utility class for hash navigation.\n\nexport default class HashNavigation {\n // Parse hash as in http://www.example.com/path#hash as if it were\n // path and arguments.\n static parseUrlHash(hash) {\n // Split 'path/?args' into 'path/' and 'args', path -> parts[0], args->path[1].\n const parts = hash.split('?', 2);\n const params = {};\n let path = [];\n if (parts[0]) {\n path = parts[0].replace('#', '').split('/');\n }\n if (parts[1]) {\n parts[1].split('&').forEach((arg) => {\n // Can't use split() because the value may contain '='.\n const eq = arg.indexOf('=');\n if (eq > 0) {\n params[arg.slice(0, eq)] = decodeURIComponent(arg.slice(eq + 1));\n }\n });\n }\n return {path: path, params: params};\n }\n\n static navigateTo(url) {\n window.location.hash = url;\n }\n\n static composeUrlHash(path, params) {\n let url = path.join('/');\n const args = [];\n for (const key in params) {\n if (params.hasOwnProperty(key)) {\n if (params[key] !== undefined) {\n args.push(key + '=' + encodeURIComponent(params[key]));\n }\n }\n }\n if (args.length > 0) {\n url += '?' + args.join('&');\n }\n return url;\n }\n\n static addUrlParam(hash, key, value) {\n const parsed = HashNavigation.parseUrlHash(hash);\n parsed.params[key] = value;\n return HashNavigation.composeUrlHash(parsed.path, parsed.params);\n }\n\n static removeUrlParam(hash, key) {\n const parsed = HashNavigation.parseUrlHash(hash);\n delete parsed.params[key];\n return HashNavigation.composeUrlHash(parsed.path, parsed.params);\n }\n\n static setUrlSidePanel(hash, sidepanel) {\n const parsed = HashNavigation.parseUrlHash(hash);\n parsed.path[0] = sidepanel;\n return HashNavigation.composeUrlHash(parsed.path, parsed.params);\n }\n\n static setUrlInfoPanel(hash, infopanel) {\n const parsed = HashNavigation.parseUrlHash(hash);\n if (infopanel) {\n parsed.params.info = infopanel;\n } else {\n delete parsed.params.info;\n }\n return HashNavigation.composeUrlHash(parsed.path, parsed.params);\n }\n\n static setUrlTopic(hash, topic) {\n const parsed = HashNavigation.parseUrlHash(hash);\n parsed.path[1] = topic;\n // Close InfoView on topic change.\n delete parsed.params.info;\n return HashNavigation.composeUrlHash(parsed.path, parsed.params);\n }\n}\n","module.exports = ReactIntl;","// Helper functions for storing values in localStorage.\n// By default localStorage can store only strings, not objects or other types.\n\nexport default class LocalStorageUtil {\n // Replace old object with the new one.\n static setObject(key, value) {\n localStorage.setItem(key, JSON.stringify(value));\n }\n\n // Get stored object.\n static getObject(key) {\n const value = localStorage.getItem(key);\n return value && JSON.parse(value);\n }\n\n // Partially or wholly update stored object.\n static updateObject(key, value) {\n const oldVal = this.getObject(key);\n this.setObject(key, Object.assign(oldVal || {}, value));\n }\n\n // Just a wrapper.\n static removeItem(key) {\n localStorage.removeItem(key);\n }\n}\n","// Short representation of time in the past.\nexport function shortDateFormat(then, locale) {\n locale = locale || window.navigator.userLanguage || window.navigator.language;\n const now = new Date();\n if (then.getFullYear() == now.getFullYear()) {\n // Same year.\n if (then.getMonth() == now.getMonth() && then.getDate() == now.getDate()) {\n // Same month and day, show time only.\n return then.toLocaleTimeString(locale, {hour12: false, hour: '2-digit', minute: '2-digit'});\n }\n // Different month and/or day, show month day, time.\n return then.toLocaleDateString(locale,\n {hour12: false, month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit'});\n }\n // Different year: just show the date.\n return then.toLocaleDateString(locale, {year: 'numeric', month: 'short', day: 'numeric'});\n}\n\n// Representation a date relative to now.\nexport function relativeDateFormat(then, locale) {\n locale = locale || window.navigator.userLanguage || window.navigator.language;\n const now = new Date();\n const thenDays = Math.floor((then.getTime() - then.getTimezoneOffset() * 60_000) / 86_400_000);\n const nowDays = Math.floor((now.getTime() - now.getTimezoneOffset() * 60_000) / 86_400_000);\n const diff = thenDays - nowDays;\n if (Math.abs(diff) < 2) {\n // Today or yesterday.\n return new Intl.RelativeTimeFormat(locale, { numeric: 'auto' }).format(diff, 'day')\n }\n // More than two days: just show the date.\n return new Intl.DateTimeFormat(locale).format(then);\n}\n\n// Convert seconds to [hours:]minutes:seconds, i.e. 156 sec -> 2:36, 3756 sec -> 1:02:36.\n// If fixedMins is true, then minutes are represented by at least two digits.\nexport function secondsToTime(seconds, fixedMin) {\n if (typeof seconds != 'number') {\n return '';\n }\n\n let min = (Math.floor(seconds / 60) | 0) % 60;\n let hours = Math.floor(seconds / 3600) | 0;\n\n if (fixedMin || hours > 0) {\n min = min < 10 ? `0${min}` : min;\n }\n let sec = (seconds | 0) % 60;\n sec = sec < 10 ? `0${sec}` : sec;\n if (hours == 0) {\n return `${min}:${sec}`;\n }\n return `${hours}:${min}:${sec}`;\n}\n\n// Convert a number of bytes to human-readable format.\nexport function bytesToHumanSize(bytes) {\n if (!bytes || bytes == 0) {\n return '0 Bytes';\n }\n\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];\n const bucket = Math.min(Math.floor(Math.log2(bytes) / 10) | 0, sizes.length-1);\n const count = bytes / Math.pow(1024, bucket);\n const round = bucket > 0 ? (count < 3 ? 2 : (count < 30 ? 1 : 0)) : 0;\n return count.toFixed(round) + ' ' + sizes[bucket];\n}\n\n// Shorten a file name to be under maxLength by clipping out the middle.\nexport function shortenFileName(filename, maxLength) {\n if (typeof filename != 'string') {\n return filename;\n }\n return filename.length > maxLength ?\n filename.slice(0, maxLength/2 - 1) + '…' + filename.slice(1 - maxLength/2) : filename;\n}\n\n// Get 32 bit integer hash value for a string. Ideally it should produce the same value\n// as Java's String#hash().\nfunction stringToColorHash(value) {\n let hash = 0;\n value = '' + value;\n for (let i = 0; i < value.length; i++) {\n hash = ((hash << 5) - hash) + value.charCodeAt(i);\n hash = hash & hash; // Convert to 32bit integer\n }\n return hash;\n}\n\n// User avatar letter color id.\nexport function letterTileColorId(userId) {\n return Math.abs(stringToColorHash(userId)) % 16;\n}\n\n// Converts user or topic ID to a CSS color class. Ideally it should produce the same color value as Java version.\n// params:\n// - {string} id: user or topic ID\n// - {boolean} light: light or dark version of the color.\n// - {boolean} fg: foreground (text) or background color.\nexport function idToColorClass(id, light, fg) {\n return (light ? 'lt-' : 'dk-') + (fg ? 'fg-' : 'bg-') + letterTileColorId(id);\n}\n\n// Takes ISO Alpha-2 country code, like 'US' and converts it to a flag emoji.\nexport function flagEmoji(countryCode) {\n const codePoints = countryCode\n .toUpperCase()\n .split('')\n .map(char => 0x1F1A5 + char.charCodeAt());\n return String.fromCodePoint(...codePoints);\n}\n","import { PACKAGE_VERSION } from './version.js';\n\n// Name of this application, used in the User-Agent.\nexport const APP_NAME = 'TinodeWeb/' + (PACKAGE_VERSION || '0.24');\n\n// API key. Use https://github.com/tinode/chat/tree/master/keygen to generate your own\nexport const API_KEY = 'AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K';\n\n// The array of possible hosts to connect to.\nexport const KNOWN_HOSTS = {hosted: 'web.tinode.co', local: 'localhost:6060'};\n\n// Default host name and port to connect to.\nexport const DEFAULT_HOST = KNOWN_HOSTS.hosted;\n\n// Enable console logging.\nexport const LOGGING_ENABLED = true;\n\n// Minimum time between two keypress notifications, milliseconds.\nexport const KEYPRESS_DELAY = 3_000;\n// Delay before sending a read notification, milliseconds.\nexport const READ_DELAY = 1_500;\n\n// The default shortest allowed tag length. Matches the value on the server.\nexport const MIN_TAG_LENGTH = 2;\n// The default greatest allowed tag length. Matches the value on the server.\nexport const MAX_TAG_LENGTH = 96;\n// The default maximum number of tags allowed. Matches the value on the server.\nexport const MAX_TAG_COUNT = 16;\n\n// Access mode for P2P subscriptions initiated by the current user.\nexport const DEFAULT_P2P_ACCESS_MODE = 'JRWPS';\n// Access mode for new group topics created by the current user.\nexport const NEW_GRP_ACCESS_MODE = 'JRWPSAO';\n// Access mode for a channel.\nexport const CHANNEL_ACCESS_MODE = 'JR';\n\n// Access mode for no access.\nexport const NO_ACCESS_MODE = 'N';\n\n// Mediaquery breakpoint between desktop and mobile, in px. Should match the value\n// in @media (max-size: 640px) in base.css\nexport const MEDIA_BREAKPOINT = 640;\n// Size of css 'rem' unit in pixels. Default 1rem = 10pt = 13px.\nexport const REM_SIZE = 13;\n\n// Size of the avatar image: when image dimensions are greater or the image is not square, it's resized to\n// a square of this size or less.\nexport const AVATAR_SIZE = 384;\n\n// Maximum size of an avatar in bytes for sending in-band. Bigger avatars will be sent out of band (as uploads).\nexport const MAX_AVATAR_BYTES = 4096;\n\n// Size of the broken_image shown in MessagesView\nexport const BROKEN_IMAGE_SIZE = 32;\n\n// Size of video preview when dimensions are missing.\nexport const NO_DIMENSIONS_VIDEO = 128;\n\n// Number of chat messages to fetch in one call.\nexport const MESSAGES_PAGE = 24;\n\n// Default maximum in-band (included directly into the message) attachment size which fits into\n// a message of 256K in size. Used when the server-provided value is unavailable. The actual\n// binary size of the attachment should be smaller due to base64 encoding expansion and some overhead,\n// for instance 1024 bytes.\n// Increase this limit to a greater value in production, if desired. Also increase\n// max_message_size in the server config.\nexport const MAX_INBAND_ATTACHMENT_SIZE = 262_144;\n\n// Default absolute maximum attachment size to be used with the server = 8MB.\n// Used when the server-provided value is unavailable. Increase to something like 100MB in production.\nexport const MAX_EXTERN_ATTACHMENT_SIZE = 1 << 23;\n\n// Maximum allowed linear dimension (pixels) of an image sent inline. Larger images will be shrunk\n// to make the larger dimension fit under this size. You may want to adjust it to 1600 or\n// 2400 for production.\nexport const MAX_IMAGE_DIM = 1024;\n\n// Linear dimensions of image preview: shrink image under this size for previews.\nexport const IMAGE_PREVIEW_DIM = 64;\n\n// Linear dimensions of video screencapture: shrink image under this size for previews.\nexport const VIDEO_PREVIEW_DIM = 96;\n\n// Linear dimensions of image thumbnail: shrink image under this size for thumbnails in reply quote previews.\nexport const IMAGE_THUMBNAIL_DIM = 36;\n// Width of video thumbnail: allow it to be wider, but not taller. Use IMAGE_THUMBNAIL_DIM for height.\nexport const VIDEO_THUMBNAIL_WIDTH = 48;\n\n// Maximum number of online users to be shown in a topic title bar. Others will be\n// hidden under \"+X more\"\nexport const MAX_ONLINE_IN_TOPIC = 4;\n\n// Maximum length of user name, topic title, and private comment.\nexport const MAX_TITLE_LENGTH = 60;\n// Maximum length of topic description.\nexport const MAX_TOPIC_DESCRIPTION_LENGTH = 360;\n// Maximum length of user name when displaying a video call.\nexport const MAX_PEER_TITLE_LENGTH = 24;\n\n// Length of message previews in chat list, in characters.\nexport const MESSAGE_PREVIEW_LENGTH = 80;\n\n// Length of a quote in quoted reply (for outgoing messages).\nexport const QUOTED_REPLY_LENGTH = 30;\n// Length of a preview of a forwarded message.\nexport const FORWARDED_PREVIEW_LENGTH = 84;\n// Length of preview for a message being edited.\nexport const EDIT_PREVIEW_LENGTH = 48;\n\n// Minimum duration of an audio recording in milliseconds (2 sec).\nexport const MIN_DURATION = 2_000;\n// Maximum duration of an audio recording in milliseconds (10 min).\nexport const MAX_DURATION = 600_000;\n\n// Link for \"Contact Us\".\nexport const LINK_CONTACT_US = 'mailto:support@tinode.co';\n\n// Link to Privacy Policy.\nexport const LINK_PRIVACY_POLICY = 'https://tinode.co/privacy.html';\n\n// Link to Terms of Service.\nexport const LINK_TERMS_OF_SERVICE = 'https://tinode.co/terms.html';\n\n// When user starts a P2P topic, automatic subscription does not\n// happen until the first message. Setting this option to true enables\n// immediate subscription.\nexport const IMMEDIATE_P2P_SUBSCRIPTION = false;\n\n// URL schemes permitted to appear in links (i.e. no javascript: scheme).\nexport const CLICKABLE_URL_SCHEMES = ['http', 'https', 'ftp', 'ftps'];\n\n// Size of the QR code in the app.\nexport const QRCODE_SIZE = 128;\n\n// How much time has to pass to consider computer awoken from sleep (80 sec).\n// Chrome throttles ticker events in inactive tabs to once per minute. This\n// value ensures that these once-a-minute events do not trigger a reconnect.\nexport const WAKE_UP_TIMEOUT = 80000;\n// Timer interval between checks if computer woke up from sleep (1 sec).\nexport const WAKE_UP_TICK = 1000;\n\n// Swipe distance to register as a gesture, in pixels.\nexport const MIN_SWIPE_DISTANCE = REM_SIZE * 3;\n\n// Self-topic avatar as an SVG icon encoded as data URI\nexport const SELF_AVATAR_URI = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48c3ZnIHZpZXdCb3g9IjAgMCAxNyAxNyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMy41NjIgMXYxNS40NTlsNC42ODYtMy4yNyA0Ljc1MiAzLjI2di0xNS40NDloLTkuNDM4ek0xMiAxNC41NTFsLTMuNzU2LTIuNTc4LTMuNjgxIDIuNTY4di0xMi41NDFoNy40Mzd2MTIuNTUxeiIgZmlsbD0iIzU1NTU1NSIgLz48L3N2Zz4=' // eslint-disable-line max-len\n\n// Toast display duration, milliseconds.\nexport const TOAST_DURATION = 3_000;\n","import React from 'react';\n\nimport LetterTile from './letter-tile.jsx';\nimport LoadSpinner from './load-spinner.jsx';\n\nimport { sanitizeUrlForMime } from '../lib/utils.js';\n\nimport { AVATAR_SIZE } from '../config.js';\n\nexport default class AvatarUpload extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n source: props.avatar\n };\n\n this.handleFileReceived = this.handleFileReceived.bind(this);\n }\n\n componentDidUpdate(prevProps) {\n if (this.props.avatar != prevProps.avatar) {\n this.setState({source: this.props.avatar});\n }\n }\n\n handleFileReceived(e) {\n const image = e.target.files[0];\n this.props.onImageUpdated(image.type, URL.createObjectURL(image), image.name);\n // Clear the value so the same file can be uploaded again.\n e.target.value = '';\n }\n\n render() {\n // Randomize id value in case more than one AvatarUpload is shown\n // at the same time.\n const randId = 'file-input-avatar-' + ('' + Math.random()).substring(0, 4);\n const className = 'avatar-upload' + (this.props.readOnly ? ' read-only' : '');\n return (\n \n {this.props.readOnly || !this.state.source ?\n null :\n
{e.preventDefault(); this.props.onImageUpdated();}}>\n clear \n }\n {this.state.source ?\n
:\n this.props.readOnly && this.props.uid ?\n
\n \n
\n :\n
{AVATAR_SIZE}×{AVATAR_SIZE}
}\n {this.props.readOnly ? null :\n
}\n {this.props.readOnly ? null :\n
\n file_upload \n }\n
\n
\n );\n }\n};\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = function(module) {\n\tvar getter = module && module.__esModule ?\n\t\tfunction() { return module['default']; } :\n\t\tfunction() { return module; };\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.f = {};\n// This file contains only the entry chunk.\n// The chunk loading function for additional chunks\n__webpack_require__.e = function(chunkId) {\n\treturn Promise.all(Object.keys(__webpack_require__.f).reduce(function(promises, key) {\n\t\t__webpack_require__.f[key](chunkId, promises);\n\t\treturn promises;\n\t}, []));\n};","// This function allow to reference async chunks\n__webpack_require__.u = function(chunkId) {\n\t// return url for filenames based on template\n\treturn \"\" + chunkId + \".prod.js\";\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.p = \"/umd/\";","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t57: 0\n};\n\n__webpack_require__.f.j = function(chunkId, promises) {\n\t\t// JSONP chunk loading for javascript\n\t\tvar installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;\n\t\tif(installedChunkData !== 0) { // 0 means \"already installed\".\n\n\t\t\t// a Promise means \"currently loading\".\n\t\t\tif(installedChunkData) {\n\t\t\t\tpromises.push(installedChunkData[2]);\n\t\t\t} else {\n\t\t\t\tif(true) { // all chunks have JS\n\t\t\t\t\t// setup Promise in chunk cache\n\t\t\t\t\tvar promise = new Promise(function(resolve, reject) { installedChunkData = installedChunks[chunkId] = [resolve, reject]; });\n\t\t\t\t\tpromises.push(installedChunkData[2] = promise);\n\n\t\t\t\t\t// start chunk loading\n\t\t\t\t\tvar url = __webpack_require__.p + __webpack_require__.u(chunkId);\n\t\t\t\t\t// create error before stack unwound to get useful stacktrace later\n\t\t\t\t\tvar error = new Error();\n\t\t\t\t\tvar loadingEnded = function(event) {\n\t\t\t\t\t\tif(__webpack_require__.o(installedChunks, chunkId)) {\n\t\t\t\t\t\t\tinstalledChunkData = installedChunks[chunkId];\n\t\t\t\t\t\t\tif(installedChunkData !== 0) installedChunks[chunkId] = undefined;\n\t\t\t\t\t\t\tif(installedChunkData) {\n\t\t\t\t\t\t\t\tvar errorType = event && (event.type === 'load' ? 'missing' : event.type);\n\t\t\t\t\t\t\t\tvar realSrc = event && event.target && event.target.src;\n\t\t\t\t\t\t\t\terror.message = 'Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';\n\t\t\t\t\t\t\t\terror.name = 'ChunkLoadError';\n\t\t\t\t\t\t\t\terror.type = errorType;\n\t\t\t\t\t\t\t\terror.request = realSrc;\n\t\t\t\t\t\t\t\tinstalledChunkData[1](error);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t__webpack_require__.l(url, loadingEnded, \"chunk-\" + chunkId, chunkId);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n};\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n// no on chunks loaded\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunktinode_webapp\"] = self[\"webpackChunktinode_webapp\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","const getDefaultsFromPostinstall = () => (undefined);\nexport { getDefaultsFromPostinstall };","import { getDefaultsFromPostinstall } from './postinstall.mjs';\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * @fileoverview Firebase constants. Some of these (@defines) can be overridden at compile-time.\n */\nconst CONSTANTS = {\n /**\n * @define {boolean} Whether this is the client Node.js SDK.\n */\n NODE_CLIENT: false,\n /**\n * @define {boolean} Whether this is the Admin Node.js SDK.\n */\n NODE_ADMIN: false,\n /**\n * Firebase SDK Version\n */\n SDK_VERSION: '${JSCORE_VERSION}'\n};\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Throws an error if the provided assertion is falsy\n */\nconst assert = function (assertion, message) {\n if (!assertion) {\n throw assertionError(message);\n }\n};\n/**\n * Returns an Error object suitable for throwing.\n */\nconst assertionError = function (message) {\n return new Error('Firebase Database (' +\n CONSTANTS.SDK_VERSION +\n ') INTERNAL ASSERT FAILED: ' +\n message);\n};\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst stringToByteArray$1 = function (str) {\n // TODO(user): Use native implementations if/when available\n const out = [];\n let p = 0;\n for (let i = 0; i < str.length; i++) {\n let c = str.charCodeAt(i);\n if (c < 128) {\n out[p++] = c;\n }\n else if (c < 2048) {\n out[p++] = (c >> 6) | 192;\n out[p++] = (c & 63) | 128;\n }\n else if ((c & 0xfc00) === 0xd800 &&\n i + 1 < str.length &&\n (str.charCodeAt(i + 1) & 0xfc00) === 0xdc00) {\n // Surrogate Pair\n c = 0x10000 + ((c & 0x03ff) << 10) + (str.charCodeAt(++i) & 0x03ff);\n out[p++] = (c >> 18) | 240;\n out[p++] = ((c >> 12) & 63) | 128;\n out[p++] = ((c >> 6) & 63) | 128;\n out[p++] = (c & 63) | 128;\n }\n else {\n out[p++] = (c >> 12) | 224;\n out[p++] = ((c >> 6) & 63) | 128;\n out[p++] = (c & 63) | 128;\n }\n }\n return out;\n};\n/**\n * Turns an array of numbers into the string given by the concatenation of the\n * characters to which the numbers correspond.\n * @param bytes Array of numbers representing characters.\n * @return Stringification of the array.\n */\nconst byteArrayToString = function (bytes) {\n // TODO(user): Use native implementations if/when available\n const out = [];\n let pos = 0, c = 0;\n while (pos < bytes.length) {\n const c1 = bytes[pos++];\n if (c1 < 128) {\n out[c++] = String.fromCharCode(c1);\n }\n else if (c1 > 191 && c1 < 224) {\n const c2 = bytes[pos++];\n out[c++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));\n }\n else if (c1 > 239 && c1 < 365) {\n // Surrogate Pair\n const c2 = bytes[pos++];\n const c3 = bytes[pos++];\n const c4 = bytes[pos++];\n const u = (((c1 & 7) << 18) | ((c2 & 63) << 12) | ((c3 & 63) << 6) | (c4 & 63)) -\n 0x10000;\n out[c++] = String.fromCharCode(0xd800 + (u >> 10));\n out[c++] = String.fromCharCode(0xdc00 + (u & 1023));\n }\n else {\n const c2 = bytes[pos++];\n const c3 = bytes[pos++];\n out[c++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));\n }\n }\n return out.join('');\n};\n// We define it as an object literal instead of a class because a class compiled down to es5 can't\n// be treeshaked. https://github.com/rollup/rollup/issues/1691\n// Static lookup maps, lazily populated by init_()\n// TODO(dlarocque): Define this as a class, since we no longer target ES5.\nconst base64 = {\n /**\n * Maps bytes to characters.\n */\n byteToCharMap_: null,\n /**\n * Maps characters to bytes.\n */\n charToByteMap_: null,\n /**\n * Maps bytes to websafe characters.\n * @private\n */\n byteToCharMapWebSafe_: null,\n /**\n * Maps websafe characters to bytes.\n * @private\n */\n charToByteMapWebSafe_: null,\n /**\n * Our default alphabet, shared between\n * ENCODED_VALS and ENCODED_VALS_WEBSAFE\n */\n ENCODED_VALS_BASE: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '0123456789',\n /**\n * Our default alphabet. Value 64 (=) is special; it means \"nothing.\"\n */\n get ENCODED_VALS() {\n return this.ENCODED_VALS_BASE + '+/=';\n },\n /**\n * Our websafe alphabet.\n */\n get ENCODED_VALS_WEBSAFE() {\n return this.ENCODED_VALS_BASE + '-_.';\n },\n /**\n * Whether this browser supports the atob and btoa functions. This extension\n * started at Mozilla but is now implemented by many browsers. We use the\n * ASSUME_* variables to avoid pulling in the full useragent detection library\n * but still allowing the standard per-browser compilations.\n *\n */\n HAS_NATIVE_SUPPORT: typeof atob === 'function',\n /**\n * Base64-encode an array of bytes.\n *\n * @param input An array of bytes (numbers with\n * value in [0, 255]) to encode.\n * @param webSafe Boolean indicating we should use the\n * alternative alphabet.\n * @return The base64 encoded string.\n */\n encodeByteArray(input, webSafe) {\n if (!Array.isArray(input)) {\n throw Error('encodeByteArray takes an array as a parameter');\n }\n this.init_();\n const byteToCharMap = webSafe\n ? this.byteToCharMapWebSafe_\n : this.byteToCharMap_;\n const output = [];\n for (let i = 0; i < input.length; i += 3) {\n const byte1 = input[i];\n const haveByte2 = i + 1 < input.length;\n const byte2 = haveByte2 ? input[i + 1] : 0;\n const haveByte3 = i + 2 < input.length;\n const byte3 = haveByte3 ? input[i + 2] : 0;\n const outByte1 = byte1 >> 2;\n const outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4);\n let outByte3 = ((byte2 & 0x0f) << 2) | (byte3 >> 6);\n let outByte4 = byte3 & 0x3f;\n if (!haveByte3) {\n outByte4 = 64;\n if (!haveByte2) {\n outByte3 = 64;\n }\n }\n output.push(byteToCharMap[outByte1], byteToCharMap[outByte2], byteToCharMap[outByte3], byteToCharMap[outByte4]);\n }\n return output.join('');\n },\n /**\n * Base64-encode a string.\n *\n * @param input A string to encode.\n * @param webSafe If true, we should use the\n * alternative alphabet.\n * @return The base64 encoded string.\n */\n encodeString(input, webSafe) {\n // Shortcut for Mozilla browsers that implement\n // a native base64 encoder in the form of \"btoa/atob\"\n if (this.HAS_NATIVE_SUPPORT && !webSafe) {\n return btoa(input);\n }\n return this.encodeByteArray(stringToByteArray$1(input), webSafe);\n },\n /**\n * Base64-decode a string.\n *\n * @param input to decode.\n * @param webSafe True if we should use the\n * alternative alphabet.\n * @return string representing the decoded value.\n */\n decodeString(input, webSafe) {\n // Shortcut for Mozilla browsers that implement\n // a native base64 encoder in the form of \"btoa/atob\"\n if (this.HAS_NATIVE_SUPPORT && !webSafe) {\n return atob(input);\n }\n return byteArrayToString(this.decodeStringToByteArray(input, webSafe));\n },\n /**\n * Base64-decode a string.\n *\n * In base-64 decoding, groups of four characters are converted into three\n * bytes. If the encoder did not apply padding, the input length may not\n * be a multiple of 4.\n *\n * In this case, the last group will have fewer than 4 characters, and\n * padding will be inferred. If the group has one or two characters, it decodes\n * to one byte. If the group has three characters, it decodes to two bytes.\n *\n * @param input Input to decode.\n * @param webSafe True if we should use the web-safe alphabet.\n * @return bytes representing the decoded value.\n */\n decodeStringToByteArray(input, webSafe) {\n this.init_();\n const charToByteMap = webSafe\n ? this.charToByteMapWebSafe_\n : this.charToByteMap_;\n const output = [];\n for (let i = 0; i < input.length;) {\n const byte1 = charToByteMap[input.charAt(i++)];\n const haveByte2 = i < input.length;\n const byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0;\n ++i;\n const haveByte3 = i < input.length;\n const byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64;\n ++i;\n const haveByte4 = i < input.length;\n const byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64;\n ++i;\n if (byte1 == null || byte2 == null || byte3 == null || byte4 == null) {\n throw new DecodeBase64StringError();\n }\n const outByte1 = (byte1 << 2) | (byte2 >> 4);\n output.push(outByte1);\n if (byte3 !== 64) {\n const outByte2 = ((byte2 << 4) & 0xf0) | (byte3 >> 2);\n output.push(outByte2);\n if (byte4 !== 64) {\n const outByte3 = ((byte3 << 6) & 0xc0) | byte4;\n output.push(outByte3);\n }\n }\n }\n return output;\n },\n /**\n * Lazy static initialization function. Called before\n * accessing any of the static map variables.\n * @private\n */\n init_() {\n if (!this.byteToCharMap_) {\n this.byteToCharMap_ = {};\n this.charToByteMap_ = {};\n this.byteToCharMapWebSafe_ = {};\n this.charToByteMapWebSafe_ = {};\n // We want quick mappings back and forth, so we precompute two maps.\n for (let i = 0; i < this.ENCODED_VALS.length; i++) {\n this.byteToCharMap_[i] = this.ENCODED_VALS.charAt(i);\n this.charToByteMap_[this.byteToCharMap_[i]] = i;\n this.byteToCharMapWebSafe_[i] = this.ENCODED_VALS_WEBSAFE.charAt(i);\n this.charToByteMapWebSafe_[this.byteToCharMapWebSafe_[i]] = i;\n // Be forgiving when decoding and correctly decode both encodings.\n if (i >= this.ENCODED_VALS_BASE.length) {\n this.charToByteMap_[this.ENCODED_VALS_WEBSAFE.charAt(i)] = i;\n this.charToByteMapWebSafe_[this.ENCODED_VALS.charAt(i)] = i;\n }\n }\n }\n }\n};\n/**\n * An error encountered while decoding base64 string.\n */\nclass DecodeBase64StringError extends Error {\n constructor() {\n super(...arguments);\n this.name = 'DecodeBase64StringError';\n }\n}\n/**\n * URL-safe base64 encoding\n */\nconst base64Encode = function (str) {\n const utf8Bytes = stringToByteArray$1(str);\n return base64.encodeByteArray(utf8Bytes, true);\n};\n/**\n * URL-safe base64 encoding (without \".\" padding in the end).\n * e.g. Used in JSON Web Token (JWT) parts.\n */\nconst base64urlEncodeWithoutPadding = function (str) {\n // Use base64url encoding and remove padding in the end (dot characters).\n return base64Encode(str).replace(/\\./g, '');\n};\n/**\n * URL-safe base64 decoding\n *\n * NOTE: DO NOT use the global atob() function - it does NOT support the\n * base64Url variant encoding.\n *\n * @param str To be decoded\n * @return Decoded result, if possible\n */\nconst base64Decode = function (str) {\n try {\n return base64.decodeString(str, true);\n }\n catch (e) {\n console.error('base64Decode failed: ', e);\n }\n return null;\n};\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Do a deep-copy of basic JavaScript Objects or Arrays.\n */\nfunction deepCopy(value) {\n return deepExtend(undefined, value);\n}\n/**\n * Copy properties from source to target (recursively allows extension\n * of Objects and Arrays). Scalar values in the target are over-written.\n * If target is undefined, an object of the appropriate type will be created\n * (and returned).\n *\n * We recursively copy all child properties of plain Objects in the source- so\n * that namespace- like dictionaries are merged.\n *\n * Note that the target can be a function, in which case the properties in\n * the source Object are copied onto it as static properties of the Function.\n *\n * Note: we don't merge __proto__ to prevent prototype pollution\n */\nfunction deepExtend(target, source) {\n if (!(source instanceof Object)) {\n return source;\n }\n switch (source.constructor) {\n case Date:\n // Treat Dates like scalars; if the target date object had any child\n // properties - they will be lost!\n const dateValue = source;\n return new Date(dateValue.getTime());\n case Object:\n if (target === undefined) {\n target = {};\n }\n break;\n case Array:\n // Always copy the array source and overwrite the target.\n target = [];\n break;\n default:\n // Not a plain Object - treat it as a scalar.\n return source;\n }\n for (const prop in source) {\n // use isValidKey to guard against prototype pollution. See https://snyk.io/vuln/SNYK-JS-LODASH-450202\n if (!source.hasOwnProperty(prop) || !isValidKey(prop)) {\n continue;\n }\n target[prop] = deepExtend(target[prop], source[prop]);\n }\n return target;\n}\nfunction isValidKey(key) {\n return key !== '__proto__';\n}\n\n/**\n * @license\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Polyfill for `globalThis` object.\n * @returns the `globalThis` object for the given environment.\n * @public\n */\nfunction getGlobal() {\n if (typeof self !== 'undefined') {\n return self;\n }\n if (typeof window !== 'undefined') {\n return window;\n }\n if (typeof global !== 'undefined') {\n return global;\n }\n throw new Error('Unable to locate global object.');\n}\n\n/**\n * @license\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst getDefaultsFromGlobal = () => getGlobal().__FIREBASE_DEFAULTS__;\n/**\n * Attempt to read defaults from a JSON string provided to\n * process(.)env(.)__FIREBASE_DEFAULTS__ or a JSON file whose path is in\n * process(.)env(.)__FIREBASE_DEFAULTS_PATH__\n * The dots are in parens because certain compilers (Vite?) cannot\n * handle seeing that variable in comments.\n * See https://github.com/firebase/firebase-js-sdk/issues/6838\n */\nconst getDefaultsFromEnvVariable = () => {\n if (typeof process === 'undefined' || typeof process.env === 'undefined') {\n return;\n }\n const defaultsJsonString = process.env.__FIREBASE_DEFAULTS__;\n if (defaultsJsonString) {\n return JSON.parse(defaultsJsonString);\n }\n};\nconst getDefaultsFromCookie = () => {\n if (typeof document === 'undefined') {\n return;\n }\n let match;\n try {\n match = document.cookie.match(/__FIREBASE_DEFAULTS__=([^;]+)/);\n }\n catch (e) {\n // Some environments such as Angular Universal SSR have a\n // `document` object but error on accessing `document.cookie`.\n return;\n }\n const decoded = match && base64Decode(match[1]);\n return decoded && JSON.parse(decoded);\n};\n/**\n * Get the __FIREBASE_DEFAULTS__ object. It checks in order:\n * (1) if such an object exists as a property of `globalThis`\n * (2) if such an object was provided on a shell environment variable\n * (3) if such an object exists in a cookie\n * @public\n */\nconst getDefaults = () => {\n try {\n return (getDefaultsFromPostinstall() ||\n getDefaultsFromGlobal() ||\n getDefaultsFromEnvVariable() ||\n getDefaultsFromCookie());\n }\n catch (e) {\n /**\n * Catch-all for being unable to get __FIREBASE_DEFAULTS__ due\n * to any environment case we have not accounted for. Log to\n * info instead of swallowing so we can find these unknown cases\n * and add paths for them if needed.\n */\n console.info(`Unable to get __FIREBASE_DEFAULTS__ due to: ${e}`);\n return;\n }\n};\n/**\n * Returns emulator host stored in the __FIREBASE_DEFAULTS__ object\n * for the given product.\n * @returns a URL host formatted like `127.0.0.1:9999` or `[::1]:4000` if available\n * @public\n */\nconst getDefaultEmulatorHost = (productName) => { var _a, _b; return (_b = (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a.emulatorHosts) === null || _b === void 0 ? void 0 : _b[productName]; };\n/**\n * Returns emulator hostname and port stored in the __FIREBASE_DEFAULTS__ object\n * for the given product.\n * @returns a pair of hostname and port like `[\"::1\", 4000]` if available\n * @public\n */\nconst getDefaultEmulatorHostnameAndPort = (productName) => {\n const host = getDefaultEmulatorHost(productName);\n if (!host) {\n return undefined;\n }\n const separatorIndex = host.lastIndexOf(':'); // Finding the last since IPv6 addr also has colons.\n if (separatorIndex <= 0 || separatorIndex + 1 === host.length) {\n throw new Error(`Invalid host ${host} with no separate hostname and port!`);\n }\n // eslint-disable-next-line no-restricted-globals\n const port = parseInt(host.substring(separatorIndex + 1), 10);\n if (host[0] === '[') {\n // Bracket-quoted `[ipv6addr]:port` => return \"ipv6addr\" (without brackets).\n return [host.substring(1, separatorIndex - 1), port];\n }\n else {\n return [host.substring(0, separatorIndex), port];\n }\n};\n/**\n * Returns Firebase app config stored in the __FIREBASE_DEFAULTS__ object.\n * @public\n */\nconst getDefaultAppConfig = () => { var _a; return (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a.config; };\n/**\n * Returns an experimental setting on the __FIREBASE_DEFAULTS__ object (properties\n * prefixed by \"_\")\n * @public\n */\nconst getExperimentalSetting = (name) => { var _a; return (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a[`_${name}`]; };\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nclass Deferred {\n constructor() {\n this.reject = () => { };\n this.resolve = () => { };\n this.promise = new Promise((resolve, reject) => {\n this.resolve = resolve;\n this.reject = reject;\n });\n }\n /**\n * Our API internals are not promisified and cannot because our callback APIs have subtle expectations around\n * invoking promises inline, which Promises are forbidden to do. This method accepts an optional node-style callback\n * and returns a node-style callback which will resolve or reject the Deferred's promise.\n */\n wrapCallback(callback) {\n return (error, value) => {\n if (error) {\n this.reject(error);\n }\n else {\n this.resolve(value);\n }\n if (typeof callback === 'function') {\n // Attaching noop handler just in case developer wasn't expecting\n // promises\n this.promise.catch(() => { });\n // Some of our callbacks don't expect a value and our own tests\n // assert that the parameter length is 1\n if (callback.length === 1) {\n callback(error);\n }\n else {\n callback(error, value);\n }\n }\n };\n }\n}\n\n/**\n * @license\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Checks whether host is a cloud workstation or not.\n * @public\n */\nfunction isCloudWorkstation(url) {\n // `isCloudWorkstation` is called without protocol in certain connect*Emulator functions\n // In HTTP request builders, it's called with the protocol.\n // If called with protocol prefix, it's a valid URL, so we extract the hostname\n // If called without, we assume the string is the hostname.\n try {\n const host = url.startsWith('http://') || url.startsWith('https://')\n ? new URL(url).hostname\n : url;\n return host.endsWith('.cloudworkstations.dev');\n }\n catch (_a) {\n return false;\n }\n}\n/**\n * Makes a fetch request to the given server.\n * Mostly used for forwarding cookies in Firebase Studio.\n * @public\n */\nasync function pingServer(endpoint) {\n const result = await fetch(endpoint, {\n credentials: 'include'\n });\n return result.ok;\n}\n\n/**\n * @license\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction createMockUserToken(token, projectId) {\n if (token.uid) {\n throw new Error('The \"uid\" field is no longer supported by mockUserToken. Please use \"sub\" instead for Firebase Auth User ID.');\n }\n // Unsecured JWTs use \"none\" as the algorithm.\n const header = {\n alg: 'none',\n type: 'JWT'\n };\n const project = projectId || 'demo-project';\n const iat = token.iat || 0;\n const sub = token.sub || token.user_id;\n if (!sub) {\n throw new Error(\"mockUserToken must contain 'sub' or 'user_id' field!\");\n }\n const payload = Object.assign({ \n // Set all required fields to decent defaults\n iss: `https://securetoken.google.com/${project}`, aud: project, iat, exp: iat + 3600, auth_time: iat, sub, user_id: sub, firebase: {\n sign_in_provider: 'custom',\n identities: {}\n } }, token);\n // Unsecured JWTs use the empty string as a signature.\n const signature = '';\n return [\n base64urlEncodeWithoutPadding(JSON.stringify(header)),\n base64urlEncodeWithoutPadding(JSON.stringify(payload)),\n signature\n ].join('.');\n}\nconst emulatorStatus = {};\n// Checks whether any products are running on an emulator\nfunction getEmulatorSummary() {\n const summary = {\n prod: [],\n emulator: []\n };\n for (const key of Object.keys(emulatorStatus)) {\n if (emulatorStatus[key]) {\n summary.emulator.push(key);\n }\n else {\n summary.prod.push(key);\n }\n }\n return summary;\n}\nfunction getOrCreateEl(id) {\n let parentDiv = document.getElementById(id);\n let created = false;\n if (!parentDiv) {\n parentDiv = document.createElement('div');\n parentDiv.setAttribute('id', id);\n created = true;\n }\n return { created, element: parentDiv };\n}\nlet previouslyDismissed = false;\n/**\n * Updates Emulator Banner. Primarily used for Firebase Studio\n * @param name\n * @param isRunningEmulator\n * @public\n */\nfunction updateEmulatorBanner(name, isRunningEmulator) {\n if (typeof window === 'undefined' ||\n typeof document === 'undefined' ||\n !isCloudWorkstation(window.location.host) ||\n emulatorStatus[name] === isRunningEmulator ||\n emulatorStatus[name] || // If already set to use emulator, can't go back to prod.\n previouslyDismissed) {\n return;\n }\n emulatorStatus[name] = isRunningEmulator;\n function prefixedId(id) {\n return `__firebase__banner__${id}`;\n }\n const bannerId = '__firebase__banner';\n const summary = getEmulatorSummary();\n const showError = summary.prod.length > 0;\n function tearDown() {\n const element = document.getElementById(bannerId);\n if (element) {\n element.remove();\n }\n }\n function setupBannerStyles(bannerEl) {\n bannerEl.style.display = 'flex';\n bannerEl.style.background = '#7faaf0';\n bannerEl.style.position = 'fixed';\n bannerEl.style.bottom = '5px';\n bannerEl.style.left = '5px';\n bannerEl.style.padding = '.5em';\n bannerEl.style.borderRadius = '5px';\n bannerEl.style.alignItems = 'center';\n }\n function setupIconStyles(prependIcon, iconId) {\n prependIcon.setAttribute('width', '24');\n prependIcon.setAttribute('id', iconId);\n prependIcon.setAttribute('height', '24');\n prependIcon.setAttribute('viewBox', '0 0 24 24');\n prependIcon.setAttribute('fill', 'none');\n prependIcon.style.marginLeft = '-6px';\n }\n function setupCloseBtn() {\n const closeBtn = document.createElement('span');\n closeBtn.style.cursor = 'pointer';\n closeBtn.style.marginLeft = '16px';\n closeBtn.style.fontSize = '24px';\n closeBtn.innerHTML = ' ×';\n closeBtn.onclick = () => {\n previouslyDismissed = true;\n tearDown();\n };\n return closeBtn;\n }\n function setupLinkStyles(learnMoreLink, learnMoreId) {\n learnMoreLink.setAttribute('id', learnMoreId);\n learnMoreLink.innerText = 'Learn more';\n learnMoreLink.href =\n 'https://firebase.google.com/docs/studio/preview-apps#preview-backend';\n learnMoreLink.setAttribute('target', '__blank');\n learnMoreLink.style.paddingLeft = '5px';\n learnMoreLink.style.textDecoration = 'underline';\n }\n function setupDom() {\n const banner = getOrCreateEl(bannerId);\n const firebaseTextId = prefixedId('text');\n const firebaseText = document.getElementById(firebaseTextId) || document.createElement('span');\n const learnMoreId = prefixedId('learnmore');\n const learnMoreLink = document.getElementById(learnMoreId) ||\n document.createElement('a');\n const prependIconId = prefixedId('preprendIcon');\n const prependIcon = document.getElementById(prependIconId) ||\n document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n if (banner.created) {\n // update styles\n const bannerEl = banner.element;\n setupBannerStyles(bannerEl);\n setupLinkStyles(learnMoreLink, learnMoreId);\n const closeBtn = setupCloseBtn();\n setupIconStyles(prependIcon, prependIconId);\n bannerEl.append(prependIcon, firebaseText, learnMoreLink, closeBtn);\n document.body.appendChild(bannerEl);\n }\n if (showError) {\n firebaseText.innerText = `Preview backend disconnected.`;\n prependIcon.innerHTML = `\n\n \n\n\n\n \n `;\n }\n else {\n prependIcon.innerHTML = `\n\n \n\n\n\n \n `;\n firebaseText.innerText = 'Preview backend running in this workspace.';\n }\n firebaseText.setAttribute('id', firebaseTextId);\n }\n if (document.readyState === 'loading') {\n window.addEventListener('DOMContentLoaded', setupDom);\n }\n else {\n setupDom();\n }\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Returns navigator.userAgent string or '' if it's not defined.\n * @return user agent string\n */\nfunction getUA() {\n if (typeof navigator !== 'undefined' &&\n typeof navigator['userAgent'] === 'string') {\n return navigator['userAgent'];\n }\n else {\n return '';\n }\n}\n/**\n * Detect Cordova / PhoneGap / Ionic frameworks on a mobile device.\n *\n * Deliberately does not rely on checking `file://` URLs (as this fails PhoneGap\n * in the Ripple emulator) nor Cordova `onDeviceReady`, which would normally\n * wait for a callback.\n */\nfunction isMobileCordova() {\n return (typeof window !== 'undefined' &&\n // @ts-ignore Setting up an broadly applicable index signature for Window\n // just to deal with this case would probably be a bad idea.\n !!(window['cordova'] || window['phonegap'] || window['PhoneGap']) &&\n /ios|iphone|ipod|ipad|android|blackberry|iemobile/i.test(getUA()));\n}\n/**\n * Detect Node.js.\n *\n * @return true if Node.js environment is detected or specified.\n */\n// Node detection logic from: https://github.com/iliakan/detect-node/\nfunction isNode() {\n var _a;\n const forceEnvironment = (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a.forceEnvironment;\n if (forceEnvironment === 'node') {\n return true;\n }\n else if (forceEnvironment === 'browser') {\n return false;\n }\n try {\n return (Object.prototype.toString.call(global.process) === '[object process]');\n }\n catch (e) {\n return false;\n }\n}\n/**\n * Detect Browser Environment.\n * Note: This will return true for certain test frameworks that are incompletely\n * mimicking a browser, and should not lead to assuming all browser APIs are\n * available.\n */\nfunction isBrowser() {\n return typeof window !== 'undefined' || isWebWorker();\n}\n/**\n * Detect Web Worker context.\n */\nfunction isWebWorker() {\n return (typeof WorkerGlobalScope !== 'undefined' &&\n typeof self !== 'undefined' &&\n self instanceof WorkerGlobalScope);\n}\n/**\n * Detect Cloudflare Worker context.\n */\nfunction isCloudflareWorker() {\n return (typeof navigator !== 'undefined' &&\n navigator.userAgent === 'Cloudflare-Workers');\n}\nfunction isBrowserExtension() {\n const runtime = typeof chrome === 'object'\n ? chrome.runtime\n : typeof browser === 'object'\n ? browser.runtime\n : undefined;\n return typeof runtime === 'object' && runtime.id !== undefined;\n}\n/**\n * Detect React Native.\n *\n * @return true if ReactNative environment is detected.\n */\nfunction isReactNative() {\n return (typeof navigator === 'object' && navigator['product'] === 'ReactNative');\n}\n/** Detects Electron apps. */\nfunction isElectron() {\n return getUA().indexOf('Electron/') >= 0;\n}\n/** Detects Internet Explorer. */\nfunction isIE() {\n const ua = getUA();\n return ua.indexOf('MSIE ') >= 0 || ua.indexOf('Trident/') >= 0;\n}\n/** Detects Universal Windows Platform apps. */\nfunction isUWP() {\n return getUA().indexOf('MSAppHost/') >= 0;\n}\n/**\n * Detect whether the current SDK build is the Node version.\n *\n * @return true if it's the Node SDK build.\n */\nfunction isNodeSdk() {\n return CONSTANTS.NODE_CLIENT === true || CONSTANTS.NODE_ADMIN === true;\n}\n/** Returns true if we are running in Safari. */\nfunction isSafari() {\n return (!isNode() &&\n !!navigator.userAgent &&\n navigator.userAgent.includes('Safari') &&\n !navigator.userAgent.includes('Chrome'));\n}\n/** Returns true if we are running in Safari or WebKit */\nfunction isSafariOrWebkit() {\n return (!isNode() &&\n !!navigator.userAgent &&\n (navigator.userAgent.includes('Safari') ||\n navigator.userAgent.includes('WebKit')) &&\n !navigator.userAgent.includes('Chrome'));\n}\n/**\n * This method checks if indexedDB is supported by current browser/service worker context\n * @return true if indexedDB is supported by current browser/service worker context\n */\nfunction isIndexedDBAvailable() {\n try {\n return typeof indexedDB === 'object';\n }\n catch (e) {\n return false;\n }\n}\n/**\n * This method validates browser/sw context for indexedDB by opening a dummy indexedDB database and reject\n * if errors occur during the database open operation.\n *\n * @throws exception if current browser/sw context can't run idb.open (ex: Safari iframe, Firefox\n * private browsing)\n */\nfunction validateIndexedDBOpenable() {\n return new Promise((resolve, reject) => {\n try {\n let preExist = true;\n const DB_CHECK_NAME = 'validate-browser-context-for-indexeddb-analytics-module';\n const request = self.indexedDB.open(DB_CHECK_NAME);\n request.onsuccess = () => {\n request.result.close();\n // delete database only when it doesn't pre-exist\n if (!preExist) {\n self.indexedDB.deleteDatabase(DB_CHECK_NAME);\n }\n resolve(true);\n };\n request.onupgradeneeded = () => {\n preExist = false;\n };\n request.onerror = () => {\n var _a;\n reject(((_a = request.error) === null || _a === void 0 ? void 0 : _a.message) || '');\n };\n }\n catch (error) {\n reject(error);\n }\n });\n}\n/**\n *\n * This method checks whether cookie is enabled within current browser\n * @return true if cookie is enabled within current browser\n */\nfunction areCookiesEnabled() {\n if (typeof navigator === 'undefined' || !navigator.cookieEnabled) {\n return false;\n }\n return true;\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * @fileoverview Standardized Firebase Error.\n *\n * Usage:\n *\n * // TypeScript string literals for type-safe codes\n * type Err =\n * 'unknown' |\n * 'object-not-found'\n * ;\n *\n * // Closure enum for type-safe error codes\n * // at-enum {string}\n * var Err = {\n * UNKNOWN: 'unknown',\n * OBJECT_NOT_FOUND: 'object-not-found',\n * }\n *\n * let errors: Map = {\n * 'generic-error': \"Unknown error\",\n * 'file-not-found': \"Could not find file: {$file}\",\n * };\n *\n * // Type-safe function - must pass a valid error code as param.\n * let error = new ErrorFactory('service', 'Service', errors);\n *\n * ...\n * throw error.create(Err.GENERIC);\n * ...\n * throw error.create(Err.FILE_NOT_FOUND, {'file': fileName});\n * ...\n * // Service: Could not file file: foo.txt (service/file-not-found).\n *\n * catch (e) {\n * assert(e.message === \"Could not find file: foo.txt.\");\n * if ((e as FirebaseError)?.code === 'service/file-not-found') {\n * console.log(\"Could not read file: \" + e['file']);\n * }\n * }\n */\nconst ERROR_NAME = 'FirebaseError';\n// Based on code from:\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types\nclass FirebaseError extends Error {\n constructor(\n /** The error code for this error. */\n code, message, \n /** Custom data for this error. */\n customData) {\n super(message);\n this.code = code;\n this.customData = customData;\n /** The custom name for all FirebaseErrors. */\n this.name = ERROR_NAME;\n // Fix For ES5\n // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work\n // TODO(dlarocque): Replace this with `new.target`: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget\n // which we can now use since we no longer target ES5.\n Object.setPrototypeOf(this, FirebaseError.prototype);\n // Maintains proper stack trace for where our error was thrown.\n // Only available on V8.\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ErrorFactory.prototype.create);\n }\n }\n}\nclass ErrorFactory {\n constructor(service, serviceName, errors) {\n this.service = service;\n this.serviceName = serviceName;\n this.errors = errors;\n }\n create(code, ...data) {\n const customData = data[0] || {};\n const fullCode = `${this.service}/${code}`;\n const template = this.errors[code];\n const message = template ? replaceTemplate(template, customData) : 'Error';\n // Service Name: Error message (service/code).\n const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`;\n const error = new FirebaseError(fullCode, fullMessage, customData);\n return error;\n }\n}\nfunction replaceTemplate(template, data) {\n return template.replace(PATTERN, (_, key) => {\n const value = data[key];\n return value != null ? String(value) : `<${key}?>`;\n });\n}\nconst PATTERN = /\\{\\$([^}]+)}/g;\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Evaluates a JSON string into a javascript object.\n *\n * @param {string} str A string containing JSON.\n * @return {*} The javascript object representing the specified JSON.\n */\nfunction jsonEval(str) {\n return JSON.parse(str);\n}\n/**\n * Returns JSON representing a javascript object.\n * @param {*} data JavaScript object to be stringified.\n * @return {string} The JSON contents of the object.\n */\nfunction stringify(data) {\n return JSON.stringify(data);\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Decodes a Firebase auth. token into constituent parts.\n *\n * Notes:\n * - May return with invalid / incomplete claims if there's no native base64 decoding support.\n * - Doesn't check if the token is actually valid.\n */\nconst decode = function (token) {\n let header = {}, claims = {}, data = {}, signature = '';\n try {\n const parts = token.split('.');\n header = jsonEval(base64Decode(parts[0]) || '');\n claims = jsonEval(base64Decode(parts[1]) || '');\n signature = parts[2];\n data = claims['d'] || {};\n delete claims['d'];\n }\n catch (e) { }\n return {\n header,\n claims,\n data,\n signature\n };\n};\n/**\n * Decodes a Firebase auth. token and checks the validity of its time-based claims. Will return true if the\n * token is within the time window authorized by the 'nbf' (not-before) and 'iat' (issued-at) claims.\n *\n * Notes:\n * - May return a false negative if there's no native base64 decoding support.\n * - Doesn't check if the token is actually valid.\n */\nconst isValidTimestamp = function (token) {\n const claims = decode(token).claims;\n const now = Math.floor(new Date().getTime() / 1000);\n let validSince = 0, validUntil = 0;\n if (typeof claims === 'object') {\n if (claims.hasOwnProperty('nbf')) {\n validSince = claims['nbf'];\n }\n else if (claims.hasOwnProperty('iat')) {\n validSince = claims['iat'];\n }\n if (claims.hasOwnProperty('exp')) {\n validUntil = claims['exp'];\n }\n else {\n // token will expire after 24h by default\n validUntil = validSince + 86400;\n }\n }\n return (!!now &&\n !!validSince &&\n !!validUntil &&\n now >= validSince &&\n now <= validUntil);\n};\n/**\n * Decodes a Firebase auth. token and returns its issued at time if valid, null otherwise.\n *\n * Notes:\n * - May return null if there's no native base64 decoding support.\n * - Doesn't check if the token is actually valid.\n */\nconst issuedAtTime = function (token) {\n const claims = decode(token).claims;\n if (typeof claims === 'object' && claims.hasOwnProperty('iat')) {\n return claims['iat'];\n }\n return null;\n};\n/**\n * Decodes a Firebase auth. token and checks the validity of its format. Expects a valid issued-at time.\n *\n * Notes:\n * - May return a false negative if there's no native base64 decoding support.\n * - Doesn't check if the token is actually valid.\n */\nconst isValidFormat = function (token) {\n const decoded = decode(token), claims = decoded.claims;\n return !!claims && typeof claims === 'object' && claims.hasOwnProperty('iat');\n};\n/**\n * Attempts to peer into an auth token and determine if it's an admin auth token by looking at the claims portion.\n *\n * Notes:\n * - May return a false negative if there's no native base64 decoding support.\n * - Doesn't check if the token is actually valid.\n */\nconst isAdmin = function (token) {\n const claims = decode(token).claims;\n return typeof claims === 'object' && claims['admin'] === true;\n};\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction contains(obj, key) {\n return Object.prototype.hasOwnProperty.call(obj, key);\n}\nfunction safeGet(obj, key) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n return obj[key];\n }\n else {\n return undefined;\n }\n}\nfunction isEmpty(obj) {\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n return false;\n }\n }\n return true;\n}\nfunction map(obj, fn, contextObj) {\n const res = {};\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n res[key] = fn.call(contextObj, obj[key], key, obj);\n }\n }\n return res;\n}\n/**\n * Deep equal two objects. Support Arrays and Objects.\n */\nfunction deepEqual(a, b) {\n if (a === b) {\n return true;\n }\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n for (const k of aKeys) {\n if (!bKeys.includes(k)) {\n return false;\n }\n const aProp = a[k];\n const bProp = b[k];\n if (isObject(aProp) && isObject(bProp)) {\n if (!deepEqual(aProp, bProp)) {\n return false;\n }\n }\n else if (aProp !== bProp) {\n return false;\n }\n }\n for (const k of bKeys) {\n if (!aKeys.includes(k)) {\n return false;\n }\n }\n return true;\n}\nfunction isObject(thing) {\n return thing !== null && typeof thing === 'object';\n}\n\n/**\n * @license\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Rejects if the given promise doesn't resolve in timeInMS milliseconds.\n * @internal\n */\nfunction promiseWithTimeout(promise, timeInMS = 2000) {\n const deferredPromise = new Deferred();\n setTimeout(() => deferredPromise.reject('timeout!'), timeInMS);\n promise.then(deferredPromise.resolve, deferredPromise.reject);\n return deferredPromise.promise;\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Returns a querystring-formatted string (e.g. &arg=val&arg2=val2) from a\n * params object (e.g. {arg: 'val', arg2: 'val2'})\n * Note: You must prepend it with ? when adding it to a URL.\n */\nfunction querystring(querystringParams) {\n const params = [];\n for (const [key, value] of Object.entries(querystringParams)) {\n if (Array.isArray(value)) {\n value.forEach(arrayVal => {\n params.push(encodeURIComponent(key) + '=' + encodeURIComponent(arrayVal));\n });\n }\n else {\n params.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));\n }\n }\n return params.length ? '&' + params.join('&') : '';\n}\n/**\n * Decodes a querystring (e.g. ?arg=val&arg2=val2) into a params object\n * (e.g. {arg: 'val', arg2: 'val2'})\n */\nfunction querystringDecode(querystring) {\n const obj = {};\n const tokens = querystring.replace(/^\\?/, '').split('&');\n tokens.forEach(token => {\n if (token) {\n const [key, value] = token.split('=');\n obj[decodeURIComponent(key)] = decodeURIComponent(value);\n }\n });\n return obj;\n}\n/**\n * Extract the query string part of a URL, including the leading question mark (if present).\n */\nfunction extractQuerystring(url) {\n const queryStart = url.indexOf('?');\n if (!queryStart) {\n return '';\n }\n const fragmentStart = url.indexOf('#', queryStart);\n return url.substring(queryStart, fragmentStart > 0 ? fragmentStart : undefined);\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * @fileoverview SHA-1 cryptographic hash.\n * Variable names follow the notation in FIPS PUB 180-3:\n * http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.\n *\n * Usage:\n * var sha1 = new sha1();\n * sha1.update(bytes);\n * var hash = sha1.digest();\n *\n * Performance:\n * Chrome 23: ~400 Mbit/s\n * Firefox 16: ~250 Mbit/s\n *\n */\n/**\n * SHA-1 cryptographic hash constructor.\n *\n * The properties declared here are discussed in the above algorithm document.\n * @constructor\n * @final\n * @struct\n */\nclass Sha1 {\n constructor() {\n /**\n * Holds the previous values of accumulated variables a-e in the compress_\n * function.\n * @private\n */\n this.chain_ = [];\n /**\n * A buffer holding the partially computed hash result.\n * @private\n */\n this.buf_ = [];\n /**\n * An array of 80 bytes, each a part of the message to be hashed. Referred to\n * as the message schedule in the docs.\n * @private\n */\n this.W_ = [];\n /**\n * Contains data needed to pad messages less than 64 bytes.\n * @private\n */\n this.pad_ = [];\n /**\n * @private {number}\n */\n this.inbuf_ = 0;\n /**\n * @private {number}\n */\n this.total_ = 0;\n this.blockSize = 512 / 8;\n this.pad_[0] = 128;\n for (let i = 1; i < this.blockSize; ++i) {\n this.pad_[i] = 0;\n }\n this.reset();\n }\n reset() {\n this.chain_[0] = 0x67452301;\n this.chain_[1] = 0xefcdab89;\n this.chain_[2] = 0x98badcfe;\n this.chain_[3] = 0x10325476;\n this.chain_[4] = 0xc3d2e1f0;\n this.inbuf_ = 0;\n this.total_ = 0;\n }\n /**\n * Internal compress helper function.\n * @param buf Block to compress.\n * @param offset Offset of the block in the buffer.\n * @private\n */\n compress_(buf, offset) {\n if (!offset) {\n offset = 0;\n }\n const W = this.W_;\n // get 16 big endian words\n if (typeof buf === 'string') {\n for (let i = 0; i < 16; i++) {\n // TODO(user): [bug 8140122] Recent versions of Safari for Mac OS and iOS\n // have a bug that turns the post-increment ++ operator into pre-increment\n // during JIT compilation. We have code that depends heavily on SHA-1 for\n // correctness and which is affected by this bug, so I've removed all uses\n // of post-increment ++ in which the result value is used. We can revert\n // this change once the Safari bug\n // (https://bugs.webkit.org/show_bug.cgi?id=109036) has been fixed and\n // most clients have been updated.\n W[i] =\n (buf.charCodeAt(offset) << 24) |\n (buf.charCodeAt(offset + 1) << 16) |\n (buf.charCodeAt(offset + 2) << 8) |\n buf.charCodeAt(offset + 3);\n offset += 4;\n }\n }\n else {\n for (let i = 0; i < 16; i++) {\n W[i] =\n (buf[offset] << 24) |\n (buf[offset + 1] << 16) |\n (buf[offset + 2] << 8) |\n buf[offset + 3];\n offset += 4;\n }\n }\n // expand to 80 words\n for (let i = 16; i < 80; i++) {\n const t = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];\n W[i] = ((t << 1) | (t >>> 31)) & 0xffffffff;\n }\n let a = this.chain_[0];\n let b = this.chain_[1];\n let c = this.chain_[2];\n let d = this.chain_[3];\n let e = this.chain_[4];\n let f, k;\n // TODO(user): Try to unroll this loop to speed up the computation.\n for (let i = 0; i < 80; i++) {\n if (i < 40) {\n if (i < 20) {\n f = d ^ (b & (c ^ d));\n k = 0x5a827999;\n }\n else {\n f = b ^ c ^ d;\n k = 0x6ed9eba1;\n }\n }\n else {\n if (i < 60) {\n f = (b & c) | (d & (b | c));\n k = 0x8f1bbcdc;\n }\n else {\n f = b ^ c ^ d;\n k = 0xca62c1d6;\n }\n }\n const t = (((a << 5) | (a >>> 27)) + f + e + k + W[i]) & 0xffffffff;\n e = d;\n d = c;\n c = ((b << 30) | (b >>> 2)) & 0xffffffff;\n b = a;\n a = t;\n }\n this.chain_[0] = (this.chain_[0] + a) & 0xffffffff;\n this.chain_[1] = (this.chain_[1] + b) & 0xffffffff;\n this.chain_[2] = (this.chain_[2] + c) & 0xffffffff;\n this.chain_[3] = (this.chain_[3] + d) & 0xffffffff;\n this.chain_[4] = (this.chain_[4] + e) & 0xffffffff;\n }\n update(bytes, length) {\n // TODO(johnlenz): tighten the function signature and remove this check\n if (bytes == null) {\n return;\n }\n if (length === undefined) {\n length = bytes.length;\n }\n const lengthMinusBlock = length - this.blockSize;\n let n = 0;\n // Using local instead of member variables gives ~5% speedup on Firefox 16.\n const buf = this.buf_;\n let inbuf = this.inbuf_;\n // The outer while loop should execute at most twice.\n while (n < length) {\n // When we have no data in the block to top up, we can directly process the\n // input buffer (assuming it contains sufficient data). This gives ~25%\n // speedup on Chrome 23 and ~15% speedup on Firefox 16, but requires that\n // the data is provided in large chunks (or in multiples of 64 bytes).\n if (inbuf === 0) {\n while (n <= lengthMinusBlock) {\n this.compress_(bytes, n);\n n += this.blockSize;\n }\n }\n if (typeof bytes === 'string') {\n while (n < length) {\n buf[inbuf] = bytes.charCodeAt(n);\n ++inbuf;\n ++n;\n if (inbuf === this.blockSize) {\n this.compress_(buf);\n inbuf = 0;\n // Jump to the outer loop so we use the full-block optimization.\n break;\n }\n }\n }\n else {\n while (n < length) {\n buf[inbuf] = bytes[n];\n ++inbuf;\n ++n;\n if (inbuf === this.blockSize) {\n this.compress_(buf);\n inbuf = 0;\n // Jump to the outer loop so we use the full-block optimization.\n break;\n }\n }\n }\n }\n this.inbuf_ = inbuf;\n this.total_ += length;\n }\n /** @override */\n digest() {\n const digest = [];\n let totalBits = this.total_ * 8;\n // Add pad 0x80 0x00*.\n if (this.inbuf_ < 56) {\n this.update(this.pad_, 56 - this.inbuf_);\n }\n else {\n this.update(this.pad_, this.blockSize - (this.inbuf_ - 56));\n }\n // Add # bits.\n for (let i = this.blockSize - 1; i >= 56; i--) {\n this.buf_[i] = totalBits & 255;\n totalBits /= 256; // Don't use bit-shifting here!\n }\n this.compress_(this.buf_);\n let n = 0;\n for (let i = 0; i < 5; i++) {\n for (let j = 24; j >= 0; j -= 8) {\n digest[n] = (this.chain_[i] >> j) & 255;\n ++n;\n }\n }\n return digest;\n }\n}\n\n/**\n * Helper to make a Subscribe function (just like Promise helps make a\n * Thenable).\n *\n * @param executor Function which can make calls to a single Observer\n * as a proxy.\n * @param onNoObservers Callback when count of Observers goes to zero.\n */\nfunction createSubscribe(executor, onNoObservers) {\n const proxy = new ObserverProxy(executor, onNoObservers);\n return proxy.subscribe.bind(proxy);\n}\n/**\n * Implement fan-out for any number of Observers attached via a subscribe\n * function.\n */\nclass ObserverProxy {\n /**\n * @param executor Function which can make calls to a single Observer\n * as a proxy.\n * @param onNoObservers Callback when count of Observers goes to zero.\n */\n constructor(executor, onNoObservers) {\n this.observers = [];\n this.unsubscribes = [];\n this.observerCount = 0;\n // Micro-task scheduling by calling task.then().\n this.task = Promise.resolve();\n this.finalized = false;\n this.onNoObservers = onNoObservers;\n // Call the executor asynchronously so subscribers that are called\n // synchronously after the creation of the subscribe function\n // can still receive the very first value generated in the executor.\n this.task\n .then(() => {\n executor(this);\n })\n .catch(e => {\n this.error(e);\n });\n }\n next(value) {\n this.forEachObserver((observer) => {\n observer.next(value);\n });\n }\n error(error) {\n this.forEachObserver((observer) => {\n observer.error(error);\n });\n this.close(error);\n }\n complete() {\n this.forEachObserver((observer) => {\n observer.complete();\n });\n this.close();\n }\n /**\n * Subscribe function that can be used to add an Observer to the fan-out list.\n *\n * - We require that no event is sent to a subscriber synchronously to their\n * call to subscribe().\n */\n subscribe(nextOrObserver, error, complete) {\n let observer;\n if (nextOrObserver === undefined &&\n error === undefined &&\n complete === undefined) {\n throw new Error('Missing Observer.');\n }\n // Assemble an Observer object when passed as callback functions.\n if (implementsAnyMethods(nextOrObserver, [\n 'next',\n 'error',\n 'complete'\n ])) {\n observer = nextOrObserver;\n }\n else {\n observer = {\n next: nextOrObserver,\n error,\n complete\n };\n }\n if (observer.next === undefined) {\n observer.next = noop;\n }\n if (observer.error === undefined) {\n observer.error = noop;\n }\n if (observer.complete === undefined) {\n observer.complete = noop;\n }\n const unsub = this.unsubscribeOne.bind(this, this.observers.length);\n // Attempt to subscribe to a terminated Observable - we\n // just respond to the Observer with the final error or complete\n // event.\n if (this.finalized) {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.task.then(() => {\n try {\n if (this.finalError) {\n observer.error(this.finalError);\n }\n else {\n observer.complete();\n }\n }\n catch (e) {\n // nothing\n }\n return;\n });\n }\n this.observers.push(observer);\n return unsub;\n }\n // Unsubscribe is synchronous - we guarantee that no events are sent to\n // any unsubscribed Observer.\n unsubscribeOne(i) {\n if (this.observers === undefined || this.observers[i] === undefined) {\n return;\n }\n delete this.observers[i];\n this.observerCount -= 1;\n if (this.observerCount === 0 && this.onNoObservers !== undefined) {\n this.onNoObservers(this);\n }\n }\n forEachObserver(fn) {\n if (this.finalized) {\n // Already closed by previous event....just eat the additional values.\n return;\n }\n // Since sendOne calls asynchronously - there is no chance that\n // this.observers will become undefined.\n for (let i = 0; i < this.observers.length; i++) {\n this.sendOne(i, fn);\n }\n }\n // Call the Observer via one of it's callback function. We are careful to\n // confirm that the observe has not been unsubscribed since this asynchronous\n // function had been queued.\n sendOne(i, fn) {\n // Execute the callback asynchronously\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.task.then(() => {\n if (this.observers !== undefined && this.observers[i] !== undefined) {\n try {\n fn(this.observers[i]);\n }\n catch (e) {\n // Ignore exceptions raised in Observers or missing methods of an\n // Observer.\n // Log error to console. b/31404806\n if (typeof console !== 'undefined' && console.error) {\n console.error(e);\n }\n }\n }\n });\n }\n close(err) {\n if (this.finalized) {\n return;\n }\n this.finalized = true;\n if (err !== undefined) {\n this.finalError = err;\n }\n // Proxy is no longer needed - garbage collect references\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.task.then(() => {\n this.observers = undefined;\n this.onNoObservers = undefined;\n });\n }\n}\n/** Turn synchronous function into one called asynchronously. */\n// eslint-disable-next-line @typescript-eslint/ban-types\nfunction async(fn, onError) {\n return (...args) => {\n Promise.resolve(true)\n .then(() => {\n fn(...args);\n })\n .catch((error) => {\n if (onError) {\n onError(error);\n }\n });\n };\n}\n/**\n * Return true if the object passed in implements any of the named methods.\n */\nfunction implementsAnyMethods(obj, methods) {\n if (typeof obj !== 'object' || obj === null) {\n return false;\n }\n for (const method of methods) {\n if (method in obj && typeof obj[method] === 'function') {\n return true;\n }\n }\n return false;\n}\nfunction noop() {\n // do nothing\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Check to make sure the appropriate number of arguments are provided for a public function.\n * Throws an error if it fails.\n *\n * @param fnName The function name\n * @param minCount The minimum number of arguments to allow for the function call\n * @param maxCount The maximum number of argument to allow for the function call\n * @param argCount The actual number of arguments provided.\n */\nconst validateArgCount = function (fnName, minCount, maxCount, argCount) {\n let argError;\n if (argCount < minCount) {\n argError = 'at least ' + minCount;\n }\n else if (argCount > maxCount) {\n argError = maxCount === 0 ? 'none' : 'no more than ' + maxCount;\n }\n if (argError) {\n const error = fnName +\n ' failed: Was called with ' +\n argCount +\n (argCount === 1 ? ' argument.' : ' arguments.') +\n ' Expects ' +\n argError +\n '.';\n throw new Error(error);\n }\n};\n/**\n * Generates a string to prefix an error message about failed argument validation\n *\n * @param fnName The function name\n * @param argName The name of the argument\n * @return The prefix to add to the error thrown for validation.\n */\nfunction errorPrefix(fnName, argName) {\n return `${fnName} failed: ${argName} argument `;\n}\n/**\n * @param fnName\n * @param argumentNumber\n * @param namespace\n * @param optional\n */\nfunction validateNamespace(fnName, namespace, optional) {\n if (optional && !namespace) {\n return;\n }\n if (typeof namespace !== 'string') {\n //TODO: I should do more validation here. We only allow certain chars in namespaces.\n throw new Error(errorPrefix(fnName, 'namespace') + 'must be a valid firebase namespace.');\n }\n}\nfunction validateCallback(fnName, argumentName, \n// eslint-disable-next-line @typescript-eslint/ban-types\ncallback, optional) {\n if (optional && !callback) {\n return;\n }\n if (typeof callback !== 'function') {\n throw new Error(errorPrefix(fnName, argumentName) + 'must be a valid function.');\n }\n}\nfunction validateContextObject(fnName, argumentName, context, optional) {\n if (optional && !context) {\n return;\n }\n if (typeof context !== 'object' || context === null) {\n throw new Error(errorPrefix(fnName, argumentName) + 'must be a valid context object.');\n }\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// Code originally came from goog.crypt.stringToUtf8ByteArray, but for some reason they\n// automatically replaced '\\r\\n' with '\\n', and they didn't handle surrogate pairs,\n// so it's been modified.\n// Note that not all Unicode characters appear as single characters in JavaScript strings.\n// fromCharCode returns the UTF-16 encoding of a character - so some Unicode characters\n// use 2 characters in JavaScript. All 4-byte UTF-8 characters begin with a first\n// character in the range 0xD800 - 0xDBFF (the first character of a so-called surrogate\n// pair).\n// See http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3\n/**\n * @param {string} str\n * @return {Array}\n */\nconst stringToByteArray = function (str) {\n const out = [];\n let p = 0;\n for (let i = 0; i < str.length; i++) {\n let c = str.charCodeAt(i);\n // Is this the lead surrogate in a surrogate pair?\n if (c >= 0xd800 && c <= 0xdbff) {\n const high = c - 0xd800; // the high 10 bits.\n i++;\n assert(i < str.length, 'Surrogate pair missing trail surrogate.');\n const low = str.charCodeAt(i) - 0xdc00; // the low 10 bits.\n c = 0x10000 + (high << 10) + low;\n }\n if (c < 128) {\n out[p++] = c;\n }\n else if (c < 2048) {\n out[p++] = (c >> 6) | 192;\n out[p++] = (c & 63) | 128;\n }\n else if (c < 65536) {\n out[p++] = (c >> 12) | 224;\n out[p++] = ((c >> 6) & 63) | 128;\n out[p++] = (c & 63) | 128;\n }\n else {\n out[p++] = (c >> 18) | 240;\n out[p++] = ((c >> 12) & 63) | 128;\n out[p++] = ((c >> 6) & 63) | 128;\n out[p++] = (c & 63) | 128;\n }\n }\n return out;\n};\n/**\n * Calculate length without actually converting; useful for doing cheaper validation.\n * @param {string} str\n * @return {number}\n */\nconst stringLength = function (str) {\n let p = 0;\n for (let i = 0; i < str.length; i++) {\n const c = str.charCodeAt(i);\n if (c < 128) {\n p++;\n }\n else if (c < 2048) {\n p += 2;\n }\n else if (c >= 0xd800 && c <= 0xdbff) {\n // Lead surrogate of a surrogate pair. The pair together will take 4 bytes to represent.\n p += 4;\n i++; // skip trail surrogate.\n }\n else {\n p += 3;\n }\n }\n return p;\n};\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * The amount of milliseconds to exponentially increase.\n */\nconst DEFAULT_INTERVAL_MILLIS = 1000;\n/**\n * The factor to backoff by.\n * Should be a number greater than 1.\n */\nconst DEFAULT_BACKOFF_FACTOR = 2;\n/**\n * The maximum milliseconds to increase to.\n *\n * Visible for testing\n */\nconst MAX_VALUE_MILLIS = 4 * 60 * 60 * 1000; // Four hours, like iOS and Android.\n/**\n * The percentage of backoff time to randomize by.\n * See\n * http://go/safe-client-behavior#step-1-determine-the-appropriate-retry-interval-to-handle-spike-traffic\n * for context.\n *\n *
Visible for testing\n */\nconst RANDOM_FACTOR = 0.5;\n/**\n * Based on the backoff method from\n * https://github.com/google/closure-library/blob/master/closure/goog/math/exponentialbackoff.js.\n * Extracted here so we don't need to pass metadata and a stateful ExponentialBackoff object around.\n */\nfunction calculateBackoffMillis(backoffCount, intervalMillis = DEFAULT_INTERVAL_MILLIS, backoffFactor = DEFAULT_BACKOFF_FACTOR) {\n // Calculates an exponentially increasing value.\n // Deviation: calculates value from count and a constant interval, so we only need to save value\n // and count to restore state.\n const currBaseValue = intervalMillis * Math.pow(backoffFactor, backoffCount);\n // A random \"fuzz\" to avoid waves of retries.\n // Deviation: randomFactor is required.\n const randomWait = Math.round(\n // A fraction of the backoff value to add/subtract.\n // Deviation: changes multiplication order to improve readability.\n RANDOM_FACTOR *\n currBaseValue *\n // A random float (rounded to int by Math.round above) in the range [-1, 1]. Determines\n // if we add or subtract.\n (Math.random() - 0.5) *\n 2);\n // Limits backoff to max to avoid effectively permanent backoff.\n return Math.min(MAX_VALUE_MILLIS, currBaseValue + randomWait);\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Provide English ordinal letters after a number\n */\nfunction ordinal(i) {\n if (!Number.isFinite(i)) {\n return `${i}`;\n }\n return i + indicator(i);\n}\nfunction indicator(i) {\n i = Math.abs(i);\n const cent = i % 100;\n if (cent >= 10 && cent <= 20) {\n return 'th';\n }\n const dec = i % 10;\n if (dec === 1) {\n return 'st';\n }\n if (dec === 2) {\n return 'nd';\n }\n if (dec === 3) {\n return 'rd';\n }\n return 'th';\n}\n\n/**\n * @license\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction getModularInstance(service) {\n if (service && service._delegate) {\n return service._delegate;\n }\n else {\n return service;\n }\n}\n\nexport { CONSTANTS, DecodeBase64StringError, Deferred, ErrorFactory, FirebaseError, MAX_VALUE_MILLIS, RANDOM_FACTOR, Sha1, areCookiesEnabled, assert, assertionError, async, base64, base64Decode, base64Encode, base64urlEncodeWithoutPadding, calculateBackoffMillis, contains, createMockUserToken, createSubscribe, decode, deepCopy, deepEqual, deepExtend, errorPrefix, extractQuerystring, getDefaultAppConfig, getDefaultEmulatorHost, getDefaultEmulatorHostnameAndPort, getDefaults, getExperimentalSetting, getGlobal, getModularInstance, getUA, isAdmin, isBrowser, isBrowserExtension, isCloudWorkstation, isCloudflareWorker, isElectron, isEmpty, isIE, isIndexedDBAvailable, isMobileCordova, isNode, isNodeSdk, isReactNative, isSafari, isSafariOrWebkit, isUWP, isValidFormat, isValidTimestamp, isWebWorker, issuedAtTime, jsonEval, map, ordinal, pingServer, promiseWithTimeout, querystring, querystringDecode, safeGet, stringLength, stringToByteArray, stringify, updateEmulatorBanner, validateArgCount, validateCallback, validateContextObject, validateIndexedDBOpenable, validateNamespace };\n//# sourceMappingURL=index.esm2017.js.map\n","import { Deferred } from '@firebase/util';\n\n/**\n * Component for service name T, e.g. `auth`, `auth-internal`\n */\nclass Component {\n /**\n *\n * @param name The public service name, e.g. app, auth, firestore, database\n * @param instanceFactory Service factory responsible for creating the public interface\n * @param type whether the service provided by the component is public or private\n */\n constructor(name, instanceFactory, type) {\n this.name = name;\n this.instanceFactory = instanceFactory;\n this.type = type;\n this.multipleInstances = false;\n /**\n * Properties to be added to the service namespace\n */\n this.serviceProps = {};\n this.instantiationMode = \"LAZY\" /* InstantiationMode.LAZY */;\n this.onInstanceCreated = null;\n }\n setInstantiationMode(mode) {\n this.instantiationMode = mode;\n return this;\n }\n setMultipleInstances(multipleInstances) {\n this.multipleInstances = multipleInstances;\n return this;\n }\n setServiceProps(props) {\n this.serviceProps = props;\n return this;\n }\n setInstanceCreatedCallback(callback) {\n this.onInstanceCreated = callback;\n return this;\n }\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst DEFAULT_ENTRY_NAME = '[DEFAULT]';\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Provider for instance for service name T, e.g. 'auth', 'auth-internal'\n * NameServiceMapping[T] is an alias for the type of the instance\n */\nclass Provider {\n constructor(name, container) {\n this.name = name;\n this.container = container;\n this.component = null;\n this.instances = new Map();\n this.instancesDeferred = new Map();\n this.instancesOptions = new Map();\n this.onInitCallbacks = new Map();\n }\n /**\n * @param identifier A provider can provide multiple instances of a service\n * if this.component.multipleInstances is true.\n */\n get(identifier) {\n // if multipleInstances is not supported, use the default name\n const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);\n if (!this.instancesDeferred.has(normalizedIdentifier)) {\n const deferred = new Deferred();\n this.instancesDeferred.set(normalizedIdentifier, deferred);\n if (this.isInitialized(normalizedIdentifier) ||\n this.shouldAutoInitialize()) {\n // initialize the service if it can be auto-initialized\n try {\n const instance = this.getOrInitializeService({\n instanceIdentifier: normalizedIdentifier\n });\n if (instance) {\n deferred.resolve(instance);\n }\n }\n catch (e) {\n // when the instance factory throws an exception during get(), it should not cause\n // a fatal error. We just return the unresolved promise in this case.\n }\n }\n }\n return this.instancesDeferred.get(normalizedIdentifier).promise;\n }\n getImmediate(options) {\n var _a;\n // if multipleInstances is not supported, use the default name\n const normalizedIdentifier = this.normalizeInstanceIdentifier(options === null || options === void 0 ? void 0 : options.identifier);\n const optional = (_a = options === null || options === void 0 ? void 0 : options.optional) !== null && _a !== void 0 ? _a : false;\n if (this.isInitialized(normalizedIdentifier) ||\n this.shouldAutoInitialize()) {\n try {\n return this.getOrInitializeService({\n instanceIdentifier: normalizedIdentifier\n });\n }\n catch (e) {\n if (optional) {\n return null;\n }\n else {\n throw e;\n }\n }\n }\n else {\n // In case a component is not initialized and should/cannot be auto-initialized at the moment, return null if the optional flag is set, or throw\n if (optional) {\n return null;\n }\n else {\n throw Error(`Service ${this.name} is not available`);\n }\n }\n }\n getComponent() {\n return this.component;\n }\n setComponent(component) {\n if (component.name !== this.name) {\n throw Error(`Mismatching Component ${component.name} for Provider ${this.name}.`);\n }\n if (this.component) {\n throw Error(`Component for ${this.name} has already been provided`);\n }\n this.component = component;\n // return early without attempting to initialize the component if the component requires explicit initialization (calling `Provider.initialize()`)\n if (!this.shouldAutoInitialize()) {\n return;\n }\n // if the service is eager, initialize the default instance\n if (isComponentEager(component)) {\n try {\n this.getOrInitializeService({ instanceIdentifier: DEFAULT_ENTRY_NAME });\n }\n catch (e) {\n // when the instance factory for an eager Component throws an exception during the eager\n // initialization, it should not cause a fatal error.\n // TODO: Investigate if we need to make it configurable, because some component may want to cause\n // a fatal error in this case?\n }\n }\n // Create service instances for the pending promises and resolve them\n // NOTE: if this.multipleInstances is false, only the default instance will be created\n // and all promises with resolve with it regardless of the identifier.\n for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {\n const normalizedIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);\n try {\n // `getOrInitializeService()` should always return a valid instance since a component is guaranteed. use ! to make typescript happy.\n const instance = this.getOrInitializeService({\n instanceIdentifier: normalizedIdentifier\n });\n instanceDeferred.resolve(instance);\n }\n catch (e) {\n // when the instance factory throws an exception, it should not cause\n // a fatal error. We just leave the promise unresolved.\n }\n }\n }\n clearInstance(identifier = DEFAULT_ENTRY_NAME) {\n this.instancesDeferred.delete(identifier);\n this.instancesOptions.delete(identifier);\n this.instances.delete(identifier);\n }\n // app.delete() will call this method on every provider to delete the services\n // TODO: should we mark the provider as deleted?\n async delete() {\n const services = Array.from(this.instances.values());\n await Promise.all([\n ...services\n .filter(service => 'INTERNAL' in service) // legacy services\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n .map(service => service.INTERNAL.delete()),\n ...services\n .filter(service => '_delete' in service) // modularized services\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n .map(service => service._delete())\n ]);\n }\n isComponentSet() {\n return this.component != null;\n }\n isInitialized(identifier = DEFAULT_ENTRY_NAME) {\n return this.instances.has(identifier);\n }\n getOptions(identifier = DEFAULT_ENTRY_NAME) {\n return this.instancesOptions.get(identifier) || {};\n }\n initialize(opts = {}) {\n const { options = {} } = opts;\n const normalizedIdentifier = this.normalizeInstanceIdentifier(opts.instanceIdentifier);\n if (this.isInitialized(normalizedIdentifier)) {\n throw Error(`${this.name}(${normalizedIdentifier}) has already been initialized`);\n }\n if (!this.isComponentSet()) {\n throw Error(`Component ${this.name} has not been registered yet`);\n }\n const instance = this.getOrInitializeService({\n instanceIdentifier: normalizedIdentifier,\n options\n });\n // resolve any pending promise waiting for the service instance\n for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {\n const normalizedDeferredIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);\n if (normalizedIdentifier === normalizedDeferredIdentifier) {\n instanceDeferred.resolve(instance);\n }\n }\n return instance;\n }\n /**\n *\n * @param callback - a function that will be invoked after the provider has been initialized by calling provider.initialize().\n * The function is invoked SYNCHRONOUSLY, so it should not execute any longrunning tasks in order to not block the program.\n *\n * @param identifier An optional instance identifier\n * @returns a function to unregister the callback\n */\n onInit(callback, identifier) {\n var _a;\n const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);\n const existingCallbacks = (_a = this.onInitCallbacks.get(normalizedIdentifier)) !== null && _a !== void 0 ? _a : new Set();\n existingCallbacks.add(callback);\n this.onInitCallbacks.set(normalizedIdentifier, existingCallbacks);\n const existingInstance = this.instances.get(normalizedIdentifier);\n if (existingInstance) {\n callback(existingInstance, normalizedIdentifier);\n }\n return () => {\n existingCallbacks.delete(callback);\n };\n }\n /**\n * Invoke onInit callbacks synchronously\n * @param instance the service instance`\n */\n invokeOnInitCallbacks(instance, identifier) {\n const callbacks = this.onInitCallbacks.get(identifier);\n if (!callbacks) {\n return;\n }\n for (const callback of callbacks) {\n try {\n callback(instance, identifier);\n }\n catch (_a) {\n // ignore errors in the onInit callback\n }\n }\n }\n getOrInitializeService({ instanceIdentifier, options = {} }) {\n let instance = this.instances.get(instanceIdentifier);\n if (!instance && this.component) {\n instance = this.component.instanceFactory(this.container, {\n instanceIdentifier: normalizeIdentifierForFactory(instanceIdentifier),\n options\n });\n this.instances.set(instanceIdentifier, instance);\n this.instancesOptions.set(instanceIdentifier, options);\n /**\n * Invoke onInit listeners.\n * Note this.component.onInstanceCreated is different, which is used by the component creator,\n * while onInit listeners are registered by consumers of the provider.\n */\n this.invokeOnInitCallbacks(instance, instanceIdentifier);\n /**\n * Order is important\n * onInstanceCreated() should be called after this.instances.set(instanceIdentifier, instance); which\n * makes `isInitialized()` return true.\n */\n if (this.component.onInstanceCreated) {\n try {\n this.component.onInstanceCreated(this.container, instanceIdentifier, instance);\n }\n catch (_a) {\n // ignore errors in the onInstanceCreatedCallback\n }\n }\n }\n return instance || null;\n }\n normalizeInstanceIdentifier(identifier = DEFAULT_ENTRY_NAME) {\n if (this.component) {\n return this.component.multipleInstances ? identifier : DEFAULT_ENTRY_NAME;\n }\n else {\n return identifier; // assume multiple instances are supported before the component is provided.\n }\n }\n shouldAutoInitialize() {\n return (!!this.component &&\n this.component.instantiationMode !== \"EXPLICIT\" /* InstantiationMode.EXPLICIT */);\n }\n}\n// undefined should be passed to the service factory for the default instance\nfunction normalizeIdentifierForFactory(identifier) {\n return identifier === DEFAULT_ENTRY_NAME ? undefined : identifier;\n}\nfunction isComponentEager(component) {\n return component.instantiationMode === \"EAGER\" /* InstantiationMode.EAGER */;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * ComponentContainer that provides Providers for service name T, e.g. `auth`, `auth-internal`\n */\nclass ComponentContainer {\n constructor(name) {\n this.name = name;\n this.providers = new Map();\n }\n /**\n *\n * @param component Component being added\n * @param overwrite When a component with the same name has already been registered,\n * if overwrite is true: overwrite the existing component with the new component and create a new\n * provider with the new component. It can be useful in tests where you want to use different mocks\n * for different tests.\n * if overwrite is false: throw an exception\n */\n addComponent(component) {\n const provider = this.getProvider(component.name);\n if (provider.isComponentSet()) {\n throw new Error(`Component ${component.name} has already been registered with ${this.name}`);\n }\n provider.setComponent(component);\n }\n addOrOverwriteComponent(component) {\n const provider = this.getProvider(component.name);\n if (provider.isComponentSet()) {\n // delete the existing provider from the container, so we can register the new component\n this.providers.delete(component.name);\n }\n this.addComponent(component);\n }\n /**\n * getProvider provides a type safe interface where it can only be called with a field name\n * present in NameServiceMapping interface.\n *\n * Firebase SDKs providing services should extend NameServiceMapping interface to register\n * themselves.\n */\n getProvider(name) {\n if (this.providers.has(name)) {\n return this.providers.get(name);\n }\n // create a Provider for a service that hasn't registered with Firebase\n const provider = new Provider(name, this);\n this.providers.set(name, provider);\n return provider;\n }\n getProviders() {\n return Array.from(this.providers.values());\n }\n}\n\nexport { Component, ComponentContainer, Provider };\n//# sourceMappingURL=index.esm2017.js.map\n","/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * A container for all of the Logger instances\n */\nconst instances = [];\n/**\n * The JS SDK supports 5 log levels and also allows a user the ability to\n * silence the logs altogether.\n *\n * The order is a follows:\n * DEBUG < VERBOSE < INFO < WARN < ERROR\n *\n * All of the log types above the current log level will be captured (i.e. if\n * you set the log level to `INFO`, errors will still be logged, but `DEBUG` and\n * `VERBOSE` logs will not)\n */\nvar LogLevel;\n(function (LogLevel) {\n LogLevel[LogLevel[\"DEBUG\"] = 0] = \"DEBUG\";\n LogLevel[LogLevel[\"VERBOSE\"] = 1] = \"VERBOSE\";\n LogLevel[LogLevel[\"INFO\"] = 2] = \"INFO\";\n LogLevel[LogLevel[\"WARN\"] = 3] = \"WARN\";\n LogLevel[LogLevel[\"ERROR\"] = 4] = \"ERROR\";\n LogLevel[LogLevel[\"SILENT\"] = 5] = \"SILENT\";\n})(LogLevel || (LogLevel = {}));\nconst levelStringToEnum = {\n 'debug': LogLevel.DEBUG,\n 'verbose': LogLevel.VERBOSE,\n 'info': LogLevel.INFO,\n 'warn': LogLevel.WARN,\n 'error': LogLevel.ERROR,\n 'silent': LogLevel.SILENT\n};\n/**\n * The default log level\n */\nconst defaultLogLevel = LogLevel.INFO;\n/**\n * By default, `console.debug` is not displayed in the developer console (in\n * chrome). To avoid forcing users to have to opt-in to these logs twice\n * (i.e. once for firebase, and once in the console), we are sending `DEBUG`\n * logs to the `console.log` function.\n */\nconst ConsoleMethod = {\n [LogLevel.DEBUG]: 'log',\n [LogLevel.VERBOSE]: 'log',\n [LogLevel.INFO]: 'info',\n [LogLevel.WARN]: 'warn',\n [LogLevel.ERROR]: 'error'\n};\n/**\n * The default log handler will forward DEBUG, VERBOSE, INFO, WARN, and ERROR\n * messages on to their corresponding console counterparts (if the log method\n * is supported by the current log level)\n */\nconst defaultLogHandler = (instance, logType, ...args) => {\n if (logType < instance.logLevel) {\n return;\n }\n const now = new Date().toISOString();\n const method = ConsoleMethod[logType];\n if (method) {\n console[method](`[${now}] ${instance.name}:`, ...args);\n }\n else {\n throw new Error(`Attempted to log a message with an invalid logType (value: ${logType})`);\n }\n};\nclass Logger {\n /**\n * Gives you an instance of a Logger to capture messages according to\n * Firebase's logging scheme.\n *\n * @param name The name that the logs will be associated with\n */\n constructor(name) {\n this.name = name;\n /**\n * The log level of the given Logger instance.\n */\n this._logLevel = defaultLogLevel;\n /**\n * The main (internal) log handler for the Logger instance.\n * Can be set to a new function in internal package code but not by user.\n */\n this._logHandler = defaultLogHandler;\n /**\n * The optional, additional, user-defined log handler for the Logger instance.\n */\n this._userLogHandler = null;\n /**\n * Capture the current instance for later use\n */\n instances.push(this);\n }\n get logLevel() {\n return this._logLevel;\n }\n set logLevel(val) {\n if (!(val in LogLevel)) {\n throw new TypeError(`Invalid value \"${val}\" assigned to \\`logLevel\\``);\n }\n this._logLevel = val;\n }\n // Workaround for setter/getter having to be the same type.\n setLogLevel(val) {\n this._logLevel = typeof val === 'string' ? levelStringToEnum[val] : val;\n }\n get logHandler() {\n return this._logHandler;\n }\n set logHandler(val) {\n if (typeof val !== 'function') {\n throw new TypeError('Value assigned to `logHandler` must be a function');\n }\n this._logHandler = val;\n }\n get userLogHandler() {\n return this._userLogHandler;\n }\n set userLogHandler(val) {\n this._userLogHandler = val;\n }\n /**\n * The functions below are all based on the `console` interface\n */\n debug(...args) {\n this._userLogHandler && this._userLogHandler(this, LogLevel.DEBUG, ...args);\n this._logHandler(this, LogLevel.DEBUG, ...args);\n }\n log(...args) {\n this._userLogHandler &&\n this._userLogHandler(this, LogLevel.VERBOSE, ...args);\n this._logHandler(this, LogLevel.VERBOSE, ...args);\n }\n info(...args) {\n this._userLogHandler && this._userLogHandler(this, LogLevel.INFO, ...args);\n this._logHandler(this, LogLevel.INFO, ...args);\n }\n warn(...args) {\n this._userLogHandler && this._userLogHandler(this, LogLevel.WARN, ...args);\n this._logHandler(this, LogLevel.WARN, ...args);\n }\n error(...args) {\n this._userLogHandler && this._userLogHandler(this, LogLevel.ERROR, ...args);\n this._logHandler(this, LogLevel.ERROR, ...args);\n }\n}\nfunction setLogLevel(level) {\n instances.forEach(inst => {\n inst.setLogLevel(level);\n });\n}\nfunction setUserLogHandler(logCallback, options) {\n for (const instance of instances) {\n let customLogLevel = null;\n if (options && options.level) {\n customLogLevel = levelStringToEnum[options.level];\n }\n if (logCallback === null) {\n instance.userLogHandler = null;\n }\n else {\n instance.userLogHandler = (instance, level, ...args) => {\n const message = args\n .map(arg => {\n if (arg == null) {\n return null;\n }\n else if (typeof arg === 'string') {\n return arg;\n }\n else if (typeof arg === 'number' || typeof arg === 'boolean') {\n return arg.toString();\n }\n else if (arg instanceof Error) {\n return arg.message;\n }\n else {\n try {\n return JSON.stringify(arg);\n }\n catch (ignored) {\n return null;\n }\n }\n })\n .filter(arg => arg)\n .join(' ');\n if (level >= (customLogLevel !== null && customLogLevel !== void 0 ? customLogLevel : instance.logLevel)) {\n logCallback({\n level: LogLevel[level].toLowerCase(),\n message,\n args,\n type: instance.name\n });\n }\n };\n }\n }\n}\n\nexport { LogLevel, Logger, setLogLevel, setUserLogHandler };\n//# sourceMappingURL=index.esm2017.js.map\n","const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);\n\nlet idbProxyableTypes;\nlet cursorAdvanceMethods;\n// This is a function to prevent it throwing up in node environments.\nfunction getIdbProxyableTypes() {\n return (idbProxyableTypes ||\n (idbProxyableTypes = [\n IDBDatabase,\n IDBObjectStore,\n IDBIndex,\n IDBCursor,\n IDBTransaction,\n ]));\n}\n// This is a function to prevent it throwing up in node environments.\nfunction getCursorAdvanceMethods() {\n return (cursorAdvanceMethods ||\n (cursorAdvanceMethods = [\n IDBCursor.prototype.advance,\n IDBCursor.prototype.continue,\n IDBCursor.prototype.continuePrimaryKey,\n ]));\n}\nconst cursorRequestMap = new WeakMap();\nconst transactionDoneMap = new WeakMap();\nconst transactionStoreNamesMap = new WeakMap();\nconst transformCache = new WeakMap();\nconst reverseTransformCache = new WeakMap();\nfunction promisifyRequest(request) {\n const promise = new Promise((resolve, reject) => {\n const unlisten = () => {\n request.removeEventListener('success', success);\n request.removeEventListener('error', error);\n };\n const success = () => {\n resolve(wrap(request.result));\n unlisten();\n };\n const error = () => {\n reject(request.error);\n unlisten();\n };\n request.addEventListener('success', success);\n request.addEventListener('error', error);\n });\n promise\n .then((value) => {\n // Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval\n // (see wrapFunction).\n if (value instanceof IDBCursor) {\n cursorRequestMap.set(value, request);\n }\n // Catching to avoid \"Uncaught Promise exceptions\"\n })\n .catch(() => { });\n // This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This\n // is because we create many promises from a single IDBRequest.\n reverseTransformCache.set(promise, request);\n return promise;\n}\nfunction cacheDonePromiseForTransaction(tx) {\n // Early bail if we've already created a done promise for this transaction.\n if (transactionDoneMap.has(tx))\n return;\n const done = new Promise((resolve, reject) => {\n const unlisten = () => {\n tx.removeEventListener('complete', complete);\n tx.removeEventListener('error', error);\n tx.removeEventListener('abort', error);\n };\n const complete = () => {\n resolve();\n unlisten();\n };\n const error = () => {\n reject(tx.error || new DOMException('AbortError', 'AbortError'));\n unlisten();\n };\n tx.addEventListener('complete', complete);\n tx.addEventListener('error', error);\n tx.addEventListener('abort', error);\n });\n // Cache it for later retrieval.\n transactionDoneMap.set(tx, done);\n}\nlet idbProxyTraps = {\n get(target, prop, receiver) {\n if (target instanceof IDBTransaction) {\n // Special handling for transaction.done.\n if (prop === 'done')\n return transactionDoneMap.get(target);\n // Polyfill for objectStoreNames because of Edge.\n if (prop === 'objectStoreNames') {\n return target.objectStoreNames || transactionStoreNamesMap.get(target);\n }\n // Make tx.store return the only store in the transaction, or undefined if there are many.\n if (prop === 'store') {\n return receiver.objectStoreNames[1]\n ? undefined\n : receiver.objectStore(receiver.objectStoreNames[0]);\n }\n }\n // Else transform whatever we get back.\n return wrap(target[prop]);\n },\n set(target, prop, value) {\n target[prop] = value;\n return true;\n },\n has(target, prop) {\n if (target instanceof IDBTransaction &&\n (prop === 'done' || prop === 'store')) {\n return true;\n }\n return prop in target;\n },\n};\nfunction replaceTraps(callback) {\n idbProxyTraps = callback(idbProxyTraps);\n}\nfunction wrapFunction(func) {\n // Due to expected object equality (which is enforced by the caching in `wrap`), we\n // only create one new func per func.\n // Edge doesn't support objectStoreNames (booo), so we polyfill it here.\n if (func === IDBDatabase.prototype.transaction &&\n !('objectStoreNames' in IDBTransaction.prototype)) {\n return function (storeNames, ...args) {\n const tx = func.call(unwrap(this), storeNames, ...args);\n transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);\n return wrap(tx);\n };\n }\n // Cursor methods are special, as the behaviour is a little more different to standard IDB. In\n // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the\n // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense\n // with real promises, so each advance methods returns a new promise for the cursor object, or\n // undefined if the end of the cursor has been reached.\n if (getCursorAdvanceMethods().includes(func)) {\n return function (...args) {\n // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n // the original object.\n func.apply(unwrap(this), args);\n return wrap(cursorRequestMap.get(this));\n };\n }\n return function (...args) {\n // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n // the original object.\n return wrap(func.apply(unwrap(this), args));\n };\n}\nfunction transformCachableValue(value) {\n if (typeof value === 'function')\n return wrapFunction(value);\n // This doesn't return, it just creates a 'done' promise for the transaction,\n // which is later returned for transaction.done (see idbObjectHandler).\n if (value instanceof IDBTransaction)\n cacheDonePromiseForTransaction(value);\n if (instanceOfAny(value, getIdbProxyableTypes()))\n return new Proxy(value, idbProxyTraps);\n // Return the same value back if we're not going to transform it.\n return value;\n}\nfunction wrap(value) {\n // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because\n // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.\n if (value instanceof IDBRequest)\n return promisifyRequest(value);\n // If we've already transformed this value before, reuse the transformed value.\n // This is faster, but it also provides object equality.\n if (transformCache.has(value))\n return transformCache.get(value);\n const newValue = transformCachableValue(value);\n // Not all types are transformed.\n // These may be primitive types, so they can't be WeakMap keys.\n if (newValue !== value) {\n transformCache.set(value, newValue);\n reverseTransformCache.set(newValue, value);\n }\n return newValue;\n}\nconst unwrap = (value) => reverseTransformCache.get(value);\n\nexport { reverseTransformCache as a, instanceOfAny as i, replaceTraps as r, unwrap as u, wrap as w };\n","import { w as wrap, r as replaceTraps } from './wrap-idb-value.js';\nexport { u as unwrap, w as wrap } from './wrap-idb-value.js';\n\n/**\n * Open a database.\n *\n * @param name Name of the database.\n * @param version Schema version.\n * @param callbacks Additional callbacks.\n */\nfunction openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {\n const request = indexedDB.open(name, version);\n const openPromise = wrap(request);\n if (upgrade) {\n request.addEventListener('upgradeneeded', (event) => {\n upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);\n });\n }\n if (blocked) {\n request.addEventListener('blocked', (event) => blocked(\n // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n event.oldVersion, event.newVersion, event));\n }\n openPromise\n .then((db) => {\n if (terminated)\n db.addEventListener('close', () => terminated());\n if (blocking) {\n db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));\n }\n })\n .catch(() => { });\n return openPromise;\n}\n/**\n * Delete a database.\n *\n * @param name Name of the database.\n */\nfunction deleteDB(name, { blocked } = {}) {\n const request = indexedDB.deleteDatabase(name);\n if (blocked) {\n request.addEventListener('blocked', (event) => blocked(\n // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n event.oldVersion, event));\n }\n return wrap(request).then(() => undefined);\n}\n\nconst readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];\nconst writeMethods = ['put', 'add', 'delete', 'clear'];\nconst cachedMethods = new Map();\nfunction getMethod(target, prop) {\n if (!(target instanceof IDBDatabase &&\n !(prop in target) &&\n typeof prop === 'string')) {\n return;\n }\n if (cachedMethods.get(prop))\n return cachedMethods.get(prop);\n const targetFuncName = prop.replace(/FromIndex$/, '');\n const useIndex = prop !== targetFuncName;\n const isWrite = writeMethods.includes(targetFuncName);\n if (\n // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.\n !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||\n !(isWrite || readMethods.includes(targetFuncName))) {\n return;\n }\n const method = async function (storeName, ...args) {\n // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(\n const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');\n let target = tx.store;\n if (useIndex)\n target = target.index(args.shift());\n // Must reject if op rejects.\n // If it's a write operation, must reject if tx.done rejects.\n // Must reject with op rejection first.\n // Must resolve with op value.\n // Must handle both promises (no unhandled rejections)\n return (await Promise.all([\n target[targetFuncName](...args),\n isWrite && tx.done,\n ]))[0];\n };\n cachedMethods.set(prop, method);\n return method;\n}\nreplaceTraps((oldTraps) => ({\n ...oldTraps,\n get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),\n has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),\n}));\n\nexport { deleteDB, openDB };\n","import { Component, ComponentContainer } from '@firebase/component';\nimport { Logger, setUserLogHandler, setLogLevel as setLogLevel$1 } from '@firebase/logger';\nimport { ErrorFactory, base64Decode, getDefaultAppConfig, deepEqual, isBrowser, isWebWorker, FirebaseError, base64urlEncodeWithoutPadding, isIndexedDBAvailable, validateIndexedDBOpenable } from '@firebase/util';\nexport { FirebaseError } from '@firebase/util';\nimport { openDB } from 'idb';\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nclass PlatformLoggerServiceImpl {\n constructor(container) {\n this.container = container;\n }\n // In initial implementation, this will be called by installations on\n // auth token refresh, and installations will send this string.\n getPlatformInfoString() {\n const providers = this.container.getProviders();\n // Loop through providers and get library/version pairs from any that are\n // version components.\n return providers\n .map(provider => {\n if (isVersionServiceProvider(provider)) {\n const service = provider.getImmediate();\n return `${service.library}/${service.version}`;\n }\n else {\n return null;\n }\n })\n .filter(logString => logString)\n .join(' ');\n }\n}\n/**\n *\n * @param provider check if this provider provides a VersionService\n *\n * NOTE: Using Provider<'app-version'> is a hack to indicate that the provider\n * provides VersionService. The provider is not necessarily a 'app-version'\n * provider.\n */\nfunction isVersionServiceProvider(provider) {\n const component = provider.getComponent();\n return (component === null || component === void 0 ? void 0 : component.type) === \"VERSION\" /* ComponentType.VERSION */;\n}\n\nconst name$q = \"@firebase/app\";\nconst version$1 = \"0.13.2\";\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst logger = new Logger('@firebase/app');\n\nconst name$p = \"@firebase/app-compat\";\n\nconst name$o = \"@firebase/analytics-compat\";\n\nconst name$n = \"@firebase/analytics\";\n\nconst name$m = \"@firebase/app-check-compat\";\n\nconst name$l = \"@firebase/app-check\";\n\nconst name$k = \"@firebase/auth\";\n\nconst name$j = \"@firebase/auth-compat\";\n\nconst name$i = \"@firebase/database\";\n\nconst name$h = \"@firebase/data-connect\";\n\nconst name$g = \"@firebase/database-compat\";\n\nconst name$f = \"@firebase/functions\";\n\nconst name$e = \"@firebase/functions-compat\";\n\nconst name$d = \"@firebase/installations\";\n\nconst name$c = \"@firebase/installations-compat\";\n\nconst name$b = \"@firebase/messaging\";\n\nconst name$a = \"@firebase/messaging-compat\";\n\nconst name$9 = \"@firebase/performance\";\n\nconst name$8 = \"@firebase/performance-compat\";\n\nconst name$7 = \"@firebase/remote-config\";\n\nconst name$6 = \"@firebase/remote-config-compat\";\n\nconst name$5 = \"@firebase/storage\";\n\nconst name$4 = \"@firebase/storage-compat\";\n\nconst name$3 = \"@firebase/firestore\";\n\nconst name$2 = \"@firebase/ai\";\n\nconst name$1 = \"@firebase/firestore-compat\";\n\nconst name = \"firebase\";\nconst version = \"11.10.0\";\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * The default app name\n *\n * @internal\n */\nconst DEFAULT_ENTRY_NAME = '[DEFAULT]';\nconst PLATFORM_LOG_STRING = {\n [name$q]: 'fire-core',\n [name$p]: 'fire-core-compat',\n [name$n]: 'fire-analytics',\n [name$o]: 'fire-analytics-compat',\n [name$l]: 'fire-app-check',\n [name$m]: 'fire-app-check-compat',\n [name$k]: 'fire-auth',\n [name$j]: 'fire-auth-compat',\n [name$i]: 'fire-rtdb',\n [name$h]: 'fire-data-connect',\n [name$g]: 'fire-rtdb-compat',\n [name$f]: 'fire-fn',\n [name$e]: 'fire-fn-compat',\n [name$d]: 'fire-iid',\n [name$c]: 'fire-iid-compat',\n [name$b]: 'fire-fcm',\n [name$a]: 'fire-fcm-compat',\n [name$9]: 'fire-perf',\n [name$8]: 'fire-perf-compat',\n [name$7]: 'fire-rc',\n [name$6]: 'fire-rc-compat',\n [name$5]: 'fire-gcs',\n [name$4]: 'fire-gcs-compat',\n [name$3]: 'fire-fst',\n [name$1]: 'fire-fst-compat',\n [name$2]: 'fire-vertex',\n 'fire-js': 'fire-js', // Platform identifier for JS SDK.\n [name]: 'fire-js-all'\n};\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * @internal\n */\nconst _apps = new Map();\n/**\n * @internal\n */\nconst _serverApps = new Map();\n/**\n * Registered components.\n *\n * @internal\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst _components = new Map();\n/**\n * @param component - the component being added to this app's container\n *\n * @internal\n */\nfunction _addComponent(app, component) {\n try {\n app.container.addComponent(component);\n }\n catch (e) {\n logger.debug(`Component ${component.name} failed to register with FirebaseApp ${app.name}`, e);\n }\n}\n/**\n *\n * @internal\n */\nfunction _addOrOverwriteComponent(app, component) {\n app.container.addOrOverwriteComponent(component);\n}\n/**\n *\n * @param component - the component to register\n * @returns whether or not the component is registered successfully\n *\n * @internal\n */\nfunction _registerComponent(component) {\n const componentName = component.name;\n if (_components.has(componentName)) {\n logger.debug(`There were multiple attempts to register component ${componentName}.`);\n return false;\n }\n _components.set(componentName, component);\n // add the component to existing app instances\n for (const app of _apps.values()) {\n _addComponent(app, component);\n }\n for (const serverApp of _serverApps.values()) {\n _addComponent(serverApp, component);\n }\n return true;\n}\n/**\n *\n * @param app - FirebaseApp instance\n * @param name - service name\n *\n * @returns the provider for the service with the matching name\n *\n * @internal\n */\nfunction _getProvider(app, name) {\n const heartbeatController = app.container\n .getProvider('heartbeat')\n .getImmediate({ optional: true });\n if (heartbeatController) {\n void heartbeatController.triggerHeartbeat();\n }\n return app.container.getProvider(name);\n}\n/**\n *\n * @param app - FirebaseApp instance\n * @param name - service name\n * @param instanceIdentifier - service instance identifier in case the service supports multiple instances\n *\n * @internal\n */\nfunction _removeServiceInstance(app, name, instanceIdentifier = DEFAULT_ENTRY_NAME) {\n _getProvider(app, name).clearInstance(instanceIdentifier);\n}\n/**\n *\n * @param obj - an object of type FirebaseApp or FirebaseOptions.\n *\n * @returns true if the provide object is of type FirebaseApp.\n *\n * @internal\n */\nfunction _isFirebaseApp(obj) {\n return obj.options !== undefined;\n}\n/**\n *\n * @param obj - an object of type FirebaseApp.\n *\n * @returns true if the provided object is of type FirebaseServerAppImpl.\n *\n * @internal\n */\nfunction _isFirebaseServerApp(obj) {\n if (obj === null || obj === undefined) {\n return false;\n }\n return obj.settings !== undefined;\n}\n/**\n * Test only\n *\n * @internal\n */\nfunction _clearComponents() {\n _components.clear();\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst ERRORS = {\n [\"no-app\" /* AppError.NO_APP */]: \"No Firebase App '{$appName}' has been created - \" +\n 'call initializeApp() first',\n [\"bad-app-name\" /* AppError.BAD_APP_NAME */]: \"Illegal App name: '{$appName}'\",\n [\"duplicate-app\" /* AppError.DUPLICATE_APP */]: \"Firebase App named '{$appName}' already exists with different options or config\",\n [\"app-deleted\" /* AppError.APP_DELETED */]: \"Firebase App named '{$appName}' already deleted\",\n [\"server-app-deleted\" /* AppError.SERVER_APP_DELETED */]: 'Firebase Server App has been deleted',\n [\"no-options\" /* AppError.NO_OPTIONS */]: 'Need to provide options, when not being deployed to hosting via source.',\n [\"invalid-app-argument\" /* AppError.INVALID_APP_ARGUMENT */]: 'firebase.{$appName}() takes either no argument or a ' +\n 'Firebase App instance.',\n [\"invalid-log-argument\" /* AppError.INVALID_LOG_ARGUMENT */]: 'First argument to `onLog` must be null or a function.',\n [\"idb-open\" /* AppError.IDB_OPEN */]: 'Error thrown when opening IndexedDB. Original error: {$originalErrorMessage}.',\n [\"idb-get\" /* AppError.IDB_GET */]: 'Error thrown when reading from IndexedDB. Original error: {$originalErrorMessage}.',\n [\"idb-set\" /* AppError.IDB_WRITE */]: 'Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.',\n [\"idb-delete\" /* AppError.IDB_DELETE */]: 'Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.',\n [\"finalization-registry-not-supported\" /* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */]: 'FirebaseServerApp deleteOnDeref field defined but the JS runtime does not support FinalizationRegistry.',\n [\"invalid-server-app-environment\" /* AppError.INVALID_SERVER_APP_ENVIRONMENT */]: 'FirebaseServerApp is not for use in browser environments.'\n};\nconst ERROR_FACTORY = new ErrorFactory('app', 'Firebase', ERRORS);\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nclass FirebaseAppImpl {\n constructor(options, config, container) {\n this._isDeleted = false;\n this._options = Object.assign({}, options);\n this._config = Object.assign({}, config);\n this._name = config.name;\n this._automaticDataCollectionEnabled =\n config.automaticDataCollectionEnabled;\n this._container = container;\n this.container.addComponent(new Component('app', () => this, \"PUBLIC\" /* ComponentType.PUBLIC */));\n }\n get automaticDataCollectionEnabled() {\n this.checkDestroyed();\n return this._automaticDataCollectionEnabled;\n }\n set automaticDataCollectionEnabled(val) {\n this.checkDestroyed();\n this._automaticDataCollectionEnabled = val;\n }\n get name() {\n this.checkDestroyed();\n return this._name;\n }\n get options() {\n this.checkDestroyed();\n return this._options;\n }\n get config() {\n this.checkDestroyed();\n return this._config;\n }\n get container() {\n return this._container;\n }\n get isDeleted() {\n return this._isDeleted;\n }\n set isDeleted(val) {\n this._isDeleted = val;\n }\n /**\n * This function will throw an Error if the App has already been deleted -\n * use before performing API actions on the App.\n */\n checkDestroyed() {\n if (this.isDeleted) {\n throw ERROR_FACTORY.create(\"app-deleted\" /* AppError.APP_DELETED */, { appName: this._name });\n }\n }\n}\n\n/**\n * @license\n * Copyright 2023 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// Parse the token and check to see if the `exp` claim is in the future.\n// Reports an error to the console if the token or claim could not be parsed, or if `exp` is in\n// the past.\nfunction validateTokenTTL(base64Token, tokenName) {\n const secondPart = base64Decode(base64Token.split('.')[1]);\n if (secondPart === null) {\n console.error(`FirebaseServerApp ${tokenName} is invalid: second part could not be parsed.`);\n return;\n }\n const expClaim = JSON.parse(secondPart).exp;\n if (expClaim === undefined) {\n console.error(`FirebaseServerApp ${tokenName} is invalid: expiration claim could not be parsed`);\n return;\n }\n const exp = JSON.parse(secondPart).exp * 1000;\n const now = new Date().getTime();\n const diff = exp - now;\n if (diff <= 0) {\n console.error(`FirebaseServerApp ${tokenName} is invalid: the token has expired.`);\n }\n}\nclass FirebaseServerAppImpl extends FirebaseAppImpl {\n constructor(options, serverConfig, name, container) {\n // Build configuration parameters for the FirebaseAppImpl base class.\n const automaticDataCollectionEnabled = serverConfig.automaticDataCollectionEnabled !== undefined\n ? serverConfig.automaticDataCollectionEnabled\n : true;\n // Create the FirebaseAppSettings object for the FirebaseAppImp constructor.\n const config = {\n name,\n automaticDataCollectionEnabled\n };\n if (options.apiKey !== undefined) {\n // Construct the parent FirebaseAppImp object.\n super(options, config, container);\n }\n else {\n const appImpl = options;\n super(appImpl.options, config, container);\n }\n // Now construct the data for the FirebaseServerAppImpl.\n this._serverConfig = Object.assign({ automaticDataCollectionEnabled }, serverConfig);\n // Ensure that the current time is within the `authIdtoken` window of validity.\n if (this._serverConfig.authIdToken) {\n validateTokenTTL(this._serverConfig.authIdToken, 'authIdToken');\n }\n // Ensure that the current time is within the `appCheckToken` window of validity.\n if (this._serverConfig.appCheckToken) {\n validateTokenTTL(this._serverConfig.appCheckToken, 'appCheckToken');\n }\n this._finalizationRegistry = null;\n if (typeof FinalizationRegistry !== 'undefined') {\n this._finalizationRegistry = new FinalizationRegistry(() => {\n this.automaticCleanup();\n });\n }\n this._refCount = 0;\n this.incRefCount(this._serverConfig.releaseOnDeref);\n // Do not retain a hard reference to the dref object, otherwise the FinalizationRegistry\n // will never trigger.\n this._serverConfig.releaseOnDeref = undefined;\n serverConfig.releaseOnDeref = undefined;\n registerVersion(name$q, version$1, 'serverapp');\n }\n toJSON() {\n return undefined;\n }\n get refCount() {\n return this._refCount;\n }\n // Increment the reference count of this server app. If an object is provided, register it\n // with the finalization registry.\n incRefCount(obj) {\n if (this.isDeleted) {\n return;\n }\n this._refCount++;\n if (obj !== undefined && this._finalizationRegistry !== null) {\n this._finalizationRegistry.register(obj, this);\n }\n }\n // Decrement the reference count.\n decRefCount() {\n if (this.isDeleted) {\n return 0;\n }\n return --this._refCount;\n }\n // Invoked by the FinalizationRegistry callback to note that this app should go through its\n // reference counts and delete itself if no reference count remain. The coordinating logic that\n // handles this is in deleteApp(...).\n automaticCleanup() {\n void deleteApp(this);\n }\n get settings() {\n this.checkDestroyed();\n return this._serverConfig;\n }\n /**\n * This function will throw an Error if the App has already been deleted -\n * use before performing API actions on the App.\n */\n checkDestroyed() {\n if (this.isDeleted) {\n throw ERROR_FACTORY.create(\"server-app-deleted\" /* AppError.SERVER_APP_DELETED */);\n }\n }\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * The current SDK version.\n *\n * @public\n */\nconst SDK_VERSION = version;\nfunction initializeApp(_options, rawConfig = {}) {\n let options = _options;\n if (typeof rawConfig !== 'object') {\n const name = rawConfig;\n rawConfig = { name };\n }\n const config = Object.assign({ name: DEFAULT_ENTRY_NAME, automaticDataCollectionEnabled: true }, rawConfig);\n const name = config.name;\n if (typeof name !== 'string' || !name) {\n throw ERROR_FACTORY.create(\"bad-app-name\" /* AppError.BAD_APP_NAME */, {\n appName: String(name)\n });\n }\n options || (options = getDefaultAppConfig());\n if (!options) {\n throw ERROR_FACTORY.create(\"no-options\" /* AppError.NO_OPTIONS */);\n }\n const existingApp = _apps.get(name);\n if (existingApp) {\n // return the existing app if options and config deep equal the ones in the existing app.\n if (deepEqual(options, existingApp.options) &&\n deepEqual(config, existingApp.config)) {\n return existingApp;\n }\n else {\n throw ERROR_FACTORY.create(\"duplicate-app\" /* AppError.DUPLICATE_APP */, { appName: name });\n }\n }\n const container = new ComponentContainer(name);\n for (const component of _components.values()) {\n container.addComponent(component);\n }\n const newApp = new FirebaseAppImpl(options, config, container);\n _apps.set(name, newApp);\n return newApp;\n}\nfunction initializeServerApp(_options, _serverAppConfig) {\n if (isBrowser() && !isWebWorker()) {\n // FirebaseServerApp isn't designed to be run in browsers.\n throw ERROR_FACTORY.create(\"invalid-server-app-environment\" /* AppError.INVALID_SERVER_APP_ENVIRONMENT */);\n }\n if (_serverAppConfig.automaticDataCollectionEnabled === undefined) {\n _serverAppConfig.automaticDataCollectionEnabled = true;\n }\n let appOptions;\n if (_isFirebaseApp(_options)) {\n appOptions = _options.options;\n }\n else {\n appOptions = _options;\n }\n // Build an app name based on a hash of the configuration options.\n const nameObj = Object.assign(Object.assign({}, _serverAppConfig), appOptions);\n // However, Do not mangle the name based on releaseOnDeref, since it will vary between the\n // construction of FirebaseServerApp instances. For example, if the object is the request headers.\n if (nameObj.releaseOnDeref !== undefined) {\n delete nameObj.releaseOnDeref;\n }\n const hashCode = (s) => {\n return [...s].reduce((hash, c) => (Math.imul(31, hash) + c.charCodeAt(0)) | 0, 0);\n };\n if (_serverAppConfig.releaseOnDeref !== undefined) {\n if (typeof FinalizationRegistry === 'undefined') {\n throw ERROR_FACTORY.create(\"finalization-registry-not-supported\" /* AppError.FINALIZATION_REGISTRY_NOT_SUPPORTED */, {});\n }\n }\n const nameString = '' + hashCode(JSON.stringify(nameObj));\n const existingApp = _serverApps.get(nameString);\n if (existingApp) {\n existingApp.incRefCount(_serverAppConfig.releaseOnDeref);\n return existingApp;\n }\n const container = new ComponentContainer(nameString);\n for (const component of _components.values()) {\n container.addComponent(component);\n }\n const newApp = new FirebaseServerAppImpl(appOptions, _serverAppConfig, nameString, container);\n _serverApps.set(nameString, newApp);\n return newApp;\n}\n/**\n * Retrieves a {@link @firebase/app#FirebaseApp} instance.\n *\n * When called with no arguments, the default app is returned. When an app name\n * is provided, the app corresponding to that name is returned.\n *\n * An exception is thrown if the app being retrieved has not yet been\n * initialized.\n *\n * @example\n * ```javascript\n * // Return the default app\n * const app = getApp();\n * ```\n *\n * @example\n * ```javascript\n * // Return a named app\n * const otherApp = getApp(\"otherApp\");\n * ```\n *\n * @param name - Optional name of the app to return. If no name is\n * provided, the default is `\"[DEFAULT]\"`.\n *\n * @returns The app corresponding to the provided app name.\n * If no app name is provided, the default app is returned.\n *\n * @public\n */\nfunction getApp(name = DEFAULT_ENTRY_NAME) {\n const app = _apps.get(name);\n if (!app && name === DEFAULT_ENTRY_NAME && getDefaultAppConfig()) {\n return initializeApp();\n }\n if (!app) {\n throw ERROR_FACTORY.create(\"no-app\" /* AppError.NO_APP */, { appName: name });\n }\n return app;\n}\n/**\n * A (read-only) array of all initialized apps.\n * @public\n */\nfunction getApps() {\n return Array.from(_apps.values());\n}\n/**\n * Renders this app unusable and frees the resources of all associated\n * services.\n *\n * @example\n * ```javascript\n * deleteApp(app)\n * .then(function() {\n * console.log(\"App deleted successfully\");\n * })\n * .catch(function(error) {\n * console.log(\"Error deleting app:\", error);\n * });\n * ```\n *\n * @public\n */\nasync function deleteApp(app) {\n let cleanupProviders = false;\n const name = app.name;\n if (_apps.has(name)) {\n cleanupProviders = true;\n _apps.delete(name);\n }\n else if (_serverApps.has(name)) {\n const firebaseServerApp = app;\n if (firebaseServerApp.decRefCount() <= 0) {\n _serverApps.delete(name);\n cleanupProviders = true;\n }\n }\n if (cleanupProviders) {\n await Promise.all(app.container\n .getProviders()\n .map(provider => provider.delete()));\n app.isDeleted = true;\n }\n}\n/**\n * Registers a library's name and version for platform logging purposes.\n * @param library - Name of 1p or 3p library (e.g. firestore, angularfire)\n * @param version - Current version of that library.\n * @param variant - Bundle variant, e.g., node, rn, etc.\n *\n * @public\n */\nfunction registerVersion(libraryKeyOrName, version, variant) {\n var _a;\n // TODO: We can use this check to whitelist strings when/if we set up\n // a good whitelist system.\n let library = (_a = PLATFORM_LOG_STRING[libraryKeyOrName]) !== null && _a !== void 0 ? _a : libraryKeyOrName;\n if (variant) {\n library += `-${variant}`;\n }\n const libraryMismatch = library.match(/\\s|\\//);\n const versionMismatch = version.match(/\\s|\\//);\n if (libraryMismatch || versionMismatch) {\n const warning = [\n `Unable to register library \"${library}\" with version \"${version}\":`\n ];\n if (libraryMismatch) {\n warning.push(`library name \"${library}\" contains illegal characters (whitespace or \"/\")`);\n }\n if (libraryMismatch && versionMismatch) {\n warning.push('and');\n }\n if (versionMismatch) {\n warning.push(`version name \"${version}\" contains illegal characters (whitespace or \"/\")`);\n }\n logger.warn(warning.join(' '));\n return;\n }\n _registerComponent(new Component(`${library}-version`, () => ({ library, version }), \"VERSION\" /* ComponentType.VERSION */));\n}\n/**\n * Sets log handler for all Firebase SDKs.\n * @param logCallback - An optional custom log handler that executes user code whenever\n * the Firebase SDK makes a logging call.\n *\n * @public\n */\nfunction onLog(logCallback, options) {\n if (logCallback !== null && typeof logCallback !== 'function') {\n throw ERROR_FACTORY.create(\"invalid-log-argument\" /* AppError.INVALID_LOG_ARGUMENT */);\n }\n setUserLogHandler(logCallback, options);\n}\n/**\n * Sets log level for all Firebase SDKs.\n *\n * All of the log types above the current log level are captured (i.e. if\n * you set the log level to `info`, errors are logged, but `debug` and\n * `verbose` logs are not).\n *\n * @public\n */\nfunction setLogLevel(logLevel) {\n setLogLevel$1(logLevel);\n}\n\n/**\n * @license\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst DB_NAME = 'firebase-heartbeat-database';\nconst DB_VERSION = 1;\nconst STORE_NAME = 'firebase-heartbeat-store';\nlet dbPromise = null;\nfunction getDbPromise() {\n if (!dbPromise) {\n dbPromise = openDB(DB_NAME, DB_VERSION, {\n upgrade: (db, oldVersion) => {\n // We don't use 'break' in this switch statement, the fall-through\n // behavior is what we want, because if there are multiple versions between\n // the old version and the current version, we want ALL the migrations\n // that correspond to those versions to run, not only the last one.\n // eslint-disable-next-line default-case\n switch (oldVersion) {\n case 0:\n try {\n db.createObjectStore(STORE_NAME);\n }\n catch (e) {\n // Safari/iOS browsers throw occasional exceptions on\n // db.createObjectStore() that may be a bug. Avoid blocking\n // the rest of the app functionality.\n console.warn(e);\n }\n }\n }\n }).catch(e => {\n throw ERROR_FACTORY.create(\"idb-open\" /* AppError.IDB_OPEN */, {\n originalErrorMessage: e.message\n });\n });\n }\n return dbPromise;\n}\nasync function readHeartbeatsFromIndexedDB(app) {\n try {\n const db = await getDbPromise();\n const tx = db.transaction(STORE_NAME);\n const result = await tx.objectStore(STORE_NAME).get(computeKey(app));\n // We already have the value but tx.done can throw,\n // so we need to await it here to catch errors\n await tx.done;\n return result;\n }\n catch (e) {\n if (e instanceof FirebaseError) {\n logger.warn(e.message);\n }\n else {\n const idbGetError = ERROR_FACTORY.create(\"idb-get\" /* AppError.IDB_GET */, {\n originalErrorMessage: e === null || e === void 0 ? void 0 : e.message\n });\n logger.warn(idbGetError.message);\n }\n }\n}\nasync function writeHeartbeatsToIndexedDB(app, heartbeatObject) {\n try {\n const db = await getDbPromise();\n const tx = db.transaction(STORE_NAME, 'readwrite');\n const objectStore = tx.objectStore(STORE_NAME);\n await objectStore.put(heartbeatObject, computeKey(app));\n await tx.done;\n }\n catch (e) {\n if (e instanceof FirebaseError) {\n logger.warn(e.message);\n }\n else {\n const idbGetError = ERROR_FACTORY.create(\"idb-set\" /* AppError.IDB_WRITE */, {\n originalErrorMessage: e === null || e === void 0 ? void 0 : e.message\n });\n logger.warn(idbGetError.message);\n }\n }\n}\nfunction computeKey(app) {\n return `${app.name}!${app.options.appId}`;\n}\n\n/**\n * @license\n * Copyright 2021 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst MAX_HEADER_BYTES = 1024;\nconst MAX_NUM_STORED_HEARTBEATS = 30;\nclass HeartbeatServiceImpl {\n constructor(container) {\n this.container = container;\n /**\n * In-memory cache for heartbeats, used by getHeartbeatsHeader() to generate\n * the header string.\n * Stores one record per date. This will be consolidated into the standard\n * format of one record per user agent string before being sent as a header.\n * Populated from indexedDB when the controller is instantiated and should\n * be kept in sync with indexedDB.\n * Leave public for easier testing.\n */\n this._heartbeatsCache = null;\n const app = this.container.getProvider('app').getImmediate();\n this._storage = new HeartbeatStorageImpl(app);\n this._heartbeatsCachePromise = this._storage.read().then(result => {\n this._heartbeatsCache = result;\n return result;\n });\n }\n /**\n * Called to report a heartbeat. The function will generate\n * a HeartbeatsByUserAgent object, update heartbeatsCache, and persist it\n * to IndexedDB.\n * Note that we only store one heartbeat per day. So if a heartbeat for today is\n * already logged, subsequent calls to this function in the same day will be ignored.\n */\n async triggerHeartbeat() {\n var _a, _b;\n try {\n const platformLogger = this.container\n .getProvider('platform-logger')\n .getImmediate();\n // This is the \"Firebase user agent\" string from the platform logger\n // service, not the browser user agent.\n const agent = platformLogger.getPlatformInfoString();\n const date = getUTCDateString();\n if (((_a = this._heartbeatsCache) === null || _a === void 0 ? void 0 : _a.heartbeats) == null) {\n this._heartbeatsCache = await this._heartbeatsCachePromise;\n // If we failed to construct a heartbeats cache, then return immediately.\n if (((_b = this._heartbeatsCache) === null || _b === void 0 ? void 0 : _b.heartbeats) == null) {\n return;\n }\n }\n // Do not store a heartbeat if one is already stored for this day\n // or if a header has already been sent today.\n if (this._heartbeatsCache.lastSentHeartbeatDate === date ||\n this._heartbeatsCache.heartbeats.some(singleDateHeartbeat => singleDateHeartbeat.date === date)) {\n return;\n }\n else {\n // There is no entry for this date. Create one.\n this._heartbeatsCache.heartbeats.push({ date, agent });\n // If the number of stored heartbeats exceeds the maximum number of stored heartbeats, remove the heartbeat with the earliest date.\n // Since this is executed each time a heartbeat is pushed, the limit can only be exceeded by one, so only one needs to be removed.\n if (this._heartbeatsCache.heartbeats.length > MAX_NUM_STORED_HEARTBEATS) {\n const earliestHeartbeatIdx = getEarliestHeartbeatIdx(this._heartbeatsCache.heartbeats);\n this._heartbeatsCache.heartbeats.splice(earliestHeartbeatIdx, 1);\n }\n }\n return this._storage.overwrite(this._heartbeatsCache);\n }\n catch (e) {\n logger.warn(e);\n }\n }\n /**\n * Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.\n * It also clears all heartbeats from memory as well as in IndexedDB.\n *\n * NOTE: Consuming product SDKs should not send the header if this method\n * returns an empty string.\n */\n async getHeartbeatsHeader() {\n var _a;\n try {\n if (this._heartbeatsCache === null) {\n await this._heartbeatsCachePromise;\n }\n // If it's still null or the array is empty, there is no data to send.\n if (((_a = this._heartbeatsCache) === null || _a === void 0 ? void 0 : _a.heartbeats) == null ||\n this._heartbeatsCache.heartbeats.length === 0) {\n return '';\n }\n const date = getUTCDateString();\n // Extract as many heartbeats from the cache as will fit under the size limit.\n const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats);\n const headerString = base64urlEncodeWithoutPadding(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend }));\n // Store last sent date to prevent another being logged/sent for the same day.\n this._heartbeatsCache.lastSentHeartbeatDate = date;\n if (unsentEntries.length > 0) {\n // Store any unsent entries if they exist.\n this._heartbeatsCache.heartbeats = unsentEntries;\n // This seems more likely than emptying the array (below) to lead to some odd state\n // since the cache isn't empty and this will be called again on the next request,\n // and is probably safest if we await it.\n await this._storage.overwrite(this._heartbeatsCache);\n }\n else {\n this._heartbeatsCache.heartbeats = [];\n // Do not wait for this, to reduce latency.\n void this._storage.overwrite(this._heartbeatsCache);\n }\n return headerString;\n }\n catch (e) {\n logger.warn(e);\n return '';\n }\n }\n}\nfunction getUTCDateString() {\n const today = new Date();\n // Returns date format 'YYYY-MM-DD'\n return today.toISOString().substring(0, 10);\n}\nfunction extractHeartbeatsForHeader(heartbeatsCache, maxSize = MAX_HEADER_BYTES) {\n // Heartbeats grouped by user agent in the standard format to be sent in\n // the header.\n const heartbeatsToSend = [];\n // Single date format heartbeats that are not sent.\n let unsentEntries = heartbeatsCache.slice();\n for (const singleDateHeartbeat of heartbeatsCache) {\n // Look for an existing entry with the same user agent.\n const heartbeatEntry = heartbeatsToSend.find(hb => hb.agent === singleDateHeartbeat.agent);\n if (!heartbeatEntry) {\n // If no entry for this user agent exists, create one.\n heartbeatsToSend.push({\n agent: singleDateHeartbeat.agent,\n dates: [singleDateHeartbeat.date]\n });\n if (countBytes(heartbeatsToSend) > maxSize) {\n // If the header would exceed max size, remove the added heartbeat\n // entry and stop adding to the header.\n heartbeatsToSend.pop();\n break;\n }\n }\n else {\n heartbeatEntry.dates.push(singleDateHeartbeat.date);\n // If the header would exceed max size, remove the added date\n // and stop adding to the header.\n if (countBytes(heartbeatsToSend) > maxSize) {\n heartbeatEntry.dates.pop();\n break;\n }\n }\n // Pop unsent entry from queue. (Skipped if adding the entry exceeded\n // quota and the loop breaks early.)\n unsentEntries = unsentEntries.slice(1);\n }\n return {\n heartbeatsToSend,\n unsentEntries\n };\n}\nclass HeartbeatStorageImpl {\n constructor(app) {\n this.app = app;\n this._canUseIndexedDBPromise = this.runIndexedDBEnvironmentCheck();\n }\n async runIndexedDBEnvironmentCheck() {\n if (!isIndexedDBAvailable()) {\n return false;\n }\n else {\n return validateIndexedDBOpenable()\n .then(() => true)\n .catch(() => false);\n }\n }\n /**\n * Read all heartbeats.\n */\n async read() {\n const canUseIndexedDB = await this._canUseIndexedDBPromise;\n if (!canUseIndexedDB) {\n return { heartbeats: [] };\n }\n else {\n const idbHeartbeatObject = await readHeartbeatsFromIndexedDB(this.app);\n if (idbHeartbeatObject === null || idbHeartbeatObject === void 0 ? void 0 : idbHeartbeatObject.heartbeats) {\n return idbHeartbeatObject;\n }\n else {\n return { heartbeats: [] };\n }\n }\n }\n // overwrite the storage with the provided heartbeats\n async overwrite(heartbeatsObject) {\n var _a;\n const canUseIndexedDB = await this._canUseIndexedDBPromise;\n if (!canUseIndexedDB) {\n return;\n }\n else {\n const existingHeartbeatsObject = await this.read();\n return writeHeartbeatsToIndexedDB(this.app, {\n lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,\n heartbeats: heartbeatsObject.heartbeats\n });\n }\n }\n // add heartbeats\n async add(heartbeatsObject) {\n var _a;\n const canUseIndexedDB = await this._canUseIndexedDBPromise;\n if (!canUseIndexedDB) {\n return;\n }\n else {\n const existingHeartbeatsObject = await this.read();\n return writeHeartbeatsToIndexedDB(this.app, {\n lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,\n heartbeats: [\n ...existingHeartbeatsObject.heartbeats,\n ...heartbeatsObject.heartbeats\n ]\n });\n }\n }\n}\n/**\n * Calculate bytes of a HeartbeatsByUserAgent array after being wrapped\n * in a platform logging header JSON object, stringified, and converted\n * to base 64.\n */\nfunction countBytes(heartbeatsCache) {\n // base64 has a restricted set of characters, all of which should be 1 byte.\n return base64urlEncodeWithoutPadding(\n // heartbeatsCache wrapper properties\n JSON.stringify({ version: 2, heartbeats: heartbeatsCache })).length;\n}\n/**\n * Returns the index of the heartbeat with the earliest date.\n * If the heartbeats array is empty, -1 is returned.\n */\nfunction getEarliestHeartbeatIdx(heartbeats) {\n if (heartbeats.length === 0) {\n return -1;\n }\n let earliestHeartbeatIdx = 0;\n let earliestHeartbeatDate = heartbeats[0].date;\n for (let i = 1; i < heartbeats.length; i++) {\n if (heartbeats[i].date < earliestHeartbeatDate) {\n earliestHeartbeatDate = heartbeats[i].date;\n earliestHeartbeatIdx = i;\n }\n }\n return earliestHeartbeatIdx;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction registerCoreComponents(variant) {\n _registerComponent(new Component('platform-logger', container => new PlatformLoggerServiceImpl(container), \"PRIVATE\" /* ComponentType.PRIVATE */));\n _registerComponent(new Component('heartbeat', container => new HeartbeatServiceImpl(container), \"PRIVATE\" /* ComponentType.PRIVATE */));\n // Register `app` package.\n registerVersion(name$q, version$1, variant);\n // BUILD_TARGET will be replaced by values like esm2017, cjs2017, etc during the compilation\n registerVersion(name$q, version$1, 'esm2017');\n // Register platform SDK identifier (no version).\n registerVersion('fire-js', '');\n}\n\n/**\n * Firebase App\n *\n * @remarks This package coordinates the communication between the different Firebase components\n * @packageDocumentation\n */\nregisterCoreComponents('');\n\nexport { SDK_VERSION, DEFAULT_ENTRY_NAME as _DEFAULT_ENTRY_NAME, _addComponent, _addOrOverwriteComponent, _apps, _clearComponents, _components, _getProvider, _isFirebaseApp, _isFirebaseServerApp, _registerComponent, _removeServiceInstance, _serverApps, deleteApp, getApp, getApps, initializeApp, initializeServerApp, onLog, registerVersion, setLogLevel };\n//# sourceMappingURL=index.esm2017.js.map\n","import { registerVersion } from '@firebase/app';\nexport * from '@firebase/app';\n\nvar name = \"firebase\";\nvar version = \"11.10.0\";\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nregisterVersion(name, version, 'app');\n//# sourceMappingURL=index.esm.js.map\n","import { _getProvider, getApp, _registerComponent, registerVersion } from '@firebase/app';\nimport { Component } from '@firebase/component';\nimport { ErrorFactory, FirebaseError } from '@firebase/util';\nimport { openDB } from 'idb';\n\nconst name = \"@firebase/installations\";\nconst version = \"0.6.18\";\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst PENDING_TIMEOUT_MS = 10000;\nconst PACKAGE_VERSION = `w:${version}`;\nconst INTERNAL_AUTH_VERSION = 'FIS_v2';\nconst INSTALLATIONS_API_URL = 'https://firebaseinstallations.googleapis.com/v1';\nconst TOKEN_EXPIRATION_BUFFER = 60 * 60 * 1000; // One hour\nconst SERVICE = 'installations';\nconst SERVICE_NAME = 'Installations';\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst ERROR_DESCRIPTION_MAP = {\n [\"missing-app-config-values\" /* ErrorCode.MISSING_APP_CONFIG_VALUES */]: 'Missing App configuration value: \"{$valueName}\"',\n [\"not-registered\" /* ErrorCode.NOT_REGISTERED */]: 'Firebase Installation is not registered.',\n [\"installation-not-found\" /* ErrorCode.INSTALLATION_NOT_FOUND */]: 'Firebase Installation not found.',\n [\"request-failed\" /* ErrorCode.REQUEST_FAILED */]: '{$requestName} request failed with error \"{$serverCode} {$serverStatus}: {$serverMessage}\"',\n [\"app-offline\" /* ErrorCode.APP_OFFLINE */]: 'Could not process request. Application offline.',\n [\"delete-pending-registration\" /* ErrorCode.DELETE_PENDING_REGISTRATION */]: \"Can't delete installation while there is a pending registration request.\"\n};\nconst ERROR_FACTORY = new ErrorFactory(SERVICE, SERVICE_NAME, ERROR_DESCRIPTION_MAP);\n/** Returns true if error is a FirebaseError that is based on an error from the server. */\nfunction isServerError(error) {\n return (error instanceof FirebaseError &&\n error.code.includes(\"request-failed\" /* ErrorCode.REQUEST_FAILED */));\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction getInstallationsEndpoint({ projectId }) {\n return `${INSTALLATIONS_API_URL}/projects/${projectId}/installations`;\n}\nfunction extractAuthTokenInfoFromResponse(response) {\n return {\n token: response.token,\n requestStatus: 2 /* RequestStatus.COMPLETED */,\n expiresIn: getExpiresInFromResponseExpiresIn(response.expiresIn),\n creationTime: Date.now()\n };\n}\nasync function getErrorFromResponse(requestName, response) {\n const responseJson = await response.json();\n const errorData = responseJson.error;\n return ERROR_FACTORY.create(\"request-failed\" /* ErrorCode.REQUEST_FAILED */, {\n requestName,\n serverCode: errorData.code,\n serverMessage: errorData.message,\n serverStatus: errorData.status\n });\n}\nfunction getHeaders({ apiKey }) {\n return new Headers({\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n 'x-goog-api-key': apiKey\n });\n}\nfunction getHeadersWithAuth(appConfig, { refreshToken }) {\n const headers = getHeaders(appConfig);\n headers.append('Authorization', getAuthorizationHeader(refreshToken));\n return headers;\n}\n/**\n * Calls the passed in fetch wrapper and returns the response.\n * If the returned response has a status of 5xx, re-runs the function once and\n * returns the response.\n */\nasync function retryIfServerError(fn) {\n const result = await fn();\n if (result.status >= 500 && result.status < 600) {\n // Internal Server Error. Retry request.\n return fn();\n }\n return result;\n}\nfunction getExpiresInFromResponseExpiresIn(responseExpiresIn) {\n // This works because the server will never respond with fractions of a second.\n return Number(responseExpiresIn.replace('s', '000'));\n}\nfunction getAuthorizationHeader(refreshToken) {\n return `${INTERNAL_AUTH_VERSION} ${refreshToken}`;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function createInstallationRequest({ appConfig, heartbeatServiceProvider }, { fid }) {\n const endpoint = getInstallationsEndpoint(appConfig);\n const headers = getHeaders(appConfig);\n // If heartbeat service exists, add the heartbeat string to the header.\n const heartbeatService = heartbeatServiceProvider.getImmediate({\n optional: true\n });\n if (heartbeatService) {\n const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader();\n if (heartbeatsHeader) {\n headers.append('x-firebase-client', heartbeatsHeader);\n }\n }\n const body = {\n fid,\n authVersion: INTERNAL_AUTH_VERSION,\n appId: appConfig.appId,\n sdkVersion: PACKAGE_VERSION\n };\n const request = {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n };\n const response = await retryIfServerError(() => fetch(endpoint, request));\n if (response.ok) {\n const responseValue = await response.json();\n const registeredInstallationEntry = {\n fid: responseValue.fid || fid,\n registrationStatus: 2 /* RequestStatus.COMPLETED */,\n refreshToken: responseValue.refreshToken,\n authToken: extractAuthTokenInfoFromResponse(responseValue.authToken)\n };\n return registeredInstallationEntry;\n }\n else {\n throw await getErrorFromResponse('Create Installation', response);\n }\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/** Returns a promise that resolves after given time passes. */\nfunction sleep(ms) {\n return new Promise(resolve => {\n setTimeout(resolve, ms);\n });\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction bufferToBase64UrlSafe(array) {\n const b64 = btoa(String.fromCharCode(...array));\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_');\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst VALID_FID_PATTERN = /^[cdef][\\w-]{21}$/;\nconst INVALID_FID = '';\n/**\n * Generates a new FID using random values from Web Crypto API.\n * Returns an empty string if FID generation fails for any reason.\n */\nfunction generateFid() {\n try {\n // A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5\n // bytes. our implementation generates a 17 byte array instead.\n const fidByteArray = new Uint8Array(17);\n const crypto = self.crypto || self.msCrypto;\n crypto.getRandomValues(fidByteArray);\n // Replace the first 4 random bits with the constant FID header of 0b0111.\n fidByteArray[0] = 0b01110000 + (fidByteArray[0] % 0b00010000);\n const fid = encode(fidByteArray);\n return VALID_FID_PATTERN.test(fid) ? fid : INVALID_FID;\n }\n catch (_a) {\n // FID generation errored\n return INVALID_FID;\n }\n}\n/** Converts a FID Uint8Array to a base64 string representation. */\nfunction encode(fidByteArray) {\n const b64String = bufferToBase64UrlSafe(fidByteArray);\n // Remove the 23rd character that was added because of the extra 4 bits at the\n // end of our 17 byte array, and the '=' padding.\n return b64String.substr(0, 22);\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/** Returns a string key that can be used to identify the app. */\nfunction getKey(appConfig) {\n return `${appConfig.appName}!${appConfig.appId}`;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst fidChangeCallbacks = new Map();\n/**\n * Calls the onIdChange callbacks with the new FID value, and broadcasts the\n * change to other tabs.\n */\nfunction fidChanged(appConfig, fid) {\n const key = getKey(appConfig);\n callFidChangeCallbacks(key, fid);\n broadcastFidChange(key, fid);\n}\nfunction addCallback(appConfig, callback) {\n // Open the broadcast channel if it's not already open,\n // to be able to listen to change events from other tabs.\n getBroadcastChannel();\n const key = getKey(appConfig);\n let callbackSet = fidChangeCallbacks.get(key);\n if (!callbackSet) {\n callbackSet = new Set();\n fidChangeCallbacks.set(key, callbackSet);\n }\n callbackSet.add(callback);\n}\nfunction removeCallback(appConfig, callback) {\n const key = getKey(appConfig);\n const callbackSet = fidChangeCallbacks.get(key);\n if (!callbackSet) {\n return;\n }\n callbackSet.delete(callback);\n if (callbackSet.size === 0) {\n fidChangeCallbacks.delete(key);\n }\n // Close broadcast channel if there are no more callbacks.\n closeBroadcastChannel();\n}\nfunction callFidChangeCallbacks(key, fid) {\n const callbacks = fidChangeCallbacks.get(key);\n if (!callbacks) {\n return;\n }\n for (const callback of callbacks) {\n callback(fid);\n }\n}\nfunction broadcastFidChange(key, fid) {\n const channel = getBroadcastChannel();\n if (channel) {\n channel.postMessage({ key, fid });\n }\n closeBroadcastChannel();\n}\nlet broadcastChannel = null;\n/** Opens and returns a BroadcastChannel if it is supported by the browser. */\nfunction getBroadcastChannel() {\n if (!broadcastChannel && 'BroadcastChannel' in self) {\n broadcastChannel = new BroadcastChannel('[Firebase] FID Change');\n broadcastChannel.onmessage = e => {\n callFidChangeCallbacks(e.data.key, e.data.fid);\n };\n }\n return broadcastChannel;\n}\nfunction closeBroadcastChannel() {\n if (fidChangeCallbacks.size === 0 && broadcastChannel) {\n broadcastChannel.close();\n broadcastChannel = null;\n }\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst DATABASE_NAME = 'firebase-installations-database';\nconst DATABASE_VERSION = 1;\nconst OBJECT_STORE_NAME = 'firebase-installations-store';\nlet dbPromise = null;\nfunction getDbPromise() {\n if (!dbPromise) {\n dbPromise = openDB(DATABASE_NAME, DATABASE_VERSION, {\n upgrade: (db, oldVersion) => {\n // We don't use 'break' in this switch statement, the fall-through\n // behavior is what we want, because if there are multiple versions between\n // the old version and the current version, we want ALL the migrations\n // that correspond to those versions to run, not only the last one.\n // eslint-disable-next-line default-case\n switch (oldVersion) {\n case 0:\n db.createObjectStore(OBJECT_STORE_NAME);\n }\n }\n });\n }\n return dbPromise;\n}\n/** Assigns or overwrites the record for the given key with the given value. */\nasync function set(appConfig, value) {\n const key = getKey(appConfig);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n const objectStore = tx.objectStore(OBJECT_STORE_NAME);\n const oldValue = (await objectStore.get(key));\n await objectStore.put(value, key);\n await tx.done;\n if (!oldValue || oldValue.fid !== value.fid) {\n fidChanged(appConfig, value.fid);\n }\n return value;\n}\n/** Removes record(s) from the objectStore that match the given key. */\nasync function remove(appConfig) {\n const key = getKey(appConfig);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n await tx.objectStore(OBJECT_STORE_NAME).delete(key);\n await tx.done;\n}\n/**\n * Atomically updates a record with the result of updateFn, which gets\n * called with the current value. If newValue is undefined, the record is\n * deleted instead.\n * @return Updated value\n */\nasync function update(appConfig, updateFn) {\n const key = getKey(appConfig);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n const store = tx.objectStore(OBJECT_STORE_NAME);\n const oldValue = (await store.get(key));\n const newValue = updateFn(oldValue);\n if (newValue === undefined) {\n await store.delete(key);\n }\n else {\n await store.put(newValue, key);\n }\n await tx.done;\n if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) {\n fidChanged(appConfig, newValue.fid);\n }\n return newValue;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Updates and returns the InstallationEntry from the database.\n * Also triggers a registration request if it is necessary and possible.\n */\nasync function getInstallationEntry(installations) {\n let registrationPromise;\n const installationEntry = await update(installations.appConfig, oldEntry => {\n const installationEntry = updateOrCreateInstallationEntry(oldEntry);\n const entryWithPromise = triggerRegistrationIfNecessary(installations, installationEntry);\n registrationPromise = entryWithPromise.registrationPromise;\n return entryWithPromise.installationEntry;\n });\n if (installationEntry.fid === INVALID_FID) {\n // FID generation failed. Waiting for the FID from the server.\n return { installationEntry: await registrationPromise };\n }\n return {\n installationEntry,\n registrationPromise\n };\n}\n/**\n * Creates a new Installation Entry if one does not exist.\n * Also clears timed out pending requests.\n */\nfunction updateOrCreateInstallationEntry(oldEntry) {\n const entry = oldEntry || {\n fid: generateFid(),\n registrationStatus: 0 /* RequestStatus.NOT_STARTED */\n };\n return clearTimedOutRequest(entry);\n}\n/**\n * If the Firebase Installation is not registered yet, this will trigger the\n * registration and return an InProgressInstallationEntry.\n *\n * If registrationPromise does not exist, the installationEntry is guaranteed\n * to be registered.\n */\nfunction triggerRegistrationIfNecessary(installations, installationEntry) {\n if (installationEntry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {\n if (!navigator.onLine) {\n // Registration required but app is offline.\n const registrationPromiseWithError = Promise.reject(ERROR_FACTORY.create(\"app-offline\" /* ErrorCode.APP_OFFLINE */));\n return {\n installationEntry,\n registrationPromise: registrationPromiseWithError\n };\n }\n // Try registering. Change status to IN_PROGRESS.\n const inProgressEntry = {\n fid: installationEntry.fid,\n registrationStatus: 1 /* RequestStatus.IN_PROGRESS */,\n registrationTime: Date.now()\n };\n const registrationPromise = registerInstallation(installations, inProgressEntry);\n return { installationEntry: inProgressEntry, registrationPromise };\n }\n else if (installationEntry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) {\n return {\n installationEntry,\n registrationPromise: waitUntilFidRegistration(installations)\n };\n }\n else {\n return { installationEntry };\n }\n}\n/** This will be executed only once for each new Firebase Installation. */\nasync function registerInstallation(installations, installationEntry) {\n try {\n const registeredInstallationEntry = await createInstallationRequest(installations, installationEntry);\n return set(installations.appConfig, registeredInstallationEntry);\n }\n catch (e) {\n if (isServerError(e) && e.customData.serverCode === 409) {\n // Server returned a \"FID cannot be used\" error.\n // Generate a new ID next time.\n await remove(installations.appConfig);\n }\n else {\n // Registration failed. Set FID as not registered.\n await set(installations.appConfig, {\n fid: installationEntry.fid,\n registrationStatus: 0 /* RequestStatus.NOT_STARTED */\n });\n }\n throw e;\n }\n}\n/** Call if FID registration is pending in another request. */\nasync function waitUntilFidRegistration(installations) {\n // Unfortunately, there is no way of reliably observing when a value in\n // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),\n // so we need to poll.\n let entry = await updateInstallationRequest(installations.appConfig);\n while (entry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) {\n // createInstallation request still in progress.\n await sleep(100);\n entry = await updateInstallationRequest(installations.appConfig);\n }\n if (entry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {\n // The request timed out or failed in a different call. Try again.\n const { installationEntry, registrationPromise } = await getInstallationEntry(installations);\n if (registrationPromise) {\n return registrationPromise;\n }\n else {\n // if there is no registrationPromise, entry is registered.\n return installationEntry;\n }\n }\n return entry;\n}\n/**\n * Called only if there is a CreateInstallation request in progress.\n *\n * Updates the InstallationEntry in the DB based on the status of the\n * CreateInstallation request.\n *\n * Returns the updated InstallationEntry.\n */\nfunction updateInstallationRequest(appConfig) {\n return update(appConfig, oldEntry => {\n if (!oldEntry) {\n throw ERROR_FACTORY.create(\"installation-not-found\" /* ErrorCode.INSTALLATION_NOT_FOUND */);\n }\n return clearTimedOutRequest(oldEntry);\n });\n}\nfunction clearTimedOutRequest(entry) {\n if (hasInstallationRequestTimedOut(entry)) {\n return {\n fid: entry.fid,\n registrationStatus: 0 /* RequestStatus.NOT_STARTED */\n };\n }\n return entry;\n}\nfunction hasInstallationRequestTimedOut(installationEntry) {\n return (installationEntry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */ &&\n installationEntry.registrationTime + PENDING_TIMEOUT_MS < Date.now());\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function generateAuthTokenRequest({ appConfig, heartbeatServiceProvider }, installationEntry) {\n const endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry);\n const headers = getHeadersWithAuth(appConfig, installationEntry);\n // If heartbeat service exists, add the heartbeat string to the header.\n const heartbeatService = heartbeatServiceProvider.getImmediate({\n optional: true\n });\n if (heartbeatService) {\n const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader();\n if (heartbeatsHeader) {\n headers.append('x-firebase-client', heartbeatsHeader);\n }\n }\n const body = {\n installation: {\n sdkVersion: PACKAGE_VERSION,\n appId: appConfig.appId\n }\n };\n const request = {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n };\n const response = await retryIfServerError(() => fetch(endpoint, request));\n if (response.ok) {\n const responseValue = await response.json();\n const completedAuthToken = extractAuthTokenInfoFromResponse(responseValue);\n return completedAuthToken;\n }\n else {\n throw await getErrorFromResponse('Generate Auth Token', response);\n }\n}\nfunction getGenerateAuthTokenEndpoint(appConfig, { fid }) {\n return `${getInstallationsEndpoint(appConfig)}/${fid}/authTokens:generate`;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Returns a valid authentication token for the installation. Generates a new\n * token if one doesn't exist, is expired or about to expire.\n *\n * Should only be called if the Firebase Installation is registered.\n */\nasync function refreshAuthToken(installations, forceRefresh = false) {\n let tokenPromise;\n const entry = await update(installations.appConfig, oldEntry => {\n if (!isEntryRegistered(oldEntry)) {\n throw ERROR_FACTORY.create(\"not-registered\" /* ErrorCode.NOT_REGISTERED */);\n }\n const oldAuthToken = oldEntry.authToken;\n if (!forceRefresh && isAuthTokenValid(oldAuthToken)) {\n // There is a valid token in the DB.\n return oldEntry;\n }\n else if (oldAuthToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */) {\n // There already is a token request in progress.\n tokenPromise = waitUntilAuthTokenRequest(installations, forceRefresh);\n return oldEntry;\n }\n else {\n // No token or token expired.\n if (!navigator.onLine) {\n throw ERROR_FACTORY.create(\"app-offline\" /* ErrorCode.APP_OFFLINE */);\n }\n const inProgressEntry = makeAuthTokenRequestInProgressEntry(oldEntry);\n tokenPromise = fetchAuthTokenFromServer(installations, inProgressEntry);\n return inProgressEntry;\n }\n });\n const authToken = tokenPromise\n ? await tokenPromise\n : entry.authToken;\n return authToken;\n}\n/**\n * Call only if FID is registered and Auth Token request is in progress.\n *\n * Waits until the current pending request finishes. If the request times out,\n * tries once in this thread as well.\n */\nasync function waitUntilAuthTokenRequest(installations, forceRefresh) {\n // Unfortunately, there is no way of reliably observing when a value in\n // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),\n // so we need to poll.\n let entry = await updateAuthTokenRequest(installations.appConfig);\n while (entry.authToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */) {\n // generateAuthToken still in progress.\n await sleep(100);\n entry = await updateAuthTokenRequest(installations.appConfig);\n }\n const authToken = entry.authToken;\n if (authToken.requestStatus === 0 /* RequestStatus.NOT_STARTED */) {\n // The request timed out or failed in a different call. Try again.\n return refreshAuthToken(installations, forceRefresh);\n }\n else {\n return authToken;\n }\n}\n/**\n * Called only if there is a GenerateAuthToken request in progress.\n *\n * Updates the InstallationEntry in the DB based on the status of the\n * GenerateAuthToken request.\n *\n * Returns the updated InstallationEntry.\n */\nfunction updateAuthTokenRequest(appConfig) {\n return update(appConfig, oldEntry => {\n if (!isEntryRegistered(oldEntry)) {\n throw ERROR_FACTORY.create(\"not-registered\" /* ErrorCode.NOT_REGISTERED */);\n }\n const oldAuthToken = oldEntry.authToken;\n if (hasAuthTokenRequestTimedOut(oldAuthToken)) {\n return Object.assign(Object.assign({}, oldEntry), { authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ } });\n }\n return oldEntry;\n });\n}\nasync function fetchAuthTokenFromServer(installations, installationEntry) {\n try {\n const authToken = await generateAuthTokenRequest(installations, installationEntry);\n const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), { authToken });\n await set(installations.appConfig, updatedInstallationEntry);\n return authToken;\n }\n catch (e) {\n if (isServerError(e) &&\n (e.customData.serverCode === 401 || e.customData.serverCode === 404)) {\n // Server returned a \"FID not found\" or a \"Invalid authentication\" error.\n // Generate a new ID next time.\n await remove(installations.appConfig);\n }\n else {\n const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), { authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ } });\n await set(installations.appConfig, updatedInstallationEntry);\n }\n throw e;\n }\n}\nfunction isEntryRegistered(installationEntry) {\n return (installationEntry !== undefined &&\n installationEntry.registrationStatus === 2 /* RequestStatus.COMPLETED */);\n}\nfunction isAuthTokenValid(authToken) {\n return (authToken.requestStatus === 2 /* RequestStatus.COMPLETED */ &&\n !isAuthTokenExpired(authToken));\n}\nfunction isAuthTokenExpired(authToken) {\n const now = Date.now();\n return (now < authToken.creationTime ||\n authToken.creationTime + authToken.expiresIn < now + TOKEN_EXPIRATION_BUFFER);\n}\n/** Returns an updated InstallationEntry with an InProgressAuthToken. */\nfunction makeAuthTokenRequestInProgressEntry(oldEntry) {\n const inProgressAuthToken = {\n requestStatus: 1 /* RequestStatus.IN_PROGRESS */,\n requestTime: Date.now()\n };\n return Object.assign(Object.assign({}, oldEntry), { authToken: inProgressAuthToken });\n}\nfunction hasAuthTokenRequestTimedOut(authToken) {\n return (authToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */ &&\n authToken.requestTime + PENDING_TIMEOUT_MS < Date.now());\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Creates a Firebase Installation if there isn't one for the app and\n * returns the Installation ID.\n * @param installations - The `Installations` instance.\n *\n * @public\n */\nasync function getId(installations) {\n const installationsImpl = installations;\n const { installationEntry, registrationPromise } = await getInstallationEntry(installationsImpl);\n if (registrationPromise) {\n registrationPromise.catch(console.error);\n }\n else {\n // If the installation is already registered, update the authentication\n // token if needed.\n refreshAuthToken(installationsImpl).catch(console.error);\n }\n return installationEntry.fid;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Returns a Firebase Installations auth token, identifying the current\n * Firebase Installation.\n * @param installations - The `Installations` instance.\n * @param forceRefresh - Force refresh regardless of token expiration.\n *\n * @public\n */\nasync function getToken(installations, forceRefresh = false) {\n const installationsImpl = installations;\n await completeInstallationRegistration(installationsImpl);\n // At this point we either have a Registered Installation in the DB, or we've\n // already thrown an error.\n const authToken = await refreshAuthToken(installationsImpl, forceRefresh);\n return authToken.token;\n}\nasync function completeInstallationRegistration(installations) {\n const { registrationPromise } = await getInstallationEntry(installations);\n if (registrationPromise) {\n // A createInstallation request is in progress. Wait until it finishes.\n await registrationPromise;\n }\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function deleteInstallationRequest(appConfig, installationEntry) {\n const endpoint = getDeleteEndpoint(appConfig, installationEntry);\n const headers = getHeadersWithAuth(appConfig, installationEntry);\n const request = {\n method: 'DELETE',\n headers\n };\n const response = await retryIfServerError(() => fetch(endpoint, request));\n if (!response.ok) {\n throw await getErrorFromResponse('Delete Installation', response);\n }\n}\nfunction getDeleteEndpoint(appConfig, { fid }) {\n return `${getInstallationsEndpoint(appConfig)}/${fid}`;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Deletes the Firebase Installation and all associated data.\n * @param installations - The `Installations` instance.\n *\n * @public\n */\nasync function deleteInstallations(installations) {\n const { appConfig } = installations;\n const entry = await update(appConfig, oldEntry => {\n if (oldEntry && oldEntry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {\n // Delete the unregistered entry without sending a deleteInstallation request.\n return undefined;\n }\n return oldEntry;\n });\n if (entry) {\n if (entry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) {\n // Can't delete while trying to register.\n throw ERROR_FACTORY.create(\"delete-pending-registration\" /* ErrorCode.DELETE_PENDING_REGISTRATION */);\n }\n else if (entry.registrationStatus === 2 /* RequestStatus.COMPLETED */) {\n if (!navigator.onLine) {\n throw ERROR_FACTORY.create(\"app-offline\" /* ErrorCode.APP_OFFLINE */);\n }\n else {\n await deleteInstallationRequest(appConfig, entry);\n await remove(appConfig);\n }\n }\n }\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Sets a new callback that will get called when Installation ID changes.\n * Returns an unsubscribe function that will remove the callback when called.\n * @param installations - The `Installations` instance.\n * @param callback - The callback function that is invoked when FID changes.\n * @returns A function that can be called to unsubscribe.\n *\n * @public\n */\nfunction onIdChange(installations, callback) {\n const { appConfig } = installations;\n addCallback(appConfig, callback);\n return () => {\n removeCallback(appConfig, callback);\n };\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Returns an instance of {@link Installations} associated with the given\n * {@link @firebase/app#FirebaseApp} instance.\n * @param app - The {@link @firebase/app#FirebaseApp} instance.\n *\n * @public\n */\nfunction getInstallations(app = getApp()) {\n const installationsImpl = _getProvider(app, 'installations').getImmediate();\n return installationsImpl;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction extractAppConfig(app) {\n if (!app || !app.options) {\n throw getMissingValueError('App Configuration');\n }\n if (!app.name) {\n throw getMissingValueError('App Name');\n }\n // Required app config keys\n const configKeys = [\n 'projectId',\n 'apiKey',\n 'appId'\n ];\n for (const keyName of configKeys) {\n if (!app.options[keyName]) {\n throw getMissingValueError(keyName);\n }\n }\n return {\n appName: app.name,\n projectId: app.options.projectId,\n apiKey: app.options.apiKey,\n appId: app.options.appId\n };\n}\nfunction getMissingValueError(valueName) {\n return ERROR_FACTORY.create(\"missing-app-config-values\" /* ErrorCode.MISSING_APP_CONFIG_VALUES */, {\n valueName\n });\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst INSTALLATIONS_NAME = 'installations';\nconst INSTALLATIONS_NAME_INTERNAL = 'installations-internal';\nconst publicFactory = (container) => {\n const app = container.getProvider('app').getImmediate();\n // Throws if app isn't configured properly.\n const appConfig = extractAppConfig(app);\n const heartbeatServiceProvider = _getProvider(app, 'heartbeat');\n const installationsImpl = {\n app,\n appConfig,\n heartbeatServiceProvider,\n _delete: () => Promise.resolve()\n };\n return installationsImpl;\n};\nconst internalFactory = (container) => {\n const app = container.getProvider('app').getImmediate();\n // Internal FIS instance relies on public FIS instance.\n const installations = _getProvider(app, INSTALLATIONS_NAME).getImmediate();\n const installationsInternal = {\n getId: () => getId(installations),\n getToken: (forceRefresh) => getToken(installations, forceRefresh)\n };\n return installationsInternal;\n};\nfunction registerInstallations() {\n _registerComponent(new Component(INSTALLATIONS_NAME, publicFactory, \"PUBLIC\" /* ComponentType.PUBLIC */));\n _registerComponent(new Component(INSTALLATIONS_NAME_INTERNAL, internalFactory, \"PRIVATE\" /* ComponentType.PRIVATE */));\n}\n\n/**\n * The Firebase Installations Web SDK.\n * This SDK does not work in a Node.js environment.\n *\n * @packageDocumentation\n */\nregisterInstallations();\nregisterVersion(name, version);\n// BUILD_TARGET will be replaced by values like esm2017, cjs2017, etc during the compilation\nregisterVersion(name, version, 'esm2017');\n\nexport { deleteInstallations, getId, getInstallations, getToken, onIdChange };\n//# sourceMappingURL=index.esm2017.js.map\n","import '@firebase/installations';\nimport { Component } from '@firebase/component';\nimport { openDB, deleteDB } from 'idb';\nimport { ErrorFactory, validateIndexedDBOpenable, isIndexedDBAvailable, areCookiesEnabled, getModularInstance } from '@firebase/util';\nimport { _registerComponent, registerVersion, _getProvider, getApp } from '@firebase/app';\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst DEFAULT_SW_PATH = '/firebase-messaging-sw.js';\nconst DEFAULT_SW_SCOPE = '/firebase-cloud-messaging-push-scope';\nconst DEFAULT_VAPID_KEY = 'BDOU99-h67HcA6JeFXHbSNMu7e2yNNu3RzoMj8TM4W88jITfq7ZmPvIM1Iv-4_l2LxQcYwhqby2xGpWwzjfAnG4';\nconst ENDPOINT = 'https://fcmregistrations.googleapis.com/v1';\nconst CONSOLE_CAMPAIGN_ID = 'google.c.a.c_id';\nconst CONSOLE_CAMPAIGN_NAME = 'google.c.a.c_l';\nconst CONSOLE_CAMPAIGN_TIME = 'google.c.a.ts';\n/** Set to '1' if Analytics is enabled for the campaign */\nconst CONSOLE_CAMPAIGN_ANALYTICS_ENABLED = 'google.c.a.e';\nconst DEFAULT_REGISTRATION_TIMEOUT = 10000;\nvar MessageType$1;\n(function (MessageType) {\n MessageType[MessageType[\"DATA_MESSAGE\"] = 1] = \"DATA_MESSAGE\";\n MessageType[MessageType[\"DISPLAY_NOTIFICATION\"] = 3] = \"DISPLAY_NOTIFICATION\";\n})(MessageType$1 || (MessageType$1 = {}));\n\n/**\n * @license\n * Copyright 2018 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License. You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under the License\n * is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\n * or implied. See the License for the specific language governing permissions and limitations under\n * the License.\n */\nvar MessageType;\n(function (MessageType) {\n MessageType[\"PUSH_RECEIVED\"] = \"push-received\";\n MessageType[\"NOTIFICATION_CLICKED\"] = \"notification-clicked\";\n})(MessageType || (MessageType = {}));\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction arrayToBase64(array) {\n const uint8Array = new Uint8Array(array);\n const base64String = btoa(String.fromCharCode(...uint8Array));\n return base64String.replace(/=/g, '').replace(/\\+/g, '-').replace(/\\//g, '_');\n}\nfunction base64ToArray(base64String) {\n const padding = '='.repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding)\n .replace(/\\-/g, '+')\n .replace(/_/g, '/');\n const rawData = atob(base64);\n const outputArray = new Uint8Array(rawData.length);\n for (let i = 0; i < rawData.length; ++i) {\n outputArray[i] = rawData.charCodeAt(i);\n }\n return outputArray;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst OLD_DB_NAME = 'fcm_token_details_db';\n/**\n * The last DB version of 'fcm_token_details_db' was 4. This is one higher, so that the upgrade\n * callback is called for all versions of the old DB.\n */\nconst OLD_DB_VERSION = 5;\nconst OLD_OBJECT_STORE_NAME = 'fcm_token_object_Store';\nasync function migrateOldDatabase(senderId) {\n if ('databases' in indexedDB) {\n // indexedDb.databases() is an IndexedDB v3 API and does not exist in all browsers. TODO: Remove\n // typecast when it lands in TS types.\n const databases = await indexedDB.databases();\n const dbNames = databases.map(db => db.name);\n if (!dbNames.includes(OLD_DB_NAME)) {\n // old DB didn't exist, no need to open.\n return null;\n }\n }\n let tokenDetails = null;\n const db = await openDB(OLD_DB_NAME, OLD_DB_VERSION, {\n upgrade: async (db, oldVersion, newVersion, upgradeTransaction) => {\n var _a;\n if (oldVersion < 2) {\n // Database too old, skip migration.\n return;\n }\n if (!db.objectStoreNames.contains(OLD_OBJECT_STORE_NAME)) {\n // Database did not exist. Nothing to do.\n return;\n }\n const objectStore = upgradeTransaction.objectStore(OLD_OBJECT_STORE_NAME);\n const value = await objectStore.index('fcmSenderId').get(senderId);\n await objectStore.clear();\n if (!value) {\n // No entry in the database, nothing to migrate.\n return;\n }\n if (oldVersion === 2) {\n const oldDetails = value;\n if (!oldDetails.auth || !oldDetails.p256dh || !oldDetails.endpoint) {\n return;\n }\n tokenDetails = {\n token: oldDetails.fcmToken,\n createTime: (_a = oldDetails.createTime) !== null && _a !== void 0 ? _a : Date.now(),\n subscriptionOptions: {\n auth: oldDetails.auth,\n p256dh: oldDetails.p256dh,\n endpoint: oldDetails.endpoint,\n swScope: oldDetails.swScope,\n vapidKey: typeof oldDetails.vapidKey === 'string'\n ? oldDetails.vapidKey\n : arrayToBase64(oldDetails.vapidKey)\n }\n };\n }\n else if (oldVersion === 3) {\n const oldDetails = value;\n tokenDetails = {\n token: oldDetails.fcmToken,\n createTime: oldDetails.createTime,\n subscriptionOptions: {\n auth: arrayToBase64(oldDetails.auth),\n p256dh: arrayToBase64(oldDetails.p256dh),\n endpoint: oldDetails.endpoint,\n swScope: oldDetails.swScope,\n vapidKey: arrayToBase64(oldDetails.vapidKey)\n }\n };\n }\n else if (oldVersion === 4) {\n const oldDetails = value;\n tokenDetails = {\n token: oldDetails.fcmToken,\n createTime: oldDetails.createTime,\n subscriptionOptions: {\n auth: arrayToBase64(oldDetails.auth),\n p256dh: arrayToBase64(oldDetails.p256dh),\n endpoint: oldDetails.endpoint,\n swScope: oldDetails.swScope,\n vapidKey: arrayToBase64(oldDetails.vapidKey)\n }\n };\n }\n }\n });\n db.close();\n // Delete all old databases.\n await deleteDB(OLD_DB_NAME);\n await deleteDB('fcm_vapid_details_db');\n await deleteDB('undefined');\n return checkTokenDetails(tokenDetails) ? tokenDetails : null;\n}\nfunction checkTokenDetails(tokenDetails) {\n if (!tokenDetails || !tokenDetails.subscriptionOptions) {\n return false;\n }\n const { subscriptionOptions } = tokenDetails;\n return (typeof tokenDetails.createTime === 'number' &&\n tokenDetails.createTime > 0 &&\n typeof tokenDetails.token === 'string' &&\n tokenDetails.token.length > 0 &&\n typeof subscriptionOptions.auth === 'string' &&\n subscriptionOptions.auth.length > 0 &&\n typeof subscriptionOptions.p256dh === 'string' &&\n subscriptionOptions.p256dh.length > 0 &&\n typeof subscriptionOptions.endpoint === 'string' &&\n subscriptionOptions.endpoint.length > 0 &&\n typeof subscriptionOptions.swScope === 'string' &&\n subscriptionOptions.swScope.length > 0 &&\n typeof subscriptionOptions.vapidKey === 'string' &&\n subscriptionOptions.vapidKey.length > 0);\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// Exported for tests.\nconst DATABASE_NAME = 'firebase-messaging-database';\nconst DATABASE_VERSION = 1;\nconst OBJECT_STORE_NAME = 'firebase-messaging-store';\nlet dbPromise = null;\nfunction getDbPromise() {\n if (!dbPromise) {\n dbPromise = openDB(DATABASE_NAME, DATABASE_VERSION, {\n upgrade: (upgradeDb, oldVersion) => {\n // We don't use 'break' in this switch statement, the fall-through behavior is what we want,\n // because if there are multiple versions between the old version and the current version, we\n // want ALL the migrations that correspond to those versions to run, not only the last one.\n // eslint-disable-next-line default-case\n switch (oldVersion) {\n case 0:\n upgradeDb.createObjectStore(OBJECT_STORE_NAME);\n }\n }\n });\n }\n return dbPromise;\n}\n/** Gets record(s) from the objectStore that match the given key. */\nasync function dbGet(firebaseDependencies) {\n const key = getKey(firebaseDependencies);\n const db = await getDbPromise();\n const tokenDetails = (await db\n .transaction(OBJECT_STORE_NAME)\n .objectStore(OBJECT_STORE_NAME)\n .get(key));\n if (tokenDetails) {\n return tokenDetails;\n }\n else {\n // Check if there is a tokenDetails object in the old DB.\n const oldTokenDetails = await migrateOldDatabase(firebaseDependencies.appConfig.senderId);\n if (oldTokenDetails) {\n await dbSet(firebaseDependencies, oldTokenDetails);\n return oldTokenDetails;\n }\n }\n}\n/** Assigns or overwrites the record for the given key with the given value. */\nasync function dbSet(firebaseDependencies, tokenDetails) {\n const key = getKey(firebaseDependencies);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n await tx.objectStore(OBJECT_STORE_NAME).put(tokenDetails, key);\n await tx.done;\n return tokenDetails;\n}\n/** Removes record(s) from the objectStore that match the given key. */\nasync function dbRemove(firebaseDependencies) {\n const key = getKey(firebaseDependencies);\n const db = await getDbPromise();\n const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');\n await tx.objectStore(OBJECT_STORE_NAME).delete(key);\n await tx.done;\n}\nfunction getKey({ appConfig }) {\n return appConfig.appId;\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst ERROR_MAP = {\n [\"missing-app-config-values\" /* ErrorCode.MISSING_APP_CONFIG_VALUES */]: 'Missing App configuration value: \"{$valueName}\"',\n [\"only-available-in-window\" /* ErrorCode.AVAILABLE_IN_WINDOW */]: 'This method is available in a Window context.',\n [\"only-available-in-sw\" /* ErrorCode.AVAILABLE_IN_SW */]: 'This method is available in a service worker context.',\n [\"permission-default\" /* ErrorCode.PERMISSION_DEFAULT */]: 'The notification permission was not granted and dismissed instead.',\n [\"permission-blocked\" /* ErrorCode.PERMISSION_BLOCKED */]: 'The notification permission was not granted and blocked instead.',\n [\"unsupported-browser\" /* ErrorCode.UNSUPPORTED_BROWSER */]: \"This browser doesn't support the API's required to use the Firebase SDK.\",\n [\"indexed-db-unsupported\" /* ErrorCode.INDEXED_DB_UNSUPPORTED */]: \"This browser doesn't support indexedDb.open() (ex. Safari iFrame, Firefox Private Browsing, etc)\",\n [\"failed-service-worker-registration\" /* ErrorCode.FAILED_DEFAULT_REGISTRATION */]: 'We are unable to register the default service worker. {$browserErrorMessage}',\n [\"token-subscribe-failed\" /* ErrorCode.TOKEN_SUBSCRIBE_FAILED */]: 'A problem occurred while subscribing the user to FCM: {$errorInfo}',\n [\"token-subscribe-no-token\" /* ErrorCode.TOKEN_SUBSCRIBE_NO_TOKEN */]: 'FCM returned no token when subscribing the user to push.',\n [\"token-unsubscribe-failed\" /* ErrorCode.TOKEN_UNSUBSCRIBE_FAILED */]: 'A problem occurred while unsubscribing the ' +\n 'user from FCM: {$errorInfo}',\n [\"token-update-failed\" /* ErrorCode.TOKEN_UPDATE_FAILED */]: 'A problem occurred while updating the user from FCM: {$errorInfo}',\n [\"token-update-no-token\" /* ErrorCode.TOKEN_UPDATE_NO_TOKEN */]: 'FCM returned no token when updating the user to push.',\n [\"use-sw-after-get-token\" /* ErrorCode.USE_SW_AFTER_GET_TOKEN */]: 'The useServiceWorker() method may only be called once and must be ' +\n 'called before calling getToken() to ensure your service worker is used.',\n [\"invalid-sw-registration\" /* ErrorCode.INVALID_SW_REGISTRATION */]: 'The input to useServiceWorker() must be a ServiceWorkerRegistration.',\n [\"invalid-bg-handler\" /* ErrorCode.INVALID_BG_HANDLER */]: 'The input to setBackgroundMessageHandler() must be a function.',\n [\"invalid-vapid-key\" /* ErrorCode.INVALID_VAPID_KEY */]: 'The public VAPID key must be a string.',\n [\"use-vapid-key-after-get-token\" /* ErrorCode.USE_VAPID_KEY_AFTER_GET_TOKEN */]: 'The usePublicVapidKey() method may only be called once and must be ' +\n 'called before calling getToken() to ensure your VAPID key is used.'\n};\nconst ERROR_FACTORY = new ErrorFactory('messaging', 'Messaging', ERROR_MAP);\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function requestGetToken(firebaseDependencies, subscriptionOptions) {\n const headers = await getHeaders(firebaseDependencies);\n const body = getBody(subscriptionOptions);\n const subscribeOptions = {\n method: 'POST',\n headers,\n body: JSON.stringify(body)\n };\n let responseData;\n try {\n const response = await fetch(getEndpoint(firebaseDependencies.appConfig), subscribeOptions);\n responseData = await response.json();\n }\n catch (err) {\n throw ERROR_FACTORY.create(\"token-subscribe-failed\" /* ErrorCode.TOKEN_SUBSCRIBE_FAILED */, {\n errorInfo: err === null || err === void 0 ? void 0 : err.toString()\n });\n }\n if (responseData.error) {\n const message = responseData.error.message;\n throw ERROR_FACTORY.create(\"token-subscribe-failed\" /* ErrorCode.TOKEN_SUBSCRIBE_FAILED */, {\n errorInfo: message\n });\n }\n if (!responseData.token) {\n throw ERROR_FACTORY.create(\"token-subscribe-no-token\" /* ErrorCode.TOKEN_SUBSCRIBE_NO_TOKEN */);\n }\n return responseData.token;\n}\nasync function requestUpdateToken(firebaseDependencies, tokenDetails) {\n const headers = await getHeaders(firebaseDependencies);\n const body = getBody(tokenDetails.subscriptionOptions);\n const updateOptions = {\n method: 'PATCH',\n headers,\n body: JSON.stringify(body)\n };\n let responseData;\n try {\n const response = await fetch(`${getEndpoint(firebaseDependencies.appConfig)}/${tokenDetails.token}`, updateOptions);\n responseData = await response.json();\n }\n catch (err) {\n throw ERROR_FACTORY.create(\"token-update-failed\" /* ErrorCode.TOKEN_UPDATE_FAILED */, {\n errorInfo: err === null || err === void 0 ? void 0 : err.toString()\n });\n }\n if (responseData.error) {\n const message = responseData.error.message;\n throw ERROR_FACTORY.create(\"token-update-failed\" /* ErrorCode.TOKEN_UPDATE_FAILED */, {\n errorInfo: message\n });\n }\n if (!responseData.token) {\n throw ERROR_FACTORY.create(\"token-update-no-token\" /* ErrorCode.TOKEN_UPDATE_NO_TOKEN */);\n }\n return responseData.token;\n}\nasync function requestDeleteToken(firebaseDependencies, token) {\n const headers = await getHeaders(firebaseDependencies);\n const unsubscribeOptions = {\n method: 'DELETE',\n headers\n };\n try {\n const response = await fetch(`${getEndpoint(firebaseDependencies.appConfig)}/${token}`, unsubscribeOptions);\n const responseData = await response.json();\n if (responseData.error) {\n const message = responseData.error.message;\n throw ERROR_FACTORY.create(\"token-unsubscribe-failed\" /* ErrorCode.TOKEN_UNSUBSCRIBE_FAILED */, {\n errorInfo: message\n });\n }\n }\n catch (err) {\n throw ERROR_FACTORY.create(\"token-unsubscribe-failed\" /* ErrorCode.TOKEN_UNSUBSCRIBE_FAILED */, {\n errorInfo: err === null || err === void 0 ? void 0 : err.toString()\n });\n }\n}\nfunction getEndpoint({ projectId }) {\n return `${ENDPOINT}/projects/${projectId}/registrations`;\n}\nasync function getHeaders({ appConfig, installations }) {\n const authToken = await installations.getToken();\n return new Headers({\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n 'x-goog-api-key': appConfig.apiKey,\n 'x-goog-firebase-installations-auth': `FIS ${authToken}`\n });\n}\nfunction getBody({ p256dh, auth, endpoint, vapidKey }) {\n const body = {\n web: {\n endpoint,\n auth,\n p256dh\n }\n };\n if (vapidKey !== DEFAULT_VAPID_KEY) {\n body.web.applicationPubKey = vapidKey;\n }\n return body;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n// UpdateRegistration will be called once every week.\nconst TOKEN_EXPIRATION_MS = 7 * 24 * 60 * 60 * 1000; // 7 days\nasync function getTokenInternal(messaging) {\n const pushSubscription = await getPushSubscription(messaging.swRegistration, messaging.vapidKey);\n const subscriptionOptions = {\n vapidKey: messaging.vapidKey,\n swScope: messaging.swRegistration.scope,\n endpoint: pushSubscription.endpoint,\n auth: arrayToBase64(pushSubscription.getKey('auth')),\n p256dh: arrayToBase64(pushSubscription.getKey('p256dh'))\n };\n const tokenDetails = await dbGet(messaging.firebaseDependencies);\n if (!tokenDetails) {\n // No token, get a new one.\n return getNewToken(messaging.firebaseDependencies, subscriptionOptions);\n }\n else if (!isTokenValid(tokenDetails.subscriptionOptions, subscriptionOptions)) {\n // Invalid token, get a new one.\n try {\n await requestDeleteToken(messaging.firebaseDependencies, tokenDetails.token);\n }\n catch (e) {\n // Suppress errors because of #2364\n console.warn(e);\n }\n return getNewToken(messaging.firebaseDependencies, subscriptionOptions);\n }\n else if (Date.now() >= tokenDetails.createTime + TOKEN_EXPIRATION_MS) {\n // Weekly token refresh\n return updateToken(messaging, {\n token: tokenDetails.token,\n createTime: Date.now(),\n subscriptionOptions\n });\n }\n else {\n // Valid token, nothing to do.\n return tokenDetails.token;\n }\n}\n/**\n * This method deletes the token from the database, unsubscribes the token from FCM, and unregisters\n * the push subscription if it exists.\n */\nasync function deleteTokenInternal(messaging) {\n const tokenDetails = await dbGet(messaging.firebaseDependencies);\n if (tokenDetails) {\n await requestDeleteToken(messaging.firebaseDependencies, tokenDetails.token);\n await dbRemove(messaging.firebaseDependencies);\n }\n // Unsubscribe from the push subscription.\n const pushSubscription = await messaging.swRegistration.pushManager.getSubscription();\n if (pushSubscription) {\n return pushSubscription.unsubscribe();\n }\n // If there's no SW, consider it a success.\n return true;\n}\nasync function updateToken(messaging, tokenDetails) {\n try {\n const updatedToken = await requestUpdateToken(messaging.firebaseDependencies, tokenDetails);\n const updatedTokenDetails = Object.assign(Object.assign({}, tokenDetails), { token: updatedToken, createTime: Date.now() });\n await dbSet(messaging.firebaseDependencies, updatedTokenDetails);\n return updatedToken;\n }\n catch (e) {\n throw e;\n }\n}\nasync function getNewToken(firebaseDependencies, subscriptionOptions) {\n const token = await requestGetToken(firebaseDependencies, subscriptionOptions);\n const tokenDetails = {\n token,\n createTime: Date.now(),\n subscriptionOptions\n };\n await dbSet(firebaseDependencies, tokenDetails);\n return tokenDetails.token;\n}\n/**\n * Gets a PushSubscription for the current user.\n */\nasync function getPushSubscription(swRegistration, vapidKey) {\n const subscription = await swRegistration.pushManager.getSubscription();\n if (subscription) {\n return subscription;\n }\n return swRegistration.pushManager.subscribe({\n userVisibleOnly: true,\n // Chrome <= 75 doesn't support base64-encoded VAPID key. For backward compatibility, VAPID key\n // submitted to pushManager#subscribe must be of type Uint8Array.\n applicationServerKey: base64ToArray(vapidKey)\n });\n}\n/**\n * Checks if the saved tokenDetails object matches the configuration provided.\n */\nfunction isTokenValid(dbOptions, currentOptions) {\n const isVapidKeyEqual = currentOptions.vapidKey === dbOptions.vapidKey;\n const isEndpointEqual = currentOptions.endpoint === dbOptions.endpoint;\n const isAuthEqual = currentOptions.auth === dbOptions.auth;\n const isP256dhEqual = currentOptions.p256dh === dbOptions.p256dh;\n return isVapidKeyEqual && isEndpointEqual && isAuthEqual && isP256dhEqual;\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction externalizePayload(internalPayload) {\n const payload = {\n from: internalPayload.from,\n // eslint-disable-next-line camelcase\n collapseKey: internalPayload.collapse_key,\n // eslint-disable-next-line camelcase\n messageId: internalPayload.fcmMessageId\n };\n propagateNotificationPayload(payload, internalPayload);\n propagateDataPayload(payload, internalPayload);\n propagateFcmOptions(payload, internalPayload);\n return payload;\n}\nfunction propagateNotificationPayload(payload, messagePayloadInternal) {\n if (!messagePayloadInternal.notification) {\n return;\n }\n payload.notification = {};\n const title = messagePayloadInternal.notification.title;\n if (!!title) {\n payload.notification.title = title;\n }\n const body = messagePayloadInternal.notification.body;\n if (!!body) {\n payload.notification.body = body;\n }\n const image = messagePayloadInternal.notification.image;\n if (!!image) {\n payload.notification.image = image;\n }\n const icon = messagePayloadInternal.notification.icon;\n if (!!icon) {\n payload.notification.icon = icon;\n }\n}\nfunction propagateDataPayload(payload, messagePayloadInternal) {\n if (!messagePayloadInternal.data) {\n return;\n }\n payload.data = messagePayloadInternal.data;\n}\nfunction propagateFcmOptions(payload, messagePayloadInternal) {\n var _a, _b, _c, _d, _e;\n // fcmOptions.link value is written into notification.click_action. see more in b/232072111\n if (!messagePayloadInternal.fcmOptions &&\n !((_a = messagePayloadInternal.notification) === null || _a === void 0 ? void 0 : _a.click_action)) {\n return;\n }\n payload.fcmOptions = {};\n const link = (_c = (_b = messagePayloadInternal.fcmOptions) === null || _b === void 0 ? void 0 : _b.link) !== null && _c !== void 0 ? _c : (_d = messagePayloadInternal.notification) === null || _d === void 0 ? void 0 : _d.click_action;\n if (!!link) {\n payload.fcmOptions.link = link;\n }\n // eslint-disable-next-line camelcase\n const analyticsLabel = (_e = messagePayloadInternal.fcmOptions) === null || _e === void 0 ? void 0 : _e.analytics_label;\n if (!!analyticsLabel) {\n payload.fcmOptions.analyticsLabel = analyticsLabel;\n }\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction isConsoleMessage(data) {\n // This message has a campaign ID, meaning it was sent using the Firebase Console.\n return typeof data === 'object' && !!data && CONSOLE_CAMPAIGN_ID in data;\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n_mergeStrings('AzSCbw63g1R0nCw85jG8', 'Iaya3yLKwmgvh7cF0q4');\nfunction _mergeStrings(s1, s2) {\n const resultArray = [];\n for (let i = 0; i < s1.length; i++) {\n resultArray.push(s1.charAt(i));\n if (i < s2.length) {\n resultArray.push(s2.charAt(i));\n }\n }\n return resultArray.join('');\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction extractAppConfig(app) {\n if (!app || !app.options) {\n throw getMissingValueError('App Configuration Object');\n }\n if (!app.name) {\n throw getMissingValueError('App Name');\n }\n // Required app config keys\n const configKeys = [\n 'projectId',\n 'apiKey',\n 'appId',\n 'messagingSenderId'\n ];\n const { options } = app;\n for (const keyName of configKeys) {\n if (!options[keyName]) {\n throw getMissingValueError(keyName);\n }\n }\n return {\n appName: app.name,\n projectId: options.projectId,\n apiKey: options.apiKey,\n appId: options.appId,\n senderId: options.messagingSenderId\n };\n}\nfunction getMissingValueError(valueName) {\n return ERROR_FACTORY.create(\"missing-app-config-values\" /* ErrorCode.MISSING_APP_CONFIG_VALUES */, {\n valueName\n });\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nclass MessagingService {\n constructor(app, installations, analyticsProvider) {\n // logging is only done with end user consent. Default to false.\n this.deliveryMetricsExportedToBigQueryEnabled = false;\n this.onBackgroundMessageHandler = null;\n this.onMessageHandler = null;\n this.logEvents = [];\n this.isLogServiceStarted = false;\n const appConfig = extractAppConfig(app);\n this.firebaseDependencies = {\n app,\n appConfig,\n installations,\n analyticsProvider\n };\n }\n _delete() {\n return Promise.resolve();\n }\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function registerDefaultSw(messaging) {\n try {\n messaging.swRegistration = await navigator.serviceWorker.register(DEFAULT_SW_PATH, {\n scope: DEFAULT_SW_SCOPE\n });\n // The timing when browser updates sw when sw has an update is unreliable from experiment. It\n // leads to version conflict when the SDK upgrades to a newer version in the main page, but sw\n // is stuck with the old version. For example,\n // https://github.com/firebase/firebase-js-sdk/issues/2590 The following line reliably updates\n // sw if there was an update.\n messaging.swRegistration.update().catch(() => {\n /* it is non blocking and we don't care if it failed */\n });\n await waitForRegistrationActive(messaging.swRegistration);\n }\n catch (e) {\n throw ERROR_FACTORY.create(\"failed-service-worker-registration\" /* ErrorCode.FAILED_DEFAULT_REGISTRATION */, {\n browserErrorMessage: e === null || e === void 0 ? void 0 : e.message\n });\n }\n}\n/**\n * Waits for registration to become active. MDN documentation claims that\n * a service worker registration should be ready to use after awaiting\n * navigator.serviceWorker.register() but that doesn't seem to be the case in\n * practice, causing the SDK to throw errors when calling\n * swRegistration.pushManager.subscribe() too soon after register(). The only\n * solution seems to be waiting for the service worker registration `state`\n * to become \"active\".\n */\nasync function waitForRegistrationActive(registration) {\n return new Promise((resolve, reject) => {\n const rejectTimeout = setTimeout(() => reject(new Error(`Service worker not registered after ${DEFAULT_REGISTRATION_TIMEOUT} ms`)), DEFAULT_REGISTRATION_TIMEOUT);\n const incomingSw = registration.installing || registration.waiting;\n if (registration.active) {\n clearTimeout(rejectTimeout);\n resolve();\n }\n else if (incomingSw) {\n incomingSw.onstatechange = ev => {\n var _a;\n if (((_a = ev.target) === null || _a === void 0 ? void 0 : _a.state) === 'activated') {\n incomingSw.onstatechange = null;\n clearTimeout(rejectTimeout);\n resolve();\n }\n };\n }\n else {\n clearTimeout(rejectTimeout);\n reject(new Error('No incoming service worker found.'));\n }\n });\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function updateSwReg(messaging, swRegistration) {\n if (!swRegistration && !messaging.swRegistration) {\n await registerDefaultSw(messaging);\n }\n if (!swRegistration && !!messaging.swRegistration) {\n return;\n }\n if (!(swRegistration instanceof ServiceWorkerRegistration)) {\n throw ERROR_FACTORY.create(\"invalid-sw-registration\" /* ErrorCode.INVALID_SW_REGISTRATION */);\n }\n messaging.swRegistration = swRegistration;\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function updateVapidKey(messaging, vapidKey) {\n if (!!vapidKey) {\n messaging.vapidKey = vapidKey;\n }\n else if (!messaging.vapidKey) {\n messaging.vapidKey = DEFAULT_VAPID_KEY;\n }\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function getToken$1(messaging, options) {\n if (!navigator) {\n throw ERROR_FACTORY.create(\"only-available-in-window\" /* ErrorCode.AVAILABLE_IN_WINDOW */);\n }\n if (Notification.permission === 'default') {\n await Notification.requestPermission();\n }\n if (Notification.permission !== 'granted') {\n throw ERROR_FACTORY.create(\"permission-blocked\" /* ErrorCode.PERMISSION_BLOCKED */);\n }\n await updateVapidKey(messaging, options === null || options === void 0 ? void 0 : options.vapidKey);\n await updateSwReg(messaging, options === null || options === void 0 ? void 0 : options.serviceWorkerRegistration);\n return getTokenInternal(messaging);\n}\n\n/**\n * @license\n * Copyright 2019 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function logToScion(messaging, messageType, data) {\n const eventType = getEventType(messageType);\n const analytics = await messaging.firebaseDependencies.analyticsProvider.get();\n analytics.logEvent(eventType, {\n /* eslint-disable camelcase */\n message_id: data[CONSOLE_CAMPAIGN_ID],\n message_name: data[CONSOLE_CAMPAIGN_NAME],\n message_time: data[CONSOLE_CAMPAIGN_TIME],\n message_device_time: Math.floor(Date.now() / 1000)\n /* eslint-enable camelcase */\n });\n}\nfunction getEventType(messageType) {\n switch (messageType) {\n case MessageType.NOTIFICATION_CLICKED:\n return 'notification_open';\n case MessageType.PUSH_RECEIVED:\n return 'notification_foreground';\n default:\n throw new Error();\n }\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function messageEventListener(messaging, event) {\n const internalPayload = event.data;\n if (!internalPayload.isFirebaseMessaging) {\n return;\n }\n if (messaging.onMessageHandler &&\n internalPayload.messageType === MessageType.PUSH_RECEIVED) {\n if (typeof messaging.onMessageHandler === 'function') {\n messaging.onMessageHandler(externalizePayload(internalPayload));\n }\n else {\n messaging.onMessageHandler.next(externalizePayload(internalPayload));\n }\n }\n // Log to Scion if applicable\n const dataPayload = internalPayload.data;\n if (isConsoleMessage(dataPayload) &&\n dataPayload[CONSOLE_CAMPAIGN_ANALYTICS_ENABLED] === '1') {\n await logToScion(messaging, internalPayload.messageType, dataPayload);\n }\n}\n\nconst name = \"@firebase/messaging\";\nconst version = \"0.12.22\";\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nconst WindowMessagingFactory = (container) => {\n const messaging = new MessagingService(container.getProvider('app').getImmediate(), container.getProvider('installations-internal').getImmediate(), container.getProvider('analytics-internal'));\n navigator.serviceWorker.addEventListener('message', e => messageEventListener(messaging, e));\n return messaging;\n};\nconst WindowMessagingInternalFactory = (container) => {\n const messaging = container\n .getProvider('messaging')\n .getImmediate();\n const messagingInternal = {\n getToken: (options) => getToken$1(messaging, options)\n };\n return messagingInternal;\n};\nfunction registerMessagingInWindow() {\n _registerComponent(new Component('messaging', WindowMessagingFactory, \"PUBLIC\" /* ComponentType.PUBLIC */));\n _registerComponent(new Component('messaging-internal', WindowMessagingInternalFactory, \"PRIVATE\" /* ComponentType.PRIVATE */));\n registerVersion(name, version);\n // BUILD_TARGET will be replaced by values like esm2017, cjs2017, etc during the compilation\n registerVersion(name, version, 'esm2017');\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Checks if all required APIs exist in the browser.\n * @returns a Promise that resolves to a boolean.\n *\n * @public\n */\nasync function isWindowSupported() {\n try {\n // This throws if open() is unsupported, so adding it to the conditional\n // statement below can cause an uncaught error.\n await validateIndexedDBOpenable();\n }\n catch (e) {\n return false;\n }\n // firebase-js-sdk/issues/2393 reveals that idb#open in Safari iframe and Firefox private browsing\n // might be prohibited to run. In these contexts, an error would be thrown during the messaging\n // instantiating phase, informing the developers to import/call isSupported for special handling.\n return (typeof window !== 'undefined' &&\n isIndexedDBAvailable() &&\n areCookiesEnabled() &&\n 'serviceWorker' in navigator &&\n 'PushManager' in window &&\n 'Notification' in window &&\n 'fetch' in window &&\n ServiceWorkerRegistration.prototype.hasOwnProperty('showNotification') &&\n PushSubscription.prototype.hasOwnProperty('getKey'));\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nasync function deleteToken$1(messaging) {\n if (!navigator) {\n throw ERROR_FACTORY.create(\"only-available-in-window\" /* ErrorCode.AVAILABLE_IN_WINDOW */);\n }\n if (!messaging.swRegistration) {\n await registerDefaultSw(messaging);\n }\n return deleteTokenInternal(messaging);\n}\n\n/**\n * @license\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nfunction onMessage$1(messaging, nextOrObserver) {\n if (!navigator) {\n throw ERROR_FACTORY.create(\"only-available-in-window\" /* ErrorCode.AVAILABLE_IN_WINDOW */);\n }\n messaging.onMessageHandler = nextOrObserver;\n return () => {\n messaging.onMessageHandler = null;\n };\n}\n\n/**\n * @license\n * Copyright 2017 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * Retrieves a Firebase Cloud Messaging instance.\n *\n * @returns The Firebase Cloud Messaging instance associated with the provided firebase app.\n *\n * @public\n */\nfunction getMessagingInWindow(app = getApp()) {\n // Conscious decision to make this async check non-blocking during the messaging instance\n // initialization phase for performance consideration. An error would be thrown latter for\n // developer's information. Developers can then choose to import and call `isSupported` for\n // special handling.\n isWindowSupported().then(isSupported => {\n // If `isWindowSupported()` resolved, but returned false.\n if (!isSupported) {\n throw ERROR_FACTORY.create(\"unsupported-browser\" /* ErrorCode.UNSUPPORTED_BROWSER */);\n }\n }, _ => {\n // If `isWindowSupported()` rejected.\n throw ERROR_FACTORY.create(\"indexed-db-unsupported\" /* ErrorCode.INDEXED_DB_UNSUPPORTED */);\n });\n return _getProvider(getModularInstance(app), 'messaging').getImmediate();\n}\n/**\n * Subscribes the {@link Messaging} instance to push notifications. Returns a Firebase Cloud\n * Messaging registration token that can be used to send push messages to that {@link Messaging}\n * instance.\n *\n * If notification permission isn't already granted, this method asks the user for permission. The\n * returned promise rejects if the user does not allow the app to show notifications.\n *\n * @param messaging - The {@link Messaging} instance.\n * @param options - Provides an optional vapid key and an optional service worker registration.\n *\n * @returns The promise resolves with an FCM registration token.\n *\n * @public\n */\nasync function getToken(messaging, options) {\n messaging = getModularInstance(messaging);\n return getToken$1(messaging, options);\n}\n/**\n * Deletes the registration token associated with this {@link Messaging} instance and unsubscribes\n * the {@link Messaging} instance from the push subscription.\n *\n * @param messaging - The {@link Messaging} instance.\n *\n * @returns The promise resolves when the token has been successfully deleted.\n *\n * @public\n */\nfunction deleteToken(messaging) {\n messaging = getModularInstance(messaging);\n return deleteToken$1(messaging);\n}\n/**\n * When a push message is received and the user is currently on a page for your origin, the\n * message is passed to the page and an `onMessage()` event is dispatched with the payload of\n * the push message.\n *\n *\n * @param messaging - The {@link Messaging} instance.\n * @param nextOrObserver - This function, or observer object with `next` defined,\n * is called when a message is received and the user is currently viewing your page.\n * @returns To stop listening for messages execute this returned function.\n *\n * @public\n */\nfunction onMessage(messaging, nextOrObserver) {\n messaging = getModularInstance(messaging);\n return onMessage$1(messaging, nextOrObserver);\n}\n\n/**\n * The Firebase Cloud Messaging Web SDK.\n * This SDK does not work in a Node.js environment.\n *\n * @packageDocumentation\n */\nregisterMessagingInWindow();\n\nexport { deleteToken, getMessagingInWindow as getMessaging, getToken, isWindowSupported as isSupported, onMessage };\n//# sourceMappingURL=index.esm2017.js.map\n","import React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nexport default class Alert extends React.PureComponent {\n render() {\n return (
\n
\n
{this.props.title}
\n
{this.props.content}
\n
\n {this.props.onReject ?\n \n {this.props.reject || }\n \n :\n null\n }\n {this.props.onConfirm ?\n \n {this.props.confirm || }\n \n :\n null\n }\n
\n
\n
);\n }\n};\n","// Context Menu: popup/dropdown menu.\nimport React from 'react';\nimport { injectIntl, defineMessages } from 'react-intl';\n\nimport { REM_SIZE } from '../config.js';\n\nconst messages = defineMessages({\n info: {\n id: 'menu_item_info',\n defaultMessage: 'Info',\n description: 'Show extended topic information'\n },\n clear_messages: {\n id: 'menu_item_clear_messages',\n defaultMessage: 'Clear messages',\n description: 'Delete all messages'\n },\n clear_for_all: {\n id: 'menu_item_clear_messages_for_all',\n defaultMessage: 'Clear for All',\n description: 'Delete all message(s) for all members'\n },\n delete: {\n id: 'menu_item_delete',\n defaultMessage: 'Delete',\n description: 'Delete selected messages'\n },\n delete_for_all: {\n id: 'menu_item_delete_for_all',\n defaultMessage: 'Delete for All',\n description: 'Delete selected message(s) for all members'\n },\n send_retry: {\n id: 'menu_item_send_retry',\n defaultMessage: 'Retry',\n description: 'Retry sending message'\n },\n mute: {\n id: 'menu_item_mute',\n defaultMessage: 'Mute',\n description: 'Turn off notifications'\n },\n unmute: {\n id: 'menu_item_unmute',\n defaultMessage: 'Unmute',\n description: 'Turn notifications on'\n },\n reply: {\n id: 'menu_item_reply',\n defaultMessage: 'Reply',\n description: 'Reply to message'\n },\n forward: {\n id: 'menu_item_forward',\n defaultMessage: 'Forward',\n description: 'Forward message'\n },\n edit: {\n id: 'menu_item_edit',\n defaultMessage: 'Edit',\n description: 'Edit message'\n },\n topic_delete: {\n id: 'menu_item_delete_topic',\n defaultMessage: 'Delete',\n description: 'Delete entire topic'\n },\n topic_delete_warning: {\n id: 'topic_delete_warning',\n defaultMessage: 'Are you sure you want to delete this conversation? It cannot be undone.',\n description: 'Alert warning when deleting entire topic'\n },\n delete_messages_warning: {\n id: 'delete_messages_warning',\n defaultMessage: 'Are you sure you want to delete all messages for everyone? It cannot be undone.',\n description: 'Alert dialog warning when hard-deleting all messages.'\n },\n unblock: {\n id: 'menu_item_unblock',\n defaultMessage: 'Unblock',\n description: 'Unblock topic or user'\n },\n // Generic string suitable for either topic or user.\n block: {\n id: 'menu_item_block',\n defaultMessage: 'Block',\n description: 'Block topic or user'\n },\n topic_block_warning: {\n id: 'topic_block_warning',\n defaultMessage: 'Are you sure you want to block this conversation?',\n description: 'Alert warning when blocking a topic.'\n },\n member_delete: {\n id: 'menu_item_member_delete',\n defaultMessage: 'Remove',\n description: 'Remove user from topic'\n },\n archive: {\n id: 'menu_item_archive_topic',\n defaultMessage: 'Archive',\n description: 'Move topic from the list of active chats to archive'\n },\n unarchive: {\n id: 'menu_item_restore_topic',\n defaultMessage: 'Restore',\n description: 'Restore topic from archive'\n },\n edit_permissions: {\n id: 'menu_item_edit_permissions',\n defaultMessage: 'Edit permissions',\n description: 'Menu item [Edit permissions]'\n },\n clear_messages_warning: {\n id: 'clear_messages_warning',\n defaultMessage: 'Are you sure you want to clear all messages? It cannot be undone.',\n description: 'Alert dialog warning when deleting all messages.'\n },\n pin_message: {\n id: 'pin_message',\n defaultMessage: 'Pin',\n description: 'Menu item [Pin] for pinning message to the top.'\n },\n unpin_message: {\n id: 'unpin_message',\n defaultMessage: 'Unpin',\n description: 'Menu item [Unpin] for un-pinning the message.'\n },\n});\n\nclass ContextMenu extends React.Component {\n constructor(props) {\n super(props);\n\n this.selfRef = React.createRef();\n\n const {formatMessage} = props.intl;\n\n this.handlePageClick = this.handlePageClick.bind(this);\n this.handleEscapeKey = this.handleEscapeKey.bind(this);\n this.handleClick = this.handleClick.bind(this);\n\n // Preconfigured menu items.\n this.MenuItems = {\n 'topic_info': {\n id: 'topic_info',\n title: formatMessage(messages.info),\n handler: null\n },\n 'messages_clear': {\n id: 'messages_clear',\n title: formatMessage(messages.clear_messages),\n handler: (params, errorHandler) => {\n return props.onShowAlert(\n formatMessage(messages.clear_messages), // title\n formatMessage(messages.clear_messages_warning), // content\n (_ => { this.deleteMessages(true, false, params, errorHandler); }), // onConfirm\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n },\n 'messages_clear_hard': {\n id: 'messages_clear_hard',\n title: formatMessage(messages.clear_for_all),\n handler: (params, errorHandler) => {\n return props.onShowAlert(\n formatMessage(messages.clear_for_all), // title\n formatMessage(messages.delete_messages_warning), // content\n (_ => { return this.deleteMessages(true, true, params, errorHandler); }),\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n },\n 'message_delete': {\n id: 'message_delete',\n title: formatMessage(messages.delete),\n handler: (params, errorHandler) => {\n return this.deleteMessages(false, false, params, errorHandler);\n }\n },\n 'message_delete_hard': {\n id: 'message_delete_hard',\n title: formatMessage(messages.delete_for_all),\n handler: (params, errorHandler) => {\n return this.deleteMessages(false, true, params, errorHandler);\n }\n },\n // Hard-delete but with just 'Delete' title.\n 'message_delete_generic': {\n id: 'message_delete_generic',\n title: formatMessage(messages.delete),\n handler: (params, errorHandler) => {\n return this.deleteMessages(false, true, params, errorHandler);\n }\n },\n 'menu_item_send_retry': {\n id: 'menu_item_send_retry',\n title: formatMessage(messages.send_retry),\n handler: (params, errorHandler) => {\n return this.retryMessage(params, errorHandler);\n }\n },\n 'menu_item_reply': {\n id: 'menu_item_reply',\n title: formatMessage(messages.reply),\n handler: (params, errorHandler) => {\n return this.replyToMessage(params, errorHandler);\n }\n },\n 'menu_item_forward': {\n id: 'menu_item_forward',\n title: formatMessage(messages.forward),\n handler: _ => {} /* the action is taken directly in tinode-web */\n },\n 'menu_item_edit': {\n id: 'menu_item_edit',\n title: formatMessage(messages.edit),\n handler: (params, errorHandler) => {\n return this.editMessage(params, errorHandler);\n }\n },\n 'menu_item_pin': {\n id: 'menu_item_pin',\n title: formatMessage(messages.pin_message),\n handler: (params, errorHandler) => {\n return this.pinMessage(true, params, errorHandler);\n }\n },\n 'menu_item_unpin': {\n id: 'menu_item_unpin',\n title: formatMessage(messages.unpin_message),\n handler: (params, errorHandler) => {\n return this.pinMessage(false, params, errorHandler);\n }\n },\n 'topic_unmute': {\n id: 'topic_unmute',\n title: formatMessage(messages.unmute),\n handler: this.topicPermissionSetter.bind(this, '+P')\n },\n 'topic_mute': {\n id: 'topic_mute',\n title: formatMessage(messages.mute),\n handler: this.topicPermissionSetter.bind(this, '-P')\n },\n 'topic_unblock': {\n id: 'topic_unblock',\n title: formatMessage(messages.unblock),\n handler: this.topicPermissionSetter.bind(this, '+JP')\n },\n 'topic_block': {\n id: 'topic_block',\n title: formatMessage(messages.block),\n handler: (params, errorHandler) => {\n return props.onShowAlert(\n formatMessage(messages.block), // title\n formatMessage(messages.topic_block_warning), // content\n (_ => this.topicPermissionSetter('-JP', params, errorHandler).then(ctrl => {\n this.props.onTopicRemoved(params.topicName);\n return ctrl;\n })),\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n },\n 'topic_delete': {\n id: 'topic_delete',\n title: formatMessage(messages.topic_delete),\n handler: (params, errorHandler) => {\n return props.onShowAlert(\n formatMessage(messages.topic_delete), // title\n formatMessage(messages.topic_delete_warning), // content\n (_ => {\n const topic = this.props.tinode.getTopic(params.topicName);\n if (!topic) {\n console.warn(\"Topic not found: \", params.topicName);\n return;\n }\n return topic.delTopic(true).catch(err => {\n if (errorHandler) {\n errorHandler(err.message, 'err');\n }\n });\n }),\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n },\n 'topic_archive': {\n id: 'topic_archive',\n title: formatMessage(messages.archive),\n handler: (params, errorHandler) => {\n const topic = this.props.tinode.getTopic(params.topicName);\n if (!topic) {\n console.warn(\"Topic not found: \", params.topicName);\n return;\n }\n return topic.archive(true).catch(err => {\n if (errorHandler) {\n errorHandler(err.message, 'err');\n }\n });\n }\n },\n 'topic_restore': {\n id: 'topic_restore',\n title: formatMessage(messages.unarchive),\n handler: (params, errorHandler) => {\n const topic = this.props.tinode.getTopic(params.topicName);\n if (!topic) {\n console.warn(\"Topic not found: \", params.topicName);\n return;\n }\n return topic.archive(false).catch(err => {\n if (errorHandler) {\n errorHandler(err.message, 'err');\n }\n });\n }\n },\n // menu_item_edit_permissions is defined elsewhere.\n 'permissions': {\n id: 'permissions',\n title: formatMessage(messages.edit_permissions),\n handler: null\n },\n 'member_delete': {\n id: 'member_delete',\n title: formatMessage(messages.member_delete),\n handler: (params, errorHandler) => {\n const topic = this.props.tinode.getTopic(params.topicName);\n if (!topic || !params.user) {\n console.warn(\"Topic or user not found: '\" + params.topicName + \"', '\" + params.user + \"'\");\n return;\n }\n return topic.delSubscription(params.user).catch(err => {\n if (errorHandler) {\n errorHandler(err.message, 'err');\n }\n });\n }\n },\n 'member_mute': {\n id: 'member_mute',\n title: formatMessage(messages.mute),\n handler: this.topicPermissionSetter.bind(this, '-P')\n },\n 'member_unmute': {\n id: 'member_unmute',\n title: formatMessage(messages.unmute),\n handler: this.topicPermissionSetter.bind(this, '+P')\n },\n 'member_block': {\n id: 'member_block',\n title: formatMessage(messages.block),\n handler: this.topicPermissionSetter.bind(this, '-JP')\n },\n 'member_unblock': {\n id: 'member_unblock',\n title: formatMessage(messages.unblock),\n handler: this.topicPermissionSetter.bind(this, '+JP')\n },\n };\n }\n\n componentDidMount() {\n document.addEventListener('mousedown', this.handlePageClick, false);\n document.addEventListener('keyup', this.handleEscapeKey, false);\n }\n\n componentWillUnmount() {\n document.removeEventListener('mousedown', this.handlePageClick, false);\n document.removeEventListener('keyup', this.handleEscapeKey, false);\n }\n\n handlePageClick(e) {\n if (this.selfRef.current.contains(e.target)) {\n return;\n }\n e.preventDefault();\n e.stopPropagation();\n this.props.hide();\n }\n\n handleEscapeKey(e) {\n if (e.keyCode === 27) {\n this.props.hide();\n }\n }\n\n handleClick(e) {\n e.preventDefault();\n e.stopPropagation();\n this.props.hide();\n let item = this.props.items[e.currentTarget.dataset.id];\n if (typeof item == 'string') {\n item = this.MenuItems[item];\n }\n\n if (!item) {\n console.error(\"Invalid menu item ID\", e.currentTarget.dataset.id);\n } else {\n this.props.onAction(\n item.id,\n item.handler(this.props.params, this.props.onError),\n this.props.params);\n }\n }\n\n // Menu Actions\n\n deleteMessages(all, hard, params, errorHandler) {\n const topic = this.props.tinode.getTopic(params.topicName);\n if (!topic) {\n console.warn(\"Topic not found: \", params.topicName);\n return;\n }\n\n // We don't know if the message is still pending (e.g. attachment is being uploaded),\n // so try cancelling first. No harm if we can't cancel.\n // The message can be cancelled if transmission to the server has not\n // started yet or if the message send has failed.\n if (!all && topic.cancelSend(params.seq)) {\n return;\n }\n\n const promise = all ?\n topic.delMessagesAll(hard) :\n params.replace > 0 ?\n topic.delMessagesEdits(params.replace, hard) :\n topic.delMessagesList([params.seq], hard);\n\n return promise.catch(err => {\n if (errorHandler) {\n errorHandler(err.message, 'err');\n }\n });\n }\n\n // Retries sending failed message.\n retryMessage(params, errorHandler) {\n const topic = this.props.tinode.getTopic(params.topicName);\n // Remove the existing message entry.\n if (!topic || !topic.flushMessage(params.seq)) {\n return;\n }\n const msg = topic.createMessage(params.content, false);\n return topic.publishDraft(msg).catch(err => {\n if (errorHandler) {\n errorHandler(err.message, 'err');\n }\n });\n }\n\n // Pin or unpin the message.\n pinMessage(pin, params, errorHandler) {\n const topic = this.props.tinode.getTopic(params.topicName);\n if (!topic) {\n return;\n }\n topic.pinMessage(params.seq, pin)\n .catch(err => errorHandler ? errorHandler(err.message, 'err') : null);\n }\n\n // Function is used by context menu to set permissions.\n topicPermissionSetter(mode, params, errorHandler) {\n const topic = this.props.tinode.getTopic(params.topicName);\n if (!topic) {\n console.warn(\"Topic not found\", params.topicName);\n return;\n }\n\n let result = topic.updateMode(params.user, mode);\n if (errorHandler) {\n result = result.catch(err => errorHandler(err.message, 'err'));\n }\n return result;\n }\n\n replyToMessage(params, errorHandler) {\n params.pickReply(params.seq, params.content, params.userFrom, params.userName, errorHandler);\n }\n\n editMessage(params, errorHandler) {\n params.editMessage(params.replace || params.seq, params.content, errorHandler);\n }\n\n render() {\n const menu = [];\n let count = 0;\n this.props.items.forEach(item => {\n if (typeof item == 'string') {\n item = this.MenuItems[item];\n }\n if (item && item.title) {\n const className = item.disabled ? 'disabled' : undefined;\n menu.push(\n item.title == '-' ?\n \n :\n {item.title} \n );\n }\n count++;\n });\n\n // Ensure that menu is inside the app-container.\n const hSize = 12 * REM_SIZE;\n const vSize = REM_SIZE * (0.7 + menu.length * 2.5);\n const left = (this.props.bounds.right - this.props.clickAt.x < hSize) ?\n (this.props.clickAt.x - this.props.bounds.left - hSize) :\n (this.props.clickAt.x - this.props.bounds.left);\n const top = (this.props.bounds.bottom - this.props.clickAt.y < vSize) ?\n (this.props.clickAt.y - this.props.bounds.top - vSize) :\n (this.props.clickAt.y - this.props.bounds.top);\n\n const position = {\n left: left + 'px',\n top: top + 'px'\n };\n\n return (\n \n );\n }\n}\n\nexport default injectIntl(ContextMenu);\n","import React from 'react';\n\nconst icon_mapping = {'muted': 'notifications_off', 'banned': 'block', 'staff': 'verified_user'};\n\n/* Contact's labels: [you], or icons [muted], [blocked] */\nexport default class ContactBadges extends React.PureComponent {\n render() {\n let badges = null;\n if (this.props.badges && this.props.badges.length > 0) {\n badges = [];\n this.props.badges.forEach(b => {\n const color = (b.color ? ' ' + b.color : '');\n if (b.icon) {\n badges.push({icon_mapping[b.icon] || b.icon} );\n } else {\n badges.push({b.name} );\n }\n });\n return <>{badges}>;\n }\n return null;\n }\n};\n","// The counter of unread messages in the topic.\nimport React from 'react';\n\nexport default class UnreadBadge extends React.PureComponent {\n render() {\n return (this.props.count > 0 ?\n {this.props.count > 9 ? \"9+\" : this.props.count} \n : null);\n }\n};\n","// Chat message describing a video or voice call.\n\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { secondsToTime } from '../lib/strformat.js';\n\nexport default class CallMessage extends React.PureComponent {\n render() {\n const isCallDropped = ['busy', 'declined', 'disconnected', 'missed'].includes(this.props.callState);\n const successClass = 'material-icons medium ' + (isCallDropped ? 'red' : 'green');\n const callIcon = this.props.incoming ?\n (isCallDropped ? 'call_missed' : 'call_received') :\n (isCallDropped ? 'call_missed_outgoing' : 'call_made');\n const title = this.props.incoming ?\n :\n ;\n let duration;\n if (isCallDropped) {\n switch (this.props.callState) {\n case 'busy':\n duration = ;\n break;\n case 'declined':\n duration = ;\n break;\n case 'missed':\n duration = this.props.incoming ?\n :\n ;\n break;\n default:\n duration = ;\n break;\n }\n } else {\n duration = {secondsToTime(this.props.duration / 1000)} ;\n }\n return \n
call
\n
\n
{title}
\n
{callIcon} {duration}
\n
\n
;\n }\n}\n","// The counter of unread messages in the topic.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { secondsToTime } from '../lib/strformat.js';\n\n// Props:\n// incoming: true | false.\n// callState: 'busy' | 'declined' | 'disconnected' | 'missed'.\n// duration: (call duration in milliseconds).\nexport default class CallStatus extends React.PureComponent {\n render() {\n const isCallDropped = ['busy', 'declined', 'disconnected', 'missed'].includes(this.props.callState);\n const icon2 = this.props.incoming ?\n (isCallDropped ? 'call_missed' : 'call_received') :\n (isCallDropped ? 'call_missed_outgoing' : 'call_made');\n let duration;\n if (isCallDropped) {\n switch (this.props.callState) {\n case 'busy':\n duration = ;\n break;\n case 'declined':\n duration = ;\n break;\n case 'missed':\n duration = this.props.incoming ?\n :\n ;\n break;\n default:\n duration = ;\n break;\n }\n } else if (['accepted', 'started'].includes(this.props.callState) && !this.props.duration) {\n duration = \n } else {\n duration = {secondsToTime(this.props.duration / 1000)} ;\n }\n return (\n <>\n \n call {icon2} \n
{duration}\n >\n );\n }\n};\n","// Element which shows static video preview:\n// an image with duration and a play button in the middle.\n\nimport React from 'react';\n\nimport { secondsToTime } from '../lib/strformat.js'\n\nexport default class InlineVideo extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.videoRef = React.createRef();\n\n this.handleClick = this.handleClick.bind(this);\n }\n\n handleClick(e) {\n if (this.props.onClick) {\n // the click target has to be the image element.\n this.props.onClick(e);\n }\n }\n\n render() {\n const duration = secondsToTime(this.props['data-duration'] / 1000);\n const className = 'inline-video' + (this.props.onClick ? ' image-clickable' : '');\n return (\n \n {React.createElement('img', this.props)}\n
\n {this.props.onClick ?\n
play_arrow \n :\n
}\n
\n {duration ?
{duration}
: null}\n
\n );\n }\n};\n","// Image with a placeholder which is replaced when the promise is resolved.\nimport React from 'react';\n\nexport default class LazyImage extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n src: this.props.isvideo ? 'img/blankvid.png' : 'img/blankimg.png',\n style: Object.assign({padding: '4px'}, this.props.style),\n className: this.props.className,\n alt: this.props.alt,\n onClick: this.props.onClick,\n };\n }\n\n componentDidMount() {\n // whenDone is a wrapper around an actual promise to be able to cancel it.\n this.props.whenDone\n .promise\n .then(data => this.setState({src: data.src, style: {...this.state.style, padding: 0}}))\n .catch(_ => this.setState({src: this.props.isvideo ? 'img/broken_video.png' : 'img/broken_image.png'}));\n }\n\n componentWillUnmount() {\n this.props.whenDone.cancel();\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.whenDone != this.props.whenDone) {\n this.setState({src: this.props.isvideo ? 'img/blankvid.png' : 'img/blankimg.png', style: {...this.state.style, padding: '4px'}});\n this.props.whenDone\n .promise\n .then(data => this.setState({src: data.src, style: {...this.state.style, padding: 0}}))\n .catch(_ => this.setState({src: this.props.isvideo ? 'img/broken_video.png' : 'img/broken_image.png'}));\n }\n }\n\n render() {\n return React.createElement('img', this.state);\n }\n};\n","// File uload/download progress indicator with a cancel inside.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nexport default class FileProgress extends React.PureComponent {\n render() {\n return (\n \n );\n }\n}\n","// Image view with progress bar and a cancel button.\nimport React from 'react';\n\nimport FileProgress from './file-progress.jsx';\n\nexport default class UploadingImage extends React.PureComponent {\n constructor(props) {\n super(props);\n }\n\n render() {\n return (\n \n {React.createElement('img', this.props)}\n
\n \n
\n
\n );\n }\n};\n","import React from 'react';\nimport { defineMessages } from 'react-intl';\n\nimport { Drafty } from 'tinode-sdk';\n\nimport AudioPlayer from '../widgets/audio-player.jsx'\nimport CallMessage from '../widgets/call-message.jsx'\nimport CallStatus from '../widgets/call-status.jsx';\nimport InlineVideo from '../widgets/inline-video.jsx';\nimport LazyImage from '../widgets/lazy-image.jsx'\nimport UploadingImage from '../widgets/uploading-image.jsx'\n\nimport { BROKEN_IMAGE_SIZE, CLICKABLE_URL_SCHEMES, IMAGE_THUMBNAIL_DIM, NO_DIMENSIONS_VIDEO, REM_SIZE,\n VIDEO_THUMBNAIL_WIDTH } from '../config.js';\nimport { base64ToBlob, blobToBase64, fitImageSize, imageScaled } from './blob-helpers.js';\nimport { idToColorClass, secondsToTime, shortenFileName } from './strformat.js';\nimport { cancelablePromise, sanitizeUrl, sanitizeUrlForMime } from './utils.js';\n\nconst messages = defineMessages({\n drafty_form: {\n id: 'drafty_form',\n defaultMessage: 'Form: ',\n description: 'Comment for form in Drafty'\n },\n drafty_attachment: {\n id: 'drafty_attachment',\n defaultMessage: 'Attachment',\n description: 'Comment for attachment in Drafty'\n },\n drafty_image: {\n id: 'drafty_image',\n defaultMessage: 'Picture',\n description: 'Comment for embedded images in Drafty'\n },\n drafty_video: {\n id: 'drafty_video',\n defaultMessage: 'Video recording',\n description: 'Comment for videos embedded in Drafty'\n },\n drafty_unknown: {\n id: 'drafty_unknown',\n defaultMessage: 'Unsupported',\n description: 'Unsupported entity in drafty'\n }\n});\n\nconst JSON_MIME_TYPE = 'application/json+drafty';\nconst JSON_MIME_TYPE_LEGACY = 'application/json'; // Remove in 2026.\n\n// The main Drafty formatter: converts Drafty elements into React classes. 'this' is set by the caller.\n// 'this' must contain:\n// viewportWidth:\n// authorizeURL:\n// onImagePreview:\n// onVideoPreview:\n// onFormButtonClick:\n// onQuoteClick:\nexport function fullFormatter(style, data, values, key, stack) {\n if (stack.includes('QQ')) {\n return quoteFormatter.call(this, style, data, values, key);\n }\n\n if (!style) {\n // Unformatted.\n return values;\n }\n\n let el = Drafty.tagName(style);\n let attr = Drafty.attrValue(style, data) || {};\n attr.key = key;\n switch (style) {\n case 'AU':\n // Show audio player.\n if (attr.src) {\n attr.src = this.authorizeURL(sanitizeUrlForMime(attr.src, 'audio'));\n attr.duration = data.duration > 0 ? (data.duration | 0) : undefined;\n attr.preview = data.preview;\n attr.loading = 'lazy';\n }\n el = AudioPlayer;\n // Audio element cannot have content.\n values = null;\n break;\n case 'BR':\n values = null;\n break;\n case 'EX':\n // Ignore.\n break;\n case 'HL':\n // Highlighted text. Assign class name.\n attr.className = 'highlight';\n break;\n case 'HD':\n el = null;\n values = null;\n break;\n case 'IM':\n // Additional processing for images\n el = handleImageData.call(this, el, data, attr);\n // Image element cannot have content.\n values = null;\n break;\n case 'BN':\n // Button\n attr.onClick = this.onFormButtonClick;\n let inner = React.Children.map(values, (child) => {\n return typeof child == 'string' ? child : undefined;\n });\n if (!inner || inner.length == 0) {\n inner = [attr.name]\n }\n // Get text which will be sent back when the button is clicked.\n attr['data-title'] = inner.join('');\n break;\n case 'LN':\n if (attr) {\n // Ensure only safe URL schemes are clickable.\n attr.href = typeof attr.href == 'string' ? sanitizeUrl(attr.href, CLICKABLE_URL_SCHEMES) : '';\n }\n break;\n case 'MN':\n // Mention\n attr.className = 'mention'\n if (data) {\n attr.className += ' ' + idToColorClass(data.val, false, true);\n }\n break;\n case 'FM':\n // Form\n attr.className = 'bot-form';\n break;\n case 'RW':\n // Form element formatting is dependent on element content.\n break;\n case 'QQ':\n // Quote/citation.\n attr.className = 'reply-quote'\n attr.onClick = this.onQuoteClick;\n break;\n case 'VC':\n el = CallMessage;\n // Video call messages do not have content.\n values = null;\n if (data) {\n attr.callState = data.state;\n attr.incoming = data.incoming;\n attr.duration = data.duration;\n }\n break;\n case 'VD':\n // Additional processing for videos.\n el = handleVideoData.call(this, el, data, attr);\n // Video element cannot have content.\n values = null;\n break;\n default:\n if (!el) {\n // Unknown element.\n el = React.Fragment;\n attr = {key: key};\n // Generate comment for unknown element.\n let body = values;\n if (!Array.isArray(values) || !values.join('').trim()) {\n body = [{this.formatMessage(messages.drafty_unknown)} ];\n }\n values = [extension , ' '].concat(body);\n }\n break;\n }\n if (!el) {\n return values;\n }\n return React.createElement(el, attr, values);\n}\n\n// Additional processing of image data.\nfunction handleImageData(el, data, attr) {\n if (!data) {\n attr.src = 'img/broken_image.png';\n attr.style = {\n width: IMAGE_THUMBNAIL_DIM + 'px',\n height: IMAGE_THUMBNAIL_DIM + 'px',\n };\n return el;\n }\n\n attr.className = 'inline-image';\n const dim = fitImageSize(data.width, data.height,\n this.viewportWidth > 0 ? Math.min(this.viewportWidth - REM_SIZE * 6.5, REM_SIZE * 34.5) :\n REM_SIZE * 34.5, REM_SIZE * 24, false) ||\n {dstWidth: BROKEN_IMAGE_SIZE, dstHeight: BROKEN_IMAGE_SIZE};\n attr.style = {\n width: dim.dstWidth + 'px',\n height: dim.dstHeight + 'px',\n // Looks like a Chrome bug: broken image does not respect 'width' and 'height'.\n minWidth: dim.dstWidth + 'px',\n minHeight: dim.dstHeight + 'px'\n };\n if (!Drafty.isProcessing(data)) {\n attr.src = this.authorizeURL(sanitizeUrlForMime(attr.src, 'image'));\n attr.alt = data.name;\n if (attr.src) {\n if (Math.max(data.width || 0, data.height || 0) > IMAGE_THUMBNAIL_DIM) {\n // Allow previews for large enough images.\n attr.onClick = this.onImagePreview;\n attr.className += ' image-clickable';\n }\n attr.loading = 'lazy';\n } else {\n attr.src = null;\n }\n } else {\n // Use custom element instead of or .\n el = UploadingImage;\n }\n\n return el;\n}\n\n// Additional processing of attached video data.\nfunction handleVideoData(el, data, attr) {\n if (!data) {\n attr.src = 'img/broken_video.png';\n attr.style = {\n width: IMAGE_THUMBNAIL_DIM + 'px',\n height: IMAGE_THUMBNAIL_DIM + 'px',\n };\n return el;\n }\n attr.className = 'inline-image';\n const dim = fitImageSize(data.width, data.height,\n this.viewportWidth > 0 ? Math.min(this.viewportWidth - REM_SIZE * 6.5, REM_SIZE * 34.5) :\n REM_SIZE * 34.5, REM_SIZE * 24, false) ||\n {dstWidth: NO_DIMENSIONS_VIDEO, dstHeight: NO_DIMENSIONS_VIDEO};\n attr.style = {\n width: dim.dstWidth + 'px',\n height: dim.dstHeight + 'px',\n // Looks like a Chrome bug: broken image does not respect 'width' and 'height'.\n minWidth: dim.dstWidth + 'px',\n minHeight: dim.dstHeight + 'px'\n };\n if (!Drafty.isProcessing(data)) {\n attr.src = this.authorizeURL(sanitizeUrlForMime(attr.src, 'image'));\n attr.alt = data.name;\n if (data.ref || data.val) {\n attr.onClick = this.onVideoPreview;\n attr.loading = 'lazy';\n }\n el = InlineVideo;\n } else {\n // Use custom element instead of or .\n el = UploadingImage;\n }\n\n return el;\n}\n\n// Converts Drafty object into a one-line preview. 'this' is set by the caller.\n// 'this' must contain:\n// formatMessage: this.props.intl.formatMessage\n// messages: formatjs messages defined with defineMessages.\nexport function previewFormatter(style, data, values, key) {\n if (!style) {\n // Unformatted.\n return values;\n }\n\n let el = Drafty.tagName(style);\n const attr = { key: key };\n switch (style) {\n case 'AU':\n // Voicemail as '[mic] 0:00'.\n el = React.Fragment;\n values = [mic , ' ', secondsToTime(data.duration/1000)];\n break;\n case 'BR':\n // Replace new line with a space.\n el = React.Fragment;\n values = [' '];\n break;\n case 'HL':\n // Make highlight less prominent in preview.\n attr.className = 'highlight preview';\n break;\n case 'LN':\n case 'MN':\n // Disable links in previews.\n el = 'span';\n break;\n case 'IM':\n // Replace image with '[icon] Image'.\n el = React.Fragment;\n values = [photo , ' ', this.formatMessage(messages.drafty_image)];\n break;\n case 'BN':\n el = 'span';\n attr.className = 'flat-button faux';\n break;\n case 'FM':\n el = React.Fragment;\n values = [dashboard ,\n this.formatMessage(messages.drafty_form)].concat(' ', values || []);\n break;\n case 'RW':\n el = React.Fragment;\n break;\n case 'EX':\n if (data) {\n if (data.mime == JSON_MIME_TYPE || data.mime == JSON_MIME_TYPE_LEGACY) {\n // Ignore JSON attachments: they are form response payloads.\n return null;\n }\n // Clear payload.\n delete data.val;\n delete data.ref;\n }\n el = React.Fragment;\n values = [attachment , ' ', this.formatMessage(messages.drafty_attachment)];\n break;\n case 'VC':\n el = CallStatus;\n if (data) {\n attr.callState = data.state;\n attr.incoming = data.incoming;\n attr.duration = data.duration;\n }\n values = null;\n break;\n case 'QQ':\n case 'HD':\n el = null;\n values = null;\n break;\n case 'VD':\n // Replace image with '[icon] Video'.\n el = React.Fragment;\n values = [play_circle_outline , ' ', this.formatMessage(messages.drafty_video)];\n break;\n default:\n if (!el) {\n // Unknown element.\n el = React.Fragment;\n values = [extension , ' ', this.formatMessage(messages.drafty_unknown)];\n }\n break;\n }\n if (!el) {\n return values;\n }\n return React.createElement(el, attr, values);\n};\n\n// Converts Drafty object into a quoted reply; 'this' is set by the caller.\nfunction inlineImageAttr(attr, data) {\n attr.style = {\n width: IMAGE_THUMBNAIL_DIM + 'px',\n height: IMAGE_THUMBNAIL_DIM + 'px',\n maxWidth: IMAGE_THUMBNAIL_DIM + 'px',\n maxHeight: IMAGE_THUMBNAIL_DIM + 'px',\n }\n attr.className = 'inline-image';\n attr.alt = this.formatMessage(messages.drafty_image);\n if (!data) {\n attr.src = 'img/broken_image.png';\n } else {\n attr.src = attr.src || 'img/broken_image.png';\n }\n attr.title = attr.alt;\n return attr;\n}\n\n// Converts Drafty object into a quoted reply; 'this' is set by the caller.\nfunction inlineVideoAttr(attr, data) {\n const dim = fitImageSize(data.width, data.height, VIDEO_THUMBNAIL_WIDTH, IMAGE_THUMBNAIL_DIM);\n attr.style = {\n width: dim.width + 'px',\n height: dim.height + 'px',\n maxWidth: VIDEO_THUMBNAIL_WIDTH + 'px',\n maxHeight: IMAGE_THUMBNAIL_DIM + 'px',\n }\n attr.className = 'inline-image';\n attr.alt = this.formatMessage(messages.drafty_video);\n attr.title = attr.alt;\n if (!data) {\n attr.src = 'img/broken_video.png';\n } else {\n attr.src = attr.src || 'img/broken_video.png';\n }\n return attr;\n}\n\n// Displays a portion of Drafty within 'QQ' quotes. 'this' is set by the caller.\n// 'this' must contain:\n// formatMessage: this.props.intl.formatMessage\n// messages: formatjs messages defined with defineMessages.\n// authorizeURL: this.props.tinode.authorizeURL\n// onQuoteClick: this.handleQuoteClick (optional)\nfunction quoteFormatter(style, data, values, key) {\n if (['BR', 'EX', 'IM', 'MN', 'VD'].includes(style)) {\n let el = Drafty.tagName(style);\n let attr = Drafty.attrValue(style, data) || {};\n attr.key = key;\n switch(style) {\n case 'BR':\n values = null;\n break;\n case 'IM':\n attr = inlineImageAttr.call(this, attr, data);\n values = [React.createElement('img', attr, null), ' ', attr.alt];\n el = React.Fragment;\n // Fragment attributes.\n attr = {key: key};\n break;\n case 'VD':\n attr = inlineVideoAttr.call(this, attr, data);\n values = [React.createElement('img', attr, null), ' ', attr.alt];\n el = React.Fragment;\n // Fragment attributes.\n attr = {key: key};\n break;\n case 'MN':\n el = 'span';\n attr.className = 'mention'\n if (data) {\n attr.className += ' ' + idToColorClass(data.val, false, true);\n }\n break;\n case 'EX':\n let fname;\n if (data) {\n if (data.mime == JSON_MIME_TYPE || data.mime == JSON_MIME_TYPE_LEGACY) {\n // Ignore JSON attachments: they are form response payloads.\n return null;\n }\n fname = data.name;\n // Clear payload.\n delete data.val;\n delete data.ref;\n }\n el = React.Fragment;\n values = [attachment ,\n shortenFileName(fname, 16) || this.formatMessage(messages.drafty_attachment)];\n break;\n }\n return React.createElement(el, attr, values);\n }\n return previewFormatter.call(this, style, data, values, key);\n}\n\n// Create image thumbnail suitable for inclusion in a quote.\nfunction quoteImageOrVideo(data, isVideo) {\n let promise;\n let bits, ref, mime;\n if (isVideo) {\n bits = data.preview;\n mime = data.premime || 'image/jpeg';\n ref = data.preref;\n } else {\n bits = data.val;\n mime = data.mime;\n ref = data.ref;\n }\n // Get the blob from the image data.\n if (bits) {\n const blob = base64ToBlob(bits, mime);\n if (!blob) {\n throw new Error(\"Invalid image\");\n }\n promise = Promise.resolve(blob);\n } else if (ref) {\n promise = fetch(this.authorizeURL(sanitizeUrlForMime(ref, 'image')))\n .then(evt => {\n if (evt.ok) {\n return evt.blob();\n } else {\n throw new Error(`Image fetch unsuccessful: ${evt.status} ${evt.statusText}`);\n }\n });\n } else {\n throw new Error(\"Missing image data\");\n }\n\n // Scale the blob.\n return promise\n .then(blob => {\n // If it's an image, cut the square from the center of the image and shrink it.\n // If it's a video, allow it to be rectantular.\n return imageScaled(blob, isVideo ? VIDEO_THUMBNAIL_WIDTH : IMAGE_THUMBNAIL_DIM, IMAGE_THUMBNAIL_DIM, -1, !isVideo)\n }).then(scaled => {\n if (isVideo) {\n data.premime = scaled.mime;\n } else {\n data.mime = scaled.mime;\n }\n data.size = scaled.blob.size;\n data.width = scaled.width;\n data.height = scaled.height;\n delete data.ref;\n delete data.preref;\n // Keeping the original file name, if provided: ex.data.name;\n\n data.src = URL.createObjectURL(scaled.blob);\n return blobToBase64(scaled.blob);\n }).then(b64 => {\n if (isVideo) {\n data.preview = b64.bits;\n } else {\n data.val = b64.bits;\n }\n return data;\n }).catch(err => {\n delete data.val;\n delete data.preview;\n delete data.src;\n data.width = IMAGE_THUMBNAIL_DIM;\n data.height = IMAGE_THUMBNAIL_DIM;\n // Rethrow.\n throw err;\n });\n}\n\n// Create a preview of a reply.\nexport function replyFormatter(style, data, values, key, stack) {\n if (style == 'IM' || style == 'VD') {\n const isImage = style == 'IM';\n const attr = isImage ? inlineImageAttr.call(this, {key: key}, data) :\n inlineVideoAttr.call(this, {key: key}, data);\n\n let loadedPromise;\n try {\n loadedPromise = cancelablePromise(quoteImageOrVideo.call(this, data, style == 'VD'));\n } catch (error) {\n console.warn(\"Failed to quote image:\", error.message);\n loadedPromise = cancelablePromise(error);\n }\n attr.whenDone = loadedPromise;\n values = [React.createElement(LazyImage, attr, null), ' ', attr.alt];\n return React.createElement(React.Fragment, {key: key}, values);\n } else if (style == 'QQ') {\n if (stack.includes('QQ')) {\n // Quote inside quote when forwarding a message.\n return React.createElement('span', {key: key},\n [format_quote , ' ']);\n }\n\n const attr = Drafty.attrValue('QQ', data) || {};\n attr.key = key;\n attr.className = 'reply-quote'\n return React.createElement(Drafty.tagName('QQ'), attr, values);\n }\n return quoteFormatter.call(this, style, data, values, key);\n}\n","// A single topic or user.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport ContactBadges from './contact-badges.jsx';\nimport LetterTile from './letter-tile.jsx';\nimport UnreadBadge from './unread-badge.jsx';\n\nimport { Drafty } from 'tinode-sdk';\n\nimport { previewFormatter } from '../lib/formatters.js';\nimport { deliveryMarker } from '../lib/utils.js';\n\nconst messages = defineMessages({\n self_topic_name: {\n id: 'self_topic_name',\n defaultMessage: 'Saved messages',\n description: 'Name of self topic for UI'\n },\n self_topic_comment: {\n id: 'self_topic_comment',\n defaultMessage: 'Notes, messages, links, files saved for posterity',\n description: 'Comment for self topic for UI'\n }\n});\n\nclass Contact extends React.Component {\n constructor(props) {\n super(props);\n\n this.handleClick = this.handleClick.bind(this);\n this.handleContextClick = this.handleContextClick.bind(this);\n }\n\n handleClick(e) {\n e.preventDefault();\n e.stopPropagation();\n if (this.props.onSelected) {\n // Index this.props.index is used by GroupManager.\n this.props.onSelected(this.props.item, this.props.index);\n }\n }\n\n handleContextClick(e) {\n e.preventDefault();\n e.stopPropagation();\n this.props.showContextMenu({ topicName: this.props.item, y: e.pageY, x: e.pageX });\n }\n\n render() {\n let title = this.props.title;\n const self = Tinode.isSelfTopicName(this.props.item);\n if (!title) {\n if (self) {\n title = this.props.intl.formatMessage(messages.self_topic_name);\n } else {\n title = ;\n }\n } else if (title.length > 30) {\n // FIXME: this is probably wrong for RTL languages.\n title = title.substring(0, 28) + '…';\n }\n const online = this.props.now ? 'online' : 'offline';\n const avatar = this.props.avatar ? this.props.avatar : true;\n const badges = this.props.badges ? this.props.badges.slice() : [];\n const icon_badges = [];\n if (this.props.isVerified) {\n icon_badges.push({icon: 'verified', color: 'verified-color'});\n }\n if (this.props.isStaff) {\n icon_badges.push({icon: 'staff', color: 'staff-color'});\n }\n if (this.props.isDangerous) {\n icon_badges.push({icon: 'dangerous', color: 'danger-color'});\n }\n if (this.props.acs) {\n if (this.props.showMode) {\n badges.push({name: this.props.acs.getMode(), key: 'mode'});\n }\n if (this.props.acs.isMuted()) {\n icon_badges.push({icon: 'muted'});\n }\n if (!this.props.acs.isJoiner()) {\n icon_badges.push({icon: 'banned'});\n }\n }\n\n // The this.props.preview contains alreay shortened Drafty or string.\n let preview;\n if (typeof this.props.preview == 'string') {\n preview = this.props.preview;\n } else if (Drafty.isValid(this.props.preview)) {\n preview = React.createElement(React.Fragment, null, Drafty.format(this.props.preview, previewFormatter,\n {formatMessage: this.props.intl.formatMessage, previewIsResponse: this.props.previewIsResponse}));\n } else if (this.props.preview) {\n preview =\n <>warning_amber \n \n >;\n }\n\n const icon = deliveryMarker(this.props.received);\n const marker = icon ? {icon.name} : null;\n const titleClass = 'contact-title' + (this.props.deleted ? ' deleted' : '');\n\n const comment = preview || this.props.comment ||\n (self ? this.props.intl.formatMessage(messages.self_topic_comment) : '\\u00A0');\n return (\n \n \n \n {this.props.deleted ? cancel :\n (!self && this.props.showOnline) ? :\n (this.props.showCheckmark && this.props.selected) ?\n check_circle \n : null}\n
\n \n
{title} \n {this.props.isGroup ?
group : null}\n {this.props.isChannel ?
: null}\n {!self ?
: null}\n {!this.props.deleted ?
: null}\n
\n {this.props.showMode ?\n
:\n this.props.small ? null :
{marker}{comment}
}\n
\n {this.props.showContextMenu ?\n \n \n expand_more \n \n : null}\n \n );\n }\n};\n\nexport default injectIntl(Contact);\n","// A panel included into a list of contacts with an action text.\nimport React from 'react';\nimport { injectIntl } from 'react-intl';\n\nclass ContactAction extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleClick = this.handleClick.bind(this);\n }\n\n handleClick(e) {\n e.preventDefault();\n e.stopPropagation();\n this.props.onAction(this.props.action);\n }\n\n render() {\n const {formatMessage} = this.props.intl;\n return (\n \n {formatMessage(this.props.title, this.props.values)}
\n \n );\n }\n};\n\nexport default injectIntl(ContactAction);\n","// ContactList: component for showing a list of contacts,\n// such as a list of group members in a group chat.\nimport React from 'react';\nimport { defineMessages, injectIntl } from 'react-intl';\n\nimport { Drafty, Tinode } from 'tinode-sdk';\n\nimport Contact from './contact.jsx';\nimport ContactAction from './contact-action.jsx';\n\nimport { makeImageUrl } from '../lib/blob-helpers.js';\n\nimport { MESSAGE_PREVIEW_LENGTH } from '../config.js';\n\nconst messages = defineMessages({\n badge_you: {\n id: 'badge_you',\n defaultMessage: 'you',\n description: 'Badge for indicating the current user'\n },\n badge_owner: {\n id: 'badge_owner',\n defaultMessage: 'owner',\n description: 'Badge for indicating the owner'\n }\n});\n\nclass ContactList extends React.Component {\n render() {\n const { formatMessage } = this.props.intl;\n const showCheckmark = Array.isArray(this.props.topicSelected);\n const contactNodes = [];\n\n // Count of contacts, excluding action items.\n let contactsCount = 0;\n if (this.props.showSelfTopic) {\n const selected = showCheckmark ?\n (this.props.topicSelected.indexOf('slf') > -1) :\n (this.props.topicSelected === 'slf');\n contactNodes.push(\n \n );\n contactsCount ++;\n }\n if (this.props.contacts && this.props.contacts.length > 0) {\n this.props.contacts.forEach(c => {\n if (c.action) {\n // Action item\n contactNodes.push(\n );\n } else {\n // Normal contact\n const key = this.props.showMode ? c.user : (c.topic || c.user);\n // If filter function is provided, filter out the items\n // which don't satisfy the condition.\n if (this.props.filterFunc && this.props.filter) {\n const filterOn = [key];\n if (c.private && c.private.comment) {\n filterOn.push(('' + c.private.comment).toLowerCase());\n }\n if (c.public && c.public.fn) {\n filterOn.push(('' + c.public.fn).toLowerCase());\n }\n if (!this.props.filterFunc(this.props.filter, filterOn)) {\n return;\n }\n }\n\n const isChannel = Tinode.isChannelTopicName(key);\n const isGroup = !isChannel && Tinode.isGroupTopicName(key);\n const selected = showCheckmark ?\n (this.props.topicSelected.indexOf(key) > -1) :\n (this.props.topicSelected === key);\n const badges = [];\n if (this.props.showMode) {\n if (key == this.props.myUserId) {\n badges.push({name: formatMessage(messages.badge_you), color: 'green'});\n }\n if (c.acs && c.acs.isOwner()) {\n badges.push({name: formatMessage(messages.badge_owner), color: 'blue'});\n }\n }\n\n const comment = Array.isArray(c.private) ?\n c.private.join(',') : (c.private ? c.private.comment : null);\n let preview;\n let forwarded;\n let previewIsResponse;\n let deliveryStatus;\n if (!this.props.showMode && c.latestMessage) {\n const msg = c.latestMessage();\n if (msg) {\n forwarded = msg.head ? msg.head.forwarded : null;\n deliveryStatus = msg._status || c.msgStatus(msg, true);\n previewIsResponse = msg.from != this.props.myUserId;\n if (msg.content) {\n preview = typeof msg.content == 'string' ?\n msg.content.substr(0, MESSAGE_PREVIEW_LENGTH) :\n Drafty.preview(msg.content, MESSAGE_PREVIEW_LENGTH);\n }\n }\n }\n\n contactNodes.push(\n \n );\n contactsCount ++;\n }\n }, this);\n }\n\n return (\n \n {contactsCount == 0 ?\n
\n :\n null\n }\n {contactNodes.length > 0 ?\n
\n :\n null\n }\n
\n );\n }\n};\n\nexport default injectIntl(ContactList);\n","import React from 'react';\n\nimport { Tinode } from 'tinode-sdk';\n\nexport default class SearchContacts extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n edited: false,\n search: ''\n };\n\n this.handleSearchChange = this.handleSearchChange.bind(this);\n this.handleSearch = this.handleSearch.bind(this);\n this.handleClear = this.handleClear.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n }\n\n componentWillUnmount() {\n if (this.state.edited) {\n this.setState({search: '', edited: false});\n this.props.onSearchContacts(Tinode.DEL_CHAR);\n }\n }\n\n handleSearchChange(e) {\n this.setState({search: e.target.value});\n }\n\n handleSearch(e) {\n e.preventDefault();\n const query = this.state.search.trim();\n this.setState({edited: (query.length > 0)});\n this.props.onSearchContacts(query.length > 0 ? query : Tinode.DEL_CHAR);\n }\n\n handleClear(e) {\n e.preventDefault();\n if (this.state.edited) {\n this.props.onSearchContacts(Tinode.DEL_CHAR);\n }\n this.setState({search: '', edited: false});\n }\n\n handleKeyDown(e) {\n if (e.key === 'Enter') {\n this.handleSearch(e);\n } else if (e.key === 'Escape') {\n this.handleClear();\n }\n }\n\n render() {\n return (\n \n );\n }\n};\n","// Forward Menu: message forwarding popup/dropdown menu.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport ContactList from './contact-list.jsx';\nimport SearchContacts from './search-contacts.jsx';\n\nexport default class ForwardDialog extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n query: null\n };\n\n this.handleEscapeKey = this.handleEscapeKey.bind(this);\n this.handleClose = this.handleClose.bind(this);\n\n this.handleSearchContacts = this.handleSearchContacts.bind(this);\n this.handleContactSelected = this.handleContactSelected.bind(this);\n }\n\n componentDidMount() {\n this.props.onInitFind();\n }\n\n handleEscapeKey(e) {\n if (e.keyCode === 27) {\n // Not forwarding the message.\n this.props.hide(false);\n }\n }\n\n handleClose(e) {\n e.preventDefault();\n this.props.hide(false);\n }\n\n handleSearchContacts(query) {\n this.setState({ query: Tinode.isNullValue(query) ? null : query });\n this.props.onSearchContacts(query);\n }\n\n handleContactSelected(uid) {\n this.props.onTopicSelected(uid);\n this.props.hide(true);\n }\n\n render() {\n let contacts = this.state.query != null ? this.props.searchResults : this.props.contacts;\n // Filter out contacts without a 'W' or 'J' permissions as well as the current topic.\n contacts = contacts.filter((c) => {\n return (c.name != this.props.topicSelected) && c.acs.isJoiner() && c.acs.isWriter();\n });\n\n return (\n \n
\n
\n
{\n (search_placeholder) => \n } \n
{\n (not_found_placeholder) => \n } \n
\n
\n );\n }\n}\n","// Video call states.\nexport const CALL_STATE_NONE = 0;\nexport const CALL_STATE_OUTGOING_INITATED = 1;\nexport const CALL_STATE_INCOMING_RECEIVED = 2;\nexport const CALL_STATE_IN_PROGRESS = 3;\n\n// Video call message headers representing call state.\nexport const CALL_HEAD_STARTED = 'started';\n\n","// IncomingCall: displays Accept & Reject buttons for incoming calls.\nimport React from 'react';\n\nimport BadgeList from './badge-list.jsx';\nimport LetterTile from './letter-tile.jsx';\n\nimport { MAX_TITLE_LENGTH, MAX_PEER_TITLE_LENGTH } from '../config.js';\nimport { CALL_STATE_INCOMING_RECEIVED } from '../constants.js';\n\nimport { makeImageUrl } from '../lib/blob-helpers.js';\nimport { clipStr } from '../lib/utils.js'\n\nconst RING_SOUND = new Audio('audio/call-in.m4a');\n\nexport default class CallIncoming extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n topic: null,\n fullName: undefined,\n avatar: null,\n trustedBadges: [],\n previousMetaDesc: undefined,\n };\n\n this.resetDesc = this.resetDesc.bind(this);\n this.onMetaDesc = this.onMetaDesc.bind(this);\n this.handleRejectCall = this.handleRejectCall.bind(this);\n this.handleAcceptCall = this.handleAcceptCall.bind(this);\n this.ringTimer = null;\n }\n\n componentDidMount() {\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n\n this.resetDesc(topic);\n if (this.props.callState == CALL_STATE_INCOMING_RECEIVED) {\n // play() throws if the user did not click the app first: https://goo.gl/xX8pDD.\n RING_SOUND.play().catch(_ => {});\n this.ringTimer = setInterval(_ => {RING_SOUND.play().catch(_ => {})}, 2000);\n this.props.onRinging(this.props.topic, this.props.seq);\n }\n }\n\n // No need to separately handle component mount.\n componentDidUpdate(props) {\n const topic = this.props.tinode.getTopic(props.topic);\n if (!topic) {\n return;\n }\n\n if (this.onMetaDesc != topic.onMetaDesc) {\n this.previousMetaDesc = topic.onMetaDesc;\n topic.onMetaDesc = this.onMetaDesc;\n }\n\n if (this.state.topic != props.topic) {\n this.setState({topic: props.topic});\n this.resetDesc(topic, props);\n }\n }\n\n componentWillUnmount() {\n if (this.ringTimer != null) {\n clearInterval(this.ringTimer);\n RING_SOUND.pause();\n }\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n this.setState({topic: null});\n topic.onMetaDesc = this.previousMetaDesc;\n }\n\n resetDesc(topic) {\n const badges = [];\n if (topic.trusted) {\n for (const [key, val] of Object.entries(topic.trusted)) {\n if (val) {\n badges.push(key);\n }\n }\n }\n\n this.setState({\n fullName: clipStr(topic.public ? topic.public.fn : undefined, MAX_TITLE_LENGTH),\n avatar: makeImageUrl(topic.public ? topic.public.photo : null),\n trustedBadges: badges,\n });\n }\n\n onMetaDesc(desc) {\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n this.resetDesc(topic);\n\n if (this.previousMetaDesc && this.previousMetaDesc != this.onMetaDesc) {\n this.previousMetaDesc(desc);\n }\n }\n\n handleAcceptCall() {\n this.props.onAcceptCall(this.props.topic);\n }\n\n handleRejectCall() {\n this.props.onReject(this.props.topic, this.props.seq);\n this.props.onClose();\n }\n\n render() {\n return (\n \n
\n
\n
\n \n
\n
{clipStr(this.state.fullName, MAX_PEER_TITLE_LENGTH)}\n
\n
\n
\n {this.props.callState == CALL_STATE_INCOMING_RECEIVED ?\n <>\n \n call_end \n \n \n call \n \n >\n :\n null\n }\n
\n
\n
\n );\n }\n};\n","// The X menu to be displayed in title bars.\nimport React from 'react';\n\nexport default class MenuCancel extends React.PureComponent {\n render() {\n return (\n {e.preventDefault(); this.props.onCancel();}}>\n close \n \n );\n }\n}\n","import React from 'react';\n\nimport MenuCancel from './menu-cancel.jsx';\n\nexport default class ErrorPanel extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n show: false,\n };\n\n this.hide = this.hide.bind(this);\n }\n\n componentDidUpdate(prevProps) {\n if (prevProps.level !== this.props.level) {\n this.setState({\n show: !(!this.props.level)\n });\n }\n }\n\n hide() {\n this.setState({show: false});\n if (this.props.onClearError) {\n this.props.onClearError();\n }\n }\n\n render() {\n const icons = {err: 'error', warn: 'warning', info: 'info'}\n const level = icons[this.props.level] || '';\n const className = 'info-box ' + level;\n return (\n \n );\n }\n};\n","import React from 'react';\n\nimport LetterTile from './letter-tile.jsx';\n\nexport default class Chip extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleCancel = this.handleCancel.bind(this);\n }\n\n handleCancel(e) {\n e.preventDefault();\n this.props.onCancel(this.props.topic, this.props.index);\n }\n\n render() {\n const title = this.props.title || this.props.topic;\n const className = this.props.invalid ? 'chip invalid' : 'chip';\n return (\n \n {this.props.noAvatar ?\n
:\n
\n \n
\n }\n
{title} \n {this.props.onCancel && !this.props.required ?\n
× \n :
}\n
\n );\n }\n};\n","import React from 'react';\n\nimport Chip from './chip.jsx';\n\nimport { makeImageUrl } from '../lib/blob-helpers.js';\n\n/* BEGIN ChipInput: group membership widget */\nexport default class ChipInput extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = ChipInput.deriveStateFromProps(props);\n this.state.input = '';\n this.state.focused = false;\n\n this.handleTextInput = this.handleTextInput.bind(this);\n this.removeChipAt = this.removeChipAt.bind(this);\n this.handleChipCancel = this.handleChipCancel.bind(this);\n this.handleFocusGained = this.handleFocusGained.bind(this);\n this.handleFocusLost = this.handleFocusLost.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n }\n\n static deriveStateFromProps(props) {\n return {\n placeholder: props.chips ? '' : props.prompt,\n sortedChips: ChipInput.sortChips(props.chips, props.staticMembers),\n chipIndex: ChipInput.indexChips(props.chips)\n };\n }\n\n componentDidUpdate(prevProps, prevState) {\n if (prevProps.chips != this.props.chips ||\n prevProps.staticMembers != this.props.staticMembers ||\n prevProps.prompt != this.props.prompt) {\n this.setState(ChipInput.deriveStateFromProps(this.props));\n }\n if (!prevState || this.props.chips.length > prevState.sortedChips.length) {\n this.setState({input: ''});\n }\n }\n\n // Map chip index to user name\n static indexChips(chips) {\n const index = {};\n let count = 0;\n chips.forEach(item => {\n index[item.user] = count;\n count ++;\n });\n return index;\n }\n\n // Have non-removable chips appear before all other chips.\n static sortChips(chips, keep) {\n const required = [];\n const normal = [];\n chips.forEach(item => {\n if (keep && keep.includes(item.user)) {\n required.push(item);\n } else {\n normal.push(item);\n }\n });\n return required.concat(normal);\n }\n\n handleTextInput(e) {\n this.setState({input: e.target.value});\n if (this.props.filterFunc) {\n this.props.filterFunc(e.target.value);\n }\n }\n\n removeChipAt(idx) {\n const removed = this.state.sortedChips[idx];\n this.props.onChipRemoved(removed.user, this.state.chipIndex[removed.user]);\n }\n\n handleChipCancel(item, idx) {\n this.removeChipAt(idx);\n }\n\n handleFocusGained() {\n this.setState({focused: true});\n }\n\n handleFocusLost() {\n this.setState({focused: false});\n if (this.props.onFocusLost) {\n this.props.onFocusLost(this.state.input);\n }\n }\n\n handleKeyDown(e) {\n if (e.key === 'Backspace') {\n if (this.state.input.length == 0 && this.state.sortedChips.length > 0) {\n const at = this.state.sortedChips.length - 1;\n if (this.state.sortedChips[at].user !== this.props.staticMembers) {\n this.removeChipAt(at);\n }\n }\n } else if (e.key === 'Enter') {\n if (this.props.onEnter) {\n this.props.onEnter(this.state.input);\n }\n } else if (e.key === 'Escape') {\n if (this.props.onCancel) {\n this.props.onCancel();\n }\n }\n }\n\n render() {\n const chips = [];\n let count = 0;\n const staticMembers = this.props.staticMembers || [];\n this.state.sortedChips.forEach(item => {\n chips.push(\n \n );\n count++;\n });\n const className = \"chip-input\" + (this.state.focused ? ' focused' : '');\n const autoFocus = !(this.props.tabIndex > 0);\n return (\n \n {chips}\n \n
\n );\n }\n};\n","// GroupMembers: control for managing a list of group members.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport ChipInput from './chip-input.jsx';\nimport ContactList from './contact-list.jsx';\n\nconst messages = defineMessages({\n no_contacts: {\n id: 'no_contacts',\n defaultMessage: 'You have no contacts :-(',\n description: 'Shown in ContactsView when the user has no contacts'\n },\n contacts_not_found_short: {\n id: 'contacts_not_found_short',\n defaultMessage: \"No contacts match ''{query}''\",\n description: 'Shown in ContactsView when search returned no results'\n }\n});\n\nclass GroupManager extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n // Array of topic members\n members: props.members,\n index: GroupManager.indexMembers(props.members),\n staticMembers: GroupManager.staticMembers(props.members, props.keepInitialMembers, props.requiredMember),\n contactFilter: '',\n noContactsMessage: props.intl.formatMessage(messages.no_contacts),\n selectedContacts: GroupManager.selectedContacts(props.members)\n };\n\n this.handleContactSelected = this.handleContactSelected.bind(this);\n this.handleMemberRemoved = this.handleMemberRemoved.bind(this);\n this.handleContactFilter = this.handleContactFilter.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n }\n\n static indexMembers(members) {\n let index = {};\n members.forEach(m => {\n index[m.user] = {delta: 0, present: true}; // Delta: 0 unchanged, +1 added, -1 removed\n });\n return index;\n }\n\n static staticMembers(members, keepInitial, requiredMember) {\n let stat = [];\n members.forEach(m => {\n if (keepInitial || m.user == requiredMember) {\n stat.push(m.user);\n }\n });\n return stat;\n }\n\n static selectedContacts(members) {\n let sel = [];\n members.forEach(m => {\n sel.push(m.user);\n });\n return sel;\n }\n\n handleContactSelected(userId, index) {\n let status = this.state.index[userId];\n if (status) {\n if (status.present) {\n // Prevent duplicate members\n return;\n }\n status.delta += 1;\n status.present = true;\n } else {\n status = {delta: 1, present: true};\n }\n\n let m = this.state.members.slice();\n m.push(this.props.contacts[index]);\n\n const sel = GroupManager.selectedContacts(m);\n\n const i = this.state.index;\n i[userId] = status;\n\n this.setState({members: m, index: i, selectedContacts: sel});\n }\n\n handleMemberRemoved(userId, index) {\n const status = this.state.index[userId];\n if (!status || !status.present) {\n return;\n }\n status.present = false;\n status.delta -= 1;\n\n let m = this.state.members.slice();\n m.splice(index, 1);\n\n const sel = GroupManager.selectedContacts(m);\n\n const i = this.state.index;\n i[userId] = status;\n\n this.setState({members: m, index: i, selectedContacts: sel});\n }\n\n handleContactFilter(val) {\n const {formatMessage} = this.props.intl;\n const msg = !val ?\n formatMessage(messages.no_contacts) :\n formatMessage(messages.contacts_not_found_short, {query: val});\n\n this.setState({contactFilter: val, noContactsMessage: msg});\n }\n\n static doContactFiltering(filter, values) {\n if (filter) {\n for (let i=0; i= 0) {\n return true;\n }\n }\n return false;\n }\n return true;\n }\n\n handleSubmit() {\n const members = [];\n const added = [];\n const removed = [];\n\n const keys = Object.keys(this.state.index);\n keys.forEach(k => {\n if (this.state.index[k].present) {\n members.push(k);\n }\n\n if (this.state.index[k].delta > 0) {\n added.push(k);\n } else if (this.state.index[k].delta < 0) {\n removed.push(k);\n }\n });\n this.props.onSubmit(members, added, removed);\n }\n\n handleCancel() {\n this.props.onCancel();\n }\n\n render() {\n return (\n \n
\n \n \n \n
\n
\n \n
\n
\n \n \n \n
\n
\n
\n \n \n \n \n \n \n
\n
\n );\n }\n};\n\nexport default injectIntl(GroupManager);\n","// PermissionsEditor: Component for editing permissions\n// \nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport CheckBox from './checkbox.jsx';\nimport Contact from './contact.jsx';\n\nimport { makeImageUrl } from '../lib/blob-helpers.js';\n\n// Translatable permission names.\nconst messages = defineMessages({\n joiner: {\n id: 'permission_join',\n defaultMessage: \"Join ({val})\",\n description: 'Name of J permission'\n },\n reader: {\n id: 'permission_read',\n defaultMessage: \"Read ({val})\",\n description: 'Name of R permission'\n },\n writer: {\n id: 'permission_write',\n defaultMessage: \"Write ({val})\",\n description: 'Name of W permission'\n },\n preser: {\n id: 'permission_pres',\n defaultMessage: \"Get notified ({val})\",\n description: 'Name of P permission'\n },\n approver: {\n id: 'permission_admin',\n defaultMessage: \"Approve ({val})\",\n description: 'Name of A permission'\n },\n sharer: {\n id: 'permission_share',\n defaultMessage: \"Share ({val})\",\n description: 'Name of S permission'\n },\n deleter: {\n id: 'permission_delete',\n defaultMessage: \"Delete ({val})\",\n description: 'Name of D permission'\n },\n owner: {\n id: 'permission_owner',\n defaultMessage: \"Owner ({val})\",\n description: 'Name of O permission'\n }\n});\n\nclass PermissionsEditor extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n mode: (props.mode || '').replace('N', '')\n };\n\n this.handleChange = this.handleChange.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n }\n\n handleChange(val) {\n let mode = this.state.mode;\n const idx = mode.indexOf(val);\n if (idx == -1) {\n mode += val;\n } else {\n mode = mode.replace(val, '');\n }\n this.setState({mode: mode});\n }\n\n handleSubmit() {\n // Normalize string, otherwise cannot check if mode has changed.\n const mode = (this.state.mode || 'N').split('').sort().join('');\n const before = (this.props.mode || 'N').split('').sort().join('')\n if (mode !== before) {\n this.props.onSubmit(mode);\n } else {\n this.props.onCancel();\n }\n }\n\n handleCancel() {\n this.props.onCancel();\n }\n\n render() {\n const {formatMessage} = this.props.intl;\n const all = 'JRWPASDO';\n const names = {\n 'J': formatMessage(messages.joiner, {val: 'J'}),\n 'R': formatMessage(messages.reader, {val: 'R'}),\n 'W': formatMessage(messages.writer, {val: 'W'}),\n 'P': formatMessage(messages.preser, {val: 'P'}),\n 'A': formatMessage(messages.approver, {val: 'A'}),\n 'S': formatMessage(messages.sharer, {val: 'S'}),\n 'D': formatMessage(messages.deleter, {val: 'D'}),\n 'O': formatMessage(messages.owner, {val: 'O'})\n };\n\n let skip = this.props.skip || '';\n let mode = this.state.mode;\n let compare = (this.props.compare || '').replace('N', '');\n let items = [];\n for (let i=0; i= 0 && mode.indexOf(c) < 0) {\n // Permission is marked as inactive: hide unchecked permissions, disable checked permissions\n continue;\n }\n items.push(\n \n {names[c]} \n {skip.indexOf(c) < 0 ?\n = 0)} onChange={this.handleChange}/>\n :\n = 0)} />\n } {this.props.compare ? \n = 0)}/>\n : null}\n \n );\n }\n\n return (\n \n {this.props.userTitle ?\n
: null}\n
\n
\n {this.props.compare ?\n \n {this.props.modeTitle} \n {this.props.compareTitle} \n :\n null}\n \n {items}\n
\n
\n
\n \n \n \n \n \n \n
\n
\n );\n }\n};\n\nexport default injectIntl(PermissionsEditor);\n","var __WEBPACK_NAMESPACE_OBJECT__ = QRCode;","import QRCode from 'qrcodejs';\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { QRCODE_SIZE } from '../config';\n\nexport default class ShowQRCode extends React.PureComponent {\n constructor(props) {\n super(props);\n this.qrCodeRef = React.createRef();\n }\n\n componentDidMount() {\n new QRCode(this.qrCodeRef.current, {\n text: this.props.uri,\n width: QRCODE_SIZE,\n height: QRCODE_SIZE,\n });\n }\n\n render() {\n return (\n \n );\n }\n};\n","// In-place text editor. Shows text with an icon which toggles it into an input field.\nimport React from 'react';\n\nimport VisiblePassword from './visible-password.jsx';\n\nexport default class InPlaceEdit extends React.Component {\n constructor(props) {\n super(props);\n\n this.selfRef = React.createRef();\n\n this.state = {\n active: props.active,\n initialValue: props.value || '',\n value: props.value || '',\n valid: true\n };\n\n this.handeTextChange = this.handeTextChange.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleStartEditing = this.handleStartEditing.bind(this);\n this.handleEditingFinished = this.handleEditingFinished.bind(this);\n this.handlePasswordFinished = this.handlePasswordFinished.bind(this);\n }\n\n componentDidUpdate(prevProps, prevState) {\n // If text has changed while in read mode, update text and discard changes.\n // Ignore update if in edit mode.\n const newValue = this.props.value || '';\n if (prevState.initialValue != newValue && !prevState.active) {\n this.setState({\n initialValue: newValue,\n value: newValue\n });\n }\n }\n\n handeTextChange(e) {\n this.setState({value: e.target.value || ''});\n if (this.props.validator) {\n Promise.resolve(this.props.validator(e.target.value))\n .then(valid => {\n this.setState({valid: valid});\n })\n .catch(err => {\n // If it's interrupted, then the err is undefined. Ignore it.\n if (err) {\n this.setState({valid: false});\n }\n });\n }\n }\n\n handleKeyDown(e) {\n if (e.keyCode === 27) {\n // Escape pressed\n this.setState({value: this.props.value, active: false});\n } else if (e.keyCode === 13) {\n // Enter pressed\n this.handleEditingFinished(e);\n }\n }\n\n handleStartEditing() {\n if (!this.props.readOnly) {\n this.setState({active: true}, _ => {\n if (this.selfRef.current) {\n this.selfRef.current.focus();\n }\n });\n }\n }\n\n handleEditingFinished(event) {\n const value = this.state.value.trim();\n if (this.props.required && (!event.target.checkValidity() || !value)) {\n // Empty input\n this.setState({value: this.props.value, active: false});\n return;\n }\n this.setState({active: false});\n if ((value || this.props.value) && (value !== this.props.value) && this.state.valid) {\n this.props.onFinished(value);\n }\n }\n\n handlePasswordFinished(value) {\n this.setState({active: false});\n if (value && (value !== this.props.value)) {\n this.props.onFinished(value);\n }\n }\n\n render() {\n if (!this.state.active) {\n let spanText = this.props.type == 'password' ? '••••••••' : this.state.value;\n let spanClass = 'in-place-edit' + (this.props.readOnly ? ' disabled' : '');\n if (!spanText) {\n spanText = this.props.placeholder;\n spanClass += ' placeholder';\n }\n if (!this.props.multiline || this.props.multiline == 1) {\n spanClass += ' short';\n }\n\n return (\n {this.props.iconLeft && {this.props.iconLeft} }\n {spanText} \n {this.props.iconRight && {this.props.iconRight} }\n );\n }\n\n let element;\n const attr = {};\n if (this.props.type == 'password') {\n element = VisiblePassword;\n attr.onFinished = this.handlePasswordFinished;\n } else {\n if (this.props.multiline > 1) {\n element = 'textarea';\n attr.rows = this.props.multiline;\n attr.className = 'in-place-edit';\n } else {\n element = 'input';\n attr.type = this.props.type || 'text';\n attr.className = 'in-place-edit' + (this.props.iconLeft ? ' with-icon-left'\n : this.props.iconRight ? ' with-icon-right' : '');\n if (this.props.maxLength) {\n attr.maxLength=this.props.maxLength;\n }\n }\n attr.value = this.state.value;\n attr.className += this.state.valid ? '' : ' invalid';\n attr.ref = this.selfRef;\n attr.onChange = this.handeTextChange;\n attr.onKeyDown = this.handleKeyDown;\n attr.onBlur = this.handleEditingFinished;\n }\n attr.placeholder = this.props.placeholder;\n attr.required = this.props.required ? 'required' : '';\n attr.autoComplete = this.props.autoComplete;\n attr.autoFocus = true;\n if (this.props.spellCheck !== undefined) {\n attr.spellCheck = this.props.spellCheck ? 'true' : 'false';\n }\n\n if (this.props.iconLeft || this.props.iconRight) {\n return (\n <>\n {this.props.iconLeft && {this.props.iconLeft} }\n {React.createElement(element, attr, null)}\n {this.props.iconRight && {this.props.iconRight} }\n >\n );\n }\n return React.createElement(element, attr, null);\n }\n};\n","// TagManager: edit topic or user tags.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport ChipInput from './chip-input.jsx';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport { MAX_TAG_COUNT, MAX_TAG_LENGTH, MIN_TAG_LENGTH } from '../config.js';\nimport { arrayEqual } from '../lib/utils.js';\n\nexport default class TagManager extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n tags: this.props.tags || [],\n alias: Tinode.tagByPrefix(this.props.tags, Tinode.TAG_ALIAS) || '',\n tagInput: '',\n activated: this.props.activated\n };\n\n this.handleTagInput = this.handleTagInput.bind(this);\n this.handleAddTag = this.handleAddTag.bind(this);\n this.handleRemoveTag = this.handleRemoveTag.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n }\n\n static getDerivedStateFromProps(nextProps, prevState) {\n const tags = nextProps.tags || [];\n if (!arrayEqual(tags, prevState.tags) && !prevState.activated) {\n return {\n tags: tags || [],\n alias: Tinode.tagByPrefix(tags, Tinode.TAG_ALIAS) || '',\n };\n }\n return null;\n }\n\n handleTagInput(text) {\n this.setState({tagInput: text});\n if (text.length > 0) {\n const last = text[text.length-1];\n if (text[0] == '\"') {\n // This is a quoted string.\n if (text.length > 1 && last == '\"') {\n this.handleAddTag(text.substring(1, text.length-1));\n }\n } else if (last == ',' || last == ' ' || last == ';' || last == '\"') {\n // User entered ',', ' ' or ';'\n this.handleAddTag(text.substring(0, text.length-1).trim());\n }\n }\n }\n\n handleAddTag(tag) {\n const maxTagCount = this.props.tinode.getServerParam(Tinode.MAX_TAG_COUNT, MAX_TAG_COUNT);\n\n if (tag.length > 0 && this.state.tags.length < maxTagCount) {\n const tags = this.state.tags.slice(0);\n tags.push(tag);\n\n this.setState({tags: tags, tagInput: ''});\n if (this.props.onTagsChanged) {\n this.props.onTagsChanged(tags);\n }\n return tags;\n }\n return this.state.tags;\n }\n\n handleRemoveTag(tag, index) {\n const tags = this.state.tags.slice(0);\n tags.splice(index, 1);\n this.setState({tags: tags});\n if (this.props.onTagsChanged) {\n this.props.onTagsChanged(tags);\n }\n }\n\n handleSubmit() {\n // Add unprocessed input to tags.\n let tags = this.handleAddTag(this.state.tagInput.trim());\n // Add back the alias (and overwrite one possibly added by hand).\n tags = Tinode.setUniqueTag(tags, this.state.alias);\n // Submit the updated list.\n this.props.onSubmit(tags);\n this.setState({activated: false, tags: this.props.tags || []});\n }\n\n handleCancel() {\n this.setState({activated: false, tagInput: '', tags: this.props.tags || []});\n if (this.props.onCancel) {\n this.props.onCancel();\n }\n }\n\n render() {\n const minTagLength = this.props.tinode.getServerParam(Tinode.MIN_TAG_LENGTH, MIN_TAG_LENGTH);\n const maxTagLength = this.props.tinode.getServerParam(Tinode.MAX_TAG_LENGTH, MAX_TAG_LENGTH);\n\n let tags = [];\n if (this.state.activated) {\n this.state.tags.forEach(tag => {\n if (tag != this.state.alias) {\n tags.push({user: tag, invalid: (tag.length < minTagLength || tag.length > maxTagLength)});\n }\n });\n\n } else {\n this.state.tags.forEach(tag => {\n if (tag != this.state.alias) {\n tags.push({tag} );\n }\n });\n if (tags.length == 0) {\n tags = (\n \n \n \n );\n }\n }\n return (\n \n
\n {this.props.title} \n
\n {this.state.activated ?\n
\n
{\n (add_tags_prompt) => \n } \n {this.props.onSubmit || this.props.onCancel ?\n
\n \n \n \n \n \n \n
\n : null}\n
\n :\n
\n }\n
\n );\n }\n};\n","// Widget for editing topic description.\n\nimport React from 'react';\nimport { defineMessages, FormattedMessage, injectIntl } from 'react-intl';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport AvatarCrop from './avatar-crop.jsx';\nimport AvatarUpload from './avatar-upload.jsx';\nimport InPlaceEdit from './in-place-edit.jsx';\nimport TagManager from './tag-manager.jsx';\n\nimport { AVATAR_SIZE, MAX_AVATAR_BYTES, MAX_EXTERN_ATTACHMENT_SIZE, MAX_TITLE_LENGTH,\n MAX_TOPIC_DESCRIPTION_LENGTH } from '../config.js';\nimport { imageScaled, blobToBase64, makeImageUrl } from '../lib/blob-helpers.js';\nimport { arrayEqual, theCard } from '../lib/utils.js';\n\nconst messages = defineMessages({\n alias_invalid: {\n id: 'alias_invalid',\n defaultMessage: '(invalid)',\n description: 'Error message for invalid alias'\n },\n alias_already_taken: {\n id: 'alias_already_taken',\n defaultMessage: '(already taken)',\n description: 'Error message for alias already taken'\n },\n self_topic_name: {\n id: 'self_topic_name',\n defaultMessage: 'Saved messages',\n description: 'Name of self topic for UI'\n },\n self_topic_comment: {\n id: 'self_topic_comment',\n defaultMessage: 'Notes, messages, links, files saved for posterity',\n description: 'Comment for self topic for UI'\n }\n});\n\nconst ALIAS_AVAILABILITY_CHECK_DELAY = 1000; // milliseconds\n\nclass TopicDescEdit extends React.Component {\n constructor(props) {\n super(props);\n\n const topic = this.props.tinode.getTopic(this.props.topic);\n const acs = topic.getAccessMode();\n const isSelf = Tinode.isSelfTopicName(this.props.topic);\n this.state = {\n isMe: Tinode.isMeTopicName(this.props.topic),\n isSelf: isSelf,\n owner: acs && acs.isOwner(),\n fullName: topic.public ? topic.public.fn :\n isSelf ? this.props.intl.formatMessage(messages.self_topic_name) : null,\n private: topic.private ? topic.private.comment : null,\n description: topic.public ? topic.public.note :\n isSelf ? this.props.intl.formatMessage(messages.self_topic_comment) : null,\n avatar: makeImageUrl(topic.public ? topic.public.photo : null),\n tags: topic.tags() || [],\n newAvatar: null,\n newAvatarMime: null,\n aliasError: ''\n };\n\n this.previousOnTags = null;\n this.aliasCheckTimer = null;\n this.aliasCheckPromise = null;\n\n this.tnNewTags = this.tnNewTags.bind(this);\n this.handleFullNameUpdate = this.handleFullNameUpdate.bind(this);\n this.handleImageUpdated = this.handleImageUpdated.bind(this);\n this.handleAvatarCropped = this.handleAvatarCropped.bind(this);\n this.handleAvatarCropCancel = this.handleAvatarCropCancel.bind(this);\n this.uploadAvatar = this.uploadAvatar.bind(this);\n this.handlePrivateUpdate = this.handlePrivateUpdate.bind(this);\n this.handleAliasUpdate = this.handleAliasUpdate.bind(this);\n this.handleDescriptionUpdate = this.handleDescriptionUpdate.bind(this);\n this.handleTagsUpdated = this.handleTagsUpdated.bind(this);\n this.validateAlias = this.validateAlias.bind(this);\n this.cancelValidator = this.cancelValidator.bind(this);\n }\n\n componentDidMount() {\n const topic = this.props.tinode.getTopic(this.props.topic);\n this.previousOnTags = topic.onTagsUpdated;\n topic.onTagsUpdated = this.tnNewTags;\n }\n\n componentWillUnmount() {\n const topic = this.props.tinode.getTopic(this.props.topic);\n topic.onTagsUpdated = this.previousOnTags;\n this.cancelValidator();\n }\n\n tnNewTags(tags) {\n this.setState({tags: tags});\n }\n\n handleFullNameUpdate(fn) {\n fn = fn.trim().substring(0, MAX_TITLE_LENGTH);\n if (fn && this.state.fullName !== fn) {\n this.setState({fullName: fn});\n this.props.onUpdateTopicDesc(this.props.topic, theCard(fn, null));\n }\n }\n\n handlePrivateUpdate(comment) {\n comment = comment.trim().substring(0, MAX_TITLE_LENGTH);\n if (this.state.private !== comment) {\n this.setState({private: comment});\n this.props.onUpdateTopicDesc(this.props.topic, null, comment || Tinode.DEL_CHAR);\n }\n }\n\n handleDescriptionUpdate(desc) {\n desc = desc.trim().substring(0, MAX_TOPIC_DESCRIPTION_LENGTH);\n if (desc) {\n this.setState({description: desc});\n this.props.onUpdateTopicDesc(this.props.topic, theCard(null, null, null, desc));\n }\n }\n\n // AvatarUpload widget has changed the avatar: received a new file or deleted the avatar.\n handleImageUpdated(mime, img) {\n // This will show the AvatarCropView is img is not null.\n this.setState({newAvatar: img, newAvatarMime: mime});\n if (!img) {\n // Deleting the avatar.\n this.setState({avatar: null});\n this.props.onUpdateTopicDesc(this.props.topic, theCard(null, Tinode.DEL_CHAR));\n }\n }\n\n // AvatarCropView calls this method when the user has cropped the image.\n handleAvatarCropped(mime, blob, width, height) {\n const url = blob ? URL.createObjectURL(blob) : null;\n this.setState({avatar: url, newAvatar: null, newAvatarMime: null});\n if (blob) {\n this.uploadAvatar(mime, blob, width, height);\n }\n }\n\n // Utility method for converting cropped avatar blob to bytes for sending inband or\n // for uploading it to the server out of band.\n uploadAvatar(mime, blob, width, height) {\n const readyToUpload = image => {\n let {mime, blob} = image;\n if (blob.size > MAX_AVATAR_BYTES) {\n // Too large to send inband - uploading out of band and sending as a link.\n const uploader = this.props.tinode.getLargeFileHelper();\n uploader.upload(blob)\n .then(url => this.props.onUpdateTopicDesc(this.props.topic, theCard(null, url)))\n .catch(err => this.props.onError(err.message, 'err'));\n } else {\n // Convert blob to base64-encoded bits.\n blobToBase64(blob)\n .then(b64 => {\n const du = makeImageUrl({data: b64.bits, type: mime});\n this.setState({source: du});\n this.props.onUpdateTopicDesc(this.props.topic, theCard(null, du));\n });\n }\n };\n\n if (width > AVATAR_SIZE || height > AVATAR_SIZE || width != height) {\n // Avatar is not square or too large even after cropping. Shrink it and make square.\n imageScaled(blob, AVATAR_SIZE, AVATAR_SIZE, MAX_EXTERN_ATTACHMENT_SIZE, true)\n .then(scaled => readyToUpload(scaled))\n .catch(err => this.props.onError(err.message, 'err'));\n } else {\n readyToUpload({mime: mime, blob: blob, width: width, height: height});\n }\n }\n\n handleAvatarCropCancel() {\n this.setState({newAvatar: null, newAvatarMime: null});\n }\n\n handleAliasUpdate(alias) {\n alias = (alias || '').trim();\n const tags = alias ?\n Tinode.setUniqueTag(this.state.tags, Tinode.TAG_ALIAS + alias.toLowerCase()) :\n Tinode.clearTagPrefix(this.state.tags, Tinode.TAG_ALIAS);\n this.handleTagsUpdated(tags);\n }\n\n validateAlias(alias) {\n // Reset pending delayed check.\n this.cancelValidator();\n\n alias = alias.trim();\n if (!alias) {\n this.setState({aliasError: ''});\n return true;\n }\n\n const valid = Tinode.isValidTagValue(alias);\n if (!valid) {\n this.setState({aliasError: this.props.intl.formatMessage(messages.alias_invalid)});\n return false;\n }\n this.setState({aliasError: ''});\n\n // Setup a delayed check for alias availability.\n const fnd = this.props.tinode.getFndTopic();\n if (!fnd) {\n // Unable to check alias availability.\n this.setState({aliasError: ''});\n return true;\n }\n this.aliasCheckPromise = {};\n const validationPromise = new Promise((resolve, reject) => {\n this.aliasCheckPromise.resolve = resolve;\n this.aliasCheckPromise.reject = reject;\n });\n this.aliasCheckTimer = setTimeout(_ => {\n this.aliasCheckTimer = null;\n fnd.checkTagUniqueness(`${Tinode.TAG_ALIAS}${alias}`, this.props.topic)\n .then(ok => {\n this.aliasCheckPromise.resolve(ok)\n this.setState({aliasError: ok ? '' : this.props.intl.formatMessage(messages.alias_already_taken)});\n })\n .catch(err => {\n this.aliasCheckPromise.reject(err);\n this.setState({aliasError: err.message});\n });\n }, ALIAS_AVAILABILITY_CHECK_DELAY);\n return validationPromise;\n }\n\n cancelValidator() {\n // Reset pending delayed check.\n if (this.aliasCheckTimer) {\n clearTimeout(this.aliasCheckTimer);\n this.aliasCheckTimer = null;\n this.aliasCheckPromise.reject(null);\n }\n }\n\n handleTagsUpdated(tags) {\n // Check if tags have actually changed.\n if (arrayEqual(this.state.tags.slice(0), tags.slice(0))) {\n return;\n }\n this.props.onUpdateTags(tags);\n }\n\n render() {\n if (this.state.newAvatar) {\n return (\n \n );\n }\n\n const editable = this.state.isMe || (this.state.owner && !this.state.isSelf);\n let alias = this.state.tags && this.state.tags.find(t => t.startsWith('alias:'));\n if (alias) {\n // Remove 'alias:' prefix.\n alias = alias.substring(6);\n }\n\n return (\n <>\n \n
\n \n \n {this.state.isMe ?\n
\n
\n \n \n
\n {\n (full_name_placeholder) => \n } \n
\n
\n :\n <>\n
\n
\n \n
\n
\n {\n (group_name_placeholder) => \n } \n
\n
\n
\n
\n \n \n \n
\n
\n {\n (private_placeholder) => \n } \n
\n
\n >\n }\n {editable || alias ?\n
\n
\n {this.state.aliasError}\n
\n
\n {\n (private_placeholder) => \n } \n
\n
\n : null\n }\n {editable || this.state.description ?\n
\n
\n \n
\n
\n {\n (private_placeholder) => \n } \n
\n
\n : null\n }\n
\n {editable && !this.state.isMe ?\n <>\n
\n {\n (title_tag_manager) => \n } \n >\n : null\n }\n >\n );\n }\n};\n\nexport default injectIntl(TopicDescEdit);\n","// View for editing topic parameters (including 'me' topic).\n\nimport React from 'react';\n\nimport TopicDescEdit from '../widgets/topic-desc-edit.jsx';\n\nimport { arrayEqual } from '../lib/utils.js';\n\nexport default class TopicCommonView extends React.Component {\n constructor(props) {\n super(props);\n\n const topic = this.props.tinode.getTopic(this.props.topic);\n const acs = topic.getAccessMode();\n this.state = {\n tags: []\n };\n\n this.previousTagsUpdated = undefined;\n\n this.onTagsUpdated = this.onTagsUpdated.bind(this);\n this.handleTagsUpdated = this.handleTagsUpdated.bind(this);\n }\n\n // No need to separately handle component mount.\n componentDidUpdate(props) {\n const topic = this.props.tinode.getTopic(props.topic);\n if (!topic) {\n return;\n }\n\n if (topic.onTagsUpdated != this.onTagsUpdated) {\n if (topic.getType() == 'grp') {\n this.previousTagsUpdated = topic.onTagsUpdated;\n topic.onTagsUpdated = this.onTagsUpdated;\n } else {\n this.previousTagsUpdated = undefined;\n }\n }\n\n if (this.state.topic != props.topic) {\n this.setState({topic: props.topic});\n }\n }\n\n componentWillUnmount() {\n const topic = this.props.tinode.getTopic(this.props.topic);\n topic.onTagsUpdated = this.previousTagsUpdated;\n }\n\n // Server informs that the tags have been updated.\n onTagsUpdated(tags) {\n this.setState({tags: tags});\n\n if (this.previousTagsUpdated && this.previousTagsUpdated != this.onTagsUpdated) {\n this.previousTagsUpdated(tags);\n }\n }\n\n // Request server to change tags.\n handleTagsUpdated(tags) {\n if (!arrayEqual(this.state.tags.slice(0), tags.slice(0))) {\n this.props.onUpdateTagsRequest(this.props.topic, tags);\n }\n }\n\n render() {\n return (\n \n \n
\n );\n }\n};\n","// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nconst messages = defineMessages({\n clear_messages: {\n id: 'action_clear_messages',\n defaultMessage: 'Clear Messages',\n description: 'Flat button [Clear Messages] (soft-delete messages)'\n },\n clear_messages_warning: {\n id: 'clear_messages_warning',\n defaultMessage: 'Are you sure you want to clear all messages? It cannot be undone.',\n description: 'Alert dialog warning when deleting all messages.'\n },\n delete_messages: {\n id: 'action_delete_messages',\n defaultMessage: 'Clear Messages for All',\n description: 'Flat button [Clear for All] (hard-delete all messages)'\n },\n delete_messages_warning: {\n id: 'delete_messages_warning',\n defaultMessage: 'Are you sure you want to delete all messages for everyone? It cannot be undone.',\n description: 'Alert dialog warning when hard-deleting all messages.'\n },\n topic_delete: {\n id: 'topic_delete',\n defaultMessage: 'Delete Conversation',\n description: 'Alert title when deleting the topic.'\n },\n topic_delete_warning: {\n id: 'topic_delete_warning',\n defaultMessage: 'Are you sure you want to delete this conversation? It cannot be undone.',\n description: 'Alert warning when deleting entire topic'\n },\n leave_chat: {\n id: 'action_leave_chat',\n defaultMessage: 'Leave Conversation',\n description: 'Flat button [Leave Conversation]'\n },\n leave_chat_warning: {\n id: 'leave_chat_warning',\n defaultMessage: 'Are you sure you want to leave this conversation?',\n description: 'Alert dialog warning when unsubscribing from a chat.'\n },\n block_contact: {\n id: 'action_block_contact',\n defaultMessage: \"Block Contact\",\n description: \"Flat button [Block Contact]\"\n },\n block_contact_warning: {\n id: 'block_contact_warning',\n defaultMessage: 'Are you sure you want to block this contact?',\n description: 'Alert dialog warning when blocking a contact.'\n },\n report_chat: {\n id: 'action_report_chat',\n defaultMessage: 'Report Conversation',\n description: 'Flat button [Report Group]'\n },\n report_chat_warning: {\n id: 'report_chat_warning',\n defaultMessage: 'Are you sure you want to block and report this conversation?',\n description: 'Alert dialog warning when reporting a conversation for abuse'\n },\n other_user: {\n id: 'label_other_user',\n defaultMessage: 'Other',\n description: 'Label for the other user when the user is unnamed'\n },\n});\n\nclass TopicSecurity extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleDeleteTopic = this.handleDeleteTopic.bind(this);\n this.handleDeleteMessages = this.handleDeleteMessages.bind(this);\n this.handleLeave = this.handleLeave.bind(this);\n this.handleBlock = this.handleBlock.bind(this);\n this.handleReport = this.handleReport.bind(this);\n }\n\n handleDeleteTopic(e) {\n e.preventDefault();\n const {formatMessage} = this.props.intl;\n this.props.onShowAlert(\n formatMessage(messages.topic_delete), // title\n formatMessage(messages.topic_delete_warning), // content\n _ => this.props.onDeleteTopic(this.props.topic), // onConfirm\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n\n handleDeleteMessages(e) {\n e.preventDefault();\n const {formatMessage} = this.props.intl;\n this.props.onShowAlert(\n formatMessage(this.props.deleter ? messages.delete_messages : messages.clear_messages), // title\n formatMessage(this.props.deleter ? messages.delete_messages_warning : messages.clear_messages_warning), // content\n _ => this.props.onDeleteMessages(this.props.topic), // onConfirm\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n\n handleLeave(e) {\n e.preventDefault();\n const {formatMessage} = this.props.intl;\n this.props.onShowAlert(\n formatMessage(messages.leave_chat), // title\n formatMessage(messages.leave_chat_warning), // content\n _ => this.props.onLeaveTopic(this.props.topic), // onConfirm\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n\n handleBlock(e) {\n e.preventDefault();\n const {formatMessage} = this.props.intl;\n this.props.onShowAlert(\n formatMessage(messages.block_contact), // title\n formatMessage(messages.block_contact_warning), // content\n _ => this.props.onBlockTopic(this.props.topic), // onConfirm\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n\n handleReport(e) {\n e.preventDefault();\n const {formatMessage} = this.props.intl;\n this.props.onShowAlert(\n formatMessage(messages.report_chat), // title\n formatMessage(messages.report_chat_warning), // content\n (_ => { this.props.onReportTopic(this.props.topic); }), // onConfirm\n null, // \"OK\"\n true, // Show Reject button\n null // \"Cancel\"\n );\n }\n\n render() {\n const {formatMessage} = this.props.intl;\n return (\n \n
\n
\n
\n {this.props.groupTopic ?\n <>\n
\n \n \n {e.preventDefault(); this.props.onLaunchPermissionsEditor('want')}}>\n {this.props.access}\n \n
\n {!this.props.channel ?\n
\n
\n \n \n \n
\n
\n
Auth: {\n e.preventDefault();\n if (this.props.owner) {\n this.props.onLaunchPermissionsEditor('auth');\n }\n }}>{this.props.auth} \n
\n
Anon: {\n e.preventDefault();\n if (this.props.owner) {\n this.props.onLaunchPermissionsEditor('anon');\n }\n }}>{this.props.anon} \n
\n
\n
\n :\n null\n }\n >\n :\n
\n
\n \n \n \n
\n
\n
\n {e.preventDefault(); this.props.onLaunchPermissionsEditor('want')}}>\n {this.props.access}\n \n
\n
{this.props.fullName ? this.props.fullName : formatMessage(messages.other_user)}:\n {e.preventDefault(); this.props.onLaunchPermissionsEditor('given')}}>\n {this.props.modeGiven2}\n \n
\n
\n
\n }\n
\n
\n );\n }\n};\n\nexport default injectIntl(TopicSecurity);\n","// InfoView: panel with topic/user info.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport { AccessMode, Tinode } from 'tinode-sdk';\n\nimport AvatarUpload from '../widgets/avatar-upload.jsx';\nimport BadgeList from '../widgets/badge-list.jsx';\nimport CheckBox from '../widgets/checkbox.jsx';\nimport ContactList from '../widgets/contact-list.jsx';\nimport ErrorPanel from '../widgets/error-panel.jsx';\nimport GroupManager from '../widgets/group-manager.jsx';\nimport MenuCancel from '../widgets/menu-cancel.jsx';\nimport PermissionsEditor from '../widgets/permissions-editor.jsx';\nimport ShowQRCode from '../widgets/show-qrcode.jsx';\nimport TopicCommonView from './topic-common-view.jsx';\nimport TopicSecurity from '../widgets/topic-security.jsx';\n\nimport { MAX_TITLE_LENGTH, MAX_TOPIC_DESCRIPTION_LENGTH,\n NO_ACCESS_MODE, TOAST_DURATION } from '../config.js';\n\nimport { makeImageUrl } from '../lib/blob-helpers.js';\nimport { theCard, clipStr } from '../lib/utils.js';\n\nconst messages = defineMessages({\n info: {\n id: 'panel_title_info',\n description: 'Title for InfoView',\n defaultMessage: 'Info'\n },\n general: {\n id: 'panel_title_general',\n description: 'Title for TopicCommon.',\n defaultMessage: 'General'\n },\n security: {\n id: 'panel_title_security',\n description: 'Title for TopicSecirity and AccSecurity.',\n defaultMessage: 'Security'\n },\n members: {\n id: 'panel_title_members',\n description: 'Title for managing group members view.',\n defaultMessage: 'Members'\n },\n crop: {\n id: 'panel_title_crop',\n description: 'Title for AvatarCropView.',\n defaultMessage: 'Drag to Adjust'\n },\n perm_want: {\n id: 'requested_permissions',\n defaultMessage: 'Requested',\n description: 'Title for permissions'\n },\n perm_given: {\n id: 'granted_permissions',\n defaultMessage: 'Granted',\n description: 'Title for permissions'\n },\n perm_auth: {\n id: 'permissions_authenticated',\n defaultMessage: 'Authenticated',\n description: 'Title for editing default authenticated permissions'\n },\n perm_anon: {\n id: 'permissions_anonymous',\n defaultMessage: 'Anonymous',\n description: 'Title for editing default anonymous permissions'\n },\n perm_user: {\n id: 'permissions_user',\n defaultMessage: 'User\\'s Permissions',\n description: 'Title for editing user\\'s permissions'\n },\n edit_permissions: {\n id: 'menu_item_edit_permissions',\n defaultMessage: 'Edit permissions',\n description: 'Menu item [Edit permissions]'\n },\n qrcode: {\n id: 'scan_qr_code',\n defaultMessage: 'Scan QR Code',\n description: 'Title for scanning QR code'\n },\n text_copied: {\n id: 'text_copied',\n defaultMessage: 'Copied to clipboard',\n description: 'Notification that text has been copied to clipboard'\n },\n self_topic_name: {\n id: 'self_topic_name',\n defaultMessage: 'Saved messages',\n description: 'Name of self topic for UI',\n },\n self_topic_comment: {\n id: 'self_topic_comment',\n defaultMessage: 'Notes, messages, links, files saved for posterity',\n description: 'Comment for self topic for UI',\n },\n});\n\nclass InfoView extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n topic: null,\n owner: false,\n admin: false,\n sharer: false,\n deleter: false,\n muted: false,\n address: null,\n groupTopic: undefined,\n isSelf: false,\n channel: undefined,\n fullName: undefined,\n description: undefined,\n avatar: null,\n private: null,\n selectedContact: null,\n access: null,\n modeGiven: null,\n modeWant: null,\n modeGiven2: null, // P2P topic, the other user mode given\n modeWant2: null, // P2P topic, the other user mode want\n auth: null,\n anon: null,\n contactList: [],\n trustedBadges: [],\n previousMetaDesc: undefined,\n previousSubsUpdated: undefined,\n };\n\n this.resetSubs = this.resetSubs.bind(this);\n this.resetDesc = this.resetDesc.bind(this);\n this.resetTags = this.resetTags.bind(this);\n this.onMetaDesc = this.onMetaDesc.bind(this);\n this.onSubsUpdated = this.onSubsUpdated.bind(this);\n this.handleImageChanged = this.handleImageChanged.bind(this);\n this.handleMuted = this.handleMuted.bind(this);\n this.handleUnarchive = this.handleUnarchive.bind(this);\n this.handlePermissionsChanged = this.handlePermissionsChanged.bind(this);\n this.handleLaunchPermissionsEditor = this.handleLaunchPermissionsEditor.bind(this);\n this.handleShowQRCode = this.handleShowQRCode.bind(this);\n this.handleCopyToClipboard = this.handleCopyToClipboard.bind(this);\n this.handleShowAddMembers = this.handleShowAddMembers.bind(this);\n this.handleMemberUpdateRequest = this.handleMemberUpdateRequest.bind(this);\n this.handleMemberSelected = this.handleMemberSelected.bind(this);\n this.handleContextMenu = this.handleContextMenu.bind(this);\n this.handleBackNavigate = this.handleBackNavigate.bind(this);\n }\n\n // No need to separately handle component mount.\n componentDidUpdate(props) {\n const topic = this.props.tinode.getTopic(props.topic);\n if (!topic) {\n return;\n }\n\n if (this.onMetaDesc != topic.onMetaDesc) {\n this.previousMetaDesc = topic.onMetaDesc;\n topic.onMetaDesc = this.onMetaDesc;\n\n this.previousSubsUpdated = topic.onSubsUpdated;\n topic.onSubsUpdated = this.onSubsUpdated;\n }\n\n if (this.state.topic != props.topic) {\n this.setState({topic: props.topic});\n this.resetDesc(topic, props);\n this.resetSubs(topic, props);\n this.resetTags(topic);\n }\n }\n\n componentWillUnmount() {\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n this.setState({topic: null});\n topic.onMetaDesc = this.previousMetaDesc;\n topic.onSubsUpdated = this.previousSubsUpdated;\n }\n\n resetSubs(topic, props) {\n const newState = {contactList: []};\n if (topic.getType() == 'p2p') {\n // Fetch the other party in the p2p conversation.\n // Topic may not be ready yet, so check if user is found.\n const user2 = topic.subscriber(props.topic);\n if (user2) {\n newState.modeGiven2 = user2.acs.getGiven();\n newState.modeWant2 = user2.acs.getWant();\n } else {\n newState.modeGiven2 = NO_ACCESS_MODE;\n newState.modeWant2 = NO_ACCESS_MODE;\n }\n } else {\n topic.subscribers((sub) => {\n newState.contactList.push(sub);\n }, this);\n }\n\n this.setState(newState);\n }\n\n resetDesc(topic, props) {\n const defacs = topic.getDefaultAccess() || {};\n const acs = topic.getAccessMode();\n\n const badges = [];\n if (topic.trusted) {\n for (const [key, val] of Object.entries(topic.trusted)) {\n if (val) {\n badges.push(key);\n }\n }\n }\n\n const isSelf = topic.isSelfType();\n\n this.setState({\n owner: acs && acs.isOwner(),\n admin: acs && acs.isAdmin(),\n sharer: acs && acs.isSharer(),\n deleter: acs && acs.isDeleter(),\n muted: acs && acs.isMuted(),\n\n fullName: isSelf ?\n props.intl.formatMessage(messages.self_topic_name) :\n clipStr(topic.public && topic.public.fn, MAX_TITLE_LENGTH),\n description: isSelf ?\n props.intl.formatMessage(messages.self_topic_comment) :\n clipStr(topic.public && topic.public.note, MAX_TOPIC_DESCRIPTION_LENGTH),\n avatar: makeImageUrl(topic.public ? topic.public.photo : null),\n trustedBadges: badges,\n private: clipStr(topic.private && topic.private.comment, MAX_TITLE_LENGTH),\n archived: topic.isArchived(),\n address: topic.name,\n groupTopic: topic.isGroupType(),\n isSelf: isSelf,\n channel: topic.isChannelType() || topic.chan,\n access: acs ? acs.getMode() : undefined,\n modeGiven: acs ? acs.getGiven() : undefined,\n modeWant: acs ? acs.getWant() : undefined,\n auth: defacs.auth,\n anon: defacs.anon\n });\n }\n\n resetTags(topic) {\n if (topic.getType() != 'grp') {\n return;\n }\n\n const acs = topic.getAccessMode();\n if (acs && acs.isOwner()) {\n // Requesting tags: owner is editing the topic.\n topic.getMeta(topic.startMetaQuery().withTags().build());\n }\n }\n\n onMetaDesc(desc) {\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n this.resetDesc(topic, this.props);\n\n if (this.previousMetaDesc && this.previousMetaDesc != this.onMetaDesc) {\n this.previousMetaDesc(desc);\n }\n }\n\n onSubsUpdated(subs) {\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n this.resetSubs(topic, this.props);\n\n if (this.previousSubsUpdated && this.previousSubsUpdated != this.onSubsUpdated) {\n this.previousSubsUpdated(subs);\n }\n }\n\n handleImageChanged(mime, img) {\n this.setState({avatar: img});\n this.props.onTopicDescUpdate(this.props.topic, theCard(null, img || Tinode.DEL_CHAR), null);\n }\n\n handleMuted(ignored, checked) {\n this.setState({muted: checked});\n this.props.onChangePermissions(this.props.topic, checked ? '-P' : '+P');\n }\n\n handleUnarchive(ignored, ignored2) {\n this.props.onTopicUnArchive(this.props.topic);\n }\n\n handlePermissionsChanged(which, perm) {\n switch (which) {\n case 'auth':\n this.props.onTopicDescUpdateRequest(this.props.topic, null, null, {auth: perm});\n break;\n case 'anon':\n this.props.onTopicDescUpdateRequest(this.props.topic, null, null, {anon: perm});\n break;\n case 'mode':\n case 'want':\n this.props.onChangePermissions(this.props.topic, perm);\n break;\n case 'given':\n this.props.onChangePermissions(this.props.topic, perm, this.props.topic);\n break;\n case 'user':\n this.props.onChangePermissions(this.props.topic, perm, this.state.userPermissionsEdited);\n break;\n }\n\n this.handleBackNavigate();\n }\n\n handleLaunchPermissionsEditor(which, uid) {\n const {formatMessage} = this.props.intl;\n let toEdit, toCompare, toSkip, titleEdit, titleCompare, userTitle, userAvatar;\n switch (which) {\n case 'mode':\n toEdit = this.state.access;\n break;\n case 'want':\n toEdit = this.state.modeWant;\n toCompare = this.state.modeGiven;\n if (this.state.owner) {\n // Don't allow owner to unset 'O' permission. All other permissions are OK.\n toSkip = 'O';\n } else {\n // Allow accepting any of 'ASDO' permissions but don't allow asking for them.\n toSkip = AccessMode.encode(AccessMode.diff('ASDO', this.state.modeGiven));\n if (this.state.channel) {\n // Channels are read-only.\n toSkip += 'W';\n }\n }\n titleEdit = formatMessage(messages.perm_want);\n titleCompare = formatMessage(messages.perm_given);\n break;\n case 'given':\n toEdit = this.state.modeGiven2;\n toCompare = this.state.modeWant2;\n toSkip = this.state.groupTopic ? (this.state.owner ? '' : 'O') : 'ASDO';\n titleEdit = formatMessage(messages.perm_given);\n titleCompare = formatMessage(messages.perm_want);\n break;\n case 'auth':\n toEdit = this.state.auth;\n toSkip = 'O';\n break;\n case 'anon':\n toEdit = this.state.anon;\n toSkip = 'O';\n break;\n case 'user': {\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n const user = topic.subscriber(uid);\n if (!user || !user.acs) {\n return;\n }\n toEdit = user.acs.getGiven();\n toCompare = user.acs.getWant();\n toSkip = this.state.owner ? '' : 'O';\n titleEdit = formatMessage(messages.perm_given);\n titleCompare = formatMessage(messages.perm_want);\n if (user.public) {\n userTitle = user.public.fn;\n userAvatar = user.public.photo;\n }\n break;\n }\n default:\n console.error(\"Unknown permission editing mode '\" + which + \"'\");\n return;\n }\n this.setState({\n userPermissionsEdited: uid,\n userPermissionsTitle: userTitle,\n userPermissionsAvatar: userAvatar,\n editedPermissions: toEdit,\n immutablePermissions: toCompare,\n editedPermissionsTitle: titleEdit,\n immutablePermissionsTitle: titleCompare,\n editedPermissionsSkipped: toSkip,\n });\n this.props.onNavigate(`perm/${which}`);\n }\n\n handleShowQRCode(e) {\n e.preventDefault();\n this.props.onNavigate('qrcode');\n }\n\n handleCopyToClipboard(e, text) {\n e.preventDefault();\n navigator.clipboard.writeText(text).then(_ => {\n this.setState({toast: this.props.intl.formatMessage(messages.text_copied)});\n setTimeout(_ => { this.setState({toast: ''}); }, TOAST_DURATION);\n });\n\n }\n\n handleShowAddMembers(e) {\n e.preventDefault();\n this.props.onInitFind();\n this.props.onNavigate('members');\n }\n\n handleMemberUpdateRequest(members, added, removed) {\n this.props.onMemberUpdateRequest(this.props.topic, added, removed);\n this.props.onNavigate('info');\n }\n\n handleMemberSelected(uid) {\n this.setState({selectedContact: uid});\n }\n\n handleBackNavigate() {\n const args = (this.props.panel || 'info').split('/');\n if (args[0] == 'info') {\n this.props.onNavigate(null);\n } else if (args[0] == 'perm') {\n if (args[1] == 'user') {\n this.props.onNavigate('info');\n } else {\n this.props.onNavigate('security');\n }\n } else {\n this.props.onNavigate('info');\n }\n }\n\n handleContextMenu(params) {\n const {formatMessage} = this.props.intl;\n const topic = this.props.tinode.getTopic(this.props.topic);\n if (!topic) {\n return;\n }\n const user = topic.subscriber(params.topicName);\n if (!user || !user.acs) {\n return;\n }\n\n const isMe = this.props.tinode.isMe(params.topicName);\n const menuItems = [{\n title: formatMessage(messages.edit_permissions),\n handler: _ => this.handleLaunchPermissionsEditor(isMe ? 'want' : 'user', params.topicName)\n }];\n if (!isMe) {\n menuItems.push('member_delete');\n }\n menuItems.push(user.acs.isMuted() ? 'member_unmute' : 'member_mute');\n if (!isMe) {\n menuItems.push(user.acs.isJoiner() ? 'member_block' : 'member_unblock');\n }\n this.props.showContextMenu({\n topicName: this.props.topic,\n x: params.x,\n y: params.y,\n user: params.topicName}, menuItems);\n }\n\n render() {\n const args = (this.props.panel || 'info').split('/');\n const view = args[0];\n args.shift();\n\n const {formatMessage} = this.props.intl;\n const panelTitle = formatMessage((view == 'perm' ? messages['perm_' + args[0]] : messages[view])\n || messages['info']);\n\n const topic = this.props.tinode.getTopic(this.state.topic);\n const alias = topic && topic.alias();\n\n return (\n \n
{this.state.toast}
\n
\n
{panelTitle}
\n
\n \n
\n
\n {this.props.displayMobile ?\n
: null}\n {view == 'members' ?\n
\n :\n view == 'perm' && args.length > 0 ?\n
this.handlePermissionsChanged(args[0], mode)}\n onCancel={this.handleBackNavigate} />\n :\n view == 'general' ?\n \n :\n view == 'security' ?\n \n :\n view == 'qrcode' ?\n \n :\n \n
\n {!this.state.isSelf ?\n
{e.preventDefault(); this.props.onNavigate('general');}}>\n edit \n \n \n : null\n }\n
\n \n \n
\n
\n \n
\n
{this.state.fullName}\n {this.state.channel ?
: null}
\n
\n {this.state.private ?\n
\n
\n \n
\n
{this.state.private}
\n
\n : null\n }\n {!this.state.isSelf ?\n <>\n
\n
\n \n {this.state.address} \n
\n
\n
\n {alias ?\n
\n : null}\n >\n : null\n }\n {this.state.trustedBadges.length > 0 ?\n
\n \n
\n : null\n }\n {this.state.description ?\n
\n
\n \n \n
{this.state.description}
\n
: null}\n
\n {!this.state.isSelf ?\n <>
\n
\n \n \n \n \n
>\n : null\n }\n {this.state.archived ?\n
\n \n \n \n \n
\n :\n null\n }\n {!this.state.isSelf ?\n <>
\n
>\n : null\n }\n {this.state.groupTopic && this.state.sharer ?\n <>\n
\n
\n \n \n \n
\n
\n
{\n (no_members) => \n } \n >\n :\n null\n }\n
\n }\n \n );\n }\n};\n\nexport default injectIntl(InfoView);\n","// CallPanel displays call in progress: local and remote viewports and controls.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport LetterTile from './letter-tile.jsx';\n\nimport { MAX_PEER_TITLE_LENGTH } from '../config.js';\nimport { CALL_STATE_OUTGOING_INITATED, CALL_STATE_IN_PROGRESS } from '../constants.js';\n\nimport { clipStr } from '../lib/utils.js'\n\nconst RING_SOUND = new Audio('audio/call-out.m4a');\nRING_SOUND.loop = true;\nconst CALL_ENDED_SOUND = new Audio('audio/call-end.m4a');\nCALL_ENDED_SOUND.loop = true;\nconst DIALING_SOUND = new Audio('audio/dialing.m4a');\n\nconst VIDEO_MUTED_EVENT = 'video:muted';\nconst VIDEO_UNMUTED_EVENT = 'video:unmuted';\n\nconst messages = defineMessages({\n already_in_call: {\n id: 'already_in_call',\n defaultMessage: 'You already in an ongoing call!',\n description: 'Error message when the user tried to accept a new call without finishing pervious one',\n }\n});\n\nclass CallPanel extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n localStream: undefined,\n remoteStream: undefined,\n pc: undefined,\n dataChannel: undefined,\n\n previousOnInfo: undefined,\n waitingForPeer: false,\n // If true, the client has received a remote SDP from the peer and has sent a local SDP to the peer.\n callInitialSetupComplete: false,\n audioOnly: props.callAudioOnly,\n // Video mute/unmute in progress.\n videoToggleInProgress: false,\n // Indicates if the remote peer has informed us that their camera is on.\n remoteVideoLive: false,\n };\n\n this.localStreamConstraints = {\n audio: true,\n video: !props.callAudioOnly\n };\n this.isOutgoingCall = props.callState == CALL_STATE_OUTGOING_INITATED;\n\n this.localRef = React.createRef();\n this.remoteRef = React.createRef();\n // Cache for remote ice candidates until initial setup gets completed.\n this.remoteIceCandidatesCache = [];\n\n this.onInfo = this.onInfo.bind(this);\n this.start = this.start.bind(this);\n this.stop = this.stop.bind(this);\n\n this.createPeerConnection = this.createPeerConnection.bind(this);\n this.canSendOffer = this.canSendOffer.bind(this);\n this.drainRemoteIceCandidatesCache = this.drainRemoteIceCandidatesCache.bind(this);\n\n this.handleNegotiationNeededEvent = this.handleNegotiationNeededEvent.bind(this);\n this.handleICECandidateEvent = this.handleICECandidateEvent.bind(this);\n this.handleNewICECandidateMsg = this.handleNewICECandidateMsg.bind(this);\n this.handleICEConnectionStateChangeEvent = this.handleICEConnectionStateChangeEvent.bind(this);\n this.handleSignalingStateChangeEvent = this.handleSignalingStateChangeEvent.bind(this);\n this.handleICEGatheringStateChangeEvent = this.handleICEGatheringStateChangeEvent.bind(this);\n this.handleIceCandidateErrorEvent = this.handleIceCandidateErrorEvent.bind(this);\n this.handleTrackEvent = this.handleTrackEvent.bind(this);\n\n this.handleVideoOfferMsg = this.handleVideoOfferMsg.bind(this);\n this.handleVideoAnswerMsg = this.handleVideoAnswerMsg.bind(this);\n this.handleNewICECandidateMsg = this.handleNewICECandidateMsg.bind(this);\n\n this.reportError = this.reportError.bind(this);\n this.handleGetUserMediaError = this.handleGetUserMediaError.bind(this);\n\n this.stopTracks = this.stopTracks.bind(this);\n this.disconnectMedia = this.disconnectMedia.bind(this);\n\n this.handleCloseClick = this.handleCloseClick.bind(this);\n this.handleToggleCameraClick = this.handleToggleCameraClick.bind(this);\n this.handleToggleMicClick = this.handleToggleMicClick.bind(this);\n\n this.handleRemoteHangup = this.handleRemoteHangup.bind(this);\n this.handleVideoCallAccepted = this.handleVideoCallAccepted.bind(this);\n\n this.muteVideo = this.muteVideo.bind(this);\n this.unmuteVideo = this.unmuteVideo.bind(this);\n this.emptyVideoTrack = this.emptyVideoTrack.bind(this);\n\n this.handleDataChannelEvent = this.handleDataChannelEvent.bind(this);\n this.handleDataChannelError = this.handleDataChannelError.bind(this);\n this.handleDataChannelMessage = this.handleDataChannelMessage.bind(this);\n this.handleDataChannelOpen = this.handleDataChannelOpen.bind(this);\n this.handleDataChannelClose = this.handleDataChannelClose.bind(this);\n }\n\n componentDidMount() {\n const topic = this.props.tinode.getTopic(this.props.topic);\n this.previousOnInfo = topic.onInfo;\n topic.onInfo = this.onInfo;\n if ((this.props.callState == CALL_STATE_OUTGOING_INITATED ||\n this.props.callState == CALL_STATE_IN_PROGRESS) && this.localRef.current) {\n this.start();\n }\n }\n\n componentWillUnmount() {\n const topic = this.props.tinode.getTopic(this.props.topic);\n topic.onInfo = this.previousOnInfo;\n this.stop();\n }\n\n handleVideoCallAccepted(info) {\n RING_SOUND.pause();\n // Create peer connection with a data channel.\n const pc = this.createPeerConnection(true);\n const stream = this.state.localStream;\n stream.getTracks().forEach(track => {\n pc.addTrack(track, stream);\n\n if (track.kind == 'video' && this.state.audioOnly) {\n // This is an audio-only call.\n // Remove dummy video track (placeholder remains).\n track.enabled = false;\n track.stop();\n stream.removeTrack(track);\n }\n });\n }\n\n onInfo(info) {\n if (info.what != 'call') {\n return;\n }\n switch (info.event) {\n case 'accept':\n this.handleVideoCallAccepted(info);\n break;\n case 'answer':\n this.handleVideoAnswerMsg(info);\n break;\n case 'ice-candidate':\n this.handleNewICECandidateMsg(info);\n break;\n case 'hang-up':\n this.handleRemoteHangup(info);\n break;\n case 'offer':\n this.handleVideoOfferMsg(info);\n break;\n case 'ringing':\n // play() throws if the user did not click the app first: https://goo.gl/xX8pDD.\n RING_SOUND.play().catch(_ => {});\n break;\n default:\n console.warn(\"Unknown call event\", info.event);\n break;\n }\n }\n\n // Creates an empty video track placeholder.\n emptyVideoTrack() {\n const width = 640;\n const height = 480;\n const canvas = Object.assign(document.createElement(\"canvas\"), {width, height});\n canvas.getContext('2d').fillRect(0, 0, width, height);\n const stream = canvas.captureStream(0);\n return Object.assign(stream.getVideoTracks()[0], {enabled: false});\n }\n\n start() {\n if (this.state.localStream) {\n this.props.onError(this.props.intl.formatMessage(messages.already_in_call), 'info');\n return;\n }\n\n if (this.props.callState == CALL_STATE_IN_PROGRESS) {\n // We apparently just accepted the call.\n this.props.onInvite(this.props.topic, this.props.seq, CALL_STATE_IN_PROGRESS, this.props.callAudioOnly);\n return;\n }\n\n // This is an outgoing call waiting for the other side to pick up.\n // Start local video.\n navigator.mediaDevices.getUserMedia(this.localStreamConstraints)\n .then(stream => {\n if (!this.localStreamConstraints.video) {\n // Starting an audio-only call. Create a dummy video track\n // (so video can be enabled during the call if the user desires).\n stream.addTrack(this.emptyVideoTrack());\n }\n this.setState({localStream: stream, waitingForPeer: true});\n this.localRef.current.srcObject = stream;\n\n DIALING_SOUND.play();\n\n // Send call invitation.\n this.props.onInvite(this.props.topic, this.props.seq, this.props.callState, this.props.callAudioOnly);\n })\n .catch(this.handleGetUserMediaError);\n }\n\n stop() {\n CALL_ENDED_SOUND.pause();\n CALL_ENDED_SOUND.currentTime = 0;\n RING_SOUND.pause();\n RING_SOUND.currentTime = 0;\n\n this.stopTracks(this.state.localStream);\n this.stopTracks(this.state.remoteStream);\n this.disconnectMedia(this.localRef.current);\n this.disconnectMedia(this.remoteRef.current);\n if (this.state.pc) {\n this.state.pc.ontrack = null;\n this.state.pc.onremovetrack = null;\n this.state.pc.onremovestream = null;\n this.state.pc.onicecandidate = null;\n this.state.pc.oniceconnectionstatechange = null;\n this.state.pc.onsignalingstatechange = null;\n this.state.pc.onicegatheringstatechange = null;\n this.state.pc.onnegotiationneeded = null;\n this.state.pc.onicecandidateerror = null;\n this.state.pc.ondatachannel = null;\n\n if (this.state.dataChannel && (this.state.dataChannel.readyState == 'open' || this.state.dataChannel.readyState == 'connecting')) {\n this.state.dataChannel.close();\n }\n this.state.pc.close();\n }\n this.setState({pc: null, waitingForPeer: false});\n }\n\n disconnectMedia(el) {\n if (!el) {\n return;\n }\n\n el.srcObject = null;\n el.src = '';\n }\n\n stopTracks(stream) {\n if (!stream) {\n return;\n }\n\n let tracks = stream.getTracks();\n if (tracks) {\n tracks.forEach(track => {\n track.stop();\n track.enabled = false;\n });\n }\n }\n\n handleDataChannelError(error) {\n console.error('data channel error', error);\n }\n\n handleDataChannelMessage(event) {\n switch (event.data) {\n case VIDEO_MUTED_EVENT:\n this.setState({remoteVideoLive: false}, _ => { this.remoteRef.current.srcObject = this.state.remoteStream; });\n break;\n case VIDEO_UNMUTED_EVENT:\n this.setState({remoteVideoLive: true}, _ => { this.remoteRef.current.srcObject = this.state.remoteStream; });\n break;\n default:\n break;\n }\n }\n\n handleDataChannelOpen(event) {\n if (!this.state.audioOnly) {\n event.target.send(VIDEO_UNMUTED_EVENT);\n }\n }\n\n handleDataChannelClose(event) {\n console.log('close data channel:', event);\n }\n\n handleDataChannelEvent(event) {\n console.log('data channel event:', event);\n const channel = event.channel;\n channel.onerror = this.handleDataChannelError;\n channel.onmessage = this.handleDataChannelMessage;\n channel.onopen = this.handleDataChannelOpen;\n channel.onclose = this.handleDataChannelClose;\n this.setState({dataChannel: channel});\n }\n\n createPeerConnection(withDataChannel) {\n const iceServers = this.props.tinode.getServerParam('iceServers', null);\n const pc = iceServers ? new RTCPeerConnection({iceServers: iceServers}) : new RTCPeerConnection();\n\n pc.onicecandidate = this.handleICECandidateEvent;\n pc.oniceconnectionstatechange = this.handleICEConnectionStateChangeEvent;\n pc.onicegatheringstatechange = this.handleICEGatheringStateChangeEvent;\n pc.onsignalingstatechange = this.handleSignalingStateChangeEvent;\n pc.onnegotiationneeded = this.handleNegotiationNeededEvent;\n pc.onicecandidateerror = this.handleIceCandidateErrorEvent;\n pc.ontrack = this.handleTrackEvent;\n pc.ondatachannel = this.handleDataChannelEvent;\n\n let stateUpdate = {pc: pc, waitingForPeer: false};\n if (withDataChannel) {\n // Create data channel for exchanging events.\n const channel = pc.createDataChannel(\"events\", {ordered: true});\n channel.onerror = this.handleDataChannelError;\n channel.onmessage = this.handleDataChannelMessage;\n channel.onopen = this.handleDataChannelOpen;\n channel.onclose = this.handleDataChannelClose;\n stateUpdate.dataChannel = channel;\n }\n this.setState(stateUpdate);\n return pc;\n }\n\n handleVideoAnswerMsg(info) {\n // Configure the remote description, which is the SDP payload\n // in 'info' message.\n const desc = new RTCSessionDescription(info.payload);\n this.state.pc.setRemoteDescription(desc)\n .then(_ => {\n this.setState({ callInitialSetupComplete: true }, _ => this.drainRemoteIceCandidatesCache());\n })\n .catch(err => this.reportError(err));\n }\n\n reportError(err) {\n this.props.onError(err.message, 'err');\n }\n\n canSendOffer() {\n return this.isOutgoingCall || this.state.callInitialSetupComplete;\n }\n\n handleNegotiationNeededEvent(event) {\n const pc = event.target;\n if (!this.canSendOffer()) {\n return;\n }\n pc.createOffer().then(offer => {\n return pc.setLocalDescription(offer);\n })\n .then(_ => {\n this.props.onSendOffer(this.props.topic, this.props.seq, pc.localDescription.toJSON());\n })\n .catch(err => this.reportError(err));\n }\n\n handleIceCandidateErrorEvent(event) {\n console.warn(\"ICE candidate error:\", event);\n }\n\n handleICECandidateEvent(event) {\n if (event.candidate) {\n this.props.onIceCandidate(this.props.topic, this.props.seq, event.candidate.toJSON());\n }\n }\n\n handleNewICECandidateMsg(info) {\n const candidate = new RTCIceCandidate(info.payload);\n if (this.state.callInitialSetupComplete) {\n this.state.pc.addIceCandidate(candidate)\n .catch(err => {\n if (candidate.candidate) {\n this.reportError(err);\n }\n console.warn(\"Error adding new ice candidate\", candidate, err);\n });\n } else {\n this.remoteIceCandidatesCache.push(candidate);\n }\n }\n\n drainRemoteIceCandidatesCache() {\n this.remoteIceCandidatesCache.forEach(candidate => {\n this.state.pc.addIceCandidate(candidate)\n .catch(err => {\n if (candidate.candidate) {\n this.reportError(err);\n }\n console.warn(\"Error adding cached ice candidate\", candidate, err);\n });\n });\n this.remoteIceCandidatesCache = [];\n }\n\n handleICEConnectionStateChangeEvent(event) {\n switch (event.target.iceConnectionState) {\n case 'closed':\n case 'failed':\n this.handleCloseClick();\n break;\n }\n }\n\n handleSignalingStateChangeEvent(event) {\n if (event.target.signalingState == 'closed') {\n this.handleCloseClick();\n }\n }\n\n handleICEGatheringStateChangeEvent(event) {\n // ICE gathering change state\n }\n\n handleTrackEvent(event) {\n // Remote video becomes available.\n this.remoteRef.current.srcObject = event.streams[0];\n this.setState({remoteStream: event.streams[0]});\n }\n\n handleGetUserMediaError(e) {\n console.error(\"Error opening camera and/or microphone\", e);\n switch(e.name) {\n case 'NotFoundError':\n // Cannot start the call b/c no camera and/or microphone found.\n this.reportError(e);\n break;\n case 'SecurityError':\n case 'PermissionDeniedError':\n // Do nothing; this is the same as the user canceling the call.\n break;\n default:\n this.reportError(e);\n break;\n }\n\n // Make sure we shut down our end of the RTCPeerConnection so we're\n // ready to try again.\n this.handleCloseClick();\n }\n\n handleVideoOfferMsg(info) {\n let localStream = null;\n // If needed, create peer connection.\n // Not creating data channel since it should be created by the peer.\n const pc = this.state.pc ? this.state.pc : this.createPeerConnection(false);\n const desc = new RTCSessionDescription(info.payload);\n\n pc.setRemoteDescription(desc).then(_ => {\n return navigator.mediaDevices.getUserMedia(this.localStreamConstraints);\n })\n .then(stream => {\n let dummyVideo;\n if (!this.localStreamConstraints.video) {\n // Starting an audio-only call. Create an empty video track so\n // so the user can enable the video during the call.\n dummyVideo = this.emptyVideoTrack();\n stream.addTrack(dummyVideo);\n }\n localStream = stream;\n this.localRef.current.srcObject = stream;\n this.setState({localStream: stream});\n\n localStream.getTracks().forEach(track => {\n pc.addTrack(track, localStream);\n });\n\n if (dummyVideo) {\n dummyVideo.enabled = false;\n dummyVideo.stop();\n stream.removeTrack(dummyVideo);\n }\n })\n .then(_ => {\n return pc.createAnswer();\n })\n .then(answer => {\n return pc.setLocalDescription(answer);\n })\n .then(_ => {\n this.props.onSendAnswer(this.props.topic, this.props.seq, pc.localDescription.toJSON());\n this.setState({ callInitialSetupComplete: true }, _ => this.drainRemoteIceCandidatesCache());\n })\n .catch(this.handleGetUserMediaError);\n }\n\n // Call disconnected by remote.\n handleRemoteHangup() {\n if (!this.state.waitingForPeer) {\n // This is live call, just hang up.\n this.handleCloseClick();\n } else {\n // This is a call which is not yet connected.\n // Stop pulse animation.\n this.setState({waitingForPeer: false});\n // Change sound and wait a bit before ending it.\n RING_SOUND.pause();\n RING_SOUND.currentTime = 0;\n CALL_ENDED_SOUND.loop = true;\n CALL_ENDED_SOUND.play().catch(_ => {});\n setTimeout(_ => {\n this.handleCloseClick();\n }, 2000);\n }\n }\n\n handleCloseClick() {\n this.stop();\n this.props.onHangup(this.props.topic, this.props.seq);\n }\n\n // Ends video track and turns off the camera.\n muteVideo() {\n if (!this.state.pc || !this.state.dataChannel) {\n return;\n }\n\n const stream = this.state.localStream;\n const t = stream.getVideoTracks()[0];\n t.enabled = false;\n t.stop();\n\n stream.removeTrack(t);\n this.state.dataChannel.send(VIDEO_MUTED_EVENT);\n this.setState({videoToggleInProgress: false});\n }\n\n unmuteVideo() {\n if (!this.state.pc || !this.state.dataChannel) {\n return;\n }\n navigator.mediaDevices.getUserMedia({ video: true })\n .then(stream => {\n // Will extract video track from stream and throw stream away,\n // and replace video track in the media sender.\n this.localRef.current.srcObject = null;\n const sender = this.state.pc.getSenders().find(s => s.track.kind == 'video');\n const track = stream.getVideoTracks()[0];\n // Remote track from new stream.\n stream.removeTrack(track);\n // Add this track to the existing local stream.\n this.state.localStream.addTrack(track);\n return sender.replaceTrack(track);\n })\n .then(_ => {\n this.localRef.current.srcObject = this.state.localStream;\n this.state.dataChannel.send(VIDEO_UNMUTED_EVENT);\n })\n .catch(err => this.handleGetUserMediaError(err))\n .finally(_ => { this.setState({videoToggleInProgress: false}); }); // Make sure we redraw the mute/unmute icons (e.g. camera -> camera_off).\n }\n\n handleToggleCameraClick() {\n if (this.state.videoToggleInProgress) {\n // Toggle currently in progress.\n return;\n }\n const tracks = this.state.localStream.getVideoTracks();\n this.setState({videoToggleInProgress: true}, _ => {\n if (tracks && tracks.length > 0 && tracks[0].enabled && tracks[0].readyState == 'live') {\n this.muteVideo();\n } else {\n this.unmuteVideo();\n }\n this.setState({audioOnly: !this.state.audioOnly});\n });\n }\n\n handleToggleMicClick() {\n const stream = this.state.localStream;\n const t = stream.getAudioTracks()[0];\n t.enabled = !t.enabled;\n // Make sure we redraw the mute/unmute icons (e.g. mic -> mic_off).\n this.forceUpdate();\n }\n\n render() {\n const audioTracks = this.state.localStream && this.state.localStream.getAudioTracks();\n const videoTracks = !this.state.audioOnly && this.state.localStream && this.state.localStream.getVideoTracks();\n const disabled = !this.state.pc || !this.state.dataChannel || !(audioTracks && audioTracks[0]);\n const audioIcon = audioTracks && audioTracks[0] && audioTracks[0].enabled ? 'mic' : 'mic_off';\n const videoIcon = videoTracks && videoTracks[0] && videoTracks[0].enabled && videoTracks[0].readyState == 'live' ? 'videocam' : 'videocam_off';\n const peerTitle = clipStr(this.props.title, MAX_PEER_TITLE_LENGTH);\n const pulseAnimation = this.state.waitingForPeer ? ' pulse' : '';\n\n let remoteActive = false;\n if (this.remoteRef.current && this.remoteRef.current.srcObject && this.state.remoteVideoLive) {\n const rstream = this.remoteRef.current.srcObject;\n if (rstream.getVideoTracks().length > 0) {\n const t = rstream.getVideoTracks()[0];\n remoteActive = t.enabled && t.readyState == 'live';\n }\n }\n\n return (\n <>\n \n
\n
\n
\n {remoteActive ?\n <>\n
\n
{peerTitle}
\n > :\n <>\n
\n
\n
\n \n
\n
{peerTitle}
\n
\n >\n }\n
\n
\n
\n \n call_end \n \n \n {videoIcon} \n \n \n {audioIcon} \n \n
\n
\n >\n );\n }\n};\n\nexport default injectIntl(CallPanel);\n","import React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport FileProgress from './file-progress.jsx';\nimport { bytesToHumanSize } from '../lib/strformat.js';\nimport { isUrlRelative, sanitizeUrl } from '../lib/utils.js';\n\nexport default class Attachment extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n downloader: null,\n progress: 0\n };\n\n this.downloadFile = this.downloadFile.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n }\n\n downloadFile(url, filename, mimetype) {\n if (!url) {\n this.props.onError(\"Invalid download URL '\" + url + \"'\");\n return;\n }\n\n const downloader = this.props.tinode.getLargeFileHelper();\n this.setState({downloader: downloader});\n downloader.download(url, filename, mimetype,\n loaded => this.setState({progress: loaded / this.props.size}),\n err => this.props.onError(err, 'err')\n )\n .then(_ => this.setState({downloader: null, progress: 0}))\n .catch(err => {\n if (err) {\n this.props.onError(\"Error downloading file: \" + err.message, 'err');\n }\n this.setState({downloader: null, progress: 0});\n });\n }\n\n handleCancel() {\n if (this.props.uploading) {\n this.props.onCancelUpload();\n } else if (this.state.downloader) {\n this.state.downloader.cancel();\n }\n }\n\n render() {\n let filename = this.props.filename || 'file_attachment';\n if (filename.length > 36) {\n filename = filename.substr(0, 16) + '...' + filename.substr(-16);\n }\n let size = this.props.size > 0 ?\n ({bytesToHumanSize(this.props.size)}) :\n null;\n\n // Detect if the download URL is relative or absolute.\n // If the URL is relative use LargeFileHelper to attach authentication\n // credentials to the request.\n let url, helperFunc;\n if (!this.props.uploading && !this.state.downloader && isUrlRelative(this.props.downloadUrl)) {\n // Relative URL. Use download helper.\n url = '#';\n helperFunc = (e) => {\n e.preventDefault();\n this.downloadFile(this.props.downloadUrl, this.props.filename, this.props.mimetype);\n };\n } else {\n url = sanitizeUrl(this.props.downloadUrl);\n helperFunc = null;\n }\n const downloadWidget = <>file_download >;\n return (\n \n
insert_drive_file
\n
\n
{filename} {size}
\n {this.props.uploading || this.state.downloader ?\n
\n :\n
\n }\n
\n
\n );\n }\n};\n","// Received/read indicator.\nimport React from 'react';\nimport { defineMessages, injectIntl } from 'react-intl';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport { deliveryMarker } from '../lib/utils.js';\n\nconst messages = defineMessages({\n message_sending: {\n id: 'message_sending',\n defaultMessage: 'sending...',\n description: 'Message being sent, in place of time stamp'\n },\n message_sending_failed: {\n id: 'message_sending_failed',\n defaultMessage: 'failed',\n description: 'Failed to send message, in place of time stamp'\n },\n message_edited_marker: {\n id: 'message_edited_marker',\n defaultMessage: ', edited',\n description: 'Marker indicating that the message was edited'\n }\n});\n\nclass ReceivedMarker extends React.PureComponent {\n render() {\n const {formatMessage} = this.props.intl;\n let timestamp;\n if (this.props.received <= Tinode.MESSAGE_STATUS_SENDING) {\n timestamp = formatMessage(messages.message_sending);\n } else if (this.props.received == Tinode.MESSAGE_STATUS_FAILED ||\n this.props.received == Tinode.MESSAGE_STATUS_FATAL) {\n timestamp = formatMessage(messages.message_sending_failed);\n } else {\n timestamp = this.props.timestamp.toLocaleTimeString(this.props.intl.locale, { timeStyle: 'short' });\n }\n\n const icon = deliveryMarker(this.props.received);\n const marker = icon ? {icon.name} : null;\n const edited = this.props.edited ? formatMessage(messages.message_edited_marker) : null;\n\n return (\n \n {timestamp}{edited}{'\\u00a0'}{marker}\n \n );\n }\n};\n\nexport default injectIntl(ReceivedMarker);\n","// Single chat message bubble, sent or received.\n\nimport React from 'react';\nimport { FormattedMessage, injectIntl } from 'react-intl';\nimport { Drafty, Tinode } from 'tinode-sdk';\n\nimport Attachment from './attachment.jsx';\nimport LetterTile from './letter-tile.jsx';\nimport ReceivedMarker from './received-marker.jsx'\n\nimport { fullFormatter } from '../lib/formatters.js';\nimport { sanitizeUrl } from '../lib/utils.js';\n\nclass BaseChatMessage extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n progress: 0\n };\n\n if (props.uploader) {\n props.uploader.onProgress = this.handleProgress.bind(this);\n }\n\n this.handleExpandImage = this.handleExpandImage.bind(this);\n this.handlePlayVideo = this.handlePlayVideo.bind(this);\n this.handleFormButtonClick = this.handleFormButtonClick.bind(this);\n this.handleContextClick = this.handleContextClick.bind(this);\n this.handleCancelUpload = this.handleCancelUpload.bind(this);\n this.handleQuoteClick = this.handleQuoteClick.bind(this);\n\n this.formatterContext = {\n formatMessage: props.intl.formatMessage.bind(props.intl),\n viewportWidth: props.viewportWidth,\n authorizeURL: props.tinode.authorizeURL.bind(props.tinode),\n\n onImagePreview: this.handleExpandImage,\n onVideoPreview: this.handlePlayVideo,\n onFormButtonClick: this.handleFormButtonClick,\n onQuoteClick: this.handleQuoteClick\n };\n }\n\n handleExpandImage(e) {\n e.preventDefault();\n this.props.onExpandMedia({\n url: e.target.src,\n filename: e.target.dataset.name,\n width: e.target.dataset.width,\n height: e.target.dataset.height,\n size: e.target.dataset.size,\n type: e.target.dataset.mime\n });\n }\n\n handlePlayVideo(e) {\n e.preventDefault();\n this.props.onExpandMedia({\n video: true,\n url: e.target.dataset.src,\n preview: e.target.src,\n filename: e.target.dataset.name,\n width: e.target.dataset.width,\n height: e.target.dataset.height,\n duration: e.target.dataset.duration,\n size: e.target.dataset.size,\n type: e.target.dataset.mime\n });\n }\n\n handleFormButtonClick(e) {\n e.preventDefault();\n const data = {\n seq: this.props.seq\n };\n data.resp = {};\n if (e.target.dataset.name) {\n data.resp[e.target.dataset.name] = e.target.dataset.val ? e.target.dataset.val :\n e.target.dataset.val === undefined ? 1 : '' + e.target.dataset.val;\n }\n if (e.target.dataset.act == 'url') {\n data.ref = sanitizeUrl(e.target.dataset.ref) || 'about:blank';\n }\n const text = e.target.dataset.title || 'unknown';\n this.props.onFormResponse(e.target.dataset.act, text, data);\n }\n\n handleContextClick(e) {\n e.preventDefault();\n e.stopPropagation();\n const menuItems = [];\n if (this.props.received == Tinode.MESSAGE_STATUS_FAILED) {\n menuItems.push('menu_item_send_retry');\n }\n if (this.props.received > Tinode.MESSAGE_STATUS_FATAL) {\n if (this.props.userIsWriter) {\n menuItems.push('menu_item_reply');\n if (!this.props.response) {\n let immutable = false;\n Drafty.entities(this.props.content, (_0, _1, tp) => {\n immutable = ['AU', 'EX', 'FM', 'IM', 'VC', 'VD'].includes(tp);\n return immutable;\n });\n if (!immutable) {\n Drafty.styles(this.props.content, tp => {\n immutable = ['QQ'].includes(tp);\n return immutable;\n });\n }\n if (!immutable) {\n menuItems.push('menu_item_edit');\n }\n }\n }\n if (this.props.userIsAdmin) {\n menuItems.push(this.props.pinned ? 'menu_item_unpin' : 'menu_item_pin');\n }\n }\n menuItems.push('menu_item_forward');\n\n this.props.showContextMenu({\n seq: this.props.seq,\n replace: this.props.edited ? parseInt(this.props.edited.split(':')[1]) : 0,\n content: this.props.content,\n userFrom: this.props.userFrom,\n userName: this.props.userName,\n y: e.pageY,\n x: e.pageX,\n pickReply: this.props.pickReply,\n editMessage: this.props.editMessage,\n timestamp: this.props.timestamp,\n }, menuItems);\n }\n\n handleProgress(ratio) {\n this.setState({progress: ratio});\n }\n\n handleCancelUpload() {\n this.props.onCancelUpload(this.props.seq, this.props.uploader);\n }\n\n handleQuoteClick(e) {\n e.preventDefault();\n e.stopPropagation();\n const replyToSeq = this.props.replyToSeq;\n if (replyToSeq) {\n this.props.onQuoteClick(replyToSeq);\n }\n }\n\n render() {\n const sideClass = this.props.sequence + ' ' + (this.props.response ? 'left' : 'right');\n const bubbleClass = (this.props.sequence == 'single' || this.props.sequence == 'last') ? 'bubble tip' : 'bubble';\n const avatar = this.props.userAvatar || true;\n let textSizeClass = 'message-content';\n const fullDisplay = (this.props.isGroup && this.props.response &&\n (this.props.sequence == 'single' || this.props.sequence == 'last'));\n\n let content = this.props.content;\n const attachments = [];\n if (this.props.mimeType == Drafty.getContentType() && Drafty.isValid(content)) {\n Drafty.attachments(content, (att, i) => {\n if (att.mime == 'application/json+drafty' ||\n att.mime == 'application/json') {\n // Don't show json drafty form response objects as attachments.\n // They are not meant for users.\n return;\n }\n attachments.push( );\n }, this);\n const tree = Drafty.format(content, fullFormatter, this.formatterContext);\n content = React.createElement(React.Fragment, null, tree);\n } else if (typeof content == 'string') {\n // Make font bigger for emoji-only messages.\n // Must use 'new RegExp(...)' because React does not like /{1-5}/.\n if (new RegExp('^\\\\p{RGI_Emoji}{1,5}$', 'v').test(content || '')) {\n // Content consists of 1-5 emoji characters. Count how many and use it to increase the font size.\n textSizeClass += ' emoji-' + (content || '').match(/\\p{RGI_Emoji}/vg).length;\n }\n } else {\n content = <>warning_amber \n >\n }\n\n return (\n \n {this.props.isGroup && this.props.response ?\n \n {fullDisplay ?\n :\n null}\n
:\n null}\n \n
\n
\n
\n {content}\n {attachments}\n
\n {this.props.timestamp ?\n
\n : null}\n
\n {this.props.showContextMenu ?\n
\n \n expand_more \n \n : null\n }\n
\n {fullDisplay ?\n
\n {this.props.userName ||\n \n }\n
\n : null\n }\n
\n \n );\n }\n};\n\nconst IntlChatMessage = injectIntl(BaseChatMessage);\nconst ChatMessage = React.forwardRef((props, ref) => );\n\nexport default ChatMessage;\n","// Send message form.\nimport React, { Suspense } from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\nimport { Drafty } from 'tinode-sdk';\n\n// Lazy-loading AudioRecorder because it's quite large due to\n// a dependency on webm-duration-fix.\nconst AudioRecorder = React.lazy(_ => import('./audio-recorder.jsx'));\n\nimport { KEYPRESS_DELAY } from '../config.js';\nimport { filePasted } from '../lib/blob-helpers.js';\nimport { replyFormatter } from '../lib/formatters.js';\n\nconst messages = defineMessages({\n messaging_disabled: {\n id: 'messaging_disabled_prompt',\n defaultMessage: 'Messaging disabled',\n description: 'Prompt in SendMessage in read-only topic'\n },\n type_new_message: {\n id: 'new_message_prompt',\n defaultMessage: 'New message',\n description: 'Prompt in send message field'\n },\n add_image_caption: {\n id: 'image_caption_prompt',\n defaultMessage: 'Image caption',\n description: 'Prompt in SendMessage for attached image'\n },\n file_attachment_too_large: {\n id: 'file_attachment_too_large',\n defaultMessage: 'The file size {size} exceeds the {limit} limit.',\n description: 'Error message when attachment is too large'\n },\n cannot_initiate_upload: {\n id: 'cannot_initiate_file_upload',\n defaultMessage: 'Cannot initiate file upload.',\n description: 'Generic error messagewhen attachment fails'\n },\n icon_title_record_voice: {\n id: 'icon_title_record_voice',\n defaultMessage: 'Record voice message',\n description: 'Icon tool tip for recording a voice message'\n },\n icon_title_attach_file: {\n id: 'icon_title_attach_file',\n defaultMessage: 'Attach file',\n description: 'Icon tool tip for attaching a file'\n },\n icon_title_add_image: {\n id: 'icon_title_add_image',\n defaultMessage: 'Add image',\n description: 'Icon tool tip for attaching an image'\n },\n icon_title_send: {\n id: 'icon_title_send',\n defaultMessage: 'Send message',\n description: 'Icon tool tip for sending a message'\n },\n});\n\nclass SendMessage extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n quote: null,\n message: '',\n audioRec: false,\n audioAvailable: !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia),\n };\n\n // Timestamp when the previous key press was sent to the server.\n this.keypressTimestamp = 0;\n\n this.handlePasteEvent = this.handlePasteEvent.bind(this);\n this.handleAttachImage = this.handleAttachImage.bind(this);\n this.handleAttachFile = this.handleAttachFile.bind(this);\n this.handleAttachAudio = this.handleAttachAudio.bind(this);\n this.handleSend = this.handleSend.bind(this);\n this.handleKeyPress = this.handleKeyPress.bind(this);\n this.handleMessageTyping = this.handleMessageTyping.bind(this);\n this.handleDropAttach = this.handleDropAttach.bind(this);\n\n this.handleQuoteClick = this.handleQuoteClick.bind(this);\n\n this.formatReply = this.formatReply.bind(this);\n }\n\n componentDidMount() {\n if (this.messageEditArea) {\n this.messageEditArea.addEventListener('paste', this.handlePasteEvent, false);\n if (window.getComputedStyle(this.messageEditArea).getPropertyValue('transition-property') == 'all') {\n // Set focus on desktop, but not on mobile: focus causes soft keyboard to pop up.\n this.messageEditArea.focus();\n }\n }\n\n this.setState({quote: this.formatReply()});\n }\n\n componentWillUnmount() {\n if (this.messageEditArea) {\n this.messageEditArea.removeEventListener('paste', this.handlePasteEvent, false);\n }\n }\n\n componentDidUpdate(prevProps) {\n if (this.messageEditArea) {\n if (window.getComputedStyle(this.messageEditArea).getPropertyValue('transition-property') == 'all') {\n // Set focus on desktop, but not on mobile: focus causes soft keyboard to pop up.\n this.messageEditArea.focus();\n }\n\n // Adjust height of the message area for the amount of text.\n this.messageEditArea.style.height = '0px';\n this.messageEditArea.style.height = this.messageEditArea.scrollHeight + 'px';\n }\n\n if (prevProps.topicName != this.props.topicName) {\n this.setState({message: this.props.initMessage || '', audioRec: false, quote: null});\n } else if (prevProps.initMessage != this.props.initMessage) {\n const msg = this.props.initMessage || '';\n this.setState({message: msg}, _ => {\n // If there is text, scroll to bottom and set caret to the end.\n this.messageEditArea.scrollTop = this.messageEditArea.scrollHeight;\n this.messageEditArea.setSelectionRange(msg.length, msg.length);\n });\n }\n if (prevProps.reply != this.props.reply) {\n this.setState({quote: this.formatReply()});\n }\n }\n\n formatReply() {\n return this.props.reply ?\n Drafty.format(this.props.reply.content, replyFormatter, {\n formatMessage: this.props.intl.formatMessage.bind(this.props.intl),\n authorizeURL: this.props.tinode.authorizeURL.bind(this.props.tinode)\n }) : null;\n }\n\n handlePasteEvent(e) {\n if (this.props.disabled) {\n return;\n }\n // FIXME: handle large files too.\n if (filePasted(e,\n file => { this.props.onAttachImage(file); },\n file => { this.props.onAttachFile(file); },\n this.props.onError)) {\n\n // If a file was pasted, don't paste base64 data into input field.\n e.preventDefault();\n }\n }\n\n handleAttachImage(e) {\n if (e.target.files && e.target.files.length > 0) {\n this.props.onAttachImage(e.target.files[0]);\n }\n // Clear the value so the same file can be uploaded again.\n e.target.value = '';\n }\n\n handleAttachFile(e) {\n if (e.target.files && e.target.files.length > 0) {\n this.props.onAttachFile(e.target.files[0]);\n }\n // Clear the value so the same file can be uploaded again.\n e.target.value = '';\n }\n\n handleDropAttach(files) {\n if (files && files.length > 0) {\n this.props.onAttachFile(files[0]);\n }\n }\n\n handleAttachAudio(url, preview, duration) {\n this.setState({audioRec: false});\n this.props.onAttachAudio(url, preview, duration);\n }\n\n handleSend(e) {\n e.preventDefault();\n const message = this.state.message.trim();\n if (message || this.props.acceptBlank || this.props.noInput) {\n this.props.onSendMessage(message);\n this.setState({message: ''});\n }\n }\n\n /* Send on Enter key */\n handleKeyPress(e) {\n if (this.state.audioRec) {\n // Ignore key presses while audio is being recorded.\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n // Remove this if you don't want Enter to trigger send\n if (e.key === 'Enter') {\n // Have Shift-Enter insert a line break instead\n if (!e.shiftKey) {\n e.preventDefault();\n e.stopPropagation();\n\n this.handleSend(e);\n }\n }\n }\n\n handleMessageTyping(e) {\n this.setState({message: e.target.value});\n if (this.props.onKeyPress) {\n const now = new Date().getTime();\n if (now - this.keypressTimestamp > KEYPRESS_DELAY) {\n this.props.onKeyPress();\n this.keypressTimestamp = now;\n }\n }\n }\n\n handleQuoteClick(e) {\n e.preventDefault();\n e.stopPropagation();\n if (this.props.reply && this.props.onQuoteClick) {\n const replyToSeq = this.props.reply.seq;\n this.props.onQuoteClick(replyToSeq);\n }\n }\n\n render() {\n const { formatMessage } = this.props.intl;\n const prompt = this.props.disabled ?\n formatMessage(messages.messaging_disabled) :\n (this.props.messagePrompt ?\n formatMessage(messages[this.props.messagePrompt]) :\n formatMessage(messages.type_new_message));\n\n const sendIcon = (this.props.reply && this.props.reply.editing) ?\n 'check_circle' : 'send';\n\n const quote = this.state.quote ?\n (\n
\n {this.state.quote}\n
) : null;\n const audioEnabled = this.state.audioAvailable && this.props.onAttachAudio;\n return (\n \n {!this.props.noInput ? quote : null}\n
}>\n
this.props.onKeyPress(true)}\n onDeleted={_ => this.setState({audioRec: false})}\n onFinished={this.handleAttachAudio}/>\n ) :\n \n \n );\n }\n};\n\nexport default injectIntl(SendMessage);\n","import React from 'react';\nimport { FormattedMessage } from 'react-intl';\nimport SendMessage from '../widgets/send-message.jsx';\n\nimport { bytesToHumanSize, shortenFileName } from '../lib/strformat.js';\n\n// Get material icon name from mime type.\nfunction iconFromMime(mime) {\n // If more icons become available in material icons, add them to this mime-to-icon mapping.\n const mimeToIcon = {default: 'insert_drive_file', image: 'image', text: 'description', video: 'theaters'};\n\n return mimeToIcon[mime] || mimeToIcon[(mime || '').split('/')[0]] || mimeToIcon['default'];\n}\n\nexport default class DocPreview extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleSendDoc = this.handleSendDoc.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n }\n\n componentDidMount() {\n document.addEventListener('keydown', this.handleKeyDown);\n }\n\n componentWillUnmount() {\n document.removeEventListener('keydown', this.handleKeyDown);\n }\n\n handleKeyDown(e) {\n e.preventDefault();\n if (e.key === 'Escape') {\n this.props.onClose();\n }\n }\n\n handleSendDoc(caption) {\n this.props.onClose();\n this.props.onSendMessage(this.props.content.file);\n }\n\n render() {\n if (!this.props.content) {\n return null;\n }\n return (\n \n
\n
\n
\n
{iconFromMime(this.props.content.type)} \n
{shortenFileName(this.props.content.name, 24) || '-'}
\n
{this.props.content.type || 'application/octet-stream'}
\n
{bytesToHumanSize(this.props.content.size)}
\n
\n
\n
\n
\n );\n }\n};\n","// GroupSubs: a list of group subscribers currently online.\n// Show in the topic title bar\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { MAX_ONLINE_IN_TOPIC } from '../config.js'\n\nimport LetterTile from './letter-tile.jsx';\nimport { makeImageUrl } from '../lib/blob-helpers.js';\n\nexport default class GroupSubs extends React.Component {\n constructor(props) {\n super(props);\n }\n\n render() {\n const usersOnline = [];\n const totalCount = (this.props.subscribers || []).length;\n const countToShow = Math.min(MAX_ONLINE_IN_TOPIC, totalCount);\n\n (this.props.subscribers || []).some((sub) => {\n usersOnline.push(\n \n \n
\n );\n return usersOnline.length == countToShow;\n });\n if (usersOnline.length == 0) {\n return null;\n }\n return (\n {usersOnline} {totalCount > countToShow ?\n \n \n : null}\n
\n );\n }\n};\n","import React from 'react';\nimport { FormattedMessage } from 'react-intl';\nimport SendMessage from './send-message.jsx';\n\nimport { REM_SIZE } from '../config.js';\nimport { fitImageSize } from '../lib/blob-helpers.js';\nimport { bytesToHumanSize, shortenFileName } from '../lib/strformat.js';\nimport { urlAsAttachment } from '../lib/utils.js';\n\nexport default class ImagePreview extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n width: 0,\n height: 0\n };\n\n this.handleSendImage = this.handleSendImage.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n }\n\n componentDidMount() {\n document.addEventListener('keydown', this.handleKeyDown);\n }\n\n componentWillUnmount() {\n document.removeEventListener('keydown', this.handleKeyDown);\n }\n\n handleKeyDown(e) {\n if (this.props.onSendMessage) {\n return;\n }\n\n e.preventDefault();\n if (e.key === 'Escape') {\n this.props.onClose();\n }\n }\n\n assignWidth(node) {\n if (node && !this.state.width) {\n const bounds = node.getBoundingClientRect();\n this.setState({\n width: bounds.width | 0,\n height: bounds.height | 0\n });\n }\n }\n\n handleSendImage(caption) {\n this.props.onClose();\n this.props.onSendMessage(caption, this.props.content.blob);\n }\n\n render() {\n if (!this.props.content) {\n return null;\n }\n\n const dim = fitImageSize(this.props.content.width, this.props.content.height,\n this.state.width, this.state.height, false);\n const size = dim ? { width: dim.dstWidth + 'px', height: dim.dstHeight + 'px' } :\n ((this.props.content.width > this.props.content.height) ? {width: '100%'} : {height: '100%'});\n size.maxWidth = '100%';\n size.maxHeight = '100%';\n\n // Average font aspect ratio is ~0.5; File name takes 1/3 of the viewport width.\n const maxlength = Math.max(((this.state.width / REM_SIZE / 1.5) | 0) - 2, 12);\n const fname = shortenFileName(this.props.content.filename, maxlength) || '-';\n\n const width = this.props.content.width || '-';\n const height = this.props.content.height || '-';\n\n const download_url = urlAsAttachment(this.props.content.url);\n\n return (\n \n
\n
this.assignWidth(node)}>\n
\n
\n {this.props.onSendMessage ?\n
\n :\n }\n
\n );\n }\n};\n","// A single topic or user.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nexport default class Invitation extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleButtonAction = this.handleButtonAction.bind(this);\n }\n\n handleButtonAction(evt, data) {\n evt.preventDefault();\n this.props.onAction(data);\n }\n\n render() {\n return (\n \n
\n \n
\n
\n { this.handleButtonAction(event, \"accept\"); }}>\n \n \n { this.handleButtonAction(event, \"delete\"); }}>\n \n \n { this.handleButtonAction(event, \"block\"); }}>\n \n \n
\n
\n );\n }\n};\n","/* This is just a static page to display when no conversation is selected. */\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport { APP_NAME } from '../config.js';\n\nexport default class LogoView extends React.PureComponent {\n render() {\n const version = APP_NAME + ' (' + Tinode.getLibrary() + ')';\n return (\n \n
\n
\n \n Tinode Web \n \n
{version}
\n
{this.props.serverVersion} ({this.props.serverAddress})
\n
\n
\n );\n }\n};\n","// Message bubble with non-payload content, such as an indicator of deleted content or a date stamp.\n\nimport React from 'react';\n\nexport default class MetaMessage extends React.PureComponent {\n constructor(props) {\n super(props);\n }\n\n render() {\n let content = null;\n let bubbleClass = 'bubble';\n if (this.props.date) {\n // A date badge.\n content = <>{this.props.date}>\n bubbleClass += ' date';\n }\n\n if (!content) {\n return <>{null}>\n }\n\n return (\n \n \n \n );\n }\n};\n","// Send message form.\nimport React from 'react';\nimport { defineMessages, injectIntl } from 'react-intl';\nimport { Drafty } from 'tinode-sdk';\n\nimport { previewFormatter } from '../lib/formatters.js';\nimport { MIN_SWIPE_DISTANCE } from '../config.js';\n\nconst messages = defineMessages({\n message_not_found: {\n id: 'message_not_found',\n defaultMessage: 'message not found',\n description: 'Pinned message is not found'\n },\n message_deleted: {\n id: 'message_deleted',\n defaultMessage: 'message deleted',\n description: 'Pinned message is deleted'\n }\n});\n\nclass PinnedMessages extends React.PureComponent {\n constructor(props) {\n super(props);\n\n // Starting location of the touch gesture.\n this.touchX = null;\n this.touchY = null;\n\n this.touchSurface = React.createRef();\n\n this.getSelectedIndex = this.getSelectedIndex.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n this.handleSelected = this.handleSelected.bind(this);\n this.handleMoveNext = this.handleMoveNext.bind(this);\n this.handleMovePrev = this.handleMovePrev.bind(this);\n this.handleTouchEventStart = this.handleTouchEventStart.bind(this);\n this.handleTouchEventEnd = this.handleTouchEventEnd.bind(this);\n this.handleTouchCancel = this.handleTouchCancel.bind(this);\n }\n\n componentDidMount() {\n this.touchSurface.current.addEventListener('touchstart', this.handleTouchEventStart, {passive: true});\n this.touchSurface.current.addEventListener('touchend', this.handleTouchEventEnd, {passive: true});\n this.touchSurface.current.addEventListener('touchcancel', this.handleTouchCancel, {passive: true});\n }\n\n componentWillUnmount() {\n this.touchSurface.current.removeEventListener('touchstart', this.handleTouchEventStart);\n this.touchSurface.current.removeEventListener('touchend', this.handleTouchEventEnd);\n this.touchSurface.current.removeEventListener('touchcancel', this.handleTouchCancel);\n }\n getSelectedIndex() {\n const list = (this.props.pins || []);\n return list.length - this.props.selected - 1;\n }\n\n handleCancel(e) {\n e.preventDefault();\n this.props.onCancel(this.props.pins[this.getSelectedIndex()]);\n }\n\n handleSelected(e) {\n e.preventDefault();\n this.props.onSelected(this.props.pins[this.getSelectedIndex()]);\n }\n\n handleMoveNext(e, isTouch) {\n // Don't call preventDefault for touch events.\n isTouch || e.preventDefault();\n e.stopPropagation();\n const idx = Math.max(this.props.selected - 1, 0);\n if (idx != this.props.selected) {\n this.props.setSelected(idx);\n }\n }\n\n handleMovePrev(e, isTouch) {\n // Don't call preventDefault for touch events.\n isTouch || e.preventDefault();\n e.stopPropagation();\n const idx = Math.min(this.props.selected + 1, (this.props.pins || []).length - 1);\n if (idx != this.props.selected) {\n this.props.setSelected(idx);\n }\n }\n\n handleTouchEventStart(e) {\n if (e.touches.length == 1) {\n this.touchX = e.touches[0].clientX;\n this.touchY = e.touches[0].clientY;\n }\n }\n\n handleTouchEventEnd(e) {\n if (this.touchX === null || e.changedTouches.length != 1) {\n this.touchX = null;\n return;\n }\n\n const dX = this.touchX - e.changedTouches[0].clientX;\n const dY = this.touchY - e.changedTouches[0].clientY;\n this.touchX = null;\n\n if (Math.abs(dX) > Math.abs(dY) || Math.abs(dY) < MIN_SWIPE_DISTANCE) {\n // Horizontal swipe or too short vertical swipe.\n return;\n }\n\n if (dY > 0) {\n this.handleMovePrev(e, true);\n } else {\n this.handleMoveNext(e, true);\n }\n }\n\n handleTouchCancel() {\n this.touchX = null;\n }\n\n render() {\n const selected = this.getSelectedIndex();\n let messageShown = (this.props.messages || [])[selected];\n messageShown = messageShown ?\n messageShown._deleted ?\n {this.props.intl.formatMessage(messages.message_deleted)} \n :\n Drafty.format(messageShown.content, previewFormatter, {\n formatMessage: this.props.intl.formatMessage.bind(this.props.intl),\n authorizeURL: this.props.tinode.authorizeURL.bind(this.props.tinode)\n })\n :\n {this.props.intl.formatMessage(messages.message_not_found)} ;\n\n const dots = [];\n this.props.pins.forEach(seq => {\n const cn = dots.length == selected ? 'adot' : 'dot';\n dots.push(
);\n });\n\n return (\n \n {this.props.isAdmin ?\n
:\n
push_pin
\n }\n
{dots}
\n
\n
\n
\n );\n }\n}\n\nexport default injectIntl(PinnedMessages);\n","import React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\nimport SendMessage from './send-message.jsx';\n\nimport { bytesToHumanSize } from '../lib/strformat.js';\n\nconst messages = defineMessages({\n unrecognized_video_format: {\n id: 'unrecognized_video_format',\n defaultMessage: 'Format of this video is not recognized',\n description: 'Error message when uploaded video is invalid',\n }\n});\n\nclass VideoPreview extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.videoRef = React.createRef();\n\n this.handleSendVideo = this.handleSendVideo.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n }\n\n componentDidMount() {\n document.addEventListener('keydown', this.handleKeyDown);\n }\n\n componentWillUnmount() {\n document.removeEventListener('keydown', this.handleKeyDown);\n }\n\n handleKeyDown(e) {\n if (this.props.onSendMessage) {\n return;\n }\n\n e.preventDefault();\n if (e.key === 'Escape') {\n this.props.onClose();\n }\n }\n\n handleSendVideo(caption) {\n this.props.onClose();\n const params = {\n width: this.videoRef.current.videoWidth,\n height: this.videoRef.current.videoHeight,\n duration: (this.videoRef.current.duration * 1000) | 0,\n mime: this.props.content.mime,\n name: this.props.content.filename\n }\n\n if (params.width == 0 || params.height == 0) {\n this.props.onError(this.props.intl.formatMessage(messages.unrecognized_video_format), 'err');\n return;\n }\n\n // Capture screen from a video.\n const canvas = document.createElement('canvas');\n canvas.width = params.width;\n canvas.height = params.height;\n const ctx = canvas.getContext('2d');\n ctx.drawImage(this.videoRef.current, 0, 0, canvas.width, canvas.height);\n ctx.canvas.toBlob(\n preview => this.props.onSendMessage(caption, this.props.content.blob, preview, params),\n 'image/jpeg', 0.75\n );\n }\n\n render() {\n if (!this.props.content) {\n return null;\n }\n\n const width = this.props.content.width || '-';\n const height = this.props.content.height || '-';\n\n const controlist = this.props.onSendMessage ? 'nodownload' : '';\n const autoPlay = !this.props.onSendMessage;\n\n return (\n \n
\n
\n \n
\n {this.props.onSendMessage ?\n
\n :\n }\n
\n );\n }\n};\n\nexport default injectIntl(VideoPreview);\n","// Panel with a chat.\n\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport { Drafty, Tinode } from 'tinode-sdk';\n\nimport CallPanel from '../widgets/call-panel.jsx';\nimport ChatMessage from '../widgets/chat-message.jsx';\nimport ContactBadges from '../widgets/contact-badges.jsx';\nimport DocPreview from '../widgets/doc-preview.jsx';\nimport ErrorPanel from '../widgets/error-panel.jsx';\nimport GroupSubs from '../widgets/group-subs.jsx';\nimport ImagePreview from '../widgets/image-preview.jsx';\nimport Invitation from '../widgets/invitation.jsx';\nimport LetterTile from '../widgets/letter-tile.jsx';\nimport LoadSpinner from '../widgets/load-spinner.jsx';\nimport LogoView from './logo-view.jsx';\nimport MetaMessage from '../widgets/meta-message.jsx';\nimport PinnedMessages from '../widgets/pinned-messages.jsx';\nimport SendMessage from '../widgets/send-message.jsx';\nimport VideoPreview from '../widgets/video-preview.jsx';\n\nimport { DEFAULT_P2P_ACCESS_MODE, EDIT_PREVIEW_LENGTH, IMAGE_PREVIEW_DIM, IMMEDIATE_P2P_SUBSCRIPTION,\n KEYPRESS_DELAY, MESSAGES_PAGE, MAX_EXTERN_ATTACHMENT_SIZE, MAX_IMAGE_DIM, MAX_INBAND_ATTACHMENT_SIZE,\n READ_DELAY, QUOTED_REPLY_LENGTH, VIDEO_PREVIEW_DIM } from '../config.js';\nimport { CALL_STATE_OUTGOING_INITATED, CALL_STATE_IN_PROGRESS } from '../constants.js';\nimport { blobToBase64, fileToBase64, imageScaled, makeImageUrl } from '../lib/blob-helpers.js';\nimport HashNavigation from '../lib/navigation.js';\nimport { bytesToHumanSize, relativeDateFormat, shortDateFormat } from '../lib/strformat.js';\n\n// Run timer with this frequency (ms) for checking notification queue.\nconst NOTIFICATION_EXEC_INTERVAL = 300;\n// Scroll distance before [go to latest message] button is shown.\nconst SHOW_GO_TO_LAST_DIST = 100;\n// Sctoll distance from the top when fetching the page of earlier messages is triggered.\nconst FETCH_PAGE_TRIGGER = 40;\n\nconst messages = defineMessages({\n online_now: {\n id: 'online_now',\n defaultMessage: 'online now',\n description: 'Indicator that the user or topic is currently online',\n },\n last_seen: {\n id: 'last_seen_timestamp',\n defaultMessage: 'Last seen',\n description: 'Label for the timestamp of when the user or topic was last online'\n },\n not_found: {\n id: 'title_not_found',\n defaultMessage: 'Not found',\n description: 'Title shown when topic is not found'\n },\n channel: {\n id: 'channel',\n defaultMessage: 'channel',\n description: 'Subtitle shown for channels in MessagesView instead of last seen'\n },\n file_attachment_too_large: {\n id: 'file_attachment_too_large',\n defaultMessage: 'The file size {size} exceeds the {limit} limit.',\n description: 'Error message when attachment is too large'\n },\n invalid_content: {\n id: 'invalid_content',\n defaultMessage: 'invalid content',\n description: 'Shown when the message is unreadable'\n },\n editing_message: {\n id: 'editing_message',\n defaultMessage: 'Editing',\n description: 'Title over message editing preview'\n },\n drag_file: {\n id: 'drag_file',\n defaultMessage: 'Drag file here',\n description: 'Prompt on the file drag-n-drop overlay banner'\n },\n self_topic_name: {\n id: 'self_topic_name',\n defaultMessage: 'Saved messages',\n description: 'Name of self topic for UI'\n },\n});\n\n// Checks if the access permissions are granted but not yet accepted.\nfunction isUnconfirmed(acs) {\n if (acs) {\n const ex = acs.getExcessive() || '';\n return acs.isJoiner('given') && (ex.includes('R') || ex.includes('W'));\n }\n return false;\n}\n\nfunction isPeerRestricted(acs) {\n if (acs) {\n const ms = acs.getMissing() || '';\n return acs.isJoiner('want') && (ms.includes('R') || ms.includes('W'));\n }\n return false;\n}\n\nfunction shouldPresentCallPanel(callState) {\n // Show call panel if either:\n // - call is outgoing (and the client is waiting for the other side to pick up) or,\n // - call is already in progress.\n return callState == CALL_STATE_OUTGOING_INITATED || callState == CALL_STATE_IN_PROGRESS;\n}\n\nclass MessagesView extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = MessagesView.getDerivedStateFromProps(props, {});\n\n this.componentSetup = this.componentSetup.bind(this);\n this.leave = this.leave.bind(this);\n this.sendMessage = this.sendMessage.bind(this);\n this.retrySend = this.retrySend.bind(this);\n this.sendImageAttachment = this.sendImageAttachment.bind(this);\n this.sendVideoAttachment = this.sendVideoAttachment.bind(this);\n this.sendFileAttachment = this.sendFileAttachment.bind(this);\n this.sendAudioAttachment = this.sendAudioAttachment.bind(this);\n this.sendKeyPress = this.sendKeyPress.bind(this);\n this.subscribe = this.subscribe.bind(this);\n this.handleScrollReference = this.handleScrollReference.bind(this);\n this.mountDnDEvents = this.mountDnDEvents.bind(this);\n this.handleScrollEvent = this.handleScrollEvent.bind(this);\n this.handleDescChange = this.handleDescChange.bind(this);\n this.handleSubsUpdated = this.handleSubsUpdated.bind(this);\n this.handleMessageUpdate = this.handleMessageUpdate.bind(this);\n this.handleAuxUpdate = this.handleAuxUpdate.bind(this);\n this.handleAllMessagesReceived = this.handleAllMessagesReceived.bind(this);\n this.handleInfoReceipt = this.handleInfoReceipt.bind(this);\n this.handleExpandMedia = this.handleExpandMedia.bind(this);\n this.handleClosePreview = this.handleClosePreview.bind(this);\n this.handleFormResponse = this.handleFormResponse.bind(this);\n this.handleContextClick = this.handleContextClick.bind(this);\n this.handleShowMessageContextMenu = this.handleShowMessageContextMenu.bind(this);\n this.handleNewChatAcceptance = this.handleNewChatAcceptance.bind(this);\n this.handleEnablePeer = this.handleEnablePeer.bind(this);\n this.handleAttachFile = this.handleAttachFile.bind(this);\n this.handleAttachImageOrVideo = this.handleAttachImageOrVideo.bind(this);\n this.handleCancelUpload = this.handleCancelUpload.bind(this);\n this.postReadNotification = this.postReadNotification.bind(this);\n this.clearNotificationQueue = this.clearNotificationQueue.bind(this);\n this.goToLatestMessage = this.goToLatestMessage.bind(this);\n this.handleFileDrop = this.handleFileDrop.bind(this);\n\n this.handlePickReply = this.handlePickReply.bind(this);\n this.handleEditMessage = this.handleEditMessage.bind(this);\n this.handleCancelReply = this.handleCancelReply.bind(this);\n this.handleQuoteClick = this.handleQuoteClick.bind(this);\n this.handleUnpinMessage = this.handleUnpinMessage.bind(this);\n this.handleCallHangup = this.handleCallHangup.bind(this);\n\n this.isDragEnabled = this.isDragEnabled.bind(this);\n this.handleDragStart = this.handleDragStart.bind(this);\n this.handleDragIn = this.handleDragIn.bind(this);\n this.handleDragOut = this.handleDragOut.bind(this);\n this.handleDrag = this.handleDrag.bind(this);\n this.handleDrop = this.handleDrop.bind(this);\n\n this.chatMessageRefs = [];\n this.getOrCreateMessageRef = this.getOrCreateMessageRef.bind(this);\n this.getVisibleMessageRange = this.getVisibleMessageRange.bind(this);\n\n // Keeps track of the drag event.\n // Need a counter b/c the browser's 'drag' events may fire multiple times\n // when the user takes the mouse pointer over the container:\n // for the component itself and for all nested/child elements.\n this.dragCounter = 0;\n this.dndRef = null;\n\n this.readNotificationQueue = [];\n this.readNotificationTimer = null;\n\n this.keyPressTimer = null;\n }\n\n getOrCreateMessageRef(seqId) {\n if (this.chatMessageRefs[seqId]) {\n return this.chatMessageRefs[seqId];\n }\n const ref = React.createRef();\n this.chatMessageRefs[seqId] = ref;\n return ref;\n }\n\n getVisibleMessageRange(holderRect) {\n let min = Number.MAX_SAFE_INTEGER, max = -1;\n let visibilityStatus = false;\n this.chatMessageRefs.every((ref, seq) => {\n if (ref.current) {\n const { top, bottom, height } = ref.current.getBoundingClientRect();\n const visible = top <= holderRect.top ? holderRect.top - top <= height : bottom - holderRect.bottom <= height;\n if (visible) {\n visibilityStatus = true;\n min = Math.min(min, seq);\n max = Math.max(max, seq);\n } else if (visibilityStatus) {\n // The remaining elements are no longer visible, no need to iterate them.\n return false;\n }\n }\n return true;\n });\n\n return max >= min ? {min: min, max: max} : {min: 0, max: 0};\n }\n\n componentDidMount() {\n if (this.messagesScroller) {\n this.messagesScroller.addEventListener('scroll', this.handleScrollEvent);\n }\n\n // Drag and drop events\n this.mountDnDEvents(this.dndRef);\n\n this.componentSetup({}, {});\n }\n\n componentWillUnmount() {\n if (this.messagesScroller) {\n this.messagesScroller.removeEventListener('scroll', this.handleScrollEvent);\n }\n\n // Flush all notifications.\n this.clearNotificationQueue();\n\n // Drag and drop events\n if (this.dndRef) {\n this.dndRef.removeEventListener('dragstart', this.handleDragStart);\n this.dndRef.removeEventListener('dragenter', this.handleDragIn);\n this.dndRef.removeEventListener('dragleave', this.handleDragOut);\n this.dndRef.removeEventListener('dragover', this.handleDrag);\n this.dndRef.removeEventListener('drop', this.handleDrop);\n }\n }\n\n componentDidUpdate(prevProps, prevState) {\n // Scroll last message into view on component update e.g. on message received\n // or vertical shrinking.\n if (this.messagesScroller &&\n (prevState.topic != this.state.topic || prevState.maxSeqId != this.state.maxSeqId ||\n prevState.minSeqId != this.state.minSeqId)) {\n // New message.\n if (this.state.scrollPosition < SHOW_GO_TO_LAST_DIST) {\n this.messagesScroller.scrollTop = this.messagesScroller.scrollHeight -\n this.state.scrollPosition - this.messagesScroller.offsetHeight;\n }\n }\n\n if (!this.props.applicationVisible) {\n // If application is not visible, flush all unsent 'read' notifications.\n this.clearNotificationQueue();\n } else {\n // Otherwise assume there are unread messages.\n this.postReadNotification(0);\n }\n\n this.componentSetup(prevProps, prevState);\n }\n\n componentSetup(prevProps, prevState) {\n const topic = this.props.tinode ? this.props.tinode.getTopic(this.state.topic) : undefined;\n if (this.state.topic != prevState.topic) {\n if (prevState.topic && !Tinode.isNewGroupTopicName(prevState.topic)) {\n this.leave(prevState.topic);\n if (prevState.rtcPanel) {\n this.handleCallHangup(prevState.topic, prevProps.callSeq);\n }\n }\n\n if (topic) {\n topic.onData = this.handleMessageUpdate;\n topic.onAllMessagesReceived = this.handleAllMessagesReceived;\n topic.onInfo = this.handleInfoReceipt;\n topic.onMetaDesc = this.handleDescChange;\n topic.onSubsUpdated = this.handleSubsUpdated;\n topic.onPres = this.handleSubsUpdated;\n topic.onAuxUpdated = this.handleAuxUpdate;\n }\n }\n\n if (topic) {\n if ((this.state.topic != prevState.topic) || (this.props.myUserId && !prevProps.myUserId)) {\n // Don't immediately subscribe to a new p2p topic, wait for the first message.\n const newTopic = (this.props.newTopicParams && this.props.newTopicParams._topicName == this.props.topic);\n if (topic.isP2PType() && newTopic && !IMMEDIATE_P2P_SUBSCRIPTION) {\n topic.getMeta(topic.startMetaQuery().withDesc().build());\n } else if (this.props.myUserId) {\n this.subscribe(topic);\n }\n } else if (topic.isSubscribed() && this.state.isReader && !prevState.isReader) {\n // If reader status has changed and data became available.\n topic.getMeta(topic.startMetaQuery().withLaterData().build());\n }\n }\n }\n\n static getDerivedStateFromProps(nextProps, prevState) {\n let nextState = {};\n if (!nextProps.topic) {\n // Default state: no topic.\n nextState = {\n minSeqId: -1,\n maxSeqId: -1,\n latestClearId: -1,\n onlineSubs: [],\n topic: null,\n title: '',\n avatar: null,\n isVerified: false,\n isStaff: false,\n isDangerous: false,\n deleted: false,\n docPreview: null,\n imagePreview: null,\n imagePostview: null,\n videoPreview: null,\n videoPostview: null,\n rtcPanel: null,\n typingIndicator: false,\n scrollPosition: 0,\n fetchingMessages: false,\n peerMessagingDisabled: false,\n channel: false,\n reply: null,\n contentToEdit: null,\n showGoToLastButton: false,\n dragging: false,\n pins: [],\n pinsLoaded: false,\n selectedPin: 0,\n subsVersion: 0\n };\n } else if (nextProps.topic != prevState.topic) {\n const topic = nextProps.tinode.getTopic(nextProps.topic);\n\n nextState = {\n topic: nextProps.topic,\n deleted: topic._deleted,\n docPreview: null,\n imagePreview: null,\n imagePostview: null,\n videoPreview: null,\n videoPostview: null,\n rtcPanel: null,\n typingIndicator: false,\n scrollPosition: 0,\n fetchingMessages: false,\n showGoToLastButton: false,\n contentToEdit: null,\n dragging: false,\n selectedPin: 0\n };\n\n if (nextProps.forwardMessage) {\n // We are forwarding a message. Show preview.\n nextState.reply = {\n content: nextProps.forwardMessage.preview,\n seq: null\n };\n } else {\n nextState.reply = null;\n }\n\n if (topic) {\n // Topic exists.\n const subs = [];\n\n if (nextProps.connected) {\n topic.subscribers((sub) => {\n if (sub.online && sub.user != nextProps.myUserId) {\n subs.push(sub);\n }\n });\n }\n\n Object.assign(nextState, {\n onlineSubs: subs\n });\n\n if (topic.isSelfType()) {\n Object.assign(nextState, {\n title: nextProps.intl.formatMessage(messages.self_topic_name),\n avatar: true\n });\n } else if (topic.public) {\n Object.assign(nextState, {\n title: topic.public.fn,\n avatar: makeImageUrl(topic.public.photo)\n });\n } else {\n Object.assign(nextState, {\n title: '',\n avatar: null\n });\n }\n\n const peer = topic.p2pPeerDesc();\n if (peer) {\n Object.assign(nextState, {\n peerMessagingDisabled: isPeerRestricted(peer.acs)\n });\n } else if (prevState.peerMessagingDisabled) {\n Object.assign(nextState, {\n peerMessagingDisabled: false\n });\n }\n Object.assign(nextState, {\n minSeqId: topic.minMsgSeq(),\n maxSeqId: topic.maxMsgSeq(),\n latestClearId: topic.maxClearId(),\n channel: topic.isChannelType(),\n pins: (topic.aux('pins') || []).slice(),\n pinsLoaded: false\n });\n\n if (nextProps.callTopic == topic.name && shouldPresentCallPanel(nextProps.callState)) {\n nextState.rtcPanel = nextProps.callTopic;\n }\n } else {\n // Invalid topic.\n Object.assign(nextState, {\n minSeqId: -1,\n maxSeqId: -1,\n latestClearId: -1,\n onlineSubs: [],\n title: '',\n avatar: null,\n peerMessagingDisabled: false,\n channel: false,\n pins: [],\n pinsLoaded: false\n });\n }\n } else {\n // We are still in same topic. Show the call panel if necessary.\n if (nextProps.callTopic == prevState.topic && !prevState.rtcPanel &&\n shouldPresentCallPanel(nextProps.callState)) {\n nextState.rtcPanel = nextProps.callTopic;\n }\n }\n\n if (nextProps.acs) {\n if (nextProps.acs.isWriter() != prevState.isWriter) {\n nextState.isWriter = !prevState.isWriter;\n }\n if (nextProps.acs.isReader() != prevState.isReader) {\n nextState.isReader = !prevState.isReader;\n }\n if (nextProps.acs.isAdmin() != prevState.isAdmin) {\n nextState.isAdmin = !prevState.isAdmin;\n }\n if (!nextProps.acs.isReader('given') != prevState.readingBlocked) {\n nextState.readingBlocked = !prevState.readingBlocked;\n }\n if (nextProps.acs.isSharer() != prevState.isSharer) {\n nextState.isSharer = !prevState.isSharer;\n }\n } else {\n if (prevState.isWriter) {\n nextState.isWriter = false;\n }\n if (prevState.isReader) {\n nextState.isReader = false;\n }\n if (prevState.isAdmin) {\n nextState.isAdmin = false;\n }\n if (!prevState.readingBlocked) {\n prevState.readingBlocked = true;\n }\n if (prevState.isSharer) {\n nextState.isSharer = false;\n }\n }\n\n if (isUnconfirmed(nextProps.acs) == !prevState.unconformed) {\n nextState.unconfirmed = !prevState.unconformed;\n }\n\n // Clear subscribers online when there is no connection.\n if (!nextProps.connected && prevState.onlineSubs && prevState.onlineSubs.length > 0) {\n nextState.onlineSubs = [];\n }\n\n return nextState;\n }\n\n subscribe(topic) {\n if (topic.isSubscribed() || !this.props.ready) {\n return;\n }\n\n // Is this a new topic?\n const newTopic = (this.props.newTopicParams && this.props.newTopicParams._topicName == this.props.topic);\n // Don't request the tags. They are useless unless the user\n // is the owner and is editing the topic.\n let getQuery = topic.startMetaQuery().withLaterDesc().withLaterSub().withAux();\n if (this.state.isReader || newTopic) {\n // Reading is either permitted or we don't know because it's a new topic. Ask for messages.\n getQuery = getQuery.withLaterData(MESSAGES_PAGE);\n if (this.state.isReader) {\n getQuery = getQuery.withLaterDel();\n }\n // And show \"loading\" spinner.\n this.setState({ fetchingMessages: true });\n }\n\n const setQuery = newTopic ? this.props.newTopicParams : undefined;\n topic.subscribe(getQuery.build(), setQuery)\n .then(ctrl => {\n if (ctrl.code == 303) {\n // Redirect to another topic requested.\n HashNavigation.navigateTo(HashNavigation.setUrlTopic('', ctrl.params.topic));\n return;\n }\n if (this.state.topic != ctrl.topic) {\n this.setState({topic: ctrl.topic});\n }\n if (this.state.deleted) {\n this.setState({deleted: false});\n }\n this.props.onNewTopicCreated(this.props.topic, ctrl.topic);\n // If there are unsent messages (except hard-failed and video call messages),\n // try sending them now. Hard-failed and unsent video call messages will be dropped.\n let discard = [];\n topic.queuedMessages(pub => {\n if (pub._sending) {\n return;\n }\n if (pub._fatal || (pub.head && pub.head.webrtc)) {\n // Filter out unsent failed & video call messages.\n discard.push(pub.seq);\n return;\n }\n if (topic.isSubscribed()) {\n this.retrySend(pub);\n }\n });\n if (discard.length > 0) {\n topic.delMessagesList(discard, true);\n }\n })\n .catch(err => {\n console.error(\"Failed subscription to\", this.state.topic, err);\n this.props.onError(err.message, 'err');\n const blankState = MessagesView.getDerivedStateFromProps({}, {});\n blankState.title = this.props.intl.formatMessage(messages.not_found);\n this.setState(blankState);\n });\n }\n\n leave(oldTopicName) {\n if (!oldTopicName || !this.props.tinode.isTopicCached(oldTopicName)) {\n return;\n }\n\n const oldTopic = this.props.tinode.getTopic(oldTopicName);\n if (oldTopic && oldTopic.isSubscribed()) {\n oldTopic.leave(false)\n .catch(_ => { /* do nothing here */ })\n .finally(_ => {\n // We don't care if the request succeeded or failed.\n // The topic is dead regardless.\n this.setState({fetchingMessages: false});\n oldTopic.onData = undefined;\n oldTopic.onAllMessagesReceived = undefined;\n oldTopic.onInfo = undefined;\n oldTopic.onMetaDesc = undefined;\n oldTopic.onSubsUpdated = undefined;\n oldTopic.onPres = undefined;\n oldTopic.onAuxUpdated = undefined;\n });\n }\n }\n\n // Don't use React.createRef as the ref.current is not available in componentDidMount in this component.\n handleScrollReference(node) {\n if (node) {\n node.addEventListener('scroll', this.handleScrollEvent);\n this.messagesScroller = node;\n this.messagesScroller.scrollTop = this.messagesScroller.scrollHeight -\n this.state.scrollPosition - this.messagesScroller.offsetHeight;\n }\n }\n\n // Get older messages and show/hide [go to latest message] button.\n handleScrollEvent(event) {\n const pos = event.target.scrollHeight - event.target.scrollTop - event.target.offsetHeight;\n this.setState({\n scrollPosition: pos,\n // Show [go to latest message] if far enough from bottom and scrolling down.\n showGoToLastButton: (pos > SHOW_GO_TO_LAST_DIST) && (pos < this.state.scrollPosition),\n });\n\n if (this.state.fetchingMessages || this.processingScrollEvent) {\n return;\n }\n\n if (event.target.scrollTop <= FETCH_PAGE_TRIGGER) {\n const topic = this.props.tinode.getTopic(this.state.topic);\n if (topic && topic.isSubscribed()) {\n this.processingScrollEvent = true;\n const {min, max} = this.getVisibleMessageRange(event.target.getBoundingClientRect());\n const gaps = topic.msgHasMoreMessages(min, max, false);\n if (gaps.length > 0) {\n this.setState({fetchingMessages: true}, _ => {\n topic.getMessagesPage(MESSAGES_PAGE, gaps, min, max)\n .catch(err => this.props.onError(err.message, 'err'))\n .finally(_ => this.setState({fetchingMessages: false}));\n });\n }\n }\n }\n this.processingScrollEvent = false;\n }\n\n /* Mount drag and drop events */\n mountDnDEvents(dnd) {\n if (dnd) {\n dnd.addEventListener('dragstart', this.handleDragStart);\n dnd.addEventListener('dragenter', this.handleDragIn);\n dnd.addEventListener('dragleave', this.handleDragOut);\n dnd.addEventListener('dragover', this.handleDrag);\n dnd.addEventListener('drop', this.handleDrop);\n this.dndRef = dnd;\n }\n }\n\n goToLatestMessage() {\n this.setState({scrollPosition: 0});\n if (this.messagesScroller) {\n this.messagesScroller.scrollTop = this.messagesScroller.scrollHeight - this.messagesScroller.offsetHeight;\n }\n }\n\n handleDescChange(desc) {\n if (Tinode.isSelfTopicName(this.props.topic)) {\n this.setState({\n title: this.props.intl.formatMessage(messages.self_topic_name),\n avatar: true\n });\n } else if (desc.public) {\n this.setState({\n title: desc.public.fn,\n avatar: makeImageUrl(desc.public.photo)\n });\n } else {\n this.setState({\n title: '',\n avatar: null\n });\n }\n\n if (desc.acs) {\n this.setState({\n isWriter: desc.acs.isWriter(),\n isReader: desc.acs.isReader(),\n isAdmin: desc.acs.isAdmin(),\n readingBlocked: !desc.acs.isReader('given'),\n unconfirmed: isUnconfirmed(desc.acs),\n });\n }\n }\n\n postReadNotification(seq) {\n // Ignore notifications if the app is invisible or topic is not yet available.\n if (!this.props.applicationVisible || !this.state.topic) {\n return;\n }\n\n // Set up the timer if it's not running already.\n if (!this.readNotificationTimer) {\n this.readNotificationTimer = setInterval(_ => {\n if (this.readNotificationQueue.length == 0) {\n // Shut down the timer if the queue is empty.\n clearInterval(this.readNotificationTimer);\n this.readNotificationTimer = null;\n return;\n }\n\n let seq = -1;\n while (this.readNotificationQueue.length > 0) {\n const n = this.readNotificationQueue[0];\n if (n.topicName != this.state.topic) {\n // Topic has changed. Drop the notification.\n this.readNotificationQueue.shift();\n continue;\n }\n\n const now = new Date();\n if (n.sendAt <= now) {\n // Remove expired notification from queue.\n this.readNotificationQueue.shift();\n if (n.seq == 0 || Tinode.isServerAssignedSeq(n.seq)) {\n seq = Math.max(seq, n.seq);\n }\n } else {\n break;\n }\n }\n\n // Send only one notification for the whole batch of messages.\n if (seq >= 0) {\n const topic = this.props.tinode.getTopic(this.state.topic);\n if (topic) {\n try {\n topic.noteRead(seq);\n } catch (err) {\n console.error(\"Failed to send read notification\", err);\n }\n }\n }\n }, NOTIFICATION_EXEC_INTERVAL);\n }\n\n const now = new Date();\n this.readNotificationQueue.push({\n topicName: this.state.topic,\n seq: seq,\n sendAt: now.setMilliseconds(now.getMilliseconds() + READ_DELAY)\n });\n }\n\n // Clear notification queue and timer.\n clearNotificationQueue() {\n this.readNotificationQueue = [];\n if (this.readNotificationTimer) {\n clearInterval(this.readNotificationTimer);\n this.readNotificationTimer = null;\n }\n }\n\n handleSubsUpdated() {\n if (this.state.topic) {\n const subs = [];\n const topic = this.props.tinode.getTopic(this.state.topic);\n topic.subscribers(sub => {\n if (sub.online && sub.user != this.props.myUserId) {\n subs.push(sub);\n }\n });\n const newState = {onlineSubs: subs, subsVersion: this.state.subsVersion + 1};\n const peer = topic.p2pPeerDesc();\n if (peer) {\n Object.assign(newState, {\n peerMessagingDisabled: isPeerRestricted(peer.acs)\n });\n } else if (this.state.peerMessagingDisabled) {\n Object.assign(newState, {\n peerMessagingDisabled: false\n });\n }\n this.setState(newState);\n }\n }\n\n // The 'msg' could be false-ish if some message ranges were deleted.\n handleMessageUpdate(msg) {\n if (!this.state.topic) {\n return;\n }\n const topic = this.props.tinode.getTopic(this.state.topic);\n if (!msg) {\n // msg could be null if one or more messages were deleted.\n // Updating state to force redraw.\n this.setState({latestClearId: topic.maxClearId()});\n return;\n }\n\n clearTimeout(this.keyPressTimer)\n this.setState({maxSeqId: topic.maxMsgSeq(), minSeqId: topic.minMsgSeq(), typingIndicator: false}, _ => {\n // Scroll to the bottom if the message is added to the end of the message\n // list if already at the bottom, otherwise show [go to latest] button.\n // Implemented as a callback to be sure the scroll height has been updated.\n if (topic.isNewMessage(msg.seq)) {\n if (this.state.scrollPosition > SHOW_GO_TO_LAST_DIST) {\n this.setState({showGoToLastButton: true});\n } else {\n this.goToLatestMessage();\n }\n } else {\n if (this.messagesScroller) {\n this.messagesScroller.scrollTop = this.messagesScroller.scrollHeight - this.state.scrollPosition -\n this.messagesScroller.offsetHeight;\n }\n }\n });\n\n // Aknowledge messages except own messages. They are\n // automatically assumed to be read and recived.\n const status = topic.msgStatus(msg, true);\n if (status >= Tinode.MESSAGE_STATUS_SENT && msg.from != this.props.myUserId) {\n this.postReadNotification(msg.seq);\n }\n }\n\n handleAllMessagesReceived(count) {\n this.setState({fetchingMessages: false});\n if (!count) {\n // All messages received. Nothing left to receive.\n const topic = this.props.tinode.getTopic(this.state.topic);\n if (topic) {\n // Send read notification for the absolute last message.\n this.postReadNotification(topic.seq);\n }\n return;\n }\n\n // Load pinned message too (if any);\n if (!this.state.pinsLoaded) {\n // This needs to be guarded to avoid an infinite loop.\n // The loop may happen if some pinned messages are deleted.\n const topic = this.props.tinode.getTopic(this.state.topic);\n this.setState({pinsLoaded: true}, _ => {\n topic.getPinnedMessages();\n });\n } else {\n this.setState({pinsLoaded: false});\n }\n }\n\n handleAuxUpdate(aux) {\n const pins = (aux['pins'] || []).slice();\n let selectedPin = this.state.selectedPin;\n if (pins.length > this.state.pins.length) {\n // New pins added, show the latest.\n selectedPin = 0;\n } else if (selectedPin >= pins.length) {\n selectedPin = Math.max(0, pins.length - 1);\n }\n this.setState({pins: pins, selectedPin: selectedPin});\n }\n\n handleInfoReceipt(info) {\n switch (info.what) {\n case 'kp': {\n clearTimeout(this.keyPressTimer);\n this.keyPressTimer = setTimeout(_ => this.setState({typingIndicator: false}), KEYPRESS_DELAY + 1000);\n if (!this.state.typingIndicator) {\n this.setState({typingIndicator: true});\n }\n break;\n }\n case 'read':\n case 'recv':\n // Redraw due to changed recv/read status.\n this.forceUpdate();\n break;\n default:\n console.info(\"Other change in topic: \", info.what);\n }\n }\n\n handleExpandMedia(content) {\n if (!content) {\n return;\n }\n\n if (content.video) {\n this.setState({videoPostview: content});\n } else {\n this.setState({imagePostview: content});\n }\n }\n\n handleClosePreview() {\n if (this.state.imagePreview && this.state.imagePreview.url) {\n URL.revokeObjectURL(this.state.imagePreview.url);\n }\n if (this.state.videoPreview && this.state.videoPreview.url) {\n URL.revokeObjectURL(this.state.videoPreview.url);\n }\n this.setState({ imagePostview: null, imagePreview: null, docPreview: null, videoPreview: null, videoPostview: null});\n }\n\n handleFormResponse(action, text, data) {\n if (action == 'pub') {\n this.sendMessage(Drafty.attachJSON(Drafty.parse(text), data));\n } else if (action == 'url') {\n const url = new URL(data.ref);\n const params = url.searchParams;\n for (let key in data.resp) {\n if (data.resp.hasOwnProperty(key)) {\n params.set(key, data.resp[key]);\n }\n }\n ['name', 'seq'].forEach(key => {\n if (data[key]) {\n params.set(key, data[key]);\n }\n });\n params.set('uid', this.props.myUserId);\n params.set('topic', this.state.topic);\n url.search = params;\n window.open(url, '_blank');\n } else {\n console.info(\"Unknown action in form\", action);\n }\n }\n\n handleContextClick(e) {\n e.preventDefault();\n e.stopPropagation();\n this.props.showContextMenu({ topicName: this.state.topic, y: e.pageY, x: e.pageX });\n }\n\n handleShowMessageContextMenu(params, messageSpecificMenuItems) {\n if (params.userFrom == 'chan') {\n params.userFrom = this.state.topic;\n params.userName = this.state.title;\n }\n params.topicName = this.state.topic;\n const menuItems = messageSpecificMenuItems || [];\n const topic = this.props.tinode.getTopic(params.topicName);\n if (topic) {\n // Self -> (1) always hard-delete with [Delete] title.\n // P2P -> (1) hard-delete if allowed and not too old, (2) always soft-delete.\n // Group -> (1) hard-delete if allowed and not too old or owner, (2) always soft-delete.\n if (topic.isSelfType()) {\n // Hard-delete with plain [Delete] title.\n menuItems.push('message_delete_generic');\n } else {\n if (!topic.isChannelType()) {\n // P2P or normal group: always allow to soft-delete.\n menuItems.push('message_delete');\n }\n\n const acs = topic.getAccessMode();\n if (acs && acs.isDeleter()) {\n // Owner can always hard-delete regardless of age.\n let canDelete = acs.isOwner();\n if (!canDelete) {\n // Not owner: check message age if configured on the server.\n const maxDelAge = this.props.tinode.getServerParam(Tinode.MSG_DELETE_AGE, 0) | 0;\n // Make sure the message is not too old. This check is here just to make the UI\n // more user-friendly. The server will enforce the limit regardless of this.\n canDelete = maxDelAge == 0 || (maxDelAge > 0 && params.timestamp ?\n params.timestamp.getTime() > (new Date().getTime() - maxDelAge * 1000) : false);\n }\n if (canDelete) {\n // [Delete for All] title.\n menuItems.push('message_delete_hard');\n }\n }\n }\n }\n this.props.showContextMenu(params, menuItems);\n }\n\n handleNewChatAcceptance(action) {\n this.props.onNewChat(this.state.topic, action);\n }\n\n handleEnablePeer(e) {\n e.preventDefault();\n this.props.onChangePermissions(this.state.topic, DEFAULT_P2P_ACCESS_MODE, this.state.topic);\n }\n\n sendKeyPress(audio) {\n const topic = this.props.tinode.getTopic(this.state.topic);\n if (topic.isSubscribed()) {\n if (audio) {\n topic.noteRecording(true);\n } else {\n topic.noteKeyPress();\n }\n }\n }\n\n // sendMessage sends the message with an optional subscription to topic first.\n sendMessage(msg, uploadCompletionPromise, uploader) {\n let head;\n if (this.props.forwardMessage) {\n // We are forwarding a message.\n msg = this.props.forwardMessage.msg;\n head = this.props.forwardMessage.head;\n this.handleCancelReply();\n } else if (this.state.reply) {\n if (this.state.reply.editing) {\n if (msg == this.state.contentToEdit) {\n // Message unchanged.\n this.handleCancelReply();\n return;\n }\n // Editing an existing message.\n head = {replace: ':' + this.state.reply.seq};\n } else if (this.state.reply.content) {\n // Replying to a message in this topic.\n // Turn it into Drafty so we can make a quoted Drafty object later.\n head = {reply: '' + this.state.reply.seq};\n if (typeof msg == 'string') {\n msg = Drafty.parse(msg);\n }\n msg = Drafty.append(Drafty.sanitizeEntities(this.state.reply.content), msg);\n }\n this.handleCancelReply();\n }\n this.props.sendMessage(msg, uploadCompletionPromise, uploader, head);\n }\n\n // Retry sending a message.\n retrySend(pub) {\n this.props.sendMessage(pub.content, undefined, undefined, pub.head)\n .then(_ => {\n // All good. Remove the original message draft from the cache.\n const topic = this.props.tinode.getTopic(this.state.topic);\n topic.delMessagesList([pub.seq], true);\n });\n }\n\n // Send attachment as Drafty message:\n // - if file is too large, upload it and send a s link.\n // - if file is small enough, just send it in-band.\n sendFileAttachment(file) {\n // Server-provided limit reduced for base64 encoding and overhead.\n const maxInbandAttachmentSize = (this.props.tinode.getServerParam('maxMessageSize',\n MAX_INBAND_ATTACHMENT_SIZE) * 0.75 - 1024) | 0;\n\n // If the attachment is a JSON file, then use 'application/octet-stream' instead of 'application/json'.\n // This is a temporary workaround for the collision with the 'application/json' MIME type of form responses.\n // Remove this code in 2026 or so.\n const jsonMimeConverter = (fileType) => fileType == 'application/json' ? 'application/octet-stream' : fileType;\n\n if (file.size > maxInbandAttachmentSize) {\n // Too large to send inband - uploading out of band and sending as a link.\n const uploader = this.props.tinode.getLargeFileHelper();\n if (!uploader) {\n this.props.onError(this.props.intl.formatMessage(messages.cannot_initiate_upload));\n return;\n }\n const uploadCompletionPromise = uploader.upload(file);\n const msg = Drafty.attachFile(null, {\n mime: jsonMimeConverter(file.type),\n filename: file.name,\n size: file.size,\n urlPromise: uploadCompletionPromise\n });\n // Pass data and the uploader to the TinodeWeb.\n this.sendMessage(msg, uploadCompletionPromise, uploader);\n } else {\n // Small enough to send inband.\n fileToBase64(file)\n .then(b64 => this.sendMessage(Drafty.attachFile(null, {\n mime: jsonMimeConverter(b64.mime),\n data: b64.bits,\n filename: b64.name,\n size: file.size\n })))\n .catch(err => this.props.onError(err.message, 'err'));\n }\n }\n\n // handleAttachFile method is called when [Attach file] button is clicked: launch attachment preview.\n handleAttachFile(file) {\n const maxExternAttachmentSize = this.props.tinode.getServerParam('maxFileUploadSize', MAX_EXTERN_ATTACHMENT_SIZE);\n\n if (file.size > maxExternAttachmentSize) {\n // Too large.\n this.props.onError(this.props.intl.formatMessage(messages.file_attachment_too_large,\n {size: bytesToHumanSize(file.size), limit: bytesToHumanSize(maxExternAttachmentSize)}), 'err');\n } else {\n this.setState({\n docPreview: {\n file: file,\n name: file.name,\n size: file.size,\n type: file.type\n }\n });\n }\n }\n\n handleCallHangup(topic, seq) {\n this.props.onVideoCallClosed();\n this.setState({\n rtcPanel: null\n });\n this.props.onCallHangup(topic, seq);\n }\n\n // sendImageAttachment sends the image bits as Drafty message.\n sendImageAttachment(caption, blob) {\n const mime = this.state.imagePreview.mime;\n const width = this.state.imagePreview.width;\n const height = this.state.imagePreview.height;\n const fname = this.state.imagePreview.filename;\n\n // Server-provided limit reduced for base64 encoding and overhead.\n const maxInbandAttachmentSize = (this.props.tinode.getServerParam('maxMessageSize',\n MAX_INBAND_ATTACHMENT_SIZE) * 0.75 - 1024) | 0;\n\n if (blob.size > maxInbandAttachmentSize) {\n // Too large to send inband - uploading out of band and sending as a link.\n const uploader = this.props.tinode.getLargeFileHelper();\n if (!uploader) {\n this.props.onError(this.props.intl.formatMessage(messages.cannot_initiate_upload));\n return;\n }\n const uploadCompletionPromise = uploader.upload(blob);\n\n // Make small preview to show while uploading.\n imageScaled(blob, IMAGE_PREVIEW_DIM, IMAGE_PREVIEW_DIM, -1, false)\n // Convert tiny image into base64 for serialization and previewing.\n .then(scaled => blobToBase64(scaled.blob))\n .then(b64 => {\n let msg = Drafty.insertImage(null, 0, {\n mime: mime,\n _tempPreview: b64.bits, // This preview will not be serialized.\n bits: b64.bits, // Image thumbnail.\n width: width,\n height: height,\n filename: fname,\n size: blob.size,\n urlPromise: uploadCompletionPromise\n });\n if (caption) {\n msg = Drafty.appendLineBreak(msg);\n msg = Drafty.append(msg, Drafty.parse(caption));\n }\n // Pass data and the uploader to the TinodeWeb.\n this.sendMessage(msg, uploadCompletionPromise, uploader);\n })\n .catch(err => this.props.onError(err, 'err'));\n return;\n }\n\n // Send the image inband if it's not too big. The image has been scaled already\n // in image preview.\n blobToBase64(blob)\n .then(b64 => {\n let msg = Drafty.insertImage(null, 0, {\n mime: b64.mime,\n bits: b64.bits,\n width: width,\n height: height,\n filename: fname,\n size: blob.size\n });\n if (caption) {\n msg = Drafty.appendLineBreak(msg);\n msg = Drafty.append(msg, Drafty.parse(caption));\n }\n this.sendMessage(msg);\n });\n }\n\n // sendVideoAttachment sends the video bits as Drafty message.\n sendVideoAttachment(caption, videoBlob, previewBlob, params) {\n const width = params.width;\n const height = params.height;\n\n // Server-provided limit reduced for base64 encoding and overhead.\n const maxInbandAttachmentSize = (this.props.tinode.getServerParam('maxMessageSize',\n MAX_INBAND_ATTACHMENT_SIZE) * 0.75 - 1024) | 0;\n\n const uploads = [];\n let uploader;\n if ((videoBlob.size + previewBlob.size) > maxInbandAttachmentSize) {\n // One or both are too large to send inband. Uploading out of band and sending as a link.\n uploader = this.props.tinode.getLargeFileHelper();\n if (!uploader) {\n this.props.onError(this.props.intl.formatMessage(messages.cannot_initiate_upload));\n return;\n }\n\n uploads[0] = videoBlob.size > maxInbandAttachmentSize * 0.675 ? uploader.upload(videoBlob) : null;\n uploads[1] = previewBlob.size > maxInbandAttachmentSize * 0.275 ? uploader.upload(previewBlob) : null;\n }\n\n if (uploads.length == 0) {\n // Both video and preview are small enough to send inband.\n Promise.all([blobToBase64(videoBlob), blobToBase64(previewBlob)])\n .then(b64s => {\n const [v64, i64] = b64s;\n let msg = Drafty.insertVideo(null, 0, {\n mime: v64.mime,\n bits: v64.bits,\n preview: i64.bits,\n premime: i64.mime,\n width: width,\n height: height,\n duration: params.duration,\n filename: params.name,\n size: videoBlob.size\n });\n if (caption) {\n msg = Drafty.appendLineBreak(msg);\n msg = Drafty.append(msg, Drafty.parse(caption));\n }\n this.sendMessage(msg);\n });\n return;\n }\n\n const uploadCompletionPromise = Promise.all(uploads);\n\n const b64conv = [];\n // Small video converted to base64.\n b64conv[0] = uploads[0] ? null : blobToBase64(videoBlob);\n // Full-size preview fits inline.\n b64conv[1] = uploads[1] ? null : imageScaled(previewBlob, MAX_IMAGE_DIM, MAX_IMAGE_DIM, -1, false)\n .then(scaled => blobToBase64(scaled.blob));\n // Small preview to show while uploading.\n b64conv[2] = imageScaled(previewBlob, VIDEO_PREVIEW_DIM, VIDEO_PREVIEW_DIM, -1, false)\n .then(scaled => blobToBase64(scaled.blob));\n // Convert tiny image into base64 for serialization and previewing.\n Promise.all(b64conv)\n .then(b64s => {\n const [video, img, preview] = b64s;\n let msg = Drafty.insertVideo(null, 0, {\n mime: params.mime,\n bits: video ? video.bits : null,\n _tempPreview: preview.bits,\n preview: img ? img.bits : preview.bits,\n premime: img ? img.mime : preview.mime,\n width: width,\n height: height,\n duration: params.duration,\n filename: params.name,\n size: videoBlob.size,\n urlPromise: uploadCompletionPromise\n });\n\n if (caption) {\n msg = Drafty.appendLineBreak(msg);\n msg = Drafty.append(msg, Drafty.parse(caption));\n }\n // Pass data and the uploader to the TinodeWeb.\n this.sendMessage(msg, uploadCompletionPromise, uploader);\n })\n .catch(err => this.props.onError(err.message, 'err'));\n }\n\n // handleAttachImageOrVideo method is called when [Attach image or video] button is clicked: launch image or video preview.\n handleAttachImageOrVideo(file) {\n const maxExternAttachmentSize = this.props.tinode.getServerParam('maxFileUploadSize', MAX_EXTERN_ATTACHMENT_SIZE);\n\n if (file.type.startsWith('video/')) {\n this.setState({videoPreview: {\n url: URL.createObjectURL(file),\n blob: file,\n filename: file.name,\n size: file.size,\n mime: file.type\n }});\n return;\n }\n\n // Get image dimensions and size, optionally scale it down.\n imageScaled(file, MAX_IMAGE_DIM, MAX_IMAGE_DIM, maxExternAttachmentSize, false)\n .then(scaled => {\n this.setState({imagePreview: {\n url: URL.createObjectURL(scaled.blob),\n blob: scaled.blob,\n filename: scaled.name,\n width: scaled.width,\n height: scaled.height,\n size: scaled.blob.size,\n mime: scaled.mime\n }});\n }).catch(err => {\n this.props.onError(err.message, 'err');\n });\n }\n\n // handleFileDrop is called when the user drags & drops a file upon the message view.\n handleFileDrop(files) {\n if (!files || files.length == 0) {\n return;\n }\n const file = files[0];\n if (file.type && file.type.startsWith('image/')) {\n this.handleAttachImageOrVideo(file);\n } else {\n this.handleAttachFile(file);\n }\n }\n\n // sendAudioAttachment sends audio bits inband as Drafty message (no preview).\n sendAudioAttachment(url, preview, duration) {\n fetch(url)\n .then(result => result.blob())\n .then(blob => {\n // Server-provided limit reduced for base64 encoding and overhead.\n const maxInbandAttachmentSize = this.props.tinode.getServerParam('maxMessageSize', MAX_INBAND_ATTACHMENT_SIZE) * 0.75 - 1024;\n if (blob.size > maxInbandAttachmentSize) {\n // Too large to send inband - uploading out of band and sending as a link.\n const uploader = this.props.tinode.getLargeFileHelper();\n if (!uploader) {\n this.props.onError(this.props.intl.formatMessage(messages.cannot_initiate_upload));\n return;\n }\n const uploadCompletionPromise = uploader.upload(blob);\n const msg = Drafty.appendAudio(null, {\n mime: blob.type,\n size: blob.size,\n duration: duration,\n preview: preview,\n urlPromise: uploadCompletionPromise\n });\n // Pass data and the uploader to the TinodeWeb.\n this.sendMessage(msg, uploadCompletionPromise, uploader);\n } else {\n // Small enough to send inband.\n blobToBase64(blob)\n .then(b64 => {\n this.sendMessage(Drafty.appendAudio(null, {\n mime: b64.mime,\n bits: b64.bits,\n size: blob.size,\n duration: duration,\n preview: preview,\n }))\n })\n }\n })\n .catch(err => {this.props.onError(err.message, 'err')});;\n }\n\n handleCancelUpload(seq, uploader) {\n const topic = this.props.tinode.getTopic(this.state.topic);\n const found = topic.findMessage(seq);\n if (found) {\n found._cancelled = true;\n }\n uploader.cancel();\n }\n\n // seq: seq ID of the source message\n // context: message content.\n // senderId: UID of the sender of the source message.\n // senderName: full name of the sender of the original message.\n handlePickReply(seq, content, senderId, senderName) {\n if (!seq || !content) {\n this.setState({reply: null});\n return;\n }\n\n content = typeof content == 'string' ? Drafty.init(content) : content;\n if (Drafty.isValid(content)) {\n content = Drafty.replyContent(content, QUOTED_REPLY_LENGTH);\n } else {\n // /!\\ invalid content.\n content = Drafty.append(Drafty.init('\\u26A0 '),\n Drafty.wrapInto(this.props.intl.formatMessage(messages.invalid_content), 'EM'));\n }\n\n this.setState({\n reply: {\n content: Drafty.quote(senderName, senderId, content),\n seq: seq\n }\n });\n this.props.onCancelForwardMessage();\n }\n\n // seq: seq ID of the message to edit.\n // context: message content.\n handleEditMessage(seq, content) {\n if (!seq || !content) {\n this.setState({reply: null});\n return;\n }\n\n content = typeof content == 'string' ? Drafty.init(content) : content;\n const editable = Drafty.toMarkdown(content);\n if (Drafty.isValid(content)) {\n content = Drafty.replyContent(content, EDIT_PREVIEW_LENGTH);\n } else {\n // /!\\ invalid content.\n content = Drafty.append(Drafty.init('\\u26A0 '),\n Drafty.wrapInto(this.props.intl.formatMessage(messages.invalid_content), 'EM'));\n }\n\n this.setState({\n reply: {\n content: Drafty.quote(this.props.intl.formatMessage(messages.editing_message), null, content),\n seq: seq,\n editing: true\n },\n contentToEdit: editable\n });\n this.props.onCancelForwardMessage();\n }\n\n\n handleCancelReply() {\n this.setState({reply: null, contentToEdit: null});\n this.props.onCancelForwardMessage();\n }\n\n handleQuoteClick(replyToSeq) {\n const ref = this.getOrCreateMessageRef(replyToSeq);\n if (ref && ref.current) {\n ref.current.scrollIntoView({block: \"center\", behavior: \"smooth\"});\n ref.current.classList.add('flash');\n setTimeout(_ => {ref.current.classList.remove('flash')} , 1000);\n } else {\n console.error(\"Unresolved message ref\", replyToSeq);\n }\n }\n\n handleUnpinMessage(seq) {\n const topic = this.props.tinode.getTopic(this.state.topic);\n topic.pinMessage(seq, false);\n }\n\n isDragEnabled() {\n return this.state.isWriter && !this.state.unconfirmed && !this.props.forwardMessage && !this.state.peerMessagingDisabled;\n }\n\n handleDragStart(e) {\n e.preventDefault();\n e.stopPropagation();\n e.dataTransfer.clearData();\n }\n\n handleDragIn(e) {\n e.preventDefault();\n e.stopPropagation();\n this.dragCounter++;\n if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {\n this.setState({dragging: true});\n }\n }\n\n handleDragOut(e) {\n e.preventDefault();\n e.stopPropagation();\n this.dragCounter--;\n if (this.dragCounter <= 0) {\n this.setState({dragging: false});\n }\n }\n\n handleDrag(e) {\n e.preventDefault();\n e.stopPropagation();\n }\n\n handleDrop(e) {\n e.preventDefault();\n e.stopPropagation();\n this.setState({dragging: false});\n if (this.isDragEnabled() && e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n this.handleFileDrop(e.dataTransfer.files);\n this.dragCounter = 0;\n }\n }\n\n render() {\n const {formatMessage} = this.props.intl;\n\n let component;\n if (!this.state.topic) {\n component = (\n \n );\n } else {\n let component2;\n if (this.state.imagePreview) {\n // Preview image before sending.\n component2 = (\n \n );\n } else if (this.state.videoPreview) {\n // Preview video.\n component2 = (\n \n );\n } else if (this.state.imagePostview) {\n // Expand received image.\n component2 = (\n \n );\n } else if (this.state.videoPostview) {\n // Play received video.\n component2 = (\n \n );\n } else if (this.state.docPreview) {\n // Preview attachment before sending.\n component2 = (\n \n );\n } else if (this.state.rtcPanel) {\n // P2P call.\n component2 = (\n \n );\n } else {\n const topic = this.props.tinode.getTopic(this.state.topic);\n const isChannel = topic.isChannelType();\n const groupTopic = topic.isGroupType() && !isChannel;\n const icon_badges = [];\n if (topic.trusted) {\n if (topic.trusted.verified) {\n icon_badges.push({icon: 'verified', color: 'badge-inv'});\n }\n if (topic.trusted.staff) {\n icon_badges.push({icon: 'staff', color: 'badge-inv'});\n }\n if (topic.trusted.danger) {\n icon_badges.push({icon: 'dangerous', color: 'badge-inv'});\n }\n }\n\n const pinnedMessages = [];\n this.state.pins.forEach(seq => pinnedMessages.push(topic.latestMsgVersion(seq) || topic.findMessage(seq)));\n\n const messageNodes = [];\n let previousFrom = null;\n let prevDate = null;\n let chatBoxClass = null;\n topic.messages((msg, prev, next, i) => {\n let nextFrom = next ? (next.from || 'chan') : null;\n\n let sequence = 'single';\n let thisFrom = msg.from || 'chan';\n if (thisFrom == previousFrom) {\n if (thisFrom == nextFrom) {\n sequence = 'middle';\n } else {\n sequence = 'last';\n }\n } else if (thisFrom == nextFrom) {\n sequence = 'first';\n }\n previousFrom = thisFrom;\n\n const isReply = !(thisFrom == this.props.myUserId);\n const deliveryStatus = topic.msgStatus(msg, true);\n\n let userFrom = thisFrom, userName, userAvatar;\n const user = topic.userDesc(thisFrom);\n if (user && user.public) {\n userName = user.public.fn;\n userAvatar = makeImageUrl(user.public.photo);\n }\n chatBoxClass = groupTopic ? 'chat-box group' : 'chat-box';\n\n // Ref for this chat message.\n const ref = this.getOrCreateMessageRef(msg.seq);\n let replyToSeq = msg.head ? parseInt(msg.head.reply) : null;\n if (!replyToSeq || isNaN(replyToSeq)) {\n replyToSeq = null;\n }\n\n if (msg.hi) {\n // Deleted message.\n messageNodes.push(\n \n );\n } else {\n const thisDate = new Date(msg.ts);\n // This message was sent on a different date than the previous.\n if (!prevDate || prevDate.toDateString() != thisDate.toDateString()) {\n messageNodes.push(\n \n );\n prevDate = thisDate;\n }\n messageNodes.push(\n \n );\n }\n });\n\n let lastSeen = null;\n if (isChannel) {\n lastSeen = formatMessage(messages.channel);\n } else {\n const cont = this.props.tinode.getMeTopic().getContact(this.state.topic);\n if (cont && Tinode.isP2PTopicName(cont.topic)) {\n if (cont.online) {\n lastSeen = formatMessage(messages.online_now);\n } else if (cont.seen) {\n lastSeen = formatMessage(messages.last_seen) + \": \" +\n shortDateFormat(cont.seen.when, this.props.intl.locale);\n // TODO: also handle user agent in c.seen.ua\n }\n }\n }\n const avatar = this.state.avatar || true;\n const online = this.state.deleted || topic.isSelfType() ? null :\n this.props.online ? 'online' + (this.state.typingIndicator ? ' typing' : '') : 'offline';\n\n const titleClass = 'panel-title' + (this.state.deleted ? ' deleted' : '');\n\n let messagesComponent = (\n <>\n \n
\n arrow_downward \n \n
\n {!this.state.isReader ?\n
\n {this.state.readingBlocked ?\n
\n \n
\n : null }\n
\n : null }\n
\n {this.state.peerMessagingDisabled && !this.state.unconfirmed ?\n : null}\n {this.state.unconfirmed ?\n \n :\n }\n >\n );\n\n component2 = (\n <>\n \n {this.props.displayMobile ?\n <>\n {this.state.pins.length > 0 ?\n this.setState({selectedPin: index})}\n onSelected={this.handleQuoteClick}\n onCancel={this.handleUnpinMessage} />\n : null\n }\n \n >\n : null}\n \n {messagesComponent}\n {this.state.dragging && this.isDragEnabled() ?\n {formatMessage(messages.drag_file)}
\n : null}\n >\n );\n }\n component = {component2}
\n }\n return component;\n }\n};\n\nexport default injectIntl(MessagesView);\n","// The <- button to be displayed in title bars.\nimport React from 'react';\n\nexport default class ButtonBack extends React.PureComponent {\n render() {\n return (\n {e.preventDefault(); this.props.onBack();}}>\n arrow_back \n \n );\n }\n}\n","import React from 'react';\n\nexport default class MenuContacts extends React.PureComponent {\n render() {\n return (\n \n );\n }\n};\n","import React from 'react';\n\nexport default class MenuStart extends React.PureComponent {\n render() {\n return (\n \n );\n }\n};\n","import React from 'react';\n\nimport LetterTile from './letter-tile.jsx';\nimport ButtonBack from './button-back.jsx';\nimport ContactBadges from './contact-badges.jsx';\nimport MenuContacts from './menu-contacts.jsx';\nimport MenuStart from './menu-start.jsx';\n\nimport { sanitizeUrlForMime } from '../lib/utils.js';\n\nexport default class SideNavbar extends React.PureComponent {\n render() {\n const icon_badges = [];\n if (this.props.trustedBadges) {\n this.props.trustedBadges.forEach(b => {\n icon_badges.push({icon: b, color: 'badge-inv'});\n });\n }\n let avatar = null;\n if (this.props.tinode) {\n avatar = this.props.tinode.authorizeURL(sanitizeUrlForMime(this.props.avatar, 'image'));\n }\n return (\n \n {this.props.onCancel ?
: null}\n {avatar ?\n
\n \n
\n :\n null}\n
{this.props.title}
\n {this.props.state === 'login' ?\n
:\n this.props.state === 'contacts' ?\n
:\n null}\n
\n );\n }\n};\n","/* ContactsView holds all contacts-related stuff */\nimport React from 'react';\nimport { FormattedMessage, defineMessages } from 'react-intl';\n\nimport ContactList from '../widgets/contact-list.jsx';\n\nimport { updateFavicon } from '../lib/utils.js';\n\nconst messages = defineMessages({\n archived_contacts_title: {\n id: \"archived_contacts\",\n defaultMessage: \"Archived contacts ({count})\",\n description: \"Label for archived chats\"\n }\n});\n\nexport default class ContactsView extends React.Component {\n constructor(props) {\n super(props);\n\n this.handleAction = this.handleAction.bind(this);\n\n this.state = ContactsView.deriveStateFromProps(props);\n }\n\n static deriveStateFromProps(props) {\n const contacts = [];\n let unreadThreads = 0;\n let archivedCount = 0;\n props.chatList.forEach(c => {\n const blocked = c.acs && !c.acs.isJoiner();\n // Show only blocked contacts only when props.blocked == true.\n if (blocked && props.blocked) {\n contacts.push(c);\n }\n if (blocked || props.blocked) {\n return;\n }\n\n if (c.private && c.private.arch) {\n if (props.archive) {\n contacts.push(c);\n } else {\n archivedCount ++;\n }\n } else if (!props.archive) {\n contacts.push(c);\n unreadThreads += c.unread > 0 ? 1 : 0;\n }\n });\n\n contacts.sort((a, b) => {\n return (b.touched || 0) - (a.touched || 0);\n });\n\n if (archivedCount > 0) {\n contacts.push({\n action: 'archive',\n title: messages.archived_contacts_title,\n values: {count: archivedCount}\n });\n }\n\n return {\n contactList: contacts,\n unreadThreads: unreadThreads\n };\n }\n\n componentDidUpdate(prevProps, prevState) {\n if (prevProps.chatList != this.props.chatList ||\n prevProps.archive != this.props.archive ||\n prevProps.blocked != this.props.blocked) {\n const newState = ContactsView.deriveStateFromProps(this.props);\n this.setState(newState);\n if (newState.unreadThreads != prevState.unreadThreads) {\n updateFavicon(newState.unreadThreads);\n }\n }\n }\n\n handleAction(action_ignored) {\n this.props.onShowArchive();\n }\n\n render() {\n return (\n ¯∖_(ツ)_/¯\"\n description=\"HTML message shown in ContactList when no contacts are found\">{\n (no_contacts) => \n }\n );\n }\n};\n","// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport CheckBox from '../widgets/checkbox.jsx';\n\nexport default class EditAccountView extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleCheckboxClick = this.handleCheckboxClick.bind(this);\n }\n\n handleCheckboxClick(what, checked) {\n if (what == 'sound') {\n this.props.onToggleMessageSounds(checked);\n } else if (what == 'alert') {\n this.props.onTogglePushNotifications(checked);\n } else if (what == 'incognito') {\n this.props.onToggleIncognitoMode(checked);\n }\n }\n\n render() {\n return (\n \n
\n \n \n \n \n
\n
\n \n {this.props.desktopAlertsEnabled ?\n \n :\n \n }\n \n \n
\n
\n \n \n \n \n
\n
\n );\n }\n};\n","// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport InPlaceEdit from '../widgets/in-place-edit.jsx';\nimport PermissionsEditor from '../widgets/permissions-editor.jsx';\n\nconst messages = defineMessages({\n delete_account: {\n id: 'delete_account',\n defaultMessage: 'Delete account',\n description: 'Title for delete account warning'\n },\n delete_account_warning: {\n id: 'delete_account_warning',\n defaultMessage: 'Are you sure you want to delete your account? It cannot be undone.',\n description: 'Warning message when deleting an account'\n }\n});\n\nclass AccSecurityView extends React.Component {\n constructor(props) {\n super(props);\n\n const me = this.props.tinode.getMeTopic();\n let blockedCount = 0;\n me.contacts((c) => {\n if (c.acs && !c.acs.isJoiner()) {\n blockedCount ++;\n }\n });\n const defacs = me.getDefaultAccess();\n this.state = {\n auth: defacs ? defacs.auth : null,\n anon: defacs ? defacs.anon : null,\n showPermissionEditorFor: undefined,\n blockedCount: blockedCount,\n };\n\n this.handlePasswordUpdate = this.handlePasswordUpdate.bind(this);\n this.handleLaunchPermissionsEditor = this.handleLaunchPermissionsEditor.bind(this);\n this.handleHidePermissionsEditor = this.handleHidePermissionsEditor.bind(this);\n this.handlePermissionsChanged = this.handlePermissionsChanged.bind(this);\n this.handleDeleteAccount = this.handleDeleteAccount.bind(this);\n }\n\n handlePasswordUpdate(pwd) {\n this.setState({password: pwd});\n this.props.onUpdatePassword(pwd);\n }\n\n handleLaunchPermissionsEditor(which) {\n this.setState({\n showPermissionEditorFor: which,\n editedPermissions: this.state[which]\n });\n }\n\n handleHidePermissionsEditor() {\n this.setState({showPermissionEditorFor: undefined});\n }\n\n handlePermissionsChanged(perm) {\n let defacs = {};\n defacs[this.state.showPermissionEditorFor] = perm;\n this.props.onUpdateAccountDesc('me', undefined, undefined, defacs);\n\n let newState = {showPermissionEditorFor: undefined};\n newState[this.state.showPermissionEditorFor] = perm;\n this.setState(newState);\n }\n\n handleDeleteAccount(e) {\n e.preventDefault();\n const {formatMessage} = this.props.intl;\n this.props.onShowAlert(\n formatMessage(messages.delete_account), // title\n formatMessage(messages.delete_account_warning), // content\n (_ => this.props.onDeleteAccount()), // onConfirm\n null, // use default text \"OK\"\n true, // Show Reject button\n null // use default text \"Cancel\"\n );\n }\n\n render() {\n return (\n <>{this.state.showPermissionEditorFor ?\n \n :\n \n
\n
\n \n \n
\n {\n (password_unchanged) => \n } \n
\n
\n
\n
\n
\n
\n
\n \n \n \n
\n
\n
Auth: {this.state.auth}
\n
Anon: {this.state.anon}
\n
\n
\n {this.state.blockedCount > 0 ?\n <>\n
\n
\n >\n : null }\n
\n }>\n );\n }\n};\n\nexport default injectIntl(AccSecurityView);\n","// Edit account parameters.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport { APP_NAME, LINK_CONTACT_US, LINK_PRIVACY_POLICY, LINK_TERMS_OF_SERVICE } from '../config.js';\n\nexport default class AccSupportView extends React.PureComponent {\n render() {\n return (\n \n
\n
\n
\n
\n \n {APP_NAME}\n
\n
\n \n {Tinode.getLibrary()}\n
\n
\n \n {this.props.serverVersion}\n
\n
\n \n {this.props.serverAddress}\n
\n
\n
\n );\n }\n};\n","// Login form.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport CheckBox from '../widgets/checkbox.jsx';\nimport VisiblePassword from '../widgets/visible-password.jsx';\n\nexport default class LoginView extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n login: props.login,\n password: '',\n hostName: props.serverAddress,\n saveToken: props.persist\n };\n this.handleLoginChange = this.handleLoginChange.bind(this);\n this.handlePasswordChange = this.handlePasswordChange.bind(this);\n this.handleToggleSaveToken = this.handleToggleSaveToken.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n }\n\n handleLoginChange(e) {\n this.setState({login: e.target.value});\n }\n\n handlePasswordChange(e) {\n this.setState({password: e.target.value});\n }\n\n handleToggleSaveToken() {\n this.props.onPersistenceChange(!this.state.saveToken);\n this.setState({saveToken: !this.state.saveToken});\n }\n\n handleSubmit(e) {\n e.preventDefault();\n this.props.onLogin(this.state.login.trim(), this.state.password.trim());\n }\n\n render() {\n let submitClasses = 'primary';\n if (this.props.disabled) {\n submitClasses += ' disabled';\n }\n\n return (\n \n );\n }\n};\n","import QRCode from 'qrcodejs';\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport { QRCODE_SIZE } from '../config';\n\nconst messages = defineMessages({\n invalid_id: {\n id: 'error_invalid_id',\n defaultMessage: 'Invalid ID',\n description: 'Error message'\n }\n});\n\nclass NewTopicById extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.qrCodeRef = React.createRef();\n\n this.state = {\n groupId: '',\n };\n\n this.handleChange = this.handleChange.bind(this);\n this.handleKeyPress = this.handleKeyPress.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n }\n\n componentDidMount() {\n new QRCode(this.qrCodeRef.current, {\n text: this.props.myURI,\n width: QRCODE_SIZE,\n height: QRCODE_SIZE,\n });\n }\n\n handleChange(e) {\n this.setState({groupId: e.target.value});\n }\n\n handleKeyPress(e) {\n if (e.key === 'Enter') {\n this.handleSubmit(e);\n }\n }\n\n handleSubmit(e) {\n e.preventDefault();\n if (this.state.groupId) {\n const name = this.state.groupId.trim();\n const prefix = name.substring(0, 3);\n if (name.length > 3 && ['usr', 'grp', 'chn'].includes(prefix)) {\n this.props.onSubmit(name);\n } else {\n this.props.onError(this.props.intl.formatMessage(messages.invalid_id), 'err');\n }\n }\n }\n\n render() {\n return (\n \n
\n {\n (prompt) => \n } \n
\n
\n \n \n \n
\n
\n
\n
\n );\n }\n};\n\nexport default injectIntl(NewTopicById);\n","import React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport AvatarCrop from './avatar-crop.jsx';\nimport AvatarUpload from './avatar-upload.jsx';\nimport CheckBox from './checkbox.jsx';\nimport TagManager from './tag-manager.jsx';\n\nimport { AVATAR_SIZE, MAX_AVATAR_BYTES, MAX_EXTERN_ATTACHMENT_SIZE, MAX_TITLE_LENGTH,\n MAX_TOPIC_DESCRIPTION_LENGTH } from '../config.js';\nimport { imageScaled, blobToBase64, makeImageUrl } from '../lib/blob-helpers.js';\n\nexport default class NewTopicGroup extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.fullName = React.createRef();\n\n this.state = {\n fullName: '', // full/formatted name\n private: '',\n description: '',\n imageUrl: null,\n tags: [],\n isChannel: false,\n newAvatar: null,\n newAvatarMime: null\n };\n\n this.handleFieldEdit = this.handleFieldEdit.bind(this);\n this.handleImageChanged = this.handleImageChanged.bind(this);\n this.handleAvatarCropped = this.handleAvatarCropped.bind(this);\n this.handleAvatarCropCancel = this.handleAvatarCropCancel.bind(this);\n this.uploadAvatar = this.uploadAvatar.bind(this);\n this.handleTagsChanged = this.handleTagsChanged.bind(this);\n this.handleChannelToggle = this.handleChannelToggle.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n }\n\n componentDidMount() {\n // this.fullName.current.focus();\n }\n\n handleFieldEdit(name, e) {\n this.setState({[name]: e.target.value || ''});\n }\n\n handleImageChanged(mime, img) {\n this.setState({newAvatar: img, newAvatarMime: mime});\n }\n\n handleAvatarCropped(mime, blob, width, height) {\n const url = blob ? URL.createObjectURL(blob) : null;\n this.setState({imageUrl: url, newAvatar: null, newAvatarMime: null});\n if (blob) {\n this.uploadAvatar(mime, blob, width, height);\n }\n }\n\n handleAvatarCropCancel() {\n this.setState({newAvatar: null, newAvatarMime: null});\n }\n\n // Utility method for converting cropped avatar blob to bytes for sending inband or\n // for uploading it to the server out of band.\n uploadAvatar(mime, blob, width, height) {\n const readyToUpload = image => {\n let {mime, blob} = image;\n if (blob.size > MAX_AVATAR_BYTES) {\n // Too large to send inband - uploading out of band and sending as a link.\n const uploader = this.props.tinode.getLargeFileHelper();\n uploader.upload(blob)\n .then(url => this.setState({imageUrl: url}))\n .catch(err => this.props.onError(err.message, 'err'));\n } else {\n // Convert blob to base64-encoded bits.\n blobToBase64(blob)\n .then(b64 => this.setState({imageUrl: makeImageUrl({data: b64.bits, type: mime})}));\n }\n };\n\n if (width > AVATAR_SIZE || height > AVATAR_SIZE || width != height) {\n // Avatar is not square or too large even after cropping. Shrink it and make square.\n imageScaled(blob, AVATAR_SIZE, AVATAR_SIZE, MAX_EXTERN_ATTACHMENT_SIZE, true)\n .then(scaled => readyToUpload(scaled))\n .catch(err => this.props.onError(err.message, 'err'));\n } else {\n readyToUpload({mime: mime, blob: blob, width: width, height: height});\n }\n }\n\n handleTagsChanged(tags) {\n this.setState({tags: tags});\n }\n\n handleChannelToggle() {\n this.setState({isChannel: !this.state.isChannel});\n }\n\n handleSubmit(e) {\n e.preventDefault();\n\n const fn = this.state.fullName.trim().substring(0, MAX_TITLE_LENGTH);\n const comment = this.state.private.trim().substring(0, MAX_TITLE_LENGTH);\n const description = this.state.description.trim().substring(0, MAX_TOPIC_DESCRIPTION_LENGTH);\n if (fn) {\n this.props.onSubmit(fn, description, this.state.imageUrl, comment, this.state.tags, this.state.isChannel);\n }\n }\n\n render() {\n if (this.state.newAvatar) {\n return (\n \n );\n }\n\n let submitClasses = 'primary';\n if (this.props.disabled) {\n submitClasses += ' disabled';\n }\n return (\n \n );\n }\n};\n","// Create new topic and invite users or send an invite.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport { Tinode } from 'tinode-sdk';\n\nimport ContactList from '../widgets/contact-list.jsx';\nimport NewTopicById from '../widgets/new-topic-by-id.jsx';\nimport NewTopicGroup from '../widgets/new-topic-group.jsx';\nimport SearchContacts from '../widgets/search-contacts.jsx';\n\nimport HashNavigation from '../lib/navigation.js';\nimport { asEmail, asPhone, theCard } from '../lib/utils.js';\n\nconst messages = defineMessages({\n search_for_contacts: {\n id: \"search_for_contacts\",\n defaultMessage: \"Use search to find contacts\",\n description: \"Text shown in contacts view when user entered no search query.\"\n },\n search_no_results: {\n id: \"search_no_results\",\n defaultMessage: \"Search returned no results\",\n description: \"Text shown in contacts view when query returned no results.\"\n },\n search_placeholder: {\n id: \"search_placeholder\",\n defaultMessage: \"List like alice@example.com, +17025550003...\",\n description: \"Placeholder in contacts search field\"\n },\n});\n\nclass NewTopicView extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n tabSelected: 'find',\n searchQuery: null\n };\n\n this.handleTabClick = this.handleTabClick.bind(this);\n this.handleSearchContacts = this.handleSearchContacts.bind(this);\n this.handleSearchResultSelected = this.handleSearchResultSelected.bind(this);\n this.handleNewGroupSubmit = this.handleNewGroupSubmit.bind(this);\n this.handleGroupByID = this.handleGroupByID.bind(this);\n }\n\n componentDidMount() {\n this.props.onInitFind();\n }\n\n handleTabClick(e) {\n e.preventDefault();\n HashNavigation.navigateTo(HashNavigation.addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id));\n this.setState({tabSelected: e.currentTarget.dataset.id});\n }\n\n handleSearchContacts(query) {\n query = query.trim() || Tinode.DEL_CHAR;\n if (!/[\\s,:]/.test(query) && query != Tinode.DEL_CHAR) {\n // No colons, spaces or commas, not DEL char. Try as email, phone, or alias.\n const email = asEmail(query);\n if (email) {\n query = `${Tinode.TAG_EMAIL}${email}`;\n } else {\n const tel = asPhone(query);\n if (tel) {\n query = `${Tinode.TAG_PHONE}${tel}`;\n } else {\n if (query[0] == '@') {\n // Strip the leading '@' sign if present.\n query = query.substring(1);\n }\n // 'alice' -> 'alias:alice,alice'\n query = `${Tinode.TAG_ALIAS}${query},${query}`;\n }\n }\n }\n this.props.onSearchContacts(query);\n this.setState({searchQuery: Tinode.isNullValue(query) ? null : query});\n }\n\n handleSearchResultSelected(topicName) {\n if (this.state.tabSelected == 'find') {\n HashNavigation.navigateTo(HashNavigation.removeUrlParam(window.location.hash, 'tab'));\n this.props.onCreateTopic(topicName);\n }\n }\n\n handleNewGroupSubmit(name, description, dataUrl, priv, tags, isChannel) {\n HashNavigation.navigateTo(HashNavigation.removeUrlParam(window.location.hash, 'tab'));\n this.props.onCreateTopic(undefined,\n {public: theCard(name, dataUrl, null, description), private: priv, tags: tags}, isChannel);\n }\n\n handleGroupByID(topicName) {\n HashNavigation.navigateTo(HashNavigation.removeUrlParam(window.location.hash, 'tab'));\n this.props.onCreateTopic(topicName);\n }\n\n render() {\n const {formatMessage} = this.props.intl;\n const no_contacts_placeholder = formatMessage(this.state.searchQuery ?\n messages.search_no_results : messages.search_for_contacts);\n const search_placeholder = formatMessage(messages.search_placeholder);\n return (\n \n
\n {this.state.tabSelected === 'grp' ?\n
:\n this.state.tabSelected === 'byid' ?\n
:\n
\n \n \n
}\n
\n );\n }\n};\n\nexport default injectIntl(NewTopicView);\n","import React from 'react';\n\nimport { KNOWN_HOSTS } from '../config.js';\n\n/* Combobox for selecting host name */\n\nexport default class HostSelector extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n hostName: props.serverAddress,\n changed: false\n };\n\n this.handleHostNameChange = this.handleHostNameChange.bind(this);\n this.handleEditingFinished = this.handleEditingFinished.bind(this);\n this.handleKeyDown = this.handleKeyDown.bind(this);\n }\n\n handleHostNameChange(e) {\n this.setState({hostName: e.target.value, changed: true});\n }\n\n handleEditingFinished() {\n if (this.state.changed) {\n this.setState({changed: false});\n this.props.onServerAddressChange(this.state.hostName.trim());\n }\n }\n\n handleKeyDown(e) {\n if (e.key == 'Enter') {\n this.handleEditingFinished();\n }\n }\n\n render() {\n const hostOptions = [];\n for (let key in KNOWN_HOSTS) {\n let item = KNOWN_HOSTS[key];\n hostOptions.push(\n \n );\n }\n return (\n \n \n \n {hostOptions}\n \n
\n );\n }\n}\n","// Tinode config panel.\nimport React from 'react';\nimport { FormattedMessage } from 'react-intl';\n\nimport CheckBox from '../widgets/checkbox.jsx';\n\nimport HostSelector from '../widgets/host-selector.jsx';\n\nexport default class SettingsView extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n transport: props.transport || 'def',\n serverAddress: props.serverAddress,\n secureConnection: props.secureConnection,\n };\n\n this.handleSubmit = this.handleSubmit.bind(this);\n this.handleTransportSelected = this.handleTransportSelected.bind(this);\n this.handleServerAddressChange = this.handleServerAddressChange.bind(this);\n this.handleToggleSecure = this.handleToggleSecure.bind(this);\n }\n\n handleSubmit(e) {\n e.preventDefault();\n this.props.onUpdate({\n transport: this.state.transport,\n serverAddress: this.state.serverAddress,\n secureConnection: this.state.secureConnection,\n });\n }\n\n handleTransportSelected(e) {\n this.setState({transport: e.currentTarget.value});\n }\n\n handleServerAddressChange(name) {\n this.setState({serverAddress: name});\n }\n\n handleToggleSecure(e) {\n this.setState({secureConnection: !this.state.secureConnection});\n }\n\n render() {\n const names = {def: \"default\", ws: \"websocket\", lp: \"long polling\"};\n const transportOptions = [];\n ['def', 'ws', 'lp'].forEach(item => {\n const id = 'transport-' + item;\n const name = names[item];\n transportOptions.push(\n \n \n {name} \n \n );\n });\n\n return (\n \n );\n }\n};\n","// ValidationView: panel for confirming credentials, like email or phone.\nimport React from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nconst messages = defineMessages({\n phone: {\n id: 'phone_dative',\n defaultMessage: 'phone',\n description: \"Dative case of 'phone', i.e. 'phone' in 'by phone'\",\n },\n email: {\n id: 'email_dative',\n defaultMessage: 'email',\n description: \"Dative case of 'email', i.e. 'email' in 'by email'\",\n }\n});\n\nclass ValidationView extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.state = {\n code: props.credCode || '',\n codeReceived: props.credCode\n };\n\n this.handleCodeChange = this.handleCodeChange.bind(this);\n this.handleKeyPress = this.handleKeyPress.bind(this);\n this.handleSubmit = this.handleSubmit.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n }\n\n static getDerivedStateFromProps(nextProps, prevState) {\n if (nextProps.credCode != prevState.codeReceived) {\n return {\n code: nextProps.credCode || '',\n codeReceived: nextProps.credCode\n };\n }\n\n return prevState;\n }\n\n componentDidMount() {\n // Submit code automatically if it's received from the parent.\n if (this.props.credCode) {\n this.props.onSubmit(this.props.credMethod, this.props.credCode, this.props.credToken);\n }\n }\n\n componentDidUpdate(prevProps, prevState) {\n // Submit code automatically if it's received from the parent.\n if (this.state.codeReceived && this.state.code && this.state.code != prevState.code) {\n this.props.onSubmit(this.props.credMethod, this.state.code, this.props.credToken);\n }\n }\n\n\n handleCodeChange(e) {\n this.setState({code: e.target.value.replace(/[^\\d]/g, '')});\n }\n\n handleKeyPress(e) {\n if (e.key === 'Enter') {\n this.handleSubmit(e);\n } else if (e.key == 'Escape') {\n this.handleCancel(e);\n }\n }\n\n handleSubmit(e) {\n e.preventDefault();\n if (this.state.code && this.state.code.trim()) {\n this.props.onSubmit(this.props.credMethod, this.state.code.trim(), this.props.credToken);\n }\n }\n\n handleCancel(e) {\n e.preventDefault();\n this.props.onCancel();\n }\n\n render() {\n const { formatMessage } = this.props.intl;\n const methods = {'email': formatMessage(messages.email), 'tel': formatMessage(messages.phone)};\n const method = methods[this.props.credMethod] || this.props.credMethod;\n return (\n \n
\n \n \n \n
\n
\n {\n (numbers_only) => \n } \n
\n
\n \n \n \n \n \n \n
\n
\n );\n }\n};\n\nexport default injectIntl(ValidationView);\n","import React, { Suspense } from 'react';\nimport { defineMessages, FormattedMessage, injectIntl } from 'react-intl';\n\nimport ErrorPanel from '../widgets/error-panel.jsx';\nimport LoadSpinner from '../widgets/load-spinner.jsx';\nimport SideNavbar from '../widgets/side-navbar.jsx';\nimport TopicCommonView from './topic-common-view.jsx';\n\nconst AccountSettingsView = React.lazy(_ => import('./account-settings-view.jsx'));\nimport ContactsView from './contacts-view.jsx';\nconst CreateAccountView = React.lazy(_ => import('./create-account-view.jsx'));\nimport AccNotificationsView from './acc-notifications-view.jsx';\nimport AccSecurityView from './acc-security-view.jsx';\nimport AccSupportView from './acc-support-view.jsx';\nimport LoginView from './login-view.jsx';\nimport NewTopicView from './new-topic-view.jsx';\nconst PasswordResetView = React.lazy(_ => import('./password-reset-view.jsx'));\nimport SettingsView from './settings-view.jsx';\nimport ValidationView from './validation-view.jsx';\n\n// Panel titles for translation.\nconst messages = defineMessages({\n login: {\n id: 'sidepanel_title_login',\n description: 'Sidepanel title for LoginView.',\n defaultMessage: 'Sign In'\n },\n register: {\n id: 'sidepanel_title_register',\n description: 'Sidepanel title for CreateAccountView.',\n defaultMessage: 'Create Account'\n },\n settings: {\n id: 'sidepanel_title_settings',\n description: 'Sidepanel title for SettingsView.',\n defaultMessage: 'Settings'\n },\n edit: {\n id: 'sidepanel_title_account_settings',\n description: 'Sidepanel title for AccountSettingsView.',\n defaultMessage: 'Account Settings'\n },\n general: {\n id: 'panel_title_general',\n description: 'Title for TopicCommon.',\n defaultMessage: 'General'\n },\n security: {\n id: 'panel_title_security',\n description: 'Title for TopicSecirity and AccSecurity.',\n defaultMessage: 'Security'\n },\n crop: {\n id: 'panel_title_crop',\n description: 'Title for AvatarCropView.',\n defaultMessage: 'Drag to Adjust'\n },\n notif: {\n id: 'sidepanel_title_acc_notifications',\n description: 'Sidepanel title for AccNotificationsView.',\n defaultMessage: 'Notifications'\n },\n support: {\n id: 'sidepanel_title_acc_support',\n description: 'Sidepanel title for AccSupportView.',\n defaultMessage: 'Support'\n },\n newtpk: {\n id: 'sidepanel_title_newtpk',\n description: 'Sidepanel title for NewTopicView.',\n defaultMessage: 'Start New Chat'\n },\n cred: {\n id: 'sidepanel_title_cred',\n description: 'Sidepanel title for ValidationView.',\n defaultMessage: 'Confirm Credentials'\n },\n reset: {\n id: 'sidepanel_title_reset',\n description: 'Sidepanel title for PasswordResetView.',\n defaultMessage: 'Reset Password'\n },\n archive: {\n id: 'sidepanel_title_archive',\n description: 'Sidepanel title for ContactsView-Archive.',\n defaultMessage: 'Archived Chats'\n },\n blocked: {\n id: 'sidepanel_title_blocked',\n description: 'Sidepanel title for ContactsView-Blocked.',\n defaultMessage: 'Blocked Chats'\n }\n});\n\nclass SidepanelView extends React.PureComponent {\n constructor(props) {\n super(props);\n\n this.handleNewTopic = this.handleNewTopic.bind(this);\n }\n\n handleNewTopic() {\n this.props.onNavigate('newtpk');\n }\n\n render() {\n const {formatMessage} = this.props.intl;\n const view = this.props.state || (this.props.myUserId ? 'contacts' : 'login');\n\n let title, avatar, badges;\n if (view == 'contacts') {\n title = this.props.title;\n avatar = this.props.avatar ? this.props.avatar : true;\n badges = this.props.trustedBadges;\n } else {\n title = formatMessage(messages[view]);\n avatar = false;\n badges = null;\n }\n\n let onCancel;\n if (['login', 'contacts'].indexOf(view) == -1) {\n onCancel = this.props.onCancel;\n }\n\n return (\n \n \n\n \n\n \n\n {view === 'login' ?\n :\n\n view === 'register' ?\n
}>\n \n :\n\n view === 'settings' ?\n :\n\n view === 'edit' ?\n }>\n \n :\n\n (view === 'general' || view === 'crop') ?\n :\n\n view === 'notif' ?\n :\n\n view === 'security' ?\n :\n\n view === 'support' ?\n :\n\n (view === 'contacts' || view == 'archive' || view == 'blocked') ?\n :\n\n view === 'newtpk' ?\n :\n\n view === 'cred' ?\n :\n\n view === 'reset' ?\n }>\n \n :\n null}\n \n );\n }\n};\n\nexport default injectIntl(SidepanelView);\n","import { KNOWN_HOSTS, DEFAULT_HOST } from '../config.js';\n\n// Detect server address from the URL\nexport function detectServerAddress() {\n let host = DEFAULT_HOST;\n if (typeof window.location == 'object') {\n if (window.location.protocol == 'file:' || window.location.hostname == 'localhost') {\n host = KNOWN_HOSTS.local;\n } else if (window.location.hostname) {\n host = window.location.hostname + (window.location.port ? ':' + window.location.port : '');\n }\n }\n return host;\n}\n\n// Detect if the page is served over HTTPS.\nexport function isSecureConnection() {\n if (typeof window.location == 'object') {\n return window.location.protocol == 'https:';\n }\n return false;\n}\n\nexport function isLocalHost() {\n if (typeof window.location == 'object') {\n return window.location.hostname == 'localhost';\n }\n return false;\n}\n","// The top-level class to hold all functionality together.\nimport React, { Suspense } from 'react';\nimport { FormattedMessage, defineMessages, injectIntl } from 'react-intl';\n\nimport { initializeApp as firebaseInitApp } from 'firebase/app';\nimport { getMessaging as firebaseGetMessaging, getToken as firebaseGetToken,\n deleteToken as firebaseDelToken, onMessage as firebaseOnMessage } from 'firebase/messaging';\n\nimport { Drafty, Tinode } from 'tinode-sdk';\n\nimport Alert from '../widgets/alert.jsx';\nimport ContextMenu from '../widgets/context-menu.jsx';\nimport ForwardDialog from '../widgets/forward-dialog.jsx';\nimport CallIncoming from '../widgets/call-incoming.jsx';\nconst PhoneCountrySelector = React.lazy(_ => import('../widgets/phone-country-selector.jsx'));\n\nimport InfoView from './info-view.jsx';\nimport MessagesView from './messages-view.jsx';\nimport SidepanelView from './sidepanel-view.jsx';\n\nimport { API_KEY, APP_NAME, DEFAULT_P2P_ACCESS_MODE, FORWARDED_PREVIEW_LENGTH, LOGGING_ENABLED,\n MEDIA_BREAKPOINT, WAKE_UP_TICK, WAKE_UP_TIMEOUT } from '../config.js';\nimport { CALL_STATE_NONE, CALL_STATE_OUTGOING_INITATED,\n CALL_STATE_INCOMING_RECEIVED, CALL_STATE_IN_PROGRESS,\n CALL_HEAD_STARTED } from '../constants.js';\nimport { PACKAGE_VERSION } from '../version.js';\nimport { base64ReEncode, makeImageUrl } from '../lib/blob-helpers.js';\nimport { detectServerAddress, isLocalHost, isSecureConnection } from '../lib/host-name.js';\nimport LocalStorageUtil from '../lib/local-storage.js';\nimport HashNavigation from '../lib/navigation.js';\nimport { secondsToTime } from '../lib/strformat.js'\nimport { updateFavicon } from '../lib/utils.js';\n\n// Sound to play on message received.\nconst POP_SOUND = new Audio('audio/msg.m4a');\n\nconst messages = defineMessages({\n reconnect_countdown: {\n id: 'reconnect_countdown',\n defaultMessage: 'Disconnected. Reconnecting in {seconds}…',\n description: 'Message shown when an app update is available.'\n },\n reconnect_now: {\n id: 'reconnect_now',\n defaultMessage: 'Try now',\n description: 'Prompt for reconnecting now'\n },\n push_init_failed: {\n id: 'push_init_failed',\n defaultMessage: 'Failed to initialize push notifications',\n description: 'Error message when push notifications have failed to initialize.'\n },\n invalid_security_token: {\n id: 'invalid_security_token',\n defaultMessage: 'Invalid security token',\n description: 'Error message when resetting password.'\n },\n no_connection: {\n id: 'no_connection',\n defaultMessage: 'No connection',\n description: 'Warning that the user is offline.'\n },\n code_doesnot_match: {\n id: 'code_doesnot_match',\n defaultMessage: 'Code does not match',\n description: 'Error message when the credential validation code is incorrect.'\n },\n menu_item_info: {\n id: 'menu_item_info',\n defaultMessage: 'Info',\n description: 'Show extended topic information'\n },\n menu_item_audio_call: {\n id: 'menu_item_audio_call',\n defaultMessage: 'Call',\n description: 'Start audio call'\n },\n menu_item_video_call: {\n id: 'menu_item_video_call',\n defaultMessage: 'Video call',\n description: 'Start video call'\n },\n cred_confirmed_successfully: {\n id: 'cred_confirmed_successfully',\n defaultMessage: 'Confirmed successfully',\n description: 'Notification message that the credential was successfully validated.'\n },\n password_reset_success: {\n id: 'password_reset_success',\n defaultMessage: 'Password reset successfully',\n description: 'Notification message that the password was successfully reset.'\n },\n select_country: {\n id: 'select_country',\n defaultMessage: 'Select country',\n description: 'Placeholder for the country selector'\n }\n});\n\nclass TinodeWeb extends React.Component {\n constructor(props) {\n super(props);\n\n this.selfRef = React.createRef();\n\n this.state = this.getBlankState();\n\n this.handleResize = this.handleResize.bind(this);\n this.handleHashRoute = this.handleHashRoute.bind(this);\n this.handleOnline = this.handleOnline.bind(this);\n this.checkForAppUpdate = this.checkForAppUpdate.bind(this);\n this.handleVisibilityEvent = this.handleVisibilityEvent.bind(this);\n this.handleError = this.handleError.bind(this);\n this.handleLoginRequest = this.handleLoginRequest.bind(this);\n this.handlePersistenceChange = this.handlePersistenceChange.bind(this);\n this.handleConnected = this.handleConnected.bind(this);\n this.handleAutoreconnectIteration = this.handleAutoreconnectIteration.bind(this);\n this.doLogin = this.doLogin.bind(this);\n this.handleLoginSuccessful = this.handleLoginSuccessful.bind(this);\n this.handleDisconnect = this.handleDisconnect.bind(this);\n this.tnMeMetaDesc = this.tnMeMetaDesc.bind(this);\n this.tnMeContactUpdate = this.tnMeContactUpdate.bind(this);\n this.tnMeSubsUpdated = this.tnMeSubsUpdated.bind(this);\n this.resetContactList = this.resetContactList.bind(this);\n this.tnInitFind = this.tnInitFind.bind(this);\n this.tnFndSubsUpdated = this.tnFndSubsUpdated.bind(this);\n this.handleSearchContacts = this.handleSearchContacts.bind(this);\n this.handleTopicSelected = this.handleTopicSelected.bind(this);\n this.handleHideMessagesView = this.handleHideMessagesView.bind(this);\n this.handleSendMessage = this.handleSendMessage.bind(this);\n this.handleNewChatInvitation = this.handleNewChatInvitation.bind(this);\n this.handleNewAccount = this.handleNewAccount.bind(this);\n this.handleNewAccountRequest = this.handleNewAccountRequest.bind(this);\n this.handleUpdatePasswordRequest = this.handleUpdatePasswordRequest.bind(this);\n this.handleUpdateAccountTagsRequest = this.handleUpdateAccountTagsRequest.bind(this);\n this.handleToggleIncognitoMode = this.handleToggleIncognitoMode.bind(this);\n this.handleSettings = this.handleSettings.bind(this);\n this.handleGlobalSettings = this.handleGlobalSettings.bind(this);\n this.handleShowArchive = this.handleShowArchive.bind(this);\n this.handleShowBlocked = this.handleShowBlocked.bind(this);\n this.handleToggleMessageSounds = this.handleToggleMessageSounds.bind(this);\n this.handleCredAdd = this.handleCredAdd.bind(this);\n this.handleCredDelete = this.handleCredDelete.bind(this);\n this.handleCredConfirm = this.handleCredConfirm.bind(this);\n this.initFCMessaging = this.initFCMessaging.bind(this);\n this.toggleFCMToken = this.toggleFCMToken.bind(this);\n this.handlePushMessage = this.handlePushMessage.bind(this);\n this.handleSidepanelCancel = this.handleSidepanelCancel.bind(this);\n this.handleStartTopicRequest = this.handleStartTopicRequest.bind(this);\n this.handleNewTopicCreated = this.handleNewTopicCreated.bind(this);\n this.handleTopicUpdateRequest = this.handleTopicUpdateRequest.bind(this);\n this.handleUnarchive = this.handleUnarchive.bind(this);\n this.handleChangePermissions = this.handleChangePermissions.bind(this);\n this.handleTagsUpdateRequest = this.handleTagsUpdateRequest.bind(this);\n this.handleLogout = this.handleLogout.bind(this);\n this.handleDeleteAccount = this.handleDeleteAccount.bind(this);\n this.handleDeleteTopicRequest = this.handleDeleteTopicRequest.bind(this);\n this.handleDeleteMessagesRequest = this.handleDeleteMessagesRequest.bind(this);\n this.handleLeaveUnsubRequest = this.handleLeaveUnsubRequest.bind(this);\n this.handleBlockTopicRequest = this.handleBlockTopicRequest.bind(this);\n this.handleReportTopic = this.handleReportTopic.bind(this);\n this.handleShowContextMenu = this.handleShowContextMenu.bind(this);\n this.defaultTopicContextMenu = this.defaultTopicContextMenu.bind(this);\n this.handleHideContextMenu = this.handleHideContextMenu.bind(this);\n this.handleShowAlert = this.handleShowAlert.bind(this);\n this.handleShowInfoView = this.handleShowInfoView.bind(this);\n this.handleMemberUpdateRequest = this.handleMemberUpdateRequest.bind(this);\n this.handleValidateCredentialsRequest = this.handleValidateCredentialsRequest.bind(this);\n this.handlePasswordResetRequest = this.handlePasswordResetRequest.bind(this);\n this.handleResetPassword = this.handleResetPassword.bind(this);\n this.handleContextMenuAction = this.handleContextMenuAction.bind(this);\n this.handleShowCountrySelector = this.handleShowCountrySelector.bind(this);\n\n this.handleShowForwardDialog = this.handleShowForwardDialog.bind(this);\n this.handleHideForwardDialog = this.handleHideForwardDialog.bind(this);\n\n this.handleStartVideoCall = this.handleStartVideoCall.bind(this);\n this.handleStartAudioCall = this.handleStartAudioCall.bind(this);\n this.handleInfoMessage = this.handleInfoMessage.bind(this);\n this.handleDataMessage = this.handleDataMessage.bind(this);\n this.handleCallClose = this.handleCallClose.bind(this);\n\n this.handleCallInvite = this.handleCallInvite.bind(this);\n this.handleCallRinging = this.handleCallRinging.bind(this);\n this.handleCallHangup = this.handleCallHangup.bind(this);\n this.handleCallSendOffer = this.handleCallSendOffer.bind(this);\n this.handleCallIceCandidate = this.handleCallIceCandidate.bind(this);\n this.handleCallSendAnswer = this.handleCallSendAnswer.bind(this);\n\n this.handleCallAccept = this.handleCallAccept.bind(this);\n\n this.sendMessageToTopic = this.sendMessageToTopic.bind(this);\n\n // FIXME: this is unused.\n this.callTimeoutTimer = null;\n }\n\n getBlankState() {\n const settings = LocalStorageUtil.getObject('settings') || {};\n const persist = !!LocalStorageUtil.getObject('keep-logged-in');\n\n return {\n connected: false,\n // Connected and subscribed to 'me'\n ready: false,\n // Try to re-login on new connection.\n autoLogin: false,\n transport: settings.transport || null,\n serverAddress: settings.serverAddress || detectServerAddress(),\n secureConnection: settings.secureConnection === undefined ?\n isSecureConnection() : settings.secureConnection,\n serverVersion: \"no connection\",\n // \"On\" is the default, so saving the \"off\" state.\n messageSounds: !settings.messageSoundsOff,\n incognitoMode: false,\n // Persistent request to enable alerts.\n desktopAlerts: persist && !!settings.desktopAlerts,\n // Enable / disable checkbox.\n desktopAlertsEnabled: (isSecureConnection() || isLocalHost()) &&\n (typeof firebaseInitApp != 'undefined') && (typeof navigator != 'undefined') &&\n (typeof FIREBASE_INIT != 'undefined'),\n firebaseToken: persist ? LocalStorageUtil.getObject('firebase-token') : null,\n\n applicationVisible: !document.hidden,\n\n errorText: '',\n errorLevel: null,\n errorAction: undefined,\n errorActionText: null,\n\n sidePanelSelected: 'login',\n sidePanelTitle: null,\n sidePanelAvatar: null,\n myTrustedBadges: [],\n loadSpinnerVisible: false,\n\n login: '',\n password: '',\n persist: persist,\n myUserId: null,\n liveConnection: navigator.onLine,\n topicSelected: '',\n topicSelectedOnline: false,\n topicSelectedAcs: null,\n newTopicParams: null,\n loginDisabled: false,\n displayMobile: (window.innerWidth <= MEDIA_BREAKPOINT),\n infoPanel: undefined,\n mobilePanel: 'sidepanel',\n\n // Video calls.\n callTopic: undefined,\n callState: CALL_STATE_NONE,\n callAudioOnly: undefined,\n // If true, call state should be transitioned to CALL_STATE_IN_PROGRESS upon\n // switching to the call topic.\n callShouldStart: false,\n\n contextMenuVisible: false,\n contextMenuBounds: null,\n contextMenuClickAt: null,\n contextMenuParams: null,\n contextMenuItems: [],\n\n forwardDialogVisible: false,\n forwardMessage: null,\n\n // Modal alert dialog.\n alertVisible: false,\n alertParams: {},\n\n // Chats as shown in the ContactsView\n chatList: [],\n // Contacts returned by a search query.\n searchResults: [],\n // Merged results of a search query and p2p chats.\n searchableContacts: [],\n // Credential validation.\n reqCredMethod: undefined,\n credMethod: undefined,\n credCode: undefined,\n credToken: undefined,\n // Topic to go to after login.\n requestedTopic: undefined\n };\n }\n\n componentDidMount() {\n window.addEventListener('resize', this.handleResize);\n this.handleOnlineOn = _ => { this.handleOnline(true); }\n window.addEventListener('online', this.handleOnlineOn);\n this.handleOnlineOff = _ => { this.handleOnline(false); }\n window.addEventListener('offline', this.handleOnlineOff);\n window.addEventListener('hashchange', this.handleHashRoute);\n\n // Process background notifications from the service worker.\n if (typeof BroadcastChannel == 'function') {\n const serviceWorkerChannel = new BroadcastChannel('tinode-sw');\n serviceWorkerChannel.addEventListener('message', this.handlePushMessage);\n } else {\n // Safari is broken by design.\n console.warn(\"Your browser does not support BroadcastChannel. Some features will not be available\");\n }\n\n // Detect if computer just woke up from sleep. Checks how much time has passed since the last tick.\n // If too much time has passed then the computer was asleep.\n this.lastWakeUpCheck = new Date().getTime();\n this.wakeUpTicker = setInterval(_ => {\n const now = new Date().getTime();\n if (now - this.lastWakeUpCheck > WAKE_UP_TIMEOUT) {\n // Trigger reconnect.\n this.handleOnlineOn();\n }\n this.lastWakeUpCheck = now;\n }, WAKE_UP_TICK);\n\n // Window/tab visible or invisible for pausing timers.\n document.addEventListener('visibilitychange', this.handleVisibilityEvent);\n\n this.setState({\n viewportWidth: document.documentElement.clientWidth,\n viewportHeight: document.documentElement.clientHeight\n });\n\n new Promise((resolve, reject) => {\n this.tinode = TinodeWeb.tnSetup(this.state.serverAddress, isSecureConnection(), this.state.transport,\n this.props.intl.locale, this.state.persist, resolve);\n this.tinode.onConnect = this.handleConnected;\n this.tinode.onDisconnect = this.handleDisconnect;\n this.tinode.onAutoreconnectIteration = this.handleAutoreconnectIteration;\n this.tinode.onInfoMessage = this.handleInfoMessage;\n this.tinode.onDataMessage = this.handleDataMessage;\n }).then(_ => {\n // Initialize desktop alerts.\n if (this.state.desktopAlertsEnabled) {\n this.initFCMessaging().catch(_ => {\n // do nothing: handled earlier.\n // catch needed to pervent unnecessary logging of error.\n });\n }\n\n // Read contacts from cache.\n this.resetContactList();\n\n const token = this.state.persist ? LocalStorageUtil.getObject('auth-token') : undefined;\n if (token) {\n this.setState({autoLogin: true});\n\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(err => {\n // Socket error\n this.handleError(err.message, 'err');\n });\n }\n\n // Parse the hash navigation params.\n const parsedNav = HashNavigation.parseUrlHash(window.location.hash);\n // Maybe navigate to home screen.\n if (!['cred', 'reset', 'register'].includes(parsedNav.path[0])) {\n // Save possible topic name.\n this.setState({requestedTopic: parsedNav.path[1]});\n const path = parsedNav.params && parsedNav.params.cred_done ?\n HashNavigation.addUrlParam('', 'cred_done', parsedNav.params.cred_done):\n '';\n HashNavigation.navigateTo(path);\n } else {\n this.handleHashRoute();\n }\n });\n }\n\n componentWillUnmount() {\n window.removeEventListener('resize', this.handleResize);\n window.removeEventListener('hashchange', this.handleHashRoute);\n window.removeEventListener('online', this.handleOnlineOn);\n window.removeEventListener('offline', this.handleOnlineOff);\n document.removeEventListener('visibilitychange', this.handleVisibilityEvent);\n\n clearInterval(this.wakeUpTicker);\n }\n\n // Setup transport (usually websocket) and server address. This will terminate connection with the server.\n static tnSetup(serverAddress, secureConnection, transport, locale, persistentCache, onSetupCompleted) {\n const tinode = new Tinode({appName: APP_NAME, host: serverAddress, apiKey: API_KEY, transport: transport,\n secure: secureConnection, persist: persistentCache}, onSetupCompleted);\n tinode.setHumanLanguage(locale);\n tinode.enableLogging(LOGGING_ENABLED, true);\n return tinode;\n }\n\n // Tinode received a push notification from the server.\n handlePushMessage(payload) {\n this.tinode.oobNotification(payload.data || {});\n }\n\n initFCMessaging() {\n const {formatMessage, locale} = this.props.intl;\n const onError = (msg, err) => {\n console.error(msg, err);\n this.handleError(formatMessage(messages.push_init_failed), 'err');\n this.setState({firebaseToken: null});\n LocalStorageUtil.updateObject('settings', {desktopAlerts: false});\n }\n\n try {\n this.fcm = firebaseGetMessaging(firebaseInitApp(FIREBASE_INIT, APP_NAME));\n return navigator.serviceWorker.getRegistration('/service-worker.js').then(reg => {\n return reg || navigator.serviceWorker.register('/service-worker.js').then(reg => {\n this.checkForAppUpdate(reg);\n return reg;\n });\n }).then(reg => {\n // Pass locale and version config to the service worker.\n (reg.active || reg.installing).postMessage(JSON.stringify({locale: locale, version: PACKAGE_VERSION}));\n // Request token.\n return TinodeWeb.requestFCMToken(this.fcm, reg);\n }).then(token => {\n const persist = LocalStorageUtil.getObject('keep-logged-in');\n if (token != this.state.firebaseToken) {\n this.tinode.setDeviceToken(token);\n if (persist) {\n LocalStorageUtil.setObject('firebase-token', token);\n }\n }\n this.setState({firebaseToken: token, desktopAlerts: true});\n if (persist) {\n LocalStorageUtil.updateObject('settings', {desktopAlerts: true});\n }\n\n // Handhe FCM pushes\n // (a) for channels always,\n // (b) pushes when the app is in foreground but has no focus.\n firebaseOnMessage(this.fcm, payload => { this.handlePushMessage(payload); });\n }).catch(err => {\n // SW registration or FCM has failed :(\n onError(err);\n throw err;\n });\n } catch (err) {\n onError(err);\n return Promise.reject(err);\n }\n }\n\n // Google's FCM API is idiotic.\n static requestFCMToken(fcm, sw) {\n return firebaseGetToken(fcm, {\n serviceWorkerRegistration: sw,\n vapidKey: FIREBASE_INIT.messagingVapidKey\n }).then(token => {\n if (token) {\n return token;\n } else if (typeof Notification != 'undefined') {\n // Try to request permissions.\n return Notification.requestPermission().then(permission => {\n if (permission === 'granted') {\n return firebaseGetToken(fcm, {\n serviceWorkerRegistration: reg,\n vapidKey: FIREBASE_INIT.messagingVapidKey\n }).then(token => {\n if (token) {\n return token;\n } else {\n throw new Error(\"Failed to initialize notifications\");\n }\n });\n } else {\n throw new Error(\"No permission to send notifications: \" + permission);\n }\n });\n }\n throw new Error(\"Notifications are not supported\");\n });\n }\n\n handleResize() {\n const mobile = document.documentElement.clientWidth <= MEDIA_BREAKPOINT;\n this.setState({\n viewportWidth: document.documentElement.clientWidth,\n viewportHeight: document.documentElement.clientHeight\n });\n if (this.state.displayMobile != mobile) {\n this.setState({displayMobile: mobile});\n }\n }\n\n // Check if a newer version of TinodeWeb app is available at the server.\n checkForAppUpdate(reg) {\n reg.onupdatefound = _ => {\n const installingWorker = reg.installing;\n installingWorker.onstatechange = _ => {\n if (installingWorker.state == 'installed' && navigator.serviceWorker.controller) {\n const msg = <>\n \n \n .>;\n this.handleError(msg, 'info');\n }\n }\n }\n }\n\n // Handle for hash navigation (hashchange) event: update state.\n handleHashRoute() {\n const hash = HashNavigation.parseUrlHash(window.location.hash);\n // Start with panel parameters.\n const newState = {\n infoPanel: hash.params.info,\n newTopicTabSelected: hash.params.tab\n };\n\n if (hash.path && hash.path.length > 0) {\n // Left-side panel selector.\n if (['register','settings','edit','notif','security','support','general','crop',\n 'cred','reset','newtpk','archive','blocked','contacts',''].includes(hash.path[0])) {\n newState.sidePanelSelected = hash.path[0];\n } else {\n console.warn(\"Unknown sidepanel view\", hash.path[0]);\n }\n\n // Topic for MessagesView selector.\n let topicName = hash.path[1] || null;\n if (topicName != this.state.topicSelected) {\n if (!Tinode.topicType(topicName)) {\n // Clear invalid topic name and hide messages view on mobile.\n topicName = null;\n newState.mobilePanel = 'sidepanel';\n } else {\n // Topic valid: show messages view on mobile.\n newState.mobilePanel = 'topic-view';\n }\n Object.assign(newState, {\n topicSelected: topicName,\n topicSelectedAcs: this.tinode.getTopicAccessMode(topicName)\n });\n }\n } else {\n // Empty hashpath\n Object.assign(newState, {sidePanelSelected: '', topicSelected: null});\n }\n\n // Save credential validation parameters, if available.\n if (hash.params.method) {\n newState.credMethod = hash.params.method;\n }\n if (hash.params.code) {\n newState.credCode = hash.params.code;\n }\n if (hash.params.token) {\n newState.credToken = hash.params.token;\n }\n\n // Show a message if validation was successful.\n if (hash.params.cred_done) {\n Object.assign(newState,\n TinodeWeb.stateForError(this.props.intl.formatMessage(messages.cred_confirmed_successfully), 'info'));\n }\n\n this.setState(newState);\n }\n\n handleOnline(online) {\n if (online) {\n this.handleError();\n clearInterval(this.reconnectCountdown);\n this.tinode.reconnect();\n } else {\n this.handleError(this.props.intl.formatMessage(messages.no_connection), 'warn');\n }\n this.setState({liveConnection: online});\n }\n\n handleVisibilityEvent() {\n this.setState({applicationVisible: !document.hidden});\n }\n\n static stateForError(err, level, action, actionText) {\n return {\n errorText: err,\n errorLevel: level,\n errorAction: action,\n errorActionText: actionText,\n callShouldStart: false,\n };\n }\n\n handleError(err, level, action, actionText) {\n this.setState(TinodeWeb.stateForError(err, level, action, actionText));\n }\n\n // User clicked Login button in the side panel.\n handleLoginRequest(login, password) {\n this.setState({\n loginDisabled: true,\n login: login,\n password: password,\n loadSpinnerVisible: true,\n autoLogin: true\n });\n this.handleError('', null);\n\n if (this.tinode.isConnected()) {\n this.doLogin(login, password, null, {meth: this.state.credMethod, resp: this.state.credCode});\n } else {\n this.tinode.connect().catch(err => {\n // Socket error\n this.setState({loginDisabled: false, autoLogin: false, loadSpinnerVisible: false});\n this.handleError(err.message, 'err');\n });\n }\n\n if (this.state.desktopAlertsEnabled && !this.state.firebaseToken) {\n // Firefox and Safari: \"The Notification permission may only be requested from inside a\n // short running user-generated event handler\".\n this.initFCMessaging();\n }\n }\n\n // Enable or disable saving the password and IndexedDB.\n handlePersistenceChange(persist) {\n if (persist) {\n this.tinode.initStorage().then(_ => {\n LocalStorageUtil.setObject('keep-logged-in', true);\n this.setState({persist: true});\n });\n } else {\n this.tinode.clearStorage().then(_ => {\n LocalStorageUtil.setObject('keep-logged-in', false);\n this.setState({persist: false});\n });\n }\n }\n\n // Connection succeeded.\n handleConnected() {\n // Just to be sure.\n clearInterval(this.reconnectCountdown);\n this.handleError();\n\n const params = this.tinode.getServerInfo();\n this.setState({\n serverVersion: params.ver + ' ' + (params.build ? params.build : 'none'),\n // \"reqCred\":{\"auth\":[\"email\"]}\n reqCredMethod: ((params.reqCred || {}).auth || [])[0] || 'email'\n });\n\n if (this.state.autoLogin) {\n this.doLogin(this.state.login, this.state.password, null,\n {meth: this.state.credMethod, resp: this.state.credCode});\n }\n }\n\n // Called for each auto-reconnect iteration.\n handleAutoreconnectIteration(sec, prom) {\n clearInterval(this.reconnectCountdown);\n\n if (sec < 0) {\n // Clear error\n this.handleError();\n return;\n }\n\n if (prom) {\n // Reconnecting now\n prom.then(_ => {\n // Reconnected: clear error\n this.handleError();\n }).catch(err => {\n this.handleError(err.message, 'err');\n });\n return;\n }\n\n const {formatMessage} = this.props.intl;\n let count = sec / 1000;\n count = count | count;\n this.reconnectCountdown = setInterval(_ => {\n if (count < -10) {\n // Count could go to negative if computer woke up from sleep.\n clearInterval(this.reconnectCountdown);\n this.tinode.reconnect();\n return;\n }\n\n const fmtTime = (count > 99) ? secondsToTime(count) : count;\n this.handleError(\n formatMessage(messages.reconnect_countdown, {seconds: fmtTime}),\n 'warn',\n _ => {\n clearInterval(this.reconnectCountdown);\n this.tinode.reconnect();\n },\n formatMessage(messages.reconnect_now)\n );\n count -= 1;\n }, 1000);\n }\n\n // Connection lost\n handleDisconnect(err) {\n this.setState({\n connected: false,\n ready: false,\n topicSelectedOnline: false,\n errorText: err && err.message ? err.message : \"Disconnected\",\n errorLevel: err && err.message ? 'err' : 'warn',\n loginDisabled: false,\n contextMenuVisible: false,\n forwardDialogVisible: false,\n serverVersion: \"no connection\"\n });\n }\n\n doLogin(login, password, tmpToken, cred) {\n if (this.tinode.isAuthenticated()) {\n // Already logged in. Go to default screen.\n HashNavigation.navigateTo('');\n return;\n }\n\n let token = tmpToken || (this.tinode.getAuthToken() || {}).token;\n if (!(login && password) && !token) {\n // No login credentials provided.\n // Make sure we are on the login page.\n HashNavigation.navigateTo('');\n this.setState({loginDisabled: false});\n return;\n }\n\n // Sanitize and package credentail.\n cred = Tinode.credential(cred);\n // May be disconnected.\n let connectionPromise = this.tinode.isConnected() ? Promise.resolve() : this.tinode.connect();\n // Try to login with login/password. If they are not available, try token; if no token, ask for login/password.\n let loginPromise;\n if (login && password) {\n token = null;\n this.setState({password: null});\n loginPromise = connectionPromise.then(_ => this.tinode.loginBasic(login, password, cred));\n } else {\n loginPromise = connectionPromise.then(_ => this.tinode.loginToken(token, cred));\n }\n\n loginPromise.then(ctrl => {\n if (ctrl.code >= 300 && ctrl.text === 'validate credentials') {\n this.setState({loadSpinnerVisible: false});\n if (cred) {\n this.handleError(this.props.intl.formatMessage(messages.code_doesnot_match), 'warn');\n }\n TinodeWeb.navigateToCredentialsView(ctrl.params);\n } else {\n this.handleLoginSuccessful();\n }\n }).catch(err => {\n const autoLogin = err.code >= 500;\n // Connection or login failed, report error.\n this.setState({\n loginDisabled: false,\n credMethod: undefined,\n credCode: undefined,\n loadSpinnerVisible: false,\n autoLogin: autoLogin\n });\n this.handleError(err.message, 'err');\n console.warn(\"Login failed\", err);\n if (!autoLogin) {\n if (token) {\n this.handleLogout();\n }\n HashNavigation.navigateTo('');\n }\n });\n }\n\n static navigateToCredentialsView(params) {\n const parsed = HashNavigation.parseUrlHash(window.location.hash);\n parsed.path[0] = 'cred';\n parsed.params['method'] = params.cred[0];\n parsed.params['token'] = params.token;\n parsed.params['code'] = params.code;\n HashNavigation.navigateTo(HashNavigation.composeUrlHash(parsed.path, parsed.params));\n }\n\n handleLoginSuccessful() {\n this.handleError();\n\n // Refresh authentication token.\n if (LocalStorageUtil.getObject('keep-logged-in')) {\n LocalStorageUtil.setObject('auth-token', this.tinode.getAuthToken());\n }\n\n const goToTopic = this.state.requestedTopic;\n // Logged in fine, subscribe to 'me' attaching callbacks from the contacts view.\n const 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 credToken: undefined,\n myUserId: this.tinode.getCurrentUserID(),\n autoLogin: true,\n requestedTopic: undefined,\n });\n // Subscribe, fetch topic desc, the list of subscriptions. Messages are not fetched.\n me.subscribe(\n me.startMetaQuery().\n withLaterSub().\n withDesc().\n withTags().\n withCred().\n build()\n ).catch(err => {\n this.tinode.disconnect();\n localStorage.removeItem('auth-token');\n this.handleError(err.message, 'err');\n HashNavigation.navigateTo('');\n }).finally(_ => {\n this.setState({loadSpinnerVisible: false});\n });\n let urlHash = HashNavigation.setUrlSidePanel(window.location.hash, 'contacts');\n if (goToTopic) {\n urlHash = HashNavigation.setUrlTopic(urlHash, goToTopic);\n }\n HashNavigation.navigateTo(urlHash);\n }\n\n tnMeMetaDesc(desc) {\n if (desc) {\n if (desc.public) {\n this.setState({\n sidePanelTitle: desc.public.fn,\n sidePanelAvatar: makeImageUrl(desc.public.photo)\n });\n }\n if (desc.trusted) {\n const badges = [];\n for (const [key, val] of Object.entries(desc.trusted)) {\n if (val) {\n badges.push(key);\n }\n }\n this.setState({\n myTrustedBadges: badges,\n });\n }\n if (desc.acs) {\n this.setState({\n incognitoMode: !desc.acs.isPresencer()\n });\n }\n }\n }\n\n // Reactions to updates to the contact list.\n tnMeContactUpdate(what, cont) {\n if (what == 'on' || what == 'off') {\n this.resetContactList();\n if (this.state.topicSelected == cont.topic) {\n this.setState({topicSelectedOnline: (what == 'on')});\n }\n } else if (what == 'read') {\n this.resetContactList();\n } else if (what == 'msg' && cont) {\n // Check if the topic is archived. If so, don't play a sound.\n const topic = this.tinode.getTopic(cont.topic);\n const archived = topic && topic.isArchived();\n\n // New message received. Maybe the message is from the current user, then unread is 0.\n if (cont.unread > 0 && this.state.messageSounds && !archived) {\n // Skip update if the topic is currently open, otherwise the badge will annoyingly flash.\n if (document.hidden || this.state.topicSelected != cont.topic) {\n POP_SOUND.play().catch(_ => {\n // play() throws if the user did not click the app first: https://goo.gl/xX8pDD.\n });\n }\n }\n // Reorder contact list to use possibly updated 'touched'.\n this.resetContactList();\n } else if (what == 'recv') {\n // 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 }\n // Redraw without the deleted topic.\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({topicSelectedAcs: cont.acs});\n }\n } else if (what == 'del') {\n // TODO: messages deleted (hard or soft) -- update pill counter.\n } else if (what == 'upd' || what == 'call') {\n // upd, call - handled by the SDK. Explicitly ignoring here.\n } else {\n // TODO(gene): handle other types of notifications:\n // * ua -- user agent changes (maybe display a pictogram for mobile/desktop).\n console.info(\"Unsupported (yet) presence update:\", what, \"in\", (cont || {}).topic);\n }\n }\n\n tnMeSubsUpdated(unused) {\n this.resetContactList();\n }\n\n // Merge search results and contact list to create a single flat\n // list of known contacts for GroupManager to use.\n static prepareSearchableContacts(chatList, foundContacts) {\n const merged = {};\n\n // For chatList topics merge only p2p topics and convert them to the\n // same format as foundContacts.\n for (const c of chatList) {\n if (Tinode.isP2PTopicName(c.topic)) {\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 }\n\n // Add all foundCountacts if they have not been added already.\n for (const c of foundContacts) {\n if (!merged[c.user]) {\n merged[c.user] = c;\n }\n }\n\n return Object.values(merged);\n }\n\n resetContactList() {\n const newState = {\n chatList: []\n };\n\n if (!this.state.ready) {\n newState.ready = true;\n }\n\n this.tinode.getMeTopic().contacts(c => {\n if (!c.topic && !c.user) {\n // Contacts expect c.topic to be set.\n c.topic = c.name;\n }\n\n newState.chatList.push(c);\n if (this.state.topicSelected == c.topic) {\n newState.topicSelectedOnline = c.online;\n newState.topicSelectedAcs = c.acs;\n }\n });\n\n const past = new Date(0);\n newState.chatList.sort((a, b) => {\n return (a.touched || past).getTime() - (b.touched || past).getTime();\n });\n\n // Merge search results and chat list.\n newState.searchableContacts = TinodeWeb.prepareSearchableContacts(newState.chatList, this.state.searchResults);\n this.setState(newState);\n }\n\n /* Fnd topic: find contacts by tokens */\n tnInitFind() {\n const fnd = this.tinode.getFndTopic();\n fnd.onSubsUpdated = this.tnFndSubsUpdated;\n if (fnd.isSubscribed()) {\n this.tnFndSubsUpdated();\n } else {\n fnd.subscribe(fnd.startMetaQuery().withSub().build()).catch(err => {\n this.handleError(err.message, 'err');\n });\n }\n }\n\n tnFndSubsUpdated() {\n const foundContacts = [];\n // Don't attempt to create P2P topics which already exist. Server will reject the duplicates.\n this.tinode.getFndTopic().contacts((s) => {\n foundContacts.push(s);\n });\n this.setState({\n searchResults: foundContacts,\n searchableContacts: TinodeWeb.prepareSearchableContacts(this.state.chatList, foundContacts)\n });\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 handleSearchContacts(query) {\n const fnd = this.tinode.getFndTopic();\n fnd.setMeta({desc: {public: query}})\n .then(_ => fnd.getMeta(fnd.startMetaQuery().withSub().build()))\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n // User clicked on a topic in the side panel or deleted a topic.\n handleTopicSelected(topicName) {\n // Clear newTopicParams after use.\n if (this.state.newTopicParams && this.state.newTopicParams._topicName != topicName) {\n this.setState({\n newTopicParams: null\n });\n }\n\n if (topicName) {\n this.setState({\n errorText: '',\n errorLevel: null,\n mobilePanel: 'topic-view',\n infoPanel: undefined\n });\n // Different topic selected.\n if (this.state.topicSelected != topicName) {\n this.setState({\n topicSelectedOnline: this.tinode.isTopicOnline(topicName),\n topicSelectedAcs: this.tinode.getTopicAccessMode(topicName),\n forwardMessage: null\n });\n HashNavigation.navigateTo(HashNavigation.setUrlTopic('', topicName));\n }\n } else {\n // Currently selected contact deleted\n this.setState({\n topicSelected: null,\n errorText: '',\n errorLevel: null,\n mobilePanel: 'sidepanel',\n topicSelectedOnline: false,\n topicSelectedAcs: null,\n infoPanel: undefined,\n forwardMessage: null\n });\n\n HashNavigation.navigateTo(HashNavigation.setUrlTopic('', null));\n }\n }\n\n // In mobile view user requested to show sidepanel\n handleHideMessagesView() {\n this.setState({\n mobilePanel: 'sidepanel'\n });\n HashNavigation.navigateTo(HashNavigation.setUrlTopic(window.location.hash, null));\n }\n\n // User is sending a message, either plain text or a drafty object, possibly\n // with attachments.\n // - msg - Drafty message with content\n // - promise - Promise to be resolved when the upload is completed\n // - uploadCompletionPromise - for tracking progress\n // - head - head dictionary to be attached to the message\n handleSendMessage(msg, uploadCompletionPromise, uploader, head) {\n const topic = this.tinode.getTopic(this.state.topicSelected);\n /* TODO: check if return is required */\n return this.sendMessageToTopic(topic, msg, uploadCompletionPromise, uploader, head);\n }\n\n sendMessageToTopic(topic, msg, uploadCompletionPromise, uploader, head) {\n msg = topic.createMessage(msg, false);\n // The uploader is used to show progress.\n msg._uploader = uploader;\n\n if (head) {\n msg.head = Object.assign(msg.head || {}, head);\n }\n\n const completion = [];\n if (uploadCompletionPromise) {\n completion.push(uploadCompletionPromise);\n }\n\n if (!topic.isSubscribed()) {\n // Topic is not subscribed yet. Subscribe.\n const subscribePromise =\n topic.subscribe()\n .then(_ => {\n // If there are unsent messages (except video call messages),\n // try sending them now. Unsent video call messages will be dropped.\n let calls = [];\n topic.queuedMessages(pub => {\n if (pub._sending || pub.seq == msg.seq) {\n return;\n }\n if (pub.head && pub.head.webrtc) {\n // Filter out unsent video call messages.\n calls.push(pub.seq);\n return;\n }\n if (topic.isSubscribed()) {\n topic.publishMessage(pub);\n }\n });\n if (calls.length > 0) {\n topic.delMessagesList(calls, true);\n }\n });\n completion.push(subscribePromise);\n }\n\n // TODO: check if return is required.\n return topic.publishDraft(msg, Promise.all(completion))\n .then(ctrl => {\n if (topic.isArchived()) {\n topic.archive(false);\n }\n return ctrl;\n })\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n handleNewChatInvitation(topicName, action) {\n const topic = this.tinode.getTopic(topicName);\n let response = null;\n switch (action) {\n case 'accept':\n // Accept given permissions.\n const mode = topic.getAccessMode().getGiven();\n response = topic.setMeta({sub: {mode: mode}});\n if (topic.isP2PType()) {\n // For P2P topics change 'given' permission of the peer too.\n // In p2p topics the other user has the same name as the topic.\n response = response.then(_ => topic.setMeta({sub: {user: topicName, mode: mode}}));\n }\n break;\n case 'delete':\n // Ignore invitation by deleting it.\n response = topic.delTopic(true);\n break;\n case 'block':\n // Ban the topic making futher invites impossible.\n // Just self-ban.\n const am = topic.getAccessMode().updateWant('-JP').getWant();\n response = topic.setMeta({sub: {mode: am}}).then(_ => this.handleTopicSelected(null));\n break;\n default:\n console.warn(\"Unknown invitation action\", '\"' + action + '\"\"');\n }\n\n if (response != null) {\n response.catch(err => this.handleError(err.message, 'err'));\n }\n }\n\n // User chose a Sign Up menu item.\n handleNewAccount() {\n this.handleError();\n\n HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, 'register'));\n }\n\n // Actual registration of a new account.\n handleNewAccountRequest(login_, password_, public_, cred_, tags_) {\n // Clear old error, if any.\n this.handleError();\n\n this.tinode.connect(this.state.serverAddress)\n .then(_ => {\n let attachments;\n if (public_ && public_.photo && public_.photo.ref) {\n attachments = [public_.photo.ref];\n }\n return this.tinode.createAccountBasic(login_, password_,\n {public: public_, tags: tags_, cred: Tinode.credential(cred_), attachments: attachments});\n }).then(ctrl => {\n if (ctrl.code >= 300 && ctrl.text == 'validate credentials') {\n TinodeWeb.navigateToCredentialsView(ctrl.params);\n } else {\n this.handleLoginSuccessful(this);\n }\n }).catch(err => {\n this.handleError(err.message, 'err');\n });\n }\n\n handleToggleIncognitoMode(on) {\n // Make state undefined.\n this.setState({incognitoMode: null});\n\n const me = this.tinode.getMeTopic();\n const am = me.getAccessMode().updateWant(on ? '-P' : '+P').getWant();\n me.setMeta({sub: {mode: am}}).catch(err => {\n // Request failed, keep existing state.\n this.setState({incognitoMode: !on});\n this.handleError(err.message, 'err');\n });\n }\n\n handleUpdateAccountTagsRequest(_, tags) {\n this.tinode.getMeTopic().setMeta({tags: tags})\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n // User chose Settings menu item.\n handleSettings() {\n this.handleError();\n\n HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash,\n this.state.myUserId ? 'edit' : 'settings'));\n }\n\n // User updated global parameters.\n handleGlobalSettings(settings) {\n const serverAddress = settings.serverAddress || this.state.serverAddress;\n const transport = settings.transport || this.state.transport;\n const secureConnection = settings.secureConnection === undefined ?\n this.state.secureConnection : settings.secureConnection;\n if (this.tinode) {\n this.tinode.clearStorage();\n this.tinode.onDisconnect = undefined;\n this.tinode.disconnect();\n }\n this.tinode = TinodeWeb.tnSetup(serverAddress, secureConnection, transport,\n this.props.intl.locale, LocalStorageUtil.getObject('keep-logged-in'));\n this.tinode.onConnect = this.handleConnected;\n this.tinode.onDisconnect = this.handleDisconnect;\n this.tinode.onAutoreconnectIteration = this.handleAutoreconnectIteration;\n this.tinode.onInfoMessage = this.handleInfoMessage;\n this.tinode.onDataMessage = this.handleDataMessage;\n\n this.setState({\n serverAddress: serverAddress,\n transport: transport,\n secureConnection: secureConnection,\n });\n LocalStorageUtil.setObject('settings', {\n serverAddress: serverAddress,\n transport: transport,\n secureConnection: secureConnection,\n });\n\n HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, ''));\n }\n\n // User chose 'Archived chats'.\n handleShowArchive() {\n HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash,\n this.state.myUserId ? 'archive' : ''));\n }\n\n // User viewes 'Blocked chats'.\n handleShowBlocked() {\n HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash,\n this.state.myUserId ? 'blocked' : ''));\n }\n\n toggleFCMToken(enabled) {\n if (enabled) {\n this.setState({desktopAlerts: null});\n if (!this.state.firebaseToken) {\n this.initFCMessaging();\n } else {\n this.setState({desktopAlerts: true});\n if (LocalStorageUtil.getObject('keep-logged-in')) {\n LocalStorageUtil.updateObject('settings', {desktopAlerts: true});\n }\n }\n } else if (this.state.firebaseToken && this.fcm) {\n firebaseDelToken(this.fcm).catch(err => {\n console.error(\"Unable to delete token.\", err);\n }).finally(_ => {\n LocalStorageUtil.updateObject('settings', {desktopAlerts: false});\n localStorage.removeItem('firebase-token');\n this.setState({desktopAlerts: false, firebaseToken: null});\n // Inform the server that the token was deleted.\n this.tinode.setDeviceToken(null);\n });\n } else {\n this.setState({desktopAlerts: false, firebaseToken: null});\n LocalStorageUtil.updateObject('settings', {desktopAlerts: false});\n }\n }\n\n handleToggleMessageSounds(enabled) {\n this.setState({messageSounds: enabled});\n LocalStorageUtil.updateObject('settings', {\n messageSoundsOff: !enabled\n });\n }\n\n handleCredAdd(method, value) {\n const me = this.tinode.getMeTopic();\n me.setMeta({cred: {meth: method, val: value}})\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n handleCredDelete(method, value) {\n const me = this.tinode.getMeTopic();\n me.delCredential(method, value)\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n handleCredConfirm(method, response) {\n TinodeWeb.navigateToCredentialsView({cred: [method], code: response});\n }\n\n // User clicked Cancel button in Setting or Sign Up panel.\n handleSidepanelCancel() {\n const parsed = HashNavigation.parseUrlHash(window.location.hash);\n let path = '';\n if (['security','support','general','notif'].includes(parsed.path[0])) {\n path = 'edit';\n } else if ('crop' == parsed.path[0]) {\n path = 'general';\n } else if ('blocked' == parsed.path[0]) {\n path = 'security';\n } else if (this.state.myUserId) {\n path = 'contacts';\n }\n parsed.path[0] = path;\n if (parsed.params) {\n delete parsed.params.code;\n delete parsed.params.method;\n delete parsed.params.tab;\n delete parsed.params.scheme;\n delete parsed.params.token;\n }\n HashNavigation.navigateTo(HashNavigation.composeUrlHash(parsed.path, parsed.params));\n this.setState({errorText: '', errorLevel: null});\n }\n\n // Sidepanel navigator. No need to bind to 'this'.\n basicNavigator(hash) {\n HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, hash));\n }\n\n // Topic info navigator. No need to bind to 'this'.\n infoNavigator(hash) {\n HashNavigation.navigateTo(HashNavigation.setUrlInfoPanel(window.location.hash, hash));\n }\n\n // Request to start a topic, new or selected from search results, or \"by ID\".\n handleStartTopicRequest(topicName, newTopicParams, isChannel) {\n // Check if topic is indeed new. If not, launch it.\n if (topicName && this.tinode.isTopicCached(topicName)) {\n this.handleTopicSelected(topicName);\n return;\n }\n\n const params = {};\n if (Tinode.isP2PTopicName(topicName)) {\n // Because we are initiating the subscription, set 'want' to all permissions.\n params.sub = {mode: DEFAULT_P2P_ACCESS_MODE};\n // Give the other user all permissions too.\n params.desc = {defacs: {auth: DEFAULT_P2P_ACCESS_MODE}};\n } else {\n topicName = topicName || this.tinode.newGroupTopicName(isChannel);\n if (newTopicParams) {\n params.desc = {public: newTopicParams.public, private: {comment: newTopicParams.private}};\n params.tags = newTopicParams.tags;\n }\n }\n params._topicName = topicName;\n this.setState({newTopicParams: params}, _ => {this.handleTopicSelected(topicName)});\n }\n\n // New topic was created, here is the new topic name.\n handleNewTopicCreated(oldName, newName) {\n let nextState = {};\n if (this.state.callShouldStart) {\n nextState = {callState: CALL_STATE_IN_PROGRESS, callShouldStart: false};\n }\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 nextState.topicSelected = newName;\n }\n this.setState(nextState, _ => {\n HashNavigation.navigateTo(HashNavigation.setUrlTopic('', newName));\n });\n }\n\n handleTopicUpdateRequest(topicName, pub, priv, defacs) {\n this.handleError();\n\n const topic = this.tinode.getTopic(topicName);\n if (topic) {\n const params = {};\n let attachments;\n if (pub) {\n if (pub.photo) {\n if (pub.photo.ref && pub.photo.ref != Tinode.DEL_CHAR) {\n attachments = [pub.photo.ref];\n } else if (!pub.photo.data || pub.photo.data == Tinode.DEL_CHAR) {\n pub.photo = Tinode.DEL_CHAR;\n }\n }\n params.public = pub;\n }\n\n if (typeof priv == 'string') {\n params.private = (priv === Tinode.DEL_CHAR) ?\n Tinode.DEL_CHAR : {comment: priv};\n }\n if (defacs) {\n params.defacs = defacs;\n }\n topic.setMeta({desc: params, attachments: attachments})\n .catch(err => this.handleError(err.message, 'err'));\n }\n }\n\n handleUnarchive(topicName) {\n const topic = this.tinode.getTopic(topicName);\n if (topic) {\n topic.archive(false).catch(err => this.handleError(err.message, 'err'));\n }\n }\n\n handleUpdatePasswordRequest(password) {\n this.handleError();\n\n if (password) {\n this.tinode.updateAccountBasic(null, this.tinode.getCurrentLogin(), password)\n .catch(err => this.handleError(err.message, 'err'));\n }\n }\n\n handleChangePermissions(topicName, mode, uid) {\n const topic = this.tinode.getTopic(topicName);\n if (topic) {\n const am = topic.getAccessMode();\n if (uid) {\n am.updateGiven(mode);\n mode = am.getGiven();\n } else {\n am.updateWant(mode);\n mode = am.getWant();\n }\n topic.setMeta({sub: {user: uid, mode: mode}})\n .catch(err => this.handleError(err.message, 'err'));\n }\n }\n\n handleTagsUpdateRequest(topicName, tags) {\n const topic = this.tinode.getTopic(topicName);\n if (topic) {\n topic.setMeta({tags: tags})\n .catch(err => this.handleError(err.message, 'err'));\n }\n }\n\n handleLogout() {\n updateFavicon(0);\n\n // Remove stored data.\n localStorage.removeItem('auth-token');\n localStorage.removeItem('firebase-token');\n localStorage.removeItem('settings');\n if (this.state.firebaseToken) {\n firebaseDelToken(this.fcm);\n }\n\n clearInterval(this.reconnectCountdown);\n\n let cleared;\n if (this.tinode) {\n cleared = this.tinode.clearStorage();\n this.tinode.onDisconnect = undefined;\n this.tinode.disconnect();\n } else {\n cleared = Promose.resolve();\n }\n this.setState(this.getBlankState());\n\n cleared.then(_ => {\n this.tinode = TinodeWeb.tnSetup(this.state.serverAddress, isSecureConnection(),\n this.state.transport, this.props.intl.locale, LocalStorageUtil.getObject('keep-logged-in'), _ => {\n this.tinode.onConnect = this.handleConnected;\n this.tinode.onDisconnect = this.handleDisconnect;\n this.tinode.onAutoreconnectIteration = this.handleAutoreconnectIteration;\n this.tinode.onInfoMessage = this.handleInfoMessage;\n this.tinode.onDataMessage = this.handleDataMessage;\n HashNavigation.navigateTo('');\n })\n });\n }\n\n handleDeleteAccount() {\n this.tinode.delCurrentUser(true).then(_ => {\n this.handleLogout();\n });\n }\n\n handleDeleteTopicRequest(topicName) {\n const topic = this.tinode.getTopic(topicName);\n if (!topic) {\n return;\n }\n\n // Request to hard-delete topic.\n topic.delTopic(true).then(_ => {\n // Hide MessagesView and InfoView panels.\n HashNavigation.navigateTo(HashNavigation.setUrlTopic(window.location.hash, ''));\n }).catch(err => {\n this.handleError(err.message, 'err');\n });\n }\n\n handleDeleteMessagesRequest(topicName) {\n const topic = this.tinode.getTopic(topicName);\n if (!topic) {\n return;\n }\n\n // Request hard-delete all messages.\n topic.delMessagesAll(true)\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n handleLeaveUnsubRequest(topicName) {\n const topic = this.tinode.getTopic(topicName);\n if (!topic) {\n return;\n }\n\n topic.leave(true).then(_ => {\n // Hide MessagesView and InfoView panels.\n HashNavigation.navigateTo(HashNavigation.setUrlTopic(window.location.hash, ''));\n }).catch(err => {\n this.handleError(err.message, 'err');\n });\n }\n\n handleBlockTopicRequest(topicName) {\n const topic = this.tinode.getTopic(topicName);\n if (!topic) {\n return;\n }\n\n topic.updateMode(null, '-JP')\n .then(_ => {\n // Hide MessagesView and InfoView panels.\n HashNavigation.navigateTo(HashNavigation.setUrlTopic(window.location.hash, ''));\n })\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n handleReportTopic(topicName) {\n const topic = this.tinode.getTopic(topicName);\n if (!topic) {\n return;\n }\n\n // Publish spam report.\n this.tinode.report('report', topicName);\n\n // Remove J and P permissions.\n topic.updateMode(null, '-JP')\n .then(_ => {\n // Hide MessagesView and InfoView panels.\n HashNavigation.navigateTo(HashNavigation.setUrlTopic(window.location.hash, ''));\n })\n .catch(err => this.handleError(err.message, 'err'));\n }\n\n handleShowContextMenu(params, menuItems) {\n this.setState({\n contextMenuVisible: true,\n contextMenuClickAt: {x: params.x, y: params.y},\n contextMenuParams: params,\n contextMenuItems: menuItems || this.defaultTopicContextMenu(params.topicName),\n contextMenuBounds: this.selfRef.current.getBoundingClientRect()\n });\n }\n\n //\n handleShowForwardDialog(params) {\n if (this.state.sidePanelSelected == 'newtpk') {\n // If the Find panel is active, close it.\n this.handleSidepanelCancel();\n }\n const header = '➦ ' + params.userName;\n const content = typeof params.content == 'string' ? Drafty.init(params.content) : Drafty.forwardedContent(params.content);\n const preview = Drafty.preview(content, FORWARDED_PREVIEW_LENGTH, true);\n const msg = Drafty.append(Drafty.appendLineBreak(Drafty.mention(header, params.userFrom)), content);\n const msgPreview = Drafty.quote(header, params.userFrom, preview);\n\n const head = {\n forwarded: params.topicName + ':' + params.seq\n };\n this.setState({\n forwardDialogVisible: true,\n forwardMessage: { head: head, msg: msg, preview: msgPreview }\n });\n }\n\n defaultTopicContextMenu(topicName) {\n const topic = this.tinode.getTopic(topicName);\n\n if (topic._deleted) {\n return [\n 'topic_delete'\n ];\n }\n\n let muted = false, blocked = false, self_blocked = false, subscribed = false, deleter = false,\n archived = false, webrtc = false, writer = false, p2p = false, self = false;\n if (topic) {\n subscribed = topic.isSubscribed();\n archived = topic.isArchived();\n\n const acs = topic.getAccessMode();\n if (acs) {\n muted = acs.isMuted();\n blocked = !acs.isJoiner();\n self_blocked = !acs.isJoiner('want');\n deleter = acs.isDeleter();\n writer = acs.isWriter();\n }\n }\n\n webrtc = writer && !!this.tinode.getServerParam('iceServers');\n p2p = Tinode.isP2PTopicName(topicName);\n self = Tinode.isSelfTopicName(topicName);\n\n return [\n subscribed ? {\n title: this.props.intl.formatMessage(messages.menu_item_info),\n handler: this.handleShowInfoView\n } : null,\n subscribed && p2p && webrtc ? {\n title: this.props.intl.formatMessage(messages.menu_item_audio_call),\n handler: this.handleStartAudioCall\n } : null,\n subscribed && p2p && webrtc ? {\n title: this.props.intl.formatMessage(messages.menu_item_video_call),\n handler: this.handleStartVideoCall\n } : null,\n subscribed ? 'messages_clear' : null,\n subscribed && deleter && !self ? 'messages_clear_hard' : null,\n self ? null : (muted ? (blocked ? null : 'topic_unmute') : 'topic_mute'),\n self ? null : (self_blocked ? 'topic_unblock' : 'topic_block'),\n archived ? 'topic_restore' : 'topic_archive',\n 'topic_delete'\n ];\n }\n\n handleHideContextMenu() {\n this.setState({\n contextMenuVisible: false,\n contextMenuClickAt: null,\n contextMenuParams: null,\n contextMenuBounds: null\n });\n }\n\n handleHideForwardDialog(keepForwardedMessage) {\n this.setState({\n forwardDialogVisible: false,\n forwardMessage: keepForwardedMessage ? this.state.forwardMessage : null\n });\n }\n\n handleContextMenuAction(action, promise, params) {\n if (action == 'topic_archive') {\n if (promise && params.topicName && params.topicName == this.state.topicSelected) {\n promise.then(_ => {\n this.handleTopicSelected(null);\n });\n }\n } else if (action == 'menu_item_forward') {\n this.handleShowForwardDialog(params);\n }\n }\n\n handleShowAlert(title, content, onConfirm, confirmText, onReject, rejectText) {\n this.setState({\n alertVisible: true,\n alertParams: {\n title: title,\n content: content,\n onConfirm: onConfirm,\n confirm: confirmText,\n onReject: onReject,\n reject: rejectText\n }\n });\n }\n\n handleShowInfoView() {\n HashNavigation.navigateTo(HashNavigation.addUrlParam(window.location.hash, 'info', 'info'));\n this.setState({infoPanel: 'info'});\n }\n\n handleMemberUpdateRequest(topicName, added, removed) {\n if (!topicName) {\n return;\n }\n\n const topic = this.tinode.getTopic(topicName);\n if (!topic) {\n return;\n }\n\n if (added && added.length > 0) {\n added.forEach(uid => {\n topic.invite(uid, null)\n .catch(err => this.handleError(err.message, 'err'));\n });\n }\n\n if (removed && removed.length > 0) {\n removed.forEach(uid => {\n topic.delSubscription(uid)\n .catch(err => this.handleError(err.message, 'err'));\n });\n }\n }\n\n handleValidateCredentialsRequest(cred, code, token) {\n if (this.tinode.isAuthenticated()) {\n // Adding new email or phone number in account setting.\n this.tinode.getMeTopic().setMeta({cred: {meth: cred, resp: code}})\n .then(_ => HashNavigation.navigateTo(HashNavigation.setUrlSidePanel(window.location.hash, 'contacts')))\n .catch(err => this.handleError(err.message, 'err'));\n } else {\n // Credential validation on signup.\n this.setState({credMethod: cred, credCode: code, credToken: token});\n this.doLogin(null, null, token, {meth: cred, resp: code});\n }\n }\n\n handlePasswordResetRequest(method, value) {\n // If already connected, connnect() will return a resolved promise.\n return this.tinode.connect()\n .then(_ => this.tinode.requestResetAuthSecret('basic', method, value))\n .catch(err => {\n // Socket error\n this.handleError(err.message, 'err');\n });\n }\n\n handleResetPassword(newPassword, tempAuth) {\n const secret = base64ReEncode(tempAuth.secret);\n if (!secret || !tempAuth.scheme) {\n this.handleError(this.props.intl.formatMessage(messages.invalid_security_token), 'err');\n } else {\n this.tinode.connect()\n .then(_ => this.tinode.updateAccountBasic(null, null, newPassword, {scheme: tempAuth.scheme, secret: secret}))\n .then(_ => {\n this.handleError(this.props.intl.formatMessage(messages.password_reset_success), 'info');\n HashNavigation.navigateTo('');\n })\n .catch(err => {\n this.handleError(err.message, 'err');\n });\n }\n }\n\n handleShowCountrySelector(code, dial, selectedCallback) {\n this.handleShowAlert(this.props.intl.formatMessage(messages.select_country),\n }>\n {\n this.setState({alertVisible: false});\n selectedCallback(c, d);\n }} />\n ,\n null, null, _ => {}, null);\n }\n\n handleStartVideoCall() {\n this.setState({\n callTopic: this.state.topicSelected,\n callState: CALL_STATE_OUTGOING_INITATED,\n callAudioOnly: false\n });\n }\n\n handleStartAudioCall() {\n this.setState({\n callTopic: this.state.topicSelected,\n callState: CALL_STATE_OUTGOING_INITATED,\n callAudioOnly: true\n });\n }\n\n handleCallInvite(callTopic, callSeq, callState, audioOnly) {\n switch (callState) {\n case CALL_STATE_OUTGOING_INITATED:\n const head = { webrtc: CALL_HEAD_STARTED, aonly: !!audioOnly };\n return this.handleSendMessage(Drafty.videoCall(audioOnly), undefined, undefined, head)\n .then(ctrl => {\n if (ctrl.code < 200 || ctrl.code >= 300 || !ctrl.params || !ctrl.params.seq) {\n this.handleCallClose();\n return ctrl;\n }\n this.setState({callSeq: ctrl.params['seq']});\n return ctrl\n });\n case CALL_STATE_IN_PROGRESS:\n const topic = this.tinode.getTopic(callTopic);\n if (!topic) {\n return;\n }\n // We've accepted the call. Let the other side know.\n topic.videoCall('accept', callSeq);\n break;\n }\n }\n\n handleCallRinging(callTopic, callSeq) {\n const topic = this.tinode.getTopic(callTopic);\n if (!topic) {\n return;\n }\n\n topic.videoCall('ringing', callSeq);\n }\n\n handleCallHangup(callTopic, callSeq) {\n const topic = this.tinode.getTopic(callTopic);\n if (!topic) {\n return;\n }\n\n topic.videoCall('hang-up', callSeq);\n }\n\n handleCallSendOffer(callTopic, callSeq, sdp) {\n const topic = this.tinode.getTopic(callTopic);\n if (!topic) {\n return;\n }\n\n topic.videoCall('offer', callSeq, sdp);\n }\n\n handleCallIceCandidate(callTopic, callSeq, candidate) {\n const topic = this.tinode.getTopic(callTopic);\n if (!topic) {\n return;\n }\n\n topic.videoCall('ice-candidate', callSeq, candidate);\n }\n handleCallSendAnswer(callTopic, callSeq, sdp) {\n const topic = this.tinode.getTopic(callTopic);\n if (!topic) {\n return;\n }\n\n topic.videoCall('answer', callSeq, sdp);\n }\n\n handleCallClose() {\n if (this.callTimeoutTimer) {\n clearTimeout(this.callTimeoutTimer);\n }\n this.setState({\n callTopic: undefined,\n callState: CALL_STATE_NONE,\n callAudioOnly: undefined\n });\n }\n\n handleCallAccept(topicName, setCallTopic, callSeq) {\n const topic = this.tinode.getTopic(topicName);\n if (!topic) {\n return;\n }\n if (topic.isSubscribed()) {\n this.handleTopicSelected(setCallTopic ? topicName : this.state.callTopic);\n const upd = {\n callState: CALL_STATE_IN_PROGRESS\n };\n if (setCallTopic) {\n upd.callTopic = topicName;\n upd.callSeq = callSeq;\n }\n this.setState(upd);\n } else {\n // We need to switch and subscribe to callTopic first.\n this.setState({\n callShouldStart: true,\n }, _ => this.handleTopicSelected(this.state.callTopic));\n }\n }\n\n handleInfoMessage(info) {\n if (info.what != 'call') {\n return;\n }\n switch (info.event) {\n case 'accept':\n // If another my session has accepted the call.\n if (Tinode.isMeTopicName(info.topic) && this.tinode.isMe(info.from)) {\n this.setState({\n callTopic: null,\n callState: CALL_STATE_NONE,\n callSeq: null,\n callAudioOnly: undefined\n });\n return;\n }\n if (info.topic == this.state.callTopic) {\n // Update state.\n this.setState({callState: CALL_STATE_IN_PROGRESS});\n }\n break;\n case 'hang-up':\n // Remote hangup.\n this.handleCallClose();\n break;\n }\n }\n\n handleDataMessage(data) {\n if (data.head && data.head.webrtc && data.head.webrtc == CALL_HEAD_STARTED && Tinode.isP2PTopicName(data.topic)) {\n // If it's a video call invite message.\n // See if we need to display incoming call UI.\n const topic = this.tinode.getTopic(data.topic);\n if (topic) {\n // Check if a later version of the message exists (which means the call\n // has been either accepted or finished already).\n const msg = topic.latestMsgVersion(data.seq) || data;\n if (msg.head && msg.head.webrtc && msg.head.webrtc == CALL_HEAD_STARTED) {\n // This is a legit new call.\n if (data.from != this.state.myUserId) {\n if (this.state.callState == CALL_STATE_NONE) {\n // Incoming call.\n this.setState({\n callTopic: data.topic,\n callState: CALL_STATE_INCOMING_RECEIVED,\n callSeq: data.seq,\n callAudioOnly: !!msg.head.aonly\n });\n } else {\n // Another call is either in progress or being established.\n // Reject the incoming call.\n this.handleCallHangup(data.topic, data.seq);\n }\n }\n }\n } else {\n console.warn(\"Received vc data message from unknown topic\", data.topic);\n }\n }\n }\n\n render() {\n return (\n \n {this.state.contextMenuVisible ?\n
{\n if (topicName == this.state.topicSelected) {\n this.handleTopicSelected(null);\n }\n }}\n onError={this.handleError} />\n :\n null\n }\n {this.state.forwardDialogVisible ?\n \n :\n null\n }\n {this.state.callTopic && this.state.callState == CALL_STATE_INCOMING_RECEIVED ?\n \n :\n null\n }\n {this.state.alertVisible ?\n this.setState({alertVisible: false})) : null}\n reject={this.state.alertParams.reject}\n onConfirm={this.state.alertParams.onConfirm ?\n (_ => {this.setState({alertVisible: false}); this.state.alertParams.onConfirm();}) : null}\n confirm={this.state.alertParams.confirm}\n /> : null}\n\n {!this.state.displayMobile || this.state.mobilePanel == 'sidepanel' ?\n \n : null}\n\n {!this.state.displayMobile || (this.state.mobilePanel == 'topic-view' && !this.state.infoPanel) ?\n \n : null}\n\n {this.state.infoPanel ?\n \n :\n null\n }\n \n );\n }\n};\n\nexport default injectIntl(TinodeWeb);\n","// Put all packages together.\n// Used to generate umd/index.prod.js\n\nimport React from 'react';\nimport { createRoot } from 'react-dom/client';\n\nimport { IntlProvider } from 'react-intl';\n\nimport TinodeWeb from './views/tinode-web.jsx';\nimport HashNavigation from './lib/navigation.js';\n\n// Insert google analytics script and tag if configured.\nif (typeof FIREBASE_INIT != 'undefined' && FIREBASE_INIT && FIREBASE_INIT.measurementId) {\n const head = document.getElementsByTagName('head')[0];\n let script = document.createElement('script');\n script.src = 'https://www.googletagmanager.com/gtag/js?id=' + FIREBASE_INIT.measurementId;\n script.async = true;\n head.prepend(script);\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', FIREBASE_INIT.measurementId);\n}\n\n// Allow loading translation strings for just one language.\nconst messageLoader = {\n 'ar': _ => import('./i18n.min/ar.json'),\n 'de': _ => import('./i18n.min/de.json'),\n 'en': _ => import('./i18n.min/en.json'),\n 'es': _ => import('./i18n.min/es.json'),\n 'fr': _ => import('./i18n.min/fr.json'),\n 'ko': _ => import('./i18n.min/ko.json'),\n 'ro': _ => import('./i18n.min/ro.json'),\n 'ru': _ => import('./i18n.min/ru.json'),\n 'th': _ => import('./i18n.min/th.json'),\n 'uk': _ => import('./i18n.min/uk.json'),\n 'zh': _ => import('./i18n.min/zh.json'),\n 'zh-TW': _ => import('./i18n.min/zh-TW.json')\n};\n\n// List of languages that are written right-to-left.\nconst rtl = ['ar', 'fa', 'he', 'ur'];\n\n// Detect human language to use in the UI:\n// Check parameters from URL hash #?hl=ru, then browser, then use 'en' as a fallback.\nconst { params } = HashNavigation.parseUrlHash(window.location.hash);\nconst language = (params && params.hl) ||\n (navigator.languages && navigator.languages[0]) ||\n navigator.language ||\n navigator.userLanguage ||\n 'en';\n\n// Make sure names like 'en_GB' and 'en-GB' consistently use '-'.\nconst normalized = language.replace('_', '-');\n// Get the base language 'en' from a more specific 'en-US' as a partial fallback.\nconst baseLanguage = normalized.split('-')[0].toLowerCase();\n\n// Try the full locale first, then the locale without the region code, fallback to 'en'.\nconst htmlLang = messageLoader[normalized] ? language : messageLoader[baseLanguage] ? baseLanguage : 'en';\n\nconst html = document.getElementsByTagName('html')[0];\n// Set lang attribute of the HTML element: \nhtml.setAttribute('lang', htmlLang);\nif (rtl.includes(baseLanguage)) {\n // Set right-to-left dir attribute of the HTML element: \n html.setAttribute('dir', 'rtl');\n}\n// Render the app.\nconst root = createRoot(document.getElementById('mountPoint'));\nmessageLoader[htmlLang]().then(messages =>\n root.render(\n \n \n \n));\n"],"names":["leafPrototypes","getProto","inProgress","dataWebpackPrefix","Cropper","React","constructor","props","super","this","state","panX","panY","originX","originY","zoom","minZoom","maxZoom","overlay","cutout","preview","boundingBox","imageWidth","imageHeight","mouseX","mouseY","prevDistance","cutoutRect","bBoxRect","initScaling","bind","onZoom","handleZoom","mouseDown","mouseUp","mouseMove","mouseTouch","positionAll","translate","componentDidMount","current","addEventListener","passive","getBoundingClientRect","width","height","componentWillUnmount","removeEventListener","setState","left","top","onChange","checkBound","currPan","img","delta","nextDiff","Math","min","imgRect","max","e","target","value","imgLeft","imgRight","coLeft","coRight","imgTop","imgBottom","coTop","coBottom","touches","pageX","pageY","window","document","body","style","dX","dY","right","bottom","preventDefault","length","touch0","touch1","distance","sqrt","scale","render","t3d","orig","className","ref","src","source","alt","transform","transformOrigin","onLoad","type","step","AvatarCrop","handleSubmit","handleChange","imageCrop","mime","avatar","then","onSubmit","blob","catch","err","onError","onCancel","onClick","FormattedMessage","id","defaultMessage","PACKAGE_VERSION","icon_mapping","messages","defineMessages","badge_verified","badge_staff","badge_danger","BadgeList","formatMessage","intl","badges","trustedBadges","forEach","b","comment","short","push","key","injectIntl","LoadSpinner","large","clear","centered","show","CheckBox","name","checked","iconName","classList","Array","isArray","attrs","join","module","exports","updateFavicon","count","oldIcon","getElementById","head","getElementsByTagName","newIcon","createElement","rel","href","removeChild","appendChild","title","theCard","fn","imageUrl","imageMimeType","note","card","trim","Tinode","DEL_CHAR","mimeType","matches","exec","photo","data","substring","indexOf","arrayEqual","a","sort","i","l","asPhone","val","test","replaceAll","asEmail","isUrlRelative","url","replace","sanitizeUrl","allowedSchemes","schemes","RegExp","sanitizeUrlForMime","mimeMajor","sanitizedUrl","urlAsAttachment","startsWith","query","fragment","idxF","idxQ","params","URLSearchParams","append","toString","deliveryMarker","received","MESSAGE_STATUS_SENDING","MESSAGE_STATUS_FAILED","MESSAGE_STATUS_FATAL","color","MESSAGE_STATUS_SENT","MESSAGE_STATUS_RECEIVED","MESSAGE_STATUS_READ","cancelablePromise","promise","hasCanceled","Error","Promise","reject","resolve","result","isCanceled","error","cancel","clipStr","str","tinode","BAR_COLOR_DARK","icon_title_play","AudioPlayer","base64ToIntArray","canPlay","playing","currentTime","duration","secondsToTime","longMin","initAudio","initCanvas","resampleBars","visualize","handlePlay","handleSeek","handleError","audioPlayer","viewBuffer","canvasRef","onloadedmetadata","ontimeupdate","onended","pause","componentDidUpdate","prevProps","Audio","_","offsetWidth","offsetHeight","canvasContext","getContext","lineCap","effectiveWidth","lineWidth","drawFrame","clearRect","requestAnimationFrame","thumbAt","LINE_WIDTH","beginPath","strokeStyle","x","y","stroke","moveTo","lineTo","arc","PI","fillStyle","fill","original","dstCount","apply","map","factor","amps","maxAmp","lo","hi","amp","j","readyState","play","console","rect","offset","clientX","playClass","ReactDOM","m","createRoot","hydrateRoot","SUPPORTED_IMAGE_FORMATS","MIME_EXTENSIONS","makeImageUrl","fitImageSize","maxWidth","maxHeight","forceSquare","size","dstWidth","dstHeight","srcWidth","srcHeight","xoffset","yoffset","fileNameForMime","fname","idx","ext","at","lastIndexOf","imageScaled","fileOrBlob","maxSize","Image","crossOrigin","onerror","onload","async","URL","revokeObjectURL","dim","canvas","ctx","imageSmoothingEnabled","drawImage","includes","toBlob","createObjectURL","objURL","fileToBase64","file","reader","FileReader","bits","split","readAsDataURL","blobToBase64","filePasted","event","onImageSuccess","onAttachmentSuccess","items","clipboardData","originalEvent","item","kind","getAsFile","base64ReEncode","btoa","atob","base64ToBlob","bin","buf","ArrayBuffer","arr","Uint8Array","charCodeAt","Blob","intArrayToBase64","String","fromCharCode","b64","c","VisiblePassword","inputRef","visible","handleVisibility","handeTextChange","handleKeyDown","handleEditingFinished","autoFocus","focus","keyCode","onFinished","currentTarget","setTimeout","contains","activeElement","tabIndex","onBlur","placeholder","maxLength","required","autoComplete","onKeyDown","LetterTile","isSelfTopicName","topic","SELF_AVATAR_URI","isGroup","isGroupTopicName","iconColor","idToColorClass","letter","charAt","deleted","authorizeURL","HashNavigation","parseUrlHash","hash","parts","path","arg","eq","slice","decodeURIComponent","navigateTo","location","composeUrlHash","args","hasOwnProperty","undefined","encodeURIComponent","addUrlParam","parsed","removeUrlParam","setUrlSidePanel","sidepanel","setUrlInfoPanel","infopanel","info","setUrlTopic","ReactIntl","LocalStorageUtil","setObject","localStorage","setItem","JSON","stringify","getObject","getItem","parse","updateObject","oldVal","Object","assign","removeItem","shortDateFormat","locale","navigator","userLanguage","language","now","Date","getFullYear","getMonth","getDate","toLocaleTimeString","hour12","hour","minute","toLocaleDateString","month","day","year","relativeDateFormat","diff","floor","getTime","getTimezoneOffset","abs","Intl","RelativeTimeFormat","numeric","format","DateTimeFormat","seconds","fixedMin","hours","sec","bytesToHumanSize","bytes","sizes","bucket","log2","pow","round","toFixed","shortenFileName","filename","light","fg","userId","stringToColorHash","flagEmoji","countryCode","codePoints","toUpperCase","char","fromCodePoint","APP_NAME","API_KEY","KNOWN_HOSTS","hosted","local","DEFAULT_HOST","LOGGING_ENABLED","KEYPRESS_DELAY","READ_DELAY","MIN_TAG_LENGTH","MAX_TAG_LENGTH","MAX_TAG_COUNT","DEFAULT_P2P_ACCESS_MODE","NO_ACCESS_MODE","MEDIA_BREAKPOINT","REM_SIZE","AVATAR_SIZE","MAX_AVATAR_BYTES","BROKEN_IMAGE_SIZE","NO_DIMENSIONS_VIDEO","MESSAGES_PAGE","MAX_INBAND_ATTACHMENT_SIZE","MAX_EXTERN_ATTACHMENT_SIZE","MAX_IMAGE_DIM","IMAGE_PREVIEW_DIM","VIDEO_PREVIEW_DIM","IMAGE_THUMBNAIL_DIM","VIDEO_THUMBNAIL_WIDTH","MAX_ONLINE_IN_TOPIC","MAX_TITLE_LENGTH","MAX_TOPIC_DESCRIPTION_LENGTH","MAX_PEER_TITLE_LENGTH","MESSAGE_PREVIEW_LENGTH","QUOTED_REPLY_LENGTH","FORWARDED_PREVIEW_LENGTH","EDIT_PREVIEW_LENGTH","MIN_DURATION","MAX_DURATION","LINK_CONTACT_US","LINK_PRIVACY_POLICY","LINK_TERMS_OF_SERVICE","IMMEDIATE_P2P_SUBSCRIPTION","CLICKABLE_URL_SCHEMES","QRCODE_SIZE","WAKE_UP_TIMEOUT","WAKE_UP_TICK","MIN_SWIPE_DISTANCE","TOAST_DURATION","AvatarUpload","handleFileReceived","image","files","onImageUpdated","randId","random","readOnly","uid","accept","htmlFor","uploading","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","call","n","getter","__esModule","d","getPrototypeOf","obj","__proto__","t","mode","ns","create","r","def","getOwnPropertyNames","definition","o","defineProperty","enumerable","get","f","chunkId","all","keys","reduce","promises","u","g","globalThis","Function","prop","prototype","done","script","needAttach","scripts","s","getAttribute","charset","timeout","nc","setAttribute","onScriptComplete","prev","clearTimeout","doneFns","parentNode","Symbol","toStringTag","p","installedChunks","installedChunkData","errorType","realSrc","message","request","webpackJsonpCallback","parentChunkLoadingFunction","chunkIds","moreModules","runtime","some","chunkLoadingGlobal","self","stringToByteArray$1","out","base64","byteToCharMap_","charToByteMap_","byteToCharMapWebSafe_","charToByteMapWebSafe_","ENCODED_VALS_BASE","ENCODED_VALS","ENCODED_VALS_WEBSAFE","HAS_NATIVE_SUPPORT","encodeByteArray","input","webSafe","init_","byteToCharMap","output","byte1","haveByte2","byte2","haveByte3","byte3","outByte1","outByte2","outByte3","outByte4","encodeString","decodeString","pos","c1","c2","c3","byteArrayToString","decodeStringToByteArray","charToByteMap","byte4","DecodeBase64StringError","arguments","base64urlEncodeWithoutPadding","utf8Bytes","base64Encode","base64Decode","getDefaultsFromGlobal","getGlobal","__FIREBASE_DEFAULTS__","getDefaults","process","env","defaultsJsonString","getDefaultsFromEnvVariable","match","cookie","decoded","getDefaultsFromCookie","getDefaultAppConfig","_a","config","Deferred","wrapCallback","callback","isIndexedDBAvailable","indexedDB","validateIndexedDBOpenable","preExist","DB_CHECK_NAME","open","onsuccess","close","deleteDatabase","onupgradeneeded","FirebaseError","code","customData","setPrototypeOf","captureStackTrace","ErrorFactory","service","serviceName","errors","fullCode","template","PATTERN","replaceTemplate","fullMessage","deepEqual","aKeys","bKeys","k","aProp","bProp","isObject","thing","getModularInstance","_delegate","Component","instanceFactory","multipleInstances","serviceProps","instantiationMode","onInstanceCreated","setInstantiationMode","setMultipleInstances","setServiceProps","setInstanceCreatedCallback","DEFAULT_ENTRY_NAME","Provider","container","component","instances","Map","instancesDeferred","instancesOptions","onInitCallbacks","identifier","normalizedIdentifier","normalizeInstanceIdentifier","has","deferred","set","isInitialized","shouldAutoInitialize","instance","getOrInitializeService","instanceIdentifier","getImmediate","options","optional","getComponent","setComponent","isComponentEager","instanceDeferred","entries","clearInstance","delete","services","from","values","filter","INTERNAL","_delete","isComponentSet","getOptions","initialize","opts","onInit","existingCallbacks","Set","add","existingInstance","invokeOnInitCallbacks","callbacks","providers","addComponent","provider","getProvider","addOrOverwriteComponent","getProviders","LogLevel","levelStringToEnum","DEBUG","VERBOSE","INFO","WARN","ERROR","SILENT","defaultLogLevel","ConsoleMethod","defaultLogHandler","logType","logLevel","toISOString","method","idbProxyableTypes","cursorAdvanceMethods","cursorRequestMap","WeakMap","transactionDoneMap","transactionStoreNamesMap","transformCache","reverseTransformCache","idbProxyTraps","receiver","IDBTransaction","objectStoreNames","objectStore","wrap","wrapFunction","func","IDBDatabase","transaction","IDBCursor","advance","continue","continuePrimaryKey","unwrap","storeNames","tx","transformCachableValue","unlisten","complete","DOMException","cacheDonePromiseForTransaction","object","IDBObjectStore","IDBIndex","Proxy","IDBRequest","success","promisifyRequest","newValue","openDB","version","blocked","upgrade","blocking","terminated","openPromise","oldVersion","newVersion","db","deleteDB","readMethods","writeMethods","cachedMethods","getMethod","targetFuncName","useIndex","isWrite","storeName","store","index","shift","oldTraps","PlatformLoggerServiceImpl","getPlatformInfoString","isVersionServiceProvider","library","logString","name$q","version$1","logger","_logLevel","_logHandler","_userLogHandler","TypeError","setLogLevel","logHandler","userLogHandler","debug","log","warn","name$p","name$o","name$n","name$m","name$l","name$k","name$j","name$i","name$h","name$g","name$f","name$e","name$d","name$c","name$b","name$a","name$9","name$8","name$7","name$6","name$5","name$4","name$3","name$2","name$1","PLATFORM_LOG_STRING","_apps","_serverApps","_components","_addComponent","app","_registerComponent","componentName","serverApp","heartbeatController","triggerHeartbeat","ERROR_FACTORY","FirebaseAppImpl","_isDeleted","_options","_config","_name","_automaticDataCollectionEnabled","automaticDataCollectionEnabled","_container","checkDestroyed","isDeleted","appName","initializeApp","rawConfig","existingApp","newApp","registerVersion","libraryKeyOrName","variant","libraryMismatch","versionMismatch","warning","STORE_NAME","dbPromise","getDbPromise","createObjectStore","originalErrorMessage","writeHeartbeatsToIndexedDB","heartbeatObject","put","computeKey","idbGetError","appId","HeartbeatServiceImpl","_heartbeatsCache","_storage","HeartbeatStorageImpl","_heartbeatsCachePromise","read","_b","agent","date","getUTCDateString","heartbeats","lastSentHeartbeatDate","singleDateHeartbeat","earliestHeartbeatIdx","earliestHeartbeatDate","getEarliestHeartbeatIdx","splice","overwrite","getHeartbeatsHeader","heartbeatsToSend","unsentEntries","heartbeatsCache","heartbeatEntry","find","hb","dates","countBytes","pop","extractHeartbeatsForHeader","headerString","_canUseIndexedDBPromise","runIndexedDBEnvironmentCheck","idbHeartbeatObject","readHeartbeatsFromIndexedDB","heartbeatsObject","existingHeartbeatsObject","PENDING_TIMEOUT_MS","INTERNAL_AUTH_VERSION","TOKEN_EXPIRATION_BUFFER","isServerError","getInstallationsEndpoint","projectId","extractAuthTokenInfoFromResponse","response","token","requestStatus","expiresIn","responseExpiresIn","Number","creationTime","getErrorFromResponse","requestName","errorData","json","serverCode","serverMessage","serverStatus","status","getHeaders","apiKey","Headers","Accept","getHeadersWithAuth","appConfig","refreshToken","headers","getAuthorizationHeader","retryIfServerError","sleep","ms","VALID_FID_PATTERN","generateFid","fidByteArray","crypto","msCrypto","getRandomValues","fid","b64String","array","substr","encode","getKey","fidChangeCallbacks","fidChanged","callFidChangeCallbacks","channel","getBroadcastChannel","postMessage","closeBroadcastChannel","broadcastFidChange","broadcastChannel","BroadcastChannel","onmessage","OBJECT_STORE_NAME","oldValue","remove","update","updateFn","getInstallationEntry","installations","registrationPromise","installationEntry","oldEntry","entry","registrationStatus","clearTimedOutRequest","updateOrCreateInstallationEntry","entryWithPromise","onLine","inProgressEntry","registrationTime","registeredInstallationEntry","heartbeatServiceProvider","endpoint","heartbeatService","heartbeatsHeader","authVersion","sdkVersion","fetch","ok","responseValue","authToken","createInstallationRequest","registerInstallation","waitUntilFidRegistration","triggerRegistrationIfNecessary","updateInstallationRequest","generateAuthTokenRequest","getGenerateAuthTokenEndpoint","installation","refreshAuthToken","forceRefresh","tokenPromise","isEntryRegistered","oldAuthToken","isAuthTokenExpired","isAuthTokenValid","updateAuthTokenRequest","waitUntilAuthTokenRequest","inProgressAuthToken","requestTime","makeAuthTokenRequestInProgressEntry","updatedInstallationEntry","fetchAuthTokenFromServer","getToken","installationsImpl","completeInstallationRegistration","getMissingValueError","valueName","INSTALLATIONS_NAME","internalFactory","getId","configKeys","keyName","extractAppConfig","DEFAULT_VAPID_KEY","CONSOLE_CAMPAIGN_ID","DEFAULT_REGISTRATION_TIMEOUT","MessageType$1","MessageType","arrayToBase64","uint8Array","base64ToArray","base64String","repeat","rawData","outputArray","OLD_DB_NAME","OLD_OBJECT_STORE_NAME","upgradeDb","dbGet","firebaseDependencies","tokenDetails","oldTokenDetails","senderId","dbNames","databases","upgradeTransaction","oldDetails","auth","p256dh","fcmToken","createTime","subscriptionOptions","swScope","vapidKey","checkTokenDetails","migrateOldDatabase","dbSet","requestDeleteToken","unsubscribeOptions","getEndpoint","responseData","errorInfo","getBody","web","applicationPubKey","getTokenInternal","messaging","pushSubscription","swRegistration","subscription","pushManager","getSubscription","subscribe","userVisibleOnly","applicationServerKey","getPushSubscription","scope","dbOptions","currentOptions","isVapidKeyEqual","isEndpointEqual","isAuthEqual","isP256dhEqual","isTokenValid","updatedToken","updateOptions","requestUpdateToken","updatedTokenDetails","updateToken","getNewToken","deleteTokenInternal","dbRemove","unsubscribe","subscribeOptions","requestGetToken","externalizePayload","internalPayload","payload","collapseKey","collapse_key","messageId","fcmMessageId","messagePayloadInternal","notification","icon","propagateNotificationPayload","propagateDataPayload","_c","_d","_e","fcmOptions","click_action","link","analyticsLabel","analytics_label","propagateFcmOptions","s1","s2","resultArray","_mergeStrings","MessagingService","analyticsProvider","deliveryMetricsExportedToBigQueryEnabled","onBackgroundMessageHandler","onMessageHandler","logEvents","isLogServiceStarted","messagingSenderId","registerDefaultSw","serviceWorker","register","registration","rejectTimeout","incomingSw","installing","waiting","active","onstatechange","ev","waitForRegistrationActive","browserErrorMessage","getToken$1","Notification","permission","requestPermission","updateVapidKey","ServiceWorkerRegistration","updateSwReg","serviceWorkerRegistration","logToScion","messageType","eventType","NOTIFICATION_CLICKED","PUSH_RECEIVED","getEventType","logEvent","message_id","message_name","message_time","message_device_time","messageEventListener","isFirebaseMessaging","next","dataPayload","WindowMessagingInternalFactory","isWindowSupported","cookieEnabled","PushSubscription","getMessagingInWindow","isSupported","deleteToken","deleteToken$1","onMessage","nextOrObserver","onMessage$1","Alert","content","onReject","onConfirm","confirm","clear_messages","clear_for_all","delete_for_all","send_retry","mute","unmute","reply","forward","edit","topic_delete","topic_delete_warning","delete_messages_warning","unblock","block","topic_block_warning","member_delete","archive","unarchive","edit_permissions","clear_messages_warning","pin_message","unpin_message","ContextMenu","selfRef","handlePageClick","handleEscapeKey","handleClick","MenuItems","handler","errorHandler","onShowAlert","deleteMessages","retryMessage","replyToMessage","editMessage","pinMessage","topicPermissionSetter","ctrl","onTopicRemoved","topicName","getTopic","delTopic","user","delSubscription","stopPropagation","hide","dataset","onAction","hard","cancelSend","seq","delMessagesAll","delMessagesEdits","delMessagesList","flushMessage","msg","createMessage","publishDraft","pin","updateMode","pickReply","userFrom","userName","menu","disabled","hSize","vSize","position","bounds","clickAt","ContactBadges","UnreadBadge","CallMessage","isCallDropped","callState","successClass","callIcon","incoming","CallStatus","icon2","InlineVideo","videoRef","LazyImage","isvideo","padding","whenDone","FileProgress","progress","UploadingImage","onCancelUpload","drafty_form","drafty_attachment","drafty_image","drafty_video","drafty_unknown","JSON_MIME_TYPE","JSON_MIME_TYPE_LEGACY","fullFormatter","stack","quoteFormatter","el","Drafty","tagName","attr","attrValue","loading","handleImageData","onFormButtonClick","inner","child","onQuoteClick","handleVideoData","concat","viewportWidth","minWidth","minHeight","isProcessing","onImagePreview","onVideoPreview","previewFormatter","inlineImageAttr","inlineVideoAttr","quoteImageOrVideo","isVideo","premime","preref","evt","statusText","scaled","replyFormatter","loadedPromise","self_topic_name","self_topic_comment","Contact","handleContextClick","onSelected","showContextMenu","online","icon_badges","isVerified","isStaff","isDangerous","acs","showMode","getMode","isMuted","isJoiner","isValid","previewIsResponse","marker","titleClass","showCheckmark","selected","showOnline","isChannel","unread","small","ContactAction","action","badge_you","badge_owner","ContactList","topicSelected","contactNodes","contactsCount","showSelfTopic","onTopicSelected","contacts","filterFunc","filterOn","private","toLowerCase","public","isChannelTopicName","myUserId","isOwner","forwarded","deliveryStatus","latestMessage","_status","msgStatus","showUnread","connected","trusted","verified","staff","danger","_deleted","noScroll","dangerouslySetInnerHTML","__html","emptyListMessage","SearchContacts","edited","search","handleSearchChange","handleSearch","handleClear","onSearchContacts","ForwardDialog","handleClose","handleSearchContacts","handleContactSelected","onInitFind","isNullValue","searchResults","isWriter","desription","search_placeholder","not_found_placeholder","CALL_HEAD_STARTED","RING_SOUND","CallIncoming","fullName","previousMetaDesc","resetDesc","onMetaDesc","handleRejectCall","handleAcceptCall","ringTimer","setInterval","onRinging","clearInterval","desc","onAcceptCall","onClose","MenuCancel","ErrorPanel","level","onClearError","text","whiteSpace","actionText","Chip","handleCancel","invalid","noAvatar","ChipInput","deriveStateFromProps","focused","handleTextInput","removeChipAt","handleChipCancel","handleFocusGained","handleFocusLost","chips","prompt","sortedChips","sortChips","staticMembers","chipIndex","indexChips","prevState","keep","normal","removed","onChipRemoved","onFocusLost","onEnter","avatarDisabled","onFocus","no_contacts","contacts_not_found_short","GroupManager","members","indexMembers","keepInitialMembers","requiredMember","contactFilter","noContactsMessage","selectedContacts","handleMemberRemoved","handleContactFilter","present","keepInitial","stat","sel","doContactFiltering","added","joiner","writer","preser","approver","sharer","deleter","owner","PermissionsEditor","names","skip","compare","userTitle","userAvatar","modeTitle","compareTitle","QRCode","ShowQRCode","qrCodeRef","uri","InPlaceEdit","initialValue","valid","handleStartEditing","handlePasswordFinished","validator","checkValidity","spanText","spanClass","multiline","iconLeft","iconRight","element","rows","spellCheck","TagManager","tags","alias","tagByPrefix","TAG_ALIAS","tagInput","activated","handleTagInput","handleAddTag","handleRemoveTag","getDerivedStateFromProps","nextProps","last","tag","maxTagCount","getServerParam","onTagsChanged","setUniqueTag","minTagLength","maxTagLength","add_tags_prompt","alias_invalid","alias_already_taken","TopicDescEdit","getAccessMode","isSelf","isMe","isMeTopicName","description","newAvatar","newAvatarMime","aliasError","previousOnTags","aliasCheckTimer","aliasCheckPromise","tnNewTags","handleFullNameUpdate","handleImageUpdated","handleAvatarCropped","handleAvatarCropCancel","uploadAvatar","handlePrivateUpdate","handleAliasUpdate","handleDescriptionUpdate","handleTagsUpdated","validateAlias","cancelValidator","onTagsUpdated","onUpdateTopicDesc","readyToUpload","getLargeFileHelper","upload","du","clearTagPrefix","isValidTagValue","fnd","getFndTopic","validationPromise","checkTagUniqueness","onUpdateTags","editable","full_name_placeholder","group_name_placeholder","private_placeholder","title_tag_manager","TopicCommonView","previousTagsUpdated","getType","onUpdateTagsRequest","delete_messages","leave_chat","leave_chat_warning","block_contact","block_contact_warning","report_chat","report_chat_warning","other_user","TopicSecurity","handleDeleteTopic","handleDeleteMessages","handleLeave","handleBlock","handleReport","onDeleteTopic","onDeleteMessages","onLeaveTopic","onBlockTopic","onReportTopic","groupTopic","onLaunchPermissionsEditor","access","anon","modeGiven2","general","security","crop","perm_want","perm_given","perm_auth","perm_anon","perm_user","qrcode","text_copied","InfoView","admin","muted","address","selectedContact","modeGiven","modeWant","modeWant2","contactList","previousSubsUpdated","resetSubs","resetTags","onSubsUpdated","handleImageChanged","handleMuted","handleUnarchive","handlePermissionsChanged","handleLaunchPermissionsEditor","handleShowQRCode","handleCopyToClipboard","handleShowAddMembers","handleMemberUpdateRequest","handleMemberSelected","handleContextMenu","handleBackNavigate","newState","user2","subscriber","getGiven","getWant","subscribers","sub","defacs","getDefaultAccess","isSelfType","isAdmin","isSharer","isDeleter","archived","isArchived","isGroupType","isChannelType","chan","getMeta","startMetaQuery","withTags","build","subs","onTopicDescUpdate","ignored","onChangePermissions","ignored2","onTopicUnArchive","which","perm","onTopicDescUpdateRequest","userPermissionsEdited","toEdit","toCompare","toSkip","titleEdit","titleCompare","AccessMode","userPermissionsTitle","userPermissionsAvatar","editedPermissions","immutablePermissions","editedPermissionsTitle","immutablePermissionsTitle","editedPermissionsSkipped","onNavigate","clipboard","writeText","toast","onMemberUpdateRequest","panel","menuItems","view","panelTitle","displayMobile","errorLevel","errorText","searchableContacts","reqCredMethod","onCredAdd","onTopicTagsUpdateRequest","onCredConfirm","onCredDelete","URI_TOPIC_ID_PREFIX","marginLeft","opacity","no_members","loop","CALL_ENDED_SOUND","DIALING_SOUND","VIDEO_MUTED_EVENT","VIDEO_UNMUTED_EVENT","already_in_call","CallPanel","localStream","remoteStream","pc","dataChannel","previousOnInfo","waitingForPeer","callInitialSetupComplete","audioOnly","callAudioOnly","videoToggleInProgress","remoteVideoLive","localStreamConstraints","audio","video","isOutgoingCall","localRef","remoteRef","remoteIceCandidatesCache","onInfo","start","stop","createPeerConnection","canSendOffer","drainRemoteIceCandidatesCache","handleNegotiationNeededEvent","handleICECandidateEvent","handleNewICECandidateMsg","handleICEConnectionStateChangeEvent","handleSignalingStateChangeEvent","handleICEGatheringStateChangeEvent","handleIceCandidateErrorEvent","handleTrackEvent","handleVideoOfferMsg","handleVideoAnswerMsg","reportError","handleGetUserMediaError","stopTracks","disconnectMedia","handleCloseClick","handleToggleCameraClick","handleToggleMicClick","handleRemoteHangup","handleVideoCallAccepted","muteVideo","unmuteVideo","emptyVideoTrack","handleDataChannelEvent","handleDataChannelError","handleDataChannelMessage","handleDataChannelOpen","handleDataChannelClose","stream","getTracks","track","addTrack","enabled","removeTrack","what","fillRect","captureStream","getVideoTracks","mediaDevices","getUserMedia","srcObject","onInvite","ontrack","onremovetrack","onremovestream","onicecandidate","oniceconnectionstatechange","onsignalingstatechange","onicegatheringstatechange","onnegotiationneeded","onicecandidateerror","ondatachannel","tracks","send","onopen","onclose","withDataChannel","iceServers","RTCPeerConnection","stateUpdate","createDataChannel","ordered","RTCSessionDescription","setRemoteDescription","createOffer","offer","setLocalDescription","onSendOffer","localDescription","toJSON","candidate","onIceCandidate","RTCIceCandidate","addIceCandidate","iceConnectionState","signalingState","streams","dummyVideo","createAnswer","answer","onSendAnswer","onHangup","sender","getSenders","replaceTrack","finally","getAudioTracks","forceUpdate","audioTracks","videoTracks","audioIcon","videoIcon","peerTitle","pulseAnimation","remoteActive","rstream","autoPlay","playsInline","Attachment","downloader","downloadFile","mimetype","download","loaded","helperFunc","downloadUrl","downloadWidget","message_sending","message_sending_failed","message_edited_marker","ReceivedMarker","timestamp","timeStyle","BaseChatMessage","uploader","onProgress","handleProgress","handleExpandImage","handlePlayVideo","handleFormButtonClick","handleCancelUpload","handleQuoteClick","formatterContext","onExpandMedia","resp","act","onFormResponse","userIsWriter","immutable","entities","_0","_1","tp","styles","userIsAdmin","pinned","parseInt","ratio","replyToSeq","sideClass","sequence","bubbleClass","textSizeClass","fullDisplay","attachments","getContentType","att","getDownloadUrl","getEntitySize","tree","innerRef","IntlChatMessage","_extends","AudioRecorder","messaging_disabled","type_new_message","add_image_caption","file_attachment_too_large","cannot_initiate_upload","icon_title_record_voice","icon_title_attach_file","icon_title_add_image","icon_title_send","SendMessage","quote","audioRec","audioAvailable","keypressTimestamp","handlePasteEvent","handleAttachImage","handleAttachFile","handleAttachAudio","handleSend","handleKeyPress","handleMessageTyping","handleDropAttach","formatReply","messageEditArea","getComputedStyle","getPropertyValue","scrollHeight","initMessage","scrollTop","setSelectionRange","onAttachImage","onAttachFile","onAttachAudio","acceptBlank","noInput","onSendMessage","shiftKey","onKeyPress","messagePrompt","sendIcon","editing","onCancelReply","audioEnabled","attachImage","click","attachFile","Suspense","fallback","onRecordingProgress","onDeleted","display","DocPreview","handleSendDoc","caption","mimeToIcon","default","iconFromMime","GroupSubs","usersOnline","totalCount","countToShow","overflow","ImagePreview","handleSendImage","assignWidth","node","maxlength","download_url","Invitation","handleButtonAction","LogoView","getLibrary","serverVersion","serverAddress","MetaMessage","message_not_found","message_deleted","PinnedMessages","touchX","touchY","touchSurface","getSelectedIndex","handleSelected","handleMoveNext","handleMovePrev","handleTouchEventStart","handleTouchEventEnd","handleTouchCancel","pins","isTouch","setSelected","clientY","changedTouches","messageShown","dots","cn","unrecognized_video_format","VideoPreview","handleSendVideo","videoWidth","videoHeight","controlist","controls","controlsList","disablePictureInPicture","poster","online_now","last_seen","not_found","invalid_content","editing_message","drag_file","isUnconfirmed","ex","getExcessive","isPeerRestricted","getMissing","shouldPresentCallPanel","MessagesView","componentSetup","leave","sendMessage","retrySend","sendImageAttachment","sendVideoAttachment","sendFileAttachment","sendAudioAttachment","sendKeyPress","handleScrollReference","mountDnDEvents","handleScrollEvent","handleDescChange","handleSubsUpdated","handleMessageUpdate","handleAuxUpdate","handleAllMessagesReceived","handleInfoReceipt","handleExpandMedia","handleClosePreview","handleFormResponse","handleShowMessageContextMenu","handleNewChatAcceptance","handleEnablePeer","handleAttachImageOrVideo","postReadNotification","clearNotificationQueue","goToLatestMessage","handleFileDrop","handlePickReply","handleEditMessage","handleCancelReply","handleUnpinMessage","handleCallHangup","isDragEnabled","handleDragStart","handleDragIn","handleDragOut","handleDrag","handleDrop","chatMessageRefs","getOrCreateMessageRef","getVisibleMessageRange","dragCounter","dndRef","readNotificationQueue","readNotificationTimer","keyPressTimer","seqId","holderRect","MAX_SAFE_INTEGER","visibilityStatus","every","messagesScroller","maxSeqId","minSeqId","scrollPosition","applicationVisible","isNewGroupTopicName","rtcPanel","callSeq","onData","onAllMessagesReceived","onPres","onAuxUpdated","newTopic","newTopicParams","_topicName","isP2PType","withDesc","isSubscribed","isReader","withLaterData","nextState","docPreview","imagePreview","imagePostview","videoPreview","videoPostview","typingIndicator","fetchingMessages","showGoToLastButton","contentToEdit","dragging","selectedPin","forwardMessage","onlineSubs","peer","p2pPeerDesc","peerMessagingDisabled","minMsgSeq","maxMsgSeq","latestClearId","maxClearId","aux","pinsLoaded","callTopic","subsVersion","readingBlocked","unconformed","unconfirmed","ready","getQuery","withLaterDesc","withLaterSub","withAux","withLaterDel","setQuery","onNewTopicCreated","discard","queuedMessages","pub","_sending","_fatal","webrtc","blankState","oldTopicName","isTopicCached","oldTopic","processingScrollEvent","gaps","msgHasMoreMessages","getMessagesPage","dnd","sendAt","isServerAssignedSeq","noteRead","setMilliseconds","getMilliseconds","isNewMessage","getPinnedMessages","attachJSON","searchParams","messageSpecificMenuItems","canDelete","maxDelAge","MSG_DELETE_AGE","onNewChat","noteRecording","noteKeyPress","uploadCompletionPromise","sanitizeEntities","maxInbandAttachmentSize","jsonMimeConverter","fileType","urlPromise","maxExternAttachmentSize","limit","onVideoCallClosed","onCallHangup","insertImage","_tempPreview","appendLineBreak","videoBlob","previewBlob","uploads","b64s","v64","i64","insertVideo","b64conv","appendAudio","found","findMessage","_cancelled","senderName","init","replyContent","wrapInto","onCancelForwardMessage","toMarkdown","scrollIntoView","behavior","dataTransfer","clearData","component2","onCallInvite","onCallSendOffer","onCallIceCandidate","onCallSendAnswer","pinnedMessages","latestMsgVersion","messageNodes","previousFrom","prevDate","chatBoxClass","nextFrom","thisFrom","isReply","userDesc","isNaN","thisDate","ts","toDateString","ChatMessage","isChan","_uploader","lastSeen","cont","getMeTopic","getContact","isP2PTopicName","seen","when","messagesComponent","onHideMessagesView","ButtonBack","onBack","MenuContacts","onNewTopic","onSettings","MenuStart","onSignUp","SideNavbar","archived_contacts_title","ContactsView","handleAction","unreadThreads","archivedCount","chatList","arch","touched","action_ignored","onShowArchive","EditAccountView","handleCheckboxClick","onToggleMessageSounds","onTogglePushNotifications","onToggleIncognitoMode","messageSounds","desktopAlertsEnabled","desktopAlerts","incognitoMode","delete_account","delete_account_warning","AccSecurityView","me","blockedCount","showPermissionEditorFor","handlePasswordUpdate","handleHidePermissionsEditor","handleDeleteAccount","pwd","password","onUpdatePassword","onUpdateAccountDesc","onDeleteAccount","password_unchanged","onLogout","onShowBlocked","AccSupportView","LoginView","login","hostName","saveToken","persist","handleLoginChange","handlePasswordChange","handleToggleSaveToken","onPersistenceChange","onLogin","submitClasses","login_prompt","autoCorrect","autoCapitalize","password_prompt","invalid_id","NewTopicById","groupId","myURI","prefix","NewTopicGroup","handleFieldEdit","handleTagsChanged","handleChannelToggle","search_for_contacts","search_no_results","NewTopicView","tabSelected","searchQuery","handleTabClick","handleSearchResultSelected","handleNewGroupSubmit","handleGroupByID","email","TAG_EMAIL","tel","TAG_PHONE","onCreateTopic","dataUrl","priv","no_contacts_placeholder","getCurrentUserID","HostSelector","changed","handleHostNameChange","onServerAddressChange","hostOptions","list","SettingsView","transport","secureConnection","handleTransportSelected","handleServerAddressChange","handleToggleSecure","onUpdate","ws","lp","transportOptions","phone","ValidationView","credCode","codeReceived","handleCodeChange","credMethod","credToken","numbers_only","AccountSettingsView","CreateAccountView","PasswordResetView","settings","notif","support","newtpk","cred","reset","SidepanelView","handleNewTopic","errorAction","errorActionText","loadSpinnerVisible","loginDisabled","onLoginRequest","onShowCountrySelector","onCreateAccount","onGlobalSettings","onUpdateAccountTags","AccNotificationsView","onValidateCredentials","onRequest","onPasswordResetRequest","onReset","onResetPassword","detectServerAddress","host","protocol","hostname","port","isSecureConnection","PhoneCountrySelector","POP_SOUND","reconnect_countdown","reconnect_now","push_init_failed","invalid_security_token","no_connection","code_doesnot_match","menu_item_info","menu_item_audio_call","menu_item_video_call","cred_confirmed_successfully","password_reset_success","select_country","TinodeWeb","getBlankState","handleResize","handleHashRoute","handleOnline","checkForAppUpdate","handleVisibilityEvent","handleLoginRequest","handlePersistenceChange","handleConnected","handleAutoreconnectIteration","doLogin","handleLoginSuccessful","handleDisconnect","tnMeMetaDesc","tnMeContactUpdate","tnMeSubsUpdated","resetContactList","tnInitFind","tnFndSubsUpdated","handleTopicSelected","handleHideMessagesView","handleSendMessage","handleNewChatInvitation","handleNewAccount","handleNewAccountRequest","handleUpdatePasswordRequest","handleUpdateAccountTagsRequest","handleToggleIncognitoMode","handleSettings","handleGlobalSettings","handleShowArchive","handleShowBlocked","handleToggleMessageSounds","handleCredAdd","handleCredDelete","handleCredConfirm","initFCMessaging","toggleFCMToken","handlePushMessage","handleSidepanelCancel","handleStartTopicRequest","handleNewTopicCreated","handleTopicUpdateRequest","handleChangePermissions","handleTagsUpdateRequest","handleLogout","handleDeleteTopicRequest","handleDeleteMessagesRequest","handleLeaveUnsubRequest","handleBlockTopicRequest","handleReportTopic","handleShowContextMenu","defaultTopicContextMenu","handleHideContextMenu","handleShowAlert","handleShowInfoView","handleValidateCredentialsRequest","handlePasswordResetRequest","handleResetPassword","handleContextMenuAction","handleShowCountrySelector","handleShowForwardDialog","handleHideForwardDialog","handleStartVideoCall","handleStartAudioCall","handleInfoMessage","handleDataMessage","handleCallClose","handleCallInvite","handleCallRinging","handleCallSendOffer","handleCallIceCandidate","handleCallSendAnswer","handleCallAccept","sendMessageToTopic","callTimeoutTimer","autoLogin","messageSoundsOff","firebaseInitApp","FIREBASE_INIT","firebaseToken","hidden","sidePanelSelected","sidePanelTitle","sidePanelAvatar","myTrustedBadges","liveConnection","topicSelectedOnline","topicSelectedAcs","innerWidth","infoPanel","mobilePanel","callShouldStart","contextMenuVisible","contextMenuBounds","contextMenuClickAt","contextMenuParams","contextMenuItems","forwardDialogVisible","alertVisible","alertParams","requestedTopic","handleOnlineOn","handleOnlineOff","lastWakeUpCheck","wakeUpTicker","documentElement","clientWidth","viewportHeight","clientHeight","tnSetup","onConnect","onDisconnect","onAutoreconnectIteration","onInfoMessage","onDataMessage","expires","setAuthToken","connect","parsedNav","cred_done","persistentCache","onSetupCompleted","secure","setHumanLanguage","enableLogging","oobNotification","fcm","firebaseGetMessaging","getRegistration","reg","requestFCMToken","setDeviceToken","firebaseOnMessage","sw","firebaseGetToken","messagingVapidKey","mobile","onupdatefound","installingWorker","controller","newTopicTabSelected","tab","topicType","getTopicAccessMode","stateForError","reconnectCountdown","reconnect","isConnected","meth","initStorage","clearStorage","getServerInfo","ver","reqCred","prom","fmtTime","tmpToken","isAuthenticated","getAuthToken","credential","loginPromise","connectionPromise","loginBasic","loginToken","navigateToCredentialsView","goToTopic","onContactUpdate","withCred","disconnect","urlHash","isPresencer","unused","prepareSearchableContacts","foundContacts","merged","updated","past","withSub","setMeta","isTopicOnline","completion","subscribePromise","calls","publishMessage","am","updateWant","login_","password_","public_","cred_","tags_","createAccountBasic","on","firebaseDelToken","delCredential","scheme","basicNavigator","infoNavigator","newGroupTopicName","oldName","newName","updateAccountBasic","getCurrentLogin","updateGiven","cleared","Promose","delCurrentUser","report","header","forwardedContent","mention","msgPreview","self_blocked","subscribed","p2p","keepForwardedMessage","confirmText","rejectText","invite","requestResetAuthSecret","newPassword","tempAuth","secret","dial","selectedCallback","aonly","videoCall","sdp","setCallTopic","upd","myUserName","onAddMember","handleManageGroupMembers","measurementId","gtag","dataLayer","prepend","messageLoader","hl","languages","normalized","baseLanguage","htmlLang","html","root","IntlProvider","textComponent"],"sourceRoot":""}
\ No newline at end of file
diff --git a/umd/tinode.dev.js b/umd/tinode.dev.js
index 36208d6f..c9970706 100644
--- a/umd/tinode.dev.js
+++ b/umd/tinode.dev.js
@@ -1452,7 +1452,8 @@ class DB {
const MAX_FORM_ELEMENTS = 8;
const MAX_PREVIEW_ATTACHMENTS = 3;
const MAX_PREVIEW_DATA_SIZE = 64;
-const JSON_MIME_TYPE = 'application/json';
+const JSON_MIME_TYPE = 'application/json+drafty';
+const JSON_MIME_TYPE_LEGACY = 'application/json';
const DRAFTY_MIME_TYPE = 'text/x-drafty';
const ALLOWED_ENT_FIELDS = ['act', 'height', 'duration', 'incoming', 'mime', 'name', 'premime', 'preref', 'preview', 'ref', 'size', 'state', 'url', 'val', 'width'];
const segmenter = new Intl.Segmenter();
@@ -2536,7 +2537,7 @@ Drafty.sanitizeEntities = function (content) {
};
Drafty.getDownloadUrl = function (entData) {
let url = null;
- if (entData.mime != JSON_MIME_TYPE && entData.val) {
+ if (entData.mime != JSON_MIME_TYPE && entData.mime != JSON_MIME_TYPE_LEGACY && entData.val) {
url = base64toObjectUrl(entData.val, entData.mime, Drafty.logger);
} else if (typeof entData.ref == 'string') {
url = entData.ref;
@@ -3020,7 +3021,7 @@ function attachmentsToEnd(tree, limit) {
if (attachments.length == limit) {
continue;
}
- if (c.data['mime'] == JSON_MIME_TYPE) {
+ if (c.data['mime'] == JSON_MIME_TYPE || c.data['mime'] == JSON_MIME_TYPE_LEGACY) {
continue;
}
delete c.att;
@@ -5396,7 +5397,7 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ PACKAGE_VERSION: () => (/* binding */ PACKAGE_VERSION)
/* harmony export */ });
-const PACKAGE_VERSION = "0.24.2";
+const PACKAGE_VERSION = "0.24.3";
/***/ })
diff --git a/umd/tinode.dev.js.map b/umd/tinode.dev.js.map
index 072938c8..78cb08c1 100644
--- a/umd/tinode.dev.js.map
+++ b/umd/tinode.dev.js.map
@@ -1 +1 @@
-{"version":3,"file":"tinode.dev.js","mappings":"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","sources":["webpack://tinode/webpack/universalModuleDefinition","webpack://tinode/./src/access-mode.js","webpack://tinode/./src/cbuffer.js","webpack://tinode/./src/comm-error.js","webpack://tinode/./src/config.js","webpack://tinode/./src/connection.js","webpack://tinode/./src/db.js","webpack://tinode/./src/drafty.js","webpack://tinode/./src/fnd-topic.js","webpack://tinode/./src/large-file.js","webpack://tinode/./src/me-topic.js","webpack://tinode/./src/meta-builder.js","webpack://tinode/./src/topic.js","webpack://tinode/./src/utils.js","webpack://tinode/./version.js","webpack://tinode/webpack/bootstrap","webpack://tinode/webpack/runtime/compat get default export","webpack://tinode/webpack/runtime/define property getters","webpack://tinode/webpack/runtime/global","webpack://tinode/webpack/runtime/hasOwnProperty shorthand","webpack://tinode/webpack/runtime/make namespace object","webpack://tinode/./src/tinode.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"tinode\"] = factory();\n\telse\n\t\troot[\"tinode\"] = factory();\n})(this, () => {\nreturn ","/**\n * @file Access control model.\n *\n * @copyright 2015-2022 Tinode LLC.\n */\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\n/**\n * Helper class for handling access mode.\n *\n * @class AccessMode\n * @memberof Tinode\n *\n * @param {AccessMode|Object=} acs - AccessMode to copy or access mode object received from the server.\n */\nexport default class AccessMode {\n constructor(acs) {\n if (acs) {\n this.given = typeof acs.given == 'number' ? acs.given : AccessMode.decode(acs.given);\n this.want = typeof acs.want == 'number' ? acs.want : AccessMode.decode(acs.want);\n this.mode = acs.mode ? (typeof acs.mode == 'number' ? acs.mode : AccessMode.decode(acs.mode)) :\n (this.given & this.want);\n }\n }\n\n static #checkFlag(val, side, flag) {\n side = side || 'mode';\n if (['given', 'want', 'mode'].includes(side)) {\n return ((val[side] & flag) != 0);\n }\n throw new Error(`Invalid AccessMode component '${side}'`);\n }\n /**\n * Parse string into an access mode value.\n * @memberof Tinode.AccessMode\n * @static\n *\n * @param {string | Number} mode - either a String representation of the access mode to parse or a set of bits to assign.\n * @returns {number} - Access mode as a numeric value.\n */\n static decode(str) {\n if (!str) {\n return null;\n } else if (typeof str == 'number') {\n return str & AccessMode._BITMASK;\n } else if (str === 'N' || str === 'n') {\n return AccessMode._NONE;\n }\n\n const bitmask = {\n 'J': AccessMode._JOIN,\n 'R': AccessMode._READ,\n 'W': AccessMode._WRITE,\n 'P': AccessMode._PRES,\n 'A': AccessMode._APPROVE,\n 'S': AccessMode._SHARE,\n 'D': AccessMode._DELETE,\n 'O': AccessMode._OWNER\n };\n\n let m0 = AccessMode._NONE;\n\n for (let i = 0; i < str.length; i++) {\n const bit = bitmask[str.charAt(i).toUpperCase()];\n if (!bit) {\n // Unrecognized bit, skip.\n continue;\n }\n m0 |= bit;\n }\n return m0;\n }\n /**\n * Convert numeric representation of the access mode into a string.\n *\n * @memberof Tinode.AccessMode\n * @static\n *\n * @param {number} val - access mode value to convert to a string.\n * @returns {string} - Access mode as a string.\n */\n static encode(val) {\n if (val === null || val === AccessMode._INVALID) {\n return null;\n } else if (val === AccessMode._NONE) {\n return 'N';\n }\n\n const bitmask = ['J', 'R', 'W', 'P', 'A', 'S', 'D', 'O'];\n let res = '';\n for (let i = 0; i < bitmask.length; i++) {\n if ((val & (1 << i)) != 0) {\n res = res + bitmask[i];\n }\n }\n return res;\n }\n /**\n * Update numeric representation of access mode with the new value. The value\n * is one of the following:\n * - a string starting with '+' or '-' then the bits to add or remove, e.g. '+R-W' or '-PS'.\n * - a new value of access mode\n *\n * @memberof Tinode.AccessMode\n * @static\n *\n * @param {number} val - access mode value to update.\n * @param {string} upd - update to apply to val.\n * @returns {number} - updated access mode.\n */\n static update(val, upd) {\n if (!upd || typeof upd != 'string') {\n return val;\n }\n\n let action = upd.charAt(0);\n if (action == '+' || action == '-') {\n let val0 = val;\n // Split delta-string like '+ABC-DEF+Z' into an array of parts including + and -.\n const parts = upd.split(/([-+])/);\n // Starting iteration from 1 because String.split() creates an array with the first empty element.\n // Iterating by 2 because we parse pairs +/- then data.\n for (let i = 1; i < parts.length - 1; i += 2) {\n action = parts[i];\n const m0 = AccessMode.decode(parts[i + 1]);\n if (m0 == AccessMode._INVALID) {\n return val;\n }\n if (m0 == null) {\n continue;\n }\n if (action === '+') {\n val0 |= m0;\n } else if (action === '-') {\n val0 &= ~m0;\n }\n }\n val = val0;\n } else {\n // The string is an explicit new value 'ABC' rather than delta.\n const val0 = AccessMode.decode(upd);\n if (val0 != AccessMode._INVALID) {\n val = val0;\n }\n }\n\n return val;\n }\n /**\n * Bits present in a1 but missing in a2.\n *\n * @static\n * @memberof Tinode\n *\n * @param {number | string} a1 - access mode to subtract from.\n * @param {number | string} a2 - access mode to subtract.\n * @returns {number} access mode with bits present in a1 but missing in a2.\n */\n static diff(a1, a2) {\n a1 = AccessMode.decode(a1);\n a2 = AccessMode.decode(a2);\n\n if (a1 == AccessMode._INVALID || a2 == AccessMode._INVALID) {\n return AccessMode._INVALID;\n }\n return a1 & ~a2;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Custom formatter\n */\n toString() {\n return '{\"mode\": \"' + AccessMode.encode(this.mode) +\n '\", \"given\": \"' + AccessMode.encode(this.given) +\n '\", \"want\": \"' + AccessMode.encode(this.want) + '\"}';\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Converts numeric values to strings.\n */\n jsonHelper() {\n return {\n mode: AccessMode.encode(this.mode),\n given: AccessMode.encode(this.given),\n want: AccessMode.encode(this.want)\n };\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Assign value to 'mode'.\n * @memberof Tinode.AccessMode\n *\n * @param {string | Number} m - either a string representation of the access mode or a set of bits.\n * @returns {AccessMode} - this AccessMode.\n */\n setMode(m) {\n this.mode = AccessMode.decode(m);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update mode value.\n * @memberof Tinode.AccessMode\n *\n * @param {string} u - string representation of the changes to apply to access mode.\n * @returns {AccessMode} - this AccessMode.\n */\n updateMode(u) {\n this.mode = AccessMode.update(this.mode, u);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get mode value as a string.\n * @memberof Tinode.AccessMode\n *\n * @returns {string} - mode value.\n */\n getMode() {\n return AccessMode.encode(this.mode);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Assign given value.\n * @memberof Tinode.AccessMode\n *\n * @param {string | Number} g - either a string representation of the access mode or a set of bits.\n * @returns {AccessMode} - this AccessMode.\n */\n setGiven(g) {\n this.given = AccessMode.decode(g);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update 'given' value.\n * @memberof Tinode.AccessMode\n *\n * @param {string} u - string representation of the changes to apply to access mode.\n * @returns {AccessMode} - this AccessMode.\n */\n updateGiven(u) {\n this.given = AccessMode.update(this.given, u);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get 'given' value as a string.\n * @memberof Tinode.AccessMode\n *\n * @returns {string} - given value.\n */\n getGiven() {\n return AccessMode.encode(this.given);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Assign 'want' value.\n * @memberof Tinode.AccessMode\n *\n * @param {string | Number} w - either a string representation of the access mode or a set of bits.\n * @returns {AccessMode} - this AccessMode.\n */\n setWant(w) {\n this.want = AccessMode.decode(w);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update 'want' value.\n * @memberof Tinode.AccessMode\n *\n * @param {string} u - string representation of the changes to apply to access mode.\n * @returns {AccessMode} - this AccessMode.\n */\n updateWant(u) {\n this.want = AccessMode.update(this.want, u);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get 'want' value as a string.\n * @memberof Tinode.AccessMode\n *\n * @returns {string} - want value.\n */\n getWant() {\n return AccessMode.encode(this.want);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get permissions present in 'want' but missing in 'given'.\n * Inverse of {@link Tinode.AccessMode#getExcessive}\n *\n * @memberof Tinode.AccessMode\n *\n * @returns {string} permissions present in want but missing in given .\n */\n getMissing() {\n return AccessMode.encode(this.want & ~this.given);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get permissions present in 'given' but missing in 'want'.\n * Inverse of {@link Tinode.AccessMode#getMissing}\n * @memberof Tinode.AccessMode\n *\n * @returns {string} permissions present in given but missing in want .\n */\n getExcessive() {\n return AccessMode.encode(this.given & ~this.want);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update 'want', 'give', and 'mode' values.\n * @memberof Tinode.AccessMode\n *\n * @param {AccessMode} val - new access mode value.\n * @returns {AccessMode} - this AccessMode.\n */\n updateAll(val) {\n if (val) {\n this.updateGiven(val.given);\n this.updateWant(val.want);\n this.mode = this.given & this.want;\n }\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Owner (O) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isOwner(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._OWNER);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Presence (P) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isPresencer(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._PRES);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Presence (P) flag is NOT set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isMuted(side) {\n return !this.isPresencer(side);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Join (J) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isJoiner(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._JOIN);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Reader (R) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isReader(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._READ);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Writer (W) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isWriter(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._WRITE);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Approver (A) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isApprover(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._APPROVE);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if either one of Owner (O) or Approver (A) flags is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isAdmin(side) {\n return this.isOwner(side) || this.isApprover(side);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if either one of Owner (O), Approver (A), or Sharer (S) flags is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isSharer(side) {\n return this.isAdmin(side) || AccessMode.#checkFlag(this, side, AccessMode._SHARE);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Deleter (D) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isDeleter(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._DELETE);\n }\n}\n\nAccessMode._NONE = 0x00;\nAccessMode._JOIN = 0x01;\nAccessMode._READ = 0x02;\nAccessMode._WRITE = 0x04;\nAccessMode._PRES = 0x08;\nAccessMode._APPROVE = 0x10;\nAccessMode._SHARE = 0x20;\nAccessMode._DELETE = 0x40;\nAccessMode._OWNER = 0x80;\n\nAccessMode._BITMASK = AccessMode._JOIN | AccessMode._READ | AccessMode._WRITE | AccessMode._PRES |\n AccessMode._APPROVE | AccessMode._SHARE | AccessMode._DELETE | AccessMode._OWNER;\nAccessMode._INVALID = 0x100000;\n","/**\n * @file In-memory sorted cache of objects.\n *\n * @copyright 2015-2025 Tinode LLC.\n */\n'use strict';\n\n/**\n * In-memory sorted cache of objects.\n *\n * @class CBuffer\n * @memberof Tinode\n * @protected\n *\n * @param {function} compare custom comparator of objects. Takes two parameters a and b;\n * returns -1 if a < b, 0 if a == b, 1 otherwise.\n * @param {boolean} unique enforce element uniqueness: when true replace existing element with a new\n * one on conflict; when false keep both elements.\n */\nexport default class CBuffer {\n #comparator = undefined;\n #unique = false;\n buffer = [];\n\n constructor(compare_, unique_) {\n this.#comparator = compare_ || ((a, b) => {\n return a === b ? 0 : a < b ? -1 : 1;\n });\n this.#unique = unique_;\n }\n\n #findNearest(elem, arr, exact) {\n let start = 0;\n let end = arr.length - 1;\n let pivot = 0;\n let diff = 0;\n let found = false;\n\n while (start <= end) {\n pivot = (start + end) / 2 | 0;\n diff = this.#comparator(arr[pivot], elem);\n if (diff < 0) {\n start = pivot + 1;\n } else if (diff > 0) {\n end = pivot - 1;\n } else {\n found = true;\n break;\n }\n }\n if (found) {\n return {\n idx: pivot,\n exact: true\n };\n }\n if (exact) {\n return {\n idx: -1\n };\n }\n // Not exact - insertion point\n return {\n idx: diff < 0 ? pivot + 1 : pivot\n };\n }\n\n // Insert element into a sorted array.\n #insertSorted(elem, arr) {\n const found = this.#findNearest(elem, arr, false);\n const count = (found.exact && this.#unique) ? 1 : 0;\n arr.splice(found.idx, count, elem);\n return arr;\n }\n\n /**\n * Get an element at the given position.\n * @memberof Tinode.CBuffer#\n * @param {number} at - Position to fetch from.\n * @returns {Object} Element at the given position or undefined.\n */\n getAt(at) {\n return this.buffer[at];\n }\n\n /**\n * Convenience method for getting the last element from the buffer.\n * @memberof Tinode.CBuffer#\n * @param {function} filter - optional filter to apply to elements. If filter is provided, the search\n * for the last element starts from the end of the buffer and goes backwards until the filter returns true.\n * @returns {Object} The last element in the buffer or undefined if buffer is empty.\n */\n getLast(filter) {\n return filter ?\n this.buffer.findLast(filter) :\n this.buffer[this.buffer.length - 1];\n }\n\n /**\n * Insert new element(s) to the buffer at the correct position according to the sort method.\n * Variadic: takes one or more arguments. If an array is passed as a single argument, its\n * elements are inserted individually.\n * @memberof Tinode.CBuffer#\n *\n * @param {...Object|Array} - One or more objects to insert.\n */\n put() {\n let insert;\n // inspect arguments: if array, insert its elements, if one or more non-array arguments, insert them one by one\n if (arguments.length == 1 && Array.isArray(arguments[0])) {\n insert = arguments[0];\n } else {\n insert = arguments;\n }\n for (let idx in insert) {\n this.#insertSorted(insert[idx], this.buffer);\n }\n }\n\n /**\n * Remove element at the given position.\n * @memberof Tinode.CBuffer#\n * @param {number} at - Position to delete at.\n * @returns {Object} Element at the given position or undefined.\n */\n delAt(at) {\n at |= 0;\n let r = this.buffer.splice(at, 1);\n if (r && r.length > 0) {\n return r[0];\n }\n return undefined;\n }\n\n /**\n * Remove elements between two positions.\n * @memberof Tinode.CBuffer#\n * @param {number} since - Position to delete from (inclusive).\n * @param {number} before - Position to delete to (exclusive).\n *\n * @returns {Array} array of removed elements (could be zero length).\n */\n delRange(since, before) {\n return this.buffer.splice(since, before - since);\n }\n\n /**\n * Return the number of elements the buffer holds.\n * @memberof Tinode.CBuffer#\n * @return {number} Number of elements in the buffer.\n */\n length() {\n return this.buffer.length;\n }\n\n /**\n * Reset the buffer discarding all elements\n * @memberof Tinode.CBuffer#\n */\n reset() {\n this.buffer = [];\n }\n\n /**\n * Callback for iterating contents of buffer. See {@link Tinode.CBuffer#forEach}.\n * @callback ForEachCallbackType\n * @memberof Tinode.CBuffer#\n * @param {Object} elem - Current element of the buffer.\n * @param {Object} prev - Previous element of the buffer.\n * @param {Object} next - Next element of the buffer.\n * @param {number} index - Index of the current element.\n */\n\n /**\n * Apply given callback to all elements of the buffer.\n * @memberof Tinode.CBuffer#\n *\n * @param {Tinode.ForEachCallbackType} callback - Function to call for each element.\n * @param {number} startIdx - Optional index to start iterating from (inclusive), default: 0.\n * @param {number} beforeIdx - Optional index to stop iterating before (exclusive), default: length of the buffer.\n * @param {Object} context - calling context (i.e. value of this in callback)\n */\n forEach(callback, startIdx, beforeIdx, context) {\n startIdx = Math.max(0, startIdx | 0);\n beforeIdx = Math.min(beforeIdx || this.buffer.length, this.buffer.length);\n\n for (let i = startIdx; i < beforeIdx; i++) {\n callback.call(context, this.buffer[i],\n (i > startIdx ? this.buffer[i - 1] : undefined),\n (i < beforeIdx - 1 ? this.buffer[i + 1] : undefined), i);\n }\n }\n\n /**\n * Find element in buffer using buffer's comparison function.\n * @memberof Tinode.CBuffer#\n *\n * @param {Object} elem - element to find.\n * @param {boolean=} nearest - when true and exact match is not found, return the nearest element (insertion point).\n * @returns {number} index of the element in the buffer or -1.\n */\n find(elem, nearest) {\n const {\n idx\n } = this.#findNearest(elem, this.buffer, !nearest);\n return idx;\n }\n\n /**\n * Callback for filtering the buffer. See {@link Tinode.CBuffer#filter}.\n * @callback FilterCallbackType\n * @memberof Tinode.CBuffer#\n * @param {Object} elem - Current element of the buffer.\n * @param {number} index - Index of the current element.\n * @returns {boolen} true to keep the element, false to remove.\n */\n\n /**\n * Remove all elements that do not pass the test implemented by the provided callback function.\n * @memberof Tinode.CBuffer#\n *\n * @param {Tinode.FilterCallbackType} callback - Function to call for each element.\n * @param {Object} context - calling context (i.e. value of this in the callback)\n */\n filter(callback, context) {\n let count = 0;\n for (let i = 0; i < this.buffer.length; i++) {\n if (callback.call(context, this.buffer[i], i)) {\n this.buffer[count] = this.buffer[i];\n count++;\n }\n }\n\n this.buffer.splice(count);\n }\n\n /**\n * Check if buffer is empty.\n * @returns {boolean} true if the buffer is empty, false otherwise.\n */\n isEmpty() {\n return this.buffer.length == 0;\n }\n}\n","/**\n * @file Throwable error with numeric error code.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nexport default class CommError extends Error {\n constructor(message, code) {\n super(`${message} (${code})`);\n this.name = 'CommError';\n this.code = code;\n }\n}\n","/**\n * @file Global constants and configuration parameters.\n *\n * @copyright 2015-2025 Tinode LLC\n */\n'use strict';\n\nimport {\n PACKAGE_VERSION\n} from '../version.js';\n\n// Global constants\nexport const PROTOCOL_VERSION = '0'; // Major component of the version, e.g. '0' in '0.17.1'.\nexport const VERSION = PACKAGE_VERSION || '0.24';\nexport const LIBRARY = 'tinodejs/' + VERSION;\n\n// Topic name prefixes.\nexport const TOPIC_NEW = 'new';\nexport const TOPIC_NEW_CHAN = 'nch';\nexport const TOPIC_ME = 'me';\nexport const TOPIC_FND = 'fnd';\nexport const TOPIC_SYS = 'sys';\nexport const TOPIC_SLF = 'slf';\nexport const TOPIC_CHAN = 'chn';\nexport const TOPIC_GRP = 'grp';\nexport const TOPIC_P2P = 'p2p';\nexport const USER_NEW = 'new';\n\n// Starting value of a locally-generated seqId used for pending messages.\nexport const LOCAL_SEQID = 0xFFFFFFF;\n\n// Status codes.\nexport const MESSAGE_STATUS_NONE = 0; // Status not assigned.\nexport const MESSAGE_STATUS_QUEUED = 10; // Local ID assigned, in progress to be sent.\nexport const MESSAGE_STATUS_SENDING = 20; // Transmission started.\nexport const MESSAGE_STATUS_FAILED = 30; // At least one attempt was made to send the message.\nexport const MESSAGE_STATUS_FATAL = 40; // Message sending failed and it should not be retried.\nexport const MESSAGE_STATUS_SENT = 50; // Delivered to the server.\nexport const MESSAGE_STATUS_RECEIVED = 60; // Received by the client.\nexport const MESSAGE_STATUS_READ = 70; // Read by the user.\nexport const MESSAGE_STATUS_TO_ME = 80; // The message is received from another user.\n\n// Reject unresolved futures after this many milliseconds.\nexport const EXPIRE_PROMISES_TIMEOUT = 5_000;\n// Periodicity of garbage collection of unresolved futures.\nexport const EXPIRE_PROMISES_PERIOD = 1_000;\n\n// Delay before acknowledging that a message was recived.\nexport const RECV_TIMEOUT = 100;\n\n// Default number of messages to pull into memory from persistent cache.\nexport const DEFAULT_MESSAGES_PAGE = 24;\n\n// Unicode DEL character indicating data was deleted.\nexport const DEL_CHAR = '\\u2421';\n\n// Maximum number of pinnned messages;\nexport const MAX_PINNED_COUNT = 5;\n\n// Tag prefixes for alias, email, phone.\nexport const TAG_ALIAS = 'alias:';\nexport const TAG_EMAIL = 'email:';\nexport const TAG_PHONE = 'tel:';\n","/**\n * @file Abstraction layer for websocket and long polling connections.\n *\n * @copyright 2015-2022 Tinode LLC.\n */\n'use strict';\n\nimport CommError from './comm-error.js';\nimport {\n jsonParseHelper\n} from './utils.js';\n\nlet WebSocketProvider;\nlet XHRProvider;\n\n// Error code to return in case of a network problem.\nconst NETWORK_ERROR = 503;\nconst NETWORK_ERROR_TEXT = \"Connection failed\";\n\n// Error code to return when user disconnected from server.\nconst NETWORK_USER = 418;\nconst NETWORK_USER_TEXT = \"Disconnected by client\";\n\n// Settings for exponential backoff\nconst _BOFF_BASE = 2000; // 2000 milliseconds, minimum delay between reconnects\nconst _BOFF_MAX_ITER = 10; // Maximum delay between reconnects 2^10 * 2000 ~ 34 minutes\nconst _BOFF_JITTER = 0.3; // Add random delay\n\n// Helper function for creating an endpoint URL.\nfunction makeBaseUrl(host, protocol, version, apiKey) {\n let url = null;\n\n if (['http', 'https', 'ws', 'wss'].includes(protocol)) {\n url = `${protocol}://${host}`;\n if (url.charAt(url.length - 1) !== '/') {\n url += '/';\n }\n url += 'v' + version + '/channels';\n if (['http', 'https'].includes(protocol)) {\n // Long polling endpoint ends with \"lp\", i.e.\n // '/v0/channels/lp' vs just '/v0/channels' for ws\n url += '/lp';\n }\n url += '?apikey=' + apiKey;\n }\n return url;\n}\n\n/**\n * An abstraction for a websocket or a long polling connection.\n *\n * @class Connection\n * @memberof Tinode\n\n * @param {Object} config - configuration parameters.\n * @param {string} config.host - Host name and optional port number to connect to.\n * @param {string} config.apiKey - API key generated by keygen.\n * @param {string} config.transport - Network transport to use, either \"ws\"/\"wss\" for websocket or\n * lp for long polling.\n * @param {boolean} config.secure - Use Secure WebSocket if true.\n * @param {string} version_ - Major value of the protocol version, e.g. '0' in '0.17.1'.\n * @param {boolean} autoreconnect_ - If connection is lost, try to reconnect automatically.\n */\nexport default class Connection {\n // Logger, does nothing by default.\n static #log = _ => {};\n\n #boffTimer = null;\n #boffIteration = 0;\n #boffClosed = false; // Indicator if the socket was manually closed - don't autoreconnect if true.\n\n // Websocket.\n #socket = null;\n\n host;\n secure;\n apiKey;\n\n version;\n autoreconnect;\n\n initialized;\n\n // (config.host, config.apiKey, config.transport, config.secure), PROTOCOL_VERSION, true\n constructor(config, version_, autoreconnect_) {\n this.host = config.host;\n this.secure = config.secure;\n this.apiKey = config.apiKey;\n\n this.version = version_;\n this.autoreconnect = autoreconnect_;\n\n if (config.transport === 'lp') {\n // explicit request to use long polling\n this.#init_lp();\n this.initialized = 'lp';\n } else if (config.transport === 'ws') {\n // explicit request to use web socket\n // if websockets are not available, horrible things will happen\n this.#init_ws();\n this.initialized = 'ws';\n }\n\n if (!this.initialized) {\n // Invalid or undefined network transport.\n Connection.#log(\"Unknown or invalid network transport. Running under Node? Call 'Tinode.setNetworkProviders()'.\");\n throw new Error(\"Unknown or invalid network transport. Running under Node? Call 'Tinode.setNetworkProviders()'.\");\n }\n }\n\n /**\n * To use Connection in a non browser context, supply WebSocket and XMLHttpRequest providers.\n * @static\n * @memberof Connection\n * @param wsProvider WebSocket provider, e.g. for nodeJS , require('ws').\n * @param xhrProvider XMLHttpRequest provider, e.g. for node require('xhr').\n */\n static setNetworkProviders(wsProvider, xhrProvider) {\n WebSocketProvider = wsProvider;\n XHRProvider = xhrProvider;\n }\n\n /**\n * Assign a non-default logger.\n * @static\n * @memberof Connection\n * @param {function} l variadic logging function.\n */\n static set logger(l) {\n Connection.#log = l;\n }\n\n /**\n * Initiate a new connection\n * @memberof Tinode.Connection#\n * @param {string} host_ Host name to connect to; if null the old host name will be used.\n * @param {boolean} force Force new connection even if one already exists.\n * @return {Promise} Promise resolved/rejected when the connection call completes, resolution is called without\n * parameters, rejection passes the {Error} as parameter.\n */\n connect(host_, force) {\n return Promise.reject(null);\n }\n\n /**\n * Try to restore a network connection, also reset backoff.\n * @memberof Tinode.Connection#\n *\n * @param {boolean} force - reconnect even if there is a live connection already.\n */\n reconnect(force) {}\n\n /**\n * Terminate the network connection\n * @memberof Tinode.Connection#\n */\n disconnect() {}\n\n /**\n * Send a string to the server.\n * @memberof Tinode.Connection#\n *\n * @param {string} msg - String to send.\n * @throws Throws an exception if the underlying connection is not live.\n */\n sendText(msg) {}\n\n /**\n * Check if connection is alive.\n * @memberof Tinode.Connection#\n * @returns {boolean} true if connection is live, false otherwise.\n */\n isConnected() {\n return false;\n }\n\n /**\n * Get the name of the current network transport.\n * @memberof Tinode.Connection#\n * @returns {string} name of the transport such as \"ws\" or \"lp\".\n */\n transport() {\n return this.initialized;\n }\n\n /**\n * Send network probe to check if connection is indeed live.\n * @memberof Tinode.Connection#\n */\n probe() {\n this.sendText('1');\n }\n\n /**\n * Reset autoreconnect counter to zero.\n * @memberof Tinode.Connection#\n */\n backoffReset() {\n this.#boffReset();\n }\n\n // Backoff implementation - reconnect after a timeout.\n #boffReconnect() {\n // Clear timer\n clearTimeout(this.#boffTimer);\n // Calculate when to fire the reconnect attempt\n const timeout = _BOFF_BASE * (Math.pow(2, this.#boffIteration) * (1.0 + _BOFF_JITTER * Math.random()));\n // Update iteration counter for future use\n this.#boffIteration = (this.#boffIteration >= _BOFF_MAX_ITER ? this.#boffIteration : this.#boffIteration + 1);\n if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(timeout);\n }\n\n this.#boffTimer = setTimeout(_ => {\n Connection.#log(`Reconnecting, iter=${this.#boffIteration}, timeout=${timeout}`);\n // Maybe the socket was closed while we waited for the timer?\n if (!this.#boffClosed) {\n const prom = this.connect();\n if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(0, prom);\n } else {\n // Suppress error if it's not used.\n prom.catch(_ => {\n /* do nothing */\n });\n }\n } else if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(-1);\n }\n }, timeout);\n }\n\n // Terminate auto-reconnect process.\n #boffStop() {\n clearTimeout(this.#boffTimer);\n this.#boffTimer = null;\n }\n\n // Reset auto-reconnect iteration counter.\n #boffReset() {\n this.#boffIteration = 0;\n }\n\n // Initialization for long polling.\n #init_lp() {\n const XDR_UNSENT = 0; // Client has been created. open() not called yet.\n const XDR_OPENED = 1; // open() has been called.\n const XDR_HEADERS_RECEIVED = 2; // send() has been called, and headers and status are available.\n const XDR_LOADING = 3; // Downloading; responseText holds partial data.\n const XDR_DONE = 4; // The operation is complete.\n\n // Fully composed endpoint URL, with API key & SID\n let _lpURL = null;\n\n let _poller = null;\n let _sender = null;\n\n let lp_sender = (url_) => {\n const sender = new XHRProvider();\n sender.onreadystatechange = (evt) => {\n if (sender.readyState == XDR_DONE && sender.status >= 400) {\n // Some sort of error response\n throw new CommError(\"LP sender failed\", sender.status);\n }\n };\n\n sender.open('POST', url_, true);\n return sender;\n }\n\n let lp_poller = (url_, resolve, reject) => {\n let poller = new XHRProvider();\n let promiseCompleted = false;\n\n poller.onreadystatechange = evt => {\n if (poller.readyState == XDR_DONE) {\n if (poller.status == 201) { // 201 == HTTP.Created, get SID\n let pkt = JSON.parse(poller.responseText, jsonParseHelper);\n _lpURL = url_ + '&sid=' + pkt.ctrl.params.sid;\n poller = lp_poller(_lpURL);\n poller.send(null);\n if (this.onOpen) {\n this.onOpen();\n }\n\n if (resolve) {\n promiseCompleted = true;\n resolve();\n }\n\n if (this.autoreconnect) {\n this.#boffStop();\n }\n } else if (poller.status > 0 && poller.status < 400) { // 0 = network error; 400 = HTTP.BadRequest\n if (this.onMessage) {\n this.onMessage(poller.responseText);\n }\n poller = lp_poller(_lpURL);\n poller.send(null);\n } else {\n // Don't throw an error here, gracefully handle server errors\n if (reject && !promiseCompleted) {\n promiseCompleted = true;\n reject(poller.responseText);\n }\n if (this.onMessage && poller.responseText) {\n this.onMessage(poller.responseText);\n }\n if (this.onDisconnect) {\n const code = poller.status || (this.#boffClosed ? NETWORK_USER : NETWORK_ERROR);\n const text = poller.responseText || (this.#boffClosed ? NETWORK_USER_TEXT : NETWORK_ERROR_TEXT);\n this.onDisconnect(new CommError(text, code), code);\n }\n\n // Polling has stopped. Indicate it by setting poller to null.\n poller = null;\n if (!this.#boffClosed && this.autoreconnect) {\n this.#boffReconnect();\n }\n }\n }\n };\n // Using POST to avoid caching response by service worker.\n poller.open('POST', url_, true);\n return poller;\n }\n\n this.connect = (host_, force) => {\n this.#boffClosed = false;\n\n if (_poller) {\n if (!force) {\n return Promise.resolve();\n }\n _poller.onreadystatechange = undefined;\n _poller.abort();\n _poller = null;\n }\n\n if (host_) {\n this.host = host_;\n }\n\n return new Promise((resolve, reject) => {\n const url = makeBaseUrl(this.host, this.secure ? 'https' : 'http', this.version, this.apiKey);\n Connection.#log(\"LP connecting to:\", url);\n _poller = lp_poller(url, resolve, reject);\n _poller.send(null);\n }).catch(err => {\n Connection.#log(\"LP connection failed:\", err);\n });\n };\n\n this.reconnect = force => {\n this.#boffStop();\n this.connect(null, force);\n };\n\n this.disconnect = _ => {\n this.#boffClosed = true;\n this.#boffStop();\n\n if (_sender) {\n _sender.onreadystatechange = undefined;\n _sender.abort();\n _sender = null;\n }\n if (_poller) {\n _poller.onreadystatechange = undefined;\n _poller.abort();\n _poller = null;\n }\n\n if (this.onDisconnect) {\n this.onDisconnect(new CommError(NETWORK_USER_TEXT, NETWORK_USER), NETWORK_USER);\n }\n // Ensure it's reconstructed\n _lpURL = null;\n };\n\n this.sendText = (msg) => {\n _sender = lp_sender(_lpURL);\n if (_sender && (_sender.readyState == XDR_OPENED)) {\n _sender.send(msg);\n } else {\n throw new Error(\"Long poller failed to connect\");\n }\n };\n\n this.isConnected = _ => {\n return (_poller && true);\n };\n }\n\n // Initialization for Websocket\n #init_ws() {\n this.connect = (host_, force) => {\n this.#boffClosed = false;\n\n if (this.#socket) {\n if (!force && this.#socket.readyState == this.#socket.OPEN) {\n // Issue a probe request to be sure the connection is live.\n // This is a non-blocking call.\n this.probe();\n return Promise.resolve();\n }\n this.#socket.close();\n this.#socket = null;\n }\n\n if (host_) {\n this.host = host_;\n }\n\n return new Promise((resolve, reject) => {\n const url = makeBaseUrl(this.host, this.secure ? 'wss' : 'ws', this.version, this.apiKey);\n\n Connection.#log(\"WS connecting to: \", url);\n\n // It throws when the server is not accessible but the exception cannot be caught:\n // https://stackoverflow.com/questions/31002592/javascript-doesnt-catch-error-in-websocket-instantiation/31003057\n const conn = new WebSocketProvider(url);\n\n conn.onerror = err => {\n reject(err);\n };\n\n conn.onopen = _ => {\n if (this.autoreconnect) {\n this.#boffStop();\n }\n\n if (this.onOpen) {\n this.onOpen();\n }\n\n resolve();\n };\n\n conn.onclose = _ => {\n this.#socket = null;\n\n if (this.onDisconnect) {\n const code = this.#boffClosed ? NETWORK_USER : NETWORK_ERROR;\n this.onDisconnect(new CommError(this.#boffClosed ? NETWORK_USER_TEXT : NETWORK_ERROR_TEXT, code), code);\n }\n\n if (!this.#boffClosed && this.autoreconnect) {\n this.#boffReconnect();\n }\n };\n\n conn.onmessage = evt => {\n if (this.onMessage) {\n this.onMessage(evt.data);\n }\n };\n\n this.#socket = conn;\n });\n }\n\n this.reconnect = force => {\n this.#boffStop();\n this.connect(null, force);\n };\n\n this.disconnect = _ => {\n this.#boffClosed = true;\n this.#boffStop();\n\n if (!this.#socket) {\n return;\n }\n this.#socket.close();\n this.#socket = null;\n };\n\n this.sendText = msg => {\n if (this.#socket && (this.#socket.readyState == this.#socket.OPEN)) {\n this.#socket.send(msg);\n } else {\n throw new Error(\"Websocket is not connected\");\n }\n };\n\n this.isConnected = _ => {\n return (this.#socket && (this.#socket.readyState == this.#socket.OPEN));\n };\n }\n\n // Callbacks:\n\n /**\n * A callback to pass incoming messages to. See {@link Tinode.Connection#onMessage}.\n * @callback Tinode.Connection.OnMessage\n * @memberof Tinode.Connection\n * @param {string} message - Message to process.\n */\n onMessage = undefined;\n\n /**\n * A callback for reporting a dropped connection.\n * @type {function}\n * @memberof Tinode.Connection#\n */\n onDisconnect = undefined;\n\n /**\n * A callback called when the connection is ready to be used for sending. For websockets it's socket open,\n * for long polling it's readyState=1 (OPENED)\n * @type {function}\n * @memberof Tinode.Connection#\n */\n onOpen = undefined;\n\n /**\n * A callback to notify of reconnection attempts. See {@link Tinode.Connection#onAutoreconnectIteration}.\n * @memberof Tinode.Connection\n * @callback AutoreconnectIterationType\n * @param {string} timeout - time till the next reconnect attempt in milliseconds. -1 means reconnect was skipped.\n * @param {Promise} promise resolved or rejected when the reconnect attemp completes.\n *\n */\n /**\n * A callback to inform when the next attampt to reconnect will happen and to receive connection promise.\n * @memberof Tinode.Connection#\n * @type {Tinode.Connection.AutoreconnectIterationType}\n */\n onAutoreconnectIteration = undefined;\n}\n\nConnection.NETWORK_ERROR = NETWORK_ERROR;\nConnection.NETWORK_ERROR_TEXT = NETWORK_ERROR_TEXT;\nConnection.NETWORK_USER = NETWORK_USER;\nConnection.NETWORK_USER_TEXT = NETWORK_USER_TEXT;\n","/**\n * @file Helper methods for dealing with IndexedDB cache of messages, users, and topics.\n *\n * @copyright 2015-2025 Tinode LLC.\n */\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\nconst DB_VERSION = 3;\nconst DB_NAME = 'tinode-web';\n\nlet IDBProvider;\n\nexport default class DB {\n #onError = _ => {};\n #logger = _ => {};\n\n // Instance of IndexDB.\n db = null;\n // Indicator that the cache is disabled.\n disabled = true;\n\n constructor(onError, logger) {\n this.#onError = onError || this.#onError;\n this.#logger = logger || this.#logger;\n }\n\n #mapObjects(source, callback, context) {\n if (!this.db) {\n return disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction([source]);\n trx.onerror = event => {\n this.#logger('PCache', 'mapObjects', source, event.target.error);\n reject(event.target.error);\n };\n trx.objectStore(source).getAll().onsuccess = event => {\n if (callback) {\n event.target.result.forEach(topic => {\n callback.call(context, topic);\n });\n }\n resolve(event.target.result);\n };\n });\n }\n\n /**\n * Initialize persistent cache: open or create/upgrade if needed.\n * @returns {Promise} promise to be resolved/rejected when the DB is initialized.\n */\n initDatabase() {\n return new Promise((resolve, reject) => {\n // Open the database and initialize callbacks.\n const req = IDBProvider.open(DB_NAME, DB_VERSION);\n req.onsuccess = event => {\n this.db = event.target.result;\n this.disabled = false;\n\n // This handler is called when a different tab tries to upgrade the database.\n this.db.onversionchange = _ => {\n this.#logger('PCache', \"another tab tries to upgrade DB, shutting down\");\n this.db.close();\n this.db = null;\n this.disabled = true;\n };\n\n resolve(this.db);\n };\n req.onerror = event => {\n this.#logger('PCache', \"failed to initialize\", event);\n reject(event.target.error);\n this.#onError(event.target.error);\n };\n req.onupgradeneeded = event => {\n this.db = event.target.result;\n\n this.db.onerror = event => {\n this.#logger('PCache', \"failed to create storage\", event);\n this.#onError(event.target.error);\n };\n\n // Individual object stores.\n\n // Alternatively could use event.oldVersion and event.newVersion\n // to determine which object stores to create or upgrade.\n\n if (!this.db.objectStoreNames.contains('topic')) {\n // Object store (table) for topics. The primary key is the topic name.\n this.db.createObjectStore('topic', {\n keyPath: 'name'\n });\n }\n\n if (!this.db.objectStoreNames.contains('user')) {\n // Users object store. UID is the primary key.\n this.db.createObjectStore('user', {\n keyPath: 'uid'\n });\n }\n\n if (!this.db.objectStoreNames.contains('subscription')) {\n // Subscriptions object store topic <-> user. Topic name + UID is the primary key.\n this.db.createObjectStore('subscription', {\n keyPath: ['topic', 'uid']\n });\n }\n\n if (!this.db.objectStoreNames.contains('message')) {\n // Messages object store. The primary key is topic name + seq.\n this.db.createObjectStore('message', {\n keyPath: ['topic', 'seq']\n });\n }\n\n if (!this.db.objectStoreNames.contains('dellog')) {\n // Records of deleted message ranges. The primary key is topic name + low seq.\n const dellog = this.db.createObjectStore('dellog', {\n keyPath: ['topic', 'low', 'hi']\n });\n if (!dellog.indexNames.contains('topic_clear')) {\n dellog.createIndex('topic_clear', ['topic', 'clear'], {\n unique: false\n });\n }\n }\n }\n });\n }\n\n /**\n * Delete persistent cache.\n */\n deleteDatabase() {\n // Close connection, otherwise operations will fail with 'onblocked'.\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n return new Promise((resolve, reject) => {\n const req = IDBProvider.deleteDatabase(DB_NAME);\n req.onblocked = _ => {\n if (this.db) {\n this.db.close();\n }\n const err = new Error(\"blocked\");\n this.#logger('PCache', 'deleteDatabase', err);\n reject(err);\n };\n req.onsuccess = _ => {\n this.db = null;\n this.disabled = true;\n resolve(true);\n };\n req.onerror = event => {\n this.#logger('PCache', 'deleteDatabase', event.target.error);\n reject(event.target.error);\n };\n });\n }\n\n /**\n * Check if persistent cache is ready for use.\n * @memberOf DB\n * @returns {boolean} true if cache is ready, false otherwise.\n */\n isReady() {\n return !!this.db;\n }\n\n // Topics.\n\n /**\n * Save to cache or update topic in persistent cache.\n * @memberOf DB\n * @param {Topic} topic - topic to be added or updated.\n * @returns {Promise} promise resolved/rejected on operation completion.\n */\n updTopic(topic) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['topic'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updTopic', event.target.error);\n reject(event.target.error);\n };\n const req = trx.objectStore('topic').get(topic.name);\n req.onsuccess = _ => {\n trx.objectStore('topic').put(DB.#serializeTopic(req.result, topic));\n trx.commit();\n };\n });\n }\n\n /**\n * Mark or unmark topic as deleted.\n * @memberOf DB\n * @param {string} name - name of the topic to mark or unmark.\n * @param {boolean} deleted - status\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n markTopicAsDeleted(name, deleted) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['topic'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'markTopicAsDeleted', event.target.error);\n reject(event.target.error);\n };\n const req = trx.objectStore('topic').get(name);\n req.onsuccess = event => {\n const topic = event.target.result;\n if (topic && topic._deleted != deleted) {\n topic._deleted = deleted;\n trx.objectStore('topic').put(topic);\n }\n trx.commit();\n };\n });\n }\n\n /**\n * Remove topic from persistent cache.\n * @memberOf DB\n * @param {string} name - name of the topic to remove from database.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n remTopic(name) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['topic', 'subscription', 'message'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'remTopic', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('topic').delete(IDBKeyRange.only(name));\n trx.objectStore('subscription').delete(IDBKeyRange.bound([name, '-'], [name, '~']));\n trx.objectStore('message').delete(IDBKeyRange.bound([name, 0], [name, Number.MAX_SAFE_INTEGER]));\n trx.commit();\n });\n }\n\n /**\n * Execute a callback for each stored topic.\n * @memberOf DB\n * @param {function} callback - function to call for each topic.\n * @param {Object} context - the value or this inside the callback.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n mapTopics(callback, context) {\n return this.#mapObjects('topic', callback, context);\n }\n\n /**\n * Copy data from serialized object to topic.\n * @memberOf DB\n * @param {Topic} topic - target to deserialize to.\n * @param {Object} src - serialized data to copy from.\n */\n deserializeTopic(topic, src) {\n DB.#deserializeTopic(topic, src);\n }\n\n // Users.\n /**\n * Add or update user object in the persistent cache.\n * @memberOf DB\n * @param {string} uid - ID of the user to save or update.\n * @param {Object} pub - user's public information.\n * @returns {Promise} promise resolved/rejected on operation completion.\n */\n updUser(uid, pub) {\n if (arguments.length < 2 || pub === undefined) {\n // No point inupdating user with invalid data.\n return;\n }\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['user'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updUser', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('user').put({\n uid: uid,\n public: pub\n });\n trx.commit();\n });\n }\n\n /**\n * Remove user from persistent cache.\n * @memberOf DB\n * @param {string} uid - ID of the user to remove from the cache.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n remUser(uid) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['user'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'remUser', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('user').delete(IDBKeyRange.only(uid));\n trx.commit();\n });\n }\n\n /**\n * Execute a callback for each stored user.\n * @memberOf DB\n * @param {function} callback - function to call for each topic.\n * @param {Object} context - the value or this inside the callback.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n mapUsers(callback, context) {\n return this.#mapObjects('user', callback, context);\n }\n\n /**\n * Read a single user from persistent cache.\n * @memberOf DB\n * @param {string} uid - ID of the user to fetch from cache.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n getUser(uid) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['user']);\n trx.oncomplete = event => {\n const user = event.target.result;\n resolve({\n user: user.uid,\n public: user.public\n });\n };\n trx.onerror = event => {\n this.#logger('PCache', 'getUser', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('user').get(uid);\n });\n }\n\n // Subscriptions.\n /**\n * Add or update subscription in persistent cache.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {string} uid - ID of the subscribed user.\n * @param {Object} sub - subscription to save.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n updSubscription(topicName, uid, sub) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['subscription'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updSubscription', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('subscription').get([topicName, uid]).onsuccess = (event) => {\n trx.objectStore('subscription').put(DB.#serializeSubscription(event.target.result, topicName, uid, sub));\n trx.commit();\n };\n });\n }\n\n /**\n * Execute a callback for each cached subscription in a given topic.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the subscriptions.\n * @param {function} callback - function to call for each subscription.\n * @param {Object} context - the value or this inside the callback.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n mapSubscriptions(topicName, callback, context) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['subscription']);\n trx.onerror = (event) => {\n this.#logger('PCache', 'mapSubscriptions', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('subscription').getAll(IDBKeyRange.bound([topicName, '-'], [topicName, '~'])).onsuccess = (event) => {\n if (callback) {\n event.target.result.forEach((topic) => {\n callback.call(context, topic);\n });\n }\n resolve(event.target.result);\n };\n });\n }\n\n // Messages.\n\n /**\n * Save message to persistent cache.\n * @memberOf DB\n * @param {Object} msg - message to save.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n addMessage(msg) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['message'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'addMessage', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('message').add(DB.#serializeMessage(null, msg));\n trx.commit();\n });\n }\n\n /**\n * Update delivery status of a message stored in persistent cache.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {number} seq - ID of the message to update\n * @param {number} status - new delivery status of the message.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n updMessageStatus(topicName, seq, status) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['message'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updMessageStatus', event.target.error);\n reject(event.target.error);\n };\n const req = trx.objectStore('message').get(IDBKeyRange.only([topicName, seq]));\n req.onsuccess = event => {\n const src = req.result || event.target.result;\n if (!src || src._status == status) {\n trx.commit();\n return;\n }\n trx.objectStore('message').put(DB.#serializeMessage(src, {\n topic: topicName,\n seq: seq,\n _status: status\n }));\n trx.commit();\n };\n });\n }\n\n /**\n * Remove one or more messages from persistent cache.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {number} from - id of the message to remove or lower boundary when removing range (inclusive).\n * @param {number=} to - upper boundary (exclusive) when removing a range of messages.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n remMessages(topicName, from, to) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n if (!from && !to) {\n from = 0;\n to = Number.MAX_SAFE_INTEGER;\n }\n const range = to > 0 ? IDBKeyRange.bound([topicName, from], [topicName, to], false, true) :\n IDBKeyRange.only([topicName, from]);\n const trx = this.db.transaction(['message'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'remMessages', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('message').delete(range);\n trx.commit();\n });\n }\n\n /**\n * Retrieve messages from persistent store.\n * @memberOf DB\n * @param {string} topicName - name of the topic to retrieve messages from.\n * @param {function} callback to call for each retrieved message.\n * @param {GetDataType} query - parameters of the message range to retrieve.\n *\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n readMessages(topicName, query, callback, context) {\n query = query || {};\n\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n const trx = this.db.transaction(['message']);\n let result = [];\n\n // Handle individual message ranges.\n if (Array.isArray(query.ranges)) {\n return new Promise((resolve, reject) => {\n trx.onerror = event => {\n this.#logger('PCache', 'readMessages', event.target.error);\n reject(event.target.error);\n };\n\n let count = 0;\n query.ranges.forEach(range => {\n const key = range.hi ? IDBKeyRange.bound([topicName, range.low], [topicName, range.hi], false, true) :\n IDBKeyRange.only([topicName, range.low]);\n trx.objectStore('message').getAll(key).onsuccess = event => {\n const msgs = event.target.result;\n if (msgs) {\n if (callback) {\n callback.call(context, msgs);\n }\n if (Array.isArray(msgs)) {\n result = result.concat(msgs);\n } else {\n result.push(msgs);\n }\n }\n count++;\n if (count == query.ranges.length) {\n resolve(result);\n }\n };\n });\n });\n }\n\n // Handle single range.\n return new Promise((resolve, reject) => {\n const since = query.since > 0 ? query.since : 0;\n const before = query.before > 0 ? query.before : Number.MAX_SAFE_INTEGER;\n const limit = query.limit | 0;\n\n trx.onerror = event => {\n this.#logger('PCache', 'readMessages', event.target.error);\n reject(event.target.error);\n };\n\n const range = IDBKeyRange.bound([topicName, since], [topicName, before], false, true);\n // Iterate in descending order.\n trx.objectStore('message').openCursor(range, 'prev')\n .onsuccess = event => {\n const cursor = event.target.result;\n if (cursor) {\n if (callback) {\n callback.call(context, cursor.value);\n }\n result.push(cursor.value);\n if (limit <= 0 || result.length < limit) {\n cursor.continue();\n } else {\n resolve(result);\n }\n } else {\n resolve(result);\n }\n };\n });\n }\n\n // Delete log\n\n /**\n * Add records of deleted messages.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {number} delId - id of the deletion transaction.\n * @param {Array.} ranges - message to save.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n addDelLog(topicName, delId, ranges) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['dellog'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'addDelLog', event.target.error);\n reject(event.target.error);\n };\n ranges.forEach(r => trx.objectStore('dellog').add({\n topic: topicName,\n clear: delId,\n low: r.low,\n hi: r.hi || (r.low + 1)\n }));\n trx.commit();\n });\n }\n\n /**\n * Retrieve deleted message records from persistent store.\n * @memberOf DB\n * @param {string} topicName - name of the topic to retrieve records for.\n * @param {GetDataType} query - parameters of the message range to retrieve.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n readDelLog(topicName, query) {\n query = query || {};\n\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n const trx = this.db.transaction(['dellog']);\n let result = [];\n\n // Handle individual message ranges.\n if (Array.isArray(query.ranges)) {\n return new Promise((resolve, reject) => {\n trx.onerror = event => {\n this.#logger('PCache', 'readDelLog', event.target.error);\n reject(event.target.error);\n };\n\n let count = 0;\n query.ranges.forEach(range => {\n const hi = range.hi || (range.low + 1);\n const key = IDBKeyRange.bound([topicName, 0, range.low], [topicName, hi, Number.MAX_SAFE_INTEGER], false, true);\n trx.objectStore('dellog').getAll(key).onsuccess = event => {\n const entries = event.target.result;\n if (entries) {\n if (Array.isArray(entries)) {\n result = result.concat(entries.map(entry => {\n return {\n low: entry.low,\n hi: entry.hi\n };\n }));\n } else {\n result.push({\n low: entries.low,\n hi: entries.hi\n });\n }\n }\n count++;\n if (count == query.ranges.length) {\n resolve(result);\n }\n };\n });\n });\n }\n\n return new Promise((resolve, reject) => {\n const since = query.since > 0 ? query.since : 0;\n const before = query.before > 0 ? query.before : Number.MAX_SAFE_INTEGER;\n const limit = query.limit | 0;\n\n trx.onerror = event => {\n this.#logger('PCache', 'readDelLog', event.target.error);\n reject(event.target.error);\n };\n\n let count = 0;\n const result = [];\n const range = IDBKeyRange.bound([topicName, 0, since], [topicName, before, Number.MAX_SAFE_INTEGER], false, true);\n trx.objectStore('dellog').openCursor(range, 'prev')\n .onsuccess = event => {\n const cursor = event.target.result;\n if (cursor) {\n result.push({\n low: cursor.value.low,\n hi: cursor.value.hi\n });\n count += cursor.value.hi - cursor.value.low;\n if (limit <= 0 || count < limit) {\n cursor.continue();\n } else {\n resolve(result);\n }\n } else {\n resolve(result);\n }\n };\n });\n }\n\n /**\n * Retrieve the latest 'clear' ID for the given topic.\n * @param {string} topicName\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n maxDelId(topicName) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve(0) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['dellog']);\n trx.onerror = event => {\n this.#logger('PCache', 'maxDelId', event.target.error);\n reject(event.target.error);\n };\n\n const index = trx.objectStore('dellog').index('topic_clear');\n index.openCursor(IDBKeyRange.bound([topicName, 0], [topicName, Number.MAX_SAFE_INTEGER]), 'prev')\n .onsuccess = event => {\n if (event.target.result) {\n resolve(event.target.result.value);\n }\n };\n });\n }\n\n // Private methods.\n\n // Serializable topic fields.\n static #topic_fields = ['created', 'updated', 'deleted', 'touched', 'read', 'recv', 'seq',\n 'clear', 'defacs', 'creds', 'public', 'trusted', 'private', '_aux', '_deleted'\n ];\n\n // Copy data from src to Topic object.\n static #deserializeTopic(topic, src) {\n DB.#topic_fields.forEach((f) => {\n if (src.hasOwnProperty(f)) {\n topic[f] = src[f];\n }\n });\n if (Array.isArray(src.tags)) {\n topic._tags = src.tags;\n }\n if (src.acs) {\n topic.setAccessMode(src.acs);\n }\n topic.seq |= 0;\n topic.read |= 0;\n topic.unread = Math.max(0, topic.seq - topic.read);\n }\n\n // Copy values from 'src' to 'dst'. Allocate dst if it's null or undefined.\n static #serializeTopic(dst, src) {\n const res = dst || {\n name: src.name\n };\n DB.#topic_fields.forEach(f => {\n if (src.hasOwnProperty(f)) {\n res[f] = src[f];\n }\n });\n if (Array.isArray(src._tags)) {\n res.tags = src._tags;\n }\n if (src.acs) {\n res.acs = src.getAccessMode().jsonHelper();\n }\n return res;\n }\n\n static #serializeSubscription(dst, topicName, uid, sub) {\n const fields = ['updated', 'mode', 'read', 'recv', 'clear', 'lastSeen', 'userAgent'];\n const res = dst || {\n topic: topicName,\n uid: uid\n };\n\n fields.forEach((f) => {\n if (sub.hasOwnProperty(f)) {\n res[f] = sub[f];\n }\n });\n\n return res;\n }\n\n static #serializeMessage(dst, msg) {\n // Serializable fields.\n const fields = ['topic', 'seq', 'ts', '_status', 'from', 'head', 'content'];\n const res = dst || {};\n fields.forEach((f) => {\n if (msg.hasOwnProperty(f)) {\n res[f] = msg[f];\n }\n });\n return res;\n }\n\n /**\n * To use DB in a non browser context, supply indexedDB provider.\n * @static\n * @memberof DB\n * @param idbProvider indexedDB provider, e.g. for node require('fake-indexeddb').\n */\n static setDatabaseProvider(idbProvider) {\n IDBProvider = idbProvider;\n }\n}\n","/**\n * @copyright 2015-2024 Tinode LLC.\n * @summary Minimally rich text representation and formatting for Tinode.\n * @license Apache 2.0\n *\n * @file Basic parser and formatter for very simple text markup. Mostly targeted at\n * mobile use cases similar to Telegram, WhatsApp, and FB Messenger.\n *\n * Supports conversion of user keyboard input to formatted text:
\n * \n * *abc* → abc \n * _abc_ → abc \n * ~abc~ → abc \n * `abc` → abc \n * \n * Also supports forms and buttons.\n *\n * Nested formatting is supported, e.g. *abc _def_* -> abc def \n * URLs, @mentions, and #hashtags are extracted and converted into links.\n * Forms and buttons can be added procedurally.\n * JSON data representation is inspired by Draft.js raw formatting.\n *\n *\n * @example\n * Text:\n * \n * this is *bold*, `code` and _italic_, ~strike~\n * combined *bold and _italic_*\n * an url: https://www.example.com/abc#fragment and another _www.tinode.co_\n * this is a @mention and a #hashtag in a string\n * second #hashtag\n * \n *\n * Sample JSON representation of the text above:\n * {\n * \"txt\": \"this is bold, code and italic, strike combined bold and italic an url: https://www.example.com/abc#fragment \" +\n * \"and another www.tinode.co this is a @mention and a #hashtag in a string second #hashtag\",\n * \"fmt\": [\n * { \"at\":8, \"len\":4,\"tp\":\"ST\" },{ \"at\":14, \"len\":4, \"tp\":\"CO\" },{ \"at\":23, \"len\":6, \"tp\":\"EM\"},\n * { \"at\":31, \"len\":6, \"tp\":\"DL\" },{ \"tp\":\"BR\", \"len\":1, \"at\":37 },{ \"at\":56, \"len\":6, \"tp\":\"EM\" },\n * { \"at\":47, \"len\":15, \"tp\":\"ST\" },{ \"tp\":\"BR\", \"len\":1, \"at\":62 },{ \"at\":120, \"len\":13, \"tp\":\"EM\" },\n * { \"at\":71, \"len\":36, \"key\":0 },{ \"at\":120, \"len\":13, \"key\":1 },{ \"tp\":\"BR\", \"len\":1, \"at\":133 },\n * { \"at\":144, \"len\":8, \"key\":2 },{ \"at\":159, \"len\":8, \"key\":3 },{ \"tp\":\"BR\", \"len\":1, \"at\":179 },\n * { \"at\":187, \"len\":8, \"key\":3 },{ \"tp\":\"BR\", \"len\":1, \"at\":195 }\n * ],\n * \"ent\": [\n * { \"tp\":\"LN\", \"data\":{ \"url\":\"https://www.example.com/abc#fragment\" } },\n * { \"tp\":\"LN\", \"data\":{ \"url\":\"http://www.tinode.co\" } },\n * { \"tp\":\"MN\", \"data\":{ \"val\":\"mention\" } },\n * { \"tp\":\"HT\", \"data\":{ \"val\":\"hashtag\" } }\n * ]\n * }\n */\n\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\nconst MAX_FORM_ELEMENTS = 8;\nconst MAX_PREVIEW_ATTACHMENTS = 3;\nconst MAX_PREVIEW_DATA_SIZE = 64;\nconst JSON_MIME_TYPE = 'application/json';\nconst DRAFTY_MIME_TYPE = 'text/x-drafty';\nconst ALLOWED_ENT_FIELDS = ['act', 'height', 'duration', 'incoming', 'mime', 'name', 'premime', 'preref', 'preview',\n 'ref', 'size', 'state', 'url', 'val', 'width'\n];\n\n// Intl.Segmenter is not available in Firefox 124 and earlier. FF 125 with support for Intl.Segmenter\n// was released on April 15, 2024. Polyfill is included in the top package (webapp).\nconst segmenter = new Intl.Segmenter();\n\n// Regular expressions for parsing inline formats. Javascript does not support lookbehind,\n// so it's a bit messy.\nconst INLINE_STYLES = [\n // Strong = bold, *bold text*\n {\n name: 'ST',\n start: /(?:^|[\\W_])(\\*)[^\\s*]/,\n end: /[^\\s*](\\*)(?=$|[\\W_])/\n },\n // Emphesized = italic, _italic text_\n {\n name: 'EM',\n start: /(?:^|\\W)(_)[^\\s_]/,\n end: /[^\\s_](_)(?=$|\\W)/\n },\n // Deleted, ~strike this though~\n {\n name: 'DL',\n start: /(?:^|[\\W_])(~)[^\\s~]/,\n end: /[^\\s~](~)(?=$|[\\W_])/\n },\n // Code block `this is monospace`\n {\n name: 'CO',\n start: /(?:^|\\W)(`)[^`]/,\n end: /[^`](`)(?=$|\\W)/\n }\n];\n\n// Relative weights of formatting spans. Greater index in array means greater weight.\nconst FMT_WEIGHT = ['QQ'];\n\n// RegExps for entity extraction (RF = reference)\nconst ENTITY_TYPES = [\n // URLs\n {\n name: 'LN',\n dataName: 'url',\n pack: function(val) {\n // Check if the protocol is specified, if not use http\n if (!/^[a-z]+:\\/\\//i.test(val)) {\n val = 'http://' + val;\n }\n return {\n url: val\n };\n },\n re: /(?:(?:https?|ftp):\\/\\/|www\\.|ftp\\.)[-A-Z0-9+&@#\\/%=~_|$?!:,.]*[A-Z0-9+&@#\\/%=~_|$]/ig\n },\n // Mentions @user (must be 2 or more characters)\n {\n name: 'MN',\n dataName: 'val',\n pack: function(val) {\n return {\n val: val.slice(1)\n };\n },\n re: /\\B@([\\p{L}\\p{N}][._\\p{L}\\p{N}]*[\\p{L}\\p{N}])/ug\n },\n // Hashtags #hashtag, like metion 2 or more characters.\n {\n name: 'HT',\n dataName: 'val',\n pack: function(val) {\n return {\n val: val.slice(1)\n };\n },\n re: /\\B#([\\p{L}\\p{N}][._\\p{L}\\p{N}]*[\\p{L}\\p{N}])/ug\n }\n];\n\n// HTML tag name suggestions\nconst FORMAT_TAGS = {\n AU: {\n html_tag: 'audio',\n md_tag: undefined,\n isVoid: false\n },\n BN: {\n html_tag: 'button',\n md_tag: undefined,\n isVoid: false\n },\n BR: {\n html_tag: 'br',\n md_tag: '\\n',\n isVoid: true\n },\n CO: {\n html_tag: 'tt',\n md_tag: '`',\n isVoid: false\n },\n DL: {\n html_tag: 'del',\n md_tag: '~',\n isVoid: false\n },\n EM: {\n html_tag: 'i',\n md_tag: '_',\n isVoid: false\n },\n EX: {\n html_tag: '',\n md_tag: undefined,\n isVoid: true\n },\n FM: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false\n },\n HD: {\n html_tag: '',\n md_tag: undefined,\n isVoid: false\n },\n HL: {\n html_tag: 'span',\n md_tag: undefined,\n isVoid: false\n },\n HT: {\n html_tag: 'a',\n md_tag: undefined,\n isVoid: false\n },\n IM: {\n html_tag: 'img',\n md_tag: undefined,\n isVoid: false\n },\n LN: {\n html_tag: 'a',\n md_tag: undefined,\n isVoid: false\n },\n MN: {\n html_tag: 'a',\n md_tag: undefined,\n isVoid: false\n },\n RW: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false,\n },\n QQ: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false\n },\n ST: {\n html_tag: 'b',\n md_tag: '*',\n isVoid: false\n },\n VC: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false\n },\n VD: {\n html_tag: 'video',\n md_tag: undefined,\n isVoid: false\n }\n};\n\n// Convert base64-encoded string into Blob.\nfunction base64toObjectUrl(b64, contentType, logger) {\n if (!b64) {\n return null;\n }\n\n try {\n const bin = atob(b64);\n const length = bin.length;\n const buf = new ArrayBuffer(length);\n const arr = new Uint8Array(buf);\n for (let i = 0; i < length; i++) {\n arr[i] = bin.charCodeAt(i);\n }\n\n return URL.createObjectURL(new Blob([buf], {\n type: contentType\n }));\n } catch (err) {\n if (logger) {\n logger(\"Drafty: failed to convert object.\", err.message);\n }\n }\n\n return null;\n}\n\nfunction base64toDataUrl(b64, contentType) {\n if (!b64) {\n return null;\n }\n contentType = contentType || 'image/jpeg';\n return 'data:' + contentType + ';base64,' + b64;\n}\n\n// Helpers for converting Drafty to HTML.\nconst DECORATORS = {\n // Visial styles\n ST: {\n open: _ => '',\n close: _ => ' '\n },\n EM: {\n open: _ => '',\n close: _ => ' '\n },\n DL: {\n open: _ => '',\n close: _ => ''\n },\n CO: {\n open: _ => '',\n close: _ => ' '\n },\n // Line break\n BR: {\n open: _ => ' ',\n close: _ => ''\n },\n // Hidden element\n HD: {\n open: _ => '',\n close: _ => ''\n },\n // Highlighted element.\n HL: {\n open: _ => '',\n close: _ => ' '\n },\n // Link (URL)\n LN: {\n open: (data) => {\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n return data ? {\n href: data.url,\n target: '_blank'\n } : null;\n },\n },\n // Mention\n MN: {\n open: (data) => {\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n return data ? {\n id: data.val\n } : null;\n },\n },\n // Hashtag\n HT: {\n open: (data) => {\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n return data ? {\n id: data.val\n } : null;\n },\n },\n // Button\n BN: {\n open: _ => '',\n close: _ => ' ',\n props: (data) => {\n return data ? {\n 'data-act': data.act,\n 'data-val': data.val,\n 'data-name': data.name,\n 'data-ref': data.ref\n } : null;\n },\n },\n // Audio recording\n AU: {\n open: (data) => {\n const url = data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger);\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n if (!data) return null;\n return {\n // Embedded data or external link.\n src: data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger),\n 'data-preload': data.ref ? 'metadata' : 'auto',\n 'data-duration': data.duration,\n 'data-name': data.name,\n 'data-size': data.val ? ((data.val.length * 0.75) | 0) : (data.size | 0),\n 'data-mime': data.mime,\n };\n }\n },\n // Image\n IM: {\n open: data => {\n // Don't use data.ref for preview: it's a security risk.\n const tmpPreviewUrl = base64toDataUrl(data._tempPreview, data.mime);\n const previewUrl = base64toObjectUrl(data.val, data.mime, Drafty.logger);\n const downloadUrl = data.ref || previewUrl;\n return (data.name ? '' : '') +\n ' ';\n },\n close: data => {\n return (data.name ? ' ' : '');\n },\n props: data => {\n if (!data) return null;\n return {\n // Temporary preview, or permanent preview, or external link.\n src: base64toDataUrl(data._tempPreview, data.mime) ||\n data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger),\n title: data.name,\n alt: data.name,\n 'data-width': data.width,\n 'data-height': data.height,\n 'data-name': data.name,\n 'data-size': data.ref ? (data.size | 0) : (data.val ? ((data.val.length * 0.75) | 0) : (data.size | 0)),\n 'data-mime': data.mime,\n };\n },\n },\n // Form - structured layout of elements.\n FM: {\n open: _ => '',\n close: _ => '
'\n },\n // Row: logic grouping of elements\n RW: {\n open: _ => '',\n close: _ => '
'\n },\n // Quoted block.\n QQ: {\n open: _ => '',\n close: _ => '
',\n props: (data) => {\n return data ? {} : null;\n },\n },\n // Video call\n VC: {\n open: _ => '',\n close: _ => '
',\n props: data => {\n if (!data) return {};\n return {\n 'data-duration': data.duration,\n 'data-state': data.state,\n };\n }\n },\n // Video.\n VD: {\n open: data => {\n const tmpPreviewUrl = base64toDataUrl(data._tempPreview, data.mime);\n const previewUrl = data.ref || base64toObjectUrl(data.preview, data.premime || 'image/jpeg', Drafty.logger);\n return ' ';\n },\n close: _ => '',\n props: data => {\n if (!data) return null;\n const poster = data.preref || base64toObjectUrl(data.preview, data.premime || 'image/jpeg', Drafty.logger);\n return {\n // Embedded data or external link.\n src: poster,\n 'data-src': data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger),\n 'data-width': data.width,\n 'data-height': data.height,\n 'data-preload': data.ref ? 'metadata' : 'auto',\n 'data-preview': poster,\n 'data-duration': data.duration | 0,\n 'data-name': data.name,\n 'data-size': data.ref ? (data.size | 0) : (data.val ? ((data.val.length * 0.75) | 0) : (data.size | 0)),\n 'data-mime': data.mime,\n };\n }\n },\n};\n\n/**\n * The main object which performs all the formatting actions.\n * @class Drafty\n * @constructor\n */\nconst Drafty = function() {\n this.txt = '';\n this.fmt = [];\n this.ent = [];\n}\n\n/**\n * Initialize Drafty document to a plain text string.\n *\n * @param {string} plainText - string to use as Drafty content.\n *\n * @returns new Drafty document or null is plainText is not a string or undefined.\n */\nDrafty.init = function(plainText) {\n if (typeof plainText == 'undefined') {\n plainText = '';\n } else if (typeof plainText != 'string') {\n return null;\n }\n\n return {\n txt: plainText\n };\n}\n\n/**\n * Parse plain text into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {string} content - plain-text content to parse.\n * @return {Drafty} parsed document or null if the source is not plain text.\n */\nDrafty.parse = function(content) {\n // Make sure we are parsing strings only.\n if (typeof content != 'string') {\n return null;\n }\n\n // Split text into lines. It makes further processing easier.\n const lines = content.split(/\\r?\\n/);\n\n // Holds entities referenced from text\n const entityMap = [];\n const entityIndex = {};\n\n // Processing lines one by one, hold intermediate result in blx.\n const blx = [];\n lines.forEach((line) => {\n let spans = [];\n let entities;\n\n // Find formatted spans in the string.\n // Try to match each style.\n INLINE_STYLES.forEach((tag) => {\n // Each style could be matched multiple times.\n spans = spans.concat(spannify(line, tag.start, tag.end, tag.name));\n });\n\n let block;\n if (spans.length == 0) {\n block = {\n txt: line\n };\n } else {\n // Sort spans by style occurence early -> late, then by length: first long then short.\n spans.sort((a, b) => {\n const diff = a.at - b.at;\n return diff != 0 ? diff : b.end - a.end;\n });\n\n // Convert an array of possibly overlapping spans into a tree.\n spans = toSpanTree(spans);\n\n // Build a tree representation of the entire string, not\n // just the formatted parts.\n const chunks = chunkify(line, 0, line.length, spans);\n\n const drafty = draftify(chunks, 0);\n\n block = {\n txt: drafty.txt,\n fmt: drafty.fmt\n };\n }\n\n // Extract entities from the cleaned up string.\n entities = extractEntities(block.txt);\n if (entities.length > 0) {\n const ranges = [];\n for (let i in entities) {\n // {offset: match['index'], unique: match[0], len: match[0].length, data: ent.packer(), type: ent.name}\n const entity = entities[i];\n let index = entityIndex[entity.unique];\n if (!index) {\n index = entityMap.length;\n entityIndex[entity.unique] = index;\n entityMap.push({\n tp: entity.type,\n data: entity.data\n });\n }\n ranges.push({\n at: entity.offset,\n len: entity.len,\n key: index\n });\n }\n block.ent = ranges;\n }\n\n blx.push(block);\n });\n\n const result = {\n txt: ''\n };\n\n // Merge lines and save line breaks as BR inline formatting.\n if (blx.length > 0) {\n result.txt = blx[0].txt;\n result.fmt = (blx[0].fmt || []).concat(blx[0].ent || []);\n\n if (result.fmt.length) {\n const segments = segmenter.segment(result.txt);\n for (const ele of result.fmt) {\n ({\n at: ele.at,\n len: ele.len\n } =\n toGraphemeValues(ele, segments, result.txt));\n }\n }\n\n for (let i = 1; i < blx.length; i++) {\n const block = blx[i];\n const offset = stringToGraphemes(result.txt).length + 1;\n\n result.fmt.push({\n tp: 'BR',\n len: 1,\n at: offset - 1\n });\n\n let segments = {};\n\n result.txt += ' ' + block.txt;\n if (block.fmt) {\n segments = segmenter.segment(block.txt);\n result.fmt = result.fmt.concat(\n block.fmt.map((s) => {\n const {\n at: correctAt,\n len: correctLen\n } =\n toGraphemeValues(s, segments, block.txt);\n s.at = correctAt + offset;\n s.len = correctLen;\n return s;\n })\n );\n }\n if (block.ent) {\n if (isEmptyObject(segments)) {\n segments = segmenter.segment(block.txt);\n }\n result.fmt = result.fmt.concat(\n block.ent.map((s) => {\n const {\n at: correctAt,\n len: correctLen\n } =\n toGraphemeValues(s, segments, block.txt);\n s.at = correctAt + offset;\n s.len = correctLen;\n return s;\n })\n );\n }\n }\n\n if (result.fmt.length == 0) {\n delete result.fmt;\n }\n\n if (entityMap.length > 0) {\n result.ent = entityMap;\n }\n }\n return result;\n}\n\n/**\n * Append one Drafty document to another.\n *\n * @param {Drafty} first - Drafty document to append to.\n * @param {Drafty|string} second - Drafty document or string being appended.\n *\n * @return {Drafty} first document with the second appended to it.\n */\nDrafty.append = function(first, second) {\n if (!first) {\n return second;\n }\n if (!second) {\n return first;\n }\n\n first.txt = first.txt || '';\n const len = stringToGraphemes(first.txt).length;\n\n if (typeof second == 'string') {\n first.txt += second;\n } else if (second.txt) {\n first.txt += second.txt;\n }\n\n if (Array.isArray(second.fmt)) {\n first.fmt = first.fmt || [];\n if (Array.isArray(second.ent)) {\n first.ent = first.ent || [];\n }\n second.fmt.forEach(src => {\n const fmt = {\n at: (src.at | 0) + len,\n len: src.len | 0\n };\n // Special case for the outside of the normal rendering flow styles.\n if (src.at == -1) {\n fmt.at = -1;\n fmt.len = 0;\n }\n if (src.tp) {\n fmt.tp = src.tp;\n } else {\n fmt.key = first.ent.length;\n first.ent.push(second.ent[src.key || 0]);\n }\n first.fmt.push(fmt);\n });\n }\n\n return first;\n}\n\n/**\n * Description of an image to attach.\n * @typedef {Object} ImageDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the image, e.g. \"image/png\".\n * @property {string} refurl - reference to the content. Could be null/undefined.\n * @property {string} bits - base64-encoded image content. Could be null/undefined.\n * @property {string} preview - base64-encoded thumbnail of the image.\n * @property {integer} width - width of the image.\n * @property {integer} height - height of the image.\n * @property {string} filename - file name suggestion for downloading the image.\n * @property {integer} size - size of the image in bytes. Treat is as an untrusted hint.\n * @property {string} _tempPreview - base64-encoded image preview used during upload process; not serializable.\n * @property {Promise} urlPromise - Promise which returns content URL when resolved.\n */\n\n/**\n * Insert inline image into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add image to.\n * @param {integer} at - index where the object is inserted. The length of the image is always 1.\n * @param {ImageDesc} imageDesc - object with image paramenets and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertImage = function(content, at, imageDesc) {\n content = content || {\n txt: ' '\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: 1,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'IM',\n data: {\n mime: imageDesc.mime,\n ref: imageDesc.refurl,\n val: imageDesc.bits || imageDesc.preview,\n width: imageDesc.width,\n height: imageDesc.height,\n name: imageDesc.filename,\n size: imageDesc.size | 0,\n }\n };\n\n if (imageDesc.urlPromise) {\n ex.data._tempPreview = imageDesc._tempPreview;\n ex.data._processing = true;\n imageDesc.urlPromise.then(\n url => {\n ex.data.ref = url;\n ex.data._tempPreview = undefined;\n ex.data._processing = undefined;\n },\n _ => {\n // Catch the error, otherwise it will appear in the console.\n ex.data._processing = undefined;\n }\n );\n }\n\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Description of a video to attach.\n * @typedef {Object} VideoDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the video, e.g. \"video/mpeg\".\n * @property {string} refurl - reference to the content. Could be null/undefined.\n * @property {string} bits - in-band base64-encoded image data. Could be null/undefined.\n * @property {string} preview - base64-encoded screencapture from the video. Could be null/undefined.\n * @property {string} preref - reference to screencapture from the video. Could be null/undefined.\n * @property {integer} width - width of the video.\n * @property {integer} height - height of the video.\n * @property {integer} duration - duration of the video.\n * @property {string} filename - file name suggestion for downloading the video.\n * @property {integer} size - size of the video in bytes. Treat is as an untrusted hint.\n * @property {string} _tempPreview - base64-encoded screencapture used during upload process; not serializable.\n * @property {Promise} urlPromise - array of two promises, which return URLs of video and preview uploads correspondingly\n * (either could be null).\n */\n\n/**\n * Insert inline image into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add video to.\n * @param {integer} at - index where the object is inserted. The length of the video is always 1.\n * @param {VideoDesc} videoDesc - object with video paramenets and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertVideo = function(content, at, videoDesc) {\n content = content || {\n txt: ' '\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: 1,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'VD',\n data: {\n mime: videoDesc.mime,\n ref: videoDesc.refurl,\n val: videoDesc.bits,\n preref: videoDesc.preref,\n preview: videoDesc.preview,\n width: videoDesc.width,\n height: videoDesc.height,\n duration: videoDesc.duration | 0,\n name: videoDesc.filename,\n size: videoDesc.size | 0,\n }\n };\n\n if (videoDesc.urlPromise) {\n ex.data._tempPreview = videoDesc._tempPreview;\n ex.data._processing = true;\n videoDesc.urlPromise.then(\n urls => {\n ex.data.ref = urls[0];\n ex.data.preref = urls[1];\n ex.data._tempPreview = undefined;\n ex.data._processing = undefined;\n },\n _ => {\n // Catch the error, otherwise it will appear in the console.\n ex.data._processing = undefined;\n }\n );\n }\n\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Description of an audio recording to attach.\n * @typedef {Object} AudioDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the audio, e.g. \"audio/ogg\".\n * @property {string} refurl - reference to the content. Could be null/undefined.\n * @property {string} bits - base64-encoded audio content. Could be null/undefined.\n * @property {integer} duration - duration of the record in milliseconds.\n * @property {string} preview - base64 encoded short array of amplitude values 0..100.\n * @property {string} filename - file name suggestion for downloading the audio.\n * @property {integer} size - size of the recording in bytes. Treat is as an untrusted hint.\n * @property {Promise} urlPromise - Promise which returns content URL when resolved.\n */\n\n/**\n * Insert audio recording into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add audio record to.\n * @param {integer} at - index where the object is inserted. The length of the record is always 1.\n * @param {AudioDesc} audioDesc - object with the audio paramenets and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertAudio = function(content, at, audioDesc) {\n content = content || {\n txt: ' '\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: 1,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'AU',\n data: {\n mime: audioDesc.mime,\n val: audioDesc.bits,\n duration: audioDesc.duration | 0,\n preview: audioDesc.preview,\n name: audioDesc.filename,\n size: audioDesc.size | 0,\n ref: audioDesc.refurl\n }\n };\n\n if (audioDesc.urlPromise) {\n ex.data._processing = true;\n audioDesc.urlPromise.then(\n url => {\n ex.data.ref = url;\n ex.data._processing = undefined;\n },\n _ => {\n // Catch the error, otherwise it will appear in the console.\n ex.data._processing = undefined;\n }\n );\n }\n\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Create a (self-contained) video call Drafty document.\n * @memberof Drafty\n * @static\n * @param {boolean} audioOnly true if the call is initially audio-only.\n * @returns Video Call drafty document.\n */\nDrafty.videoCall = function(audioOnly) {\n const content = {\n txt: ' ',\n fmt: [{\n at: 0,\n len: 1,\n key: 0\n }],\n ent: [{\n tp: 'VC',\n data: {\n aonly: audioOnly\n },\n }]\n };\n return content;\n}\n\n/**\n * Update video call (VC) entity with the new status and duration.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - VC document to update.\n * @param {object} params - new video call parameters.\n * @param {string} params.state - state of video call.\n * @param {number} params.duration - duration of the video call in milliseconds.\n *\n * @returns the same document with update applied.\n */\nDrafty.updateVideoCall = function(content, params) {\n // The video element could be just a format or a format + entity.\n // Must ensure it's the latter first.\n const fmt = ((content || {}).fmt || [])[0];\n if (!fmt) {\n // Unrecognized content.\n return content;\n }\n\n let ent;\n if (fmt.tp == 'VC') {\n // Just a format, convert to format + entity.\n delete fmt.tp;\n fmt.key = 0;\n ent = {\n tp: 'VC'\n };\n content.ent = [ent];\n } else {\n ent = (content.ent || [])[fmt.key | 0];\n if (!ent || ent.tp != 'VC') {\n // Not a VC entity.\n return content;\n }\n }\n ent.data = ent.data || {};\n Object.assign(ent.data, params);\n return content;\n}\n\n/**\n * Create a quote to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {string} header - Quote header (title, etc.).\n * @param {string} uid - UID of the author to mention.\n * @param {Drafty} body - Body of the quoted message.\n *\n * @returns Reply quote Drafty doc with the quote formatting.\n */\nDrafty.quote = function(header, uid, body) {\n const quote = Drafty.append(Drafty.appendLineBreak(Drafty.mention(header, uid)), body);\n\n // Wrap into a quote.\n quote.fmt.push({\n at: 0,\n len: stringToGraphemes(quote.txt).length,\n tp: 'QQ'\n });\n\n return quote;\n}\n\n/**\n * Create a Drafty document with a mention.\n *\n * @param {string} name - mentioned name.\n * @param {string} uid - mentioned user ID.\n *\n * @returns {Drafty} document with the mention.\n */\nDrafty.mention = function(name, uid) {\n return {\n txt: name || '',\n fmt: [{\n at: 0,\n len: stringToGraphemes(name || '').length,\n key: 0\n }],\n ent: [{\n tp: 'MN',\n data: {\n val: uid\n }\n }]\n };\n}\n\n/**\n * Append a link to a Drafty document.\n *\n * @param {Drafty} content - Drafty document to append link to.\n * @param {Object} linkData - Link info in format {txt: 'ankor text', url: 'http://...'}.\n *\n * @returns {Drafty} the same document as content.\n */\nDrafty.appendLink = function(content, linkData) {\n content = content || {\n txt: ''\n };\n\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: content.txt.length,\n len: linkData.txt.length,\n key: content.ent.length\n });\n content.txt += linkData.txt;\n\n const ex = {\n tp: 'LN',\n data: {\n url: linkData.url\n }\n }\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Append image to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add image to.\n * @param {ImageDesc} imageDesc - object with image paramenets.\n *\n * @return {Drafty} updated document.\n */\nDrafty.appendImage = function(content, imageDesc) {\n content = content || {\n txt: ''\n };\n content.txt += ' ';\n return Drafty.insertImage(content, content.txt.length - 1, imageDesc);\n}\n\n/**\n * Append audio recodring to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add recording to.\n * @param {AudioDesc} audioDesc - object with audio data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.appendAudio = function(content, audioDesc) {\n content = content || {\n txt: ''\n };\n content.txt += ' ';\n return Drafty.insertAudio(content, content.txt.length - 1, audioDesc);\n}\n\n/**\n * Description of a file to attach.\n * @typedef {Object} AttachmentDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the attachment, e.g. \"application/octet-stream\"\n * @property {string} data - base64-encoded in-band content of small attachments. Could be null/undefined.\n * @property {string} filename - file name suggestion for downloading the attachment.\n * @property {integer} size - size of the file in bytes. Treat is as an untrusted hint.\n * @property {string} refurl - reference to the out-of-band content. Could be null/undefined.\n * @property {Promise} urlPromise - Promise which returns content URL when resolved.\n */\n\n/**\n * Attach file to Drafty content. Either as a blob or as a reference.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to attach file to.\n * @param {AttachmentDesc} object - containing attachment description and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.attachFile = function(content, attachmentDesc) {\n content = content || {\n txt: ''\n };\n\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: -1,\n len: 0,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'EX',\n data: {\n mime: attachmentDesc.mime,\n val: attachmentDesc.data,\n name: attachmentDesc.filename,\n ref: attachmentDesc.refurl,\n size: attachmentDesc.size | 0\n }\n }\n if (attachmentDesc.urlPromise) {\n ex.data._processing = true;\n attachmentDesc.urlPromise.then(\n url => {\n ex.data.ref = url;\n ex.data._processing = undefined;\n },\n _ => {\n /* catch the error, otherwise it will appear in the console. */\n ex.data._processing = undefined;\n }\n );\n }\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Wraps drafty document into a simple formatting style.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - document or string to wrap into a style.\n * @param {string} style - two-letter style to wrap into.\n * @param {number} at - index where the style starts, default 0.\n * @param {number} len - length of the form content, default all of it.\n *\n * @return {Drafty} updated document.\n */\nDrafty.wrapInto = function(content, style, at, len) {\n if (typeof content == 'string') {\n content = {\n txt: content\n };\n }\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at || 0,\n len: len || content.txt.length,\n tp: style,\n });\n\n return content;\n}\n\n/**\n * Wraps content into an interactive form.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - to wrap into a form.\n * @param {number} at - index where the forms starts.\n * @param {number} len - length of the form content.\n *\n * @return {Drafty} updated document.\n */\nDrafty.wrapAsForm = function(content, at, len) {\n return Drafty.wrapInto(content, 'FM', at, len);\n}\n\n/**\n * Insert clickable button into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - Drafty document to insert button to or a string to be used as button text.\n * @param {number} at - location where the button is inserted.\n * @param {number} len - the length of the text to be used as button title.\n * @param {string} name - the button. Client should return it to the server when the button is clicked.\n * @param {string} actionType - the type of the button, one of 'url' or 'pub'.\n * @param {string} actionValue - the value to return on click:\n * @param {string} refUrl - the URL to go to when the 'url' button is clicked.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertButton = function(content, at, len, name, actionType, actionValue, refUrl) {\n if (typeof content == 'string') {\n content = {\n txt: content\n };\n }\n\n if (!content || !content.txt || content.txt.length < at + len) {\n return null;\n }\n\n if (len <= 0 || ['url', 'pub'].indexOf(actionType) == -1) {\n return null;\n }\n // Ensure refUrl is a string.\n if (actionType == 'url' && !refUrl) {\n return null;\n }\n refUrl = '' + refUrl;\n\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: len,\n key: content.ent.length\n });\n content.ent.push({\n tp: 'BN',\n data: {\n act: actionType,\n val: actionValue,\n ref: refUrl,\n name: name\n }\n });\n\n return content;\n}\n\n/**\n * Append clickable button to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - Drafty document to insert button to or a string to be used as button text.\n * @param {string} title - the text to be used as button title.\n * @param {string} name - the button. Client should return it to the server when the button is clicked.\n * @param {string} actionType - the type of the button, one of 'url' or 'pub'.\n * @param {string} actionValue - the value to return on click:\n * @param {string} refUrl - the URL to go to when the 'url' button is clicked.\n *\n * @return {Drafty} updated document.\n */\nDrafty.appendButton = function(content, title, name, actionType, actionValue, refUrl) {\n content = content || {\n txt: ''\n };\n const at = content.txt.length;\n content.txt += title;\n return Drafty.insertButton(content, at, title.length, name, actionType, actionValue, refUrl);\n}\n\n/**\n * Attach a generic JS object. The object is attached as a json string.\n * Intended for representing a form response.\n *\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - Drafty document to attach file to.\n * @param {Object} data - data to convert to json string and attach.\n * @returns {Drafty} the same document as content.\n */\nDrafty.attachJSON = function(content, data) {\n content = content || {\n txt: ''\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: -1,\n len: 0,\n key: content.ent.length\n });\n\n content.ent.push({\n tp: 'EX',\n data: {\n mime: JSON_MIME_TYPE,\n val: data\n }\n });\n\n return content;\n}\n/**\n * Append line break to a Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - Drafty document to append linebreak to.\n * @returns {Drafty} the same document as content.\n */\nDrafty.appendLineBreak = function(content) {\n content = content || {\n txt: ''\n };\n content.fmt = content.fmt || [];\n content.fmt.push({\n at: stringToGraphemes(content.txt).length,\n len: 1,\n tp: 'BR'\n });\n content.txt += ' ';\n\n return content;\n}\n/**\n * Given Drafty document, convert it to HTML.\n * No attempt is made to strip pre-existing html markup.\n * This is potentially unsafe because content.txt may contain malicious HTML\n * markup.\n * @memberof Tinode.Drafty\n * @static\n *\n * @param {Drafty} doc - document to convert.\n *\n * @returns {string} HTML-representation of content.\n */\nDrafty.UNSAFE_toHTML = function(doc) {\n const tree = draftyToTree(doc);\n const htmlFormatter = function(type, data, values) {\n const tag = DECORATORS[type];\n let result = values ? values.join('') : '';\n if (tag) {\n result = tag.open(data) + result + tag.close(data);\n }\n return result;\n };\n return treeBottomUp(tree, htmlFormatter, 0);\n}\n\n/**\n * Callback for applying custom formatting to a Drafty document.\n * Called once for each style span.\n * @memberof Drafty\n * @static\n *\n * @callback Formatter\n * @param {string} style - style code such as \"ST\" or \"IM\".\n * @param {Object} data - entity's data.\n * @param {Object} values - possibly styled subspans contained in this style span.\n * @param {number} index - index of the element guaranteed to be unique.\n */\n\n/**\n * Convert Drafty document to a representation suitable for display.\n * The context may expose a function getFormatter(style). If it's available\n * it will call it to obtain a formatter for a subtree of styles under the style.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|Object} content - Drafty document to transform.\n * @param {Formatter} formatter - callback which formats individual elements.\n * @param {Object} context - context provided to formatter as this.\n *\n * @return {Object} transformed object\n */\nDrafty.format = function(original, formatter, context) {\n return treeBottomUp(draftyToTree(original), formatter, 0, [], context);\n}\n\n/**\n * Shorten Drafty document making the drafty text no longer than the limit.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @param {number} limit - length in characrets to shorten to.\n * @param {boolean} light - remove heavy data from entities.\n * @returns new shortened Drafty object leaving the original intact.\n */\nDrafty.shorten = function(original, limit, light) {\n let tree = draftyToTree(original);\n tree = shortenTree(tree, limit, '…');\n if (tree && light) {\n tree = lightEntity(tree);\n }\n return treeToDrafty({}, tree, []);\n}\n\n/**\n * Transform Drafty doc for forwarding: strip leading @mention and any leading line breaks or whitespace.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @returns converted Drafty object leaving the original intact.\n */\nDrafty.forwardedContent = function(original) {\n let tree = draftyToTree(original);\n const rmMention = function(node) {\n if (node.type == 'MN') {\n if (!node.parent || !node.parent.type) {\n return null;\n }\n }\n return node;\n }\n // Strip leading mention.\n tree = treeTopDown(tree, rmMention);\n // Remove leading whitespace.\n tree = lTrim(tree);\n // Convert back to Drafty.\n return treeToDrafty({}, tree, []);\n}\n\n/**\n * Prepare Drafty doc for wrapping into QQ as a reply:\n * - Replace forwarding mention with symbol '➦' and remove data (UID).\n * - Remove quoted text completely.\n * - Replace line breaks with spaces.\n * - Strip entities of heavy content.\n * - Move attachments to the end of the document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @param {number} limit - length in characters to shorten to.\n * @returns converted Drafty object leaving the original intact.\n */\nDrafty.replyContent = function(original, limit) {\n const convMNnQQnBR = function(node) {\n if (node.type == 'QQ') {\n return null;\n } else if (node.type == 'MN') {\n if ((!node.parent || !node.parent.type) && (node.text || '').startsWith('➦')) {\n node.text = '➦';\n delete node.children;\n delete node.data;\n }\n } else if (node.type == 'BR') {\n node.text = ' ';\n delete node.type;\n delete node.children;\n }\n return node;\n }\n\n let tree = draftyToTree(original);\n if (!tree) {\n return original;\n }\n\n // Strip leading mention.\n tree = treeTopDown(tree, convMNnQQnBR);\n // Move attachments to the end of the doc.\n tree = attachmentsToEnd(tree, MAX_PREVIEW_ATTACHMENTS);\n // Shorten the doc.\n tree = shortenTree(tree, limit, '…');\n // Strip heavy elements except IM.data['val'] and VD.data['preview'] (have to keep them to generate previews later).\n const filter = node => {\n switch (node.type) {\n case 'IM':\n return ['val'];\n case 'VD':\n return ['preview'];\n }\n return null;\n };\n tree = lightEntity(tree, filter);\n // Convert back to Drafty.\n return treeToDrafty({}, tree, []);\n}\n\n\n/**\n * Generate drafty preview:\n * - Shorten the document.\n * - Strip all heavy entity data leaving just inline styles and entity references.\n * - Replace line breaks with spaces.\n * - Replace content of QQ with a space.\n * - Replace forwarding mention with symbol '➦'.\n * move all attachments to the end of the document and make them visible.\n * The context may expose a function getFormatter(style). If it's available\n * it will call it to obtain a formatter for a subtree of styles under the style.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @param {number} limit - length in characters to shorten to.\n * @param {boolean} forwarding - this a forwarding message preview.\n * @returns new shortened Drafty object leaving the original intact.\n */\nDrafty.preview = function(original, limit, forwarding) {\n let tree = draftyToTree(original);\n\n // Move attachments to the end.\n tree = attachmentsToEnd(tree, MAX_PREVIEW_ATTACHMENTS);\n\n // Convert leading mention to '➦' and replace QQ and BR with a space ' '.\n const convMNnQQnBR = function(node) {\n if (node.type == 'MN') {\n if ((!node.parent || !node.parent.type) && (node.text || '').startsWith('➦')) {\n node.text = '➦';\n delete node.children;\n }\n } else if (node.type == 'QQ') {\n node.text = ' ';\n delete node.children;\n } else if (node.type == 'BR') {\n node.text = ' ';\n delete node.children;\n delete node.type;\n }\n return node;\n }\n tree = treeTopDown(tree, convMNnQQnBR);\n\n tree = shortenTree(tree, limit, '…');\n if (forwarding) {\n // Keep some IM and VD data for preview.\n const filter = {\n IM: ['val'],\n VD: ['preview']\n };\n tree = lightEntity(tree, node => {\n return filter[node.type];\n });\n } else {\n tree = lightEntity(tree);\n }\n\n // Convert back to Drafty.\n return treeToDrafty({}, tree, []);\n}\n\n/**\n * Given Drafty document, convert it to plain text.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to convert to plain text.\n * @returns {string} plain-text representation of the drafty document.\n */\nDrafty.toPlainText = function(content) {\n return typeof content == 'string' ? content : content.txt;\n}\n\n/**\n * Check if the document has no markup and no entities.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - content to check for presence of markup.\n * @returns true is content is plain text, false otherwise.\n */\nDrafty.isPlainText = function(content) {\n return typeof content == 'string' || !(content.fmt || content.ent);\n}\n\n/**\n * Convert document to plain text with markdown. All elements which cannot\n * be represented in markdown are stripped.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to convert to plain text with markdown.\n */\nDrafty.toMarkdown = function(content) {\n let tree = draftyToTree(content);\n const mdFormatter = function(type, _, values) {\n const def = FORMAT_TAGS[type];\n let result = (values ? values.join('') : '');\n if (def) {\n if (def.isVoid) {\n result = def.md_tag || '';\n } else if (def.md_tag) {\n result = def.md_tag + result + def.md_tag;\n }\n }\n return result;\n };\n return treeBottomUp(tree, mdFormatter, 0);\n}\n\n/**\n * Checks if the object represets is a valid Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - content to check for validity.\n * @returns true is content is valid, false otherwise.\n */\nDrafty.isValid = function(content) {\n if (!content) {\n return false;\n }\n\n const {\n txt,\n fmt,\n ent\n } = content;\n\n if (!txt && txt !== '' && !fmt && !ent) {\n return false;\n }\n\n const txt_type = typeof txt;\n if (txt_type != 'string' && txt_type != 'undefined' && txt !== null) {\n return false;\n }\n\n if (typeof fmt != 'undefined' && !Array.isArray(fmt) && fmt !== null) {\n return false;\n }\n\n if (typeof ent != 'undefined' && !Array.isArray(ent) && ent !== null) {\n return false;\n }\n return true;\n}\n\n/**\n * Check if the drafty document has attachments: style EX and outside of normal rendering flow,\n * i.e. at = -1.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to check for attachments.\n * @returns true if there are attachments.\n */\nDrafty.hasAttachments = function(content) {\n if (!Array.isArray(content.fmt)) {\n return false;\n }\n for (let i in content.fmt) {\n const fmt = content.fmt[i];\n if (fmt && fmt.at < 0) {\n const ent = content.ent[fmt.key | 0];\n return ent && ent.tp == 'EX' && ent.data;\n }\n }\n return false;\n}\n\n/**\n * Callback for enumerating entities in a Drafty document.\n * Called once for each entity.\n * @memberof Drafty\n * @static\n *\n * @callback EntityCallback\n * @param {Object} data entity data.\n * @param {string} entity type.\n * @param {number} index entity's index in `content.ent`.\n *\n * @return 'true-ish' to stop processing, 'false-ish' otherwise.\n */\n\n/**\n * Enumerate attachments: style EX and outside of normal rendering flow, i.e. at = -1.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to process for attachments.\n * @param {EntityCallback} callback - callback to call for each attachment.\n * @param {Object} context - value of \"this\" for callback.\n */\nDrafty.attachments = function(content, callback, context) {\n if (!Array.isArray(content.fmt)) {\n return;\n }\n let count = 0;\n for (let i in content.fmt) {\n let fmt = content.fmt[i];\n if (fmt && fmt.at < 0) {\n const ent = content.ent[fmt.key | 0];\n if (ent && ent.tp == 'EX' && ent.data) {\n if (callback.call(context, ent.data, count++, 'EX')) {\n break;\n }\n }\n }\n };\n}\n\n/**\n * Check if the drafty document has entities.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to check for entities.\n * @returns true if there are entities.\n */\nDrafty.hasEntities = function(content) {\n return content.ent && content.ent.length > 0;\n}\n\n/**\n * Enumerate entities. Enumeration stops if callback returns 'true'.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document with entities to enumerate.\n * @param {EntityCallback} callback - callback to call for each entity.\n * @param {Object} context - value of \"this\" for callback.\n *\n */\nDrafty.entities = function(content, callback, context) {\n if (content.ent && content.ent.length > 0) {\n for (let i in content.ent) {\n if (content.ent[i]) {\n if (callback.call(context, content.ent[i].data, i, content.ent[i].tp)) {\n break;\n }\n }\n }\n }\n}\n\n/**\n * Callback for enumerating styles (inline formats) in a Drafty document.\n * Called once for each style.\n * @memberof Drafty\n * @static\n *\n * @callback StyleCallback\n * @param {string} tp - format type.\n * @param {number} at - starting position of the format in text.\n * @param {number} len - extent of the format in characters.\n * @param {number} key - index of the entity if format is a reference.\n * @param {number} index - style's index in `content.fmt`.\n *\n * @return 'true-ish' to stop processing, 'false-ish' otherwise.\n */\n\n/**\n * Enumerate styles (inline formats). Enumeration stops if callback returns 'true'.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document with styles (formats) to enumerate.\n * @param {StyleCallback} callback - callback to call for each format.\n * @param {Object} context - value of \"this\" for callback.\n */\nDrafty.styles = function(content, callback, context) {\n if (content.fmt && content.fmt.length > 0) {\n for (let i in content.fmt) {\n const fmt = content.fmt[i];\n if (fmt) {\n if (callback.call(context, fmt.tp, fmt.at, fmt.len, fmt.key, i)) {\n break;\n }\n }\n }\n }\n}\n\n/**\n * Remove unrecognized fields from entity data\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document with entities to enumerate.\n * @returns content.\n */\nDrafty.sanitizeEntities = function(content) {\n if (content && content.ent && content.ent.length > 0) {\n for (let i in content.ent) {\n const ent = content.ent[i];\n if (ent && ent.data) {\n const data = copyEntData(ent.data);\n if (data) {\n content.ent[i].data = data;\n } else {\n delete content.ent[i].data;\n }\n }\n }\n }\n return content;\n}\n\n/**\n * Given the entity, get URL which can be used for downloading\n * entity data.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entData - entity.data to get the URl from.\n * @returns {string} URL to download entity data or null.\n */\nDrafty.getDownloadUrl = function(entData) {\n let url = null;\n if (entData.mime != JSON_MIME_TYPE && entData.val) {\n url = base64toObjectUrl(entData.val, entData.mime, Drafty.logger);\n } else if (typeof entData.ref == 'string') {\n url = entData.ref;\n }\n return url;\n}\n\n/**\n * Check if the entity data is not ready for sending, such as being uploaded to the server.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entity.data to get the URl from.\n * @returns {boolean} true if upload is in progress, false otherwise.\n */\nDrafty.isProcessing = function(entData) {\n return !!entData._processing;\n}\n\n/**\n * Given the entity, get URL which can be used for previewing\n * the entity.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entity.data to get the URl from.\n *\n * @returns {string} url for previewing or null if no such url is available.\n */\nDrafty.getPreviewUrl = function(entData) {\n return entData.val ? base64toObjectUrl(entData.val, entData.mime, Drafty.logger) : null;\n}\n\n/**\n * Get approximate size of the entity.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entData - entity.data to get the size for.\n * @returns {number} size of entity data in bytes.\n */\nDrafty.getEntitySize = function(entData) {\n // Either size hint or length of value. The value is base64 encoded,\n // the actual object size is smaller than the encoded length.\n return entData.size ? entData.size : entData.val ? (entData.val.length * 0.75) | 0 : 0;\n}\n\n/**\n * Get entity mime type.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entData - entity.data to get the type for.\n * @returns {string} mime type of entity.\n */\nDrafty.getEntityMimeType = function(entData) {\n return entData.mime || 'text/plain';\n}\n\n/**\n * Get HTML tag for a given two-letter style name.\n * @memberof Drafty\n * @static\n *\n * @param {string} style - two-letter style, like ST or LN.\n *\n * @returns {string} HTML tag name if style is found, {code: undefined} if style is falsish or not found.\n */\nDrafty.tagName = function(style) {\n return FORMAT_TAGS[style] && FORMAT_TAGS[style].html_tag;\n}\n\n/**\n * For a given data bundle generate an object with HTML attributes,\n * for instance, given {url: \"http://www.example.com/\"} return\n * {href: \"http://www.example.com/\"}\n * @memberof Drafty\n * @static\n *\n * @param {string} style - two-letter style to generate attributes for.\n * @param {Object} data - data bundle to convert to attributes\n *\n * @returns {Object} object with HTML attributes.\n */\nDrafty.attrValue = function(style, data) {\n if (data && DECORATORS[style] && DECORATORS[style].props) {\n return DECORATORS[style].props(data);\n }\n\n return undefined;\n}\n\n/**\n * Drafty MIME type.\n * @memberof Drafty\n * @static\n *\n * @returns {string} content-Type \"text/x-drafty\".\n */\nDrafty.getContentType = function() {\n return DRAFTY_MIME_TYPE;\n}\n\n// =================\n// Utility methods.\n// =================\n\n// Take a string and defined earlier style spans, re-compose them into a tree where each leaf is\n// a same-style (including unstyled) string. I.e. 'hello *bold _italic_* and ~more~ world' ->\n// ('hello ', (b: 'bold ', (i: 'italic')), ' and ', (s: 'more'), ' world');\n//\n// This is needed in order to clear markup, i.e. 'hello *world*' -> 'hello world' and convert\n// ranges from markup-ed offsets to plain text offsets.\nfunction chunkify(line, start, end, spans) {\n const chunks = [];\n\n if (spans.length == 0) {\n return [];\n }\n\n for (let i in spans) {\n // Get the next chunk from the queue\n const span = spans[i];\n\n // Grab the initial unstyled chunk\n if (span.at > start) {\n chunks.push({\n txt: line.slice(start, span.at)\n });\n }\n\n // Grab the styled chunk. It may include subchunks.\n const chunk = {\n tp: span.tp\n };\n const chld = chunkify(line, span.at + 1, span.end, span.children);\n if (chld.length > 0) {\n chunk.children = chld;\n } else {\n chunk.txt = span.txt;\n }\n chunks.push(chunk);\n start = span.end + 1; // '+1' is to skip the formatting character\n }\n\n // Grab the remaining unstyled chunk, after the last span\n if (start < end) {\n chunks.push({\n txt: line.slice(start, end)\n });\n }\n\n return chunks;\n}\n\n// Detect starts and ends of formatting spans. Unformatted spans are\n// ignored at this stage.\nfunction spannify(original, re_start, re_end, type) {\n const result = [];\n let index = 0;\n let line = original.slice(0); // make a copy;\n\n while (line.length > 0) {\n // match[0]; // match, like '*abc*'\n // match[1]; // match captured in parenthesis, like 'abc'\n // match['index']; // offset where the match started.\n\n // Find the opening token.\n const start = re_start.exec(line);\n if (start == null) {\n break;\n }\n\n // Because javascript RegExp does not support lookbehind, the actual offset may not point\n // at the markup character. Find it in the matched string.\n let start_offset = start['index'] + start[0].lastIndexOf(start[1]);\n // Clip the processed part of the string.\n line = line.slice(start_offset + 1);\n // start_offset is an offset within the clipped string. Convert to original index.\n start_offset += index;\n // Index now point to the beginning of 'line' within the 'original' string.\n index = start_offset + 1;\n\n // Find the matching closing token.\n const end = re_end ? re_end.exec(line) : null;\n if (end == null) {\n break;\n }\n let end_offset = end['index'] + end[0].indexOf(end[1]);\n // Clip the processed part of the string.\n line = line.slice(end_offset + 1);\n // Update offsets\n end_offset += index;\n // Index now points to the beginning of 'line' within the 'original' string.\n index = end_offset + 1;\n\n result.push({\n txt: original.slice(start_offset + 1, end_offset),\n children: [],\n at: start_offset,\n end: end_offset,\n tp: type\n });\n }\n\n return result;\n}\n\n// Convert linear array or spans into a tree representation.\n// Keep standalone and nested spans, throw away partially overlapping spans.\nfunction toSpanTree(spans) {\n if (spans.length == 0) {\n return [];\n }\n\n const tree = [spans[0]];\n let last = spans[0];\n for (let i = 1; i < spans.length; i++) {\n // Keep spans which start after the end of the previous span or those which\n // are complete within the previous span.\n if (spans[i].at > last.end) {\n // Span is completely outside of the previous span.\n tree.push(spans[i]);\n last = spans[i];\n } else if (spans[i].end <= last.end) {\n // Span is fully inside of the previous span. Push to subnode.\n last.children.push(spans[i]);\n }\n // Span could partially overlap, ignoring it as invalid.\n }\n\n // Recursively rearrange the subnodes.\n for (let i in tree) {\n tree[i].children = toSpanTree(tree[i].children);\n }\n\n return tree;\n}\n\n// Convert drafty document to a tree.\nfunction draftyToTree(doc) {\n if (!doc) {\n return null;\n }\n\n doc = (typeof doc == 'string') ? {\n txt: doc\n } : doc;\n let {\n txt,\n fmt,\n ent\n } = doc;\n\n txt = txt || '';\n if (!Array.isArray(ent)) {\n ent = [];\n }\n\n if (!Array.isArray(fmt) || fmt.length == 0) {\n if (ent.length == 0) {\n return {\n text: txt\n };\n }\n\n // Handle special case when all values in fmt are 0 and fmt therefore is skipped.\n fmt = [{\n at: 0,\n len: 0,\n key: 0\n }];\n }\n\n // Sanitize spans.\n const spans = [];\n const attachments = [];\n fmt.forEach((span) => {\n if (!span || typeof span != 'object') {\n return;\n }\n\n if (!['undefined', 'number'].includes(typeof span.at)) {\n // Present, but non-numeric 'at'.\n return;\n }\n if (!['undefined', 'number'].includes(typeof span.len)) {\n // Present, but non-numeric 'len'.\n return;\n }\n let at = span.at | 0;\n let len = span.len | 0;\n if (len < 0) {\n // Invalid span length.\n return;\n }\n\n let key = span.key || 0;\n if (ent.length > 0 && (typeof key != 'number' || key < 0 || key >= ent.length)) {\n // Invalid key value.\n return;\n }\n\n if (at <= -1) {\n // Attachment. Store attachments separately.\n attachments.push({\n start: -1,\n end: 0,\n key: key\n });\n return;\n } else if (at + len > stringToGraphemes(txt).length) {\n // Span is out of bounds.\n return;\n }\n\n if (!span.tp) {\n if (ent.length > 0 && (typeof ent[key] == 'object')) {\n spans.push({\n start: at,\n end: at + len,\n key: key\n });\n }\n } else {\n spans.push({\n type: span.tp,\n start: at,\n end: at + len\n });\n }\n });\n\n // Sort spans first by start index (asc) then by length (desc), then by weight.\n spans.sort((a, b) => {\n let diff = a.start - b.start;\n if (diff != 0) {\n return diff;\n }\n diff = b.end - a.end;\n if (diff != 0) {\n return diff;\n }\n return FMT_WEIGHT.indexOf(b.type) - FMT_WEIGHT.indexOf(a.type);\n });\n\n // Move attachments to the end of the list.\n if (attachments.length > 0) {\n spans.push(...attachments);\n }\n\n spans.forEach((span) => {\n if (ent.length > 0 && !span.type && ent[span.key] && typeof ent[span.key] == 'object') {\n span.type = ent[span.key].tp;\n span.data = ent[span.key].data;\n }\n\n // Is type still undefined? Hide the invalid element!\n if (!span.type) {\n span.type = 'HD';\n }\n });\n\n const graphemes = stringToGraphemes(txt);\n let tree = spansToTree({}, graphemes, 0, graphemes.length, spans);\n\n // Flatten tree nodes.\n const flatten = function(node) {\n if (Array.isArray(node.children) && node.children.length == 1) {\n // Unwrap.\n const child = node.children[0];\n if (!node.type) {\n const parent = node.parent;\n node = child;\n node.parent = parent;\n } else if (!child.type && !child.children) {\n node.text = child.text;\n delete node.children;\n }\n }\n return node;\n }\n tree = treeTopDown(tree, flatten);\n\n return tree;\n}\n\n// Add tree node to a parent tree.\nfunction addNode(parent, n) {\n if (!n) {\n return parent;\n }\n\n if (!parent.children) {\n parent.children = [];\n }\n\n // If text is present, move it to a subnode.\n if (parent.text) {\n parent.children.push({\n text: parent.text,\n parent: parent\n });\n delete parent.text;\n }\n\n n.parent = parent;\n parent.children.push(n);\n\n return parent;\n}\n\n// Returns a tree of nodes.\nfunction spansToTree(parent, graphemes, start, end, spans) {\n if (!spans || spans.length == 0) {\n if (start < end) {\n addNode(parent, {\n text: graphemes.slice(start, end)\n .map(segment => segment.segment)\n .join('')\n });\n }\n return parent;\n }\n\n // Process subspans.\n for (let i = 0; i < spans.length; i++) {\n const span = spans[i];\n if (span.start < 0 && span.type == 'EX') {\n addNode(parent, {\n type: span.type,\n data: span.data,\n key: span.key,\n att: true\n });\n continue;\n }\n\n // Add un-styled range before the styled span starts.\n if (start < span.start) {\n addNode(parent, {\n text: graphemes.slice(start, span.start)\n .map(segment => segment.segment)\n .join('')\n });\n start = span.start;\n }\n\n // Get all spans which are within the current span.\n const subspans = [];\n while (i < spans.length - 1) {\n const inner = spans[i + 1];\n if (inner.start < 0) {\n // Attachments are in the end. Stop.\n break;\n } else if (inner.start < span.end) {\n if (inner.end <= span.end) {\n const tag = FORMAT_TAGS[inner.tp] || {};\n if (inner.start < inner.end || tag.isVoid) {\n // Valid subspan: completely within the current span and\n // either non-zero length or zero length is acceptable.\n subspans.push(inner);\n }\n }\n i++;\n // Overlapping subspans are ignored.\n } else {\n // Past the end of the current span. Stop.\n break;\n }\n }\n\n addNode(parent, spansToTree({\n type: span.type,\n data: span.data,\n key: span.key\n }, graphemes, start, span.end, subspans));\n start = span.end;\n }\n\n // Add the last unformatted range.\n if (start < end) {\n addNode(parent, {\n text: graphemes\n .slice(start, end)\n .map((segment) => segment.segment)\n .join('')\n });\n }\n\n return parent;\n}\n\n// Append a tree to a Drafty doc.\nfunction treeToDrafty(doc, tree, keymap) {\n if (!tree) {\n return doc;\n }\n\n doc.txt = doc.txt || '';\n\n // Checkpoint to measure length of the current tree node.\n const start = stringToGraphemes(doc.txt).length;\n\n if (tree.text) {\n doc.txt += tree.text;\n } else if (Array.isArray(tree.children)) {\n tree.children.forEach((c) => {\n treeToDrafty(doc, c, keymap);\n });\n }\n\n if (tree.type) {\n const len = stringToGraphemes(doc.txt).length - start;\n doc.fmt = doc.fmt || [];\n if (Object.keys(tree.data || {}).length > 0) {\n doc.ent = doc.ent || [];\n const newKey = (typeof keymap[tree.key] == 'undefined') ? doc.ent.length : keymap[tree.key];\n keymap[tree.key] = newKey;\n doc.ent[newKey] = {\n tp: tree.type,\n data: tree.data\n };\n if (tree.att) {\n // Attachment.\n doc.fmt.push({\n at: -1,\n len: 0,\n key: newKey\n });\n } else {\n doc.fmt.push({\n at: start,\n len: len,\n key: newKey\n });\n }\n } else {\n doc.fmt.push({\n tp: tree.type,\n at: start,\n len: len\n });\n }\n }\n return doc;\n}\n\n// Traverse the tree top down transforming the nodes: apply transformer to every tree node.\nfunction treeTopDown(src, transformer, context) {\n if (!src) {\n return null;\n }\n\n let dst = transformer.call(context, src);\n if (!dst || !dst.children) {\n return dst;\n }\n\n const children = [];\n for (let i in dst.children) {\n let n = dst.children[i];\n if (n) {\n n = treeTopDown(n, transformer, context);\n if (n) {\n children.push(n);\n }\n }\n }\n\n if (children.length == 0) {\n dst.children = null;\n } else {\n dst.children = children;\n }\n\n return dst;\n}\n\n// Traverse the tree bottom-up: apply formatter to every node.\n// The formatter must maintain its state through context.\nfunction treeBottomUp(src, formatter, index, stack, context) {\n if (!src) {\n return null;\n }\n\n if (stack && src.type) {\n stack.push(src.type);\n }\n\n let values = [];\n for (let i in src.children) {\n const n = treeBottomUp(src.children[i], formatter, i, stack, context);\n if (n) {\n values.push(n);\n }\n }\n if (values.length == 0) {\n if (src.text) {\n values = [src.text];\n } else {\n values = null;\n }\n }\n\n if (stack && src.type) {\n stack.pop();\n }\n\n return formatter.call(context, src.type, src.data, values, index, stack);\n}\n\n// Clip tree to the provided limit.\nfunction shortenTree(tree, limit, tail) {\n if (!tree) {\n return null;\n }\n\n if (tail) {\n limit -= tail.length;\n }\n\n const shortener = function(node) {\n if (limit <= -1) {\n // Limit -1 means the doc was already clipped.\n return null;\n }\n\n if (node.att) {\n // Attachments are unchanged.\n return node;\n }\n if (limit == 0) {\n node.text = tail;\n limit = -1;\n } else if (node.text) {\n const graphemes = stringToGraphemes(node.text);\n if (graphemes.length > limit) {\n node.text = graphemes\n .slice(0, limit)\n .map((segment) => segment.segment)\n .join('') + tail;\n limit = -1;\n } else {\n limit -= graphemes.length;\n }\n }\n return node;\n }\n\n return treeTopDown(tree, shortener);\n}\n\n// Strip heavy entities from a tree.\nfunction lightEntity(tree, allow) {\n const lightCopy = node => {\n const data = copyEntData(node.data, true, allow ? allow(node) : null);\n if (data) {\n node.data = data;\n } else {\n delete node.data;\n }\n return node;\n }\n return treeTopDown(tree, lightCopy);\n}\n\n// Remove spaces and breaks on the left.\nfunction lTrim(tree) {\n if (tree.type == 'BR') {\n tree = null;\n } else if (tree.text) {\n if (!tree.type) {\n tree.text = tree.text.trimStart();\n if (!tree.text) {\n tree = null;\n }\n }\n } else if (!tree.type && tree.children && tree.children.length > 0) {\n const c = lTrim(tree.children[0]);\n if (c) {\n tree.children[0] = c;\n } else {\n tree.children.shift();\n if (!tree.type && tree.children.length == 0) {\n tree = null;\n }\n }\n }\n return tree;\n}\n\n// Move attachments to the end. Attachments must be at the top level, no need to traverse the tree.\nfunction attachmentsToEnd(tree, limit) {\n if (!tree) {\n return null;\n }\n\n if (tree.att) {\n tree.text = ' ';\n delete tree.att;\n delete tree.children;\n } else if (tree.children) {\n const attachments = [];\n const children = [];\n for (let i in tree.children) {\n const c = tree.children[i];\n if (c.att) {\n if (attachments.length == limit) {\n // Too many attachments to preview;\n continue;\n }\n if (c.data['mime'] == JSON_MIME_TYPE) {\n // JSON attachments are not shown in preview.\n continue;\n }\n\n delete c.att;\n delete c.children;\n c.text = ' ';\n attachments.push(c);\n } else {\n children.push(c);\n }\n }\n tree.children = children.concat(attachments);\n }\n return tree;\n}\n\n// Get a list of entities from a text.\nfunction extractEntities(line) {\n let match;\n let extracted = [];\n ENTITY_TYPES.forEach((entity) => {\n while ((match = entity.re.exec(line)) !== null) {\n extracted.push({\n offset: match['index'],\n len: match[0].length,\n unique: match[0],\n data: entity.pack(match[0]),\n type: entity.name\n });\n }\n });\n\n if (extracted.length == 0) {\n return extracted;\n }\n\n // Remove entities detected inside other entities, like #hashtag in a URL.\n extracted.sort((a, b) => {\n return a.offset - b.offset;\n });\n\n let idx = -1;\n extracted = extracted.filter((el) => {\n const result = (el.offset > idx);\n idx = el.offset + el.len;\n return result;\n });\n\n return extracted;\n}\n\n// Convert the chunks into format suitable for serialization.\nfunction draftify(chunks, startAt) {\n let plain = '';\n let ranges = [];\n for (let i in chunks) {\n const chunk = chunks[i];\n if (!chunk.txt) {\n const drafty = draftify(chunk.children, plain.length + startAt);\n chunk.txt = drafty.txt;\n ranges = ranges.concat(drafty.fmt);\n }\n\n if (chunk.tp) {\n ranges.push({\n at: plain.length + startAt,\n len: chunk.txt.length,\n tp: chunk.tp\n });\n }\n\n plain += chunk.txt;\n }\n return {\n txt: plain,\n fmt: ranges\n };\n}\n\n// Create a copy of entity data with (light=false) or without (light=true) the large payload.\n// The array 'allow' contains a list of fields exempt from stripping.\nfunction copyEntData(data, light, allow) {\n if (data && Object.entries(data).length > 0) {\n allow = allow || [];\n const dc = {};\n ALLOWED_ENT_FIELDS.forEach(key => {\n if (data[key]) {\n if (light && !allow.includes(key) &&\n (typeof data[key] == 'string' || Array.isArray(data[key])) &&\n data[key].length > MAX_PREVIEW_DATA_SIZE) {\n return;\n }\n if (typeof data[key] == 'object') {\n return;\n }\n dc[key] = data[key];\n }\n });\n\n if (Object.entries(dc).length != 0) {\n return dc;\n }\n }\n return null;\n}\n\n// Returns true if object is empty, if undefined returns true\nfunction isEmptyObject(obj) {\n return Object.keys(obj ?? {}).length == 0;\n};\n\n\n// Returns an array (of length equal to the length of the original string) such that each index\n// denotes the position of char in string in a grapheme array (created from that string)\n// Eg: string: \"Hi👋🏼Hi\" -> [0,1,2,2,2,2,3,4]\nfunction graphemeIndices(graphemes) {\n const result = [];\n let graphemeIndex = 0;\n let charIndex = 0;\n\n // Iterate over the grapheme clusters.\n for (const {\n segment\n }\n of graphemes) {\n // Map the character indices to the grapheme index.\n for (let i = 0; i < segment.length; i++) {\n result[charIndex + i] = graphemeIndex;\n }\n\n // Increment the character index by the length of the grapheme cluster.\n charIndex += segment.length;\n\n // Increment the grapheme index.\n graphemeIndex++;\n }\n\n return result;\n}\n\n// Convert fmt.at and fmt.len from character-expressed index and length to grapheme-expressed\n// index and length.\nfunction toGraphemeValues(fmt, segments, txt) {\n segments = segments ?? segmenter.segment(txt);\n\n const indices = graphemeIndices(segments);\n\n const correctAt = indices[fmt.at];\n const correctLen = fmt.at + fmt.len <= txt.length ?\n indices[fmt.at + fmt.len - 1] - correctAt : fmt.len;\n\n return {\n at: correctAt,\n len: correctLen + 1\n };\n}\n\n// Convert string to graphme cluster array.\nfunction stringToGraphemes(str) {\n return Array.from(segmenter.segment(str));\n}\n\nif (typeof module != 'undefined') {\n module.exports = Drafty;\n}\n","/**\n * @file Definition of 'fnd' topic.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport * as Const from './config.js';\nimport Topic from './topic.js';\nimport {\n mergeToCache\n} from './utils.js';\n\n\n/**\n * Special case of {@link Tinode.Topic} for searching for contacts and group topics\n * @extends Tinode.Topic\n *\n */\nexport default class TopicFnd extends Topic {\n // List of users and topics uid or topic_name -> Contact object)\n _contacts = {};\n\n /**\n * Create TopicFnd.\n *\n * @param {TopicFnd.Callbacks} callbacks - Callbacks to receive various events.\n */\n constructor(callbacks) {\n super(Const.TOPIC_FND, callbacks);\n }\n\n // Override the original Topic._processMetaSubs\n _processMetaSubs(subs) {\n let updateCount = Object.getOwnPropertyNames(this._contacts).length;\n // Reset contact list.\n this._contacts = {};\n for (let idx in subs) {\n let sub = subs[idx];\n const indexBy = sub.topic ? sub.topic : sub.user;\n\n sub = mergeToCache(this._contacts, indexBy, sub);\n updateCount++;\n\n if (this.onMetaSub) {\n this.onMetaSub(sub);\n }\n }\n\n if (updateCount > 0 && this.onSubsUpdated) {\n this.onSubsUpdated(Object.keys(this._contacts));\n }\n }\n\n /**\n * Publishing to TopicFnd is not supported. {@link Topic#publish} is overriden and thows an {Error} if called.\n * @memberof Tinode.TopicFnd#\n * @throws {Error} Always throws an error.\n */\n publish() {\n return Promise.reject(new Error(\"Publishing to 'fnd' is not supported\"));\n }\n\n /**\n * setMeta to TopicFnd resets contact list in addition to sending the message.\n * @memberof Tinode.TopicFnd#\n * @param {Tinode.SetParams} params parameters to update.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n setMeta(params) {\n return Object.getPrototypeOf(TopicFnd.prototype).setMeta.call(this, params).then(_ => {\n if (Object.keys(this._contacts).length > 0) {\n this._contacts = {};\n if (this.onSubsUpdated) {\n this.onSubsUpdated([]);\n }\n }\n });\n }\n\n /**\n * Check if the given tag is unique by asking the server.\n * @param tag tag to check.\n * @return promise to be resolved with true if the tag is unique, false otherwise.\n */\n checkTagUniqueness(tag, caller) {\n return new Promise((resolve, reject) => {\n this.subscribe()\n .then(_ => this.setMeta({\n desc: {\n public: tag\n }\n }))\n .then(_ => this.getMeta(this.startMetaQuery().withTags().build()))\n .then(meta => {\n if (!meta || !Array.isArray(meta.tags) || meta.tags.length == 0) {\n resolve(true);\n }\n const tags = meta.tags.filter(t => t !== caller);\n resolve(tags.length == 0);\n })\n .catch(err => {\n reject(err);\n });\n });\n }\n\n /**\n * Iterate over found contacts. If callback is undefined, use {@link this.onMetaSub}.\n * @function\n * @memberof Tinode.TopicFnd#\n * @param {TopicFnd.ContactCallback} callback - Callback to call for each contact.\n * @param {Object} context - Context to use for calling the `callback`, i.e. the value of `this` inside the callback.\n */\n contacts(callback, context) {\n const cb = (callback || this.onMetaSub);\n if (cb) {\n for (let idx in this._contacts) {\n cb.call(context, this._contacts[idx], idx, this._contacts);\n }\n }\n }\n}\n","/**\n * @file Utilities for uploading and downloading files.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport CommError from './comm-error.js';\nimport {\n isUrlRelative,\n jsonParseHelper\n} from './utils.js';\n\nlet XHRProvider;\n\nfunction addURLParam(relUrl, key, value) {\n const url = new URL(relUrl, window.location.origin);\n url.searchParams.append(key, value);\n return url.toString().substring(window.location.origin.length);\n}\n\n/**\n * @class LargeFileHelper - utilities for uploading and downloading files out of band.\n * Don't instantiate this class directly. Use {Tinode.getLargeFileHelper} instead.\n * @memberof Tinode\n *\n * @param {Tinode} tinode - the main Tinode object.\n * @param {string} version - protocol version, i.e. '0'.\n */\nexport default class LargeFileHelper {\n constructor(tinode, version) {\n this._tinode = tinode;\n this._version = version;\n\n this._apiKey = tinode._apiKey;\n this._authToken = tinode.getAuthToken();\n\n // Ongoing requests.\n this.xhr = [];\n }\n\n /**\n * Start uploading the file to an endpoint at baseUrl.\n *\n * @memberof Tinode.LargeFileHelper#\n *\n * @param {string} baseUrl base URL of upload server.\n * @param {File|Blob} data data to upload.\n * @param {string} avatarFor topic name if the upload represents an avatar.\n * @param {Callback} onProgress callback. Takes one {float} parameter 0..1\n * @param {Callback} onSuccess callback. Called when the file is successfully uploaded.\n * @param {Callback} onFailure callback. Called in case of a failure.\n *\n * @returns {Promise} resolved/rejected when the upload is completed/failed.\n */\n uploadWithBaseUrl(baseUrl, data, avatarFor, onProgress, onSuccess, onFailure) {\n let url = `/v${this._version}/file/u/`;\n if (baseUrl) {\n let base = baseUrl;\n if (base.endsWith('/')) {\n // Removing trailing slash.\n base = base.slice(0, -1);\n }\n if (base.startsWith('http://') || base.startsWith('https://')) {\n url = base + url;\n } else {\n throw new Error(`Invalid base URL '${baseUrl}'`);\n }\n }\n\n const instance = this;\n const xhr = new XHRProvider();\n this.xhr.push(xhr);\n\n xhr.open('POST', url, true);\n xhr.setRequestHeader('X-Tinode-APIKey', this._apiKey);\n if (this._authToken) {\n xhr.setRequestHeader('X-Tinode-Auth', `Token ${this._authToken.token}`);\n }\n\n let toResolve = null;\n let toReject = null;\n\n const result = new Promise((resolve, reject) => {\n toResolve = resolve;\n toReject = reject;\n });\n\n xhr.upload.onprogress = e => {\n if (e.lengthComputable) {\n if (onProgress) {\n onProgress(e.loaded / e.total);\n }\n if (this.onProgress) {\n this.onProgress(e.loaded / e.total);\n }\n }\n };\n\n xhr.onload = function() {\n let pkt;\n try {\n pkt = JSON.parse(this.response, jsonParseHelper);\n } catch (err) {\n instance._tinode.logger(\"ERROR: Invalid server response in LargeFileHelper\", this.response);\n pkt = {\n ctrl: {\n code: this.status,\n text: this.statusText\n }\n };\n }\n\n if (this.status >= 200 && this.status < 300) {\n if (toResolve) {\n toResolve(pkt.ctrl.params.url);\n }\n if (onSuccess) {\n onSuccess(pkt.ctrl);\n }\n } else if (this.status >= 400) {\n if (toReject) {\n toReject(new CommError(pkt.ctrl.text, pkt.ctrl.code));\n }\n if (onFailure) {\n onFailure(pkt.ctrl);\n }\n } else {\n instance._tinode.logger(\"ERROR: Unexpected server response status\", this.status, this.response);\n }\n };\n\n xhr.onerror = function(e) {\n if (toReject) {\n toReject(e || new Error(\"failed\"));\n }\n if (onFailure) {\n onFailure(null);\n }\n };\n\n xhr.onabort = function(e) {\n if (toReject) {\n toReject(new Error(\"upload cancelled by user\"));\n }\n if (onFailure) {\n onFailure(null);\n }\n };\n\n try {\n const form = new FormData();\n form.append('file', data);\n form.set('id', this._tinode.getNextUniqueId());\n if (avatarFor) {\n form.set('topic', avatarFor);\n }\n xhr.send(form);\n } catch (err) {\n if (toReject) {\n toReject(err);\n }\n if (onFailure) {\n onFailure(null);\n }\n }\n\n return result;\n }\n /**\n * Start uploading the file to default endpoint.\n *\n * @memberof Tinode.LargeFileHelper#\n *\n * @param {File|Blob} data to upload\n * @param {string} avatarFor topic name if the upload represents an avatar.\n * @param {Callback} onProgress callback. Takes one {float} parameter 0..1\n * @param {Callback} onSuccess callback. Called when the file is successfully uploaded.\n * @param {Callback} onFailure callback. Called in case of a failure.\n *\n * @returns {Promise} resolved/rejected when the upload is completed/failed.\n */\n upload(data, avatarFor, onProgress, onSuccess, onFailure) {\n const baseUrl = (this._tinode._secure ? 'https://' : 'http://') + this._tinode._host;\n return this.uploadWithBaseUrl(baseUrl, data, avatarFor, onProgress, onSuccess, onFailure);\n }\n /**\n * Download the file from a given URL using GET request. This method works with the Tinode server only.\n *\n * @memberof Tinode.LargeFileHelper#\n *\n * @param {string} relativeUrl - URL to download the file from. Must be relative url, i.e. must not contain the host.\n * @param {string=} filename - file name to use for the downloaded file.\n *\n * @returns {Promise} resolved/rejected when the download is completed/failed.\n */\n download(relativeUrl, filename, mimetype, onProgress, onError) {\n if (!isUrlRelative(relativeUrl)) {\n // As a security measure refuse to download from an absolute URL.\n if (onError) {\n onError(`The URL '${relativeUrl}' must be relative, not absolute`);\n }\n return;\n }\n if (!this._authToken) {\n if (onError) {\n onError(\"Must authenticate first\");\n }\n return;\n }\n const instance = this;\n\n const xhr = new XHRProvider();\n this.xhr.push(xhr);\n\n // Add '&asatt=1' to URL to request 'Content-Disposition: attachment' response header.\n relativeUrl = addURLParam(relativeUrl, 'asatt', '1');\n\n // Get data as blob (stored by the browser as a temporary file).\n xhr.open('GET', relativeUrl, true);\n xhr.setRequestHeader('X-Tinode-APIKey', this._apiKey);\n xhr.setRequestHeader('X-Tinode-Auth', 'Token ' + this._authToken.token);\n xhr.responseType = 'blob';\n\n xhr.onprogress = function(e) {\n if (onProgress) {\n // Passing e.loaded instead of e.loaded/e.total because e.total\n // is always 0 with gzip compression enabled by the server.\n onProgress(e.loaded);\n }\n };\n\n let toResolve = null;\n let toReject = null;\n\n const result = new Promise((resolve, reject) => {\n toResolve = resolve;\n toReject = reject;\n });\n\n // The blob needs to be saved as file. There is no known way to\n // save the blob as file other than to fake a click on an .\n xhr.onload = function() {\n if (this.status == 200) {\n const link = document.createElement('a');\n // URL.createObjectURL is not available in non-browser environment. This call will fail.\n link.href = window.URL.createObjectURL(new Blob([this.response], {\n type: mimetype\n }));\n link.style.display = 'none';\n link.setAttribute('download', filename);\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n window.URL.revokeObjectURL(link.href);\n if (toResolve) {\n toResolve();\n }\n } else if (this.status >= 400 && toReject) {\n // The this.responseText is undefined, must use this.response which is a blob.\n // Need to convert this.response to JSON. The blob can only be accessed by the\n // FileReader.\n const reader = new FileReader();\n reader.onload = function() {\n try {\n const pkt = JSON.parse(this.result, jsonParseHelper);\n toReject(new CommError(pkt.ctrl.text, pkt.ctrl.code));\n } catch (err) {\n instance._tinode.logger(\"ERROR: Invalid server response in LargeFileHelper\", this.result);\n toReject(err);\n }\n };\n reader.readAsText(this.response);\n }\n };\n\n xhr.onerror = function(e) {\n if (toReject) {\n toReject(new Error(\"failed\"));\n }\n if (onError) {\n onError(e);\n }\n };\n\n xhr.onabort = function() {\n if (toReject) {\n toReject(null);\n }\n };\n\n try {\n xhr.send();\n } catch (err) {\n if (toReject) {\n toReject(err);\n }\n if (onError) {\n onError(err);\n }\n }\n\n return result;\n }\n /**\n * Try to cancel all ongoing uploads or downloads.\n * @memberof Tinode.LargeFileHelper#\n */\n cancel() {\n this.xhr.forEach(req => {\n if (req.readyState < 4) {\n req.abort();\n }\n });\n }\n /**\n * To use LargeFileHelper in a non browser context, supply XMLHttpRequest provider.\n * @static\n * @memberof LargeFileHelper\n * @param xhrProvider XMLHttpRequest provider, e.g. for node require('xhr').\n */\n static setNetworkProvider(xhrProvider) {\n XHRProvider = xhrProvider;\n }\n}\n","/**\n * @file Definition of 'me' topic.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport AccessMode from './access-mode.js';\nimport * as Const from './config.js';\nimport Topic from './topic.js';\nimport {\n mergeObj\n} from './utils.js';\n\n/**\n * @class TopicMe - special case of {@link Tinode.Topic} for\n * managing data of the current user, including contact list.\n * @extends Tinode.Topic\n * @memberof Tinode\n *\n * @param {TopicMe.Callbacks} callbacks - Callbacks to receive various events.\n */\nexport default class TopicMe extends Topic {\n onContactUpdate;\n\n constructor(callbacks) {\n super(Const.TOPIC_ME, callbacks);\n\n // me-specific callbacks\n if (callbacks) {\n this.onContactUpdate = callbacks.onContactUpdate;\n }\n }\n\n // Override the original Topic._processMetaDesc.\n _processMetaDesc(desc) {\n // Check if online contacts need to be turned off because P permission was removed.\n const turnOff = (desc.acs && !desc.acs.isPresencer()) && (this.acs && this.acs.isPresencer());\n\n // Copy parameters from desc object to this topic.\n mergeObj(this, desc);\n this._tinode._db.updTopic(this);\n // Update current user's record in the global cache.\n this._updateCachedUser(this._tinode._myUID, desc);\n\n // 'P' permission was removed. All topics are offline now.\n if (turnOff) {\n this._tinode.mapTopics((cont) => {\n if (cont.online) {\n cont.online = false;\n cont.seen = Object.assign(cont.seen || {}, {\n when: new Date()\n });\n this._refreshContact('off', cont);\n }\n });\n }\n\n if (this.onMetaDesc) {\n this.onMetaDesc(this);\n }\n }\n\n // Override the original Topic._processMetaSubs\n _processMetaSubs(subs) {\n let updateCount = 0;\n subs.forEach((sub) => {\n const topicName = sub.topic;\n // Don't show 'me' and 'fnd' topics in the list of contacts.\n if (topicName == Const.TOPIC_FND || topicName == Const.TOPIC_ME) {\n return;\n }\n sub.online = !!sub.online;\n\n let cont = null;\n if (sub.deleted) {\n cont = sub;\n this._tinode.cacheRemTopic(topicName);\n this._tinode._db.remTopic(topicName);\n } else {\n // Ensure the values are defined and are integers.\n if (typeof sub.seq != 'undefined') {\n sub.seq = sub.seq | 0;\n sub.recv = sub.recv | 0;\n sub.read = sub.read | 0;\n sub.unread = sub.seq - sub.read;\n }\n\n const topic = this._tinode.getTopic(topicName);\n if (topic._new) {\n delete topic._new;\n }\n\n cont = mergeObj(topic, sub);\n this._tinode._db.updTopic(cont);\n\n if (Topic.isP2PTopicName(topicName)) {\n this._cachePutUser(topicName, cont);\n this._tinode._db.updUser(topicName, cont.public);\n }\n // Notify topic of the update if it's an external update.\n if (!sub._noForwarding && topic) {\n sub._noForwarding = true;\n topic._processMetaDesc(sub);\n }\n }\n\n updateCount++;\n\n if (this.onMetaSub) {\n this.onMetaSub(cont);\n }\n });\n\n if (this.onSubsUpdated && updateCount > 0) {\n const keys = [];\n subs.forEach((s) => {\n keys.push(s.topic);\n });\n this.onSubsUpdated(keys, updateCount);\n }\n }\n\n // Called by Tinode when meta.sub is recived.\n _processMetaCreds(creds, upd) {\n if (creds.length == 1 && creds[0] == Const.DEL_CHAR) {\n creds = [];\n }\n if (upd) {\n creds.forEach((cr) => {\n if (cr.val) {\n // Adding a credential.\n let idx = this._credentials.findIndex((el) => {\n return el.meth == cr.meth && el.val == cr.val;\n });\n if (idx < 0) {\n // Not found.\n if (!cr.done) {\n // Unconfirmed credential replaces previous unconfirmed credential of the same method.\n idx = this._credentials.findIndex((el) => {\n return el.meth == cr.meth && !el.done;\n });\n if (idx >= 0) {\n // Remove previous unconfirmed credential.\n this._credentials.splice(idx, 1);\n }\n }\n this._credentials.push(cr);\n } else {\n // Found. Maybe change 'done' status.\n this._credentials[idx].done = cr.done;\n }\n } else if (cr.resp) {\n // Handle credential confirmation.\n const idx = this._credentials.findIndex((el) => {\n return el.meth == cr.meth && !el.done;\n });\n if (idx >= 0) {\n this._credentials[idx].done = true;\n }\n }\n });\n } else {\n this._credentials = creds;\n }\n if (this.onCredsUpdated) {\n this.onCredsUpdated(this._credentials);\n }\n }\n\n // Process presence change message\n _routePres(pres) {\n if (pres.what == 'term') {\n // The 'me' topic itself is detached. Mark as unsubscribed.\n this._resetSub();\n return;\n }\n\n if (pres.what == 'upd' && pres.src == Const.TOPIC_ME) {\n // Update to me's description. Request updated value.\n this.getMeta(this.startMetaQuery().withDesc().build());\n return;\n }\n\n const cont = this._tinode.cacheGetTopic(pres.src);\n if (cont) {\n switch (pres.what) {\n case 'on': // topic came online\n cont.online = true;\n break;\n case 'off': // topic went offline\n if (cont.online) {\n cont.online = false;\n cont.seen = Object.assign(cont.seen || {}, {\n when: new Date()\n });\n }\n break;\n case 'msg': // new message received\n cont._updateReceived(pres.seq, pres.act);\n break;\n case 'upd': // desc updated\n // Request updated subscription.\n this.getMeta(this.startMetaQuery().withLaterOneSub(pres.src).build());\n break;\n case 'acs': // access mode changed\n // If 'tgt' is not set then this is an update to the permissions of the current user.\n // Otherwise it's an update to group topic subscriber permissions while the topic is offline.\n // Just gnore it then.\n if (!pres.tgt) {\n if (cont.acs) {\n cont.acs.updateAll(pres.dacs);\n } else {\n cont.acs = new AccessMode().updateAll(pres.dacs);\n }\n cont.touched = new Date();\n }\n break;\n case 'ua':\n // user agent changed.\n cont.seen = {\n when: new Date(),\n ua: pres.ua\n };\n break;\n case 'recv':\n // user's other session marked some messges as received.\n pres.seq = pres.seq | 0;\n cont.recv = cont.recv ? Math.max(cont.recv, pres.seq) : pres.seq;\n break;\n case 'read':\n // user's other session marked some messages as read.\n pres.seq = pres.seq | 0;\n cont.read = cont.read ? Math.max(cont.read, pres.seq) : pres.seq;\n cont.recv = cont.recv ? Math.max(cont.read, cont.recv) : cont.recv;\n cont.unread = cont.seq - cont.read;\n break;\n case 'gone':\n // topic deleted or unsubscribed from.\n this._tinode.cacheRemTopic(pres.src);\n if (!cont._deleted) {\n cont._deleted = true;\n cont._attached = false;\n this._tinode._db.markTopicAsDeleted(pres.src, true);\n } else {\n this._tinode._db.remTopic(pres.src);\n }\n break;\n case 'del':\n // Update topic.del value.\n break;\n default:\n this._tinode.logger(\"INFO: Unsupported presence update in 'me'\", pres.what);\n }\n\n this._refreshContact(pres.what, cont);\n } else {\n if (pres.what == 'acs') {\n // New subscriptions and deleted/banned subscriptions have full\n // access mode (no + or - in the dacs string). Changes to known subscriptions are sent as\n // deltas, but they should not happen here.\n const acs = new AccessMode(pres.dacs);\n if (!acs || acs.mode == AccessMode._INVALID) {\n this._tinode.logger(\"ERROR: Invalid access mode update\", pres.src, pres.dacs);\n return;\n } else if (acs.mode == AccessMode._NONE) {\n this._tinode.logger(\"WARNING: Removing non-existent subscription\", pres.src, pres.dacs);\n return;\n } else {\n // New subscription. Send request for the full description.\n // Using .withOneSub (not .withLaterOneSub) to make sure IfModifiedSince is not set.\n this.getMeta(this.startMetaQuery().withOneSub(undefined, pres.src).build());\n // Create a dummy entry to catch online status update.\n const dummy = this._tinode.getTopic(pres.src);\n dummy.topic = pres.src;\n dummy.online = false;\n dummy.acs = acs;\n this._tinode._db.updTopic(dummy);\n }\n } else if (pres.what == 'tags') {\n this.getMeta(this.startMetaQuery().withTags().build());\n } else if (pres.what == 'msg') {\n // Message received for un unknown (previously deleted) topic.\n this.getMeta(this.startMetaQuery().withOneSub(undefined, pres.src).build());\n // Create an entry to catch updates and messages.\n const dummy = this._tinode.getTopic(pres.src);\n dummy._deleted = false;\n this._tinode._db.updTopic(dummy);\n }\n\n this._refreshContact(pres.what, cont);\n }\n\n if (this.onPres) {\n this.onPres(pres);\n }\n }\n\n // Contact is updated, execute callbacks.\n _refreshContact(what, cont) {\n if (this.onContactUpdate) {\n this.onContactUpdate(what, cont);\n }\n }\n\n /**\n * Publishing to TopicMe is not supported. {@link Topic#publish} is overriden and thows an {Error} if called.\n * @memberof Tinode.TopicMe#\n * @throws {Error} Always throws an error.\n */\n publish() {\n return Promise.reject(new Error(\"Publishing to 'me' is not supported\"));\n }\n\n /**\n * Delete validation credential.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} topic - Name of the topic to delete\n * @param {string} user - User ID to remove.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delCredential(method, value) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot delete credential in inactive 'me' topic\"));\n }\n // Send {del} message, return promise\n return this._tinode.delCredential(method, value).then(ctrl => {\n // Remove deleted credential from the cache.\n const index = this._credentials.findIndex((el) => {\n return el.meth == method && el.val == value;\n });\n if (index > -1) {\n this._credentials.splice(index, 1);\n }\n // Notify listeners\n if (this.onCredsUpdated) {\n this.onCredsUpdated(this._credentials);\n }\n return ctrl;\n });\n }\n\n /**\n * @callback contactFilter\n * @param {Object} contact to check for inclusion.\n * @returns {boolean} true if contact should be processed, false to exclude it.\n */\n /**\n * Iterate over cached contacts.\n *\n * @function\n * @memberof Tinode.TopicMe#\n * @param {TopicMe.ContactCallback} callback - Callback to call for each contact.\n * @param {contactFilter=} filter - Optionally filter contacts; include all if filter is false-ish, otherwise\n * include those for which filter returns true-ish.\n * @param {Object=} context - Context to use for calling the `callback`, i.e. the value of `this` inside the callback.\n */\n contacts(callback, filter, context) {\n this._tinode.mapTopics((c, idx) => {\n if (c.isCommType() && (!filter || filter(c))) {\n callback.call(context, c, idx);\n }\n });\n }\n\n /**\n * Get a contact from cache.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} name - Name of the contact to get, either a UID (for p2p topics) or a topic name.\n * @returns {Tinode.Contact} - Contact or `undefined`.\n */\n getContact(name) {\n return this._tinode.cacheGetTopic(name);\n }\n\n /**\n * Get access mode of a given contact from cache.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} name - Name of the contact to get access mode for, either a UID (for p2p topics)\n * or a topic name; if missing, access mode for the 'me' topic itself.\n * @returns {string} - access mode, such as `RWP`.\n */\n getAccessMode(name) {\n if (name) {\n const cont = this._tinode.cacheGetTopic(name);\n return cont ? cont.acs : null;\n }\n return this.acs;\n }\n\n /**\n * Check if contact is archived, i.e. contact.private.arch == true.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} name - Name of the contact to check archived status, either a UID (for p2p topics) or a topic name.\n * @returns {boolean} - true if contact is archived, false otherwise.\n */\n isArchived(name) {\n const cont = this._tinode.cacheGetTopic(name);\n return cont && cont.private && !!cont.private.arch;\n }\n\n /**\n * @typedef Tinode.Credential\n * @memberof Tinode\n * @type Object\n * @property {string} meth - validation method such as 'email' or 'tel'.\n * @property {string} val - credential value, i.e. 'jdoe@example.com' or '+17025551234'\n * @property {boolean} done - true if credential is validated.\n */\n /**\n * Get the user's credentials: email, phone, etc.\n * @memberof Tinode.TopicMe#\n *\n * @returns {Tinode.Credential[]} - array of credentials.\n */\n getCredentials() {\n return this._credentials;\n }\n}\n","/**\n * @file Helper class for constructing {@link Tinode.GetQuery}.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport {\n listToRanges,\n normalizeRanges\n} from './utils';\n\n/**\n * Helper class for constructing {@link Tinode.GetQuery}.\n *\n * @class MetaGetBuilder\n * @memberof Tinode\n *\n * @param {Tinode.Topic} parent topic which instantiated this builder.\n */\nexport default class MetaGetBuilder {\n constructor(parent) {\n this.topic = parent;\n this.what = {};\n }\n\n // Get timestamp of the most recent desc update.\n #get_desc_ims() {\n return this.topic._deleted ? undefined : this.topic.updated;\n }\n\n // Get timestamp of the most recent subs update.\n #get_subs_ims() {\n if (this.topic.isP2PType()) {\n return this.#get_desc_ims();\n }\n return this.topic._deleted ? undefined : this.topic._lastSubsUpdate;\n }\n /**\n * Add query parameters to fetch messages within explicit limits.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} since - messages newer than this (inclusive);\n * @param {number=} before - older than this (exclusive)\n * @param {number=} limit - number of messages to fetch\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withData(since, before, limit) {\n this.what['data'] = {\n since: since,\n before: before,\n limit: limit\n };\n return this;\n }\n /**\n * Add query parameters to fetch messages newer than the latest saved message.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - number of messages to fetch\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterData(limit) {\n return this.withData(this.topic._maxSeq > 0 ? this.topic._maxSeq + 1 : undefined, undefined, limit);\n }\n /**\n * Add query parameters to fetch messages within ID ranges.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Array.} ranges - ranges of seq IDs to fetch.\n * @param {number=} limit - maximum number of messages to fetch.\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDataRanges(ranges, limit) {\n this.what['data'] = {\n ranges: normalizeRanges(ranges, this.topic._maxSeq),\n limit: limit\n };\n return this;\n }\n /**\n * Add query parameters to fetch messages by an array of IDs.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number[]} list - array of seq IDs to fetch.\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDataList(list) {\n return this.withDataRanges(listToRanges(list));\n }\n /**\n * Add query parameters to fetch messages older than the earliest saved message.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - maximum number of messages to fetch.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withEarlierData(limit) {\n return this.withData(undefined, this.topic._minSeq > 0 ? this.topic._minSeq : undefined, limit);\n }\n /**\n * Add query parameters to fetch topic description if it's newer than the given timestamp.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Date=} ims - fetch messages newer than this timestamp.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDesc(ims) {\n this.what['desc'] = {\n ims: ims\n };\n return this;\n }\n /**\n * Add query parameters to fetch topic description if it's newer than the last update.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterDesc() {\n return this.withDesc(this.#get_desc_ims());\n }\n /**\n * Add query parameters to fetch subscriptions.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Date=} ims - fetch subscriptions modified more recently than this timestamp\n * @param {number=} limit - maximum number of subscriptions to fetch.\n * @param {string=} userOrTopic - user ID or topic name to fetch for fetching one subscription.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withSub(ims, limit, userOrTopic) {\n const opts = {\n ims: ims,\n limit: limit\n };\n if (this.topic.getType() == 'me') {\n opts.topic = userOrTopic;\n } else {\n opts.user = userOrTopic;\n }\n this.what['sub'] = opts;\n return this;\n }\n /**\n * Add query parameters to fetch a single subscription.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Date=} ims - fetch subscriptions modified more recently than this timestamp\n * @param {string=} userOrTopic - user ID or topic name to fetch for fetching one subscription.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withOneSub(ims, userOrTopic) {\n return this.withSub(ims, undefined, userOrTopic);\n }\n /**\n * Add query parameters to fetch a single subscription if it's been updated since the last update.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {string=} userOrTopic - user ID or topic name to fetch for fetching one subscription.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterOneSub(userOrTopic) {\n return this.withOneSub(this.topic._lastSubsUpdate, userOrTopic);\n }\n /**\n * Add query parameters to fetch subscriptions updated since the last update.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - maximum number of subscriptions to fetch.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterSub(limit) {\n return this.withSub(this.#get_subs_ims(), limit);\n }\n /**\n * Add query parameters to fetch topic tags.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withTags() {\n this.what['tags'] = true;\n return this;\n }\n /**\n * Add query parameters to fetch user's credentials. 'me' topic only.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withCred() {\n if (this.topic.getType() == 'me') {\n this.what['cred'] = true;\n } else {\n this.topic._tinode.logger(\"ERROR: Invalid topic type for MetaGetBuilder:withCreds\", this.topic.getType());\n }\n return this;\n }\n /**\n * Add query parameters to fetch topic tags.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withAux() {\n this.what['aux'] = true;\n return this;\n }\n /**\n * Add query parameters to fetch deleted messages within explicit limits. Any/all parameters can be null.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} since - ids of messages deleted since this 'del' id (inclusive)\n * @param {number=} limit - number of deleted message ids to fetch\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDel(since, limit) {\n if (since || limit) {\n this.what['del'] = {\n since: since,\n limit: limit\n };\n }\n return this;\n }\n /**\n * Add query parameters to fetch messages deleted after the saved 'del' id.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - number of deleted message ids to fetch\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterDel(limit) {\n // Specify 'since' only if we have already received some messages. If\n // we have no locally cached messages then we don't care if any messages were deleted.\n return this.withDel(this.topic._maxSeq > 0 ? this.topic._maxDel + 1 : undefined, limit);\n }\n\n /**\n * Extract subquery: get an object that contains specified subquery.\n * @memberof Tinode.MetaGetBuilder#\n * @param {string} what - subquery to return: one of 'data', 'sub', 'desc', 'tags', 'cred', 'del'.\n * @returns {Object} requested subquery or undefined.\n */\n extract(what) {\n return this.what[what];\n }\n\n /**\n * Construct parameters.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.GetQuery} Get query\n */\n build() {\n const what = [];\n let params = {};\n ['data', 'sub', 'desc', 'tags', 'cred', 'aux', 'del'].forEach((key) => {\n if (this.what.hasOwnProperty(key)) {\n what.push(key);\n if (Object.getOwnPropertyNames(this.what[key]).length > 0) {\n params[key] = this.what[key];\n }\n }\n });\n if (what.length > 0) {\n params.what = what.join(' ');\n } else {\n params = undefined;\n }\n return params;\n }\n}\n","/**\n * @file Topic management.\n *\n * @copyright 2015-2025 Tinode LLC.\n */\n'use strict';\n\nimport AccessMode from './access-mode.js';\nimport CBuffer from './cbuffer.js';\nimport CommError from './comm-error.js';\nimport * as Const from './config.js';\nimport Drafty from './drafty.js';\nimport MetaGetBuilder from './meta-builder.js';\nimport {\n listToRanges,\n mergeObj,\n mergeToCache,\n normalizeArray,\n normalizeRanges\n} from './utils.js';\n\n/**\n * Topic is a class representing a logical communication channel.\n */\nexport default class Topic {\n /**\n * @callback onData\n * @param {Data} data - Data packet\n */\n\n /**\n * Create topic.\n * @param {string} name - Name of the topic to create.\n * @param {Object=} callbacks - Object with various event callbacks.\n * @param {onData} callbacks.onData - Callback which receives a {data} message.\n * @param {callback} callbacks.onMeta - Callback which receives a {meta} message.\n * @param {callback} callbacks.onPres - Callback which receives a {pres} message.\n * @param {callback} callbacks.onInfo - Callback which receives an {info} message.\n * @param {callback} callbacks.onMetaDesc - Callback which receives changes to topic desctioption {@link desc}.\n * @param {callback} callbacks.onMetaSub - Called for a single subscription record change.\n * @param {callback} callbacks.onSubsUpdated - Called after a batch of subscription changes have been recieved and cached.\n * @param {callback} callbacks.onDeleteTopic - Called after the topic is deleted.\n * @param {callback} callbacls.onAllMessagesReceived - Called when all requested {data} messages have been recived.\n */\n constructor(name, callbacks) {\n // Parent Tinode object.\n this._tinode = null;\n\n // Server-provided data, locally immutable.\n // topic name\n this.name = name;\n // Timestamp when the topic was created.\n this.created = null;\n // Timestamp when the topic was last updated.\n this.updated = null;\n // Timestamp of the last messages\n this.touched = new Date(0);\n // Access mode, see AccessMode\n this.acs = new AccessMode(null);\n // Per-topic private data (accessible by current user only).\n this.private = null;\n // Per-topic public data (accessible by all users).\n this.public = null;\n // Per-topic system-provided data (accessible by all users).\n this.trusted = null;\n\n // Locally cached data\n // Subscribed users, for tracking read/recv/msg notifications.\n this._users = {};\n\n // Current value of locally issued seqId, used for pending messages.\n this._queuedSeqId = Const.LOCAL_SEQID;\n\n // The maximum known {data.seq} value.\n this._maxSeq = 0;\n // The minimum known {data.seq} value.\n this._minSeq = 0;\n // Indicator that the last request for earlier messages returned 0.\n this._noEarlierMsgs = false;\n // The maximum known deletion ID.\n this._maxDel = 0;\n // Timer object used to send 'recv' notifications.\n this._recvNotificationTimer = null;\n\n // User discovery tags\n this._tags = [];\n // Credentials such as email or phone number.\n this._credentials = [];\n // Auxiliary data\n this._aux = {};\n\n // Message versions cache (e.g. for edited messages).\n // Keys: original message seq ID.\n // Values: CBuffers containing newer versions of the original message\n // ordered by seq id.\n this._messageVersions = {};\n // Message cache, sorted by message seq values, from old to new.\n this._messages = new CBuffer((a, b) => {\n return a.seq - b.seq;\n }, true);\n // Boolean, true if the topic is currently live\n this._attached = false;\n // Timestap of the most recently updated subscription.\n this._lastSubsUpdate = new Date(0);\n // Topic created but not yet synced with the server. Used only during initialization.\n this._new = true;\n // The topic is deleted at the server, this is a local copy.\n this._deleted = false;\n\n // Timer used to trgger {leave} request after a delay.\n this._delayedLeaveTimer = null;\n\n // Callbacks\n if (callbacks) {\n this.onData = callbacks.onData;\n this.onMeta = callbacks.onMeta;\n this.onPres = callbacks.onPres;\n this.onInfo = callbacks.onInfo;\n // A single desc update;\n this.onMetaDesc = callbacks.onMetaDesc;\n // A single subscription record;\n this.onMetaSub = callbacks.onMetaSub;\n // All subscription records received;\n this.onSubsUpdated = callbacks.onSubsUpdated;\n this.onTagsUpdated = callbacks.onTagsUpdated;\n this.onCredsUpdated = callbacks.onCredsUpdated;\n this.onAuxUpdated = callbacks.onAuxUpdated;\n this.onDeleteTopic = callbacks.onDeleteTopic;\n this.onAllMessagesReceived = callbacks.onAllMessagesReceived;\n }\n }\n\n // Static methods.\n\n /**\n * Determine topic type from topic's name: grp, p2p, me, fnd, sys.\n *\n * @param {string} name - Name of the topic to test.\n * @returns {string} One of \"me\", \"fnd\", \"sys\", \"grp\",\n * \"p2p\" or undefined.\n */\n static topicType(name) {\n const types = {\n 'me': Const.TOPIC_ME,\n 'fnd': Const.TOPIC_FND,\n 'grp': Const.TOPIC_GRP,\n 'new': Const.TOPIC_GRP,\n 'nch': Const.TOPIC_GRP,\n 'chn': Const.TOPIC_GRP,\n 'usr': Const.TOPIC_P2P,\n 'sys': Const.TOPIC_SYS,\n 'slf': Const.TOPIC_SLF\n };\n return types[(typeof name == 'string') ? name.substring(0, 3) : 'xxx'];\n }\n\n /**\n * Check if the given topic name is a name of a 'me' topic.\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'me' topic, false otherwise.\n */\n static isMeTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_ME;\n }\n\n /**\n * Check if the given topic name is a name of a 'slf' topic.\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'slf' topic, false otherwise.\n */\n static isSelfTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_SLF;\n }\n\n /**\n * Check if the given topic name is a name of a group topic.\n * @static\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a group topic, false otherwise.\n */\n static isGroupTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_GRP;\n }\n\n /**\n * Check if the given topic name is a name of a p2p topic.\n * @static\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p topic, false otherwise.\n */\n static isP2PTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_P2P;\n }\n\n /**\n * Check if the given topic name is a name of a communication topic, i.e. P2P or group.\n * @static\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p or group topic, false otherwise.\n */\n static isCommTopicName(name) {\n return Topic.isP2PTopicName(name) || Topic.isGroupTopicName(name) || Topic.isSelfTopicName(name);\n }\n\n /**\n * Check if the topic name is a name of a new topic.\n * @static\n *\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a new topic, false otherwise.\n */\n static isNewGroupTopicName(name) {\n return (typeof name == 'string') &&\n (name.substring(0, 3) == Const.TOPIC_NEW || name.substring(0, 3) == Const.TOPIC_NEW_CHAN);\n }\n\n /**\n * Check if the topic name is a name of a channel.\n * @static\n *\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a channel, false otherwise.\n */\n static isChannelTopicName(name) {\n return (typeof name == 'string') &&\n (name.substring(0, 3) == Const.TOPIC_CHAN || name.substring(0, 3) == Const.TOPIC_NEW_CHAN);\n }\n\n // Returns true if pub is meant to replace another message (e.g. original message was edited).\n static #isReplacementMsg(pub) {\n return pub.head && pub.head.replace;\n }\n\n /**\n * Check if the topic is subscribed.\n * @returns {boolean} True is topic is attached/subscribed, false otherwise.\n */\n isSubscribed() {\n return this._attached;\n }\n\n /**\n * Request topic to subscribe. Wrapper for {@link Tinode#subscribe}.\n *\n * @param {Tinode.GetQuery=} getParams - get query parameters.\n * @param {Tinode.SetParams=} setParams - set parameters.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n subscribe(getParams, setParams) {\n // Clear request to leave topic.\n clearTimeout(this._delayedLeaveTimer);\n this._delayedLeaveTimer = null;\n\n // If the topic is already subscribed, return resolved promise\n if (this._attached) {\n return Promise.resolve(this);\n }\n\n // Send subscribe message, handle async response.\n // If topic name is explicitly provided, use it. If no name, then it's a new group topic,\n // use \"new\".\n return this._tinode.subscribe(this.name || Const.TOPIC_NEW, getParams, setParams).then(ctrl => {\n if (ctrl.code >= 300) {\n // Do nothing if subscription status has not changed.\n return ctrl;\n }\n\n this._attached = true;\n this._deleted = false;\n this.acs = (ctrl.params && ctrl.params.acs) ? ctrl.params.acs : this.acs;\n\n // Set topic name for new topics and add it to cache.\n if (this._new) {\n delete this._new;\n\n if (this.name != ctrl.topic) {\n // Name may change new123456 -> grpAbCdEf. Remove from cache under the old name.\n this._cacheDelSelf();\n this.name = ctrl.topic;\n }\n this._cachePutSelf();\n\n this.created = ctrl.ts;\n this.updated = ctrl.ts;\n\n if (this.name != Const.TOPIC_ME && this.name != Const.TOPIC_FND) {\n // Add the new topic to the list of contacts maintained by the 'me' topic.\n const me = this._tinode.getMeTopic();\n if (me.onMetaSub) {\n me.onMetaSub(this);\n }\n if (me.onSubsUpdated) {\n me.onSubsUpdated([this.name], 1);\n }\n }\n\n if (setParams && setParams.desc) {\n setParams.desc._noForwarding = true;\n this._processMetaDesc(setParams.desc);\n }\n }\n return ctrl;\n });\n }\n\n /**\n * Create a draft of a message without sending it to the server.\n * @memberof Tinode.Topic#\n *\n * @param {string | Object} data - Content to wrap in a draft.\n * @param {boolean=} noEcho - If true server will not echo message back to originating\n * session. Otherwise the server will send a copy of the message to sender.\n *\n * @returns {Object} message draft.\n */\n createMessage(data, noEcho) {\n return this._tinode.createMessage(this.name, data, noEcho);\n }\n\n /**\n * Immediately publish data to topic. Wrapper for {@link Tinode#publish}.\n * @memberof Tinode.Topic#\n *\n * @param {string | Object} data - Message to publish, either plain string or a Drafty object.\n * @param {boolean=} noEcho - If true server will not echo message back to originating\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n publish(data, noEcho) {\n return this.publishMessage(this.createMessage(data, noEcho));\n }\n\n /**\n * Publish message created by {@link Tinode.Topic#createMessage}.\n * @memberof Tinode.Topic#\n *\n * @param {Object} pub - {data} object to publish. Must be created by {@link Tinode.Topic#createMessage}\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n publishMessage(pub) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot publish on inactive topic\"));\n }\n if (this._sending) {\n return Promise.reject(new Error(\"The message is already being sent\"));\n }\n\n // Send data.\n pub._sending = true;\n pub._failed = false;\n\n // Extract refereces to attachments and out of band image records.\n let attachments = null;\n if (Drafty.hasEntities(pub.content)) {\n attachments = [];\n Drafty.entities(pub.content, data => {\n if (data) {\n if (data.ref) {\n attachments.push(data.ref);\n }\n if (data.preref) {\n attachments.push(data.preref);\n }\n }\n });\n if (attachments.length == 0) {\n attachments = null;\n }\n }\n\n return this._tinode.publishMessage(pub, attachments).then(ctrl => {\n pub._sending = false;\n pub.ts = ctrl.ts;\n this.swapMessageId(pub, ctrl.params.seq);\n this._maybeUpdateMessageVersionsCache(pub);\n this._routeData(pub);\n return ctrl;\n }).catch(err => {\n this._tinode.logger(\"WARNING: Message rejected by the server\", err);\n pub._sending = false;\n pub._failed = true;\n if (this.onData) {\n this.onData();\n }\n });\n }\n\n /**\n * Add message to local message cache, send to the server when the promise is resolved.\n * If promise is null or undefined, the message will be sent immediately.\n * The message is sent when the\n * The message should be created by {@link Tinode.Topic#createMessage}.\n * This is probably not the final API.\n * @memberof Tinode.Topic#\n *\n * @param {Object} pub - Message to use as a draft.\n * @param {Promise} prom - Message will be sent when this promise is resolved, discarded if rejected.\n *\n * @returns {Promise} derived promise.\n */\n publishDraft(pub, prom) {\n const seq = pub.seq || this._getQueuedSeqId();\n if (!pub._noForwarding) {\n // The 'seq', 'ts', and 'from' are added to mimic {data}. They are removed later\n // before the message is sent.\n pub._noForwarding = true;\n pub.seq = seq;\n pub.ts = new Date();\n pub.from = this._tinode.getCurrentUserID();\n\n // Don't need an echo message because the message is added to local cache right away.\n pub.noecho = true;\n // Add to cache.\n this._messages.put(pub);\n this._tinode._db.addMessage(pub);\n\n if (this.onData) {\n this.onData(pub);\n }\n }\n // If promise is provided, send the queued message when it's resolved.\n // If no promise is provided, create a resolved one and send immediately.\n return (prom || Promise.resolve())\n .then(_ => {\n if (pub._cancelled) {\n return {\n code: 300,\n text: \"cancelled\"\n };\n }\n return this.publishMessage(pub);\n }).catch(err => {\n this._tinode.logger(\"WARNING: Message draft rejected\", err);\n pub._sending = false;\n pub._failed = true;\n pub._fatal = err instanceof CommError ? (err.code >= 400 && err.code < 500) : false;\n if (this.onData) {\n this.onData();\n }\n // Rethrow to let caller know that the operation failed.\n throw err;\n });\n }\n\n /**\n * Leave the topic, optionally unsibscribe. Leaving the topic means the topic will stop\n * receiving updates from the server. Unsubscribing will terminate user's relationship with the topic.\n * Wrapper for {@link Tinode#leave}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean=} unsub - If true, unsubscribe, otherwise just leave.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n leave(unsub) {\n // It's possible to unsubscribe (unsub==true) from inactive topic.\n if (!this._attached && !unsub) {\n return Promise.reject(new Error(\"Cannot leave inactive topic\"));\n }\n\n // Send a 'leave' message, handle async response\n return this._tinode.leave(this.name, unsub).then(ctrl => {\n this._resetSub();\n if (unsub) {\n this._gone();\n }\n return ctrl;\n });\n }\n\n /**\n * Leave the topic, optionally unsibscribe after a delay. Leaving the topic means the topic will stop\n * receiving updates from the server. Unsubscribing will terminate user's relationship with the topic.\n * Wrapper for {@link Tinode#leave}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} unsub - If true, unsubscribe, otherwise just leave.\n * @param {number} delay - time in milliseconds to delay leave request.\n */\n leaveDelayed(unsub, delay) {\n clearTimeout(this._delayedLeaveTimer);\n this._delayedLeaveTimer = setTimeout(_ => {\n this._delayedLeaveTimer = null;\n this.leave(unsub)\n }, delay);\n }\n\n /**\n * Request topic metadata from the local cache or from the server.\n * @memberof Tinode.Topic#\n *\n * @param {Tinode.GetQuery} request parameters\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n getMeta(params) {\n // Send {get} message, return promise.\n return this._tinode.getMeta(this.name, params);\n }\n\n /**\n * Request more messages from the server. The goal is to load continous range of messages\n * covering at least between 'min' and 'max' + one full page forward (newer = true) or backwards\n * (newer=false).\n * @memberof Tinode.Topic#\n *\n * @param {number} limit number of messages to get.\n * @param {Array.} gaps - ranges of messages to load.\n * @param {number} min if non-negative, request newer messages with seq >= min.\n * @param {number} max if positive, request older messages with seq < max.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n getMessagesPage(limit, gaps, min, max, newer) {\n let query = gaps ?\n this.startMetaQuery().withDataRanges(gaps, limit) :\n newer ?\n this.startMetaQuery().withData(min, undefined, limit) :\n this.startMetaQuery().withData(undefined, max, limit);\n // First try fetching from DB, then from the server.\n return this._loadMessages(this._tinode._db, query.extract('data'))\n .then(count => {\n // Recalculate missing ranges.\n gaps = this.msgHasMoreMessages(min, max, newer);\n if (gaps.length == 0) {\n // All messages loaded.\n return Promise.resolve({\n topic: this.name,\n code: 200,\n params: {\n count: count\n }\n });\n }\n\n // Reduce the count of requested messages.\n limit -= count;\n // Update query with new values loaded from DB.\n query = this.startMetaQuery().withDataRanges(gaps, limit);\n return this.getMeta(query.build());\n });\n }\n\n /**\n * Request to get pinned messages from the local cache or from the server.\n * @memberof Tinode.Topic#\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n getPinnedMessages() {\n const pins = this.aux('pins');\n if (!Array.isArray(pins)) {\n return Promise.resolve(0);\n }\n\n const loaded = [];\n let remains = pins;\n // First try fetching from DB, then check deleted log, then ask the server.\n return this._tinode._db.readMessages(this.name, {\n ranges: listToRanges(remains)\n })\n .then(msgs => {\n msgs.forEach(data => {\n // The 'data' could be undefined.\n if (data) {\n loaded.push(data.seq);\n this._messages.put(data);\n this._maybeUpdateMessageVersionsCache(data);\n }\n });\n if (loaded.length < pins.length) {\n // Some messages are missing, try dellog.\n remains = pins.filter(seq => !loaded.includes(seq));\n return this._tinode._db.readMessages(this.name, {\n ranges: listToRanges(remains)\n });\n }\n return null;\n })\n .then(ranges => {\n if (ranges) {\n // Found some deleted ranges in dellog.\n remains.forEach(seq => {\n if (ranges.find(r => r.low <= seq && r.hi > seq)) {\n loaded.push(seq);\n }\n });\n }\n if (loaded.length == pins.length) {\n // Got all pinned messages from the local cache.\n return Promise.resolve({\n topic: this.name,\n code: 200,\n params: {\n count: loaded.length\n }\n });\n }\n\n remains = pins.filter(seq => !loaded.includes(seq));\n return this.getMeta(this.startMetaQuery().withDataList(remains).build());\n });\n }\n\n /**\n * Update topic metadata.\n * @memberof Tinode.Topic#\n *\n * @param {Tinode.SetParams} params parameters to update.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n setMeta(params) {\n if (params.tags) {\n params.tags = normalizeArray(params.tags);\n }\n // Send Set message, handle async response.\n return this._tinode.setMeta(this.name, params)\n .then(ctrl => {\n if (ctrl && ctrl.code >= 300) {\n // Not modified\n return ctrl;\n }\n\n if (params.sub) {\n params.sub.topic = this.name;\n if (ctrl.params && ctrl.params.acs) {\n params.sub.acs = ctrl.params.acs;\n params.sub.updated = ctrl.ts;\n }\n if (!params.sub.user) {\n // This is a subscription update of the current user.\n // Assign user ID otherwise the update will be ignored by _processMetaSubs.\n params.sub.user = this._tinode.getCurrentUserID();\n if (!params.desc) {\n // Force update to topic's asc.\n params.desc = {};\n }\n }\n params.sub._noForwarding = true;\n this._processMetaSubs([params.sub]);\n }\n\n if (params.desc) {\n if (ctrl.params && ctrl.params.acs) {\n params.desc.acs = ctrl.params.acs;\n params.desc.updated = ctrl.ts;\n }\n this._processMetaDesc(params.desc);\n }\n\n if (params.tags) {\n this._processMetaTags(params.tags);\n }\n if (params.cred) {\n this._processMetaCreds([params.cred], true);\n }\n if (params.aux) {\n this._processMetaAux(params.aux);\n }\n\n return ctrl;\n });\n }\n /**\n * Update access mode of the current user or of another topic subsriber.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - UID of the user to update or null to update current user.\n * @param {string} update - the update value, full or delta.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n updateMode(uid, update) {\n const user = uid ? this.subscriber(uid) : null;\n const am = user ?\n user.acs.updateGiven(update).getGiven() :\n this.getAccessMode().updateWant(update).getWant();\n\n return this.setMeta({\n sub: {\n user: uid,\n mode: am\n }\n });\n }\n /**\n * Create new topic subscription. Wrapper for {@link Tinode#setMeta}.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - ID of the user to invite\n * @param {string=} mode - Access mode. null means to use default.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n invite(uid, mode) {\n return this.setMeta({\n sub: {\n user: uid,\n mode: mode\n }\n });\n }\n /**\n * Archive or un-archive the topic. Wrapper for {@link Tinode#setMeta}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} arch - true to archive the topic, false otherwise.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n archive(arch) {\n if (this.private && (!this.private.arch == !arch)) {\n return Promise.resolve(arch);\n }\n return this.setMeta({\n desc: {\n private: {\n arch: arch ? true : Const.DEL_CHAR\n }\n }\n });\n }\n /**\n * Set message as pinned or unpinned by adding it to aux.pins array. Wrapper for {@link Tinode#setMeta}.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - seq ID of the message to pin or un-pin.\n * @param {boolean} pin - true to pin the message, false to un-pin.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n pinMessage(seq, pin) {\n let pinned = this.aux('pins');\n if (!Array.isArray(pinned)) {\n pinned = [];\n }\n let changed = false;\n if (pin) {\n if (!pinned.includes(seq)) {\n changed = true;\n if (pinned.length == Const.MAX_PINNED_COUNT) {\n pinned.shift();\n }\n pinned.push(seq);\n }\n } else {\n if (pinned.includes(seq)) {\n changed = true;\n pinned = pinned.filter(id => id != seq);\n if (pinned.length == 0) {\n pinned = Const.DEL_CHAR;\n }\n }\n }\n if (changed) {\n return this.setMeta({\n aux: {\n pins: pinned\n }\n });\n }\n return Promise.resolve();\n }\n /**\n * Delete messages. Hard-deleting messages requires Deleter (D) permission.\n * Wrapper for {@link Tinode#delMessages}.\n * @memberof Tinode.Topic#\n *\n * @param {Array.} ranges - Ranges of message IDs to delete.\n * @param {boolean=} hard - Hard or soft delete\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delMessages(ranges, hard) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot delete messages in inactive topic\"));\n }\n\n const tosend = normalizeRanges(ranges, this._maxSeq)\n\n // Send {del} message, return promise\n let result;\n if (tosend.length > 0) {\n result = this._tinode.delMessages(this.name, tosend, hard);\n } else {\n result = Promise.resolve({\n params: {\n del: 0\n }\n });\n }\n // Update local cache.\n return result.then(ctrl => {\n if (ctrl.params.del > this._maxDel) {\n this._maxDel = Math.max(ctrl.params.del, this._maxDel);\n this.clear = Math.max(ctrl.params.del, this.clear);\n }\n\n ranges.forEach(rec => {\n if (rec.hi) {\n this.flushMessageRange(rec.low, rec.hi);\n } else {\n this.flushMessage(rec.low);\n }\n this._messages.put({\n seq: rec.low,\n low: rec.low,\n hi: rec.hi,\n _deleted: true\n });\n });\n\n // Make a record.\n this._tinode._db.addDelLog(this.name, ctrl.params.del, ranges);\n\n if (this.onData) {\n // Calling with no parameters to indicate the messages were deleted.\n this.onData();\n }\n return ctrl;\n });\n }\n /**\n * Delete all messages. Hard-deleting messages requires Deleter permission.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} hardDel - true if messages should be hard-deleted.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delMessagesAll(hardDel) {\n if (!this._maxSeq || this._maxSeq <= 0) {\n // There are no messages to delete.\n return Promise.resolve();\n }\n return this.delMessages([{\n low: 1,\n hi: this._maxSeq + 1,\n _all: true\n }], hardDel);\n }\n\n /**\n * Delete multiple messages defined by their IDs. Hard-deleting messages requires Deleter permission.\n * @memberof Tinode.Topic#\n *\n * @param {Array.} list - list of seq IDs to delete.\n * @param {boolean=} hardDel - true if messages should be hard-deleted.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delMessagesList(list, hardDel) {\n // Send {del} message, return promise\n return this.delMessages(listToRanges(list), hardDel);\n }\n\n /**\n * Delete original message and edited variants. Hard-deleting messages requires Deleter permission.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - original seq ID of the message to delete.\n * @param {boolean=} hardDel - true if messages should be hard-deleted.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n delMessagesEdits(seq, hardDel) {\n const list = [seq];\n this.messageVersions(seq, msg => list.push(msg.seq));\n // Send {del} message, return promise\n return this.delMessagesList(list, hardDel);\n }\n\n /**\n * Delete topic. Requires Owner permission. Wrapper for {@link Tinode#delTopic}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} hard - had-delete topic.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n delTopic(hard) {\n if (this._deleted) {\n // The topic is already deleted at the server, just remove from DB.\n this._gone();\n return Promise.resolve(null);\n }\n\n return this._tinode.delTopic(this.name, hard).then(ctrl => {\n this._deleted = true;\n this._resetSub();\n this._gone();\n return ctrl;\n });\n }\n /**\n * Delete subscription. Requires Share permission. Wrapper for {@link Tinode#delSubscription}.\n * @memberof Tinode.Topic#\n *\n * @param {string} user - ID of the user to remove subscription for.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delSubscription(user) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot delete subscription in inactive topic\"));\n }\n // Send {del} message, return promise\n return this._tinode.delSubscription(this.name, user).then(ctrl => {\n // Remove the object from the subscription cache;\n delete this._users[user];\n // Notify listeners\n if (this.onSubsUpdated) {\n this.onSubsUpdated(Object.keys(this._users));\n }\n return ctrl;\n });\n }\n /**\n * Send a read/recv notification.\n * @memberof Tinode.Topic#\n *\n * @param {string} what - what notification to send: recv, read.\n * @param {number} seq - ID or the message read or received.\n */\n note(what, seq) {\n if (!this._attached) {\n // Cannot sending {note} on an inactive topic\".\n return;\n }\n\n // Update local cache with the new count.\n const user = this._users[this._tinode.getCurrentUserID()];\n let update = false;\n if (user) {\n // Self-subscription is found.\n if (!user[what] || user[what] < seq) {\n user[what] = seq;\n update = true;\n }\n } else {\n // Self-subscription is not found.\n update = (this[what] | 0) < seq;\n }\n\n if (update) {\n // Send notification to the server.\n this._tinode.note(this.name, what, seq);\n // Update locally cached contact with the new count.\n this._updateMyReadRecv(what, seq);\n\n if (this.acs != null && !this.acs.isMuted()) {\n const me = this._tinode.getMeTopic();\n // Sent a notification to 'me' listeners.\n me._refreshContact(what, this);\n }\n }\n }\n\n /**\n * Send a 'recv' receipt. Wrapper for {@link Tinode#noteRecv}.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - ID of the message to aknowledge.\n */\n noteRecv(seq) {\n this.note('recv', seq);\n }\n /**\n * Send a 'read' receipt. Wrapper for {@link Tinode#noteRead}.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - ID of the message to aknowledge or 0/undefined to acknowledge the latest messages.\n */\n noteRead(seq) {\n seq = seq || this._maxSeq;\n if (seq > 0) {\n this.note('read', seq);\n }\n }\n /**\n * Send a key-press notification. Wrapper for {@link Tinode#noteKeyPress}.\n * @memberof Tinode.Topic#\n */\n noteKeyPress() {\n if (this._attached) {\n this._tinode.noteKeyPress(this.name);\n } else {\n this._tinode.logger(\"INFO: Cannot send notification in inactive topic\");\n }\n }\n /**\n * Send a notification than a video or audio message is . Wrapper for {@link Tinode#noteKeyPress}.\n * @memberof Tinode.Topic#\n * @param audioOnly - true if the recording is audio-only, false if it's a video recording.\n */\n noteRecording(audioOnly) {\n if (this._attached) {\n this._tinode.noteKeyPress(this.name, audioOnly ? 'kpa' : 'kpv');\n } else {\n this._tinode.logger(\"INFO: Cannot send notification in inactive topic\");\n }\n }\n\n /**\n * Send a {note what='call'}. Wrapper for {@link Tinode#videoCall}.\n * @memberof Tinode#\n *\n * @param {string} evt - Call event.\n * @param {int} seq - ID of the call message the event pertains to.\n * @param {string} payload - Payload associated with this event (e.g. SDP string).\n *\n * @returns {Promise} Promise (for some call events) which will\n * be resolved/rejected on receiving server reply\n */\n videoCall(evt, seq, payload) {\n if (!this._attached && !['ringing', 'hang-up'].includes(evt)) {\n // Cannot {call} on an inactive topic\".\n return;\n }\n return this._tinode.videoCall(this.name, seq, evt, payload);\n }\n\n // Update cached read/recv/unread counts for the current user.\n _updateMyReadRecv(what, seq, ts) {\n let oldVal, doUpdate = false;\n\n seq = seq | 0;\n this.seq = this.seq | 0;\n this.read = this.read | 0;\n this.recv = this.recv | 0;\n switch (what) {\n case 'recv':\n oldVal = this.recv;\n this.recv = Math.max(this.recv, seq);\n doUpdate = (oldVal != this.recv);\n break;\n case 'read':\n oldVal = this.read;\n this.read = Math.max(this.read, seq);\n doUpdate = (oldVal != this.read);\n break;\n case 'msg':\n oldVal = this.seq;\n this.seq = Math.max(this.seq, seq);\n if (!this.touched || this.touched < ts) {\n this.touched = ts;\n }\n doUpdate = (oldVal != this.seq);\n break;\n }\n\n // Sanity checks.\n if (this.recv < this.read) {\n this.recv = this.read;\n doUpdate = true;\n }\n if (this.seq < this.recv) {\n this.seq = this.recv;\n if (!this.touched || this.touched < ts) {\n this.touched = ts;\n }\n doUpdate = true;\n }\n this.unread = this.seq - this.read;\n return doUpdate;\n }\n /**\n * Get user description from global cache. The user does not need to be a\n * subscriber of this topic.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - ID of the user to fetch.\n * @return {Object} user description or undefined.\n */\n userDesc(uid) {\n // TODO: handle asynchronous requests\n const user = this._cacheGetUser(uid);\n if (user) {\n return user; // Promise.resolve(user)\n }\n }\n /**\n * Get description of the p2p peer from subscription cache.\n * @memberof Tinode.Topic#\n *\n * @return {Object} peer's description or undefined.\n */\n p2pPeerDesc() {\n if (!this.isP2PType()) {\n return undefined;\n }\n return this._users[this.name];\n }\n /**\n * Iterate over cached subscribers. If callback is undefined, use this.onMetaSub.\n * @memberof Tinode.Topic#\n *\n * @param {function} callback - Callback which will receive subscribers one by one.\n * @param {Object=} context - Value of `this` inside the `callback`.\n */\n subscribers(callback, context) {\n const cb = (callback || this.onMetaSub);\n if (cb) {\n for (let idx in this._users) {\n cb.call(context, this._users[idx], idx, this._users);\n }\n }\n }\n /**\n * Get a copy of cached tags.\n * @memberof Tinode.Topic#\n *\n * @return {Array.} a copy of tags\n */\n tags() {\n // Return a copy.\n return this._tags.slice(0);\n }\n /**\n * Get auxiliary entry by key.\n * @memberof Tinode.Topic#\n * @param {string} key - auxiliary data key to retrieve.\n * @return {Object} value for the key or undefined.\n */\n aux(key) {\n return this._aux[key];\n }\n /**\n * Get alias value (unique tag with alias: prefix), if present.\n * The prefix is stripped off.\n * @memberof Tinode.Topic#\n * @return {string} alias or undefined.\n */\n alias() {\n const alias = this._tags && this._tags.find(t => t.startsWith(Const.TAG_ALIAS));\n if (!alias) {\n return undefined;\n }\n // Remove 'alias:' prefix.\n return alias.substring(Const.TAG_ALIAS.length);\n }\n\n /**\n * Get cached subscription for the given user ID.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - id of the user to query for\n * @return user description or undefined.\n */\n subscriber(uid) {\n return this._users[uid];\n }\n /**\n * Iterate over versions of a message: call callback for each version (excluding original).\n * If callback is undefined, does nothing.\n * @memberof Tinode.Topic#\n *\n * @param {number} origSeq - seq ID of the original message.\n * @param {Tinode.ForEachCallbackType} callback - Callback which will receive messages one by one. See {@link Tinode.CBuffer#forEach}\n * @param {Object} context - Value of `this` inside the `callback`.\n */\n messageVersions(origSeq, callback, context) {\n if (!callback) {\n // No callback? We are done then.\n return;\n }\n const versions = this._messageVersions[origSeq];\n if (!versions) {\n return;\n }\n versions.forEach(callback, undefined, undefined, context);\n }\n /**\n * Iterate over cached messages: call callback for each message in the range [sinceIdx, beforeIdx).\n * If callback is undefined, use this.onData.\n * @memberof Tinode.Topic#\n *\n * @param {Tinode.ForEachCallbackType} callback - Callback which will receive messages one by one. See {@link Tinode.CBuffer#forEach}\n * @param {number} sinceId - Optional seqId to start iterating from (inclusive).\n * @param {number} beforeId - Optional seqId to stop iterating before it is reached (exclusive).\n * @param {Object} context - Value of `this` inside the `callback`.\n */\n messages(callback, sinceId, beforeId, context) {\n const cb = (callback || this.onData);\n if (cb) {\n const startIdx = typeof sinceId == 'number' ? this._messages.find({\n seq: sinceId\n }, true) : undefined;\n const beforeIdx = typeof beforeId == 'number' ? this._messages.find({\n seq: beforeId\n }, true) : undefined;\n if (startIdx != -1 && beforeIdx != -1) {\n // Step 1. Filter out all replacement messages and\n // save displayable messages in a temporary buffer.\n let msgs = [];\n this._messages.forEach((msg, unused1, unused2, i) => {\n if (Topic.#isReplacementMsg(msg)) {\n // Skip replacements.\n return;\n }\n if (msg._deleted) {\n // Skip deleted ranges.\n return;\n }\n // In case the massage was edited, replace timestamp of the version with the original's timestamp.\n const latest = this.latestMsgVersion(msg.seq) || msg;\n if (!latest._origTs) {\n latest._origTs = latest.ts;\n latest._origSeq = latest.seq;\n latest.ts = msg.ts;\n latest.seq = msg.seq;\n }\n msgs.push({\n data: latest,\n idx: i\n });\n }, startIdx, beforeIdx, {});\n // Step 2. Loop over displayble messages invoking cb on each of them.\n msgs.forEach((val, i) => {\n cb.call(context, val.data,\n (i > 0 ? msgs[i - 1].data : undefined),\n (i < msgs.length - 1 ? msgs[i + 1].data : undefined), val.idx);\n });\n }\n }\n }\n /**\n * Get the message from cache by literal seq (does not resolve message edits).\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - message seqId to search for.\n * @returns {Object} the message with the given seq or undefined, if no such message is found.\n */\n findMessage(seq) {\n const idx = this._messages.find({\n seq: seq\n });\n if (idx >= 0) {\n return this._messages.getAt(idx);\n }\n return undefined;\n }\n /**\n * Get the most recent non-deleted message from cache.\n * @memberof Tinode.Topic#\n *\n * @returns {Object} the most recent cached message or undefined, if no messages are cached.\n */\n latestMessage() {\n return this._messages.getLast(msg => !msg._deleted);\n }\n /**\n * Get the latest version for message.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - original seq ID of the message.\n * @returns {Object} the latest version of the message or null if message not found.\n */\n latestMsgVersion(seq) {\n const versions = this._messageVersions[seq];\n return versions ? versions.getLast() : null;\n }\n /**\n * Get the maximum cached seq ID.\n * @memberof Tinode.Topic#\n *\n * @returns {number} the greatest seq ID in cache.\n */\n maxMsgSeq() {\n return this._maxSeq;\n }\n /**\n * Get the minimum cached seq ID.\n * @memberof Tinode.Topic#\n *\n * @returns {number} the smallest seq ID in cache or 0.\n */\n minMsgSeq() {\n return this._minSeq;\n }\n /**\n * Get the maximum deletion ID.\n * @memberof Tinode.Topic#\n *\n * @returns {number} the greatest deletion ID.\n */\n maxClearId() {\n return this._maxDel;\n }\n /**\n * Get the number of messages in the cache.\n * @memberof Tinode.Topic#\n *\n * @returns {number} count of cached messages.\n */\n messageCount() {\n return this._messages.length();\n }\n /**\n * Iterate over cached unsent messages. Wraps {@link Tinode.Topic#messages}.\n * @memberof Tinode.Topic#\n *\n * @param {function} callback - Callback which will receive messages one by one. See {@link Tinode.CBuffer#forEach}\n * @param {Object} context - Value of this inside the callback.\n */\n queuedMessages(callback, context) {\n if (!callback) {\n throw new Error(\"Callback must be provided\");\n }\n this.messages(callback, Const.LOCAL_SEQID, undefined, context);\n }\n /**\n * Get the number of topic subscribers who marked this message as either recv or read\n * Current user is excluded from the count.\n * @memberof Tinode.Topic#\n *\n * @param {string} what - what action to consider: received \"recv\" or read \"read\".\n * @param {number} seq - ID or the message read or received.\n *\n * @returns {number} the number of subscribers who marked the message with the given ID as read or received.\n */\n msgReceiptCount(what, seq) {\n let count = 0;\n if (seq > 0) {\n const me = this._tinode.getCurrentUserID();\n for (let idx in this._users) {\n const user = this._users[idx];\n if (user.user !== me && user[what] >= seq) {\n count++;\n }\n }\n }\n return count;\n }\n /**\n * Get the number of topic subscribers who marked this message (and all older messages) as read.\n * The current user is excluded from the count.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - message id to check.\n * @returns {number} number of subscribers who claim to have received the message.\n */\n msgReadCount(seq) {\n return this.msgReceiptCount('read', seq);\n }\n /**\n * Get the number of topic subscribers who marked this message (and all older messages) as received.\n * The current user is excluded from the count.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - Message id to check.\n * @returns {number} Number of subscribers who claim to have received the message.\n */\n msgRecvCount(seq) {\n return this.msgReceiptCount('recv', seq);\n }\n /**\n * Check if cached message IDs indicate that the server may have more messages.\n * @memberof Tinode.Topic#\n *\n * @param {number} min - smallest seq ID loaded range.\n * @param {number} max - greatest seq ID in loaded range.\n * @param {boolean} newer - if true, check for newer messages only.\n * @returns {Array.} - missing ranges in the selected direction.\n */\n msgHasMoreMessages(min, max, newer) {\n // Find gaps in cached messages.\n const gaps = [];\n if (min >= max) {\n return gaps;\n }\n let maxSeq = 0;\n let gap;\n this._messages.forEach((msg, prev) => {\n const p = prev || {\n seq: 0\n };\n const expected = p._deleted ? p.hi : p.seq + 1;\n if (msg.seq > expected) {\n gap = {\n low: expected,\n hi: msg.seq\n };\n } else {\n gap = null;\n }\n // If newer: collect all gaps from min to infinity.\n // If older: collect all gaps from max to zero.\n if (gap && (newer ? gap.hi >= min : gap.low < max)) {\n gaps.push(gap);\n }\n maxSeq = expected;\n });\n\n if (maxSeq < this.seq) {\n gap = {\n low: maxSeq + 1,\n hi: this.seq + 1\n };\n if (newer ? gap.hi >= min : gap.low < max) {\n gaps.push(gap);\n }\n }\n return gaps;\n }\n /**\n * Check if the given seq Id is id of the most recent message.\n * @memberof Tinode.Topic#\n *\n * @param {number} seqId id of the message to check\n */\n isNewMessage(seqId) {\n return this._maxSeq <= seqId;\n }\n /**\n * Remove one message from local cache.\n * @memberof Tinode.Topic#\n *\n * @param {number} seqId id of the message to remove from cache.\n * @returns {Message} removed message or undefined if such message was not found.\n */\n flushMessage(seqId) {\n const idx = this._messages.find({\n seq: seqId\n });\n delete this._messageVersions[seqId];\n if (idx >= 0) {\n this._tinode._db.remMessages(this.name, seqId);\n return this._messages.delAt(idx);\n }\n return undefined;\n }\n /**\n * Remove a range of messages from the local cache.\n * @memberof Tinode.Topic#\n *\n * @param {number} fromId seq ID of the first message to remove (inclusive).\n * @param {number} untilId seqID of the last message to remove (exclusive).\n *\n * @returns {Message[]} array of removed messages (could be empty).\n */\n flushMessageRange(fromId, untilId) {\n // Remove range from persistent cache.\n this._tinode._db.remMessages(this.name, fromId, untilId);\n\n // Remove all versions keyed by IDs in the range.\n for (let i = fromId; i < untilId; i++) {\n delete this._messageVersions[i];\n }\n\n // start, end: find insertion points (nearest == true).\n const since = this._messages.find({\n seq: fromId\n }, true);\n return since >= 0 ? this._messages.delRange(since, this._messages.find({\n seq: untilId\n }, true)) : [];\n }\n /**\n * Update message's seqId.\n * @memberof Tinode.Topic#\n *\n * @param {Object} pub message object.\n * @param {number} newSeqId new seq id for pub.\n */\n swapMessageId(pub, newSeqId) {\n const idx = this._messages.find(pub);\n const numMessages = this._messages.length();\n if (0 <= idx && idx < numMessages) {\n // Remove message with the old seq ID.\n this._messages.delAt(idx);\n this._tinode._db.remMessages(this.name, pub.seq);\n // Add message with the new seq ID.\n pub.seq = newSeqId;\n this._messages.put(pub);\n this._tinode._db.addMessage(pub);\n }\n }\n /**\n * Attempt to stop message from being sent.\n * @memberof Tinode.Topic#\n *\n * @param {number} seqId id of the message to stop sending and remove from cache.\n *\n * @returns {boolean} true if message was cancelled, false otherwise.\n */\n cancelSend(seqId) {\n const idx = this._messages.find({\n seq: seqId\n });\n if (idx >= 0) {\n const msg = this._messages.getAt(idx);\n const status = this.msgStatus(msg);\n if (status == Const.MESSAGE_STATUS_QUEUED ||\n status == Const.MESSAGE_STATUS_FAILED ||\n status == Const.MESSAGE_STATUS_FATAL) {\n this._tinode._db.remMessages(this.name, seqId);\n msg._cancelled = true;\n this._messages.delAt(idx);\n if (this.onData) {\n // Calling with no parameters to indicate the message was deleted.\n this.onData();\n }\n return true;\n }\n }\n return false;\n }\n /**\n * Get type of the topic: me, p2p, grp, fnd...\n * @memberof Tinode.Topic#\n *\n * @returns {string} One of 'me', 'p2p', 'grp', 'fnd', 'sys' or undefined.\n */\n getType() {\n return Topic.topicType(this.name);\n }\n /**\n * Get current user's access mode of the topic.\n * @memberof Tinode.Topic#\n *\n * @returns {Tinode.AccessMode} - user's access mode\n */\n getAccessMode() {\n return this.acs;\n }\n /**\n * Set current user's access mode of the topic.\n * @memberof Tinode.Topic#\n *\n * @param {AccessMode | Object} acs - access mode to set.\n */\n setAccessMode(acs) {\n return this.acs = new AccessMode(acs);\n }\n /**\n * Get topic's default access mode.\n * @memberof Tinode.Topic#\n *\n * @returns {Tinode.DefAcs} - access mode, such as {auth: `RWP`, anon: `N`}.\n */\n getDefaultAccess() {\n return this.defacs;\n }\n /**\n * Initialize new meta {@link Tinode.GetQuery} builder. The query is attched to the current topic.\n * It will not work correctly if used with a different topic.\n * @memberof Tinode.Topic#\n *\n * @returns {Tinode.MetaGetBuilder} query attached to the current topic.\n */\n startMetaQuery() {\n return new MetaGetBuilder(this);\n }\n /**\n * Check if topic is archived, i.e. private.arch == true.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is archived, false otherwise.\n */\n isArchived() {\n return this.private && !!this.private.arch;\n }\n /**\n * Check if topic is a 'me' topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a 'me' topic, false otherwise.\n */\n isMeType() {\n return Topic.isMeTopicName(this.name);\n }\n /**\n * Check if topic is a 'slf' topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a 'slf' topic, false otherwise.\n */\n isSelfType() {\n return Topic.isSelfTopicName(this.name);\n }\n /**\n * Check if topic is a channel.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a channel, false otherwise.\n */\n isChannelType() {\n return Topic.isChannelTopicName(this.name);\n }\n /**\n * Check if topic is a group topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a group, false otherwise.\n */\n isGroupType() {\n return Topic.isGroupTopicName(this.name);\n }\n /**\n * Check if topic is a p2p topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a p2p topic, false otherwise.\n */\n isP2PType() {\n return Topic.isP2PTopicName(this.name);\n }\n /**\n * Check if topic is a communication topic, i.e. a group or p2p topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a p2p or group topic, false otherwise.\n */\n isCommType() {\n return Topic.isCommTopicName(this.name);\n }\n /**\n * Get status (queued, sent, received etc) of a given message in the context\n * of this topic.\n * @memberof Tinode.Topic#\n *\n * @param {Message} msg - message to check for status.\n * @param {boolean} upd - update chached message status.\n *\n * @returns message status constant.\n */\n msgStatus(msg, upd) {\n let status = Const.MESSAGE_STATUS_NONE;\n if (this._tinode.isMe(msg.from)) {\n if (msg._sending) {\n status = Const.MESSAGE_STATUS_SENDING;\n } else if (msg._fatal || msg._cancelled) {\n status = Const.MESSAGE_STATUS_FATAL;\n } else if (msg._failed) {\n status = Const.MESSAGE_STATUS_FAILED;\n } else if (msg.seq >= Const.LOCAL_SEQID) {\n status = Const.MESSAGE_STATUS_QUEUED;\n } else if (this.msgReadCount(msg.seq) > 0) {\n status = Const.MESSAGE_STATUS_READ;\n } else if (this.msgRecvCount(msg.seq) > 0) {\n status = Const.MESSAGE_STATUS_RECEIVED;\n } else if (msg.seq > 0) {\n status = Const.MESSAGE_STATUS_SENT;\n }\n } else {\n status = Const.MESSAGE_STATUS_TO_ME;\n }\n\n if (upd && msg._status != status) {\n msg._status = status;\n this._tinode._db.updMessageStatus(this.name, msg.seq, status);\n }\n\n return status;\n }\n\n // If msg is a replacement for another message, save the msg in the message versions cache\n // as a newer version for the message it's supposed to replace.\n _maybeUpdateMessageVersionsCache(msg) {\n if (!Topic.#isReplacementMsg(msg)) {\n // Check if this message is the original in the chain of edits and if so\n // ensure all version have the same sender.\n if (this._messageVersions[msg.seq]) {\n // Remove versions with different 'from'.\n this._messageVersions[msg.seq].filter(version => version.from == msg.from);\n if (this._messageVersions[msg.seq].isEmpty()) {\n delete this._messageVersions[msg.seq];\n }\n }\n return;\n }\n\n const targetSeq = parseInt(msg.head.replace.split(':')[1]);\n if (targetSeq > msg.seq) {\n // Substitutes are supposed to have higher seq ids.\n return;\n }\n const targetMsg = this.findMessage(targetSeq);\n if (targetMsg && targetMsg.from != msg.from) {\n // Substitute cannot change the sender.\n return;\n }\n const versions = this._messageVersions[targetSeq] || new CBuffer((a, b) => {\n return a.seq - b.seq;\n }, true);\n versions.put(msg);\n this._messageVersions[targetSeq] = versions;\n }\n\n // Process data message\n _routeData(data) {\n if (data.content) {\n if (!this.touched || this.touched < data.ts) {\n this.touched = data.ts;\n this._tinode._db.updTopic(this);\n }\n }\n\n if (data.seq > this._maxSeq) {\n this._maxSeq = data.seq;\n this.msgStatus(data, true);\n // Ackn receiving the message.\n clearTimeout(this._recvNotificationTimer);\n this._recvNotificationTimer = setTimeout(_ => {\n this._recvNotificationTimer = null;\n this.noteRecv(this._maxSeq);\n }, Const.RECV_TIMEOUT);\n }\n\n if (data.seq < this._minSeq || this._minSeq == 0) {\n this._minSeq = data.seq;\n }\n\n const outgoing = ((!this.isChannelType() && !data.from) || this._tinode.isMe(data.from));\n\n if (data.head && data.head.webrtc && data.head.mime == Drafty.getContentType() && data.content) {\n // Rewrite VC body with info from the headers.\n const upd = {\n state: data.head.webrtc,\n duration: data.head['webrtc-duration'],\n incoming: !outgoing,\n };\n if (data.head.vc) {\n upd.vc = true;\n }\n data.content = Drafty.updateVideoCall(data.content, upd);\n }\n\n if (!data._noForwarding) {\n this._messages.put(data);\n this._tinode._db.addMessage(data);\n this._maybeUpdateMessageVersionsCache(data);\n }\n\n if (this.onData) {\n this.onData(data);\n }\n\n // Update locally cached contact with the new message count.\n const what = outgoing ? 'read' : 'msg';\n this._updateMyReadRecv(what, data.seq, data.ts);\n\n if (!outgoing && data.from) {\n // Mark messages as read by the sender.\n this._routeInfo({\n what: 'read',\n from: data.from,\n seq: data.seq,\n _noForwarding: true\n });\n }\n\n // Notify 'me' listeners of the change.\n this._tinode.getMeTopic()._refreshContact(what, this);\n }\n\n // Process metadata message\n _routeMeta(meta) {\n if (meta.desc) {\n this._processMetaDesc(meta.desc);\n }\n if (meta.sub && meta.sub.length > 0) {\n this._processMetaSubs(meta.sub);\n }\n if (meta.del) {\n this._processDelMessages(meta.del.clear, meta.del.delseq);\n }\n if (meta.tags) {\n this._processMetaTags(meta.tags);\n }\n if (meta.cred) {\n this._processMetaCreds(meta.cred);\n }\n if (meta.aux) {\n this._processMetaAux(meta.aux);\n }\n if (this.onMeta) {\n this.onMeta(meta);\n }\n }\n // Process presence change message\n _routePres(pres) {\n let user, uid;\n switch (pres.what) {\n case 'del':\n // Delete cached messages.\n this._processDelMessages(pres.clear, pres.delseq);\n break;\n case 'on':\n case 'off':\n // Update online status of a subscription.\n user = this._users[pres.src];\n if (user) {\n user.online = pres.what == 'on';\n } else {\n this._tinode.logger(\"WARNING: Presence update for an unknown user\", this.name, pres.src);\n }\n break;\n case 'term':\n // Attachment to topic is terminated probably due to cluster rehashing.\n this._resetSub();\n break;\n case 'upd':\n // A topic subscriber has updated his description.\n // Issue {get sub} only if the current user has no p2p topics with the updated user (p2p name is not in cache).\n // Otherwise 'me' will issue a {get desc} request.\n if (pres.src && !this._tinode.isTopicCached(pres.src)) {\n this.getMeta(this.startMetaQuery().withOneSub(undefined, pres.src).build());\n }\n break;\n case 'aux':\n // Auxiliary data updated.\n this.getMeta(this.startMetaQuery().withAux().build());\n break;\n case 'acs':\n uid = pres.src || this._tinode.getCurrentUserID();\n user = this._users[uid];\n if (!user) {\n // Update for an unknown user: notification of a new subscription.\n const acs = new AccessMode().updateAll(pres.dacs);\n if (acs && acs.mode != AccessMode._NONE) {\n user = this._cacheGetUser(uid);\n if (!user) {\n user = {\n user: uid,\n acs: acs\n };\n this.getMeta(this.startMetaQuery().withOneSub(undefined, uid).build());\n } else {\n user.acs = acs;\n }\n user.updated = new Date();\n this._processMetaSubs([user]);\n }\n } else {\n // Known user\n user.acs.updateAll(pres.dacs);\n // Update user's access mode.\n this._processMetaSubs([{\n user: uid,\n updated: new Date(),\n acs: user.acs\n }]);\n }\n break;\n default:\n this._tinode.logger(\"INFO: Ignored presence update\", pres.what);\n }\n\n if (this.onPres) {\n this.onPres(pres);\n }\n }\n // Process {info} message\n _routeInfo(info) {\n switch (info.what) {\n case 'recv':\n case 'read':\n const user = this._users[info.from];\n if (user) {\n user[info.what] = info.seq;\n if (user.recv < user.read) {\n user.recv = user.read;\n }\n }\n const msg = this.latestMessage();\n if (msg) {\n this.msgStatus(msg, true);\n }\n\n // If this is an update from the current user, update the cache with the new count.\n if (this._tinode.isMe(info.from) && !info._noForwarding) {\n this._updateMyReadRecv(info.what, info.seq);\n }\n\n // Notify 'me' listener of the status change.\n this._tinode.getMeTopic()._refreshContact(info.what, this);\n break;\n case 'kp':\n case 'kpa':\n case 'kpv':\n // Typing or audio/video recording notification. Do nothing.\n break;\n case 'call':\n // Do nothing here.\n break;\n default:\n this._tinode.logger(\"INFO: Ignored info update\", info.what);\n }\n\n if (this.onInfo) {\n this.onInfo(info);\n }\n }\n // Called by Tinode when meta.desc packet is received.\n // Called by 'me' topic on contact update (desc._noForwarding is true).\n _processMetaDesc(desc) {\n if (this.isP2PType()) {\n // Synthetic desc may include defacs for p2p topics which is useless.\n // Remove it.\n delete desc.defacs;\n\n // Update to p2p desc is the same as user update. Update cached user.\n this._tinode._db.updUser(this.name, desc.public);\n }\n\n // Copy parameters from desc object to this topic.\n mergeObj(this, desc);\n // Update persistent cache.\n this._tinode._db.updTopic(this);\n\n // Notify 'me' listener, if available:\n if (this.name !== Const.TOPIC_ME && !desc._noForwarding) {\n const me = this._tinode.getMeTopic();\n if (me.onMetaSub) {\n me.onMetaSub(this);\n }\n if (me.onSubsUpdated) {\n me.onSubsUpdated([this.name], 1);\n }\n }\n\n if (this.onMetaDesc) {\n this.onMetaDesc(this);\n }\n }\n // Called by Tinode when meta.sub is recived or in response to received\n // {ctrl} after setMeta-sub.\n _processMetaSubs(subs) {\n for (let idx in subs) {\n const sub = subs[idx];\n\n // Fill defaults.\n sub.online = !!sub.online;\n // Update timestamp of the most recent subscription update.\n this._lastSubsUpdate = new Date(Math.max(this._lastSubsUpdate, sub.updated));\n\n let user = null;\n if (!sub.deleted) {\n // If this is a change to user's own permissions, update them in topic too.\n // Desc will update 'me' topic.\n if (this._tinode.isMe(sub.user) && sub.acs) {\n this._processMetaDesc({\n updated: sub.updated,\n touched: sub.touched,\n acs: sub.acs\n });\n }\n user = this._updateCachedUser(sub.user, sub);\n } else {\n // Subscription is deleted, remove it from topic (but leave in Users cache)\n delete this._users[sub.user];\n user = sub;\n }\n\n if (this.onMetaSub) {\n this.onMetaSub(user);\n }\n }\n\n if (this.onSubsUpdated) {\n this.onSubsUpdated(Object.keys(this._users));\n }\n }\n // Called by Tinode when meta.tags is recived.\n _processMetaTags(tags) {\n if (tags == Const.DEL_CHAR || (tags.length == 1 && tags[0] == Const.DEL_CHAR)) {\n tags = [];\n }\n this._tags = tags;\n this._tinode._db.updTopic(this);\n if (this.onTagsUpdated) {\n this.onTagsUpdated(tags);\n }\n }\n // Do nothing for topics other than 'me'\n _processMetaCreds(creds) {}\n\n // Called by Tinode when meta.aux is recived.\n _processMetaAux(aux) {\n aux = (!aux || aux == Const.DEL_CHAR) ? {} : aux;\n this._aux = mergeObj(this._aux, aux);\n this._tinode._db.updTopic(this);\n if (this.onAuxUpdated) {\n this.onAuxUpdated(this._aux);\n }\n }\n\n // Delete cached messages and update cached transaction IDs\n _processDelMessages(clear, delseq) {\n this._maxDel = Math.max(clear, this._maxDel);\n this.clear = Math.max(clear, this.clear);\n let count = 0;\n if (Array.isArray(delseq)) {\n delseq.forEach(rec => {\n if (!rec.hi) {\n count++;\n this.flushMessage(rec.low);\n } else {\n count += rec.hi - rec.low;\n this.flushMessageRange(rec.low, rec.hi);\n }\n this._messages.put({\n seq: rec.low,\n low: rec.low,\n hi: rec.hi,\n _deleted: true\n });\n });\n\n this._tinode._db.addDelLog(this.name, clear, delseq);\n }\n\n if (count > 0) {\n if (this.onData) {\n this.onData();\n }\n }\n }\n // Topic is informed that the entire response to {get what=data} has been received.\n _allMessagesReceived(count) {\n\n if (this.onAllMessagesReceived) {\n this.onAllMessagesReceived(count);\n }\n }\n // Reset subscribed state\n _resetSub() {\n this._attached = false;\n }\n // This topic is either deleted or unsubscribed from.\n _gone() {\n this._messages.reset();\n this._tinode._db.remMessages(this.name);\n this._users = {};\n this.acs = new AccessMode(null);\n this.private = null;\n this.public = null;\n this.trusted = null;\n this._maxSeq = 0;\n this._minSeq = 0;\n this._attached = false;\n\n const me = this._tinode.getMeTopic();\n if (me) {\n me._routePres({\n _noForwarding: true,\n what: 'gone',\n topic: Const.TOPIC_ME,\n src: this.name\n });\n }\n if (this.onDeleteTopic) {\n this.onDeleteTopic();\n }\n }\n // Update global user cache and local subscribers cache.\n // Don't call this method for non-subscribers.\n _updateCachedUser(uid, obj) {\n // Fetch user object from the global cache.\n // This is a clone of the stored object\n let cached = this._cacheGetUser(uid);\n cached = mergeObj(cached || {}, obj);\n // Save to global cache\n this._cachePutUser(uid, cached);\n // Save to the list of topic subsribers.\n return mergeToCache(this._users, uid, cached);\n }\n // Get local seqId for a queued message.\n _getQueuedSeqId() {\n return this._queuedSeqId++;\n }\n\n // Load most recent messages from persistent cache.\n _loadMessages(db, query) {\n query = query || {};\n query.limit = query.limit || Const.DEFAULT_MESSAGES_PAGE;\n\n // Count of message loaded from DB.\n let count = 0;\n return db.readMessages(this.name, query)\n .then(msgs => {\n msgs.forEach(data => {\n if (data.seq > this._maxSeq) {\n this._maxSeq = data.seq;\n }\n if (data.seq < this._minSeq || this._minSeq == 0) {\n this._minSeq = data.seq;\n }\n this._messages.put(data);\n this._maybeUpdateMessageVersionsCache(data);\n });\n count = msgs.length;\n })\n .then(_ => db.readDelLog(this.name, query))\n .then(dellog => {\n return dellog.forEach(rec => {\n this._messages.put({\n seq: rec.low,\n low: rec.low,\n hi: rec.hi,\n _deleted: true\n });\n });\n })\n .then(_ => {\n // DEBUG\n return count;\n });\n }\n\n // Push or {pres}: message received.\n _updateReceived(seq, act) {\n this.touched = new Date();\n this.seq = seq | 0;\n // Check if message is sent by the current user. If so it's been read already.\n if (!act || this._tinode.isMe(act)) {\n this.read = this.read ? Math.max(this.read, this.seq) : this.seq;\n this.recv = this.recv ? Math.max(this.read, this.recv) : this.read;\n }\n this.unread = this.seq - (this.read | 0);\n this._tinode._db.updTopic(this);\n }\n}\n","/**\n * @file Utilities used in multiple places.\n *\n * @copyright 2015-2022 Tinode LLC.\n */\n'use strict';\n\nimport AccessMode from './access-mode.js';\nimport {\n DEL_CHAR,\n LOCAL_SEQID\n} from './config.js';\n\n// Attempt to convert date and AccessMode strings to objects.\nexport function jsonParseHelper(key, val) {\n // Try to convert string timestamps with optional milliseconds to Date,\n // e.g. 2015-09-02T01:45:43[.123]Z\n if (typeof val == 'string' && val.length >= 20 && val.length <= 24 && ['ts', 'touched', 'updated', 'created', 'when', 'deleted', 'expires'].includes(key)) {\n const date = new Date(val);\n if (!isNaN(date)) {\n return date;\n }\n } else if (key === 'acs' && typeof val === 'object') {\n return new AccessMode(val);\n }\n return val;\n}\n\n// Checks if URL is a relative url, i.e. has no 'scheme://', including the case of missing scheme '//'.\n// The scheme is expected to be RFC-compliant, e.g. [a-z][a-z0-9+.-]*\n// example.html - ok\n// https:example.com - not ok.\n// http:/example.com - not ok.\n// ' ↲ https://example.com' - not ok. (↲ means carriage return)\nexport function isUrlRelative(url) {\n return url && !/^\\s*([a-z][a-z0-9+.-]*:|\\/\\/)/im.test(url);\n}\n\nfunction isValidDate(d) {\n return (d instanceof Date) && !isNaN(d) && (d.getTime() != 0);\n}\n\n// RFC3339 formater of Date\nexport function rfc3339DateString(d) {\n if (!isValidDate(d)) {\n return undefined;\n }\n\n const pad = function(val, sp) {\n sp = sp || 2;\n return '0'.repeat(sp - ('' + val).length) + val;\n };\n\n const millis = d.getUTCMilliseconds();\n return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate()) +\n 'T' + pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) +\n (millis ? '.' + pad(millis, 3) : '') + 'Z';\n}\n\n// Recursively merge src's own properties to dst.\n// Ignore properties where ignore[property] is true.\n// Array and Date objects are shallow-copied.\nexport function mergeObj(dst, src, ignore) {\n if (typeof src != 'object') {\n if (src === undefined) {\n return dst;\n }\n if (src === DEL_CHAR) {\n return undefined;\n }\n return src;\n }\n // JS is crazy: typeof null is 'object'.\n if (src === null) {\n return src;\n }\n\n // Handle Date\n if (src instanceof Date && !isNaN(src)) {\n return (!dst || !(dst instanceof Date) || isNaN(dst) || dst < src) ? src : dst;\n }\n\n // Access mode\n if (src instanceof AccessMode) {\n return new AccessMode(src);\n }\n\n // Handle Array\n if (src instanceof Array) {\n return src;\n }\n\n if (!dst || dst === DEL_CHAR) {\n dst = src.constructor();\n }\n\n for (let prop in src) {\n if (src.hasOwnProperty(prop) && (!ignore || !ignore[prop]) && (prop != '_noForwarding')) {\n try {\n dst[prop] = mergeObj(dst[prop], src[prop]);\n } catch (err) {\n // FIXME: probably need to log something here.\n }\n }\n }\n return dst;\n}\n\n// Update object stored in a cache. Returns updated value.\nexport function mergeToCache(cache, key, newval, ignore) {\n cache[key] = mergeObj(cache[key], newval, ignore);\n return cache[key];\n}\n\n// Strips all values from an object of they evaluate to false or if their name starts with '_'.\n// Used on all outgoing object before serialization to string.\nexport function simplify(obj) {\n Object.keys(obj).forEach((key) => {\n if (key[0] == '_') {\n // Strip fields like \"obj._key\".\n delete obj[key];\n } else if (!obj[key]) {\n // Strip fields which evaluate to false.\n delete obj[key];\n } else if (Array.isArray(obj[key]) && obj[key].length == 0) {\n // Strip empty arrays.\n delete obj[key];\n } else if (!obj[key]) {\n // Strip fields which evaluate to false.\n delete obj[key];\n } else if (obj[key] instanceof Date) {\n // Strip invalid or zero date.\n if (!isValidDate(obj[key])) {\n delete obj[key];\n }\n } else if (typeof obj[key] == 'object') {\n simplify(obj[key]);\n // Strip empty objects.\n if (Object.getOwnPropertyNames(obj[key]).length == 0) {\n delete obj[key];\n }\n }\n });\n return obj;\n};\n\n\n// Trim whitespace, convert to lowercase, strip empty, short, and duplicate elements elements.\n// If the result is an empty array, add a single element \"\\u2421\" (Unicode Del character).\nexport function normalizeArray(arr) {\n let out = [];\n if (Array.isArray(arr)) {\n // Trim, throw away very short and empty tags.\n for (let i = 0, l = arr.length; i < l; i++) {\n let t = arr[i];\n if (t) {\n t = t.trim().toLowerCase();\n if (t.length > 1) {\n out.push(t);\n }\n }\n }\n out = out.sort().filter((item, pos, ary) => {\n return !pos || item != ary[pos - 1];\n });\n }\n if (out.length == 0) {\n // Add single tag with a Unicode Del character, otherwise an ampty array\n // is ambiguos. The Del tag will be stripped by the server.\n out.push(DEL_CHAR);\n }\n return out;\n}\n\n// Convert input to valid ranges of IDs.\nexport function normalizeRanges(ranges, maxSeq) {\n if (!Array.isArray(ranges)) {\n return [];\n }\n\n // Sort ranges in accending order by low, then descending by hi.\n ranges.sort((r1, r2) => {\n if (r1.low < r2.low) {\n return -1;\n }\n if (r1.low == r2.low) {\n return (r2.hi | 0) - r1.hi;\n }\n return 1;\n });\n\n // Remove pending messages from ranges possibly clipping some ranges.\n ranges = ranges.reduce((out, r) => {\n if (r.low < LOCAL_SEQID && r.low > 0) {\n if (!r.hi || r.hi < LOCAL_SEQID) {\n out.push(r);\n } else {\n // Clip hi to max allowed value.\n out.push({\n low: r.low,\n hi: maxSeq + 1\n });\n }\n }\n return out;\n }, []);\n\n // Merge overlapping ranges.\n ranges = ranges.reduce((out, r) => {\n if (out.length == 0) {\n out.push(r);\n } else {\n let prev = out[out.length - 1];\n if (r.low <= prev.hi) {\n prev.hi = Math.max(prev.hi, r.hi);\n } else {\n out.push(r);\n }\n }\n return out;\n }, []);\n\n return ranges;\n}\n\n// Convert array of IDs to array of ranges.\nexport function listToRanges(list) {\n // Sort the list in ascending order\n list.sort((a, b) => a - b);\n // Convert the array of IDs to ranges.\n return list.reduce((out, id) => {\n if (out.length == 0) {\n // First element.\n out.push({\n low: id\n });\n } else {\n let prev = out[out.length - 1];\n if ((!prev.hi && (id != prev.low + 1)) || (id > prev.hi)) {\n // New range.\n out.push({\n low: id\n });\n } else {\n // Expand existing range.\n prev.hi = prev.hi ? Math.max(prev.hi, id + 1) : id + 1;\n }\n }\n return out;\n }, []);\n}\n\n// Cuts 'clip' range out of the 'src' range.\n// Returns an array with 0, 1 or 2 elements.\nexport function clipOutRange(src, clip) {\n if (clip.hi <= src.low || clip.low >= src.hi) {\n // Clip is completely outside of src, no intersection.\n return [src];\n }\n\n\n if (clip.low <= src.low) {\n if (clip.hi >= src.hi) {\n // The source range is completely inside the clipping range.\n return [];\n }\n // Partial clipping at the top.\n return [{\n low: clip.hi,\n hi: src.hi\n }];\n }\n\n // Range on the lower end.\n const result = [{\n low: src.low,\n hi: clip.low\n }];\n if (clip.hi < src.hi) {\n // Maybe a range on the higher end, if clip is completely inside the source.\n result.push({\n low: clip.hi,\n hi: src.hi\n });\n }\n\n return result;\n}\n\n// Cuts 'src' range to be completely within 'clip' range.\n// Returns clipped range or null if 'src' is outside of 'clip'.\nexport function clipInRange(src, clip) {\n if (clip.hi <= src.low || clip.low >= src.hi) {\n // The src is completely outside of the clip, no intersection.\n return null;\n }\n\n if (src.low >= clip.low && src.hi <= clip.hi) {\n // Src is completely within the clip, return the entire src.\n return src;\n }\n\n // Partial overlap.\n return {\n low: Math.max(src.low, clip.low),\n hi: Math.min(src.hi, clip.hi)\n };\n\n return result;\n}\n","export const PACKAGE_VERSION = \"0.24.2\";\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/**\n * @module tinode-sdk\n *\n * @copyright 2015-2025 Tinode LLC.\n * @summary Javascript bindings for Tinode.\n * @license Apache 2.0\n * @version 0.24\n *\n * See https://github.com/tinode/webapp for real-life usage.\n *\n * @example\n * \n * \n * \n *\n * \n * ...\n * \n * \n */\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\nimport AccessMode from './access-mode.js';\nimport * as Const from './config.js';\nimport CommError from './comm-error.js';\nimport Connection from './connection.js';\nimport DBCache from './db.js';\nimport Drafty from './drafty.js';\nimport LargeFileHelper from './large-file.js';\nimport MetaGetBuilder from './meta-builder.js';\nimport Topic from './topic.js';\nimport TopicFnd from './fnd-topic.js';\nimport TopicMe from './me-topic.js';\n\nimport {\n isUrlRelative,\n jsonParseHelper,\n mergeObj,\n rfc3339DateString,\n simplify\n} from './utils.js';\n\n// Re-export AccessMode\nexport {\n AccessMode\n};\n\nlet WebSocketProvider;\nif (typeof WebSocket != 'undefined') {\n WebSocketProvider = WebSocket;\n}\n\nlet XHRProvider;\nif (typeof XMLHttpRequest != 'undefined') {\n XHRProvider = XMLHttpRequest;\n}\n\nlet IndexedDBProvider;\nif (typeof indexedDB != 'undefined') {\n IndexedDBProvider = indexedDB;\n}\n\n// Re-export Drafty.\nexport {\n Drafty\n}\n\ninitForNonBrowserApp();\n\n// Utility functions\n\n// Polyfill for non-browser context, e.g. NodeJs.\nfunction initForNonBrowserApp() {\n // Tinode requirement in native mode because react native doesn't provide Base64 method\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n\n if (typeof btoa == 'undefined') {\n global.btoa = function(input = '') {\n let str = input;\n let output = '';\n\n for (let block = 0, charCode, i = 0, map = chars; str.charAt(i | 0) || (map = '=', i % 1); output += map.charAt(63 & block >> 8 - i % 1 * 8)) {\n\n charCode = str.charCodeAt(i += 3 / 4);\n\n if (charCode > 0xFF) {\n throw new Error(\"'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.\");\n }\n block = block << 8 | charCode;\n }\n\n return output;\n };\n }\n\n if (typeof atob == 'undefined') {\n global.atob = function(input = '') {\n let str = input.replace(/=+$/, '');\n let output = '';\n\n if (str.length % 4 == 1) {\n throw new Error(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n for (let bc = 0, bs = 0, buffer, i = 0; buffer = str.charAt(i++);\n\n ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,\n bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0\n ) {\n buffer = chars.indexOf(buffer);\n }\n\n return output;\n };\n }\n\n if (typeof window == 'undefined') {\n global.window = {\n WebSocket: WebSocketProvider,\n XMLHttpRequest: XHRProvider,\n indexedDB: IndexedDBProvider,\n URL: {\n createObjectURL: function() {\n throw new Error(\"Unable to use URL.createObjectURL in a non-browser application\");\n }\n }\n }\n }\n\n Connection.setNetworkProviders(WebSocketProvider, XHRProvider);\n LargeFileHelper.setNetworkProvider(XHRProvider);\n DBCache.setDatabaseProvider(IndexedDBProvider);\n}\n\n// Detect find most useful network transport.\nfunction detectTransport() {\n if (typeof window == 'object') {\n if (window['WebSocket']) {\n return 'ws';\n } else if (window['XMLHttpRequest']) {\n // The browser or node has no websockets, using long polling.\n return 'lp';\n }\n }\n return null;\n}\n\n// btoa replacement. Stock btoa fails on on non-Latin1 strings.\nfunction b64EncodeUnicode(str) {\n // The encodeURIComponent percent-encodes UTF-8 string,\n // then the percent encoding is converted into raw bytes which\n // can be fed into btoa.\n return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,\n function toSolidBytes(match, p1) {\n return String.fromCharCode('0x' + p1);\n }));\n}\n\n// JSON stringify helper - pre-processor for JSON.stringify\nfunction jsonBuildHelper(key, val) {\n if (val instanceof Date) {\n // Convert javascript Date objects to rfc3339 strings\n val = rfc3339DateString(val);\n } else if (val instanceof AccessMode) {\n val = val.jsonHelper();\n } else if (val === undefined || val === null || val === false ||\n (Array.isArray(val) && val.length == 0) ||\n ((typeof val == 'object') && (Object.keys(val).length == 0))) {\n // strip out empty elements while serializing objects to JSON\n return undefined;\n }\n\n return val;\n};\n\n// Trims very long strings (encoded images) to make logged packets more readable.\nfunction jsonLoggerHelper(key, val) {\n if (typeof val == 'string' && val.length > 128) {\n return '<' + val.length + ', bytes: ' + val.substring(0, 12) + '...' + val.substring(val.length - 12) + '>';\n }\n return jsonBuildHelper(key, val);\n};\n\n// Parse browser user agent to extract browser name and version.\nfunction getBrowserInfo(ua, product) {\n ua = ua || '';\n let reactnative = '';\n // Check if this is a ReactNative app.\n if (/reactnative/i.test(product)) {\n reactnative = 'ReactNative; ';\n }\n let result;\n // Remove useless string.\n ua = ua.replace(' (KHTML, like Gecko)', '');\n // Test for WebKit-based browser.\n let m = ua.match(/(AppleWebKit\\/[.\\d]+)/i);\n if (m) {\n // List of common strings, from more useful to less useful.\n // All unknown strings get the highest (-1) priority.\n const priority = ['edg', 'chrome', 'safari', 'mobile', 'version'];\n let tmp = ua.substr(m.index + m[0].length).split(' ');\n let tokens = [];\n let version; // 1.0 in Version/1.0 or undefined;\n // Split string like 'Name/0.0.0' into ['Name', '0.0.0', 3] where the last element is the priority.\n for (let i = 0; i < tmp.length; i++) {\n let m2 = /([\\w.]+)[\\/]([\\.\\d]+)/.exec(tmp[i]);\n if (m2) {\n // Unknown values are highest priority (-1).\n tokens.push([m2[1], m2[2], priority.findIndex((e) => {\n return m2[1].toLowerCase().startsWith(e);\n })]);\n if (m2[1] == 'Version') {\n version = m2[2];\n }\n }\n }\n // Sort by priority: more interesting is earlier than less interesting.\n tokens.sort((a, b) => {\n return a[2] - b[2];\n });\n if (tokens.length > 0) {\n // Return the least common browser string and version.\n if (tokens[0][0].toLowerCase().startsWith('edg')) {\n tokens[0][0] = 'Edge';\n } else if (tokens[0][0] == 'OPR') {\n tokens[0][0] = 'Opera';\n } else if (tokens[0][0] == 'Safari' && version) {\n tokens[0][1] = version;\n }\n result = tokens[0][0] + '/' + tokens[0][1];\n } else {\n // Failed to ID the browser. Return the webkit version.\n result = m[1];\n }\n } else if (/firefox/i.test(ua)) {\n m = /Firefox\\/([.\\d]+)/g.exec(ua);\n if (m) {\n result = 'Firefox/' + m[1];\n } else {\n result = 'Firefox/?';\n }\n } else {\n // Neither AppleWebKit nor Firefox. Try the last resort.\n m = /([\\w.]+)\\/([.\\d]+)/.exec(ua);\n if (m) {\n result = m[1] + '/' + m[2];\n } else {\n m = ua.split(' ');\n result = m[0];\n }\n }\n\n // Shorten the version to one dot 'a.bb.ccc.d -> a.bb' at most.\n m = result.split('/');\n if (m.length > 1) {\n const v = m[1].split('.');\n const minor = v[1] ? '.' + v[1].substr(0, 2) : '';\n result = `${m[0]}/${v[0]}${minor}`;\n }\n return reactnative + result;\n}\n\n/**\n * The main class for interacting with Tinode server.\n */\nexport class Tinode {\n _host;\n _secure;\n\n _appName;\n\n // API Key.\n _apiKey;\n\n // Name and version of the browser.\n _browser = '';\n _platform;\n // Hardware\n _hwos = 'undefined';\n _humanLanguage = 'xx';\n\n // Logging to console enabled\n _loggingEnabled = false;\n // When logging, trip long strings (base64-encoded images) for readability\n _trimLongStrings = false;\n // UID of the currently authenticated user.\n _myUID = null;\n // Status of connection: authenticated or not.\n _authenticated = false;\n // Login used in the last successful basic authentication\n _login = null;\n // Token which can be used for login instead of login/password.\n _authToken = null;\n // Counter of received packets\n _inPacketCount = 0;\n // Counter for generating unique message IDs\n _messageId = Math.floor((Math.random() * 0xFFFF) + 0xFFFF);\n // Information about the server, if connected\n _serverInfo = null;\n // Push notification token. Called deviceToken for consistency with the Android SDK.\n _deviceToken = null;\n\n // Cache of pending promises by message id.\n _pendingPromises = {};\n // The Timeout object returned by the reject expired promises setInterval.\n _expirePromises = null;\n\n // Websocket or long polling connection.\n _connection = null;\n\n // Use indexDB for caching topics and messages.\n _persist = false;\n // IndexedDB wrapper object.\n _db = null;\n\n // Tinode's cache of objects\n _cache = {};\n\n /**\n * Create Tinode object.\n *\n * @param {Object} config - configuration parameters.\n * @param {string} config.appName - Name of the calling application to be reported in the User Agent.\n * @param {string} config.host - Host name and optional port number to connect to.\n * @param {string} config.apiKey - API key generated by keygen.\n * @param {string} config.transport - See {@link Tinode.Connection#transport}.\n * @param {boolean} config.secure - Use Secure WebSocket if true.\n * @param {string} config.platform - Optional platform identifier, one of \"ios\", \"web\", \"android\".\n * @param {boolen} config.persist - Use IndexedDB persistent storage.\n * @param {function} onComplete - callback to call when initialization is completed.\n */\n constructor(config, onComplete) {\n this._host = config.host;\n this._secure = config.secure;\n\n // Client-provided application name, format /\n this._appName = config.appName || \"Undefined\";\n\n // API Key.\n this._apiKey = config.apiKey;\n\n // Name and version of the browser.\n this._platform = config.platform || 'web';\n // Underlying OS.\n if (typeof navigator != 'undefined') {\n this._browser = getBrowserInfo(navigator.userAgent, navigator.product);\n this._hwos = navigator.platform;\n // This is the default language. It could be changed by client.\n this._humanLanguage = navigator.language || 'en-US';\n }\n\n Connection.logger = this.logger;\n Drafty.logger = this.logger;\n\n // WebSocket or long polling network connection.\n if (config.transport != 'lp' && config.transport != 'ws') {\n config.transport = detectTransport();\n }\n this._connection = new Connection(config, Const.PROTOCOL_VERSION, /* autoreconnect */ true);\n this._connection.onMessage = (data) => {\n // Call the main message dispatcher.\n this.#dispatchMessage(data);\n }\n\n // Ready to start sending.\n this._connection.onOpen = _ => this.#connectionOpen();\n this._connection.onDisconnect = (err, code) => this.#disconnected(err, code);\n\n // Wrapper for the reconnect iterator callback.\n this._connection.onAutoreconnectIteration = (timeout, promise) => {\n if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(timeout, promise);\n }\n }\n\n this._persist = config.persist;\n // Initialize object regardless. It simplifies the code.\n this._db = new DBCache(this.logger, this.logger);\n\n if (this._persist) {\n // Create the persistent cache.\n // Store promises to be resolved when messages load into memory.\n const prom = [];\n this._db.initDatabase().then(_ => {\n // First load topics into memory.\n return this._db.mapTopics(data => {\n let topic = this.#cacheGet('topic', data.name);\n if (topic) {\n return;\n }\n if (data.name == Const.TOPIC_ME) {\n topic = new TopicMe();\n } else if (data.name == Const.TOPIC_FND) {\n topic = new TopicFnd();\n } else {\n topic = new Topic(data.name);\n }\n this._db.deserializeTopic(topic, data);\n this.#attachCacheToTopic(topic);\n topic._cachePutSelf();\n this._db.maxDelId(topic.name).then(clear => {\n topic._maxDel = Math.max(topic._maxDel, clear || 0);\n });\n // Topic loaded from DB is not new.\n delete topic._new;\n // Request to load messages and save the promise.\n prom.push(topic._loadMessages(this._db));\n });\n }).then(_ => {\n // Then load users.\n return this._db.mapUsers((data) => {\n this.#cachePut('user', data.uid, mergeObj({}, data.public));\n });\n }).then(_ => {\n // Now wait for all messages to finish loading.\n return Promise.all(prom);\n }).then(_ => {\n if (onComplete) {\n onComplete();\n }\n this.logger(\"Persistent cache initialized.\");\n }).catch(err => {\n if (onComplete) {\n onComplete(err);\n }\n this.logger(\"Failed to initialize persistent cache:\", err);\n });\n } else {\n this._db.deleteDatabase().then(_ => {\n if (onComplete) {\n onComplete();\n }\n });\n }\n }\n\n // Private methods.\n\n // Console logger. Babel somehow fails to parse '...rest' parameter.\n logger(str, ...args) {\n if (this._loggingEnabled) {\n const d = new Date();\n const dateString = ('0' + d.getUTCHours()).slice(-2) + ':' +\n ('0' + d.getUTCMinutes()).slice(-2) + ':' +\n ('0' + d.getUTCSeconds()).slice(-2) + '.' +\n ('00' + d.getUTCMilliseconds()).slice(-3);\n\n console.log('[' + dateString + ']', str, args.join(' '));\n }\n }\n\n // Generator of default promises for sent packets.\n #makePromise(id) {\n let promise = null;\n if (id) {\n promise = new Promise((resolve, reject) => {\n // Stored callbacks will be called when the response packet with this Id arrives\n this._pendingPromises[id] = {\n 'resolve': resolve,\n 'reject': reject,\n 'ts': new Date()\n };\n });\n }\n return promise;\n };\n\n // Resolve or reject a pending promise.\n // Unresolved promises are stored in _pendingPromises.\n #execPromise(id, code, onOK, errorText) {\n const callbacks = this._pendingPromises[id];\n if (callbacks) {\n delete this._pendingPromises[id];\n if (code >= 200 && code < 400) {\n if (callbacks.resolve) {\n callbacks.resolve(onOK);\n }\n } else if (callbacks.reject) {\n callbacks.reject(new CommError(errorText, code));\n }\n }\n }\n\n // Send a packet. If packet id is provided return a promise.\n #send(pkt, id) {\n let promise;\n if (id) {\n promise = this.#makePromise(id);\n }\n pkt = simplify(pkt);\n let msg = JSON.stringify(pkt);\n this.logger(\"out: \" + (this._trimLongStrings ? JSON.stringify(pkt, jsonLoggerHelper) : msg));\n try {\n this._connection.sendText(msg);\n } catch (err) {\n // If sendText throws, wrap the error in a promise or rethrow.\n if (id) {\n this.#execPromise(id, Connection.NETWORK_ERROR, null, err.message);\n } else {\n throw err;\n }\n }\n return promise;\n }\n\n // The main message dispatcher.\n #dispatchMessage(data) {\n // Skip empty response. This happens when LP times out.\n if (!data)\n return;\n\n this._inPacketCount++;\n\n // Send raw message to listener\n if (this.onRawMessage) {\n this.onRawMessage(data);\n }\n\n if (data === '0') {\n // Server response to a network probe.\n if (this.onNetworkProbe) {\n this.onNetworkProbe();\n }\n // No processing is necessary.\n return;\n }\n\n let pkt = JSON.parse(data, jsonParseHelper);\n if (!pkt) {\n this.logger(\"in: \" + data);\n this.logger(\"ERROR: failed to parse data\");\n } else {\n this.logger(\"in: \" + (this._trimLongStrings ? JSON.stringify(pkt, jsonLoggerHelper) : data));\n\n // Send complete packet to listener\n if (this.onMessage) {\n this.onMessage(pkt);\n }\n\n if (pkt.ctrl) {\n // Handling {ctrl} message\n if (this.onCtrlMessage) {\n this.onCtrlMessage(pkt.ctrl);\n }\n\n // Resolve or reject a pending promise, if any\n if (pkt.ctrl.id) {\n this.#execPromise(pkt.ctrl.id, pkt.ctrl.code, pkt.ctrl, pkt.ctrl.text);\n }\n setTimeout(_ => {\n if (pkt.ctrl.code == 205 && pkt.ctrl.text == 'evicted') {\n // User evicted from topic.\n const topic = this.#cacheGet('topic', pkt.ctrl.topic);\n if (topic) {\n topic._resetSub();\n if (pkt.ctrl.params && pkt.ctrl.params.unsub) {\n topic._gone();\n }\n }\n } else if (pkt.ctrl.code < 300 && pkt.ctrl.params) {\n if (pkt.ctrl.params.what == 'data') {\n // code=208, all messages received: \"params\":{\"count\":11,\"what\":\"data\"},\n const topic = this.#cacheGet('topic', pkt.ctrl.topic);\n if (topic) {\n topic._allMessagesReceived(pkt.ctrl.params.count);\n }\n } else if (pkt.ctrl.params.what == 'sub') {\n // code=204, the topic has no (refreshed) subscriptions.\n const topic = this.#cacheGet('topic', pkt.ctrl.topic);\n if (topic) {\n // Trigger topic.onSubsUpdated.\n topic._processMetaSubs([]);\n }\n }\n }\n }, 0);\n } else {\n setTimeout(_ => {\n if (pkt.meta) {\n // Handling a {meta} message.\n // Preferred API: Route meta to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.meta.topic);\n if (topic) {\n topic._routeMeta(pkt.meta);\n }\n\n if (pkt.meta.id) {\n this.#execPromise(pkt.meta.id, 200, pkt.meta, 'META');\n }\n\n // Secondary API: callback\n if (this.onMetaMessage) {\n this.onMetaMessage(pkt.meta);\n }\n } else if (pkt.data) {\n // Handling {data} message\n // Preferred API: Route data to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.data.topic);\n if (topic) {\n topic._routeData(pkt.data);\n }\n\n // Secondary API: Call callback\n if (this.onDataMessage) {\n this.onDataMessage(pkt.data);\n }\n } else if (pkt.pres) {\n // Handling {pres} message\n // Preferred API: Route presence to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.pres.topic);\n if (topic) {\n topic._routePres(pkt.pres);\n }\n\n // Secondary API - callback\n if (this.onPresMessage) {\n this.onPresMessage(pkt.pres);\n }\n } else if (pkt.info) {\n // {info} message - read/received notifications and key presses\n // Preferred API: Route {info}} to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.info.topic);\n if (topic) {\n topic._routeInfo(pkt.info);\n }\n\n // Secondary API - callback\n if (this.onInfoMessage) {\n this.onInfoMessage(pkt.info);\n }\n } else {\n this.logger(\"ERROR: Unknown packet received.\");\n }\n }, 0);\n }\n }\n }\n\n // Connection open, ready to start sending.\n #connectionOpen() {\n if (!this._expirePromises) {\n // Reject promises which have not been resolved for too long.\n this._expirePromises = setInterval(_ => {\n const err = new CommError(\"timeout\", 504);\n const expires = new Date(new Date().getTime() - Const.EXPIRE_PROMISES_TIMEOUT);\n for (let id in this._pendingPromises) {\n let callbacks = this._pendingPromises[id];\n if (callbacks && callbacks.ts < expires) {\n this.logger(\"Promise expired\", id);\n delete this._pendingPromises[id];\n if (callbacks.reject) {\n callbacks.reject(err);\n }\n }\n }\n }, Const.EXPIRE_PROMISES_PERIOD);\n }\n this.hello();\n }\n\n #disconnected(err, code) {\n this._inPacketCount = 0;\n this._serverInfo = null;\n this._authenticated = false;\n\n if (this._expirePromises) {\n clearInterval(this._expirePromises);\n this._expirePromises = null;\n }\n\n // Mark all topics as unsubscribed\n this.#cacheMap('topic', (topic, key) => {\n topic._resetSub();\n });\n\n // Reject all pending promises\n for (let key in this._pendingPromises) {\n const callbacks = this._pendingPromises[key];\n if (callbacks && callbacks.reject) {\n callbacks.reject(err);\n }\n }\n this._pendingPromises = {};\n\n if (this.onDisconnect) {\n this.onDisconnect(err);\n }\n }\n\n // Get User Agent string\n #getUserAgent() {\n return this._appName + ' (' + (this._browser ? this._browser + '; ' : '') + this._hwos + '); ' + Const.LIBRARY;\n }\n\n // Generator of packets stubs\n #initPacket(type, topic) {\n switch (type) {\n case 'hi':\n return {\n 'hi': {\n 'id': this.getNextUniqueId(),\n 'ver': Const.VERSION,\n 'ua': this.#getUserAgent(),\n 'dev': this._deviceToken,\n 'lang': this._humanLanguage,\n 'platf': this._platform\n }\n };\n\n case 'acc':\n return {\n 'acc': {\n 'id': this.getNextUniqueId(),\n 'user': null,\n 'scheme': null,\n 'secret': null,\n 'tmpscheme': null,\n 'tmpsecret': null,\n 'login': false,\n 'tags': null,\n 'desc': {},\n 'cred': {}\n }\n };\n\n case 'login':\n return {\n 'login': {\n 'id': this.getNextUniqueId(),\n 'scheme': null,\n 'secret': null\n }\n };\n\n case 'sub':\n return {\n 'sub': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'set': {},\n 'get': {}\n }\n };\n\n case 'leave':\n return {\n 'leave': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'unsub': false\n }\n };\n\n case 'pub':\n return {\n 'pub': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'noecho': false,\n 'head': null,\n 'content': {}\n }\n };\n\n case 'get':\n return {\n 'get': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'what': null,\n 'desc': {},\n 'sub': {},\n 'data': {}\n }\n };\n\n case 'set':\n return {\n 'set': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'desc': {},\n 'sub': {},\n 'tags': [],\n 'aux': {}\n }\n };\n\n case 'del':\n return {\n 'del': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'what': null,\n 'delseq': null,\n 'user': null,\n 'hard': false\n }\n };\n\n case 'note':\n return {\n 'note': {\n // no id by design (except calls).\n 'topic': topic,\n 'what': null, // one of \"recv\", \"read\", \"kp\", \"call\"\n 'seq': undefined // the server-side message id acknowledged as received or read.\n }\n };\n\n default:\n throw new Error(`Unknown packet type requested: ${type}`);\n }\n }\n\n // Cache management\n #cachePut(type, name, obj) {\n this._cache[type + ':' + name] = obj;\n }\n #cacheGet(type, name) {\n return this._cache[type + ':' + name];\n }\n #cacheDel(type, name) {\n delete this._cache[type + ':' + name];\n }\n\n // Enumerate all items in cache, call func for each item.\n // Enumeration stops if func returns true.\n #cacheMap(type, func, context) {\n const key = type ? type + ':' : undefined;\n for (let idx in this._cache) {\n if (!key || idx.indexOf(key) == 0) {\n if (func.call(context, this._cache[idx], idx)) {\n break;\n }\n }\n }\n }\n\n // Make limited cache management available to topic.\n // Caching user.public only. Everything else is per-topic.\n #attachCacheToTopic(topic) {\n topic._tinode = this;\n\n topic._cacheGetUser = (uid) => {\n const pub = this.#cacheGet('user', uid);\n if (pub) {\n return {\n user: uid,\n public: mergeObj({}, pub)\n };\n }\n return undefined;\n };\n topic._cachePutUser = (uid, user) => {\n this.#cachePut('user', uid, mergeObj({}, user.public));\n };\n topic._cacheDelUser = (uid) => {\n this.#cacheDel('user', uid);\n };\n topic._cachePutSelf = _ => {\n this.#cachePut('topic', topic.name, topic);\n };\n topic._cacheDelSelf = _ => {\n this.#cacheDel('topic', topic.name);\n };\n }\n\n // On successful login save server-provided data.\n #loginSuccessful(ctrl) {\n if (!ctrl.params || !ctrl.params.user) {\n return ctrl;\n }\n // This is a response to a successful login,\n // extract UID and security token, save it in Tinode module\n this._myUID = ctrl.params.user;\n this._authenticated = (ctrl && ctrl.code >= 200 && ctrl.code < 300);\n if (ctrl.params && ctrl.params.token && ctrl.params.expires) {\n this._authToken = {\n token: ctrl.params.token,\n expires: ctrl.params.expires\n };\n } else {\n this._authToken = null;\n }\n\n if (this.onLogin) {\n this.onLogin(ctrl.code, ctrl.text);\n }\n\n return ctrl;\n }\n\n // Static methods.\n /**\n * Helper method to package account credential.\n *\n * @param {string | Credential} meth - validation method or object with validation data.\n * @param {string=} val - validation value (e.g. email or phone number).\n * @param {Object=} params - validation parameters.\n * @param {string=} resp - validation response.\n *\n * @returns {Array.} array with a single credential or null if no valid credentials were given.\n */\n static credential(meth, val, params, resp) {\n if (typeof meth == 'object') {\n ({\n val,\n params,\n resp,\n meth\n } = meth);\n }\n if (meth && (val || resp)) {\n return [{\n 'meth': meth,\n 'val': val,\n 'resp': resp,\n 'params': params\n }];\n }\n return null;\n }\n\n /**\n * Determine topic type from topic's name: grp, p2p, me, fnd, sys.\n * @param {string} name - Name of the topic to test.\n * @returns {string} One of \"me\", \"fnd\", \"sys\", \"grp\",\n * \"p2p\" or undefined.\n */\n static topicType(name) {\n return Topic.topicType(name);\n }\n\n /**\n * Check if the given topic name is a name of a 'me' topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'me' topic, false otherwise.\n */\n static isMeTopicName(name) {\n return Topic.isMeTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a 'slf' topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'slf' topic, false otherwise.\n */\n static isSelfTopicName(name) {\n return Topic.isSelfTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a group topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a group topic, false otherwise.\n */\n static isGroupTopicName(name) {\n return Topic.isGroupTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a p2p topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p topic, false otherwise.\n */\n static isP2PTopicName(name) {\n return Topic.isP2PTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a communication topic, i.e. P2P or group.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p or group topic, false otherwise.\n */\n static isCommTopicName(name) {\n return Topic.isCommTopicName(name);\n }\n /**\n * Check if the topic name is a name of a new topic.\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a new topic, false otherwise.\n */\n static isNewGroupTopicName(name) {\n return Topic.isNewGroupTopicName(name);\n }\n /**\n * Check if the topic name is a name of a channel.\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a channel, false otherwise.\n */\n static isChannelTopicName(name) {\n return Topic.isChannelTopicName(name);\n }\n /**\n * Get information about the current version of this Tinode client library.\n * @returns {string} semantic version of the library, e.g. \"0.15.5-rc1\".\n */\n static getVersion() {\n return Const.VERSION;\n }\n /**\n * To use Tinode in a non browser context, supply WebSocket and XMLHttpRequest providers.\n * @static\n *\n * @param wsProvider WebSocket provider, e.g. for nodeJS , require('ws').\n * @param xhrProvider XMLHttpRequest provider, e.g. for node require('xhr').\n */\n static setNetworkProviders(wsProvider, xhrProvider) {\n WebSocketProvider = wsProvider;\n XHRProvider = xhrProvider;\n\n Connection.setNetworkProviders(WebSocketProvider, XHRProvider);\n LargeFileHelper.setNetworkProvider(XHRProvider);\n }\n /**\n * To use Tinode in a non browser context, supply indexedDB provider.\n * @static\n *\n * @param idbProvider indexedDB provider, e.g. for nodeJS , require('fake-indexeddb').\n */\n static setDatabaseProvider(idbProvider) {\n IndexedDBProvider = idbProvider;\n\n DBCache.setDatabaseProvider(IndexedDBProvider);\n }\n /**\n * Return information about the current name and version of this Tinode library.\n * @static\n *\n * @returns {string} the name of the library and it's version.\n */\n static getLibrary() {\n return Const.LIBRARY;\n }\n /**\n * Check if the given string represents NULL value as defined by Tinode ('\\u2421').\n * @param {string} str - string to check for NULL value.\n * @returns {boolean} true if string represents NULL value, false otherwise.\n */\n static isNullValue(str) {\n return str === Const.DEL_CHAR;\n }\n /**\n * Check if the given seq ID is likely to be issued by the server as oppisite to being temporary locally assigned ID.\n * @param {int} seq - seq ID to check.\n * @returns {boolean} true if seq is likely server-issued, false otherwise.\n */\n static isServerAssignedSeq(seq) {\n return seq > 0 && seq < Const.LOCAL_SEQID;\n }\n\n /**\n * Check if the given string is a valid tag value.\n * @param {string} tag - string to check.\n * @returns {boolean} true if the string is a valid tag value, false otherwise.\n */\n static isValidTagValue(tag) {\n // 4-24 characters, starting with letter or digit, then letters, digits, hyphen, underscore.\n const ALIAS_REGEX = /^[a-z0-9][a-z0-9_\\-]{3,23}$/i;\n return tag && typeof tag == 'string' && tag.length > 3 && tag.length < 24 && ALIAS_REGEX.test(tag);\n }\n\n /**\n * Split fully-qualified tag into prefix and value.\n */\n static tagSplit(tag) {\n if (!tag) {\n return null;\n }\n\n tag = tag.trim();\n\n const splitAt = tag.indexOf(':');\n if (splitAt <= 0) {\n // Invalid syntax.\n return null;\n }\n\n const value = tag.substring(splitAt + 1);\n if (!value) {\n return null;\n }\n return {\n prefix: tag.substring(0, splitAt),\n value: value\n };\n }\n\n /**\n * Set a unique namespace tag.\n * If the tag with this namespace is already present then it's replaced with the new tag.\n * @param uniqueTag tag to add, must be fully-qualified; if null or empty, no action is taken.\n */\n static setUniqueTag(tags, uniqueTag) {\n if (!tags || tags.length == 0) {\n // No tags, just add the new one.\n return [uniqueTag];\n }\n\n const parts = Tinode.tagSplit(uniqueTag)\n if (!parts) {\n // Invalid tag.\n return tags;\n }\n\n // Remove the old tag with the same prefix.\n tags = tags.filter(tag => tag && !tag.startsWith(parts.prefix));\n // Add the new tag.\n tags.push(uniqueTag);\n return tags;\n }\n\n /**\n * Remove a unique tag with the given prefix.\n * @param prefix prefix to remove\n */\n static clearTagPrefix(tags, prefix) {\n if (!tags || tags.length == 0) {\n return [];\n }\n return tags.filter(tag => tag && !tag.startsWith(prefix));\n }\n\n /**\n * Find the first tag with the given prefix.\n * @param prefix prefix to search for.\n * @return the first tag with the given prefix if found or undefined.\n */\n static tagByPrefix(tags, prefix) {\n if (!tags) {\n return undefined;\n }\n\n return tags.find(tag => tag && tag.startsWith(prefix));\n }\n\n // Instance methods.\n\n // Generates unique message IDs\n getNextUniqueId() {\n return (this._messageId != 0) ? '' + this._messageId++ : undefined;\n };\n\n /**\n * Connect to the server.\n *\n * @param {string} host_ - name of the host to connect to.\n * @return {Promise} Promise resolved/rejected when the connection call completes:\n * resolve() is called without parameters, reject() receives the\n * Error as a single parameter.\n */\n connect(host_) {\n return this._connection.connect(host_);\n }\n\n /**\n * Attempt to reconnect to the server immediately.\n *\n * @param {string} force - if true, reconnect even if there is a connection already.\n */\n reconnect(force) {\n this._connection.reconnect(force);\n }\n\n /**\n * Disconnect from the server.\n */\n disconnect() {\n this._connection.disconnect();\n }\n\n /**\n * Clear persistent cache: remove IndexedDB.\n *\n * @return {Promise} Promise resolved/rejected when the operation is completed.\n */\n clearStorage() {\n if (this._db.isReady()) {\n return this._db.deleteDatabase();\n }\n return Promise.resolve();\n }\n\n /**\n * Initialize persistent cache: create IndexedDB cache.\n *\n * @return {Promise} Promise resolved/rejected when the operation is completed.\n */\n initStorage() {\n if (!this._db.isReady()) {\n return this._db.initDatabase();\n }\n return Promise.resolve();\n }\n\n /**\n * Send a network probe message to make sure the connection is alive.\n */\n networkProbe() {\n this._connection.probe();\n }\n\n /**\n * Check for live connection to server.\n *\n * @returns {boolean} true if there is a live connection, false otherwise.\n */\n isConnected() {\n return this._connection.isConnected();\n }\n\n /**\n * Check if connection is authenticated (last login was successful).\n *\n * @returns {boolean} true if authenticated, false otherwise.\n */\n isAuthenticated() {\n return this._authenticated;\n }\n\n /**\n * Add API key and auth token to the relative URL making it usable for getting data\n * from the server in a simple HTTP GET request.\n *\n * @param {string} URL - URL to wrap.\n * @returns {string} URL with appended API key and token, if valid token is present.\n */\n authorizeURL(url) {\n if (typeof url != 'string') {\n return url;\n }\n\n if (isUrlRelative(url)) {\n // Fake base to make the relative URL parseable.\n const base = 'scheme://host/';\n const parsed = new URL(url, base);\n if (this._apiKey) {\n parsed.searchParams.append('apikey', this._apiKey);\n }\n if (this._authToken && this._authToken.token) {\n parsed.searchParams.append('auth', 'token');\n parsed.searchParams.append('secret', this._authToken.token);\n }\n // Convert back to string and strip fake base URL except for the root slash.\n url = parsed.toString().substring(base.length - 1);\n }\n return url;\n }\n\n /**\n * @typedef AccountParams\n * @type {Object}\n * @property {DefAcs=} defacs - Default access parameters for user's me topic.\n * @property {Object=} public - Public application-defined data exposed on me topic.\n * @property {Object=} private - Private application-defined data accessible on me topic.\n * @property {Object=} trusted - Trusted user data which can be set by a root user only.\n * @property {Array.} tags - array of string tags for user discovery.\n * @property {string} scheme - Temporary authentication scheme for password reset.\n * @property {string} secret - Temporary authentication secret for password reset.\n * @property {Array.=} attachments - Array of references to out of band attachments used in account description.\n */\n /**\n * @typedef DefAcs\n * @type {Object}\n * @property {string=} auth - Access mode for me for authenticated users.\n * @property {string=} anon - Access mode for me for anonymous users.\n */\n\n /**\n * Create or update an account.\n *\n * @param {string} uid - User id to update\n * @param {string} scheme - Authentication scheme; \"basic\" and \"anonymous\" are the currently supported schemes.\n * @param {string} secret - Authentication secret, assumed to be already base64 encoded.\n * @param {boolean=} login - Use new account to authenticate current session\n * @param {AccountParams=} params - User data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n account(uid, scheme, secret, login, params) {\n const pkt = this.#initPacket('acc');\n pkt.acc.user = uid;\n pkt.acc.scheme = scheme;\n pkt.acc.secret = secret;\n // Log in to the new account using selected scheme\n pkt.acc.login = login;\n\n if (params) {\n pkt.acc.desc.defacs = params.defacs;\n pkt.acc.desc.public = params.public;\n pkt.acc.desc.private = params.private;\n pkt.acc.desc.trusted = params.trusted;\n\n pkt.acc.tags = params.tags;\n pkt.acc.cred = params.cred;\n\n pkt.acc.tmpscheme = params.scheme;\n pkt.acc.tmpsecret = params.secret;\n\n if (Array.isArray(params.attachments) && params.attachments.length > 0) {\n pkt.extra = {\n attachments: params.attachments.filter(ref => isUrlRelative(ref))\n };\n }\n }\n\n return this.#send(pkt, pkt.acc.id);\n }\n\n /**\n * Create a new user. Wrapper for {@link Tinode#account}.\n *\n * @param {string} scheme - Authentication scheme; \"basic\" is the only currently supported scheme.\n * @param {string} secret - Authentication.\n * @param {boolean=} login - Use new account to authenticate current session\n * @param {AccountParams=} params - User data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n createAccount(scheme, secret, login, params) {\n let promise = this.account(Const.USER_NEW, scheme, secret, login, params);\n if (login) {\n promise = promise.then(ctrl => this.#loginSuccessful(ctrl));\n }\n return promise;\n }\n\n /**\n * Create user with 'basic' authentication scheme and immediately\n * use it for authentication. Wrapper for {@link Tinode#account}.\n *\n * @param {string} username - Login to use for the new account.\n * @param {string} password - User's password.\n * @param {AccountParams=} params - User data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n createAccountBasic(username, password, params) {\n // Make sure we are not using 'null' or 'undefined';\n username = username || '';\n password = password || '';\n return this.createAccount('basic',\n b64EncodeUnicode(username + ':' + password), true, params);\n }\n\n /**\n * Update user's credentials for 'basic' authentication scheme. Wrapper for {@link Tinode#account}.\n *\n * @param {string} uid - User ID to update.\n * @param {string} username - Login to use for the new account.\n * @param {string} password - User's password.\n * @param {AccountParams=} params - data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n updateAccountBasic(uid, username, password, params) {\n // Make sure we are not using 'null' or 'undefined';\n username = username || '';\n password = password || '';\n return this.account(uid, 'basic',\n b64EncodeUnicode(username + ':' + password), false, params);\n }\n\n /**\n * Send handshake to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n hello() {\n const pkt = this.#initPacket('hi');\n\n return this.#send(pkt, pkt.hi.id)\n .then(ctrl => {\n // Reset backoff counter on successful connection.\n this._connection.backoffReset();\n\n // Server response contains server protocol version, build, constraints,\n // session ID for long polling. Save them.\n if (ctrl.params) {\n this._serverInfo = ctrl.params;\n }\n\n if (this.onConnect) {\n this.onConnect();\n }\n\n return ctrl;\n }).catch(err => {\n this._connection.reconnect(true);\n\n if (this.onDisconnect) {\n this.onDisconnect(err);\n }\n });\n }\n\n /**\n * Set or refresh the push notifications/device token. If the client is connected,\n * the deviceToken can be sent to the server.\n *\n * @param {string} dt - token obtained from the provider or false,\n * null or undefined to clear the token.\n *\n * @returns true if attempt was made to send the update to the server.\n */\n setDeviceToken(dt) {\n let sent = false;\n // Convert any falsish value to null.\n dt = dt || null;\n if (dt != this._deviceToken) {\n this._deviceToken = dt;\n if (this.isConnected() && this.isAuthenticated()) {\n this.#send({\n 'hi': {\n 'dev': dt || Tinode.DEL_CHAR\n }\n });\n sent = true;\n }\n }\n return sent;\n }\n\n /**\n * @typedef Credential\n * @type {Object}\n * @property {string} meth - validation method.\n * @property {string} val - value to validate (e.g. email or phone number).\n * @property {string} resp - validation response.\n * @property {Object} params - validation parameters.\n */\n /**\n * Authenticate current session.\n *\n * @param {string} scheme - Authentication scheme; \"basic\" is the only currently supported scheme.\n * @param {string} secret - Authentication secret, assumed to be already base64 encoded.\n * @param {Credential=} cred - credential confirmation, if required.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n login(scheme, secret, cred) {\n const pkt = this.#initPacket('login');\n pkt.login.scheme = scheme;\n pkt.login.secret = secret;\n pkt.login.cred = cred;\n\n return this.#send(pkt, pkt.login.id)\n .then(ctrl => this.#loginSuccessful(ctrl));\n }\n\n /**\n * Wrapper for {@link Tinode#login} with basic authentication\n *\n * @param {string} uname - User name.\n * @param {string} password - Password.\n * @param {Credential=} cred - credential confirmation, if required.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n loginBasic(uname, password, cred) {\n return this.login('basic', b64EncodeUnicode(uname + ':' + password), cred)\n .then(ctrl => {\n this._login = uname;\n return ctrl;\n });\n }\n\n /**\n * Wrapper for {@link Tinode#login} with token authentication\n *\n * @param {string} token - Token received in response to earlier login.\n * @param {Credential=} cred - credential confirmation, if required.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n loginToken(token, cred) {\n return this.login('token', token, cred);\n }\n\n /**\n * Send a request for resetting an authentication secret.\n *\n * @param {string} scheme - authentication scheme to reset.\n * @param {string} method - method to use for resetting the secret, such as \"email\" or \"tel\".\n * @param {string} value - value of the credential to use, a specific email address or a phone number.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving the server reply.\n */\n requestResetAuthSecret(scheme, method, value) {\n return this.login('reset', b64EncodeUnicode(scheme + ':' + method + ':' + value));\n }\n\n /**\n * @typedef AuthToken\n * @type {Object}\n * @property {string} token - Token value.\n * @property {Date} expires - Token expiration time.\n */\n /**\n * Get stored authentication token.\n *\n * @returns {AuthToken} authentication token.\n */\n getAuthToken() {\n if (this._authToken && (this._authToken.expires.getTime() > Date.now())) {\n return this._authToken;\n } else {\n this._authToken = null;\n }\n return null;\n }\n\n /**\n * Application may provide a saved authentication token.\n *\n * @param {AuthToken} token - authentication token.\n */\n setAuthToken(token) {\n this._authToken = token;\n }\n\n /**\n * @typedef SetParams\n * @type {Object}\n * @property {SetDesc=} desc - Topic initialization parameters when creating a new topic or a new subscription.\n * @property {SetSub=} sub - Subscription initialization parameters.\n * @property {Array.=} tags - Search tags.\n * @property {Object} aux - Auxiliary topic data.\n * @property {Array.=} attachments - URLs of out of band attachments used in parameters.\n */\n /**\n * @typedef SetDesc\n * @type {Object}\n * @property {DefAcs=} defacs - Default access mode.\n * @property {Object=} public - Free-form topic description, publically accessible.\n * @property {Object=} private - Free-form topic description accessible only to the owner.\n * @property {Object=} trusted - Trusted user data which can be set by a root user only.\n */\n /**\n * @typedef SetSub\n * @type {Object}\n * @property {string=} user - UID of the user affected by the request. Default (empty) - current user.\n * @property {string=} mode - User access mode, either requested or assigned dependent on context.\n */\n /**\n * Send a topic subscription request.\n *\n * @param {string} topic - Name of the topic to subscribe to.\n * @param {GetQuery=} getParams - Optional subscription metadata query\n * @param {SetParams=} setParams - Optional initialization parameters\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n subscribe(topicName, getParams, setParams) {\n const pkt = this.#initPacket('sub', topicName)\n if (!topicName) {\n topicName = Const.TOPIC_NEW;\n }\n\n pkt.sub.get = getParams;\n\n if (setParams) {\n if (setParams.sub) {\n pkt.sub.set.sub = setParams.sub;\n }\n\n if (setParams.desc) {\n const desc = setParams.desc;\n if (Tinode.isNewGroupTopicName(topicName)) {\n // Full set.desc params are used for new topics only\n pkt.sub.set.desc = desc;\n } else if (Tinode.isP2PTopicName(topicName) && desc.defacs) {\n // Use optional default permissions only.\n pkt.sub.set.desc = {\n defacs: desc.defacs\n };\n }\n }\n\n // See if external objects were used in topic description.\n if (Array.isArray(setParams.attachments) && setParams.attachments.length > 0) {\n pkt.extra = {\n attachments: setParams.attachments.filter(ref => isUrlRelative(ref))\n };\n }\n\n if (setParams.tags) {\n pkt.sub.set.tags = setParams.tags;\n }\n if (setParams.aux) {\n pkt.sub.set.aux = setParams.aux;\n }\n }\n return this.#send(pkt, pkt.sub.id);\n }\n\n /**\n * Detach and optionally unsubscribe from the topic\n *\n * @param {string} topic - Topic to detach from.\n * @param {boolean} unsub - If true, detach and unsubscribe, otherwise just detach.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n leave(topic, unsub) {\n const pkt = this.#initPacket('leave', topic);\n pkt.leave.unsub = unsub;\n\n return this.#send(pkt, pkt.leave.id);\n }\n\n /**\n * Create message draft without sending it to the server.\n *\n * @param {string} topic - Name of the topic to publish to.\n * @param {Object} content - Payload to publish.\n * @param {boolean=} noEcho - If true, tell the server not to echo the message to the original session.\n *\n * @returns {Object} new message which can be sent to the server or otherwise used.\n */\n createMessage(topic, content, noEcho) {\n const pkt = this.#initPacket('pub', topic);\n\n let dft = typeof content == 'string' ? Drafty.parse(content) : content;\n if (dft && !Drafty.isPlainText(dft)) {\n pkt.pub.head = {\n mime: Drafty.getContentType()\n };\n content = dft;\n }\n pkt.pub.noecho = noEcho;\n pkt.pub.content = content;\n\n return pkt.pub;\n }\n\n /**\n * Publish {data} message to topic.\n *\n * @param {string} topicName - Name of the topic to publish to.\n * @param {Object} content - Payload to publish.\n * @param {boolean=} noEcho - If true, tell the server not to echo the message to the original session.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n publish(topicName, content, noEcho) {\n return this.publishMessage(\n this.createMessage(topicName, content, noEcho)\n );\n }\n\n /**\n * Publish message to topic. The message should be created by {@link Tinode#createMessage}.\n *\n * @param {Object} pub - Message to publish.\n * @param {Array.=} attachments - array of URLs with attachments.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n publishMessage(pub, attachments) {\n // Make a shallow copy. Needed in order to clear locally-assigned temp values;\n pub = Object.assign({}, pub);\n pub.seq = undefined;\n pub.from = undefined;\n pub.ts = undefined;\n const msg = {\n pub: pub,\n };\n if (attachments) {\n msg.extra = {\n attachments: attachments.filter(ref => isUrlRelative(ref))\n };\n }\n return this.#send(msg, pub.id);\n }\n\n /**\n * Out of band notification: notify topic that an external (push) notification was recived by the client.\n *\n * @param {object} data - notification payload.\n * @param {string} data.what - notification type, 'msg', 'read', 'sub'.\n * @param {string} data.topic - name of the updated topic.\n * @param {number=} data.seq - seq ID of the affected message.\n * @param {string=} data.xfrom - UID of the sender.\n * @param {object=} data.given - new subscription 'given', e.g. 'ASWP...'.\n * @param {object=} data.want - new subscription 'want', e.g. 'RWJ...'.\n */\n oobNotification(data) {\n this.logger('oob: ' + (this._trimLongStrings ? JSON.stringify(data, jsonLoggerHelper) : data));\n\n switch (data.what) {\n case 'msg':\n if (!data.seq || data.seq < 1 || !data.topic) {\n // Server sent invalid data.\n break;\n }\n\n if (!this.isConnected()) {\n // Let's ignore the message if there is no connection: no connection means there are no open\n // tabs with Tinode.\n break;\n }\n\n const topic = this.#cacheGet('topic', data.topic);\n if (!topic) {\n // TODO: check if there is a case when a message can arrive from an unknown topic.\n break;\n }\n\n if (topic.isSubscribed()) {\n // No need to fetch: topic is already subscribed and got data through normal channel.\n break;\n }\n\n if (topic.maxMsgSeq() < data.seq) {\n if (topic.isChannelType()) {\n topic._updateReceived(data.seq, 'fake-uid');\n }\n\n // New message.\n if (data.xfrom && !this.#cacheGet('user', data.xfrom)) {\n // Message from unknown sender, fetch description from the server.\n // Sending asynchronously without a subscription.\n this.getMeta(data.xfrom, new MetaGetBuilder().withDesc().build()).catch(err => {\n this.logger(\"Failed to get the name of a new sender\", err);\n });\n }\n\n topic.subscribe(null).then(_ => {\n return topic.getMeta(new MetaGetBuilder(topic).withLaterData(24).withLaterDel(24).build());\n }).then(_ => {\n // Allow data fetch to complete and get processed successfully.\n topic.leaveDelayed(false, 1000);\n }).catch(err => {\n this.logger(\"On push data fetch failed\", err);\n }).finally(_ => {\n this.getMeTopic()._refreshContact('msg', topic);\n });\n }\n break;\n\n case 'read':\n this.getMeTopic()._routePres({\n what: 'read',\n seq: data.seq\n });\n break;\n\n case 'sub':\n if (!this.isMe(data.xfrom)) {\n // TODO: handle updates from other users.\n break;\n }\n\n const mode = {\n given: data.modeGiven,\n want: data.modeWant\n };\n const acs = new AccessMode(mode);\n const pres = (!acs.mode || acs.mode == AccessMode._NONE) ?\n // Subscription deleted.\n {\n what: 'gone',\n src: data.topic\n } :\n // New subscription or subscription updated.\n {\n what: 'acs',\n src: data.topic,\n dacs: mode\n };\n this.getMeTopic()._routePres(pres);\n break;\n\n default:\n this.logger(\"Unknown push type ignored\", data.what);\n }\n }\n\n /**\n * @typedef GetOptsType\n * @type {Object}\n * @property {Date=} ims - \"If modified since\", fetch data only it was was modified since stated date.\n * @property {number=} limit - Maximum number of results to return. Ignored when querying topic description.\n */\n\n /**\n * @typedef GetDataType\n * @type {Object}\n * @property {number=} since - Load messages with seq ID equal or greater than this value.\n * @property {number=} before - Load messages with seq ID lower than this number.\n * @property {number=} limit - Maximum number of results to return.\n * @property {Array.=} range - Ranges of seq IDs to fetch.\n */\n\n /**\n * @typedef GetQuery\n * @type {Object}\n * @property {GetOptsType=} desc - If provided (even if empty), fetch topic description.\n * @property {GetOptsType=} sub - If provided (even if empty), fetch topic subscriptions.\n * @property {GetDataType=} data - If provided (even if empty), get messages.\n */\n\n /**\n * Request topic metadata\n *\n * @param {string} topic - Name of the topic to query.\n * @param {GetQuery} params - Parameters of the query. Use {@link Tinode.MetaGetBuilder} to generate.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n getMeta(topic, params) {\n const pkt = this.#initPacket('get', topic);\n\n pkt.get = mergeObj(pkt.get, params);\n\n return this.#send(pkt, pkt.get.id);\n }\n\n /**\n * Update topic's metadata: description, subscribtions.\n *\n * @param {string} topic - Topic to update.\n * @param {SetParams} params - topic metadata to update.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n setMeta(topic, params) {\n const pkt = this.#initPacket('set', topic);\n const what = [];\n\n if (params) {\n ['desc', 'sub', 'tags', 'cred', 'aux'].forEach(key => {\n if (params.hasOwnProperty(key)) {\n what.push(key);\n pkt.set[key] = params[key];\n }\n });\n\n if (Array.isArray(params.attachments) && params.attachments.length > 0) {\n pkt.extra = {\n attachments: params.attachments.filter(ref => isUrlRelative(ref))\n };\n }\n }\n\n if (what.length == 0) {\n return Promise.reject(new Error(\"Invalid {set} parameters\"));\n }\n\n return this.#send(pkt, pkt.set.id);\n }\n\n /**\n * Range of message IDs.\n *\n * @typedef SeqRange\n * @type {Object}\n * @property {number} low - low end of the range, inclusive (closed).\n * @property {number=} hi - high end of the range, exclusive (open).\n */\n /**\n * Delete some or all messages in a topic.\n *\n * @param {string} topic - Topic name to delete messages from.\n * @param {Array.} list - Ranges of message IDs to delete.\n * @param {boolean=} hard - Hard or soft delete\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delMessages(topic, ranges, hard) {\n const pkt = this.#initPacket('del', topic);\n\n pkt.del.what = 'msg';\n pkt.del.delseq = ranges;\n pkt.del.hard = hard;\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Delete the topic alltogether. Requires Owner permission.\n *\n * @param {string} topicName - Name of the topic to delete\n * @param {boolean} hard - hard-delete topic.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delTopic(topicName, hard) {\n const pkt = this.#initPacket('del', topicName);\n pkt.del.what = 'topic';\n pkt.del.hard = hard;\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Delete subscription. Requires Share permission.\n *\n * @param {string} topicName - Name of the topic to delete\n * @param {string} user - User ID to remove.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delSubscription(topicName, user) {\n const pkt = this.#initPacket('del', topicName);\n pkt.del.what = 'sub';\n pkt.del.user = user;\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Delete credential. Always sent on 'me' topic.\n *\n * @param {string} method - validation method such as 'email' or 'tel'.\n * @param {string} value - validation value, i.e. 'alice@example.com'.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delCredential(method, value) {\n const pkt = this.#initPacket('del', Const.TOPIC_ME);\n pkt.del.what = 'cred';\n pkt.del.cred = {\n meth: method,\n val: value\n };\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Request to delete account of the current user.\n *\n * @param {boolean} hard - hard-delete user.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delCurrentUser(hard) {\n const pkt = this.#initPacket('del', null);\n pkt.del.what = 'user';\n pkt.del.hard = hard;\n\n return this.#send(pkt, pkt.del.id).then(_ => {\n this._myUID = null;\n });\n }\n\n /**\n * Notify server that a message or messages were read or received. Does NOT return promise.\n *\n * @param {string} topicName - Name of the topic where the mesage is being aknowledged.\n * @param {string} what - Action being aknowledged, either \"read\" or \"recv\".\n * @param {number} seq - Maximum id of the message being acknowledged.\n * @throws {Error} if seq is invalid.\n */\n note(topicName, what, seq) {\n if (seq <= 0 || seq >= Const.LOCAL_SEQID) {\n throw new Error(`Invalid message id ${seq}`);\n }\n\n const pkt = this.#initPacket('note', topicName);\n pkt.note.what = what;\n pkt.note.seq = seq;\n this.#send(pkt);\n }\n\n /**\n * Broadcast a key-press notification to topic subscribers. Used to show\n * typing notifications \"user X is typing...\".\n *\n * @param {string} topicName - Name of the topic to broadcast to.\n * @param {string=} type - notification to send, default is 'kp'.\n */\n noteKeyPress(topicName, type) {\n const pkt = this.#initPacket('note', topicName);\n pkt.note.what = type || 'kp';\n this.#send(pkt);\n }\n\n /**\n * Send a video call notification to topic subscribers (including dialing,\n * hangup, etc.).\n *\n * @param {string} topicName - Name of the topic to broadcast to.\n * @param {int} seq - ID of the call message the event pertains to.\n * @param {string} evt - Call event.\n * @param {string} payload - Payload associated with this event (e.g. SDP string).\n *\n * @returns {Promise} Promise (for some call events) which will\n * be resolved/rejected on receiving server reply\n */\n videoCall(topicName, seq, evt, payload) {\n const pkt = this.#initPacket('note', topicName);\n pkt.note.seq = seq;\n pkt.note.what = 'call';\n pkt.note.event = evt;\n pkt.note.payload = payload;\n this.#send(pkt, pkt.note.id);\n }\n\n /**\n * Get a named topic, either pull it from cache or create a new instance.\n * There is a single instance of topic for each name.\n *\n * @param {string} topicName - Name of the topic to get.\n *\n * @returns {Topic} Requested or newly created topic or undefined if topic name is invalid.\n */\n getTopic(topicName) {\n let topic = this.#cacheGet('topic', topicName);\n if (!topic && topicName) {\n if (topicName == Const.TOPIC_ME) {\n topic = new TopicMe();\n } else if (topicName == Const.TOPIC_FND) {\n topic = new TopicFnd();\n } else {\n topic = new Topic(topicName);\n }\n // Cache management.\n this.#attachCacheToTopic(topic);\n topic._cachePutSelf();\n // Don't save to DB here: a record will be added when the topic is subscribed.\n }\n return topic;\n }\n\n /**\n * Get a named topic from cache.\n *\n * @param {string} topicName - Name of the topic to get.\n *\n * @returns {Topic} Requested topic or undefined if topic is not found in cache.\n */\n cacheGetTopic(topicName) {\n return this.#cacheGet('topic', topicName);\n }\n\n /**\n * Remove named topic from cache.\n *\n * @param {string} topicName - Name of the topic to remove from cache.\n */\n cacheRemTopic(topicName) {\n this.#cacheDel('topic', topicName);\n }\n\n /**\n * Iterate over cached topics.\n *\n * @param {Function} func - callback to call for each topic.\n * @param {Object} context - 'this' inside the 'func'.\n */\n mapTopics(func, context) {\n this.#cacheMap('topic', func, context);\n }\n\n /**\n * Check if named topic is already present in cache.\n *\n * @param {string} topicName - Name of the topic to check.\n * @returns {boolean} true if topic is found in cache, false otherwise.\n */\n isTopicCached(topicName) {\n return !!this.#cacheGet('topic', topicName);\n }\n\n /**\n * Generate unique name like 'new123456' suitable for creating a new group topic.\n *\n * @param {boolean} isChan - if the topic is channel-enabled.\n * @returns {string} name which can be used for creating a new group topic.\n */\n newGroupTopicName(isChan) {\n return (isChan ? Const.TOPIC_NEW_CHAN : Const.TOPIC_NEW) + this.getNextUniqueId();\n }\n\n /**\n * Instantiate 'me' topic or get it from cache.\n *\n * @returns {TopicMe} Instance of 'me' topic.\n */\n getMeTopic() {\n return this.getTopic(Const.TOPIC_ME);\n }\n\n /**\n * Instantiate 'fnd' (find) topic or get it from cache.\n *\n * @returns {Topic} Instance of 'fnd' topic.\n */\n getFndTopic() {\n return this.getTopic(Const.TOPIC_FND);\n }\n\n /**\n * Create a new {@link LargeFileHelper} instance\n *\n * @returns {LargeFileHelper} instance of a {@link Tinode.LargeFileHelper}.\n */\n getLargeFileHelper() {\n return new LargeFileHelper(this, Const.PROTOCOL_VERSION);\n }\n\n /**\n * Get the UID of the the current authenticated user.\n *\n * @returns {string} UID of the current user or undefined if the session is not yet\n * authenticated or if there is no session.\n */\n getCurrentUserID() {\n return this._myUID;\n }\n\n /**\n * Check if the given user ID is equal to the current user's UID.\n *\n * @param {string} uid - UID to check.\n *\n * @returns {boolean} true if the given UID belongs to the current logged in user.\n */\n isMe(uid) {\n return this._myUID === uid;\n }\n\n /**\n * Get login used for last successful authentication.\n *\n * @returns {string} login last used successfully or undefined.\n */\n getCurrentLogin() {\n return this._login;\n }\n\n /**\n * Return information about the server: protocol version and build timestamp.\n *\n * @returns {Object} build and version of the server or null if there is no connection or\n * if the first server response has not been received yet.\n */\n getServerInfo() {\n return this._serverInfo;\n }\n\n /**\n * Report a topic for abuse. Wrapper for {@link Tinode#publish}.\n *\n * @param {string} action - the only supported action is 'report'.\n * @param {string} target - name of the topic being reported.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n report(action, target) {\n return this.publish(Const.TOPIC_SYS, Drafty.attachJSON(null, {\n 'action': action,\n 'target': target\n }));\n }\n\n /**\n * Return server-provided configuration value.\n *\n * @param {string} name of the value to return.\n * @param {Object} defaultValue to return in case the parameter is not set or not found.\n *\n * @returns {Object} named value.\n */\n getServerParam(name, defaultValue) {\n return this._serverInfo && this._serverInfo[name] || defaultValue;\n }\n\n /**\n * Toggle console logging. Logging is off by default.\n *\n * @param {boolean} enabled - Set to true to enable logging to console.\n * @param {boolean} trimLongStrings - Set to true to trim long strings.\n */\n enableLogging(enabled, trimLongStrings) {\n this._loggingEnabled = enabled;\n this._trimLongStrings = enabled && trimLongStrings;\n }\n\n /**\n * Set UI language to report to the server. Must be called before 'hi' is sent, otherwise it will not be used.\n *\n * @param {string} hl - human (UI) language, like \"en_US\" or \"zh-Hans\".\n */\n setHumanLanguage(hl) {\n if (hl) {\n this._humanLanguage = hl;\n }\n }\n\n /**\n * Check if given topic is online.\n *\n * @param {string} name of the topic to test.\n * @returns {boolean} true if topic is online, false otherwise.\n */\n isTopicOnline(name) {\n const topic = this.#cacheGet('topic', name);\n return topic && topic.online;\n }\n\n /**\n * Get access mode for the given contact.\n *\n * @param {string} name of the topic to query.\n * @returns {AccessMode} access mode if topic is found, null otherwise.\n */\n getTopicAccessMode(name) {\n const topic = this.#cacheGet('topic', name);\n return topic ? topic.acs : null;\n }\n\n /**\n * Include message ID into all subsequest messages to server instructin it to send aknowledgemens.\n * Required for promises to function. Default is \"on\".\n *\n * @param {boolean} status - Turn aknowledgemens on or off.\n * @deprecated\n */\n wantAkn(status) {\n if (status) {\n this._messageId = Math.floor((Math.random() * 0xFFFFFF) + 0xFFFFFF);\n } else {\n this._messageId = 0;\n }\n }\n\n // Callbacks:\n /**\n * Callback to report when the websocket is opened. The callback has no parameters.\n *\n * @type {onWebsocketOpen}\n */\n onWebsocketOpen = undefined;\n\n /**\n * @typedef ServerParams\n *\n * @type {Object}\n * @property {string} ver - Server version\n * @property {string} build - Server build\n * @property {string=} sid - Session ID, long polling connections only.\n */\n\n /**\n * @callback onConnect\n * @param {number} code - Result code\n * @param {string} text - Text epxplaining the completion, i.e \"OK\" or an error message.\n * @param {ServerParams} params - Parameters returned by the server.\n */\n /**\n * Callback to report when connection with Tinode server is established.\n * @type {onConnect}\n */\n onConnect = undefined;\n\n /**\n * Callback to report when connection is lost. The callback has no parameters.\n * @type {onDisconnect}\n */\n onDisconnect = undefined;\n\n /**\n * @callback onLogin\n * @param {number} code - NUmeric completion code, same as HTTP status codes.\n * @param {string} text - Explanation of the completion code.\n */\n /**\n * Callback to report login completion.\n * @type {onLogin}\n */\n onLogin = undefined;\n\n /**\n * Callback to receive {ctrl} (control) messages.\n * @type {onCtrlMessage}\n */\n onCtrlMessage = undefined;\n\n /**\n * Callback to recieve {data} (content) messages.\n * @type {onDataMessage}\n */\n onDataMessage = undefined;\n\n /**\n * Callback to receive {pres} (presence) messages.\n * @type {onPresMessage}\n */\n onPresMessage = undefined;\n\n /**\n * Callback to receive all messages as objects.\n * @type {onMessage}\n */\n onMessage = undefined;\n\n /**\n * Callback to receive all messages as unparsed text.\n * @type {onRawMessage}\n */\n onRawMessage = undefined;\n\n /**\n * Callback to receive server responses to network probes. See {@link Tinode#networkProbe}\n * @type {onNetworkProbe}\n */\n onNetworkProbe = undefined;\n\n /**\n * Callback to be notified when exponential backoff is iterating.\n * @type {onAutoreconnectIteration}\n */\n onAutoreconnectIteration = undefined;\n};\n\n// Exported constants\nTinode.MESSAGE_STATUS_NONE = Const.MESSAGE_STATUS_NONE;\nTinode.MESSAGE_STATUS_QUEUED = Const.MESSAGE_STATUS_QUEUED;\nTinode.MESSAGE_STATUS_SENDING = Const.MESSAGE_STATUS_SENDING;\nTinode.MESSAGE_STATUS_FAILED = Const.MESSAGE_STATUS_FAILED;\nTinode.MESSAGE_STATUS_FATAL = Const.MESSAGE_STATUS_FATAL;\nTinode.MESSAGE_STATUS_SENT = Const.MESSAGE_STATUS_SENT;\nTinode.MESSAGE_STATUS_RECEIVED = Const.MESSAGE_STATUS_RECEIVED;\nTinode.MESSAGE_STATUS_READ = Const.MESSAGE_STATUS_READ;\nTinode.MESSAGE_STATUS_TO_ME = Const.MESSAGE_STATUS_TO_ME;\n\n// Unicode [del] symbol.\nTinode.DEL_CHAR = Const.DEL_CHAR;\n\n// Names of keys to server-provided configuration limits.\nTinode.MAX_MESSAGE_SIZE = 'maxMessageSize';\nTinode.MAX_SUBSCRIBER_COUNT = 'maxSubscriberCount';\nTinode.MIN_TAG_LENGTH = 'minTagLength';\nTinode.MAX_TAG_LENGTH = 'maxTagLength';\nTinode.MAX_TAG_COUNT = 'maxTagCount';\nTinode.MAX_FILE_UPLOAD_SIZE = 'maxFileUploadSize';\nTinode.REQ_CRED_VALIDATORS = 'reqCred';\nTinode.MSG_DELETE_AGE = 'msgDelAge';\n\n// Tinode URI topic ID prefix, 'scheme:path/'.\nTinode.URI_TOPIC_ID_PREFIX = 'tinode:topic/';\n\n// Tag prefixes for alias, email, phone.\nTinode.TAG_ALIAS = Const.TAG_ALIAS;\nTinode.TAG_EMAIL = Const.TAG_EMAIL;\nTinode.TAG_PHONE = Const.TAG_PHONE;\n"],"names":["AccessMode","constructor","acs","given","decode","want","mode","checkFlag","#checkFlag","val","side","flag","includes","Error","str","_BITMASK","_NONE","bitmask","_JOIN","_READ","_WRITE","_PRES","_APPROVE","_SHARE","_DELETE","_OWNER","m0","i","length","bit","charAt","toUpperCase","encode","_INVALID","res","update","upd","action","val0","parts","split","diff","a1","a2","toString","jsonHelper","setMode","m","updateMode","u","getMode","setGiven","g","updateGiven","getGiven","setWant","w","updateWant","getWant","getMissing","getExcessive","updateAll","isOwner","isPresencer","isMuted","isJoiner","isReader","isWriter","isApprover","isAdmin","isSharer","isDeleter","CBuffer","comparator","undefined","unique","buffer","compare_","unique_","a","b","findNearest","#findNearest","elem","arr","exact","start","end","pivot","found","idx","insertSorted","#insertSorted","count","splice","getAt","at","getLast","filter","findLast","put","insert","arguments","Array","isArray","delAt","r","delRange","since","before","reset","forEach","callback","startIdx","beforeIdx","context","Math","max","min","call","find","nearest","isEmpty","CommError","message","code","name","PACKAGE_VERSION","PROTOCOL_VERSION","VERSION","LIBRARY","TOPIC_NEW","TOPIC_NEW_CHAN","TOPIC_ME","TOPIC_FND","TOPIC_SYS","TOPIC_SLF","TOPIC_CHAN","TOPIC_GRP","TOPIC_P2P","USER_NEW","LOCAL_SEQID","MESSAGE_STATUS_NONE","MESSAGE_STATUS_QUEUED","MESSAGE_STATUS_SENDING","MESSAGE_STATUS_FAILED","MESSAGE_STATUS_FATAL","MESSAGE_STATUS_SENT","MESSAGE_STATUS_RECEIVED","MESSAGE_STATUS_READ","MESSAGE_STATUS_TO_ME","EXPIRE_PROMISES_TIMEOUT","EXPIRE_PROMISES_PERIOD","RECV_TIMEOUT","DEFAULT_MESSAGES_PAGE","DEL_CHAR","MAX_PINNED_COUNT","TAG_ALIAS","TAG_EMAIL","TAG_PHONE","jsonParseHelper","WebSocketProvider","XHRProvider","NETWORK_ERROR","NETWORK_ERROR_TEXT","NETWORK_USER","NETWORK_USER_TEXT","_BOFF_BASE","_BOFF_MAX_ITER","_BOFF_JITTER","makeBaseUrl","host","protocol","version","apiKey","url","Connection","log","_","boffTimer","boffIteration","boffClosed","socket","secure","autoreconnect","initialized","config","version_","autoreconnect_","transport","init_lp","init_ws","setNetworkProviders","wsProvider","xhrProvider","logger","l","connect","host_","force","Promise","reject","reconnect","disconnect","sendText","msg","isConnected","probe","backoffReset","boffReset","boffReconnect","#boffReconnect","clearTimeout","timeout","pow","random","onAutoreconnectIteration","setTimeout","prom","catch","boffStop","#boffStop","#boffReset","#init_lp","XDR_UNSENT","XDR_OPENED","XDR_HEADERS_RECEIVED","XDR_LOADING","XDR_DONE","_lpURL","_poller","_sender","lp_sender","url_","sender","onreadystatechange","evt","readyState","status","open","lp_poller","resolve","poller","promiseCompleted","pkt","JSON","parse","responseText","ctrl","params","sid","send","onOpen","onMessage","onDisconnect","text","abort","err","#init_ws","OPEN","close","conn","onerror","onopen","onclose","onmessage","data","DB_VERSION","DB_NAME","IDBProvider","DB","onError","db","disabled","mapObjects","#mapObjects","source","trx","transaction","event","target","error","objectStore","getAll","onsuccess","result","topic","initDatabase","req","onversionchange","onupgradeneeded","objectStoreNames","contains","createObjectStore","keyPath","dellog","indexNames","createIndex","deleteDatabase","onblocked","isReady","updTopic","oncomplete","get","serializeTopic","commit","markTopicAsDeleted","deleted","_deleted","remTopic","delete","IDBKeyRange","only","bound","Number","MAX_SAFE_INTEGER","mapTopics","deserializeTopic","src","updUser","uid","pub","public","remUser","mapUsers","getUser","user","updSubscription","topicName","sub","serializeSubscription","mapSubscriptions","addMessage","add","serializeMessage","updMessageStatus","seq","_status","remMessages","from","to","range","readMessages","query","ranges","key","hi","low","msgs","concat","push","limit","openCursor","cursor","value","continue","addDelLog","delId","clear","readDelLog","entries","map","entry","maxDelId","index","topic_fields","#deserializeTopic","f","hasOwnProperty","tags","_tags","setAccessMode","read","unread","#serializeTopic","dst","getAccessMode","#serializeSubscription","fields","#serializeMessage","setDatabaseProvider","idbProvider","MAX_FORM_ELEMENTS","MAX_PREVIEW_ATTACHMENTS","MAX_PREVIEW_DATA_SIZE","JSON_MIME_TYPE","DRAFTY_MIME_TYPE","ALLOWED_ENT_FIELDS","segmenter","Intl","Segmenter","INLINE_STYLES","FMT_WEIGHT","ENTITY_TYPES","dataName","pack","test","re","slice","FORMAT_TAGS","AU","html_tag","md_tag","isVoid","BN","BR","CO","DL","EM","EX","FM","HD","HL","HT","IM","LN","MN","RW","QQ","ST","VC","VD","base64toObjectUrl","b64","contentType","bin","atob","buf","ArrayBuffer","Uint8Array","charCodeAt","URL","createObjectURL","Blob","type","base64toDataUrl","DECORATORS","props","href","id","act","ref","mime","Drafty","duration","size","tmpPreviewUrl","_tempPreview","previewUrl","downloadUrl","width","height","title","alt","state","preview","premime","poster","preref","txt","fmt","ent","init","plainText","content","lines","entityMap","entityIndex","blx","line","spans","entities","tag","spannify","block","sort","toSpanTree","chunks","chunkify","drafty","draftify","extractEntities","entity","tp","offset","len","segments","segment","ele","toGraphemeValues","stringToGraphemes","s","correctAt","correctLen","isEmptyObject","append","first","second","insertImage","imageDesc","ex","refurl","bits","filename","urlPromise","_processing","then","insertVideo","videoDesc","urls","insertAudio","audioDesc","videoCall","audioOnly","aonly","updateVideoCall","Object","assign","quote","header","body","appendLineBreak","mention","appendLink","linkData","appendImage","appendAudio","attachFile","attachmentDesc","wrapInto","style","wrapAsForm","insertButton","actionType","actionValue","refUrl","indexOf","appendButton","attachJSON","UNSAFE_toHTML","doc","tree","draftyToTree","htmlFormatter","values","join","treeBottomUp","format","original","formatter","shorten","light","shortenTree","lightEntity","treeToDrafty","forwardedContent","rmMention","node","parent","treeTopDown","lTrim","replyContent","convMNnQQnBR","startsWith","children","attachmentsToEnd","forwarding","toPlainText","isPlainText","toMarkdown","mdFormatter","def","isValid","txt_type","hasAttachments","attachments","hasEntities","styles","sanitizeEntities","copyEntData","getDownloadUrl","entData","isProcessing","getPreviewUrl","getEntitySize","getEntityMimeType","tagName","attrValue","getContentType","span","chunk","chld","re_start","re_end","exec","start_offset","lastIndexOf","end_offset","last","graphemes","spansToTree","flatten","child","addNode","n","att","subspans","inner","keymap","c","keys","newKey","transformer","stack","pop","tail","shortener","allow","lightCopy","trimStart","shift","match","extracted","el","startAt","plain","dc","obj","graphemeIndices","graphemeIndex","charIndex","indices","module","exports","Const","Topic","mergeToCache","TopicFnd","_contacts","callbacks","_processMetaSubs","subs","updateCount","getOwnPropertyNames","indexBy","onMetaSub","onSubsUpdated","publish","setMeta","getPrototypeOf","prototype","checkTagUniqueness","caller","subscribe","desc","getMeta","startMetaQuery","withTags","build","meta","t","contacts","cb","isUrlRelative","addURLParam","relUrl","window","location","origin","searchParams","substring","LargeFileHelper","tinode","_tinode","_version","_apiKey","_authToken","getAuthToken","xhr","uploadWithBaseUrl","baseUrl","avatarFor","onProgress","onSuccess","onFailure","base","endsWith","instance","setRequestHeader","token","toResolve","toReject","upload","onprogress","e","lengthComputable","loaded","total","onload","response","statusText","onabort","form","FormData","set","getNextUniqueId","_secure","_host","download","relativeUrl","mimetype","responseType","link","document","createElement","display","setAttribute","appendChild","click","removeChild","revokeObjectURL","reader","FileReader","readAsText","cancel","setNetworkProvider","mergeObj","TopicMe","onContactUpdate","_processMetaDesc","turnOff","_db","_updateCachedUser","_myUID","cont","online","seen","when","Date","_refreshContact","onMetaDesc","cacheRemTopic","recv","getTopic","_new","isP2PTopicName","_cachePutUser","_noForwarding","_processMetaCreds","creds","cr","_credentials","findIndex","meth","done","resp","onCredsUpdated","_routePres","pres","what","_resetSub","withDesc","cacheGetTopic","_updateReceived","withLaterOneSub","tgt","dacs","touched","ua","_attached","withOneSub","dummy","onPres","delCredential","method","isCommType","getContact","isArchived","private","arch","getCredentials","listToRanges","normalizeRanges","MetaGetBuilder","get_desc_ims","#get_desc_ims","updated","get_subs_ims","#get_subs_ims","isP2PType","_lastSubsUpdate","withData","withLaterData","_maxSeq","withDataRanges","withDataList","list","withEarlierData","_minSeq","ims","withLaterDesc","withSub","userOrTopic","opts","getType","withLaterSub","withCred","withAux","withDel","withLaterDel","_maxDel","extract","normalizeArray","created","trusted","_users","_queuedSeqId","_noEarlierMsgs","_recvNotificationTimer","_aux","_messageVersions","_messages","_delayedLeaveTimer","onData","onMeta","onInfo","onTagsUpdated","onAuxUpdated","onDeleteTopic","onAllMessagesReceived","topicType","types","isMeTopicName","isSelfTopicName","isGroupTopicName","isCommTopicName","isNewGroupTopicName","isChannelTopicName","isReplacementMsg","#isReplacementMsg","head","replace","isSubscribed","getParams","setParams","_cacheDelSelf","_cachePutSelf","ts","me","getMeTopic","createMessage","noEcho","publishMessage","_sending","_failed","swapMessageId","_maybeUpdateMessageVersionsCache","_routeData","publishDraft","_getQueuedSeqId","getCurrentUserID","noecho","_cancelled","_fatal","leave","unsub","_gone","leaveDelayed","delay","getMessagesPage","gaps","newer","_loadMessages","msgHasMoreMessages","getPinnedMessages","pins","aux","remains","_processMetaTags","cred","_processMetaAux","subscriber","am","invite","archive","pinMessage","pin","pinned","changed","delMessages","hard","tosend","del","rec","flushMessageRange","flushMessage","delMessagesAll","hardDel","_all","delMessagesList","delMessagesEdits","messageVersions","delTopic","delSubscription","note","_updateMyReadRecv","noteRecv","noteRead","noteKeyPress","noteRecording","payload","oldVal","doUpdate","userDesc","_cacheGetUser","p2pPeerDesc","subscribers","alias","origSeq","versions","messages","sinceId","beforeId","unused1","unused2","latest","latestMsgVersion","_origTs","_origSeq","findMessage","latestMessage","maxMsgSeq","minMsgSeq","maxClearId","messageCount","queuedMessages","msgReceiptCount","msgReadCount","msgRecvCount","maxSeq","gap","prev","p","expected","isNewMessage","seqId","fromId","untilId","newSeqId","numMessages","cancelSend","msgStatus","getDefaultAccess","defacs","isMeType","isSelfType","isChannelType","isGroupType","isMe","targetSeq","parseInt","targetMsg","outgoing","webrtc","incoming","vc","_routeInfo","_routeMeta","_processDelMessages","delseq","isTopicCached","info","_allMessagesReceived","cached","date","isNaN","isValidDate","d","getTime","rfc3339DateString","pad","sp","repeat","millis","getUTCMilliseconds","getUTCFullYear","getUTCMonth","getUTCDate","getUTCHours","getUTCMinutes","getUTCSeconds","ignore","prop","cache","newval","simplify","out","trim","toLowerCase","item","pos","ary","r1","r2","reduce","clipOutRange","clip","clipInRange","DBCache","WebSocket","XMLHttpRequest","IndexedDBProvider","indexedDB","initForNonBrowserApp","chars","btoa","global","input","output","charCode","bc","bs","String","fromCharCode","detectTransport","b64EncodeUnicode","encodeURIComponent","toSolidBytes","p1","jsonBuildHelper","jsonLoggerHelper","getBrowserInfo","product","reactnative","priority","tmp","substr","tokens","m2","v","minor","Tinode","_appName","_browser","_platform","_hwos","_humanLanguage","_loggingEnabled","_trimLongStrings","_authenticated","_login","_inPacketCount","_messageId","floor","_serverInfo","_deviceToken","_pendingPromises","_expirePromises","_connection","_persist","_cache","onComplete","appName","platform","navigator","userAgent","language","dispatchMessage","connectionOpen","disconnected","promise","persist","cacheGet","attachCacheToTopic","cachePut","all","args","dateString","console","makePromise","#makePromise","execPromise","#execPromise","onOK","errorText","#send","stringify","#dispatchMessage","onRawMessage","onNetworkProbe","onCtrlMessage","onMetaMessage","onDataMessage","onPresMessage","onInfoMessage","#connectionOpen","setInterval","expires","hello","#disconnected","clearInterval","cacheMap","getUserAgent","#getUserAgent","initPacket","#initPacket","#cachePut","#cacheGet","cacheDel","#cacheDel","#cacheMap","func","#attachCacheToTopic","_cacheDelUser","loginSuccessful","#loginSuccessful","onLogin","credential","getVersion","getLibrary","isNullValue","isServerAssignedSeq","isValidTagValue","ALIAS_REGEX","tagSplit","splitAt","prefix","setUniqueTag","uniqueTag","clearTagPrefix","tagByPrefix","clearStorage","initStorage","networkProbe","isAuthenticated","authorizeURL","parsed","account","scheme","secret","login","acc","tmpscheme","tmpsecret","extra","createAccount","createAccountBasic","username","password","updateAccountBasic","onConnect","setDeviceToken","dt","sent","loginBasic","uname","loginToken","requestResetAuthSecret","now","setAuthToken","dft","oobNotification","xfrom","finally","modeGiven","modeWant","delCurrentUser","newGroupTopicName","isChan","getFndTopic","getLargeFileHelper","getCurrentLogin","getServerInfo","report","getServerParam","defaultValue","enableLogging","enabled","trimLongStrings","setHumanLanguage","hl","isTopicOnline","getTopicAccessMode","wantAkn","onWebsocketOpen","MAX_MESSAGE_SIZE","MAX_SUBSCRIBER_COUNT","MIN_TAG_LENGTH","MAX_TAG_LENGTH","MAX_TAG_COUNT","MAX_FILE_UPLOAD_SIZE","REQ_CRED_VALIDATORS","MSG_DELETE_AGE","URI_TOPIC_ID_PREFIX"],"sourceRoot":""}
\ No newline at end of file
+{"version":3,"file":"tinode.dev.js","mappings":"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","sources":["webpack://tinode/webpack/universalModuleDefinition","webpack://tinode/./src/access-mode.js","webpack://tinode/./src/cbuffer.js","webpack://tinode/./src/comm-error.js","webpack://tinode/./src/config.js","webpack://tinode/./src/connection.js","webpack://tinode/./src/db.js","webpack://tinode/./src/drafty.js","webpack://tinode/./src/fnd-topic.js","webpack://tinode/./src/large-file.js","webpack://tinode/./src/me-topic.js","webpack://tinode/./src/meta-builder.js","webpack://tinode/./src/topic.js","webpack://tinode/./src/utils.js","webpack://tinode/./version.js","webpack://tinode/webpack/bootstrap","webpack://tinode/webpack/runtime/compat get default export","webpack://tinode/webpack/runtime/define property getters","webpack://tinode/webpack/runtime/global","webpack://tinode/webpack/runtime/hasOwnProperty shorthand","webpack://tinode/webpack/runtime/make namespace object","webpack://tinode/./src/tinode.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"tinode\"] = factory();\n\telse\n\t\troot[\"tinode\"] = factory();\n})(this, () => {\nreturn ","/**\n * @file Access control model.\n *\n * @copyright 2015-2022 Tinode LLC.\n */\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\n/**\n * Helper class for handling access mode.\n *\n * @class AccessMode\n * @memberof Tinode\n *\n * @param {AccessMode|Object=} acs - AccessMode to copy or access mode object received from the server.\n */\nexport default class AccessMode {\n constructor(acs) {\n if (acs) {\n this.given = typeof acs.given == 'number' ? acs.given : AccessMode.decode(acs.given);\n this.want = typeof acs.want == 'number' ? acs.want : AccessMode.decode(acs.want);\n this.mode = acs.mode ? (typeof acs.mode == 'number' ? acs.mode : AccessMode.decode(acs.mode)) :\n (this.given & this.want);\n }\n }\n\n static #checkFlag(val, side, flag) {\n side = side || 'mode';\n if (['given', 'want', 'mode'].includes(side)) {\n return ((val[side] & flag) != 0);\n }\n throw new Error(`Invalid AccessMode component '${side}'`);\n }\n /**\n * Parse string into an access mode value.\n * @memberof Tinode.AccessMode\n * @static\n *\n * @param {string | Number} mode - either a String representation of the access mode to parse or a set of bits to assign.\n * @returns {number} - Access mode as a numeric value.\n */\n static decode(str) {\n if (!str) {\n return null;\n } else if (typeof str == 'number') {\n return str & AccessMode._BITMASK;\n } else if (str === 'N' || str === 'n') {\n return AccessMode._NONE;\n }\n\n const bitmask = {\n 'J': AccessMode._JOIN,\n 'R': AccessMode._READ,\n 'W': AccessMode._WRITE,\n 'P': AccessMode._PRES,\n 'A': AccessMode._APPROVE,\n 'S': AccessMode._SHARE,\n 'D': AccessMode._DELETE,\n 'O': AccessMode._OWNER\n };\n\n let m0 = AccessMode._NONE;\n\n for (let i = 0; i < str.length; i++) {\n const bit = bitmask[str.charAt(i).toUpperCase()];\n if (!bit) {\n // Unrecognized bit, skip.\n continue;\n }\n m0 |= bit;\n }\n return m0;\n }\n /**\n * Convert numeric representation of the access mode into a string.\n *\n * @memberof Tinode.AccessMode\n * @static\n *\n * @param {number} val - access mode value to convert to a string.\n * @returns {string} - Access mode as a string.\n */\n static encode(val) {\n if (val === null || val === AccessMode._INVALID) {\n return null;\n } else if (val === AccessMode._NONE) {\n return 'N';\n }\n\n const bitmask = ['J', 'R', 'W', 'P', 'A', 'S', 'D', 'O'];\n let res = '';\n for (let i = 0; i < bitmask.length; i++) {\n if ((val & (1 << i)) != 0) {\n res = res + bitmask[i];\n }\n }\n return res;\n }\n /**\n * Update numeric representation of access mode with the new value. The value\n * is one of the following:\n * - a string starting with '+' or '-' then the bits to add or remove, e.g. '+R-W' or '-PS'.\n * - a new value of access mode\n *\n * @memberof Tinode.AccessMode\n * @static\n *\n * @param {number} val - access mode value to update.\n * @param {string} upd - update to apply to val.\n * @returns {number} - updated access mode.\n */\n static update(val, upd) {\n if (!upd || typeof upd != 'string') {\n return val;\n }\n\n let action = upd.charAt(0);\n if (action == '+' || action == '-') {\n let val0 = val;\n // Split delta-string like '+ABC-DEF+Z' into an array of parts including + and -.\n const parts = upd.split(/([-+])/);\n // Starting iteration from 1 because String.split() creates an array with the first empty element.\n // Iterating by 2 because we parse pairs +/- then data.\n for (let i = 1; i < parts.length - 1; i += 2) {\n action = parts[i];\n const m0 = AccessMode.decode(parts[i + 1]);\n if (m0 == AccessMode._INVALID) {\n return val;\n }\n if (m0 == null) {\n continue;\n }\n if (action === '+') {\n val0 |= m0;\n } else if (action === '-') {\n val0 &= ~m0;\n }\n }\n val = val0;\n } else {\n // The string is an explicit new value 'ABC' rather than delta.\n const val0 = AccessMode.decode(upd);\n if (val0 != AccessMode._INVALID) {\n val = val0;\n }\n }\n\n return val;\n }\n /**\n * Bits present in a1 but missing in a2.\n *\n * @static\n * @memberof Tinode\n *\n * @param {number | string} a1 - access mode to subtract from.\n * @param {number | string} a2 - access mode to subtract.\n * @returns {number} access mode with bits present in a1 but missing in a2.\n */\n static diff(a1, a2) {\n a1 = AccessMode.decode(a1);\n a2 = AccessMode.decode(a2);\n\n if (a1 == AccessMode._INVALID || a2 == AccessMode._INVALID) {\n return AccessMode._INVALID;\n }\n return a1 & ~a2;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Custom formatter\n */\n toString() {\n return '{\"mode\": \"' + AccessMode.encode(this.mode) +\n '\", \"given\": \"' + AccessMode.encode(this.given) +\n '\", \"want\": \"' + AccessMode.encode(this.want) + '\"}';\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Converts numeric values to strings.\n */\n jsonHelper() {\n return {\n mode: AccessMode.encode(this.mode),\n given: AccessMode.encode(this.given),\n want: AccessMode.encode(this.want)\n };\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Assign value to 'mode'.\n * @memberof Tinode.AccessMode\n *\n * @param {string | Number} m - either a string representation of the access mode or a set of bits.\n * @returns {AccessMode} - this AccessMode.\n */\n setMode(m) {\n this.mode = AccessMode.decode(m);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update mode value.\n * @memberof Tinode.AccessMode\n *\n * @param {string} u - string representation of the changes to apply to access mode.\n * @returns {AccessMode} - this AccessMode.\n */\n updateMode(u) {\n this.mode = AccessMode.update(this.mode, u);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get mode value as a string.\n * @memberof Tinode.AccessMode\n *\n * @returns {string} - mode value.\n */\n getMode() {\n return AccessMode.encode(this.mode);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Assign given value.\n * @memberof Tinode.AccessMode\n *\n * @param {string | Number} g - either a string representation of the access mode or a set of bits.\n * @returns {AccessMode} - this AccessMode.\n */\n setGiven(g) {\n this.given = AccessMode.decode(g);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update 'given' value.\n * @memberof Tinode.AccessMode\n *\n * @param {string} u - string representation of the changes to apply to access mode.\n * @returns {AccessMode} - this AccessMode.\n */\n updateGiven(u) {\n this.given = AccessMode.update(this.given, u);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get 'given' value as a string.\n * @memberof Tinode.AccessMode\n *\n * @returns {string} - given value.\n */\n getGiven() {\n return AccessMode.encode(this.given);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Assign 'want' value.\n * @memberof Tinode.AccessMode\n *\n * @param {string | Number} w - either a string representation of the access mode or a set of bits.\n * @returns {AccessMode} - this AccessMode.\n */\n setWant(w) {\n this.want = AccessMode.decode(w);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update 'want' value.\n * @memberof Tinode.AccessMode\n *\n * @param {string} u - string representation of the changes to apply to access mode.\n * @returns {AccessMode} - this AccessMode.\n */\n updateWant(u) {\n this.want = AccessMode.update(this.want, u);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get 'want' value as a string.\n * @memberof Tinode.AccessMode\n *\n * @returns {string} - want value.\n */\n getWant() {\n return AccessMode.encode(this.want);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get permissions present in 'want' but missing in 'given'.\n * Inverse of {@link Tinode.AccessMode#getExcessive}\n *\n * @memberof Tinode.AccessMode\n *\n * @returns {string} permissions present in want but missing in given .\n */\n getMissing() {\n return AccessMode.encode(this.want & ~this.given);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get permissions present in 'given' but missing in 'want'.\n * Inverse of {@link Tinode.AccessMode#getMissing}\n * @memberof Tinode.AccessMode\n *\n * @returns {string} permissions present in given but missing in want .\n */\n getExcessive() {\n return AccessMode.encode(this.given & ~this.want);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update 'want', 'give', and 'mode' values.\n * @memberof Tinode.AccessMode\n *\n * @param {AccessMode} val - new access mode value.\n * @returns {AccessMode} - this AccessMode.\n */\n updateAll(val) {\n if (val) {\n this.updateGiven(val.given);\n this.updateWant(val.want);\n this.mode = this.given & this.want;\n }\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Owner (O) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isOwner(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._OWNER);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Presence (P) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isPresencer(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._PRES);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Presence (P) flag is NOT set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isMuted(side) {\n return !this.isPresencer(side);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Join (J) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isJoiner(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._JOIN);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Reader (R) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isReader(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._READ);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Writer (W) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isWriter(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._WRITE);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Approver (A) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isApprover(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._APPROVE);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if either one of Owner (O) or Approver (A) flags is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isAdmin(side) {\n return this.isOwner(side) || this.isApprover(side);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if either one of Owner (O), Approver (A), or Sharer (S) flags is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isSharer(side) {\n return this.isAdmin(side) || AccessMode.#checkFlag(this, side, AccessMode._SHARE);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Deleter (D) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isDeleter(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._DELETE);\n }\n}\n\nAccessMode._NONE = 0x00;\nAccessMode._JOIN = 0x01;\nAccessMode._READ = 0x02;\nAccessMode._WRITE = 0x04;\nAccessMode._PRES = 0x08;\nAccessMode._APPROVE = 0x10;\nAccessMode._SHARE = 0x20;\nAccessMode._DELETE = 0x40;\nAccessMode._OWNER = 0x80;\n\nAccessMode._BITMASK = AccessMode._JOIN | AccessMode._READ | AccessMode._WRITE | AccessMode._PRES |\n AccessMode._APPROVE | AccessMode._SHARE | AccessMode._DELETE | AccessMode._OWNER;\nAccessMode._INVALID = 0x100000;\n","/**\n * @file In-memory sorted cache of objects.\n *\n * @copyright 2015-2025 Tinode LLC.\n */\n'use strict';\n\n/**\n * In-memory sorted cache of objects.\n *\n * @class CBuffer\n * @memberof Tinode\n * @protected\n *\n * @param {function} compare custom comparator of objects. Takes two parameters a and b;\n * returns -1 if a < b, 0 if a == b, 1 otherwise.\n * @param {boolean} unique enforce element uniqueness: when true replace existing element with a new\n * one on conflict; when false keep both elements.\n */\nexport default class CBuffer {\n #comparator = undefined;\n #unique = false;\n buffer = [];\n\n constructor(compare_, unique_) {\n this.#comparator = compare_ || ((a, b) => {\n return a === b ? 0 : a < b ? -1 : 1;\n });\n this.#unique = unique_;\n }\n\n #findNearest(elem, arr, exact) {\n let start = 0;\n let end = arr.length - 1;\n let pivot = 0;\n let diff = 0;\n let found = false;\n\n while (start <= end) {\n pivot = (start + end) / 2 | 0;\n diff = this.#comparator(arr[pivot], elem);\n if (diff < 0) {\n start = pivot + 1;\n } else if (diff > 0) {\n end = pivot - 1;\n } else {\n found = true;\n break;\n }\n }\n if (found) {\n return {\n idx: pivot,\n exact: true\n };\n }\n if (exact) {\n return {\n idx: -1\n };\n }\n // Not exact - insertion point\n return {\n idx: diff < 0 ? pivot + 1 : pivot\n };\n }\n\n // Insert element into a sorted array.\n #insertSorted(elem, arr) {\n const found = this.#findNearest(elem, arr, false);\n const count = (found.exact && this.#unique) ? 1 : 0;\n arr.splice(found.idx, count, elem);\n return arr;\n }\n\n /**\n * Get an element at the given position.\n * @memberof Tinode.CBuffer#\n * @param {number} at - Position to fetch from.\n * @returns {Object} Element at the given position or undefined.\n */\n getAt(at) {\n return this.buffer[at];\n }\n\n /**\n * Convenience method for getting the last element from the buffer.\n * @memberof Tinode.CBuffer#\n * @param {function} filter - optional filter to apply to elements. If filter is provided, the search\n * for the last element starts from the end of the buffer and goes backwards until the filter returns true.\n * @returns {Object} The last element in the buffer or undefined if buffer is empty.\n */\n getLast(filter) {\n return filter ?\n this.buffer.findLast(filter) :\n this.buffer[this.buffer.length - 1];\n }\n\n /**\n * Insert new element(s) to the buffer at the correct position according to the sort method.\n * Variadic: takes one or more arguments. If an array is passed as a single argument, its\n * elements are inserted individually.\n * @memberof Tinode.CBuffer#\n *\n * @param {...Object|Array} - One or more objects to insert.\n */\n put() {\n let insert;\n // inspect arguments: if array, insert its elements, if one or more non-array arguments, insert them one by one\n if (arguments.length == 1 && Array.isArray(arguments[0])) {\n insert = arguments[0];\n } else {\n insert = arguments;\n }\n for (let idx in insert) {\n this.#insertSorted(insert[idx], this.buffer);\n }\n }\n\n /**\n * Remove element at the given position.\n * @memberof Tinode.CBuffer#\n * @param {number} at - Position to delete at.\n * @returns {Object} Element at the given position or undefined.\n */\n delAt(at) {\n at |= 0;\n let r = this.buffer.splice(at, 1);\n if (r && r.length > 0) {\n return r[0];\n }\n return undefined;\n }\n\n /**\n * Remove elements between two positions.\n * @memberof Tinode.CBuffer#\n * @param {number} since - Position to delete from (inclusive).\n * @param {number} before - Position to delete to (exclusive).\n *\n * @returns {Array} array of removed elements (could be zero length).\n */\n delRange(since, before) {\n return this.buffer.splice(since, before - since);\n }\n\n /**\n * Return the number of elements the buffer holds.\n * @memberof Tinode.CBuffer#\n * @return {number} Number of elements in the buffer.\n */\n length() {\n return this.buffer.length;\n }\n\n /**\n * Reset the buffer discarding all elements\n * @memberof Tinode.CBuffer#\n */\n reset() {\n this.buffer = [];\n }\n\n /**\n * Callback for iterating contents of buffer. See {@link Tinode.CBuffer#forEach}.\n * @callback ForEachCallbackType\n * @memberof Tinode.CBuffer#\n * @param {Object} elem - Current element of the buffer.\n * @param {Object} prev - Previous element of the buffer.\n * @param {Object} next - Next element of the buffer.\n * @param {number} index - Index of the current element.\n */\n\n /**\n * Apply given callback to all elements of the buffer.\n * @memberof Tinode.CBuffer#\n *\n * @param {Tinode.ForEachCallbackType} callback - Function to call for each element.\n * @param {number} startIdx - Optional index to start iterating from (inclusive), default: 0.\n * @param {number} beforeIdx - Optional index to stop iterating before (exclusive), default: length of the buffer.\n * @param {Object} context - calling context (i.e. value of this in callback)\n */\n forEach(callback, startIdx, beforeIdx, context) {\n startIdx = Math.max(0, startIdx | 0);\n beforeIdx = Math.min(beforeIdx || this.buffer.length, this.buffer.length);\n\n for (let i = startIdx; i < beforeIdx; i++) {\n callback.call(context, this.buffer[i],\n (i > startIdx ? this.buffer[i - 1] : undefined),\n (i < beforeIdx - 1 ? this.buffer[i + 1] : undefined), i);\n }\n }\n\n /**\n * Find element in buffer using buffer's comparison function.\n * @memberof Tinode.CBuffer#\n *\n * @param {Object} elem - element to find.\n * @param {boolean=} nearest - when true and exact match is not found, return the nearest element (insertion point).\n * @returns {number} index of the element in the buffer or -1.\n */\n find(elem, nearest) {\n const {\n idx\n } = this.#findNearest(elem, this.buffer, !nearest);\n return idx;\n }\n\n /**\n * Callback for filtering the buffer. See {@link Tinode.CBuffer#filter}.\n * @callback FilterCallbackType\n * @memberof Tinode.CBuffer#\n * @param {Object} elem - Current element of the buffer.\n * @param {number} index - Index of the current element.\n * @returns {boolen} true to keep the element, false to remove.\n */\n\n /**\n * Remove all elements that do not pass the test implemented by the provided callback function.\n * @memberof Tinode.CBuffer#\n *\n * @param {Tinode.FilterCallbackType} callback - Function to call for each element.\n * @param {Object} context - calling context (i.e. value of this in the callback)\n */\n filter(callback, context) {\n let count = 0;\n for (let i = 0; i < this.buffer.length; i++) {\n if (callback.call(context, this.buffer[i], i)) {\n this.buffer[count] = this.buffer[i];\n count++;\n }\n }\n\n this.buffer.splice(count);\n }\n\n /**\n * Check if buffer is empty.\n * @returns {boolean} true if the buffer is empty, false otherwise.\n */\n isEmpty() {\n return this.buffer.length == 0;\n }\n}\n","/**\n * @file Throwable error with numeric error code.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nexport default class CommError extends Error {\n constructor(message, code) {\n super(`${message} (${code})`);\n this.name = 'CommError';\n this.code = code;\n }\n}\n","/**\n * @file Global constants and configuration parameters.\n *\n * @copyright 2015-2025 Tinode LLC\n */\n'use strict';\n\nimport {\n PACKAGE_VERSION\n} from '../version.js';\n\n// Global constants\nexport const PROTOCOL_VERSION = '0'; // Major component of the version, e.g. '0' in '0.17.1'.\nexport const VERSION = PACKAGE_VERSION || '0.24';\nexport const LIBRARY = 'tinodejs/' + VERSION;\n\n// Topic name prefixes.\nexport const TOPIC_NEW = 'new';\nexport const TOPIC_NEW_CHAN = 'nch';\nexport const TOPIC_ME = 'me';\nexport const TOPIC_FND = 'fnd';\nexport const TOPIC_SYS = 'sys';\nexport const TOPIC_SLF = 'slf';\nexport const TOPIC_CHAN = 'chn';\nexport const TOPIC_GRP = 'grp';\nexport const TOPIC_P2P = 'p2p';\nexport const USER_NEW = 'new';\n\n// Starting value of a locally-generated seqId used for pending messages.\nexport const LOCAL_SEQID = 0xFFFFFFF;\n\n// Status codes.\nexport const MESSAGE_STATUS_NONE = 0; // Status not assigned.\nexport const MESSAGE_STATUS_QUEUED = 10; // Local ID assigned, in progress to be sent.\nexport const MESSAGE_STATUS_SENDING = 20; // Transmission started.\nexport const MESSAGE_STATUS_FAILED = 30; // At least one attempt was made to send the message.\nexport const MESSAGE_STATUS_FATAL = 40; // Message sending failed and it should not be retried.\nexport const MESSAGE_STATUS_SENT = 50; // Delivered to the server.\nexport const MESSAGE_STATUS_RECEIVED = 60; // Received by the client.\nexport const MESSAGE_STATUS_READ = 70; // Read by the user.\nexport const MESSAGE_STATUS_TO_ME = 80; // The message is received from another user.\n\n// Reject unresolved futures after this many milliseconds.\nexport const EXPIRE_PROMISES_TIMEOUT = 5_000;\n// Periodicity of garbage collection of unresolved futures.\nexport const EXPIRE_PROMISES_PERIOD = 1_000;\n\n// Delay before acknowledging that a message was recived.\nexport const RECV_TIMEOUT = 100;\n\n// Default number of messages to pull into memory from persistent cache.\nexport const DEFAULT_MESSAGES_PAGE = 24;\n\n// Unicode DEL character indicating data was deleted.\nexport const DEL_CHAR = '\\u2421';\n\n// Maximum number of pinnned messages;\nexport const MAX_PINNED_COUNT = 5;\n\n// Tag prefixes for alias, email, phone.\nexport const TAG_ALIAS = 'alias:';\nexport const TAG_EMAIL = 'email:';\nexport const TAG_PHONE = 'tel:';\n","/**\n * @file Abstraction layer for websocket and long polling connections.\n *\n * @copyright 2015-2022 Tinode LLC.\n */\n'use strict';\n\nimport CommError from './comm-error.js';\nimport {\n jsonParseHelper\n} from './utils.js';\n\nlet WebSocketProvider;\nlet XHRProvider;\n\n// Error code to return in case of a network problem.\nconst NETWORK_ERROR = 503;\nconst NETWORK_ERROR_TEXT = \"Connection failed\";\n\n// Error code to return when user disconnected from server.\nconst NETWORK_USER = 418;\nconst NETWORK_USER_TEXT = \"Disconnected by client\";\n\n// Settings for exponential backoff\nconst _BOFF_BASE = 2000; // 2000 milliseconds, minimum delay between reconnects\nconst _BOFF_MAX_ITER = 10; // Maximum delay between reconnects 2^10 * 2000 ~ 34 minutes\nconst _BOFF_JITTER = 0.3; // Add random delay\n\n// Helper function for creating an endpoint URL.\nfunction makeBaseUrl(host, protocol, version, apiKey) {\n let url = null;\n\n if (['http', 'https', 'ws', 'wss'].includes(protocol)) {\n url = `${protocol}://${host}`;\n if (url.charAt(url.length - 1) !== '/') {\n url += '/';\n }\n url += 'v' + version + '/channels';\n if (['http', 'https'].includes(protocol)) {\n // Long polling endpoint ends with \"lp\", i.e.\n // '/v0/channels/lp' vs just '/v0/channels' for ws\n url += '/lp';\n }\n url += '?apikey=' + apiKey;\n }\n return url;\n}\n\n/**\n * An abstraction for a websocket or a long polling connection.\n *\n * @class Connection\n * @memberof Tinode\n\n * @param {Object} config - configuration parameters.\n * @param {string} config.host - Host name and optional port number to connect to.\n * @param {string} config.apiKey - API key generated by keygen.\n * @param {string} config.transport - Network transport to use, either \"ws\"/\"wss\" for websocket or\n * lp for long polling.\n * @param {boolean} config.secure - Use Secure WebSocket if true.\n * @param {string} version_ - Major value of the protocol version, e.g. '0' in '0.17.1'.\n * @param {boolean} autoreconnect_ - If connection is lost, try to reconnect automatically.\n */\nexport default class Connection {\n // Logger, does nothing by default.\n static #log = _ => {};\n\n #boffTimer = null;\n #boffIteration = 0;\n #boffClosed = false; // Indicator if the socket was manually closed - don't autoreconnect if true.\n\n // Websocket.\n #socket = null;\n\n host;\n secure;\n apiKey;\n\n version;\n autoreconnect;\n\n initialized;\n\n // (config.host, config.apiKey, config.transport, config.secure), PROTOCOL_VERSION, true\n constructor(config, version_, autoreconnect_) {\n this.host = config.host;\n this.secure = config.secure;\n this.apiKey = config.apiKey;\n\n this.version = version_;\n this.autoreconnect = autoreconnect_;\n\n if (config.transport === 'lp') {\n // explicit request to use long polling\n this.#init_lp();\n this.initialized = 'lp';\n } else if (config.transport === 'ws') {\n // explicit request to use web socket\n // if websockets are not available, horrible things will happen\n this.#init_ws();\n this.initialized = 'ws';\n }\n\n if (!this.initialized) {\n // Invalid or undefined network transport.\n Connection.#log(\"Unknown or invalid network transport. Running under Node? Call 'Tinode.setNetworkProviders()'.\");\n throw new Error(\"Unknown or invalid network transport. Running under Node? Call 'Tinode.setNetworkProviders()'.\");\n }\n }\n\n /**\n * To use Connection in a non browser context, supply WebSocket and XMLHttpRequest providers.\n * @static\n * @memberof Connection\n * @param wsProvider WebSocket provider, e.g. for nodeJS , require('ws').\n * @param xhrProvider XMLHttpRequest provider, e.g. for node require('xhr').\n */\n static setNetworkProviders(wsProvider, xhrProvider) {\n WebSocketProvider = wsProvider;\n XHRProvider = xhrProvider;\n }\n\n /**\n * Assign a non-default logger.\n * @static\n * @memberof Connection\n * @param {function} l variadic logging function.\n */\n static set logger(l) {\n Connection.#log = l;\n }\n\n /**\n * Initiate a new connection\n * @memberof Tinode.Connection#\n * @param {string} host_ Host name to connect to; if null the old host name will be used.\n * @param {boolean} force Force new connection even if one already exists.\n * @return {Promise} Promise resolved/rejected when the connection call completes, resolution is called without\n * parameters, rejection passes the {Error} as parameter.\n */\n connect(host_, force) {\n return Promise.reject(null);\n }\n\n /**\n * Try to restore a network connection, also reset backoff.\n * @memberof Tinode.Connection#\n *\n * @param {boolean} force - reconnect even if there is a live connection already.\n */\n reconnect(force) {}\n\n /**\n * Terminate the network connection\n * @memberof Tinode.Connection#\n */\n disconnect() {}\n\n /**\n * Send a string to the server.\n * @memberof Tinode.Connection#\n *\n * @param {string} msg - String to send.\n * @throws Throws an exception if the underlying connection is not live.\n */\n sendText(msg) {}\n\n /**\n * Check if connection is alive.\n * @memberof Tinode.Connection#\n * @returns {boolean} true if connection is live, false otherwise.\n */\n isConnected() {\n return false;\n }\n\n /**\n * Get the name of the current network transport.\n * @memberof Tinode.Connection#\n * @returns {string} name of the transport such as \"ws\" or \"lp\".\n */\n transport() {\n return this.initialized;\n }\n\n /**\n * Send network probe to check if connection is indeed live.\n * @memberof Tinode.Connection#\n */\n probe() {\n this.sendText('1');\n }\n\n /**\n * Reset autoreconnect counter to zero.\n * @memberof Tinode.Connection#\n */\n backoffReset() {\n this.#boffReset();\n }\n\n // Backoff implementation - reconnect after a timeout.\n #boffReconnect() {\n // Clear timer\n clearTimeout(this.#boffTimer);\n // Calculate when to fire the reconnect attempt\n const timeout = _BOFF_BASE * (Math.pow(2, this.#boffIteration) * (1.0 + _BOFF_JITTER * Math.random()));\n // Update iteration counter for future use\n this.#boffIteration = (this.#boffIteration >= _BOFF_MAX_ITER ? this.#boffIteration : this.#boffIteration + 1);\n if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(timeout);\n }\n\n this.#boffTimer = setTimeout(_ => {\n Connection.#log(`Reconnecting, iter=${this.#boffIteration}, timeout=${timeout}`);\n // Maybe the socket was closed while we waited for the timer?\n if (!this.#boffClosed) {\n const prom = this.connect();\n if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(0, prom);\n } else {\n // Suppress error if it's not used.\n prom.catch(_ => {\n /* do nothing */\n });\n }\n } else if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(-1);\n }\n }, timeout);\n }\n\n // Terminate auto-reconnect process.\n #boffStop() {\n clearTimeout(this.#boffTimer);\n this.#boffTimer = null;\n }\n\n // Reset auto-reconnect iteration counter.\n #boffReset() {\n this.#boffIteration = 0;\n }\n\n // Initialization for long polling.\n #init_lp() {\n const XDR_UNSENT = 0; // Client has been created. open() not called yet.\n const XDR_OPENED = 1; // open() has been called.\n const XDR_HEADERS_RECEIVED = 2; // send() has been called, and headers and status are available.\n const XDR_LOADING = 3; // Downloading; responseText holds partial data.\n const XDR_DONE = 4; // The operation is complete.\n\n // Fully composed endpoint URL, with API key & SID\n let _lpURL = null;\n\n let _poller = null;\n let _sender = null;\n\n let lp_sender = (url_) => {\n const sender = new XHRProvider();\n sender.onreadystatechange = (evt) => {\n if (sender.readyState == XDR_DONE && sender.status >= 400) {\n // Some sort of error response\n throw new CommError(\"LP sender failed\", sender.status);\n }\n };\n\n sender.open('POST', url_, true);\n return sender;\n }\n\n let lp_poller = (url_, resolve, reject) => {\n let poller = new XHRProvider();\n let promiseCompleted = false;\n\n poller.onreadystatechange = evt => {\n if (poller.readyState == XDR_DONE) {\n if (poller.status == 201) { // 201 == HTTP.Created, get SID\n let pkt = JSON.parse(poller.responseText, jsonParseHelper);\n _lpURL = url_ + '&sid=' + pkt.ctrl.params.sid;\n poller = lp_poller(_lpURL);\n poller.send(null);\n if (this.onOpen) {\n this.onOpen();\n }\n\n if (resolve) {\n promiseCompleted = true;\n resolve();\n }\n\n if (this.autoreconnect) {\n this.#boffStop();\n }\n } else if (poller.status > 0 && poller.status < 400) { // 0 = network error; 400 = HTTP.BadRequest\n if (this.onMessage) {\n this.onMessage(poller.responseText);\n }\n poller = lp_poller(_lpURL);\n poller.send(null);\n } else {\n // Don't throw an error here, gracefully handle server errors\n if (reject && !promiseCompleted) {\n promiseCompleted = true;\n reject(poller.responseText);\n }\n if (this.onMessage && poller.responseText) {\n this.onMessage(poller.responseText);\n }\n if (this.onDisconnect) {\n const code = poller.status || (this.#boffClosed ? NETWORK_USER : NETWORK_ERROR);\n const text = poller.responseText || (this.#boffClosed ? NETWORK_USER_TEXT : NETWORK_ERROR_TEXT);\n this.onDisconnect(new CommError(text, code), code);\n }\n\n // Polling has stopped. Indicate it by setting poller to null.\n poller = null;\n if (!this.#boffClosed && this.autoreconnect) {\n this.#boffReconnect();\n }\n }\n }\n };\n // Using POST to avoid caching response by service worker.\n poller.open('POST', url_, true);\n return poller;\n }\n\n this.connect = (host_, force) => {\n this.#boffClosed = false;\n\n if (_poller) {\n if (!force) {\n return Promise.resolve();\n }\n _poller.onreadystatechange = undefined;\n _poller.abort();\n _poller = null;\n }\n\n if (host_) {\n this.host = host_;\n }\n\n return new Promise((resolve, reject) => {\n const url = makeBaseUrl(this.host, this.secure ? 'https' : 'http', this.version, this.apiKey);\n Connection.#log(\"LP connecting to:\", url);\n _poller = lp_poller(url, resolve, reject);\n _poller.send(null);\n }).catch(err => {\n Connection.#log(\"LP connection failed:\", err);\n });\n };\n\n this.reconnect = force => {\n this.#boffStop();\n this.connect(null, force);\n };\n\n this.disconnect = _ => {\n this.#boffClosed = true;\n this.#boffStop();\n\n if (_sender) {\n _sender.onreadystatechange = undefined;\n _sender.abort();\n _sender = null;\n }\n if (_poller) {\n _poller.onreadystatechange = undefined;\n _poller.abort();\n _poller = null;\n }\n\n if (this.onDisconnect) {\n this.onDisconnect(new CommError(NETWORK_USER_TEXT, NETWORK_USER), NETWORK_USER);\n }\n // Ensure it's reconstructed\n _lpURL = null;\n };\n\n this.sendText = (msg) => {\n _sender = lp_sender(_lpURL);\n if (_sender && (_sender.readyState == XDR_OPENED)) {\n _sender.send(msg);\n } else {\n throw new Error(\"Long poller failed to connect\");\n }\n };\n\n this.isConnected = _ => {\n return (_poller && true);\n };\n }\n\n // Initialization for Websocket\n #init_ws() {\n this.connect = (host_, force) => {\n this.#boffClosed = false;\n\n if (this.#socket) {\n if (!force && this.#socket.readyState == this.#socket.OPEN) {\n // Issue a probe request to be sure the connection is live.\n // This is a non-blocking call.\n this.probe();\n return Promise.resolve();\n }\n this.#socket.close();\n this.#socket = null;\n }\n\n if (host_) {\n this.host = host_;\n }\n\n return new Promise((resolve, reject) => {\n const url = makeBaseUrl(this.host, this.secure ? 'wss' : 'ws', this.version, this.apiKey);\n\n Connection.#log(\"WS connecting to: \", url);\n\n // It throws when the server is not accessible but the exception cannot be caught:\n // https://stackoverflow.com/questions/31002592/javascript-doesnt-catch-error-in-websocket-instantiation/31003057\n const conn = new WebSocketProvider(url);\n\n conn.onerror = err => {\n reject(err);\n };\n\n conn.onopen = _ => {\n if (this.autoreconnect) {\n this.#boffStop();\n }\n\n if (this.onOpen) {\n this.onOpen();\n }\n\n resolve();\n };\n\n conn.onclose = _ => {\n this.#socket = null;\n\n if (this.onDisconnect) {\n const code = this.#boffClosed ? NETWORK_USER : NETWORK_ERROR;\n this.onDisconnect(new CommError(this.#boffClosed ? NETWORK_USER_TEXT : NETWORK_ERROR_TEXT, code), code);\n }\n\n if (!this.#boffClosed && this.autoreconnect) {\n this.#boffReconnect();\n }\n };\n\n conn.onmessage = evt => {\n if (this.onMessage) {\n this.onMessage(evt.data);\n }\n };\n\n this.#socket = conn;\n });\n }\n\n this.reconnect = force => {\n this.#boffStop();\n this.connect(null, force);\n };\n\n this.disconnect = _ => {\n this.#boffClosed = true;\n this.#boffStop();\n\n if (!this.#socket) {\n return;\n }\n this.#socket.close();\n this.#socket = null;\n };\n\n this.sendText = msg => {\n if (this.#socket && (this.#socket.readyState == this.#socket.OPEN)) {\n this.#socket.send(msg);\n } else {\n throw new Error(\"Websocket is not connected\");\n }\n };\n\n this.isConnected = _ => {\n return (this.#socket && (this.#socket.readyState == this.#socket.OPEN));\n };\n }\n\n // Callbacks:\n\n /**\n * A callback to pass incoming messages to. See {@link Tinode.Connection#onMessage}.\n * @callback Tinode.Connection.OnMessage\n * @memberof Tinode.Connection\n * @param {string} message - Message to process.\n */\n onMessage = undefined;\n\n /**\n * A callback for reporting a dropped connection.\n * @type {function}\n * @memberof Tinode.Connection#\n */\n onDisconnect = undefined;\n\n /**\n * A callback called when the connection is ready to be used for sending. For websockets it's socket open,\n * for long polling it's readyState=1 (OPENED)\n * @type {function}\n * @memberof Tinode.Connection#\n */\n onOpen = undefined;\n\n /**\n * A callback to notify of reconnection attempts. See {@link Tinode.Connection#onAutoreconnectIteration}.\n * @memberof Tinode.Connection\n * @callback AutoreconnectIterationType\n * @param {string} timeout - time till the next reconnect attempt in milliseconds. -1 means reconnect was skipped.\n * @param {Promise} promise resolved or rejected when the reconnect attemp completes.\n *\n */\n /**\n * A callback to inform when the next attampt to reconnect will happen and to receive connection promise.\n * @memberof Tinode.Connection#\n * @type {Tinode.Connection.AutoreconnectIterationType}\n */\n onAutoreconnectIteration = undefined;\n}\n\nConnection.NETWORK_ERROR = NETWORK_ERROR;\nConnection.NETWORK_ERROR_TEXT = NETWORK_ERROR_TEXT;\nConnection.NETWORK_USER = NETWORK_USER;\nConnection.NETWORK_USER_TEXT = NETWORK_USER_TEXT;\n","/**\n * @file Helper methods for dealing with IndexedDB cache of messages, users, and topics.\n *\n * @copyright 2015-2025 Tinode LLC.\n */\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\nconst DB_VERSION = 3;\nconst DB_NAME = 'tinode-web';\n\nlet IDBProvider;\n\nexport default class DB {\n #onError = _ => {};\n #logger = _ => {};\n\n // Instance of IndexDB.\n db = null;\n // Indicator that the cache is disabled.\n disabled = true;\n\n constructor(onError, logger) {\n this.#onError = onError || this.#onError;\n this.#logger = logger || this.#logger;\n }\n\n #mapObjects(source, callback, context) {\n if (!this.db) {\n return disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction([source]);\n trx.onerror = event => {\n this.#logger('PCache', 'mapObjects', source, event.target.error);\n reject(event.target.error);\n };\n trx.objectStore(source).getAll().onsuccess = event => {\n if (callback) {\n event.target.result.forEach(topic => {\n callback.call(context, topic);\n });\n }\n resolve(event.target.result);\n };\n });\n }\n\n /**\n * Initialize persistent cache: open or create/upgrade if needed.\n * @returns {Promise} promise to be resolved/rejected when the DB is initialized.\n */\n initDatabase() {\n return new Promise((resolve, reject) => {\n // Open the database and initialize callbacks.\n const req = IDBProvider.open(DB_NAME, DB_VERSION);\n req.onsuccess = event => {\n this.db = event.target.result;\n this.disabled = false;\n\n // This handler is called when a different tab tries to upgrade the database.\n this.db.onversionchange = _ => {\n this.#logger('PCache', \"another tab tries to upgrade DB, shutting down\");\n this.db.close();\n this.db = null;\n this.disabled = true;\n };\n\n resolve(this.db);\n };\n req.onerror = event => {\n this.#logger('PCache', \"failed to initialize\", event);\n reject(event.target.error);\n this.#onError(event.target.error);\n };\n req.onupgradeneeded = event => {\n this.db = event.target.result;\n\n this.db.onerror = event => {\n this.#logger('PCache', \"failed to create storage\", event);\n this.#onError(event.target.error);\n };\n\n // Individual object stores.\n\n // Alternatively could use event.oldVersion and event.newVersion\n // to determine which object stores to create or upgrade.\n\n if (!this.db.objectStoreNames.contains('topic')) {\n // Object store (table) for topics. The primary key is the topic name.\n this.db.createObjectStore('topic', {\n keyPath: 'name'\n });\n }\n\n if (!this.db.objectStoreNames.contains('user')) {\n // Users object store. UID is the primary key.\n this.db.createObjectStore('user', {\n keyPath: 'uid'\n });\n }\n\n if (!this.db.objectStoreNames.contains('subscription')) {\n // Subscriptions object store topic <-> user. Topic name + UID is the primary key.\n this.db.createObjectStore('subscription', {\n keyPath: ['topic', 'uid']\n });\n }\n\n if (!this.db.objectStoreNames.contains('message')) {\n // Messages object store. The primary key is topic name + seq.\n this.db.createObjectStore('message', {\n keyPath: ['topic', 'seq']\n });\n }\n\n if (!this.db.objectStoreNames.contains('dellog')) {\n // Records of deleted message ranges. The primary key is topic name + low seq.\n const dellog = this.db.createObjectStore('dellog', {\n keyPath: ['topic', 'low', 'hi']\n });\n if (!dellog.indexNames.contains('topic_clear')) {\n dellog.createIndex('topic_clear', ['topic', 'clear'], {\n unique: false\n });\n }\n }\n }\n });\n }\n\n /**\n * Delete persistent cache.\n */\n deleteDatabase() {\n // Close connection, otherwise operations will fail with 'onblocked'.\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n return new Promise((resolve, reject) => {\n const req = IDBProvider.deleteDatabase(DB_NAME);\n req.onblocked = _ => {\n if (this.db) {\n this.db.close();\n }\n const err = new Error(\"blocked\");\n this.#logger('PCache', 'deleteDatabase', err);\n reject(err);\n };\n req.onsuccess = _ => {\n this.db = null;\n this.disabled = true;\n resolve(true);\n };\n req.onerror = event => {\n this.#logger('PCache', 'deleteDatabase', event.target.error);\n reject(event.target.error);\n };\n });\n }\n\n /**\n * Check if persistent cache is ready for use.\n * @memberOf DB\n * @returns {boolean} true if cache is ready, false otherwise.\n */\n isReady() {\n return !!this.db;\n }\n\n // Topics.\n\n /**\n * Save to cache or update topic in persistent cache.\n * @memberOf DB\n * @param {Topic} topic - topic to be added or updated.\n * @returns {Promise} promise resolved/rejected on operation completion.\n */\n updTopic(topic) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['topic'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updTopic', event.target.error);\n reject(event.target.error);\n };\n const req = trx.objectStore('topic').get(topic.name);\n req.onsuccess = _ => {\n trx.objectStore('topic').put(DB.#serializeTopic(req.result, topic));\n trx.commit();\n };\n });\n }\n\n /**\n * Mark or unmark topic as deleted.\n * @memberOf DB\n * @param {string} name - name of the topic to mark or unmark.\n * @param {boolean} deleted - status\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n markTopicAsDeleted(name, deleted) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['topic'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'markTopicAsDeleted', event.target.error);\n reject(event.target.error);\n };\n const req = trx.objectStore('topic').get(name);\n req.onsuccess = event => {\n const topic = event.target.result;\n if (topic && topic._deleted != deleted) {\n topic._deleted = deleted;\n trx.objectStore('topic').put(topic);\n }\n trx.commit();\n };\n });\n }\n\n /**\n * Remove topic from persistent cache.\n * @memberOf DB\n * @param {string} name - name of the topic to remove from database.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n remTopic(name) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['topic', 'subscription', 'message'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'remTopic', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('topic').delete(IDBKeyRange.only(name));\n trx.objectStore('subscription').delete(IDBKeyRange.bound([name, '-'], [name, '~']));\n trx.objectStore('message').delete(IDBKeyRange.bound([name, 0], [name, Number.MAX_SAFE_INTEGER]));\n trx.commit();\n });\n }\n\n /**\n * Execute a callback for each stored topic.\n * @memberOf DB\n * @param {function} callback - function to call for each topic.\n * @param {Object} context - the value or this inside the callback.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n mapTopics(callback, context) {\n return this.#mapObjects('topic', callback, context);\n }\n\n /**\n * Copy data from serialized object to topic.\n * @memberOf DB\n * @param {Topic} topic - target to deserialize to.\n * @param {Object} src - serialized data to copy from.\n */\n deserializeTopic(topic, src) {\n DB.#deserializeTopic(topic, src);\n }\n\n // Users.\n /**\n * Add or update user object in the persistent cache.\n * @memberOf DB\n * @param {string} uid - ID of the user to save or update.\n * @param {Object} pub - user's public information.\n * @returns {Promise} promise resolved/rejected on operation completion.\n */\n updUser(uid, pub) {\n if (arguments.length < 2 || pub === undefined) {\n // No point inupdating user with invalid data.\n return;\n }\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['user'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updUser', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('user').put({\n uid: uid,\n public: pub\n });\n trx.commit();\n });\n }\n\n /**\n * Remove user from persistent cache.\n * @memberOf DB\n * @param {string} uid - ID of the user to remove from the cache.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n remUser(uid) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['user'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'remUser', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('user').delete(IDBKeyRange.only(uid));\n trx.commit();\n });\n }\n\n /**\n * Execute a callback for each stored user.\n * @memberOf DB\n * @param {function} callback - function to call for each topic.\n * @param {Object} context - the value or this inside the callback.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n mapUsers(callback, context) {\n return this.#mapObjects('user', callback, context);\n }\n\n /**\n * Read a single user from persistent cache.\n * @memberOf DB\n * @param {string} uid - ID of the user to fetch from cache.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n getUser(uid) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['user']);\n trx.oncomplete = event => {\n const user = event.target.result;\n resolve({\n user: user.uid,\n public: user.public\n });\n };\n trx.onerror = event => {\n this.#logger('PCache', 'getUser', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('user').get(uid);\n });\n }\n\n // Subscriptions.\n /**\n * Add or update subscription in persistent cache.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {string} uid - ID of the subscribed user.\n * @param {Object} sub - subscription to save.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n updSubscription(topicName, uid, sub) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['subscription'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updSubscription', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('subscription').get([topicName, uid]).onsuccess = (event) => {\n trx.objectStore('subscription').put(DB.#serializeSubscription(event.target.result, topicName, uid, sub));\n trx.commit();\n };\n });\n }\n\n /**\n * Execute a callback for each cached subscription in a given topic.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the subscriptions.\n * @param {function} callback - function to call for each subscription.\n * @param {Object} context - the value or this inside the callback.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n mapSubscriptions(topicName, callback, context) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['subscription']);\n trx.onerror = (event) => {\n this.#logger('PCache', 'mapSubscriptions', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('subscription').getAll(IDBKeyRange.bound([topicName, '-'], [topicName, '~'])).onsuccess = (event) => {\n if (callback) {\n event.target.result.forEach((topic) => {\n callback.call(context, topic);\n });\n }\n resolve(event.target.result);\n };\n });\n }\n\n // Messages.\n\n /**\n * Save message to persistent cache.\n * @memberOf DB\n * @param {Object} msg - message to save.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n addMessage(msg) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['message'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'addMessage', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('message').add(DB.#serializeMessage(null, msg));\n trx.commit();\n });\n }\n\n /**\n * Update delivery status of a message stored in persistent cache.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {number} seq - ID of the message to update\n * @param {number} status - new delivery status of the message.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n updMessageStatus(topicName, seq, status) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['message'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updMessageStatus', event.target.error);\n reject(event.target.error);\n };\n const req = trx.objectStore('message').get(IDBKeyRange.only([topicName, seq]));\n req.onsuccess = event => {\n const src = req.result || event.target.result;\n if (!src || src._status == status) {\n trx.commit();\n return;\n }\n trx.objectStore('message').put(DB.#serializeMessage(src, {\n topic: topicName,\n seq: seq,\n _status: status\n }));\n trx.commit();\n };\n });\n }\n\n /**\n * Remove one or more messages from persistent cache.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {number} from - id of the message to remove or lower boundary when removing range (inclusive).\n * @param {number=} to - upper boundary (exclusive) when removing a range of messages.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n remMessages(topicName, from, to) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n if (!from && !to) {\n from = 0;\n to = Number.MAX_SAFE_INTEGER;\n }\n const range = to > 0 ? IDBKeyRange.bound([topicName, from], [topicName, to], false, true) :\n IDBKeyRange.only([topicName, from]);\n const trx = this.db.transaction(['message'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'remMessages', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('message').delete(range);\n trx.commit();\n });\n }\n\n /**\n * Retrieve messages from persistent store.\n * @memberOf DB\n * @param {string} topicName - name of the topic to retrieve messages from.\n * @param {function} callback to call for each retrieved message.\n * @param {GetDataType} query - parameters of the message range to retrieve.\n *\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n readMessages(topicName, query, callback, context) {\n query = query || {};\n\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n const trx = this.db.transaction(['message']);\n let result = [];\n\n // Handle individual message ranges.\n if (Array.isArray(query.ranges)) {\n return new Promise((resolve, reject) => {\n trx.onerror = event => {\n this.#logger('PCache', 'readMessages', event.target.error);\n reject(event.target.error);\n };\n\n let count = 0;\n query.ranges.forEach(range => {\n const key = range.hi ? IDBKeyRange.bound([topicName, range.low], [topicName, range.hi], false, true) :\n IDBKeyRange.only([topicName, range.low]);\n trx.objectStore('message').getAll(key).onsuccess = event => {\n const msgs = event.target.result;\n if (msgs) {\n if (callback) {\n callback.call(context, msgs);\n }\n if (Array.isArray(msgs)) {\n result = result.concat(msgs);\n } else {\n result.push(msgs);\n }\n }\n count++;\n if (count == query.ranges.length) {\n resolve(result);\n }\n };\n });\n });\n }\n\n // Handle single range.\n return new Promise((resolve, reject) => {\n const since = query.since > 0 ? query.since : 0;\n const before = query.before > 0 ? query.before : Number.MAX_SAFE_INTEGER;\n const limit = query.limit | 0;\n\n trx.onerror = event => {\n this.#logger('PCache', 'readMessages', event.target.error);\n reject(event.target.error);\n };\n\n const range = IDBKeyRange.bound([topicName, since], [topicName, before], false, true);\n // Iterate in descending order.\n trx.objectStore('message').openCursor(range, 'prev')\n .onsuccess = event => {\n const cursor = event.target.result;\n if (cursor) {\n if (callback) {\n callback.call(context, cursor.value);\n }\n result.push(cursor.value);\n if (limit <= 0 || result.length < limit) {\n cursor.continue();\n } else {\n resolve(result);\n }\n } else {\n resolve(result);\n }\n };\n });\n }\n\n // Delete log\n\n /**\n * Add records of deleted messages.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {number} delId - id of the deletion transaction.\n * @param {Array.} ranges - message to save.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n addDelLog(topicName, delId, ranges) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['dellog'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'addDelLog', event.target.error);\n reject(event.target.error);\n };\n ranges.forEach(r => trx.objectStore('dellog').add({\n topic: topicName,\n clear: delId,\n low: r.low,\n hi: r.hi || (r.low + 1)\n }));\n trx.commit();\n });\n }\n\n /**\n * Retrieve deleted message records from persistent store.\n * @memberOf DB\n * @param {string} topicName - name of the topic to retrieve records for.\n * @param {GetDataType} query - parameters of the message range to retrieve.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n readDelLog(topicName, query) {\n query = query || {};\n\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n const trx = this.db.transaction(['dellog']);\n let result = [];\n\n // Handle individual message ranges.\n if (Array.isArray(query.ranges)) {\n return new Promise((resolve, reject) => {\n trx.onerror = event => {\n this.#logger('PCache', 'readDelLog', event.target.error);\n reject(event.target.error);\n };\n\n let count = 0;\n query.ranges.forEach(range => {\n const hi = range.hi || (range.low + 1);\n const key = IDBKeyRange.bound([topicName, 0, range.low], [topicName, hi, Number.MAX_SAFE_INTEGER], false, true);\n trx.objectStore('dellog').getAll(key).onsuccess = event => {\n const entries = event.target.result;\n if (entries) {\n if (Array.isArray(entries)) {\n result = result.concat(entries.map(entry => {\n return {\n low: entry.low,\n hi: entry.hi\n };\n }));\n } else {\n result.push({\n low: entries.low,\n hi: entries.hi\n });\n }\n }\n count++;\n if (count == query.ranges.length) {\n resolve(result);\n }\n };\n });\n });\n }\n\n return new Promise((resolve, reject) => {\n const since = query.since > 0 ? query.since : 0;\n const before = query.before > 0 ? query.before : Number.MAX_SAFE_INTEGER;\n const limit = query.limit | 0;\n\n trx.onerror = event => {\n this.#logger('PCache', 'readDelLog', event.target.error);\n reject(event.target.error);\n };\n\n let count = 0;\n const result = [];\n const range = IDBKeyRange.bound([topicName, 0, since], [topicName, before, Number.MAX_SAFE_INTEGER], false, true);\n trx.objectStore('dellog').openCursor(range, 'prev')\n .onsuccess = event => {\n const cursor = event.target.result;\n if (cursor) {\n result.push({\n low: cursor.value.low,\n hi: cursor.value.hi\n });\n count += cursor.value.hi - cursor.value.low;\n if (limit <= 0 || count < limit) {\n cursor.continue();\n } else {\n resolve(result);\n }\n } else {\n resolve(result);\n }\n };\n });\n }\n\n /**\n * Retrieve the latest 'clear' ID for the given topic.\n * @param {string} topicName\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n maxDelId(topicName) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve(0) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['dellog']);\n trx.onerror = event => {\n this.#logger('PCache', 'maxDelId', event.target.error);\n reject(event.target.error);\n };\n\n const index = trx.objectStore('dellog').index('topic_clear');\n index.openCursor(IDBKeyRange.bound([topicName, 0], [topicName, Number.MAX_SAFE_INTEGER]), 'prev')\n .onsuccess = event => {\n if (event.target.result) {\n resolve(event.target.result.value);\n }\n };\n });\n }\n\n // Private methods.\n\n // Serializable topic fields.\n static #topic_fields = ['created', 'updated', 'deleted', 'touched', 'read', 'recv', 'seq',\n 'clear', 'defacs', 'creds', 'public', 'trusted', 'private', '_aux', '_deleted'\n ];\n\n // Copy data from src to Topic object.\n static #deserializeTopic(topic, src) {\n DB.#topic_fields.forEach((f) => {\n if (src.hasOwnProperty(f)) {\n topic[f] = src[f];\n }\n });\n if (Array.isArray(src.tags)) {\n topic._tags = src.tags;\n }\n if (src.acs) {\n topic.setAccessMode(src.acs);\n }\n topic.seq |= 0;\n topic.read |= 0;\n topic.unread = Math.max(0, topic.seq - topic.read);\n }\n\n // Copy values from 'src' to 'dst'. Allocate dst if it's null or undefined.\n static #serializeTopic(dst, src) {\n const res = dst || {\n name: src.name\n };\n DB.#topic_fields.forEach(f => {\n if (src.hasOwnProperty(f)) {\n res[f] = src[f];\n }\n });\n if (Array.isArray(src._tags)) {\n res.tags = src._tags;\n }\n if (src.acs) {\n res.acs = src.getAccessMode().jsonHelper();\n }\n return res;\n }\n\n static #serializeSubscription(dst, topicName, uid, sub) {\n const fields = ['updated', 'mode', 'read', 'recv', 'clear', 'lastSeen', 'userAgent'];\n const res = dst || {\n topic: topicName,\n uid: uid\n };\n\n fields.forEach((f) => {\n if (sub.hasOwnProperty(f)) {\n res[f] = sub[f];\n }\n });\n\n return res;\n }\n\n static #serializeMessage(dst, msg) {\n // Serializable fields.\n const fields = ['topic', 'seq', 'ts', '_status', 'from', 'head', 'content'];\n const res = dst || {};\n fields.forEach((f) => {\n if (msg.hasOwnProperty(f)) {\n res[f] = msg[f];\n }\n });\n return res;\n }\n\n /**\n * To use DB in a non browser context, supply indexedDB provider.\n * @static\n * @memberof DB\n * @param idbProvider indexedDB provider, e.g. for node require('fake-indexeddb').\n */\n static setDatabaseProvider(idbProvider) {\n IDBProvider = idbProvider;\n }\n}\n","/**\n * @copyright 2015-2024 Tinode LLC.\n * @summary Minimally rich text representation and formatting for Tinode.\n * @license Apache 2.0\n *\n * @file Basic parser and formatter for very simple text markup. Mostly targeted at\n * mobile use cases similar to Telegram, WhatsApp, and FB Messenger.\n *\n * Supports conversion of user keyboard input to formatted text:
\n * \n * *abc* → abc \n * _abc_ → abc \n * ~abc~ → abc \n * `abc` → abc \n * \n * Also supports forms and buttons.\n *\n * Nested formatting is supported, e.g. *abc _def_* -> abc def \n * URLs, @mentions, and #hashtags are extracted and converted into links.\n * Forms and buttons can be added procedurally.\n * JSON data representation is inspired by Draft.js raw formatting.\n *\n *\n * @example\n * Text:\n * \n * this is *bold*, `code` and _italic_, ~strike~\n * combined *bold and _italic_*\n * an url: https://www.example.com/abc#fragment and another _www.tinode.co_\n * this is a @mention and a #hashtag in a string\n * second #hashtag\n * \n *\n * Sample JSON representation of the text above:\n * {\n * \"txt\": \"this is bold, code and italic, strike combined bold and italic an url: https://www.example.com/abc#fragment \" +\n * \"and another www.tinode.co this is a @mention and a #hashtag in a string second #hashtag\",\n * \"fmt\": [\n * { \"at\":8, \"len\":4,\"tp\":\"ST\" },{ \"at\":14, \"len\":4, \"tp\":\"CO\" },{ \"at\":23, \"len\":6, \"tp\":\"EM\"},\n * { \"at\":31, \"len\":6, \"tp\":\"DL\" },{ \"tp\":\"BR\", \"len\":1, \"at\":37 },{ \"at\":56, \"len\":6, \"tp\":\"EM\" },\n * { \"at\":47, \"len\":15, \"tp\":\"ST\" },{ \"tp\":\"BR\", \"len\":1, \"at\":62 },{ \"at\":120, \"len\":13, \"tp\":\"EM\" },\n * { \"at\":71, \"len\":36, \"key\":0 },{ \"at\":120, \"len\":13, \"key\":1 },{ \"tp\":\"BR\", \"len\":1, \"at\":133 },\n * { \"at\":144, \"len\":8, \"key\":2 },{ \"at\":159, \"len\":8, \"key\":3 },{ \"tp\":\"BR\", \"len\":1, \"at\":179 },\n * { \"at\":187, \"len\":8, \"key\":3 },{ \"tp\":\"BR\", \"len\":1, \"at\":195 }\n * ],\n * \"ent\": [\n * { \"tp\":\"LN\", \"data\":{ \"url\":\"https://www.example.com/abc#fragment\" } },\n * { \"tp\":\"LN\", \"data\":{ \"url\":\"http://www.tinode.co\" } },\n * { \"tp\":\"MN\", \"data\":{ \"val\":\"mention\" } },\n * { \"tp\":\"HT\", \"data\":{ \"val\":\"hashtag\" } }\n * ]\n * }\n */\n\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\nconst MAX_FORM_ELEMENTS = 8;\nconst MAX_PREVIEW_ATTACHMENTS = 3;\nconst MAX_PREVIEW_DATA_SIZE = 64;\nconst JSON_MIME_TYPE = 'application/json+drafty';\nconst JSON_MIME_TYPE_LEGACY = 'application/json'; // Remove in 2026.\nconst DRAFTY_MIME_TYPE = 'text/x-drafty';\nconst ALLOWED_ENT_FIELDS = ['act', 'height', 'duration', 'incoming', 'mime', 'name', 'premime', 'preref', 'preview',\n 'ref', 'size', 'state', 'url', 'val', 'width'\n];\n\n// Intl.Segmenter is not available in Firefox 124 and earlier. FF 125 with support for Intl.Segmenter\n// was released on April 15, 2024. Polyfill is included in the top package (webapp).\nconst segmenter = new Intl.Segmenter();\n\n// Regular expressions for parsing inline formats. Javascript does not support lookbehind,\n// so it's a bit messy.\nconst INLINE_STYLES = [\n // Strong = bold, *bold text*\n {\n name: 'ST',\n start: /(?:^|[\\W_])(\\*)[^\\s*]/,\n end: /[^\\s*](\\*)(?=$|[\\W_])/\n },\n // Emphesized = italic, _italic text_\n {\n name: 'EM',\n start: /(?:^|\\W)(_)[^\\s_]/,\n end: /[^\\s_](_)(?=$|\\W)/\n },\n // Deleted, ~strike this though~\n {\n name: 'DL',\n start: /(?:^|[\\W_])(~)[^\\s~]/,\n end: /[^\\s~](~)(?=$|[\\W_])/\n },\n // Code block `this is monospace`\n {\n name: 'CO',\n start: /(?:^|\\W)(`)[^`]/,\n end: /[^`](`)(?=$|\\W)/\n }\n];\n\n// Relative weights of formatting spans. Greater index in array means greater weight.\nconst FMT_WEIGHT = ['QQ'];\n\n// RegExps for entity extraction (RF = reference)\nconst ENTITY_TYPES = [\n // URLs\n {\n name: 'LN',\n dataName: 'url',\n pack: function(val) {\n // Check if the protocol is specified, if not use http\n if (!/^[a-z]+:\\/\\//i.test(val)) {\n val = 'http://' + val;\n }\n return {\n url: val\n };\n },\n re: /(?:(?:https?|ftp):\\/\\/|www\\.|ftp\\.)[-A-Z0-9+&@#\\/%=~_|$?!:,.]*[A-Z0-9+&@#\\/%=~_|$]/ig\n },\n // Mentions @user (must be 2 or more characters)\n {\n name: 'MN',\n dataName: 'val',\n pack: function(val) {\n return {\n val: val.slice(1)\n };\n },\n re: /\\B@([\\p{L}\\p{N}][._\\p{L}\\p{N}]*[\\p{L}\\p{N}])/ug\n },\n // Hashtags #hashtag, like metion 2 or more characters.\n {\n name: 'HT',\n dataName: 'val',\n pack: function(val) {\n return {\n val: val.slice(1)\n };\n },\n re: /\\B#([\\p{L}\\p{N}][._\\p{L}\\p{N}]*[\\p{L}\\p{N}])/ug\n }\n];\n\n// HTML tag name suggestions\nconst FORMAT_TAGS = {\n AU: {\n html_tag: 'audio',\n md_tag: undefined,\n isVoid: false\n },\n BN: {\n html_tag: 'button',\n md_tag: undefined,\n isVoid: false\n },\n BR: {\n html_tag: 'br',\n md_tag: '\\n',\n isVoid: true\n },\n CO: {\n html_tag: 'tt',\n md_tag: '`',\n isVoid: false\n },\n DL: {\n html_tag: 'del',\n md_tag: '~',\n isVoid: false\n },\n EM: {\n html_tag: 'i',\n md_tag: '_',\n isVoid: false\n },\n EX: {\n html_tag: '',\n md_tag: undefined,\n isVoid: true\n },\n FM: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false\n },\n HD: {\n html_tag: '',\n md_tag: undefined,\n isVoid: false\n },\n HL: {\n html_tag: 'span',\n md_tag: undefined,\n isVoid: false\n },\n HT: {\n html_tag: 'a',\n md_tag: undefined,\n isVoid: false\n },\n IM: {\n html_tag: 'img',\n md_tag: undefined,\n isVoid: false\n },\n LN: {\n html_tag: 'a',\n md_tag: undefined,\n isVoid: false\n },\n MN: {\n html_tag: 'a',\n md_tag: undefined,\n isVoid: false\n },\n RW: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false,\n },\n QQ: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false\n },\n ST: {\n html_tag: 'b',\n md_tag: '*',\n isVoid: false\n },\n VC: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false\n },\n VD: {\n html_tag: 'video',\n md_tag: undefined,\n isVoid: false\n }\n};\n\n// Convert base64-encoded string into Blob.\nfunction base64toObjectUrl(b64, contentType, logger) {\n if (!b64) {\n return null;\n }\n\n try {\n const bin = atob(b64);\n const length = bin.length;\n const buf = new ArrayBuffer(length);\n const arr = new Uint8Array(buf);\n for (let i = 0; i < length; i++) {\n arr[i] = bin.charCodeAt(i);\n }\n\n return URL.createObjectURL(new Blob([buf], {\n type: contentType\n }));\n } catch (err) {\n if (logger) {\n logger(\"Drafty: failed to convert object.\", err.message);\n }\n }\n\n return null;\n}\n\nfunction base64toDataUrl(b64, contentType) {\n if (!b64) {\n return null;\n }\n contentType = contentType || 'image/jpeg';\n return 'data:' + contentType + ';base64,' + b64;\n}\n\n// Helpers for converting Drafty to HTML.\nconst DECORATORS = {\n // Visial styles\n ST: {\n open: _ => '',\n close: _ => ' '\n },\n EM: {\n open: _ => '',\n close: _ => ' '\n },\n DL: {\n open: _ => '',\n close: _ => ''\n },\n CO: {\n open: _ => '',\n close: _ => ' '\n },\n // Line break\n BR: {\n open: _ => ' ',\n close: _ => ''\n },\n // Hidden element\n HD: {\n open: _ => '',\n close: _ => ''\n },\n // Highlighted element.\n HL: {\n open: _ => '',\n close: _ => ' '\n },\n // Link (URL)\n LN: {\n open: (data) => {\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n return data ? {\n href: data.url,\n target: '_blank'\n } : null;\n },\n },\n // Mention\n MN: {\n open: (data) => {\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n return data ? {\n id: data.val\n } : null;\n },\n },\n // Hashtag\n HT: {\n open: (data) => {\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n return data ? {\n id: data.val\n } : null;\n },\n },\n // Button\n BN: {\n open: _ => '',\n close: _ => ' ',\n props: (data) => {\n return data ? {\n 'data-act': data.act,\n 'data-val': data.val,\n 'data-name': data.name,\n 'data-ref': data.ref\n } : null;\n },\n },\n // Audio recording\n AU: {\n open: (data) => {\n const url = data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger);\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n if (!data) return null;\n return {\n // Embedded data or external link.\n src: data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger),\n 'data-preload': data.ref ? 'metadata' : 'auto',\n 'data-duration': data.duration,\n 'data-name': data.name,\n 'data-size': data.val ? ((data.val.length * 0.75) | 0) : (data.size | 0),\n 'data-mime': data.mime,\n };\n }\n },\n // Image\n IM: {\n open: data => {\n // Don't use data.ref for preview: it's a security risk.\n const tmpPreviewUrl = base64toDataUrl(data._tempPreview, data.mime);\n const previewUrl = base64toObjectUrl(data.val, data.mime, Drafty.logger);\n const downloadUrl = data.ref || previewUrl;\n return (data.name ? '' : '') +\n ' ';\n },\n close: data => {\n return (data.name ? ' ' : '');\n },\n props: data => {\n if (!data) return null;\n return {\n // Temporary preview, or permanent preview, or external link.\n src: base64toDataUrl(data._tempPreview, data.mime) ||\n data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger),\n title: data.name,\n alt: data.name,\n 'data-width': data.width,\n 'data-height': data.height,\n 'data-name': data.name,\n 'data-size': data.ref ? (data.size | 0) : (data.val ? ((data.val.length * 0.75) | 0) : (data.size | 0)),\n 'data-mime': data.mime,\n };\n },\n },\n // Form - structured layout of elements.\n FM: {\n open: _ => '',\n close: _ => '
'\n },\n // Row: logic grouping of elements\n RW: {\n open: _ => '',\n close: _ => '
'\n },\n // Quoted block.\n QQ: {\n open: _ => '',\n close: _ => '
',\n props: (data) => {\n return data ? {} : null;\n },\n },\n // Video call\n VC: {\n open: _ => '',\n close: _ => '
',\n props: data => {\n if (!data) return {};\n return {\n 'data-duration': data.duration,\n 'data-state': data.state,\n };\n }\n },\n // Video.\n VD: {\n open: data => {\n const tmpPreviewUrl = base64toDataUrl(data._tempPreview, data.mime);\n const previewUrl = data.ref || base64toObjectUrl(data.preview, data.premime || 'image/jpeg', Drafty.logger);\n return ' ';\n },\n close: _ => '',\n props: data => {\n if (!data) return null;\n const poster = data.preref || base64toObjectUrl(data.preview, data.premime || 'image/jpeg', Drafty.logger);\n return {\n // Embedded data or external link.\n src: poster,\n 'data-src': data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger),\n 'data-width': data.width,\n 'data-height': data.height,\n 'data-preload': data.ref ? 'metadata' : 'auto',\n 'data-preview': poster,\n 'data-duration': data.duration | 0,\n 'data-name': data.name,\n 'data-size': data.ref ? (data.size | 0) : (data.val ? ((data.val.length * 0.75) | 0) : (data.size | 0)),\n 'data-mime': data.mime,\n };\n }\n },\n};\n\n/**\n * The main object which performs all the formatting actions.\n * @class Drafty\n * @constructor\n */\nconst Drafty = function() {\n this.txt = '';\n this.fmt = [];\n this.ent = [];\n}\n\n/**\n * Initialize Drafty document to a plain text string.\n *\n * @param {string} plainText - string to use as Drafty content.\n *\n * @returns new Drafty document or null is plainText is not a string or undefined.\n */\nDrafty.init = function(plainText) {\n if (typeof plainText == 'undefined') {\n plainText = '';\n } else if (typeof plainText != 'string') {\n return null;\n }\n\n return {\n txt: plainText\n };\n}\n\n/**\n * Parse plain text into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {string} content - plain-text content to parse.\n * @return {Drafty} parsed document or null if the source is not plain text.\n */\nDrafty.parse = function(content) {\n // Make sure we are parsing strings only.\n if (typeof content != 'string') {\n return null;\n }\n\n // Split text into lines. It makes further processing easier.\n const lines = content.split(/\\r?\\n/);\n\n // Holds entities referenced from text\n const entityMap = [];\n const entityIndex = {};\n\n // Processing lines one by one, hold intermediate result in blx.\n const blx = [];\n lines.forEach((line) => {\n let spans = [];\n let entities;\n\n // Find formatted spans in the string.\n // Try to match each style.\n INLINE_STYLES.forEach((tag) => {\n // Each style could be matched multiple times.\n spans = spans.concat(spannify(line, tag.start, tag.end, tag.name));\n });\n\n let block;\n if (spans.length == 0) {\n block = {\n txt: line\n };\n } else {\n // Sort spans by style occurence early -> late, then by length: first long then short.\n spans.sort((a, b) => {\n const diff = a.at - b.at;\n return diff != 0 ? diff : b.end - a.end;\n });\n\n // Convert an array of possibly overlapping spans into a tree.\n spans = toSpanTree(spans);\n\n // Build a tree representation of the entire string, not\n // just the formatted parts.\n const chunks = chunkify(line, 0, line.length, spans);\n\n const drafty = draftify(chunks, 0);\n\n block = {\n txt: drafty.txt,\n fmt: drafty.fmt\n };\n }\n\n // Extract entities from the cleaned up string.\n entities = extractEntities(block.txt);\n if (entities.length > 0) {\n const ranges = [];\n for (let i in entities) {\n // {offset: match['index'], unique: match[0], len: match[0].length, data: ent.packer(), type: ent.name}\n const entity = entities[i];\n let index = entityIndex[entity.unique];\n if (!index) {\n index = entityMap.length;\n entityIndex[entity.unique] = index;\n entityMap.push({\n tp: entity.type,\n data: entity.data\n });\n }\n ranges.push({\n at: entity.offset,\n len: entity.len,\n key: index\n });\n }\n block.ent = ranges;\n }\n\n blx.push(block);\n });\n\n const result = {\n txt: ''\n };\n\n // Merge lines and save line breaks as BR inline formatting.\n if (blx.length > 0) {\n result.txt = blx[0].txt;\n result.fmt = (blx[0].fmt || []).concat(blx[0].ent || []);\n\n if (result.fmt.length) {\n const segments = segmenter.segment(result.txt);\n for (const ele of result.fmt) {\n ({\n at: ele.at,\n len: ele.len\n } =\n toGraphemeValues(ele, segments, result.txt));\n }\n }\n\n for (let i = 1; i < blx.length; i++) {\n const block = blx[i];\n const offset = stringToGraphemes(result.txt).length + 1;\n\n result.fmt.push({\n tp: 'BR',\n len: 1,\n at: offset - 1\n });\n\n let segments = {};\n\n result.txt += ' ' + block.txt;\n if (block.fmt) {\n segments = segmenter.segment(block.txt);\n result.fmt = result.fmt.concat(\n block.fmt.map((s) => {\n const {\n at: correctAt,\n len: correctLen\n } =\n toGraphemeValues(s, segments, block.txt);\n s.at = correctAt + offset;\n s.len = correctLen;\n return s;\n })\n );\n }\n if (block.ent) {\n if (isEmptyObject(segments)) {\n segments = segmenter.segment(block.txt);\n }\n result.fmt = result.fmt.concat(\n block.ent.map((s) => {\n const {\n at: correctAt,\n len: correctLen\n } =\n toGraphemeValues(s, segments, block.txt);\n s.at = correctAt + offset;\n s.len = correctLen;\n return s;\n })\n );\n }\n }\n\n if (result.fmt.length == 0) {\n delete result.fmt;\n }\n\n if (entityMap.length > 0) {\n result.ent = entityMap;\n }\n }\n return result;\n}\n\n/**\n * Append one Drafty document to another.\n *\n * @param {Drafty} first - Drafty document to append to.\n * @param {Drafty|string} second - Drafty document or string being appended.\n *\n * @return {Drafty} first document with the second appended to it.\n */\nDrafty.append = function(first, second) {\n if (!first) {\n return second;\n }\n if (!second) {\n return first;\n }\n\n first.txt = first.txt || '';\n const len = stringToGraphemes(first.txt).length;\n\n if (typeof second == 'string') {\n first.txt += second;\n } else if (second.txt) {\n first.txt += second.txt;\n }\n\n if (Array.isArray(second.fmt)) {\n first.fmt = first.fmt || [];\n if (Array.isArray(second.ent)) {\n first.ent = first.ent || [];\n }\n second.fmt.forEach(src => {\n const fmt = {\n at: (src.at | 0) + len,\n len: src.len | 0\n };\n // Special case for the outside of the normal rendering flow styles.\n if (src.at == -1) {\n fmt.at = -1;\n fmt.len = 0;\n }\n if (src.tp) {\n fmt.tp = src.tp;\n } else {\n fmt.key = first.ent.length;\n first.ent.push(second.ent[src.key || 0]);\n }\n first.fmt.push(fmt);\n });\n }\n\n return first;\n}\n\n/**\n * Description of an image to attach.\n * @typedef {Object} ImageDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the image, e.g. \"image/png\".\n * @property {string} refurl - reference to the content. Could be null/undefined.\n * @property {string} bits - base64-encoded image content. Could be null/undefined.\n * @property {string} preview - base64-encoded thumbnail of the image.\n * @property {integer} width - width of the image.\n * @property {integer} height - height of the image.\n * @property {string} filename - file name suggestion for downloading the image.\n * @property {integer} size - size of the image in bytes. Treat is as an untrusted hint.\n * @property {string} _tempPreview - base64-encoded image preview used during upload process; not serializable.\n * @property {Promise} urlPromise - Promise which returns content URL when resolved.\n */\n\n/**\n * Insert inline image into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add image to.\n * @param {integer} at - index where the object is inserted. The length of the image is always 1.\n * @param {ImageDesc} imageDesc - object with image paramenets and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertImage = function(content, at, imageDesc) {\n content = content || {\n txt: ' '\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: 1,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'IM',\n data: {\n mime: imageDesc.mime,\n ref: imageDesc.refurl,\n val: imageDesc.bits || imageDesc.preview,\n width: imageDesc.width,\n height: imageDesc.height,\n name: imageDesc.filename,\n size: imageDesc.size | 0,\n }\n };\n\n if (imageDesc.urlPromise) {\n ex.data._tempPreview = imageDesc._tempPreview;\n ex.data._processing = true;\n imageDesc.urlPromise.then(\n url => {\n ex.data.ref = url;\n ex.data._tempPreview = undefined;\n ex.data._processing = undefined;\n },\n _ => {\n // Catch the error, otherwise it will appear in the console.\n ex.data._processing = undefined;\n }\n );\n }\n\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Description of a video to attach.\n * @typedef {Object} VideoDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the video, e.g. \"video/mpeg\".\n * @property {string} refurl - reference to the content. Could be null/undefined.\n * @property {string} bits - in-band base64-encoded image data. Could be null/undefined.\n * @property {string} preview - base64-encoded screencapture from the video. Could be null/undefined.\n * @property {string} preref - reference to screencapture from the video. Could be null/undefined.\n * @property {integer} width - width of the video.\n * @property {integer} height - height of the video.\n * @property {integer} duration - duration of the video.\n * @property {string} filename - file name suggestion for downloading the video.\n * @property {integer} size - size of the video in bytes. Treat is as an untrusted hint.\n * @property {string} _tempPreview - base64-encoded screencapture used during upload process; not serializable.\n * @property {Promise} urlPromise - array of two promises, which return URLs of video and preview uploads correspondingly\n * (either could be null).\n */\n\n/**\n * Insert inline image into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add video to.\n * @param {integer} at - index where the object is inserted. The length of the video is always 1.\n * @param {VideoDesc} videoDesc - object with video paramenets and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertVideo = function(content, at, videoDesc) {\n content = content || {\n txt: ' '\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: 1,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'VD',\n data: {\n mime: videoDesc.mime,\n ref: videoDesc.refurl,\n val: videoDesc.bits,\n preref: videoDesc.preref,\n preview: videoDesc.preview,\n width: videoDesc.width,\n height: videoDesc.height,\n duration: videoDesc.duration | 0,\n name: videoDesc.filename,\n size: videoDesc.size | 0,\n }\n };\n\n if (videoDesc.urlPromise) {\n ex.data._tempPreview = videoDesc._tempPreview;\n ex.data._processing = true;\n videoDesc.urlPromise.then(\n urls => {\n ex.data.ref = urls[0];\n ex.data.preref = urls[1];\n ex.data._tempPreview = undefined;\n ex.data._processing = undefined;\n },\n _ => {\n // Catch the error, otherwise it will appear in the console.\n ex.data._processing = undefined;\n }\n );\n }\n\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Description of an audio recording to attach.\n * @typedef {Object} AudioDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the audio, e.g. \"audio/ogg\".\n * @property {string} refurl - reference to the content. Could be null/undefined.\n * @property {string} bits - base64-encoded audio content. Could be null/undefined.\n * @property {integer} duration - duration of the record in milliseconds.\n * @property {string} preview - base64 encoded short array of amplitude values 0..100.\n * @property {string} filename - file name suggestion for downloading the audio.\n * @property {integer} size - size of the recording in bytes. Treat is as an untrusted hint.\n * @property {Promise} urlPromise - Promise which returns content URL when resolved.\n */\n\n/**\n * Insert audio recording into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add audio record to.\n * @param {integer} at - index where the object is inserted. The length of the record is always 1.\n * @param {AudioDesc} audioDesc - object with the audio paramenets and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertAudio = function(content, at, audioDesc) {\n content = content || {\n txt: ' '\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: 1,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'AU',\n data: {\n mime: audioDesc.mime,\n val: audioDesc.bits,\n duration: audioDesc.duration | 0,\n preview: audioDesc.preview,\n name: audioDesc.filename,\n size: audioDesc.size | 0,\n ref: audioDesc.refurl\n }\n };\n\n if (audioDesc.urlPromise) {\n ex.data._processing = true;\n audioDesc.urlPromise.then(\n url => {\n ex.data.ref = url;\n ex.data._processing = undefined;\n },\n _ => {\n // Catch the error, otherwise it will appear in the console.\n ex.data._processing = undefined;\n }\n );\n }\n\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Create a (self-contained) video call Drafty document.\n * @memberof Drafty\n * @static\n * @param {boolean} audioOnly true if the call is initially audio-only.\n * @returns Video Call drafty document.\n */\nDrafty.videoCall = function(audioOnly) {\n const content = {\n txt: ' ',\n fmt: [{\n at: 0,\n len: 1,\n key: 0\n }],\n ent: [{\n tp: 'VC',\n data: {\n aonly: audioOnly\n },\n }]\n };\n return content;\n}\n\n/**\n * Update video call (VC) entity with the new status and duration.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - VC document to update.\n * @param {object} params - new video call parameters.\n * @param {string} params.state - state of video call.\n * @param {number} params.duration - duration of the video call in milliseconds.\n *\n * @returns the same document with update applied.\n */\nDrafty.updateVideoCall = function(content, params) {\n // The video element could be just a format or a format + entity.\n // Must ensure it's the latter first.\n const fmt = ((content || {}).fmt || [])[0];\n if (!fmt) {\n // Unrecognized content.\n return content;\n }\n\n let ent;\n if (fmt.tp == 'VC') {\n // Just a format, convert to format + entity.\n delete fmt.tp;\n fmt.key = 0;\n ent = {\n tp: 'VC'\n };\n content.ent = [ent];\n } else {\n ent = (content.ent || [])[fmt.key | 0];\n if (!ent || ent.tp != 'VC') {\n // Not a VC entity.\n return content;\n }\n }\n ent.data = ent.data || {};\n Object.assign(ent.data, params);\n return content;\n}\n\n/**\n * Create a quote to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {string} header - Quote header (title, etc.).\n * @param {string} uid - UID of the author to mention.\n * @param {Drafty} body - Body of the quoted message.\n *\n * @returns Reply quote Drafty doc with the quote formatting.\n */\nDrafty.quote = function(header, uid, body) {\n const quote = Drafty.append(Drafty.appendLineBreak(Drafty.mention(header, uid)), body);\n\n // Wrap into a quote.\n quote.fmt.push({\n at: 0,\n len: stringToGraphemes(quote.txt).length,\n tp: 'QQ'\n });\n\n return quote;\n}\n\n/**\n * Create a Drafty document with a mention.\n *\n * @param {string} name - mentioned name.\n * @param {string} uid - mentioned user ID.\n *\n * @returns {Drafty} document with the mention.\n */\nDrafty.mention = function(name, uid) {\n return {\n txt: name || '',\n fmt: [{\n at: 0,\n len: stringToGraphemes(name || '').length,\n key: 0\n }],\n ent: [{\n tp: 'MN',\n data: {\n val: uid\n }\n }]\n };\n}\n\n/**\n * Append a link to a Drafty document.\n *\n * @param {Drafty} content - Drafty document to append link to.\n * @param {Object} linkData - Link info in format {txt: 'ankor text', url: 'http://...'}.\n *\n * @returns {Drafty} the same document as content.\n */\nDrafty.appendLink = function(content, linkData) {\n content = content || {\n txt: ''\n };\n\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: content.txt.length,\n len: linkData.txt.length,\n key: content.ent.length\n });\n content.txt += linkData.txt;\n\n const ex = {\n tp: 'LN',\n data: {\n url: linkData.url\n }\n }\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Append image to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add image to.\n * @param {ImageDesc} imageDesc - object with image paramenets.\n *\n * @return {Drafty} updated document.\n */\nDrafty.appendImage = function(content, imageDesc) {\n content = content || {\n txt: ''\n };\n content.txt += ' ';\n return Drafty.insertImage(content, content.txt.length - 1, imageDesc);\n}\n\n/**\n * Append audio recodring to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add recording to.\n * @param {AudioDesc} audioDesc - object with audio data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.appendAudio = function(content, audioDesc) {\n content = content || {\n txt: ''\n };\n content.txt += ' ';\n return Drafty.insertAudio(content, content.txt.length - 1, audioDesc);\n}\n\n/**\n * Description of a file to attach.\n * @typedef {Object} AttachmentDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the attachment, e.g. \"application/octet-stream\"\n * @property {string} data - base64-encoded in-band content of small attachments. Could be null/undefined.\n * @property {string} filename - file name suggestion for downloading the attachment.\n * @property {integer} size - size of the file in bytes. Treat is as an untrusted hint.\n * @property {string} refurl - reference to the out-of-band content. Could be null/undefined.\n * @property {Promise} urlPromise - Promise which returns content URL when resolved.\n */\n\n/**\n * Attach file to Drafty content. Either as a blob or as a reference.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to attach file to.\n * @param {AttachmentDesc} object - containing attachment description and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.attachFile = function(content, attachmentDesc) {\n content = content || {\n txt: ''\n };\n\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: -1,\n len: 0,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'EX',\n data: {\n mime: attachmentDesc.mime,\n val: attachmentDesc.data,\n name: attachmentDesc.filename,\n ref: attachmentDesc.refurl,\n size: attachmentDesc.size | 0\n }\n }\n if (attachmentDesc.urlPromise) {\n ex.data._processing = true;\n attachmentDesc.urlPromise.then(\n url => {\n ex.data.ref = url;\n ex.data._processing = undefined;\n },\n _ => {\n /* catch the error, otherwise it will appear in the console. */\n ex.data._processing = undefined;\n }\n );\n }\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Wraps drafty document into a simple formatting style.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - document or string to wrap into a style.\n * @param {string} style - two-letter style to wrap into.\n * @param {number} at - index where the style starts, default 0.\n * @param {number} len - length of the form content, default all of it.\n *\n * @return {Drafty} updated document.\n */\nDrafty.wrapInto = function(content, style, at, len) {\n if (typeof content == 'string') {\n content = {\n txt: content\n };\n }\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at || 0,\n len: len || content.txt.length,\n tp: style,\n });\n\n return content;\n}\n\n/**\n * Wraps content into an interactive form.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - to wrap into a form.\n * @param {number} at - index where the forms starts.\n * @param {number} len - length of the form content.\n *\n * @return {Drafty} updated document.\n */\nDrafty.wrapAsForm = function(content, at, len) {\n return Drafty.wrapInto(content, 'FM', at, len);\n}\n\n/**\n * Insert clickable button into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - Drafty document to insert button to or a string to be used as button text.\n * @param {number} at - location where the button is inserted.\n * @param {number} len - the length of the text to be used as button title.\n * @param {string} name - the button. Client should return it to the server when the button is clicked.\n * @param {string} actionType - the type of the button, one of 'url' or 'pub'.\n * @param {string} actionValue - the value to return on click:\n * @param {string} refUrl - the URL to go to when the 'url' button is clicked.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertButton = function(content, at, len, name, actionType, actionValue, refUrl) {\n if (typeof content == 'string') {\n content = {\n txt: content\n };\n }\n\n if (!content || !content.txt || content.txt.length < at + len) {\n return null;\n }\n\n if (len <= 0 || ['url', 'pub'].indexOf(actionType) == -1) {\n return null;\n }\n // Ensure refUrl is a string.\n if (actionType == 'url' && !refUrl) {\n return null;\n }\n refUrl = '' + refUrl;\n\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: len,\n key: content.ent.length\n });\n content.ent.push({\n tp: 'BN',\n data: {\n act: actionType,\n val: actionValue,\n ref: refUrl,\n name: name\n }\n });\n\n return content;\n}\n\n/**\n * Append clickable button to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - Drafty document to insert button to or a string to be used as button text.\n * @param {string} title - the text to be used as button title.\n * @param {string} name - the button. Client should return it to the server when the button is clicked.\n * @param {string} actionType - the type of the button, one of 'url' or 'pub'.\n * @param {string} actionValue - the value to return on click:\n * @param {string} refUrl - the URL to go to when the 'url' button is clicked.\n *\n * @return {Drafty} updated document.\n */\nDrafty.appendButton = function(content, title, name, actionType, actionValue, refUrl) {\n content = content || {\n txt: ''\n };\n const at = content.txt.length;\n content.txt += title;\n return Drafty.insertButton(content, at, title.length, name, actionType, actionValue, refUrl);\n}\n\n/**\n * Attach a generic JS object. The object is attached as a json string.\n * Intended for representing a form response.\n *\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - Drafty document to attach file to.\n * @param {Object} data - data to convert to json string and attach.\n * @returns {Drafty} the same document as content.\n */\nDrafty.attachJSON = function(content, data) {\n content = content || {\n txt: ''\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: -1,\n len: 0,\n key: content.ent.length\n });\n\n content.ent.push({\n tp: 'EX',\n data: {\n mime: JSON_MIME_TYPE,\n val: data\n }\n });\n\n return content;\n}\n/**\n * Append line break to a Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - Drafty document to append linebreak to.\n * @returns {Drafty} the same document as content.\n */\nDrafty.appendLineBreak = function(content) {\n content = content || {\n txt: ''\n };\n content.fmt = content.fmt || [];\n content.fmt.push({\n at: stringToGraphemes(content.txt).length,\n len: 1,\n tp: 'BR'\n });\n content.txt += ' ';\n\n return content;\n}\n/**\n * Given Drafty document, convert it to HTML.\n * No attempt is made to strip pre-existing html markup.\n * This is potentially unsafe because content.txt may contain malicious HTML\n * markup.\n * @memberof Tinode.Drafty\n * @static\n *\n * @param {Drafty} doc - document to convert.\n *\n * @returns {string} HTML-representation of content.\n */\nDrafty.UNSAFE_toHTML = function(doc) {\n const tree = draftyToTree(doc);\n const htmlFormatter = function(type, data, values) {\n const tag = DECORATORS[type];\n let result = values ? values.join('') : '';\n if (tag) {\n result = tag.open(data) + result + tag.close(data);\n }\n return result;\n };\n return treeBottomUp(tree, htmlFormatter, 0);\n}\n\n/**\n * Callback for applying custom formatting to a Drafty document.\n * Called once for each style span.\n * @memberof Drafty\n * @static\n *\n * @callback Formatter\n * @param {string} style - style code such as \"ST\" or \"IM\".\n * @param {Object} data - entity's data.\n * @param {Object} values - possibly styled subspans contained in this style span.\n * @param {number} index - index of the element guaranteed to be unique.\n */\n\n/**\n * Convert Drafty document to a representation suitable for display.\n * The context may expose a function getFormatter(style). If it's available\n * it will call it to obtain a formatter for a subtree of styles under the style.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|Object} content - Drafty document to transform.\n * @param {Formatter} formatter - callback which formats individual elements.\n * @param {Object} context - context provided to formatter as this.\n *\n * @return {Object} transformed object\n */\nDrafty.format = function(original, formatter, context) {\n return treeBottomUp(draftyToTree(original), formatter, 0, [], context);\n}\n\n/**\n * Shorten Drafty document making the drafty text no longer than the limit.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @param {number} limit - length in characrets to shorten to.\n * @param {boolean} light - remove heavy data from entities.\n * @returns new shortened Drafty object leaving the original intact.\n */\nDrafty.shorten = function(original, limit, light) {\n let tree = draftyToTree(original);\n tree = shortenTree(tree, limit, '…');\n if (tree && light) {\n tree = lightEntity(tree);\n }\n return treeToDrafty({}, tree, []);\n}\n\n/**\n * Transform Drafty doc for forwarding: strip leading @mention and any leading line breaks or whitespace.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @returns converted Drafty object leaving the original intact.\n */\nDrafty.forwardedContent = function(original) {\n let tree = draftyToTree(original);\n const rmMention = function(node) {\n if (node.type == 'MN') {\n if (!node.parent || !node.parent.type) {\n return null;\n }\n }\n return node;\n }\n // Strip leading mention.\n tree = treeTopDown(tree, rmMention);\n // Remove leading whitespace.\n tree = lTrim(tree);\n // Convert back to Drafty.\n return treeToDrafty({}, tree, []);\n}\n\n/**\n * Prepare Drafty doc for wrapping into QQ as a reply:\n * - Replace forwarding mention with symbol '➦' and remove data (UID).\n * - Remove quoted text completely.\n * - Replace line breaks with spaces.\n * - Strip entities of heavy content.\n * - Move attachments to the end of the document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @param {number} limit - length in characters to shorten to.\n * @returns converted Drafty object leaving the original intact.\n */\nDrafty.replyContent = function(original, limit) {\n const convMNnQQnBR = function(node) {\n if (node.type == 'QQ') {\n return null;\n } else if (node.type == 'MN') {\n if ((!node.parent || !node.parent.type) && (node.text || '').startsWith('➦')) {\n node.text = '➦';\n delete node.children;\n delete node.data;\n }\n } else if (node.type == 'BR') {\n node.text = ' ';\n delete node.type;\n delete node.children;\n }\n return node;\n }\n\n let tree = draftyToTree(original);\n if (!tree) {\n return original;\n }\n\n // Strip leading mention.\n tree = treeTopDown(tree, convMNnQQnBR);\n // Move attachments to the end of the doc.\n tree = attachmentsToEnd(tree, MAX_PREVIEW_ATTACHMENTS);\n // Shorten the doc.\n tree = shortenTree(tree, limit, '…');\n // Strip heavy elements except IM.data['val'] and VD.data['preview'] (have to keep them to generate previews later).\n const filter = node => {\n switch (node.type) {\n case 'IM':\n return ['val'];\n case 'VD':\n return ['preview'];\n }\n return null;\n };\n tree = lightEntity(tree, filter);\n // Convert back to Drafty.\n return treeToDrafty({}, tree, []);\n}\n\n\n/**\n * Generate drafty preview:\n * - Shorten the document.\n * - Strip all heavy entity data leaving just inline styles and entity references.\n * - Replace line breaks with spaces.\n * - Replace content of QQ with a space.\n * - Replace forwarding mention with symbol '➦'.\n * move all attachments to the end of the document and make them visible.\n * The context may expose a function getFormatter(style). If it's available\n * it will call it to obtain a formatter for a subtree of styles under the style.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @param {number} limit - length in characters to shorten to.\n * @param {boolean} forwarding - this a forwarding message preview.\n * @returns new shortened Drafty object leaving the original intact.\n */\nDrafty.preview = function(original, limit, forwarding) {\n let tree = draftyToTree(original);\n\n // Move attachments to the end.\n tree = attachmentsToEnd(tree, MAX_PREVIEW_ATTACHMENTS);\n\n // Convert leading mention to '➦' and replace QQ and BR with a space ' '.\n const convMNnQQnBR = function(node) {\n if (node.type == 'MN') {\n if ((!node.parent || !node.parent.type) && (node.text || '').startsWith('➦')) {\n node.text = '➦';\n delete node.children;\n }\n } else if (node.type == 'QQ') {\n node.text = ' ';\n delete node.children;\n } else if (node.type == 'BR') {\n node.text = ' ';\n delete node.children;\n delete node.type;\n }\n return node;\n }\n tree = treeTopDown(tree, convMNnQQnBR);\n\n tree = shortenTree(tree, limit, '…');\n if (forwarding) {\n // Keep some IM and VD data for preview.\n const filter = {\n IM: ['val'],\n VD: ['preview']\n };\n tree = lightEntity(tree, node => {\n return filter[node.type];\n });\n } else {\n tree = lightEntity(tree);\n }\n\n // Convert back to Drafty.\n return treeToDrafty({}, tree, []);\n}\n\n/**\n * Given Drafty document, convert it to plain text.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to convert to plain text.\n * @returns {string} plain-text representation of the drafty document.\n */\nDrafty.toPlainText = function(content) {\n return typeof content == 'string' ? content : content.txt;\n}\n\n/**\n * Check if the document has no markup and no entities.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - content to check for presence of markup.\n * @returns true is content is plain text, false otherwise.\n */\nDrafty.isPlainText = function(content) {\n return typeof content == 'string' || !(content.fmt || content.ent);\n}\n\n/**\n * Convert document to plain text with markdown. All elements which cannot\n * be represented in markdown are stripped.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to convert to plain text with markdown.\n */\nDrafty.toMarkdown = function(content) {\n let tree = draftyToTree(content);\n const mdFormatter = function(type, _, values) {\n const def = FORMAT_TAGS[type];\n let result = (values ? values.join('') : '');\n if (def) {\n if (def.isVoid) {\n result = def.md_tag || '';\n } else if (def.md_tag) {\n result = def.md_tag + result + def.md_tag;\n }\n }\n return result;\n };\n return treeBottomUp(tree, mdFormatter, 0);\n}\n\n/**\n * Checks if the object represets is a valid Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - content to check for validity.\n * @returns true is content is valid, false otherwise.\n */\nDrafty.isValid = function(content) {\n if (!content) {\n return false;\n }\n\n const {\n txt,\n fmt,\n ent\n } = content;\n\n if (!txt && txt !== '' && !fmt && !ent) {\n return false;\n }\n\n const txt_type = typeof txt;\n if (txt_type != 'string' && txt_type != 'undefined' && txt !== null) {\n return false;\n }\n\n if (typeof fmt != 'undefined' && !Array.isArray(fmt) && fmt !== null) {\n return false;\n }\n\n if (typeof ent != 'undefined' && !Array.isArray(ent) && ent !== null) {\n return false;\n }\n return true;\n}\n\n/**\n * Check if the drafty document has attachments: style EX and outside of normal rendering flow,\n * i.e. at = -1.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to check for attachments.\n * @returns true if there are attachments.\n */\nDrafty.hasAttachments = function(content) {\n if (!Array.isArray(content.fmt)) {\n return false;\n }\n for (let i in content.fmt) {\n const fmt = content.fmt[i];\n if (fmt && fmt.at < 0) {\n const ent = content.ent[fmt.key | 0];\n return ent && ent.tp == 'EX' && ent.data;\n }\n }\n return false;\n}\n\n/**\n * Callback for enumerating entities in a Drafty document.\n * Called once for each entity.\n * @memberof Drafty\n * @static\n *\n * @callback EntityCallback\n * @param {Object} data entity data.\n * @param {string} entity type.\n * @param {number} index entity's index in `content.ent`.\n *\n * @return 'true-ish' to stop processing, 'false-ish' otherwise.\n */\n\n/**\n * Enumerate attachments: style EX and outside of normal rendering flow, i.e. at = -1.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to process for attachments.\n * @param {EntityCallback} callback - callback to call for each attachment.\n * @param {Object} context - value of \"this\" for callback.\n */\nDrafty.attachments = function(content, callback, context) {\n if (!Array.isArray(content.fmt)) {\n return;\n }\n let count = 0;\n for (let i in content.fmt) {\n let fmt = content.fmt[i];\n if (fmt && fmt.at < 0) {\n const ent = content.ent[fmt.key | 0];\n if (ent && ent.tp == 'EX' && ent.data) {\n if (callback.call(context, ent.data, count++, 'EX')) {\n break;\n }\n }\n }\n };\n}\n\n/**\n * Check if the drafty document has entities.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to check for entities.\n * @returns true if there are entities.\n */\nDrafty.hasEntities = function(content) {\n return content.ent && content.ent.length > 0;\n}\n\n/**\n * Enumerate entities. Enumeration stops if callback returns 'true'.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document with entities to enumerate.\n * @param {EntityCallback} callback - callback to call for each entity.\n * @param {Object} context - value of \"this\" for callback.\n *\n */\nDrafty.entities = function(content, callback, context) {\n if (content.ent && content.ent.length > 0) {\n for (let i in content.ent) {\n if (content.ent[i]) {\n if (callback.call(context, content.ent[i].data, i, content.ent[i].tp)) {\n break;\n }\n }\n }\n }\n}\n\n/**\n * Callback for enumerating styles (inline formats) in a Drafty document.\n * Called once for each style.\n * @memberof Drafty\n * @static\n *\n * @callback StyleCallback\n * @param {string} tp - format type.\n * @param {number} at - starting position of the format in text.\n * @param {number} len - extent of the format in characters.\n * @param {number} key - index of the entity if format is a reference.\n * @param {number} index - style's index in `content.fmt`.\n *\n * @return 'true-ish' to stop processing, 'false-ish' otherwise.\n */\n\n/**\n * Enumerate styles (inline formats). Enumeration stops if callback returns 'true'.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document with styles (formats) to enumerate.\n * @param {StyleCallback} callback - callback to call for each format.\n * @param {Object} context - value of \"this\" for callback.\n */\nDrafty.styles = function(content, callback, context) {\n if (content.fmt && content.fmt.length > 0) {\n for (let i in content.fmt) {\n const fmt = content.fmt[i];\n if (fmt) {\n if (callback.call(context, fmt.tp, fmt.at, fmt.len, fmt.key, i)) {\n break;\n }\n }\n }\n }\n}\n\n/**\n * Remove unrecognized fields from entity data\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document with entities to enumerate.\n * @returns content.\n */\nDrafty.sanitizeEntities = function(content) {\n if (content && content.ent && content.ent.length > 0) {\n for (let i in content.ent) {\n const ent = content.ent[i];\n if (ent && ent.data) {\n const data = copyEntData(ent.data);\n if (data) {\n content.ent[i].data = data;\n } else {\n delete content.ent[i].data;\n }\n }\n }\n }\n return content;\n}\n\n/**\n * Given the entity, get URL which can be used for downloading\n * entity data.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entData - entity.data to get the URl from.\n * @returns {string} URL to download entity data or null.\n */\nDrafty.getDownloadUrl = function(entData) {\n let url = null;\n if (entData.mime != JSON_MIME_TYPE && entData.mime != JSON_MIME_TYPE_LEGACY && entData.val) {\n url = base64toObjectUrl(entData.val, entData.mime, Drafty.logger);\n } else if (typeof entData.ref == 'string') {\n url = entData.ref;\n }\n return url;\n}\n\n/**\n * Check if the entity data is not ready for sending, such as being uploaded to the server.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entity.data to get the URl from.\n * @returns {boolean} true if upload is in progress, false otherwise.\n */\nDrafty.isProcessing = function(entData) {\n return !!entData._processing;\n}\n\n/**\n * Given the entity, get URL which can be used for previewing\n * the entity.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entity.data to get the URl from.\n *\n * @returns {string} url for previewing or null if no such url is available.\n */\nDrafty.getPreviewUrl = function(entData) {\n return entData.val ? base64toObjectUrl(entData.val, entData.mime, Drafty.logger) : null;\n}\n\n/**\n * Get approximate size of the entity.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entData - entity.data to get the size for.\n * @returns {number} size of entity data in bytes.\n */\nDrafty.getEntitySize = function(entData) {\n // Either size hint or length of value. The value is base64 encoded,\n // the actual object size is smaller than the encoded length.\n return entData.size ? entData.size : entData.val ? (entData.val.length * 0.75) | 0 : 0;\n}\n\n/**\n * Get entity mime type.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entData - entity.data to get the type for.\n * @returns {string} mime type of entity.\n */\nDrafty.getEntityMimeType = function(entData) {\n return entData.mime || 'text/plain';\n}\n\n/**\n * Get HTML tag for a given two-letter style name.\n * @memberof Drafty\n * @static\n *\n * @param {string} style - two-letter style, like ST or LN.\n *\n * @returns {string} HTML tag name if style is found, {code: undefined} if style is falsish or not found.\n */\nDrafty.tagName = function(style) {\n return FORMAT_TAGS[style] && FORMAT_TAGS[style].html_tag;\n}\n\n/**\n * For a given data bundle generate an object with HTML attributes,\n * for instance, given {url: \"http://www.example.com/\"} return\n * {href: \"http://www.example.com/\"}\n * @memberof Drafty\n * @static\n *\n * @param {string} style - two-letter style to generate attributes for.\n * @param {Object} data - data bundle to convert to attributes\n *\n * @returns {Object} object with HTML attributes.\n */\nDrafty.attrValue = function(style, data) {\n if (data && DECORATORS[style] && DECORATORS[style].props) {\n return DECORATORS[style].props(data);\n }\n\n return undefined;\n}\n\n/**\n * Drafty MIME type.\n * @memberof Drafty\n * @static\n *\n * @returns {string} content-Type \"text/x-drafty\".\n */\nDrafty.getContentType = function() {\n return DRAFTY_MIME_TYPE;\n}\n\n// =================\n// Utility methods.\n// =================\n\n// Take a string and defined earlier style spans, re-compose them into a tree where each leaf is\n// a same-style (including unstyled) string. I.e. 'hello *bold _italic_* and ~more~ world' ->\n// ('hello ', (b: 'bold ', (i: 'italic')), ' and ', (s: 'more'), ' world');\n//\n// This is needed in order to clear markup, i.e. 'hello *world*' -> 'hello world' and convert\n// ranges from markup-ed offsets to plain text offsets.\nfunction chunkify(line, start, end, spans) {\n const chunks = [];\n\n if (spans.length == 0) {\n return [];\n }\n\n for (let i in spans) {\n // Get the next chunk from the queue\n const span = spans[i];\n\n // Grab the initial unstyled chunk\n if (span.at > start) {\n chunks.push({\n txt: line.slice(start, span.at)\n });\n }\n\n // Grab the styled chunk. It may include subchunks.\n const chunk = {\n tp: span.tp\n };\n const chld = chunkify(line, span.at + 1, span.end, span.children);\n if (chld.length > 0) {\n chunk.children = chld;\n } else {\n chunk.txt = span.txt;\n }\n chunks.push(chunk);\n start = span.end + 1; // '+1' is to skip the formatting character\n }\n\n // Grab the remaining unstyled chunk, after the last span\n if (start < end) {\n chunks.push({\n txt: line.slice(start, end)\n });\n }\n\n return chunks;\n}\n\n// Detect starts and ends of formatting spans. Unformatted spans are\n// ignored at this stage.\nfunction spannify(original, re_start, re_end, type) {\n const result = [];\n let index = 0;\n let line = original.slice(0); // make a copy;\n\n while (line.length > 0) {\n // match[0]; // match, like '*abc*'\n // match[1]; // match captured in parenthesis, like 'abc'\n // match['index']; // offset where the match started.\n\n // Find the opening token.\n const start = re_start.exec(line);\n if (start == null) {\n break;\n }\n\n // Because javascript RegExp does not support lookbehind, the actual offset may not point\n // at the markup character. Find it in the matched string.\n let start_offset = start['index'] + start[0].lastIndexOf(start[1]);\n // Clip the processed part of the string.\n line = line.slice(start_offset + 1);\n // start_offset is an offset within the clipped string. Convert to original index.\n start_offset += index;\n // Index now point to the beginning of 'line' within the 'original' string.\n index = start_offset + 1;\n\n // Find the matching closing token.\n const end = re_end ? re_end.exec(line) : null;\n if (end == null) {\n break;\n }\n let end_offset = end['index'] + end[0].indexOf(end[1]);\n // Clip the processed part of the string.\n line = line.slice(end_offset + 1);\n // Update offsets\n end_offset += index;\n // Index now points to the beginning of 'line' within the 'original' string.\n index = end_offset + 1;\n\n result.push({\n txt: original.slice(start_offset + 1, end_offset),\n children: [],\n at: start_offset,\n end: end_offset,\n tp: type\n });\n }\n\n return result;\n}\n\n// Convert linear array or spans into a tree representation.\n// Keep standalone and nested spans, throw away partially overlapping spans.\nfunction toSpanTree(spans) {\n if (spans.length == 0) {\n return [];\n }\n\n const tree = [spans[0]];\n let last = spans[0];\n for (let i = 1; i < spans.length; i++) {\n // Keep spans which start after the end of the previous span or those which\n // are complete within the previous span.\n if (spans[i].at > last.end) {\n // Span is completely outside of the previous span.\n tree.push(spans[i]);\n last = spans[i];\n } else if (spans[i].end <= last.end) {\n // Span is fully inside of the previous span. Push to subnode.\n last.children.push(spans[i]);\n }\n // Span could partially overlap, ignoring it as invalid.\n }\n\n // Recursively rearrange the subnodes.\n for (let i in tree) {\n tree[i].children = toSpanTree(tree[i].children);\n }\n\n return tree;\n}\n\n// Convert drafty document to a tree.\nfunction draftyToTree(doc) {\n if (!doc) {\n return null;\n }\n\n doc = (typeof doc == 'string') ? {\n txt: doc\n } : doc;\n let {\n txt,\n fmt,\n ent\n } = doc;\n\n txt = txt || '';\n if (!Array.isArray(ent)) {\n ent = [];\n }\n\n if (!Array.isArray(fmt) || fmt.length == 0) {\n if (ent.length == 0) {\n return {\n text: txt\n };\n }\n\n // Handle special case when all values in fmt are 0 and fmt therefore is skipped.\n fmt = [{\n at: 0,\n len: 0,\n key: 0\n }];\n }\n\n // Sanitize spans.\n const spans = [];\n const attachments = [];\n fmt.forEach((span) => {\n if (!span || typeof span != 'object') {\n return;\n }\n\n if (!['undefined', 'number'].includes(typeof span.at)) {\n // Present, but non-numeric 'at'.\n return;\n }\n if (!['undefined', 'number'].includes(typeof span.len)) {\n // Present, but non-numeric 'len'.\n return;\n }\n let at = span.at | 0;\n let len = span.len | 0;\n if (len < 0) {\n // Invalid span length.\n return;\n }\n\n let key = span.key || 0;\n if (ent.length > 0 && (typeof key != 'number' || key < 0 || key >= ent.length)) {\n // Invalid key value.\n return;\n }\n\n if (at <= -1) {\n // Attachment. Store attachments separately.\n attachments.push({\n start: -1,\n end: 0,\n key: key\n });\n return;\n } else if (at + len > stringToGraphemes(txt).length) {\n // Span is out of bounds.\n return;\n }\n\n if (!span.tp) {\n if (ent.length > 0 && (typeof ent[key] == 'object')) {\n spans.push({\n start: at,\n end: at + len,\n key: key\n });\n }\n } else {\n spans.push({\n type: span.tp,\n start: at,\n end: at + len\n });\n }\n });\n\n // Sort spans first by start index (asc) then by length (desc), then by weight.\n spans.sort((a, b) => {\n let diff = a.start - b.start;\n if (diff != 0) {\n return diff;\n }\n diff = b.end - a.end;\n if (diff != 0) {\n return diff;\n }\n return FMT_WEIGHT.indexOf(b.type) - FMT_WEIGHT.indexOf(a.type);\n });\n\n // Move attachments to the end of the list.\n if (attachments.length > 0) {\n spans.push(...attachments);\n }\n\n spans.forEach((span) => {\n if (ent.length > 0 && !span.type && ent[span.key] && typeof ent[span.key] == 'object') {\n span.type = ent[span.key].tp;\n span.data = ent[span.key].data;\n }\n\n // Is type still undefined? Hide the invalid element!\n if (!span.type) {\n span.type = 'HD';\n }\n });\n\n const graphemes = stringToGraphemes(txt);\n let tree = spansToTree({}, graphemes, 0, graphemes.length, spans);\n\n // Flatten tree nodes.\n const flatten = function(node) {\n if (Array.isArray(node.children) && node.children.length == 1) {\n // Unwrap.\n const child = node.children[0];\n if (!node.type) {\n const parent = node.parent;\n node = child;\n node.parent = parent;\n } else if (!child.type && !child.children) {\n node.text = child.text;\n delete node.children;\n }\n }\n return node;\n }\n tree = treeTopDown(tree, flatten);\n\n return tree;\n}\n\n// Add tree node to a parent tree.\nfunction addNode(parent, n) {\n if (!n) {\n return parent;\n }\n\n if (!parent.children) {\n parent.children = [];\n }\n\n // If text is present, move it to a subnode.\n if (parent.text) {\n parent.children.push({\n text: parent.text,\n parent: parent\n });\n delete parent.text;\n }\n\n n.parent = parent;\n parent.children.push(n);\n\n return parent;\n}\n\n// Returns a tree of nodes.\nfunction spansToTree(parent, graphemes, start, end, spans) {\n if (!spans || spans.length == 0) {\n if (start < end) {\n addNode(parent, {\n text: graphemes.slice(start, end)\n .map(segment => segment.segment)\n .join('')\n });\n }\n return parent;\n }\n\n // Process subspans.\n for (let i = 0; i < spans.length; i++) {\n const span = spans[i];\n if (span.start < 0 && span.type == 'EX') {\n addNode(parent, {\n type: span.type,\n data: span.data,\n key: span.key,\n att: true\n });\n continue;\n }\n\n // Add un-styled range before the styled span starts.\n if (start < span.start) {\n addNode(parent, {\n text: graphemes.slice(start, span.start)\n .map(segment => segment.segment)\n .join('')\n });\n start = span.start;\n }\n\n // Get all spans which are within the current span.\n const subspans = [];\n while (i < spans.length - 1) {\n const inner = spans[i + 1];\n if (inner.start < 0) {\n // Attachments are in the end. Stop.\n break;\n } else if (inner.start < span.end) {\n if (inner.end <= span.end) {\n const tag = FORMAT_TAGS[inner.tp] || {};\n if (inner.start < inner.end || tag.isVoid) {\n // Valid subspan: completely within the current span and\n // either non-zero length or zero length is acceptable.\n subspans.push(inner);\n }\n }\n i++;\n // Overlapping subspans are ignored.\n } else {\n // Past the end of the current span. Stop.\n break;\n }\n }\n\n addNode(parent, spansToTree({\n type: span.type,\n data: span.data,\n key: span.key\n }, graphemes, start, span.end, subspans));\n start = span.end;\n }\n\n // Add the last unformatted range.\n if (start < end) {\n addNode(parent, {\n text: graphemes\n .slice(start, end)\n .map((segment) => segment.segment)\n .join('')\n });\n }\n\n return parent;\n}\n\n// Append a tree to a Drafty doc.\nfunction treeToDrafty(doc, tree, keymap) {\n if (!tree) {\n return doc;\n }\n\n doc.txt = doc.txt || '';\n\n // Checkpoint to measure length of the current tree node.\n const start = stringToGraphemes(doc.txt).length;\n\n if (tree.text) {\n doc.txt += tree.text;\n } else if (Array.isArray(tree.children)) {\n tree.children.forEach((c) => {\n treeToDrafty(doc, c, keymap);\n });\n }\n\n if (tree.type) {\n const len = stringToGraphemes(doc.txt).length - start;\n doc.fmt = doc.fmt || [];\n if (Object.keys(tree.data || {}).length > 0) {\n doc.ent = doc.ent || [];\n const newKey = (typeof keymap[tree.key] == 'undefined') ? doc.ent.length : keymap[tree.key];\n keymap[tree.key] = newKey;\n doc.ent[newKey] = {\n tp: tree.type,\n data: tree.data\n };\n if (tree.att) {\n // Attachment.\n doc.fmt.push({\n at: -1,\n len: 0,\n key: newKey\n });\n } else {\n doc.fmt.push({\n at: start,\n len: len,\n key: newKey\n });\n }\n } else {\n doc.fmt.push({\n tp: tree.type,\n at: start,\n len: len\n });\n }\n }\n return doc;\n}\n\n// Traverse the tree top down transforming the nodes: apply transformer to every tree node.\nfunction treeTopDown(src, transformer, context) {\n if (!src) {\n return null;\n }\n\n let dst = transformer.call(context, src);\n if (!dst || !dst.children) {\n return dst;\n }\n\n const children = [];\n for (let i in dst.children) {\n let n = dst.children[i];\n if (n) {\n n = treeTopDown(n, transformer, context);\n if (n) {\n children.push(n);\n }\n }\n }\n\n if (children.length == 0) {\n dst.children = null;\n } else {\n dst.children = children;\n }\n\n return dst;\n}\n\n// Traverse the tree bottom-up: apply formatter to every node.\n// The formatter must maintain its state through context.\nfunction treeBottomUp(src, formatter, index, stack, context) {\n if (!src) {\n return null;\n }\n\n if (stack && src.type) {\n stack.push(src.type);\n }\n\n let values = [];\n for (let i in src.children) {\n const n = treeBottomUp(src.children[i], formatter, i, stack, context);\n if (n) {\n values.push(n);\n }\n }\n if (values.length == 0) {\n if (src.text) {\n values = [src.text];\n } else {\n values = null;\n }\n }\n\n if (stack && src.type) {\n stack.pop();\n }\n\n return formatter.call(context, src.type, src.data, values, index, stack);\n}\n\n// Clip tree to the provided limit.\nfunction shortenTree(tree, limit, tail) {\n if (!tree) {\n return null;\n }\n\n if (tail) {\n limit -= tail.length;\n }\n\n const shortener = function(node) {\n if (limit <= -1) {\n // Limit -1 means the doc was already clipped.\n return null;\n }\n\n if (node.att) {\n // Attachments are unchanged.\n return node;\n }\n if (limit == 0) {\n node.text = tail;\n limit = -1;\n } else if (node.text) {\n const graphemes = stringToGraphemes(node.text);\n if (graphemes.length > limit) {\n node.text = graphemes\n .slice(0, limit)\n .map((segment) => segment.segment)\n .join('') + tail;\n limit = -1;\n } else {\n limit -= graphemes.length;\n }\n }\n return node;\n }\n\n return treeTopDown(tree, shortener);\n}\n\n// Strip heavy entities from a tree.\nfunction lightEntity(tree, allow) {\n const lightCopy = node => {\n const data = copyEntData(node.data, true, allow ? allow(node) : null);\n if (data) {\n node.data = data;\n } else {\n delete node.data;\n }\n return node;\n }\n return treeTopDown(tree, lightCopy);\n}\n\n// Remove spaces and breaks on the left.\nfunction lTrim(tree) {\n if (tree.type == 'BR') {\n tree = null;\n } else if (tree.text) {\n if (!tree.type) {\n tree.text = tree.text.trimStart();\n if (!tree.text) {\n tree = null;\n }\n }\n } else if (!tree.type && tree.children && tree.children.length > 0) {\n const c = lTrim(tree.children[0]);\n if (c) {\n tree.children[0] = c;\n } else {\n tree.children.shift();\n if (!tree.type && tree.children.length == 0) {\n tree = null;\n }\n }\n }\n return tree;\n}\n\n// Move attachments to the end. Attachments must be at the top level, no need to traverse the tree.\nfunction attachmentsToEnd(tree, limit) {\n if (!tree) {\n return null;\n }\n\n if (tree.att) {\n tree.text = ' ';\n delete tree.att;\n delete tree.children;\n } else if (tree.children) {\n const attachments = [];\n const children = [];\n for (let i in tree.children) {\n const c = tree.children[i];\n if (c.att) {\n if (attachments.length == limit) {\n // Too many attachments to preview;\n continue;\n }\n if (c.data['mime'] == JSON_MIME_TYPE || c.data['mime'] == JSON_MIME_TYPE_LEGACY) {\n // JSON attachments are not shown in preview.\n continue;\n }\n\n delete c.att;\n delete c.children;\n c.text = ' ';\n attachments.push(c);\n } else {\n children.push(c);\n }\n }\n tree.children = children.concat(attachments);\n }\n return tree;\n}\n\n// Get a list of entities from a text.\nfunction extractEntities(line) {\n let match;\n let extracted = [];\n ENTITY_TYPES.forEach((entity) => {\n while ((match = entity.re.exec(line)) !== null) {\n extracted.push({\n offset: match['index'],\n len: match[0].length,\n unique: match[0],\n data: entity.pack(match[0]),\n type: entity.name\n });\n }\n });\n\n if (extracted.length == 0) {\n return extracted;\n }\n\n // Remove entities detected inside other entities, like #hashtag in a URL.\n extracted.sort((a, b) => {\n return a.offset - b.offset;\n });\n\n let idx = -1;\n extracted = extracted.filter((el) => {\n const result = (el.offset > idx);\n idx = el.offset + el.len;\n return result;\n });\n\n return extracted;\n}\n\n// Convert the chunks into format suitable for serialization.\nfunction draftify(chunks, startAt) {\n let plain = '';\n let ranges = [];\n for (let i in chunks) {\n const chunk = chunks[i];\n if (!chunk.txt) {\n const drafty = draftify(chunk.children, plain.length + startAt);\n chunk.txt = drafty.txt;\n ranges = ranges.concat(drafty.fmt);\n }\n\n if (chunk.tp) {\n ranges.push({\n at: plain.length + startAt,\n len: chunk.txt.length,\n tp: chunk.tp\n });\n }\n\n plain += chunk.txt;\n }\n return {\n txt: plain,\n fmt: ranges\n };\n}\n\n// Create a copy of entity data with (light=false) or without (light=true) the large payload.\n// The array 'allow' contains a list of fields exempt from stripping.\nfunction copyEntData(data, light, allow) {\n if (data && Object.entries(data).length > 0) {\n allow = allow || [];\n const dc = {};\n ALLOWED_ENT_FIELDS.forEach(key => {\n if (data[key]) {\n if (light && !allow.includes(key) &&\n (typeof data[key] == 'string' || Array.isArray(data[key])) &&\n data[key].length > MAX_PREVIEW_DATA_SIZE) {\n return;\n }\n if (typeof data[key] == 'object') {\n return;\n }\n dc[key] = data[key];\n }\n });\n\n if (Object.entries(dc).length != 0) {\n return dc;\n }\n }\n return null;\n}\n\n// Returns true if object is empty, if undefined returns true\nfunction isEmptyObject(obj) {\n return Object.keys(obj ?? {}).length == 0;\n};\n\n\n// Returns an array (of length equal to the length of the original string) such that each index\n// denotes the position of char in string in a grapheme array (created from that string)\n// Eg: string: \"Hi👋🏼Hi\" -> [0,1,2,2,2,2,3,4]\nfunction graphemeIndices(graphemes) {\n const result = [];\n let graphemeIndex = 0;\n let charIndex = 0;\n\n // Iterate over the grapheme clusters.\n for (const {\n segment\n }\n of graphemes) {\n // Map the character indices to the grapheme index.\n for (let i = 0; i < segment.length; i++) {\n result[charIndex + i] = graphemeIndex;\n }\n\n // Increment the character index by the length of the grapheme cluster.\n charIndex += segment.length;\n\n // Increment the grapheme index.\n graphemeIndex++;\n }\n\n return result;\n}\n\n// Convert fmt.at and fmt.len from character-expressed index and length to grapheme-expressed\n// index and length.\nfunction toGraphemeValues(fmt, segments, txt) {\n segments = segments ?? segmenter.segment(txt);\n\n const indices = graphemeIndices(segments);\n\n const correctAt = indices[fmt.at];\n const correctLen = fmt.at + fmt.len <= txt.length ?\n indices[fmt.at + fmt.len - 1] - correctAt : fmt.len;\n\n return {\n at: correctAt,\n len: correctLen + 1\n };\n}\n\n// Convert string to graphme cluster array.\nfunction stringToGraphemes(str) {\n return Array.from(segmenter.segment(str));\n}\n\nif (typeof module != 'undefined') {\n module.exports = Drafty;\n}\n","/**\n * @file Definition of 'fnd' topic.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport * as Const from './config.js';\nimport Topic from './topic.js';\nimport {\n mergeToCache\n} from './utils.js';\n\n\n/**\n * Special case of {@link Tinode.Topic} for searching for contacts and group topics\n * @extends Tinode.Topic\n *\n */\nexport default class TopicFnd extends Topic {\n // List of users and topics uid or topic_name -> Contact object)\n _contacts = {};\n\n /**\n * Create TopicFnd.\n *\n * @param {TopicFnd.Callbacks} callbacks - Callbacks to receive various events.\n */\n constructor(callbacks) {\n super(Const.TOPIC_FND, callbacks);\n }\n\n // Override the original Topic._processMetaSubs\n _processMetaSubs(subs) {\n let updateCount = Object.getOwnPropertyNames(this._contacts).length;\n // Reset contact list.\n this._contacts = {};\n for (let idx in subs) {\n let sub = subs[idx];\n const indexBy = sub.topic ? sub.topic : sub.user;\n\n sub = mergeToCache(this._contacts, indexBy, sub);\n updateCount++;\n\n if (this.onMetaSub) {\n this.onMetaSub(sub);\n }\n }\n\n if (updateCount > 0 && this.onSubsUpdated) {\n this.onSubsUpdated(Object.keys(this._contacts));\n }\n }\n\n /**\n * Publishing to TopicFnd is not supported. {@link Topic#publish} is overriden and thows an {Error} if called.\n * @memberof Tinode.TopicFnd#\n * @throws {Error} Always throws an error.\n */\n publish() {\n return Promise.reject(new Error(\"Publishing to 'fnd' is not supported\"));\n }\n\n /**\n * setMeta to TopicFnd resets contact list in addition to sending the message.\n * @memberof Tinode.TopicFnd#\n * @param {Tinode.SetParams} params parameters to update.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n setMeta(params) {\n return Object.getPrototypeOf(TopicFnd.prototype).setMeta.call(this, params).then(_ => {\n if (Object.keys(this._contacts).length > 0) {\n this._contacts = {};\n if (this.onSubsUpdated) {\n this.onSubsUpdated([]);\n }\n }\n });\n }\n\n /**\n * Check if the given tag is unique by asking the server.\n * @param tag tag to check.\n * @return promise to be resolved with true if the tag is unique, false otherwise.\n */\n checkTagUniqueness(tag, caller) {\n return new Promise((resolve, reject) => {\n this.subscribe()\n .then(_ => this.setMeta({\n desc: {\n public: tag\n }\n }))\n .then(_ => this.getMeta(this.startMetaQuery().withTags().build()))\n .then(meta => {\n if (!meta || !Array.isArray(meta.tags) || meta.tags.length == 0) {\n resolve(true);\n }\n const tags = meta.tags.filter(t => t !== caller);\n resolve(tags.length == 0);\n })\n .catch(err => {\n reject(err);\n });\n });\n }\n\n /**\n * Iterate over found contacts. If callback is undefined, use {@link this.onMetaSub}.\n * @function\n * @memberof Tinode.TopicFnd#\n * @param {TopicFnd.ContactCallback} callback - Callback to call for each contact.\n * @param {Object} context - Context to use for calling the `callback`, i.e. the value of `this` inside the callback.\n */\n contacts(callback, context) {\n const cb = (callback || this.onMetaSub);\n if (cb) {\n for (let idx in this._contacts) {\n cb.call(context, this._contacts[idx], idx, this._contacts);\n }\n }\n }\n}\n","/**\n * @file Utilities for uploading and downloading files.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport CommError from './comm-error.js';\nimport {\n isUrlRelative,\n jsonParseHelper\n} from './utils.js';\n\nlet XHRProvider;\n\nfunction addURLParam(relUrl, key, value) {\n const url = new URL(relUrl, window.location.origin);\n url.searchParams.append(key, value);\n return url.toString().substring(window.location.origin.length);\n}\n\n/**\n * @class LargeFileHelper - utilities for uploading and downloading files out of band.\n * Don't instantiate this class directly. Use {Tinode.getLargeFileHelper} instead.\n * @memberof Tinode\n *\n * @param {Tinode} tinode - the main Tinode object.\n * @param {string} version - protocol version, i.e. '0'.\n */\nexport default class LargeFileHelper {\n constructor(tinode, version) {\n this._tinode = tinode;\n this._version = version;\n\n this._apiKey = tinode._apiKey;\n this._authToken = tinode.getAuthToken();\n\n // Ongoing requests.\n this.xhr = [];\n }\n\n /**\n * Start uploading the file to an endpoint at baseUrl.\n *\n * @memberof Tinode.LargeFileHelper#\n *\n * @param {string} baseUrl base URL of upload server.\n * @param {File|Blob} data data to upload.\n * @param {string} avatarFor topic name if the upload represents an avatar.\n * @param {Callback} onProgress callback. Takes one {float} parameter 0..1\n * @param {Callback} onSuccess callback. Called when the file is successfully uploaded.\n * @param {Callback} onFailure callback. Called in case of a failure.\n *\n * @returns {Promise} resolved/rejected when the upload is completed/failed.\n */\n uploadWithBaseUrl(baseUrl, data, avatarFor, onProgress, onSuccess, onFailure) {\n let url = `/v${this._version}/file/u/`;\n if (baseUrl) {\n let base = baseUrl;\n if (base.endsWith('/')) {\n // Removing trailing slash.\n base = base.slice(0, -1);\n }\n if (base.startsWith('http://') || base.startsWith('https://')) {\n url = base + url;\n } else {\n throw new Error(`Invalid base URL '${baseUrl}'`);\n }\n }\n\n const instance = this;\n const xhr = new XHRProvider();\n this.xhr.push(xhr);\n\n xhr.open('POST', url, true);\n xhr.setRequestHeader('X-Tinode-APIKey', this._apiKey);\n if (this._authToken) {\n xhr.setRequestHeader('X-Tinode-Auth', `Token ${this._authToken.token}`);\n }\n\n let toResolve = null;\n let toReject = null;\n\n const result = new Promise((resolve, reject) => {\n toResolve = resolve;\n toReject = reject;\n });\n\n xhr.upload.onprogress = e => {\n if (e.lengthComputable) {\n if (onProgress) {\n onProgress(e.loaded / e.total);\n }\n if (this.onProgress) {\n this.onProgress(e.loaded / e.total);\n }\n }\n };\n\n xhr.onload = function() {\n let pkt;\n try {\n pkt = JSON.parse(this.response, jsonParseHelper);\n } catch (err) {\n instance._tinode.logger(\"ERROR: Invalid server response in LargeFileHelper\", this.response);\n pkt = {\n ctrl: {\n code: this.status,\n text: this.statusText\n }\n };\n }\n\n if (this.status >= 200 && this.status < 300) {\n if (toResolve) {\n toResolve(pkt.ctrl.params.url);\n }\n if (onSuccess) {\n onSuccess(pkt.ctrl);\n }\n } else if (this.status >= 400) {\n if (toReject) {\n toReject(new CommError(pkt.ctrl.text, pkt.ctrl.code));\n }\n if (onFailure) {\n onFailure(pkt.ctrl);\n }\n } else {\n instance._tinode.logger(\"ERROR: Unexpected server response status\", this.status, this.response);\n }\n };\n\n xhr.onerror = function(e) {\n if (toReject) {\n toReject(e || new Error(\"failed\"));\n }\n if (onFailure) {\n onFailure(null);\n }\n };\n\n xhr.onabort = function(e) {\n if (toReject) {\n toReject(new Error(\"upload cancelled by user\"));\n }\n if (onFailure) {\n onFailure(null);\n }\n };\n\n try {\n const form = new FormData();\n form.append('file', data);\n form.set('id', this._tinode.getNextUniqueId());\n if (avatarFor) {\n form.set('topic', avatarFor);\n }\n xhr.send(form);\n } catch (err) {\n if (toReject) {\n toReject(err);\n }\n if (onFailure) {\n onFailure(null);\n }\n }\n\n return result;\n }\n /**\n * Start uploading the file to default endpoint.\n *\n * @memberof Tinode.LargeFileHelper#\n *\n * @param {File|Blob} data to upload\n * @param {string} avatarFor topic name if the upload represents an avatar.\n * @param {Callback} onProgress callback. Takes one {float} parameter 0..1\n * @param {Callback} onSuccess callback. Called when the file is successfully uploaded.\n * @param {Callback} onFailure callback. Called in case of a failure.\n *\n * @returns {Promise} resolved/rejected when the upload is completed/failed.\n */\n upload(data, avatarFor, onProgress, onSuccess, onFailure) {\n const baseUrl = (this._tinode._secure ? 'https://' : 'http://') + this._tinode._host;\n return this.uploadWithBaseUrl(baseUrl, data, avatarFor, onProgress, onSuccess, onFailure);\n }\n /**\n * Download the file from a given URL using GET request. This method works with the Tinode server only.\n *\n * @memberof Tinode.LargeFileHelper#\n *\n * @param {string} relativeUrl - URL to download the file from. Must be relative url, i.e. must not contain the host.\n * @param {string=} filename - file name to use for the downloaded file.\n *\n * @returns {Promise} resolved/rejected when the download is completed/failed.\n */\n download(relativeUrl, filename, mimetype, onProgress, onError) {\n if (!isUrlRelative(relativeUrl)) {\n // As a security measure refuse to download from an absolute URL.\n if (onError) {\n onError(`The URL '${relativeUrl}' must be relative, not absolute`);\n }\n return;\n }\n if (!this._authToken) {\n if (onError) {\n onError(\"Must authenticate first\");\n }\n return;\n }\n const instance = this;\n\n const xhr = new XHRProvider();\n this.xhr.push(xhr);\n\n // Add '&asatt=1' to URL to request 'Content-Disposition: attachment' response header.\n relativeUrl = addURLParam(relativeUrl, 'asatt', '1');\n\n // Get data as blob (stored by the browser as a temporary file).\n xhr.open('GET', relativeUrl, true);\n xhr.setRequestHeader('X-Tinode-APIKey', this._apiKey);\n xhr.setRequestHeader('X-Tinode-Auth', 'Token ' + this._authToken.token);\n xhr.responseType = 'blob';\n\n xhr.onprogress = function(e) {\n if (onProgress) {\n // Passing e.loaded instead of e.loaded/e.total because e.total\n // is always 0 with gzip compression enabled by the server.\n onProgress(e.loaded);\n }\n };\n\n let toResolve = null;\n let toReject = null;\n\n const result = new Promise((resolve, reject) => {\n toResolve = resolve;\n toReject = reject;\n });\n\n // The blob needs to be saved as file. There is no known way to\n // save the blob as file other than to fake a click on an .\n xhr.onload = function() {\n if (this.status == 200) {\n const link = document.createElement('a');\n // URL.createObjectURL is not available in non-browser environment. This call will fail.\n link.href = window.URL.createObjectURL(new Blob([this.response], {\n type: mimetype\n }));\n link.style.display = 'none';\n link.setAttribute('download', filename);\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n window.URL.revokeObjectURL(link.href);\n if (toResolve) {\n toResolve();\n }\n } else if (this.status >= 400 && toReject) {\n // The this.responseText is undefined, must use this.response which is a blob.\n // Need to convert this.response to JSON. The blob can only be accessed by the\n // FileReader.\n const reader = new FileReader();\n reader.onload = function() {\n try {\n const pkt = JSON.parse(this.result, jsonParseHelper);\n toReject(new CommError(pkt.ctrl.text, pkt.ctrl.code));\n } catch (err) {\n instance._tinode.logger(\"ERROR: Invalid server response in LargeFileHelper\", this.result);\n toReject(err);\n }\n };\n reader.readAsText(this.response);\n }\n };\n\n xhr.onerror = function(e) {\n if (toReject) {\n toReject(new Error(\"failed\"));\n }\n if (onError) {\n onError(e);\n }\n };\n\n xhr.onabort = function() {\n if (toReject) {\n toReject(null);\n }\n };\n\n try {\n xhr.send();\n } catch (err) {\n if (toReject) {\n toReject(err);\n }\n if (onError) {\n onError(err);\n }\n }\n\n return result;\n }\n /**\n * Try to cancel all ongoing uploads or downloads.\n * @memberof Tinode.LargeFileHelper#\n */\n cancel() {\n this.xhr.forEach(req => {\n if (req.readyState < 4) {\n req.abort();\n }\n });\n }\n /**\n * To use LargeFileHelper in a non browser context, supply XMLHttpRequest provider.\n * @static\n * @memberof LargeFileHelper\n * @param xhrProvider XMLHttpRequest provider, e.g. for node require('xhr').\n */\n static setNetworkProvider(xhrProvider) {\n XHRProvider = xhrProvider;\n }\n}\n","/**\n * @file Definition of 'me' topic.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport AccessMode from './access-mode.js';\nimport * as Const from './config.js';\nimport Topic from './topic.js';\nimport {\n mergeObj\n} from './utils.js';\n\n/**\n * @class TopicMe - special case of {@link Tinode.Topic} for\n * managing data of the current user, including contact list.\n * @extends Tinode.Topic\n * @memberof Tinode\n *\n * @param {TopicMe.Callbacks} callbacks - Callbacks to receive various events.\n */\nexport default class TopicMe extends Topic {\n onContactUpdate;\n\n constructor(callbacks) {\n super(Const.TOPIC_ME, callbacks);\n\n // me-specific callbacks\n if (callbacks) {\n this.onContactUpdate = callbacks.onContactUpdate;\n }\n }\n\n // Override the original Topic._processMetaDesc.\n _processMetaDesc(desc) {\n // Check if online contacts need to be turned off because P permission was removed.\n const turnOff = (desc.acs && !desc.acs.isPresencer()) && (this.acs && this.acs.isPresencer());\n\n // Copy parameters from desc object to this topic.\n mergeObj(this, desc);\n this._tinode._db.updTopic(this);\n // Update current user's record in the global cache.\n this._updateCachedUser(this._tinode._myUID, desc);\n\n // 'P' permission was removed. All topics are offline now.\n if (turnOff) {\n this._tinode.mapTopics((cont) => {\n if (cont.online) {\n cont.online = false;\n cont.seen = Object.assign(cont.seen || {}, {\n when: new Date()\n });\n this._refreshContact('off', cont);\n }\n });\n }\n\n if (this.onMetaDesc) {\n this.onMetaDesc(this);\n }\n }\n\n // Override the original Topic._processMetaSubs\n _processMetaSubs(subs) {\n let updateCount = 0;\n subs.forEach((sub) => {\n const topicName = sub.topic;\n // Don't show 'me' and 'fnd' topics in the list of contacts.\n if (topicName == Const.TOPIC_FND || topicName == Const.TOPIC_ME) {\n return;\n }\n sub.online = !!sub.online;\n\n let cont = null;\n if (sub.deleted) {\n cont = sub;\n this._tinode.cacheRemTopic(topicName);\n this._tinode._db.remTopic(topicName);\n } else {\n // Ensure the values are defined and are integers.\n if (typeof sub.seq != 'undefined') {\n sub.seq = sub.seq | 0;\n sub.recv = sub.recv | 0;\n sub.read = sub.read | 0;\n sub.unread = sub.seq - sub.read;\n }\n\n const topic = this._tinode.getTopic(topicName);\n if (topic._new) {\n delete topic._new;\n }\n\n cont = mergeObj(topic, sub);\n this._tinode._db.updTopic(cont);\n\n if (Topic.isP2PTopicName(topicName)) {\n this._cachePutUser(topicName, cont);\n this._tinode._db.updUser(topicName, cont.public);\n }\n // Notify topic of the update if it's an external update.\n if (!sub._noForwarding && topic) {\n sub._noForwarding = true;\n topic._processMetaDesc(sub);\n }\n }\n\n updateCount++;\n\n if (this.onMetaSub) {\n this.onMetaSub(cont);\n }\n });\n\n if (this.onSubsUpdated && updateCount > 0) {\n const keys = [];\n subs.forEach((s) => {\n keys.push(s.topic);\n });\n this.onSubsUpdated(keys, updateCount);\n }\n }\n\n // Called by Tinode when meta.sub is recived.\n _processMetaCreds(creds, upd) {\n if (creds.length == 1 && creds[0] == Const.DEL_CHAR) {\n creds = [];\n }\n if (upd) {\n creds.forEach((cr) => {\n if (cr.val) {\n // Adding a credential.\n let idx = this._credentials.findIndex((el) => {\n return el.meth == cr.meth && el.val == cr.val;\n });\n if (idx < 0) {\n // Not found.\n if (!cr.done) {\n // Unconfirmed credential replaces previous unconfirmed credential of the same method.\n idx = this._credentials.findIndex((el) => {\n return el.meth == cr.meth && !el.done;\n });\n if (idx >= 0) {\n // Remove previous unconfirmed credential.\n this._credentials.splice(idx, 1);\n }\n }\n this._credentials.push(cr);\n } else {\n // Found. Maybe change 'done' status.\n this._credentials[idx].done = cr.done;\n }\n } else if (cr.resp) {\n // Handle credential confirmation.\n const idx = this._credentials.findIndex((el) => {\n return el.meth == cr.meth && !el.done;\n });\n if (idx >= 0) {\n this._credentials[idx].done = true;\n }\n }\n });\n } else {\n this._credentials = creds;\n }\n if (this.onCredsUpdated) {\n this.onCredsUpdated(this._credentials);\n }\n }\n\n // Process presence change message\n _routePres(pres) {\n if (pres.what == 'term') {\n // The 'me' topic itself is detached. Mark as unsubscribed.\n this._resetSub();\n return;\n }\n\n if (pres.what == 'upd' && pres.src == Const.TOPIC_ME) {\n // Update to me's description. Request updated value.\n this.getMeta(this.startMetaQuery().withDesc().build());\n return;\n }\n\n const cont = this._tinode.cacheGetTopic(pres.src);\n if (cont) {\n switch (pres.what) {\n case 'on': // topic came online\n cont.online = true;\n break;\n case 'off': // topic went offline\n if (cont.online) {\n cont.online = false;\n cont.seen = Object.assign(cont.seen || {}, {\n when: new Date()\n });\n }\n break;\n case 'msg': // new message received\n cont._updateReceived(pres.seq, pres.act);\n break;\n case 'upd': // desc updated\n // Request updated subscription.\n this.getMeta(this.startMetaQuery().withLaterOneSub(pres.src).build());\n break;\n case 'acs': // access mode changed\n // If 'tgt' is not set then this is an update to the permissions of the current user.\n // Otherwise it's an update to group topic subscriber permissions while the topic is offline.\n // Just gnore it then.\n if (!pres.tgt) {\n if (cont.acs) {\n cont.acs.updateAll(pres.dacs);\n } else {\n cont.acs = new AccessMode().updateAll(pres.dacs);\n }\n cont.touched = new Date();\n }\n break;\n case 'ua':\n // user agent changed.\n cont.seen = {\n when: new Date(),\n ua: pres.ua\n };\n break;\n case 'recv':\n // user's other session marked some messges as received.\n pres.seq = pres.seq | 0;\n cont.recv = cont.recv ? Math.max(cont.recv, pres.seq) : pres.seq;\n break;\n case 'read':\n // user's other session marked some messages as read.\n pres.seq = pres.seq | 0;\n cont.read = cont.read ? Math.max(cont.read, pres.seq) : pres.seq;\n cont.recv = cont.recv ? Math.max(cont.read, cont.recv) : cont.recv;\n cont.unread = cont.seq - cont.read;\n break;\n case 'gone':\n // topic deleted or unsubscribed from.\n this._tinode.cacheRemTopic(pres.src);\n if (!cont._deleted) {\n cont._deleted = true;\n cont._attached = false;\n this._tinode._db.markTopicAsDeleted(pres.src, true);\n } else {\n this._tinode._db.remTopic(pres.src);\n }\n break;\n case 'del':\n // Update topic.del value.\n break;\n default:\n this._tinode.logger(\"INFO: Unsupported presence update in 'me'\", pres.what);\n }\n\n this._refreshContact(pres.what, cont);\n } else {\n if (pres.what == 'acs') {\n // New subscriptions and deleted/banned subscriptions have full\n // access mode (no + or - in the dacs string). Changes to known subscriptions are sent as\n // deltas, but they should not happen here.\n const acs = new AccessMode(pres.dacs);\n if (!acs || acs.mode == AccessMode._INVALID) {\n this._tinode.logger(\"ERROR: Invalid access mode update\", pres.src, pres.dacs);\n return;\n } else if (acs.mode == AccessMode._NONE) {\n this._tinode.logger(\"WARNING: Removing non-existent subscription\", pres.src, pres.dacs);\n return;\n } else {\n // New subscription. Send request for the full description.\n // Using .withOneSub (not .withLaterOneSub) to make sure IfModifiedSince is not set.\n this.getMeta(this.startMetaQuery().withOneSub(undefined, pres.src).build());\n // Create a dummy entry to catch online status update.\n const dummy = this._tinode.getTopic(pres.src);\n dummy.topic = pres.src;\n dummy.online = false;\n dummy.acs = acs;\n this._tinode._db.updTopic(dummy);\n }\n } else if (pres.what == 'tags') {\n this.getMeta(this.startMetaQuery().withTags().build());\n } else if (pres.what == 'msg') {\n // Message received for un unknown (previously deleted) topic.\n this.getMeta(this.startMetaQuery().withOneSub(undefined, pres.src).build());\n // Create an entry to catch updates and messages.\n const dummy = this._tinode.getTopic(pres.src);\n dummy._deleted = false;\n this._tinode._db.updTopic(dummy);\n }\n\n this._refreshContact(pres.what, cont);\n }\n\n if (this.onPres) {\n this.onPres(pres);\n }\n }\n\n // Contact is updated, execute callbacks.\n _refreshContact(what, cont) {\n if (this.onContactUpdate) {\n this.onContactUpdate(what, cont);\n }\n }\n\n /**\n * Publishing to TopicMe is not supported. {@link Topic#publish} is overriden and thows an {Error} if called.\n * @memberof Tinode.TopicMe#\n * @throws {Error} Always throws an error.\n */\n publish() {\n return Promise.reject(new Error(\"Publishing to 'me' is not supported\"));\n }\n\n /**\n * Delete validation credential.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} topic - Name of the topic to delete\n * @param {string} user - User ID to remove.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delCredential(method, value) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot delete credential in inactive 'me' topic\"));\n }\n // Send {del} message, return promise\n return this._tinode.delCredential(method, value).then(ctrl => {\n // Remove deleted credential from the cache.\n const index = this._credentials.findIndex((el) => {\n return el.meth == method && el.val == value;\n });\n if (index > -1) {\n this._credentials.splice(index, 1);\n }\n // Notify listeners\n if (this.onCredsUpdated) {\n this.onCredsUpdated(this._credentials);\n }\n return ctrl;\n });\n }\n\n /**\n * @callback contactFilter\n * @param {Object} contact to check for inclusion.\n * @returns {boolean} true if contact should be processed, false to exclude it.\n */\n /**\n * Iterate over cached contacts.\n *\n * @function\n * @memberof Tinode.TopicMe#\n * @param {TopicMe.ContactCallback} callback - Callback to call for each contact.\n * @param {contactFilter=} filter - Optionally filter contacts; include all if filter is false-ish, otherwise\n * include those for which filter returns true-ish.\n * @param {Object=} context - Context to use for calling the `callback`, i.e. the value of `this` inside the callback.\n */\n contacts(callback, filter, context) {\n this._tinode.mapTopics((c, idx) => {\n if (c.isCommType() && (!filter || filter(c))) {\n callback.call(context, c, idx);\n }\n });\n }\n\n /**\n * Get a contact from cache.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} name - Name of the contact to get, either a UID (for p2p topics) or a topic name.\n * @returns {Tinode.Contact} - Contact or `undefined`.\n */\n getContact(name) {\n return this._tinode.cacheGetTopic(name);\n }\n\n /**\n * Get access mode of a given contact from cache.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} name - Name of the contact to get access mode for, either a UID (for p2p topics)\n * or a topic name; if missing, access mode for the 'me' topic itself.\n * @returns {string} - access mode, such as `RWP`.\n */\n getAccessMode(name) {\n if (name) {\n const cont = this._tinode.cacheGetTopic(name);\n return cont ? cont.acs : null;\n }\n return this.acs;\n }\n\n /**\n * Check if contact is archived, i.e. contact.private.arch == true.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} name - Name of the contact to check archived status, either a UID (for p2p topics) or a topic name.\n * @returns {boolean} - true if contact is archived, false otherwise.\n */\n isArchived(name) {\n const cont = this._tinode.cacheGetTopic(name);\n return cont && cont.private && !!cont.private.arch;\n }\n\n /**\n * @typedef Tinode.Credential\n * @memberof Tinode\n * @type Object\n * @property {string} meth - validation method such as 'email' or 'tel'.\n * @property {string} val - credential value, i.e. 'jdoe@example.com' or '+17025551234'\n * @property {boolean} done - true if credential is validated.\n */\n /**\n * Get the user's credentials: email, phone, etc.\n * @memberof Tinode.TopicMe#\n *\n * @returns {Tinode.Credential[]} - array of credentials.\n */\n getCredentials() {\n return this._credentials;\n }\n}\n","/**\n * @file Helper class for constructing {@link Tinode.GetQuery}.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport {\n listToRanges,\n normalizeRanges\n} from './utils';\n\n/**\n * Helper class for constructing {@link Tinode.GetQuery}.\n *\n * @class MetaGetBuilder\n * @memberof Tinode\n *\n * @param {Tinode.Topic} parent topic which instantiated this builder.\n */\nexport default class MetaGetBuilder {\n constructor(parent) {\n this.topic = parent;\n this.what = {};\n }\n\n // Get timestamp of the most recent desc update.\n #get_desc_ims() {\n return this.topic._deleted ? undefined : this.topic.updated;\n }\n\n // Get timestamp of the most recent subs update.\n #get_subs_ims() {\n if (this.topic.isP2PType()) {\n return this.#get_desc_ims();\n }\n return this.topic._deleted ? undefined : this.topic._lastSubsUpdate;\n }\n /**\n * Add query parameters to fetch messages within explicit limits.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} since - messages newer than this (inclusive);\n * @param {number=} before - older than this (exclusive)\n * @param {number=} limit - number of messages to fetch\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withData(since, before, limit) {\n this.what['data'] = {\n since: since,\n before: before,\n limit: limit\n };\n return this;\n }\n /**\n * Add query parameters to fetch messages newer than the latest saved message.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - number of messages to fetch\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterData(limit) {\n return this.withData(this.topic._maxSeq > 0 ? this.topic._maxSeq + 1 : undefined, undefined, limit);\n }\n /**\n * Add query parameters to fetch messages within ID ranges.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Array.} ranges - ranges of seq IDs to fetch.\n * @param {number=} limit - maximum number of messages to fetch.\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDataRanges(ranges, limit) {\n this.what['data'] = {\n ranges: normalizeRanges(ranges, this.topic._maxSeq),\n limit: limit\n };\n return this;\n }\n /**\n * Add query parameters to fetch messages by an array of IDs.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number[]} list - array of seq IDs to fetch.\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDataList(list) {\n return this.withDataRanges(listToRanges(list));\n }\n /**\n * Add query parameters to fetch messages older than the earliest saved message.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - maximum number of messages to fetch.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withEarlierData(limit) {\n return this.withData(undefined, this.topic._minSeq > 0 ? this.topic._minSeq : undefined, limit);\n }\n /**\n * Add query parameters to fetch topic description if it's newer than the given timestamp.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Date=} ims - fetch messages newer than this timestamp.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDesc(ims) {\n this.what['desc'] = {\n ims: ims\n };\n return this;\n }\n /**\n * Add query parameters to fetch topic description if it's newer than the last update.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterDesc() {\n return this.withDesc(this.#get_desc_ims());\n }\n /**\n * Add query parameters to fetch subscriptions.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Date=} ims - fetch subscriptions modified more recently than this timestamp\n * @param {number=} limit - maximum number of subscriptions to fetch.\n * @param {string=} userOrTopic - user ID or topic name to fetch for fetching one subscription.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withSub(ims, limit, userOrTopic) {\n const opts = {\n ims: ims,\n limit: limit\n };\n if (this.topic.getType() == 'me') {\n opts.topic = userOrTopic;\n } else {\n opts.user = userOrTopic;\n }\n this.what['sub'] = opts;\n return this;\n }\n /**\n * Add query parameters to fetch a single subscription.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Date=} ims - fetch subscriptions modified more recently than this timestamp\n * @param {string=} userOrTopic - user ID or topic name to fetch for fetching one subscription.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withOneSub(ims, userOrTopic) {\n return this.withSub(ims, undefined, userOrTopic);\n }\n /**\n * Add query parameters to fetch a single subscription if it's been updated since the last update.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {string=} userOrTopic - user ID or topic name to fetch for fetching one subscription.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterOneSub(userOrTopic) {\n return this.withOneSub(this.topic._lastSubsUpdate, userOrTopic);\n }\n /**\n * Add query parameters to fetch subscriptions updated since the last update.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - maximum number of subscriptions to fetch.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterSub(limit) {\n return this.withSub(this.#get_subs_ims(), limit);\n }\n /**\n * Add query parameters to fetch topic tags.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withTags() {\n this.what['tags'] = true;\n return this;\n }\n /**\n * Add query parameters to fetch user's credentials. 'me' topic only.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withCred() {\n if (this.topic.getType() == 'me') {\n this.what['cred'] = true;\n } else {\n this.topic._tinode.logger(\"ERROR: Invalid topic type for MetaGetBuilder:withCreds\", this.topic.getType());\n }\n return this;\n }\n /**\n * Add query parameters to fetch topic tags.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withAux() {\n this.what['aux'] = true;\n return this;\n }\n /**\n * Add query parameters to fetch deleted messages within explicit limits. Any/all parameters can be null.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} since - ids of messages deleted since this 'del' id (inclusive)\n * @param {number=} limit - number of deleted message ids to fetch\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDel(since, limit) {\n if (since || limit) {\n this.what['del'] = {\n since: since,\n limit: limit\n };\n }\n return this;\n }\n /**\n * Add query parameters to fetch messages deleted after the saved 'del' id.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - number of deleted message ids to fetch\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterDel(limit) {\n // Specify 'since' only if we have already received some messages. If\n // we have no locally cached messages then we don't care if any messages were deleted.\n return this.withDel(this.topic._maxSeq > 0 ? this.topic._maxDel + 1 : undefined, limit);\n }\n\n /**\n * Extract subquery: get an object that contains specified subquery.\n * @memberof Tinode.MetaGetBuilder#\n * @param {string} what - subquery to return: one of 'data', 'sub', 'desc', 'tags', 'cred', 'del'.\n * @returns {Object} requested subquery or undefined.\n */\n extract(what) {\n return this.what[what];\n }\n\n /**\n * Construct parameters.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.GetQuery} Get query\n */\n build() {\n const what = [];\n let params = {};\n ['data', 'sub', 'desc', 'tags', 'cred', 'aux', 'del'].forEach((key) => {\n if (this.what.hasOwnProperty(key)) {\n what.push(key);\n if (Object.getOwnPropertyNames(this.what[key]).length > 0) {\n params[key] = this.what[key];\n }\n }\n });\n if (what.length > 0) {\n params.what = what.join(' ');\n } else {\n params = undefined;\n }\n return params;\n }\n}\n","/**\n * @file Topic management.\n *\n * @copyright 2015-2025 Tinode LLC.\n */\n'use strict';\n\nimport AccessMode from './access-mode.js';\nimport CBuffer from './cbuffer.js';\nimport CommError from './comm-error.js';\nimport * as Const from './config.js';\nimport Drafty from './drafty.js';\nimport MetaGetBuilder from './meta-builder.js';\nimport {\n listToRanges,\n mergeObj,\n mergeToCache,\n normalizeArray,\n normalizeRanges\n} from './utils.js';\n\n/**\n * Topic is a class representing a logical communication channel.\n */\nexport default class Topic {\n /**\n * @callback onData\n * @param {Data} data - Data packet\n */\n\n /**\n * Create topic.\n * @param {string} name - Name of the topic to create.\n * @param {Object=} callbacks - Object with various event callbacks.\n * @param {onData} callbacks.onData - Callback which receives a {data} message.\n * @param {callback} callbacks.onMeta - Callback which receives a {meta} message.\n * @param {callback} callbacks.onPres - Callback which receives a {pres} message.\n * @param {callback} callbacks.onInfo - Callback which receives an {info} message.\n * @param {callback} callbacks.onMetaDesc - Callback which receives changes to topic desctioption {@link desc}.\n * @param {callback} callbacks.onMetaSub - Called for a single subscription record change.\n * @param {callback} callbacks.onSubsUpdated - Called after a batch of subscription changes have been recieved and cached.\n * @param {callback} callbacks.onDeleteTopic - Called after the topic is deleted.\n * @param {callback} callbacls.onAllMessagesReceived - Called when all requested {data} messages have been recived.\n */\n constructor(name, callbacks) {\n // Parent Tinode object.\n this._tinode = null;\n\n // Server-provided data, locally immutable.\n // topic name\n this.name = name;\n // Timestamp when the topic was created.\n this.created = null;\n // Timestamp when the topic was last updated.\n this.updated = null;\n // Timestamp of the last messages\n this.touched = new Date(0);\n // Access mode, see AccessMode\n this.acs = new AccessMode(null);\n // Per-topic private data (accessible by current user only).\n this.private = null;\n // Per-topic public data (accessible by all users).\n this.public = null;\n // Per-topic system-provided data (accessible by all users).\n this.trusted = null;\n\n // Locally cached data\n // Subscribed users, for tracking read/recv/msg notifications.\n this._users = {};\n\n // Current value of locally issued seqId, used for pending messages.\n this._queuedSeqId = Const.LOCAL_SEQID;\n\n // The maximum known {data.seq} value.\n this._maxSeq = 0;\n // The minimum known {data.seq} value.\n this._minSeq = 0;\n // Indicator that the last request for earlier messages returned 0.\n this._noEarlierMsgs = false;\n // The maximum known deletion ID.\n this._maxDel = 0;\n // Timer object used to send 'recv' notifications.\n this._recvNotificationTimer = null;\n\n // User discovery tags\n this._tags = [];\n // Credentials such as email or phone number.\n this._credentials = [];\n // Auxiliary data\n this._aux = {};\n\n // Message versions cache (e.g. for edited messages).\n // Keys: original message seq ID.\n // Values: CBuffers containing newer versions of the original message\n // ordered by seq id.\n this._messageVersions = {};\n // Message cache, sorted by message seq values, from old to new.\n this._messages = new CBuffer((a, b) => {\n return a.seq - b.seq;\n }, true);\n // Boolean, true if the topic is currently live\n this._attached = false;\n // Timestap of the most recently updated subscription.\n this._lastSubsUpdate = new Date(0);\n // Topic created but not yet synced with the server. Used only during initialization.\n this._new = true;\n // The topic is deleted at the server, this is a local copy.\n this._deleted = false;\n\n // Timer used to trgger {leave} request after a delay.\n this._delayedLeaveTimer = null;\n\n // Callbacks\n if (callbacks) {\n this.onData = callbacks.onData;\n this.onMeta = callbacks.onMeta;\n this.onPres = callbacks.onPres;\n this.onInfo = callbacks.onInfo;\n // A single desc update;\n this.onMetaDesc = callbacks.onMetaDesc;\n // A single subscription record;\n this.onMetaSub = callbacks.onMetaSub;\n // All subscription records received;\n this.onSubsUpdated = callbacks.onSubsUpdated;\n this.onTagsUpdated = callbacks.onTagsUpdated;\n this.onCredsUpdated = callbacks.onCredsUpdated;\n this.onAuxUpdated = callbacks.onAuxUpdated;\n this.onDeleteTopic = callbacks.onDeleteTopic;\n this.onAllMessagesReceived = callbacks.onAllMessagesReceived;\n }\n }\n\n // Static methods.\n\n /**\n * Determine topic type from topic's name: grp, p2p, me, fnd, sys.\n *\n * @param {string} name - Name of the topic to test.\n * @returns {string} One of \"me\", \"fnd\", \"sys\", \"grp\",\n * \"p2p\" or undefined.\n */\n static topicType(name) {\n const types = {\n 'me': Const.TOPIC_ME,\n 'fnd': Const.TOPIC_FND,\n 'grp': Const.TOPIC_GRP,\n 'new': Const.TOPIC_GRP,\n 'nch': Const.TOPIC_GRP,\n 'chn': Const.TOPIC_GRP,\n 'usr': Const.TOPIC_P2P,\n 'sys': Const.TOPIC_SYS,\n 'slf': Const.TOPIC_SLF\n };\n return types[(typeof name == 'string') ? name.substring(0, 3) : 'xxx'];\n }\n\n /**\n * Check if the given topic name is a name of a 'me' topic.\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'me' topic, false otherwise.\n */\n static isMeTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_ME;\n }\n\n /**\n * Check if the given topic name is a name of a 'slf' topic.\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'slf' topic, false otherwise.\n */\n static isSelfTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_SLF;\n }\n\n /**\n * Check if the given topic name is a name of a group topic.\n * @static\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a group topic, false otherwise.\n */\n static isGroupTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_GRP;\n }\n\n /**\n * Check if the given topic name is a name of a p2p topic.\n * @static\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p topic, false otherwise.\n */\n static isP2PTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_P2P;\n }\n\n /**\n * Check if the given topic name is a name of a communication topic, i.e. P2P or group.\n * @static\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p or group topic, false otherwise.\n */\n static isCommTopicName(name) {\n return Topic.isP2PTopicName(name) || Topic.isGroupTopicName(name) || Topic.isSelfTopicName(name);\n }\n\n /**\n * Check if the topic name is a name of a new topic.\n * @static\n *\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a new topic, false otherwise.\n */\n static isNewGroupTopicName(name) {\n return (typeof name == 'string') &&\n (name.substring(0, 3) == Const.TOPIC_NEW || name.substring(0, 3) == Const.TOPIC_NEW_CHAN);\n }\n\n /**\n * Check if the topic name is a name of a channel.\n * @static\n *\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a channel, false otherwise.\n */\n static isChannelTopicName(name) {\n return (typeof name == 'string') &&\n (name.substring(0, 3) == Const.TOPIC_CHAN || name.substring(0, 3) == Const.TOPIC_NEW_CHAN);\n }\n\n // Returns true if pub is meant to replace another message (e.g. original message was edited).\n static #isReplacementMsg(pub) {\n return pub.head && pub.head.replace;\n }\n\n /**\n * Check if the topic is subscribed.\n * @returns {boolean} True is topic is attached/subscribed, false otherwise.\n */\n isSubscribed() {\n return this._attached;\n }\n\n /**\n * Request topic to subscribe. Wrapper for {@link Tinode#subscribe}.\n *\n * @param {Tinode.GetQuery=} getParams - get query parameters.\n * @param {Tinode.SetParams=} setParams - set parameters.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n subscribe(getParams, setParams) {\n // Clear request to leave topic.\n clearTimeout(this._delayedLeaveTimer);\n this._delayedLeaveTimer = null;\n\n // If the topic is already subscribed, return resolved promise\n if (this._attached) {\n return Promise.resolve(this);\n }\n\n // Send subscribe message, handle async response.\n // If topic name is explicitly provided, use it. If no name, then it's a new group topic,\n // use \"new\".\n return this._tinode.subscribe(this.name || Const.TOPIC_NEW, getParams, setParams).then(ctrl => {\n if (ctrl.code >= 300) {\n // Do nothing if subscription status has not changed.\n return ctrl;\n }\n\n this._attached = true;\n this._deleted = false;\n this.acs = (ctrl.params && ctrl.params.acs) ? ctrl.params.acs : this.acs;\n\n // Set topic name for new topics and add it to cache.\n if (this._new) {\n delete this._new;\n\n if (this.name != ctrl.topic) {\n // Name may change new123456 -> grpAbCdEf. Remove from cache under the old name.\n this._cacheDelSelf();\n this.name = ctrl.topic;\n }\n this._cachePutSelf();\n\n this.created = ctrl.ts;\n this.updated = ctrl.ts;\n\n if (this.name != Const.TOPIC_ME && this.name != Const.TOPIC_FND) {\n // Add the new topic to the list of contacts maintained by the 'me' topic.\n const me = this._tinode.getMeTopic();\n if (me.onMetaSub) {\n me.onMetaSub(this);\n }\n if (me.onSubsUpdated) {\n me.onSubsUpdated([this.name], 1);\n }\n }\n\n if (setParams && setParams.desc) {\n setParams.desc._noForwarding = true;\n this._processMetaDesc(setParams.desc);\n }\n }\n return ctrl;\n });\n }\n\n /**\n * Create a draft of a message without sending it to the server.\n * @memberof Tinode.Topic#\n *\n * @param {string | Object} data - Content to wrap in a draft.\n * @param {boolean=} noEcho - If true server will not echo message back to originating\n * session. Otherwise the server will send a copy of the message to sender.\n *\n * @returns {Object} message draft.\n */\n createMessage(data, noEcho) {\n return this._tinode.createMessage(this.name, data, noEcho);\n }\n\n /**\n * Immediately publish data to topic. Wrapper for {@link Tinode#publish}.\n * @memberof Tinode.Topic#\n *\n * @param {string | Object} data - Message to publish, either plain string or a Drafty object.\n * @param {boolean=} noEcho - If true server will not echo message back to originating\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n publish(data, noEcho) {\n return this.publishMessage(this.createMessage(data, noEcho));\n }\n\n /**\n * Publish message created by {@link Tinode.Topic#createMessage}.\n * @memberof Tinode.Topic#\n *\n * @param {Object} pub - {data} object to publish. Must be created by {@link Tinode.Topic#createMessage}\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n publishMessage(pub) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot publish on inactive topic\"));\n }\n if (this._sending) {\n return Promise.reject(new Error(\"The message is already being sent\"));\n }\n\n // Send data.\n pub._sending = true;\n pub._failed = false;\n\n // Extract refereces to attachments and out of band image records.\n let attachments = null;\n if (Drafty.hasEntities(pub.content)) {\n attachments = [];\n Drafty.entities(pub.content, data => {\n if (data) {\n if (data.ref) {\n attachments.push(data.ref);\n }\n if (data.preref) {\n attachments.push(data.preref);\n }\n }\n });\n if (attachments.length == 0) {\n attachments = null;\n }\n }\n\n return this._tinode.publishMessage(pub, attachments).then(ctrl => {\n pub._sending = false;\n pub.ts = ctrl.ts;\n this.swapMessageId(pub, ctrl.params.seq);\n this._maybeUpdateMessageVersionsCache(pub);\n this._routeData(pub);\n return ctrl;\n }).catch(err => {\n this._tinode.logger(\"WARNING: Message rejected by the server\", err);\n pub._sending = false;\n pub._failed = true;\n if (this.onData) {\n this.onData();\n }\n });\n }\n\n /**\n * Add message to local message cache, send to the server when the promise is resolved.\n * If promise is null or undefined, the message will be sent immediately.\n * The message is sent when the\n * The message should be created by {@link Tinode.Topic#createMessage}.\n * This is probably not the final API.\n * @memberof Tinode.Topic#\n *\n * @param {Object} pub - Message to use as a draft.\n * @param {Promise} prom - Message will be sent when this promise is resolved, discarded if rejected.\n *\n * @returns {Promise} derived promise.\n */\n publishDraft(pub, prom) {\n const seq = pub.seq || this._getQueuedSeqId();\n if (!pub._noForwarding) {\n // The 'seq', 'ts', and 'from' are added to mimic {data}. They are removed later\n // before the message is sent.\n pub._noForwarding = true;\n pub.seq = seq;\n pub.ts = new Date();\n pub.from = this._tinode.getCurrentUserID();\n\n // Don't need an echo message because the message is added to local cache right away.\n pub.noecho = true;\n // Add to cache.\n this._messages.put(pub);\n this._tinode._db.addMessage(pub);\n\n if (this.onData) {\n this.onData(pub);\n }\n }\n // If promise is provided, send the queued message when it's resolved.\n // If no promise is provided, create a resolved one and send immediately.\n return (prom || Promise.resolve())\n .then(_ => {\n if (pub._cancelled) {\n return {\n code: 300,\n text: \"cancelled\"\n };\n }\n return this.publishMessage(pub);\n }).catch(err => {\n this._tinode.logger(\"WARNING: Message draft rejected\", err);\n pub._sending = false;\n pub._failed = true;\n pub._fatal = err instanceof CommError ? (err.code >= 400 && err.code < 500) : false;\n if (this.onData) {\n this.onData();\n }\n // Rethrow to let caller know that the operation failed.\n throw err;\n });\n }\n\n /**\n * Leave the topic, optionally unsibscribe. Leaving the topic means the topic will stop\n * receiving updates from the server. Unsubscribing will terminate user's relationship with the topic.\n * Wrapper for {@link Tinode#leave}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean=} unsub - If true, unsubscribe, otherwise just leave.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n leave(unsub) {\n // It's possible to unsubscribe (unsub==true) from inactive topic.\n if (!this._attached && !unsub) {\n return Promise.reject(new Error(\"Cannot leave inactive topic\"));\n }\n\n // Send a 'leave' message, handle async response\n return this._tinode.leave(this.name, unsub).then(ctrl => {\n this._resetSub();\n if (unsub) {\n this._gone();\n }\n return ctrl;\n });\n }\n\n /**\n * Leave the topic, optionally unsibscribe after a delay. Leaving the topic means the topic will stop\n * receiving updates from the server. Unsubscribing will terminate user's relationship with the topic.\n * Wrapper for {@link Tinode#leave}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} unsub - If true, unsubscribe, otherwise just leave.\n * @param {number} delay - time in milliseconds to delay leave request.\n */\n leaveDelayed(unsub, delay) {\n clearTimeout(this._delayedLeaveTimer);\n this._delayedLeaveTimer = setTimeout(_ => {\n this._delayedLeaveTimer = null;\n this.leave(unsub)\n }, delay);\n }\n\n /**\n * Request topic metadata from the local cache or from the server.\n * @memberof Tinode.Topic#\n *\n * @param {Tinode.GetQuery} request parameters\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n getMeta(params) {\n // Send {get} message, return promise.\n return this._tinode.getMeta(this.name, params);\n }\n\n /**\n * Request more messages from the server. The goal is to load continous range of messages\n * covering at least between 'min' and 'max' + one full page forward (newer = true) or backwards\n * (newer=false).\n * @memberof Tinode.Topic#\n *\n * @param {number} limit number of messages to get.\n * @param {Array.} gaps - ranges of messages to load.\n * @param {number} min if non-negative, request newer messages with seq >= min.\n * @param {number} max if positive, request older messages with seq < max.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n getMessagesPage(limit, gaps, min, max, newer) {\n let query = gaps ?\n this.startMetaQuery().withDataRanges(gaps, limit) :\n newer ?\n this.startMetaQuery().withData(min, undefined, limit) :\n this.startMetaQuery().withData(undefined, max, limit);\n // First try fetching from DB, then from the server.\n return this._loadMessages(this._tinode._db, query.extract('data'))\n .then(count => {\n // Recalculate missing ranges.\n gaps = this.msgHasMoreMessages(min, max, newer);\n if (gaps.length == 0) {\n // All messages loaded.\n return Promise.resolve({\n topic: this.name,\n code: 200,\n params: {\n count: count\n }\n });\n }\n\n // Reduce the count of requested messages.\n limit -= count;\n // Update query with new values loaded from DB.\n query = this.startMetaQuery().withDataRanges(gaps, limit);\n return this.getMeta(query.build());\n });\n }\n\n /**\n * Request to get pinned messages from the local cache or from the server.\n * @memberof Tinode.Topic#\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n getPinnedMessages() {\n const pins = this.aux('pins');\n if (!Array.isArray(pins)) {\n return Promise.resolve(0);\n }\n\n const loaded = [];\n let remains = pins;\n // First try fetching from DB, then check deleted log, then ask the server.\n return this._tinode._db.readMessages(this.name, {\n ranges: listToRanges(remains)\n })\n .then(msgs => {\n msgs.forEach(data => {\n // The 'data' could be undefined.\n if (data) {\n loaded.push(data.seq);\n this._messages.put(data);\n this._maybeUpdateMessageVersionsCache(data);\n }\n });\n if (loaded.length < pins.length) {\n // Some messages are missing, try dellog.\n remains = pins.filter(seq => !loaded.includes(seq));\n return this._tinode._db.readMessages(this.name, {\n ranges: listToRanges(remains)\n });\n }\n return null;\n })\n .then(ranges => {\n if (ranges) {\n // Found some deleted ranges in dellog.\n remains.forEach(seq => {\n if (ranges.find(r => r.low <= seq && r.hi > seq)) {\n loaded.push(seq);\n }\n });\n }\n if (loaded.length == pins.length) {\n // Got all pinned messages from the local cache.\n return Promise.resolve({\n topic: this.name,\n code: 200,\n params: {\n count: loaded.length\n }\n });\n }\n\n remains = pins.filter(seq => !loaded.includes(seq));\n return this.getMeta(this.startMetaQuery().withDataList(remains).build());\n });\n }\n\n /**\n * Update topic metadata.\n * @memberof Tinode.Topic#\n *\n * @param {Tinode.SetParams} params parameters to update.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n setMeta(params) {\n if (params.tags) {\n params.tags = normalizeArray(params.tags);\n }\n // Send Set message, handle async response.\n return this._tinode.setMeta(this.name, params)\n .then(ctrl => {\n if (ctrl && ctrl.code >= 300) {\n // Not modified\n return ctrl;\n }\n\n if (params.sub) {\n params.sub.topic = this.name;\n if (ctrl.params && ctrl.params.acs) {\n params.sub.acs = ctrl.params.acs;\n params.sub.updated = ctrl.ts;\n }\n if (!params.sub.user) {\n // This is a subscription update of the current user.\n // Assign user ID otherwise the update will be ignored by _processMetaSubs.\n params.sub.user = this._tinode.getCurrentUserID();\n if (!params.desc) {\n // Force update to topic's asc.\n params.desc = {};\n }\n }\n params.sub._noForwarding = true;\n this._processMetaSubs([params.sub]);\n }\n\n if (params.desc) {\n if (ctrl.params && ctrl.params.acs) {\n params.desc.acs = ctrl.params.acs;\n params.desc.updated = ctrl.ts;\n }\n this._processMetaDesc(params.desc);\n }\n\n if (params.tags) {\n this._processMetaTags(params.tags);\n }\n if (params.cred) {\n this._processMetaCreds([params.cred], true);\n }\n if (params.aux) {\n this._processMetaAux(params.aux);\n }\n\n return ctrl;\n });\n }\n /**\n * Update access mode of the current user or of another topic subsriber.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - UID of the user to update or null to update current user.\n * @param {string} update - the update value, full or delta.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n updateMode(uid, update) {\n const user = uid ? this.subscriber(uid) : null;\n const am = user ?\n user.acs.updateGiven(update).getGiven() :\n this.getAccessMode().updateWant(update).getWant();\n\n return this.setMeta({\n sub: {\n user: uid,\n mode: am\n }\n });\n }\n /**\n * Create new topic subscription. Wrapper for {@link Tinode#setMeta}.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - ID of the user to invite\n * @param {string=} mode - Access mode. null means to use default.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n invite(uid, mode) {\n return this.setMeta({\n sub: {\n user: uid,\n mode: mode\n }\n });\n }\n /**\n * Archive or un-archive the topic. Wrapper for {@link Tinode#setMeta}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} arch - true to archive the topic, false otherwise.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n archive(arch) {\n if (this.private && (!this.private.arch == !arch)) {\n return Promise.resolve(arch);\n }\n return this.setMeta({\n desc: {\n private: {\n arch: arch ? true : Const.DEL_CHAR\n }\n }\n });\n }\n /**\n * Set message as pinned or unpinned by adding it to aux.pins array. Wrapper for {@link Tinode#setMeta}.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - seq ID of the message to pin or un-pin.\n * @param {boolean} pin - true to pin the message, false to un-pin.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n pinMessage(seq, pin) {\n let pinned = this.aux('pins');\n if (!Array.isArray(pinned)) {\n pinned = [];\n }\n let changed = false;\n if (pin) {\n if (!pinned.includes(seq)) {\n changed = true;\n if (pinned.length == Const.MAX_PINNED_COUNT) {\n pinned.shift();\n }\n pinned.push(seq);\n }\n } else {\n if (pinned.includes(seq)) {\n changed = true;\n pinned = pinned.filter(id => id != seq);\n if (pinned.length == 0) {\n pinned = Const.DEL_CHAR;\n }\n }\n }\n if (changed) {\n return this.setMeta({\n aux: {\n pins: pinned\n }\n });\n }\n return Promise.resolve();\n }\n /**\n * Delete messages. Hard-deleting messages requires Deleter (D) permission.\n * Wrapper for {@link Tinode#delMessages}.\n * @memberof Tinode.Topic#\n *\n * @param {Array.} ranges - Ranges of message IDs to delete.\n * @param {boolean=} hard - Hard or soft delete\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delMessages(ranges, hard) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot delete messages in inactive topic\"));\n }\n\n const tosend = normalizeRanges(ranges, this._maxSeq)\n\n // Send {del} message, return promise\n let result;\n if (tosend.length > 0) {\n result = this._tinode.delMessages(this.name, tosend, hard);\n } else {\n result = Promise.resolve({\n params: {\n del: 0\n }\n });\n }\n // Update local cache.\n return result.then(ctrl => {\n if (ctrl.params.del > this._maxDel) {\n this._maxDel = Math.max(ctrl.params.del, this._maxDel);\n this.clear = Math.max(ctrl.params.del, this.clear);\n }\n\n ranges.forEach(rec => {\n if (rec.hi) {\n this.flushMessageRange(rec.low, rec.hi);\n } else {\n this.flushMessage(rec.low);\n }\n this._messages.put({\n seq: rec.low,\n low: rec.low,\n hi: rec.hi,\n _deleted: true\n });\n });\n\n // Make a record.\n this._tinode._db.addDelLog(this.name, ctrl.params.del, ranges);\n\n if (this.onData) {\n // Calling with no parameters to indicate the messages were deleted.\n this.onData();\n }\n return ctrl;\n });\n }\n /**\n * Delete all messages. Hard-deleting messages requires Deleter permission.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} hardDel - true if messages should be hard-deleted.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delMessagesAll(hardDel) {\n if (!this._maxSeq || this._maxSeq <= 0) {\n // There are no messages to delete.\n return Promise.resolve();\n }\n return this.delMessages([{\n low: 1,\n hi: this._maxSeq + 1,\n _all: true\n }], hardDel);\n }\n\n /**\n * Delete multiple messages defined by their IDs. Hard-deleting messages requires Deleter permission.\n * @memberof Tinode.Topic#\n *\n * @param {Array.} list - list of seq IDs to delete.\n * @param {boolean=} hardDel - true if messages should be hard-deleted.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delMessagesList(list, hardDel) {\n // Send {del} message, return promise\n return this.delMessages(listToRanges(list), hardDel);\n }\n\n /**\n * Delete original message and edited variants. Hard-deleting messages requires Deleter permission.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - original seq ID of the message to delete.\n * @param {boolean=} hardDel - true if messages should be hard-deleted.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n delMessagesEdits(seq, hardDel) {\n const list = [seq];\n this.messageVersions(seq, msg => list.push(msg.seq));\n // Send {del} message, return promise\n return this.delMessagesList(list, hardDel);\n }\n\n /**\n * Delete topic. Requires Owner permission. Wrapper for {@link Tinode#delTopic}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} hard - had-delete topic.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n delTopic(hard) {\n if (this._deleted) {\n // The topic is already deleted at the server, just remove from DB.\n this._gone();\n return Promise.resolve(null);\n }\n\n return this._tinode.delTopic(this.name, hard).then(ctrl => {\n this._deleted = true;\n this._resetSub();\n this._gone();\n return ctrl;\n });\n }\n /**\n * Delete subscription. Requires Share permission. Wrapper for {@link Tinode#delSubscription}.\n * @memberof Tinode.Topic#\n *\n * @param {string} user - ID of the user to remove subscription for.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delSubscription(user) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot delete subscription in inactive topic\"));\n }\n // Send {del} message, return promise\n return this._tinode.delSubscription(this.name, user).then(ctrl => {\n // Remove the object from the subscription cache;\n delete this._users[user];\n // Notify listeners\n if (this.onSubsUpdated) {\n this.onSubsUpdated(Object.keys(this._users));\n }\n return ctrl;\n });\n }\n /**\n * Send a read/recv notification.\n * @memberof Tinode.Topic#\n *\n * @param {string} what - what notification to send: recv, read.\n * @param {number} seq - ID or the message read or received.\n */\n note(what, seq) {\n if (!this._attached) {\n // Cannot sending {note} on an inactive topic\".\n return;\n }\n\n // Update local cache with the new count.\n const user = this._users[this._tinode.getCurrentUserID()];\n let update = false;\n if (user) {\n // Self-subscription is found.\n if (!user[what] || user[what] < seq) {\n user[what] = seq;\n update = true;\n }\n } else {\n // Self-subscription is not found.\n update = (this[what] | 0) < seq;\n }\n\n if (update) {\n // Send notification to the server.\n this._tinode.note(this.name, what, seq);\n // Update locally cached contact with the new count.\n this._updateMyReadRecv(what, seq);\n\n if (this.acs != null && !this.acs.isMuted()) {\n const me = this._tinode.getMeTopic();\n // Sent a notification to 'me' listeners.\n me._refreshContact(what, this);\n }\n }\n }\n\n /**\n * Send a 'recv' receipt. Wrapper for {@link Tinode#noteRecv}.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - ID of the message to aknowledge.\n */\n noteRecv(seq) {\n this.note('recv', seq);\n }\n /**\n * Send a 'read' receipt. Wrapper for {@link Tinode#noteRead}.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - ID of the message to aknowledge or 0/undefined to acknowledge the latest messages.\n */\n noteRead(seq) {\n seq = seq || this._maxSeq;\n if (seq > 0) {\n this.note('read', seq);\n }\n }\n /**\n * Send a key-press notification. Wrapper for {@link Tinode#noteKeyPress}.\n * @memberof Tinode.Topic#\n */\n noteKeyPress() {\n if (this._attached) {\n this._tinode.noteKeyPress(this.name);\n } else {\n this._tinode.logger(\"INFO: Cannot send notification in inactive topic\");\n }\n }\n /**\n * Send a notification than a video or audio message is . Wrapper for {@link Tinode#noteKeyPress}.\n * @memberof Tinode.Topic#\n * @param audioOnly - true if the recording is audio-only, false if it's a video recording.\n */\n noteRecording(audioOnly) {\n if (this._attached) {\n this._tinode.noteKeyPress(this.name, audioOnly ? 'kpa' : 'kpv');\n } else {\n this._tinode.logger(\"INFO: Cannot send notification in inactive topic\");\n }\n }\n\n /**\n * Send a {note what='call'}. Wrapper for {@link Tinode#videoCall}.\n * @memberof Tinode#\n *\n * @param {string} evt - Call event.\n * @param {int} seq - ID of the call message the event pertains to.\n * @param {string} payload - Payload associated with this event (e.g. SDP string).\n *\n * @returns {Promise} Promise (for some call events) which will\n * be resolved/rejected on receiving server reply\n */\n videoCall(evt, seq, payload) {\n if (!this._attached && !['ringing', 'hang-up'].includes(evt)) {\n // Cannot {call} on an inactive topic\".\n return;\n }\n return this._tinode.videoCall(this.name, seq, evt, payload);\n }\n\n // Update cached read/recv/unread counts for the current user.\n _updateMyReadRecv(what, seq, ts) {\n let oldVal, doUpdate = false;\n\n seq = seq | 0;\n this.seq = this.seq | 0;\n this.read = this.read | 0;\n this.recv = this.recv | 0;\n switch (what) {\n case 'recv':\n oldVal = this.recv;\n this.recv = Math.max(this.recv, seq);\n doUpdate = (oldVal != this.recv);\n break;\n case 'read':\n oldVal = this.read;\n this.read = Math.max(this.read, seq);\n doUpdate = (oldVal != this.read);\n break;\n case 'msg':\n oldVal = this.seq;\n this.seq = Math.max(this.seq, seq);\n if (!this.touched || this.touched < ts) {\n this.touched = ts;\n }\n doUpdate = (oldVal != this.seq);\n break;\n }\n\n // Sanity checks.\n if (this.recv < this.read) {\n this.recv = this.read;\n doUpdate = true;\n }\n if (this.seq < this.recv) {\n this.seq = this.recv;\n if (!this.touched || this.touched < ts) {\n this.touched = ts;\n }\n doUpdate = true;\n }\n this.unread = this.seq - this.read;\n return doUpdate;\n }\n /**\n * Get user description from global cache. The user does not need to be a\n * subscriber of this topic.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - ID of the user to fetch.\n * @return {Object} user description or undefined.\n */\n userDesc(uid) {\n // TODO: handle asynchronous requests\n const user = this._cacheGetUser(uid);\n if (user) {\n return user; // Promise.resolve(user)\n }\n }\n /**\n * Get description of the p2p peer from subscription cache.\n * @memberof Tinode.Topic#\n *\n * @return {Object} peer's description or undefined.\n */\n p2pPeerDesc() {\n if (!this.isP2PType()) {\n return undefined;\n }\n return this._users[this.name];\n }\n /**\n * Iterate over cached subscribers. If callback is undefined, use this.onMetaSub.\n * @memberof Tinode.Topic#\n *\n * @param {function} callback - Callback which will receive subscribers one by one.\n * @param {Object=} context - Value of `this` inside the `callback`.\n */\n subscribers(callback, context) {\n const cb = (callback || this.onMetaSub);\n if (cb) {\n for (let idx in this._users) {\n cb.call(context, this._users[idx], idx, this._users);\n }\n }\n }\n /**\n * Get a copy of cached tags.\n * @memberof Tinode.Topic#\n *\n * @return {Array.} a copy of tags\n */\n tags() {\n // Return a copy.\n return this._tags.slice(0);\n }\n /**\n * Get auxiliary entry by key.\n * @memberof Tinode.Topic#\n * @param {string} key - auxiliary data key to retrieve.\n * @return {Object} value for the key or undefined.\n */\n aux(key) {\n return this._aux[key];\n }\n /**\n * Get alias value (unique tag with alias: prefix), if present.\n * The prefix is stripped off.\n * @memberof Tinode.Topic#\n * @return {string} alias or undefined.\n */\n alias() {\n const alias = this._tags && this._tags.find(t => t.startsWith(Const.TAG_ALIAS));\n if (!alias) {\n return undefined;\n }\n // Remove 'alias:' prefix.\n return alias.substring(Const.TAG_ALIAS.length);\n }\n\n /**\n * Get cached subscription for the given user ID.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - id of the user to query for\n * @return user description or undefined.\n */\n subscriber(uid) {\n return this._users[uid];\n }\n /**\n * Iterate over versions of a message: call callback for each version (excluding original).\n * If callback is undefined, does nothing.\n * @memberof Tinode.Topic#\n *\n * @param {number} origSeq - seq ID of the original message.\n * @param {Tinode.ForEachCallbackType} callback - Callback which will receive messages one by one. See {@link Tinode.CBuffer#forEach}\n * @param {Object} context - Value of `this` inside the `callback`.\n */\n messageVersions(origSeq, callback, context) {\n if (!callback) {\n // No callback? We are done then.\n return;\n }\n const versions = this._messageVersions[origSeq];\n if (!versions) {\n return;\n }\n versions.forEach(callback, undefined, undefined, context);\n }\n /**\n * Iterate over cached messages: call callback for each message in the range [sinceIdx, beforeIdx).\n * If callback is undefined, use this.onData.\n * @memberof Tinode.Topic#\n *\n * @param {Tinode.ForEachCallbackType} callback - Callback which will receive messages one by one. See {@link Tinode.CBuffer#forEach}\n * @param {number} sinceId - Optional seqId to start iterating from (inclusive).\n * @param {number} beforeId - Optional seqId to stop iterating before it is reached (exclusive).\n * @param {Object} context - Value of `this` inside the `callback`.\n */\n messages(callback, sinceId, beforeId, context) {\n const cb = (callback || this.onData);\n if (cb) {\n const startIdx = typeof sinceId == 'number' ? this._messages.find({\n seq: sinceId\n }, true) : undefined;\n const beforeIdx = typeof beforeId == 'number' ? this._messages.find({\n seq: beforeId\n }, true) : undefined;\n if (startIdx != -1 && beforeIdx != -1) {\n // Step 1. Filter out all replacement messages and\n // save displayable messages in a temporary buffer.\n let msgs = [];\n this._messages.forEach((msg, unused1, unused2, i) => {\n if (Topic.#isReplacementMsg(msg)) {\n // Skip replacements.\n return;\n }\n if (msg._deleted) {\n // Skip deleted ranges.\n return;\n }\n // In case the massage was edited, replace timestamp of the version with the original's timestamp.\n const latest = this.latestMsgVersion(msg.seq) || msg;\n if (!latest._origTs) {\n latest._origTs = latest.ts;\n latest._origSeq = latest.seq;\n latest.ts = msg.ts;\n latest.seq = msg.seq;\n }\n msgs.push({\n data: latest,\n idx: i\n });\n }, startIdx, beforeIdx, {});\n // Step 2. Loop over displayble messages invoking cb on each of them.\n msgs.forEach((val, i) => {\n cb.call(context, val.data,\n (i > 0 ? msgs[i - 1].data : undefined),\n (i < msgs.length - 1 ? msgs[i + 1].data : undefined), val.idx);\n });\n }\n }\n }\n /**\n * Get the message from cache by literal seq (does not resolve message edits).\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - message seqId to search for.\n * @returns {Object} the message with the given seq or undefined, if no such message is found.\n */\n findMessage(seq) {\n const idx = this._messages.find({\n seq: seq\n });\n if (idx >= 0) {\n return this._messages.getAt(idx);\n }\n return undefined;\n }\n /**\n * Get the most recent non-deleted message from cache.\n * @memberof Tinode.Topic#\n *\n * @returns {Object} the most recent cached message or undefined, if no messages are cached.\n */\n latestMessage() {\n return this._messages.getLast(msg => !msg._deleted);\n }\n /**\n * Get the latest version for message.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - original seq ID of the message.\n * @returns {Object} the latest version of the message or null if message not found.\n */\n latestMsgVersion(seq) {\n const versions = this._messageVersions[seq];\n return versions ? versions.getLast() : null;\n }\n /**\n * Get the maximum cached seq ID.\n * @memberof Tinode.Topic#\n *\n * @returns {number} the greatest seq ID in cache.\n */\n maxMsgSeq() {\n return this._maxSeq;\n }\n /**\n * Get the minimum cached seq ID.\n * @memberof Tinode.Topic#\n *\n * @returns {number} the smallest seq ID in cache or 0.\n */\n minMsgSeq() {\n return this._minSeq;\n }\n /**\n * Get the maximum deletion ID.\n * @memberof Tinode.Topic#\n *\n * @returns {number} the greatest deletion ID.\n */\n maxClearId() {\n return this._maxDel;\n }\n /**\n * Get the number of messages in the cache.\n * @memberof Tinode.Topic#\n *\n * @returns {number} count of cached messages.\n */\n messageCount() {\n return this._messages.length();\n }\n /**\n * Iterate over cached unsent messages. Wraps {@link Tinode.Topic#messages}.\n * @memberof Tinode.Topic#\n *\n * @param {function} callback - Callback which will receive messages one by one. See {@link Tinode.CBuffer#forEach}\n * @param {Object} context - Value of this inside the callback.\n */\n queuedMessages(callback, context) {\n if (!callback) {\n throw new Error(\"Callback must be provided\");\n }\n this.messages(callback, Const.LOCAL_SEQID, undefined, context);\n }\n /**\n * Get the number of topic subscribers who marked this message as either recv or read\n * Current user is excluded from the count.\n * @memberof Tinode.Topic#\n *\n * @param {string} what - what action to consider: received \"recv\" or read \"read\".\n * @param {number} seq - ID or the message read or received.\n *\n * @returns {number} the number of subscribers who marked the message with the given ID as read or received.\n */\n msgReceiptCount(what, seq) {\n let count = 0;\n if (seq > 0) {\n const me = this._tinode.getCurrentUserID();\n for (let idx in this._users) {\n const user = this._users[idx];\n if (user.user !== me && user[what] >= seq) {\n count++;\n }\n }\n }\n return count;\n }\n /**\n * Get the number of topic subscribers who marked this message (and all older messages) as read.\n * The current user is excluded from the count.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - message id to check.\n * @returns {number} number of subscribers who claim to have received the message.\n */\n msgReadCount(seq) {\n return this.msgReceiptCount('read', seq);\n }\n /**\n * Get the number of topic subscribers who marked this message (and all older messages) as received.\n * The current user is excluded from the count.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - Message id to check.\n * @returns {number} Number of subscribers who claim to have received the message.\n */\n msgRecvCount(seq) {\n return this.msgReceiptCount('recv', seq);\n }\n /**\n * Check if cached message IDs indicate that the server may have more messages.\n * @memberof Tinode.Topic#\n *\n * @param {number} min - smallest seq ID loaded range.\n * @param {number} max - greatest seq ID in loaded range.\n * @param {boolean} newer - if true, check for newer messages only.\n * @returns {Array.} - missing ranges in the selected direction.\n */\n msgHasMoreMessages(min, max, newer) {\n // Find gaps in cached messages.\n const gaps = [];\n if (min >= max) {\n return gaps;\n }\n let maxSeq = 0;\n let gap;\n this._messages.forEach((msg, prev) => {\n const p = prev || {\n seq: 0\n };\n const expected = p._deleted ? p.hi : p.seq + 1;\n if (msg.seq > expected) {\n gap = {\n low: expected,\n hi: msg.seq\n };\n } else {\n gap = null;\n }\n // If newer: collect all gaps from min to infinity.\n // If older: collect all gaps from max to zero.\n if (gap && (newer ? gap.hi >= min : gap.low < max)) {\n gaps.push(gap);\n }\n maxSeq = expected;\n });\n\n if (maxSeq < this.seq) {\n gap = {\n low: maxSeq + 1,\n hi: this.seq + 1\n };\n if (newer ? gap.hi >= min : gap.low < max) {\n gaps.push(gap);\n }\n }\n return gaps;\n }\n /**\n * Check if the given seq Id is id of the most recent message.\n * @memberof Tinode.Topic#\n *\n * @param {number} seqId id of the message to check\n */\n isNewMessage(seqId) {\n return this._maxSeq <= seqId;\n }\n /**\n * Remove one message from local cache.\n * @memberof Tinode.Topic#\n *\n * @param {number} seqId id of the message to remove from cache.\n * @returns {Message} removed message or undefined if such message was not found.\n */\n flushMessage(seqId) {\n const idx = this._messages.find({\n seq: seqId\n });\n delete this._messageVersions[seqId];\n if (idx >= 0) {\n this._tinode._db.remMessages(this.name, seqId);\n return this._messages.delAt(idx);\n }\n return undefined;\n }\n /**\n * Remove a range of messages from the local cache.\n * @memberof Tinode.Topic#\n *\n * @param {number} fromId seq ID of the first message to remove (inclusive).\n * @param {number} untilId seqID of the last message to remove (exclusive).\n *\n * @returns {Message[]} array of removed messages (could be empty).\n */\n flushMessageRange(fromId, untilId) {\n // Remove range from persistent cache.\n this._tinode._db.remMessages(this.name, fromId, untilId);\n\n // Remove all versions keyed by IDs in the range.\n for (let i = fromId; i < untilId; i++) {\n delete this._messageVersions[i];\n }\n\n // start, end: find insertion points (nearest == true).\n const since = this._messages.find({\n seq: fromId\n }, true);\n return since >= 0 ? this._messages.delRange(since, this._messages.find({\n seq: untilId\n }, true)) : [];\n }\n /**\n * Update message's seqId.\n * @memberof Tinode.Topic#\n *\n * @param {Object} pub message object.\n * @param {number} newSeqId new seq id for pub.\n */\n swapMessageId(pub, newSeqId) {\n const idx = this._messages.find(pub);\n const numMessages = this._messages.length();\n if (0 <= idx && idx < numMessages) {\n // Remove message with the old seq ID.\n this._messages.delAt(idx);\n this._tinode._db.remMessages(this.name, pub.seq);\n // Add message with the new seq ID.\n pub.seq = newSeqId;\n this._messages.put(pub);\n this._tinode._db.addMessage(pub);\n }\n }\n /**\n * Attempt to stop message from being sent.\n * @memberof Tinode.Topic#\n *\n * @param {number} seqId id of the message to stop sending and remove from cache.\n *\n * @returns {boolean} true if message was cancelled, false otherwise.\n */\n cancelSend(seqId) {\n const idx = this._messages.find({\n seq: seqId\n });\n if (idx >= 0) {\n const msg = this._messages.getAt(idx);\n const status = this.msgStatus(msg);\n if (status == Const.MESSAGE_STATUS_QUEUED ||\n status == Const.MESSAGE_STATUS_FAILED ||\n status == Const.MESSAGE_STATUS_FATAL) {\n this._tinode._db.remMessages(this.name, seqId);\n msg._cancelled = true;\n this._messages.delAt(idx);\n if (this.onData) {\n // Calling with no parameters to indicate the message was deleted.\n this.onData();\n }\n return true;\n }\n }\n return false;\n }\n /**\n * Get type of the topic: me, p2p, grp, fnd...\n * @memberof Tinode.Topic#\n *\n * @returns {string} One of 'me', 'p2p', 'grp', 'fnd', 'sys' or undefined.\n */\n getType() {\n return Topic.topicType(this.name);\n }\n /**\n * Get current user's access mode of the topic.\n * @memberof Tinode.Topic#\n *\n * @returns {Tinode.AccessMode} - user's access mode\n */\n getAccessMode() {\n return this.acs;\n }\n /**\n * Set current user's access mode of the topic.\n * @memberof Tinode.Topic#\n *\n * @param {AccessMode | Object} acs - access mode to set.\n */\n setAccessMode(acs) {\n return this.acs = new AccessMode(acs);\n }\n /**\n * Get topic's default access mode.\n * @memberof Tinode.Topic#\n *\n * @returns {Tinode.DefAcs} - access mode, such as {auth: `RWP`, anon: `N`}.\n */\n getDefaultAccess() {\n return this.defacs;\n }\n /**\n * Initialize new meta {@link Tinode.GetQuery} builder. The query is attched to the current topic.\n * It will not work correctly if used with a different topic.\n * @memberof Tinode.Topic#\n *\n * @returns {Tinode.MetaGetBuilder} query attached to the current topic.\n */\n startMetaQuery() {\n return new MetaGetBuilder(this);\n }\n /**\n * Check if topic is archived, i.e. private.arch == true.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is archived, false otherwise.\n */\n isArchived() {\n return this.private && !!this.private.arch;\n }\n /**\n * Check if topic is a 'me' topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a 'me' topic, false otherwise.\n */\n isMeType() {\n return Topic.isMeTopicName(this.name);\n }\n /**\n * Check if topic is a 'slf' topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a 'slf' topic, false otherwise.\n */\n isSelfType() {\n return Topic.isSelfTopicName(this.name);\n }\n /**\n * Check if topic is a channel.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a channel, false otherwise.\n */\n isChannelType() {\n return Topic.isChannelTopicName(this.name);\n }\n /**\n * Check if topic is a group topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a group, false otherwise.\n */\n isGroupType() {\n return Topic.isGroupTopicName(this.name);\n }\n /**\n * Check if topic is a p2p topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a p2p topic, false otherwise.\n */\n isP2PType() {\n return Topic.isP2PTopicName(this.name);\n }\n /**\n * Check if topic is a communication topic, i.e. a group or p2p topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a p2p or group topic, false otherwise.\n */\n isCommType() {\n return Topic.isCommTopicName(this.name);\n }\n /**\n * Get status (queued, sent, received etc) of a given message in the context\n * of this topic.\n * @memberof Tinode.Topic#\n *\n * @param {Message} msg - message to check for status.\n * @param {boolean} upd - update chached message status.\n *\n * @returns message status constant.\n */\n msgStatus(msg, upd) {\n let status = Const.MESSAGE_STATUS_NONE;\n if (this._tinode.isMe(msg.from)) {\n if (msg._sending) {\n status = Const.MESSAGE_STATUS_SENDING;\n } else if (msg._fatal || msg._cancelled) {\n status = Const.MESSAGE_STATUS_FATAL;\n } else if (msg._failed) {\n status = Const.MESSAGE_STATUS_FAILED;\n } else if (msg.seq >= Const.LOCAL_SEQID) {\n status = Const.MESSAGE_STATUS_QUEUED;\n } else if (this.msgReadCount(msg.seq) > 0) {\n status = Const.MESSAGE_STATUS_READ;\n } else if (this.msgRecvCount(msg.seq) > 0) {\n status = Const.MESSAGE_STATUS_RECEIVED;\n } else if (msg.seq > 0) {\n status = Const.MESSAGE_STATUS_SENT;\n }\n } else {\n status = Const.MESSAGE_STATUS_TO_ME;\n }\n\n if (upd && msg._status != status) {\n msg._status = status;\n this._tinode._db.updMessageStatus(this.name, msg.seq, status);\n }\n\n return status;\n }\n\n // If msg is a replacement for another message, save the msg in the message versions cache\n // as a newer version for the message it's supposed to replace.\n _maybeUpdateMessageVersionsCache(msg) {\n if (!Topic.#isReplacementMsg(msg)) {\n // Check if this message is the original in the chain of edits and if so\n // ensure all version have the same sender.\n if (this._messageVersions[msg.seq]) {\n // Remove versions with different 'from'.\n this._messageVersions[msg.seq].filter(version => version.from == msg.from);\n if (this._messageVersions[msg.seq].isEmpty()) {\n delete this._messageVersions[msg.seq];\n }\n }\n return;\n }\n\n const targetSeq = parseInt(msg.head.replace.split(':')[1]);\n if (targetSeq > msg.seq) {\n // Substitutes are supposed to have higher seq ids.\n return;\n }\n const targetMsg = this.findMessage(targetSeq);\n if (targetMsg && targetMsg.from != msg.from) {\n // Substitute cannot change the sender.\n return;\n }\n const versions = this._messageVersions[targetSeq] || new CBuffer((a, b) => {\n return a.seq - b.seq;\n }, true);\n versions.put(msg);\n this._messageVersions[targetSeq] = versions;\n }\n\n // Process data message\n _routeData(data) {\n if (data.content) {\n if (!this.touched || this.touched < data.ts) {\n this.touched = data.ts;\n this._tinode._db.updTopic(this);\n }\n }\n\n if (data.seq > this._maxSeq) {\n this._maxSeq = data.seq;\n this.msgStatus(data, true);\n // Ackn receiving the message.\n clearTimeout(this._recvNotificationTimer);\n this._recvNotificationTimer = setTimeout(_ => {\n this._recvNotificationTimer = null;\n this.noteRecv(this._maxSeq);\n }, Const.RECV_TIMEOUT);\n }\n\n if (data.seq < this._minSeq || this._minSeq == 0) {\n this._minSeq = data.seq;\n }\n\n const outgoing = ((!this.isChannelType() && !data.from) || this._tinode.isMe(data.from));\n\n if (data.head && data.head.webrtc && data.head.mime == Drafty.getContentType() && data.content) {\n // Rewrite VC body with info from the headers.\n const upd = {\n state: data.head.webrtc,\n duration: data.head['webrtc-duration'],\n incoming: !outgoing,\n };\n if (data.head.vc) {\n upd.vc = true;\n }\n data.content = Drafty.updateVideoCall(data.content, upd);\n }\n\n if (!data._noForwarding) {\n this._messages.put(data);\n this._tinode._db.addMessage(data);\n this._maybeUpdateMessageVersionsCache(data);\n }\n\n if (this.onData) {\n this.onData(data);\n }\n\n // Update locally cached contact with the new message count.\n const what = outgoing ? 'read' : 'msg';\n this._updateMyReadRecv(what, data.seq, data.ts);\n\n if (!outgoing && data.from) {\n // Mark messages as read by the sender.\n this._routeInfo({\n what: 'read',\n from: data.from,\n seq: data.seq,\n _noForwarding: true\n });\n }\n\n // Notify 'me' listeners of the change.\n this._tinode.getMeTopic()._refreshContact(what, this);\n }\n\n // Process metadata message\n _routeMeta(meta) {\n if (meta.desc) {\n this._processMetaDesc(meta.desc);\n }\n if (meta.sub && meta.sub.length > 0) {\n this._processMetaSubs(meta.sub);\n }\n if (meta.del) {\n this._processDelMessages(meta.del.clear, meta.del.delseq);\n }\n if (meta.tags) {\n this._processMetaTags(meta.tags);\n }\n if (meta.cred) {\n this._processMetaCreds(meta.cred);\n }\n if (meta.aux) {\n this._processMetaAux(meta.aux);\n }\n if (this.onMeta) {\n this.onMeta(meta);\n }\n }\n // Process presence change message\n _routePres(pres) {\n let user, uid;\n switch (pres.what) {\n case 'del':\n // Delete cached messages.\n this._processDelMessages(pres.clear, pres.delseq);\n break;\n case 'on':\n case 'off':\n // Update online status of a subscription.\n user = this._users[pres.src];\n if (user) {\n user.online = pres.what == 'on';\n } else {\n this._tinode.logger(\"WARNING: Presence update for an unknown user\", this.name, pres.src);\n }\n break;\n case 'term':\n // Attachment to topic is terminated probably due to cluster rehashing.\n this._resetSub();\n break;\n case 'upd':\n // A topic subscriber has updated his description.\n // Issue {get sub} only if the current user has no p2p topics with the updated user (p2p name is not in cache).\n // Otherwise 'me' will issue a {get desc} request.\n if (pres.src && !this._tinode.isTopicCached(pres.src)) {\n this.getMeta(this.startMetaQuery().withOneSub(undefined, pres.src).build());\n }\n break;\n case 'aux':\n // Auxiliary data updated.\n this.getMeta(this.startMetaQuery().withAux().build());\n break;\n case 'acs':\n uid = pres.src || this._tinode.getCurrentUserID();\n user = this._users[uid];\n if (!user) {\n // Update for an unknown user: notification of a new subscription.\n const acs = new AccessMode().updateAll(pres.dacs);\n if (acs && acs.mode != AccessMode._NONE) {\n user = this._cacheGetUser(uid);\n if (!user) {\n user = {\n user: uid,\n acs: acs\n };\n this.getMeta(this.startMetaQuery().withOneSub(undefined, uid).build());\n } else {\n user.acs = acs;\n }\n user.updated = new Date();\n this._processMetaSubs([user]);\n }\n } else {\n // Known user\n user.acs.updateAll(pres.dacs);\n // Update user's access mode.\n this._processMetaSubs([{\n user: uid,\n updated: new Date(),\n acs: user.acs\n }]);\n }\n break;\n default:\n this._tinode.logger(\"INFO: Ignored presence update\", pres.what);\n }\n\n if (this.onPres) {\n this.onPres(pres);\n }\n }\n // Process {info} message\n _routeInfo(info) {\n switch (info.what) {\n case 'recv':\n case 'read':\n const user = this._users[info.from];\n if (user) {\n user[info.what] = info.seq;\n if (user.recv < user.read) {\n user.recv = user.read;\n }\n }\n const msg = this.latestMessage();\n if (msg) {\n this.msgStatus(msg, true);\n }\n\n // If this is an update from the current user, update the cache with the new count.\n if (this._tinode.isMe(info.from) && !info._noForwarding) {\n this._updateMyReadRecv(info.what, info.seq);\n }\n\n // Notify 'me' listener of the status change.\n this._tinode.getMeTopic()._refreshContact(info.what, this);\n break;\n case 'kp':\n case 'kpa':\n case 'kpv':\n // Typing or audio/video recording notification. Do nothing.\n break;\n case 'call':\n // Do nothing here.\n break;\n default:\n this._tinode.logger(\"INFO: Ignored info update\", info.what);\n }\n\n if (this.onInfo) {\n this.onInfo(info);\n }\n }\n // Called by Tinode when meta.desc packet is received.\n // Called by 'me' topic on contact update (desc._noForwarding is true).\n _processMetaDesc(desc) {\n if (this.isP2PType()) {\n // Synthetic desc may include defacs for p2p topics which is useless.\n // Remove it.\n delete desc.defacs;\n\n // Update to p2p desc is the same as user update. Update cached user.\n this._tinode._db.updUser(this.name, desc.public);\n }\n\n // Copy parameters from desc object to this topic.\n mergeObj(this, desc);\n // Update persistent cache.\n this._tinode._db.updTopic(this);\n\n // Notify 'me' listener, if available:\n if (this.name !== Const.TOPIC_ME && !desc._noForwarding) {\n const me = this._tinode.getMeTopic();\n if (me.onMetaSub) {\n me.onMetaSub(this);\n }\n if (me.onSubsUpdated) {\n me.onSubsUpdated([this.name], 1);\n }\n }\n\n if (this.onMetaDesc) {\n this.onMetaDesc(this);\n }\n }\n // Called by Tinode when meta.sub is recived or in response to received\n // {ctrl} after setMeta-sub.\n _processMetaSubs(subs) {\n for (let idx in subs) {\n const sub = subs[idx];\n\n // Fill defaults.\n sub.online = !!sub.online;\n // Update timestamp of the most recent subscription update.\n this._lastSubsUpdate = new Date(Math.max(this._lastSubsUpdate, sub.updated));\n\n let user = null;\n if (!sub.deleted) {\n // If this is a change to user's own permissions, update them in topic too.\n // Desc will update 'me' topic.\n if (this._tinode.isMe(sub.user) && sub.acs) {\n this._processMetaDesc({\n updated: sub.updated,\n touched: sub.touched,\n acs: sub.acs\n });\n }\n user = this._updateCachedUser(sub.user, sub);\n } else {\n // Subscription is deleted, remove it from topic (but leave in Users cache)\n delete this._users[sub.user];\n user = sub;\n }\n\n if (this.onMetaSub) {\n this.onMetaSub(user);\n }\n }\n\n if (this.onSubsUpdated) {\n this.onSubsUpdated(Object.keys(this._users));\n }\n }\n // Called by Tinode when meta.tags is recived.\n _processMetaTags(tags) {\n if (tags == Const.DEL_CHAR || (tags.length == 1 && tags[0] == Const.DEL_CHAR)) {\n tags = [];\n }\n this._tags = tags;\n this._tinode._db.updTopic(this);\n if (this.onTagsUpdated) {\n this.onTagsUpdated(tags);\n }\n }\n // Do nothing for topics other than 'me'\n _processMetaCreds(creds) {}\n\n // Called by Tinode when meta.aux is recived.\n _processMetaAux(aux) {\n aux = (!aux || aux == Const.DEL_CHAR) ? {} : aux;\n this._aux = mergeObj(this._aux, aux);\n this._tinode._db.updTopic(this);\n if (this.onAuxUpdated) {\n this.onAuxUpdated(this._aux);\n }\n }\n\n // Delete cached messages and update cached transaction IDs\n _processDelMessages(clear, delseq) {\n this._maxDel = Math.max(clear, this._maxDel);\n this.clear = Math.max(clear, this.clear);\n let count = 0;\n if (Array.isArray(delseq)) {\n delseq.forEach(rec => {\n if (!rec.hi) {\n count++;\n this.flushMessage(rec.low);\n } else {\n count += rec.hi - rec.low;\n this.flushMessageRange(rec.low, rec.hi);\n }\n this._messages.put({\n seq: rec.low,\n low: rec.low,\n hi: rec.hi,\n _deleted: true\n });\n });\n\n this._tinode._db.addDelLog(this.name, clear, delseq);\n }\n\n if (count > 0) {\n if (this.onData) {\n this.onData();\n }\n }\n }\n // Topic is informed that the entire response to {get what=data} has been received.\n _allMessagesReceived(count) {\n\n if (this.onAllMessagesReceived) {\n this.onAllMessagesReceived(count);\n }\n }\n // Reset subscribed state\n _resetSub() {\n this._attached = false;\n }\n // This topic is either deleted or unsubscribed from.\n _gone() {\n this._messages.reset();\n this._tinode._db.remMessages(this.name);\n this._users = {};\n this.acs = new AccessMode(null);\n this.private = null;\n this.public = null;\n this.trusted = null;\n this._maxSeq = 0;\n this._minSeq = 0;\n this._attached = false;\n\n const me = this._tinode.getMeTopic();\n if (me) {\n me._routePres({\n _noForwarding: true,\n what: 'gone',\n topic: Const.TOPIC_ME,\n src: this.name\n });\n }\n if (this.onDeleteTopic) {\n this.onDeleteTopic();\n }\n }\n // Update global user cache and local subscribers cache.\n // Don't call this method for non-subscribers.\n _updateCachedUser(uid, obj) {\n // Fetch user object from the global cache.\n // This is a clone of the stored object\n let cached = this._cacheGetUser(uid);\n cached = mergeObj(cached || {}, obj);\n // Save to global cache\n this._cachePutUser(uid, cached);\n // Save to the list of topic subsribers.\n return mergeToCache(this._users, uid, cached);\n }\n // Get local seqId for a queued message.\n _getQueuedSeqId() {\n return this._queuedSeqId++;\n }\n\n // Load most recent messages from persistent cache.\n _loadMessages(db, query) {\n query = query || {};\n query.limit = query.limit || Const.DEFAULT_MESSAGES_PAGE;\n\n // Count of message loaded from DB.\n let count = 0;\n return db.readMessages(this.name, query)\n .then(msgs => {\n msgs.forEach(data => {\n if (data.seq > this._maxSeq) {\n this._maxSeq = data.seq;\n }\n if (data.seq < this._minSeq || this._minSeq == 0) {\n this._minSeq = data.seq;\n }\n this._messages.put(data);\n this._maybeUpdateMessageVersionsCache(data);\n });\n count = msgs.length;\n })\n .then(_ => db.readDelLog(this.name, query))\n .then(dellog => {\n return dellog.forEach(rec => {\n this._messages.put({\n seq: rec.low,\n low: rec.low,\n hi: rec.hi,\n _deleted: true\n });\n });\n })\n .then(_ => {\n // DEBUG\n return count;\n });\n }\n\n // Push or {pres}: message received.\n _updateReceived(seq, act) {\n this.touched = new Date();\n this.seq = seq | 0;\n // Check if message is sent by the current user. If so it's been read already.\n if (!act || this._tinode.isMe(act)) {\n this.read = this.read ? Math.max(this.read, this.seq) : this.seq;\n this.recv = this.recv ? Math.max(this.read, this.recv) : this.read;\n }\n this.unread = this.seq - (this.read | 0);\n this._tinode._db.updTopic(this);\n }\n}\n","/**\n * @file Utilities used in multiple places.\n *\n * @copyright 2015-2022 Tinode LLC.\n */\n'use strict';\n\nimport AccessMode from './access-mode.js';\nimport {\n DEL_CHAR,\n LOCAL_SEQID\n} from './config.js';\n\n// Attempt to convert date and AccessMode strings to objects.\nexport function jsonParseHelper(key, val) {\n // Try to convert string timestamps with optional milliseconds to Date,\n // e.g. 2015-09-02T01:45:43[.123]Z\n if (typeof val == 'string' && val.length >= 20 && val.length <= 24 && ['ts', 'touched', 'updated', 'created', 'when', 'deleted', 'expires'].includes(key)) {\n const date = new Date(val);\n if (!isNaN(date)) {\n return date;\n }\n } else if (key === 'acs' && typeof val === 'object') {\n return new AccessMode(val);\n }\n return val;\n}\n\n// Checks if URL is a relative url, i.e. has no 'scheme://', including the case of missing scheme '//'.\n// The scheme is expected to be RFC-compliant, e.g. [a-z][a-z0-9+.-]*\n// example.html - ok\n// https:example.com - not ok.\n// http:/example.com - not ok.\n// ' ↲ https://example.com' - not ok. (↲ means carriage return)\nexport function isUrlRelative(url) {\n return url && !/^\\s*([a-z][a-z0-9+.-]*:|\\/\\/)/im.test(url);\n}\n\nfunction isValidDate(d) {\n return (d instanceof Date) && !isNaN(d) && (d.getTime() != 0);\n}\n\n// RFC3339 formater of Date\nexport function rfc3339DateString(d) {\n if (!isValidDate(d)) {\n return undefined;\n }\n\n const pad = function(val, sp) {\n sp = sp || 2;\n return '0'.repeat(sp - ('' + val).length) + val;\n };\n\n const millis = d.getUTCMilliseconds();\n return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate()) +\n 'T' + pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) +\n (millis ? '.' + pad(millis, 3) : '') + 'Z';\n}\n\n// Recursively merge src's own properties to dst.\n// Ignore properties where ignore[property] is true.\n// Array and Date objects are shallow-copied.\nexport function mergeObj(dst, src, ignore) {\n if (typeof src != 'object') {\n if (src === undefined) {\n return dst;\n }\n if (src === DEL_CHAR) {\n return undefined;\n }\n return src;\n }\n // JS is crazy: typeof null is 'object'.\n if (src === null) {\n return src;\n }\n\n // Handle Date\n if (src instanceof Date && !isNaN(src)) {\n return (!dst || !(dst instanceof Date) || isNaN(dst) || dst < src) ? src : dst;\n }\n\n // Access mode\n if (src instanceof AccessMode) {\n return new AccessMode(src);\n }\n\n // Handle Array\n if (src instanceof Array) {\n return src;\n }\n\n if (!dst || dst === DEL_CHAR) {\n dst = src.constructor();\n }\n\n for (let prop in src) {\n if (src.hasOwnProperty(prop) && (!ignore || !ignore[prop]) && (prop != '_noForwarding')) {\n try {\n dst[prop] = mergeObj(dst[prop], src[prop]);\n } catch (err) {\n // FIXME: probably need to log something here.\n }\n }\n }\n return dst;\n}\n\n// Update object stored in a cache. Returns updated value.\nexport function mergeToCache(cache, key, newval, ignore) {\n cache[key] = mergeObj(cache[key], newval, ignore);\n return cache[key];\n}\n\n// Strips all values from an object of they evaluate to false or if their name starts with '_'.\n// Used on all outgoing object before serialization to string.\nexport function simplify(obj) {\n Object.keys(obj).forEach((key) => {\n if (key[0] == '_') {\n // Strip fields like \"obj._key\".\n delete obj[key];\n } else if (!obj[key]) {\n // Strip fields which evaluate to false.\n delete obj[key];\n } else if (Array.isArray(obj[key]) && obj[key].length == 0) {\n // Strip empty arrays.\n delete obj[key];\n } else if (!obj[key]) {\n // Strip fields which evaluate to false.\n delete obj[key];\n } else if (obj[key] instanceof Date) {\n // Strip invalid or zero date.\n if (!isValidDate(obj[key])) {\n delete obj[key];\n }\n } else if (typeof obj[key] == 'object') {\n simplify(obj[key]);\n // Strip empty objects.\n if (Object.getOwnPropertyNames(obj[key]).length == 0) {\n delete obj[key];\n }\n }\n });\n return obj;\n};\n\n\n// Trim whitespace, convert to lowercase, strip empty, short, and duplicate elements elements.\n// If the result is an empty array, add a single element \"\\u2421\" (Unicode Del character).\nexport function normalizeArray(arr) {\n let out = [];\n if (Array.isArray(arr)) {\n // Trim, throw away very short and empty tags.\n for (let i = 0, l = arr.length; i < l; i++) {\n let t = arr[i];\n if (t) {\n t = t.trim().toLowerCase();\n if (t.length > 1) {\n out.push(t);\n }\n }\n }\n out = out.sort().filter((item, pos, ary) => {\n return !pos || item != ary[pos - 1];\n });\n }\n if (out.length == 0) {\n // Add single tag with a Unicode Del character, otherwise an ampty array\n // is ambiguos. The Del tag will be stripped by the server.\n out.push(DEL_CHAR);\n }\n return out;\n}\n\n// Convert input to valid ranges of IDs.\nexport function normalizeRanges(ranges, maxSeq) {\n if (!Array.isArray(ranges)) {\n return [];\n }\n\n // Sort ranges in accending order by low, then descending by hi.\n ranges.sort((r1, r2) => {\n if (r1.low < r2.low) {\n return -1;\n }\n if (r1.low == r2.low) {\n return (r2.hi | 0) - r1.hi;\n }\n return 1;\n });\n\n // Remove pending messages from ranges possibly clipping some ranges.\n ranges = ranges.reduce((out, r) => {\n if (r.low < LOCAL_SEQID && r.low > 0) {\n if (!r.hi || r.hi < LOCAL_SEQID) {\n out.push(r);\n } else {\n // Clip hi to max allowed value.\n out.push({\n low: r.low,\n hi: maxSeq + 1\n });\n }\n }\n return out;\n }, []);\n\n // Merge overlapping ranges.\n ranges = ranges.reduce((out, r) => {\n if (out.length == 0) {\n out.push(r);\n } else {\n let prev = out[out.length - 1];\n if (r.low <= prev.hi) {\n prev.hi = Math.max(prev.hi, r.hi);\n } else {\n out.push(r);\n }\n }\n return out;\n }, []);\n\n return ranges;\n}\n\n// Convert array of IDs to array of ranges.\nexport function listToRanges(list) {\n // Sort the list in ascending order\n list.sort((a, b) => a - b);\n // Convert the array of IDs to ranges.\n return list.reduce((out, id) => {\n if (out.length == 0) {\n // First element.\n out.push({\n low: id\n });\n } else {\n let prev = out[out.length - 1];\n if ((!prev.hi && (id != prev.low + 1)) || (id > prev.hi)) {\n // New range.\n out.push({\n low: id\n });\n } else {\n // Expand existing range.\n prev.hi = prev.hi ? Math.max(prev.hi, id + 1) : id + 1;\n }\n }\n return out;\n }, []);\n}\n\n// Cuts 'clip' range out of the 'src' range.\n// Returns an array with 0, 1 or 2 elements.\nexport function clipOutRange(src, clip) {\n if (clip.hi <= src.low || clip.low >= src.hi) {\n // Clip is completely outside of src, no intersection.\n return [src];\n }\n\n\n if (clip.low <= src.low) {\n if (clip.hi >= src.hi) {\n // The source range is completely inside the clipping range.\n return [];\n }\n // Partial clipping at the top.\n return [{\n low: clip.hi,\n hi: src.hi\n }];\n }\n\n // Range on the lower end.\n const result = [{\n low: src.low,\n hi: clip.low\n }];\n if (clip.hi < src.hi) {\n // Maybe a range on the higher end, if clip is completely inside the source.\n result.push({\n low: clip.hi,\n hi: src.hi\n });\n }\n\n return result;\n}\n\n// Cuts 'src' range to be completely within 'clip' range.\n// Returns clipped range or null if 'src' is outside of 'clip'.\nexport function clipInRange(src, clip) {\n if (clip.hi <= src.low || clip.low >= src.hi) {\n // The src is completely outside of the clip, no intersection.\n return null;\n }\n\n if (src.low >= clip.low && src.hi <= clip.hi) {\n // Src is completely within the clip, return the entire src.\n return src;\n }\n\n // Partial overlap.\n return {\n low: Math.max(src.low, clip.low),\n hi: Math.min(src.hi, clip.hi)\n };\n\n return result;\n}\n","export const PACKAGE_VERSION = \"0.24.3\";\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/**\n * @module tinode-sdk\n *\n * @copyright 2015-2025 Tinode LLC.\n * @summary Javascript bindings for Tinode.\n * @license Apache 2.0\n * @version 0.24\n *\n * See https://github.com/tinode/webapp for real-life usage.\n *\n * @example\n * \n * \n * \n *\n * \n * ...\n * \n * \n */\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\nimport AccessMode from './access-mode.js';\nimport * as Const from './config.js';\nimport CommError from './comm-error.js';\nimport Connection from './connection.js';\nimport DBCache from './db.js';\nimport Drafty from './drafty.js';\nimport LargeFileHelper from './large-file.js';\nimport MetaGetBuilder from './meta-builder.js';\nimport Topic from './topic.js';\nimport TopicFnd from './fnd-topic.js';\nimport TopicMe from './me-topic.js';\n\nimport {\n isUrlRelative,\n jsonParseHelper,\n mergeObj,\n rfc3339DateString,\n simplify\n} from './utils.js';\n\n// Re-export AccessMode\nexport {\n AccessMode\n};\n\nlet WebSocketProvider;\nif (typeof WebSocket != 'undefined') {\n WebSocketProvider = WebSocket;\n}\n\nlet XHRProvider;\nif (typeof XMLHttpRequest != 'undefined') {\n XHRProvider = XMLHttpRequest;\n}\n\nlet IndexedDBProvider;\nif (typeof indexedDB != 'undefined') {\n IndexedDBProvider = indexedDB;\n}\n\n// Re-export Drafty.\nexport {\n Drafty\n}\n\ninitForNonBrowserApp();\n\n// Utility functions\n\n// Polyfill for non-browser context, e.g. NodeJs.\nfunction initForNonBrowserApp() {\n // Tinode requirement in native mode because react native doesn't provide Base64 method\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n\n if (typeof btoa == 'undefined') {\n global.btoa = function(input = '') {\n let str = input;\n let output = '';\n\n for (let block = 0, charCode, i = 0, map = chars; str.charAt(i | 0) || (map = '=', i % 1); output += map.charAt(63 & block >> 8 - i % 1 * 8)) {\n\n charCode = str.charCodeAt(i += 3 / 4);\n\n if (charCode > 0xFF) {\n throw new Error(\"'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.\");\n }\n block = block << 8 | charCode;\n }\n\n return output;\n };\n }\n\n if (typeof atob == 'undefined') {\n global.atob = function(input = '') {\n let str = input.replace(/=+$/, '');\n let output = '';\n\n if (str.length % 4 == 1) {\n throw new Error(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n for (let bc = 0, bs = 0, buffer, i = 0; buffer = str.charAt(i++);\n\n ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,\n bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0\n ) {\n buffer = chars.indexOf(buffer);\n }\n\n return output;\n };\n }\n\n if (typeof window == 'undefined') {\n global.window = {\n WebSocket: WebSocketProvider,\n XMLHttpRequest: XHRProvider,\n indexedDB: IndexedDBProvider,\n URL: {\n createObjectURL: function() {\n throw new Error(\"Unable to use URL.createObjectURL in a non-browser application\");\n }\n }\n }\n }\n\n Connection.setNetworkProviders(WebSocketProvider, XHRProvider);\n LargeFileHelper.setNetworkProvider(XHRProvider);\n DBCache.setDatabaseProvider(IndexedDBProvider);\n}\n\n// Detect find most useful network transport.\nfunction detectTransport() {\n if (typeof window == 'object') {\n if (window['WebSocket']) {\n return 'ws';\n } else if (window['XMLHttpRequest']) {\n // The browser or node has no websockets, using long polling.\n return 'lp';\n }\n }\n return null;\n}\n\n// btoa replacement. Stock btoa fails on on non-Latin1 strings.\nfunction b64EncodeUnicode(str) {\n // The encodeURIComponent percent-encodes UTF-8 string,\n // then the percent encoding is converted into raw bytes which\n // can be fed into btoa.\n return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,\n function toSolidBytes(match, p1) {\n return String.fromCharCode('0x' + p1);\n }));\n}\n\n// JSON stringify helper - pre-processor for JSON.stringify\nfunction jsonBuildHelper(key, val) {\n if (val instanceof Date) {\n // Convert javascript Date objects to rfc3339 strings\n val = rfc3339DateString(val);\n } else if (val instanceof AccessMode) {\n val = val.jsonHelper();\n } else if (val === undefined || val === null || val === false ||\n (Array.isArray(val) && val.length == 0) ||\n ((typeof val == 'object') && (Object.keys(val).length == 0))) {\n // strip out empty elements while serializing objects to JSON\n return undefined;\n }\n\n return val;\n};\n\n// Trims very long strings (encoded images) to make logged packets more readable.\nfunction jsonLoggerHelper(key, val) {\n if (typeof val == 'string' && val.length > 128) {\n return '<' + val.length + ', bytes: ' + val.substring(0, 12) + '...' + val.substring(val.length - 12) + '>';\n }\n return jsonBuildHelper(key, val);\n};\n\n// Parse browser user agent to extract browser name and version.\nfunction getBrowserInfo(ua, product) {\n ua = ua || '';\n let reactnative = '';\n // Check if this is a ReactNative app.\n if (/reactnative/i.test(product)) {\n reactnative = 'ReactNative; ';\n }\n let result;\n // Remove useless string.\n ua = ua.replace(' (KHTML, like Gecko)', '');\n // Test for WebKit-based browser.\n let m = ua.match(/(AppleWebKit\\/[.\\d]+)/i);\n if (m) {\n // List of common strings, from more useful to less useful.\n // All unknown strings get the highest (-1) priority.\n const priority = ['edg', 'chrome', 'safari', 'mobile', 'version'];\n let tmp = ua.substr(m.index + m[0].length).split(' ');\n let tokens = [];\n let version; // 1.0 in Version/1.0 or undefined;\n // Split string like 'Name/0.0.0' into ['Name', '0.0.0', 3] where the last element is the priority.\n for (let i = 0; i < tmp.length; i++) {\n let m2 = /([\\w.]+)[\\/]([\\.\\d]+)/.exec(tmp[i]);\n if (m2) {\n // Unknown values are highest priority (-1).\n tokens.push([m2[1], m2[2], priority.findIndex((e) => {\n return m2[1].toLowerCase().startsWith(e);\n })]);\n if (m2[1] == 'Version') {\n version = m2[2];\n }\n }\n }\n // Sort by priority: more interesting is earlier than less interesting.\n tokens.sort((a, b) => {\n return a[2] - b[2];\n });\n if (tokens.length > 0) {\n // Return the least common browser string and version.\n if (tokens[0][0].toLowerCase().startsWith('edg')) {\n tokens[0][0] = 'Edge';\n } else if (tokens[0][0] == 'OPR') {\n tokens[0][0] = 'Opera';\n } else if (tokens[0][0] == 'Safari' && version) {\n tokens[0][1] = version;\n }\n result = tokens[0][0] + '/' + tokens[0][1];\n } else {\n // Failed to ID the browser. Return the webkit version.\n result = m[1];\n }\n } else if (/firefox/i.test(ua)) {\n m = /Firefox\\/([.\\d]+)/g.exec(ua);\n if (m) {\n result = 'Firefox/' + m[1];\n } else {\n result = 'Firefox/?';\n }\n } else {\n // Neither AppleWebKit nor Firefox. Try the last resort.\n m = /([\\w.]+)\\/([.\\d]+)/.exec(ua);\n if (m) {\n result = m[1] + '/' + m[2];\n } else {\n m = ua.split(' ');\n result = m[0];\n }\n }\n\n // Shorten the version to one dot 'a.bb.ccc.d -> a.bb' at most.\n m = result.split('/');\n if (m.length > 1) {\n const v = m[1].split('.');\n const minor = v[1] ? '.' + v[1].substr(0, 2) : '';\n result = `${m[0]}/${v[0]}${minor}`;\n }\n return reactnative + result;\n}\n\n/**\n * The main class for interacting with Tinode server.\n */\nexport class Tinode {\n _host;\n _secure;\n\n _appName;\n\n // API Key.\n _apiKey;\n\n // Name and version of the browser.\n _browser = '';\n _platform;\n // Hardware\n _hwos = 'undefined';\n _humanLanguage = 'xx';\n\n // Logging to console enabled\n _loggingEnabled = false;\n // When logging, trip long strings (base64-encoded images) for readability\n _trimLongStrings = false;\n // UID of the currently authenticated user.\n _myUID = null;\n // Status of connection: authenticated or not.\n _authenticated = false;\n // Login used in the last successful basic authentication\n _login = null;\n // Token which can be used for login instead of login/password.\n _authToken = null;\n // Counter of received packets\n _inPacketCount = 0;\n // Counter for generating unique message IDs\n _messageId = Math.floor((Math.random() * 0xFFFF) + 0xFFFF);\n // Information about the server, if connected\n _serverInfo = null;\n // Push notification token. Called deviceToken for consistency with the Android SDK.\n _deviceToken = null;\n\n // Cache of pending promises by message id.\n _pendingPromises = {};\n // The Timeout object returned by the reject expired promises setInterval.\n _expirePromises = null;\n\n // Websocket or long polling connection.\n _connection = null;\n\n // Use indexDB for caching topics and messages.\n _persist = false;\n // IndexedDB wrapper object.\n _db = null;\n\n // Tinode's cache of objects\n _cache = {};\n\n /**\n * Create Tinode object.\n *\n * @param {Object} config - configuration parameters.\n * @param {string} config.appName - Name of the calling application to be reported in the User Agent.\n * @param {string} config.host - Host name and optional port number to connect to.\n * @param {string} config.apiKey - API key generated by keygen.\n * @param {string} config.transport - See {@link Tinode.Connection#transport}.\n * @param {boolean} config.secure - Use Secure WebSocket if true.\n * @param {string} config.platform - Optional platform identifier, one of \"ios\", \"web\", \"android\".\n * @param {boolen} config.persist - Use IndexedDB persistent storage.\n * @param {function} onComplete - callback to call when initialization is completed.\n */\n constructor(config, onComplete) {\n this._host = config.host;\n this._secure = config.secure;\n\n // Client-provided application name, format /\n this._appName = config.appName || \"Undefined\";\n\n // API Key.\n this._apiKey = config.apiKey;\n\n // Name and version of the browser.\n this._platform = config.platform || 'web';\n // Underlying OS.\n if (typeof navigator != 'undefined') {\n this._browser = getBrowserInfo(navigator.userAgent, navigator.product);\n this._hwos = navigator.platform;\n // This is the default language. It could be changed by client.\n this._humanLanguage = navigator.language || 'en-US';\n }\n\n Connection.logger = this.logger;\n Drafty.logger = this.logger;\n\n // WebSocket or long polling network connection.\n if (config.transport != 'lp' && config.transport != 'ws') {\n config.transport = detectTransport();\n }\n this._connection = new Connection(config, Const.PROTOCOL_VERSION, /* autoreconnect */ true);\n this._connection.onMessage = (data) => {\n // Call the main message dispatcher.\n this.#dispatchMessage(data);\n }\n\n // Ready to start sending.\n this._connection.onOpen = _ => this.#connectionOpen();\n this._connection.onDisconnect = (err, code) => this.#disconnected(err, code);\n\n // Wrapper for the reconnect iterator callback.\n this._connection.onAutoreconnectIteration = (timeout, promise) => {\n if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(timeout, promise);\n }\n }\n\n this._persist = config.persist;\n // Initialize object regardless. It simplifies the code.\n this._db = new DBCache(this.logger, this.logger);\n\n if (this._persist) {\n // Create the persistent cache.\n // Store promises to be resolved when messages load into memory.\n const prom = [];\n this._db.initDatabase().then(_ => {\n // First load topics into memory.\n return this._db.mapTopics(data => {\n let topic = this.#cacheGet('topic', data.name);\n if (topic) {\n return;\n }\n if (data.name == Const.TOPIC_ME) {\n topic = new TopicMe();\n } else if (data.name == Const.TOPIC_FND) {\n topic = new TopicFnd();\n } else {\n topic = new Topic(data.name);\n }\n this._db.deserializeTopic(topic, data);\n this.#attachCacheToTopic(topic);\n topic._cachePutSelf();\n this._db.maxDelId(topic.name).then(clear => {\n topic._maxDel = Math.max(topic._maxDel, clear || 0);\n });\n // Topic loaded from DB is not new.\n delete topic._new;\n // Request to load messages and save the promise.\n prom.push(topic._loadMessages(this._db));\n });\n }).then(_ => {\n // Then load users.\n return this._db.mapUsers((data) => {\n this.#cachePut('user', data.uid, mergeObj({}, data.public));\n });\n }).then(_ => {\n // Now wait for all messages to finish loading.\n return Promise.all(prom);\n }).then(_ => {\n if (onComplete) {\n onComplete();\n }\n this.logger(\"Persistent cache initialized.\");\n }).catch(err => {\n if (onComplete) {\n onComplete(err);\n }\n this.logger(\"Failed to initialize persistent cache:\", err);\n });\n } else {\n this._db.deleteDatabase().then(_ => {\n if (onComplete) {\n onComplete();\n }\n });\n }\n }\n\n // Private methods.\n\n // Console logger. Babel somehow fails to parse '...rest' parameter.\n logger(str, ...args) {\n if (this._loggingEnabled) {\n const d = new Date();\n const dateString = ('0' + d.getUTCHours()).slice(-2) + ':' +\n ('0' + d.getUTCMinutes()).slice(-2) + ':' +\n ('0' + d.getUTCSeconds()).slice(-2) + '.' +\n ('00' + d.getUTCMilliseconds()).slice(-3);\n\n console.log('[' + dateString + ']', str, args.join(' '));\n }\n }\n\n // Generator of default promises for sent packets.\n #makePromise(id) {\n let promise = null;\n if (id) {\n promise = new Promise((resolve, reject) => {\n // Stored callbacks will be called when the response packet with this Id arrives\n this._pendingPromises[id] = {\n 'resolve': resolve,\n 'reject': reject,\n 'ts': new Date()\n };\n });\n }\n return promise;\n };\n\n // Resolve or reject a pending promise.\n // Unresolved promises are stored in _pendingPromises.\n #execPromise(id, code, onOK, errorText) {\n const callbacks = this._pendingPromises[id];\n if (callbacks) {\n delete this._pendingPromises[id];\n if (code >= 200 && code < 400) {\n if (callbacks.resolve) {\n callbacks.resolve(onOK);\n }\n } else if (callbacks.reject) {\n callbacks.reject(new CommError(errorText, code));\n }\n }\n }\n\n // Send a packet. If packet id is provided return a promise.\n #send(pkt, id) {\n let promise;\n if (id) {\n promise = this.#makePromise(id);\n }\n pkt = simplify(pkt);\n let msg = JSON.stringify(pkt);\n this.logger(\"out: \" + (this._trimLongStrings ? JSON.stringify(pkt, jsonLoggerHelper) : msg));\n try {\n this._connection.sendText(msg);\n } catch (err) {\n // If sendText throws, wrap the error in a promise or rethrow.\n if (id) {\n this.#execPromise(id, Connection.NETWORK_ERROR, null, err.message);\n } else {\n throw err;\n }\n }\n return promise;\n }\n\n // The main message dispatcher.\n #dispatchMessage(data) {\n // Skip empty response. This happens when LP times out.\n if (!data)\n return;\n\n this._inPacketCount++;\n\n // Send raw message to listener\n if (this.onRawMessage) {\n this.onRawMessage(data);\n }\n\n if (data === '0') {\n // Server response to a network probe.\n if (this.onNetworkProbe) {\n this.onNetworkProbe();\n }\n // No processing is necessary.\n return;\n }\n\n let pkt = JSON.parse(data, jsonParseHelper);\n if (!pkt) {\n this.logger(\"in: \" + data);\n this.logger(\"ERROR: failed to parse data\");\n } else {\n this.logger(\"in: \" + (this._trimLongStrings ? JSON.stringify(pkt, jsonLoggerHelper) : data));\n\n // Send complete packet to listener\n if (this.onMessage) {\n this.onMessage(pkt);\n }\n\n if (pkt.ctrl) {\n // Handling {ctrl} message\n if (this.onCtrlMessage) {\n this.onCtrlMessage(pkt.ctrl);\n }\n\n // Resolve or reject a pending promise, if any\n if (pkt.ctrl.id) {\n this.#execPromise(pkt.ctrl.id, pkt.ctrl.code, pkt.ctrl, pkt.ctrl.text);\n }\n setTimeout(_ => {\n if (pkt.ctrl.code == 205 && pkt.ctrl.text == 'evicted') {\n // User evicted from topic.\n const topic = this.#cacheGet('topic', pkt.ctrl.topic);\n if (topic) {\n topic._resetSub();\n if (pkt.ctrl.params && pkt.ctrl.params.unsub) {\n topic._gone();\n }\n }\n } else if (pkt.ctrl.code < 300 && pkt.ctrl.params) {\n if (pkt.ctrl.params.what == 'data') {\n // code=208, all messages received: \"params\":{\"count\":11,\"what\":\"data\"},\n const topic = this.#cacheGet('topic', pkt.ctrl.topic);\n if (topic) {\n topic._allMessagesReceived(pkt.ctrl.params.count);\n }\n } else if (pkt.ctrl.params.what == 'sub') {\n // code=204, the topic has no (refreshed) subscriptions.\n const topic = this.#cacheGet('topic', pkt.ctrl.topic);\n if (topic) {\n // Trigger topic.onSubsUpdated.\n topic._processMetaSubs([]);\n }\n }\n }\n }, 0);\n } else {\n setTimeout(_ => {\n if (pkt.meta) {\n // Handling a {meta} message.\n // Preferred API: Route meta to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.meta.topic);\n if (topic) {\n topic._routeMeta(pkt.meta);\n }\n\n if (pkt.meta.id) {\n this.#execPromise(pkt.meta.id, 200, pkt.meta, 'META');\n }\n\n // Secondary API: callback\n if (this.onMetaMessage) {\n this.onMetaMessage(pkt.meta);\n }\n } else if (pkt.data) {\n // Handling {data} message\n // Preferred API: Route data to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.data.topic);\n if (topic) {\n topic._routeData(pkt.data);\n }\n\n // Secondary API: Call callback\n if (this.onDataMessage) {\n this.onDataMessage(pkt.data);\n }\n } else if (pkt.pres) {\n // Handling {pres} message\n // Preferred API: Route presence to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.pres.topic);\n if (topic) {\n topic._routePres(pkt.pres);\n }\n\n // Secondary API - callback\n if (this.onPresMessage) {\n this.onPresMessage(pkt.pres);\n }\n } else if (pkt.info) {\n // {info} message - read/received notifications and key presses\n // Preferred API: Route {info}} to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.info.topic);\n if (topic) {\n topic._routeInfo(pkt.info);\n }\n\n // Secondary API - callback\n if (this.onInfoMessage) {\n this.onInfoMessage(pkt.info);\n }\n } else {\n this.logger(\"ERROR: Unknown packet received.\");\n }\n }, 0);\n }\n }\n }\n\n // Connection open, ready to start sending.\n #connectionOpen() {\n if (!this._expirePromises) {\n // Reject promises which have not been resolved for too long.\n this._expirePromises = setInterval(_ => {\n const err = new CommError(\"timeout\", 504);\n const expires = new Date(new Date().getTime() - Const.EXPIRE_PROMISES_TIMEOUT);\n for (let id in this._pendingPromises) {\n let callbacks = this._pendingPromises[id];\n if (callbacks && callbacks.ts < expires) {\n this.logger(\"Promise expired\", id);\n delete this._pendingPromises[id];\n if (callbacks.reject) {\n callbacks.reject(err);\n }\n }\n }\n }, Const.EXPIRE_PROMISES_PERIOD);\n }\n this.hello();\n }\n\n #disconnected(err, code) {\n this._inPacketCount = 0;\n this._serverInfo = null;\n this._authenticated = false;\n\n if (this._expirePromises) {\n clearInterval(this._expirePromises);\n this._expirePromises = null;\n }\n\n // Mark all topics as unsubscribed\n this.#cacheMap('topic', (topic, key) => {\n topic._resetSub();\n });\n\n // Reject all pending promises\n for (let key in this._pendingPromises) {\n const callbacks = this._pendingPromises[key];\n if (callbacks && callbacks.reject) {\n callbacks.reject(err);\n }\n }\n this._pendingPromises = {};\n\n if (this.onDisconnect) {\n this.onDisconnect(err);\n }\n }\n\n // Get User Agent string\n #getUserAgent() {\n return this._appName + ' (' + (this._browser ? this._browser + '; ' : '') + this._hwos + '); ' + Const.LIBRARY;\n }\n\n // Generator of packets stubs\n #initPacket(type, topic) {\n switch (type) {\n case 'hi':\n return {\n 'hi': {\n 'id': this.getNextUniqueId(),\n 'ver': Const.VERSION,\n 'ua': this.#getUserAgent(),\n 'dev': this._deviceToken,\n 'lang': this._humanLanguage,\n 'platf': this._platform\n }\n };\n\n case 'acc':\n return {\n 'acc': {\n 'id': this.getNextUniqueId(),\n 'user': null,\n 'scheme': null,\n 'secret': null,\n 'tmpscheme': null,\n 'tmpsecret': null,\n 'login': false,\n 'tags': null,\n 'desc': {},\n 'cred': {}\n }\n };\n\n case 'login':\n return {\n 'login': {\n 'id': this.getNextUniqueId(),\n 'scheme': null,\n 'secret': null\n }\n };\n\n case 'sub':\n return {\n 'sub': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'set': {},\n 'get': {}\n }\n };\n\n case 'leave':\n return {\n 'leave': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'unsub': false\n }\n };\n\n case 'pub':\n return {\n 'pub': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'noecho': false,\n 'head': null,\n 'content': {}\n }\n };\n\n case 'get':\n return {\n 'get': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'what': null,\n 'desc': {},\n 'sub': {},\n 'data': {}\n }\n };\n\n case 'set':\n return {\n 'set': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'desc': {},\n 'sub': {},\n 'tags': [],\n 'aux': {}\n }\n };\n\n case 'del':\n return {\n 'del': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'what': null,\n 'delseq': null,\n 'user': null,\n 'hard': false\n }\n };\n\n case 'note':\n return {\n 'note': {\n // no id by design (except calls).\n 'topic': topic,\n 'what': null, // one of \"recv\", \"read\", \"kp\", \"call\"\n 'seq': undefined // the server-side message id acknowledged as received or read.\n }\n };\n\n default:\n throw new Error(`Unknown packet type requested: ${type}`);\n }\n }\n\n // Cache management\n #cachePut(type, name, obj) {\n this._cache[type + ':' + name] = obj;\n }\n #cacheGet(type, name) {\n return this._cache[type + ':' + name];\n }\n #cacheDel(type, name) {\n delete this._cache[type + ':' + name];\n }\n\n // Enumerate all items in cache, call func for each item.\n // Enumeration stops if func returns true.\n #cacheMap(type, func, context) {\n const key = type ? type + ':' : undefined;\n for (let idx in this._cache) {\n if (!key || idx.indexOf(key) == 0) {\n if (func.call(context, this._cache[idx], idx)) {\n break;\n }\n }\n }\n }\n\n // Make limited cache management available to topic.\n // Caching user.public only. Everything else is per-topic.\n #attachCacheToTopic(topic) {\n topic._tinode = this;\n\n topic._cacheGetUser = (uid) => {\n const pub = this.#cacheGet('user', uid);\n if (pub) {\n return {\n user: uid,\n public: mergeObj({}, pub)\n };\n }\n return undefined;\n };\n topic._cachePutUser = (uid, user) => {\n this.#cachePut('user', uid, mergeObj({}, user.public));\n };\n topic._cacheDelUser = (uid) => {\n this.#cacheDel('user', uid);\n };\n topic._cachePutSelf = _ => {\n this.#cachePut('topic', topic.name, topic);\n };\n topic._cacheDelSelf = _ => {\n this.#cacheDel('topic', topic.name);\n };\n }\n\n // On successful login save server-provided data.\n #loginSuccessful(ctrl) {\n if (!ctrl.params || !ctrl.params.user) {\n return ctrl;\n }\n // This is a response to a successful login,\n // extract UID and security token, save it in Tinode module\n this._myUID = ctrl.params.user;\n this._authenticated = (ctrl && ctrl.code >= 200 && ctrl.code < 300);\n if (ctrl.params && ctrl.params.token && ctrl.params.expires) {\n this._authToken = {\n token: ctrl.params.token,\n expires: ctrl.params.expires\n };\n } else {\n this._authToken = null;\n }\n\n if (this.onLogin) {\n this.onLogin(ctrl.code, ctrl.text);\n }\n\n return ctrl;\n }\n\n // Static methods.\n /**\n * Helper method to package account credential.\n *\n * @param {string | Credential} meth - validation method or object with validation data.\n * @param {string=} val - validation value (e.g. email or phone number).\n * @param {Object=} params - validation parameters.\n * @param {string=} resp - validation response.\n *\n * @returns {Array.} array with a single credential or null if no valid credentials were given.\n */\n static credential(meth, val, params, resp) {\n if (typeof meth == 'object') {\n ({\n val,\n params,\n resp,\n meth\n } = meth);\n }\n if (meth && (val || resp)) {\n return [{\n 'meth': meth,\n 'val': val,\n 'resp': resp,\n 'params': params\n }];\n }\n return null;\n }\n\n /**\n * Determine topic type from topic's name: grp, p2p, me, fnd, sys.\n * @param {string} name - Name of the topic to test.\n * @returns {string} One of \"me\", \"fnd\", \"sys\", \"grp\",\n * \"p2p\" or undefined.\n */\n static topicType(name) {\n return Topic.topicType(name);\n }\n\n /**\n * Check if the given topic name is a name of a 'me' topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'me' topic, false otherwise.\n */\n static isMeTopicName(name) {\n return Topic.isMeTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a 'slf' topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'slf' topic, false otherwise.\n */\n static isSelfTopicName(name) {\n return Topic.isSelfTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a group topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a group topic, false otherwise.\n */\n static isGroupTopicName(name) {\n return Topic.isGroupTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a p2p topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p topic, false otherwise.\n */\n static isP2PTopicName(name) {\n return Topic.isP2PTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a communication topic, i.e. P2P or group.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p or group topic, false otherwise.\n */\n static isCommTopicName(name) {\n return Topic.isCommTopicName(name);\n }\n /**\n * Check if the topic name is a name of a new topic.\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a new topic, false otherwise.\n */\n static isNewGroupTopicName(name) {\n return Topic.isNewGroupTopicName(name);\n }\n /**\n * Check if the topic name is a name of a channel.\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a channel, false otherwise.\n */\n static isChannelTopicName(name) {\n return Topic.isChannelTopicName(name);\n }\n /**\n * Get information about the current version of this Tinode client library.\n * @returns {string} semantic version of the library, e.g. \"0.15.5-rc1\".\n */\n static getVersion() {\n return Const.VERSION;\n }\n /**\n * To use Tinode in a non browser context, supply WebSocket and XMLHttpRequest providers.\n * @static\n *\n * @param wsProvider WebSocket provider, e.g. for nodeJS , require('ws').\n * @param xhrProvider XMLHttpRequest provider, e.g. for node require('xhr').\n */\n static setNetworkProviders(wsProvider, xhrProvider) {\n WebSocketProvider = wsProvider;\n XHRProvider = xhrProvider;\n\n Connection.setNetworkProviders(WebSocketProvider, XHRProvider);\n LargeFileHelper.setNetworkProvider(XHRProvider);\n }\n /**\n * To use Tinode in a non browser context, supply indexedDB provider.\n * @static\n *\n * @param idbProvider indexedDB provider, e.g. for nodeJS , require('fake-indexeddb').\n */\n static setDatabaseProvider(idbProvider) {\n IndexedDBProvider = idbProvider;\n\n DBCache.setDatabaseProvider(IndexedDBProvider);\n }\n /**\n * Return information about the current name and version of this Tinode library.\n * @static\n *\n * @returns {string} the name of the library and it's version.\n */\n static getLibrary() {\n return Const.LIBRARY;\n }\n /**\n * Check if the given string represents NULL value as defined by Tinode ('\\u2421').\n * @param {string} str - string to check for NULL value.\n * @returns {boolean} true if string represents NULL value, false otherwise.\n */\n static isNullValue(str) {\n return str === Const.DEL_CHAR;\n }\n /**\n * Check if the given seq ID is likely to be issued by the server as oppisite to being temporary locally assigned ID.\n * @param {int} seq - seq ID to check.\n * @returns {boolean} true if seq is likely server-issued, false otherwise.\n */\n static isServerAssignedSeq(seq) {\n return seq > 0 && seq < Const.LOCAL_SEQID;\n }\n\n /**\n * Check if the given string is a valid tag value.\n * @param {string} tag - string to check.\n * @returns {boolean} true if the string is a valid tag value, false otherwise.\n */\n static isValidTagValue(tag) {\n // 4-24 characters, starting with letter or digit, then letters, digits, hyphen, underscore.\n const ALIAS_REGEX = /^[a-z0-9][a-z0-9_\\-]{3,23}$/i;\n return tag && typeof tag == 'string' && tag.length > 3 && tag.length < 24 && ALIAS_REGEX.test(tag);\n }\n\n /**\n * Split fully-qualified tag into prefix and value.\n */\n static tagSplit(tag) {\n if (!tag) {\n return null;\n }\n\n tag = tag.trim();\n\n const splitAt = tag.indexOf(':');\n if (splitAt <= 0) {\n // Invalid syntax.\n return null;\n }\n\n const value = tag.substring(splitAt + 1);\n if (!value) {\n return null;\n }\n return {\n prefix: tag.substring(0, splitAt),\n value: value\n };\n }\n\n /**\n * Set a unique namespace tag.\n * If the tag with this namespace is already present then it's replaced with the new tag.\n * @param uniqueTag tag to add, must be fully-qualified; if null or empty, no action is taken.\n */\n static setUniqueTag(tags, uniqueTag) {\n if (!tags || tags.length == 0) {\n // No tags, just add the new one.\n return [uniqueTag];\n }\n\n const parts = Tinode.tagSplit(uniqueTag)\n if (!parts) {\n // Invalid tag.\n return tags;\n }\n\n // Remove the old tag with the same prefix.\n tags = tags.filter(tag => tag && !tag.startsWith(parts.prefix));\n // Add the new tag.\n tags.push(uniqueTag);\n return tags;\n }\n\n /**\n * Remove a unique tag with the given prefix.\n * @param prefix prefix to remove\n */\n static clearTagPrefix(tags, prefix) {\n if (!tags || tags.length == 0) {\n return [];\n }\n return tags.filter(tag => tag && !tag.startsWith(prefix));\n }\n\n /**\n * Find the first tag with the given prefix.\n * @param prefix prefix to search for.\n * @return the first tag with the given prefix if found or undefined.\n */\n static tagByPrefix(tags, prefix) {\n if (!tags) {\n return undefined;\n }\n\n return tags.find(tag => tag && tag.startsWith(prefix));\n }\n\n // Instance methods.\n\n // Generates unique message IDs\n getNextUniqueId() {\n return (this._messageId != 0) ? '' + this._messageId++ : undefined;\n };\n\n /**\n * Connect to the server.\n *\n * @param {string} host_ - name of the host to connect to.\n * @return {Promise} Promise resolved/rejected when the connection call completes:\n * resolve() is called without parameters, reject() receives the\n * Error as a single parameter.\n */\n connect(host_) {\n return this._connection.connect(host_);\n }\n\n /**\n * Attempt to reconnect to the server immediately.\n *\n * @param {string} force - if true, reconnect even if there is a connection already.\n */\n reconnect(force) {\n this._connection.reconnect(force);\n }\n\n /**\n * Disconnect from the server.\n */\n disconnect() {\n this._connection.disconnect();\n }\n\n /**\n * Clear persistent cache: remove IndexedDB.\n *\n * @return {Promise} Promise resolved/rejected when the operation is completed.\n */\n clearStorage() {\n if (this._db.isReady()) {\n return this._db.deleteDatabase();\n }\n return Promise.resolve();\n }\n\n /**\n * Initialize persistent cache: create IndexedDB cache.\n *\n * @return {Promise} Promise resolved/rejected when the operation is completed.\n */\n initStorage() {\n if (!this._db.isReady()) {\n return this._db.initDatabase();\n }\n return Promise.resolve();\n }\n\n /**\n * Send a network probe message to make sure the connection is alive.\n */\n networkProbe() {\n this._connection.probe();\n }\n\n /**\n * Check for live connection to server.\n *\n * @returns {boolean} true if there is a live connection, false otherwise.\n */\n isConnected() {\n return this._connection.isConnected();\n }\n\n /**\n * Check if connection is authenticated (last login was successful).\n *\n * @returns {boolean} true if authenticated, false otherwise.\n */\n isAuthenticated() {\n return this._authenticated;\n }\n\n /**\n * Add API key and auth token to the relative URL making it usable for getting data\n * from the server in a simple HTTP GET request.\n *\n * @param {string} URL - URL to wrap.\n * @returns {string} URL with appended API key and token, if valid token is present.\n */\n authorizeURL(url) {\n if (typeof url != 'string') {\n return url;\n }\n\n if (isUrlRelative(url)) {\n // Fake base to make the relative URL parseable.\n const base = 'scheme://host/';\n const parsed = new URL(url, base);\n if (this._apiKey) {\n parsed.searchParams.append('apikey', this._apiKey);\n }\n if (this._authToken && this._authToken.token) {\n parsed.searchParams.append('auth', 'token');\n parsed.searchParams.append('secret', this._authToken.token);\n }\n // Convert back to string and strip fake base URL except for the root slash.\n url = parsed.toString().substring(base.length - 1);\n }\n return url;\n }\n\n /**\n * @typedef AccountParams\n * @type {Object}\n * @property {DefAcs=} defacs - Default access parameters for user's me topic.\n * @property {Object=} public - Public application-defined data exposed on me topic.\n * @property {Object=} private - Private application-defined data accessible on me topic.\n * @property {Object=} trusted - Trusted user data which can be set by a root user only.\n * @property {Array.} tags - array of string tags for user discovery.\n * @property {string} scheme - Temporary authentication scheme for password reset.\n * @property {string} secret - Temporary authentication secret for password reset.\n * @property {Array.=} attachments - Array of references to out of band attachments used in account description.\n */\n /**\n * @typedef DefAcs\n * @type {Object}\n * @property {string=} auth - Access mode for me for authenticated users.\n * @property {string=} anon - Access mode for me for anonymous users.\n */\n\n /**\n * Create or update an account.\n *\n * @param {string} uid - User id to update\n * @param {string} scheme - Authentication scheme; \"basic\" and \"anonymous\" are the currently supported schemes.\n * @param {string} secret - Authentication secret, assumed to be already base64 encoded.\n * @param {boolean=} login - Use new account to authenticate current session\n * @param {AccountParams=} params - User data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n account(uid, scheme, secret, login, params) {\n const pkt = this.#initPacket('acc');\n pkt.acc.user = uid;\n pkt.acc.scheme = scheme;\n pkt.acc.secret = secret;\n // Log in to the new account using selected scheme\n pkt.acc.login = login;\n\n if (params) {\n pkt.acc.desc.defacs = params.defacs;\n pkt.acc.desc.public = params.public;\n pkt.acc.desc.private = params.private;\n pkt.acc.desc.trusted = params.trusted;\n\n pkt.acc.tags = params.tags;\n pkt.acc.cred = params.cred;\n\n pkt.acc.tmpscheme = params.scheme;\n pkt.acc.tmpsecret = params.secret;\n\n if (Array.isArray(params.attachments) && params.attachments.length > 0) {\n pkt.extra = {\n attachments: params.attachments.filter(ref => isUrlRelative(ref))\n };\n }\n }\n\n return this.#send(pkt, pkt.acc.id);\n }\n\n /**\n * Create a new user. Wrapper for {@link Tinode#account}.\n *\n * @param {string} scheme - Authentication scheme; \"basic\" is the only currently supported scheme.\n * @param {string} secret - Authentication.\n * @param {boolean=} login - Use new account to authenticate current session\n * @param {AccountParams=} params - User data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n createAccount(scheme, secret, login, params) {\n let promise = this.account(Const.USER_NEW, scheme, secret, login, params);\n if (login) {\n promise = promise.then(ctrl => this.#loginSuccessful(ctrl));\n }\n return promise;\n }\n\n /**\n * Create user with 'basic' authentication scheme and immediately\n * use it for authentication. Wrapper for {@link Tinode#account}.\n *\n * @param {string} username - Login to use for the new account.\n * @param {string} password - User's password.\n * @param {AccountParams=} params - User data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n createAccountBasic(username, password, params) {\n // Make sure we are not using 'null' or 'undefined';\n username = username || '';\n password = password || '';\n return this.createAccount('basic',\n b64EncodeUnicode(username + ':' + password), true, params);\n }\n\n /**\n * Update user's credentials for 'basic' authentication scheme. Wrapper for {@link Tinode#account}.\n *\n * @param {string} uid - User ID to update.\n * @param {string} username - Login to use for the new account.\n * @param {string} password - User's password.\n * @param {AccountParams=} params - data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n updateAccountBasic(uid, username, password, params) {\n // Make sure we are not using 'null' or 'undefined';\n username = username || '';\n password = password || '';\n return this.account(uid, 'basic',\n b64EncodeUnicode(username + ':' + password), false, params);\n }\n\n /**\n * Send handshake to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n hello() {\n const pkt = this.#initPacket('hi');\n\n return this.#send(pkt, pkt.hi.id)\n .then(ctrl => {\n // Reset backoff counter on successful connection.\n this._connection.backoffReset();\n\n // Server response contains server protocol version, build, constraints,\n // session ID for long polling. Save them.\n if (ctrl.params) {\n this._serverInfo = ctrl.params;\n }\n\n if (this.onConnect) {\n this.onConnect();\n }\n\n return ctrl;\n }).catch(err => {\n this._connection.reconnect(true);\n\n if (this.onDisconnect) {\n this.onDisconnect(err);\n }\n });\n }\n\n /**\n * Set or refresh the push notifications/device token. If the client is connected,\n * the deviceToken can be sent to the server.\n *\n * @param {string} dt - token obtained from the provider or false,\n * null or undefined to clear the token.\n *\n * @returns true if attempt was made to send the update to the server.\n */\n setDeviceToken(dt) {\n let sent = false;\n // Convert any falsish value to null.\n dt = dt || null;\n if (dt != this._deviceToken) {\n this._deviceToken = dt;\n if (this.isConnected() && this.isAuthenticated()) {\n this.#send({\n 'hi': {\n 'dev': dt || Tinode.DEL_CHAR\n }\n });\n sent = true;\n }\n }\n return sent;\n }\n\n /**\n * @typedef Credential\n * @type {Object}\n * @property {string} meth - validation method.\n * @property {string} val - value to validate (e.g. email or phone number).\n * @property {string} resp - validation response.\n * @property {Object} params - validation parameters.\n */\n /**\n * Authenticate current session.\n *\n * @param {string} scheme - Authentication scheme; \"basic\" is the only currently supported scheme.\n * @param {string} secret - Authentication secret, assumed to be already base64 encoded.\n * @param {Credential=} cred - credential confirmation, if required.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n login(scheme, secret, cred) {\n const pkt = this.#initPacket('login');\n pkt.login.scheme = scheme;\n pkt.login.secret = secret;\n pkt.login.cred = cred;\n\n return this.#send(pkt, pkt.login.id)\n .then(ctrl => this.#loginSuccessful(ctrl));\n }\n\n /**\n * Wrapper for {@link Tinode#login} with basic authentication\n *\n * @param {string} uname - User name.\n * @param {string} password - Password.\n * @param {Credential=} cred - credential confirmation, if required.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n loginBasic(uname, password, cred) {\n return this.login('basic', b64EncodeUnicode(uname + ':' + password), cred)\n .then(ctrl => {\n this._login = uname;\n return ctrl;\n });\n }\n\n /**\n * Wrapper for {@link Tinode#login} with token authentication\n *\n * @param {string} token - Token received in response to earlier login.\n * @param {Credential=} cred - credential confirmation, if required.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n loginToken(token, cred) {\n return this.login('token', token, cred);\n }\n\n /**\n * Send a request for resetting an authentication secret.\n *\n * @param {string} scheme - authentication scheme to reset.\n * @param {string} method - method to use for resetting the secret, such as \"email\" or \"tel\".\n * @param {string} value - value of the credential to use, a specific email address or a phone number.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving the server reply.\n */\n requestResetAuthSecret(scheme, method, value) {\n return this.login('reset', b64EncodeUnicode(scheme + ':' + method + ':' + value));\n }\n\n /**\n * @typedef AuthToken\n * @type {Object}\n * @property {string} token - Token value.\n * @property {Date} expires - Token expiration time.\n */\n /**\n * Get stored authentication token.\n *\n * @returns {AuthToken} authentication token.\n */\n getAuthToken() {\n if (this._authToken && (this._authToken.expires.getTime() > Date.now())) {\n return this._authToken;\n } else {\n this._authToken = null;\n }\n return null;\n }\n\n /**\n * Application may provide a saved authentication token.\n *\n * @param {AuthToken} token - authentication token.\n */\n setAuthToken(token) {\n this._authToken = token;\n }\n\n /**\n * @typedef SetParams\n * @type {Object}\n * @property {SetDesc=} desc - Topic initialization parameters when creating a new topic or a new subscription.\n * @property {SetSub=} sub - Subscription initialization parameters.\n * @property {Array.=} tags - Search tags.\n * @property {Object} aux - Auxiliary topic data.\n * @property {Array.=} attachments - URLs of out of band attachments used in parameters.\n */\n /**\n * @typedef SetDesc\n * @type {Object}\n * @property {DefAcs=} defacs - Default access mode.\n * @property {Object=} public - Free-form topic description, publically accessible.\n * @property {Object=} private - Free-form topic description accessible only to the owner.\n * @property {Object=} trusted - Trusted user data which can be set by a root user only.\n */\n /**\n * @typedef SetSub\n * @type {Object}\n * @property {string=} user - UID of the user affected by the request. Default (empty) - current user.\n * @property {string=} mode - User access mode, either requested or assigned dependent on context.\n */\n /**\n * Send a topic subscription request.\n *\n * @param {string} topic - Name of the topic to subscribe to.\n * @param {GetQuery=} getParams - Optional subscription metadata query\n * @param {SetParams=} setParams - Optional initialization parameters\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n subscribe(topicName, getParams, setParams) {\n const pkt = this.#initPacket('sub', topicName)\n if (!topicName) {\n topicName = Const.TOPIC_NEW;\n }\n\n pkt.sub.get = getParams;\n\n if (setParams) {\n if (setParams.sub) {\n pkt.sub.set.sub = setParams.sub;\n }\n\n if (setParams.desc) {\n const desc = setParams.desc;\n if (Tinode.isNewGroupTopicName(topicName)) {\n // Full set.desc params are used for new topics only\n pkt.sub.set.desc = desc;\n } else if (Tinode.isP2PTopicName(topicName) && desc.defacs) {\n // Use optional default permissions only.\n pkt.sub.set.desc = {\n defacs: desc.defacs\n };\n }\n }\n\n // See if external objects were used in topic description.\n if (Array.isArray(setParams.attachments) && setParams.attachments.length > 0) {\n pkt.extra = {\n attachments: setParams.attachments.filter(ref => isUrlRelative(ref))\n };\n }\n\n if (setParams.tags) {\n pkt.sub.set.tags = setParams.tags;\n }\n if (setParams.aux) {\n pkt.sub.set.aux = setParams.aux;\n }\n }\n return this.#send(pkt, pkt.sub.id);\n }\n\n /**\n * Detach and optionally unsubscribe from the topic\n *\n * @param {string} topic - Topic to detach from.\n * @param {boolean} unsub - If true, detach and unsubscribe, otherwise just detach.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n leave(topic, unsub) {\n const pkt = this.#initPacket('leave', topic);\n pkt.leave.unsub = unsub;\n\n return this.#send(pkt, pkt.leave.id);\n }\n\n /**\n * Create message draft without sending it to the server.\n *\n * @param {string} topic - Name of the topic to publish to.\n * @param {Object} content - Payload to publish.\n * @param {boolean=} noEcho - If true, tell the server not to echo the message to the original session.\n *\n * @returns {Object} new message which can be sent to the server or otherwise used.\n */\n createMessage(topic, content, noEcho) {\n const pkt = this.#initPacket('pub', topic);\n\n let dft = typeof content == 'string' ? Drafty.parse(content) : content;\n if (dft && !Drafty.isPlainText(dft)) {\n pkt.pub.head = {\n mime: Drafty.getContentType()\n };\n content = dft;\n }\n pkt.pub.noecho = noEcho;\n pkt.pub.content = content;\n\n return pkt.pub;\n }\n\n /**\n * Publish {data} message to topic.\n *\n * @param {string} topicName - Name of the topic to publish to.\n * @param {Object} content - Payload to publish.\n * @param {boolean=} noEcho - If true, tell the server not to echo the message to the original session.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n publish(topicName, content, noEcho) {\n return this.publishMessage(\n this.createMessage(topicName, content, noEcho)\n );\n }\n\n /**\n * Publish message to topic. The message should be created by {@link Tinode#createMessage}.\n *\n * @param {Object} pub - Message to publish.\n * @param {Array.=} attachments - array of URLs with attachments.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n publishMessage(pub, attachments) {\n // Make a shallow copy. Needed in order to clear locally-assigned temp values;\n pub = Object.assign({}, pub);\n pub.seq = undefined;\n pub.from = undefined;\n pub.ts = undefined;\n const msg = {\n pub: pub,\n };\n if (attachments) {\n msg.extra = {\n attachments: attachments.filter(ref => isUrlRelative(ref))\n };\n }\n return this.#send(msg, pub.id);\n }\n\n /**\n * Out of band notification: notify topic that an external (push) notification was recived by the client.\n *\n * @param {object} data - notification payload.\n * @param {string} data.what - notification type, 'msg', 'read', 'sub'.\n * @param {string} data.topic - name of the updated topic.\n * @param {number=} data.seq - seq ID of the affected message.\n * @param {string=} data.xfrom - UID of the sender.\n * @param {object=} data.given - new subscription 'given', e.g. 'ASWP...'.\n * @param {object=} data.want - new subscription 'want', e.g. 'RWJ...'.\n */\n oobNotification(data) {\n this.logger('oob: ' + (this._trimLongStrings ? JSON.stringify(data, jsonLoggerHelper) : data));\n\n switch (data.what) {\n case 'msg':\n if (!data.seq || data.seq < 1 || !data.topic) {\n // Server sent invalid data.\n break;\n }\n\n if (!this.isConnected()) {\n // Let's ignore the message if there is no connection: no connection means there are no open\n // tabs with Tinode.\n break;\n }\n\n const topic = this.#cacheGet('topic', data.topic);\n if (!topic) {\n // TODO: check if there is a case when a message can arrive from an unknown topic.\n break;\n }\n\n if (topic.isSubscribed()) {\n // No need to fetch: topic is already subscribed and got data through normal channel.\n break;\n }\n\n if (topic.maxMsgSeq() < data.seq) {\n if (topic.isChannelType()) {\n topic._updateReceived(data.seq, 'fake-uid');\n }\n\n // New message.\n if (data.xfrom && !this.#cacheGet('user', data.xfrom)) {\n // Message from unknown sender, fetch description from the server.\n // Sending asynchronously without a subscription.\n this.getMeta(data.xfrom, new MetaGetBuilder().withDesc().build()).catch(err => {\n this.logger(\"Failed to get the name of a new sender\", err);\n });\n }\n\n topic.subscribe(null).then(_ => {\n return topic.getMeta(new MetaGetBuilder(topic).withLaterData(24).withLaterDel(24).build());\n }).then(_ => {\n // Allow data fetch to complete and get processed successfully.\n topic.leaveDelayed(false, 1000);\n }).catch(err => {\n this.logger(\"On push data fetch failed\", err);\n }).finally(_ => {\n this.getMeTopic()._refreshContact('msg', topic);\n });\n }\n break;\n\n case 'read':\n this.getMeTopic()._routePres({\n what: 'read',\n seq: data.seq\n });\n break;\n\n case 'sub':\n if (!this.isMe(data.xfrom)) {\n // TODO: handle updates from other users.\n break;\n }\n\n const mode = {\n given: data.modeGiven,\n want: data.modeWant\n };\n const acs = new AccessMode(mode);\n const pres = (!acs.mode || acs.mode == AccessMode._NONE) ?\n // Subscription deleted.\n {\n what: 'gone',\n src: data.topic\n } :\n // New subscription or subscription updated.\n {\n what: 'acs',\n src: data.topic,\n dacs: mode\n };\n this.getMeTopic()._routePres(pres);\n break;\n\n default:\n this.logger(\"Unknown push type ignored\", data.what);\n }\n }\n\n /**\n * @typedef GetOptsType\n * @type {Object}\n * @property {Date=} ims - \"If modified since\", fetch data only it was was modified since stated date.\n * @property {number=} limit - Maximum number of results to return. Ignored when querying topic description.\n */\n\n /**\n * @typedef GetDataType\n * @type {Object}\n * @property {number=} since - Load messages with seq ID equal or greater than this value.\n * @property {number=} before - Load messages with seq ID lower than this number.\n * @property {number=} limit - Maximum number of results to return.\n * @property {Array.=} range - Ranges of seq IDs to fetch.\n */\n\n /**\n * @typedef GetQuery\n * @type {Object}\n * @property {GetOptsType=} desc - If provided (even if empty), fetch topic description.\n * @property {GetOptsType=} sub - If provided (even if empty), fetch topic subscriptions.\n * @property {GetDataType=} data - If provided (even if empty), get messages.\n */\n\n /**\n * Request topic metadata\n *\n * @param {string} topic - Name of the topic to query.\n * @param {GetQuery} params - Parameters of the query. Use {@link Tinode.MetaGetBuilder} to generate.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n getMeta(topic, params) {\n const pkt = this.#initPacket('get', topic);\n\n pkt.get = mergeObj(pkt.get, params);\n\n return this.#send(pkt, pkt.get.id);\n }\n\n /**\n * Update topic's metadata: description, subscribtions.\n *\n * @param {string} topic - Topic to update.\n * @param {SetParams} params - topic metadata to update.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n setMeta(topic, params) {\n const pkt = this.#initPacket('set', topic);\n const what = [];\n\n if (params) {\n ['desc', 'sub', 'tags', 'cred', 'aux'].forEach(key => {\n if (params.hasOwnProperty(key)) {\n what.push(key);\n pkt.set[key] = params[key];\n }\n });\n\n if (Array.isArray(params.attachments) && params.attachments.length > 0) {\n pkt.extra = {\n attachments: params.attachments.filter(ref => isUrlRelative(ref))\n };\n }\n }\n\n if (what.length == 0) {\n return Promise.reject(new Error(\"Invalid {set} parameters\"));\n }\n\n return this.#send(pkt, pkt.set.id);\n }\n\n /**\n * Range of message IDs.\n *\n * @typedef SeqRange\n * @type {Object}\n * @property {number} low - low end of the range, inclusive (closed).\n * @property {number=} hi - high end of the range, exclusive (open).\n */\n /**\n * Delete some or all messages in a topic.\n *\n * @param {string} topic - Topic name to delete messages from.\n * @param {Array.} list - Ranges of message IDs to delete.\n * @param {boolean=} hard - Hard or soft delete\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delMessages(topic, ranges, hard) {\n const pkt = this.#initPacket('del', topic);\n\n pkt.del.what = 'msg';\n pkt.del.delseq = ranges;\n pkt.del.hard = hard;\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Delete the topic alltogether. Requires Owner permission.\n *\n * @param {string} topicName - Name of the topic to delete\n * @param {boolean} hard - hard-delete topic.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delTopic(topicName, hard) {\n const pkt = this.#initPacket('del', topicName);\n pkt.del.what = 'topic';\n pkt.del.hard = hard;\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Delete subscription. Requires Share permission.\n *\n * @param {string} topicName - Name of the topic to delete\n * @param {string} user - User ID to remove.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delSubscription(topicName, user) {\n const pkt = this.#initPacket('del', topicName);\n pkt.del.what = 'sub';\n pkt.del.user = user;\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Delete credential. Always sent on 'me' topic.\n *\n * @param {string} method - validation method such as 'email' or 'tel'.\n * @param {string} value - validation value, i.e. 'alice@example.com'.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delCredential(method, value) {\n const pkt = this.#initPacket('del', Const.TOPIC_ME);\n pkt.del.what = 'cred';\n pkt.del.cred = {\n meth: method,\n val: value\n };\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Request to delete account of the current user.\n *\n * @param {boolean} hard - hard-delete user.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delCurrentUser(hard) {\n const pkt = this.#initPacket('del', null);\n pkt.del.what = 'user';\n pkt.del.hard = hard;\n\n return this.#send(pkt, pkt.del.id).then(_ => {\n this._myUID = null;\n });\n }\n\n /**\n * Notify server that a message or messages were read or received. Does NOT return promise.\n *\n * @param {string} topicName - Name of the topic where the mesage is being aknowledged.\n * @param {string} what - Action being aknowledged, either \"read\" or \"recv\".\n * @param {number} seq - Maximum id of the message being acknowledged.\n * @throws {Error} if seq is invalid.\n */\n note(topicName, what, seq) {\n if (seq <= 0 || seq >= Const.LOCAL_SEQID) {\n throw new Error(`Invalid message id ${seq}`);\n }\n\n const pkt = this.#initPacket('note', topicName);\n pkt.note.what = what;\n pkt.note.seq = seq;\n this.#send(pkt);\n }\n\n /**\n * Broadcast a key-press notification to topic subscribers. Used to show\n * typing notifications \"user X is typing...\".\n *\n * @param {string} topicName - Name of the topic to broadcast to.\n * @param {string=} type - notification to send, default is 'kp'.\n */\n noteKeyPress(topicName, type) {\n const pkt = this.#initPacket('note', topicName);\n pkt.note.what = type || 'kp';\n this.#send(pkt);\n }\n\n /**\n * Send a video call notification to topic subscribers (including dialing,\n * hangup, etc.).\n *\n * @param {string} topicName - Name of the topic to broadcast to.\n * @param {int} seq - ID of the call message the event pertains to.\n * @param {string} evt - Call event.\n * @param {string} payload - Payload associated with this event (e.g. SDP string).\n *\n * @returns {Promise} Promise (for some call events) which will\n * be resolved/rejected on receiving server reply\n */\n videoCall(topicName, seq, evt, payload) {\n const pkt = this.#initPacket('note', topicName);\n pkt.note.seq = seq;\n pkt.note.what = 'call';\n pkt.note.event = evt;\n pkt.note.payload = payload;\n this.#send(pkt, pkt.note.id);\n }\n\n /**\n * Get a named topic, either pull it from cache or create a new instance.\n * There is a single instance of topic for each name.\n *\n * @param {string} topicName - Name of the topic to get.\n *\n * @returns {Topic} Requested or newly created topic or undefined if topic name is invalid.\n */\n getTopic(topicName) {\n let topic = this.#cacheGet('topic', topicName);\n if (!topic && topicName) {\n if (topicName == Const.TOPIC_ME) {\n topic = new TopicMe();\n } else if (topicName == Const.TOPIC_FND) {\n topic = new TopicFnd();\n } else {\n topic = new Topic(topicName);\n }\n // Cache management.\n this.#attachCacheToTopic(topic);\n topic._cachePutSelf();\n // Don't save to DB here: a record will be added when the topic is subscribed.\n }\n return topic;\n }\n\n /**\n * Get a named topic from cache.\n *\n * @param {string} topicName - Name of the topic to get.\n *\n * @returns {Topic} Requested topic or undefined if topic is not found in cache.\n */\n cacheGetTopic(topicName) {\n return this.#cacheGet('topic', topicName);\n }\n\n /**\n * Remove named topic from cache.\n *\n * @param {string} topicName - Name of the topic to remove from cache.\n */\n cacheRemTopic(topicName) {\n this.#cacheDel('topic', topicName);\n }\n\n /**\n * Iterate over cached topics.\n *\n * @param {Function} func - callback to call for each topic.\n * @param {Object} context - 'this' inside the 'func'.\n */\n mapTopics(func, context) {\n this.#cacheMap('topic', func, context);\n }\n\n /**\n * Check if named topic is already present in cache.\n *\n * @param {string} topicName - Name of the topic to check.\n * @returns {boolean} true if topic is found in cache, false otherwise.\n */\n isTopicCached(topicName) {\n return !!this.#cacheGet('topic', topicName);\n }\n\n /**\n * Generate unique name like 'new123456' suitable for creating a new group topic.\n *\n * @param {boolean} isChan - if the topic is channel-enabled.\n * @returns {string} name which can be used for creating a new group topic.\n */\n newGroupTopicName(isChan) {\n return (isChan ? Const.TOPIC_NEW_CHAN : Const.TOPIC_NEW) + this.getNextUniqueId();\n }\n\n /**\n * Instantiate 'me' topic or get it from cache.\n *\n * @returns {TopicMe} Instance of 'me' topic.\n */\n getMeTopic() {\n return this.getTopic(Const.TOPIC_ME);\n }\n\n /**\n * Instantiate 'fnd' (find) topic or get it from cache.\n *\n * @returns {Topic} Instance of 'fnd' topic.\n */\n getFndTopic() {\n return this.getTopic(Const.TOPIC_FND);\n }\n\n /**\n * Create a new {@link LargeFileHelper} instance\n *\n * @returns {LargeFileHelper} instance of a {@link Tinode.LargeFileHelper}.\n */\n getLargeFileHelper() {\n return new LargeFileHelper(this, Const.PROTOCOL_VERSION);\n }\n\n /**\n * Get the UID of the the current authenticated user.\n *\n * @returns {string} UID of the current user or undefined if the session is not yet\n * authenticated or if there is no session.\n */\n getCurrentUserID() {\n return this._myUID;\n }\n\n /**\n * Check if the given user ID is equal to the current user's UID.\n *\n * @param {string} uid - UID to check.\n *\n * @returns {boolean} true if the given UID belongs to the current logged in user.\n */\n isMe(uid) {\n return this._myUID === uid;\n }\n\n /**\n * Get login used for last successful authentication.\n *\n * @returns {string} login last used successfully or undefined.\n */\n getCurrentLogin() {\n return this._login;\n }\n\n /**\n * Return information about the server: protocol version and build timestamp.\n *\n * @returns {Object} build and version of the server or null if there is no connection or\n * if the first server response has not been received yet.\n */\n getServerInfo() {\n return this._serverInfo;\n }\n\n /**\n * Report a topic for abuse. Wrapper for {@link Tinode#publish}.\n *\n * @param {string} action - the only supported action is 'report'.\n * @param {string} target - name of the topic being reported.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n report(action, target) {\n return this.publish(Const.TOPIC_SYS, Drafty.attachJSON(null, {\n 'action': action,\n 'target': target\n }));\n }\n\n /**\n * Return server-provided configuration value.\n *\n * @param {string} name of the value to return.\n * @param {Object} defaultValue to return in case the parameter is not set or not found.\n *\n * @returns {Object} named value.\n */\n getServerParam(name, defaultValue) {\n return this._serverInfo && this._serverInfo[name] || defaultValue;\n }\n\n /**\n * Toggle console logging. Logging is off by default.\n *\n * @param {boolean} enabled - Set to true to enable logging to console.\n * @param {boolean} trimLongStrings - Set to true to trim long strings.\n */\n enableLogging(enabled, trimLongStrings) {\n this._loggingEnabled = enabled;\n this._trimLongStrings = enabled && trimLongStrings;\n }\n\n /**\n * Set UI language to report to the server. Must be called before 'hi' is sent, otherwise it will not be used.\n *\n * @param {string} hl - human (UI) language, like \"en_US\" or \"zh-Hans\".\n */\n setHumanLanguage(hl) {\n if (hl) {\n this._humanLanguage = hl;\n }\n }\n\n /**\n * Check if given topic is online.\n *\n * @param {string} name of the topic to test.\n * @returns {boolean} true if topic is online, false otherwise.\n */\n isTopicOnline(name) {\n const topic = this.#cacheGet('topic', name);\n return topic && topic.online;\n }\n\n /**\n * Get access mode for the given contact.\n *\n * @param {string} name of the topic to query.\n * @returns {AccessMode} access mode if topic is found, null otherwise.\n */\n getTopicAccessMode(name) {\n const topic = this.#cacheGet('topic', name);\n return topic ? topic.acs : null;\n }\n\n /**\n * Include message ID into all subsequest messages to server instructin it to send aknowledgemens.\n * Required for promises to function. Default is \"on\".\n *\n * @param {boolean} status - Turn aknowledgemens on or off.\n * @deprecated\n */\n wantAkn(status) {\n if (status) {\n this._messageId = Math.floor((Math.random() * 0xFFFFFF) + 0xFFFFFF);\n } else {\n this._messageId = 0;\n }\n }\n\n // Callbacks:\n /**\n * Callback to report when the websocket is opened. The callback has no parameters.\n *\n * @type {onWebsocketOpen}\n */\n onWebsocketOpen = undefined;\n\n /**\n * @typedef ServerParams\n *\n * @type {Object}\n * @property {string} ver - Server version\n * @property {string} build - Server build\n * @property {string=} sid - Session ID, long polling connections only.\n */\n\n /**\n * @callback onConnect\n * @param {number} code - Result code\n * @param {string} text - Text epxplaining the completion, i.e \"OK\" or an error message.\n * @param {ServerParams} params - Parameters returned by the server.\n */\n /**\n * Callback to report when connection with Tinode server is established.\n * @type {onConnect}\n */\n onConnect = undefined;\n\n /**\n * Callback to report when connection is lost. The callback has no parameters.\n * @type {onDisconnect}\n */\n onDisconnect = undefined;\n\n /**\n * @callback onLogin\n * @param {number} code - NUmeric completion code, same as HTTP status codes.\n * @param {string} text - Explanation of the completion code.\n */\n /**\n * Callback to report login completion.\n * @type {onLogin}\n */\n onLogin = undefined;\n\n /**\n * Callback to receive {ctrl} (control) messages.\n * @type {onCtrlMessage}\n */\n onCtrlMessage = undefined;\n\n /**\n * Callback to recieve {data} (content) messages.\n * @type {onDataMessage}\n */\n onDataMessage = undefined;\n\n /**\n * Callback to receive {pres} (presence) messages.\n * @type {onPresMessage}\n */\n onPresMessage = undefined;\n\n /**\n * Callback to receive all messages as objects.\n * @type {onMessage}\n */\n onMessage = undefined;\n\n /**\n * Callback to receive all messages as unparsed text.\n * @type {onRawMessage}\n */\n onRawMessage = undefined;\n\n /**\n * Callback to receive server responses to network probes. See {@link Tinode#networkProbe}\n * @type {onNetworkProbe}\n */\n onNetworkProbe = undefined;\n\n /**\n * Callback to be notified when exponential backoff is iterating.\n * @type {onAutoreconnectIteration}\n */\n onAutoreconnectIteration = undefined;\n};\n\n// Exported constants\nTinode.MESSAGE_STATUS_NONE = Const.MESSAGE_STATUS_NONE;\nTinode.MESSAGE_STATUS_QUEUED = Const.MESSAGE_STATUS_QUEUED;\nTinode.MESSAGE_STATUS_SENDING = Const.MESSAGE_STATUS_SENDING;\nTinode.MESSAGE_STATUS_FAILED = Const.MESSAGE_STATUS_FAILED;\nTinode.MESSAGE_STATUS_FATAL = Const.MESSAGE_STATUS_FATAL;\nTinode.MESSAGE_STATUS_SENT = Const.MESSAGE_STATUS_SENT;\nTinode.MESSAGE_STATUS_RECEIVED = Const.MESSAGE_STATUS_RECEIVED;\nTinode.MESSAGE_STATUS_READ = Const.MESSAGE_STATUS_READ;\nTinode.MESSAGE_STATUS_TO_ME = Const.MESSAGE_STATUS_TO_ME;\n\n// Unicode [del] symbol.\nTinode.DEL_CHAR = Const.DEL_CHAR;\n\n// Names of keys to server-provided configuration limits.\nTinode.MAX_MESSAGE_SIZE = 'maxMessageSize';\nTinode.MAX_SUBSCRIBER_COUNT = 'maxSubscriberCount';\nTinode.MIN_TAG_LENGTH = 'minTagLength';\nTinode.MAX_TAG_LENGTH = 'maxTagLength';\nTinode.MAX_TAG_COUNT = 'maxTagCount';\nTinode.MAX_FILE_UPLOAD_SIZE = 'maxFileUploadSize';\nTinode.REQ_CRED_VALIDATORS = 'reqCred';\nTinode.MSG_DELETE_AGE = 'msgDelAge';\n\n// Tinode URI topic ID prefix, 'scheme:path/'.\nTinode.URI_TOPIC_ID_PREFIX = 'tinode:topic/';\n\n// Tag prefixes for alias, email, phone.\nTinode.TAG_ALIAS = Const.TAG_ALIAS;\nTinode.TAG_EMAIL = Const.TAG_EMAIL;\nTinode.TAG_PHONE = Const.TAG_PHONE;\n"],"names":["AccessMode","constructor","acs","given","decode","want","mode","checkFlag","#checkFlag","val","side","flag","includes","Error","str","_BITMASK","_NONE","bitmask","_JOIN","_READ","_WRITE","_PRES","_APPROVE","_SHARE","_DELETE","_OWNER","m0","i","length","bit","charAt","toUpperCase","encode","_INVALID","res","update","upd","action","val0","parts","split","diff","a1","a2","toString","jsonHelper","setMode","m","updateMode","u","getMode","setGiven","g","updateGiven","getGiven","setWant","w","updateWant","getWant","getMissing","getExcessive","updateAll","isOwner","isPresencer","isMuted","isJoiner","isReader","isWriter","isApprover","isAdmin","isSharer","isDeleter","CBuffer","comparator","undefined","unique","buffer","compare_","unique_","a","b","findNearest","#findNearest","elem","arr","exact","start","end","pivot","found","idx","insertSorted","#insertSorted","count","splice","getAt","at","getLast","filter","findLast","put","insert","arguments","Array","isArray","delAt","r","delRange","since","before","reset","forEach","callback","startIdx","beforeIdx","context","Math","max","min","call","find","nearest","isEmpty","CommError","message","code","name","PACKAGE_VERSION","PROTOCOL_VERSION","VERSION","LIBRARY","TOPIC_NEW","TOPIC_NEW_CHAN","TOPIC_ME","TOPIC_FND","TOPIC_SYS","TOPIC_SLF","TOPIC_CHAN","TOPIC_GRP","TOPIC_P2P","USER_NEW","LOCAL_SEQID","MESSAGE_STATUS_NONE","MESSAGE_STATUS_QUEUED","MESSAGE_STATUS_SENDING","MESSAGE_STATUS_FAILED","MESSAGE_STATUS_FATAL","MESSAGE_STATUS_SENT","MESSAGE_STATUS_RECEIVED","MESSAGE_STATUS_READ","MESSAGE_STATUS_TO_ME","EXPIRE_PROMISES_TIMEOUT","EXPIRE_PROMISES_PERIOD","RECV_TIMEOUT","DEFAULT_MESSAGES_PAGE","DEL_CHAR","MAX_PINNED_COUNT","TAG_ALIAS","TAG_EMAIL","TAG_PHONE","jsonParseHelper","WebSocketProvider","XHRProvider","NETWORK_ERROR","NETWORK_ERROR_TEXT","NETWORK_USER","NETWORK_USER_TEXT","_BOFF_BASE","_BOFF_MAX_ITER","_BOFF_JITTER","makeBaseUrl","host","protocol","version","apiKey","url","Connection","log","_","boffTimer","boffIteration","boffClosed","socket","secure","autoreconnect","initialized","config","version_","autoreconnect_","transport","init_lp","init_ws","setNetworkProviders","wsProvider","xhrProvider","logger","l","connect","host_","force","Promise","reject","reconnect","disconnect","sendText","msg","isConnected","probe","backoffReset","boffReset","boffReconnect","#boffReconnect","clearTimeout","timeout","pow","random","onAutoreconnectIteration","setTimeout","prom","catch","boffStop","#boffStop","#boffReset","#init_lp","XDR_UNSENT","XDR_OPENED","XDR_HEADERS_RECEIVED","XDR_LOADING","XDR_DONE","_lpURL","_poller","_sender","lp_sender","url_","sender","onreadystatechange","evt","readyState","status","open","lp_poller","resolve","poller","promiseCompleted","pkt","JSON","parse","responseText","ctrl","params","sid","send","onOpen","onMessage","onDisconnect","text","abort","err","#init_ws","OPEN","close","conn","onerror","onopen","onclose","onmessage","data","DB_VERSION","DB_NAME","IDBProvider","DB","onError","db","disabled","mapObjects","#mapObjects","source","trx","transaction","event","target","error","objectStore","getAll","onsuccess","result","topic","initDatabase","req","onversionchange","onupgradeneeded","objectStoreNames","contains","createObjectStore","keyPath","dellog","indexNames","createIndex","deleteDatabase","onblocked","isReady","updTopic","oncomplete","get","serializeTopic","commit","markTopicAsDeleted","deleted","_deleted","remTopic","delete","IDBKeyRange","only","bound","Number","MAX_SAFE_INTEGER","mapTopics","deserializeTopic","src","updUser","uid","pub","public","remUser","mapUsers","getUser","user","updSubscription","topicName","sub","serializeSubscription","mapSubscriptions","addMessage","add","serializeMessage","updMessageStatus","seq","_status","remMessages","from","to","range","readMessages","query","ranges","key","hi","low","msgs","concat","push","limit","openCursor","cursor","value","continue","addDelLog","delId","clear","readDelLog","entries","map","entry","maxDelId","index","topic_fields","#deserializeTopic","f","hasOwnProperty","tags","_tags","setAccessMode","read","unread","#serializeTopic","dst","getAccessMode","#serializeSubscription","fields","#serializeMessage","setDatabaseProvider","idbProvider","MAX_FORM_ELEMENTS","MAX_PREVIEW_ATTACHMENTS","MAX_PREVIEW_DATA_SIZE","JSON_MIME_TYPE","JSON_MIME_TYPE_LEGACY","DRAFTY_MIME_TYPE","ALLOWED_ENT_FIELDS","segmenter","Intl","Segmenter","INLINE_STYLES","FMT_WEIGHT","ENTITY_TYPES","dataName","pack","test","re","slice","FORMAT_TAGS","AU","html_tag","md_tag","isVoid","BN","BR","CO","DL","EM","EX","FM","HD","HL","HT","IM","LN","MN","RW","QQ","ST","VC","VD","base64toObjectUrl","b64","contentType","bin","atob","buf","ArrayBuffer","Uint8Array","charCodeAt","URL","createObjectURL","Blob","type","base64toDataUrl","DECORATORS","props","href","id","act","ref","mime","Drafty","duration","size","tmpPreviewUrl","_tempPreview","previewUrl","downloadUrl","width","height","title","alt","state","preview","premime","poster","preref","txt","fmt","ent","init","plainText","content","lines","entityMap","entityIndex","blx","line","spans","entities","tag","spannify","block","sort","toSpanTree","chunks","chunkify","drafty","draftify","extractEntities","entity","tp","offset","len","segments","segment","ele","toGraphemeValues","stringToGraphemes","s","correctAt","correctLen","isEmptyObject","append","first","second","insertImage","imageDesc","ex","refurl","bits","filename","urlPromise","_processing","then","insertVideo","videoDesc","urls","insertAudio","audioDesc","videoCall","audioOnly","aonly","updateVideoCall","Object","assign","quote","header","body","appendLineBreak","mention","appendLink","linkData","appendImage","appendAudio","attachFile","attachmentDesc","wrapInto","style","wrapAsForm","insertButton","actionType","actionValue","refUrl","indexOf","appendButton","attachJSON","UNSAFE_toHTML","doc","tree","draftyToTree","htmlFormatter","values","join","treeBottomUp","format","original","formatter","shorten","light","shortenTree","lightEntity","treeToDrafty","forwardedContent","rmMention","node","parent","treeTopDown","lTrim","replyContent","convMNnQQnBR","startsWith","children","attachmentsToEnd","forwarding","toPlainText","isPlainText","toMarkdown","mdFormatter","def","isValid","txt_type","hasAttachments","attachments","hasEntities","styles","sanitizeEntities","copyEntData","getDownloadUrl","entData","isProcessing","getPreviewUrl","getEntitySize","getEntityMimeType","tagName","attrValue","getContentType","span","chunk","chld","re_start","re_end","exec","start_offset","lastIndexOf","end_offset","last","graphemes","spansToTree","flatten","child","addNode","n","att","subspans","inner","keymap","c","keys","newKey","transformer","stack","pop","tail","shortener","allow","lightCopy","trimStart","shift","match","extracted","el","startAt","plain","dc","obj","graphemeIndices","graphemeIndex","charIndex","indices","module","exports","Const","Topic","mergeToCache","TopicFnd","_contacts","callbacks","_processMetaSubs","subs","updateCount","getOwnPropertyNames","indexBy","onMetaSub","onSubsUpdated","publish","setMeta","getPrototypeOf","prototype","checkTagUniqueness","caller","subscribe","desc","getMeta","startMetaQuery","withTags","build","meta","t","contacts","cb","isUrlRelative","addURLParam","relUrl","window","location","origin","searchParams","substring","LargeFileHelper","tinode","_tinode","_version","_apiKey","_authToken","getAuthToken","xhr","uploadWithBaseUrl","baseUrl","avatarFor","onProgress","onSuccess","onFailure","base","endsWith","instance","setRequestHeader","token","toResolve","toReject","upload","onprogress","e","lengthComputable","loaded","total","onload","response","statusText","onabort","form","FormData","set","getNextUniqueId","_secure","_host","download","relativeUrl","mimetype","responseType","link","document","createElement","display","setAttribute","appendChild","click","removeChild","revokeObjectURL","reader","FileReader","readAsText","cancel","setNetworkProvider","mergeObj","TopicMe","onContactUpdate","_processMetaDesc","turnOff","_db","_updateCachedUser","_myUID","cont","online","seen","when","Date","_refreshContact","onMetaDesc","cacheRemTopic","recv","getTopic","_new","isP2PTopicName","_cachePutUser","_noForwarding","_processMetaCreds","creds","cr","_credentials","findIndex","meth","done","resp","onCredsUpdated","_routePres","pres","what","_resetSub","withDesc","cacheGetTopic","_updateReceived","withLaterOneSub","tgt","dacs","touched","ua","_attached","withOneSub","dummy","onPres","delCredential","method","isCommType","getContact","isArchived","private","arch","getCredentials","listToRanges","normalizeRanges","MetaGetBuilder","get_desc_ims","#get_desc_ims","updated","get_subs_ims","#get_subs_ims","isP2PType","_lastSubsUpdate","withData","withLaterData","_maxSeq","withDataRanges","withDataList","list","withEarlierData","_minSeq","ims","withLaterDesc","withSub","userOrTopic","opts","getType","withLaterSub","withCred","withAux","withDel","withLaterDel","_maxDel","extract","normalizeArray","created","trusted","_users","_queuedSeqId","_noEarlierMsgs","_recvNotificationTimer","_aux","_messageVersions","_messages","_delayedLeaveTimer","onData","onMeta","onInfo","onTagsUpdated","onAuxUpdated","onDeleteTopic","onAllMessagesReceived","topicType","types","isMeTopicName","isSelfTopicName","isGroupTopicName","isCommTopicName","isNewGroupTopicName","isChannelTopicName","isReplacementMsg","#isReplacementMsg","head","replace","isSubscribed","getParams","setParams","_cacheDelSelf","_cachePutSelf","ts","me","getMeTopic","createMessage","noEcho","publishMessage","_sending","_failed","swapMessageId","_maybeUpdateMessageVersionsCache","_routeData","publishDraft","_getQueuedSeqId","getCurrentUserID","noecho","_cancelled","_fatal","leave","unsub","_gone","leaveDelayed","delay","getMessagesPage","gaps","newer","_loadMessages","msgHasMoreMessages","getPinnedMessages","pins","aux","remains","_processMetaTags","cred","_processMetaAux","subscriber","am","invite","archive","pinMessage","pin","pinned","changed","delMessages","hard","tosend","del","rec","flushMessageRange","flushMessage","delMessagesAll","hardDel","_all","delMessagesList","delMessagesEdits","messageVersions","delTopic","delSubscription","note","_updateMyReadRecv","noteRecv","noteRead","noteKeyPress","noteRecording","payload","oldVal","doUpdate","userDesc","_cacheGetUser","p2pPeerDesc","subscribers","alias","origSeq","versions","messages","sinceId","beforeId","unused1","unused2","latest","latestMsgVersion","_origTs","_origSeq","findMessage","latestMessage","maxMsgSeq","minMsgSeq","maxClearId","messageCount","queuedMessages","msgReceiptCount","msgReadCount","msgRecvCount","maxSeq","gap","prev","p","expected","isNewMessage","seqId","fromId","untilId","newSeqId","numMessages","cancelSend","msgStatus","getDefaultAccess","defacs","isMeType","isSelfType","isChannelType","isGroupType","isMe","targetSeq","parseInt","targetMsg","outgoing","webrtc","incoming","vc","_routeInfo","_routeMeta","_processDelMessages","delseq","isTopicCached","info","_allMessagesReceived","cached","date","isNaN","isValidDate","d","getTime","rfc3339DateString","pad","sp","repeat","millis","getUTCMilliseconds","getUTCFullYear","getUTCMonth","getUTCDate","getUTCHours","getUTCMinutes","getUTCSeconds","ignore","prop","cache","newval","simplify","out","trim","toLowerCase","item","pos","ary","r1","r2","reduce","clipOutRange","clip","clipInRange","DBCache","WebSocket","XMLHttpRequest","IndexedDBProvider","indexedDB","initForNonBrowserApp","chars","btoa","global","input","output","charCode","bc","bs","String","fromCharCode","detectTransport","b64EncodeUnicode","encodeURIComponent","toSolidBytes","p1","jsonBuildHelper","jsonLoggerHelper","getBrowserInfo","product","reactnative","priority","tmp","substr","tokens","m2","v","minor","Tinode","_appName","_browser","_platform","_hwos","_humanLanguage","_loggingEnabled","_trimLongStrings","_authenticated","_login","_inPacketCount","_messageId","floor","_serverInfo","_deviceToken","_pendingPromises","_expirePromises","_connection","_persist","_cache","onComplete","appName","platform","navigator","userAgent","language","dispatchMessage","connectionOpen","disconnected","promise","persist","cacheGet","attachCacheToTopic","cachePut","all","args","dateString","console","makePromise","#makePromise","execPromise","#execPromise","onOK","errorText","#send","stringify","#dispatchMessage","onRawMessage","onNetworkProbe","onCtrlMessage","onMetaMessage","onDataMessage","onPresMessage","onInfoMessage","#connectionOpen","setInterval","expires","hello","#disconnected","clearInterval","cacheMap","getUserAgent","#getUserAgent","initPacket","#initPacket","#cachePut","#cacheGet","cacheDel","#cacheDel","#cacheMap","func","#attachCacheToTopic","_cacheDelUser","loginSuccessful","#loginSuccessful","onLogin","credential","getVersion","getLibrary","isNullValue","isServerAssignedSeq","isValidTagValue","ALIAS_REGEX","tagSplit","splitAt","prefix","setUniqueTag","uniqueTag","clearTagPrefix","tagByPrefix","clearStorage","initStorage","networkProbe","isAuthenticated","authorizeURL","parsed","account","scheme","secret","login","acc","tmpscheme","tmpsecret","extra","createAccount","createAccountBasic","username","password","updateAccountBasic","onConnect","setDeviceToken","dt","sent","loginBasic","uname","loginToken","requestResetAuthSecret","now","setAuthToken","dft","oobNotification","xfrom","finally","modeGiven","modeWant","delCurrentUser","newGroupTopicName","isChan","getFndTopic","getLargeFileHelper","getCurrentLogin","getServerInfo","report","getServerParam","defaultValue","enableLogging","enabled","trimLongStrings","setHumanLanguage","hl","isTopicOnline","getTopicAccessMode","wantAkn","onWebsocketOpen","MAX_MESSAGE_SIZE","MAX_SUBSCRIBER_COUNT","MIN_TAG_LENGTH","MAX_TAG_LENGTH","MAX_TAG_COUNT","MAX_FILE_UPLOAD_SIZE","REQ_CRED_VALIDATORS","MSG_DELETE_AGE","URI_TOPIC_ID_PREFIX"],"sourceRoot":""}
\ No newline at end of file
diff --git a/umd/tinode.prod.js b/umd/tinode.prod.js
index f5d60001..061f5abd 100644
--- a/umd/tinode.prod.js
+++ b/umd/tinode.prod.js
@@ -1 +1 @@
-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.tinode=t():e.tinode=t()}(this,()=>(()=>{"use strict";var e={767:e=>{const t="application/json",s=["act","height","duration","incoming","mime","name","premime","preref","preview","ref","size","state","url","val","width"],i=new Intl.Segmenter,n=[{name:"ST",start:/(?:^|[\W_])(\*)[^\s*]/,end:/[^\s*](\*)(?=$|[\W_])/},{name:"EM",start:/(?:^|\W)(_)[^\s_]/,end:/[^\s_](_)(?=$|\W)/},{name:"DL",start:/(?:^|[\W_])(~)[^\s~]/,end:/[^\s~](~)(?=$|[\W_])/},{name:"CO",start:/(?:^|\W)(`)[^`]/,end:/[^`](`)(?=$|\W)/}],r=["QQ"],a=[{name:"LN",dataName:"url",pack:function(e){return/^[a-z]+:\/\//i.test(e)||(e="http://"+e),{url:e}},re:/(?:(?:https?|ftp):\/\/|www\.|ftp\.)[-A-Z0-9+&@#\/%=~_|$?!:,.]*[A-Z0-9+&@#\/%=~_|$]/gi},{name:"MN",dataName:"val",pack:function(e){return{val:e.slice(1)}},re:/\B@([\p{L}\p{N}][._\p{L}\p{N}]*[\p{L}\p{N}])/gu},{name:"HT",dataName:"val",pack:function(e){return{val:e.slice(1)}},re:/\B#([\p{L}\p{N}][._\p{L}\p{N}]*[\p{L}\p{N}])/gu}],o={AU:{html_tag:"audio",md_tag:void 0,isVoid:!1},BN:{html_tag:"button",md_tag:void 0,isVoid:!1},BR:{html_tag:"br",md_tag:"\n",isVoid:!0},CO:{html_tag:"tt",md_tag:"`",isVoid:!1},DL:{html_tag:"del",md_tag:"~",isVoid:!1},EM:{html_tag:"i",md_tag:"_",isVoid:!1},EX:{html_tag:"",md_tag:void 0,isVoid:!0},FM:{html_tag:"div",md_tag:void 0,isVoid:!1},HD:{html_tag:"",md_tag:void 0,isVoid:!1},HL:{html_tag:"span",md_tag:void 0,isVoid:!1},HT:{html_tag:"a",md_tag:void 0,isVoid:!1},IM:{html_tag:"img",md_tag:void 0,isVoid:!1},LN:{html_tag:"a",md_tag:void 0,isVoid:!1},MN:{html_tag:"a",md_tag:void 0,isVoid:!1},RW:{html_tag:"div",md_tag:void 0,isVoid:!1},QQ:{html_tag:"div",md_tag:void 0,isVoid:!1},ST:{html_tag:"b",md_tag:"*",isVoid:!1},VC:{html_tag:"div",md_tag:void 0,isVoid:!1},VD:{html_tag:"video",md_tag:void 0,isVoid:!1}};function h(e,t,s){if(!e)return null;try{const s=atob(e),i=s.length,n=new ArrayBuffer(i),r=new Uint8Array(n);for(let e=0;e"",close:e=>" "},EM:{open:e=>"",close:e=>" "},DL:{open:e=>"",close:e=>""},CO:{open:e=>"",close:e=>" "},BR:{open:e=>" ",close:e=>""},HD:{open:e=>"",close:e=>""},HL:{open:e=>'',close:e=>" "},LN:{open:e=>'',close:e=>" ",props:e=>e?{href:e.url,target:"_blank"}:null},MN:{open:e=>'',close:e=>" ",props:e=>e?{id:e.val}:null},HT:{open:e=>'',close:e=>" ",props:e=>e?{id:e.val}:null},BN:{open:e=>"",close:e=>" ",props:e=>e?{"data-act":e.act,"data-val":e.val,"data-name":e.name,"data-ref":e.ref}:null},AU:{open:e=>'',close:e=>" ",props:e=>e?{src:e.ref||h(e.val,e.mime,l.logger),"data-preload":e.ref?"metadata":"auto","data-duration":e.duration,"data-name":e.name,"data-size":e.val?.75*e.val.length|0:0|e.size,"data-mime":e.mime}:null},IM:{open:e=>{const t=c(e._tempPreview,e.mime),s=h(e.val,e.mime,l.logger),i=e.ref||s;return(e.name?'':"")+' '},close:e=>e.name?" ":"",props:e=>e?{src:c(e._tempPreview,e.mime)||e.ref||h(e.val,e.mime,l.logger),title:e.name,alt:e.name,"data-width":e.width,"data-height":e.height,"data-name":e.name,"data-size":e.ref?0|e.size:e.val?.75*e.val.length|0:0|e.size,"data-mime":e.mime}:null},FM:{open:e=>" ",close:e=>"
"},RW:{open:e=>"",close:e=>"
"},QQ:{open:e=>"",close:e=>"
",props:e=>e?{}:null},VC:{open:e=>"",close:e=>"
",props:e=>e?{"data-duration":e.duration,"data-state":e.state}:{}},VD:{open:e=>{const t=c(e._tempPreview,e.mime),s=e.ref||h(e.preview,e.premime||"image/jpeg",l.logger);return' '},close:e=>"",props:e=>{if(!e)return null;const t=e.preref||h(e.preview,e.premime||"image/jpeg",l.logger);return{src:t,"data-src":e.ref||h(e.val,e.mime,l.logger),"data-width":e.width,"data-height":e.height,"data-preload":e.ref?"metadata":"auto","data-preview":t,"data-duration":0|e.duration,"data-name":e.name,"data-size":e.ref?0|e.size:e.val?.75*e.val.length|0:0|e.size,"data-mime":e.mime}}}},l=function(){this.txt="",this.fmt=[],this.ent=[]};function u(e,t,s,i){const n=[];if(0==i.length)return[];for(let s in i){const r=i[s];r.at>t&&n.push({txt:e.slice(t,r.at)});const a={tp:r.tp},o=u(e,r.at+1,r.end,r.children);o.length>0?a.children=o:a.txt=r.txt,n.push(a),t=r.end+1}return ts.end?(t.push(e[i]),s=e[i]):e[i].end<=s.end&&s.children.push(e[i]);for(let e in t)t[e].children=p(t[e].children);return t}function g(e){if(!e)return null;e="string"==typeof e?{txt:e}:e;let{txt:t,fmt:s,ent:i}=e;if(t=t||"",Array.isArray(i)||(i=[]),!Array.isArray(s)||0==s.length){if(0==i.length)return{text:t};s=[{at:0,len:0,key:0}]}const n=[],a=[];s.forEach(e=>{if(!e||"object"!=typeof e)return;if(!["undefined","number"].includes(typeof e.at))return;if(!["undefined","number"].includes(typeof e.len))return;let s=0|e.at,r=0|e.len;if(r<0)return;let o=e.key||0;i.length>0&&("number"!=typeof o||o<0||o>=i.length)||(s<=-1?a.push({start:-1,end:0,key:o}):s+r>D(t).length||(e.tp?n.push({type:e.tp,start:s,end:s+r}):i.length>0&&"object"==typeof i[o]&&n.push({start:s,end:s+r,key:o})))}),n.sort((e,t)=>{let s=e.start-t.start;return 0!=s?s:(s=t.end-e.end,0!=s?s:r.indexOf(t.type)-r.indexOf(e.type))}),a.length>0&&n.push(...a),n.forEach(e=>{i.length>0&&!e.type&&i[e.key]&&"object"==typeof i[e.key]&&(e.type=i[e.key].tp,e.data=i[e.key].data),e.type||(e.type="HD")});const o=D(t);let h=f({},o,0,o.length,n);return h=b(h,function(e){if(Array.isArray(e.children)&&1==e.children.length){const t=e.children[0];if(e.type)t.type||t.children||(e.text=t.text,delete e.children);else{const s=e.parent;(e=t).parent=s}}return e}),h}function m(e,t){return t?(e.children||(e.children=[]),e.text&&(e.children.push({text:e.text,parent:e}),delete e.text),t.parent=e,e.children.push(t),e):e}function f(e,t,s,i,n){if(!n||0==n.length)return se.segment).join("")}),e;for(let i=0;ie.segment).join("")}),s=r.start);const a=[];for(;ie.segment).join("")}),e}function _(e,t,s){if(!t)return e;e.txt=e.txt||"";const i=D(e.txt).length;if(t.text?e.txt+=t.text:Array.isArray(t.children)&&t.children.forEach(t=>{_(e,t,s)}),t.type){const n=D(e.txt).length-i;if(e.fmt=e.fmt||[],Object.keys(t.data||{}).length>0){e.ent=e.ent||[];const r=void 0===s[t.key]?e.ent.length:s[t.key];s[t.key]=r,e.ent[r]={tp:t.type,data:t.data},t.att?e.fmt.push({at:-1,len:0,key:r}):e.fmt.push({at:i,len:n,key:r})}else e.fmt.push({tp:t.type,at:i,len:n})}return e}function b(e,t,s){if(!e)return null;let i=t.call(s,e);if(!i||!i.children)return i;const n=[];for(let e in i.children){let r=i.children[e];r&&(r=b(r,t,s),r&&n.push(r))}return 0==n.length?i.children=null:i.children=n,i}function w(e,t,s,i,n){if(!e)return null;i&&e.type&&i.push(e.type);let r=[];for(let s in e.children){const a=w(e.children[s],t,s,i,n);a&&r.push(a)}return 0==r.length&&(r=e.text?[e.text]:null),i&&e.type&&i.pop(),t.call(n,e.type,e.data,r,s,i)}function v(e,t,s){return e?(s&&(t-=s.length),b(e,function(e){if(t<=-1)return null;if(e.att)return e;if(0==t)e.text=s,t=-1;else if(e.text){const i=D(e.text);i.length>t?(e.text=i.slice(0,t).map(e=>e.segment).join("")+s,t=-1):t-=i.length}return e})):null}function y(e,t){return b(e,e=>{const s=S(e.data,!0,t?t(e):null);return s?e.data=s:delete e.data,e})}function M(e){if("BR"==e.type)e=null;else if(e.text)e.type||(e.text=e.text.trimStart(),e.text||(e=null));else if(!e.type&&e.children&&e.children.length>0){const t=M(e.children[0]);t?e.children[0]=t:(e.children.shift(),e.type||0!=e.children.length||(e=null))}return e}function x(e,s){if(!e)return null;if(e.att)e.text=" ",delete e.att,delete e.children;else if(e.children){const i=[],n=[];for(let r in e.children){const a=e.children[r];if(a.att){if(i.length==s)continue;if(a.data.mime==t)continue;delete a.att,delete a.children,a.text=" ",i.push(a)}else n.push(a)}e.children=n.concat(i)}return e}function T(e,t){let s="",i=[];for(let n in e){const r=e[n];if(!r.txt){const e=T(r.children,s.length+t);r.txt=e.txt,i=i.concat(e.fmt)}r.tp&&i.push({at:s.length+t,len:r.txt.length,tp:r.tp}),s+=r.txt}return{txt:s,fmt:i}}function S(e,t,i){if(e&&Object.entries(e).length>0){i=i||[];const n={};if(s.forEach(s=>{if(e[s]){if(t&&!i.includes(s)&&("string"==typeof e[s]||Array.isArray(e[s]))&&e[s].length>64)return;if("object"==typeof e[s])return;n[s]=e[s]}}),0!=Object.entries(n).length)return n}return null}function P(e){return 0==Object.keys(e??{}).length}function A(e,t,s){const n=function(e){const t=[];let s=0,i=0;for(const{segment:n}of e){for(let e=0;e{let t,i,h=[];if(n.forEach(t=>{h=h.concat(function(e,t,s,i){const n=[];let r=0,a=e.slice(0);for(;a.length>0;){const o=t.exec(a);if(null==o)break;let h=o.index+o[0].lastIndexOf(o[1]);a=a.slice(h+1),h+=r,r=h+1;const c=s?s.exec(a):null;if(null==c)break;let d=c.index+c[0].indexOf(c[1]);a=a.slice(d+1),d+=r,r=d+1,n.push({txt:e.slice(h+1,d),children:[],at:h,end:d,tp:i})}return n}(e,t.start,t.end,t.name))}),0==h.length)i={txt:e};else{h.sort((e,t)=>{const s=e.at-t.at;return 0!=s?s:t.end-e.end}),h=p(h);const t=T(u(e,0,e.length,h),0);i={txt:t.txt,fmt:t.fmt}}if(t=function(e){let t,s=[];if(a.forEach(i=>{for(;null!==(t=i.re.exec(e));)s.push({offset:t.index,len:t[0].length,unique:t[0],data:i.pack(t[0]),type:i.name})}),0==s.length)return s;s.sort((e,t)=>e.offset-t.offset);let i=-1;return s=s.filter(e=>{const t=e.offset>i;return i=e.offset+e.len,t}),s}(i.txt),t.length>0){const e=[];for(let i in t){const n=t[i];let a=r[n.unique];a||(a=s.length,r[n.unique]=a,s.push({tp:n.type,data:n.data})),e.push({at:n.offset,len:n.len,key:a})}i.ent=e}o.push(i)});const h={txt:""};if(o.length>0){if(h.txt=o[0].txt,h.fmt=(o[0].fmt||[]).concat(o[0].ent||[]),h.fmt.length){const e=i.segment(h.txt);for(const t of h.fmt)({at:t.at,len:t.len}=A(t,e,h.txt))}for(let e=1;e{const{at:i,len:r}=A(e,n,t.txt);return e.at=i+s,e.len=r,e}))),t.ent&&(P(n)&&(n=i.segment(t.txt)),h.fmt=h.fmt.concat(t.ent.map(e=>{const{at:i,len:r}=A(e,n,t.txt);return e.at=i+s,e.len=r,e})))}0==h.fmt.length&&delete h.fmt,s.length>0&&(h.ent=s)}return h},l.append=function(e,t){if(!e)return t;if(!t)return e;e.txt=e.txt||"";const s=D(e.txt).length;return"string"==typeof t?e.txt+=t:t.txt&&(e.txt+=t.txt),Array.isArray(t.fmt)&&(e.fmt=e.fmt||[],Array.isArray(t.ent)&&(e.ent=e.ent||[]),t.fmt.forEach(i=>{const n={at:(0|i.at)+s,len:0|i.len};-1==i.at&&(n.at=-1,n.len=0),i.tp?n.tp=i.tp:(n.key=e.ent.length,e.ent.push(t.ent[i.key||0])),e.fmt.push(n)})),e},l.insertImage=function(e,t,s){(e=e||{txt:" "}).ent=e.ent||[],e.fmt=e.fmt||[],e.fmt.push({at:0|t,len:1,key:e.ent.length});const i={tp:"IM",data:{mime:s.mime,ref:s.refurl,val:s.bits||s.preview,width:s.width,height:s.height,name:s.filename,size:0|s.size}};return s.urlPromise&&(i.data._tempPreview=s._tempPreview,i.data._processing=!0,s.urlPromise.then(e=>{i.data.ref=e,i.data._tempPreview=void 0,i.data._processing=void 0},e=>{i.data._processing=void 0})),e.ent.push(i),e},l.insertVideo=function(e,t,s){(e=e||{txt:" "}).ent=e.ent||[],e.fmt=e.fmt||[],e.fmt.push({at:0|t,len:1,key:e.ent.length});const i={tp:"VD",data:{mime:s.mime,ref:s.refurl,val:s.bits,preref:s.preref,preview:s.preview,width:s.width,height:s.height,duration:0|s.duration,name:s.filename,size:0|s.size}};return s.urlPromise&&(i.data._tempPreview=s._tempPreview,i.data._processing=!0,s.urlPromise.then(e=>{i.data.ref=e[0],i.data.preref=e[1],i.data._tempPreview=void 0,i.data._processing=void 0},e=>{i.data._processing=void 0})),e.ent.push(i),e},l.insertAudio=function(e,t,s){(e=e||{txt:" "}).ent=e.ent||[],e.fmt=e.fmt||[],e.fmt.push({at:0|t,len:1,key:e.ent.length});const i={tp:"AU",data:{mime:s.mime,val:s.bits,duration:0|s.duration,preview:s.preview,name:s.filename,size:0|s.size,ref:s.refurl}};return s.urlPromise&&(i.data._processing=!0,s.urlPromise.then(e=>{i.data.ref=e,i.data._processing=void 0},e=>{i.data._processing=void 0})),e.ent.push(i),e},l.videoCall=function(e){return{txt:" ",fmt:[{at:0,len:1,key:0}],ent:[{tp:"VC",data:{aonly:e}}]}},l.updateVideoCall=function(e,t){const s=((e||{}).fmt||[])[0];if(!s)return e;let i;if("VC"==s.tp)delete s.tp,s.key=0,i={tp:"VC"},e.ent=[i];else if(i=(e.ent||[])[0|s.key],!i||"VC"!=i.tp)return e;return i.data=i.data||{},Object.assign(i.data,t),e},l.quote=function(e,t,s){const i=l.append(l.appendLineBreak(l.mention(e,t)),s);return i.fmt.push({at:0,len:D(i.txt).length,tp:"QQ"}),i},l.mention=function(e,t){return{txt:e||"",fmt:[{at:0,len:D(e||"").length,key:0}],ent:[{tp:"MN",data:{val:t}}]}},l.appendLink=function(e,t){(e=e||{txt:""}).ent=e.ent||[],e.fmt=e.fmt||[],e.fmt.push({at:e.txt.length,len:t.txt.length,key:e.ent.length}),e.txt+=t.txt;const s={tp:"LN",data:{url:t.url}};return e.ent.push(s),e},l.appendImage=function(e,t){return(e=e||{txt:""}).txt+=" ",l.insertImage(e,e.txt.length-1,t)},l.appendAudio=function(e,t){return(e=e||{txt:""}).txt+=" ",l.insertAudio(e,e.txt.length-1,t)},l.attachFile=function(e,t){(e=e||{txt:""}).ent=e.ent||[],e.fmt=e.fmt||[],e.fmt.push({at:-1,len:0,key:e.ent.length});const s={tp:"EX",data:{mime:t.mime,val:t.data,name:t.filename,ref:t.refurl,size:0|t.size}};return t.urlPromise&&(s.data._processing=!0,t.urlPromise.then(e=>{s.data.ref=e,s.data._processing=void 0},e=>{s.data._processing=void 0})),e.ent.push(s),e},l.wrapInto=function(e,t,s,i){return"string"==typeof e&&(e={txt:e}),e.fmt=e.fmt||[],e.fmt.push({at:s||0,len:i||e.txt.length,tp:t}),e},l.wrapAsForm=function(e,t,s){return l.wrapInto(e,"FM",t,s)},l.insertButton=function(e,t,s,i,n,r,a){return"string"==typeof e&&(e={txt:e}),!e||!e.txt||e.txt.length{switch(e.type){case"IM":return["val"];case"VD":return["preview"]}return null}),_({},s,[])):e},l.preview=function(e,t,s){let i=g(e);if(i=x(i,3),i=b(i,function(e){return"MN"==e.type?e.parent&&e.parent.type||!(e.text||"").startsWith("➦")||(e.text="➦",delete e.children):"QQ"==e.type?(e.text=" ",delete e.children):"BR"==e.type&&(e.text=" ",delete e.children,delete e.type),e}),i=v(i,t,"…"),s){const e={IM:["val"],VD:["preview"]};i=y(i,t=>e[t.type])}else i=y(i);return _({},i,[])},l.toPlainText=function(e){return"string"==typeof e?e:e.txt},l.isPlainText=function(e){return"string"==typeof e||!(e.fmt||e.ent)},l.toMarkdown=function(e){return w(g(e),function(e,t,s){const i=o[e];let n=s?s.join(""):"";return i&&(i.isVoid?n=i.md_tag||"":i.md_tag&&(n=i.md_tag+n+i.md_tag)),n},0)},l.isValid=function(e){if(!e)return!1;const{txt:t,fmt:s,ent:i}=e;if(!t&&""!==t&&!s&&!i)return!1;const n=typeof t;return!("string"!=n&&"undefined"!=n&&null!==t||void 0!==s&&!Array.isArray(s)&&null!==s||void 0!==i&&!Array.isArray(i)&&null!==i)},l.hasAttachments=function(e){if(!Array.isArray(e.fmt))return!1;for(let t in e.fmt){const s=e.fmt[t];if(s&&s.at<0){const t=e.ent[0|s.key];return t&&"EX"==t.tp&&t.data}}return!1},l.attachments=function(e,t,s){if(!Array.isArray(e.fmt))return;let i=0;for(let n in e.fmt){let r=e.fmt[n];if(r&&r.at<0){const n=e.ent[0|r.key];if(n&&"EX"==n.tp&&n.data&&t.call(s,n.data,i++,"EX"))break}}},l.hasEntities=function(e){return e.ent&&e.ent.length>0},l.entities=function(e,t,s){if(e.ent&&e.ent.length>0)for(let i in e.ent)if(e.ent[i]&&t.call(s,e.ent[i].data,i,e.ent[i].tp))break},l.styles=function(e,t,s){if(e.fmt&&e.fmt.length>0)for(let i in e.fmt){const n=e.fmt[i];if(n&&t.call(s,n.tp,n.at,n.len,n.key,i))break}},l.sanitizeEntities=function(e){if(e&&e.ent&&e.ent.length>0)for(let t in e.ent){const s=e.ent[t];if(s&&s.data){const i=S(s.data);i?e.ent[t].data=i:delete e.ent[t].data}}return e},l.getDownloadUrl=function(e){let s=null;return e.mime!=t&&e.val?s=h(e.val,e.mime,l.logger):"string"==typeof e.ref&&(s=e.ref),s},l.isProcessing=function(e){return!!e._processing},l.getPreviewUrl=function(e){return e.val?h(e.val,e.mime,l.logger):null},l.getEntitySize=function(e){return e.size?e.size:e.val?.75*e.val.length|0:0},l.getEntityMimeType=function(e){return e.mime||"text/plain"},l.tagName=function(e){return o[e]&&o[e].html_tag},l.attrValue=function(e,t){if(t&&d[e]&&d[e].props)return d[e].props(t)},l.getContentType=function(){return"text/x-drafty"},e.exports=l}},t={};function s(i){var n=t[i];if(void 0!==n)return n.exports;var r=t[i]={exports:{}};return e[i](r,r.exports,s),r.exports}s.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return s.d(t,{a:t}),t},s.d=(e,t)=>{for(var i in t)s.o(t,i)&&!s.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},s.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),s.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),s.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var i={};s.r(i),s.d(i,{AccessMode:()=>n,Drafty:()=>q(),Tinode:()=>Q});class n{constructor(e){e&&(this.given="number"==typeof e.given?e.given:n.decode(e.given),this.want="number"==typeof e.want?e.want:n.decode(e.want),this.mode=e.mode?"number"==typeof e.mode?e.mode:n.decode(e.mode):this.given&this.want)}static#e(e,t,s){if(["given","want","mode"].includes(t=t||"mode"))return 0!=(e[t]&s);throw new Error(`Invalid AccessMode component '${t}'`)}static decode(e){if(!e)return null;if("number"==typeof e)return e&n._BITMASK;if("N"===e||"n"===e)return n._NONE;const t={J:n._JOIN,R:n._READ,W:n._WRITE,P:n._PRES,A:n._APPROVE,S:n._SHARE,D:n._DELETE,O:n._OWNER};let s=n._NONE;for(let i=0;i=20&&t.length<=24&&["ts","touched","updated","created","when","deleted","expires"].includes(e)){const e=new Date(t);if(!isNaN(e))return e}else if("acs"===e&&"object"==typeof t)return new n(t);return t}function _(e){return e&&!/^\s*([a-z][a-z0-9+.-]*:|\/\/)/im.test(e)}function b(e){return e instanceof Date&&!isNaN(e)&&0!=e.getTime()}function w(e,t,s){if("object"!=typeof t){if(void 0===t)return e;if(t===p)return;return t}if(null===t)return t;if(t instanceof Date&&!isNaN(t))return!e||!(e instanceof Date)||isNaN(e)||e{"_"==t[0]?delete e[t]:e[t]?Array.isArray(e[t])&&0==e[t].length?delete e[t]:e[t]?e[t]instanceof Date?b(e[t])||delete e[t]:"object"==typeof e[t]&&(y(e[t]),0==Object.getOwnPropertyNames(e[t]).length&&delete e[t]):delete e[t]:delete e[t]}),e}function M(e,t){return Array.isArray(e)?(e.sort((e,t)=>e.low(s.low0&&(!s.hi||s.hi{if(0==e.length)e.push(t);else{let s=e[e.length-1];t.low<=s.hi?s.hi=Math.max(s.hi,t.hi):e.push(t)}return e},[])):[]}function x(e){return e.sort((e,t)=>e-t),e.reduce((e,t)=>{if(0==e.length)e.push({low:t});else{let s=e[e.length-1];!s.hi&&t!=s.low+1||t>s.hi?e.push({low:t}):s.hi=s.hi?Math.max(s.hi,t+1):t+1}return e},[])}let T,S;const P="Connection failed",A=418,D="Disconnected by client";function E(e,t,s,i){let n=null;return["http","https","ws","wss"].includes(t)&&(n=`${t}://${e}`,"/"!==n.charAt(n.length-1)&&(n+="/"),n+="v"+s+"/channels",["http","https"].includes(t)&&(n+="/lp"),n+="?apikey="+i),n}class N{static#t=e=>{};#s=null;#i=0;#n=!1;#r=null;host;secure;apiKey;version;autoreconnect;initialized;constructor(e,t,s){if(this.host=e.host,this.secure=e.secure,this.apiKey=e.apiKey,this.version=t,this.autoreconnect=s,"lp"===e.transport?(this.#a(),this.initialized="lp"):"ws"===e.transport&&(this.#o(),this.initialized="ws"),!this.initialized)throw N.#t("Unknown or invalid network transport. Running under Node? Call 'Tinode.setNetworkProviders()'."),new Error("Unknown or invalid network transport. Running under Node? Call 'Tinode.setNetworkProviders()'.")}static setNetworkProviders(e,t){T=e,S=t}static set logger(e){N.#t=e}connect(e,t){return Promise.reject(null)}reconnect(e){}disconnect(){}sendText(e){}isConnected(){return!1}transport(){return this.initialized}probe(){this.sendText("1")}backoffReset(){this.#h()}#c(){clearTimeout(this.#s);const e=Math.pow(2,this.#i)*(1+.3*Math.random())*2e3;this.#i=this.#i>=10?this.#i:this.#i+1,this.onAutoreconnectIteration&&this.onAutoreconnectIteration(e),this.#s=setTimeout(t=>{if(N.#t(`Reconnecting, iter=${this.#i}, timeout=${e}`),this.#n)this.onAutoreconnectIteration&&this.onAutoreconnectIteration(-1);else{const e=this.connect();this.onAutoreconnectIteration?this.onAutoreconnectIteration(0,e):e.catch(e=>{})}},e)}#d(){clearTimeout(this.#s),this.#s=null}#h(){this.#i=0}#a(){let e=null,t=null,s=null,i=(t,s,n)=>{let r=new S,a=!1;return r.onreadystatechange=o=>{if(4==r.readyState)if(201==r.status){let n=JSON.parse(r.responseText,f);e=t+"&sid="+n.ctrl.params.sid,r=i(e),r.send(null),this.onOpen&&this.onOpen(),s&&(a=!0,s()),this.autoreconnect&&this.#d()}else if(r.status>0&&r.status<400)this.onMessage&&this.onMessage(r.responseText),r=i(e),r.send(null);else{if(n&&!a&&(a=!0,n(r.responseText)),this.onMessage&&r.responseText&&this.onMessage(r.responseText),this.onDisconnect){const e=r.status||(this.#n?A:503),t=r.responseText||(this.#n?D:P);this.onDisconnect(new m(t,e),e)}r=null,!this.#n&&this.autoreconnect&&this.#c()}},r.open("POST",t,!0),r};this.connect=(e,s)=>{if(this.#n=!1,t){if(!s)return Promise.resolve();t.onreadystatechange=void 0,t.abort(),t=null}return e&&(this.host=e),new Promise((e,s)=>{const n=E(this.host,this.secure?"https":"http",this.version,this.apiKey);N.#t("LP connecting to:",n),t=i(n,e,s),t.send(null)}).catch(e=>{N.#t("LP connection failed:",e)})},this.reconnect=e=>{this.#d(),this.connect(null,e)},this.disconnect=i=>{this.#n=!0,this.#d(),s&&(s.onreadystatechange=void 0,s.abort(),s=null),t&&(t.onreadystatechange=void 0,t.abort(),t=null),this.onDisconnect&&this.onDisconnect(new m(D,A),A),e=null},this.sendText=t=>{if(s=(e=>{const t=new S;return t.onreadystatechange=e=>{if(4==t.readyState&&t.status>=400)throw new m("LP sender failed",t.status)},t.open("POST",e,!0),t})(e),!s||1!=s.readyState)throw new Error("Long poller failed to connect");s.send(t)},this.isConnected=e=>t&&!0}#o(){this.connect=(e,t)=>{if(this.#n=!1,this.#r){if(!t&&this.#r.readyState==this.#r.OPEN)return this.probe(),Promise.resolve();this.#r.close(),this.#r=null}return e&&(this.host=e),new Promise((e,t)=>{const s=E(this.host,this.secure?"wss":"ws",this.version,this.apiKey);N.#t("WS connecting to: ",s);const i=new T(s);i.onerror=e=>{t(e)},i.onopen=t=>{this.autoreconnect&&this.#d(),this.onOpen&&this.onOpen(),e()},i.onclose=e=>{if(this.#r=null,this.onDisconnect){const e=this.#n?A:503;this.onDisconnect(new m(this.#n?D:P,e),e)}!this.#n&&this.autoreconnect&&this.#c()},i.onmessage=e=>{this.onMessage&&this.onMessage(e.data)},this.#r=i})},this.reconnect=e=>{this.#d(),this.connect(null,e)},this.disconnect=e=>{this.#n=!0,this.#d(),this.#r&&(this.#r.close(),this.#r=null)},this.sendText=e=>{if(!this.#r||this.#r.readyState!=this.#r.OPEN)throw new Error("Websocket is not connected");this.#r.send(e)},this.isConnected=e=>this.#r&&this.#r.readyState==this.#r.OPEN}onMessage=void 0;onDisconnect=void 0;onOpen=void 0;onAutoreconnectIteration=void 0}N.NETWORK_ERROR=503,N.NETWORK_ERROR_TEXT=P,N.NETWORK_USER=A,N.NETWORK_USER_TEXT=D;const R="tinode-web";let I;class k{#l=e=>{};#u=e=>{};db=null;disabled=!0;constructor(e,t){this.#l=e||this.#l,this.#u=t||this.#u}#p(e,t,s){return this.db?new Promise((i,n)=>{const r=this.db.transaction([e]);r.onerror=t=>{this.#u("PCache","mapObjects",e,t.target.error),n(t.target.error)},r.objectStore(e).getAll().onsuccess=e=>{t&&e.target.result.forEach(e=>{t.call(s,e)}),i(e.target.result)}}):disabled?Promise.resolve([]):Promise.reject(new Error("not initialized"))}initDatabase(){return new Promise((e,t)=>{const s=I.open(R,3);s.onsuccess=t=>{this.db=t.target.result,this.disabled=!1,this.db.onversionchange=e=>{this.#u("PCache","another tab tries to upgrade DB, shutting down"),this.db.close(),this.db=null,this.disabled=!0},e(this.db)},s.onerror=e=>{this.#u("PCache","failed to initialize",e),t(e.target.error),this.#l(e.target.error)},s.onupgradeneeded=e=>{if(this.db=e.target.result,this.db.onerror=e=>{this.#u("PCache","failed to create storage",e),this.#l(e.target.error)},this.db.objectStoreNames.contains("topic")||this.db.createObjectStore("topic",{keyPath:"name"}),this.db.objectStoreNames.contains("user")||this.db.createObjectStore("user",{keyPath:"uid"}),this.db.objectStoreNames.contains("subscription")||this.db.createObjectStore("subscription",{keyPath:["topic","uid"]}),this.db.objectStoreNames.contains("message")||this.db.createObjectStore("message",{keyPath:["topic","seq"]}),!this.db.objectStoreNames.contains("dellog")){const e=this.db.createObjectStore("dellog",{keyPath:["topic","low","hi"]});e.indexNames.contains("topic_clear")||e.createIndex("topic_clear",["topic","clear"],{unique:!1})}}})}deleteDatabase(){return this.db&&(this.db.close(),this.db=null),new Promise((e,t)=>{const s=I.deleteDatabase(R);s.onblocked=e=>{this.db&&this.db.close();const s=new Error("blocked");this.#u("PCache","deleteDatabase",s),t(s)},s.onsuccess=t=>{this.db=null,this.disabled=!0,e(!0)},s.onerror=e=>{this.#u("PCache","deleteDatabase",e.target.error),t(e.target.error)}})}isReady(){return!!this.db}updTopic(e){return this.isReady()?new Promise((t,s)=>{const i=this.db.transaction(["topic"],"readwrite");i.oncomplete=e=>{t(e.target.result)},i.onerror=e=>{this.#u("PCache","updTopic",e.target.error),s(e.target.error)};const n=i.objectStore("topic").get(e.name);n.onsuccess=t=>{i.objectStore("topic").put(k.#g(n.result,e)),i.commit()}}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}markTopicAsDeleted(e,t){return this.isReady()?new Promise((s,i)=>{const n=this.db.transaction(["topic"],"readwrite");n.oncomplete=e=>{s(e.target.result)},n.onerror=e=>{this.#u("PCache","markTopicAsDeleted",e.target.error),i(e.target.error)},n.objectStore("topic").get(e).onsuccess=e=>{const s=e.target.result;s&&s._deleted!=t&&(s._deleted=t,n.objectStore("topic").put(s)),n.commit()}}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}remTopic(e){return this.isReady()?new Promise((t,s)=>{const i=this.db.transaction(["topic","subscription","message"],"readwrite");i.oncomplete=e=>{t(e.target.result)},i.onerror=e=>{this.#u("PCache","remTopic",e.target.error),s(e.target.error)},i.objectStore("topic").delete(IDBKeyRange.only(e)),i.objectStore("subscription").delete(IDBKeyRange.bound([e,"-"],[e,"~"])),i.objectStore("message").delete(IDBKeyRange.bound([e,0],[e,Number.MAX_SAFE_INTEGER])),i.commit()}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}mapTopics(e,t){return this.#p("topic",e,t)}deserializeTopic(e,t){k.#m(e,t)}updUser(e,t){if(!(arguments.length<2||void 0===t))return this.isReady()?new Promise((s,i)=>{const n=this.db.transaction(["user"],"readwrite");n.oncomplete=e=>{s(e.target.result)},n.onerror=e=>{this.#u("PCache","updUser",e.target.error),i(e.target.error)},n.objectStore("user").put({uid:e,public:t}),n.commit()}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}remUser(e){return this.isReady()?new Promise((t,s)=>{const i=this.db.transaction(["user"],"readwrite");i.oncomplete=e=>{t(e.target.result)},i.onerror=e=>{this.#u("PCache","remUser",e.target.error),s(e.target.error)},i.objectStore("user").delete(IDBKeyRange.only(e)),i.commit()}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}mapUsers(e,t){return this.#p("user",e,t)}getUser(e){return this.isReady()?new Promise((t,s)=>{const i=this.db.transaction(["user"]);i.oncomplete=e=>{const s=e.target.result;t({user:s.uid,public:s.public})},i.onerror=e=>{this.#u("PCache","getUser",e.target.error),s(e.target.error)},i.objectStore("user").get(e)}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}updSubscription(e,t,s){return this.isReady()?new Promise((i,n)=>{const r=this.db.transaction(["subscription"],"readwrite");r.oncomplete=e=>{i(e.target.result)},r.onerror=e=>{this.#u("PCache","updSubscription",e.target.error),n(e.target.error)},r.objectStore("subscription").get([e,t]).onsuccess=i=>{r.objectStore("subscription").put(k.#f(i.target.result,e,t,s)),r.commit()}}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}mapSubscriptions(e,t,s){return this.isReady()?new Promise((i,n)=>{const r=this.db.transaction(["subscription"]);r.onerror=e=>{this.#u("PCache","mapSubscriptions",e.target.error),n(e.target.error)},r.objectStore("subscription").getAll(IDBKeyRange.bound([e,"-"],[e,"~"])).onsuccess=e=>{t&&e.target.result.forEach(e=>{t.call(s,e)}),i(e.target.result)}}):this.disabled?Promise.resolve([]):Promise.reject(new Error("not initialized"))}addMessage(e){return this.isReady()?new Promise((t,s)=>{const i=this.db.transaction(["message"],"readwrite");i.onsuccess=e=>{t(e.target.result)},i.onerror=e=>{this.#u("PCache","addMessage",e.target.error),s(e.target.error)},i.objectStore("message").add(k.#_(null,e)),i.commit()}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}updMessageStatus(e,t,s){return this.isReady()?new Promise((i,n)=>{const r=this.db.transaction(["message"],"readwrite");r.onsuccess=e=>{i(e.target.result)},r.onerror=e=>{this.#u("PCache","updMessageStatus",e.target.error),n(e.target.error)};const a=r.objectStore("message").get(IDBKeyRange.only([e,t]));a.onsuccess=i=>{const n=a.result||i.target.result;n&&n._status!=s?(r.objectStore("message").put(k.#_(n,{topic:e,seq:t,_status:s})),r.commit()):r.commit()}}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}remMessages(e,t,s){return this.isReady()?new Promise((i,n)=>{t||s||(t=0,s=Number.MAX_SAFE_INTEGER);const r=s>0?IDBKeyRange.bound([e,t],[e,s],!1,!0):IDBKeyRange.only([e,t]),a=this.db.transaction(["message"],"readwrite");a.onsuccess=e=>{i(e.target.result)},a.onerror=e=>{this.#u("PCache","remMessages",e.target.error),n(e.target.error)},a.objectStore("message").delete(r),a.commit()}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}readMessages(e,t,s,i){if(t=t||{},!this.isReady())return this.disabled?Promise.resolve([]):Promise.reject(new Error("not initialized"));const n=this.db.transaction(["message"]);let r=[];return Array.isArray(t.ranges)?new Promise((a,o)=>{n.onerror=e=>{this.#u("PCache","readMessages",e.target.error),o(e.target.error)};let h=0;t.ranges.forEach(o=>{const c=o.hi?IDBKeyRange.bound([e,o.low],[e,o.hi],!1,!0):IDBKeyRange.only([e,o.low]);n.objectStore("message").getAll(c).onsuccess=e=>{const n=e.target.result;n&&(s&&s.call(i,n),Array.isArray(n)?r=r.concat(n):r.push(n)),h++,h==t.ranges.length&&a(r)}})}):new Promise((a,o)=>{const h=t.since>0?t.since:0,c=t.before>0?t.before:Number.MAX_SAFE_INTEGER,d=0|t.limit;n.onerror=e=>{this.#u("PCache","readMessages",e.target.error),o(e.target.error)};const l=IDBKeyRange.bound([e,h],[e,c],!1,!0);n.objectStore("message").openCursor(l,"prev").onsuccess=e=>{const t=e.target.result;t?(s&&s.call(i,t.value),r.push(t.value),d<=0||r.length{const r=this.db.transaction(["dellog"],"readwrite");r.onsuccess=e=>{i(e.target.result)},r.onerror=e=>{this.#u("PCache","addDelLog",e.target.error),n(e.target.error)},s.forEach(s=>r.objectStore("dellog").add({topic:e,clear:t,low:s.low,hi:s.hi||s.low+1})),r.commit()}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}readDelLog(e,t){if(t=t||{},!this.isReady())return this.disabled?Promise.resolve([]):Promise.reject(new Error("not initialized"));const s=this.db.transaction(["dellog"]);let i=[];return Array.isArray(t.ranges)?new Promise((n,r)=>{s.onerror=e=>{this.#u("PCache","readDelLog",e.target.error),r(e.target.error)};let a=0;t.ranges.forEach(r=>{const o=r.hi||r.low+1,h=IDBKeyRange.bound([e,0,r.low],[e,o,Number.MAX_SAFE_INTEGER],!1,!0);s.objectStore("dellog").getAll(h).onsuccess=e=>{const s=e.target.result;s&&(Array.isArray(s)?i=i.concat(s.map(e=>({low:e.low,hi:e.hi}))):i.push({low:s.low,hi:s.hi})),a++,a==t.ranges.length&&n(i)}})}):new Promise((i,n)=>{const r=t.since>0?t.since:0,a=t.before>0?t.before:Number.MAX_SAFE_INTEGER,o=0|t.limit;s.onerror=e=>{this.#u("PCache","readDelLog",e.target.error),n(e.target.error)};let h=0;const c=[],d=IDBKeyRange.bound([e,0,r],[e,a,Number.MAX_SAFE_INTEGER],!1,!0);s.objectStore("dellog").openCursor(d,"prev").onsuccess=e=>{const t=e.target.result;t?(c.push({low:t.value.low,hi:t.value.hi}),h+=t.value.hi-t.value.low,o<=0||h{const i=this.db.transaction(["dellog"]);i.onerror=e=>{this.#u("PCache","maxDelId",e.target.error),s(e.target.error)},i.objectStore("dellog").index("topic_clear").openCursor(IDBKeyRange.bound([e,0],[e,Number.MAX_SAFE_INTEGER]),"prev").onsuccess=e=>{e.target.result&&t(e.target.result.value)}}):this.disabled?Promise.resolve(0):Promise.reject(new Error("not initialized"))}static#b=["created","updated","deleted","touched","read","recv","seq","clear","defacs","creds","public","trusted","private","_aux","_deleted"];static#m(e,t){k.#b.forEach(s=>{t.hasOwnProperty(s)&&(e[s]=t[s])}),Array.isArray(t.tags)&&(e._tags=t.tags),t.acs&&e.setAccessMode(t.acs),e.seq|=0,e.read|=0,e.unread=Math.max(0,e.seq-e.read)}static#g(e,t){const s=e||{name:t.name};return k.#b.forEach(e=>{t.hasOwnProperty(e)&&(s[e]=t[e])}),Array.isArray(t._tags)&&(s.tags=t._tags),t.acs&&(s.acs=t.getAccessMode().jsonHelper()),s}static#f(e,t,s,i){const n=e||{topic:t,uid:s};return["updated","mode","read","recv","clear","lastSeen","userAgent"].forEach(e=>{i.hasOwnProperty(e)&&(n[e]=i[e])}),n}static#_(e,t){const s=e||{};return["topic","seq","ts","_status","from","head","content"].forEach(e=>{t.hasOwnProperty(e)&&(s[e]=t[e])}),s}static setDatabaseProvider(e){I=e}}var C=s(767),q=s.n(C);let U,O,j,L;class V{constructor(e,t){this._tinode=e,this._version=t,this._apiKey=e._apiKey,this._authToken=e.getAuthToken(),this.xhr=[]}uploadWithBaseUrl(e,t,s,i,n,r){let a=`/v${this._version}/file/u/`;if(e){let t=e;if(t.endsWith("/")&&(t=t.slice(0,-1)),!t.startsWith("http://")&&!t.startsWith("https://"))throw new Error(`Invalid base URL '${e}'`);a=t+a}const o=this,h=new U;this.xhr.push(h),h.open("POST",a,!0),h.setRequestHeader("X-Tinode-APIKey",this._apiKey),this._authToken&&h.setRequestHeader("X-Tinode-Auth",`Token ${this._authToken.token}`);let c=null,d=null;const l=new Promise((e,t)=>{c=e,d=t});h.upload.onprogress=e=>{e.lengthComputable&&(i&&i(e.loaded/e.total),this.onProgress&&this.onProgress(e.loaded/e.total))},h.onload=function(){let e;try{e=JSON.parse(this.response,f)}catch(t){o._tinode.logger("ERROR: Invalid server response in LargeFileHelper",this.response),e={ctrl:{code:this.status,text:this.statusText}}}this.status>=200&&this.status<300?(c&&c(e.ctrl.params.url),n&&n(e.ctrl)):this.status>=400?(d&&d(new m(e.ctrl.text,e.ctrl.code)),r&&r(e.ctrl)):o._tinode.logger("ERROR: Unexpected server response status",this.status,this.response)},h.onerror=function(e){d&&d(e||new Error("failed")),r&&r(null)},h.onabort=function(e){d&&d(new Error("upload cancelled by user")),r&&r(null)};try{const e=new FormData;e.append("file",t),e.set("id",this._tinode.getNextUniqueId()),s&&e.set("topic",s),h.send(e)}catch(e){d&&d(e),r&&r(null)}return l}upload(e,t,s,i,n){const r=(this._tinode._secure?"https://":"http://")+this._tinode._host;return this.uploadWithBaseUrl(r,e,t,s,i,n)}download(e,t,s,i,n){if(!_(e))return void(n&&n(`The URL '${e}' must be relative, not absolute`));if(!this._authToken)return void(n&&n("Must authenticate first"));const r=this,a=new U;this.xhr.push(a),e=function(e){const t=new URL(e,window.location.origin);return t.searchParams.append("asatt","1"),t.toString().substring(window.location.origin.length)}(e),a.open("GET",e,!0),a.setRequestHeader("X-Tinode-APIKey",this._apiKey),a.setRequestHeader("X-Tinode-Auth","Token "+this._authToken.token),a.responseType="blob",a.onprogress=function(e){i&&i(e.loaded)};let o=null,h=null;const c=new Promise((e,t)=>{o=e,h=t});a.onload=function(){if(200==this.status){const e=document.createElement("a");e.href=window.URL.createObjectURL(new Blob([this.response],{type:s})),e.style.display="none",e.setAttribute("download",t),document.body.appendChild(e),e.click(),document.body.removeChild(e),window.URL.revokeObjectURL(e.href),o&&o()}else if(this.status>=400&&h){const e=new FileReader;e.onload=function(){try{const e=JSON.parse(this.result,f);h(new m(e.ctrl.text,e.ctrl.code))}catch(e){r._tinode.logger("ERROR: Invalid server response in LargeFileHelper",this.result),h(e)}},e.readAsText(this.response)}},a.onerror=function(e){h&&h(new Error("failed")),n&&n(e)},a.onabort=function(){h&&h(null)};try{a.send()}catch(e){h&&h(e),n&&n(e)}return c}cancel(){this.xhr.forEach(e=>{e.readyState<4&&e.abort()})}static setNetworkProvider(e){U=e}}class G{constructor(e){this.topic=e,this.what={}}#w(){return this.topic._deleted?void 0:this.topic.updated}#v(){return this.topic.isP2PType()?this.#w():this.topic._deleted?void 0:this.topic._lastSubsUpdate}withData(e,t,s){return this.what.data={since:e,before:t,limit:s},this}withLaterData(e){return this.withData(this.topic._maxSeq>0?this.topic._maxSeq+1:void 0,void 0,e)}withDataRanges(e,t){return this.what.data={ranges:M(e,this.topic._maxSeq),limit:t},this}withDataList(e){return this.withDataRanges(x(e))}withEarlierData(e){return this.withData(void 0,this.topic._minSeq>0?this.topic._minSeq:void 0,e)}withDesc(e){return this.what.desc={ims:e},this}withLaterDesc(){return this.withDesc(this.#w())}withSub(e,t,s){const i={ims:e,limit:t};return"me"==this.topic.getType()?i.topic=s:i.user=s,this.what.sub=i,this}withOneSub(e,t){return this.withSub(e,void 0,t)}withLaterOneSub(e){return this.withOneSub(this.topic._lastSubsUpdate,e)}withLaterSub(e){return this.withSub(this.#v(),e)}withTags(){return this.what.tags=!0,this}withCred(){return"me"==this.topic.getType()?this.what.cred=!0:this.topic._tinode.logger("ERROR: Invalid topic type for MetaGetBuilder:withCreds",this.topic.getType()),this}withAux(){return this.what.aux=!0,this}withDel(e,t){return(e||t)&&(this.what.del={since:e,limit:t}),this}withLaterDel(e){return this.withDel(this.topic._maxSeq>0?this.topic._maxDel+1:void 0,e)}extract(e){return this.what[e]}build(){const e=[];let t={};return["data","sub","desc","tags","cred","aux","del"].forEach(s=>{this.what.hasOwnProperty(s)&&(e.push(s),Object.getOwnPropertyNames(this.what[s]).length>0&&(t[s]=this.what[s]))}),e.length>0?t.what=e.join(" "):t=void 0,t}}class W{#y=void 0;#M=!1;buffer=[];constructor(e,t){this.#y=e||((e,t)=>e===t?0:e0)){o=!0;break}n=r-1}return o?{idx:r,exact:!0}:s?{idx:-1}:{idx:a<0?r+1:r}}#T(e,t){const s=this.#x(e,t,!1),i=s.exact&&this.#M?1:0;return t.splice(s.idx,i,e),t}getAt(e){return this.buffer[e]}getLast(e){return e?this.buffer.findLast(e):this.buffer[this.buffer.length-1]}put(){let e;e=1==arguments.length&&Array.isArray(arguments[0])?arguments[0]:arguments;for(let t in e)this.#T(e[t],this.buffer)}delAt(e){e|=0;let t=this.buffer.splice(e,1);if(t&&t.length>0)return t[0]}delRange(e,t){return this.buffer.splice(e,t-e)}length(){return this.buffer.length}reset(){this.buffer=[]}forEach(e,t,s,i){t=Math.max(0,0|t),s=Math.min(s||this.buffer.length,this.buffer.length);for(let n=t;nt?this.buffer[n-1]:void 0,ne.seq-t.seq,!0),this._attached=!1,this._lastSubsUpdate=new Date(0),this._new=!0,this._deleted=!1,this._delayedLeaveTimer=null,t&&(this.onData=t.onData,this.onMeta=t.onMeta,this.onPres=t.onPres,this.onInfo=t.onInfo,this.onMetaDesc=t.onMetaDesc,this.onMetaSub=t.onMetaSub,this.onSubsUpdated=t.onSubsUpdated,this.onTagsUpdated=t.onTagsUpdated,this.onCredsUpdated=t.onCredsUpdated,this.onAuxUpdated=t.onAuxUpdated,this.onDeleteTopic=t.onDeleteTopic,this.onAllMessagesReceived=t.onAllMessagesReceived)}static topicType(e){return{me:c,fnd:d,grp:l,new:l,nch:l,chn:l,usr:"p2p",sys:"sys",slf:"slf"}["string"==typeof e?e.substring(0,3):"xxx"]}static isMeTopicName(e){return z.topicType(e)==c}static isSelfTopicName(e){return"slf"==z.topicType(e)}static isGroupTopicName(e){return z.topicType(e)==l}static isP2PTopicName(e){return"p2p"==z.topicType(e)}static isCommTopicName(e){return z.isP2PTopicName(e)||z.isGroupTopicName(e)||z.isSelfTopicName(e)}static isNewGroupTopicName(e){return"string"==typeof e&&(e.substring(0,3)==o||e.substring(0,3)==h)}static isChannelTopicName(e){return"string"==typeof e&&("chn"==e.substring(0,3)||e.substring(0,3)==h)}static#S(e){return e.head&&e.head.replace}isSubscribed(){return this._attached}subscribe(e,t){return clearTimeout(this._delayedLeaveTimer),this._delayedLeaveTimer=null,this._attached?Promise.resolve(this):this._tinode.subscribe(this.name||o,e,t).then(e=>{if(e.code>=300)return e;if(this._attached=!0,this._deleted=!1,this.acs=e.params&&e.params.acs?e.params.acs:this.acs,this._new){if(delete this._new,this.name!=e.topic&&(this._cacheDelSelf(),this.name=e.topic),this._cachePutSelf(),this.created=e.ts,this.updated=e.ts,this.name!=c&&this.name!=d){const e=this._tinode.getMeTopic();e.onMetaSub&&e.onMetaSub(this),e.onSubsUpdated&&e.onSubsUpdated([this.name],1)}t&&t.desc&&(t.desc._noForwarding=!0,this._processMetaDesc(t.desc))}return e})}createMessage(e,t){return this._tinode.createMessage(this.name,e,t)}publish(e,t){return this.publishMessage(this.createMessage(e,t))}publishMessage(e){if(!this._attached)return Promise.reject(new Error("Cannot publish on inactive topic"));if(this._sending)return Promise.reject(new Error("The message is already being sent"));e._sending=!0,e._failed=!1;let t=null;return q().hasEntities(e.content)&&(t=[],q().entities(e.content,e=>{e&&(e.ref&&t.push(e.ref),e.preref&&t.push(e.preref))}),0==t.length&&(t=null)),this._tinode.publishMessage(e,t).then(t=>(e._sending=!1,e.ts=t.ts,this.swapMessageId(e,t.params.seq),this._maybeUpdateMessageVersionsCache(e),this._routeData(e),t)).catch(t=>{this._tinode.logger("WARNING: Message rejected by the server",t),e._sending=!1,e._failed=!0,this.onData&&this.onData()})}publishDraft(e,t){const s=e.seq||this._getQueuedSeqId();return e._noForwarding||(e._noForwarding=!0,e.seq=s,e.ts=new Date,e.from=this._tinode.getCurrentUserID(),e.noecho=!0,this._messages.put(e),this._tinode._db.addMessage(e),this.onData&&this.onData(e)),(t||Promise.resolve()).then(t=>e._cancelled?{code:300,text:"cancelled"}:this.publishMessage(e)).catch(t=>{throw this._tinode.logger("WARNING: Message draft rejected",t),e._sending=!1,e._failed=!0,e._fatal=t instanceof m&&t.code>=400&&t.code<500,this.onData&&this.onData(),t})}leave(e){return this._attached||e?this._tinode.leave(this.name,e).then(t=>(this._resetSub(),e&&this._gone(),t)):Promise.reject(new Error("Cannot leave inactive topic"))}leaveDelayed(e,t){clearTimeout(this._delayedLeaveTimer),this._delayedLeaveTimer=setTimeout(t=>{this._delayedLeaveTimer=null,this.leave(e)},t)}getMeta(e){return this._tinode.getMeta(this.name,e)}getMessagesPage(e,t,s,i,n){let r=t?this.startMetaQuery().withDataRanges(t,e):n?this.startMetaQuery().withData(s,void 0,e):this.startMetaQuery().withData(void 0,i,e);return this._loadMessages(this._tinode._db,r.extract("data")).then(a=>0==(t=this.msgHasMoreMessages(s,i,n)).length?Promise.resolve({topic:this.name,code:200,params:{count:a}}):(e-=a,r=this.startMetaQuery().withDataRanges(t,e),this.getMeta(r.build())))}getPinnedMessages(){const e=this.aux("pins");if(!Array.isArray(e))return Promise.resolve(0);const t=[];let s=e;return this._tinode._db.readMessages(this.name,{ranges:x(s)}).then(i=>(i.forEach(e=>{e&&(t.push(e.seq),this._messages.put(e),this._maybeUpdateMessageVersionsCache(e))}),t.length!t.includes(e)),this._tinode._db.readMessages(this.name,{ranges:x(s)})):null)).then(i=>(i&&s.forEach(e=>{i.find(t=>t.low<=e&&t.hi>e)&&t.push(e)}),t.length==e.length?Promise.resolve({topic:this.name,code:200,params:{count:t.length}}):(s=e.filter(e=>!t.includes(e)),this.getMeta(this.startMetaQuery().withDataList(s).build()))))}setMeta(e){return e.tags&&(e.tags=function(e){let t=[];if(Array.isArray(e)){for(let s=0,i=e.length;s1&&t.push(i))}t=t.sort().filter((e,t,s)=>!t||e!=s[t-1])}return 0==t.length&&t.push(p),t}(e.tags)),this._tinode.setMeta(this.name,e).then(t=>(t&&t.code>=300||(e.sub&&(e.sub.topic=this.name,t.params&&t.params.acs&&(e.sub.acs=t.params.acs,e.sub.updated=t.ts),e.sub.user||(e.sub.user=this._tinode.getCurrentUserID(),e.desc||(e.desc={})),e.sub._noForwarding=!0,this._processMetaSubs([e.sub])),e.desc&&(t.params&&t.params.acs&&(e.desc.acs=t.params.acs,e.desc.updated=t.ts),this._processMetaDesc(e.desc)),e.tags&&this._processMetaTags(e.tags),e.cred&&this._processMetaCreds([e.cred],!0),e.aux&&this._processMetaAux(e.aux)),t))}updateMode(e,t){const s=e?this.subscriber(e):null,i=s?s.acs.updateGiven(t).getGiven():this.getAccessMode().updateWant(t).getWant();return this.setMeta({sub:{user:e,mode:i}})}invite(e,t){return this.setMeta({sub:{user:e,mode:t}})}archive(e){return this.private&&!this.private.arch==!e?Promise.resolve(e):this.setMeta({desc:{private:{arch:!!e||p}}})}pinMessage(e,t){let s=this.aux("pins");Array.isArray(s)||(s=[]);let i=!1;return t?s.includes(e)||(i=!0,5==s.length&&s.shift(),s.push(e)):s.includes(e)&&(i=!0,s=s.filter(t=>t!=e),0==s.length&&(s=p)),i?this.setMeta({aux:{pins:s}}):Promise.resolve()}delMessages(e,t){if(!this._attached)return Promise.reject(new Error("Cannot delete messages in inactive topic"));const s=M(e,this._maxSeq);let i;return i=s.length>0?this._tinode.delMessages(this.name,s,t):Promise.resolve({params:{del:0}}),i.then(t=>(t.params.del>this._maxDel&&(this._maxDel=Math.max(t.params.del,this._maxDel),this.clear=Math.max(t.params.del,this.clear)),e.forEach(e=>{e.hi?this.flushMessageRange(e.low,e.hi):this.flushMessage(e.low),this._messages.put({seq:e.low,low:e.low,hi:e.hi,_deleted:!0})}),this._tinode._db.addDelLog(this.name,t.params.del,e),this.onData&&this.onData(),t))}delMessagesAll(e){return!this._maxSeq||this._maxSeq<=0?Promise.resolve():this.delMessages([{low:1,hi:this._maxSeq+1,_all:!0}],e)}delMessagesList(e,t){return this.delMessages(x(e),t)}delMessagesEdits(e,t){const s=[e];return this.messageVersions(e,e=>s.push(e.seq)),this.delMessagesList(s,t)}delTopic(e){return this._deleted?(this._gone(),Promise.resolve(null)):this._tinode.delTopic(this.name,e).then(e=>(this._deleted=!0,this._resetSub(),this._gone(),e))}delSubscription(e){return this._attached?this._tinode.delSubscription(this.name,e).then(t=>(delete this._users[e],this.onSubsUpdated&&this.onSubsUpdated(Object.keys(this._users)),t)):Promise.reject(new Error("Cannot delete subscription in inactive topic"))}note(e,t){if(!this._attached)return;const s=this._users[this._tinode.getCurrentUserID()];let i=!1;s?(!s[e]||s[e]0&&this.note("read",e)}noteKeyPress(){this._attached?this._tinode.noteKeyPress(this.name):this._tinode.logger("INFO: Cannot send notification in inactive topic")}noteRecording(e){this._attached?this._tinode.noteKeyPress(this.name,e?"kpa":"kpv"):this._tinode.logger("INFO: Cannot send notification in inactive topic")}videoCall(e,t,s){if(this._attached||["ringing","hang-up"].includes(e))return this._tinode.videoCall(this.name,t,e,s)}_updateMyReadRecv(e,t,s){let i,n=!1;switch(t|=0,this.seq=0|this.seq,this.read=0|this.read,this.recv=0|this.recv,e){case"recv":i=this.recv,this.recv=Math.max(this.recv,t),n=i!=this.recv;break;case"read":i=this.read,this.read=Math.max(this.read,t),n=i!=this.read;break;case"msg":i=this.seq,this.seq=Math.max(this.seq,t),(!this.touched||this.touchede.startsWith(g));if(e)return e.substring(6)}subscriber(e){return this._users[e]}messageVersions(e,t,s){if(!t)return;const i=this._messageVersions[e];i&&i.forEach(t,void 0,void 0,s)}messages(e,t,s,i){const n=e||this.onData;if(n){const e="number"==typeof t?this._messages.find({seq:t},!0):void 0,r="number"==typeof s?this._messages.find({seq:s},!0):void 0;if(-1!=e&&-1!=r){let t=[];this._messages.forEach((e,s,i,n)=>{if(z.#S(e))return;if(e._deleted)return;const r=this.latestMsgVersion(e.seq)||e;r._origTs||(r._origTs=r.ts,r._origSeq=r.seq,r.ts=e.ts,r.seq=e.seq),t.push({data:r,idx:n})},e,r,{}),t.forEach((e,s)=>{n.call(i,e.data,s>0?t[s-1].data:void 0,s=0)return this._messages.getAt(t)}latestMessage(){return this._messages.getLast(e=>!e._deleted)}latestMsgVersion(e){const t=this._messageVersions[e];return t?t.getLast():null}maxMsgSeq(){return this._maxSeq}minMsgSeq(){return this._minSeq}maxClearId(){return this._maxDel}messageCount(){return this._messages.length()}queuedMessages(e,t){if(!e)throw new Error("Callback must be provided");this.messages(e,u,void 0,t)}msgReceiptCount(e,t){let s=0;if(t>0){const i=this._tinode.getCurrentUserID();for(let n in this._users){const r=this._users[n];r.user!==i&&r[e]>=t&&s++}}return s}msgReadCount(e){return this.msgReceiptCount("read",e)}msgRecvCount(e){return this.msgReceiptCount("recv",e)}msgHasMoreMessages(e,t,s){const i=[];if(e>=t)return i;let n,r=0;return this._messages.forEach((a,o)=>{const h=o||{seq:0},c=h._deleted?h.hi:h.seq+1;n=a.seq>c?{low:c,hi:a.seq}:null,n&&(s?n.hi>=e:n.low=e:n.low=0)return this._tinode._db.remMessages(this.name,e),this._messages.delAt(t)}flushMessageRange(e,t){this._tinode._db.remMessages(this.name,e,t);for(let s=e;s=0?this._messages.delRange(s,this._messages.find({seq:t},!0)):[]}swapMessageId(e,t){const s=this._messages.find(e),i=this._messages.length();0<=s&&s=0){const s=this._messages.getAt(t),i=this.msgStatus(s);if(10==i||30==i||40==i)return this._tinode._db.remMessages(this.name,e),s._cancelled=!0,this._messages.delAt(t),this.onData&&this.onData(),!0}return!1}getType(){return z.topicType(this.name)}getAccessMode(){return this.acs}setAccessMode(e){return this.acs=new n(e)}getDefaultAccess(){return this.defacs}startMetaQuery(){return new G(this)}isArchived(){return this.private&&!!this.private.arch}isMeType(){return z.isMeTopicName(this.name)}isSelfType(){return z.isSelfTopicName(this.name)}isChannelType(){return z.isChannelTopicName(this.name)}isGroupType(){return z.isGroupTopicName(this.name)}isP2PType(){return z.isP2PTopicName(this.name)}isCommType(){return z.isCommTopicName(this.name)}msgStatus(e,t){let s=0;return this._tinode.isMe(e.from)?e._sending?s=20:e._fatal||e._cancelled?s=40:e._failed?s=30:e.seq>=u?s=10:this.msgReadCount(e.seq)>0?s=70:this.msgRecvCount(e.seq)>0?s=60:e.seq>0&&(s=50):s=80,t&&e._status!=s&&(e._status=s,this._tinode._db.updMessageStatus(this.name,e.seq,s)),s}_maybeUpdateMessageVersionsCache(e){if(!z.#S(e))return void(this._messageVersions[e.seq]&&(this._messageVersions[e.seq].filter(t=>t.from==e.from),this._messageVersions[e.seq].isEmpty()&&delete this._messageVersions[e.seq]));const t=parseInt(e.head.replace.split(":")[1]);if(t>e.seq)return;const s=this.findMessage(t);if(s&&s.from!=e.from)return;const i=this._messageVersions[t]||new W((e,t)=>e.seq-t.seq,!0);i.put(e),this._messageVersions[t]=i}_routeData(e){e.content&&(!this.touched||this.touchedthis._maxSeq&&(this._maxSeq=e.seq,this.msgStatus(e,!0),clearTimeout(this._recvNotificationTimer),this._recvNotificationTimer=setTimeout(e=>{this._recvNotificationTimer=null,this.noteRecv(this._maxSeq)},100)),(e.seq0&&this._processMetaSubs(e.sub),e.del&&this._processDelMessages(e.del.clear,e.del.delseq),e.tags&&this._processMetaTags(e.tags),e.cred&&this._processMetaCreds(e.cred),e.aux&&this._processMetaAux(e.aux),this.onMeta&&this.onMeta(e)}_routePres(e){let t,s;switch(e.what){case"del":this._processDelMessages(e.clear,e.delseq);break;case"on":case"off":t=this._users[e.src],t?t.online="on"==e.what:this._tinode.logger("WARNING: Presence update for an unknown user",this.name,e.src);break;case"term":this._resetSub();break;case"upd":e.src&&!this._tinode.isTopicCached(e.src)&&this.getMeta(this.startMetaQuery().withOneSub(void 0,e.src).build());break;case"aux":this.getMeta(this.startMetaQuery().withAux().build());break;case"acs":if(s=e.src||this._tinode.getCurrentUserID(),t=this._users[s],t)t.acs.updateAll(e.dacs),this._processMetaSubs([{user:s,updated:new Date,acs:t.acs}]);else{const i=(new n).updateAll(e.dacs);i&&i.mode!=n._NONE&&(t=this._cacheGetUser(s),t?t.acs=i:(t={user:s,acs:i},this.getMeta(this.startMetaQuery().withOneSub(void 0,s).build())),t.updated=new Date,this._processMetaSubs([t]))}break;default:this._tinode.logger("INFO: Ignored presence update",e.what)}this.onPres&&this.onPres(e)}_routeInfo(e){switch(e.what){case"recv":case"read":const t=this._users[e.from];t&&(t[e.what]=e.seq,t.recv{e.hi?(s+=e.hi-e.low,this.flushMessageRange(e.low,e.hi)):(s++,this.flushMessage(e.low)),this._messages.put({seq:e.low,low:e.low,hi:e.hi,_deleted:!0})}),this._tinode._db.addDelLog(this.name,e,t)),s>0&&this.onData&&this.onData()}_allMessagesReceived(e){this.onAllMessagesReceived&&this.onAllMessagesReceived(e)}_resetSub(){this._attached=!1}_gone(){this._messages.reset(),this._tinode._db.remMessages(this.name),this._users={},this.acs=new n(null),this.private=null,this.public=null,this.trusted=null,this._maxSeq=0,this._minSeq=0,this._attached=!1;const e=this._tinode.getMeTopic();e&&e._routePres({_noForwarding:!0,what:"gone",topic:c,src:this.name}),this.onDeleteTopic&&this.onDeleteTopic()}_updateCachedUser(e,t){let s=this._cacheGetUser(e);return s=w(s||{},t),this._cachePutUser(e,s),v(this._users,e,s)}_getQueuedSeqId(){return this._queuedSeqId++}_loadMessages(e,t){(t=t||{}).limit=t.limit||24;let s=0;return e.readMessages(this.name,t).then(e=>{e.forEach(e=>{e.seq>this._maxSeq&&(this._maxSeq=e.seq),(e.seqe.readDelLog(this.name,t)).then(e=>e.forEach(e=>{this._messages.put({seq:e.low,low:e.low,hi:e.hi,_deleted:!0})})).then(e=>s)}_updateReceived(e,t){this.touched=new Date,this.seq=0|e,t&&!this._tinode.isMe(t)||(this.read=this.read?Math.max(this.read,this.seq):this.seq,this.recv=this.recv?Math.max(this.read,this.recv):this.read),this.unread=this.seq-(0|this.read),this._tinode._db.updTopic(this)}}class B extends z{_contacts={};constructor(e){super(d,e)}_processMetaSubs(e){let t=Object.getOwnPropertyNames(this._contacts).length;this._contacts={};for(let s in e){let i=e[s];const n=i.topic?i.topic:i.user;i=v(this._contacts,n,i),t++,this.onMetaSub&&this.onMetaSub(i)}t>0&&this.onSubsUpdated&&this.onSubsUpdated(Object.keys(this._contacts))}publish(){return Promise.reject(new Error("Publishing to 'fnd' is not supported"))}setMeta(e){return Object.getPrototypeOf(B.prototype).setMeta.call(this,e).then(e=>{Object.keys(this._contacts).length>0&&(this._contacts={},this.onSubsUpdated&&this.onSubsUpdated([]))})}checkTagUniqueness(e,t){return new Promise((s,i)=>{this.subscribe().then(t=>this.setMeta({desc:{public:e}})).then(e=>this.getMeta(this.startMetaQuery().withTags().build())).then(e=>{e&&Array.isArray(e.tags)&&0!=e.tags.length||s(!0);const i=e.tags.filter(e=>e!==t);s(0==i.length)}).catch(e=>{i(e)})})}contacts(e,t){const s=e||this.onMetaSub;if(s)for(let e in this._contacts)s.call(t,this._contacts[e],e,this._contacts)}}class F extends z{onContactUpdate;constructor(e){super(c,e),e&&(this.onContactUpdate=e.onContactUpdate)}_processMetaDesc(e){const t=e.acs&&!e.acs.isPresencer()&&this.acs&&this.acs.isPresencer();w(this,e),this._tinode._db.updTopic(this),this._updateCachedUser(this._tinode._myUID,e),t&&this._tinode.mapTopics(e=>{e.online&&(e.online=!1,e.seen=Object.assign(e.seen||{},{when:new Date}),this._refreshContact("off",e))}),this.onMetaDesc&&this.onMetaDesc(this)}_processMetaSubs(e){let t=0;if(e.forEach(e=>{const s=e.topic;if(s==d||s==c)return;e.online=!!e.online;let i=null;if(e.deleted)i=e,this._tinode.cacheRemTopic(s),this._tinode._db.remTopic(s);else{void 0!==e.seq&&(e.seq=0|e.seq,e.recv=0|e.recv,e.read=0|e.read,e.unread=e.seq-e.read);const t=this._tinode.getTopic(s);t._new&&delete t._new,i=w(t,e),this._tinode._db.updTopic(i),z.isP2PTopicName(s)&&(this._cachePutUser(s,i),this._tinode._db.updUser(s,i.public)),!e._noForwarding&&t&&(e._noForwarding=!0,t._processMetaDesc(e))}t++,this.onMetaSub&&this.onMetaSub(i)}),this.onSubsUpdated&&t>0){const s=[];e.forEach(e=>{s.push(e.topic)}),this.onSubsUpdated(s,t)}}_processMetaCreds(e,t){1==e.length&&e[0]==p&&(e=[]),t?e.forEach(e=>{if(e.val){let t=this._credentials.findIndex(t=>t.meth==e.meth&&t.val==e.val);t<0?(e.done||(t=this._credentials.findIndex(t=>t.meth==e.meth&&!t.done),t>=0&&this._credentials.splice(t,1)),this._credentials.push(e)):this._credentials[t].done=e.done}else if(e.resp){const t=this._credentials.findIndex(t=>t.meth==e.meth&&!t.done);t>=0&&(this._credentials[t].done=!0)}}):this._credentials=e,this.onCredsUpdated&&this.onCredsUpdated(this._credentials)}_routePres(e){if("term"==e.what)return void this._resetSub();if("upd"==e.what&&e.src==c)return void this.getMeta(this.startMetaQuery().withDesc().build());const t=this._tinode.cacheGetTopic(e.src);if(t){switch(e.what){case"on":t.online=!0;break;case"off":t.online&&(t.online=!1,t.seen=Object.assign(t.seen||{},{when:new Date}));break;case"msg":t._updateReceived(e.seq,e.act);break;case"upd":this.getMeta(this.startMetaQuery().withLaterOneSub(e.src).build());break;case"acs":e.tgt||(t.acs?t.acs.updateAll(e.dacs):t.acs=(new n).updateAll(e.dacs),t.touched=new Date);break;case"ua":t.seen={when:new Date,ua:e.ua};break;case"recv":e.seq=0|e.seq,t.recv=t.recv?Math.max(t.recv,e.seq):e.seq;break;case"read":e.seq=0|e.seq,t.read=t.read?Math.max(t.read,e.seq):e.seq,t.recv=t.recv?Math.max(t.read,t.recv):t.recv,t.unread=t.seq-t.read;break;case"gone":this._tinode.cacheRemTopic(e.src),t._deleted?this._tinode._db.remTopic(e.src):(t._deleted=!0,t._attached=!1,this._tinode._db.markTopicAsDeleted(e.src,!0));break;case"del":break;default:this._tinode.logger("INFO: Unsupported presence update in 'me'",e.what)}this._refreshContact(e.what,t)}else{if("acs"==e.what){const t=new n(e.dacs);if(!t||t.mode==n._INVALID)return void this._tinode.logger("ERROR: Invalid access mode update",e.src,e.dacs);if(t.mode==n._NONE)return void this._tinode.logger("WARNING: Removing non-existent subscription",e.src,e.dacs);{this.getMeta(this.startMetaQuery().withOneSub(void 0,e.src).build());const s=this._tinode.getTopic(e.src);s.topic=e.src,s.online=!1,s.acs=t,this._tinode._db.updTopic(s)}}else if("tags"==e.what)this.getMeta(this.startMetaQuery().withTags().build());else if("msg"==e.what){this.getMeta(this.startMetaQuery().withOneSub(void 0,e.src).build());const t=this._tinode.getTopic(e.src);t._deleted=!1,this._tinode._db.updTopic(t)}this._refreshContact(e.what,t)}this.onPres&&this.onPres(e)}_refreshContact(e,t){this.onContactUpdate&&this.onContactUpdate(e,t)}publish(){return Promise.reject(new Error("Publishing to 'me' is not supported"))}delCredential(e,t){return this._attached?this._tinode.delCredential(e,t).then(s=>{const i=this._credentials.findIndex(s=>s.meth==e&&s.val==t);return i>-1&&this._credentials.splice(i,1),this.onCredsUpdated&&this.onCredsUpdated(this._credentials),s}):Promise.reject(new Error("Cannot delete credential in inactive 'me' topic"))}contacts(e,t,s){this._tinode.mapTopics((i,n)=>{!i.isCommType()||t&&!t(i)||e.call(s,i,n)})}getContact(e){return this._tinode.cacheGetTopic(e)}getAccessMode(e){if(e){const t=this._tinode.cacheGetTopic(e);return t?t.acs:null}return this.acs}isArchived(e){const t=this._tinode.cacheGetTopic(e);return t&&t.private&&!!t.private.arch}getCredentials(){return this._credentials}}function K(e){return btoa(encodeURIComponent(e).replace(/%([0-9A-F]{2})/g,function(e,t){return String.fromCharCode("0x"+t)}))}function H(e,t){return"string"==typeof t&&t.length>128?"<"+t.length+", bytes: "+t.substring(0,12)+"..."+t.substring(t.length-12)+">":function(e,t){if(t instanceof Date)t=function(e){if(!b(e))return;const t=function(e,t){return"0".repeat((t=t||2)-(""+e).length)+e},s=e.getUTCMilliseconds();return e.getUTCFullYear()+"-"+t(e.getUTCMonth()+1)+"-"+t(e.getUTCDate())+"T"+t(e.getUTCHours())+":"+t(e.getUTCMinutes())+":"+t(e.getUTCSeconds())+(s?"."+t(s,3):"")+"Z"}(t);else if(t instanceof n)t=t.jsonHelper();else if(null==t||!1===t||Array.isArray(t)&&0==t.length||"object"==typeof t&&0==Object.keys(t).length)return;return t}(0,t)}"undefined"!=typeof WebSocket&&(O=WebSocket),"undefined"!=typeof XMLHttpRequest&&(j=XMLHttpRequest),"undefined"!=typeof indexedDB&&(L=indexedDB),function(){const e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";"undefined"==typeof btoa&&(s.g.btoa=function(t=""){let s=t,i="";for(let t,n=0,r=0,a=e;s.charAt(0|r)||(a="=",r%1);i+=a.charAt(63&n>>8-r%1*8)){if(t=s.charCodeAt(r+=3/4),t>255)throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");n=n<<8|t}return i}),"undefined"==typeof atob&&(s.g.atob=function(t=""){let s=t.replace(/=+$/,""),i="";if(s.length%4==1)throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");for(let t,n=0,r=0,a=0;t=s.charAt(a++);~t&&(r=n%4?64*r+t:t,n++%4)?i+=String.fromCharCode(255&r>>(-2*n&6)):0)t=e.indexOf(t);return i}),"undefined"==typeof window&&(s.g.window={WebSocket:O,XMLHttpRequest:j,indexedDB:L,URL:{createObjectURL:function(){throw new Error("Unable to use URL.createObjectURL in a non-browser application")}}}),N.setNetworkProviders(O,j),V.setNetworkProvider(j),k.setDatabaseProvider(L)}();class Q{_host;_secure;_appName;_apiKey;_browser="";_platform;_hwos="undefined";_humanLanguage="xx";_loggingEnabled=!1;_trimLongStrings=!1;_myUID=null;_authenticated=!1;_login=null;_authToken=null;_inPacketCount=0;_messageId=Math.floor(65535*Math.random()+65535);_serverInfo=null;_deviceToken=null;_pendingPromises={};_expirePromises=null;_connection=null;_persist=!1;_db=null;_cache={};constructor(e,t){if(this._host=e.host,this._secure=e.secure,this._appName=e.appName||"Undefined",this._apiKey=e.apiKey,this._platform=e.platform||"web","undefined"!=typeof navigator&&(this._browser=function(e,t){e=e||"";let s,i="";/reactnative/i.test(t)&&(i="ReactNative; ");let n=(e=e.replace(" (KHTML, like Gecko)","")).match(/(AppleWebKit\/[.\d]+)/i);if(n){const t=["edg","chrome","safari","mobile","version"];let i,r=e.substr(n.index+n[0].length).split(" "),a=[];for(let e=0;es[1].toLowerCase().startsWith(e))]),"Version"==s[1]&&(i=s[2]))}a.sort((e,t)=>e[2]-t[2]),a.length>0?(a[0][0].toLowerCase().startsWith("edg")?a[0][0]="Edge":"OPR"==a[0][0]?a[0][0]="Opera":"Safari"==a[0][0]&&i&&(a[0][1]=i),s=a[0][0]+"/"+a[0][1]):s=n[1]}else/firefox/i.test(e)?(n=/Firefox\/([.\d]+)/g.exec(e),s=n?"Firefox/"+n[1]:"Firefox/?"):(n=/([\w.]+)\/([.\d]+)/.exec(e),n?s=n[1]+"/"+n[2]:(n=e.split(" "),s=n[0]));if(n=s.split("/"),n.length>1){const e=n[1].split("."),t=e[1]?"."+e[1].substr(0,2):"";s=`${n[0]}/${e[0]}${t}`}return i+s}(navigator.userAgent,navigator.product),this._hwos=navigator.platform,this._humanLanguage=navigator.language||"en-US"),N.logger=this.logger,q().logger=this.logger,"lp"!=e.transport&&"ws"!=e.transport&&(e.transport=function(){if("object"==typeof window){if(window.WebSocket)return"ws";if(window.XMLHttpRequest)return"lp"}return null}()),this._connection=new N(e,"0",!0),this._connection.onMessage=e=>{this.#P(e)},this._connection.onOpen=e=>this.#A(),this._connection.onDisconnect=(e,t)=>this.#D(e,t),this._connection.onAutoreconnectIteration=(e,t)=>{this.onAutoreconnectIteration&&this.onAutoreconnectIteration(e,t)},this._persist=e.persist,this._db=new k(this.logger,this.logger),this._persist){const e=[];this._db.initDatabase().then(t=>this._db.mapTopics(t=>{let s=this.#E("topic",t.name);s||(s=t.name==c?new F:t.name==d?new B:new z(t.name),this._db.deserializeTopic(s,t),this.#N(s),s._cachePutSelf(),this._db.maxDelId(s.name).then(e=>{s._maxDel=Math.max(s._maxDel,e||0)}),delete s._new,e.push(s._loadMessages(this._db)))})).then(e=>this._db.mapUsers(e=>{this.#R("user",e.uid,w({},e.public))})).then(t=>Promise.all(e)).then(e=>{t&&t(),this.logger("Persistent cache initialized.")}).catch(e=>{t&&t(e),this.logger("Failed to initialize persistent cache:",e)})}else this._db.deleteDatabase().then(e=>{t&&t()})}logger(e,...t){if(this._loggingEnabled){const s=new Date,i=("0"+s.getUTCHours()).slice(-2)+":"+("0"+s.getUTCMinutes()).slice(-2)+":"+("0"+s.getUTCSeconds()).slice(-2)+"."+("00"+s.getUTCMilliseconds()).slice(-3);console.log("["+i+"]",e,t.join(" "))}}#I(e){let t=null;return e&&(t=new Promise((t,s)=>{this._pendingPromises[e]={resolve:t,reject:s,ts:new Date}})),t}#k(e,t,s,i){const n=this._pendingPromises[e];n&&(delete this._pendingPromises[e],t>=200&&t<400?n.resolve&&n.resolve(s):n.reject&&n.reject(new m(i,t)))}#C(e,t){let s;t&&(s=this.#I(t)),e=y(e);let i=JSON.stringify(e);this.logger("out: "+(this._trimLongStrings?JSON.stringify(e,H):i));try{this._connection.sendText(i)}catch(e){if(!t)throw e;this.#k(t,N.NETWORK_ERROR,null,e.message)}return s}#P(e){if(!e)return;if(this._inPacketCount++,this.onRawMessage&&this.onRawMessage(e),"0"===e)return void(this.onNetworkProbe&&this.onNetworkProbe());let t=JSON.parse(e,f);t?(this.logger("in: "+(this._trimLongStrings?JSON.stringify(t,H):e)),this.onMessage&&this.onMessage(t),t.ctrl?(this.onCtrlMessage&&this.onCtrlMessage(t.ctrl),t.ctrl.id&&this.#k(t.ctrl.id,t.ctrl.code,t.ctrl,t.ctrl.text),setTimeout(e=>{if(205==t.ctrl.code&&"evicted"==t.ctrl.text){const e=this.#E("topic",t.ctrl.topic);e&&(e._resetSub(),t.ctrl.params&&t.ctrl.params.unsub&&e._gone())}else if(t.ctrl.code<300&&t.ctrl.params)if("data"==t.ctrl.params.what){const e=this.#E("topic",t.ctrl.topic);e&&e._allMessagesReceived(t.ctrl.params.count)}else if("sub"==t.ctrl.params.what){const e=this.#E("topic",t.ctrl.topic);e&&e._processMetaSubs([])}},0)):setTimeout(e=>{if(t.meta){const e=this.#E("topic",t.meta.topic);e&&e._routeMeta(t.meta),t.meta.id&&this.#k(t.meta.id,200,t.meta,"META"),this.onMetaMessage&&this.onMetaMessage(t.meta)}else if(t.data){const e=this.#E("topic",t.data.topic);e&&e._routeData(t.data),this.onDataMessage&&this.onDataMessage(t.data)}else if(t.pres){const e=this.#E("topic",t.pres.topic);e&&e._routePres(t.pres),this.onPresMessage&&this.onPresMessage(t.pres)}else if(t.info){const e=this.#E("topic",t.info.topic);e&&e._routeInfo(t.info),this.onInfoMessage&&this.onInfoMessage(t.info)}else this.logger("ERROR: Unknown packet received.")},0)):(this.logger("in: "+e),this.logger("ERROR: failed to parse data"))}#A(){this._expirePromises||(this._expirePromises=setInterval(e=>{const t=new m("timeout",504),s=new Date((new Date).getTime()-5e3);for(let e in this._pendingPromises){let i=this._pendingPromises[e];i&&i.ts{e._resetSub()});for(let t in this._pendingPromises){const s=this._pendingPromises[t];s&&s.reject&&s.reject(e)}this._pendingPromises={},this.onDisconnect&&this.onDisconnect(e)}#U(){return this._appName+" ("+(this._browser?this._browser+"; ":"")+this._hwos+"); "+a}#O(e,t){switch(e){case"hi":return{hi:{id:this.getNextUniqueId(),ver:r,ua:this.#U(),dev:this._deviceToken,lang:this._humanLanguage,platf:this._platform}};case"acc":return{acc:{id:this.getNextUniqueId(),user:null,scheme:null,secret:null,tmpscheme:null,tmpsecret:null,login:!1,tags:null,desc:{},cred:{}}};case"login":return{login:{id:this.getNextUniqueId(),scheme:null,secret:null}};case"sub":return{sub:{id:this.getNextUniqueId(),topic:t,set:{},get:{}}};case"leave":return{leave:{id:this.getNextUniqueId(),topic:t,unsub:!1}};case"pub":return{pub:{id:this.getNextUniqueId(),topic:t,noecho:!1,head:null,content:{}}};case"get":return{get:{id:this.getNextUniqueId(),topic:t,what:null,desc:{},sub:{},data:{}}};case"set":return{set:{id:this.getNextUniqueId(),topic:t,desc:{},sub:{},tags:[],aux:{}}};case"del":return{del:{id:this.getNextUniqueId(),topic:t,what:null,delseq:null,user:null,hard:!1}};case"note":return{note:{topic:t,what:null,seq:void 0}};default:throw new Error(`Unknown packet type requested: ${e}`)}}#R(e,t,s){this._cache[e+":"+t]=s}#E(e,t){return this._cache[e+":"+t]}#j(e,t){delete this._cache[e+":"+t]}#q(e,t,s){const i=e?e+":":void 0;for(let e in this._cache)if((!i||0==e.indexOf(i))&&t.call(s,this._cache[e],e))break}#N(e){e._tinode=this,e._cacheGetUser=e=>{const t=this.#E("user",e);if(t)return{user:e,public:w({},t)}},e._cachePutUser=(e,t)=>{this.#R("user",e,w({},t.public))},e._cacheDelUser=e=>{this.#j("user",e)},e._cachePutSelf=t=>{this.#R("topic",e.name,e)},e._cacheDelSelf=t=>{this.#j("topic",e.name)}}#L(e){return e.params&&e.params.user?(this._myUID=e.params.user,this._authenticated=e&&e.code>=200&&e.code<300,e.params&&e.params.token&&e.params.expires?this._authToken={token:e.params.token,expires:e.params.expires}:this._authToken=null,this.onLogin&&this.onLogin(e.code,e.text),e):e}static credential(e,t,s,i){return"object"==typeof e&&({val:t,params:s,resp:i,meth:e}=e),e&&(t||i)?[{meth:e,val:t,resp:i,params:s}]:null}static topicType(e){return z.topicType(e)}static isMeTopicName(e){return z.isMeTopicName(e)}static isSelfTopicName(e){return z.isSelfTopicName(e)}static isGroupTopicName(e){return z.isGroupTopicName(e)}static isP2PTopicName(e){return z.isP2PTopicName(e)}static isCommTopicName(e){return z.isCommTopicName(e)}static isNewGroupTopicName(e){return z.isNewGroupTopicName(e)}static isChannelTopicName(e){return z.isChannelTopicName(e)}static getVersion(){return r}static setNetworkProviders(e,t){O=e,j=t,N.setNetworkProviders(O,j),V.setNetworkProvider(j)}static setDatabaseProvider(e){L=e,k.setDatabaseProvider(L)}static getLibrary(){return a}static isNullValue(e){return e===p}static isServerAssignedSeq(e){return e>0&&e3&&e.length<24&&/^[a-z0-9][a-z0-9_\-]{3,23}$/i.test(e)}static tagSplit(e){if(!e)return null;const t=(e=e.trim()).indexOf(":");if(t<=0)return null;const s=e.substring(t+1);return s?{prefix:e.substring(0,t),value:s}:null}static setUniqueTag(e,t){if(!e||0==e.length)return[t];const s=Q.tagSplit(t);return s?((e=e.filter(e=>e&&!e.startsWith(s.prefix))).push(t),e):e}static clearTagPrefix(e,t){return e&&0!=e.length?e.filter(e=>e&&!e.startsWith(t)):[]}static tagByPrefix(e,t){if(e)return e.find(e=>e&&e.startsWith(t))}getNextUniqueId(){return 0!=this._messageId?""+this._messageId++:void 0}connect(e){return this._connection.connect(e)}reconnect(e){this._connection.reconnect(e)}disconnect(){this._connection.disconnect()}clearStorage(){return this._db.isReady()?this._db.deleteDatabase():Promise.resolve()}initStorage(){return this._db.isReady()?Promise.resolve():this._db.initDatabase()}networkProbe(){this._connection.probe()}isConnected(){return this._connection.isConnected()}isAuthenticated(){return this._authenticated}authorizeURL(e){if("string"!=typeof e)return e;if(_(e)){const t="scheme://host/",s=new URL(e,t);this._apiKey&&s.searchParams.append("apikey",this._apiKey),this._authToken&&this._authToken.token&&(s.searchParams.append("auth","token"),s.searchParams.append("secret",this._authToken.token)),e=s.toString().substring(t.length-1)}return e}account(e,t,s,i,n){const r=this.#O("acc");return r.acc.user=e,r.acc.scheme=t,r.acc.secret=s,r.acc.login=i,n&&(r.acc.desc.defacs=n.defacs,r.acc.desc.public=n.public,r.acc.desc.private=n.private,r.acc.desc.trusted=n.trusted,r.acc.tags=n.tags,r.acc.cred=n.cred,r.acc.tmpscheme=n.scheme,r.acc.tmpsecret=n.secret,Array.isArray(n.attachments)&&n.attachments.length>0&&(r.extra={attachments:n.attachments.filter(e=>_(e))})),this.#C(r,r.acc.id)}createAccount(e,t,s,i){let n=this.account("new",e,t,s,i);return s&&(n=n.then(e=>this.#L(e))),n}createAccountBasic(e,t,s){return e=e||"",t=t||"",this.createAccount("basic",K(e+":"+t),!0,s)}updateAccountBasic(e,t,s,i){return t=t||"",s=s||"",this.account(e,"basic",K(t+":"+s),!1,i)}hello(){const e=this.#O("hi");return this.#C(e,e.hi.id).then(e=>(this._connection.backoffReset(),e.params&&(this._serverInfo=e.params),this.onConnect&&this.onConnect(),e)).catch(e=>{this._connection.reconnect(!0),this.onDisconnect&&this.onDisconnect(e)})}setDeviceToken(e){let t=!1;return(e=e||null)!=this._deviceToken&&(this._deviceToken=e,this.isConnected()&&this.isAuthenticated()&&(this.#C({hi:{dev:e||Q.DEL_CHAR}}),t=!0)),t}login(e,t,s){const i=this.#O("login");return i.login.scheme=e,i.login.secret=t,i.login.cred=s,this.#C(i,i.login.id).then(e=>this.#L(e))}loginBasic(e,t,s){return this.login("basic",K(e+":"+t),s).then(t=>(this._login=e,t))}loginToken(e,t){return this.login("token",e,t)}requestResetAuthSecret(e,t,s){return this.login("reset",K(e+":"+t+":"+s))}getAuthToken(){return this._authToken&&this._authToken.expires.getTime()>Date.now()?this._authToken:(this._authToken=null,null)}setAuthToken(e){this._authToken=e}subscribe(e,t,s){const i=this.#O("sub",e);if(e||(e=o),i.sub.get=t,s){if(s.sub&&(i.sub.set.sub=s.sub),s.desc){const t=s.desc;Q.isNewGroupTopicName(e)?i.sub.set.desc=t:Q.isP2PTopicName(e)&&t.defacs&&(i.sub.set.desc={defacs:t.defacs})}Array.isArray(s.attachments)&&s.attachments.length>0&&(i.extra={attachments:s.attachments.filter(e=>_(e))}),s.tags&&(i.sub.set.tags=s.tags),s.aux&&(i.sub.set.aux=s.aux)}return this.#C(i,i.sub.id)}leave(e,t){const s=this.#O("leave",e);return s.leave.unsub=t,this.#C(s,s.leave.id)}createMessage(e,t,s){const i=this.#O("pub",e);let n="string"==typeof t?q().parse(t):t;return n&&!q().isPlainText(n)&&(i.pub.head={mime:q().getContentType()},t=n),i.pub.noecho=s,i.pub.content=t,i.pub}publish(e,t,s){return this.publishMessage(this.createMessage(e,t,s))}publishMessage(e,t){(e=Object.assign({},e)).seq=void 0,e.from=void 0,e.ts=void 0;const s={pub:e};return t&&(s.extra={attachments:t.filter(e=>_(e))}),this.#C(s,e.id)}oobNotification(e){switch(this.logger("oob: "+(this._trimLongStrings?JSON.stringify(e,H):e)),e.what){case"msg":if(!e.seq||e.seq<1||!e.topic)break;if(!this.isConnected())break;const t=this.#E("topic",e.topic);if(!t)break;if(t.isSubscribed())break;t.maxMsgSeq(){this.logger("Failed to get the name of a new sender",e)}),t.subscribe(null).then(e=>t.getMeta(new G(t).withLaterData(24).withLaterDel(24).build())).then(e=>{t.leaveDelayed(!1,1e3)}).catch(e=>{this.logger("On push data fetch failed",e)}).finally(e=>{this.getMeTopic()._refreshContact("msg",t)}));break;case"read":this.getMeTopic()._routePres({what:"read",seq:e.seq});break;case"sub":if(!this.isMe(e.xfrom))break;const s={given:e.modeGiven,want:e.modeWant},i=new n(s),r=i.mode&&i.mode!=n._NONE?{what:"acs",src:e.topic,dacs:s}:{what:"gone",src:e.topic};this.getMeTopic()._routePres(r);break;default:this.logger("Unknown push type ignored",e.what)}}getMeta(e,t){const s=this.#O("get",e);return s.get=w(s.get,t),this.#C(s,s.get.id)}setMeta(e,t){const s=this.#O("set",e),i=[];return t&&(["desc","sub","tags","cred","aux"].forEach(e=>{t.hasOwnProperty(e)&&(i.push(e),s.set[e]=t[e])}),Array.isArray(t.attachments)&&t.attachments.length>0&&(s.extra={attachments:t.attachments.filter(e=>_(e))})),0==i.length?Promise.reject(new Error("Invalid {set} parameters")):this.#C(s,s.set.id)}delMessages(e,t,s){const i=this.#O("del",e);return i.del.what="msg",i.del.delseq=t,i.del.hard=s,this.#C(i,i.del.id)}delTopic(e,t){const s=this.#O("del",e);return s.del.what="topic",s.del.hard=t,this.#C(s,s.del.id)}delSubscription(e,t){const s=this.#O("del",e);return s.del.what="sub",s.del.user=t,this.#C(s,s.del.id)}delCredential(e,t){const s=this.#O("del",c);return s.del.what="cred",s.del.cred={meth:e,val:t},this.#C(s,s.del.id)}delCurrentUser(e){const t=this.#O("del",null);return t.del.what="user",t.del.hard=e,this.#C(t,t.del.id).then(e=>{this._myUID=null})}note(e,t,s){if(s<=0||s>=u)throw new Error(`Invalid message id ${s}`);const i=this.#O("note",e);i.note.what=t,i.note.seq=s,this.#C(i)}noteKeyPress(e,t){const s=this.#O("note",e);s.note.what=t||"kp",this.#C(s)}videoCall(e,t,s,i){const n=this.#O("note",e);n.note.seq=t,n.note.what="call",n.note.event=s,n.note.payload=i,this.#C(n,n.note.id)}getTopic(e){let t=this.#E("topic",e);return!t&&e&&(t=e==c?new F:e==d?new B:new z(e),this.#N(t),t._cachePutSelf()),t}cacheGetTopic(e){return this.#E("topic",e)}cacheRemTopic(e){this.#j("topic",e)}mapTopics(e,t){this.#q("topic",e,t)}isTopicCached(e){return!!this.#E("topic",e)}newGroupTopicName(e){return(e?h:o)+this.getNextUniqueId()}getMeTopic(){return this.getTopic(c)}getFndTopic(){return this.getTopic(d)}getLargeFileHelper(){return new V(this,"0")}getCurrentUserID(){return this._myUID}isMe(e){return this._myUID===e}getCurrentLogin(){return this._login}getServerInfo(){return this._serverInfo}report(e,t){return this.publish("sys",q().attachJSON(null,{action:e,target:t}))}getServerParam(e,t){return this._serverInfo&&this._serverInfo[e]||t}enableLogging(e,t){this._loggingEnabled=e,this._trimLongStrings=e&&t}setHumanLanguage(e){e&&(this._humanLanguage=e)}isTopicOnline(e){const t=this.#E("topic",e);return t&&t.online}getTopicAccessMode(e){const t=this.#E("topic",e);return t?t.acs:null}wantAkn(e){this._messageId=e?Math.floor(16777215*Math.random()+16777215):0}onWebsocketOpen=void 0;onConnect=void 0;onDisconnect=void 0;onLogin=void 0;onCtrlMessage=void 0;onDataMessage=void 0;onPresMessage=void 0;onMessage=void 0;onRawMessage=void 0;onNetworkProbe=void 0;onAutoreconnectIteration=void 0}return Q.MESSAGE_STATUS_NONE=0,Q.MESSAGE_STATUS_QUEUED=10,Q.MESSAGE_STATUS_SENDING=20,Q.MESSAGE_STATUS_FAILED=30,Q.MESSAGE_STATUS_FATAL=40,Q.MESSAGE_STATUS_SENT=50,Q.MESSAGE_STATUS_RECEIVED=60,Q.MESSAGE_STATUS_READ=70,Q.MESSAGE_STATUS_TO_ME=80,Q.DEL_CHAR=p,Q.MAX_MESSAGE_SIZE="maxMessageSize",Q.MAX_SUBSCRIBER_COUNT="maxSubscriberCount",Q.MIN_TAG_LENGTH="minTagLength",Q.MAX_TAG_LENGTH="maxTagLength",Q.MAX_TAG_COUNT="maxTagCount",Q.MAX_FILE_UPLOAD_SIZE="maxFileUploadSize",Q.REQ_CRED_VALIDATORS="reqCred",Q.MSG_DELETE_AGE="msgDelAge",Q.URI_TOPIC_ID_PREFIX="tinode:topic/",Q.TAG_ALIAS=g,Q.TAG_EMAIL="email:",Q.TAG_PHONE="tel:",i})());
\ No newline at end of file
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.tinode=t():e.tinode=t()}(this,()=>(()=>{"use strict";var e={767:e=>{const t="application/json+drafty",s="application/json",i=["act","height","duration","incoming","mime","name","premime","preref","preview","ref","size","state","url","val","width"],n=new Intl.Segmenter,r=[{name:"ST",start:/(?:^|[\W_])(\*)[^\s*]/,end:/[^\s*](\*)(?=$|[\W_])/},{name:"EM",start:/(?:^|\W)(_)[^\s_]/,end:/[^\s_](_)(?=$|\W)/},{name:"DL",start:/(?:^|[\W_])(~)[^\s~]/,end:/[^\s~](~)(?=$|[\W_])/},{name:"CO",start:/(?:^|\W)(`)[^`]/,end:/[^`](`)(?=$|\W)/}],a=["QQ"],o=[{name:"LN",dataName:"url",pack:function(e){return/^[a-z]+:\/\//i.test(e)||(e="http://"+e),{url:e}},re:/(?:(?:https?|ftp):\/\/|www\.|ftp\.)[-A-Z0-9+&@#\/%=~_|$?!:,.]*[A-Z0-9+&@#\/%=~_|$]/gi},{name:"MN",dataName:"val",pack:function(e){return{val:e.slice(1)}},re:/\B@([\p{L}\p{N}][._\p{L}\p{N}]*[\p{L}\p{N}])/gu},{name:"HT",dataName:"val",pack:function(e){return{val:e.slice(1)}},re:/\B#([\p{L}\p{N}][._\p{L}\p{N}]*[\p{L}\p{N}])/gu}],h={AU:{html_tag:"audio",md_tag:void 0,isVoid:!1},BN:{html_tag:"button",md_tag:void 0,isVoid:!1},BR:{html_tag:"br",md_tag:"\n",isVoid:!0},CO:{html_tag:"tt",md_tag:"`",isVoid:!1},DL:{html_tag:"del",md_tag:"~",isVoid:!1},EM:{html_tag:"i",md_tag:"_",isVoid:!1},EX:{html_tag:"",md_tag:void 0,isVoid:!0},FM:{html_tag:"div",md_tag:void 0,isVoid:!1},HD:{html_tag:"",md_tag:void 0,isVoid:!1},HL:{html_tag:"span",md_tag:void 0,isVoid:!1},HT:{html_tag:"a",md_tag:void 0,isVoid:!1},IM:{html_tag:"img",md_tag:void 0,isVoid:!1},LN:{html_tag:"a",md_tag:void 0,isVoid:!1},MN:{html_tag:"a",md_tag:void 0,isVoid:!1},RW:{html_tag:"div",md_tag:void 0,isVoid:!1},QQ:{html_tag:"div",md_tag:void 0,isVoid:!1},ST:{html_tag:"b",md_tag:"*",isVoid:!1},VC:{html_tag:"div",md_tag:void 0,isVoid:!1},VD:{html_tag:"video",md_tag:void 0,isVoid:!1}};function c(e,t,s){if(!e)return null;try{const s=atob(e),i=s.length,n=new ArrayBuffer(i),r=new Uint8Array(n);for(let e=0;e"",close:e=>" "},EM:{open:e=>"",close:e=>" "},DL:{open:e=>"",close:e=>""},CO:{open:e=>"",close:e=>" "},BR:{open:e=>" ",close:e=>""},HD:{open:e=>"",close:e=>""},HL:{open:e=>'',close:e=>" "},LN:{open:e=>'',close:e=>" ",props:e=>e?{href:e.url,target:"_blank"}:null},MN:{open:e=>'',close:e=>" ",props:e=>e?{id:e.val}:null},HT:{open:e=>'',close:e=>" ",props:e=>e?{id:e.val}:null},BN:{open:e=>"",close:e=>" ",props:e=>e?{"data-act":e.act,"data-val":e.val,"data-name":e.name,"data-ref":e.ref}:null},AU:{open:e=>'',close:e=>" ",props:e=>e?{src:e.ref||c(e.val,e.mime,u.logger),"data-preload":e.ref?"metadata":"auto","data-duration":e.duration,"data-name":e.name,"data-size":e.val?.75*e.val.length|0:0|e.size,"data-mime":e.mime}:null},IM:{open:e=>{const t=d(e._tempPreview,e.mime),s=c(e.val,e.mime,u.logger),i=e.ref||s;return(e.name?'':"")+' '},close:e=>e.name?" ":"",props:e=>e?{src:d(e._tempPreview,e.mime)||e.ref||c(e.val,e.mime,u.logger),title:e.name,alt:e.name,"data-width":e.width,"data-height":e.height,"data-name":e.name,"data-size":e.ref?0|e.size:e.val?.75*e.val.length|0:0|e.size,"data-mime":e.mime}:null},FM:{open:e=>" ",close:e=>"
"},RW:{open:e=>"",close:e=>"
"},QQ:{open:e=>"",close:e=>"
",props:e=>e?{}:null},VC:{open:e=>"",close:e=>"
",props:e=>e?{"data-duration":e.duration,"data-state":e.state}:{}},VD:{open:e=>{const t=d(e._tempPreview,e.mime),s=e.ref||c(e.preview,e.premime||"image/jpeg",u.logger);return' '},close:e=>"",props:e=>{if(!e)return null;const t=e.preref||c(e.preview,e.premime||"image/jpeg",u.logger);return{src:t,"data-src":e.ref||c(e.val,e.mime,u.logger),"data-width":e.width,"data-height":e.height,"data-preload":e.ref?"metadata":"auto","data-preview":t,"data-duration":0|e.duration,"data-name":e.name,"data-size":e.ref?0|e.size:e.val?.75*e.val.length|0:0|e.size,"data-mime":e.mime}}}},u=function(){this.txt="",this.fmt=[],this.ent=[]};function p(e,t,s,i){const n=[];if(0==i.length)return[];for(let s in i){const r=i[s];r.at>t&&n.push({txt:e.slice(t,r.at)});const a={tp:r.tp},o=p(e,r.at+1,r.end,r.children);o.length>0?a.children=o:a.txt=r.txt,n.push(a),t=r.end+1}return ts.end?(t.push(e[i]),s=e[i]):e[i].end<=s.end&&s.children.push(e[i]);for(let e in t)t[e].children=g(t[e].children);return t}function m(e){if(!e)return null;e="string"==typeof e?{txt:e}:e;let{txt:t,fmt:s,ent:i}=e;if(t=t||"",Array.isArray(i)||(i=[]),!Array.isArray(s)||0==s.length){if(0==i.length)return{text:t};s=[{at:0,len:0,key:0}]}const n=[],r=[];s.forEach(e=>{if(!e||"object"!=typeof e)return;if(!["undefined","number"].includes(typeof e.at))return;if(!["undefined","number"].includes(typeof e.len))return;let s=0|e.at,a=0|e.len;if(a<0)return;let o=e.key||0;i.length>0&&("number"!=typeof o||o<0||o>=i.length)||(s<=-1?r.push({start:-1,end:0,key:o}):s+a>E(t).length||(e.tp?n.push({type:e.tp,start:s,end:s+a}):i.length>0&&"object"==typeof i[o]&&n.push({start:s,end:s+a,key:o})))}),n.sort((e,t)=>{let s=e.start-t.start;return 0!=s?s:(s=t.end-e.end,0!=s?s:a.indexOf(t.type)-a.indexOf(e.type))}),r.length>0&&n.push(...r),n.forEach(e=>{i.length>0&&!e.type&&i[e.key]&&"object"==typeof i[e.key]&&(e.type=i[e.key].tp,e.data=i[e.key].data),e.type||(e.type="HD")});const o=E(t);let h=_({},o,0,o.length,n);return h=w(h,function(e){if(Array.isArray(e.children)&&1==e.children.length){const t=e.children[0];if(e.type)t.type||t.children||(e.text=t.text,delete e.children);else{const s=e.parent;(e=t).parent=s}}return e}),h}function f(e,t){return t?(e.children||(e.children=[]),e.text&&(e.children.push({text:e.text,parent:e}),delete e.text),t.parent=e,e.children.push(t),e):e}function _(e,t,s,i,n){if(!n||0==n.length)return se.segment).join("")}),e;for(let i=0;ie.segment).join("")}),s=r.start);const a=[];for(;ie.segment).join("")}),e}function b(e,t,s){if(!t)return e;e.txt=e.txt||"";const i=E(e.txt).length;if(t.text?e.txt+=t.text:Array.isArray(t.children)&&t.children.forEach(t=>{b(e,t,s)}),t.type){const n=E(e.txt).length-i;if(e.fmt=e.fmt||[],Object.keys(t.data||{}).length>0){e.ent=e.ent||[];const r=void 0===s[t.key]?e.ent.length:s[t.key];s[t.key]=r,e.ent[r]={tp:t.type,data:t.data},t.att?e.fmt.push({at:-1,len:0,key:r}):e.fmt.push({at:i,len:n,key:r})}else e.fmt.push({tp:t.type,at:i,len:n})}return e}function w(e,t,s){if(!e)return null;let i=t.call(s,e);if(!i||!i.children)return i;const n=[];for(let e in i.children){let r=i.children[e];r&&(r=w(r,t,s),r&&n.push(r))}return 0==n.length?i.children=null:i.children=n,i}function v(e,t,s,i,n){if(!e)return null;i&&e.type&&i.push(e.type);let r=[];for(let s in e.children){const a=v(e.children[s],t,s,i,n);a&&r.push(a)}return 0==r.length&&(r=e.text?[e.text]:null),i&&e.type&&i.pop(),t.call(n,e.type,e.data,r,s,i)}function y(e,t,s){return e?(s&&(t-=s.length),w(e,function(e){if(t<=-1)return null;if(e.att)return e;if(0==t)e.text=s,t=-1;else if(e.text){const i=E(e.text);i.length>t?(e.text=i.slice(0,t).map(e=>e.segment).join("")+s,t=-1):t-=i.length}return e})):null}function M(e,t){return w(e,e=>{const s=P(e.data,!0,t?t(e):null);return s?e.data=s:delete e.data,e})}function x(e){if("BR"==e.type)e=null;else if(e.text)e.type||(e.text=e.text.trimStart(),e.text||(e=null));else if(!e.type&&e.children&&e.children.length>0){const t=x(e.children[0]);t?e.children[0]=t:(e.children.shift(),e.type||0!=e.children.length||(e=null))}return e}function T(e,i){if(!e)return null;if(e.att)e.text=" ",delete e.att,delete e.children;else if(e.children){const n=[],r=[];for(let a in e.children){const o=e.children[a];if(o.att){if(n.length==i)continue;if(o.data.mime==t||o.data.mime==s)continue;delete o.att,delete o.children,o.text=" ",n.push(o)}else r.push(o)}e.children=r.concat(n)}return e}function S(e,t){let s="",i=[];for(let n in e){const r=e[n];if(!r.txt){const e=S(r.children,s.length+t);r.txt=e.txt,i=i.concat(e.fmt)}r.tp&&i.push({at:s.length+t,len:r.txt.length,tp:r.tp}),s+=r.txt}return{txt:s,fmt:i}}function P(e,t,s){if(e&&Object.entries(e).length>0){s=s||[];const n={};if(i.forEach(i=>{if(e[i]){if(t&&!s.includes(i)&&("string"==typeof e[i]||Array.isArray(e[i]))&&e[i].length>64)return;if("object"==typeof e[i])return;n[i]=e[i]}}),0!=Object.entries(n).length)return n}return null}function A(e){return 0==Object.keys(e??{}).length}function D(e,t,s){const i=function(e){const t=[];let s=0,i=0;for(const{segment:n}of e){for(let e=0;e{let t,n,h=[];if(r.forEach(t=>{h=h.concat(function(e,t,s,i){const n=[];let r=0,a=e.slice(0);for(;a.length>0;){const o=t.exec(a);if(null==o)break;let h=o.index+o[0].lastIndexOf(o[1]);a=a.slice(h+1),h+=r,r=h+1;const c=s?s.exec(a):null;if(null==c)break;let d=c.index+c[0].indexOf(c[1]);a=a.slice(d+1),d+=r,r=d+1,n.push({txt:e.slice(h+1,d),children:[],at:h,end:d,tp:i})}return n}(e,t.start,t.end,t.name))}),0==h.length)n={txt:e};else{h.sort((e,t)=>{const s=e.at-t.at;return 0!=s?s:t.end-e.end}),h=g(h);const t=S(p(e,0,e.length,h),0);n={txt:t.txt,fmt:t.fmt}}if(t=function(e){let t,s=[];if(o.forEach(i=>{for(;null!==(t=i.re.exec(e));)s.push({offset:t.index,len:t[0].length,unique:t[0],data:i.pack(t[0]),type:i.name})}),0==s.length)return s;s.sort((e,t)=>e.offset-t.offset);let i=-1;return s=s.filter(e=>{const t=e.offset>i;return i=e.offset+e.len,t}),s}(n.txt),t.length>0){const e=[];for(let n in t){const r=t[n];let a=i[r.unique];a||(a=s.length,i[r.unique]=a,s.push({tp:r.type,data:r.data})),e.push({at:r.offset,len:r.len,key:a})}n.ent=e}a.push(n)});const h={txt:""};if(a.length>0){if(h.txt=a[0].txt,h.fmt=(a[0].fmt||[]).concat(a[0].ent||[]),h.fmt.length){const e=n.segment(h.txt);for(const t of h.fmt)({at:t.at,len:t.len}=D(t,e,h.txt))}for(let e=1;e{const{at:n,len:r}=D(e,i,t.txt);return e.at=n+s,e.len=r,e}))),t.ent&&(A(i)&&(i=n.segment(t.txt)),h.fmt=h.fmt.concat(t.ent.map(e=>{const{at:n,len:r}=D(e,i,t.txt);return e.at=n+s,e.len=r,e})))}0==h.fmt.length&&delete h.fmt,s.length>0&&(h.ent=s)}return h},u.append=function(e,t){if(!e)return t;if(!t)return e;e.txt=e.txt||"";const s=E(e.txt).length;return"string"==typeof t?e.txt+=t:t.txt&&(e.txt+=t.txt),Array.isArray(t.fmt)&&(e.fmt=e.fmt||[],Array.isArray(t.ent)&&(e.ent=e.ent||[]),t.fmt.forEach(i=>{const n={at:(0|i.at)+s,len:0|i.len};-1==i.at&&(n.at=-1,n.len=0),i.tp?n.tp=i.tp:(n.key=e.ent.length,e.ent.push(t.ent[i.key||0])),e.fmt.push(n)})),e},u.insertImage=function(e,t,s){(e=e||{txt:" "}).ent=e.ent||[],e.fmt=e.fmt||[],e.fmt.push({at:0|t,len:1,key:e.ent.length});const i={tp:"IM",data:{mime:s.mime,ref:s.refurl,val:s.bits||s.preview,width:s.width,height:s.height,name:s.filename,size:0|s.size}};return s.urlPromise&&(i.data._tempPreview=s._tempPreview,i.data._processing=!0,s.urlPromise.then(e=>{i.data.ref=e,i.data._tempPreview=void 0,i.data._processing=void 0},e=>{i.data._processing=void 0})),e.ent.push(i),e},u.insertVideo=function(e,t,s){(e=e||{txt:" "}).ent=e.ent||[],e.fmt=e.fmt||[],e.fmt.push({at:0|t,len:1,key:e.ent.length});const i={tp:"VD",data:{mime:s.mime,ref:s.refurl,val:s.bits,preref:s.preref,preview:s.preview,width:s.width,height:s.height,duration:0|s.duration,name:s.filename,size:0|s.size}};return s.urlPromise&&(i.data._tempPreview=s._tempPreview,i.data._processing=!0,s.urlPromise.then(e=>{i.data.ref=e[0],i.data.preref=e[1],i.data._tempPreview=void 0,i.data._processing=void 0},e=>{i.data._processing=void 0})),e.ent.push(i),e},u.insertAudio=function(e,t,s){(e=e||{txt:" "}).ent=e.ent||[],e.fmt=e.fmt||[],e.fmt.push({at:0|t,len:1,key:e.ent.length});const i={tp:"AU",data:{mime:s.mime,val:s.bits,duration:0|s.duration,preview:s.preview,name:s.filename,size:0|s.size,ref:s.refurl}};return s.urlPromise&&(i.data._processing=!0,s.urlPromise.then(e=>{i.data.ref=e,i.data._processing=void 0},e=>{i.data._processing=void 0})),e.ent.push(i),e},u.videoCall=function(e){return{txt:" ",fmt:[{at:0,len:1,key:0}],ent:[{tp:"VC",data:{aonly:e}}]}},u.updateVideoCall=function(e,t){const s=((e||{}).fmt||[])[0];if(!s)return e;let i;if("VC"==s.tp)delete s.tp,s.key=0,i={tp:"VC"},e.ent=[i];else if(i=(e.ent||[])[0|s.key],!i||"VC"!=i.tp)return e;return i.data=i.data||{},Object.assign(i.data,t),e},u.quote=function(e,t,s){const i=u.append(u.appendLineBreak(u.mention(e,t)),s);return i.fmt.push({at:0,len:E(i.txt).length,tp:"QQ"}),i},u.mention=function(e,t){return{txt:e||"",fmt:[{at:0,len:E(e||"").length,key:0}],ent:[{tp:"MN",data:{val:t}}]}},u.appendLink=function(e,t){(e=e||{txt:""}).ent=e.ent||[],e.fmt=e.fmt||[],e.fmt.push({at:e.txt.length,len:t.txt.length,key:e.ent.length}),e.txt+=t.txt;const s={tp:"LN",data:{url:t.url}};return e.ent.push(s),e},u.appendImage=function(e,t){return(e=e||{txt:""}).txt+=" ",u.insertImage(e,e.txt.length-1,t)},u.appendAudio=function(e,t){return(e=e||{txt:""}).txt+=" ",u.insertAudio(e,e.txt.length-1,t)},u.attachFile=function(e,t){(e=e||{txt:""}).ent=e.ent||[],e.fmt=e.fmt||[],e.fmt.push({at:-1,len:0,key:e.ent.length});const s={tp:"EX",data:{mime:t.mime,val:t.data,name:t.filename,ref:t.refurl,size:0|t.size}};return t.urlPromise&&(s.data._processing=!0,t.urlPromise.then(e=>{s.data.ref=e,s.data._processing=void 0},e=>{s.data._processing=void 0})),e.ent.push(s),e},u.wrapInto=function(e,t,s,i){return"string"==typeof e&&(e={txt:e}),e.fmt=e.fmt||[],e.fmt.push({at:s||0,len:i||e.txt.length,tp:t}),e},u.wrapAsForm=function(e,t,s){return u.wrapInto(e,"FM",t,s)},u.insertButton=function(e,t,s,i,n,r,a){return"string"==typeof e&&(e={txt:e}),!e||!e.txt||e.txt.length{switch(e.type){case"IM":return["val"];case"VD":return["preview"]}return null}),b({},s,[])):e},u.preview=function(e,t,s){let i=m(e);if(i=T(i,3),i=w(i,function(e){return"MN"==e.type?e.parent&&e.parent.type||!(e.text||"").startsWith("➦")||(e.text="➦",delete e.children):"QQ"==e.type?(e.text=" ",delete e.children):"BR"==e.type&&(e.text=" ",delete e.children,delete e.type),e}),i=y(i,t,"…"),s){const e={IM:["val"],VD:["preview"]};i=M(i,t=>e[t.type])}else i=M(i);return b({},i,[])},u.toPlainText=function(e){return"string"==typeof e?e:e.txt},u.isPlainText=function(e){return"string"==typeof e||!(e.fmt||e.ent)},u.toMarkdown=function(e){return v(m(e),function(e,t,s){const i=h[e];let n=s?s.join(""):"";return i&&(i.isVoid?n=i.md_tag||"":i.md_tag&&(n=i.md_tag+n+i.md_tag)),n},0)},u.isValid=function(e){if(!e)return!1;const{txt:t,fmt:s,ent:i}=e;if(!t&&""!==t&&!s&&!i)return!1;const n=typeof t;return!("string"!=n&&"undefined"!=n&&null!==t||void 0!==s&&!Array.isArray(s)&&null!==s||void 0!==i&&!Array.isArray(i)&&null!==i)},u.hasAttachments=function(e){if(!Array.isArray(e.fmt))return!1;for(let t in e.fmt){const s=e.fmt[t];if(s&&s.at<0){const t=e.ent[0|s.key];return t&&"EX"==t.tp&&t.data}}return!1},u.attachments=function(e,t,s){if(!Array.isArray(e.fmt))return;let i=0;for(let n in e.fmt){let r=e.fmt[n];if(r&&r.at<0){const n=e.ent[0|r.key];if(n&&"EX"==n.tp&&n.data&&t.call(s,n.data,i++,"EX"))break}}},u.hasEntities=function(e){return e.ent&&e.ent.length>0},u.entities=function(e,t,s){if(e.ent&&e.ent.length>0)for(let i in e.ent)if(e.ent[i]&&t.call(s,e.ent[i].data,i,e.ent[i].tp))break},u.styles=function(e,t,s){if(e.fmt&&e.fmt.length>0)for(let i in e.fmt){const n=e.fmt[i];if(n&&t.call(s,n.tp,n.at,n.len,n.key,i))break}},u.sanitizeEntities=function(e){if(e&&e.ent&&e.ent.length>0)for(let t in e.ent){const s=e.ent[t];if(s&&s.data){const i=P(s.data);i?e.ent[t].data=i:delete e.ent[t].data}}return e},u.getDownloadUrl=function(e){let i=null;return e.mime!=t&&e.mime!=s&&e.val?i=c(e.val,e.mime,u.logger):"string"==typeof e.ref&&(i=e.ref),i},u.isProcessing=function(e){return!!e._processing},u.getPreviewUrl=function(e){return e.val?c(e.val,e.mime,u.logger):null},u.getEntitySize=function(e){return e.size?e.size:e.val?.75*e.val.length|0:0},u.getEntityMimeType=function(e){return e.mime||"text/plain"},u.tagName=function(e){return h[e]&&h[e].html_tag},u.attrValue=function(e,t){if(t&&l[e]&&l[e].props)return l[e].props(t)},u.getContentType=function(){return"text/x-drafty"},e.exports=u}},t={};function s(i){var n=t[i];if(void 0!==n)return n.exports;var r=t[i]={exports:{}};return e[i](r,r.exports,s),r.exports}s.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return s.d(t,{a:t}),t},s.d=(e,t)=>{for(var i in t)s.o(t,i)&&!s.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},s.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),s.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),s.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var i={};s.r(i),s.d(i,{AccessMode:()=>n,Drafty:()=>q(),Tinode:()=>Q});class n{constructor(e){e&&(this.given="number"==typeof e.given?e.given:n.decode(e.given),this.want="number"==typeof e.want?e.want:n.decode(e.want),this.mode=e.mode?"number"==typeof e.mode?e.mode:n.decode(e.mode):this.given&this.want)}static#e(e,t,s){if(["given","want","mode"].includes(t=t||"mode"))return 0!=(e[t]&s);throw new Error(`Invalid AccessMode component '${t}'`)}static decode(e){if(!e)return null;if("number"==typeof e)return e&n._BITMASK;if("N"===e||"n"===e)return n._NONE;const t={J:n._JOIN,R:n._READ,W:n._WRITE,P:n._PRES,A:n._APPROVE,S:n._SHARE,D:n._DELETE,O:n._OWNER};let s=n._NONE;for(let i=0;i=20&&t.length<=24&&["ts","touched","updated","created","when","deleted","expires"].includes(e)){const e=new Date(t);if(!isNaN(e))return e}else if("acs"===e&&"object"==typeof t)return new n(t);return t}function _(e){return e&&!/^\s*([a-z][a-z0-9+.-]*:|\/\/)/im.test(e)}function b(e){return e instanceof Date&&!isNaN(e)&&0!=e.getTime()}function w(e,t,s){if("object"!=typeof t){if(void 0===t)return e;if(t===p)return;return t}if(null===t)return t;if(t instanceof Date&&!isNaN(t))return!e||!(e instanceof Date)||isNaN(e)||e{"_"==t[0]?delete e[t]:e[t]?Array.isArray(e[t])&&0==e[t].length?delete e[t]:e[t]?e[t]instanceof Date?b(e[t])||delete e[t]:"object"==typeof e[t]&&(y(e[t]),0==Object.getOwnPropertyNames(e[t]).length&&delete e[t]):delete e[t]:delete e[t]}),e}function M(e,t){return Array.isArray(e)?(e.sort((e,t)=>e.low(s.low0&&(!s.hi||s.hi{if(0==e.length)e.push(t);else{let s=e[e.length-1];t.low<=s.hi?s.hi=Math.max(s.hi,t.hi):e.push(t)}return e},[])):[]}function x(e){return e.sort((e,t)=>e-t),e.reduce((e,t)=>{if(0==e.length)e.push({low:t});else{let s=e[e.length-1];!s.hi&&t!=s.low+1||t>s.hi?e.push({low:t}):s.hi=s.hi?Math.max(s.hi,t+1):t+1}return e},[])}let T,S;const P="Connection failed",A=418,D="Disconnected by client";function E(e,t,s,i){let n=null;return["http","https","ws","wss"].includes(t)&&(n=`${t}://${e}`,"/"!==n.charAt(n.length-1)&&(n+="/"),n+="v"+s+"/channels",["http","https"].includes(t)&&(n+="/lp"),n+="?apikey="+i),n}class N{static#t=e=>{};#s=null;#i=0;#n=!1;#r=null;host;secure;apiKey;version;autoreconnect;initialized;constructor(e,t,s){if(this.host=e.host,this.secure=e.secure,this.apiKey=e.apiKey,this.version=t,this.autoreconnect=s,"lp"===e.transport?(this.#a(),this.initialized="lp"):"ws"===e.transport&&(this.#o(),this.initialized="ws"),!this.initialized)throw N.#t("Unknown or invalid network transport. Running under Node? Call 'Tinode.setNetworkProviders()'."),new Error("Unknown or invalid network transport. Running under Node? Call 'Tinode.setNetworkProviders()'.")}static setNetworkProviders(e,t){T=e,S=t}static set logger(e){N.#t=e}connect(e,t){return Promise.reject(null)}reconnect(e){}disconnect(){}sendText(e){}isConnected(){return!1}transport(){return this.initialized}probe(){this.sendText("1")}backoffReset(){this.#h()}#c(){clearTimeout(this.#s);const e=Math.pow(2,this.#i)*(1+.3*Math.random())*2e3;this.#i=this.#i>=10?this.#i:this.#i+1,this.onAutoreconnectIteration&&this.onAutoreconnectIteration(e),this.#s=setTimeout(t=>{if(N.#t(`Reconnecting, iter=${this.#i}, timeout=${e}`),this.#n)this.onAutoreconnectIteration&&this.onAutoreconnectIteration(-1);else{const e=this.connect();this.onAutoreconnectIteration?this.onAutoreconnectIteration(0,e):e.catch(e=>{})}},e)}#d(){clearTimeout(this.#s),this.#s=null}#h(){this.#i=0}#a(){let e=null,t=null,s=null,i=(t,s,n)=>{let r=new S,a=!1;return r.onreadystatechange=o=>{if(4==r.readyState)if(201==r.status){let n=JSON.parse(r.responseText,f);e=t+"&sid="+n.ctrl.params.sid,r=i(e),r.send(null),this.onOpen&&this.onOpen(),s&&(a=!0,s()),this.autoreconnect&&this.#d()}else if(r.status>0&&r.status<400)this.onMessage&&this.onMessage(r.responseText),r=i(e),r.send(null);else{if(n&&!a&&(a=!0,n(r.responseText)),this.onMessage&&r.responseText&&this.onMessage(r.responseText),this.onDisconnect){const e=r.status||(this.#n?A:503),t=r.responseText||(this.#n?D:P);this.onDisconnect(new m(t,e),e)}r=null,!this.#n&&this.autoreconnect&&this.#c()}},r.open("POST",t,!0),r};this.connect=(e,s)=>{if(this.#n=!1,t){if(!s)return Promise.resolve();t.onreadystatechange=void 0,t.abort(),t=null}return e&&(this.host=e),new Promise((e,s)=>{const n=E(this.host,this.secure?"https":"http",this.version,this.apiKey);N.#t("LP connecting to:",n),t=i(n,e,s),t.send(null)}).catch(e=>{N.#t("LP connection failed:",e)})},this.reconnect=e=>{this.#d(),this.connect(null,e)},this.disconnect=i=>{this.#n=!0,this.#d(),s&&(s.onreadystatechange=void 0,s.abort(),s=null),t&&(t.onreadystatechange=void 0,t.abort(),t=null),this.onDisconnect&&this.onDisconnect(new m(D,A),A),e=null},this.sendText=t=>{if(s=(e=>{const t=new S;return t.onreadystatechange=e=>{if(4==t.readyState&&t.status>=400)throw new m("LP sender failed",t.status)},t.open("POST",e,!0),t})(e),!s||1!=s.readyState)throw new Error("Long poller failed to connect");s.send(t)},this.isConnected=e=>t&&!0}#o(){this.connect=(e,t)=>{if(this.#n=!1,this.#r){if(!t&&this.#r.readyState==this.#r.OPEN)return this.probe(),Promise.resolve();this.#r.close(),this.#r=null}return e&&(this.host=e),new Promise((e,t)=>{const s=E(this.host,this.secure?"wss":"ws",this.version,this.apiKey);N.#t("WS connecting to: ",s);const i=new T(s);i.onerror=e=>{t(e)},i.onopen=t=>{this.autoreconnect&&this.#d(),this.onOpen&&this.onOpen(),e()},i.onclose=e=>{if(this.#r=null,this.onDisconnect){const e=this.#n?A:503;this.onDisconnect(new m(this.#n?D:P,e),e)}!this.#n&&this.autoreconnect&&this.#c()},i.onmessage=e=>{this.onMessage&&this.onMessage(e.data)},this.#r=i})},this.reconnect=e=>{this.#d(),this.connect(null,e)},this.disconnect=e=>{this.#n=!0,this.#d(),this.#r&&(this.#r.close(),this.#r=null)},this.sendText=e=>{if(!this.#r||this.#r.readyState!=this.#r.OPEN)throw new Error("Websocket is not connected");this.#r.send(e)},this.isConnected=e=>this.#r&&this.#r.readyState==this.#r.OPEN}onMessage=void 0;onDisconnect=void 0;onOpen=void 0;onAutoreconnectIteration=void 0}N.NETWORK_ERROR=503,N.NETWORK_ERROR_TEXT=P,N.NETWORK_USER=A,N.NETWORK_USER_TEXT=D;const R="tinode-web";let I;class k{#l=e=>{};#u=e=>{};db=null;disabled=!0;constructor(e,t){this.#l=e||this.#l,this.#u=t||this.#u}#p(e,t,s){return this.db?new Promise((i,n)=>{const r=this.db.transaction([e]);r.onerror=t=>{this.#u("PCache","mapObjects",e,t.target.error),n(t.target.error)},r.objectStore(e).getAll().onsuccess=e=>{t&&e.target.result.forEach(e=>{t.call(s,e)}),i(e.target.result)}}):disabled?Promise.resolve([]):Promise.reject(new Error("not initialized"))}initDatabase(){return new Promise((e,t)=>{const s=I.open(R,3);s.onsuccess=t=>{this.db=t.target.result,this.disabled=!1,this.db.onversionchange=e=>{this.#u("PCache","another tab tries to upgrade DB, shutting down"),this.db.close(),this.db=null,this.disabled=!0},e(this.db)},s.onerror=e=>{this.#u("PCache","failed to initialize",e),t(e.target.error),this.#l(e.target.error)},s.onupgradeneeded=e=>{if(this.db=e.target.result,this.db.onerror=e=>{this.#u("PCache","failed to create storage",e),this.#l(e.target.error)},this.db.objectStoreNames.contains("topic")||this.db.createObjectStore("topic",{keyPath:"name"}),this.db.objectStoreNames.contains("user")||this.db.createObjectStore("user",{keyPath:"uid"}),this.db.objectStoreNames.contains("subscription")||this.db.createObjectStore("subscription",{keyPath:["topic","uid"]}),this.db.objectStoreNames.contains("message")||this.db.createObjectStore("message",{keyPath:["topic","seq"]}),!this.db.objectStoreNames.contains("dellog")){const e=this.db.createObjectStore("dellog",{keyPath:["topic","low","hi"]});e.indexNames.contains("topic_clear")||e.createIndex("topic_clear",["topic","clear"],{unique:!1})}}})}deleteDatabase(){return this.db&&(this.db.close(),this.db=null),new Promise((e,t)=>{const s=I.deleteDatabase(R);s.onblocked=e=>{this.db&&this.db.close();const s=new Error("blocked");this.#u("PCache","deleteDatabase",s),t(s)},s.onsuccess=t=>{this.db=null,this.disabled=!0,e(!0)},s.onerror=e=>{this.#u("PCache","deleteDatabase",e.target.error),t(e.target.error)}})}isReady(){return!!this.db}updTopic(e){return this.isReady()?new Promise((t,s)=>{const i=this.db.transaction(["topic"],"readwrite");i.oncomplete=e=>{t(e.target.result)},i.onerror=e=>{this.#u("PCache","updTopic",e.target.error),s(e.target.error)};const n=i.objectStore("topic").get(e.name);n.onsuccess=t=>{i.objectStore("topic").put(k.#g(n.result,e)),i.commit()}}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}markTopicAsDeleted(e,t){return this.isReady()?new Promise((s,i)=>{const n=this.db.transaction(["topic"],"readwrite");n.oncomplete=e=>{s(e.target.result)},n.onerror=e=>{this.#u("PCache","markTopicAsDeleted",e.target.error),i(e.target.error)},n.objectStore("topic").get(e).onsuccess=e=>{const s=e.target.result;s&&s._deleted!=t&&(s._deleted=t,n.objectStore("topic").put(s)),n.commit()}}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}remTopic(e){return this.isReady()?new Promise((t,s)=>{const i=this.db.transaction(["topic","subscription","message"],"readwrite");i.oncomplete=e=>{t(e.target.result)},i.onerror=e=>{this.#u("PCache","remTopic",e.target.error),s(e.target.error)},i.objectStore("topic").delete(IDBKeyRange.only(e)),i.objectStore("subscription").delete(IDBKeyRange.bound([e,"-"],[e,"~"])),i.objectStore("message").delete(IDBKeyRange.bound([e,0],[e,Number.MAX_SAFE_INTEGER])),i.commit()}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}mapTopics(e,t){return this.#p("topic",e,t)}deserializeTopic(e,t){k.#m(e,t)}updUser(e,t){if(!(arguments.length<2||void 0===t))return this.isReady()?new Promise((s,i)=>{const n=this.db.transaction(["user"],"readwrite");n.oncomplete=e=>{s(e.target.result)},n.onerror=e=>{this.#u("PCache","updUser",e.target.error),i(e.target.error)},n.objectStore("user").put({uid:e,public:t}),n.commit()}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}remUser(e){return this.isReady()?new Promise((t,s)=>{const i=this.db.transaction(["user"],"readwrite");i.oncomplete=e=>{t(e.target.result)},i.onerror=e=>{this.#u("PCache","remUser",e.target.error),s(e.target.error)},i.objectStore("user").delete(IDBKeyRange.only(e)),i.commit()}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}mapUsers(e,t){return this.#p("user",e,t)}getUser(e){return this.isReady()?new Promise((t,s)=>{const i=this.db.transaction(["user"]);i.oncomplete=e=>{const s=e.target.result;t({user:s.uid,public:s.public})},i.onerror=e=>{this.#u("PCache","getUser",e.target.error),s(e.target.error)},i.objectStore("user").get(e)}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}updSubscription(e,t,s){return this.isReady()?new Promise((i,n)=>{const r=this.db.transaction(["subscription"],"readwrite");r.oncomplete=e=>{i(e.target.result)},r.onerror=e=>{this.#u("PCache","updSubscription",e.target.error),n(e.target.error)},r.objectStore("subscription").get([e,t]).onsuccess=i=>{r.objectStore("subscription").put(k.#f(i.target.result,e,t,s)),r.commit()}}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}mapSubscriptions(e,t,s){return this.isReady()?new Promise((i,n)=>{const r=this.db.transaction(["subscription"]);r.onerror=e=>{this.#u("PCache","mapSubscriptions",e.target.error),n(e.target.error)},r.objectStore("subscription").getAll(IDBKeyRange.bound([e,"-"],[e,"~"])).onsuccess=e=>{t&&e.target.result.forEach(e=>{t.call(s,e)}),i(e.target.result)}}):this.disabled?Promise.resolve([]):Promise.reject(new Error("not initialized"))}addMessage(e){return this.isReady()?new Promise((t,s)=>{const i=this.db.transaction(["message"],"readwrite");i.onsuccess=e=>{t(e.target.result)},i.onerror=e=>{this.#u("PCache","addMessage",e.target.error),s(e.target.error)},i.objectStore("message").add(k.#_(null,e)),i.commit()}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}updMessageStatus(e,t,s){return this.isReady()?new Promise((i,n)=>{const r=this.db.transaction(["message"],"readwrite");r.onsuccess=e=>{i(e.target.result)},r.onerror=e=>{this.#u("PCache","updMessageStatus",e.target.error),n(e.target.error)};const a=r.objectStore("message").get(IDBKeyRange.only([e,t]));a.onsuccess=i=>{const n=a.result||i.target.result;n&&n._status!=s?(r.objectStore("message").put(k.#_(n,{topic:e,seq:t,_status:s})),r.commit()):r.commit()}}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}remMessages(e,t,s){return this.isReady()?new Promise((i,n)=>{t||s||(t=0,s=Number.MAX_SAFE_INTEGER);const r=s>0?IDBKeyRange.bound([e,t],[e,s],!1,!0):IDBKeyRange.only([e,t]),a=this.db.transaction(["message"],"readwrite");a.onsuccess=e=>{i(e.target.result)},a.onerror=e=>{this.#u("PCache","remMessages",e.target.error),n(e.target.error)},a.objectStore("message").delete(r),a.commit()}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}readMessages(e,t,s,i){if(t=t||{},!this.isReady())return this.disabled?Promise.resolve([]):Promise.reject(new Error("not initialized"));const n=this.db.transaction(["message"]);let r=[];return Array.isArray(t.ranges)?new Promise((a,o)=>{n.onerror=e=>{this.#u("PCache","readMessages",e.target.error),o(e.target.error)};let h=0;t.ranges.forEach(o=>{const c=o.hi?IDBKeyRange.bound([e,o.low],[e,o.hi],!1,!0):IDBKeyRange.only([e,o.low]);n.objectStore("message").getAll(c).onsuccess=e=>{const n=e.target.result;n&&(s&&s.call(i,n),Array.isArray(n)?r=r.concat(n):r.push(n)),h++,h==t.ranges.length&&a(r)}})}):new Promise((a,o)=>{const h=t.since>0?t.since:0,c=t.before>0?t.before:Number.MAX_SAFE_INTEGER,d=0|t.limit;n.onerror=e=>{this.#u("PCache","readMessages",e.target.error),o(e.target.error)};const l=IDBKeyRange.bound([e,h],[e,c],!1,!0);n.objectStore("message").openCursor(l,"prev").onsuccess=e=>{const t=e.target.result;t?(s&&s.call(i,t.value),r.push(t.value),d<=0||r.length{const r=this.db.transaction(["dellog"],"readwrite");r.onsuccess=e=>{i(e.target.result)},r.onerror=e=>{this.#u("PCache","addDelLog",e.target.error),n(e.target.error)},s.forEach(s=>r.objectStore("dellog").add({topic:e,clear:t,low:s.low,hi:s.hi||s.low+1})),r.commit()}):this.disabled?Promise.resolve():Promise.reject(new Error("not initialized"))}readDelLog(e,t){if(t=t||{},!this.isReady())return this.disabled?Promise.resolve([]):Promise.reject(new Error("not initialized"));const s=this.db.transaction(["dellog"]);let i=[];return Array.isArray(t.ranges)?new Promise((n,r)=>{s.onerror=e=>{this.#u("PCache","readDelLog",e.target.error),r(e.target.error)};let a=0;t.ranges.forEach(r=>{const o=r.hi||r.low+1,h=IDBKeyRange.bound([e,0,r.low],[e,o,Number.MAX_SAFE_INTEGER],!1,!0);s.objectStore("dellog").getAll(h).onsuccess=e=>{const s=e.target.result;s&&(Array.isArray(s)?i=i.concat(s.map(e=>({low:e.low,hi:e.hi}))):i.push({low:s.low,hi:s.hi})),a++,a==t.ranges.length&&n(i)}})}):new Promise((i,n)=>{const r=t.since>0?t.since:0,a=t.before>0?t.before:Number.MAX_SAFE_INTEGER,o=0|t.limit;s.onerror=e=>{this.#u("PCache","readDelLog",e.target.error),n(e.target.error)};let h=0;const c=[],d=IDBKeyRange.bound([e,0,r],[e,a,Number.MAX_SAFE_INTEGER],!1,!0);s.objectStore("dellog").openCursor(d,"prev").onsuccess=e=>{const t=e.target.result;t?(c.push({low:t.value.low,hi:t.value.hi}),h+=t.value.hi-t.value.low,o<=0||h{const i=this.db.transaction(["dellog"]);i.onerror=e=>{this.#u("PCache","maxDelId",e.target.error),s(e.target.error)},i.objectStore("dellog").index("topic_clear").openCursor(IDBKeyRange.bound([e,0],[e,Number.MAX_SAFE_INTEGER]),"prev").onsuccess=e=>{e.target.result&&t(e.target.result.value)}}):this.disabled?Promise.resolve(0):Promise.reject(new Error("not initialized"))}static#b=["created","updated","deleted","touched","read","recv","seq","clear","defacs","creds","public","trusted","private","_aux","_deleted"];static#m(e,t){k.#b.forEach(s=>{t.hasOwnProperty(s)&&(e[s]=t[s])}),Array.isArray(t.tags)&&(e._tags=t.tags),t.acs&&e.setAccessMode(t.acs),e.seq|=0,e.read|=0,e.unread=Math.max(0,e.seq-e.read)}static#g(e,t){const s=e||{name:t.name};return k.#b.forEach(e=>{t.hasOwnProperty(e)&&(s[e]=t[e])}),Array.isArray(t._tags)&&(s.tags=t._tags),t.acs&&(s.acs=t.getAccessMode().jsonHelper()),s}static#f(e,t,s,i){const n=e||{topic:t,uid:s};return["updated","mode","read","recv","clear","lastSeen","userAgent"].forEach(e=>{i.hasOwnProperty(e)&&(n[e]=i[e])}),n}static#_(e,t){const s=e||{};return["topic","seq","ts","_status","from","head","content"].forEach(e=>{t.hasOwnProperty(e)&&(s[e]=t[e])}),s}static setDatabaseProvider(e){I=e}}var C=s(767),q=s.n(C);let U,O,j,L;class V{constructor(e,t){this._tinode=e,this._version=t,this._apiKey=e._apiKey,this._authToken=e.getAuthToken(),this.xhr=[]}uploadWithBaseUrl(e,t,s,i,n,r){let a=`/v${this._version}/file/u/`;if(e){let t=e;if(t.endsWith("/")&&(t=t.slice(0,-1)),!t.startsWith("http://")&&!t.startsWith("https://"))throw new Error(`Invalid base URL '${e}'`);a=t+a}const o=this,h=new U;this.xhr.push(h),h.open("POST",a,!0),h.setRequestHeader("X-Tinode-APIKey",this._apiKey),this._authToken&&h.setRequestHeader("X-Tinode-Auth",`Token ${this._authToken.token}`);let c=null,d=null;const l=new Promise((e,t)=>{c=e,d=t});h.upload.onprogress=e=>{e.lengthComputable&&(i&&i(e.loaded/e.total),this.onProgress&&this.onProgress(e.loaded/e.total))},h.onload=function(){let e;try{e=JSON.parse(this.response,f)}catch(t){o._tinode.logger("ERROR: Invalid server response in LargeFileHelper",this.response),e={ctrl:{code:this.status,text:this.statusText}}}this.status>=200&&this.status<300?(c&&c(e.ctrl.params.url),n&&n(e.ctrl)):this.status>=400?(d&&d(new m(e.ctrl.text,e.ctrl.code)),r&&r(e.ctrl)):o._tinode.logger("ERROR: Unexpected server response status",this.status,this.response)},h.onerror=function(e){d&&d(e||new Error("failed")),r&&r(null)},h.onabort=function(e){d&&d(new Error("upload cancelled by user")),r&&r(null)};try{const e=new FormData;e.append("file",t),e.set("id",this._tinode.getNextUniqueId()),s&&e.set("topic",s),h.send(e)}catch(e){d&&d(e),r&&r(null)}return l}upload(e,t,s,i,n){const r=(this._tinode._secure?"https://":"http://")+this._tinode._host;return this.uploadWithBaseUrl(r,e,t,s,i,n)}download(e,t,s,i,n){if(!_(e))return void(n&&n(`The URL '${e}' must be relative, not absolute`));if(!this._authToken)return void(n&&n("Must authenticate first"));const r=this,a=new U;this.xhr.push(a),e=function(e){const t=new URL(e,window.location.origin);return t.searchParams.append("asatt","1"),t.toString().substring(window.location.origin.length)}(e),a.open("GET",e,!0),a.setRequestHeader("X-Tinode-APIKey",this._apiKey),a.setRequestHeader("X-Tinode-Auth","Token "+this._authToken.token),a.responseType="blob",a.onprogress=function(e){i&&i(e.loaded)};let o=null,h=null;const c=new Promise((e,t)=>{o=e,h=t});a.onload=function(){if(200==this.status){const e=document.createElement("a");e.href=window.URL.createObjectURL(new Blob([this.response],{type:s})),e.style.display="none",e.setAttribute("download",t),document.body.appendChild(e),e.click(),document.body.removeChild(e),window.URL.revokeObjectURL(e.href),o&&o()}else if(this.status>=400&&h){const e=new FileReader;e.onload=function(){try{const e=JSON.parse(this.result,f);h(new m(e.ctrl.text,e.ctrl.code))}catch(e){r._tinode.logger("ERROR: Invalid server response in LargeFileHelper",this.result),h(e)}},e.readAsText(this.response)}},a.onerror=function(e){h&&h(new Error("failed")),n&&n(e)},a.onabort=function(){h&&h(null)};try{a.send()}catch(e){h&&h(e),n&&n(e)}return c}cancel(){this.xhr.forEach(e=>{e.readyState<4&&e.abort()})}static setNetworkProvider(e){U=e}}class G{constructor(e){this.topic=e,this.what={}}#w(){return this.topic._deleted?void 0:this.topic.updated}#v(){return this.topic.isP2PType()?this.#w():this.topic._deleted?void 0:this.topic._lastSubsUpdate}withData(e,t,s){return this.what.data={since:e,before:t,limit:s},this}withLaterData(e){return this.withData(this.topic._maxSeq>0?this.topic._maxSeq+1:void 0,void 0,e)}withDataRanges(e,t){return this.what.data={ranges:M(e,this.topic._maxSeq),limit:t},this}withDataList(e){return this.withDataRanges(x(e))}withEarlierData(e){return this.withData(void 0,this.topic._minSeq>0?this.topic._minSeq:void 0,e)}withDesc(e){return this.what.desc={ims:e},this}withLaterDesc(){return this.withDesc(this.#w())}withSub(e,t,s){const i={ims:e,limit:t};return"me"==this.topic.getType()?i.topic=s:i.user=s,this.what.sub=i,this}withOneSub(e,t){return this.withSub(e,void 0,t)}withLaterOneSub(e){return this.withOneSub(this.topic._lastSubsUpdate,e)}withLaterSub(e){return this.withSub(this.#v(),e)}withTags(){return this.what.tags=!0,this}withCred(){return"me"==this.topic.getType()?this.what.cred=!0:this.topic._tinode.logger("ERROR: Invalid topic type for MetaGetBuilder:withCreds",this.topic.getType()),this}withAux(){return this.what.aux=!0,this}withDel(e,t){return(e||t)&&(this.what.del={since:e,limit:t}),this}withLaterDel(e){return this.withDel(this.topic._maxSeq>0?this.topic._maxDel+1:void 0,e)}extract(e){return this.what[e]}build(){const e=[];let t={};return["data","sub","desc","tags","cred","aux","del"].forEach(s=>{this.what.hasOwnProperty(s)&&(e.push(s),Object.getOwnPropertyNames(this.what[s]).length>0&&(t[s]=this.what[s]))}),e.length>0?t.what=e.join(" "):t=void 0,t}}class W{#y=void 0;#M=!1;buffer=[];constructor(e,t){this.#y=e||((e,t)=>e===t?0:e0)){o=!0;break}n=r-1}return o?{idx:r,exact:!0}:s?{idx:-1}:{idx:a<0?r+1:r}}#T(e,t){const s=this.#x(e,t,!1),i=s.exact&&this.#M?1:0;return t.splice(s.idx,i,e),t}getAt(e){return this.buffer[e]}getLast(e){return e?this.buffer.findLast(e):this.buffer[this.buffer.length-1]}put(){let e;e=1==arguments.length&&Array.isArray(arguments[0])?arguments[0]:arguments;for(let t in e)this.#T(e[t],this.buffer)}delAt(e){e|=0;let t=this.buffer.splice(e,1);if(t&&t.length>0)return t[0]}delRange(e,t){return this.buffer.splice(e,t-e)}length(){return this.buffer.length}reset(){this.buffer=[]}forEach(e,t,s,i){t=Math.max(0,0|t),s=Math.min(s||this.buffer.length,this.buffer.length);for(let n=t;nt?this.buffer[n-1]:void 0,ne.seq-t.seq,!0),this._attached=!1,this._lastSubsUpdate=new Date(0),this._new=!0,this._deleted=!1,this._delayedLeaveTimer=null,t&&(this.onData=t.onData,this.onMeta=t.onMeta,this.onPres=t.onPres,this.onInfo=t.onInfo,this.onMetaDesc=t.onMetaDesc,this.onMetaSub=t.onMetaSub,this.onSubsUpdated=t.onSubsUpdated,this.onTagsUpdated=t.onTagsUpdated,this.onCredsUpdated=t.onCredsUpdated,this.onAuxUpdated=t.onAuxUpdated,this.onDeleteTopic=t.onDeleteTopic,this.onAllMessagesReceived=t.onAllMessagesReceived)}static topicType(e){return{me:c,fnd:d,grp:l,new:l,nch:l,chn:l,usr:"p2p",sys:"sys",slf:"slf"}["string"==typeof e?e.substring(0,3):"xxx"]}static isMeTopicName(e){return z.topicType(e)==c}static isSelfTopicName(e){return"slf"==z.topicType(e)}static isGroupTopicName(e){return z.topicType(e)==l}static isP2PTopicName(e){return"p2p"==z.topicType(e)}static isCommTopicName(e){return z.isP2PTopicName(e)||z.isGroupTopicName(e)||z.isSelfTopicName(e)}static isNewGroupTopicName(e){return"string"==typeof e&&(e.substring(0,3)==o||e.substring(0,3)==h)}static isChannelTopicName(e){return"string"==typeof e&&("chn"==e.substring(0,3)||e.substring(0,3)==h)}static#S(e){return e.head&&e.head.replace}isSubscribed(){return this._attached}subscribe(e,t){return clearTimeout(this._delayedLeaveTimer),this._delayedLeaveTimer=null,this._attached?Promise.resolve(this):this._tinode.subscribe(this.name||o,e,t).then(e=>{if(e.code>=300)return e;if(this._attached=!0,this._deleted=!1,this.acs=e.params&&e.params.acs?e.params.acs:this.acs,this._new){if(delete this._new,this.name!=e.topic&&(this._cacheDelSelf(),this.name=e.topic),this._cachePutSelf(),this.created=e.ts,this.updated=e.ts,this.name!=c&&this.name!=d){const e=this._tinode.getMeTopic();e.onMetaSub&&e.onMetaSub(this),e.onSubsUpdated&&e.onSubsUpdated([this.name],1)}t&&t.desc&&(t.desc._noForwarding=!0,this._processMetaDesc(t.desc))}return e})}createMessage(e,t){return this._tinode.createMessage(this.name,e,t)}publish(e,t){return this.publishMessage(this.createMessage(e,t))}publishMessage(e){if(!this._attached)return Promise.reject(new Error("Cannot publish on inactive topic"));if(this._sending)return Promise.reject(new Error("The message is already being sent"));e._sending=!0,e._failed=!1;let t=null;return q().hasEntities(e.content)&&(t=[],q().entities(e.content,e=>{e&&(e.ref&&t.push(e.ref),e.preref&&t.push(e.preref))}),0==t.length&&(t=null)),this._tinode.publishMessage(e,t).then(t=>(e._sending=!1,e.ts=t.ts,this.swapMessageId(e,t.params.seq),this._maybeUpdateMessageVersionsCache(e),this._routeData(e),t)).catch(t=>{this._tinode.logger("WARNING: Message rejected by the server",t),e._sending=!1,e._failed=!0,this.onData&&this.onData()})}publishDraft(e,t){const s=e.seq||this._getQueuedSeqId();return e._noForwarding||(e._noForwarding=!0,e.seq=s,e.ts=new Date,e.from=this._tinode.getCurrentUserID(),e.noecho=!0,this._messages.put(e),this._tinode._db.addMessage(e),this.onData&&this.onData(e)),(t||Promise.resolve()).then(t=>e._cancelled?{code:300,text:"cancelled"}:this.publishMessage(e)).catch(t=>{throw this._tinode.logger("WARNING: Message draft rejected",t),e._sending=!1,e._failed=!0,e._fatal=t instanceof m&&t.code>=400&&t.code<500,this.onData&&this.onData(),t})}leave(e){return this._attached||e?this._tinode.leave(this.name,e).then(t=>(this._resetSub(),e&&this._gone(),t)):Promise.reject(new Error("Cannot leave inactive topic"))}leaveDelayed(e,t){clearTimeout(this._delayedLeaveTimer),this._delayedLeaveTimer=setTimeout(t=>{this._delayedLeaveTimer=null,this.leave(e)},t)}getMeta(e){return this._tinode.getMeta(this.name,e)}getMessagesPage(e,t,s,i,n){let r=t?this.startMetaQuery().withDataRanges(t,e):n?this.startMetaQuery().withData(s,void 0,e):this.startMetaQuery().withData(void 0,i,e);return this._loadMessages(this._tinode._db,r.extract("data")).then(a=>0==(t=this.msgHasMoreMessages(s,i,n)).length?Promise.resolve({topic:this.name,code:200,params:{count:a}}):(e-=a,r=this.startMetaQuery().withDataRanges(t,e),this.getMeta(r.build())))}getPinnedMessages(){const e=this.aux("pins");if(!Array.isArray(e))return Promise.resolve(0);const t=[];let s=e;return this._tinode._db.readMessages(this.name,{ranges:x(s)}).then(i=>(i.forEach(e=>{e&&(t.push(e.seq),this._messages.put(e),this._maybeUpdateMessageVersionsCache(e))}),t.length!t.includes(e)),this._tinode._db.readMessages(this.name,{ranges:x(s)})):null)).then(i=>(i&&s.forEach(e=>{i.find(t=>t.low<=e&&t.hi>e)&&t.push(e)}),t.length==e.length?Promise.resolve({topic:this.name,code:200,params:{count:t.length}}):(s=e.filter(e=>!t.includes(e)),this.getMeta(this.startMetaQuery().withDataList(s).build()))))}setMeta(e){return e.tags&&(e.tags=function(e){let t=[];if(Array.isArray(e)){for(let s=0,i=e.length;s1&&t.push(i))}t=t.sort().filter((e,t,s)=>!t||e!=s[t-1])}return 0==t.length&&t.push(p),t}(e.tags)),this._tinode.setMeta(this.name,e).then(t=>(t&&t.code>=300||(e.sub&&(e.sub.topic=this.name,t.params&&t.params.acs&&(e.sub.acs=t.params.acs,e.sub.updated=t.ts),e.sub.user||(e.sub.user=this._tinode.getCurrentUserID(),e.desc||(e.desc={})),e.sub._noForwarding=!0,this._processMetaSubs([e.sub])),e.desc&&(t.params&&t.params.acs&&(e.desc.acs=t.params.acs,e.desc.updated=t.ts),this._processMetaDesc(e.desc)),e.tags&&this._processMetaTags(e.tags),e.cred&&this._processMetaCreds([e.cred],!0),e.aux&&this._processMetaAux(e.aux)),t))}updateMode(e,t){const s=e?this.subscriber(e):null,i=s?s.acs.updateGiven(t).getGiven():this.getAccessMode().updateWant(t).getWant();return this.setMeta({sub:{user:e,mode:i}})}invite(e,t){return this.setMeta({sub:{user:e,mode:t}})}archive(e){return this.private&&!this.private.arch==!e?Promise.resolve(e):this.setMeta({desc:{private:{arch:!!e||p}}})}pinMessage(e,t){let s=this.aux("pins");Array.isArray(s)||(s=[]);let i=!1;return t?s.includes(e)||(i=!0,5==s.length&&s.shift(),s.push(e)):s.includes(e)&&(i=!0,s=s.filter(t=>t!=e),0==s.length&&(s=p)),i?this.setMeta({aux:{pins:s}}):Promise.resolve()}delMessages(e,t){if(!this._attached)return Promise.reject(new Error("Cannot delete messages in inactive topic"));const s=M(e,this._maxSeq);let i;return i=s.length>0?this._tinode.delMessages(this.name,s,t):Promise.resolve({params:{del:0}}),i.then(t=>(t.params.del>this._maxDel&&(this._maxDel=Math.max(t.params.del,this._maxDel),this.clear=Math.max(t.params.del,this.clear)),e.forEach(e=>{e.hi?this.flushMessageRange(e.low,e.hi):this.flushMessage(e.low),this._messages.put({seq:e.low,low:e.low,hi:e.hi,_deleted:!0})}),this._tinode._db.addDelLog(this.name,t.params.del,e),this.onData&&this.onData(),t))}delMessagesAll(e){return!this._maxSeq||this._maxSeq<=0?Promise.resolve():this.delMessages([{low:1,hi:this._maxSeq+1,_all:!0}],e)}delMessagesList(e,t){return this.delMessages(x(e),t)}delMessagesEdits(e,t){const s=[e];return this.messageVersions(e,e=>s.push(e.seq)),this.delMessagesList(s,t)}delTopic(e){return this._deleted?(this._gone(),Promise.resolve(null)):this._tinode.delTopic(this.name,e).then(e=>(this._deleted=!0,this._resetSub(),this._gone(),e))}delSubscription(e){return this._attached?this._tinode.delSubscription(this.name,e).then(t=>(delete this._users[e],this.onSubsUpdated&&this.onSubsUpdated(Object.keys(this._users)),t)):Promise.reject(new Error("Cannot delete subscription in inactive topic"))}note(e,t){if(!this._attached)return;const s=this._users[this._tinode.getCurrentUserID()];let i=!1;s?(!s[e]||s[e]0&&this.note("read",e)}noteKeyPress(){this._attached?this._tinode.noteKeyPress(this.name):this._tinode.logger("INFO: Cannot send notification in inactive topic")}noteRecording(e){this._attached?this._tinode.noteKeyPress(this.name,e?"kpa":"kpv"):this._tinode.logger("INFO: Cannot send notification in inactive topic")}videoCall(e,t,s){if(this._attached||["ringing","hang-up"].includes(e))return this._tinode.videoCall(this.name,t,e,s)}_updateMyReadRecv(e,t,s){let i,n=!1;switch(t|=0,this.seq=0|this.seq,this.read=0|this.read,this.recv=0|this.recv,e){case"recv":i=this.recv,this.recv=Math.max(this.recv,t),n=i!=this.recv;break;case"read":i=this.read,this.read=Math.max(this.read,t),n=i!=this.read;break;case"msg":i=this.seq,this.seq=Math.max(this.seq,t),(!this.touched||this.touchede.startsWith(g));if(e)return e.substring(6)}subscriber(e){return this._users[e]}messageVersions(e,t,s){if(!t)return;const i=this._messageVersions[e];i&&i.forEach(t,void 0,void 0,s)}messages(e,t,s,i){const n=e||this.onData;if(n){const e="number"==typeof t?this._messages.find({seq:t},!0):void 0,r="number"==typeof s?this._messages.find({seq:s},!0):void 0;if(-1!=e&&-1!=r){let t=[];this._messages.forEach((e,s,i,n)=>{if(z.#S(e))return;if(e._deleted)return;const r=this.latestMsgVersion(e.seq)||e;r._origTs||(r._origTs=r.ts,r._origSeq=r.seq,r.ts=e.ts,r.seq=e.seq),t.push({data:r,idx:n})},e,r,{}),t.forEach((e,s)=>{n.call(i,e.data,s>0?t[s-1].data:void 0,s=0)return this._messages.getAt(t)}latestMessage(){return this._messages.getLast(e=>!e._deleted)}latestMsgVersion(e){const t=this._messageVersions[e];return t?t.getLast():null}maxMsgSeq(){return this._maxSeq}minMsgSeq(){return this._minSeq}maxClearId(){return this._maxDel}messageCount(){return this._messages.length()}queuedMessages(e,t){if(!e)throw new Error("Callback must be provided");this.messages(e,u,void 0,t)}msgReceiptCount(e,t){let s=0;if(t>0){const i=this._tinode.getCurrentUserID();for(let n in this._users){const r=this._users[n];r.user!==i&&r[e]>=t&&s++}}return s}msgReadCount(e){return this.msgReceiptCount("read",e)}msgRecvCount(e){return this.msgReceiptCount("recv",e)}msgHasMoreMessages(e,t,s){const i=[];if(e>=t)return i;let n,r=0;return this._messages.forEach((a,o)=>{const h=o||{seq:0},c=h._deleted?h.hi:h.seq+1;n=a.seq>c?{low:c,hi:a.seq}:null,n&&(s?n.hi>=e:n.low=e:n.low=0)return this._tinode._db.remMessages(this.name,e),this._messages.delAt(t)}flushMessageRange(e,t){this._tinode._db.remMessages(this.name,e,t);for(let s=e;s=0?this._messages.delRange(s,this._messages.find({seq:t},!0)):[]}swapMessageId(e,t){const s=this._messages.find(e),i=this._messages.length();0<=s&&s=0){const s=this._messages.getAt(t),i=this.msgStatus(s);if(10==i||30==i||40==i)return this._tinode._db.remMessages(this.name,e),s._cancelled=!0,this._messages.delAt(t),this.onData&&this.onData(),!0}return!1}getType(){return z.topicType(this.name)}getAccessMode(){return this.acs}setAccessMode(e){return this.acs=new n(e)}getDefaultAccess(){return this.defacs}startMetaQuery(){return new G(this)}isArchived(){return this.private&&!!this.private.arch}isMeType(){return z.isMeTopicName(this.name)}isSelfType(){return z.isSelfTopicName(this.name)}isChannelType(){return z.isChannelTopicName(this.name)}isGroupType(){return z.isGroupTopicName(this.name)}isP2PType(){return z.isP2PTopicName(this.name)}isCommType(){return z.isCommTopicName(this.name)}msgStatus(e,t){let s=0;return this._tinode.isMe(e.from)?e._sending?s=20:e._fatal||e._cancelled?s=40:e._failed?s=30:e.seq>=u?s=10:this.msgReadCount(e.seq)>0?s=70:this.msgRecvCount(e.seq)>0?s=60:e.seq>0&&(s=50):s=80,t&&e._status!=s&&(e._status=s,this._tinode._db.updMessageStatus(this.name,e.seq,s)),s}_maybeUpdateMessageVersionsCache(e){if(!z.#S(e))return void(this._messageVersions[e.seq]&&(this._messageVersions[e.seq].filter(t=>t.from==e.from),this._messageVersions[e.seq].isEmpty()&&delete this._messageVersions[e.seq]));const t=parseInt(e.head.replace.split(":")[1]);if(t>e.seq)return;const s=this.findMessage(t);if(s&&s.from!=e.from)return;const i=this._messageVersions[t]||new W((e,t)=>e.seq-t.seq,!0);i.put(e),this._messageVersions[t]=i}_routeData(e){e.content&&(!this.touched||this.touchedthis._maxSeq&&(this._maxSeq=e.seq,this.msgStatus(e,!0),clearTimeout(this._recvNotificationTimer),this._recvNotificationTimer=setTimeout(e=>{this._recvNotificationTimer=null,this.noteRecv(this._maxSeq)},100)),(e.seq0&&this._processMetaSubs(e.sub),e.del&&this._processDelMessages(e.del.clear,e.del.delseq),e.tags&&this._processMetaTags(e.tags),e.cred&&this._processMetaCreds(e.cred),e.aux&&this._processMetaAux(e.aux),this.onMeta&&this.onMeta(e)}_routePres(e){let t,s;switch(e.what){case"del":this._processDelMessages(e.clear,e.delseq);break;case"on":case"off":t=this._users[e.src],t?t.online="on"==e.what:this._tinode.logger("WARNING: Presence update for an unknown user",this.name,e.src);break;case"term":this._resetSub();break;case"upd":e.src&&!this._tinode.isTopicCached(e.src)&&this.getMeta(this.startMetaQuery().withOneSub(void 0,e.src).build());break;case"aux":this.getMeta(this.startMetaQuery().withAux().build());break;case"acs":if(s=e.src||this._tinode.getCurrentUserID(),t=this._users[s],t)t.acs.updateAll(e.dacs),this._processMetaSubs([{user:s,updated:new Date,acs:t.acs}]);else{const i=(new n).updateAll(e.dacs);i&&i.mode!=n._NONE&&(t=this._cacheGetUser(s),t?t.acs=i:(t={user:s,acs:i},this.getMeta(this.startMetaQuery().withOneSub(void 0,s).build())),t.updated=new Date,this._processMetaSubs([t]))}break;default:this._tinode.logger("INFO: Ignored presence update",e.what)}this.onPres&&this.onPres(e)}_routeInfo(e){switch(e.what){case"recv":case"read":const t=this._users[e.from];t&&(t[e.what]=e.seq,t.recv{e.hi?(s+=e.hi-e.low,this.flushMessageRange(e.low,e.hi)):(s++,this.flushMessage(e.low)),this._messages.put({seq:e.low,low:e.low,hi:e.hi,_deleted:!0})}),this._tinode._db.addDelLog(this.name,e,t)),s>0&&this.onData&&this.onData()}_allMessagesReceived(e){this.onAllMessagesReceived&&this.onAllMessagesReceived(e)}_resetSub(){this._attached=!1}_gone(){this._messages.reset(),this._tinode._db.remMessages(this.name),this._users={},this.acs=new n(null),this.private=null,this.public=null,this.trusted=null,this._maxSeq=0,this._minSeq=0,this._attached=!1;const e=this._tinode.getMeTopic();e&&e._routePres({_noForwarding:!0,what:"gone",topic:c,src:this.name}),this.onDeleteTopic&&this.onDeleteTopic()}_updateCachedUser(e,t){let s=this._cacheGetUser(e);return s=w(s||{},t),this._cachePutUser(e,s),v(this._users,e,s)}_getQueuedSeqId(){return this._queuedSeqId++}_loadMessages(e,t){(t=t||{}).limit=t.limit||24;let s=0;return e.readMessages(this.name,t).then(e=>{e.forEach(e=>{e.seq>this._maxSeq&&(this._maxSeq=e.seq),(e.seqe.readDelLog(this.name,t)).then(e=>e.forEach(e=>{this._messages.put({seq:e.low,low:e.low,hi:e.hi,_deleted:!0})})).then(e=>s)}_updateReceived(e,t){this.touched=new Date,this.seq=0|e,t&&!this._tinode.isMe(t)||(this.read=this.read?Math.max(this.read,this.seq):this.seq,this.recv=this.recv?Math.max(this.read,this.recv):this.read),this.unread=this.seq-(0|this.read),this._tinode._db.updTopic(this)}}class B extends z{_contacts={};constructor(e){super(d,e)}_processMetaSubs(e){let t=Object.getOwnPropertyNames(this._contacts).length;this._contacts={};for(let s in e){let i=e[s];const n=i.topic?i.topic:i.user;i=v(this._contacts,n,i),t++,this.onMetaSub&&this.onMetaSub(i)}t>0&&this.onSubsUpdated&&this.onSubsUpdated(Object.keys(this._contacts))}publish(){return Promise.reject(new Error("Publishing to 'fnd' is not supported"))}setMeta(e){return Object.getPrototypeOf(B.prototype).setMeta.call(this,e).then(e=>{Object.keys(this._contacts).length>0&&(this._contacts={},this.onSubsUpdated&&this.onSubsUpdated([]))})}checkTagUniqueness(e,t){return new Promise((s,i)=>{this.subscribe().then(t=>this.setMeta({desc:{public:e}})).then(e=>this.getMeta(this.startMetaQuery().withTags().build())).then(e=>{e&&Array.isArray(e.tags)&&0!=e.tags.length||s(!0);const i=e.tags.filter(e=>e!==t);s(0==i.length)}).catch(e=>{i(e)})})}contacts(e,t){const s=e||this.onMetaSub;if(s)for(let e in this._contacts)s.call(t,this._contacts[e],e,this._contacts)}}class F extends z{onContactUpdate;constructor(e){super(c,e),e&&(this.onContactUpdate=e.onContactUpdate)}_processMetaDesc(e){const t=e.acs&&!e.acs.isPresencer()&&this.acs&&this.acs.isPresencer();w(this,e),this._tinode._db.updTopic(this),this._updateCachedUser(this._tinode._myUID,e),t&&this._tinode.mapTopics(e=>{e.online&&(e.online=!1,e.seen=Object.assign(e.seen||{},{when:new Date}),this._refreshContact("off",e))}),this.onMetaDesc&&this.onMetaDesc(this)}_processMetaSubs(e){let t=0;if(e.forEach(e=>{const s=e.topic;if(s==d||s==c)return;e.online=!!e.online;let i=null;if(e.deleted)i=e,this._tinode.cacheRemTopic(s),this._tinode._db.remTopic(s);else{void 0!==e.seq&&(e.seq=0|e.seq,e.recv=0|e.recv,e.read=0|e.read,e.unread=e.seq-e.read);const t=this._tinode.getTopic(s);t._new&&delete t._new,i=w(t,e),this._tinode._db.updTopic(i),z.isP2PTopicName(s)&&(this._cachePutUser(s,i),this._tinode._db.updUser(s,i.public)),!e._noForwarding&&t&&(e._noForwarding=!0,t._processMetaDesc(e))}t++,this.onMetaSub&&this.onMetaSub(i)}),this.onSubsUpdated&&t>0){const s=[];e.forEach(e=>{s.push(e.topic)}),this.onSubsUpdated(s,t)}}_processMetaCreds(e,t){1==e.length&&e[0]==p&&(e=[]),t?e.forEach(e=>{if(e.val){let t=this._credentials.findIndex(t=>t.meth==e.meth&&t.val==e.val);t<0?(e.done||(t=this._credentials.findIndex(t=>t.meth==e.meth&&!t.done),t>=0&&this._credentials.splice(t,1)),this._credentials.push(e)):this._credentials[t].done=e.done}else if(e.resp){const t=this._credentials.findIndex(t=>t.meth==e.meth&&!t.done);t>=0&&(this._credentials[t].done=!0)}}):this._credentials=e,this.onCredsUpdated&&this.onCredsUpdated(this._credentials)}_routePres(e){if("term"==e.what)return void this._resetSub();if("upd"==e.what&&e.src==c)return void this.getMeta(this.startMetaQuery().withDesc().build());const t=this._tinode.cacheGetTopic(e.src);if(t){switch(e.what){case"on":t.online=!0;break;case"off":t.online&&(t.online=!1,t.seen=Object.assign(t.seen||{},{when:new Date}));break;case"msg":t._updateReceived(e.seq,e.act);break;case"upd":this.getMeta(this.startMetaQuery().withLaterOneSub(e.src).build());break;case"acs":e.tgt||(t.acs?t.acs.updateAll(e.dacs):t.acs=(new n).updateAll(e.dacs),t.touched=new Date);break;case"ua":t.seen={when:new Date,ua:e.ua};break;case"recv":e.seq=0|e.seq,t.recv=t.recv?Math.max(t.recv,e.seq):e.seq;break;case"read":e.seq=0|e.seq,t.read=t.read?Math.max(t.read,e.seq):e.seq,t.recv=t.recv?Math.max(t.read,t.recv):t.recv,t.unread=t.seq-t.read;break;case"gone":this._tinode.cacheRemTopic(e.src),t._deleted?this._tinode._db.remTopic(e.src):(t._deleted=!0,t._attached=!1,this._tinode._db.markTopicAsDeleted(e.src,!0));break;case"del":break;default:this._tinode.logger("INFO: Unsupported presence update in 'me'",e.what)}this._refreshContact(e.what,t)}else{if("acs"==e.what){const t=new n(e.dacs);if(!t||t.mode==n._INVALID)return void this._tinode.logger("ERROR: Invalid access mode update",e.src,e.dacs);if(t.mode==n._NONE)return void this._tinode.logger("WARNING: Removing non-existent subscription",e.src,e.dacs);{this.getMeta(this.startMetaQuery().withOneSub(void 0,e.src).build());const s=this._tinode.getTopic(e.src);s.topic=e.src,s.online=!1,s.acs=t,this._tinode._db.updTopic(s)}}else if("tags"==e.what)this.getMeta(this.startMetaQuery().withTags().build());else if("msg"==e.what){this.getMeta(this.startMetaQuery().withOneSub(void 0,e.src).build());const t=this._tinode.getTopic(e.src);t._deleted=!1,this._tinode._db.updTopic(t)}this._refreshContact(e.what,t)}this.onPres&&this.onPres(e)}_refreshContact(e,t){this.onContactUpdate&&this.onContactUpdate(e,t)}publish(){return Promise.reject(new Error("Publishing to 'me' is not supported"))}delCredential(e,t){return this._attached?this._tinode.delCredential(e,t).then(s=>{const i=this._credentials.findIndex(s=>s.meth==e&&s.val==t);return i>-1&&this._credentials.splice(i,1),this.onCredsUpdated&&this.onCredsUpdated(this._credentials),s}):Promise.reject(new Error("Cannot delete credential in inactive 'me' topic"))}contacts(e,t,s){this._tinode.mapTopics((i,n)=>{!i.isCommType()||t&&!t(i)||e.call(s,i,n)})}getContact(e){return this._tinode.cacheGetTopic(e)}getAccessMode(e){if(e){const t=this._tinode.cacheGetTopic(e);return t?t.acs:null}return this.acs}isArchived(e){const t=this._tinode.cacheGetTopic(e);return t&&t.private&&!!t.private.arch}getCredentials(){return this._credentials}}function K(e){return btoa(encodeURIComponent(e).replace(/%([0-9A-F]{2})/g,function(e,t){return String.fromCharCode("0x"+t)}))}function H(e,t){return"string"==typeof t&&t.length>128?"<"+t.length+", bytes: "+t.substring(0,12)+"..."+t.substring(t.length-12)+">":function(e,t){if(t instanceof Date)t=function(e){if(!b(e))return;const t=function(e,t){return"0".repeat((t=t||2)-(""+e).length)+e},s=e.getUTCMilliseconds();return e.getUTCFullYear()+"-"+t(e.getUTCMonth()+1)+"-"+t(e.getUTCDate())+"T"+t(e.getUTCHours())+":"+t(e.getUTCMinutes())+":"+t(e.getUTCSeconds())+(s?"."+t(s,3):"")+"Z"}(t);else if(t instanceof n)t=t.jsonHelper();else if(null==t||!1===t||Array.isArray(t)&&0==t.length||"object"==typeof t&&0==Object.keys(t).length)return;return t}(0,t)}"undefined"!=typeof WebSocket&&(O=WebSocket),"undefined"!=typeof XMLHttpRequest&&(j=XMLHttpRequest),"undefined"!=typeof indexedDB&&(L=indexedDB),function(){const e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";"undefined"==typeof btoa&&(s.g.btoa=function(t=""){let s=t,i="";for(let t,n=0,r=0,a=e;s.charAt(0|r)||(a="=",r%1);i+=a.charAt(63&n>>8-r%1*8)){if(t=s.charCodeAt(r+=3/4),t>255)throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");n=n<<8|t}return i}),"undefined"==typeof atob&&(s.g.atob=function(t=""){let s=t.replace(/=+$/,""),i="";if(s.length%4==1)throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");for(let t,n=0,r=0,a=0;t=s.charAt(a++);~t&&(r=n%4?64*r+t:t,n++%4)?i+=String.fromCharCode(255&r>>(-2*n&6)):0)t=e.indexOf(t);return i}),"undefined"==typeof window&&(s.g.window={WebSocket:O,XMLHttpRequest:j,indexedDB:L,URL:{createObjectURL:function(){throw new Error("Unable to use URL.createObjectURL in a non-browser application")}}}),N.setNetworkProviders(O,j),V.setNetworkProvider(j),k.setDatabaseProvider(L)}();class Q{_host;_secure;_appName;_apiKey;_browser="";_platform;_hwos="undefined";_humanLanguage="xx";_loggingEnabled=!1;_trimLongStrings=!1;_myUID=null;_authenticated=!1;_login=null;_authToken=null;_inPacketCount=0;_messageId=Math.floor(65535*Math.random()+65535);_serverInfo=null;_deviceToken=null;_pendingPromises={};_expirePromises=null;_connection=null;_persist=!1;_db=null;_cache={};constructor(e,t){if(this._host=e.host,this._secure=e.secure,this._appName=e.appName||"Undefined",this._apiKey=e.apiKey,this._platform=e.platform||"web","undefined"!=typeof navigator&&(this._browser=function(e,t){e=e||"";let s,i="";/reactnative/i.test(t)&&(i="ReactNative; ");let n=(e=e.replace(" (KHTML, like Gecko)","")).match(/(AppleWebKit\/[.\d]+)/i);if(n){const t=["edg","chrome","safari","mobile","version"];let i,r=e.substr(n.index+n[0].length).split(" "),a=[];for(let e=0;es[1].toLowerCase().startsWith(e))]),"Version"==s[1]&&(i=s[2]))}a.sort((e,t)=>e[2]-t[2]),a.length>0?(a[0][0].toLowerCase().startsWith("edg")?a[0][0]="Edge":"OPR"==a[0][0]?a[0][0]="Opera":"Safari"==a[0][0]&&i&&(a[0][1]=i),s=a[0][0]+"/"+a[0][1]):s=n[1]}else/firefox/i.test(e)?(n=/Firefox\/([.\d]+)/g.exec(e),s=n?"Firefox/"+n[1]:"Firefox/?"):(n=/([\w.]+)\/([.\d]+)/.exec(e),n?s=n[1]+"/"+n[2]:(n=e.split(" "),s=n[0]));if(n=s.split("/"),n.length>1){const e=n[1].split("."),t=e[1]?"."+e[1].substr(0,2):"";s=`${n[0]}/${e[0]}${t}`}return i+s}(navigator.userAgent,navigator.product),this._hwos=navigator.platform,this._humanLanguage=navigator.language||"en-US"),N.logger=this.logger,q().logger=this.logger,"lp"!=e.transport&&"ws"!=e.transport&&(e.transport=function(){if("object"==typeof window){if(window.WebSocket)return"ws";if(window.XMLHttpRequest)return"lp"}return null}()),this._connection=new N(e,"0",!0),this._connection.onMessage=e=>{this.#P(e)},this._connection.onOpen=e=>this.#A(),this._connection.onDisconnect=(e,t)=>this.#D(e,t),this._connection.onAutoreconnectIteration=(e,t)=>{this.onAutoreconnectIteration&&this.onAutoreconnectIteration(e,t)},this._persist=e.persist,this._db=new k(this.logger,this.logger),this._persist){const e=[];this._db.initDatabase().then(t=>this._db.mapTopics(t=>{let s=this.#E("topic",t.name);s||(s=t.name==c?new F:t.name==d?new B:new z(t.name),this._db.deserializeTopic(s,t),this.#N(s),s._cachePutSelf(),this._db.maxDelId(s.name).then(e=>{s._maxDel=Math.max(s._maxDel,e||0)}),delete s._new,e.push(s._loadMessages(this._db)))})).then(e=>this._db.mapUsers(e=>{this.#R("user",e.uid,w({},e.public))})).then(t=>Promise.all(e)).then(e=>{t&&t(),this.logger("Persistent cache initialized.")}).catch(e=>{t&&t(e),this.logger("Failed to initialize persistent cache:",e)})}else this._db.deleteDatabase().then(e=>{t&&t()})}logger(e,...t){if(this._loggingEnabled){const s=new Date,i=("0"+s.getUTCHours()).slice(-2)+":"+("0"+s.getUTCMinutes()).slice(-2)+":"+("0"+s.getUTCSeconds()).slice(-2)+"."+("00"+s.getUTCMilliseconds()).slice(-3);console.log("["+i+"]",e,t.join(" "))}}#I(e){let t=null;return e&&(t=new Promise((t,s)=>{this._pendingPromises[e]={resolve:t,reject:s,ts:new Date}})),t}#k(e,t,s,i){const n=this._pendingPromises[e];n&&(delete this._pendingPromises[e],t>=200&&t<400?n.resolve&&n.resolve(s):n.reject&&n.reject(new m(i,t)))}#C(e,t){let s;t&&(s=this.#I(t)),e=y(e);let i=JSON.stringify(e);this.logger("out: "+(this._trimLongStrings?JSON.stringify(e,H):i));try{this._connection.sendText(i)}catch(e){if(!t)throw e;this.#k(t,N.NETWORK_ERROR,null,e.message)}return s}#P(e){if(!e)return;if(this._inPacketCount++,this.onRawMessage&&this.onRawMessage(e),"0"===e)return void(this.onNetworkProbe&&this.onNetworkProbe());let t=JSON.parse(e,f);t?(this.logger("in: "+(this._trimLongStrings?JSON.stringify(t,H):e)),this.onMessage&&this.onMessage(t),t.ctrl?(this.onCtrlMessage&&this.onCtrlMessage(t.ctrl),t.ctrl.id&&this.#k(t.ctrl.id,t.ctrl.code,t.ctrl,t.ctrl.text),setTimeout(e=>{if(205==t.ctrl.code&&"evicted"==t.ctrl.text){const e=this.#E("topic",t.ctrl.topic);e&&(e._resetSub(),t.ctrl.params&&t.ctrl.params.unsub&&e._gone())}else if(t.ctrl.code<300&&t.ctrl.params)if("data"==t.ctrl.params.what){const e=this.#E("topic",t.ctrl.topic);e&&e._allMessagesReceived(t.ctrl.params.count)}else if("sub"==t.ctrl.params.what){const e=this.#E("topic",t.ctrl.topic);e&&e._processMetaSubs([])}},0)):setTimeout(e=>{if(t.meta){const e=this.#E("topic",t.meta.topic);e&&e._routeMeta(t.meta),t.meta.id&&this.#k(t.meta.id,200,t.meta,"META"),this.onMetaMessage&&this.onMetaMessage(t.meta)}else if(t.data){const e=this.#E("topic",t.data.topic);e&&e._routeData(t.data),this.onDataMessage&&this.onDataMessage(t.data)}else if(t.pres){const e=this.#E("topic",t.pres.topic);e&&e._routePres(t.pres),this.onPresMessage&&this.onPresMessage(t.pres)}else if(t.info){const e=this.#E("topic",t.info.topic);e&&e._routeInfo(t.info),this.onInfoMessage&&this.onInfoMessage(t.info)}else this.logger("ERROR: Unknown packet received.")},0)):(this.logger("in: "+e),this.logger("ERROR: failed to parse data"))}#A(){this._expirePromises||(this._expirePromises=setInterval(e=>{const t=new m("timeout",504),s=new Date((new Date).getTime()-5e3);for(let e in this._pendingPromises){let i=this._pendingPromises[e];i&&i.ts{e._resetSub()});for(let t in this._pendingPromises){const s=this._pendingPromises[t];s&&s.reject&&s.reject(e)}this._pendingPromises={},this.onDisconnect&&this.onDisconnect(e)}#U(){return this._appName+" ("+(this._browser?this._browser+"; ":"")+this._hwos+"); "+a}#O(e,t){switch(e){case"hi":return{hi:{id:this.getNextUniqueId(),ver:r,ua:this.#U(),dev:this._deviceToken,lang:this._humanLanguage,platf:this._platform}};case"acc":return{acc:{id:this.getNextUniqueId(),user:null,scheme:null,secret:null,tmpscheme:null,tmpsecret:null,login:!1,tags:null,desc:{},cred:{}}};case"login":return{login:{id:this.getNextUniqueId(),scheme:null,secret:null}};case"sub":return{sub:{id:this.getNextUniqueId(),topic:t,set:{},get:{}}};case"leave":return{leave:{id:this.getNextUniqueId(),topic:t,unsub:!1}};case"pub":return{pub:{id:this.getNextUniqueId(),topic:t,noecho:!1,head:null,content:{}}};case"get":return{get:{id:this.getNextUniqueId(),topic:t,what:null,desc:{},sub:{},data:{}}};case"set":return{set:{id:this.getNextUniqueId(),topic:t,desc:{},sub:{},tags:[],aux:{}}};case"del":return{del:{id:this.getNextUniqueId(),topic:t,what:null,delseq:null,user:null,hard:!1}};case"note":return{note:{topic:t,what:null,seq:void 0}};default:throw new Error(`Unknown packet type requested: ${e}`)}}#R(e,t,s){this._cache[e+":"+t]=s}#E(e,t){return this._cache[e+":"+t]}#j(e,t){delete this._cache[e+":"+t]}#q(e,t,s){const i=e?e+":":void 0;for(let e in this._cache)if((!i||0==e.indexOf(i))&&t.call(s,this._cache[e],e))break}#N(e){e._tinode=this,e._cacheGetUser=e=>{const t=this.#E("user",e);if(t)return{user:e,public:w({},t)}},e._cachePutUser=(e,t)=>{this.#R("user",e,w({},t.public))},e._cacheDelUser=e=>{this.#j("user",e)},e._cachePutSelf=t=>{this.#R("topic",e.name,e)},e._cacheDelSelf=t=>{this.#j("topic",e.name)}}#L(e){return e.params&&e.params.user?(this._myUID=e.params.user,this._authenticated=e&&e.code>=200&&e.code<300,e.params&&e.params.token&&e.params.expires?this._authToken={token:e.params.token,expires:e.params.expires}:this._authToken=null,this.onLogin&&this.onLogin(e.code,e.text),e):e}static credential(e,t,s,i){return"object"==typeof e&&({val:t,params:s,resp:i,meth:e}=e),e&&(t||i)?[{meth:e,val:t,resp:i,params:s}]:null}static topicType(e){return z.topicType(e)}static isMeTopicName(e){return z.isMeTopicName(e)}static isSelfTopicName(e){return z.isSelfTopicName(e)}static isGroupTopicName(e){return z.isGroupTopicName(e)}static isP2PTopicName(e){return z.isP2PTopicName(e)}static isCommTopicName(e){return z.isCommTopicName(e)}static isNewGroupTopicName(e){return z.isNewGroupTopicName(e)}static isChannelTopicName(e){return z.isChannelTopicName(e)}static getVersion(){return r}static setNetworkProviders(e,t){O=e,j=t,N.setNetworkProviders(O,j),V.setNetworkProvider(j)}static setDatabaseProvider(e){L=e,k.setDatabaseProvider(L)}static getLibrary(){return a}static isNullValue(e){return e===p}static isServerAssignedSeq(e){return e>0&&e3&&e.length<24&&/^[a-z0-9][a-z0-9_\-]{3,23}$/i.test(e)}static tagSplit(e){if(!e)return null;const t=(e=e.trim()).indexOf(":");if(t<=0)return null;const s=e.substring(t+1);return s?{prefix:e.substring(0,t),value:s}:null}static setUniqueTag(e,t){if(!e||0==e.length)return[t];const s=Q.tagSplit(t);return s?((e=e.filter(e=>e&&!e.startsWith(s.prefix))).push(t),e):e}static clearTagPrefix(e,t){return e&&0!=e.length?e.filter(e=>e&&!e.startsWith(t)):[]}static tagByPrefix(e,t){if(e)return e.find(e=>e&&e.startsWith(t))}getNextUniqueId(){return 0!=this._messageId?""+this._messageId++:void 0}connect(e){return this._connection.connect(e)}reconnect(e){this._connection.reconnect(e)}disconnect(){this._connection.disconnect()}clearStorage(){return this._db.isReady()?this._db.deleteDatabase():Promise.resolve()}initStorage(){return this._db.isReady()?Promise.resolve():this._db.initDatabase()}networkProbe(){this._connection.probe()}isConnected(){return this._connection.isConnected()}isAuthenticated(){return this._authenticated}authorizeURL(e){if("string"!=typeof e)return e;if(_(e)){const t="scheme://host/",s=new URL(e,t);this._apiKey&&s.searchParams.append("apikey",this._apiKey),this._authToken&&this._authToken.token&&(s.searchParams.append("auth","token"),s.searchParams.append("secret",this._authToken.token)),e=s.toString().substring(t.length-1)}return e}account(e,t,s,i,n){const r=this.#O("acc");return r.acc.user=e,r.acc.scheme=t,r.acc.secret=s,r.acc.login=i,n&&(r.acc.desc.defacs=n.defacs,r.acc.desc.public=n.public,r.acc.desc.private=n.private,r.acc.desc.trusted=n.trusted,r.acc.tags=n.tags,r.acc.cred=n.cred,r.acc.tmpscheme=n.scheme,r.acc.tmpsecret=n.secret,Array.isArray(n.attachments)&&n.attachments.length>0&&(r.extra={attachments:n.attachments.filter(e=>_(e))})),this.#C(r,r.acc.id)}createAccount(e,t,s,i){let n=this.account("new",e,t,s,i);return s&&(n=n.then(e=>this.#L(e))),n}createAccountBasic(e,t,s){return e=e||"",t=t||"",this.createAccount("basic",K(e+":"+t),!0,s)}updateAccountBasic(e,t,s,i){return t=t||"",s=s||"",this.account(e,"basic",K(t+":"+s),!1,i)}hello(){const e=this.#O("hi");return this.#C(e,e.hi.id).then(e=>(this._connection.backoffReset(),e.params&&(this._serverInfo=e.params),this.onConnect&&this.onConnect(),e)).catch(e=>{this._connection.reconnect(!0),this.onDisconnect&&this.onDisconnect(e)})}setDeviceToken(e){let t=!1;return(e=e||null)!=this._deviceToken&&(this._deviceToken=e,this.isConnected()&&this.isAuthenticated()&&(this.#C({hi:{dev:e||Q.DEL_CHAR}}),t=!0)),t}login(e,t,s){const i=this.#O("login");return i.login.scheme=e,i.login.secret=t,i.login.cred=s,this.#C(i,i.login.id).then(e=>this.#L(e))}loginBasic(e,t,s){return this.login("basic",K(e+":"+t),s).then(t=>(this._login=e,t))}loginToken(e,t){return this.login("token",e,t)}requestResetAuthSecret(e,t,s){return this.login("reset",K(e+":"+t+":"+s))}getAuthToken(){return this._authToken&&this._authToken.expires.getTime()>Date.now()?this._authToken:(this._authToken=null,null)}setAuthToken(e){this._authToken=e}subscribe(e,t,s){const i=this.#O("sub",e);if(e||(e=o),i.sub.get=t,s){if(s.sub&&(i.sub.set.sub=s.sub),s.desc){const t=s.desc;Q.isNewGroupTopicName(e)?i.sub.set.desc=t:Q.isP2PTopicName(e)&&t.defacs&&(i.sub.set.desc={defacs:t.defacs})}Array.isArray(s.attachments)&&s.attachments.length>0&&(i.extra={attachments:s.attachments.filter(e=>_(e))}),s.tags&&(i.sub.set.tags=s.tags),s.aux&&(i.sub.set.aux=s.aux)}return this.#C(i,i.sub.id)}leave(e,t){const s=this.#O("leave",e);return s.leave.unsub=t,this.#C(s,s.leave.id)}createMessage(e,t,s){const i=this.#O("pub",e);let n="string"==typeof t?q().parse(t):t;return n&&!q().isPlainText(n)&&(i.pub.head={mime:q().getContentType()},t=n),i.pub.noecho=s,i.pub.content=t,i.pub}publish(e,t,s){return this.publishMessage(this.createMessage(e,t,s))}publishMessage(e,t){(e=Object.assign({},e)).seq=void 0,e.from=void 0,e.ts=void 0;const s={pub:e};return t&&(s.extra={attachments:t.filter(e=>_(e))}),this.#C(s,e.id)}oobNotification(e){switch(this.logger("oob: "+(this._trimLongStrings?JSON.stringify(e,H):e)),e.what){case"msg":if(!e.seq||e.seq<1||!e.topic)break;if(!this.isConnected())break;const t=this.#E("topic",e.topic);if(!t)break;if(t.isSubscribed())break;t.maxMsgSeq(){this.logger("Failed to get the name of a new sender",e)}),t.subscribe(null).then(e=>t.getMeta(new G(t).withLaterData(24).withLaterDel(24).build())).then(e=>{t.leaveDelayed(!1,1e3)}).catch(e=>{this.logger("On push data fetch failed",e)}).finally(e=>{this.getMeTopic()._refreshContact("msg",t)}));break;case"read":this.getMeTopic()._routePres({what:"read",seq:e.seq});break;case"sub":if(!this.isMe(e.xfrom))break;const s={given:e.modeGiven,want:e.modeWant},i=new n(s),r=i.mode&&i.mode!=n._NONE?{what:"acs",src:e.topic,dacs:s}:{what:"gone",src:e.topic};this.getMeTopic()._routePres(r);break;default:this.logger("Unknown push type ignored",e.what)}}getMeta(e,t){const s=this.#O("get",e);return s.get=w(s.get,t),this.#C(s,s.get.id)}setMeta(e,t){const s=this.#O("set",e),i=[];return t&&(["desc","sub","tags","cred","aux"].forEach(e=>{t.hasOwnProperty(e)&&(i.push(e),s.set[e]=t[e])}),Array.isArray(t.attachments)&&t.attachments.length>0&&(s.extra={attachments:t.attachments.filter(e=>_(e))})),0==i.length?Promise.reject(new Error("Invalid {set} parameters")):this.#C(s,s.set.id)}delMessages(e,t,s){const i=this.#O("del",e);return i.del.what="msg",i.del.delseq=t,i.del.hard=s,this.#C(i,i.del.id)}delTopic(e,t){const s=this.#O("del",e);return s.del.what="topic",s.del.hard=t,this.#C(s,s.del.id)}delSubscription(e,t){const s=this.#O("del",e);return s.del.what="sub",s.del.user=t,this.#C(s,s.del.id)}delCredential(e,t){const s=this.#O("del",c);return s.del.what="cred",s.del.cred={meth:e,val:t},this.#C(s,s.del.id)}delCurrentUser(e){const t=this.#O("del",null);return t.del.what="user",t.del.hard=e,this.#C(t,t.del.id).then(e=>{this._myUID=null})}note(e,t,s){if(s<=0||s>=u)throw new Error(`Invalid message id ${s}`);const i=this.#O("note",e);i.note.what=t,i.note.seq=s,this.#C(i)}noteKeyPress(e,t){const s=this.#O("note",e);s.note.what=t||"kp",this.#C(s)}videoCall(e,t,s,i){const n=this.#O("note",e);n.note.seq=t,n.note.what="call",n.note.event=s,n.note.payload=i,this.#C(n,n.note.id)}getTopic(e){let t=this.#E("topic",e);return!t&&e&&(t=e==c?new F:e==d?new B:new z(e),this.#N(t),t._cachePutSelf()),t}cacheGetTopic(e){return this.#E("topic",e)}cacheRemTopic(e){this.#j("topic",e)}mapTopics(e,t){this.#q("topic",e,t)}isTopicCached(e){return!!this.#E("topic",e)}newGroupTopicName(e){return(e?h:o)+this.getNextUniqueId()}getMeTopic(){return this.getTopic(c)}getFndTopic(){return this.getTopic(d)}getLargeFileHelper(){return new V(this,"0")}getCurrentUserID(){return this._myUID}isMe(e){return this._myUID===e}getCurrentLogin(){return this._login}getServerInfo(){return this._serverInfo}report(e,t){return this.publish("sys",q().attachJSON(null,{action:e,target:t}))}getServerParam(e,t){return this._serverInfo&&this._serverInfo[e]||t}enableLogging(e,t){this._loggingEnabled=e,this._trimLongStrings=e&&t}setHumanLanguage(e){e&&(this._humanLanguage=e)}isTopicOnline(e){const t=this.#E("topic",e);return t&&t.online}getTopicAccessMode(e){const t=this.#E("topic",e);return t?t.acs:null}wantAkn(e){this._messageId=e?Math.floor(16777215*Math.random()+16777215):0}onWebsocketOpen=void 0;onConnect=void 0;onDisconnect=void 0;onLogin=void 0;onCtrlMessage=void 0;onDataMessage=void 0;onPresMessage=void 0;onMessage=void 0;onRawMessage=void 0;onNetworkProbe=void 0;onAutoreconnectIteration=void 0}return Q.MESSAGE_STATUS_NONE=0,Q.MESSAGE_STATUS_QUEUED=10,Q.MESSAGE_STATUS_SENDING=20,Q.MESSAGE_STATUS_FAILED=30,Q.MESSAGE_STATUS_FATAL=40,Q.MESSAGE_STATUS_SENT=50,Q.MESSAGE_STATUS_RECEIVED=60,Q.MESSAGE_STATUS_READ=70,Q.MESSAGE_STATUS_TO_ME=80,Q.DEL_CHAR=p,Q.MAX_MESSAGE_SIZE="maxMessageSize",Q.MAX_SUBSCRIBER_COUNT="maxSubscriberCount",Q.MIN_TAG_LENGTH="minTagLength",Q.MAX_TAG_LENGTH="maxTagLength",Q.MAX_TAG_COUNT="maxTagCount",Q.MAX_FILE_UPLOAD_SIZE="maxFileUploadSize",Q.REQ_CRED_VALIDATORS="reqCred",Q.MSG_DELETE_AGE="msgDelAge",Q.URI_TOPIC_ID_PREFIX="tinode:topic/",Q.TAG_ALIAS=g,Q.TAG_EMAIL="email:",Q.TAG_PHONE="tel:",i})());
\ No newline at end of file
diff --git a/umd/tinode.prod.js.map b/umd/tinode.prod.js.map
index 3d3bf7d6..b88d8dc1 100644
--- a/umd/tinode.prod.js.map
+++ b/umd/tinode.prod.js.map
@@ -1 +1 @@
-{"version":3,"file":"tinode.prod.js","mappings":"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","sources":["webpack://tinode/webpack/universalModuleDefinition","webpack://tinode/./src/drafty.js","webpack://tinode/webpack/bootstrap","webpack://tinode/webpack/runtime/compat get default export","webpack://tinode/webpack/runtime/define property getters","webpack://tinode/webpack/runtime/global","webpack://tinode/webpack/runtime/hasOwnProperty shorthand","webpack://tinode/webpack/runtime/make namespace object","webpack://tinode/./src/access-mode.js","webpack://tinode/./version.js","webpack://tinode/./src/config.js","webpack://tinode/./src/comm-error.js","webpack://tinode/./src/utils.js","webpack://tinode/./src/connection.js","webpack://tinode/./src/db.js","webpack://tinode/./src/large-file.js","webpack://tinode/./src/tinode.js","webpack://tinode/./src/meta-builder.js","webpack://tinode/./src/cbuffer.js","webpack://tinode/./src/topic.js","webpack://tinode/./src/fnd-topic.js","webpack://tinode/./src/me-topic.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"tinode\"] = factory();\n\telse\n\t\troot[\"tinode\"] = factory();\n})(this, () => {\nreturn ","/**\n * @copyright 2015-2024 Tinode LLC.\n * @summary Minimally rich text representation and formatting for Tinode.\n * @license Apache 2.0\n *\n * @file Basic parser and formatter for very simple text markup. Mostly targeted at\n * mobile use cases similar to Telegram, WhatsApp, and FB Messenger.\n *\n * Supports conversion of user keyboard input to formatted text:
\n * \n * *abc* → abc \n * _abc_ → abc \n * ~abc~ → abc \n * `abc` → abc \n * \n * Also supports forms and buttons.\n *\n * Nested formatting is supported, e.g. *abc _def_* -> abc def \n * URLs, @mentions, and #hashtags are extracted and converted into links.\n * Forms and buttons can be added procedurally.\n * JSON data representation is inspired by Draft.js raw formatting.\n *\n *\n * @example\n * Text:\n * \n * this is *bold*, `code` and _italic_, ~strike~\n * combined *bold and _italic_*\n * an url: https://www.example.com/abc#fragment and another _www.tinode.co_\n * this is a @mention and a #hashtag in a string\n * second #hashtag\n * \n *\n * Sample JSON representation of the text above:\n * {\n * \"txt\": \"this is bold, code and italic, strike combined bold and italic an url: https://www.example.com/abc#fragment \" +\n * \"and another www.tinode.co this is a @mention and a #hashtag in a string second #hashtag\",\n * \"fmt\": [\n * { \"at\":8, \"len\":4,\"tp\":\"ST\" },{ \"at\":14, \"len\":4, \"tp\":\"CO\" },{ \"at\":23, \"len\":6, \"tp\":\"EM\"},\n * { \"at\":31, \"len\":6, \"tp\":\"DL\" },{ \"tp\":\"BR\", \"len\":1, \"at\":37 },{ \"at\":56, \"len\":6, \"tp\":\"EM\" },\n * { \"at\":47, \"len\":15, \"tp\":\"ST\" },{ \"tp\":\"BR\", \"len\":1, \"at\":62 },{ \"at\":120, \"len\":13, \"tp\":\"EM\" },\n * { \"at\":71, \"len\":36, \"key\":0 },{ \"at\":120, \"len\":13, \"key\":1 },{ \"tp\":\"BR\", \"len\":1, \"at\":133 },\n * { \"at\":144, \"len\":8, \"key\":2 },{ \"at\":159, \"len\":8, \"key\":3 },{ \"tp\":\"BR\", \"len\":1, \"at\":179 },\n * { \"at\":187, \"len\":8, \"key\":3 },{ \"tp\":\"BR\", \"len\":1, \"at\":195 }\n * ],\n * \"ent\": [\n * { \"tp\":\"LN\", \"data\":{ \"url\":\"https://www.example.com/abc#fragment\" } },\n * { \"tp\":\"LN\", \"data\":{ \"url\":\"http://www.tinode.co\" } },\n * { \"tp\":\"MN\", \"data\":{ \"val\":\"mention\" } },\n * { \"tp\":\"HT\", \"data\":{ \"val\":\"hashtag\" } }\n * ]\n * }\n */\n\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\nconst MAX_FORM_ELEMENTS = 8;\nconst MAX_PREVIEW_ATTACHMENTS = 3;\nconst MAX_PREVIEW_DATA_SIZE = 64;\nconst JSON_MIME_TYPE = 'application/json';\nconst DRAFTY_MIME_TYPE = 'text/x-drafty';\nconst ALLOWED_ENT_FIELDS = ['act', 'height', 'duration', 'incoming', 'mime', 'name', 'premime', 'preref', 'preview',\n 'ref', 'size', 'state', 'url', 'val', 'width'\n];\n\n// Intl.Segmenter is not available in Firefox 124 and earlier. FF 125 with support for Intl.Segmenter\n// was released on April 15, 2024. Polyfill is included in the top package (webapp).\nconst segmenter = new Intl.Segmenter();\n\n// Regular expressions for parsing inline formats. Javascript does not support lookbehind,\n// so it's a bit messy.\nconst INLINE_STYLES = [\n // Strong = bold, *bold text*\n {\n name: 'ST',\n start: /(?:^|[\\W_])(\\*)[^\\s*]/,\n end: /[^\\s*](\\*)(?=$|[\\W_])/\n },\n // Emphesized = italic, _italic text_\n {\n name: 'EM',\n start: /(?:^|\\W)(_)[^\\s_]/,\n end: /[^\\s_](_)(?=$|\\W)/\n },\n // Deleted, ~strike this though~\n {\n name: 'DL',\n start: /(?:^|[\\W_])(~)[^\\s~]/,\n end: /[^\\s~](~)(?=$|[\\W_])/\n },\n // Code block `this is monospace`\n {\n name: 'CO',\n start: /(?:^|\\W)(`)[^`]/,\n end: /[^`](`)(?=$|\\W)/\n }\n];\n\n// Relative weights of formatting spans. Greater index in array means greater weight.\nconst FMT_WEIGHT = ['QQ'];\n\n// RegExps for entity extraction (RF = reference)\nconst ENTITY_TYPES = [\n // URLs\n {\n name: 'LN',\n dataName: 'url',\n pack: function(val) {\n // Check if the protocol is specified, if not use http\n if (!/^[a-z]+:\\/\\//i.test(val)) {\n val = 'http://' + val;\n }\n return {\n url: val\n };\n },\n re: /(?:(?:https?|ftp):\\/\\/|www\\.|ftp\\.)[-A-Z0-9+&@#\\/%=~_|$?!:,.]*[A-Z0-9+&@#\\/%=~_|$]/ig\n },\n // Mentions @user (must be 2 or more characters)\n {\n name: 'MN',\n dataName: 'val',\n pack: function(val) {\n return {\n val: val.slice(1)\n };\n },\n re: /\\B@([\\p{L}\\p{N}][._\\p{L}\\p{N}]*[\\p{L}\\p{N}])/ug\n },\n // Hashtags #hashtag, like metion 2 or more characters.\n {\n name: 'HT',\n dataName: 'val',\n pack: function(val) {\n return {\n val: val.slice(1)\n };\n },\n re: /\\B#([\\p{L}\\p{N}][._\\p{L}\\p{N}]*[\\p{L}\\p{N}])/ug\n }\n];\n\n// HTML tag name suggestions\nconst FORMAT_TAGS = {\n AU: {\n html_tag: 'audio',\n md_tag: undefined,\n isVoid: false\n },\n BN: {\n html_tag: 'button',\n md_tag: undefined,\n isVoid: false\n },\n BR: {\n html_tag: 'br',\n md_tag: '\\n',\n isVoid: true\n },\n CO: {\n html_tag: 'tt',\n md_tag: '`',\n isVoid: false\n },\n DL: {\n html_tag: 'del',\n md_tag: '~',\n isVoid: false\n },\n EM: {\n html_tag: 'i',\n md_tag: '_',\n isVoid: false\n },\n EX: {\n html_tag: '',\n md_tag: undefined,\n isVoid: true\n },\n FM: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false\n },\n HD: {\n html_tag: '',\n md_tag: undefined,\n isVoid: false\n },\n HL: {\n html_tag: 'span',\n md_tag: undefined,\n isVoid: false\n },\n HT: {\n html_tag: 'a',\n md_tag: undefined,\n isVoid: false\n },\n IM: {\n html_tag: 'img',\n md_tag: undefined,\n isVoid: false\n },\n LN: {\n html_tag: 'a',\n md_tag: undefined,\n isVoid: false\n },\n MN: {\n html_tag: 'a',\n md_tag: undefined,\n isVoid: false\n },\n RW: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false,\n },\n QQ: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false\n },\n ST: {\n html_tag: 'b',\n md_tag: '*',\n isVoid: false\n },\n VC: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false\n },\n VD: {\n html_tag: 'video',\n md_tag: undefined,\n isVoid: false\n }\n};\n\n// Convert base64-encoded string into Blob.\nfunction base64toObjectUrl(b64, contentType, logger) {\n if (!b64) {\n return null;\n }\n\n try {\n const bin = atob(b64);\n const length = bin.length;\n const buf = new ArrayBuffer(length);\n const arr = new Uint8Array(buf);\n for (let i = 0; i < length; i++) {\n arr[i] = bin.charCodeAt(i);\n }\n\n return URL.createObjectURL(new Blob([buf], {\n type: contentType\n }));\n } catch (err) {\n if (logger) {\n logger(\"Drafty: failed to convert object.\", err.message);\n }\n }\n\n return null;\n}\n\nfunction base64toDataUrl(b64, contentType) {\n if (!b64) {\n return null;\n }\n contentType = contentType || 'image/jpeg';\n return 'data:' + contentType + ';base64,' + b64;\n}\n\n// Helpers for converting Drafty to HTML.\nconst DECORATORS = {\n // Visial styles\n ST: {\n open: _ => '',\n close: _ => ' '\n },\n EM: {\n open: _ => '',\n close: _ => ' '\n },\n DL: {\n open: _ => '',\n close: _ => ''\n },\n CO: {\n open: _ => '',\n close: _ => ' '\n },\n // Line break\n BR: {\n open: _ => ' ',\n close: _ => ''\n },\n // Hidden element\n HD: {\n open: _ => '',\n close: _ => ''\n },\n // Highlighted element.\n HL: {\n open: _ => '',\n close: _ => ' '\n },\n // Link (URL)\n LN: {\n open: (data) => {\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n return data ? {\n href: data.url,\n target: '_blank'\n } : null;\n },\n },\n // Mention\n MN: {\n open: (data) => {\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n return data ? {\n id: data.val\n } : null;\n },\n },\n // Hashtag\n HT: {\n open: (data) => {\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n return data ? {\n id: data.val\n } : null;\n },\n },\n // Button\n BN: {\n open: _ => '',\n close: _ => ' ',\n props: (data) => {\n return data ? {\n 'data-act': data.act,\n 'data-val': data.val,\n 'data-name': data.name,\n 'data-ref': data.ref\n } : null;\n },\n },\n // Audio recording\n AU: {\n open: (data) => {\n const url = data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger);\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n if (!data) return null;\n return {\n // Embedded data or external link.\n src: data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger),\n 'data-preload': data.ref ? 'metadata' : 'auto',\n 'data-duration': data.duration,\n 'data-name': data.name,\n 'data-size': data.val ? ((data.val.length * 0.75) | 0) : (data.size | 0),\n 'data-mime': data.mime,\n };\n }\n },\n // Image\n IM: {\n open: data => {\n // Don't use data.ref for preview: it's a security risk.\n const tmpPreviewUrl = base64toDataUrl(data._tempPreview, data.mime);\n const previewUrl = base64toObjectUrl(data.val, data.mime, Drafty.logger);\n const downloadUrl = data.ref || previewUrl;\n return (data.name ? '' : '') +\n ' ';\n },\n close: data => {\n return (data.name ? ' ' : '');\n },\n props: data => {\n if (!data) return null;\n return {\n // Temporary preview, or permanent preview, or external link.\n src: base64toDataUrl(data._tempPreview, data.mime) ||\n data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger),\n title: data.name,\n alt: data.name,\n 'data-width': data.width,\n 'data-height': data.height,\n 'data-name': data.name,\n 'data-size': data.ref ? (data.size | 0) : (data.val ? ((data.val.length * 0.75) | 0) : (data.size | 0)),\n 'data-mime': data.mime,\n };\n },\n },\n // Form - structured layout of elements.\n FM: {\n open: _ => '',\n close: _ => '
'\n },\n // Row: logic grouping of elements\n RW: {\n open: _ => '',\n close: _ => '
'\n },\n // Quoted block.\n QQ: {\n open: _ => '',\n close: _ => '
',\n props: (data) => {\n return data ? {} : null;\n },\n },\n // Video call\n VC: {\n open: _ => '',\n close: _ => '
',\n props: data => {\n if (!data) return {};\n return {\n 'data-duration': data.duration,\n 'data-state': data.state,\n };\n }\n },\n // Video.\n VD: {\n open: data => {\n const tmpPreviewUrl = base64toDataUrl(data._tempPreview, data.mime);\n const previewUrl = data.ref || base64toObjectUrl(data.preview, data.premime || 'image/jpeg', Drafty.logger);\n return ' ';\n },\n close: _ => '',\n props: data => {\n if (!data) return null;\n const poster = data.preref || base64toObjectUrl(data.preview, data.premime || 'image/jpeg', Drafty.logger);\n return {\n // Embedded data or external link.\n src: poster,\n 'data-src': data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger),\n 'data-width': data.width,\n 'data-height': data.height,\n 'data-preload': data.ref ? 'metadata' : 'auto',\n 'data-preview': poster,\n 'data-duration': data.duration | 0,\n 'data-name': data.name,\n 'data-size': data.ref ? (data.size | 0) : (data.val ? ((data.val.length * 0.75) | 0) : (data.size | 0)),\n 'data-mime': data.mime,\n };\n }\n },\n};\n\n/**\n * The main object which performs all the formatting actions.\n * @class Drafty\n * @constructor\n */\nconst Drafty = function() {\n this.txt = '';\n this.fmt = [];\n this.ent = [];\n}\n\n/**\n * Initialize Drafty document to a plain text string.\n *\n * @param {string} plainText - string to use as Drafty content.\n *\n * @returns new Drafty document or null is plainText is not a string or undefined.\n */\nDrafty.init = function(plainText) {\n if (typeof plainText == 'undefined') {\n plainText = '';\n } else if (typeof plainText != 'string') {\n return null;\n }\n\n return {\n txt: plainText\n };\n}\n\n/**\n * Parse plain text into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {string} content - plain-text content to parse.\n * @return {Drafty} parsed document or null if the source is not plain text.\n */\nDrafty.parse = function(content) {\n // Make sure we are parsing strings only.\n if (typeof content != 'string') {\n return null;\n }\n\n // Split text into lines. It makes further processing easier.\n const lines = content.split(/\\r?\\n/);\n\n // Holds entities referenced from text\n const entityMap = [];\n const entityIndex = {};\n\n // Processing lines one by one, hold intermediate result in blx.\n const blx = [];\n lines.forEach((line) => {\n let spans = [];\n let entities;\n\n // Find formatted spans in the string.\n // Try to match each style.\n INLINE_STYLES.forEach((tag) => {\n // Each style could be matched multiple times.\n spans = spans.concat(spannify(line, tag.start, tag.end, tag.name));\n });\n\n let block;\n if (spans.length == 0) {\n block = {\n txt: line\n };\n } else {\n // Sort spans by style occurence early -> late, then by length: first long then short.\n spans.sort((a, b) => {\n const diff = a.at - b.at;\n return diff != 0 ? diff : b.end - a.end;\n });\n\n // Convert an array of possibly overlapping spans into a tree.\n spans = toSpanTree(spans);\n\n // Build a tree representation of the entire string, not\n // just the formatted parts.\n const chunks = chunkify(line, 0, line.length, spans);\n\n const drafty = draftify(chunks, 0);\n\n block = {\n txt: drafty.txt,\n fmt: drafty.fmt\n };\n }\n\n // Extract entities from the cleaned up string.\n entities = extractEntities(block.txt);\n if (entities.length > 0) {\n const ranges = [];\n for (let i in entities) {\n // {offset: match['index'], unique: match[0], len: match[0].length, data: ent.packer(), type: ent.name}\n const entity = entities[i];\n let index = entityIndex[entity.unique];\n if (!index) {\n index = entityMap.length;\n entityIndex[entity.unique] = index;\n entityMap.push({\n tp: entity.type,\n data: entity.data\n });\n }\n ranges.push({\n at: entity.offset,\n len: entity.len,\n key: index\n });\n }\n block.ent = ranges;\n }\n\n blx.push(block);\n });\n\n const result = {\n txt: ''\n };\n\n // Merge lines and save line breaks as BR inline formatting.\n if (blx.length > 0) {\n result.txt = blx[0].txt;\n result.fmt = (blx[0].fmt || []).concat(blx[0].ent || []);\n\n if (result.fmt.length) {\n const segments = segmenter.segment(result.txt);\n for (const ele of result.fmt) {\n ({\n at: ele.at,\n len: ele.len\n } =\n toGraphemeValues(ele, segments, result.txt));\n }\n }\n\n for (let i = 1; i < blx.length; i++) {\n const block = blx[i];\n const offset = stringToGraphemes(result.txt).length + 1;\n\n result.fmt.push({\n tp: 'BR',\n len: 1,\n at: offset - 1\n });\n\n let segments = {};\n\n result.txt += ' ' + block.txt;\n if (block.fmt) {\n segments = segmenter.segment(block.txt);\n result.fmt = result.fmt.concat(\n block.fmt.map((s) => {\n const {\n at: correctAt,\n len: correctLen\n } =\n toGraphemeValues(s, segments, block.txt);\n s.at = correctAt + offset;\n s.len = correctLen;\n return s;\n })\n );\n }\n if (block.ent) {\n if (isEmptyObject(segments)) {\n segments = segmenter.segment(block.txt);\n }\n result.fmt = result.fmt.concat(\n block.ent.map((s) => {\n const {\n at: correctAt,\n len: correctLen\n } =\n toGraphemeValues(s, segments, block.txt);\n s.at = correctAt + offset;\n s.len = correctLen;\n return s;\n })\n );\n }\n }\n\n if (result.fmt.length == 0) {\n delete result.fmt;\n }\n\n if (entityMap.length > 0) {\n result.ent = entityMap;\n }\n }\n return result;\n}\n\n/**\n * Append one Drafty document to another.\n *\n * @param {Drafty} first - Drafty document to append to.\n * @param {Drafty|string} second - Drafty document or string being appended.\n *\n * @return {Drafty} first document with the second appended to it.\n */\nDrafty.append = function(first, second) {\n if (!first) {\n return second;\n }\n if (!second) {\n return first;\n }\n\n first.txt = first.txt || '';\n const len = stringToGraphemes(first.txt).length;\n\n if (typeof second == 'string') {\n first.txt += second;\n } else if (second.txt) {\n first.txt += second.txt;\n }\n\n if (Array.isArray(second.fmt)) {\n first.fmt = first.fmt || [];\n if (Array.isArray(second.ent)) {\n first.ent = first.ent || [];\n }\n second.fmt.forEach(src => {\n const fmt = {\n at: (src.at | 0) + len,\n len: src.len | 0\n };\n // Special case for the outside of the normal rendering flow styles.\n if (src.at == -1) {\n fmt.at = -1;\n fmt.len = 0;\n }\n if (src.tp) {\n fmt.tp = src.tp;\n } else {\n fmt.key = first.ent.length;\n first.ent.push(second.ent[src.key || 0]);\n }\n first.fmt.push(fmt);\n });\n }\n\n return first;\n}\n\n/**\n * Description of an image to attach.\n * @typedef {Object} ImageDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the image, e.g. \"image/png\".\n * @property {string} refurl - reference to the content. Could be null/undefined.\n * @property {string} bits - base64-encoded image content. Could be null/undefined.\n * @property {string} preview - base64-encoded thumbnail of the image.\n * @property {integer} width - width of the image.\n * @property {integer} height - height of the image.\n * @property {string} filename - file name suggestion for downloading the image.\n * @property {integer} size - size of the image in bytes. Treat is as an untrusted hint.\n * @property {string} _tempPreview - base64-encoded image preview used during upload process; not serializable.\n * @property {Promise} urlPromise - Promise which returns content URL when resolved.\n */\n\n/**\n * Insert inline image into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add image to.\n * @param {integer} at - index where the object is inserted. The length of the image is always 1.\n * @param {ImageDesc} imageDesc - object with image paramenets and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertImage = function(content, at, imageDesc) {\n content = content || {\n txt: ' '\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: 1,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'IM',\n data: {\n mime: imageDesc.mime,\n ref: imageDesc.refurl,\n val: imageDesc.bits || imageDesc.preview,\n width: imageDesc.width,\n height: imageDesc.height,\n name: imageDesc.filename,\n size: imageDesc.size | 0,\n }\n };\n\n if (imageDesc.urlPromise) {\n ex.data._tempPreview = imageDesc._tempPreview;\n ex.data._processing = true;\n imageDesc.urlPromise.then(\n url => {\n ex.data.ref = url;\n ex.data._tempPreview = undefined;\n ex.data._processing = undefined;\n },\n _ => {\n // Catch the error, otherwise it will appear in the console.\n ex.data._processing = undefined;\n }\n );\n }\n\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Description of a video to attach.\n * @typedef {Object} VideoDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the video, e.g. \"video/mpeg\".\n * @property {string} refurl - reference to the content. Could be null/undefined.\n * @property {string} bits - in-band base64-encoded image data. Could be null/undefined.\n * @property {string} preview - base64-encoded screencapture from the video. Could be null/undefined.\n * @property {string} preref - reference to screencapture from the video. Could be null/undefined.\n * @property {integer} width - width of the video.\n * @property {integer} height - height of the video.\n * @property {integer} duration - duration of the video.\n * @property {string} filename - file name suggestion for downloading the video.\n * @property {integer} size - size of the video in bytes. Treat is as an untrusted hint.\n * @property {string} _tempPreview - base64-encoded screencapture used during upload process; not serializable.\n * @property {Promise} urlPromise - array of two promises, which return URLs of video and preview uploads correspondingly\n * (either could be null).\n */\n\n/**\n * Insert inline image into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add video to.\n * @param {integer} at - index where the object is inserted. The length of the video is always 1.\n * @param {VideoDesc} videoDesc - object with video paramenets and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertVideo = function(content, at, videoDesc) {\n content = content || {\n txt: ' '\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: 1,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'VD',\n data: {\n mime: videoDesc.mime,\n ref: videoDesc.refurl,\n val: videoDesc.bits,\n preref: videoDesc.preref,\n preview: videoDesc.preview,\n width: videoDesc.width,\n height: videoDesc.height,\n duration: videoDesc.duration | 0,\n name: videoDesc.filename,\n size: videoDesc.size | 0,\n }\n };\n\n if (videoDesc.urlPromise) {\n ex.data._tempPreview = videoDesc._tempPreview;\n ex.data._processing = true;\n videoDesc.urlPromise.then(\n urls => {\n ex.data.ref = urls[0];\n ex.data.preref = urls[1];\n ex.data._tempPreview = undefined;\n ex.data._processing = undefined;\n },\n _ => {\n // Catch the error, otherwise it will appear in the console.\n ex.data._processing = undefined;\n }\n );\n }\n\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Description of an audio recording to attach.\n * @typedef {Object} AudioDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the audio, e.g. \"audio/ogg\".\n * @property {string} refurl - reference to the content. Could be null/undefined.\n * @property {string} bits - base64-encoded audio content. Could be null/undefined.\n * @property {integer} duration - duration of the record in milliseconds.\n * @property {string} preview - base64 encoded short array of amplitude values 0..100.\n * @property {string} filename - file name suggestion for downloading the audio.\n * @property {integer} size - size of the recording in bytes. Treat is as an untrusted hint.\n * @property {Promise} urlPromise - Promise which returns content URL when resolved.\n */\n\n/**\n * Insert audio recording into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add audio record to.\n * @param {integer} at - index where the object is inserted. The length of the record is always 1.\n * @param {AudioDesc} audioDesc - object with the audio paramenets and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertAudio = function(content, at, audioDesc) {\n content = content || {\n txt: ' '\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: 1,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'AU',\n data: {\n mime: audioDesc.mime,\n val: audioDesc.bits,\n duration: audioDesc.duration | 0,\n preview: audioDesc.preview,\n name: audioDesc.filename,\n size: audioDesc.size | 0,\n ref: audioDesc.refurl\n }\n };\n\n if (audioDesc.urlPromise) {\n ex.data._processing = true;\n audioDesc.urlPromise.then(\n url => {\n ex.data.ref = url;\n ex.data._processing = undefined;\n },\n _ => {\n // Catch the error, otherwise it will appear in the console.\n ex.data._processing = undefined;\n }\n );\n }\n\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Create a (self-contained) video call Drafty document.\n * @memberof Drafty\n * @static\n * @param {boolean} audioOnly true if the call is initially audio-only.\n * @returns Video Call drafty document.\n */\nDrafty.videoCall = function(audioOnly) {\n const content = {\n txt: ' ',\n fmt: [{\n at: 0,\n len: 1,\n key: 0\n }],\n ent: [{\n tp: 'VC',\n data: {\n aonly: audioOnly\n },\n }]\n };\n return content;\n}\n\n/**\n * Update video call (VC) entity with the new status and duration.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - VC document to update.\n * @param {object} params - new video call parameters.\n * @param {string} params.state - state of video call.\n * @param {number} params.duration - duration of the video call in milliseconds.\n *\n * @returns the same document with update applied.\n */\nDrafty.updateVideoCall = function(content, params) {\n // The video element could be just a format or a format + entity.\n // Must ensure it's the latter first.\n const fmt = ((content || {}).fmt || [])[0];\n if (!fmt) {\n // Unrecognized content.\n return content;\n }\n\n let ent;\n if (fmt.tp == 'VC') {\n // Just a format, convert to format + entity.\n delete fmt.tp;\n fmt.key = 0;\n ent = {\n tp: 'VC'\n };\n content.ent = [ent];\n } else {\n ent = (content.ent || [])[fmt.key | 0];\n if (!ent || ent.tp != 'VC') {\n // Not a VC entity.\n return content;\n }\n }\n ent.data = ent.data || {};\n Object.assign(ent.data, params);\n return content;\n}\n\n/**\n * Create a quote to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {string} header - Quote header (title, etc.).\n * @param {string} uid - UID of the author to mention.\n * @param {Drafty} body - Body of the quoted message.\n *\n * @returns Reply quote Drafty doc with the quote formatting.\n */\nDrafty.quote = function(header, uid, body) {\n const quote = Drafty.append(Drafty.appendLineBreak(Drafty.mention(header, uid)), body);\n\n // Wrap into a quote.\n quote.fmt.push({\n at: 0,\n len: stringToGraphemes(quote.txt).length,\n tp: 'QQ'\n });\n\n return quote;\n}\n\n/**\n * Create a Drafty document with a mention.\n *\n * @param {string} name - mentioned name.\n * @param {string} uid - mentioned user ID.\n *\n * @returns {Drafty} document with the mention.\n */\nDrafty.mention = function(name, uid) {\n return {\n txt: name || '',\n fmt: [{\n at: 0,\n len: stringToGraphemes(name || '').length,\n key: 0\n }],\n ent: [{\n tp: 'MN',\n data: {\n val: uid\n }\n }]\n };\n}\n\n/**\n * Append a link to a Drafty document.\n *\n * @param {Drafty} content - Drafty document to append link to.\n * @param {Object} linkData - Link info in format {txt: 'ankor text', url: 'http://...'}.\n *\n * @returns {Drafty} the same document as content.\n */\nDrafty.appendLink = function(content, linkData) {\n content = content || {\n txt: ''\n };\n\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: content.txt.length,\n len: linkData.txt.length,\n key: content.ent.length\n });\n content.txt += linkData.txt;\n\n const ex = {\n tp: 'LN',\n data: {\n url: linkData.url\n }\n }\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Append image to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add image to.\n * @param {ImageDesc} imageDesc - object with image paramenets.\n *\n * @return {Drafty} updated document.\n */\nDrafty.appendImage = function(content, imageDesc) {\n content = content || {\n txt: ''\n };\n content.txt += ' ';\n return Drafty.insertImage(content, content.txt.length - 1, imageDesc);\n}\n\n/**\n * Append audio recodring to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add recording to.\n * @param {AudioDesc} audioDesc - object with audio data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.appendAudio = function(content, audioDesc) {\n content = content || {\n txt: ''\n };\n content.txt += ' ';\n return Drafty.insertAudio(content, content.txt.length - 1, audioDesc);\n}\n\n/**\n * Description of a file to attach.\n * @typedef {Object} AttachmentDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the attachment, e.g. \"application/octet-stream\"\n * @property {string} data - base64-encoded in-band content of small attachments. Could be null/undefined.\n * @property {string} filename - file name suggestion for downloading the attachment.\n * @property {integer} size - size of the file in bytes. Treat is as an untrusted hint.\n * @property {string} refurl - reference to the out-of-band content. Could be null/undefined.\n * @property {Promise} urlPromise - Promise which returns content URL when resolved.\n */\n\n/**\n * Attach file to Drafty content. Either as a blob or as a reference.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to attach file to.\n * @param {AttachmentDesc} object - containing attachment description and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.attachFile = function(content, attachmentDesc) {\n content = content || {\n txt: ''\n };\n\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: -1,\n len: 0,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'EX',\n data: {\n mime: attachmentDesc.mime,\n val: attachmentDesc.data,\n name: attachmentDesc.filename,\n ref: attachmentDesc.refurl,\n size: attachmentDesc.size | 0\n }\n }\n if (attachmentDesc.urlPromise) {\n ex.data._processing = true;\n attachmentDesc.urlPromise.then(\n url => {\n ex.data.ref = url;\n ex.data._processing = undefined;\n },\n _ => {\n /* catch the error, otherwise it will appear in the console. */\n ex.data._processing = undefined;\n }\n );\n }\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Wraps drafty document into a simple formatting style.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - document or string to wrap into a style.\n * @param {string} style - two-letter style to wrap into.\n * @param {number} at - index where the style starts, default 0.\n * @param {number} len - length of the form content, default all of it.\n *\n * @return {Drafty} updated document.\n */\nDrafty.wrapInto = function(content, style, at, len) {\n if (typeof content == 'string') {\n content = {\n txt: content\n };\n }\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at || 0,\n len: len || content.txt.length,\n tp: style,\n });\n\n return content;\n}\n\n/**\n * Wraps content into an interactive form.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - to wrap into a form.\n * @param {number} at - index where the forms starts.\n * @param {number} len - length of the form content.\n *\n * @return {Drafty} updated document.\n */\nDrafty.wrapAsForm = function(content, at, len) {\n return Drafty.wrapInto(content, 'FM', at, len);\n}\n\n/**\n * Insert clickable button into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - Drafty document to insert button to or a string to be used as button text.\n * @param {number} at - location where the button is inserted.\n * @param {number} len - the length of the text to be used as button title.\n * @param {string} name - the button. Client should return it to the server when the button is clicked.\n * @param {string} actionType - the type of the button, one of 'url' or 'pub'.\n * @param {string} actionValue - the value to return on click:\n * @param {string} refUrl - the URL to go to when the 'url' button is clicked.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertButton = function(content, at, len, name, actionType, actionValue, refUrl) {\n if (typeof content == 'string') {\n content = {\n txt: content\n };\n }\n\n if (!content || !content.txt || content.txt.length < at + len) {\n return null;\n }\n\n if (len <= 0 || ['url', 'pub'].indexOf(actionType) == -1) {\n return null;\n }\n // Ensure refUrl is a string.\n if (actionType == 'url' && !refUrl) {\n return null;\n }\n refUrl = '' + refUrl;\n\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: len,\n key: content.ent.length\n });\n content.ent.push({\n tp: 'BN',\n data: {\n act: actionType,\n val: actionValue,\n ref: refUrl,\n name: name\n }\n });\n\n return content;\n}\n\n/**\n * Append clickable button to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - Drafty document to insert button to or a string to be used as button text.\n * @param {string} title - the text to be used as button title.\n * @param {string} name - the button. Client should return it to the server when the button is clicked.\n * @param {string} actionType - the type of the button, one of 'url' or 'pub'.\n * @param {string} actionValue - the value to return on click:\n * @param {string} refUrl - the URL to go to when the 'url' button is clicked.\n *\n * @return {Drafty} updated document.\n */\nDrafty.appendButton = function(content, title, name, actionType, actionValue, refUrl) {\n content = content || {\n txt: ''\n };\n const at = content.txt.length;\n content.txt += title;\n return Drafty.insertButton(content, at, title.length, name, actionType, actionValue, refUrl);\n}\n\n/**\n * Attach a generic JS object. The object is attached as a json string.\n * Intended for representing a form response.\n *\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - Drafty document to attach file to.\n * @param {Object} data - data to convert to json string and attach.\n * @returns {Drafty} the same document as content.\n */\nDrafty.attachJSON = function(content, data) {\n content = content || {\n txt: ''\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: -1,\n len: 0,\n key: content.ent.length\n });\n\n content.ent.push({\n tp: 'EX',\n data: {\n mime: JSON_MIME_TYPE,\n val: data\n }\n });\n\n return content;\n}\n/**\n * Append line break to a Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - Drafty document to append linebreak to.\n * @returns {Drafty} the same document as content.\n */\nDrafty.appendLineBreak = function(content) {\n content = content || {\n txt: ''\n };\n content.fmt = content.fmt || [];\n content.fmt.push({\n at: stringToGraphemes(content.txt).length,\n len: 1,\n tp: 'BR'\n });\n content.txt += ' ';\n\n return content;\n}\n/**\n * Given Drafty document, convert it to HTML.\n * No attempt is made to strip pre-existing html markup.\n * This is potentially unsafe because content.txt may contain malicious HTML\n * markup.\n * @memberof Tinode.Drafty\n * @static\n *\n * @param {Drafty} doc - document to convert.\n *\n * @returns {string} HTML-representation of content.\n */\nDrafty.UNSAFE_toHTML = function(doc) {\n const tree = draftyToTree(doc);\n const htmlFormatter = function(type, data, values) {\n const tag = DECORATORS[type];\n let result = values ? values.join('') : '';\n if (tag) {\n result = tag.open(data) + result + tag.close(data);\n }\n return result;\n };\n return treeBottomUp(tree, htmlFormatter, 0);\n}\n\n/**\n * Callback for applying custom formatting to a Drafty document.\n * Called once for each style span.\n * @memberof Drafty\n * @static\n *\n * @callback Formatter\n * @param {string} style - style code such as \"ST\" or \"IM\".\n * @param {Object} data - entity's data.\n * @param {Object} values - possibly styled subspans contained in this style span.\n * @param {number} index - index of the element guaranteed to be unique.\n */\n\n/**\n * Convert Drafty document to a representation suitable for display.\n * The context may expose a function getFormatter(style). If it's available\n * it will call it to obtain a formatter for a subtree of styles under the style.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|Object} content - Drafty document to transform.\n * @param {Formatter} formatter - callback which formats individual elements.\n * @param {Object} context - context provided to formatter as this.\n *\n * @return {Object} transformed object\n */\nDrafty.format = function(original, formatter, context) {\n return treeBottomUp(draftyToTree(original), formatter, 0, [], context);\n}\n\n/**\n * Shorten Drafty document making the drafty text no longer than the limit.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @param {number} limit - length in characrets to shorten to.\n * @param {boolean} light - remove heavy data from entities.\n * @returns new shortened Drafty object leaving the original intact.\n */\nDrafty.shorten = function(original, limit, light) {\n let tree = draftyToTree(original);\n tree = shortenTree(tree, limit, '…');\n if (tree && light) {\n tree = lightEntity(tree);\n }\n return treeToDrafty({}, tree, []);\n}\n\n/**\n * Transform Drafty doc for forwarding: strip leading @mention and any leading line breaks or whitespace.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @returns converted Drafty object leaving the original intact.\n */\nDrafty.forwardedContent = function(original) {\n let tree = draftyToTree(original);\n const rmMention = function(node) {\n if (node.type == 'MN') {\n if (!node.parent || !node.parent.type) {\n return null;\n }\n }\n return node;\n }\n // Strip leading mention.\n tree = treeTopDown(tree, rmMention);\n // Remove leading whitespace.\n tree = lTrim(tree);\n // Convert back to Drafty.\n return treeToDrafty({}, tree, []);\n}\n\n/**\n * Prepare Drafty doc for wrapping into QQ as a reply:\n * - Replace forwarding mention with symbol '➦' and remove data (UID).\n * - Remove quoted text completely.\n * - Replace line breaks with spaces.\n * - Strip entities of heavy content.\n * - Move attachments to the end of the document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @param {number} limit - length in characters to shorten to.\n * @returns converted Drafty object leaving the original intact.\n */\nDrafty.replyContent = function(original, limit) {\n const convMNnQQnBR = function(node) {\n if (node.type == 'QQ') {\n return null;\n } else if (node.type == 'MN') {\n if ((!node.parent || !node.parent.type) && (node.text || '').startsWith('➦')) {\n node.text = '➦';\n delete node.children;\n delete node.data;\n }\n } else if (node.type == 'BR') {\n node.text = ' ';\n delete node.type;\n delete node.children;\n }\n return node;\n }\n\n let tree = draftyToTree(original);\n if (!tree) {\n return original;\n }\n\n // Strip leading mention.\n tree = treeTopDown(tree, convMNnQQnBR);\n // Move attachments to the end of the doc.\n tree = attachmentsToEnd(tree, MAX_PREVIEW_ATTACHMENTS);\n // Shorten the doc.\n tree = shortenTree(tree, limit, '…');\n // Strip heavy elements except IM.data['val'] and VD.data['preview'] (have to keep them to generate previews later).\n const filter = node => {\n switch (node.type) {\n case 'IM':\n return ['val'];\n case 'VD':\n return ['preview'];\n }\n return null;\n };\n tree = lightEntity(tree, filter);\n // Convert back to Drafty.\n return treeToDrafty({}, tree, []);\n}\n\n\n/**\n * Generate drafty preview:\n * - Shorten the document.\n * - Strip all heavy entity data leaving just inline styles and entity references.\n * - Replace line breaks with spaces.\n * - Replace content of QQ with a space.\n * - Replace forwarding mention with symbol '➦'.\n * move all attachments to the end of the document and make them visible.\n * The context may expose a function getFormatter(style). If it's available\n * it will call it to obtain a formatter for a subtree of styles under the style.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @param {number} limit - length in characters to shorten to.\n * @param {boolean} forwarding - this a forwarding message preview.\n * @returns new shortened Drafty object leaving the original intact.\n */\nDrafty.preview = function(original, limit, forwarding) {\n let tree = draftyToTree(original);\n\n // Move attachments to the end.\n tree = attachmentsToEnd(tree, MAX_PREVIEW_ATTACHMENTS);\n\n // Convert leading mention to '➦' and replace QQ and BR with a space ' '.\n const convMNnQQnBR = function(node) {\n if (node.type == 'MN') {\n if ((!node.parent || !node.parent.type) && (node.text || '').startsWith('➦')) {\n node.text = '➦';\n delete node.children;\n }\n } else if (node.type == 'QQ') {\n node.text = ' ';\n delete node.children;\n } else if (node.type == 'BR') {\n node.text = ' ';\n delete node.children;\n delete node.type;\n }\n return node;\n }\n tree = treeTopDown(tree, convMNnQQnBR);\n\n tree = shortenTree(tree, limit, '…');\n if (forwarding) {\n // Keep some IM and VD data for preview.\n const filter = {\n IM: ['val'],\n VD: ['preview']\n };\n tree = lightEntity(tree, node => {\n return filter[node.type];\n });\n } else {\n tree = lightEntity(tree);\n }\n\n // Convert back to Drafty.\n return treeToDrafty({}, tree, []);\n}\n\n/**\n * Given Drafty document, convert it to plain text.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to convert to plain text.\n * @returns {string} plain-text representation of the drafty document.\n */\nDrafty.toPlainText = function(content) {\n return typeof content == 'string' ? content : content.txt;\n}\n\n/**\n * Check if the document has no markup and no entities.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - content to check for presence of markup.\n * @returns true is content is plain text, false otherwise.\n */\nDrafty.isPlainText = function(content) {\n return typeof content == 'string' || !(content.fmt || content.ent);\n}\n\n/**\n * Convert document to plain text with markdown. All elements which cannot\n * be represented in markdown are stripped.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to convert to plain text with markdown.\n */\nDrafty.toMarkdown = function(content) {\n let tree = draftyToTree(content);\n const mdFormatter = function(type, _, values) {\n const def = FORMAT_TAGS[type];\n let result = (values ? values.join('') : '');\n if (def) {\n if (def.isVoid) {\n result = def.md_tag || '';\n } else if (def.md_tag) {\n result = def.md_tag + result + def.md_tag;\n }\n }\n return result;\n };\n return treeBottomUp(tree, mdFormatter, 0);\n}\n\n/**\n * Checks if the object represets is a valid Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - content to check for validity.\n * @returns true is content is valid, false otherwise.\n */\nDrafty.isValid = function(content) {\n if (!content) {\n return false;\n }\n\n const {\n txt,\n fmt,\n ent\n } = content;\n\n if (!txt && txt !== '' && !fmt && !ent) {\n return false;\n }\n\n const txt_type = typeof txt;\n if (txt_type != 'string' && txt_type != 'undefined' && txt !== null) {\n return false;\n }\n\n if (typeof fmt != 'undefined' && !Array.isArray(fmt) && fmt !== null) {\n return false;\n }\n\n if (typeof ent != 'undefined' && !Array.isArray(ent) && ent !== null) {\n return false;\n }\n return true;\n}\n\n/**\n * Check if the drafty document has attachments: style EX and outside of normal rendering flow,\n * i.e. at = -1.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to check for attachments.\n * @returns true if there are attachments.\n */\nDrafty.hasAttachments = function(content) {\n if (!Array.isArray(content.fmt)) {\n return false;\n }\n for (let i in content.fmt) {\n const fmt = content.fmt[i];\n if (fmt && fmt.at < 0) {\n const ent = content.ent[fmt.key | 0];\n return ent && ent.tp == 'EX' && ent.data;\n }\n }\n return false;\n}\n\n/**\n * Callback for enumerating entities in a Drafty document.\n * Called once for each entity.\n * @memberof Drafty\n * @static\n *\n * @callback EntityCallback\n * @param {Object} data entity data.\n * @param {string} entity type.\n * @param {number} index entity's index in `content.ent`.\n *\n * @return 'true-ish' to stop processing, 'false-ish' otherwise.\n */\n\n/**\n * Enumerate attachments: style EX and outside of normal rendering flow, i.e. at = -1.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to process for attachments.\n * @param {EntityCallback} callback - callback to call for each attachment.\n * @param {Object} context - value of \"this\" for callback.\n */\nDrafty.attachments = function(content, callback, context) {\n if (!Array.isArray(content.fmt)) {\n return;\n }\n let count = 0;\n for (let i in content.fmt) {\n let fmt = content.fmt[i];\n if (fmt && fmt.at < 0) {\n const ent = content.ent[fmt.key | 0];\n if (ent && ent.tp == 'EX' && ent.data) {\n if (callback.call(context, ent.data, count++, 'EX')) {\n break;\n }\n }\n }\n };\n}\n\n/**\n * Check if the drafty document has entities.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to check for entities.\n * @returns true if there are entities.\n */\nDrafty.hasEntities = function(content) {\n return content.ent && content.ent.length > 0;\n}\n\n/**\n * Enumerate entities. Enumeration stops if callback returns 'true'.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document with entities to enumerate.\n * @param {EntityCallback} callback - callback to call for each entity.\n * @param {Object} context - value of \"this\" for callback.\n *\n */\nDrafty.entities = function(content, callback, context) {\n if (content.ent && content.ent.length > 0) {\n for (let i in content.ent) {\n if (content.ent[i]) {\n if (callback.call(context, content.ent[i].data, i, content.ent[i].tp)) {\n break;\n }\n }\n }\n }\n}\n\n/**\n * Callback for enumerating styles (inline formats) in a Drafty document.\n * Called once for each style.\n * @memberof Drafty\n * @static\n *\n * @callback StyleCallback\n * @param {string} tp - format type.\n * @param {number} at - starting position of the format in text.\n * @param {number} len - extent of the format in characters.\n * @param {number} key - index of the entity if format is a reference.\n * @param {number} index - style's index in `content.fmt`.\n *\n * @return 'true-ish' to stop processing, 'false-ish' otherwise.\n */\n\n/**\n * Enumerate styles (inline formats). Enumeration stops if callback returns 'true'.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document with styles (formats) to enumerate.\n * @param {StyleCallback} callback - callback to call for each format.\n * @param {Object} context - value of \"this\" for callback.\n */\nDrafty.styles = function(content, callback, context) {\n if (content.fmt && content.fmt.length > 0) {\n for (let i in content.fmt) {\n const fmt = content.fmt[i];\n if (fmt) {\n if (callback.call(context, fmt.tp, fmt.at, fmt.len, fmt.key, i)) {\n break;\n }\n }\n }\n }\n}\n\n/**\n * Remove unrecognized fields from entity data\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document with entities to enumerate.\n * @returns content.\n */\nDrafty.sanitizeEntities = function(content) {\n if (content && content.ent && content.ent.length > 0) {\n for (let i in content.ent) {\n const ent = content.ent[i];\n if (ent && ent.data) {\n const data = copyEntData(ent.data);\n if (data) {\n content.ent[i].data = data;\n } else {\n delete content.ent[i].data;\n }\n }\n }\n }\n return content;\n}\n\n/**\n * Given the entity, get URL which can be used for downloading\n * entity data.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entData - entity.data to get the URl from.\n * @returns {string} URL to download entity data or null.\n */\nDrafty.getDownloadUrl = function(entData) {\n let url = null;\n if (entData.mime != JSON_MIME_TYPE && entData.val) {\n url = base64toObjectUrl(entData.val, entData.mime, Drafty.logger);\n } else if (typeof entData.ref == 'string') {\n url = entData.ref;\n }\n return url;\n}\n\n/**\n * Check if the entity data is not ready for sending, such as being uploaded to the server.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entity.data to get the URl from.\n * @returns {boolean} true if upload is in progress, false otherwise.\n */\nDrafty.isProcessing = function(entData) {\n return !!entData._processing;\n}\n\n/**\n * Given the entity, get URL which can be used for previewing\n * the entity.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entity.data to get the URl from.\n *\n * @returns {string} url for previewing or null if no such url is available.\n */\nDrafty.getPreviewUrl = function(entData) {\n return entData.val ? base64toObjectUrl(entData.val, entData.mime, Drafty.logger) : null;\n}\n\n/**\n * Get approximate size of the entity.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entData - entity.data to get the size for.\n * @returns {number} size of entity data in bytes.\n */\nDrafty.getEntitySize = function(entData) {\n // Either size hint or length of value. The value is base64 encoded,\n // the actual object size is smaller than the encoded length.\n return entData.size ? entData.size : entData.val ? (entData.val.length * 0.75) | 0 : 0;\n}\n\n/**\n * Get entity mime type.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entData - entity.data to get the type for.\n * @returns {string} mime type of entity.\n */\nDrafty.getEntityMimeType = function(entData) {\n return entData.mime || 'text/plain';\n}\n\n/**\n * Get HTML tag for a given two-letter style name.\n * @memberof Drafty\n * @static\n *\n * @param {string} style - two-letter style, like ST or LN.\n *\n * @returns {string} HTML tag name if style is found, {code: undefined} if style is falsish or not found.\n */\nDrafty.tagName = function(style) {\n return FORMAT_TAGS[style] && FORMAT_TAGS[style].html_tag;\n}\n\n/**\n * For a given data bundle generate an object with HTML attributes,\n * for instance, given {url: \"http://www.example.com/\"} return\n * {href: \"http://www.example.com/\"}\n * @memberof Drafty\n * @static\n *\n * @param {string} style - two-letter style to generate attributes for.\n * @param {Object} data - data bundle to convert to attributes\n *\n * @returns {Object} object with HTML attributes.\n */\nDrafty.attrValue = function(style, data) {\n if (data && DECORATORS[style] && DECORATORS[style].props) {\n return DECORATORS[style].props(data);\n }\n\n return undefined;\n}\n\n/**\n * Drafty MIME type.\n * @memberof Drafty\n * @static\n *\n * @returns {string} content-Type \"text/x-drafty\".\n */\nDrafty.getContentType = function() {\n return DRAFTY_MIME_TYPE;\n}\n\n// =================\n// Utility methods.\n// =================\n\n// Take a string and defined earlier style spans, re-compose them into a tree where each leaf is\n// a same-style (including unstyled) string. I.e. 'hello *bold _italic_* and ~more~ world' ->\n// ('hello ', (b: 'bold ', (i: 'italic')), ' and ', (s: 'more'), ' world');\n//\n// This is needed in order to clear markup, i.e. 'hello *world*' -> 'hello world' and convert\n// ranges from markup-ed offsets to plain text offsets.\nfunction chunkify(line, start, end, spans) {\n const chunks = [];\n\n if (spans.length == 0) {\n return [];\n }\n\n for (let i in spans) {\n // Get the next chunk from the queue\n const span = spans[i];\n\n // Grab the initial unstyled chunk\n if (span.at > start) {\n chunks.push({\n txt: line.slice(start, span.at)\n });\n }\n\n // Grab the styled chunk. It may include subchunks.\n const chunk = {\n tp: span.tp\n };\n const chld = chunkify(line, span.at + 1, span.end, span.children);\n if (chld.length > 0) {\n chunk.children = chld;\n } else {\n chunk.txt = span.txt;\n }\n chunks.push(chunk);\n start = span.end + 1; // '+1' is to skip the formatting character\n }\n\n // Grab the remaining unstyled chunk, after the last span\n if (start < end) {\n chunks.push({\n txt: line.slice(start, end)\n });\n }\n\n return chunks;\n}\n\n// Detect starts and ends of formatting spans. Unformatted spans are\n// ignored at this stage.\nfunction spannify(original, re_start, re_end, type) {\n const result = [];\n let index = 0;\n let line = original.slice(0); // make a copy;\n\n while (line.length > 0) {\n // match[0]; // match, like '*abc*'\n // match[1]; // match captured in parenthesis, like 'abc'\n // match['index']; // offset where the match started.\n\n // Find the opening token.\n const start = re_start.exec(line);\n if (start == null) {\n break;\n }\n\n // Because javascript RegExp does not support lookbehind, the actual offset may not point\n // at the markup character. Find it in the matched string.\n let start_offset = start['index'] + start[0].lastIndexOf(start[1]);\n // Clip the processed part of the string.\n line = line.slice(start_offset + 1);\n // start_offset is an offset within the clipped string. Convert to original index.\n start_offset += index;\n // Index now point to the beginning of 'line' within the 'original' string.\n index = start_offset + 1;\n\n // Find the matching closing token.\n const end = re_end ? re_end.exec(line) : null;\n if (end == null) {\n break;\n }\n let end_offset = end['index'] + end[0].indexOf(end[1]);\n // Clip the processed part of the string.\n line = line.slice(end_offset + 1);\n // Update offsets\n end_offset += index;\n // Index now points to the beginning of 'line' within the 'original' string.\n index = end_offset + 1;\n\n result.push({\n txt: original.slice(start_offset + 1, end_offset),\n children: [],\n at: start_offset,\n end: end_offset,\n tp: type\n });\n }\n\n return result;\n}\n\n// Convert linear array or spans into a tree representation.\n// Keep standalone and nested spans, throw away partially overlapping spans.\nfunction toSpanTree(spans) {\n if (spans.length == 0) {\n return [];\n }\n\n const tree = [spans[0]];\n let last = spans[0];\n for (let i = 1; i < spans.length; i++) {\n // Keep spans which start after the end of the previous span or those which\n // are complete within the previous span.\n if (spans[i].at > last.end) {\n // Span is completely outside of the previous span.\n tree.push(spans[i]);\n last = spans[i];\n } else if (spans[i].end <= last.end) {\n // Span is fully inside of the previous span. Push to subnode.\n last.children.push(spans[i]);\n }\n // Span could partially overlap, ignoring it as invalid.\n }\n\n // Recursively rearrange the subnodes.\n for (let i in tree) {\n tree[i].children = toSpanTree(tree[i].children);\n }\n\n return tree;\n}\n\n// Convert drafty document to a tree.\nfunction draftyToTree(doc) {\n if (!doc) {\n return null;\n }\n\n doc = (typeof doc == 'string') ? {\n txt: doc\n } : doc;\n let {\n txt,\n fmt,\n ent\n } = doc;\n\n txt = txt || '';\n if (!Array.isArray(ent)) {\n ent = [];\n }\n\n if (!Array.isArray(fmt) || fmt.length == 0) {\n if (ent.length == 0) {\n return {\n text: txt\n };\n }\n\n // Handle special case when all values in fmt are 0 and fmt therefore is skipped.\n fmt = [{\n at: 0,\n len: 0,\n key: 0\n }];\n }\n\n // Sanitize spans.\n const spans = [];\n const attachments = [];\n fmt.forEach((span) => {\n if (!span || typeof span != 'object') {\n return;\n }\n\n if (!['undefined', 'number'].includes(typeof span.at)) {\n // Present, but non-numeric 'at'.\n return;\n }\n if (!['undefined', 'number'].includes(typeof span.len)) {\n // Present, but non-numeric 'len'.\n return;\n }\n let at = span.at | 0;\n let len = span.len | 0;\n if (len < 0) {\n // Invalid span length.\n return;\n }\n\n let key = span.key || 0;\n if (ent.length > 0 && (typeof key != 'number' || key < 0 || key >= ent.length)) {\n // Invalid key value.\n return;\n }\n\n if (at <= -1) {\n // Attachment. Store attachments separately.\n attachments.push({\n start: -1,\n end: 0,\n key: key\n });\n return;\n } else if (at + len > stringToGraphemes(txt).length) {\n // Span is out of bounds.\n return;\n }\n\n if (!span.tp) {\n if (ent.length > 0 && (typeof ent[key] == 'object')) {\n spans.push({\n start: at,\n end: at + len,\n key: key\n });\n }\n } else {\n spans.push({\n type: span.tp,\n start: at,\n end: at + len\n });\n }\n });\n\n // Sort spans first by start index (asc) then by length (desc), then by weight.\n spans.sort((a, b) => {\n let diff = a.start - b.start;\n if (diff != 0) {\n return diff;\n }\n diff = b.end - a.end;\n if (diff != 0) {\n return diff;\n }\n return FMT_WEIGHT.indexOf(b.type) - FMT_WEIGHT.indexOf(a.type);\n });\n\n // Move attachments to the end of the list.\n if (attachments.length > 0) {\n spans.push(...attachments);\n }\n\n spans.forEach((span) => {\n if (ent.length > 0 && !span.type && ent[span.key] && typeof ent[span.key] == 'object') {\n span.type = ent[span.key].tp;\n span.data = ent[span.key].data;\n }\n\n // Is type still undefined? Hide the invalid element!\n if (!span.type) {\n span.type = 'HD';\n }\n });\n\n const graphemes = stringToGraphemes(txt);\n let tree = spansToTree({}, graphemes, 0, graphemes.length, spans);\n\n // Flatten tree nodes.\n const flatten = function(node) {\n if (Array.isArray(node.children) && node.children.length == 1) {\n // Unwrap.\n const child = node.children[0];\n if (!node.type) {\n const parent = node.parent;\n node = child;\n node.parent = parent;\n } else if (!child.type && !child.children) {\n node.text = child.text;\n delete node.children;\n }\n }\n return node;\n }\n tree = treeTopDown(tree, flatten);\n\n return tree;\n}\n\n// Add tree node to a parent tree.\nfunction addNode(parent, n) {\n if (!n) {\n return parent;\n }\n\n if (!parent.children) {\n parent.children = [];\n }\n\n // If text is present, move it to a subnode.\n if (parent.text) {\n parent.children.push({\n text: parent.text,\n parent: parent\n });\n delete parent.text;\n }\n\n n.parent = parent;\n parent.children.push(n);\n\n return parent;\n}\n\n// Returns a tree of nodes.\nfunction spansToTree(parent, graphemes, start, end, spans) {\n if (!spans || spans.length == 0) {\n if (start < end) {\n addNode(parent, {\n text: graphemes.slice(start, end)\n .map(segment => segment.segment)\n .join('')\n });\n }\n return parent;\n }\n\n // Process subspans.\n for (let i = 0; i < spans.length; i++) {\n const span = spans[i];\n if (span.start < 0 && span.type == 'EX') {\n addNode(parent, {\n type: span.type,\n data: span.data,\n key: span.key,\n att: true\n });\n continue;\n }\n\n // Add un-styled range before the styled span starts.\n if (start < span.start) {\n addNode(parent, {\n text: graphemes.slice(start, span.start)\n .map(segment => segment.segment)\n .join('')\n });\n start = span.start;\n }\n\n // Get all spans which are within the current span.\n const subspans = [];\n while (i < spans.length - 1) {\n const inner = spans[i + 1];\n if (inner.start < 0) {\n // Attachments are in the end. Stop.\n break;\n } else if (inner.start < span.end) {\n if (inner.end <= span.end) {\n const tag = FORMAT_TAGS[inner.tp] || {};\n if (inner.start < inner.end || tag.isVoid) {\n // Valid subspan: completely within the current span and\n // either non-zero length or zero length is acceptable.\n subspans.push(inner);\n }\n }\n i++;\n // Overlapping subspans are ignored.\n } else {\n // Past the end of the current span. Stop.\n break;\n }\n }\n\n addNode(parent, spansToTree({\n type: span.type,\n data: span.data,\n key: span.key\n }, graphemes, start, span.end, subspans));\n start = span.end;\n }\n\n // Add the last unformatted range.\n if (start < end) {\n addNode(parent, {\n text: graphemes\n .slice(start, end)\n .map((segment) => segment.segment)\n .join('')\n });\n }\n\n return parent;\n}\n\n// Append a tree to a Drafty doc.\nfunction treeToDrafty(doc, tree, keymap) {\n if (!tree) {\n return doc;\n }\n\n doc.txt = doc.txt || '';\n\n // Checkpoint to measure length of the current tree node.\n const start = stringToGraphemes(doc.txt).length;\n\n if (tree.text) {\n doc.txt += tree.text;\n } else if (Array.isArray(tree.children)) {\n tree.children.forEach((c) => {\n treeToDrafty(doc, c, keymap);\n });\n }\n\n if (tree.type) {\n const len = stringToGraphemes(doc.txt).length - start;\n doc.fmt = doc.fmt || [];\n if (Object.keys(tree.data || {}).length > 0) {\n doc.ent = doc.ent || [];\n const newKey = (typeof keymap[tree.key] == 'undefined') ? doc.ent.length : keymap[tree.key];\n keymap[tree.key] = newKey;\n doc.ent[newKey] = {\n tp: tree.type,\n data: tree.data\n };\n if (tree.att) {\n // Attachment.\n doc.fmt.push({\n at: -1,\n len: 0,\n key: newKey\n });\n } else {\n doc.fmt.push({\n at: start,\n len: len,\n key: newKey\n });\n }\n } else {\n doc.fmt.push({\n tp: tree.type,\n at: start,\n len: len\n });\n }\n }\n return doc;\n}\n\n// Traverse the tree top down transforming the nodes: apply transformer to every tree node.\nfunction treeTopDown(src, transformer, context) {\n if (!src) {\n return null;\n }\n\n let dst = transformer.call(context, src);\n if (!dst || !dst.children) {\n return dst;\n }\n\n const children = [];\n for (let i in dst.children) {\n let n = dst.children[i];\n if (n) {\n n = treeTopDown(n, transformer, context);\n if (n) {\n children.push(n);\n }\n }\n }\n\n if (children.length == 0) {\n dst.children = null;\n } else {\n dst.children = children;\n }\n\n return dst;\n}\n\n// Traverse the tree bottom-up: apply formatter to every node.\n// The formatter must maintain its state through context.\nfunction treeBottomUp(src, formatter, index, stack, context) {\n if (!src) {\n return null;\n }\n\n if (stack && src.type) {\n stack.push(src.type);\n }\n\n let values = [];\n for (let i in src.children) {\n const n = treeBottomUp(src.children[i], formatter, i, stack, context);\n if (n) {\n values.push(n);\n }\n }\n if (values.length == 0) {\n if (src.text) {\n values = [src.text];\n } else {\n values = null;\n }\n }\n\n if (stack && src.type) {\n stack.pop();\n }\n\n return formatter.call(context, src.type, src.data, values, index, stack);\n}\n\n// Clip tree to the provided limit.\nfunction shortenTree(tree, limit, tail) {\n if (!tree) {\n return null;\n }\n\n if (tail) {\n limit -= tail.length;\n }\n\n const shortener = function(node) {\n if (limit <= -1) {\n // Limit -1 means the doc was already clipped.\n return null;\n }\n\n if (node.att) {\n // Attachments are unchanged.\n return node;\n }\n if (limit == 0) {\n node.text = tail;\n limit = -1;\n } else if (node.text) {\n const graphemes = stringToGraphemes(node.text);\n if (graphemes.length > limit) {\n node.text = graphemes\n .slice(0, limit)\n .map((segment) => segment.segment)\n .join('') + tail;\n limit = -1;\n } else {\n limit -= graphemes.length;\n }\n }\n return node;\n }\n\n return treeTopDown(tree, shortener);\n}\n\n// Strip heavy entities from a tree.\nfunction lightEntity(tree, allow) {\n const lightCopy = node => {\n const data = copyEntData(node.data, true, allow ? allow(node) : null);\n if (data) {\n node.data = data;\n } else {\n delete node.data;\n }\n return node;\n }\n return treeTopDown(tree, lightCopy);\n}\n\n// Remove spaces and breaks on the left.\nfunction lTrim(tree) {\n if (tree.type == 'BR') {\n tree = null;\n } else if (tree.text) {\n if (!tree.type) {\n tree.text = tree.text.trimStart();\n if (!tree.text) {\n tree = null;\n }\n }\n } else if (!tree.type && tree.children && tree.children.length > 0) {\n const c = lTrim(tree.children[0]);\n if (c) {\n tree.children[0] = c;\n } else {\n tree.children.shift();\n if (!tree.type && tree.children.length == 0) {\n tree = null;\n }\n }\n }\n return tree;\n}\n\n// Move attachments to the end. Attachments must be at the top level, no need to traverse the tree.\nfunction attachmentsToEnd(tree, limit) {\n if (!tree) {\n return null;\n }\n\n if (tree.att) {\n tree.text = ' ';\n delete tree.att;\n delete tree.children;\n } else if (tree.children) {\n const attachments = [];\n const children = [];\n for (let i in tree.children) {\n const c = tree.children[i];\n if (c.att) {\n if (attachments.length == limit) {\n // Too many attachments to preview;\n continue;\n }\n if (c.data['mime'] == JSON_MIME_TYPE) {\n // JSON attachments are not shown in preview.\n continue;\n }\n\n delete c.att;\n delete c.children;\n c.text = ' ';\n attachments.push(c);\n } else {\n children.push(c);\n }\n }\n tree.children = children.concat(attachments);\n }\n return tree;\n}\n\n// Get a list of entities from a text.\nfunction extractEntities(line) {\n let match;\n let extracted = [];\n ENTITY_TYPES.forEach((entity) => {\n while ((match = entity.re.exec(line)) !== null) {\n extracted.push({\n offset: match['index'],\n len: match[0].length,\n unique: match[0],\n data: entity.pack(match[0]),\n type: entity.name\n });\n }\n });\n\n if (extracted.length == 0) {\n return extracted;\n }\n\n // Remove entities detected inside other entities, like #hashtag in a URL.\n extracted.sort((a, b) => {\n return a.offset - b.offset;\n });\n\n let idx = -1;\n extracted = extracted.filter((el) => {\n const result = (el.offset > idx);\n idx = el.offset + el.len;\n return result;\n });\n\n return extracted;\n}\n\n// Convert the chunks into format suitable for serialization.\nfunction draftify(chunks, startAt) {\n let plain = '';\n let ranges = [];\n for (let i in chunks) {\n const chunk = chunks[i];\n if (!chunk.txt) {\n const drafty = draftify(chunk.children, plain.length + startAt);\n chunk.txt = drafty.txt;\n ranges = ranges.concat(drafty.fmt);\n }\n\n if (chunk.tp) {\n ranges.push({\n at: plain.length + startAt,\n len: chunk.txt.length,\n tp: chunk.tp\n });\n }\n\n plain += chunk.txt;\n }\n return {\n txt: plain,\n fmt: ranges\n };\n}\n\n// Create a copy of entity data with (light=false) or without (light=true) the large payload.\n// The array 'allow' contains a list of fields exempt from stripping.\nfunction copyEntData(data, light, allow) {\n if (data && Object.entries(data).length > 0) {\n allow = allow || [];\n const dc = {};\n ALLOWED_ENT_FIELDS.forEach(key => {\n if (data[key]) {\n if (light && !allow.includes(key) &&\n (typeof data[key] == 'string' || Array.isArray(data[key])) &&\n data[key].length > MAX_PREVIEW_DATA_SIZE) {\n return;\n }\n if (typeof data[key] == 'object') {\n return;\n }\n dc[key] = data[key];\n }\n });\n\n if (Object.entries(dc).length != 0) {\n return dc;\n }\n }\n return null;\n}\n\n// Returns true if object is empty, if undefined returns true\nfunction isEmptyObject(obj) {\n return Object.keys(obj ?? {}).length == 0;\n};\n\n\n// Returns an array (of length equal to the length of the original string) such that each index\n// denotes the position of char in string in a grapheme array (created from that string)\n// Eg: string: \"Hi👋🏼Hi\" -> [0,1,2,2,2,2,3,4]\nfunction graphemeIndices(graphemes) {\n const result = [];\n let graphemeIndex = 0;\n let charIndex = 0;\n\n // Iterate over the grapheme clusters.\n for (const {\n segment\n }\n of graphemes) {\n // Map the character indices to the grapheme index.\n for (let i = 0; i < segment.length; i++) {\n result[charIndex + i] = graphemeIndex;\n }\n\n // Increment the character index by the length of the grapheme cluster.\n charIndex += segment.length;\n\n // Increment the grapheme index.\n graphemeIndex++;\n }\n\n return result;\n}\n\n// Convert fmt.at and fmt.len from character-expressed index and length to grapheme-expressed\n// index and length.\nfunction toGraphemeValues(fmt, segments, txt) {\n segments = segments ?? segmenter.segment(txt);\n\n const indices = graphemeIndices(segments);\n\n const correctAt = indices[fmt.at];\n const correctLen = fmt.at + fmt.len <= txt.length ?\n indices[fmt.at + fmt.len - 1] - correctAt : fmt.len;\n\n return {\n at: correctAt,\n len: correctLen + 1\n };\n}\n\n// Convert string to graphme cluster array.\nfunction stringToGraphemes(str) {\n return Array.from(segmenter.segment(str));\n}\n\nif (typeof module != 'undefined') {\n module.exports = Drafty;\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/**\n * @file Access control model.\n *\n * @copyright 2015-2022 Tinode LLC.\n */\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\n/**\n * Helper class for handling access mode.\n *\n * @class AccessMode\n * @memberof Tinode\n *\n * @param {AccessMode|Object=} acs - AccessMode to copy or access mode object received from the server.\n */\nexport default class AccessMode {\n constructor(acs) {\n if (acs) {\n this.given = typeof acs.given == 'number' ? acs.given : AccessMode.decode(acs.given);\n this.want = typeof acs.want == 'number' ? acs.want : AccessMode.decode(acs.want);\n this.mode = acs.mode ? (typeof acs.mode == 'number' ? acs.mode : AccessMode.decode(acs.mode)) :\n (this.given & this.want);\n }\n }\n\n static #checkFlag(val, side, flag) {\n side = side || 'mode';\n if (['given', 'want', 'mode'].includes(side)) {\n return ((val[side] & flag) != 0);\n }\n throw new Error(`Invalid AccessMode component '${side}'`);\n }\n /**\n * Parse string into an access mode value.\n * @memberof Tinode.AccessMode\n * @static\n *\n * @param {string | Number} mode - either a String representation of the access mode to parse or a set of bits to assign.\n * @returns {number} - Access mode as a numeric value.\n */\n static decode(str) {\n if (!str) {\n return null;\n } else if (typeof str == 'number') {\n return str & AccessMode._BITMASK;\n } else if (str === 'N' || str === 'n') {\n return AccessMode._NONE;\n }\n\n const bitmask = {\n 'J': AccessMode._JOIN,\n 'R': AccessMode._READ,\n 'W': AccessMode._WRITE,\n 'P': AccessMode._PRES,\n 'A': AccessMode._APPROVE,\n 'S': AccessMode._SHARE,\n 'D': AccessMode._DELETE,\n 'O': AccessMode._OWNER\n };\n\n let m0 = AccessMode._NONE;\n\n for (let i = 0; i < str.length; i++) {\n const bit = bitmask[str.charAt(i).toUpperCase()];\n if (!bit) {\n // Unrecognized bit, skip.\n continue;\n }\n m0 |= bit;\n }\n return m0;\n }\n /**\n * Convert numeric representation of the access mode into a string.\n *\n * @memberof Tinode.AccessMode\n * @static\n *\n * @param {number} val - access mode value to convert to a string.\n * @returns {string} - Access mode as a string.\n */\n static encode(val) {\n if (val === null || val === AccessMode._INVALID) {\n return null;\n } else if (val === AccessMode._NONE) {\n return 'N';\n }\n\n const bitmask = ['J', 'R', 'W', 'P', 'A', 'S', 'D', 'O'];\n let res = '';\n for (let i = 0; i < bitmask.length; i++) {\n if ((val & (1 << i)) != 0) {\n res = res + bitmask[i];\n }\n }\n return res;\n }\n /**\n * Update numeric representation of access mode with the new value. The value\n * is one of the following:\n * - a string starting with '+' or '-' then the bits to add or remove, e.g. '+R-W' or '-PS'.\n * - a new value of access mode\n *\n * @memberof Tinode.AccessMode\n * @static\n *\n * @param {number} val - access mode value to update.\n * @param {string} upd - update to apply to val.\n * @returns {number} - updated access mode.\n */\n static update(val, upd) {\n if (!upd || typeof upd != 'string') {\n return val;\n }\n\n let action = upd.charAt(0);\n if (action == '+' || action == '-') {\n let val0 = val;\n // Split delta-string like '+ABC-DEF+Z' into an array of parts including + and -.\n const parts = upd.split(/([-+])/);\n // Starting iteration from 1 because String.split() creates an array with the first empty element.\n // Iterating by 2 because we parse pairs +/- then data.\n for (let i = 1; i < parts.length - 1; i += 2) {\n action = parts[i];\n const m0 = AccessMode.decode(parts[i + 1]);\n if (m0 == AccessMode._INVALID) {\n return val;\n }\n if (m0 == null) {\n continue;\n }\n if (action === '+') {\n val0 |= m0;\n } else if (action === '-') {\n val0 &= ~m0;\n }\n }\n val = val0;\n } else {\n // The string is an explicit new value 'ABC' rather than delta.\n const val0 = AccessMode.decode(upd);\n if (val0 != AccessMode._INVALID) {\n val = val0;\n }\n }\n\n return val;\n }\n /**\n * Bits present in a1 but missing in a2.\n *\n * @static\n * @memberof Tinode\n *\n * @param {number | string} a1 - access mode to subtract from.\n * @param {number | string} a2 - access mode to subtract.\n * @returns {number} access mode with bits present in a1 but missing in a2.\n */\n static diff(a1, a2) {\n a1 = AccessMode.decode(a1);\n a2 = AccessMode.decode(a2);\n\n if (a1 == AccessMode._INVALID || a2 == AccessMode._INVALID) {\n return AccessMode._INVALID;\n }\n return a1 & ~a2;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Custom formatter\n */\n toString() {\n return '{\"mode\": \"' + AccessMode.encode(this.mode) +\n '\", \"given\": \"' + AccessMode.encode(this.given) +\n '\", \"want\": \"' + AccessMode.encode(this.want) + '\"}';\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Converts numeric values to strings.\n */\n jsonHelper() {\n return {\n mode: AccessMode.encode(this.mode),\n given: AccessMode.encode(this.given),\n want: AccessMode.encode(this.want)\n };\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Assign value to 'mode'.\n * @memberof Tinode.AccessMode\n *\n * @param {string | Number} m - either a string representation of the access mode or a set of bits.\n * @returns {AccessMode} - this AccessMode.\n */\n setMode(m) {\n this.mode = AccessMode.decode(m);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update mode value.\n * @memberof Tinode.AccessMode\n *\n * @param {string} u - string representation of the changes to apply to access mode.\n * @returns {AccessMode} - this AccessMode.\n */\n updateMode(u) {\n this.mode = AccessMode.update(this.mode, u);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get mode value as a string.\n * @memberof Tinode.AccessMode\n *\n * @returns {string} - mode value.\n */\n getMode() {\n return AccessMode.encode(this.mode);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Assign given value.\n * @memberof Tinode.AccessMode\n *\n * @param {string | Number} g - either a string representation of the access mode or a set of bits.\n * @returns {AccessMode} - this AccessMode.\n */\n setGiven(g) {\n this.given = AccessMode.decode(g);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update 'given' value.\n * @memberof Tinode.AccessMode\n *\n * @param {string} u - string representation of the changes to apply to access mode.\n * @returns {AccessMode} - this AccessMode.\n */\n updateGiven(u) {\n this.given = AccessMode.update(this.given, u);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get 'given' value as a string.\n * @memberof Tinode.AccessMode\n *\n * @returns {string} - given value.\n */\n getGiven() {\n return AccessMode.encode(this.given);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Assign 'want' value.\n * @memberof Tinode.AccessMode\n *\n * @param {string | Number} w - either a string representation of the access mode or a set of bits.\n * @returns {AccessMode} - this AccessMode.\n */\n setWant(w) {\n this.want = AccessMode.decode(w);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update 'want' value.\n * @memberof Tinode.AccessMode\n *\n * @param {string} u - string representation of the changes to apply to access mode.\n * @returns {AccessMode} - this AccessMode.\n */\n updateWant(u) {\n this.want = AccessMode.update(this.want, u);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get 'want' value as a string.\n * @memberof Tinode.AccessMode\n *\n * @returns {string} - want value.\n */\n getWant() {\n return AccessMode.encode(this.want);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get permissions present in 'want' but missing in 'given'.\n * Inverse of {@link Tinode.AccessMode#getExcessive}\n *\n * @memberof Tinode.AccessMode\n *\n * @returns {string} permissions present in want but missing in given .\n */\n getMissing() {\n return AccessMode.encode(this.want & ~this.given);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get permissions present in 'given' but missing in 'want'.\n * Inverse of {@link Tinode.AccessMode#getMissing}\n * @memberof Tinode.AccessMode\n *\n * @returns {string} permissions present in given but missing in want .\n */\n getExcessive() {\n return AccessMode.encode(this.given & ~this.want);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update 'want', 'give', and 'mode' values.\n * @memberof Tinode.AccessMode\n *\n * @param {AccessMode} val - new access mode value.\n * @returns {AccessMode} - this AccessMode.\n */\n updateAll(val) {\n if (val) {\n this.updateGiven(val.given);\n this.updateWant(val.want);\n this.mode = this.given & this.want;\n }\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Owner (O) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isOwner(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._OWNER);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Presence (P) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isPresencer(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._PRES);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Presence (P) flag is NOT set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isMuted(side) {\n return !this.isPresencer(side);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Join (J) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isJoiner(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._JOIN);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Reader (R) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isReader(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._READ);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Writer (W) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isWriter(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._WRITE);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Approver (A) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isApprover(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._APPROVE);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if either one of Owner (O) or Approver (A) flags is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isAdmin(side) {\n return this.isOwner(side) || this.isApprover(side);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if either one of Owner (O), Approver (A), or Sharer (S) flags is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isSharer(side) {\n return this.isAdmin(side) || AccessMode.#checkFlag(this, side, AccessMode._SHARE);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Deleter (D) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isDeleter(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._DELETE);\n }\n}\n\nAccessMode._NONE = 0x00;\nAccessMode._JOIN = 0x01;\nAccessMode._READ = 0x02;\nAccessMode._WRITE = 0x04;\nAccessMode._PRES = 0x08;\nAccessMode._APPROVE = 0x10;\nAccessMode._SHARE = 0x20;\nAccessMode._DELETE = 0x40;\nAccessMode._OWNER = 0x80;\n\nAccessMode._BITMASK = AccessMode._JOIN | AccessMode._READ | AccessMode._WRITE | AccessMode._PRES |\n AccessMode._APPROVE | AccessMode._SHARE | AccessMode._DELETE | AccessMode._OWNER;\nAccessMode._INVALID = 0x100000;\n","export const PACKAGE_VERSION = \"0.24.2\";\n","/**\n * @file Global constants and configuration parameters.\n *\n * @copyright 2015-2025 Tinode LLC\n */\n'use strict';\n\nimport {\n PACKAGE_VERSION\n} from '../version.js';\n\n// Global constants\nexport const PROTOCOL_VERSION = '0'; // Major component of the version, e.g. '0' in '0.17.1'.\nexport const VERSION = PACKAGE_VERSION || '0.24';\nexport const LIBRARY = 'tinodejs/' + VERSION;\n\n// Topic name prefixes.\nexport const TOPIC_NEW = 'new';\nexport const TOPIC_NEW_CHAN = 'nch';\nexport const TOPIC_ME = 'me';\nexport const TOPIC_FND = 'fnd';\nexport const TOPIC_SYS = 'sys';\nexport const TOPIC_SLF = 'slf';\nexport const TOPIC_CHAN = 'chn';\nexport const TOPIC_GRP = 'grp';\nexport const TOPIC_P2P = 'p2p';\nexport const USER_NEW = 'new';\n\n// Starting value of a locally-generated seqId used for pending messages.\nexport const LOCAL_SEQID = 0xFFFFFFF;\n\n// Status codes.\nexport const MESSAGE_STATUS_NONE = 0; // Status not assigned.\nexport const MESSAGE_STATUS_QUEUED = 10; // Local ID assigned, in progress to be sent.\nexport const MESSAGE_STATUS_SENDING = 20; // Transmission started.\nexport const MESSAGE_STATUS_FAILED = 30; // At least one attempt was made to send the message.\nexport const MESSAGE_STATUS_FATAL = 40; // Message sending failed and it should not be retried.\nexport const MESSAGE_STATUS_SENT = 50; // Delivered to the server.\nexport const MESSAGE_STATUS_RECEIVED = 60; // Received by the client.\nexport const MESSAGE_STATUS_READ = 70; // Read by the user.\nexport const MESSAGE_STATUS_TO_ME = 80; // The message is received from another user.\n\n// Reject unresolved futures after this many milliseconds.\nexport const EXPIRE_PROMISES_TIMEOUT = 5_000;\n// Periodicity of garbage collection of unresolved futures.\nexport const EXPIRE_PROMISES_PERIOD = 1_000;\n\n// Delay before acknowledging that a message was recived.\nexport const RECV_TIMEOUT = 100;\n\n// Default number of messages to pull into memory from persistent cache.\nexport const DEFAULT_MESSAGES_PAGE = 24;\n\n// Unicode DEL character indicating data was deleted.\nexport const DEL_CHAR = '\\u2421';\n\n// Maximum number of pinnned messages;\nexport const MAX_PINNED_COUNT = 5;\n\n// Tag prefixes for alias, email, phone.\nexport const TAG_ALIAS = 'alias:';\nexport const TAG_EMAIL = 'email:';\nexport const TAG_PHONE = 'tel:';\n","/**\n * @file Throwable error with numeric error code.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nexport default class CommError extends Error {\n constructor(message, code) {\n super(`${message} (${code})`);\n this.name = 'CommError';\n this.code = code;\n }\n}\n","/**\n * @file Utilities used in multiple places.\n *\n * @copyright 2015-2022 Tinode LLC.\n */\n'use strict';\n\nimport AccessMode from './access-mode.js';\nimport {\n DEL_CHAR,\n LOCAL_SEQID\n} from './config.js';\n\n// Attempt to convert date and AccessMode strings to objects.\nexport function jsonParseHelper(key, val) {\n // Try to convert string timestamps with optional milliseconds to Date,\n // e.g. 2015-09-02T01:45:43[.123]Z\n if (typeof val == 'string' && val.length >= 20 && val.length <= 24 && ['ts', 'touched', 'updated', 'created', 'when', 'deleted', 'expires'].includes(key)) {\n const date = new Date(val);\n if (!isNaN(date)) {\n return date;\n }\n } else if (key === 'acs' && typeof val === 'object') {\n return new AccessMode(val);\n }\n return val;\n}\n\n// Checks if URL is a relative url, i.e. has no 'scheme://', including the case of missing scheme '//'.\n// The scheme is expected to be RFC-compliant, e.g. [a-z][a-z0-9+.-]*\n// example.html - ok\n// https:example.com - not ok.\n// http:/example.com - not ok.\n// ' ↲ https://example.com' - not ok. (↲ means carriage return)\nexport function isUrlRelative(url) {\n return url && !/^\\s*([a-z][a-z0-9+.-]*:|\\/\\/)/im.test(url);\n}\n\nfunction isValidDate(d) {\n return (d instanceof Date) && !isNaN(d) && (d.getTime() != 0);\n}\n\n// RFC3339 formater of Date\nexport function rfc3339DateString(d) {\n if (!isValidDate(d)) {\n return undefined;\n }\n\n const pad = function(val, sp) {\n sp = sp || 2;\n return '0'.repeat(sp - ('' + val).length) + val;\n };\n\n const millis = d.getUTCMilliseconds();\n return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate()) +\n 'T' + pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) +\n (millis ? '.' + pad(millis, 3) : '') + 'Z';\n}\n\n// Recursively merge src's own properties to dst.\n// Ignore properties where ignore[property] is true.\n// Array and Date objects are shallow-copied.\nexport function mergeObj(dst, src, ignore) {\n if (typeof src != 'object') {\n if (src === undefined) {\n return dst;\n }\n if (src === DEL_CHAR) {\n return undefined;\n }\n return src;\n }\n // JS is crazy: typeof null is 'object'.\n if (src === null) {\n return src;\n }\n\n // Handle Date\n if (src instanceof Date && !isNaN(src)) {\n return (!dst || !(dst instanceof Date) || isNaN(dst) || dst < src) ? src : dst;\n }\n\n // Access mode\n if (src instanceof AccessMode) {\n return new AccessMode(src);\n }\n\n // Handle Array\n if (src instanceof Array) {\n return src;\n }\n\n if (!dst || dst === DEL_CHAR) {\n dst = src.constructor();\n }\n\n for (let prop in src) {\n if (src.hasOwnProperty(prop) && (!ignore || !ignore[prop]) && (prop != '_noForwarding')) {\n try {\n dst[prop] = mergeObj(dst[prop], src[prop]);\n } catch (err) {\n // FIXME: probably need to log something here.\n }\n }\n }\n return dst;\n}\n\n// Update object stored in a cache. Returns updated value.\nexport function mergeToCache(cache, key, newval, ignore) {\n cache[key] = mergeObj(cache[key], newval, ignore);\n return cache[key];\n}\n\n// Strips all values from an object of they evaluate to false or if their name starts with '_'.\n// Used on all outgoing object before serialization to string.\nexport function simplify(obj) {\n Object.keys(obj).forEach((key) => {\n if (key[0] == '_') {\n // Strip fields like \"obj._key\".\n delete obj[key];\n } else if (!obj[key]) {\n // Strip fields which evaluate to false.\n delete obj[key];\n } else if (Array.isArray(obj[key]) && obj[key].length == 0) {\n // Strip empty arrays.\n delete obj[key];\n } else if (!obj[key]) {\n // Strip fields which evaluate to false.\n delete obj[key];\n } else if (obj[key] instanceof Date) {\n // Strip invalid or zero date.\n if (!isValidDate(obj[key])) {\n delete obj[key];\n }\n } else if (typeof obj[key] == 'object') {\n simplify(obj[key]);\n // Strip empty objects.\n if (Object.getOwnPropertyNames(obj[key]).length == 0) {\n delete obj[key];\n }\n }\n });\n return obj;\n};\n\n\n// Trim whitespace, convert to lowercase, strip empty, short, and duplicate elements elements.\n// If the result is an empty array, add a single element \"\\u2421\" (Unicode Del character).\nexport function normalizeArray(arr) {\n let out = [];\n if (Array.isArray(arr)) {\n // Trim, throw away very short and empty tags.\n for (let i = 0, l = arr.length; i < l; i++) {\n let t = arr[i];\n if (t) {\n t = t.trim().toLowerCase();\n if (t.length > 1) {\n out.push(t);\n }\n }\n }\n out = out.sort().filter((item, pos, ary) => {\n return !pos || item != ary[pos - 1];\n });\n }\n if (out.length == 0) {\n // Add single tag with a Unicode Del character, otherwise an ampty array\n // is ambiguos. The Del tag will be stripped by the server.\n out.push(DEL_CHAR);\n }\n return out;\n}\n\n// Convert input to valid ranges of IDs.\nexport function normalizeRanges(ranges, maxSeq) {\n if (!Array.isArray(ranges)) {\n return [];\n }\n\n // Sort ranges in accending order by low, then descending by hi.\n ranges.sort((r1, r2) => {\n if (r1.low < r2.low) {\n return -1;\n }\n if (r1.low == r2.low) {\n return (r2.hi | 0) - r1.hi;\n }\n return 1;\n });\n\n // Remove pending messages from ranges possibly clipping some ranges.\n ranges = ranges.reduce((out, r) => {\n if (r.low < LOCAL_SEQID && r.low > 0) {\n if (!r.hi || r.hi < LOCAL_SEQID) {\n out.push(r);\n } else {\n // Clip hi to max allowed value.\n out.push({\n low: r.low,\n hi: maxSeq + 1\n });\n }\n }\n return out;\n }, []);\n\n // Merge overlapping ranges.\n ranges = ranges.reduce((out, r) => {\n if (out.length == 0) {\n out.push(r);\n } else {\n let prev = out[out.length - 1];\n if (r.low <= prev.hi) {\n prev.hi = Math.max(prev.hi, r.hi);\n } else {\n out.push(r);\n }\n }\n return out;\n }, []);\n\n return ranges;\n}\n\n// Convert array of IDs to array of ranges.\nexport function listToRanges(list) {\n // Sort the list in ascending order\n list.sort((a, b) => a - b);\n // Convert the array of IDs to ranges.\n return list.reduce((out, id) => {\n if (out.length == 0) {\n // First element.\n out.push({\n low: id\n });\n } else {\n let prev = out[out.length - 1];\n if ((!prev.hi && (id != prev.low + 1)) || (id > prev.hi)) {\n // New range.\n out.push({\n low: id\n });\n } else {\n // Expand existing range.\n prev.hi = prev.hi ? Math.max(prev.hi, id + 1) : id + 1;\n }\n }\n return out;\n }, []);\n}\n\n// Cuts 'clip' range out of the 'src' range.\n// Returns an array with 0, 1 or 2 elements.\nexport function clipOutRange(src, clip) {\n if (clip.hi <= src.low || clip.low >= src.hi) {\n // Clip is completely outside of src, no intersection.\n return [src];\n }\n\n\n if (clip.low <= src.low) {\n if (clip.hi >= src.hi) {\n // The source range is completely inside the clipping range.\n return [];\n }\n // Partial clipping at the top.\n return [{\n low: clip.hi,\n hi: src.hi\n }];\n }\n\n // Range on the lower end.\n const result = [{\n low: src.low,\n hi: clip.low\n }];\n if (clip.hi < src.hi) {\n // Maybe a range on the higher end, if clip is completely inside the source.\n result.push({\n low: clip.hi,\n hi: src.hi\n });\n }\n\n return result;\n}\n\n// Cuts 'src' range to be completely within 'clip' range.\n// Returns clipped range or null if 'src' is outside of 'clip'.\nexport function clipInRange(src, clip) {\n if (clip.hi <= src.low || clip.low >= src.hi) {\n // The src is completely outside of the clip, no intersection.\n return null;\n }\n\n if (src.low >= clip.low && src.hi <= clip.hi) {\n // Src is completely within the clip, return the entire src.\n return src;\n }\n\n // Partial overlap.\n return {\n low: Math.max(src.low, clip.low),\n hi: Math.min(src.hi, clip.hi)\n };\n\n return result;\n}\n","/**\n * @file Abstraction layer for websocket and long polling connections.\n *\n * @copyright 2015-2022 Tinode LLC.\n */\n'use strict';\n\nimport CommError from './comm-error.js';\nimport {\n jsonParseHelper\n} from './utils.js';\n\nlet WebSocketProvider;\nlet XHRProvider;\n\n// Error code to return in case of a network problem.\nconst NETWORK_ERROR = 503;\nconst NETWORK_ERROR_TEXT = \"Connection failed\";\n\n// Error code to return when user disconnected from server.\nconst NETWORK_USER = 418;\nconst NETWORK_USER_TEXT = \"Disconnected by client\";\n\n// Settings for exponential backoff\nconst _BOFF_BASE = 2000; // 2000 milliseconds, minimum delay between reconnects\nconst _BOFF_MAX_ITER = 10; // Maximum delay between reconnects 2^10 * 2000 ~ 34 minutes\nconst _BOFF_JITTER = 0.3; // Add random delay\n\n// Helper function for creating an endpoint URL.\nfunction makeBaseUrl(host, protocol, version, apiKey) {\n let url = null;\n\n if (['http', 'https', 'ws', 'wss'].includes(protocol)) {\n url = `${protocol}://${host}`;\n if (url.charAt(url.length - 1) !== '/') {\n url += '/';\n }\n url += 'v' + version + '/channels';\n if (['http', 'https'].includes(protocol)) {\n // Long polling endpoint ends with \"lp\", i.e.\n // '/v0/channels/lp' vs just '/v0/channels' for ws\n url += '/lp';\n }\n url += '?apikey=' + apiKey;\n }\n return url;\n}\n\n/**\n * An abstraction for a websocket or a long polling connection.\n *\n * @class Connection\n * @memberof Tinode\n\n * @param {Object} config - configuration parameters.\n * @param {string} config.host - Host name and optional port number to connect to.\n * @param {string} config.apiKey - API key generated by keygen.\n * @param {string} config.transport - Network transport to use, either \"ws\"/\"wss\" for websocket or\n * lp for long polling.\n * @param {boolean} config.secure - Use Secure WebSocket if true.\n * @param {string} version_ - Major value of the protocol version, e.g. '0' in '0.17.1'.\n * @param {boolean} autoreconnect_ - If connection is lost, try to reconnect automatically.\n */\nexport default class Connection {\n // Logger, does nothing by default.\n static #log = _ => {};\n\n #boffTimer = null;\n #boffIteration = 0;\n #boffClosed = false; // Indicator if the socket was manually closed - don't autoreconnect if true.\n\n // Websocket.\n #socket = null;\n\n host;\n secure;\n apiKey;\n\n version;\n autoreconnect;\n\n initialized;\n\n // (config.host, config.apiKey, config.transport, config.secure), PROTOCOL_VERSION, true\n constructor(config, version_, autoreconnect_) {\n this.host = config.host;\n this.secure = config.secure;\n this.apiKey = config.apiKey;\n\n this.version = version_;\n this.autoreconnect = autoreconnect_;\n\n if (config.transport === 'lp') {\n // explicit request to use long polling\n this.#init_lp();\n this.initialized = 'lp';\n } else if (config.transport === 'ws') {\n // explicit request to use web socket\n // if websockets are not available, horrible things will happen\n this.#init_ws();\n this.initialized = 'ws';\n }\n\n if (!this.initialized) {\n // Invalid or undefined network transport.\n Connection.#log(\"Unknown or invalid network transport. Running under Node? Call 'Tinode.setNetworkProviders()'.\");\n throw new Error(\"Unknown or invalid network transport. Running under Node? Call 'Tinode.setNetworkProviders()'.\");\n }\n }\n\n /**\n * To use Connection in a non browser context, supply WebSocket and XMLHttpRequest providers.\n * @static\n * @memberof Connection\n * @param wsProvider WebSocket provider, e.g. for nodeJS , require('ws').\n * @param xhrProvider XMLHttpRequest provider, e.g. for node require('xhr').\n */\n static setNetworkProviders(wsProvider, xhrProvider) {\n WebSocketProvider = wsProvider;\n XHRProvider = xhrProvider;\n }\n\n /**\n * Assign a non-default logger.\n * @static\n * @memberof Connection\n * @param {function} l variadic logging function.\n */\n static set logger(l) {\n Connection.#log = l;\n }\n\n /**\n * Initiate a new connection\n * @memberof Tinode.Connection#\n * @param {string} host_ Host name to connect to; if null the old host name will be used.\n * @param {boolean} force Force new connection even if one already exists.\n * @return {Promise} Promise resolved/rejected when the connection call completes, resolution is called without\n * parameters, rejection passes the {Error} as parameter.\n */\n connect(host_, force) {\n return Promise.reject(null);\n }\n\n /**\n * Try to restore a network connection, also reset backoff.\n * @memberof Tinode.Connection#\n *\n * @param {boolean} force - reconnect even if there is a live connection already.\n */\n reconnect(force) {}\n\n /**\n * Terminate the network connection\n * @memberof Tinode.Connection#\n */\n disconnect() {}\n\n /**\n * Send a string to the server.\n * @memberof Tinode.Connection#\n *\n * @param {string} msg - String to send.\n * @throws Throws an exception if the underlying connection is not live.\n */\n sendText(msg) {}\n\n /**\n * Check if connection is alive.\n * @memberof Tinode.Connection#\n * @returns {boolean} true if connection is live, false otherwise.\n */\n isConnected() {\n return false;\n }\n\n /**\n * Get the name of the current network transport.\n * @memberof Tinode.Connection#\n * @returns {string} name of the transport such as \"ws\" or \"lp\".\n */\n transport() {\n return this.initialized;\n }\n\n /**\n * Send network probe to check if connection is indeed live.\n * @memberof Tinode.Connection#\n */\n probe() {\n this.sendText('1');\n }\n\n /**\n * Reset autoreconnect counter to zero.\n * @memberof Tinode.Connection#\n */\n backoffReset() {\n this.#boffReset();\n }\n\n // Backoff implementation - reconnect after a timeout.\n #boffReconnect() {\n // Clear timer\n clearTimeout(this.#boffTimer);\n // Calculate when to fire the reconnect attempt\n const timeout = _BOFF_BASE * (Math.pow(2, this.#boffIteration) * (1.0 + _BOFF_JITTER * Math.random()));\n // Update iteration counter for future use\n this.#boffIteration = (this.#boffIteration >= _BOFF_MAX_ITER ? this.#boffIteration : this.#boffIteration + 1);\n if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(timeout);\n }\n\n this.#boffTimer = setTimeout(_ => {\n Connection.#log(`Reconnecting, iter=${this.#boffIteration}, timeout=${timeout}`);\n // Maybe the socket was closed while we waited for the timer?\n if (!this.#boffClosed) {\n const prom = this.connect();\n if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(0, prom);\n } else {\n // Suppress error if it's not used.\n prom.catch(_ => {\n /* do nothing */\n });\n }\n } else if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(-1);\n }\n }, timeout);\n }\n\n // Terminate auto-reconnect process.\n #boffStop() {\n clearTimeout(this.#boffTimer);\n this.#boffTimer = null;\n }\n\n // Reset auto-reconnect iteration counter.\n #boffReset() {\n this.#boffIteration = 0;\n }\n\n // Initialization for long polling.\n #init_lp() {\n const XDR_UNSENT = 0; // Client has been created. open() not called yet.\n const XDR_OPENED = 1; // open() has been called.\n const XDR_HEADERS_RECEIVED = 2; // send() has been called, and headers and status are available.\n const XDR_LOADING = 3; // Downloading; responseText holds partial data.\n const XDR_DONE = 4; // The operation is complete.\n\n // Fully composed endpoint URL, with API key & SID\n let _lpURL = null;\n\n let _poller = null;\n let _sender = null;\n\n let lp_sender = (url_) => {\n const sender = new XHRProvider();\n sender.onreadystatechange = (evt) => {\n if (sender.readyState == XDR_DONE && sender.status >= 400) {\n // Some sort of error response\n throw new CommError(\"LP sender failed\", sender.status);\n }\n };\n\n sender.open('POST', url_, true);\n return sender;\n }\n\n let lp_poller = (url_, resolve, reject) => {\n let poller = new XHRProvider();\n let promiseCompleted = false;\n\n poller.onreadystatechange = evt => {\n if (poller.readyState == XDR_DONE) {\n if (poller.status == 201) { // 201 == HTTP.Created, get SID\n let pkt = JSON.parse(poller.responseText, jsonParseHelper);\n _lpURL = url_ + '&sid=' + pkt.ctrl.params.sid;\n poller = lp_poller(_lpURL);\n poller.send(null);\n if (this.onOpen) {\n this.onOpen();\n }\n\n if (resolve) {\n promiseCompleted = true;\n resolve();\n }\n\n if (this.autoreconnect) {\n this.#boffStop();\n }\n } else if (poller.status > 0 && poller.status < 400) { // 0 = network error; 400 = HTTP.BadRequest\n if (this.onMessage) {\n this.onMessage(poller.responseText);\n }\n poller = lp_poller(_lpURL);\n poller.send(null);\n } else {\n // Don't throw an error here, gracefully handle server errors\n if (reject && !promiseCompleted) {\n promiseCompleted = true;\n reject(poller.responseText);\n }\n if (this.onMessage && poller.responseText) {\n this.onMessage(poller.responseText);\n }\n if (this.onDisconnect) {\n const code = poller.status || (this.#boffClosed ? NETWORK_USER : NETWORK_ERROR);\n const text = poller.responseText || (this.#boffClosed ? NETWORK_USER_TEXT : NETWORK_ERROR_TEXT);\n this.onDisconnect(new CommError(text, code), code);\n }\n\n // Polling has stopped. Indicate it by setting poller to null.\n poller = null;\n if (!this.#boffClosed && this.autoreconnect) {\n this.#boffReconnect();\n }\n }\n }\n };\n // Using POST to avoid caching response by service worker.\n poller.open('POST', url_, true);\n return poller;\n }\n\n this.connect = (host_, force) => {\n this.#boffClosed = false;\n\n if (_poller) {\n if (!force) {\n return Promise.resolve();\n }\n _poller.onreadystatechange = undefined;\n _poller.abort();\n _poller = null;\n }\n\n if (host_) {\n this.host = host_;\n }\n\n return new Promise((resolve, reject) => {\n const url = makeBaseUrl(this.host, this.secure ? 'https' : 'http', this.version, this.apiKey);\n Connection.#log(\"LP connecting to:\", url);\n _poller = lp_poller(url, resolve, reject);\n _poller.send(null);\n }).catch(err => {\n Connection.#log(\"LP connection failed:\", err);\n });\n };\n\n this.reconnect = force => {\n this.#boffStop();\n this.connect(null, force);\n };\n\n this.disconnect = _ => {\n this.#boffClosed = true;\n this.#boffStop();\n\n if (_sender) {\n _sender.onreadystatechange = undefined;\n _sender.abort();\n _sender = null;\n }\n if (_poller) {\n _poller.onreadystatechange = undefined;\n _poller.abort();\n _poller = null;\n }\n\n if (this.onDisconnect) {\n this.onDisconnect(new CommError(NETWORK_USER_TEXT, NETWORK_USER), NETWORK_USER);\n }\n // Ensure it's reconstructed\n _lpURL = null;\n };\n\n this.sendText = (msg) => {\n _sender = lp_sender(_lpURL);\n if (_sender && (_sender.readyState == XDR_OPENED)) {\n _sender.send(msg);\n } else {\n throw new Error(\"Long poller failed to connect\");\n }\n };\n\n this.isConnected = _ => {\n return (_poller && true);\n };\n }\n\n // Initialization for Websocket\n #init_ws() {\n this.connect = (host_, force) => {\n this.#boffClosed = false;\n\n if (this.#socket) {\n if (!force && this.#socket.readyState == this.#socket.OPEN) {\n // Issue a probe request to be sure the connection is live.\n // This is a non-blocking call.\n this.probe();\n return Promise.resolve();\n }\n this.#socket.close();\n this.#socket = null;\n }\n\n if (host_) {\n this.host = host_;\n }\n\n return new Promise((resolve, reject) => {\n const url = makeBaseUrl(this.host, this.secure ? 'wss' : 'ws', this.version, this.apiKey);\n\n Connection.#log(\"WS connecting to: \", url);\n\n // It throws when the server is not accessible but the exception cannot be caught:\n // https://stackoverflow.com/questions/31002592/javascript-doesnt-catch-error-in-websocket-instantiation/31003057\n const conn = new WebSocketProvider(url);\n\n conn.onerror = err => {\n reject(err);\n };\n\n conn.onopen = _ => {\n if (this.autoreconnect) {\n this.#boffStop();\n }\n\n if (this.onOpen) {\n this.onOpen();\n }\n\n resolve();\n };\n\n conn.onclose = _ => {\n this.#socket = null;\n\n if (this.onDisconnect) {\n const code = this.#boffClosed ? NETWORK_USER : NETWORK_ERROR;\n this.onDisconnect(new CommError(this.#boffClosed ? NETWORK_USER_TEXT : NETWORK_ERROR_TEXT, code), code);\n }\n\n if (!this.#boffClosed && this.autoreconnect) {\n this.#boffReconnect();\n }\n };\n\n conn.onmessage = evt => {\n if (this.onMessage) {\n this.onMessage(evt.data);\n }\n };\n\n this.#socket = conn;\n });\n }\n\n this.reconnect = force => {\n this.#boffStop();\n this.connect(null, force);\n };\n\n this.disconnect = _ => {\n this.#boffClosed = true;\n this.#boffStop();\n\n if (!this.#socket) {\n return;\n }\n this.#socket.close();\n this.#socket = null;\n };\n\n this.sendText = msg => {\n if (this.#socket && (this.#socket.readyState == this.#socket.OPEN)) {\n this.#socket.send(msg);\n } else {\n throw new Error(\"Websocket is not connected\");\n }\n };\n\n this.isConnected = _ => {\n return (this.#socket && (this.#socket.readyState == this.#socket.OPEN));\n };\n }\n\n // Callbacks:\n\n /**\n * A callback to pass incoming messages to. See {@link Tinode.Connection#onMessage}.\n * @callback Tinode.Connection.OnMessage\n * @memberof Tinode.Connection\n * @param {string} message - Message to process.\n */\n onMessage = undefined;\n\n /**\n * A callback for reporting a dropped connection.\n * @type {function}\n * @memberof Tinode.Connection#\n */\n onDisconnect = undefined;\n\n /**\n * A callback called when the connection is ready to be used for sending. For websockets it's socket open,\n * for long polling it's readyState=1 (OPENED)\n * @type {function}\n * @memberof Tinode.Connection#\n */\n onOpen = undefined;\n\n /**\n * A callback to notify of reconnection attempts. See {@link Tinode.Connection#onAutoreconnectIteration}.\n * @memberof Tinode.Connection\n * @callback AutoreconnectIterationType\n * @param {string} timeout - time till the next reconnect attempt in milliseconds. -1 means reconnect was skipped.\n * @param {Promise} promise resolved or rejected when the reconnect attemp completes.\n *\n */\n /**\n * A callback to inform when the next attampt to reconnect will happen and to receive connection promise.\n * @memberof Tinode.Connection#\n * @type {Tinode.Connection.AutoreconnectIterationType}\n */\n onAutoreconnectIteration = undefined;\n}\n\nConnection.NETWORK_ERROR = NETWORK_ERROR;\nConnection.NETWORK_ERROR_TEXT = NETWORK_ERROR_TEXT;\nConnection.NETWORK_USER = NETWORK_USER;\nConnection.NETWORK_USER_TEXT = NETWORK_USER_TEXT;\n","/**\n * @file Helper methods for dealing with IndexedDB cache of messages, users, and topics.\n *\n * @copyright 2015-2025 Tinode LLC.\n */\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\nconst DB_VERSION = 3;\nconst DB_NAME = 'tinode-web';\n\nlet IDBProvider;\n\nexport default class DB {\n #onError = _ => {};\n #logger = _ => {};\n\n // Instance of IndexDB.\n db = null;\n // Indicator that the cache is disabled.\n disabled = true;\n\n constructor(onError, logger) {\n this.#onError = onError || this.#onError;\n this.#logger = logger || this.#logger;\n }\n\n #mapObjects(source, callback, context) {\n if (!this.db) {\n return disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction([source]);\n trx.onerror = event => {\n this.#logger('PCache', 'mapObjects', source, event.target.error);\n reject(event.target.error);\n };\n trx.objectStore(source).getAll().onsuccess = event => {\n if (callback) {\n event.target.result.forEach(topic => {\n callback.call(context, topic);\n });\n }\n resolve(event.target.result);\n };\n });\n }\n\n /**\n * Initialize persistent cache: open or create/upgrade if needed.\n * @returns {Promise} promise to be resolved/rejected when the DB is initialized.\n */\n initDatabase() {\n return new Promise((resolve, reject) => {\n // Open the database and initialize callbacks.\n const req = IDBProvider.open(DB_NAME, DB_VERSION);\n req.onsuccess = event => {\n this.db = event.target.result;\n this.disabled = false;\n\n // This handler is called when a different tab tries to upgrade the database.\n this.db.onversionchange = _ => {\n this.#logger('PCache', \"another tab tries to upgrade DB, shutting down\");\n this.db.close();\n this.db = null;\n this.disabled = true;\n };\n\n resolve(this.db);\n };\n req.onerror = event => {\n this.#logger('PCache', \"failed to initialize\", event);\n reject(event.target.error);\n this.#onError(event.target.error);\n };\n req.onupgradeneeded = event => {\n this.db = event.target.result;\n\n this.db.onerror = event => {\n this.#logger('PCache', \"failed to create storage\", event);\n this.#onError(event.target.error);\n };\n\n // Individual object stores.\n\n // Alternatively could use event.oldVersion and event.newVersion\n // to determine which object stores to create or upgrade.\n\n if (!this.db.objectStoreNames.contains('topic')) {\n // Object store (table) for topics. The primary key is the topic name.\n this.db.createObjectStore('topic', {\n keyPath: 'name'\n });\n }\n\n if (!this.db.objectStoreNames.contains('user')) {\n // Users object store. UID is the primary key.\n this.db.createObjectStore('user', {\n keyPath: 'uid'\n });\n }\n\n if (!this.db.objectStoreNames.contains('subscription')) {\n // Subscriptions object store topic <-> user. Topic name + UID is the primary key.\n this.db.createObjectStore('subscription', {\n keyPath: ['topic', 'uid']\n });\n }\n\n if (!this.db.objectStoreNames.contains('message')) {\n // Messages object store. The primary key is topic name + seq.\n this.db.createObjectStore('message', {\n keyPath: ['topic', 'seq']\n });\n }\n\n if (!this.db.objectStoreNames.contains('dellog')) {\n // Records of deleted message ranges. The primary key is topic name + low seq.\n const dellog = this.db.createObjectStore('dellog', {\n keyPath: ['topic', 'low', 'hi']\n });\n if (!dellog.indexNames.contains('topic_clear')) {\n dellog.createIndex('topic_clear', ['topic', 'clear'], {\n unique: false\n });\n }\n }\n }\n });\n }\n\n /**\n * Delete persistent cache.\n */\n deleteDatabase() {\n // Close connection, otherwise operations will fail with 'onblocked'.\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n return new Promise((resolve, reject) => {\n const req = IDBProvider.deleteDatabase(DB_NAME);\n req.onblocked = _ => {\n if (this.db) {\n this.db.close();\n }\n const err = new Error(\"blocked\");\n this.#logger('PCache', 'deleteDatabase', err);\n reject(err);\n };\n req.onsuccess = _ => {\n this.db = null;\n this.disabled = true;\n resolve(true);\n };\n req.onerror = event => {\n this.#logger('PCache', 'deleteDatabase', event.target.error);\n reject(event.target.error);\n };\n });\n }\n\n /**\n * Check if persistent cache is ready for use.\n * @memberOf DB\n * @returns {boolean} true if cache is ready, false otherwise.\n */\n isReady() {\n return !!this.db;\n }\n\n // Topics.\n\n /**\n * Save to cache or update topic in persistent cache.\n * @memberOf DB\n * @param {Topic} topic - topic to be added or updated.\n * @returns {Promise} promise resolved/rejected on operation completion.\n */\n updTopic(topic) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['topic'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updTopic', event.target.error);\n reject(event.target.error);\n };\n const req = trx.objectStore('topic').get(topic.name);\n req.onsuccess = _ => {\n trx.objectStore('topic').put(DB.#serializeTopic(req.result, topic));\n trx.commit();\n };\n });\n }\n\n /**\n * Mark or unmark topic as deleted.\n * @memberOf DB\n * @param {string} name - name of the topic to mark or unmark.\n * @param {boolean} deleted - status\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n markTopicAsDeleted(name, deleted) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['topic'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'markTopicAsDeleted', event.target.error);\n reject(event.target.error);\n };\n const req = trx.objectStore('topic').get(name);\n req.onsuccess = event => {\n const topic = event.target.result;\n if (topic && topic._deleted != deleted) {\n topic._deleted = deleted;\n trx.objectStore('topic').put(topic);\n }\n trx.commit();\n };\n });\n }\n\n /**\n * Remove topic from persistent cache.\n * @memberOf DB\n * @param {string} name - name of the topic to remove from database.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n remTopic(name) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['topic', 'subscription', 'message'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'remTopic', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('topic').delete(IDBKeyRange.only(name));\n trx.objectStore('subscription').delete(IDBKeyRange.bound([name, '-'], [name, '~']));\n trx.objectStore('message').delete(IDBKeyRange.bound([name, 0], [name, Number.MAX_SAFE_INTEGER]));\n trx.commit();\n });\n }\n\n /**\n * Execute a callback for each stored topic.\n * @memberOf DB\n * @param {function} callback - function to call for each topic.\n * @param {Object} context - the value or this inside the callback.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n mapTopics(callback, context) {\n return this.#mapObjects('topic', callback, context);\n }\n\n /**\n * Copy data from serialized object to topic.\n * @memberOf DB\n * @param {Topic} topic - target to deserialize to.\n * @param {Object} src - serialized data to copy from.\n */\n deserializeTopic(topic, src) {\n DB.#deserializeTopic(topic, src);\n }\n\n // Users.\n /**\n * Add or update user object in the persistent cache.\n * @memberOf DB\n * @param {string} uid - ID of the user to save or update.\n * @param {Object} pub - user's public information.\n * @returns {Promise} promise resolved/rejected on operation completion.\n */\n updUser(uid, pub) {\n if (arguments.length < 2 || pub === undefined) {\n // No point inupdating user with invalid data.\n return;\n }\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['user'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updUser', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('user').put({\n uid: uid,\n public: pub\n });\n trx.commit();\n });\n }\n\n /**\n * Remove user from persistent cache.\n * @memberOf DB\n * @param {string} uid - ID of the user to remove from the cache.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n remUser(uid) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['user'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'remUser', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('user').delete(IDBKeyRange.only(uid));\n trx.commit();\n });\n }\n\n /**\n * Execute a callback for each stored user.\n * @memberOf DB\n * @param {function} callback - function to call for each topic.\n * @param {Object} context - the value or this inside the callback.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n mapUsers(callback, context) {\n return this.#mapObjects('user', callback, context);\n }\n\n /**\n * Read a single user from persistent cache.\n * @memberOf DB\n * @param {string} uid - ID of the user to fetch from cache.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n getUser(uid) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['user']);\n trx.oncomplete = event => {\n const user = event.target.result;\n resolve({\n user: user.uid,\n public: user.public\n });\n };\n trx.onerror = event => {\n this.#logger('PCache', 'getUser', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('user').get(uid);\n });\n }\n\n // Subscriptions.\n /**\n * Add or update subscription in persistent cache.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {string} uid - ID of the subscribed user.\n * @param {Object} sub - subscription to save.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n updSubscription(topicName, uid, sub) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['subscription'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updSubscription', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('subscription').get([topicName, uid]).onsuccess = (event) => {\n trx.objectStore('subscription').put(DB.#serializeSubscription(event.target.result, topicName, uid, sub));\n trx.commit();\n };\n });\n }\n\n /**\n * Execute a callback for each cached subscription in a given topic.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the subscriptions.\n * @param {function} callback - function to call for each subscription.\n * @param {Object} context - the value or this inside the callback.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n mapSubscriptions(topicName, callback, context) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['subscription']);\n trx.onerror = (event) => {\n this.#logger('PCache', 'mapSubscriptions', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('subscription').getAll(IDBKeyRange.bound([topicName, '-'], [topicName, '~'])).onsuccess = (event) => {\n if (callback) {\n event.target.result.forEach((topic) => {\n callback.call(context, topic);\n });\n }\n resolve(event.target.result);\n };\n });\n }\n\n // Messages.\n\n /**\n * Save message to persistent cache.\n * @memberOf DB\n * @param {Object} msg - message to save.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n addMessage(msg) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['message'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'addMessage', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('message').add(DB.#serializeMessage(null, msg));\n trx.commit();\n });\n }\n\n /**\n * Update delivery status of a message stored in persistent cache.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {number} seq - ID of the message to update\n * @param {number} status - new delivery status of the message.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n updMessageStatus(topicName, seq, status) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['message'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updMessageStatus', event.target.error);\n reject(event.target.error);\n };\n const req = trx.objectStore('message').get(IDBKeyRange.only([topicName, seq]));\n req.onsuccess = event => {\n const src = req.result || event.target.result;\n if (!src || src._status == status) {\n trx.commit();\n return;\n }\n trx.objectStore('message').put(DB.#serializeMessage(src, {\n topic: topicName,\n seq: seq,\n _status: status\n }));\n trx.commit();\n };\n });\n }\n\n /**\n * Remove one or more messages from persistent cache.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {number} from - id of the message to remove or lower boundary when removing range (inclusive).\n * @param {number=} to - upper boundary (exclusive) when removing a range of messages.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n remMessages(topicName, from, to) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n if (!from && !to) {\n from = 0;\n to = Number.MAX_SAFE_INTEGER;\n }\n const range = to > 0 ? IDBKeyRange.bound([topicName, from], [topicName, to], false, true) :\n IDBKeyRange.only([topicName, from]);\n const trx = this.db.transaction(['message'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'remMessages', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('message').delete(range);\n trx.commit();\n });\n }\n\n /**\n * Retrieve messages from persistent store.\n * @memberOf DB\n * @param {string} topicName - name of the topic to retrieve messages from.\n * @param {function} callback to call for each retrieved message.\n * @param {GetDataType} query - parameters of the message range to retrieve.\n *\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n readMessages(topicName, query, callback, context) {\n query = query || {};\n\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n const trx = this.db.transaction(['message']);\n let result = [];\n\n // Handle individual message ranges.\n if (Array.isArray(query.ranges)) {\n return new Promise((resolve, reject) => {\n trx.onerror = event => {\n this.#logger('PCache', 'readMessages', event.target.error);\n reject(event.target.error);\n };\n\n let count = 0;\n query.ranges.forEach(range => {\n const key = range.hi ? IDBKeyRange.bound([topicName, range.low], [topicName, range.hi], false, true) :\n IDBKeyRange.only([topicName, range.low]);\n trx.objectStore('message').getAll(key).onsuccess = event => {\n const msgs = event.target.result;\n if (msgs) {\n if (callback) {\n callback.call(context, msgs);\n }\n if (Array.isArray(msgs)) {\n result = result.concat(msgs);\n } else {\n result.push(msgs);\n }\n }\n count++;\n if (count == query.ranges.length) {\n resolve(result);\n }\n };\n });\n });\n }\n\n // Handle single range.\n return new Promise((resolve, reject) => {\n const since = query.since > 0 ? query.since : 0;\n const before = query.before > 0 ? query.before : Number.MAX_SAFE_INTEGER;\n const limit = query.limit | 0;\n\n trx.onerror = event => {\n this.#logger('PCache', 'readMessages', event.target.error);\n reject(event.target.error);\n };\n\n const range = IDBKeyRange.bound([topicName, since], [topicName, before], false, true);\n // Iterate in descending order.\n trx.objectStore('message').openCursor(range, 'prev')\n .onsuccess = event => {\n const cursor = event.target.result;\n if (cursor) {\n if (callback) {\n callback.call(context, cursor.value);\n }\n result.push(cursor.value);\n if (limit <= 0 || result.length < limit) {\n cursor.continue();\n } else {\n resolve(result);\n }\n } else {\n resolve(result);\n }\n };\n });\n }\n\n // Delete log\n\n /**\n * Add records of deleted messages.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {number} delId - id of the deletion transaction.\n * @param {Array.} ranges - message to save.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n addDelLog(topicName, delId, ranges) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['dellog'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'addDelLog', event.target.error);\n reject(event.target.error);\n };\n ranges.forEach(r => trx.objectStore('dellog').add({\n topic: topicName,\n clear: delId,\n low: r.low,\n hi: r.hi || (r.low + 1)\n }));\n trx.commit();\n });\n }\n\n /**\n * Retrieve deleted message records from persistent store.\n * @memberOf DB\n * @param {string} topicName - name of the topic to retrieve records for.\n * @param {GetDataType} query - parameters of the message range to retrieve.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n readDelLog(topicName, query) {\n query = query || {};\n\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n const trx = this.db.transaction(['dellog']);\n let result = [];\n\n // Handle individual message ranges.\n if (Array.isArray(query.ranges)) {\n return new Promise((resolve, reject) => {\n trx.onerror = event => {\n this.#logger('PCache', 'readDelLog', event.target.error);\n reject(event.target.error);\n };\n\n let count = 0;\n query.ranges.forEach(range => {\n const hi = range.hi || (range.low + 1);\n const key = IDBKeyRange.bound([topicName, 0, range.low], [topicName, hi, Number.MAX_SAFE_INTEGER], false, true);\n trx.objectStore('dellog').getAll(key).onsuccess = event => {\n const entries = event.target.result;\n if (entries) {\n if (Array.isArray(entries)) {\n result = result.concat(entries.map(entry => {\n return {\n low: entry.low,\n hi: entry.hi\n };\n }));\n } else {\n result.push({\n low: entries.low,\n hi: entries.hi\n });\n }\n }\n count++;\n if (count == query.ranges.length) {\n resolve(result);\n }\n };\n });\n });\n }\n\n return new Promise((resolve, reject) => {\n const since = query.since > 0 ? query.since : 0;\n const before = query.before > 0 ? query.before : Number.MAX_SAFE_INTEGER;\n const limit = query.limit | 0;\n\n trx.onerror = event => {\n this.#logger('PCache', 'readDelLog', event.target.error);\n reject(event.target.error);\n };\n\n let count = 0;\n const result = [];\n const range = IDBKeyRange.bound([topicName, 0, since], [topicName, before, Number.MAX_SAFE_INTEGER], false, true);\n trx.objectStore('dellog').openCursor(range, 'prev')\n .onsuccess = event => {\n const cursor = event.target.result;\n if (cursor) {\n result.push({\n low: cursor.value.low,\n hi: cursor.value.hi\n });\n count += cursor.value.hi - cursor.value.low;\n if (limit <= 0 || count < limit) {\n cursor.continue();\n } else {\n resolve(result);\n }\n } else {\n resolve(result);\n }\n };\n });\n }\n\n /**\n * Retrieve the latest 'clear' ID for the given topic.\n * @param {string} topicName\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n maxDelId(topicName) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve(0) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['dellog']);\n trx.onerror = event => {\n this.#logger('PCache', 'maxDelId', event.target.error);\n reject(event.target.error);\n };\n\n const index = trx.objectStore('dellog').index('topic_clear');\n index.openCursor(IDBKeyRange.bound([topicName, 0], [topicName, Number.MAX_SAFE_INTEGER]), 'prev')\n .onsuccess = event => {\n if (event.target.result) {\n resolve(event.target.result.value);\n }\n };\n });\n }\n\n // Private methods.\n\n // Serializable topic fields.\n static #topic_fields = ['created', 'updated', 'deleted', 'touched', 'read', 'recv', 'seq',\n 'clear', 'defacs', 'creds', 'public', 'trusted', 'private', '_aux', '_deleted'\n ];\n\n // Copy data from src to Topic object.\n static #deserializeTopic(topic, src) {\n DB.#topic_fields.forEach((f) => {\n if (src.hasOwnProperty(f)) {\n topic[f] = src[f];\n }\n });\n if (Array.isArray(src.tags)) {\n topic._tags = src.tags;\n }\n if (src.acs) {\n topic.setAccessMode(src.acs);\n }\n topic.seq |= 0;\n topic.read |= 0;\n topic.unread = Math.max(0, topic.seq - topic.read);\n }\n\n // Copy values from 'src' to 'dst'. Allocate dst if it's null or undefined.\n static #serializeTopic(dst, src) {\n const res = dst || {\n name: src.name\n };\n DB.#topic_fields.forEach(f => {\n if (src.hasOwnProperty(f)) {\n res[f] = src[f];\n }\n });\n if (Array.isArray(src._tags)) {\n res.tags = src._tags;\n }\n if (src.acs) {\n res.acs = src.getAccessMode().jsonHelper();\n }\n return res;\n }\n\n static #serializeSubscription(dst, topicName, uid, sub) {\n const fields = ['updated', 'mode', 'read', 'recv', 'clear', 'lastSeen', 'userAgent'];\n const res = dst || {\n topic: topicName,\n uid: uid\n };\n\n fields.forEach((f) => {\n if (sub.hasOwnProperty(f)) {\n res[f] = sub[f];\n }\n });\n\n return res;\n }\n\n static #serializeMessage(dst, msg) {\n // Serializable fields.\n const fields = ['topic', 'seq', 'ts', '_status', 'from', 'head', 'content'];\n const res = dst || {};\n fields.forEach((f) => {\n if (msg.hasOwnProperty(f)) {\n res[f] = msg[f];\n }\n });\n return res;\n }\n\n /**\n * To use DB in a non browser context, supply indexedDB provider.\n * @static\n * @memberof DB\n * @param idbProvider indexedDB provider, e.g. for node require('fake-indexeddb').\n */\n static setDatabaseProvider(idbProvider) {\n IDBProvider = idbProvider;\n }\n}\n","/**\n * @file Utilities for uploading and downloading files.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport CommError from './comm-error.js';\nimport {\n isUrlRelative,\n jsonParseHelper\n} from './utils.js';\n\nlet XHRProvider;\n\nfunction addURLParam(relUrl, key, value) {\n const url = new URL(relUrl, window.location.origin);\n url.searchParams.append(key, value);\n return url.toString().substring(window.location.origin.length);\n}\n\n/**\n * @class LargeFileHelper - utilities for uploading and downloading files out of band.\n * Don't instantiate this class directly. Use {Tinode.getLargeFileHelper} instead.\n * @memberof Tinode\n *\n * @param {Tinode} tinode - the main Tinode object.\n * @param {string} version - protocol version, i.e. '0'.\n */\nexport default class LargeFileHelper {\n constructor(tinode, version) {\n this._tinode = tinode;\n this._version = version;\n\n this._apiKey = tinode._apiKey;\n this._authToken = tinode.getAuthToken();\n\n // Ongoing requests.\n this.xhr = [];\n }\n\n /**\n * Start uploading the file to an endpoint at baseUrl.\n *\n * @memberof Tinode.LargeFileHelper#\n *\n * @param {string} baseUrl base URL of upload server.\n * @param {File|Blob} data data to upload.\n * @param {string} avatarFor topic name if the upload represents an avatar.\n * @param {Callback} onProgress callback. Takes one {float} parameter 0..1\n * @param {Callback} onSuccess callback. Called when the file is successfully uploaded.\n * @param {Callback} onFailure callback. Called in case of a failure.\n *\n * @returns {Promise} resolved/rejected when the upload is completed/failed.\n */\n uploadWithBaseUrl(baseUrl, data, avatarFor, onProgress, onSuccess, onFailure) {\n let url = `/v${this._version}/file/u/`;\n if (baseUrl) {\n let base = baseUrl;\n if (base.endsWith('/')) {\n // Removing trailing slash.\n base = base.slice(0, -1);\n }\n if (base.startsWith('http://') || base.startsWith('https://')) {\n url = base + url;\n } else {\n throw new Error(`Invalid base URL '${baseUrl}'`);\n }\n }\n\n const instance = this;\n const xhr = new XHRProvider();\n this.xhr.push(xhr);\n\n xhr.open('POST', url, true);\n xhr.setRequestHeader('X-Tinode-APIKey', this._apiKey);\n if (this._authToken) {\n xhr.setRequestHeader('X-Tinode-Auth', `Token ${this._authToken.token}`);\n }\n\n let toResolve = null;\n let toReject = null;\n\n const result = new Promise((resolve, reject) => {\n toResolve = resolve;\n toReject = reject;\n });\n\n xhr.upload.onprogress = e => {\n if (e.lengthComputable) {\n if (onProgress) {\n onProgress(e.loaded / e.total);\n }\n if (this.onProgress) {\n this.onProgress(e.loaded / e.total);\n }\n }\n };\n\n xhr.onload = function() {\n let pkt;\n try {\n pkt = JSON.parse(this.response, jsonParseHelper);\n } catch (err) {\n instance._tinode.logger(\"ERROR: Invalid server response in LargeFileHelper\", this.response);\n pkt = {\n ctrl: {\n code: this.status,\n text: this.statusText\n }\n };\n }\n\n if (this.status >= 200 && this.status < 300) {\n if (toResolve) {\n toResolve(pkt.ctrl.params.url);\n }\n if (onSuccess) {\n onSuccess(pkt.ctrl);\n }\n } else if (this.status >= 400) {\n if (toReject) {\n toReject(new CommError(pkt.ctrl.text, pkt.ctrl.code));\n }\n if (onFailure) {\n onFailure(pkt.ctrl);\n }\n } else {\n instance._tinode.logger(\"ERROR: Unexpected server response status\", this.status, this.response);\n }\n };\n\n xhr.onerror = function(e) {\n if (toReject) {\n toReject(e || new Error(\"failed\"));\n }\n if (onFailure) {\n onFailure(null);\n }\n };\n\n xhr.onabort = function(e) {\n if (toReject) {\n toReject(new Error(\"upload cancelled by user\"));\n }\n if (onFailure) {\n onFailure(null);\n }\n };\n\n try {\n const form = new FormData();\n form.append('file', data);\n form.set('id', this._tinode.getNextUniqueId());\n if (avatarFor) {\n form.set('topic', avatarFor);\n }\n xhr.send(form);\n } catch (err) {\n if (toReject) {\n toReject(err);\n }\n if (onFailure) {\n onFailure(null);\n }\n }\n\n return result;\n }\n /**\n * Start uploading the file to default endpoint.\n *\n * @memberof Tinode.LargeFileHelper#\n *\n * @param {File|Blob} data to upload\n * @param {string} avatarFor topic name if the upload represents an avatar.\n * @param {Callback} onProgress callback. Takes one {float} parameter 0..1\n * @param {Callback} onSuccess callback. Called when the file is successfully uploaded.\n * @param {Callback} onFailure callback. Called in case of a failure.\n *\n * @returns {Promise} resolved/rejected when the upload is completed/failed.\n */\n upload(data, avatarFor, onProgress, onSuccess, onFailure) {\n const baseUrl = (this._tinode._secure ? 'https://' : 'http://') + this._tinode._host;\n return this.uploadWithBaseUrl(baseUrl, data, avatarFor, onProgress, onSuccess, onFailure);\n }\n /**\n * Download the file from a given URL using GET request. This method works with the Tinode server only.\n *\n * @memberof Tinode.LargeFileHelper#\n *\n * @param {string} relativeUrl - URL to download the file from. Must be relative url, i.e. must not contain the host.\n * @param {string=} filename - file name to use for the downloaded file.\n *\n * @returns {Promise} resolved/rejected when the download is completed/failed.\n */\n download(relativeUrl, filename, mimetype, onProgress, onError) {\n if (!isUrlRelative(relativeUrl)) {\n // As a security measure refuse to download from an absolute URL.\n if (onError) {\n onError(`The URL '${relativeUrl}' must be relative, not absolute`);\n }\n return;\n }\n if (!this._authToken) {\n if (onError) {\n onError(\"Must authenticate first\");\n }\n return;\n }\n const instance = this;\n\n const xhr = new XHRProvider();\n this.xhr.push(xhr);\n\n // Add '&asatt=1' to URL to request 'Content-Disposition: attachment' response header.\n relativeUrl = addURLParam(relativeUrl, 'asatt', '1');\n\n // Get data as blob (stored by the browser as a temporary file).\n xhr.open('GET', relativeUrl, true);\n xhr.setRequestHeader('X-Tinode-APIKey', this._apiKey);\n xhr.setRequestHeader('X-Tinode-Auth', 'Token ' + this._authToken.token);\n xhr.responseType = 'blob';\n\n xhr.onprogress = function(e) {\n if (onProgress) {\n // Passing e.loaded instead of e.loaded/e.total because e.total\n // is always 0 with gzip compression enabled by the server.\n onProgress(e.loaded);\n }\n };\n\n let toResolve = null;\n let toReject = null;\n\n const result = new Promise((resolve, reject) => {\n toResolve = resolve;\n toReject = reject;\n });\n\n // The blob needs to be saved as file. There is no known way to\n // save the blob as file other than to fake a click on an .\n xhr.onload = function() {\n if (this.status == 200) {\n const link = document.createElement('a');\n // URL.createObjectURL is not available in non-browser environment. This call will fail.\n link.href = window.URL.createObjectURL(new Blob([this.response], {\n type: mimetype\n }));\n link.style.display = 'none';\n link.setAttribute('download', filename);\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n window.URL.revokeObjectURL(link.href);\n if (toResolve) {\n toResolve();\n }\n } else if (this.status >= 400 && toReject) {\n // The this.responseText is undefined, must use this.response which is a blob.\n // Need to convert this.response to JSON. The blob can only be accessed by the\n // FileReader.\n const reader = new FileReader();\n reader.onload = function() {\n try {\n const pkt = JSON.parse(this.result, jsonParseHelper);\n toReject(new CommError(pkt.ctrl.text, pkt.ctrl.code));\n } catch (err) {\n instance._tinode.logger(\"ERROR: Invalid server response in LargeFileHelper\", this.result);\n toReject(err);\n }\n };\n reader.readAsText(this.response);\n }\n };\n\n xhr.onerror = function(e) {\n if (toReject) {\n toReject(new Error(\"failed\"));\n }\n if (onError) {\n onError(e);\n }\n };\n\n xhr.onabort = function() {\n if (toReject) {\n toReject(null);\n }\n };\n\n try {\n xhr.send();\n } catch (err) {\n if (toReject) {\n toReject(err);\n }\n if (onError) {\n onError(err);\n }\n }\n\n return result;\n }\n /**\n * Try to cancel all ongoing uploads or downloads.\n * @memberof Tinode.LargeFileHelper#\n */\n cancel() {\n this.xhr.forEach(req => {\n if (req.readyState < 4) {\n req.abort();\n }\n });\n }\n /**\n * To use LargeFileHelper in a non browser context, supply XMLHttpRequest provider.\n * @static\n * @memberof LargeFileHelper\n * @param xhrProvider XMLHttpRequest provider, e.g. for node require('xhr').\n */\n static setNetworkProvider(xhrProvider) {\n XHRProvider = xhrProvider;\n }\n}\n","/**\n * @module tinode-sdk\n *\n * @copyright 2015-2025 Tinode LLC.\n * @summary Javascript bindings for Tinode.\n * @license Apache 2.0\n * @version 0.24\n *\n * See https://github.com/tinode/webapp for real-life usage.\n *\n * @example\n * \n * \n * \n *\n * \n * ...\n * \n * \n */\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\nimport AccessMode from './access-mode.js';\nimport * as Const from './config.js';\nimport CommError from './comm-error.js';\nimport Connection from './connection.js';\nimport DBCache from './db.js';\nimport Drafty from './drafty.js';\nimport LargeFileHelper from './large-file.js';\nimport MetaGetBuilder from './meta-builder.js';\nimport Topic from './topic.js';\nimport TopicFnd from './fnd-topic.js';\nimport TopicMe from './me-topic.js';\n\nimport {\n isUrlRelative,\n jsonParseHelper,\n mergeObj,\n rfc3339DateString,\n simplify\n} from './utils.js';\n\n// Re-export AccessMode\nexport {\n AccessMode\n};\n\nlet WebSocketProvider;\nif (typeof WebSocket != 'undefined') {\n WebSocketProvider = WebSocket;\n}\n\nlet XHRProvider;\nif (typeof XMLHttpRequest != 'undefined') {\n XHRProvider = XMLHttpRequest;\n}\n\nlet IndexedDBProvider;\nif (typeof indexedDB != 'undefined') {\n IndexedDBProvider = indexedDB;\n}\n\n// Re-export Drafty.\nexport {\n Drafty\n}\n\ninitForNonBrowserApp();\n\n// Utility functions\n\n// Polyfill for non-browser context, e.g. NodeJs.\nfunction initForNonBrowserApp() {\n // Tinode requirement in native mode because react native doesn't provide Base64 method\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n\n if (typeof btoa == 'undefined') {\n global.btoa = function(input = '') {\n let str = input;\n let output = '';\n\n for (let block = 0, charCode, i = 0, map = chars; str.charAt(i | 0) || (map = '=', i % 1); output += map.charAt(63 & block >> 8 - i % 1 * 8)) {\n\n charCode = str.charCodeAt(i += 3 / 4);\n\n if (charCode > 0xFF) {\n throw new Error(\"'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.\");\n }\n block = block << 8 | charCode;\n }\n\n return output;\n };\n }\n\n if (typeof atob == 'undefined') {\n global.atob = function(input = '') {\n let str = input.replace(/=+$/, '');\n let output = '';\n\n if (str.length % 4 == 1) {\n throw new Error(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n for (let bc = 0, bs = 0, buffer, i = 0; buffer = str.charAt(i++);\n\n ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,\n bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0\n ) {\n buffer = chars.indexOf(buffer);\n }\n\n return output;\n };\n }\n\n if (typeof window == 'undefined') {\n global.window = {\n WebSocket: WebSocketProvider,\n XMLHttpRequest: XHRProvider,\n indexedDB: IndexedDBProvider,\n URL: {\n createObjectURL: function() {\n throw new Error(\"Unable to use URL.createObjectURL in a non-browser application\");\n }\n }\n }\n }\n\n Connection.setNetworkProviders(WebSocketProvider, XHRProvider);\n LargeFileHelper.setNetworkProvider(XHRProvider);\n DBCache.setDatabaseProvider(IndexedDBProvider);\n}\n\n// Detect find most useful network transport.\nfunction detectTransport() {\n if (typeof window == 'object') {\n if (window['WebSocket']) {\n return 'ws';\n } else if (window['XMLHttpRequest']) {\n // The browser or node has no websockets, using long polling.\n return 'lp';\n }\n }\n return null;\n}\n\n// btoa replacement. Stock btoa fails on on non-Latin1 strings.\nfunction b64EncodeUnicode(str) {\n // The encodeURIComponent percent-encodes UTF-8 string,\n // then the percent encoding is converted into raw bytes which\n // can be fed into btoa.\n return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,\n function toSolidBytes(match, p1) {\n return String.fromCharCode('0x' + p1);\n }));\n}\n\n// JSON stringify helper - pre-processor for JSON.stringify\nfunction jsonBuildHelper(key, val) {\n if (val instanceof Date) {\n // Convert javascript Date objects to rfc3339 strings\n val = rfc3339DateString(val);\n } else if (val instanceof AccessMode) {\n val = val.jsonHelper();\n } else if (val === undefined || val === null || val === false ||\n (Array.isArray(val) && val.length == 0) ||\n ((typeof val == 'object') && (Object.keys(val).length == 0))) {\n // strip out empty elements while serializing objects to JSON\n return undefined;\n }\n\n return val;\n};\n\n// Trims very long strings (encoded images) to make logged packets more readable.\nfunction jsonLoggerHelper(key, val) {\n if (typeof val == 'string' && val.length > 128) {\n return '<' + val.length + ', bytes: ' + val.substring(0, 12) + '...' + val.substring(val.length - 12) + '>';\n }\n return jsonBuildHelper(key, val);\n};\n\n// Parse browser user agent to extract browser name and version.\nfunction getBrowserInfo(ua, product) {\n ua = ua || '';\n let reactnative = '';\n // Check if this is a ReactNative app.\n if (/reactnative/i.test(product)) {\n reactnative = 'ReactNative; ';\n }\n let result;\n // Remove useless string.\n ua = ua.replace(' (KHTML, like Gecko)', '');\n // Test for WebKit-based browser.\n let m = ua.match(/(AppleWebKit\\/[.\\d]+)/i);\n if (m) {\n // List of common strings, from more useful to less useful.\n // All unknown strings get the highest (-1) priority.\n const priority = ['edg', 'chrome', 'safari', 'mobile', 'version'];\n let tmp = ua.substr(m.index + m[0].length).split(' ');\n let tokens = [];\n let version; // 1.0 in Version/1.0 or undefined;\n // Split string like 'Name/0.0.0' into ['Name', '0.0.0', 3] where the last element is the priority.\n for (let i = 0; i < tmp.length; i++) {\n let m2 = /([\\w.]+)[\\/]([\\.\\d]+)/.exec(tmp[i]);\n if (m2) {\n // Unknown values are highest priority (-1).\n tokens.push([m2[1], m2[2], priority.findIndex((e) => {\n return m2[1].toLowerCase().startsWith(e);\n })]);\n if (m2[1] == 'Version') {\n version = m2[2];\n }\n }\n }\n // Sort by priority: more interesting is earlier than less interesting.\n tokens.sort((a, b) => {\n return a[2] - b[2];\n });\n if (tokens.length > 0) {\n // Return the least common browser string and version.\n if (tokens[0][0].toLowerCase().startsWith('edg')) {\n tokens[0][0] = 'Edge';\n } else if (tokens[0][0] == 'OPR') {\n tokens[0][0] = 'Opera';\n } else if (tokens[0][0] == 'Safari' && version) {\n tokens[0][1] = version;\n }\n result = tokens[0][0] + '/' + tokens[0][1];\n } else {\n // Failed to ID the browser. Return the webkit version.\n result = m[1];\n }\n } else if (/firefox/i.test(ua)) {\n m = /Firefox\\/([.\\d]+)/g.exec(ua);\n if (m) {\n result = 'Firefox/' + m[1];\n } else {\n result = 'Firefox/?';\n }\n } else {\n // Neither AppleWebKit nor Firefox. Try the last resort.\n m = /([\\w.]+)\\/([.\\d]+)/.exec(ua);\n if (m) {\n result = m[1] + '/' + m[2];\n } else {\n m = ua.split(' ');\n result = m[0];\n }\n }\n\n // Shorten the version to one dot 'a.bb.ccc.d -> a.bb' at most.\n m = result.split('/');\n if (m.length > 1) {\n const v = m[1].split('.');\n const minor = v[1] ? '.' + v[1].substr(0, 2) : '';\n result = `${m[0]}/${v[0]}${minor}`;\n }\n return reactnative + result;\n}\n\n/**\n * The main class for interacting with Tinode server.\n */\nexport class Tinode {\n _host;\n _secure;\n\n _appName;\n\n // API Key.\n _apiKey;\n\n // Name and version of the browser.\n _browser = '';\n _platform;\n // Hardware\n _hwos = 'undefined';\n _humanLanguage = 'xx';\n\n // Logging to console enabled\n _loggingEnabled = false;\n // When logging, trip long strings (base64-encoded images) for readability\n _trimLongStrings = false;\n // UID of the currently authenticated user.\n _myUID = null;\n // Status of connection: authenticated or not.\n _authenticated = false;\n // Login used in the last successful basic authentication\n _login = null;\n // Token which can be used for login instead of login/password.\n _authToken = null;\n // Counter of received packets\n _inPacketCount = 0;\n // Counter for generating unique message IDs\n _messageId = Math.floor((Math.random() * 0xFFFF) + 0xFFFF);\n // Information about the server, if connected\n _serverInfo = null;\n // Push notification token. Called deviceToken for consistency with the Android SDK.\n _deviceToken = null;\n\n // Cache of pending promises by message id.\n _pendingPromises = {};\n // The Timeout object returned by the reject expired promises setInterval.\n _expirePromises = null;\n\n // Websocket or long polling connection.\n _connection = null;\n\n // Use indexDB for caching topics and messages.\n _persist = false;\n // IndexedDB wrapper object.\n _db = null;\n\n // Tinode's cache of objects\n _cache = {};\n\n /**\n * Create Tinode object.\n *\n * @param {Object} config - configuration parameters.\n * @param {string} config.appName - Name of the calling application to be reported in the User Agent.\n * @param {string} config.host - Host name and optional port number to connect to.\n * @param {string} config.apiKey - API key generated by keygen.\n * @param {string} config.transport - See {@link Tinode.Connection#transport}.\n * @param {boolean} config.secure - Use Secure WebSocket if true.\n * @param {string} config.platform - Optional platform identifier, one of \"ios\", \"web\", \"android\".\n * @param {boolen} config.persist - Use IndexedDB persistent storage.\n * @param {function} onComplete - callback to call when initialization is completed.\n */\n constructor(config, onComplete) {\n this._host = config.host;\n this._secure = config.secure;\n\n // Client-provided application name, format /\n this._appName = config.appName || \"Undefined\";\n\n // API Key.\n this._apiKey = config.apiKey;\n\n // Name and version of the browser.\n this._platform = config.platform || 'web';\n // Underlying OS.\n if (typeof navigator != 'undefined') {\n this._browser = getBrowserInfo(navigator.userAgent, navigator.product);\n this._hwos = navigator.platform;\n // This is the default language. It could be changed by client.\n this._humanLanguage = navigator.language || 'en-US';\n }\n\n Connection.logger = this.logger;\n Drafty.logger = this.logger;\n\n // WebSocket or long polling network connection.\n if (config.transport != 'lp' && config.transport != 'ws') {\n config.transport = detectTransport();\n }\n this._connection = new Connection(config, Const.PROTOCOL_VERSION, /* autoreconnect */ true);\n this._connection.onMessage = (data) => {\n // Call the main message dispatcher.\n this.#dispatchMessage(data);\n }\n\n // Ready to start sending.\n this._connection.onOpen = _ => this.#connectionOpen();\n this._connection.onDisconnect = (err, code) => this.#disconnected(err, code);\n\n // Wrapper for the reconnect iterator callback.\n this._connection.onAutoreconnectIteration = (timeout, promise) => {\n if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(timeout, promise);\n }\n }\n\n this._persist = config.persist;\n // Initialize object regardless. It simplifies the code.\n this._db = new DBCache(this.logger, this.logger);\n\n if (this._persist) {\n // Create the persistent cache.\n // Store promises to be resolved when messages load into memory.\n const prom = [];\n this._db.initDatabase().then(_ => {\n // First load topics into memory.\n return this._db.mapTopics(data => {\n let topic = this.#cacheGet('topic', data.name);\n if (topic) {\n return;\n }\n if (data.name == Const.TOPIC_ME) {\n topic = new TopicMe();\n } else if (data.name == Const.TOPIC_FND) {\n topic = new TopicFnd();\n } else {\n topic = new Topic(data.name);\n }\n this._db.deserializeTopic(topic, data);\n this.#attachCacheToTopic(topic);\n topic._cachePutSelf();\n this._db.maxDelId(topic.name).then(clear => {\n topic._maxDel = Math.max(topic._maxDel, clear || 0);\n });\n // Topic loaded from DB is not new.\n delete topic._new;\n // Request to load messages and save the promise.\n prom.push(topic._loadMessages(this._db));\n });\n }).then(_ => {\n // Then load users.\n return this._db.mapUsers((data) => {\n this.#cachePut('user', data.uid, mergeObj({}, data.public));\n });\n }).then(_ => {\n // Now wait for all messages to finish loading.\n return Promise.all(prom);\n }).then(_ => {\n if (onComplete) {\n onComplete();\n }\n this.logger(\"Persistent cache initialized.\");\n }).catch(err => {\n if (onComplete) {\n onComplete(err);\n }\n this.logger(\"Failed to initialize persistent cache:\", err);\n });\n } else {\n this._db.deleteDatabase().then(_ => {\n if (onComplete) {\n onComplete();\n }\n });\n }\n }\n\n // Private methods.\n\n // Console logger. Babel somehow fails to parse '...rest' parameter.\n logger(str, ...args) {\n if (this._loggingEnabled) {\n const d = new Date();\n const dateString = ('0' + d.getUTCHours()).slice(-2) + ':' +\n ('0' + d.getUTCMinutes()).slice(-2) + ':' +\n ('0' + d.getUTCSeconds()).slice(-2) + '.' +\n ('00' + d.getUTCMilliseconds()).slice(-3);\n\n console.log('[' + dateString + ']', str, args.join(' '));\n }\n }\n\n // Generator of default promises for sent packets.\n #makePromise(id) {\n let promise = null;\n if (id) {\n promise = new Promise((resolve, reject) => {\n // Stored callbacks will be called when the response packet with this Id arrives\n this._pendingPromises[id] = {\n 'resolve': resolve,\n 'reject': reject,\n 'ts': new Date()\n };\n });\n }\n return promise;\n };\n\n // Resolve or reject a pending promise.\n // Unresolved promises are stored in _pendingPromises.\n #execPromise(id, code, onOK, errorText) {\n const callbacks = this._pendingPromises[id];\n if (callbacks) {\n delete this._pendingPromises[id];\n if (code >= 200 && code < 400) {\n if (callbacks.resolve) {\n callbacks.resolve(onOK);\n }\n } else if (callbacks.reject) {\n callbacks.reject(new CommError(errorText, code));\n }\n }\n }\n\n // Send a packet. If packet id is provided return a promise.\n #send(pkt, id) {\n let promise;\n if (id) {\n promise = this.#makePromise(id);\n }\n pkt = simplify(pkt);\n let msg = JSON.stringify(pkt);\n this.logger(\"out: \" + (this._trimLongStrings ? JSON.stringify(pkt, jsonLoggerHelper) : msg));\n try {\n this._connection.sendText(msg);\n } catch (err) {\n // If sendText throws, wrap the error in a promise or rethrow.\n if (id) {\n this.#execPromise(id, Connection.NETWORK_ERROR, null, err.message);\n } else {\n throw err;\n }\n }\n return promise;\n }\n\n // The main message dispatcher.\n #dispatchMessage(data) {\n // Skip empty response. This happens when LP times out.\n if (!data)\n return;\n\n this._inPacketCount++;\n\n // Send raw message to listener\n if (this.onRawMessage) {\n this.onRawMessage(data);\n }\n\n if (data === '0') {\n // Server response to a network probe.\n if (this.onNetworkProbe) {\n this.onNetworkProbe();\n }\n // No processing is necessary.\n return;\n }\n\n let pkt = JSON.parse(data, jsonParseHelper);\n if (!pkt) {\n this.logger(\"in: \" + data);\n this.logger(\"ERROR: failed to parse data\");\n } else {\n this.logger(\"in: \" + (this._trimLongStrings ? JSON.stringify(pkt, jsonLoggerHelper) : data));\n\n // Send complete packet to listener\n if (this.onMessage) {\n this.onMessage(pkt);\n }\n\n if (pkt.ctrl) {\n // Handling {ctrl} message\n if (this.onCtrlMessage) {\n this.onCtrlMessage(pkt.ctrl);\n }\n\n // Resolve or reject a pending promise, if any\n if (pkt.ctrl.id) {\n this.#execPromise(pkt.ctrl.id, pkt.ctrl.code, pkt.ctrl, pkt.ctrl.text);\n }\n setTimeout(_ => {\n if (pkt.ctrl.code == 205 && pkt.ctrl.text == 'evicted') {\n // User evicted from topic.\n const topic = this.#cacheGet('topic', pkt.ctrl.topic);\n if (topic) {\n topic._resetSub();\n if (pkt.ctrl.params && pkt.ctrl.params.unsub) {\n topic._gone();\n }\n }\n } else if (pkt.ctrl.code < 300 && pkt.ctrl.params) {\n if (pkt.ctrl.params.what == 'data') {\n // code=208, all messages received: \"params\":{\"count\":11,\"what\":\"data\"},\n const topic = this.#cacheGet('topic', pkt.ctrl.topic);\n if (topic) {\n topic._allMessagesReceived(pkt.ctrl.params.count);\n }\n } else if (pkt.ctrl.params.what == 'sub') {\n // code=204, the topic has no (refreshed) subscriptions.\n const topic = this.#cacheGet('topic', pkt.ctrl.topic);\n if (topic) {\n // Trigger topic.onSubsUpdated.\n topic._processMetaSubs([]);\n }\n }\n }\n }, 0);\n } else {\n setTimeout(_ => {\n if (pkt.meta) {\n // Handling a {meta} message.\n // Preferred API: Route meta to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.meta.topic);\n if (topic) {\n topic._routeMeta(pkt.meta);\n }\n\n if (pkt.meta.id) {\n this.#execPromise(pkt.meta.id, 200, pkt.meta, 'META');\n }\n\n // Secondary API: callback\n if (this.onMetaMessage) {\n this.onMetaMessage(pkt.meta);\n }\n } else if (pkt.data) {\n // Handling {data} message\n // Preferred API: Route data to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.data.topic);\n if (topic) {\n topic._routeData(pkt.data);\n }\n\n // Secondary API: Call callback\n if (this.onDataMessage) {\n this.onDataMessage(pkt.data);\n }\n } else if (pkt.pres) {\n // Handling {pres} message\n // Preferred API: Route presence to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.pres.topic);\n if (topic) {\n topic._routePres(pkt.pres);\n }\n\n // Secondary API - callback\n if (this.onPresMessage) {\n this.onPresMessage(pkt.pres);\n }\n } else if (pkt.info) {\n // {info} message - read/received notifications and key presses\n // Preferred API: Route {info}} to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.info.topic);\n if (topic) {\n topic._routeInfo(pkt.info);\n }\n\n // Secondary API - callback\n if (this.onInfoMessage) {\n this.onInfoMessage(pkt.info);\n }\n } else {\n this.logger(\"ERROR: Unknown packet received.\");\n }\n }, 0);\n }\n }\n }\n\n // Connection open, ready to start sending.\n #connectionOpen() {\n if (!this._expirePromises) {\n // Reject promises which have not been resolved for too long.\n this._expirePromises = setInterval(_ => {\n const err = new CommError(\"timeout\", 504);\n const expires = new Date(new Date().getTime() - Const.EXPIRE_PROMISES_TIMEOUT);\n for (let id in this._pendingPromises) {\n let callbacks = this._pendingPromises[id];\n if (callbacks && callbacks.ts < expires) {\n this.logger(\"Promise expired\", id);\n delete this._pendingPromises[id];\n if (callbacks.reject) {\n callbacks.reject(err);\n }\n }\n }\n }, Const.EXPIRE_PROMISES_PERIOD);\n }\n this.hello();\n }\n\n #disconnected(err, code) {\n this._inPacketCount = 0;\n this._serverInfo = null;\n this._authenticated = false;\n\n if (this._expirePromises) {\n clearInterval(this._expirePromises);\n this._expirePromises = null;\n }\n\n // Mark all topics as unsubscribed\n this.#cacheMap('topic', (topic, key) => {\n topic._resetSub();\n });\n\n // Reject all pending promises\n for (let key in this._pendingPromises) {\n const callbacks = this._pendingPromises[key];\n if (callbacks && callbacks.reject) {\n callbacks.reject(err);\n }\n }\n this._pendingPromises = {};\n\n if (this.onDisconnect) {\n this.onDisconnect(err);\n }\n }\n\n // Get User Agent string\n #getUserAgent() {\n return this._appName + ' (' + (this._browser ? this._browser + '; ' : '') + this._hwos + '); ' + Const.LIBRARY;\n }\n\n // Generator of packets stubs\n #initPacket(type, topic) {\n switch (type) {\n case 'hi':\n return {\n 'hi': {\n 'id': this.getNextUniqueId(),\n 'ver': Const.VERSION,\n 'ua': this.#getUserAgent(),\n 'dev': this._deviceToken,\n 'lang': this._humanLanguage,\n 'platf': this._platform\n }\n };\n\n case 'acc':\n return {\n 'acc': {\n 'id': this.getNextUniqueId(),\n 'user': null,\n 'scheme': null,\n 'secret': null,\n 'tmpscheme': null,\n 'tmpsecret': null,\n 'login': false,\n 'tags': null,\n 'desc': {},\n 'cred': {}\n }\n };\n\n case 'login':\n return {\n 'login': {\n 'id': this.getNextUniqueId(),\n 'scheme': null,\n 'secret': null\n }\n };\n\n case 'sub':\n return {\n 'sub': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'set': {},\n 'get': {}\n }\n };\n\n case 'leave':\n return {\n 'leave': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'unsub': false\n }\n };\n\n case 'pub':\n return {\n 'pub': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'noecho': false,\n 'head': null,\n 'content': {}\n }\n };\n\n case 'get':\n return {\n 'get': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'what': null,\n 'desc': {},\n 'sub': {},\n 'data': {}\n }\n };\n\n case 'set':\n return {\n 'set': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'desc': {},\n 'sub': {},\n 'tags': [],\n 'aux': {}\n }\n };\n\n case 'del':\n return {\n 'del': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'what': null,\n 'delseq': null,\n 'user': null,\n 'hard': false\n }\n };\n\n case 'note':\n return {\n 'note': {\n // no id by design (except calls).\n 'topic': topic,\n 'what': null, // one of \"recv\", \"read\", \"kp\", \"call\"\n 'seq': undefined // the server-side message id acknowledged as received or read.\n }\n };\n\n default:\n throw new Error(`Unknown packet type requested: ${type}`);\n }\n }\n\n // Cache management\n #cachePut(type, name, obj) {\n this._cache[type + ':' + name] = obj;\n }\n #cacheGet(type, name) {\n return this._cache[type + ':' + name];\n }\n #cacheDel(type, name) {\n delete this._cache[type + ':' + name];\n }\n\n // Enumerate all items in cache, call func for each item.\n // Enumeration stops if func returns true.\n #cacheMap(type, func, context) {\n const key = type ? type + ':' : undefined;\n for (let idx in this._cache) {\n if (!key || idx.indexOf(key) == 0) {\n if (func.call(context, this._cache[idx], idx)) {\n break;\n }\n }\n }\n }\n\n // Make limited cache management available to topic.\n // Caching user.public only. Everything else is per-topic.\n #attachCacheToTopic(topic) {\n topic._tinode = this;\n\n topic._cacheGetUser = (uid) => {\n const pub = this.#cacheGet('user', uid);\n if (pub) {\n return {\n user: uid,\n public: mergeObj({}, pub)\n };\n }\n return undefined;\n };\n topic._cachePutUser = (uid, user) => {\n this.#cachePut('user', uid, mergeObj({}, user.public));\n };\n topic._cacheDelUser = (uid) => {\n this.#cacheDel('user', uid);\n };\n topic._cachePutSelf = _ => {\n this.#cachePut('topic', topic.name, topic);\n };\n topic._cacheDelSelf = _ => {\n this.#cacheDel('topic', topic.name);\n };\n }\n\n // On successful login save server-provided data.\n #loginSuccessful(ctrl) {\n if (!ctrl.params || !ctrl.params.user) {\n return ctrl;\n }\n // This is a response to a successful login,\n // extract UID and security token, save it in Tinode module\n this._myUID = ctrl.params.user;\n this._authenticated = (ctrl && ctrl.code >= 200 && ctrl.code < 300);\n if (ctrl.params && ctrl.params.token && ctrl.params.expires) {\n this._authToken = {\n token: ctrl.params.token,\n expires: ctrl.params.expires\n };\n } else {\n this._authToken = null;\n }\n\n if (this.onLogin) {\n this.onLogin(ctrl.code, ctrl.text);\n }\n\n return ctrl;\n }\n\n // Static methods.\n /**\n * Helper method to package account credential.\n *\n * @param {string | Credential} meth - validation method or object with validation data.\n * @param {string=} val - validation value (e.g. email or phone number).\n * @param {Object=} params - validation parameters.\n * @param {string=} resp - validation response.\n *\n * @returns {Array.} array with a single credential or null if no valid credentials were given.\n */\n static credential(meth, val, params, resp) {\n if (typeof meth == 'object') {\n ({\n val,\n params,\n resp,\n meth\n } = meth);\n }\n if (meth && (val || resp)) {\n return [{\n 'meth': meth,\n 'val': val,\n 'resp': resp,\n 'params': params\n }];\n }\n return null;\n }\n\n /**\n * Determine topic type from topic's name: grp, p2p, me, fnd, sys.\n * @param {string} name - Name of the topic to test.\n * @returns {string} One of \"me\", \"fnd\", \"sys\", \"grp\",\n * \"p2p\" or undefined.\n */\n static topicType(name) {\n return Topic.topicType(name);\n }\n\n /**\n * Check if the given topic name is a name of a 'me' topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'me' topic, false otherwise.\n */\n static isMeTopicName(name) {\n return Topic.isMeTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a 'slf' topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'slf' topic, false otherwise.\n */\n static isSelfTopicName(name) {\n return Topic.isSelfTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a group topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a group topic, false otherwise.\n */\n static isGroupTopicName(name) {\n return Topic.isGroupTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a p2p topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p topic, false otherwise.\n */\n static isP2PTopicName(name) {\n return Topic.isP2PTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a communication topic, i.e. P2P or group.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p or group topic, false otherwise.\n */\n static isCommTopicName(name) {\n return Topic.isCommTopicName(name);\n }\n /**\n * Check if the topic name is a name of a new topic.\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a new topic, false otherwise.\n */\n static isNewGroupTopicName(name) {\n return Topic.isNewGroupTopicName(name);\n }\n /**\n * Check if the topic name is a name of a channel.\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a channel, false otherwise.\n */\n static isChannelTopicName(name) {\n return Topic.isChannelTopicName(name);\n }\n /**\n * Get information about the current version of this Tinode client library.\n * @returns {string} semantic version of the library, e.g. \"0.15.5-rc1\".\n */\n static getVersion() {\n return Const.VERSION;\n }\n /**\n * To use Tinode in a non browser context, supply WebSocket and XMLHttpRequest providers.\n * @static\n *\n * @param wsProvider WebSocket provider, e.g. for nodeJS , require('ws').\n * @param xhrProvider XMLHttpRequest provider, e.g. for node require('xhr').\n */\n static setNetworkProviders(wsProvider, xhrProvider) {\n WebSocketProvider = wsProvider;\n XHRProvider = xhrProvider;\n\n Connection.setNetworkProviders(WebSocketProvider, XHRProvider);\n LargeFileHelper.setNetworkProvider(XHRProvider);\n }\n /**\n * To use Tinode in a non browser context, supply indexedDB provider.\n * @static\n *\n * @param idbProvider indexedDB provider, e.g. for nodeJS , require('fake-indexeddb').\n */\n static setDatabaseProvider(idbProvider) {\n IndexedDBProvider = idbProvider;\n\n DBCache.setDatabaseProvider(IndexedDBProvider);\n }\n /**\n * Return information about the current name and version of this Tinode library.\n * @static\n *\n * @returns {string} the name of the library and it's version.\n */\n static getLibrary() {\n return Const.LIBRARY;\n }\n /**\n * Check if the given string represents NULL value as defined by Tinode ('\\u2421').\n * @param {string} str - string to check for NULL value.\n * @returns {boolean} true if string represents NULL value, false otherwise.\n */\n static isNullValue(str) {\n return str === Const.DEL_CHAR;\n }\n /**\n * Check if the given seq ID is likely to be issued by the server as oppisite to being temporary locally assigned ID.\n * @param {int} seq - seq ID to check.\n * @returns {boolean} true if seq is likely server-issued, false otherwise.\n */\n static isServerAssignedSeq(seq) {\n return seq > 0 && seq < Const.LOCAL_SEQID;\n }\n\n /**\n * Check if the given string is a valid tag value.\n * @param {string} tag - string to check.\n * @returns {boolean} true if the string is a valid tag value, false otherwise.\n */\n static isValidTagValue(tag) {\n // 4-24 characters, starting with letter or digit, then letters, digits, hyphen, underscore.\n const ALIAS_REGEX = /^[a-z0-9][a-z0-9_\\-]{3,23}$/i;\n return tag && typeof tag == 'string' && tag.length > 3 && tag.length < 24 && ALIAS_REGEX.test(tag);\n }\n\n /**\n * Split fully-qualified tag into prefix and value.\n */\n static tagSplit(tag) {\n if (!tag) {\n return null;\n }\n\n tag = tag.trim();\n\n const splitAt = tag.indexOf(':');\n if (splitAt <= 0) {\n // Invalid syntax.\n return null;\n }\n\n const value = tag.substring(splitAt + 1);\n if (!value) {\n return null;\n }\n return {\n prefix: tag.substring(0, splitAt),\n value: value\n };\n }\n\n /**\n * Set a unique namespace tag.\n * If the tag with this namespace is already present then it's replaced with the new tag.\n * @param uniqueTag tag to add, must be fully-qualified; if null or empty, no action is taken.\n */\n static setUniqueTag(tags, uniqueTag) {\n if (!tags || tags.length == 0) {\n // No tags, just add the new one.\n return [uniqueTag];\n }\n\n const parts = Tinode.tagSplit(uniqueTag)\n if (!parts) {\n // Invalid tag.\n return tags;\n }\n\n // Remove the old tag with the same prefix.\n tags = tags.filter(tag => tag && !tag.startsWith(parts.prefix));\n // Add the new tag.\n tags.push(uniqueTag);\n return tags;\n }\n\n /**\n * Remove a unique tag with the given prefix.\n * @param prefix prefix to remove\n */\n static clearTagPrefix(tags, prefix) {\n if (!tags || tags.length == 0) {\n return [];\n }\n return tags.filter(tag => tag && !tag.startsWith(prefix));\n }\n\n /**\n * Find the first tag with the given prefix.\n * @param prefix prefix to search for.\n * @return the first tag with the given prefix if found or undefined.\n */\n static tagByPrefix(tags, prefix) {\n if (!tags) {\n return undefined;\n }\n\n return tags.find(tag => tag && tag.startsWith(prefix));\n }\n\n // Instance methods.\n\n // Generates unique message IDs\n getNextUniqueId() {\n return (this._messageId != 0) ? '' + this._messageId++ : undefined;\n };\n\n /**\n * Connect to the server.\n *\n * @param {string} host_ - name of the host to connect to.\n * @return {Promise} Promise resolved/rejected when the connection call completes:\n * resolve() is called without parameters, reject() receives the\n * Error as a single parameter.\n */\n connect(host_) {\n return this._connection.connect(host_);\n }\n\n /**\n * Attempt to reconnect to the server immediately.\n *\n * @param {string} force - if true, reconnect even if there is a connection already.\n */\n reconnect(force) {\n this._connection.reconnect(force);\n }\n\n /**\n * Disconnect from the server.\n */\n disconnect() {\n this._connection.disconnect();\n }\n\n /**\n * Clear persistent cache: remove IndexedDB.\n *\n * @return {Promise} Promise resolved/rejected when the operation is completed.\n */\n clearStorage() {\n if (this._db.isReady()) {\n return this._db.deleteDatabase();\n }\n return Promise.resolve();\n }\n\n /**\n * Initialize persistent cache: create IndexedDB cache.\n *\n * @return {Promise} Promise resolved/rejected when the operation is completed.\n */\n initStorage() {\n if (!this._db.isReady()) {\n return this._db.initDatabase();\n }\n return Promise.resolve();\n }\n\n /**\n * Send a network probe message to make sure the connection is alive.\n */\n networkProbe() {\n this._connection.probe();\n }\n\n /**\n * Check for live connection to server.\n *\n * @returns {boolean} true if there is a live connection, false otherwise.\n */\n isConnected() {\n return this._connection.isConnected();\n }\n\n /**\n * Check if connection is authenticated (last login was successful).\n *\n * @returns {boolean} true if authenticated, false otherwise.\n */\n isAuthenticated() {\n return this._authenticated;\n }\n\n /**\n * Add API key and auth token to the relative URL making it usable for getting data\n * from the server in a simple HTTP GET request.\n *\n * @param {string} URL - URL to wrap.\n * @returns {string} URL with appended API key and token, if valid token is present.\n */\n authorizeURL(url) {\n if (typeof url != 'string') {\n return url;\n }\n\n if (isUrlRelative(url)) {\n // Fake base to make the relative URL parseable.\n const base = 'scheme://host/';\n const parsed = new URL(url, base);\n if (this._apiKey) {\n parsed.searchParams.append('apikey', this._apiKey);\n }\n if (this._authToken && this._authToken.token) {\n parsed.searchParams.append('auth', 'token');\n parsed.searchParams.append('secret', this._authToken.token);\n }\n // Convert back to string and strip fake base URL except for the root slash.\n url = parsed.toString().substring(base.length - 1);\n }\n return url;\n }\n\n /**\n * @typedef AccountParams\n * @type {Object}\n * @property {DefAcs=} defacs - Default access parameters for user's me topic.\n * @property {Object=} public - Public application-defined data exposed on me topic.\n * @property {Object=} private - Private application-defined data accessible on me topic.\n * @property {Object=} trusted - Trusted user data which can be set by a root user only.\n * @property {Array.} tags - array of string tags for user discovery.\n * @property {string} scheme - Temporary authentication scheme for password reset.\n * @property {string} secret - Temporary authentication secret for password reset.\n * @property {Array.=} attachments - Array of references to out of band attachments used in account description.\n */\n /**\n * @typedef DefAcs\n * @type {Object}\n * @property {string=} auth - Access mode for me for authenticated users.\n * @property {string=} anon - Access mode for me for anonymous users.\n */\n\n /**\n * Create or update an account.\n *\n * @param {string} uid - User id to update\n * @param {string} scheme - Authentication scheme; \"basic\" and \"anonymous\" are the currently supported schemes.\n * @param {string} secret - Authentication secret, assumed to be already base64 encoded.\n * @param {boolean=} login - Use new account to authenticate current session\n * @param {AccountParams=} params - User data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n account(uid, scheme, secret, login, params) {\n const pkt = this.#initPacket('acc');\n pkt.acc.user = uid;\n pkt.acc.scheme = scheme;\n pkt.acc.secret = secret;\n // Log in to the new account using selected scheme\n pkt.acc.login = login;\n\n if (params) {\n pkt.acc.desc.defacs = params.defacs;\n pkt.acc.desc.public = params.public;\n pkt.acc.desc.private = params.private;\n pkt.acc.desc.trusted = params.trusted;\n\n pkt.acc.tags = params.tags;\n pkt.acc.cred = params.cred;\n\n pkt.acc.tmpscheme = params.scheme;\n pkt.acc.tmpsecret = params.secret;\n\n if (Array.isArray(params.attachments) && params.attachments.length > 0) {\n pkt.extra = {\n attachments: params.attachments.filter(ref => isUrlRelative(ref))\n };\n }\n }\n\n return this.#send(pkt, pkt.acc.id);\n }\n\n /**\n * Create a new user. Wrapper for {@link Tinode#account}.\n *\n * @param {string} scheme - Authentication scheme; \"basic\" is the only currently supported scheme.\n * @param {string} secret - Authentication.\n * @param {boolean=} login - Use new account to authenticate current session\n * @param {AccountParams=} params - User data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n createAccount(scheme, secret, login, params) {\n let promise = this.account(Const.USER_NEW, scheme, secret, login, params);\n if (login) {\n promise = promise.then(ctrl => this.#loginSuccessful(ctrl));\n }\n return promise;\n }\n\n /**\n * Create user with 'basic' authentication scheme and immediately\n * use it for authentication. Wrapper for {@link Tinode#account}.\n *\n * @param {string} username - Login to use for the new account.\n * @param {string} password - User's password.\n * @param {AccountParams=} params - User data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n createAccountBasic(username, password, params) {\n // Make sure we are not using 'null' or 'undefined';\n username = username || '';\n password = password || '';\n return this.createAccount('basic',\n b64EncodeUnicode(username + ':' + password), true, params);\n }\n\n /**\n * Update user's credentials for 'basic' authentication scheme. Wrapper for {@link Tinode#account}.\n *\n * @param {string} uid - User ID to update.\n * @param {string} username - Login to use for the new account.\n * @param {string} password - User's password.\n * @param {AccountParams=} params - data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n updateAccountBasic(uid, username, password, params) {\n // Make sure we are not using 'null' or 'undefined';\n username = username || '';\n password = password || '';\n return this.account(uid, 'basic',\n b64EncodeUnicode(username + ':' + password), false, params);\n }\n\n /**\n * Send handshake to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n hello() {\n const pkt = this.#initPacket('hi');\n\n return this.#send(pkt, pkt.hi.id)\n .then(ctrl => {\n // Reset backoff counter on successful connection.\n this._connection.backoffReset();\n\n // Server response contains server protocol version, build, constraints,\n // session ID for long polling. Save them.\n if (ctrl.params) {\n this._serverInfo = ctrl.params;\n }\n\n if (this.onConnect) {\n this.onConnect();\n }\n\n return ctrl;\n }).catch(err => {\n this._connection.reconnect(true);\n\n if (this.onDisconnect) {\n this.onDisconnect(err);\n }\n });\n }\n\n /**\n * Set or refresh the push notifications/device token. If the client is connected,\n * the deviceToken can be sent to the server.\n *\n * @param {string} dt - token obtained from the provider or false,\n * null or undefined to clear the token.\n *\n * @returns true if attempt was made to send the update to the server.\n */\n setDeviceToken(dt) {\n let sent = false;\n // Convert any falsish value to null.\n dt = dt || null;\n if (dt != this._deviceToken) {\n this._deviceToken = dt;\n if (this.isConnected() && this.isAuthenticated()) {\n this.#send({\n 'hi': {\n 'dev': dt || Tinode.DEL_CHAR\n }\n });\n sent = true;\n }\n }\n return sent;\n }\n\n /**\n * @typedef Credential\n * @type {Object}\n * @property {string} meth - validation method.\n * @property {string} val - value to validate (e.g. email or phone number).\n * @property {string} resp - validation response.\n * @property {Object} params - validation parameters.\n */\n /**\n * Authenticate current session.\n *\n * @param {string} scheme - Authentication scheme; \"basic\" is the only currently supported scheme.\n * @param {string} secret - Authentication secret, assumed to be already base64 encoded.\n * @param {Credential=} cred - credential confirmation, if required.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n login(scheme, secret, cred) {\n const pkt = this.#initPacket('login');\n pkt.login.scheme = scheme;\n pkt.login.secret = secret;\n pkt.login.cred = cred;\n\n return this.#send(pkt, pkt.login.id)\n .then(ctrl => this.#loginSuccessful(ctrl));\n }\n\n /**\n * Wrapper for {@link Tinode#login} with basic authentication\n *\n * @param {string} uname - User name.\n * @param {string} password - Password.\n * @param {Credential=} cred - credential confirmation, if required.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n loginBasic(uname, password, cred) {\n return this.login('basic', b64EncodeUnicode(uname + ':' + password), cred)\n .then(ctrl => {\n this._login = uname;\n return ctrl;\n });\n }\n\n /**\n * Wrapper for {@link Tinode#login} with token authentication\n *\n * @param {string} token - Token received in response to earlier login.\n * @param {Credential=} cred - credential confirmation, if required.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n loginToken(token, cred) {\n return this.login('token', token, cred);\n }\n\n /**\n * Send a request for resetting an authentication secret.\n *\n * @param {string} scheme - authentication scheme to reset.\n * @param {string} method - method to use for resetting the secret, such as \"email\" or \"tel\".\n * @param {string} value - value of the credential to use, a specific email address or a phone number.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving the server reply.\n */\n requestResetAuthSecret(scheme, method, value) {\n return this.login('reset', b64EncodeUnicode(scheme + ':' + method + ':' + value));\n }\n\n /**\n * @typedef AuthToken\n * @type {Object}\n * @property {string} token - Token value.\n * @property {Date} expires - Token expiration time.\n */\n /**\n * Get stored authentication token.\n *\n * @returns {AuthToken} authentication token.\n */\n getAuthToken() {\n if (this._authToken && (this._authToken.expires.getTime() > Date.now())) {\n return this._authToken;\n } else {\n this._authToken = null;\n }\n return null;\n }\n\n /**\n * Application may provide a saved authentication token.\n *\n * @param {AuthToken} token - authentication token.\n */\n setAuthToken(token) {\n this._authToken = token;\n }\n\n /**\n * @typedef SetParams\n * @type {Object}\n * @property {SetDesc=} desc - Topic initialization parameters when creating a new topic or a new subscription.\n * @property {SetSub=} sub - Subscription initialization parameters.\n * @property {Array.=} tags - Search tags.\n * @property {Object} aux - Auxiliary topic data.\n * @property {Array.=} attachments - URLs of out of band attachments used in parameters.\n */\n /**\n * @typedef SetDesc\n * @type {Object}\n * @property {DefAcs=} defacs - Default access mode.\n * @property {Object=} public - Free-form topic description, publically accessible.\n * @property {Object=} private - Free-form topic description accessible only to the owner.\n * @property {Object=} trusted - Trusted user data which can be set by a root user only.\n */\n /**\n * @typedef SetSub\n * @type {Object}\n * @property {string=} user - UID of the user affected by the request. Default (empty) - current user.\n * @property {string=} mode - User access mode, either requested or assigned dependent on context.\n */\n /**\n * Send a topic subscription request.\n *\n * @param {string} topic - Name of the topic to subscribe to.\n * @param {GetQuery=} getParams - Optional subscription metadata query\n * @param {SetParams=} setParams - Optional initialization parameters\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n subscribe(topicName, getParams, setParams) {\n const pkt = this.#initPacket('sub', topicName)\n if (!topicName) {\n topicName = Const.TOPIC_NEW;\n }\n\n pkt.sub.get = getParams;\n\n if (setParams) {\n if (setParams.sub) {\n pkt.sub.set.sub = setParams.sub;\n }\n\n if (setParams.desc) {\n const desc = setParams.desc;\n if (Tinode.isNewGroupTopicName(topicName)) {\n // Full set.desc params are used for new topics only\n pkt.sub.set.desc = desc;\n } else if (Tinode.isP2PTopicName(topicName) && desc.defacs) {\n // Use optional default permissions only.\n pkt.sub.set.desc = {\n defacs: desc.defacs\n };\n }\n }\n\n // See if external objects were used in topic description.\n if (Array.isArray(setParams.attachments) && setParams.attachments.length > 0) {\n pkt.extra = {\n attachments: setParams.attachments.filter(ref => isUrlRelative(ref))\n };\n }\n\n if (setParams.tags) {\n pkt.sub.set.tags = setParams.tags;\n }\n if (setParams.aux) {\n pkt.sub.set.aux = setParams.aux;\n }\n }\n return this.#send(pkt, pkt.sub.id);\n }\n\n /**\n * Detach and optionally unsubscribe from the topic\n *\n * @param {string} topic - Topic to detach from.\n * @param {boolean} unsub - If true, detach and unsubscribe, otherwise just detach.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n leave(topic, unsub) {\n const pkt = this.#initPacket('leave', topic);\n pkt.leave.unsub = unsub;\n\n return this.#send(pkt, pkt.leave.id);\n }\n\n /**\n * Create message draft without sending it to the server.\n *\n * @param {string} topic - Name of the topic to publish to.\n * @param {Object} content - Payload to publish.\n * @param {boolean=} noEcho - If true, tell the server not to echo the message to the original session.\n *\n * @returns {Object} new message which can be sent to the server or otherwise used.\n */\n createMessage(topic, content, noEcho) {\n const pkt = this.#initPacket('pub', topic);\n\n let dft = typeof content == 'string' ? Drafty.parse(content) : content;\n if (dft && !Drafty.isPlainText(dft)) {\n pkt.pub.head = {\n mime: Drafty.getContentType()\n };\n content = dft;\n }\n pkt.pub.noecho = noEcho;\n pkt.pub.content = content;\n\n return pkt.pub;\n }\n\n /**\n * Publish {data} message to topic.\n *\n * @param {string} topicName - Name of the topic to publish to.\n * @param {Object} content - Payload to publish.\n * @param {boolean=} noEcho - If true, tell the server not to echo the message to the original session.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n publish(topicName, content, noEcho) {\n return this.publishMessage(\n this.createMessage(topicName, content, noEcho)\n );\n }\n\n /**\n * Publish message to topic. The message should be created by {@link Tinode#createMessage}.\n *\n * @param {Object} pub - Message to publish.\n * @param {Array.=} attachments - array of URLs with attachments.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n publishMessage(pub, attachments) {\n // Make a shallow copy. Needed in order to clear locally-assigned temp values;\n pub = Object.assign({}, pub);\n pub.seq = undefined;\n pub.from = undefined;\n pub.ts = undefined;\n const msg = {\n pub: pub,\n };\n if (attachments) {\n msg.extra = {\n attachments: attachments.filter(ref => isUrlRelative(ref))\n };\n }\n return this.#send(msg, pub.id);\n }\n\n /**\n * Out of band notification: notify topic that an external (push) notification was recived by the client.\n *\n * @param {object} data - notification payload.\n * @param {string} data.what - notification type, 'msg', 'read', 'sub'.\n * @param {string} data.topic - name of the updated topic.\n * @param {number=} data.seq - seq ID of the affected message.\n * @param {string=} data.xfrom - UID of the sender.\n * @param {object=} data.given - new subscription 'given', e.g. 'ASWP...'.\n * @param {object=} data.want - new subscription 'want', e.g. 'RWJ...'.\n */\n oobNotification(data) {\n this.logger('oob: ' + (this._trimLongStrings ? JSON.stringify(data, jsonLoggerHelper) : data));\n\n switch (data.what) {\n case 'msg':\n if (!data.seq || data.seq < 1 || !data.topic) {\n // Server sent invalid data.\n break;\n }\n\n if (!this.isConnected()) {\n // Let's ignore the message if there is no connection: no connection means there are no open\n // tabs with Tinode.\n break;\n }\n\n const topic = this.#cacheGet('topic', data.topic);\n if (!topic) {\n // TODO: check if there is a case when a message can arrive from an unknown topic.\n break;\n }\n\n if (topic.isSubscribed()) {\n // No need to fetch: topic is already subscribed and got data through normal channel.\n break;\n }\n\n if (topic.maxMsgSeq() < data.seq) {\n if (topic.isChannelType()) {\n topic._updateReceived(data.seq, 'fake-uid');\n }\n\n // New message.\n if (data.xfrom && !this.#cacheGet('user', data.xfrom)) {\n // Message from unknown sender, fetch description from the server.\n // Sending asynchronously without a subscription.\n this.getMeta(data.xfrom, new MetaGetBuilder().withDesc().build()).catch(err => {\n this.logger(\"Failed to get the name of a new sender\", err);\n });\n }\n\n topic.subscribe(null).then(_ => {\n return topic.getMeta(new MetaGetBuilder(topic).withLaterData(24).withLaterDel(24).build());\n }).then(_ => {\n // Allow data fetch to complete and get processed successfully.\n topic.leaveDelayed(false, 1000);\n }).catch(err => {\n this.logger(\"On push data fetch failed\", err);\n }).finally(_ => {\n this.getMeTopic()._refreshContact('msg', topic);\n });\n }\n break;\n\n case 'read':\n this.getMeTopic()._routePres({\n what: 'read',\n seq: data.seq\n });\n break;\n\n case 'sub':\n if (!this.isMe(data.xfrom)) {\n // TODO: handle updates from other users.\n break;\n }\n\n const mode = {\n given: data.modeGiven,\n want: data.modeWant\n };\n const acs = new AccessMode(mode);\n const pres = (!acs.mode || acs.mode == AccessMode._NONE) ?\n // Subscription deleted.\n {\n what: 'gone',\n src: data.topic\n } :\n // New subscription or subscription updated.\n {\n what: 'acs',\n src: data.topic,\n dacs: mode\n };\n this.getMeTopic()._routePres(pres);\n break;\n\n default:\n this.logger(\"Unknown push type ignored\", data.what);\n }\n }\n\n /**\n * @typedef GetOptsType\n * @type {Object}\n * @property {Date=} ims - \"If modified since\", fetch data only it was was modified since stated date.\n * @property {number=} limit - Maximum number of results to return. Ignored when querying topic description.\n */\n\n /**\n * @typedef GetDataType\n * @type {Object}\n * @property {number=} since - Load messages with seq ID equal or greater than this value.\n * @property {number=} before - Load messages with seq ID lower than this number.\n * @property {number=} limit - Maximum number of results to return.\n * @property {Array.=} range - Ranges of seq IDs to fetch.\n */\n\n /**\n * @typedef GetQuery\n * @type {Object}\n * @property {GetOptsType=} desc - If provided (even if empty), fetch topic description.\n * @property {GetOptsType=} sub - If provided (even if empty), fetch topic subscriptions.\n * @property {GetDataType=} data - If provided (even if empty), get messages.\n */\n\n /**\n * Request topic metadata\n *\n * @param {string} topic - Name of the topic to query.\n * @param {GetQuery} params - Parameters of the query. Use {@link Tinode.MetaGetBuilder} to generate.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n getMeta(topic, params) {\n const pkt = this.#initPacket('get', topic);\n\n pkt.get = mergeObj(pkt.get, params);\n\n return this.#send(pkt, pkt.get.id);\n }\n\n /**\n * Update topic's metadata: description, subscribtions.\n *\n * @param {string} topic - Topic to update.\n * @param {SetParams} params - topic metadata to update.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n setMeta(topic, params) {\n const pkt = this.#initPacket('set', topic);\n const what = [];\n\n if (params) {\n ['desc', 'sub', 'tags', 'cred', 'aux'].forEach(key => {\n if (params.hasOwnProperty(key)) {\n what.push(key);\n pkt.set[key] = params[key];\n }\n });\n\n if (Array.isArray(params.attachments) && params.attachments.length > 0) {\n pkt.extra = {\n attachments: params.attachments.filter(ref => isUrlRelative(ref))\n };\n }\n }\n\n if (what.length == 0) {\n return Promise.reject(new Error(\"Invalid {set} parameters\"));\n }\n\n return this.#send(pkt, pkt.set.id);\n }\n\n /**\n * Range of message IDs.\n *\n * @typedef SeqRange\n * @type {Object}\n * @property {number} low - low end of the range, inclusive (closed).\n * @property {number=} hi - high end of the range, exclusive (open).\n */\n /**\n * Delete some or all messages in a topic.\n *\n * @param {string} topic - Topic name to delete messages from.\n * @param {Array.} list - Ranges of message IDs to delete.\n * @param {boolean=} hard - Hard or soft delete\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delMessages(topic, ranges, hard) {\n const pkt = this.#initPacket('del', topic);\n\n pkt.del.what = 'msg';\n pkt.del.delseq = ranges;\n pkt.del.hard = hard;\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Delete the topic alltogether. Requires Owner permission.\n *\n * @param {string} topicName - Name of the topic to delete\n * @param {boolean} hard - hard-delete topic.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delTopic(topicName, hard) {\n const pkt = this.#initPacket('del', topicName);\n pkt.del.what = 'topic';\n pkt.del.hard = hard;\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Delete subscription. Requires Share permission.\n *\n * @param {string} topicName - Name of the topic to delete\n * @param {string} user - User ID to remove.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delSubscription(topicName, user) {\n const pkt = this.#initPacket('del', topicName);\n pkt.del.what = 'sub';\n pkt.del.user = user;\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Delete credential. Always sent on 'me' topic.\n *\n * @param {string} method - validation method such as 'email' or 'tel'.\n * @param {string} value - validation value, i.e. 'alice@example.com'.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delCredential(method, value) {\n const pkt = this.#initPacket('del', Const.TOPIC_ME);\n pkt.del.what = 'cred';\n pkt.del.cred = {\n meth: method,\n val: value\n };\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Request to delete account of the current user.\n *\n * @param {boolean} hard - hard-delete user.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delCurrentUser(hard) {\n const pkt = this.#initPacket('del', null);\n pkt.del.what = 'user';\n pkt.del.hard = hard;\n\n return this.#send(pkt, pkt.del.id).then(_ => {\n this._myUID = null;\n });\n }\n\n /**\n * Notify server that a message or messages were read or received. Does NOT return promise.\n *\n * @param {string} topicName - Name of the topic where the mesage is being aknowledged.\n * @param {string} what - Action being aknowledged, either \"read\" or \"recv\".\n * @param {number} seq - Maximum id of the message being acknowledged.\n * @throws {Error} if seq is invalid.\n */\n note(topicName, what, seq) {\n if (seq <= 0 || seq >= Const.LOCAL_SEQID) {\n throw new Error(`Invalid message id ${seq}`);\n }\n\n const pkt = this.#initPacket('note', topicName);\n pkt.note.what = what;\n pkt.note.seq = seq;\n this.#send(pkt);\n }\n\n /**\n * Broadcast a key-press notification to topic subscribers. Used to show\n * typing notifications \"user X is typing...\".\n *\n * @param {string} topicName - Name of the topic to broadcast to.\n * @param {string=} type - notification to send, default is 'kp'.\n */\n noteKeyPress(topicName, type) {\n const pkt = this.#initPacket('note', topicName);\n pkt.note.what = type || 'kp';\n this.#send(pkt);\n }\n\n /**\n * Send a video call notification to topic subscribers (including dialing,\n * hangup, etc.).\n *\n * @param {string} topicName - Name of the topic to broadcast to.\n * @param {int} seq - ID of the call message the event pertains to.\n * @param {string} evt - Call event.\n * @param {string} payload - Payload associated with this event (e.g. SDP string).\n *\n * @returns {Promise} Promise (for some call events) which will\n * be resolved/rejected on receiving server reply\n */\n videoCall(topicName, seq, evt, payload) {\n const pkt = this.#initPacket('note', topicName);\n pkt.note.seq = seq;\n pkt.note.what = 'call';\n pkt.note.event = evt;\n pkt.note.payload = payload;\n this.#send(pkt, pkt.note.id);\n }\n\n /**\n * Get a named topic, either pull it from cache or create a new instance.\n * There is a single instance of topic for each name.\n *\n * @param {string} topicName - Name of the topic to get.\n *\n * @returns {Topic} Requested or newly created topic or undefined if topic name is invalid.\n */\n getTopic(topicName) {\n let topic = this.#cacheGet('topic', topicName);\n if (!topic && topicName) {\n if (topicName == Const.TOPIC_ME) {\n topic = new TopicMe();\n } else if (topicName == Const.TOPIC_FND) {\n topic = new TopicFnd();\n } else {\n topic = new Topic(topicName);\n }\n // Cache management.\n this.#attachCacheToTopic(topic);\n topic._cachePutSelf();\n // Don't save to DB here: a record will be added when the topic is subscribed.\n }\n return topic;\n }\n\n /**\n * Get a named topic from cache.\n *\n * @param {string} topicName - Name of the topic to get.\n *\n * @returns {Topic} Requested topic or undefined if topic is not found in cache.\n */\n cacheGetTopic(topicName) {\n return this.#cacheGet('topic', topicName);\n }\n\n /**\n * Remove named topic from cache.\n *\n * @param {string} topicName - Name of the topic to remove from cache.\n */\n cacheRemTopic(topicName) {\n this.#cacheDel('topic', topicName);\n }\n\n /**\n * Iterate over cached topics.\n *\n * @param {Function} func - callback to call for each topic.\n * @param {Object} context - 'this' inside the 'func'.\n */\n mapTopics(func, context) {\n this.#cacheMap('topic', func, context);\n }\n\n /**\n * Check if named topic is already present in cache.\n *\n * @param {string} topicName - Name of the topic to check.\n * @returns {boolean} true if topic is found in cache, false otherwise.\n */\n isTopicCached(topicName) {\n return !!this.#cacheGet('topic', topicName);\n }\n\n /**\n * Generate unique name like 'new123456' suitable for creating a new group topic.\n *\n * @param {boolean} isChan - if the topic is channel-enabled.\n * @returns {string} name which can be used for creating a new group topic.\n */\n newGroupTopicName(isChan) {\n return (isChan ? Const.TOPIC_NEW_CHAN : Const.TOPIC_NEW) + this.getNextUniqueId();\n }\n\n /**\n * Instantiate 'me' topic or get it from cache.\n *\n * @returns {TopicMe} Instance of 'me' topic.\n */\n getMeTopic() {\n return this.getTopic(Const.TOPIC_ME);\n }\n\n /**\n * Instantiate 'fnd' (find) topic or get it from cache.\n *\n * @returns {Topic} Instance of 'fnd' topic.\n */\n getFndTopic() {\n return this.getTopic(Const.TOPIC_FND);\n }\n\n /**\n * Create a new {@link LargeFileHelper} instance\n *\n * @returns {LargeFileHelper} instance of a {@link Tinode.LargeFileHelper}.\n */\n getLargeFileHelper() {\n return new LargeFileHelper(this, Const.PROTOCOL_VERSION);\n }\n\n /**\n * Get the UID of the the current authenticated user.\n *\n * @returns {string} UID of the current user or undefined if the session is not yet\n * authenticated or if there is no session.\n */\n getCurrentUserID() {\n return this._myUID;\n }\n\n /**\n * Check if the given user ID is equal to the current user's UID.\n *\n * @param {string} uid - UID to check.\n *\n * @returns {boolean} true if the given UID belongs to the current logged in user.\n */\n isMe(uid) {\n return this._myUID === uid;\n }\n\n /**\n * Get login used for last successful authentication.\n *\n * @returns {string} login last used successfully or undefined.\n */\n getCurrentLogin() {\n return this._login;\n }\n\n /**\n * Return information about the server: protocol version and build timestamp.\n *\n * @returns {Object} build and version of the server or null if there is no connection or\n * if the first server response has not been received yet.\n */\n getServerInfo() {\n return this._serverInfo;\n }\n\n /**\n * Report a topic for abuse. Wrapper for {@link Tinode#publish}.\n *\n * @param {string} action - the only supported action is 'report'.\n * @param {string} target - name of the topic being reported.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n report(action, target) {\n return this.publish(Const.TOPIC_SYS, Drafty.attachJSON(null, {\n 'action': action,\n 'target': target\n }));\n }\n\n /**\n * Return server-provided configuration value.\n *\n * @param {string} name of the value to return.\n * @param {Object} defaultValue to return in case the parameter is not set or not found.\n *\n * @returns {Object} named value.\n */\n getServerParam(name, defaultValue) {\n return this._serverInfo && this._serverInfo[name] || defaultValue;\n }\n\n /**\n * Toggle console logging. Logging is off by default.\n *\n * @param {boolean} enabled - Set to true to enable logging to console.\n * @param {boolean} trimLongStrings - Set to true to trim long strings.\n */\n enableLogging(enabled, trimLongStrings) {\n this._loggingEnabled = enabled;\n this._trimLongStrings = enabled && trimLongStrings;\n }\n\n /**\n * Set UI language to report to the server. Must be called before 'hi' is sent, otherwise it will not be used.\n *\n * @param {string} hl - human (UI) language, like \"en_US\" or \"zh-Hans\".\n */\n setHumanLanguage(hl) {\n if (hl) {\n this._humanLanguage = hl;\n }\n }\n\n /**\n * Check if given topic is online.\n *\n * @param {string} name of the topic to test.\n * @returns {boolean} true if topic is online, false otherwise.\n */\n isTopicOnline(name) {\n const topic = this.#cacheGet('topic', name);\n return topic && topic.online;\n }\n\n /**\n * Get access mode for the given contact.\n *\n * @param {string} name of the topic to query.\n * @returns {AccessMode} access mode if topic is found, null otherwise.\n */\n getTopicAccessMode(name) {\n const topic = this.#cacheGet('topic', name);\n return topic ? topic.acs : null;\n }\n\n /**\n * Include message ID into all subsequest messages to server instructin it to send aknowledgemens.\n * Required for promises to function. Default is \"on\".\n *\n * @param {boolean} status - Turn aknowledgemens on or off.\n * @deprecated\n */\n wantAkn(status) {\n if (status) {\n this._messageId = Math.floor((Math.random() * 0xFFFFFF) + 0xFFFFFF);\n } else {\n this._messageId = 0;\n }\n }\n\n // Callbacks:\n /**\n * Callback to report when the websocket is opened. The callback has no parameters.\n *\n * @type {onWebsocketOpen}\n */\n onWebsocketOpen = undefined;\n\n /**\n * @typedef ServerParams\n *\n * @type {Object}\n * @property {string} ver - Server version\n * @property {string} build - Server build\n * @property {string=} sid - Session ID, long polling connections only.\n */\n\n /**\n * @callback onConnect\n * @param {number} code - Result code\n * @param {string} text - Text epxplaining the completion, i.e \"OK\" or an error message.\n * @param {ServerParams} params - Parameters returned by the server.\n */\n /**\n * Callback to report when connection with Tinode server is established.\n * @type {onConnect}\n */\n onConnect = undefined;\n\n /**\n * Callback to report when connection is lost. The callback has no parameters.\n * @type {onDisconnect}\n */\n onDisconnect = undefined;\n\n /**\n * @callback onLogin\n * @param {number} code - NUmeric completion code, same as HTTP status codes.\n * @param {string} text - Explanation of the completion code.\n */\n /**\n * Callback to report login completion.\n * @type {onLogin}\n */\n onLogin = undefined;\n\n /**\n * Callback to receive {ctrl} (control) messages.\n * @type {onCtrlMessage}\n */\n onCtrlMessage = undefined;\n\n /**\n * Callback to recieve {data} (content) messages.\n * @type {onDataMessage}\n */\n onDataMessage = undefined;\n\n /**\n * Callback to receive {pres} (presence) messages.\n * @type {onPresMessage}\n */\n onPresMessage = undefined;\n\n /**\n * Callback to receive all messages as objects.\n * @type {onMessage}\n */\n onMessage = undefined;\n\n /**\n * Callback to receive all messages as unparsed text.\n * @type {onRawMessage}\n */\n onRawMessage = undefined;\n\n /**\n * Callback to receive server responses to network probes. See {@link Tinode#networkProbe}\n * @type {onNetworkProbe}\n */\n onNetworkProbe = undefined;\n\n /**\n * Callback to be notified when exponential backoff is iterating.\n * @type {onAutoreconnectIteration}\n */\n onAutoreconnectIteration = undefined;\n};\n\n// Exported constants\nTinode.MESSAGE_STATUS_NONE = Const.MESSAGE_STATUS_NONE;\nTinode.MESSAGE_STATUS_QUEUED = Const.MESSAGE_STATUS_QUEUED;\nTinode.MESSAGE_STATUS_SENDING = Const.MESSAGE_STATUS_SENDING;\nTinode.MESSAGE_STATUS_FAILED = Const.MESSAGE_STATUS_FAILED;\nTinode.MESSAGE_STATUS_FATAL = Const.MESSAGE_STATUS_FATAL;\nTinode.MESSAGE_STATUS_SENT = Const.MESSAGE_STATUS_SENT;\nTinode.MESSAGE_STATUS_RECEIVED = Const.MESSAGE_STATUS_RECEIVED;\nTinode.MESSAGE_STATUS_READ = Const.MESSAGE_STATUS_READ;\nTinode.MESSAGE_STATUS_TO_ME = Const.MESSAGE_STATUS_TO_ME;\n\n// Unicode [del] symbol.\nTinode.DEL_CHAR = Const.DEL_CHAR;\n\n// Names of keys to server-provided configuration limits.\nTinode.MAX_MESSAGE_SIZE = 'maxMessageSize';\nTinode.MAX_SUBSCRIBER_COUNT = 'maxSubscriberCount';\nTinode.MIN_TAG_LENGTH = 'minTagLength';\nTinode.MAX_TAG_LENGTH = 'maxTagLength';\nTinode.MAX_TAG_COUNT = 'maxTagCount';\nTinode.MAX_FILE_UPLOAD_SIZE = 'maxFileUploadSize';\nTinode.REQ_CRED_VALIDATORS = 'reqCred';\nTinode.MSG_DELETE_AGE = 'msgDelAge';\n\n// Tinode URI topic ID prefix, 'scheme:path/'.\nTinode.URI_TOPIC_ID_PREFIX = 'tinode:topic/';\n\n// Tag prefixes for alias, email, phone.\nTinode.TAG_ALIAS = Const.TAG_ALIAS;\nTinode.TAG_EMAIL = Const.TAG_EMAIL;\nTinode.TAG_PHONE = Const.TAG_PHONE;\n","/**\n * @file Helper class for constructing {@link Tinode.GetQuery}.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport {\n listToRanges,\n normalizeRanges\n} from './utils';\n\n/**\n * Helper class for constructing {@link Tinode.GetQuery}.\n *\n * @class MetaGetBuilder\n * @memberof Tinode\n *\n * @param {Tinode.Topic} parent topic which instantiated this builder.\n */\nexport default class MetaGetBuilder {\n constructor(parent) {\n this.topic = parent;\n this.what = {};\n }\n\n // Get timestamp of the most recent desc update.\n #get_desc_ims() {\n return this.topic._deleted ? undefined : this.topic.updated;\n }\n\n // Get timestamp of the most recent subs update.\n #get_subs_ims() {\n if (this.topic.isP2PType()) {\n return this.#get_desc_ims();\n }\n return this.topic._deleted ? undefined : this.topic._lastSubsUpdate;\n }\n /**\n * Add query parameters to fetch messages within explicit limits.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} since - messages newer than this (inclusive);\n * @param {number=} before - older than this (exclusive)\n * @param {number=} limit - number of messages to fetch\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withData(since, before, limit) {\n this.what['data'] = {\n since: since,\n before: before,\n limit: limit\n };\n return this;\n }\n /**\n * Add query parameters to fetch messages newer than the latest saved message.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - number of messages to fetch\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterData(limit) {\n return this.withData(this.topic._maxSeq > 0 ? this.topic._maxSeq + 1 : undefined, undefined, limit);\n }\n /**\n * Add query parameters to fetch messages within ID ranges.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Array.} ranges - ranges of seq IDs to fetch.\n * @param {number=} limit - maximum number of messages to fetch.\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDataRanges(ranges, limit) {\n this.what['data'] = {\n ranges: normalizeRanges(ranges, this.topic._maxSeq),\n limit: limit\n };\n return this;\n }\n /**\n * Add query parameters to fetch messages by an array of IDs.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number[]} list - array of seq IDs to fetch.\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDataList(list) {\n return this.withDataRanges(listToRanges(list));\n }\n /**\n * Add query parameters to fetch messages older than the earliest saved message.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - maximum number of messages to fetch.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withEarlierData(limit) {\n return this.withData(undefined, this.topic._minSeq > 0 ? this.topic._minSeq : undefined, limit);\n }\n /**\n * Add query parameters to fetch topic description if it's newer than the given timestamp.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Date=} ims - fetch messages newer than this timestamp.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDesc(ims) {\n this.what['desc'] = {\n ims: ims\n };\n return this;\n }\n /**\n * Add query parameters to fetch topic description if it's newer than the last update.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterDesc() {\n return this.withDesc(this.#get_desc_ims());\n }\n /**\n * Add query parameters to fetch subscriptions.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Date=} ims - fetch subscriptions modified more recently than this timestamp\n * @param {number=} limit - maximum number of subscriptions to fetch.\n * @param {string=} userOrTopic - user ID or topic name to fetch for fetching one subscription.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withSub(ims, limit, userOrTopic) {\n const opts = {\n ims: ims,\n limit: limit\n };\n if (this.topic.getType() == 'me') {\n opts.topic = userOrTopic;\n } else {\n opts.user = userOrTopic;\n }\n this.what['sub'] = opts;\n return this;\n }\n /**\n * Add query parameters to fetch a single subscription.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Date=} ims - fetch subscriptions modified more recently than this timestamp\n * @param {string=} userOrTopic - user ID or topic name to fetch for fetching one subscription.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withOneSub(ims, userOrTopic) {\n return this.withSub(ims, undefined, userOrTopic);\n }\n /**\n * Add query parameters to fetch a single subscription if it's been updated since the last update.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {string=} userOrTopic - user ID or topic name to fetch for fetching one subscription.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterOneSub(userOrTopic) {\n return this.withOneSub(this.topic._lastSubsUpdate, userOrTopic);\n }\n /**\n * Add query parameters to fetch subscriptions updated since the last update.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - maximum number of subscriptions to fetch.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterSub(limit) {\n return this.withSub(this.#get_subs_ims(), limit);\n }\n /**\n * Add query parameters to fetch topic tags.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withTags() {\n this.what['tags'] = true;\n return this;\n }\n /**\n * Add query parameters to fetch user's credentials. 'me' topic only.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withCred() {\n if (this.topic.getType() == 'me') {\n this.what['cred'] = true;\n } else {\n this.topic._tinode.logger(\"ERROR: Invalid topic type for MetaGetBuilder:withCreds\", this.topic.getType());\n }\n return this;\n }\n /**\n * Add query parameters to fetch topic tags.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withAux() {\n this.what['aux'] = true;\n return this;\n }\n /**\n * Add query parameters to fetch deleted messages within explicit limits. Any/all parameters can be null.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} since - ids of messages deleted since this 'del' id (inclusive)\n * @param {number=} limit - number of deleted message ids to fetch\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDel(since, limit) {\n if (since || limit) {\n this.what['del'] = {\n since: since,\n limit: limit\n };\n }\n return this;\n }\n /**\n * Add query parameters to fetch messages deleted after the saved 'del' id.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - number of deleted message ids to fetch\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterDel(limit) {\n // Specify 'since' only if we have already received some messages. If\n // we have no locally cached messages then we don't care if any messages were deleted.\n return this.withDel(this.topic._maxSeq > 0 ? this.topic._maxDel + 1 : undefined, limit);\n }\n\n /**\n * Extract subquery: get an object that contains specified subquery.\n * @memberof Tinode.MetaGetBuilder#\n * @param {string} what - subquery to return: one of 'data', 'sub', 'desc', 'tags', 'cred', 'del'.\n * @returns {Object} requested subquery or undefined.\n */\n extract(what) {\n return this.what[what];\n }\n\n /**\n * Construct parameters.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.GetQuery} Get query\n */\n build() {\n const what = [];\n let params = {};\n ['data', 'sub', 'desc', 'tags', 'cred', 'aux', 'del'].forEach((key) => {\n if (this.what.hasOwnProperty(key)) {\n what.push(key);\n if (Object.getOwnPropertyNames(this.what[key]).length > 0) {\n params[key] = this.what[key];\n }\n }\n });\n if (what.length > 0) {\n params.what = what.join(' ');\n } else {\n params = undefined;\n }\n return params;\n }\n}\n","/**\n * @file In-memory sorted cache of objects.\n *\n * @copyright 2015-2025 Tinode LLC.\n */\n'use strict';\n\n/**\n * In-memory sorted cache of objects.\n *\n * @class CBuffer\n * @memberof Tinode\n * @protected\n *\n * @param {function} compare custom comparator of objects. Takes two parameters a and b;\n * returns -1 if a < b, 0 if a == b, 1 otherwise.\n * @param {boolean} unique enforce element uniqueness: when true replace existing element with a new\n * one on conflict; when false keep both elements.\n */\nexport default class CBuffer {\n #comparator = undefined;\n #unique = false;\n buffer = [];\n\n constructor(compare_, unique_) {\n this.#comparator = compare_ || ((a, b) => {\n return a === b ? 0 : a < b ? -1 : 1;\n });\n this.#unique = unique_;\n }\n\n #findNearest(elem, arr, exact) {\n let start = 0;\n let end = arr.length - 1;\n let pivot = 0;\n let diff = 0;\n let found = false;\n\n while (start <= end) {\n pivot = (start + end) / 2 | 0;\n diff = this.#comparator(arr[pivot], elem);\n if (diff < 0) {\n start = pivot + 1;\n } else if (diff > 0) {\n end = pivot - 1;\n } else {\n found = true;\n break;\n }\n }\n if (found) {\n return {\n idx: pivot,\n exact: true\n };\n }\n if (exact) {\n return {\n idx: -1\n };\n }\n // Not exact - insertion point\n return {\n idx: diff < 0 ? pivot + 1 : pivot\n };\n }\n\n // Insert element into a sorted array.\n #insertSorted(elem, arr) {\n const found = this.#findNearest(elem, arr, false);\n const count = (found.exact && this.#unique) ? 1 : 0;\n arr.splice(found.idx, count, elem);\n return arr;\n }\n\n /**\n * Get an element at the given position.\n * @memberof Tinode.CBuffer#\n * @param {number} at - Position to fetch from.\n * @returns {Object} Element at the given position or undefined.\n */\n getAt(at) {\n return this.buffer[at];\n }\n\n /**\n * Convenience method for getting the last element from the buffer.\n * @memberof Tinode.CBuffer#\n * @param {function} filter - optional filter to apply to elements. If filter is provided, the search\n * for the last element starts from the end of the buffer and goes backwards until the filter returns true.\n * @returns {Object} The last element in the buffer or undefined if buffer is empty.\n */\n getLast(filter) {\n return filter ?\n this.buffer.findLast(filter) :\n this.buffer[this.buffer.length - 1];\n }\n\n /**\n * Insert new element(s) to the buffer at the correct position according to the sort method.\n * Variadic: takes one or more arguments. If an array is passed as a single argument, its\n * elements are inserted individually.\n * @memberof Tinode.CBuffer#\n *\n * @param {...Object|Array} - One or more objects to insert.\n */\n put() {\n let insert;\n // inspect arguments: if array, insert its elements, if one or more non-array arguments, insert them one by one\n if (arguments.length == 1 && Array.isArray(arguments[0])) {\n insert = arguments[0];\n } else {\n insert = arguments;\n }\n for (let idx in insert) {\n this.#insertSorted(insert[idx], this.buffer);\n }\n }\n\n /**\n * Remove element at the given position.\n * @memberof Tinode.CBuffer#\n * @param {number} at - Position to delete at.\n * @returns {Object} Element at the given position or undefined.\n */\n delAt(at) {\n at |= 0;\n let r = this.buffer.splice(at, 1);\n if (r && r.length > 0) {\n return r[0];\n }\n return undefined;\n }\n\n /**\n * Remove elements between two positions.\n * @memberof Tinode.CBuffer#\n * @param {number} since - Position to delete from (inclusive).\n * @param {number} before - Position to delete to (exclusive).\n *\n * @returns {Array} array of removed elements (could be zero length).\n */\n delRange(since, before) {\n return this.buffer.splice(since, before - since);\n }\n\n /**\n * Return the number of elements the buffer holds.\n * @memberof Tinode.CBuffer#\n * @return {number} Number of elements in the buffer.\n */\n length() {\n return this.buffer.length;\n }\n\n /**\n * Reset the buffer discarding all elements\n * @memberof Tinode.CBuffer#\n */\n reset() {\n this.buffer = [];\n }\n\n /**\n * Callback for iterating contents of buffer. See {@link Tinode.CBuffer#forEach}.\n * @callback ForEachCallbackType\n * @memberof Tinode.CBuffer#\n * @param {Object} elem - Current element of the buffer.\n * @param {Object} prev - Previous element of the buffer.\n * @param {Object} next - Next element of the buffer.\n * @param {number} index - Index of the current element.\n */\n\n /**\n * Apply given callback to all elements of the buffer.\n * @memberof Tinode.CBuffer#\n *\n * @param {Tinode.ForEachCallbackType} callback - Function to call for each element.\n * @param {number} startIdx - Optional index to start iterating from (inclusive), default: 0.\n * @param {number} beforeIdx - Optional index to stop iterating before (exclusive), default: length of the buffer.\n * @param {Object} context - calling context (i.e. value of this in callback)\n */\n forEach(callback, startIdx, beforeIdx, context) {\n startIdx = Math.max(0, startIdx | 0);\n beforeIdx = Math.min(beforeIdx || this.buffer.length, this.buffer.length);\n\n for (let i = startIdx; i < beforeIdx; i++) {\n callback.call(context, this.buffer[i],\n (i > startIdx ? this.buffer[i - 1] : undefined),\n (i < beforeIdx - 1 ? this.buffer[i + 1] : undefined), i);\n }\n }\n\n /**\n * Find element in buffer using buffer's comparison function.\n * @memberof Tinode.CBuffer#\n *\n * @param {Object} elem - element to find.\n * @param {boolean=} nearest - when true and exact match is not found, return the nearest element (insertion point).\n * @returns {number} index of the element in the buffer or -1.\n */\n find(elem, nearest) {\n const {\n idx\n } = this.#findNearest(elem, this.buffer, !nearest);\n return idx;\n }\n\n /**\n * Callback for filtering the buffer. See {@link Tinode.CBuffer#filter}.\n * @callback FilterCallbackType\n * @memberof Tinode.CBuffer#\n * @param {Object} elem - Current element of the buffer.\n * @param {number} index - Index of the current element.\n * @returns {boolen} true to keep the element, false to remove.\n */\n\n /**\n * Remove all elements that do not pass the test implemented by the provided callback function.\n * @memberof Tinode.CBuffer#\n *\n * @param {Tinode.FilterCallbackType} callback - Function to call for each element.\n * @param {Object} context - calling context (i.e. value of this in the callback)\n */\n filter(callback, context) {\n let count = 0;\n for (let i = 0; i < this.buffer.length; i++) {\n if (callback.call(context, this.buffer[i], i)) {\n this.buffer[count] = this.buffer[i];\n count++;\n }\n }\n\n this.buffer.splice(count);\n }\n\n /**\n * Check if buffer is empty.\n * @returns {boolean} true if the buffer is empty, false otherwise.\n */\n isEmpty() {\n return this.buffer.length == 0;\n }\n}\n","/**\n * @file Topic management.\n *\n * @copyright 2015-2025 Tinode LLC.\n */\n'use strict';\n\nimport AccessMode from './access-mode.js';\nimport CBuffer from './cbuffer.js';\nimport CommError from './comm-error.js';\nimport * as Const from './config.js';\nimport Drafty from './drafty.js';\nimport MetaGetBuilder from './meta-builder.js';\nimport {\n listToRanges,\n mergeObj,\n mergeToCache,\n normalizeArray,\n normalizeRanges\n} from './utils.js';\n\n/**\n * Topic is a class representing a logical communication channel.\n */\nexport default class Topic {\n /**\n * @callback onData\n * @param {Data} data - Data packet\n */\n\n /**\n * Create topic.\n * @param {string} name - Name of the topic to create.\n * @param {Object=} callbacks - Object with various event callbacks.\n * @param {onData} callbacks.onData - Callback which receives a {data} message.\n * @param {callback} callbacks.onMeta - Callback which receives a {meta} message.\n * @param {callback} callbacks.onPres - Callback which receives a {pres} message.\n * @param {callback} callbacks.onInfo - Callback which receives an {info} message.\n * @param {callback} callbacks.onMetaDesc - Callback which receives changes to topic desctioption {@link desc}.\n * @param {callback} callbacks.onMetaSub - Called for a single subscription record change.\n * @param {callback} callbacks.onSubsUpdated - Called after a batch of subscription changes have been recieved and cached.\n * @param {callback} callbacks.onDeleteTopic - Called after the topic is deleted.\n * @param {callback} callbacls.onAllMessagesReceived - Called when all requested {data} messages have been recived.\n */\n constructor(name, callbacks) {\n // Parent Tinode object.\n this._tinode = null;\n\n // Server-provided data, locally immutable.\n // topic name\n this.name = name;\n // Timestamp when the topic was created.\n this.created = null;\n // Timestamp when the topic was last updated.\n this.updated = null;\n // Timestamp of the last messages\n this.touched = new Date(0);\n // Access mode, see AccessMode\n this.acs = new AccessMode(null);\n // Per-topic private data (accessible by current user only).\n this.private = null;\n // Per-topic public data (accessible by all users).\n this.public = null;\n // Per-topic system-provided data (accessible by all users).\n this.trusted = null;\n\n // Locally cached data\n // Subscribed users, for tracking read/recv/msg notifications.\n this._users = {};\n\n // Current value of locally issued seqId, used for pending messages.\n this._queuedSeqId = Const.LOCAL_SEQID;\n\n // The maximum known {data.seq} value.\n this._maxSeq = 0;\n // The minimum known {data.seq} value.\n this._minSeq = 0;\n // Indicator that the last request for earlier messages returned 0.\n this._noEarlierMsgs = false;\n // The maximum known deletion ID.\n this._maxDel = 0;\n // Timer object used to send 'recv' notifications.\n this._recvNotificationTimer = null;\n\n // User discovery tags\n this._tags = [];\n // Credentials such as email or phone number.\n this._credentials = [];\n // Auxiliary data\n this._aux = {};\n\n // Message versions cache (e.g. for edited messages).\n // Keys: original message seq ID.\n // Values: CBuffers containing newer versions of the original message\n // ordered by seq id.\n this._messageVersions = {};\n // Message cache, sorted by message seq values, from old to new.\n this._messages = new CBuffer((a, b) => {\n return a.seq - b.seq;\n }, true);\n // Boolean, true if the topic is currently live\n this._attached = false;\n // Timestap of the most recently updated subscription.\n this._lastSubsUpdate = new Date(0);\n // Topic created but not yet synced with the server. Used only during initialization.\n this._new = true;\n // The topic is deleted at the server, this is a local copy.\n this._deleted = false;\n\n // Timer used to trgger {leave} request after a delay.\n this._delayedLeaveTimer = null;\n\n // Callbacks\n if (callbacks) {\n this.onData = callbacks.onData;\n this.onMeta = callbacks.onMeta;\n this.onPres = callbacks.onPres;\n this.onInfo = callbacks.onInfo;\n // A single desc update;\n this.onMetaDesc = callbacks.onMetaDesc;\n // A single subscription record;\n this.onMetaSub = callbacks.onMetaSub;\n // All subscription records received;\n this.onSubsUpdated = callbacks.onSubsUpdated;\n this.onTagsUpdated = callbacks.onTagsUpdated;\n this.onCredsUpdated = callbacks.onCredsUpdated;\n this.onAuxUpdated = callbacks.onAuxUpdated;\n this.onDeleteTopic = callbacks.onDeleteTopic;\n this.onAllMessagesReceived = callbacks.onAllMessagesReceived;\n }\n }\n\n // Static methods.\n\n /**\n * Determine topic type from topic's name: grp, p2p, me, fnd, sys.\n *\n * @param {string} name - Name of the topic to test.\n * @returns {string} One of \"me\", \"fnd\", \"sys\", \"grp\",\n * \"p2p\" or undefined.\n */\n static topicType(name) {\n const types = {\n 'me': Const.TOPIC_ME,\n 'fnd': Const.TOPIC_FND,\n 'grp': Const.TOPIC_GRP,\n 'new': Const.TOPIC_GRP,\n 'nch': Const.TOPIC_GRP,\n 'chn': Const.TOPIC_GRP,\n 'usr': Const.TOPIC_P2P,\n 'sys': Const.TOPIC_SYS,\n 'slf': Const.TOPIC_SLF\n };\n return types[(typeof name == 'string') ? name.substring(0, 3) : 'xxx'];\n }\n\n /**\n * Check if the given topic name is a name of a 'me' topic.\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'me' topic, false otherwise.\n */\n static isMeTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_ME;\n }\n\n /**\n * Check if the given topic name is a name of a 'slf' topic.\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'slf' topic, false otherwise.\n */\n static isSelfTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_SLF;\n }\n\n /**\n * Check if the given topic name is a name of a group topic.\n * @static\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a group topic, false otherwise.\n */\n static isGroupTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_GRP;\n }\n\n /**\n * Check if the given topic name is a name of a p2p topic.\n * @static\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p topic, false otherwise.\n */\n static isP2PTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_P2P;\n }\n\n /**\n * Check if the given topic name is a name of a communication topic, i.e. P2P or group.\n * @static\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p or group topic, false otherwise.\n */\n static isCommTopicName(name) {\n return Topic.isP2PTopicName(name) || Topic.isGroupTopicName(name) || Topic.isSelfTopicName(name);\n }\n\n /**\n * Check if the topic name is a name of a new topic.\n * @static\n *\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a new topic, false otherwise.\n */\n static isNewGroupTopicName(name) {\n return (typeof name == 'string') &&\n (name.substring(0, 3) == Const.TOPIC_NEW || name.substring(0, 3) == Const.TOPIC_NEW_CHAN);\n }\n\n /**\n * Check if the topic name is a name of a channel.\n * @static\n *\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a channel, false otherwise.\n */\n static isChannelTopicName(name) {\n return (typeof name == 'string') &&\n (name.substring(0, 3) == Const.TOPIC_CHAN || name.substring(0, 3) == Const.TOPIC_NEW_CHAN);\n }\n\n // Returns true if pub is meant to replace another message (e.g. original message was edited).\n static #isReplacementMsg(pub) {\n return pub.head && pub.head.replace;\n }\n\n /**\n * Check if the topic is subscribed.\n * @returns {boolean} True is topic is attached/subscribed, false otherwise.\n */\n isSubscribed() {\n return this._attached;\n }\n\n /**\n * Request topic to subscribe. Wrapper for {@link Tinode#subscribe}.\n *\n * @param {Tinode.GetQuery=} getParams - get query parameters.\n * @param {Tinode.SetParams=} setParams - set parameters.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n subscribe(getParams, setParams) {\n // Clear request to leave topic.\n clearTimeout(this._delayedLeaveTimer);\n this._delayedLeaveTimer = null;\n\n // If the topic is already subscribed, return resolved promise\n if (this._attached) {\n return Promise.resolve(this);\n }\n\n // Send subscribe message, handle async response.\n // If topic name is explicitly provided, use it. If no name, then it's a new group topic,\n // use \"new\".\n return this._tinode.subscribe(this.name || Const.TOPIC_NEW, getParams, setParams).then(ctrl => {\n if (ctrl.code >= 300) {\n // Do nothing if subscription status has not changed.\n return ctrl;\n }\n\n this._attached = true;\n this._deleted = false;\n this.acs = (ctrl.params && ctrl.params.acs) ? ctrl.params.acs : this.acs;\n\n // Set topic name for new topics and add it to cache.\n if (this._new) {\n delete this._new;\n\n if (this.name != ctrl.topic) {\n // Name may change new123456 -> grpAbCdEf. Remove from cache under the old name.\n this._cacheDelSelf();\n this.name = ctrl.topic;\n }\n this._cachePutSelf();\n\n this.created = ctrl.ts;\n this.updated = ctrl.ts;\n\n if (this.name != Const.TOPIC_ME && this.name != Const.TOPIC_FND) {\n // Add the new topic to the list of contacts maintained by the 'me' topic.\n const me = this._tinode.getMeTopic();\n if (me.onMetaSub) {\n me.onMetaSub(this);\n }\n if (me.onSubsUpdated) {\n me.onSubsUpdated([this.name], 1);\n }\n }\n\n if (setParams && setParams.desc) {\n setParams.desc._noForwarding = true;\n this._processMetaDesc(setParams.desc);\n }\n }\n return ctrl;\n });\n }\n\n /**\n * Create a draft of a message without sending it to the server.\n * @memberof Tinode.Topic#\n *\n * @param {string | Object} data - Content to wrap in a draft.\n * @param {boolean=} noEcho - If true server will not echo message back to originating\n * session. Otherwise the server will send a copy of the message to sender.\n *\n * @returns {Object} message draft.\n */\n createMessage(data, noEcho) {\n return this._tinode.createMessage(this.name, data, noEcho);\n }\n\n /**\n * Immediately publish data to topic. Wrapper for {@link Tinode#publish}.\n * @memberof Tinode.Topic#\n *\n * @param {string | Object} data - Message to publish, either plain string or a Drafty object.\n * @param {boolean=} noEcho - If true server will not echo message back to originating\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n publish(data, noEcho) {\n return this.publishMessage(this.createMessage(data, noEcho));\n }\n\n /**\n * Publish message created by {@link Tinode.Topic#createMessage}.\n * @memberof Tinode.Topic#\n *\n * @param {Object} pub - {data} object to publish. Must be created by {@link Tinode.Topic#createMessage}\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n publishMessage(pub) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot publish on inactive topic\"));\n }\n if (this._sending) {\n return Promise.reject(new Error(\"The message is already being sent\"));\n }\n\n // Send data.\n pub._sending = true;\n pub._failed = false;\n\n // Extract refereces to attachments and out of band image records.\n let attachments = null;\n if (Drafty.hasEntities(pub.content)) {\n attachments = [];\n Drafty.entities(pub.content, data => {\n if (data) {\n if (data.ref) {\n attachments.push(data.ref);\n }\n if (data.preref) {\n attachments.push(data.preref);\n }\n }\n });\n if (attachments.length == 0) {\n attachments = null;\n }\n }\n\n return this._tinode.publishMessage(pub, attachments).then(ctrl => {\n pub._sending = false;\n pub.ts = ctrl.ts;\n this.swapMessageId(pub, ctrl.params.seq);\n this._maybeUpdateMessageVersionsCache(pub);\n this._routeData(pub);\n return ctrl;\n }).catch(err => {\n this._tinode.logger(\"WARNING: Message rejected by the server\", err);\n pub._sending = false;\n pub._failed = true;\n if (this.onData) {\n this.onData();\n }\n });\n }\n\n /**\n * Add message to local message cache, send to the server when the promise is resolved.\n * If promise is null or undefined, the message will be sent immediately.\n * The message is sent when the\n * The message should be created by {@link Tinode.Topic#createMessage}.\n * This is probably not the final API.\n * @memberof Tinode.Topic#\n *\n * @param {Object} pub - Message to use as a draft.\n * @param {Promise} prom - Message will be sent when this promise is resolved, discarded if rejected.\n *\n * @returns {Promise} derived promise.\n */\n publishDraft(pub, prom) {\n const seq = pub.seq || this._getQueuedSeqId();\n if (!pub._noForwarding) {\n // The 'seq', 'ts', and 'from' are added to mimic {data}. They are removed later\n // before the message is sent.\n pub._noForwarding = true;\n pub.seq = seq;\n pub.ts = new Date();\n pub.from = this._tinode.getCurrentUserID();\n\n // Don't need an echo message because the message is added to local cache right away.\n pub.noecho = true;\n // Add to cache.\n this._messages.put(pub);\n this._tinode._db.addMessage(pub);\n\n if (this.onData) {\n this.onData(pub);\n }\n }\n // If promise is provided, send the queued message when it's resolved.\n // If no promise is provided, create a resolved one and send immediately.\n return (prom || Promise.resolve())\n .then(_ => {\n if (pub._cancelled) {\n return {\n code: 300,\n text: \"cancelled\"\n };\n }\n return this.publishMessage(pub);\n }).catch(err => {\n this._tinode.logger(\"WARNING: Message draft rejected\", err);\n pub._sending = false;\n pub._failed = true;\n pub._fatal = err instanceof CommError ? (err.code >= 400 && err.code < 500) : false;\n if (this.onData) {\n this.onData();\n }\n // Rethrow to let caller know that the operation failed.\n throw err;\n });\n }\n\n /**\n * Leave the topic, optionally unsibscribe. Leaving the topic means the topic will stop\n * receiving updates from the server. Unsubscribing will terminate user's relationship with the topic.\n * Wrapper for {@link Tinode#leave}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean=} unsub - If true, unsubscribe, otherwise just leave.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n leave(unsub) {\n // It's possible to unsubscribe (unsub==true) from inactive topic.\n if (!this._attached && !unsub) {\n return Promise.reject(new Error(\"Cannot leave inactive topic\"));\n }\n\n // Send a 'leave' message, handle async response\n return this._tinode.leave(this.name, unsub).then(ctrl => {\n this._resetSub();\n if (unsub) {\n this._gone();\n }\n return ctrl;\n });\n }\n\n /**\n * Leave the topic, optionally unsibscribe after a delay. Leaving the topic means the topic will stop\n * receiving updates from the server. Unsubscribing will terminate user's relationship with the topic.\n * Wrapper for {@link Tinode#leave}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} unsub - If true, unsubscribe, otherwise just leave.\n * @param {number} delay - time in milliseconds to delay leave request.\n */\n leaveDelayed(unsub, delay) {\n clearTimeout(this._delayedLeaveTimer);\n this._delayedLeaveTimer = setTimeout(_ => {\n this._delayedLeaveTimer = null;\n this.leave(unsub)\n }, delay);\n }\n\n /**\n * Request topic metadata from the local cache or from the server.\n * @memberof Tinode.Topic#\n *\n * @param {Tinode.GetQuery} request parameters\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n getMeta(params) {\n // Send {get} message, return promise.\n return this._tinode.getMeta(this.name, params);\n }\n\n /**\n * Request more messages from the server. The goal is to load continous range of messages\n * covering at least between 'min' and 'max' + one full page forward (newer = true) or backwards\n * (newer=false).\n * @memberof Tinode.Topic#\n *\n * @param {number} limit number of messages to get.\n * @param {Array.} gaps - ranges of messages to load.\n * @param {number} min if non-negative, request newer messages with seq >= min.\n * @param {number} max if positive, request older messages with seq < max.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n getMessagesPage(limit, gaps, min, max, newer) {\n let query = gaps ?\n this.startMetaQuery().withDataRanges(gaps, limit) :\n newer ?\n this.startMetaQuery().withData(min, undefined, limit) :\n this.startMetaQuery().withData(undefined, max, limit);\n // First try fetching from DB, then from the server.\n return this._loadMessages(this._tinode._db, query.extract('data'))\n .then(count => {\n // Recalculate missing ranges.\n gaps = this.msgHasMoreMessages(min, max, newer);\n if (gaps.length == 0) {\n // All messages loaded.\n return Promise.resolve({\n topic: this.name,\n code: 200,\n params: {\n count: count\n }\n });\n }\n\n // Reduce the count of requested messages.\n limit -= count;\n // Update query with new values loaded from DB.\n query = this.startMetaQuery().withDataRanges(gaps, limit);\n return this.getMeta(query.build());\n });\n }\n\n /**\n * Request to get pinned messages from the local cache or from the server.\n * @memberof Tinode.Topic#\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n getPinnedMessages() {\n const pins = this.aux('pins');\n if (!Array.isArray(pins)) {\n return Promise.resolve(0);\n }\n\n const loaded = [];\n let remains = pins;\n // First try fetching from DB, then check deleted log, then ask the server.\n return this._tinode._db.readMessages(this.name, {\n ranges: listToRanges(remains)\n })\n .then(msgs => {\n msgs.forEach(data => {\n // The 'data' could be undefined.\n if (data) {\n loaded.push(data.seq);\n this._messages.put(data);\n this._maybeUpdateMessageVersionsCache(data);\n }\n });\n if (loaded.length < pins.length) {\n // Some messages are missing, try dellog.\n remains = pins.filter(seq => !loaded.includes(seq));\n return this._tinode._db.readMessages(this.name, {\n ranges: listToRanges(remains)\n });\n }\n return null;\n })\n .then(ranges => {\n if (ranges) {\n // Found some deleted ranges in dellog.\n remains.forEach(seq => {\n if (ranges.find(r => r.low <= seq && r.hi > seq)) {\n loaded.push(seq);\n }\n });\n }\n if (loaded.length == pins.length) {\n // Got all pinned messages from the local cache.\n return Promise.resolve({\n topic: this.name,\n code: 200,\n params: {\n count: loaded.length\n }\n });\n }\n\n remains = pins.filter(seq => !loaded.includes(seq));\n return this.getMeta(this.startMetaQuery().withDataList(remains).build());\n });\n }\n\n /**\n * Update topic metadata.\n * @memberof Tinode.Topic#\n *\n * @param {Tinode.SetParams} params parameters to update.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n setMeta(params) {\n if (params.tags) {\n params.tags = normalizeArray(params.tags);\n }\n // Send Set message, handle async response.\n return this._tinode.setMeta(this.name, params)\n .then(ctrl => {\n if (ctrl && ctrl.code >= 300) {\n // Not modified\n return ctrl;\n }\n\n if (params.sub) {\n params.sub.topic = this.name;\n if (ctrl.params && ctrl.params.acs) {\n params.sub.acs = ctrl.params.acs;\n params.sub.updated = ctrl.ts;\n }\n if (!params.sub.user) {\n // This is a subscription update of the current user.\n // Assign user ID otherwise the update will be ignored by _processMetaSubs.\n params.sub.user = this._tinode.getCurrentUserID();\n if (!params.desc) {\n // Force update to topic's asc.\n params.desc = {};\n }\n }\n params.sub._noForwarding = true;\n this._processMetaSubs([params.sub]);\n }\n\n if (params.desc) {\n if (ctrl.params && ctrl.params.acs) {\n params.desc.acs = ctrl.params.acs;\n params.desc.updated = ctrl.ts;\n }\n this._processMetaDesc(params.desc);\n }\n\n if (params.tags) {\n this._processMetaTags(params.tags);\n }\n if (params.cred) {\n this._processMetaCreds([params.cred], true);\n }\n if (params.aux) {\n this._processMetaAux(params.aux);\n }\n\n return ctrl;\n });\n }\n /**\n * Update access mode of the current user or of another topic subsriber.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - UID of the user to update or null to update current user.\n * @param {string} update - the update value, full or delta.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n updateMode(uid, update) {\n const user = uid ? this.subscriber(uid) : null;\n const am = user ?\n user.acs.updateGiven(update).getGiven() :\n this.getAccessMode().updateWant(update).getWant();\n\n return this.setMeta({\n sub: {\n user: uid,\n mode: am\n }\n });\n }\n /**\n * Create new topic subscription. Wrapper for {@link Tinode#setMeta}.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - ID of the user to invite\n * @param {string=} mode - Access mode. null means to use default.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n invite(uid, mode) {\n return this.setMeta({\n sub: {\n user: uid,\n mode: mode\n }\n });\n }\n /**\n * Archive or un-archive the topic. Wrapper for {@link Tinode#setMeta}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} arch - true to archive the topic, false otherwise.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n archive(arch) {\n if (this.private && (!this.private.arch == !arch)) {\n return Promise.resolve(arch);\n }\n return this.setMeta({\n desc: {\n private: {\n arch: arch ? true : Const.DEL_CHAR\n }\n }\n });\n }\n /**\n * Set message as pinned or unpinned by adding it to aux.pins array. Wrapper for {@link Tinode#setMeta}.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - seq ID of the message to pin or un-pin.\n * @param {boolean} pin - true to pin the message, false to un-pin.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n pinMessage(seq, pin) {\n let pinned = this.aux('pins');\n if (!Array.isArray(pinned)) {\n pinned = [];\n }\n let changed = false;\n if (pin) {\n if (!pinned.includes(seq)) {\n changed = true;\n if (pinned.length == Const.MAX_PINNED_COUNT) {\n pinned.shift();\n }\n pinned.push(seq);\n }\n } else {\n if (pinned.includes(seq)) {\n changed = true;\n pinned = pinned.filter(id => id != seq);\n if (pinned.length == 0) {\n pinned = Const.DEL_CHAR;\n }\n }\n }\n if (changed) {\n return this.setMeta({\n aux: {\n pins: pinned\n }\n });\n }\n return Promise.resolve();\n }\n /**\n * Delete messages. Hard-deleting messages requires Deleter (D) permission.\n * Wrapper for {@link Tinode#delMessages}.\n * @memberof Tinode.Topic#\n *\n * @param {Array.} ranges - Ranges of message IDs to delete.\n * @param {boolean=} hard - Hard or soft delete\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delMessages(ranges, hard) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot delete messages in inactive topic\"));\n }\n\n const tosend = normalizeRanges(ranges, this._maxSeq)\n\n // Send {del} message, return promise\n let result;\n if (tosend.length > 0) {\n result = this._tinode.delMessages(this.name, tosend, hard);\n } else {\n result = Promise.resolve({\n params: {\n del: 0\n }\n });\n }\n // Update local cache.\n return result.then(ctrl => {\n if (ctrl.params.del > this._maxDel) {\n this._maxDel = Math.max(ctrl.params.del, this._maxDel);\n this.clear = Math.max(ctrl.params.del, this.clear);\n }\n\n ranges.forEach(rec => {\n if (rec.hi) {\n this.flushMessageRange(rec.low, rec.hi);\n } else {\n this.flushMessage(rec.low);\n }\n this._messages.put({\n seq: rec.low,\n low: rec.low,\n hi: rec.hi,\n _deleted: true\n });\n });\n\n // Make a record.\n this._tinode._db.addDelLog(this.name, ctrl.params.del, ranges);\n\n if (this.onData) {\n // Calling with no parameters to indicate the messages were deleted.\n this.onData();\n }\n return ctrl;\n });\n }\n /**\n * Delete all messages. Hard-deleting messages requires Deleter permission.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} hardDel - true if messages should be hard-deleted.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delMessagesAll(hardDel) {\n if (!this._maxSeq || this._maxSeq <= 0) {\n // There are no messages to delete.\n return Promise.resolve();\n }\n return this.delMessages([{\n low: 1,\n hi: this._maxSeq + 1,\n _all: true\n }], hardDel);\n }\n\n /**\n * Delete multiple messages defined by their IDs. Hard-deleting messages requires Deleter permission.\n * @memberof Tinode.Topic#\n *\n * @param {Array.} list - list of seq IDs to delete.\n * @param {boolean=} hardDel - true if messages should be hard-deleted.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delMessagesList(list, hardDel) {\n // Send {del} message, return promise\n return this.delMessages(listToRanges(list), hardDel);\n }\n\n /**\n * Delete original message and edited variants. Hard-deleting messages requires Deleter permission.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - original seq ID of the message to delete.\n * @param {boolean=} hardDel - true if messages should be hard-deleted.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n delMessagesEdits(seq, hardDel) {\n const list = [seq];\n this.messageVersions(seq, msg => list.push(msg.seq));\n // Send {del} message, return promise\n return this.delMessagesList(list, hardDel);\n }\n\n /**\n * Delete topic. Requires Owner permission. Wrapper for {@link Tinode#delTopic}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} hard - had-delete topic.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n delTopic(hard) {\n if (this._deleted) {\n // The topic is already deleted at the server, just remove from DB.\n this._gone();\n return Promise.resolve(null);\n }\n\n return this._tinode.delTopic(this.name, hard).then(ctrl => {\n this._deleted = true;\n this._resetSub();\n this._gone();\n return ctrl;\n });\n }\n /**\n * Delete subscription. Requires Share permission. Wrapper for {@link Tinode#delSubscription}.\n * @memberof Tinode.Topic#\n *\n * @param {string} user - ID of the user to remove subscription for.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delSubscription(user) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot delete subscription in inactive topic\"));\n }\n // Send {del} message, return promise\n return this._tinode.delSubscription(this.name, user).then(ctrl => {\n // Remove the object from the subscription cache;\n delete this._users[user];\n // Notify listeners\n if (this.onSubsUpdated) {\n this.onSubsUpdated(Object.keys(this._users));\n }\n return ctrl;\n });\n }\n /**\n * Send a read/recv notification.\n * @memberof Tinode.Topic#\n *\n * @param {string} what - what notification to send: recv, read.\n * @param {number} seq - ID or the message read or received.\n */\n note(what, seq) {\n if (!this._attached) {\n // Cannot sending {note} on an inactive topic\".\n return;\n }\n\n // Update local cache with the new count.\n const user = this._users[this._tinode.getCurrentUserID()];\n let update = false;\n if (user) {\n // Self-subscription is found.\n if (!user[what] || user[what] < seq) {\n user[what] = seq;\n update = true;\n }\n } else {\n // Self-subscription is not found.\n update = (this[what] | 0) < seq;\n }\n\n if (update) {\n // Send notification to the server.\n this._tinode.note(this.name, what, seq);\n // Update locally cached contact with the new count.\n this._updateMyReadRecv(what, seq);\n\n if (this.acs != null && !this.acs.isMuted()) {\n const me = this._tinode.getMeTopic();\n // Sent a notification to 'me' listeners.\n me._refreshContact(what, this);\n }\n }\n }\n\n /**\n * Send a 'recv' receipt. Wrapper for {@link Tinode#noteRecv}.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - ID of the message to aknowledge.\n */\n noteRecv(seq) {\n this.note('recv', seq);\n }\n /**\n * Send a 'read' receipt. Wrapper for {@link Tinode#noteRead}.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - ID of the message to aknowledge or 0/undefined to acknowledge the latest messages.\n */\n noteRead(seq) {\n seq = seq || this._maxSeq;\n if (seq > 0) {\n this.note('read', seq);\n }\n }\n /**\n * Send a key-press notification. Wrapper for {@link Tinode#noteKeyPress}.\n * @memberof Tinode.Topic#\n */\n noteKeyPress() {\n if (this._attached) {\n this._tinode.noteKeyPress(this.name);\n } else {\n this._tinode.logger(\"INFO: Cannot send notification in inactive topic\");\n }\n }\n /**\n * Send a notification than a video or audio message is . Wrapper for {@link Tinode#noteKeyPress}.\n * @memberof Tinode.Topic#\n * @param audioOnly - true if the recording is audio-only, false if it's a video recording.\n */\n noteRecording(audioOnly) {\n if (this._attached) {\n this._tinode.noteKeyPress(this.name, audioOnly ? 'kpa' : 'kpv');\n } else {\n this._tinode.logger(\"INFO: Cannot send notification in inactive topic\");\n }\n }\n\n /**\n * Send a {note what='call'}. Wrapper for {@link Tinode#videoCall}.\n * @memberof Tinode#\n *\n * @param {string} evt - Call event.\n * @param {int} seq - ID of the call message the event pertains to.\n * @param {string} payload - Payload associated with this event (e.g. SDP string).\n *\n * @returns {Promise} Promise (for some call events) which will\n * be resolved/rejected on receiving server reply\n */\n videoCall(evt, seq, payload) {\n if (!this._attached && !['ringing', 'hang-up'].includes(evt)) {\n // Cannot {call} on an inactive topic\".\n return;\n }\n return this._tinode.videoCall(this.name, seq, evt, payload);\n }\n\n // Update cached read/recv/unread counts for the current user.\n _updateMyReadRecv(what, seq, ts) {\n let oldVal, doUpdate = false;\n\n seq = seq | 0;\n this.seq = this.seq | 0;\n this.read = this.read | 0;\n this.recv = this.recv | 0;\n switch (what) {\n case 'recv':\n oldVal = this.recv;\n this.recv = Math.max(this.recv, seq);\n doUpdate = (oldVal != this.recv);\n break;\n case 'read':\n oldVal = this.read;\n this.read = Math.max(this.read, seq);\n doUpdate = (oldVal != this.read);\n break;\n case 'msg':\n oldVal = this.seq;\n this.seq = Math.max(this.seq, seq);\n if (!this.touched || this.touched < ts) {\n this.touched = ts;\n }\n doUpdate = (oldVal != this.seq);\n break;\n }\n\n // Sanity checks.\n if (this.recv < this.read) {\n this.recv = this.read;\n doUpdate = true;\n }\n if (this.seq < this.recv) {\n this.seq = this.recv;\n if (!this.touched || this.touched < ts) {\n this.touched = ts;\n }\n doUpdate = true;\n }\n this.unread = this.seq - this.read;\n return doUpdate;\n }\n /**\n * Get user description from global cache. The user does not need to be a\n * subscriber of this topic.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - ID of the user to fetch.\n * @return {Object} user description or undefined.\n */\n userDesc(uid) {\n // TODO: handle asynchronous requests\n const user = this._cacheGetUser(uid);\n if (user) {\n return user; // Promise.resolve(user)\n }\n }\n /**\n * Get description of the p2p peer from subscription cache.\n * @memberof Tinode.Topic#\n *\n * @return {Object} peer's description or undefined.\n */\n p2pPeerDesc() {\n if (!this.isP2PType()) {\n return undefined;\n }\n return this._users[this.name];\n }\n /**\n * Iterate over cached subscribers. If callback is undefined, use this.onMetaSub.\n * @memberof Tinode.Topic#\n *\n * @param {function} callback - Callback which will receive subscribers one by one.\n * @param {Object=} context - Value of `this` inside the `callback`.\n */\n subscribers(callback, context) {\n const cb = (callback || this.onMetaSub);\n if (cb) {\n for (let idx in this._users) {\n cb.call(context, this._users[idx], idx, this._users);\n }\n }\n }\n /**\n * Get a copy of cached tags.\n * @memberof Tinode.Topic#\n *\n * @return {Array.} a copy of tags\n */\n tags() {\n // Return a copy.\n return this._tags.slice(0);\n }\n /**\n * Get auxiliary entry by key.\n * @memberof Tinode.Topic#\n * @param {string} key - auxiliary data key to retrieve.\n * @return {Object} value for the key or undefined.\n */\n aux(key) {\n return this._aux[key];\n }\n /**\n * Get alias value (unique tag with alias: prefix), if present.\n * The prefix is stripped off.\n * @memberof Tinode.Topic#\n * @return {string} alias or undefined.\n */\n alias() {\n const alias = this._tags && this._tags.find(t => t.startsWith(Const.TAG_ALIAS));\n if (!alias) {\n return undefined;\n }\n // Remove 'alias:' prefix.\n return alias.substring(Const.TAG_ALIAS.length);\n }\n\n /**\n * Get cached subscription for the given user ID.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - id of the user to query for\n * @return user description or undefined.\n */\n subscriber(uid) {\n return this._users[uid];\n }\n /**\n * Iterate over versions of a message: call callback for each version (excluding original).\n * If callback is undefined, does nothing.\n * @memberof Tinode.Topic#\n *\n * @param {number} origSeq - seq ID of the original message.\n * @param {Tinode.ForEachCallbackType} callback - Callback which will receive messages one by one. See {@link Tinode.CBuffer#forEach}\n * @param {Object} context - Value of `this` inside the `callback`.\n */\n messageVersions(origSeq, callback, context) {\n if (!callback) {\n // No callback? We are done then.\n return;\n }\n const versions = this._messageVersions[origSeq];\n if (!versions) {\n return;\n }\n versions.forEach(callback, undefined, undefined, context);\n }\n /**\n * Iterate over cached messages: call callback for each message in the range [sinceIdx, beforeIdx).\n * If callback is undefined, use this.onData.\n * @memberof Tinode.Topic#\n *\n * @param {Tinode.ForEachCallbackType} callback - Callback which will receive messages one by one. See {@link Tinode.CBuffer#forEach}\n * @param {number} sinceId - Optional seqId to start iterating from (inclusive).\n * @param {number} beforeId - Optional seqId to stop iterating before it is reached (exclusive).\n * @param {Object} context - Value of `this` inside the `callback`.\n */\n messages(callback, sinceId, beforeId, context) {\n const cb = (callback || this.onData);\n if (cb) {\n const startIdx = typeof sinceId == 'number' ? this._messages.find({\n seq: sinceId\n }, true) : undefined;\n const beforeIdx = typeof beforeId == 'number' ? this._messages.find({\n seq: beforeId\n }, true) : undefined;\n if (startIdx != -1 && beforeIdx != -1) {\n // Step 1. Filter out all replacement messages and\n // save displayable messages in a temporary buffer.\n let msgs = [];\n this._messages.forEach((msg, unused1, unused2, i) => {\n if (Topic.#isReplacementMsg(msg)) {\n // Skip replacements.\n return;\n }\n if (msg._deleted) {\n // Skip deleted ranges.\n return;\n }\n // In case the massage was edited, replace timestamp of the version with the original's timestamp.\n const latest = this.latestMsgVersion(msg.seq) || msg;\n if (!latest._origTs) {\n latest._origTs = latest.ts;\n latest._origSeq = latest.seq;\n latest.ts = msg.ts;\n latest.seq = msg.seq;\n }\n msgs.push({\n data: latest,\n idx: i\n });\n }, startIdx, beforeIdx, {});\n // Step 2. Loop over displayble messages invoking cb on each of them.\n msgs.forEach((val, i) => {\n cb.call(context, val.data,\n (i > 0 ? msgs[i - 1].data : undefined),\n (i < msgs.length - 1 ? msgs[i + 1].data : undefined), val.idx);\n });\n }\n }\n }\n /**\n * Get the message from cache by literal seq (does not resolve message edits).\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - message seqId to search for.\n * @returns {Object} the message with the given seq or undefined, if no such message is found.\n */\n findMessage(seq) {\n const idx = this._messages.find({\n seq: seq\n });\n if (idx >= 0) {\n return this._messages.getAt(idx);\n }\n return undefined;\n }\n /**\n * Get the most recent non-deleted message from cache.\n * @memberof Tinode.Topic#\n *\n * @returns {Object} the most recent cached message or undefined, if no messages are cached.\n */\n latestMessage() {\n return this._messages.getLast(msg => !msg._deleted);\n }\n /**\n * Get the latest version for message.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - original seq ID of the message.\n * @returns {Object} the latest version of the message or null if message not found.\n */\n latestMsgVersion(seq) {\n const versions = this._messageVersions[seq];\n return versions ? versions.getLast() : null;\n }\n /**\n * Get the maximum cached seq ID.\n * @memberof Tinode.Topic#\n *\n * @returns {number} the greatest seq ID in cache.\n */\n maxMsgSeq() {\n return this._maxSeq;\n }\n /**\n * Get the minimum cached seq ID.\n * @memberof Tinode.Topic#\n *\n * @returns {number} the smallest seq ID in cache or 0.\n */\n minMsgSeq() {\n return this._minSeq;\n }\n /**\n * Get the maximum deletion ID.\n * @memberof Tinode.Topic#\n *\n * @returns {number} the greatest deletion ID.\n */\n maxClearId() {\n return this._maxDel;\n }\n /**\n * Get the number of messages in the cache.\n * @memberof Tinode.Topic#\n *\n * @returns {number} count of cached messages.\n */\n messageCount() {\n return this._messages.length();\n }\n /**\n * Iterate over cached unsent messages. Wraps {@link Tinode.Topic#messages}.\n * @memberof Tinode.Topic#\n *\n * @param {function} callback - Callback which will receive messages one by one. See {@link Tinode.CBuffer#forEach}\n * @param {Object} context - Value of this inside the callback.\n */\n queuedMessages(callback, context) {\n if (!callback) {\n throw new Error(\"Callback must be provided\");\n }\n this.messages(callback, Const.LOCAL_SEQID, undefined, context);\n }\n /**\n * Get the number of topic subscribers who marked this message as either recv or read\n * Current user is excluded from the count.\n * @memberof Tinode.Topic#\n *\n * @param {string} what - what action to consider: received \"recv\" or read \"read\".\n * @param {number} seq - ID or the message read or received.\n *\n * @returns {number} the number of subscribers who marked the message with the given ID as read or received.\n */\n msgReceiptCount(what, seq) {\n let count = 0;\n if (seq > 0) {\n const me = this._tinode.getCurrentUserID();\n for (let idx in this._users) {\n const user = this._users[idx];\n if (user.user !== me && user[what] >= seq) {\n count++;\n }\n }\n }\n return count;\n }\n /**\n * Get the number of topic subscribers who marked this message (and all older messages) as read.\n * The current user is excluded from the count.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - message id to check.\n * @returns {number} number of subscribers who claim to have received the message.\n */\n msgReadCount(seq) {\n return this.msgReceiptCount('read', seq);\n }\n /**\n * Get the number of topic subscribers who marked this message (and all older messages) as received.\n * The current user is excluded from the count.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - Message id to check.\n * @returns {number} Number of subscribers who claim to have received the message.\n */\n msgRecvCount(seq) {\n return this.msgReceiptCount('recv', seq);\n }\n /**\n * Check if cached message IDs indicate that the server may have more messages.\n * @memberof Tinode.Topic#\n *\n * @param {number} min - smallest seq ID loaded range.\n * @param {number} max - greatest seq ID in loaded range.\n * @param {boolean} newer - if true, check for newer messages only.\n * @returns {Array.} - missing ranges in the selected direction.\n */\n msgHasMoreMessages(min, max, newer) {\n // Find gaps in cached messages.\n const gaps = [];\n if (min >= max) {\n return gaps;\n }\n let maxSeq = 0;\n let gap;\n this._messages.forEach((msg, prev) => {\n const p = prev || {\n seq: 0\n };\n const expected = p._deleted ? p.hi : p.seq + 1;\n if (msg.seq > expected) {\n gap = {\n low: expected,\n hi: msg.seq\n };\n } else {\n gap = null;\n }\n // If newer: collect all gaps from min to infinity.\n // If older: collect all gaps from max to zero.\n if (gap && (newer ? gap.hi >= min : gap.low < max)) {\n gaps.push(gap);\n }\n maxSeq = expected;\n });\n\n if (maxSeq < this.seq) {\n gap = {\n low: maxSeq + 1,\n hi: this.seq + 1\n };\n if (newer ? gap.hi >= min : gap.low < max) {\n gaps.push(gap);\n }\n }\n return gaps;\n }\n /**\n * Check if the given seq Id is id of the most recent message.\n * @memberof Tinode.Topic#\n *\n * @param {number} seqId id of the message to check\n */\n isNewMessage(seqId) {\n return this._maxSeq <= seqId;\n }\n /**\n * Remove one message from local cache.\n * @memberof Tinode.Topic#\n *\n * @param {number} seqId id of the message to remove from cache.\n * @returns {Message} removed message or undefined if such message was not found.\n */\n flushMessage(seqId) {\n const idx = this._messages.find({\n seq: seqId\n });\n delete this._messageVersions[seqId];\n if (idx >= 0) {\n this._tinode._db.remMessages(this.name, seqId);\n return this._messages.delAt(idx);\n }\n return undefined;\n }\n /**\n * Remove a range of messages from the local cache.\n * @memberof Tinode.Topic#\n *\n * @param {number} fromId seq ID of the first message to remove (inclusive).\n * @param {number} untilId seqID of the last message to remove (exclusive).\n *\n * @returns {Message[]} array of removed messages (could be empty).\n */\n flushMessageRange(fromId, untilId) {\n // Remove range from persistent cache.\n this._tinode._db.remMessages(this.name, fromId, untilId);\n\n // Remove all versions keyed by IDs in the range.\n for (let i = fromId; i < untilId; i++) {\n delete this._messageVersions[i];\n }\n\n // start, end: find insertion points (nearest == true).\n const since = this._messages.find({\n seq: fromId\n }, true);\n return since >= 0 ? this._messages.delRange(since, this._messages.find({\n seq: untilId\n }, true)) : [];\n }\n /**\n * Update message's seqId.\n * @memberof Tinode.Topic#\n *\n * @param {Object} pub message object.\n * @param {number} newSeqId new seq id for pub.\n */\n swapMessageId(pub, newSeqId) {\n const idx = this._messages.find(pub);\n const numMessages = this._messages.length();\n if (0 <= idx && idx < numMessages) {\n // Remove message with the old seq ID.\n this._messages.delAt(idx);\n this._tinode._db.remMessages(this.name, pub.seq);\n // Add message with the new seq ID.\n pub.seq = newSeqId;\n this._messages.put(pub);\n this._tinode._db.addMessage(pub);\n }\n }\n /**\n * Attempt to stop message from being sent.\n * @memberof Tinode.Topic#\n *\n * @param {number} seqId id of the message to stop sending and remove from cache.\n *\n * @returns {boolean} true if message was cancelled, false otherwise.\n */\n cancelSend(seqId) {\n const idx = this._messages.find({\n seq: seqId\n });\n if (idx >= 0) {\n const msg = this._messages.getAt(idx);\n const status = this.msgStatus(msg);\n if (status == Const.MESSAGE_STATUS_QUEUED ||\n status == Const.MESSAGE_STATUS_FAILED ||\n status == Const.MESSAGE_STATUS_FATAL) {\n this._tinode._db.remMessages(this.name, seqId);\n msg._cancelled = true;\n this._messages.delAt(idx);\n if (this.onData) {\n // Calling with no parameters to indicate the message was deleted.\n this.onData();\n }\n return true;\n }\n }\n return false;\n }\n /**\n * Get type of the topic: me, p2p, grp, fnd...\n * @memberof Tinode.Topic#\n *\n * @returns {string} One of 'me', 'p2p', 'grp', 'fnd', 'sys' or undefined.\n */\n getType() {\n return Topic.topicType(this.name);\n }\n /**\n * Get current user's access mode of the topic.\n * @memberof Tinode.Topic#\n *\n * @returns {Tinode.AccessMode} - user's access mode\n */\n getAccessMode() {\n return this.acs;\n }\n /**\n * Set current user's access mode of the topic.\n * @memberof Tinode.Topic#\n *\n * @param {AccessMode | Object} acs - access mode to set.\n */\n setAccessMode(acs) {\n return this.acs = new AccessMode(acs);\n }\n /**\n * Get topic's default access mode.\n * @memberof Tinode.Topic#\n *\n * @returns {Tinode.DefAcs} - access mode, such as {auth: `RWP`, anon: `N`}.\n */\n getDefaultAccess() {\n return this.defacs;\n }\n /**\n * Initialize new meta {@link Tinode.GetQuery} builder. The query is attched to the current topic.\n * It will not work correctly if used with a different topic.\n * @memberof Tinode.Topic#\n *\n * @returns {Tinode.MetaGetBuilder} query attached to the current topic.\n */\n startMetaQuery() {\n return new MetaGetBuilder(this);\n }\n /**\n * Check if topic is archived, i.e. private.arch == true.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is archived, false otherwise.\n */\n isArchived() {\n return this.private && !!this.private.arch;\n }\n /**\n * Check if topic is a 'me' topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a 'me' topic, false otherwise.\n */\n isMeType() {\n return Topic.isMeTopicName(this.name);\n }\n /**\n * Check if topic is a 'slf' topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a 'slf' topic, false otherwise.\n */\n isSelfType() {\n return Topic.isSelfTopicName(this.name);\n }\n /**\n * Check if topic is a channel.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a channel, false otherwise.\n */\n isChannelType() {\n return Topic.isChannelTopicName(this.name);\n }\n /**\n * Check if topic is a group topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a group, false otherwise.\n */\n isGroupType() {\n return Topic.isGroupTopicName(this.name);\n }\n /**\n * Check if topic is a p2p topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a p2p topic, false otherwise.\n */\n isP2PType() {\n return Topic.isP2PTopicName(this.name);\n }\n /**\n * Check if topic is a communication topic, i.e. a group or p2p topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a p2p or group topic, false otherwise.\n */\n isCommType() {\n return Topic.isCommTopicName(this.name);\n }\n /**\n * Get status (queued, sent, received etc) of a given message in the context\n * of this topic.\n * @memberof Tinode.Topic#\n *\n * @param {Message} msg - message to check for status.\n * @param {boolean} upd - update chached message status.\n *\n * @returns message status constant.\n */\n msgStatus(msg, upd) {\n let status = Const.MESSAGE_STATUS_NONE;\n if (this._tinode.isMe(msg.from)) {\n if (msg._sending) {\n status = Const.MESSAGE_STATUS_SENDING;\n } else if (msg._fatal || msg._cancelled) {\n status = Const.MESSAGE_STATUS_FATAL;\n } else if (msg._failed) {\n status = Const.MESSAGE_STATUS_FAILED;\n } else if (msg.seq >= Const.LOCAL_SEQID) {\n status = Const.MESSAGE_STATUS_QUEUED;\n } else if (this.msgReadCount(msg.seq) > 0) {\n status = Const.MESSAGE_STATUS_READ;\n } else if (this.msgRecvCount(msg.seq) > 0) {\n status = Const.MESSAGE_STATUS_RECEIVED;\n } else if (msg.seq > 0) {\n status = Const.MESSAGE_STATUS_SENT;\n }\n } else {\n status = Const.MESSAGE_STATUS_TO_ME;\n }\n\n if (upd && msg._status != status) {\n msg._status = status;\n this._tinode._db.updMessageStatus(this.name, msg.seq, status);\n }\n\n return status;\n }\n\n // If msg is a replacement for another message, save the msg in the message versions cache\n // as a newer version for the message it's supposed to replace.\n _maybeUpdateMessageVersionsCache(msg) {\n if (!Topic.#isReplacementMsg(msg)) {\n // Check if this message is the original in the chain of edits and if so\n // ensure all version have the same sender.\n if (this._messageVersions[msg.seq]) {\n // Remove versions with different 'from'.\n this._messageVersions[msg.seq].filter(version => version.from == msg.from);\n if (this._messageVersions[msg.seq].isEmpty()) {\n delete this._messageVersions[msg.seq];\n }\n }\n return;\n }\n\n const targetSeq = parseInt(msg.head.replace.split(':')[1]);\n if (targetSeq > msg.seq) {\n // Substitutes are supposed to have higher seq ids.\n return;\n }\n const targetMsg = this.findMessage(targetSeq);\n if (targetMsg && targetMsg.from != msg.from) {\n // Substitute cannot change the sender.\n return;\n }\n const versions = this._messageVersions[targetSeq] || new CBuffer((a, b) => {\n return a.seq - b.seq;\n }, true);\n versions.put(msg);\n this._messageVersions[targetSeq] = versions;\n }\n\n // Process data message\n _routeData(data) {\n if (data.content) {\n if (!this.touched || this.touched < data.ts) {\n this.touched = data.ts;\n this._tinode._db.updTopic(this);\n }\n }\n\n if (data.seq > this._maxSeq) {\n this._maxSeq = data.seq;\n this.msgStatus(data, true);\n // Ackn receiving the message.\n clearTimeout(this._recvNotificationTimer);\n this._recvNotificationTimer = setTimeout(_ => {\n this._recvNotificationTimer = null;\n this.noteRecv(this._maxSeq);\n }, Const.RECV_TIMEOUT);\n }\n\n if (data.seq < this._minSeq || this._minSeq == 0) {\n this._minSeq = data.seq;\n }\n\n const outgoing = ((!this.isChannelType() && !data.from) || this._tinode.isMe(data.from));\n\n if (data.head && data.head.webrtc && data.head.mime == Drafty.getContentType() && data.content) {\n // Rewrite VC body with info from the headers.\n const upd = {\n state: data.head.webrtc,\n duration: data.head['webrtc-duration'],\n incoming: !outgoing,\n };\n if (data.head.vc) {\n upd.vc = true;\n }\n data.content = Drafty.updateVideoCall(data.content, upd);\n }\n\n if (!data._noForwarding) {\n this._messages.put(data);\n this._tinode._db.addMessage(data);\n this._maybeUpdateMessageVersionsCache(data);\n }\n\n if (this.onData) {\n this.onData(data);\n }\n\n // Update locally cached contact with the new message count.\n const what = outgoing ? 'read' : 'msg';\n this._updateMyReadRecv(what, data.seq, data.ts);\n\n if (!outgoing && data.from) {\n // Mark messages as read by the sender.\n this._routeInfo({\n what: 'read',\n from: data.from,\n seq: data.seq,\n _noForwarding: true\n });\n }\n\n // Notify 'me' listeners of the change.\n this._tinode.getMeTopic()._refreshContact(what, this);\n }\n\n // Process metadata message\n _routeMeta(meta) {\n if (meta.desc) {\n this._processMetaDesc(meta.desc);\n }\n if (meta.sub && meta.sub.length > 0) {\n this._processMetaSubs(meta.sub);\n }\n if (meta.del) {\n this._processDelMessages(meta.del.clear, meta.del.delseq);\n }\n if (meta.tags) {\n this._processMetaTags(meta.tags);\n }\n if (meta.cred) {\n this._processMetaCreds(meta.cred);\n }\n if (meta.aux) {\n this._processMetaAux(meta.aux);\n }\n if (this.onMeta) {\n this.onMeta(meta);\n }\n }\n // Process presence change message\n _routePres(pres) {\n let user, uid;\n switch (pres.what) {\n case 'del':\n // Delete cached messages.\n this._processDelMessages(pres.clear, pres.delseq);\n break;\n case 'on':\n case 'off':\n // Update online status of a subscription.\n user = this._users[pres.src];\n if (user) {\n user.online = pres.what == 'on';\n } else {\n this._tinode.logger(\"WARNING: Presence update for an unknown user\", this.name, pres.src);\n }\n break;\n case 'term':\n // Attachment to topic is terminated probably due to cluster rehashing.\n this._resetSub();\n break;\n case 'upd':\n // A topic subscriber has updated his description.\n // Issue {get sub} only if the current user has no p2p topics with the updated user (p2p name is not in cache).\n // Otherwise 'me' will issue a {get desc} request.\n if (pres.src && !this._tinode.isTopicCached(pres.src)) {\n this.getMeta(this.startMetaQuery().withOneSub(undefined, pres.src).build());\n }\n break;\n case 'aux':\n // Auxiliary data updated.\n this.getMeta(this.startMetaQuery().withAux().build());\n break;\n case 'acs':\n uid = pres.src || this._tinode.getCurrentUserID();\n user = this._users[uid];\n if (!user) {\n // Update for an unknown user: notification of a new subscription.\n const acs = new AccessMode().updateAll(pres.dacs);\n if (acs && acs.mode != AccessMode._NONE) {\n user = this._cacheGetUser(uid);\n if (!user) {\n user = {\n user: uid,\n acs: acs\n };\n this.getMeta(this.startMetaQuery().withOneSub(undefined, uid).build());\n } else {\n user.acs = acs;\n }\n user.updated = new Date();\n this._processMetaSubs([user]);\n }\n } else {\n // Known user\n user.acs.updateAll(pres.dacs);\n // Update user's access mode.\n this._processMetaSubs([{\n user: uid,\n updated: new Date(),\n acs: user.acs\n }]);\n }\n break;\n default:\n this._tinode.logger(\"INFO: Ignored presence update\", pres.what);\n }\n\n if (this.onPres) {\n this.onPres(pres);\n }\n }\n // Process {info} message\n _routeInfo(info) {\n switch (info.what) {\n case 'recv':\n case 'read':\n const user = this._users[info.from];\n if (user) {\n user[info.what] = info.seq;\n if (user.recv < user.read) {\n user.recv = user.read;\n }\n }\n const msg = this.latestMessage();\n if (msg) {\n this.msgStatus(msg, true);\n }\n\n // If this is an update from the current user, update the cache with the new count.\n if (this._tinode.isMe(info.from) && !info._noForwarding) {\n this._updateMyReadRecv(info.what, info.seq);\n }\n\n // Notify 'me' listener of the status change.\n this._tinode.getMeTopic()._refreshContact(info.what, this);\n break;\n case 'kp':\n case 'kpa':\n case 'kpv':\n // Typing or audio/video recording notification. Do nothing.\n break;\n case 'call':\n // Do nothing here.\n break;\n default:\n this._tinode.logger(\"INFO: Ignored info update\", info.what);\n }\n\n if (this.onInfo) {\n this.onInfo(info);\n }\n }\n // Called by Tinode when meta.desc packet is received.\n // Called by 'me' topic on contact update (desc._noForwarding is true).\n _processMetaDesc(desc) {\n if (this.isP2PType()) {\n // Synthetic desc may include defacs for p2p topics which is useless.\n // Remove it.\n delete desc.defacs;\n\n // Update to p2p desc is the same as user update. Update cached user.\n this._tinode._db.updUser(this.name, desc.public);\n }\n\n // Copy parameters from desc object to this topic.\n mergeObj(this, desc);\n // Update persistent cache.\n this._tinode._db.updTopic(this);\n\n // Notify 'me' listener, if available:\n if (this.name !== Const.TOPIC_ME && !desc._noForwarding) {\n const me = this._tinode.getMeTopic();\n if (me.onMetaSub) {\n me.onMetaSub(this);\n }\n if (me.onSubsUpdated) {\n me.onSubsUpdated([this.name], 1);\n }\n }\n\n if (this.onMetaDesc) {\n this.onMetaDesc(this);\n }\n }\n // Called by Tinode when meta.sub is recived or in response to received\n // {ctrl} after setMeta-sub.\n _processMetaSubs(subs) {\n for (let idx in subs) {\n const sub = subs[idx];\n\n // Fill defaults.\n sub.online = !!sub.online;\n // Update timestamp of the most recent subscription update.\n this._lastSubsUpdate = new Date(Math.max(this._lastSubsUpdate, sub.updated));\n\n let user = null;\n if (!sub.deleted) {\n // If this is a change to user's own permissions, update them in topic too.\n // Desc will update 'me' topic.\n if (this._tinode.isMe(sub.user) && sub.acs) {\n this._processMetaDesc({\n updated: sub.updated,\n touched: sub.touched,\n acs: sub.acs\n });\n }\n user = this._updateCachedUser(sub.user, sub);\n } else {\n // Subscription is deleted, remove it from topic (but leave in Users cache)\n delete this._users[sub.user];\n user = sub;\n }\n\n if (this.onMetaSub) {\n this.onMetaSub(user);\n }\n }\n\n if (this.onSubsUpdated) {\n this.onSubsUpdated(Object.keys(this._users));\n }\n }\n // Called by Tinode when meta.tags is recived.\n _processMetaTags(tags) {\n if (tags == Const.DEL_CHAR || (tags.length == 1 && tags[0] == Const.DEL_CHAR)) {\n tags = [];\n }\n this._tags = tags;\n this._tinode._db.updTopic(this);\n if (this.onTagsUpdated) {\n this.onTagsUpdated(tags);\n }\n }\n // Do nothing for topics other than 'me'\n _processMetaCreds(creds) {}\n\n // Called by Tinode when meta.aux is recived.\n _processMetaAux(aux) {\n aux = (!aux || aux == Const.DEL_CHAR) ? {} : aux;\n this._aux = mergeObj(this._aux, aux);\n this._tinode._db.updTopic(this);\n if (this.onAuxUpdated) {\n this.onAuxUpdated(this._aux);\n }\n }\n\n // Delete cached messages and update cached transaction IDs\n _processDelMessages(clear, delseq) {\n this._maxDel = Math.max(clear, this._maxDel);\n this.clear = Math.max(clear, this.clear);\n let count = 0;\n if (Array.isArray(delseq)) {\n delseq.forEach(rec => {\n if (!rec.hi) {\n count++;\n this.flushMessage(rec.low);\n } else {\n count += rec.hi - rec.low;\n this.flushMessageRange(rec.low, rec.hi);\n }\n this._messages.put({\n seq: rec.low,\n low: rec.low,\n hi: rec.hi,\n _deleted: true\n });\n });\n\n this._tinode._db.addDelLog(this.name, clear, delseq);\n }\n\n if (count > 0) {\n if (this.onData) {\n this.onData();\n }\n }\n }\n // Topic is informed that the entire response to {get what=data} has been received.\n _allMessagesReceived(count) {\n\n if (this.onAllMessagesReceived) {\n this.onAllMessagesReceived(count);\n }\n }\n // Reset subscribed state\n _resetSub() {\n this._attached = false;\n }\n // This topic is either deleted or unsubscribed from.\n _gone() {\n this._messages.reset();\n this._tinode._db.remMessages(this.name);\n this._users = {};\n this.acs = new AccessMode(null);\n this.private = null;\n this.public = null;\n this.trusted = null;\n this._maxSeq = 0;\n this._minSeq = 0;\n this._attached = false;\n\n const me = this._tinode.getMeTopic();\n if (me) {\n me._routePres({\n _noForwarding: true,\n what: 'gone',\n topic: Const.TOPIC_ME,\n src: this.name\n });\n }\n if (this.onDeleteTopic) {\n this.onDeleteTopic();\n }\n }\n // Update global user cache and local subscribers cache.\n // Don't call this method for non-subscribers.\n _updateCachedUser(uid, obj) {\n // Fetch user object from the global cache.\n // This is a clone of the stored object\n let cached = this._cacheGetUser(uid);\n cached = mergeObj(cached || {}, obj);\n // Save to global cache\n this._cachePutUser(uid, cached);\n // Save to the list of topic subsribers.\n return mergeToCache(this._users, uid, cached);\n }\n // Get local seqId for a queued message.\n _getQueuedSeqId() {\n return this._queuedSeqId++;\n }\n\n // Load most recent messages from persistent cache.\n _loadMessages(db, query) {\n query = query || {};\n query.limit = query.limit || Const.DEFAULT_MESSAGES_PAGE;\n\n // Count of message loaded from DB.\n let count = 0;\n return db.readMessages(this.name, query)\n .then(msgs => {\n msgs.forEach(data => {\n if (data.seq > this._maxSeq) {\n this._maxSeq = data.seq;\n }\n if (data.seq < this._minSeq || this._minSeq == 0) {\n this._minSeq = data.seq;\n }\n this._messages.put(data);\n this._maybeUpdateMessageVersionsCache(data);\n });\n count = msgs.length;\n })\n .then(_ => db.readDelLog(this.name, query))\n .then(dellog => {\n return dellog.forEach(rec => {\n this._messages.put({\n seq: rec.low,\n low: rec.low,\n hi: rec.hi,\n _deleted: true\n });\n });\n })\n .then(_ => {\n // DEBUG\n return count;\n });\n }\n\n // Push or {pres}: message received.\n _updateReceived(seq, act) {\n this.touched = new Date();\n this.seq = seq | 0;\n // Check if message is sent by the current user. If so it's been read already.\n if (!act || this._tinode.isMe(act)) {\n this.read = this.read ? Math.max(this.read, this.seq) : this.seq;\n this.recv = this.recv ? Math.max(this.read, this.recv) : this.read;\n }\n this.unread = this.seq - (this.read | 0);\n this._tinode._db.updTopic(this);\n }\n}\n","/**\n * @file Definition of 'fnd' topic.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport * as Const from './config.js';\nimport Topic from './topic.js';\nimport {\n mergeToCache\n} from './utils.js';\n\n\n/**\n * Special case of {@link Tinode.Topic} for searching for contacts and group topics\n * @extends Tinode.Topic\n *\n */\nexport default class TopicFnd extends Topic {\n // List of users and topics uid or topic_name -> Contact object)\n _contacts = {};\n\n /**\n * Create TopicFnd.\n *\n * @param {TopicFnd.Callbacks} callbacks - Callbacks to receive various events.\n */\n constructor(callbacks) {\n super(Const.TOPIC_FND, callbacks);\n }\n\n // Override the original Topic._processMetaSubs\n _processMetaSubs(subs) {\n let updateCount = Object.getOwnPropertyNames(this._contacts).length;\n // Reset contact list.\n this._contacts = {};\n for (let idx in subs) {\n let sub = subs[idx];\n const indexBy = sub.topic ? sub.topic : sub.user;\n\n sub = mergeToCache(this._contacts, indexBy, sub);\n updateCount++;\n\n if (this.onMetaSub) {\n this.onMetaSub(sub);\n }\n }\n\n if (updateCount > 0 && this.onSubsUpdated) {\n this.onSubsUpdated(Object.keys(this._contacts));\n }\n }\n\n /**\n * Publishing to TopicFnd is not supported. {@link Topic#publish} is overriden and thows an {Error} if called.\n * @memberof Tinode.TopicFnd#\n * @throws {Error} Always throws an error.\n */\n publish() {\n return Promise.reject(new Error(\"Publishing to 'fnd' is not supported\"));\n }\n\n /**\n * setMeta to TopicFnd resets contact list in addition to sending the message.\n * @memberof Tinode.TopicFnd#\n * @param {Tinode.SetParams} params parameters to update.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n setMeta(params) {\n return Object.getPrototypeOf(TopicFnd.prototype).setMeta.call(this, params).then(_ => {\n if (Object.keys(this._contacts).length > 0) {\n this._contacts = {};\n if (this.onSubsUpdated) {\n this.onSubsUpdated([]);\n }\n }\n });\n }\n\n /**\n * Check if the given tag is unique by asking the server.\n * @param tag tag to check.\n * @return promise to be resolved with true if the tag is unique, false otherwise.\n */\n checkTagUniqueness(tag, caller) {\n return new Promise((resolve, reject) => {\n this.subscribe()\n .then(_ => this.setMeta({\n desc: {\n public: tag\n }\n }))\n .then(_ => this.getMeta(this.startMetaQuery().withTags().build()))\n .then(meta => {\n if (!meta || !Array.isArray(meta.tags) || meta.tags.length == 0) {\n resolve(true);\n }\n const tags = meta.tags.filter(t => t !== caller);\n resolve(tags.length == 0);\n })\n .catch(err => {\n reject(err);\n });\n });\n }\n\n /**\n * Iterate over found contacts. If callback is undefined, use {@link this.onMetaSub}.\n * @function\n * @memberof Tinode.TopicFnd#\n * @param {TopicFnd.ContactCallback} callback - Callback to call for each contact.\n * @param {Object} context - Context to use for calling the `callback`, i.e. the value of `this` inside the callback.\n */\n contacts(callback, context) {\n const cb = (callback || this.onMetaSub);\n if (cb) {\n for (let idx in this._contacts) {\n cb.call(context, this._contacts[idx], idx, this._contacts);\n }\n }\n }\n}\n","/**\n * @file Definition of 'me' topic.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport AccessMode from './access-mode.js';\nimport * as Const from './config.js';\nimport Topic from './topic.js';\nimport {\n mergeObj\n} from './utils.js';\n\n/**\n * @class TopicMe - special case of {@link Tinode.Topic} for\n * managing data of the current user, including contact list.\n * @extends Tinode.Topic\n * @memberof Tinode\n *\n * @param {TopicMe.Callbacks} callbacks - Callbacks to receive various events.\n */\nexport default class TopicMe extends Topic {\n onContactUpdate;\n\n constructor(callbacks) {\n super(Const.TOPIC_ME, callbacks);\n\n // me-specific callbacks\n if (callbacks) {\n this.onContactUpdate = callbacks.onContactUpdate;\n }\n }\n\n // Override the original Topic._processMetaDesc.\n _processMetaDesc(desc) {\n // Check if online contacts need to be turned off because P permission was removed.\n const turnOff = (desc.acs && !desc.acs.isPresencer()) && (this.acs && this.acs.isPresencer());\n\n // Copy parameters from desc object to this topic.\n mergeObj(this, desc);\n this._tinode._db.updTopic(this);\n // Update current user's record in the global cache.\n this._updateCachedUser(this._tinode._myUID, desc);\n\n // 'P' permission was removed. All topics are offline now.\n if (turnOff) {\n this._tinode.mapTopics((cont) => {\n if (cont.online) {\n cont.online = false;\n cont.seen = Object.assign(cont.seen || {}, {\n when: new Date()\n });\n this._refreshContact('off', cont);\n }\n });\n }\n\n if (this.onMetaDesc) {\n this.onMetaDesc(this);\n }\n }\n\n // Override the original Topic._processMetaSubs\n _processMetaSubs(subs) {\n let updateCount = 0;\n subs.forEach((sub) => {\n const topicName = sub.topic;\n // Don't show 'me' and 'fnd' topics in the list of contacts.\n if (topicName == Const.TOPIC_FND || topicName == Const.TOPIC_ME) {\n return;\n }\n sub.online = !!sub.online;\n\n let cont = null;\n if (sub.deleted) {\n cont = sub;\n this._tinode.cacheRemTopic(topicName);\n this._tinode._db.remTopic(topicName);\n } else {\n // Ensure the values are defined and are integers.\n if (typeof sub.seq != 'undefined') {\n sub.seq = sub.seq | 0;\n sub.recv = sub.recv | 0;\n sub.read = sub.read | 0;\n sub.unread = sub.seq - sub.read;\n }\n\n const topic = this._tinode.getTopic(topicName);\n if (topic._new) {\n delete topic._new;\n }\n\n cont = mergeObj(topic, sub);\n this._tinode._db.updTopic(cont);\n\n if (Topic.isP2PTopicName(topicName)) {\n this._cachePutUser(topicName, cont);\n this._tinode._db.updUser(topicName, cont.public);\n }\n // Notify topic of the update if it's an external update.\n if (!sub._noForwarding && topic) {\n sub._noForwarding = true;\n topic._processMetaDesc(sub);\n }\n }\n\n updateCount++;\n\n if (this.onMetaSub) {\n this.onMetaSub(cont);\n }\n });\n\n if (this.onSubsUpdated && updateCount > 0) {\n const keys = [];\n subs.forEach((s) => {\n keys.push(s.topic);\n });\n this.onSubsUpdated(keys, updateCount);\n }\n }\n\n // Called by Tinode when meta.sub is recived.\n _processMetaCreds(creds, upd) {\n if (creds.length == 1 && creds[0] == Const.DEL_CHAR) {\n creds = [];\n }\n if (upd) {\n creds.forEach((cr) => {\n if (cr.val) {\n // Adding a credential.\n let idx = this._credentials.findIndex((el) => {\n return el.meth == cr.meth && el.val == cr.val;\n });\n if (idx < 0) {\n // Not found.\n if (!cr.done) {\n // Unconfirmed credential replaces previous unconfirmed credential of the same method.\n idx = this._credentials.findIndex((el) => {\n return el.meth == cr.meth && !el.done;\n });\n if (idx >= 0) {\n // Remove previous unconfirmed credential.\n this._credentials.splice(idx, 1);\n }\n }\n this._credentials.push(cr);\n } else {\n // Found. Maybe change 'done' status.\n this._credentials[idx].done = cr.done;\n }\n } else if (cr.resp) {\n // Handle credential confirmation.\n const idx = this._credentials.findIndex((el) => {\n return el.meth == cr.meth && !el.done;\n });\n if (idx >= 0) {\n this._credentials[idx].done = true;\n }\n }\n });\n } else {\n this._credentials = creds;\n }\n if (this.onCredsUpdated) {\n this.onCredsUpdated(this._credentials);\n }\n }\n\n // Process presence change message\n _routePres(pres) {\n if (pres.what == 'term') {\n // The 'me' topic itself is detached. Mark as unsubscribed.\n this._resetSub();\n return;\n }\n\n if (pres.what == 'upd' && pres.src == Const.TOPIC_ME) {\n // Update to me's description. Request updated value.\n this.getMeta(this.startMetaQuery().withDesc().build());\n return;\n }\n\n const cont = this._tinode.cacheGetTopic(pres.src);\n if (cont) {\n switch (pres.what) {\n case 'on': // topic came online\n cont.online = true;\n break;\n case 'off': // topic went offline\n if (cont.online) {\n cont.online = false;\n cont.seen = Object.assign(cont.seen || {}, {\n when: new Date()\n });\n }\n break;\n case 'msg': // new message received\n cont._updateReceived(pres.seq, pres.act);\n break;\n case 'upd': // desc updated\n // Request updated subscription.\n this.getMeta(this.startMetaQuery().withLaterOneSub(pres.src).build());\n break;\n case 'acs': // access mode changed\n // If 'tgt' is not set then this is an update to the permissions of the current user.\n // Otherwise it's an update to group topic subscriber permissions while the topic is offline.\n // Just gnore it then.\n if (!pres.tgt) {\n if (cont.acs) {\n cont.acs.updateAll(pres.dacs);\n } else {\n cont.acs = new AccessMode().updateAll(pres.dacs);\n }\n cont.touched = new Date();\n }\n break;\n case 'ua':\n // user agent changed.\n cont.seen = {\n when: new Date(),\n ua: pres.ua\n };\n break;\n case 'recv':\n // user's other session marked some messges as received.\n pres.seq = pres.seq | 0;\n cont.recv = cont.recv ? Math.max(cont.recv, pres.seq) : pres.seq;\n break;\n case 'read':\n // user's other session marked some messages as read.\n pres.seq = pres.seq | 0;\n cont.read = cont.read ? Math.max(cont.read, pres.seq) : pres.seq;\n cont.recv = cont.recv ? Math.max(cont.read, cont.recv) : cont.recv;\n cont.unread = cont.seq - cont.read;\n break;\n case 'gone':\n // topic deleted or unsubscribed from.\n this._tinode.cacheRemTopic(pres.src);\n if (!cont._deleted) {\n cont._deleted = true;\n cont._attached = false;\n this._tinode._db.markTopicAsDeleted(pres.src, true);\n } else {\n this._tinode._db.remTopic(pres.src);\n }\n break;\n case 'del':\n // Update topic.del value.\n break;\n default:\n this._tinode.logger(\"INFO: Unsupported presence update in 'me'\", pres.what);\n }\n\n this._refreshContact(pres.what, cont);\n } else {\n if (pres.what == 'acs') {\n // New subscriptions and deleted/banned subscriptions have full\n // access mode (no + or - in the dacs string). Changes to known subscriptions are sent as\n // deltas, but they should not happen here.\n const acs = new AccessMode(pres.dacs);\n if (!acs || acs.mode == AccessMode._INVALID) {\n this._tinode.logger(\"ERROR: Invalid access mode update\", pres.src, pres.dacs);\n return;\n } else if (acs.mode == AccessMode._NONE) {\n this._tinode.logger(\"WARNING: Removing non-existent subscription\", pres.src, pres.dacs);\n return;\n } else {\n // New subscription. Send request for the full description.\n // Using .withOneSub (not .withLaterOneSub) to make sure IfModifiedSince is not set.\n this.getMeta(this.startMetaQuery().withOneSub(undefined, pres.src).build());\n // Create a dummy entry to catch online status update.\n const dummy = this._tinode.getTopic(pres.src);\n dummy.topic = pres.src;\n dummy.online = false;\n dummy.acs = acs;\n this._tinode._db.updTopic(dummy);\n }\n } else if (pres.what == 'tags') {\n this.getMeta(this.startMetaQuery().withTags().build());\n } else if (pres.what == 'msg') {\n // Message received for un unknown (previously deleted) topic.\n this.getMeta(this.startMetaQuery().withOneSub(undefined, pres.src).build());\n // Create an entry to catch updates and messages.\n const dummy = this._tinode.getTopic(pres.src);\n dummy._deleted = false;\n this._tinode._db.updTopic(dummy);\n }\n\n this._refreshContact(pres.what, cont);\n }\n\n if (this.onPres) {\n this.onPres(pres);\n }\n }\n\n // Contact is updated, execute callbacks.\n _refreshContact(what, cont) {\n if (this.onContactUpdate) {\n this.onContactUpdate(what, cont);\n }\n }\n\n /**\n * Publishing to TopicMe is not supported. {@link Topic#publish} is overriden and thows an {Error} if called.\n * @memberof Tinode.TopicMe#\n * @throws {Error} Always throws an error.\n */\n publish() {\n return Promise.reject(new Error(\"Publishing to 'me' is not supported\"));\n }\n\n /**\n * Delete validation credential.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} topic - Name of the topic to delete\n * @param {string} user - User ID to remove.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delCredential(method, value) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot delete credential in inactive 'me' topic\"));\n }\n // Send {del} message, return promise\n return this._tinode.delCredential(method, value).then(ctrl => {\n // Remove deleted credential from the cache.\n const index = this._credentials.findIndex((el) => {\n return el.meth == method && el.val == value;\n });\n if (index > -1) {\n this._credentials.splice(index, 1);\n }\n // Notify listeners\n if (this.onCredsUpdated) {\n this.onCredsUpdated(this._credentials);\n }\n return ctrl;\n });\n }\n\n /**\n * @callback contactFilter\n * @param {Object} contact to check for inclusion.\n * @returns {boolean} true if contact should be processed, false to exclude it.\n */\n /**\n * Iterate over cached contacts.\n *\n * @function\n * @memberof Tinode.TopicMe#\n * @param {TopicMe.ContactCallback} callback - Callback to call for each contact.\n * @param {contactFilter=} filter - Optionally filter contacts; include all if filter is false-ish, otherwise\n * include those for which filter returns true-ish.\n * @param {Object=} context - Context to use for calling the `callback`, i.e. the value of `this` inside the callback.\n */\n contacts(callback, filter, context) {\n this._tinode.mapTopics((c, idx) => {\n if (c.isCommType() && (!filter || filter(c))) {\n callback.call(context, c, idx);\n }\n });\n }\n\n /**\n * Get a contact from cache.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} name - Name of the contact to get, either a UID (for p2p topics) or a topic name.\n * @returns {Tinode.Contact} - Contact or `undefined`.\n */\n getContact(name) {\n return this._tinode.cacheGetTopic(name);\n }\n\n /**\n * Get access mode of a given contact from cache.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} name - Name of the contact to get access mode for, either a UID (for p2p topics)\n * or a topic name; if missing, access mode for the 'me' topic itself.\n * @returns {string} - access mode, such as `RWP`.\n */\n getAccessMode(name) {\n if (name) {\n const cont = this._tinode.cacheGetTopic(name);\n return cont ? cont.acs : null;\n }\n return this.acs;\n }\n\n /**\n * Check if contact is archived, i.e. contact.private.arch == true.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} name - Name of the contact to check archived status, either a UID (for p2p topics) or a topic name.\n * @returns {boolean} - true if contact is archived, false otherwise.\n */\n isArchived(name) {\n const cont = this._tinode.cacheGetTopic(name);\n return cont && cont.private && !!cont.private.arch;\n }\n\n /**\n * @typedef Tinode.Credential\n * @memberof Tinode\n * @type Object\n * @property {string} meth - validation method such as 'email' or 'tel'.\n * @property {string} val - credential value, i.e. 'jdoe@example.com' or '+17025551234'\n * @property {boolean} done - true if credential is validated.\n */\n /**\n * Get the user's credentials: email, phone, etc.\n * @memberof Tinode.TopicMe#\n *\n * @returns {Tinode.Credential[]} - array of credentials.\n */\n getCredentials() {\n return this._credentials;\n }\n}\n"],"names":["root","factory","exports","module","define","amd","this","JSON_MIME_TYPE","ALLOWED_ENT_FIELDS","segmenter","Intl","Segmenter","INLINE_STYLES","name","start","end","FMT_WEIGHT","ENTITY_TYPES","dataName","pack","val","test","url","re","slice","FORMAT_TAGS","AU","html_tag","md_tag","undefined","isVoid","BN","BR","CO","DL","EM","EX","FM","HD","HL","HT","IM","LN","MN","RW","QQ","ST","VC","VD","base64toObjectUrl","b64","contentType","logger","bin","atob","length","buf","ArrayBuffer","arr","Uint8Array","i","charCodeAt","URL","createObjectURL","Blob","type","err","message","base64toDataUrl","DECORATORS","open","_","close","data","props","href","target","id","act","ref","mime","Drafty","src","duration","size","tmpPreviewUrl","_tempPreview","previewUrl","downloadUrl","width","height","title","alt","state","preview","premime","poster","preref","txt","fmt","ent","chunkify","line","spans","chunks","span","at","push","chunk","tp","chld","children","toSpanTree","tree","last","draftyToTree","doc","Array","isArray","text","len","key","attachments","forEach","includes","stringToGraphemes","sort","a","b","diff","indexOf","graphemes","spansToTree","treeTopDown","node","child","parent","addNode","n","map","segment","join","att","subspans","inner","tag","treeToDrafty","keymap","c","Object","keys","newKey","transformer","context","dst","call","treeBottomUp","formatter","index","stack","values","pop","shortenTree","limit","tail","lightEntity","allow","copyEntData","lTrim","trimStart","shift","attachmentsToEnd","concat","draftify","startAt","plain","ranges","drafty","light","entries","dc","isEmptyObject","obj","toGraphemeValues","segments","indices","result","graphemeIndex","charIndex","graphemeIndices","correctAt","str","from","init","plainText","parse","content","lines","split","entityMap","entityIndex","blx","entities","block","original","re_start","re_end","exec","start_offset","lastIndexOf","end_offset","spannify","match","extracted","entity","offset","unique","idx","filter","el","extractEntities","ele","s","correctLen","append","first","second","insertImage","imageDesc","ex","refurl","bits","filename","urlPromise","_processing","then","insertVideo","videoDesc","urls","insertAudio","audioDesc","videoCall","audioOnly","aonly","updateVideoCall","params","assign","quote","header","uid","body","appendLineBreak","mention","appendLink","linkData","appendImage","appendAudio","attachFile","attachmentDesc","wrapInto","style","wrapAsForm","insertButton","actionType","actionValue","refUrl","appendButton","attachJSON","UNSAFE_toHTML","format","shorten","forwardedContent","replyContent","startsWith","forwarding","toPlainText","isPlainText","toMarkdown","def","isValid","txt_type","hasAttachments","callback","count","hasEntities","styles","sanitizeEntities","getDownloadUrl","entData","isProcessing","getPreviewUrl","getEntitySize","getEntityMimeType","tagName","attrValue","getContentType","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","getter","__esModule","d","definition","o","defineProperty","enumerable","get","g","globalThis","Function","e","window","prop","prototype","hasOwnProperty","r","Symbol","toStringTag","value","AccessMode","constructor","acs","given","decode","want","mode","side","flag","Error","_BITMASK","_NONE","bitmask","_JOIN","_READ","_WRITE","_PRES","_APPROVE","_SHARE","_DELETE","_OWNER","m0","bit","charAt","toUpperCase","encode","_INVALID","res","update","upd","action","val0","parts","a1","a2","toString","jsonHelper","setMode","m","updateMode","u","getMode","setGiven","updateGiven","getGiven","setWant","w","updateWant","getWant","getMissing","getExcessive","updateAll","isOwner","isPresencer","isMuted","isJoiner","isReader","isWriter","isApprover","isAdmin","isSharer","isDeleter","VERSION","LIBRARY","TOPIC_NEW","TOPIC_NEW_CHAN","TOPIC_ME","TOPIC_FND","TOPIC_GRP","LOCAL_SEQID","DEL_CHAR","TAG_ALIAS","CommError","code","super","jsonParseHelper","date","Date","isNaN","isUrlRelative","isValidDate","getTime","mergeObj","ignore","mergeToCache","cache","newval","simplify","getOwnPropertyNames","normalizeRanges","maxSeq","r1","r2","low","hi","reduce","out","prev","Math","max","listToRanges","list","WebSocketProvider","XHRProvider","NETWORK_ERROR_TEXT","NETWORK_USER","NETWORK_USER_TEXT","makeBaseUrl","host","protocol","version","apiKey","Connection","static","secure","autoreconnect","initialized","config","version_","autoreconnect_","transport","setNetworkProviders","wsProvider","xhrProvider","l","connect","host_","force","Promise","reject","reconnect","disconnect","sendText","msg","isConnected","probe","backoffReset","clearTimeout","timeout","pow","random","onAutoreconnectIteration","setTimeout","prom","catch","_lpURL","_poller","_sender","lp_poller","url_","resolve","poller","promiseCompleted","onreadystatechange","evt","readyState","status","pkt","JSON","responseText","ctrl","sid","send","onOpen","onMessage","onDisconnect","abort","sender","lp_sender","OPEN","conn","onerror","onopen","onclose","onmessage","NETWORK_ERROR","DB_NAME","IDBProvider","DB","db","disabled","onError","source","trx","transaction","event","error","objectStore","getAll","onsuccess","topic","initDatabase","req","onversionchange","onupgradeneeded","objectStoreNames","contains","createObjectStore","keyPath","dellog","indexNames","createIndex","deleteDatabase","onblocked","isReady","updTopic","oncomplete","put","commit","markTopicAsDeleted","deleted","_deleted","remTopic","delete","IDBKeyRange","only","bound","Number","MAX_SAFE_INTEGER","mapTopics","deserializeTopic","updUser","pub","arguments","public","remUser","mapUsers","getUser","user","updSubscription","topicName","sub","mapSubscriptions","addMessage","add","updMessageStatus","seq","_status","remMessages","to","range","readMessages","query","msgs","since","before","openCursor","cursor","continue","addDelLog","delId","clear","readDelLog","entry","maxDelId","f","tags","_tags","setAccessMode","read","unread","getAccessMode","setDatabaseProvider","idbProvider","IndexedDBProvider","LargeFileHelper","tinode","_tinode","_version","_apiKey","_authToken","getAuthToken","xhr","uploadWithBaseUrl","baseUrl","avatarFor","onProgress","onSuccess","onFailure","base","endsWith","instance","setRequestHeader","token","toResolve","toReject","upload","onprogress","lengthComputable","loaded","total","onload","response","statusText","onabort","form","FormData","set","getNextUniqueId","_secure","_host","download","relativeUrl","mimetype","relUrl","location","origin","searchParams","substring","addURLParam","responseType","link","document","createElement","display","setAttribute","appendChild","click","removeChild","revokeObjectURL","reader","FileReader","readAsText","cancel","setNetworkProvider","MetaGetBuilder","what","updated","isP2PType","_lastSubsUpdate","withData","withLaterData","_maxSeq","withDataRanges","withDataList","withEarlierData","_minSeq","withDesc","ims","withLaterDesc","withSub","userOrTopic","opts","getType","withOneSub","withLaterOneSub","withLaterSub","withTags","withCred","withAux","withDel","withLaterDel","_maxDel","extract","build","CBuffer","buffer","compare_","unique_","elem","exact","pivot","found","splice","getAt","getLast","findLast","insert","delAt","delRange","reset","startIdx","beforeIdx","min","find","nearest","isEmpty","Topic","callbacks","created","touched","private","trusted","_users","_queuedSeqId","Const","_noEarlierMsgs","_recvNotificationTimer","_credentials","_aux","_messageVersions","_messages","_attached","_new","_delayedLeaveTimer","onData","onMeta","onPres","onInfo","onMetaDesc","onMetaSub","onSubsUpdated","onTagsUpdated","onCredsUpdated","onAuxUpdated","onDeleteTopic","onAllMessagesReceived","topicType","isMeTopicName","isSelfTopicName","isGroupTopicName","isP2PTopicName","isCommTopicName","isNewGroupTopicName","isChannelTopicName","head","replace","isSubscribed","subscribe","getParams","setParams","_cacheDelSelf","_cachePutSelf","ts","me","getMeTopic","desc","_noForwarding","_processMetaDesc","createMessage","noEcho","publish","publishMessage","_sending","_failed","swapMessageId","_maybeUpdateMessageVersionsCache","_routeData","publishDraft","_getQueuedSeqId","getCurrentUserID","noecho","_db","_cancelled","_fatal","leave","unsub","_resetSub","_gone","leaveDelayed","delay","getMeta","getMessagesPage","gaps","newer","startMetaQuery","_loadMessages","msgHasMoreMessages","getPinnedMessages","pins","aux","remains","setMeta","t","trim","toLowerCase","item","pos","ary","normalizeArray","_processMetaSubs","_processMetaTags","cred","_processMetaCreds","_processMetaAux","subscriber","am","invite","archive","arch","pinMessage","pin","pinned","changed","delMessages","hard","tosend","del","rec","flushMessageRange","flushMessage","delMessagesAll","hardDel","_all","delMessagesList","delMessagesEdits","messageVersions","delTopic","delSubscription","note","_updateMyReadRecv","_refreshContact","noteRecv","noteRead","noteKeyPress","noteRecording","payload","oldVal","doUpdate","recv","userDesc","_cacheGetUser","p2pPeerDesc","subscribers","cb","alias","origSeq","versions","messages","sinceId","beforeId","unused1","unused2","latest","latestMsgVersion","_origTs","_origSeq","findMessage","latestMessage","maxMsgSeq","minMsgSeq","maxClearId","messageCount","queuedMessages","msgReceiptCount","msgReadCount","msgRecvCount","gap","p","expected","isNewMessage","seqId","fromId","untilId","newSeqId","numMessages","cancelSend","msgStatus","getDefaultAccess","defacs","isArchived","isMeType","isSelfType","isChannelType","isGroupType","isCommType","isMe","targetSeq","parseInt","targetMsg","outgoing","webrtc","incoming","vc","_routeInfo","_routeMeta","meta","_processDelMessages","delseq","_routePres","pres","online","isTopicCached","dacs","info","subs","_updateCachedUser","creds","_allMessagesReceived","cached","_cachePutUser","_updateReceived","TopicFnd","_contacts","updateCount","indexBy","getPrototypeOf","checkTagUniqueness","caller","contacts","TopicMe","onContactUpdate","turnOff","_myUID","cont","seen","when","cacheRemTopic","getTopic","cr","findIndex","meth","done","resp","cacheGetTopic","tgt","ua","dummy","delCredential","method","getContact","getCredentials","b64EncodeUnicode","btoa","encodeURIComponent","p1","String","fromCharCode","jsonBuildHelper","pad","sp","repeat","millis","getUTCMilliseconds","getUTCFullYear","getUTCMonth","getUTCDate","getUTCHours","getUTCMinutes","getUTCSeconds","rfc3339DateString","jsonLoggerHelper","WebSocket","XMLHttpRequest","indexedDB","chars","global","input","output","charCode","bc","bs","DBCache","initForNonBrowserApp","Tinode","_appName","_browser","_platform","_hwos","_humanLanguage","_loggingEnabled","_trimLongStrings","_authenticated","_login","_inPacketCount","_messageId","floor","_serverInfo","_deviceToken","_pendingPromises","_expirePromises","_connection","_persist","_cache","onComplete","appName","platform","navigator","product","reactnative","priority","tmp","substr","tokens","m2","v","minor","getBrowserInfo","userAgent","language","detectTransport","promise","persist","all","args","dateString","console","log","onOK","errorText","stringify","onRawMessage","onNetworkProbe","onCtrlMessage","onMetaMessage","onDataMessage","onPresMessage","onInfoMessage","setInterval","expires","hello","clearInterval","func","_cacheDelUser","onLogin","credential","getVersion","getLibrary","isNullValue","isServerAssignedSeq","isValidTagValue","tagSplit","splitAt","prefix","setUniqueTag","uniqueTag","clearTagPrefix","tagByPrefix","clearStorage","initStorage","networkProbe","isAuthenticated","authorizeURL","parsed","account","scheme","secret","login","acc","tmpscheme","tmpsecret","extra","createAccount","createAccountBasic","username","password","updateAccountBasic","onConnect","setDeviceToken","dt","sent","loginBasic","uname","loginToken","requestResetAuthSecret","now","setAuthToken","dft","oobNotification","xfrom","finally","modeGiven","modeWant","delCurrentUser","newGroupTopicName","isChan","getFndTopic","getLargeFileHelper","getCurrentLogin","getServerInfo","report","getServerParam","defaultValue","enableLogging","enabled","trimLongStrings","setHumanLanguage","hl","isTopicOnline","getTopicAccessMode","wantAkn","onWebsocketOpen","MESSAGE_STATUS_NONE","MESSAGE_STATUS_QUEUED","MESSAGE_STATUS_SENDING","MESSAGE_STATUS_FAILED","MESSAGE_STATUS_FATAL","MESSAGE_STATUS_SENT","MESSAGE_STATUS_RECEIVED","MESSAGE_STATUS_READ","MESSAGE_STATUS_TO_ME","MAX_MESSAGE_SIZE","MAX_SUBSCRIBER_COUNT","MIN_TAG_LENGTH","MAX_TAG_LENGTH","MAX_TAG_COUNT","MAX_FILE_UPLOAD_SIZE","REQ_CRED_VALIDATORS","MSG_DELETE_AGE","URI_TOPIC_ID_PREFIX","TAG_EMAIL","TAG_PHONE"],"sourceRoot":""}
\ No newline at end of file
+{"version":3,"file":"tinode.prod.js","mappings":"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","sources":["webpack://tinode/webpack/universalModuleDefinition","webpack://tinode/./src/drafty.js","webpack://tinode/webpack/bootstrap","webpack://tinode/webpack/runtime/compat get default export","webpack://tinode/webpack/runtime/define property getters","webpack://tinode/webpack/runtime/global","webpack://tinode/webpack/runtime/hasOwnProperty shorthand","webpack://tinode/webpack/runtime/make namespace object","webpack://tinode/./src/access-mode.js","webpack://tinode/./version.js","webpack://tinode/./src/config.js","webpack://tinode/./src/comm-error.js","webpack://tinode/./src/utils.js","webpack://tinode/./src/connection.js","webpack://tinode/./src/db.js","webpack://tinode/./src/large-file.js","webpack://tinode/./src/tinode.js","webpack://tinode/./src/meta-builder.js","webpack://tinode/./src/cbuffer.js","webpack://tinode/./src/topic.js","webpack://tinode/./src/fnd-topic.js","webpack://tinode/./src/me-topic.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"tinode\"] = factory();\n\telse\n\t\troot[\"tinode\"] = factory();\n})(this, () => {\nreturn ","/**\n * @copyright 2015-2024 Tinode LLC.\n * @summary Minimally rich text representation and formatting for Tinode.\n * @license Apache 2.0\n *\n * @file Basic parser and formatter for very simple text markup. Mostly targeted at\n * mobile use cases similar to Telegram, WhatsApp, and FB Messenger.\n *\n * Supports conversion of user keyboard input to formatted text:
\n * \n * *abc* → abc \n * _abc_ → abc \n * ~abc~ → abc \n * `abc` → abc \n * \n * Also supports forms and buttons.\n *\n * Nested formatting is supported, e.g. *abc _def_* -> abc def \n * URLs, @mentions, and #hashtags are extracted and converted into links.\n * Forms and buttons can be added procedurally.\n * JSON data representation is inspired by Draft.js raw formatting.\n *\n *\n * @example\n * Text:\n * \n * this is *bold*, `code` and _italic_, ~strike~\n * combined *bold and _italic_*\n * an url: https://www.example.com/abc#fragment and another _www.tinode.co_\n * this is a @mention and a #hashtag in a string\n * second #hashtag\n * \n *\n * Sample JSON representation of the text above:\n * {\n * \"txt\": \"this is bold, code and italic, strike combined bold and italic an url: https://www.example.com/abc#fragment \" +\n * \"and another www.tinode.co this is a @mention and a #hashtag in a string second #hashtag\",\n * \"fmt\": [\n * { \"at\":8, \"len\":4,\"tp\":\"ST\" },{ \"at\":14, \"len\":4, \"tp\":\"CO\" },{ \"at\":23, \"len\":6, \"tp\":\"EM\"},\n * { \"at\":31, \"len\":6, \"tp\":\"DL\" },{ \"tp\":\"BR\", \"len\":1, \"at\":37 },{ \"at\":56, \"len\":6, \"tp\":\"EM\" },\n * { \"at\":47, \"len\":15, \"tp\":\"ST\" },{ \"tp\":\"BR\", \"len\":1, \"at\":62 },{ \"at\":120, \"len\":13, \"tp\":\"EM\" },\n * { \"at\":71, \"len\":36, \"key\":0 },{ \"at\":120, \"len\":13, \"key\":1 },{ \"tp\":\"BR\", \"len\":1, \"at\":133 },\n * { \"at\":144, \"len\":8, \"key\":2 },{ \"at\":159, \"len\":8, \"key\":3 },{ \"tp\":\"BR\", \"len\":1, \"at\":179 },\n * { \"at\":187, \"len\":8, \"key\":3 },{ \"tp\":\"BR\", \"len\":1, \"at\":195 }\n * ],\n * \"ent\": [\n * { \"tp\":\"LN\", \"data\":{ \"url\":\"https://www.example.com/abc#fragment\" } },\n * { \"tp\":\"LN\", \"data\":{ \"url\":\"http://www.tinode.co\" } },\n * { \"tp\":\"MN\", \"data\":{ \"val\":\"mention\" } },\n * { \"tp\":\"HT\", \"data\":{ \"val\":\"hashtag\" } }\n * ]\n * }\n */\n\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\nconst MAX_FORM_ELEMENTS = 8;\nconst MAX_PREVIEW_ATTACHMENTS = 3;\nconst MAX_PREVIEW_DATA_SIZE = 64;\nconst JSON_MIME_TYPE = 'application/json+drafty';\nconst JSON_MIME_TYPE_LEGACY = 'application/json'; // Remove in 2026.\nconst DRAFTY_MIME_TYPE = 'text/x-drafty';\nconst ALLOWED_ENT_FIELDS = ['act', 'height', 'duration', 'incoming', 'mime', 'name', 'premime', 'preref', 'preview',\n 'ref', 'size', 'state', 'url', 'val', 'width'\n];\n\n// Intl.Segmenter is not available in Firefox 124 and earlier. FF 125 with support for Intl.Segmenter\n// was released on April 15, 2024. Polyfill is included in the top package (webapp).\nconst segmenter = new Intl.Segmenter();\n\n// Regular expressions for parsing inline formats. Javascript does not support lookbehind,\n// so it's a bit messy.\nconst INLINE_STYLES = [\n // Strong = bold, *bold text*\n {\n name: 'ST',\n start: /(?:^|[\\W_])(\\*)[^\\s*]/,\n end: /[^\\s*](\\*)(?=$|[\\W_])/\n },\n // Emphesized = italic, _italic text_\n {\n name: 'EM',\n start: /(?:^|\\W)(_)[^\\s_]/,\n end: /[^\\s_](_)(?=$|\\W)/\n },\n // Deleted, ~strike this though~\n {\n name: 'DL',\n start: /(?:^|[\\W_])(~)[^\\s~]/,\n end: /[^\\s~](~)(?=$|[\\W_])/\n },\n // Code block `this is monospace`\n {\n name: 'CO',\n start: /(?:^|\\W)(`)[^`]/,\n end: /[^`](`)(?=$|\\W)/\n }\n];\n\n// Relative weights of formatting spans. Greater index in array means greater weight.\nconst FMT_WEIGHT = ['QQ'];\n\n// RegExps for entity extraction (RF = reference)\nconst ENTITY_TYPES = [\n // URLs\n {\n name: 'LN',\n dataName: 'url',\n pack: function(val) {\n // Check if the protocol is specified, if not use http\n if (!/^[a-z]+:\\/\\//i.test(val)) {\n val = 'http://' + val;\n }\n return {\n url: val\n };\n },\n re: /(?:(?:https?|ftp):\\/\\/|www\\.|ftp\\.)[-A-Z0-9+&@#\\/%=~_|$?!:,.]*[A-Z0-9+&@#\\/%=~_|$]/ig\n },\n // Mentions @user (must be 2 or more characters)\n {\n name: 'MN',\n dataName: 'val',\n pack: function(val) {\n return {\n val: val.slice(1)\n };\n },\n re: /\\B@([\\p{L}\\p{N}][._\\p{L}\\p{N}]*[\\p{L}\\p{N}])/ug\n },\n // Hashtags #hashtag, like metion 2 or more characters.\n {\n name: 'HT',\n dataName: 'val',\n pack: function(val) {\n return {\n val: val.slice(1)\n };\n },\n re: /\\B#([\\p{L}\\p{N}][._\\p{L}\\p{N}]*[\\p{L}\\p{N}])/ug\n }\n];\n\n// HTML tag name suggestions\nconst FORMAT_TAGS = {\n AU: {\n html_tag: 'audio',\n md_tag: undefined,\n isVoid: false\n },\n BN: {\n html_tag: 'button',\n md_tag: undefined,\n isVoid: false\n },\n BR: {\n html_tag: 'br',\n md_tag: '\\n',\n isVoid: true\n },\n CO: {\n html_tag: 'tt',\n md_tag: '`',\n isVoid: false\n },\n DL: {\n html_tag: 'del',\n md_tag: '~',\n isVoid: false\n },\n EM: {\n html_tag: 'i',\n md_tag: '_',\n isVoid: false\n },\n EX: {\n html_tag: '',\n md_tag: undefined,\n isVoid: true\n },\n FM: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false\n },\n HD: {\n html_tag: '',\n md_tag: undefined,\n isVoid: false\n },\n HL: {\n html_tag: 'span',\n md_tag: undefined,\n isVoid: false\n },\n HT: {\n html_tag: 'a',\n md_tag: undefined,\n isVoid: false\n },\n IM: {\n html_tag: 'img',\n md_tag: undefined,\n isVoid: false\n },\n LN: {\n html_tag: 'a',\n md_tag: undefined,\n isVoid: false\n },\n MN: {\n html_tag: 'a',\n md_tag: undefined,\n isVoid: false\n },\n RW: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false,\n },\n QQ: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false\n },\n ST: {\n html_tag: 'b',\n md_tag: '*',\n isVoid: false\n },\n VC: {\n html_tag: 'div',\n md_tag: undefined,\n isVoid: false\n },\n VD: {\n html_tag: 'video',\n md_tag: undefined,\n isVoid: false\n }\n};\n\n// Convert base64-encoded string into Blob.\nfunction base64toObjectUrl(b64, contentType, logger) {\n if (!b64) {\n return null;\n }\n\n try {\n const bin = atob(b64);\n const length = bin.length;\n const buf = new ArrayBuffer(length);\n const arr = new Uint8Array(buf);\n for (let i = 0; i < length; i++) {\n arr[i] = bin.charCodeAt(i);\n }\n\n return URL.createObjectURL(new Blob([buf], {\n type: contentType\n }));\n } catch (err) {\n if (logger) {\n logger(\"Drafty: failed to convert object.\", err.message);\n }\n }\n\n return null;\n}\n\nfunction base64toDataUrl(b64, contentType) {\n if (!b64) {\n return null;\n }\n contentType = contentType || 'image/jpeg';\n return 'data:' + contentType + ';base64,' + b64;\n}\n\n// Helpers for converting Drafty to HTML.\nconst DECORATORS = {\n // Visial styles\n ST: {\n open: _ => '',\n close: _ => ' '\n },\n EM: {\n open: _ => '',\n close: _ => ' '\n },\n DL: {\n open: _ => '',\n close: _ => ''\n },\n CO: {\n open: _ => '',\n close: _ => ' '\n },\n // Line break\n BR: {\n open: _ => ' ',\n close: _ => ''\n },\n // Hidden element\n HD: {\n open: _ => '',\n close: _ => ''\n },\n // Highlighted element.\n HL: {\n open: _ => '',\n close: _ => ' '\n },\n // Link (URL)\n LN: {\n open: (data) => {\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n return data ? {\n href: data.url,\n target: '_blank'\n } : null;\n },\n },\n // Mention\n MN: {\n open: (data) => {\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n return data ? {\n id: data.val\n } : null;\n },\n },\n // Hashtag\n HT: {\n open: (data) => {\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n return data ? {\n id: data.val\n } : null;\n },\n },\n // Button\n BN: {\n open: _ => '',\n close: _ => ' ',\n props: (data) => {\n return data ? {\n 'data-act': data.act,\n 'data-val': data.val,\n 'data-name': data.name,\n 'data-ref': data.ref\n } : null;\n },\n },\n // Audio recording\n AU: {\n open: (data) => {\n const url = data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger);\n return '';\n },\n close: _ => ' ',\n props: (data) => {\n if (!data) return null;\n return {\n // Embedded data or external link.\n src: data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger),\n 'data-preload': data.ref ? 'metadata' : 'auto',\n 'data-duration': data.duration,\n 'data-name': data.name,\n 'data-size': data.val ? ((data.val.length * 0.75) | 0) : (data.size | 0),\n 'data-mime': data.mime,\n };\n }\n },\n // Image\n IM: {\n open: data => {\n // Don't use data.ref for preview: it's a security risk.\n const tmpPreviewUrl = base64toDataUrl(data._tempPreview, data.mime);\n const previewUrl = base64toObjectUrl(data.val, data.mime, Drafty.logger);\n const downloadUrl = data.ref || previewUrl;\n return (data.name ? '' : '') +\n ' ';\n },\n close: data => {\n return (data.name ? ' ' : '');\n },\n props: data => {\n if (!data) return null;\n return {\n // Temporary preview, or permanent preview, or external link.\n src: base64toDataUrl(data._tempPreview, data.mime) ||\n data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger),\n title: data.name,\n alt: data.name,\n 'data-width': data.width,\n 'data-height': data.height,\n 'data-name': data.name,\n 'data-size': data.ref ? (data.size | 0) : (data.val ? ((data.val.length * 0.75) | 0) : (data.size | 0)),\n 'data-mime': data.mime,\n };\n },\n },\n // Form - structured layout of elements.\n FM: {\n open: _ => '',\n close: _ => '
'\n },\n // Row: logic grouping of elements\n RW: {\n open: _ => '',\n close: _ => '
'\n },\n // Quoted block.\n QQ: {\n open: _ => '',\n close: _ => '
',\n props: (data) => {\n return data ? {} : null;\n },\n },\n // Video call\n VC: {\n open: _ => '',\n close: _ => '
',\n props: data => {\n if (!data) return {};\n return {\n 'data-duration': data.duration,\n 'data-state': data.state,\n };\n }\n },\n // Video.\n VD: {\n open: data => {\n const tmpPreviewUrl = base64toDataUrl(data._tempPreview, data.mime);\n const previewUrl = data.ref || base64toObjectUrl(data.preview, data.premime || 'image/jpeg', Drafty.logger);\n return ' ';\n },\n close: _ => '',\n props: data => {\n if (!data) return null;\n const poster = data.preref || base64toObjectUrl(data.preview, data.premime || 'image/jpeg', Drafty.logger);\n return {\n // Embedded data or external link.\n src: poster,\n 'data-src': data.ref || base64toObjectUrl(data.val, data.mime, Drafty.logger),\n 'data-width': data.width,\n 'data-height': data.height,\n 'data-preload': data.ref ? 'metadata' : 'auto',\n 'data-preview': poster,\n 'data-duration': data.duration | 0,\n 'data-name': data.name,\n 'data-size': data.ref ? (data.size | 0) : (data.val ? ((data.val.length * 0.75) | 0) : (data.size | 0)),\n 'data-mime': data.mime,\n };\n }\n },\n};\n\n/**\n * The main object which performs all the formatting actions.\n * @class Drafty\n * @constructor\n */\nconst Drafty = function() {\n this.txt = '';\n this.fmt = [];\n this.ent = [];\n}\n\n/**\n * Initialize Drafty document to a plain text string.\n *\n * @param {string} plainText - string to use as Drafty content.\n *\n * @returns new Drafty document or null is plainText is not a string or undefined.\n */\nDrafty.init = function(plainText) {\n if (typeof plainText == 'undefined') {\n plainText = '';\n } else if (typeof plainText != 'string') {\n return null;\n }\n\n return {\n txt: plainText\n };\n}\n\n/**\n * Parse plain text into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {string} content - plain-text content to parse.\n * @return {Drafty} parsed document or null if the source is not plain text.\n */\nDrafty.parse = function(content) {\n // Make sure we are parsing strings only.\n if (typeof content != 'string') {\n return null;\n }\n\n // Split text into lines. It makes further processing easier.\n const lines = content.split(/\\r?\\n/);\n\n // Holds entities referenced from text\n const entityMap = [];\n const entityIndex = {};\n\n // Processing lines one by one, hold intermediate result in blx.\n const blx = [];\n lines.forEach((line) => {\n let spans = [];\n let entities;\n\n // Find formatted spans in the string.\n // Try to match each style.\n INLINE_STYLES.forEach((tag) => {\n // Each style could be matched multiple times.\n spans = spans.concat(spannify(line, tag.start, tag.end, tag.name));\n });\n\n let block;\n if (spans.length == 0) {\n block = {\n txt: line\n };\n } else {\n // Sort spans by style occurence early -> late, then by length: first long then short.\n spans.sort((a, b) => {\n const diff = a.at - b.at;\n return diff != 0 ? diff : b.end - a.end;\n });\n\n // Convert an array of possibly overlapping spans into a tree.\n spans = toSpanTree(spans);\n\n // Build a tree representation of the entire string, not\n // just the formatted parts.\n const chunks = chunkify(line, 0, line.length, spans);\n\n const drafty = draftify(chunks, 0);\n\n block = {\n txt: drafty.txt,\n fmt: drafty.fmt\n };\n }\n\n // Extract entities from the cleaned up string.\n entities = extractEntities(block.txt);\n if (entities.length > 0) {\n const ranges = [];\n for (let i in entities) {\n // {offset: match['index'], unique: match[0], len: match[0].length, data: ent.packer(), type: ent.name}\n const entity = entities[i];\n let index = entityIndex[entity.unique];\n if (!index) {\n index = entityMap.length;\n entityIndex[entity.unique] = index;\n entityMap.push({\n tp: entity.type,\n data: entity.data\n });\n }\n ranges.push({\n at: entity.offset,\n len: entity.len,\n key: index\n });\n }\n block.ent = ranges;\n }\n\n blx.push(block);\n });\n\n const result = {\n txt: ''\n };\n\n // Merge lines and save line breaks as BR inline formatting.\n if (blx.length > 0) {\n result.txt = blx[0].txt;\n result.fmt = (blx[0].fmt || []).concat(blx[0].ent || []);\n\n if (result.fmt.length) {\n const segments = segmenter.segment(result.txt);\n for (const ele of result.fmt) {\n ({\n at: ele.at,\n len: ele.len\n } =\n toGraphemeValues(ele, segments, result.txt));\n }\n }\n\n for (let i = 1; i < blx.length; i++) {\n const block = blx[i];\n const offset = stringToGraphemes(result.txt).length + 1;\n\n result.fmt.push({\n tp: 'BR',\n len: 1,\n at: offset - 1\n });\n\n let segments = {};\n\n result.txt += ' ' + block.txt;\n if (block.fmt) {\n segments = segmenter.segment(block.txt);\n result.fmt = result.fmt.concat(\n block.fmt.map((s) => {\n const {\n at: correctAt,\n len: correctLen\n } =\n toGraphemeValues(s, segments, block.txt);\n s.at = correctAt + offset;\n s.len = correctLen;\n return s;\n })\n );\n }\n if (block.ent) {\n if (isEmptyObject(segments)) {\n segments = segmenter.segment(block.txt);\n }\n result.fmt = result.fmt.concat(\n block.ent.map((s) => {\n const {\n at: correctAt,\n len: correctLen\n } =\n toGraphemeValues(s, segments, block.txt);\n s.at = correctAt + offset;\n s.len = correctLen;\n return s;\n })\n );\n }\n }\n\n if (result.fmt.length == 0) {\n delete result.fmt;\n }\n\n if (entityMap.length > 0) {\n result.ent = entityMap;\n }\n }\n return result;\n}\n\n/**\n * Append one Drafty document to another.\n *\n * @param {Drafty} first - Drafty document to append to.\n * @param {Drafty|string} second - Drafty document or string being appended.\n *\n * @return {Drafty} first document with the second appended to it.\n */\nDrafty.append = function(first, second) {\n if (!first) {\n return second;\n }\n if (!second) {\n return first;\n }\n\n first.txt = first.txt || '';\n const len = stringToGraphemes(first.txt).length;\n\n if (typeof second == 'string') {\n first.txt += second;\n } else if (second.txt) {\n first.txt += second.txt;\n }\n\n if (Array.isArray(second.fmt)) {\n first.fmt = first.fmt || [];\n if (Array.isArray(second.ent)) {\n first.ent = first.ent || [];\n }\n second.fmt.forEach(src => {\n const fmt = {\n at: (src.at | 0) + len,\n len: src.len | 0\n };\n // Special case for the outside of the normal rendering flow styles.\n if (src.at == -1) {\n fmt.at = -1;\n fmt.len = 0;\n }\n if (src.tp) {\n fmt.tp = src.tp;\n } else {\n fmt.key = first.ent.length;\n first.ent.push(second.ent[src.key || 0]);\n }\n first.fmt.push(fmt);\n });\n }\n\n return first;\n}\n\n/**\n * Description of an image to attach.\n * @typedef {Object} ImageDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the image, e.g. \"image/png\".\n * @property {string} refurl - reference to the content. Could be null/undefined.\n * @property {string} bits - base64-encoded image content. Could be null/undefined.\n * @property {string} preview - base64-encoded thumbnail of the image.\n * @property {integer} width - width of the image.\n * @property {integer} height - height of the image.\n * @property {string} filename - file name suggestion for downloading the image.\n * @property {integer} size - size of the image in bytes. Treat is as an untrusted hint.\n * @property {string} _tempPreview - base64-encoded image preview used during upload process; not serializable.\n * @property {Promise} urlPromise - Promise which returns content URL when resolved.\n */\n\n/**\n * Insert inline image into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add image to.\n * @param {integer} at - index where the object is inserted. The length of the image is always 1.\n * @param {ImageDesc} imageDesc - object with image paramenets and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertImage = function(content, at, imageDesc) {\n content = content || {\n txt: ' '\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: 1,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'IM',\n data: {\n mime: imageDesc.mime,\n ref: imageDesc.refurl,\n val: imageDesc.bits || imageDesc.preview,\n width: imageDesc.width,\n height: imageDesc.height,\n name: imageDesc.filename,\n size: imageDesc.size | 0,\n }\n };\n\n if (imageDesc.urlPromise) {\n ex.data._tempPreview = imageDesc._tempPreview;\n ex.data._processing = true;\n imageDesc.urlPromise.then(\n url => {\n ex.data.ref = url;\n ex.data._tempPreview = undefined;\n ex.data._processing = undefined;\n },\n _ => {\n // Catch the error, otherwise it will appear in the console.\n ex.data._processing = undefined;\n }\n );\n }\n\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Description of a video to attach.\n * @typedef {Object} VideoDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the video, e.g. \"video/mpeg\".\n * @property {string} refurl - reference to the content. Could be null/undefined.\n * @property {string} bits - in-band base64-encoded image data. Could be null/undefined.\n * @property {string} preview - base64-encoded screencapture from the video. Could be null/undefined.\n * @property {string} preref - reference to screencapture from the video. Could be null/undefined.\n * @property {integer} width - width of the video.\n * @property {integer} height - height of the video.\n * @property {integer} duration - duration of the video.\n * @property {string} filename - file name suggestion for downloading the video.\n * @property {integer} size - size of the video in bytes. Treat is as an untrusted hint.\n * @property {string} _tempPreview - base64-encoded screencapture used during upload process; not serializable.\n * @property {Promise} urlPromise - array of two promises, which return URLs of video and preview uploads correspondingly\n * (either could be null).\n */\n\n/**\n * Insert inline image into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add video to.\n * @param {integer} at - index where the object is inserted. The length of the video is always 1.\n * @param {VideoDesc} videoDesc - object with video paramenets and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertVideo = function(content, at, videoDesc) {\n content = content || {\n txt: ' '\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: 1,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'VD',\n data: {\n mime: videoDesc.mime,\n ref: videoDesc.refurl,\n val: videoDesc.bits,\n preref: videoDesc.preref,\n preview: videoDesc.preview,\n width: videoDesc.width,\n height: videoDesc.height,\n duration: videoDesc.duration | 0,\n name: videoDesc.filename,\n size: videoDesc.size | 0,\n }\n };\n\n if (videoDesc.urlPromise) {\n ex.data._tempPreview = videoDesc._tempPreview;\n ex.data._processing = true;\n videoDesc.urlPromise.then(\n urls => {\n ex.data.ref = urls[0];\n ex.data.preref = urls[1];\n ex.data._tempPreview = undefined;\n ex.data._processing = undefined;\n },\n _ => {\n // Catch the error, otherwise it will appear in the console.\n ex.data._processing = undefined;\n }\n );\n }\n\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Description of an audio recording to attach.\n * @typedef {Object} AudioDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the audio, e.g. \"audio/ogg\".\n * @property {string} refurl - reference to the content. Could be null/undefined.\n * @property {string} bits - base64-encoded audio content. Could be null/undefined.\n * @property {integer} duration - duration of the record in milliseconds.\n * @property {string} preview - base64 encoded short array of amplitude values 0..100.\n * @property {string} filename - file name suggestion for downloading the audio.\n * @property {integer} size - size of the recording in bytes. Treat is as an untrusted hint.\n * @property {Promise} urlPromise - Promise which returns content URL when resolved.\n */\n\n/**\n * Insert audio recording into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add audio record to.\n * @param {integer} at - index where the object is inserted. The length of the record is always 1.\n * @param {AudioDesc} audioDesc - object with the audio paramenets and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertAudio = function(content, at, audioDesc) {\n content = content || {\n txt: ' '\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: 1,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'AU',\n data: {\n mime: audioDesc.mime,\n val: audioDesc.bits,\n duration: audioDesc.duration | 0,\n preview: audioDesc.preview,\n name: audioDesc.filename,\n size: audioDesc.size | 0,\n ref: audioDesc.refurl\n }\n };\n\n if (audioDesc.urlPromise) {\n ex.data._processing = true;\n audioDesc.urlPromise.then(\n url => {\n ex.data.ref = url;\n ex.data._processing = undefined;\n },\n _ => {\n // Catch the error, otherwise it will appear in the console.\n ex.data._processing = undefined;\n }\n );\n }\n\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Create a (self-contained) video call Drafty document.\n * @memberof Drafty\n * @static\n * @param {boolean} audioOnly true if the call is initially audio-only.\n * @returns Video Call drafty document.\n */\nDrafty.videoCall = function(audioOnly) {\n const content = {\n txt: ' ',\n fmt: [{\n at: 0,\n len: 1,\n key: 0\n }],\n ent: [{\n tp: 'VC',\n data: {\n aonly: audioOnly\n },\n }]\n };\n return content;\n}\n\n/**\n * Update video call (VC) entity with the new status and duration.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - VC document to update.\n * @param {object} params - new video call parameters.\n * @param {string} params.state - state of video call.\n * @param {number} params.duration - duration of the video call in milliseconds.\n *\n * @returns the same document with update applied.\n */\nDrafty.updateVideoCall = function(content, params) {\n // The video element could be just a format or a format + entity.\n // Must ensure it's the latter first.\n const fmt = ((content || {}).fmt || [])[0];\n if (!fmt) {\n // Unrecognized content.\n return content;\n }\n\n let ent;\n if (fmt.tp == 'VC') {\n // Just a format, convert to format + entity.\n delete fmt.tp;\n fmt.key = 0;\n ent = {\n tp: 'VC'\n };\n content.ent = [ent];\n } else {\n ent = (content.ent || [])[fmt.key | 0];\n if (!ent || ent.tp != 'VC') {\n // Not a VC entity.\n return content;\n }\n }\n ent.data = ent.data || {};\n Object.assign(ent.data, params);\n return content;\n}\n\n/**\n * Create a quote to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {string} header - Quote header (title, etc.).\n * @param {string} uid - UID of the author to mention.\n * @param {Drafty} body - Body of the quoted message.\n *\n * @returns Reply quote Drafty doc with the quote formatting.\n */\nDrafty.quote = function(header, uid, body) {\n const quote = Drafty.append(Drafty.appendLineBreak(Drafty.mention(header, uid)), body);\n\n // Wrap into a quote.\n quote.fmt.push({\n at: 0,\n len: stringToGraphemes(quote.txt).length,\n tp: 'QQ'\n });\n\n return quote;\n}\n\n/**\n * Create a Drafty document with a mention.\n *\n * @param {string} name - mentioned name.\n * @param {string} uid - mentioned user ID.\n *\n * @returns {Drafty} document with the mention.\n */\nDrafty.mention = function(name, uid) {\n return {\n txt: name || '',\n fmt: [{\n at: 0,\n len: stringToGraphemes(name || '').length,\n key: 0\n }],\n ent: [{\n tp: 'MN',\n data: {\n val: uid\n }\n }]\n };\n}\n\n/**\n * Append a link to a Drafty document.\n *\n * @param {Drafty} content - Drafty document to append link to.\n * @param {Object} linkData - Link info in format {txt: 'ankor text', url: 'http://...'}.\n *\n * @returns {Drafty} the same document as content.\n */\nDrafty.appendLink = function(content, linkData) {\n content = content || {\n txt: ''\n };\n\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: content.txt.length,\n len: linkData.txt.length,\n key: content.ent.length\n });\n content.txt += linkData.txt;\n\n const ex = {\n tp: 'LN',\n data: {\n url: linkData.url\n }\n }\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Append image to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add image to.\n * @param {ImageDesc} imageDesc - object with image paramenets.\n *\n * @return {Drafty} updated document.\n */\nDrafty.appendImage = function(content, imageDesc) {\n content = content || {\n txt: ''\n };\n content.txt += ' ';\n return Drafty.insertImage(content, content.txt.length - 1, imageDesc);\n}\n\n/**\n * Append audio recodring to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to add recording to.\n * @param {AudioDesc} audioDesc - object with audio data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.appendAudio = function(content, audioDesc) {\n content = content || {\n txt: ''\n };\n content.txt += ' ';\n return Drafty.insertAudio(content, content.txt.length - 1, audioDesc);\n}\n\n/**\n * Description of a file to attach.\n * @typedef {Object} AttachmentDesc\n * @memberof Drafty\n *\n * @property {string} mime - mime-type of the attachment, e.g. \"application/octet-stream\"\n * @property {string} data - base64-encoded in-band content of small attachments. Could be null/undefined.\n * @property {string} filename - file name suggestion for downloading the attachment.\n * @property {integer} size - size of the file in bytes. Treat is as an untrusted hint.\n * @property {string} refurl - reference to the out-of-band content. Could be null/undefined.\n * @property {Promise} urlPromise - Promise which returns content URL when resolved.\n */\n\n/**\n * Attach file to Drafty content. Either as a blob or as a reference.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to attach file to.\n * @param {AttachmentDesc} object - containing attachment description and data.\n *\n * @return {Drafty} updated document.\n */\nDrafty.attachFile = function(content, attachmentDesc) {\n content = content || {\n txt: ''\n };\n\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: -1,\n len: 0,\n key: content.ent.length\n });\n\n const ex = {\n tp: 'EX',\n data: {\n mime: attachmentDesc.mime,\n val: attachmentDesc.data,\n name: attachmentDesc.filename,\n ref: attachmentDesc.refurl,\n size: attachmentDesc.size | 0\n }\n }\n if (attachmentDesc.urlPromise) {\n ex.data._processing = true;\n attachmentDesc.urlPromise.then(\n url => {\n ex.data.ref = url;\n ex.data._processing = undefined;\n },\n _ => {\n /* catch the error, otherwise it will appear in the console. */\n ex.data._processing = undefined;\n }\n );\n }\n content.ent.push(ex);\n\n return content;\n}\n\n/**\n * Wraps drafty document into a simple formatting style.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - document or string to wrap into a style.\n * @param {string} style - two-letter style to wrap into.\n * @param {number} at - index where the style starts, default 0.\n * @param {number} len - length of the form content, default all of it.\n *\n * @return {Drafty} updated document.\n */\nDrafty.wrapInto = function(content, style, at, len) {\n if (typeof content == 'string') {\n content = {\n txt: content\n };\n }\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at || 0,\n len: len || content.txt.length,\n tp: style,\n });\n\n return content;\n}\n\n/**\n * Wraps content into an interactive form.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - to wrap into a form.\n * @param {number} at - index where the forms starts.\n * @param {number} len - length of the form content.\n *\n * @return {Drafty} updated document.\n */\nDrafty.wrapAsForm = function(content, at, len) {\n return Drafty.wrapInto(content, 'FM', at, len);\n}\n\n/**\n * Insert clickable button into Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - Drafty document to insert button to or a string to be used as button text.\n * @param {number} at - location where the button is inserted.\n * @param {number} len - the length of the text to be used as button title.\n * @param {string} name - the button. Client should return it to the server when the button is clicked.\n * @param {string} actionType - the type of the button, one of 'url' or 'pub'.\n * @param {string} actionValue - the value to return on click:\n * @param {string} refUrl - the URL to go to when the 'url' button is clicked.\n *\n * @return {Drafty} updated document.\n */\nDrafty.insertButton = function(content, at, len, name, actionType, actionValue, refUrl) {\n if (typeof content == 'string') {\n content = {\n txt: content\n };\n }\n\n if (!content || !content.txt || content.txt.length < at + len) {\n return null;\n }\n\n if (len <= 0 || ['url', 'pub'].indexOf(actionType) == -1) {\n return null;\n }\n // Ensure refUrl is a string.\n if (actionType == 'url' && !refUrl) {\n return null;\n }\n refUrl = '' + refUrl;\n\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: at | 0,\n len: len,\n key: content.ent.length\n });\n content.ent.push({\n tp: 'BN',\n data: {\n act: actionType,\n val: actionValue,\n ref: refUrl,\n name: name\n }\n });\n\n return content;\n}\n\n/**\n * Append clickable button to Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} content - Drafty document to insert button to or a string to be used as button text.\n * @param {string} title - the text to be used as button title.\n * @param {string} name - the button. Client should return it to the server when the button is clicked.\n * @param {string} actionType - the type of the button, one of 'url' or 'pub'.\n * @param {string} actionValue - the value to return on click:\n * @param {string} refUrl - the URL to go to when the 'url' button is clicked.\n *\n * @return {Drafty} updated document.\n */\nDrafty.appendButton = function(content, title, name, actionType, actionValue, refUrl) {\n content = content || {\n txt: ''\n };\n const at = content.txt.length;\n content.txt += title;\n return Drafty.insertButton(content, at, title.length, name, actionType, actionValue, refUrl);\n}\n\n/**\n * Attach a generic JS object. The object is attached as a json string.\n * Intended for representing a form response.\n *\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - Drafty document to attach file to.\n * @param {Object} data - data to convert to json string and attach.\n * @returns {Drafty} the same document as content.\n */\nDrafty.attachJSON = function(content, data) {\n content = content || {\n txt: ''\n };\n content.ent = content.ent || [];\n content.fmt = content.fmt || [];\n\n content.fmt.push({\n at: -1,\n len: 0,\n key: content.ent.length\n });\n\n content.ent.push({\n tp: 'EX',\n data: {\n mime: JSON_MIME_TYPE,\n val: data\n }\n });\n\n return content;\n}\n/**\n * Append line break to a Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - Drafty document to append linebreak to.\n * @returns {Drafty} the same document as content.\n */\nDrafty.appendLineBreak = function(content) {\n content = content || {\n txt: ''\n };\n content.fmt = content.fmt || [];\n content.fmt.push({\n at: stringToGraphemes(content.txt).length,\n len: 1,\n tp: 'BR'\n });\n content.txt += ' ';\n\n return content;\n}\n/**\n * Given Drafty document, convert it to HTML.\n * No attempt is made to strip pre-existing html markup.\n * This is potentially unsafe because content.txt may contain malicious HTML\n * markup.\n * @memberof Tinode.Drafty\n * @static\n *\n * @param {Drafty} doc - document to convert.\n *\n * @returns {string} HTML-representation of content.\n */\nDrafty.UNSAFE_toHTML = function(doc) {\n const tree = draftyToTree(doc);\n const htmlFormatter = function(type, data, values) {\n const tag = DECORATORS[type];\n let result = values ? values.join('') : '';\n if (tag) {\n result = tag.open(data) + result + tag.close(data);\n }\n return result;\n };\n return treeBottomUp(tree, htmlFormatter, 0);\n}\n\n/**\n * Callback for applying custom formatting to a Drafty document.\n * Called once for each style span.\n * @memberof Drafty\n * @static\n *\n * @callback Formatter\n * @param {string} style - style code such as \"ST\" or \"IM\".\n * @param {Object} data - entity's data.\n * @param {Object} values - possibly styled subspans contained in this style span.\n * @param {number} index - index of the element guaranteed to be unique.\n */\n\n/**\n * Convert Drafty document to a representation suitable for display.\n * The context may expose a function getFormatter(style). If it's available\n * it will call it to obtain a formatter for a subtree of styles under the style.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|Object} content - Drafty document to transform.\n * @param {Formatter} formatter - callback which formats individual elements.\n * @param {Object} context - context provided to formatter as this.\n *\n * @return {Object} transformed object\n */\nDrafty.format = function(original, formatter, context) {\n return treeBottomUp(draftyToTree(original), formatter, 0, [], context);\n}\n\n/**\n * Shorten Drafty document making the drafty text no longer than the limit.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @param {number} limit - length in characrets to shorten to.\n * @param {boolean} light - remove heavy data from entities.\n * @returns new shortened Drafty object leaving the original intact.\n */\nDrafty.shorten = function(original, limit, light) {\n let tree = draftyToTree(original);\n tree = shortenTree(tree, limit, '…');\n if (tree && light) {\n tree = lightEntity(tree);\n }\n return treeToDrafty({}, tree, []);\n}\n\n/**\n * Transform Drafty doc for forwarding: strip leading @mention and any leading line breaks or whitespace.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @returns converted Drafty object leaving the original intact.\n */\nDrafty.forwardedContent = function(original) {\n let tree = draftyToTree(original);\n const rmMention = function(node) {\n if (node.type == 'MN') {\n if (!node.parent || !node.parent.type) {\n return null;\n }\n }\n return node;\n }\n // Strip leading mention.\n tree = treeTopDown(tree, rmMention);\n // Remove leading whitespace.\n tree = lTrim(tree);\n // Convert back to Drafty.\n return treeToDrafty({}, tree, []);\n}\n\n/**\n * Prepare Drafty doc for wrapping into QQ as a reply:\n * - Replace forwarding mention with symbol '➦' and remove data (UID).\n * - Remove quoted text completely.\n * - Replace line breaks with spaces.\n * - Strip entities of heavy content.\n * - Move attachments to the end of the document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @param {number} limit - length in characters to shorten to.\n * @returns converted Drafty object leaving the original intact.\n */\nDrafty.replyContent = function(original, limit) {\n const convMNnQQnBR = function(node) {\n if (node.type == 'QQ') {\n return null;\n } else if (node.type == 'MN') {\n if ((!node.parent || !node.parent.type) && (node.text || '').startsWith('➦')) {\n node.text = '➦';\n delete node.children;\n delete node.data;\n }\n } else if (node.type == 'BR') {\n node.text = ' ';\n delete node.type;\n delete node.children;\n }\n return node;\n }\n\n let tree = draftyToTree(original);\n if (!tree) {\n return original;\n }\n\n // Strip leading mention.\n tree = treeTopDown(tree, convMNnQQnBR);\n // Move attachments to the end of the doc.\n tree = attachmentsToEnd(tree, MAX_PREVIEW_ATTACHMENTS);\n // Shorten the doc.\n tree = shortenTree(tree, limit, '…');\n // Strip heavy elements except IM.data['val'] and VD.data['preview'] (have to keep them to generate previews later).\n const filter = node => {\n switch (node.type) {\n case 'IM':\n return ['val'];\n case 'VD':\n return ['preview'];\n }\n return null;\n };\n tree = lightEntity(tree, filter);\n // Convert back to Drafty.\n return treeToDrafty({}, tree, []);\n}\n\n\n/**\n * Generate drafty preview:\n * - Shorten the document.\n * - Strip all heavy entity data leaving just inline styles and entity references.\n * - Replace line breaks with spaces.\n * - Replace content of QQ with a space.\n * - Replace forwarding mention with symbol '➦'.\n * move all attachments to the end of the document and make them visible.\n * The context may expose a function getFormatter(style). If it's available\n * it will call it to obtain a formatter for a subtree of styles under the style.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty|string} original - Drafty object to shorten.\n * @param {number} limit - length in characters to shorten to.\n * @param {boolean} forwarding - this a forwarding message preview.\n * @returns new shortened Drafty object leaving the original intact.\n */\nDrafty.preview = function(original, limit, forwarding) {\n let tree = draftyToTree(original);\n\n // Move attachments to the end.\n tree = attachmentsToEnd(tree, MAX_PREVIEW_ATTACHMENTS);\n\n // Convert leading mention to '➦' and replace QQ and BR with a space ' '.\n const convMNnQQnBR = function(node) {\n if (node.type == 'MN') {\n if ((!node.parent || !node.parent.type) && (node.text || '').startsWith('➦')) {\n node.text = '➦';\n delete node.children;\n }\n } else if (node.type == 'QQ') {\n node.text = ' ';\n delete node.children;\n } else if (node.type == 'BR') {\n node.text = ' ';\n delete node.children;\n delete node.type;\n }\n return node;\n }\n tree = treeTopDown(tree, convMNnQQnBR);\n\n tree = shortenTree(tree, limit, '…');\n if (forwarding) {\n // Keep some IM and VD data for preview.\n const filter = {\n IM: ['val'],\n VD: ['preview']\n };\n tree = lightEntity(tree, node => {\n return filter[node.type];\n });\n } else {\n tree = lightEntity(tree);\n }\n\n // Convert back to Drafty.\n return treeToDrafty({}, tree, []);\n}\n\n/**\n * Given Drafty document, convert it to plain text.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to convert to plain text.\n * @returns {string} plain-text representation of the drafty document.\n */\nDrafty.toPlainText = function(content) {\n return typeof content == 'string' ? content : content.txt;\n}\n\n/**\n * Check if the document has no markup and no entities.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - content to check for presence of markup.\n * @returns true is content is plain text, false otherwise.\n */\nDrafty.isPlainText = function(content) {\n return typeof content == 'string' || !(content.fmt || content.ent);\n}\n\n/**\n * Convert document to plain text with markdown. All elements which cannot\n * be represented in markdown are stripped.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to convert to plain text with markdown.\n */\nDrafty.toMarkdown = function(content) {\n let tree = draftyToTree(content);\n const mdFormatter = function(type, _, values) {\n const def = FORMAT_TAGS[type];\n let result = (values ? values.join('') : '');\n if (def) {\n if (def.isVoid) {\n result = def.md_tag || '';\n } else if (def.md_tag) {\n result = def.md_tag + result + def.md_tag;\n }\n }\n return result;\n };\n return treeBottomUp(tree, mdFormatter, 0);\n}\n\n/**\n * Checks if the object represets is a valid Drafty document.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - content to check for validity.\n * @returns true is content is valid, false otherwise.\n */\nDrafty.isValid = function(content) {\n if (!content) {\n return false;\n }\n\n const {\n txt,\n fmt,\n ent\n } = content;\n\n if (!txt && txt !== '' && !fmt && !ent) {\n return false;\n }\n\n const txt_type = typeof txt;\n if (txt_type != 'string' && txt_type != 'undefined' && txt !== null) {\n return false;\n }\n\n if (typeof fmt != 'undefined' && !Array.isArray(fmt) && fmt !== null) {\n return false;\n }\n\n if (typeof ent != 'undefined' && !Array.isArray(ent) && ent !== null) {\n return false;\n }\n return true;\n}\n\n/**\n * Check if the drafty document has attachments: style EX and outside of normal rendering flow,\n * i.e. at = -1.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to check for attachments.\n * @returns true if there are attachments.\n */\nDrafty.hasAttachments = function(content) {\n if (!Array.isArray(content.fmt)) {\n return false;\n }\n for (let i in content.fmt) {\n const fmt = content.fmt[i];\n if (fmt && fmt.at < 0) {\n const ent = content.ent[fmt.key | 0];\n return ent && ent.tp == 'EX' && ent.data;\n }\n }\n return false;\n}\n\n/**\n * Callback for enumerating entities in a Drafty document.\n * Called once for each entity.\n * @memberof Drafty\n * @static\n *\n * @callback EntityCallback\n * @param {Object} data entity data.\n * @param {string} entity type.\n * @param {number} index entity's index in `content.ent`.\n *\n * @return 'true-ish' to stop processing, 'false-ish' otherwise.\n */\n\n/**\n * Enumerate attachments: style EX and outside of normal rendering flow, i.e. at = -1.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to process for attachments.\n * @param {EntityCallback} callback - callback to call for each attachment.\n * @param {Object} context - value of \"this\" for callback.\n */\nDrafty.attachments = function(content, callback, context) {\n if (!Array.isArray(content.fmt)) {\n return;\n }\n let count = 0;\n for (let i in content.fmt) {\n let fmt = content.fmt[i];\n if (fmt && fmt.at < 0) {\n const ent = content.ent[fmt.key | 0];\n if (ent && ent.tp == 'EX' && ent.data) {\n if (callback.call(context, ent.data, count++, 'EX')) {\n break;\n }\n }\n }\n };\n}\n\n/**\n * Check if the drafty document has entities.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document to check for entities.\n * @returns true if there are entities.\n */\nDrafty.hasEntities = function(content) {\n return content.ent && content.ent.length > 0;\n}\n\n/**\n * Enumerate entities. Enumeration stops if callback returns 'true'.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document with entities to enumerate.\n * @param {EntityCallback} callback - callback to call for each entity.\n * @param {Object} context - value of \"this\" for callback.\n *\n */\nDrafty.entities = function(content, callback, context) {\n if (content.ent && content.ent.length > 0) {\n for (let i in content.ent) {\n if (content.ent[i]) {\n if (callback.call(context, content.ent[i].data, i, content.ent[i].tp)) {\n break;\n }\n }\n }\n }\n}\n\n/**\n * Callback for enumerating styles (inline formats) in a Drafty document.\n * Called once for each style.\n * @memberof Drafty\n * @static\n *\n * @callback StyleCallback\n * @param {string} tp - format type.\n * @param {number} at - starting position of the format in text.\n * @param {number} len - extent of the format in characters.\n * @param {number} key - index of the entity if format is a reference.\n * @param {number} index - style's index in `content.fmt`.\n *\n * @return 'true-ish' to stop processing, 'false-ish' otherwise.\n */\n\n/**\n * Enumerate styles (inline formats). Enumeration stops if callback returns 'true'.\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document with styles (formats) to enumerate.\n * @param {StyleCallback} callback - callback to call for each format.\n * @param {Object} context - value of \"this\" for callback.\n */\nDrafty.styles = function(content, callback, context) {\n if (content.fmt && content.fmt.length > 0) {\n for (let i in content.fmt) {\n const fmt = content.fmt[i];\n if (fmt) {\n if (callback.call(context, fmt.tp, fmt.at, fmt.len, fmt.key, i)) {\n break;\n }\n }\n }\n }\n}\n\n/**\n * Remove unrecognized fields from entity data\n * @memberof Drafty\n * @static\n *\n * @param {Drafty} content - document with entities to enumerate.\n * @returns content.\n */\nDrafty.sanitizeEntities = function(content) {\n if (content && content.ent && content.ent.length > 0) {\n for (let i in content.ent) {\n const ent = content.ent[i];\n if (ent && ent.data) {\n const data = copyEntData(ent.data);\n if (data) {\n content.ent[i].data = data;\n } else {\n delete content.ent[i].data;\n }\n }\n }\n }\n return content;\n}\n\n/**\n * Given the entity, get URL which can be used for downloading\n * entity data.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entData - entity.data to get the URl from.\n * @returns {string} URL to download entity data or null.\n */\nDrafty.getDownloadUrl = function(entData) {\n let url = null;\n if (entData.mime != JSON_MIME_TYPE && entData.mime != JSON_MIME_TYPE_LEGACY && entData.val) {\n url = base64toObjectUrl(entData.val, entData.mime, Drafty.logger);\n } else if (typeof entData.ref == 'string') {\n url = entData.ref;\n }\n return url;\n}\n\n/**\n * Check if the entity data is not ready for sending, such as being uploaded to the server.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entity.data to get the URl from.\n * @returns {boolean} true if upload is in progress, false otherwise.\n */\nDrafty.isProcessing = function(entData) {\n return !!entData._processing;\n}\n\n/**\n * Given the entity, get URL which can be used for previewing\n * the entity.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entity.data to get the URl from.\n *\n * @returns {string} url for previewing or null if no such url is available.\n */\nDrafty.getPreviewUrl = function(entData) {\n return entData.val ? base64toObjectUrl(entData.val, entData.mime, Drafty.logger) : null;\n}\n\n/**\n * Get approximate size of the entity.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entData - entity.data to get the size for.\n * @returns {number} size of entity data in bytes.\n */\nDrafty.getEntitySize = function(entData) {\n // Either size hint or length of value. The value is base64 encoded,\n // the actual object size is smaller than the encoded length.\n return entData.size ? entData.size : entData.val ? (entData.val.length * 0.75) | 0 : 0;\n}\n\n/**\n * Get entity mime type.\n * @memberof Drafty\n * @static\n *\n * @param {Object} entData - entity.data to get the type for.\n * @returns {string} mime type of entity.\n */\nDrafty.getEntityMimeType = function(entData) {\n return entData.mime || 'text/plain';\n}\n\n/**\n * Get HTML tag for a given two-letter style name.\n * @memberof Drafty\n * @static\n *\n * @param {string} style - two-letter style, like ST or LN.\n *\n * @returns {string} HTML tag name if style is found, {code: undefined} if style is falsish or not found.\n */\nDrafty.tagName = function(style) {\n return FORMAT_TAGS[style] && FORMAT_TAGS[style].html_tag;\n}\n\n/**\n * For a given data bundle generate an object with HTML attributes,\n * for instance, given {url: \"http://www.example.com/\"} return\n * {href: \"http://www.example.com/\"}\n * @memberof Drafty\n * @static\n *\n * @param {string} style - two-letter style to generate attributes for.\n * @param {Object} data - data bundle to convert to attributes\n *\n * @returns {Object} object with HTML attributes.\n */\nDrafty.attrValue = function(style, data) {\n if (data && DECORATORS[style] && DECORATORS[style].props) {\n return DECORATORS[style].props(data);\n }\n\n return undefined;\n}\n\n/**\n * Drafty MIME type.\n * @memberof Drafty\n * @static\n *\n * @returns {string} content-Type \"text/x-drafty\".\n */\nDrafty.getContentType = function() {\n return DRAFTY_MIME_TYPE;\n}\n\n// =================\n// Utility methods.\n// =================\n\n// Take a string and defined earlier style spans, re-compose them into a tree where each leaf is\n// a same-style (including unstyled) string. I.e. 'hello *bold _italic_* and ~more~ world' ->\n// ('hello ', (b: 'bold ', (i: 'italic')), ' and ', (s: 'more'), ' world');\n//\n// This is needed in order to clear markup, i.e. 'hello *world*' -> 'hello world' and convert\n// ranges from markup-ed offsets to plain text offsets.\nfunction chunkify(line, start, end, spans) {\n const chunks = [];\n\n if (spans.length == 0) {\n return [];\n }\n\n for (let i in spans) {\n // Get the next chunk from the queue\n const span = spans[i];\n\n // Grab the initial unstyled chunk\n if (span.at > start) {\n chunks.push({\n txt: line.slice(start, span.at)\n });\n }\n\n // Grab the styled chunk. It may include subchunks.\n const chunk = {\n tp: span.tp\n };\n const chld = chunkify(line, span.at + 1, span.end, span.children);\n if (chld.length > 0) {\n chunk.children = chld;\n } else {\n chunk.txt = span.txt;\n }\n chunks.push(chunk);\n start = span.end + 1; // '+1' is to skip the formatting character\n }\n\n // Grab the remaining unstyled chunk, after the last span\n if (start < end) {\n chunks.push({\n txt: line.slice(start, end)\n });\n }\n\n return chunks;\n}\n\n// Detect starts and ends of formatting spans. Unformatted spans are\n// ignored at this stage.\nfunction spannify(original, re_start, re_end, type) {\n const result = [];\n let index = 0;\n let line = original.slice(0); // make a copy;\n\n while (line.length > 0) {\n // match[0]; // match, like '*abc*'\n // match[1]; // match captured in parenthesis, like 'abc'\n // match['index']; // offset where the match started.\n\n // Find the opening token.\n const start = re_start.exec(line);\n if (start == null) {\n break;\n }\n\n // Because javascript RegExp does not support lookbehind, the actual offset may not point\n // at the markup character. Find it in the matched string.\n let start_offset = start['index'] + start[0].lastIndexOf(start[1]);\n // Clip the processed part of the string.\n line = line.slice(start_offset + 1);\n // start_offset is an offset within the clipped string. Convert to original index.\n start_offset += index;\n // Index now point to the beginning of 'line' within the 'original' string.\n index = start_offset + 1;\n\n // Find the matching closing token.\n const end = re_end ? re_end.exec(line) : null;\n if (end == null) {\n break;\n }\n let end_offset = end['index'] + end[0].indexOf(end[1]);\n // Clip the processed part of the string.\n line = line.slice(end_offset + 1);\n // Update offsets\n end_offset += index;\n // Index now points to the beginning of 'line' within the 'original' string.\n index = end_offset + 1;\n\n result.push({\n txt: original.slice(start_offset + 1, end_offset),\n children: [],\n at: start_offset,\n end: end_offset,\n tp: type\n });\n }\n\n return result;\n}\n\n// Convert linear array or spans into a tree representation.\n// Keep standalone and nested spans, throw away partially overlapping spans.\nfunction toSpanTree(spans) {\n if (spans.length == 0) {\n return [];\n }\n\n const tree = [spans[0]];\n let last = spans[0];\n for (let i = 1; i < spans.length; i++) {\n // Keep spans which start after the end of the previous span or those which\n // are complete within the previous span.\n if (spans[i].at > last.end) {\n // Span is completely outside of the previous span.\n tree.push(spans[i]);\n last = spans[i];\n } else if (spans[i].end <= last.end) {\n // Span is fully inside of the previous span. Push to subnode.\n last.children.push(spans[i]);\n }\n // Span could partially overlap, ignoring it as invalid.\n }\n\n // Recursively rearrange the subnodes.\n for (let i in tree) {\n tree[i].children = toSpanTree(tree[i].children);\n }\n\n return tree;\n}\n\n// Convert drafty document to a tree.\nfunction draftyToTree(doc) {\n if (!doc) {\n return null;\n }\n\n doc = (typeof doc == 'string') ? {\n txt: doc\n } : doc;\n let {\n txt,\n fmt,\n ent\n } = doc;\n\n txt = txt || '';\n if (!Array.isArray(ent)) {\n ent = [];\n }\n\n if (!Array.isArray(fmt) || fmt.length == 0) {\n if (ent.length == 0) {\n return {\n text: txt\n };\n }\n\n // Handle special case when all values in fmt are 0 and fmt therefore is skipped.\n fmt = [{\n at: 0,\n len: 0,\n key: 0\n }];\n }\n\n // Sanitize spans.\n const spans = [];\n const attachments = [];\n fmt.forEach((span) => {\n if (!span || typeof span != 'object') {\n return;\n }\n\n if (!['undefined', 'number'].includes(typeof span.at)) {\n // Present, but non-numeric 'at'.\n return;\n }\n if (!['undefined', 'number'].includes(typeof span.len)) {\n // Present, but non-numeric 'len'.\n return;\n }\n let at = span.at | 0;\n let len = span.len | 0;\n if (len < 0) {\n // Invalid span length.\n return;\n }\n\n let key = span.key || 0;\n if (ent.length > 0 && (typeof key != 'number' || key < 0 || key >= ent.length)) {\n // Invalid key value.\n return;\n }\n\n if (at <= -1) {\n // Attachment. Store attachments separately.\n attachments.push({\n start: -1,\n end: 0,\n key: key\n });\n return;\n } else if (at + len > stringToGraphemes(txt).length) {\n // Span is out of bounds.\n return;\n }\n\n if (!span.tp) {\n if (ent.length > 0 && (typeof ent[key] == 'object')) {\n spans.push({\n start: at,\n end: at + len,\n key: key\n });\n }\n } else {\n spans.push({\n type: span.tp,\n start: at,\n end: at + len\n });\n }\n });\n\n // Sort spans first by start index (asc) then by length (desc), then by weight.\n spans.sort((a, b) => {\n let diff = a.start - b.start;\n if (diff != 0) {\n return diff;\n }\n diff = b.end - a.end;\n if (diff != 0) {\n return diff;\n }\n return FMT_WEIGHT.indexOf(b.type) - FMT_WEIGHT.indexOf(a.type);\n });\n\n // Move attachments to the end of the list.\n if (attachments.length > 0) {\n spans.push(...attachments);\n }\n\n spans.forEach((span) => {\n if (ent.length > 0 && !span.type && ent[span.key] && typeof ent[span.key] == 'object') {\n span.type = ent[span.key].tp;\n span.data = ent[span.key].data;\n }\n\n // Is type still undefined? Hide the invalid element!\n if (!span.type) {\n span.type = 'HD';\n }\n });\n\n const graphemes = stringToGraphemes(txt);\n let tree = spansToTree({}, graphemes, 0, graphemes.length, spans);\n\n // Flatten tree nodes.\n const flatten = function(node) {\n if (Array.isArray(node.children) && node.children.length == 1) {\n // Unwrap.\n const child = node.children[0];\n if (!node.type) {\n const parent = node.parent;\n node = child;\n node.parent = parent;\n } else if (!child.type && !child.children) {\n node.text = child.text;\n delete node.children;\n }\n }\n return node;\n }\n tree = treeTopDown(tree, flatten);\n\n return tree;\n}\n\n// Add tree node to a parent tree.\nfunction addNode(parent, n) {\n if (!n) {\n return parent;\n }\n\n if (!parent.children) {\n parent.children = [];\n }\n\n // If text is present, move it to a subnode.\n if (parent.text) {\n parent.children.push({\n text: parent.text,\n parent: parent\n });\n delete parent.text;\n }\n\n n.parent = parent;\n parent.children.push(n);\n\n return parent;\n}\n\n// Returns a tree of nodes.\nfunction spansToTree(parent, graphemes, start, end, spans) {\n if (!spans || spans.length == 0) {\n if (start < end) {\n addNode(parent, {\n text: graphemes.slice(start, end)\n .map(segment => segment.segment)\n .join('')\n });\n }\n return parent;\n }\n\n // Process subspans.\n for (let i = 0; i < spans.length; i++) {\n const span = spans[i];\n if (span.start < 0 && span.type == 'EX') {\n addNode(parent, {\n type: span.type,\n data: span.data,\n key: span.key,\n att: true\n });\n continue;\n }\n\n // Add un-styled range before the styled span starts.\n if (start < span.start) {\n addNode(parent, {\n text: graphemes.slice(start, span.start)\n .map(segment => segment.segment)\n .join('')\n });\n start = span.start;\n }\n\n // Get all spans which are within the current span.\n const subspans = [];\n while (i < spans.length - 1) {\n const inner = spans[i + 1];\n if (inner.start < 0) {\n // Attachments are in the end. Stop.\n break;\n } else if (inner.start < span.end) {\n if (inner.end <= span.end) {\n const tag = FORMAT_TAGS[inner.tp] || {};\n if (inner.start < inner.end || tag.isVoid) {\n // Valid subspan: completely within the current span and\n // either non-zero length or zero length is acceptable.\n subspans.push(inner);\n }\n }\n i++;\n // Overlapping subspans are ignored.\n } else {\n // Past the end of the current span. Stop.\n break;\n }\n }\n\n addNode(parent, spansToTree({\n type: span.type,\n data: span.data,\n key: span.key\n }, graphemes, start, span.end, subspans));\n start = span.end;\n }\n\n // Add the last unformatted range.\n if (start < end) {\n addNode(parent, {\n text: graphemes\n .slice(start, end)\n .map((segment) => segment.segment)\n .join('')\n });\n }\n\n return parent;\n}\n\n// Append a tree to a Drafty doc.\nfunction treeToDrafty(doc, tree, keymap) {\n if (!tree) {\n return doc;\n }\n\n doc.txt = doc.txt || '';\n\n // Checkpoint to measure length of the current tree node.\n const start = stringToGraphemes(doc.txt).length;\n\n if (tree.text) {\n doc.txt += tree.text;\n } else if (Array.isArray(tree.children)) {\n tree.children.forEach((c) => {\n treeToDrafty(doc, c, keymap);\n });\n }\n\n if (tree.type) {\n const len = stringToGraphemes(doc.txt).length - start;\n doc.fmt = doc.fmt || [];\n if (Object.keys(tree.data || {}).length > 0) {\n doc.ent = doc.ent || [];\n const newKey = (typeof keymap[tree.key] == 'undefined') ? doc.ent.length : keymap[tree.key];\n keymap[tree.key] = newKey;\n doc.ent[newKey] = {\n tp: tree.type,\n data: tree.data\n };\n if (tree.att) {\n // Attachment.\n doc.fmt.push({\n at: -1,\n len: 0,\n key: newKey\n });\n } else {\n doc.fmt.push({\n at: start,\n len: len,\n key: newKey\n });\n }\n } else {\n doc.fmt.push({\n tp: tree.type,\n at: start,\n len: len\n });\n }\n }\n return doc;\n}\n\n// Traverse the tree top down transforming the nodes: apply transformer to every tree node.\nfunction treeTopDown(src, transformer, context) {\n if (!src) {\n return null;\n }\n\n let dst = transformer.call(context, src);\n if (!dst || !dst.children) {\n return dst;\n }\n\n const children = [];\n for (let i in dst.children) {\n let n = dst.children[i];\n if (n) {\n n = treeTopDown(n, transformer, context);\n if (n) {\n children.push(n);\n }\n }\n }\n\n if (children.length == 0) {\n dst.children = null;\n } else {\n dst.children = children;\n }\n\n return dst;\n}\n\n// Traverse the tree bottom-up: apply formatter to every node.\n// The formatter must maintain its state through context.\nfunction treeBottomUp(src, formatter, index, stack, context) {\n if (!src) {\n return null;\n }\n\n if (stack && src.type) {\n stack.push(src.type);\n }\n\n let values = [];\n for (let i in src.children) {\n const n = treeBottomUp(src.children[i], formatter, i, stack, context);\n if (n) {\n values.push(n);\n }\n }\n if (values.length == 0) {\n if (src.text) {\n values = [src.text];\n } else {\n values = null;\n }\n }\n\n if (stack && src.type) {\n stack.pop();\n }\n\n return formatter.call(context, src.type, src.data, values, index, stack);\n}\n\n// Clip tree to the provided limit.\nfunction shortenTree(tree, limit, tail) {\n if (!tree) {\n return null;\n }\n\n if (tail) {\n limit -= tail.length;\n }\n\n const shortener = function(node) {\n if (limit <= -1) {\n // Limit -1 means the doc was already clipped.\n return null;\n }\n\n if (node.att) {\n // Attachments are unchanged.\n return node;\n }\n if (limit == 0) {\n node.text = tail;\n limit = -1;\n } else if (node.text) {\n const graphemes = stringToGraphemes(node.text);\n if (graphemes.length > limit) {\n node.text = graphemes\n .slice(0, limit)\n .map((segment) => segment.segment)\n .join('') + tail;\n limit = -1;\n } else {\n limit -= graphemes.length;\n }\n }\n return node;\n }\n\n return treeTopDown(tree, shortener);\n}\n\n// Strip heavy entities from a tree.\nfunction lightEntity(tree, allow) {\n const lightCopy = node => {\n const data = copyEntData(node.data, true, allow ? allow(node) : null);\n if (data) {\n node.data = data;\n } else {\n delete node.data;\n }\n return node;\n }\n return treeTopDown(tree, lightCopy);\n}\n\n// Remove spaces and breaks on the left.\nfunction lTrim(tree) {\n if (tree.type == 'BR') {\n tree = null;\n } else if (tree.text) {\n if (!tree.type) {\n tree.text = tree.text.trimStart();\n if (!tree.text) {\n tree = null;\n }\n }\n } else if (!tree.type && tree.children && tree.children.length > 0) {\n const c = lTrim(tree.children[0]);\n if (c) {\n tree.children[0] = c;\n } else {\n tree.children.shift();\n if (!tree.type && tree.children.length == 0) {\n tree = null;\n }\n }\n }\n return tree;\n}\n\n// Move attachments to the end. Attachments must be at the top level, no need to traverse the tree.\nfunction attachmentsToEnd(tree, limit) {\n if (!tree) {\n return null;\n }\n\n if (tree.att) {\n tree.text = ' ';\n delete tree.att;\n delete tree.children;\n } else if (tree.children) {\n const attachments = [];\n const children = [];\n for (let i in tree.children) {\n const c = tree.children[i];\n if (c.att) {\n if (attachments.length == limit) {\n // Too many attachments to preview;\n continue;\n }\n if (c.data['mime'] == JSON_MIME_TYPE || c.data['mime'] == JSON_MIME_TYPE_LEGACY) {\n // JSON attachments are not shown in preview.\n continue;\n }\n\n delete c.att;\n delete c.children;\n c.text = ' ';\n attachments.push(c);\n } else {\n children.push(c);\n }\n }\n tree.children = children.concat(attachments);\n }\n return tree;\n}\n\n// Get a list of entities from a text.\nfunction extractEntities(line) {\n let match;\n let extracted = [];\n ENTITY_TYPES.forEach((entity) => {\n while ((match = entity.re.exec(line)) !== null) {\n extracted.push({\n offset: match['index'],\n len: match[0].length,\n unique: match[0],\n data: entity.pack(match[0]),\n type: entity.name\n });\n }\n });\n\n if (extracted.length == 0) {\n return extracted;\n }\n\n // Remove entities detected inside other entities, like #hashtag in a URL.\n extracted.sort((a, b) => {\n return a.offset - b.offset;\n });\n\n let idx = -1;\n extracted = extracted.filter((el) => {\n const result = (el.offset > idx);\n idx = el.offset + el.len;\n return result;\n });\n\n return extracted;\n}\n\n// Convert the chunks into format suitable for serialization.\nfunction draftify(chunks, startAt) {\n let plain = '';\n let ranges = [];\n for (let i in chunks) {\n const chunk = chunks[i];\n if (!chunk.txt) {\n const drafty = draftify(chunk.children, plain.length + startAt);\n chunk.txt = drafty.txt;\n ranges = ranges.concat(drafty.fmt);\n }\n\n if (chunk.tp) {\n ranges.push({\n at: plain.length + startAt,\n len: chunk.txt.length,\n tp: chunk.tp\n });\n }\n\n plain += chunk.txt;\n }\n return {\n txt: plain,\n fmt: ranges\n };\n}\n\n// Create a copy of entity data with (light=false) or without (light=true) the large payload.\n// The array 'allow' contains a list of fields exempt from stripping.\nfunction copyEntData(data, light, allow) {\n if (data && Object.entries(data).length > 0) {\n allow = allow || [];\n const dc = {};\n ALLOWED_ENT_FIELDS.forEach(key => {\n if (data[key]) {\n if (light && !allow.includes(key) &&\n (typeof data[key] == 'string' || Array.isArray(data[key])) &&\n data[key].length > MAX_PREVIEW_DATA_SIZE) {\n return;\n }\n if (typeof data[key] == 'object') {\n return;\n }\n dc[key] = data[key];\n }\n });\n\n if (Object.entries(dc).length != 0) {\n return dc;\n }\n }\n return null;\n}\n\n// Returns true if object is empty, if undefined returns true\nfunction isEmptyObject(obj) {\n return Object.keys(obj ?? {}).length == 0;\n};\n\n\n// Returns an array (of length equal to the length of the original string) such that each index\n// denotes the position of char in string in a grapheme array (created from that string)\n// Eg: string: \"Hi👋🏼Hi\" -> [0,1,2,2,2,2,3,4]\nfunction graphemeIndices(graphemes) {\n const result = [];\n let graphemeIndex = 0;\n let charIndex = 0;\n\n // Iterate over the grapheme clusters.\n for (const {\n segment\n }\n of graphemes) {\n // Map the character indices to the grapheme index.\n for (let i = 0; i < segment.length; i++) {\n result[charIndex + i] = graphemeIndex;\n }\n\n // Increment the character index by the length of the grapheme cluster.\n charIndex += segment.length;\n\n // Increment the grapheme index.\n graphemeIndex++;\n }\n\n return result;\n}\n\n// Convert fmt.at and fmt.len from character-expressed index and length to grapheme-expressed\n// index and length.\nfunction toGraphemeValues(fmt, segments, txt) {\n segments = segments ?? segmenter.segment(txt);\n\n const indices = graphemeIndices(segments);\n\n const correctAt = indices[fmt.at];\n const correctLen = fmt.at + fmt.len <= txt.length ?\n indices[fmt.at + fmt.len - 1] - correctAt : fmt.len;\n\n return {\n at: correctAt,\n len: correctLen + 1\n };\n}\n\n// Convert string to graphme cluster array.\nfunction stringToGraphemes(str) {\n return Array.from(segmenter.segment(str));\n}\n\nif (typeof module != 'undefined') {\n module.exports = Drafty;\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/**\n * @file Access control model.\n *\n * @copyright 2015-2022 Tinode LLC.\n */\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\n/**\n * Helper class for handling access mode.\n *\n * @class AccessMode\n * @memberof Tinode\n *\n * @param {AccessMode|Object=} acs - AccessMode to copy or access mode object received from the server.\n */\nexport default class AccessMode {\n constructor(acs) {\n if (acs) {\n this.given = typeof acs.given == 'number' ? acs.given : AccessMode.decode(acs.given);\n this.want = typeof acs.want == 'number' ? acs.want : AccessMode.decode(acs.want);\n this.mode = acs.mode ? (typeof acs.mode == 'number' ? acs.mode : AccessMode.decode(acs.mode)) :\n (this.given & this.want);\n }\n }\n\n static #checkFlag(val, side, flag) {\n side = side || 'mode';\n if (['given', 'want', 'mode'].includes(side)) {\n return ((val[side] & flag) != 0);\n }\n throw new Error(`Invalid AccessMode component '${side}'`);\n }\n /**\n * Parse string into an access mode value.\n * @memberof Tinode.AccessMode\n * @static\n *\n * @param {string | Number} mode - either a String representation of the access mode to parse or a set of bits to assign.\n * @returns {number} - Access mode as a numeric value.\n */\n static decode(str) {\n if (!str) {\n return null;\n } else if (typeof str == 'number') {\n return str & AccessMode._BITMASK;\n } else if (str === 'N' || str === 'n') {\n return AccessMode._NONE;\n }\n\n const bitmask = {\n 'J': AccessMode._JOIN,\n 'R': AccessMode._READ,\n 'W': AccessMode._WRITE,\n 'P': AccessMode._PRES,\n 'A': AccessMode._APPROVE,\n 'S': AccessMode._SHARE,\n 'D': AccessMode._DELETE,\n 'O': AccessMode._OWNER\n };\n\n let m0 = AccessMode._NONE;\n\n for (let i = 0; i < str.length; i++) {\n const bit = bitmask[str.charAt(i).toUpperCase()];\n if (!bit) {\n // Unrecognized bit, skip.\n continue;\n }\n m0 |= bit;\n }\n return m0;\n }\n /**\n * Convert numeric representation of the access mode into a string.\n *\n * @memberof Tinode.AccessMode\n * @static\n *\n * @param {number} val - access mode value to convert to a string.\n * @returns {string} - Access mode as a string.\n */\n static encode(val) {\n if (val === null || val === AccessMode._INVALID) {\n return null;\n } else if (val === AccessMode._NONE) {\n return 'N';\n }\n\n const bitmask = ['J', 'R', 'W', 'P', 'A', 'S', 'D', 'O'];\n let res = '';\n for (let i = 0; i < bitmask.length; i++) {\n if ((val & (1 << i)) != 0) {\n res = res + bitmask[i];\n }\n }\n return res;\n }\n /**\n * Update numeric representation of access mode with the new value. The value\n * is one of the following:\n * - a string starting with '+' or '-' then the bits to add or remove, e.g. '+R-W' or '-PS'.\n * - a new value of access mode\n *\n * @memberof Tinode.AccessMode\n * @static\n *\n * @param {number} val - access mode value to update.\n * @param {string} upd - update to apply to val.\n * @returns {number} - updated access mode.\n */\n static update(val, upd) {\n if (!upd || typeof upd != 'string') {\n return val;\n }\n\n let action = upd.charAt(0);\n if (action == '+' || action == '-') {\n let val0 = val;\n // Split delta-string like '+ABC-DEF+Z' into an array of parts including + and -.\n const parts = upd.split(/([-+])/);\n // Starting iteration from 1 because String.split() creates an array with the first empty element.\n // Iterating by 2 because we parse pairs +/- then data.\n for (let i = 1; i < parts.length - 1; i += 2) {\n action = parts[i];\n const m0 = AccessMode.decode(parts[i + 1]);\n if (m0 == AccessMode._INVALID) {\n return val;\n }\n if (m0 == null) {\n continue;\n }\n if (action === '+') {\n val0 |= m0;\n } else if (action === '-') {\n val0 &= ~m0;\n }\n }\n val = val0;\n } else {\n // The string is an explicit new value 'ABC' rather than delta.\n const val0 = AccessMode.decode(upd);\n if (val0 != AccessMode._INVALID) {\n val = val0;\n }\n }\n\n return val;\n }\n /**\n * Bits present in a1 but missing in a2.\n *\n * @static\n * @memberof Tinode\n *\n * @param {number | string} a1 - access mode to subtract from.\n * @param {number | string} a2 - access mode to subtract.\n * @returns {number} access mode with bits present in a1 but missing in a2.\n */\n static diff(a1, a2) {\n a1 = AccessMode.decode(a1);\n a2 = AccessMode.decode(a2);\n\n if (a1 == AccessMode._INVALID || a2 == AccessMode._INVALID) {\n return AccessMode._INVALID;\n }\n return a1 & ~a2;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Custom formatter\n */\n toString() {\n return '{\"mode\": \"' + AccessMode.encode(this.mode) +\n '\", \"given\": \"' + AccessMode.encode(this.given) +\n '\", \"want\": \"' + AccessMode.encode(this.want) + '\"}';\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Converts numeric values to strings.\n */\n jsonHelper() {\n return {\n mode: AccessMode.encode(this.mode),\n given: AccessMode.encode(this.given),\n want: AccessMode.encode(this.want)\n };\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Assign value to 'mode'.\n * @memberof Tinode.AccessMode\n *\n * @param {string | Number} m - either a string representation of the access mode or a set of bits.\n * @returns {AccessMode} - this AccessMode.\n */\n setMode(m) {\n this.mode = AccessMode.decode(m);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update mode value.\n * @memberof Tinode.AccessMode\n *\n * @param {string} u - string representation of the changes to apply to access mode.\n * @returns {AccessMode} - this AccessMode.\n */\n updateMode(u) {\n this.mode = AccessMode.update(this.mode, u);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get mode value as a string.\n * @memberof Tinode.AccessMode\n *\n * @returns {string} - mode value.\n */\n getMode() {\n return AccessMode.encode(this.mode);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Assign given value.\n * @memberof Tinode.AccessMode\n *\n * @param {string | Number} g - either a string representation of the access mode or a set of bits.\n * @returns {AccessMode} - this AccessMode.\n */\n setGiven(g) {\n this.given = AccessMode.decode(g);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update 'given' value.\n * @memberof Tinode.AccessMode\n *\n * @param {string} u - string representation of the changes to apply to access mode.\n * @returns {AccessMode} - this AccessMode.\n */\n updateGiven(u) {\n this.given = AccessMode.update(this.given, u);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get 'given' value as a string.\n * @memberof Tinode.AccessMode\n *\n * @returns {string} - given value.\n */\n getGiven() {\n return AccessMode.encode(this.given);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Assign 'want' value.\n * @memberof Tinode.AccessMode\n *\n * @param {string | Number} w - either a string representation of the access mode or a set of bits.\n * @returns {AccessMode} - this AccessMode.\n */\n setWant(w) {\n this.want = AccessMode.decode(w);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update 'want' value.\n * @memberof Tinode.AccessMode\n *\n * @param {string} u - string representation of the changes to apply to access mode.\n * @returns {AccessMode} - this AccessMode.\n */\n updateWant(u) {\n this.want = AccessMode.update(this.want, u);\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get 'want' value as a string.\n * @memberof Tinode.AccessMode\n *\n * @returns {string} - want value.\n */\n getWant() {\n return AccessMode.encode(this.want);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get permissions present in 'want' but missing in 'given'.\n * Inverse of {@link Tinode.AccessMode#getExcessive}\n *\n * @memberof Tinode.AccessMode\n *\n * @returns {string} permissions present in want but missing in given .\n */\n getMissing() {\n return AccessMode.encode(this.want & ~this.given);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Get permissions present in 'given' but missing in 'want'.\n * Inverse of {@link Tinode.AccessMode#getMissing}\n * @memberof Tinode.AccessMode\n *\n * @returns {string} permissions present in given but missing in want .\n */\n getExcessive() {\n return AccessMode.encode(this.given & ~this.want);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Update 'want', 'give', and 'mode' values.\n * @memberof Tinode.AccessMode\n *\n * @param {AccessMode} val - new access mode value.\n * @returns {AccessMode} - this AccessMode.\n */\n updateAll(val) {\n if (val) {\n this.updateGiven(val.given);\n this.updateWant(val.want);\n this.mode = this.given & this.want;\n }\n return this;\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Owner (O) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isOwner(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._OWNER);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Presence (P) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isPresencer(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._PRES);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Presence (P) flag is NOT set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isMuted(side) {\n return !this.isPresencer(side);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Join (J) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isJoiner(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._JOIN);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Reader (R) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isReader(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._READ);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Writer (W) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isWriter(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._WRITE);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Approver (A) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isApprover(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._APPROVE);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if either one of Owner (O) or Approver (A) flags is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isAdmin(side) {\n return this.isOwner(side) || this.isApprover(side);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if either one of Owner (O), Approver (A), or Sharer (S) flags is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isSharer(side) {\n return this.isAdmin(side) || AccessMode.#checkFlag(this, side, AccessMode._SHARE);\n }\n /**\n * AccessMode is a class representing topic access mode.\n *\n * @memberof Tinode\n * @class AccessMode\n */\n /**\n * Check if Deleter (D) flag is set.\n * @memberof Tinode.AccessMode\n * @param {string=} side - which permission to check: given, want, mode; default: mode.\n * @returns {boolean} - true if flag is set.\n */\n isDeleter(side) {\n return AccessMode.#checkFlag(this, side, AccessMode._DELETE);\n }\n}\n\nAccessMode._NONE = 0x00;\nAccessMode._JOIN = 0x01;\nAccessMode._READ = 0x02;\nAccessMode._WRITE = 0x04;\nAccessMode._PRES = 0x08;\nAccessMode._APPROVE = 0x10;\nAccessMode._SHARE = 0x20;\nAccessMode._DELETE = 0x40;\nAccessMode._OWNER = 0x80;\n\nAccessMode._BITMASK = AccessMode._JOIN | AccessMode._READ | AccessMode._WRITE | AccessMode._PRES |\n AccessMode._APPROVE | AccessMode._SHARE | AccessMode._DELETE | AccessMode._OWNER;\nAccessMode._INVALID = 0x100000;\n","export const PACKAGE_VERSION = \"0.24.3\";\n","/**\n * @file Global constants and configuration parameters.\n *\n * @copyright 2015-2025 Tinode LLC\n */\n'use strict';\n\nimport {\n PACKAGE_VERSION\n} from '../version.js';\n\n// Global constants\nexport const PROTOCOL_VERSION = '0'; // Major component of the version, e.g. '0' in '0.17.1'.\nexport const VERSION = PACKAGE_VERSION || '0.24';\nexport const LIBRARY = 'tinodejs/' + VERSION;\n\n// Topic name prefixes.\nexport const TOPIC_NEW = 'new';\nexport const TOPIC_NEW_CHAN = 'nch';\nexport const TOPIC_ME = 'me';\nexport const TOPIC_FND = 'fnd';\nexport const TOPIC_SYS = 'sys';\nexport const TOPIC_SLF = 'slf';\nexport const TOPIC_CHAN = 'chn';\nexport const TOPIC_GRP = 'grp';\nexport const TOPIC_P2P = 'p2p';\nexport const USER_NEW = 'new';\n\n// Starting value of a locally-generated seqId used for pending messages.\nexport const LOCAL_SEQID = 0xFFFFFFF;\n\n// Status codes.\nexport const MESSAGE_STATUS_NONE = 0; // Status not assigned.\nexport const MESSAGE_STATUS_QUEUED = 10; // Local ID assigned, in progress to be sent.\nexport const MESSAGE_STATUS_SENDING = 20; // Transmission started.\nexport const MESSAGE_STATUS_FAILED = 30; // At least one attempt was made to send the message.\nexport const MESSAGE_STATUS_FATAL = 40; // Message sending failed and it should not be retried.\nexport const MESSAGE_STATUS_SENT = 50; // Delivered to the server.\nexport const MESSAGE_STATUS_RECEIVED = 60; // Received by the client.\nexport const MESSAGE_STATUS_READ = 70; // Read by the user.\nexport const MESSAGE_STATUS_TO_ME = 80; // The message is received from another user.\n\n// Reject unresolved futures after this many milliseconds.\nexport const EXPIRE_PROMISES_TIMEOUT = 5_000;\n// Periodicity of garbage collection of unresolved futures.\nexport const EXPIRE_PROMISES_PERIOD = 1_000;\n\n// Delay before acknowledging that a message was recived.\nexport const RECV_TIMEOUT = 100;\n\n// Default number of messages to pull into memory from persistent cache.\nexport const DEFAULT_MESSAGES_PAGE = 24;\n\n// Unicode DEL character indicating data was deleted.\nexport const DEL_CHAR = '\\u2421';\n\n// Maximum number of pinnned messages;\nexport const MAX_PINNED_COUNT = 5;\n\n// Tag prefixes for alias, email, phone.\nexport const TAG_ALIAS = 'alias:';\nexport const TAG_EMAIL = 'email:';\nexport const TAG_PHONE = 'tel:';\n","/**\n * @file Throwable error with numeric error code.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nexport default class CommError extends Error {\n constructor(message, code) {\n super(`${message} (${code})`);\n this.name = 'CommError';\n this.code = code;\n }\n}\n","/**\n * @file Utilities used in multiple places.\n *\n * @copyright 2015-2022 Tinode LLC.\n */\n'use strict';\n\nimport AccessMode from './access-mode.js';\nimport {\n DEL_CHAR,\n LOCAL_SEQID\n} from './config.js';\n\n// Attempt to convert date and AccessMode strings to objects.\nexport function jsonParseHelper(key, val) {\n // Try to convert string timestamps with optional milliseconds to Date,\n // e.g. 2015-09-02T01:45:43[.123]Z\n if (typeof val == 'string' && val.length >= 20 && val.length <= 24 && ['ts', 'touched', 'updated', 'created', 'when', 'deleted', 'expires'].includes(key)) {\n const date = new Date(val);\n if (!isNaN(date)) {\n return date;\n }\n } else if (key === 'acs' && typeof val === 'object') {\n return new AccessMode(val);\n }\n return val;\n}\n\n// Checks if URL is a relative url, i.e. has no 'scheme://', including the case of missing scheme '//'.\n// The scheme is expected to be RFC-compliant, e.g. [a-z][a-z0-9+.-]*\n// example.html - ok\n// https:example.com - not ok.\n// http:/example.com - not ok.\n// ' ↲ https://example.com' - not ok. (↲ means carriage return)\nexport function isUrlRelative(url) {\n return url && !/^\\s*([a-z][a-z0-9+.-]*:|\\/\\/)/im.test(url);\n}\n\nfunction isValidDate(d) {\n return (d instanceof Date) && !isNaN(d) && (d.getTime() != 0);\n}\n\n// RFC3339 formater of Date\nexport function rfc3339DateString(d) {\n if (!isValidDate(d)) {\n return undefined;\n }\n\n const pad = function(val, sp) {\n sp = sp || 2;\n return '0'.repeat(sp - ('' + val).length) + val;\n };\n\n const millis = d.getUTCMilliseconds();\n return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate()) +\n 'T' + pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) +\n (millis ? '.' + pad(millis, 3) : '') + 'Z';\n}\n\n// Recursively merge src's own properties to dst.\n// Ignore properties where ignore[property] is true.\n// Array and Date objects are shallow-copied.\nexport function mergeObj(dst, src, ignore) {\n if (typeof src != 'object') {\n if (src === undefined) {\n return dst;\n }\n if (src === DEL_CHAR) {\n return undefined;\n }\n return src;\n }\n // JS is crazy: typeof null is 'object'.\n if (src === null) {\n return src;\n }\n\n // Handle Date\n if (src instanceof Date && !isNaN(src)) {\n return (!dst || !(dst instanceof Date) || isNaN(dst) || dst < src) ? src : dst;\n }\n\n // Access mode\n if (src instanceof AccessMode) {\n return new AccessMode(src);\n }\n\n // Handle Array\n if (src instanceof Array) {\n return src;\n }\n\n if (!dst || dst === DEL_CHAR) {\n dst = src.constructor();\n }\n\n for (let prop in src) {\n if (src.hasOwnProperty(prop) && (!ignore || !ignore[prop]) && (prop != '_noForwarding')) {\n try {\n dst[prop] = mergeObj(dst[prop], src[prop]);\n } catch (err) {\n // FIXME: probably need to log something here.\n }\n }\n }\n return dst;\n}\n\n// Update object stored in a cache. Returns updated value.\nexport function mergeToCache(cache, key, newval, ignore) {\n cache[key] = mergeObj(cache[key], newval, ignore);\n return cache[key];\n}\n\n// Strips all values from an object of they evaluate to false or if their name starts with '_'.\n// Used on all outgoing object before serialization to string.\nexport function simplify(obj) {\n Object.keys(obj).forEach((key) => {\n if (key[0] == '_') {\n // Strip fields like \"obj._key\".\n delete obj[key];\n } else if (!obj[key]) {\n // Strip fields which evaluate to false.\n delete obj[key];\n } else if (Array.isArray(obj[key]) && obj[key].length == 0) {\n // Strip empty arrays.\n delete obj[key];\n } else if (!obj[key]) {\n // Strip fields which evaluate to false.\n delete obj[key];\n } else if (obj[key] instanceof Date) {\n // Strip invalid or zero date.\n if (!isValidDate(obj[key])) {\n delete obj[key];\n }\n } else if (typeof obj[key] == 'object') {\n simplify(obj[key]);\n // Strip empty objects.\n if (Object.getOwnPropertyNames(obj[key]).length == 0) {\n delete obj[key];\n }\n }\n });\n return obj;\n};\n\n\n// Trim whitespace, convert to lowercase, strip empty, short, and duplicate elements elements.\n// If the result is an empty array, add a single element \"\\u2421\" (Unicode Del character).\nexport function normalizeArray(arr) {\n let out = [];\n if (Array.isArray(arr)) {\n // Trim, throw away very short and empty tags.\n for (let i = 0, l = arr.length; i < l; i++) {\n let t = arr[i];\n if (t) {\n t = t.trim().toLowerCase();\n if (t.length > 1) {\n out.push(t);\n }\n }\n }\n out = out.sort().filter((item, pos, ary) => {\n return !pos || item != ary[pos - 1];\n });\n }\n if (out.length == 0) {\n // Add single tag with a Unicode Del character, otherwise an ampty array\n // is ambiguos. The Del tag will be stripped by the server.\n out.push(DEL_CHAR);\n }\n return out;\n}\n\n// Convert input to valid ranges of IDs.\nexport function normalizeRanges(ranges, maxSeq) {\n if (!Array.isArray(ranges)) {\n return [];\n }\n\n // Sort ranges in accending order by low, then descending by hi.\n ranges.sort((r1, r2) => {\n if (r1.low < r2.low) {\n return -1;\n }\n if (r1.low == r2.low) {\n return (r2.hi | 0) - r1.hi;\n }\n return 1;\n });\n\n // Remove pending messages from ranges possibly clipping some ranges.\n ranges = ranges.reduce((out, r) => {\n if (r.low < LOCAL_SEQID && r.low > 0) {\n if (!r.hi || r.hi < LOCAL_SEQID) {\n out.push(r);\n } else {\n // Clip hi to max allowed value.\n out.push({\n low: r.low,\n hi: maxSeq + 1\n });\n }\n }\n return out;\n }, []);\n\n // Merge overlapping ranges.\n ranges = ranges.reduce((out, r) => {\n if (out.length == 0) {\n out.push(r);\n } else {\n let prev = out[out.length - 1];\n if (r.low <= prev.hi) {\n prev.hi = Math.max(prev.hi, r.hi);\n } else {\n out.push(r);\n }\n }\n return out;\n }, []);\n\n return ranges;\n}\n\n// Convert array of IDs to array of ranges.\nexport function listToRanges(list) {\n // Sort the list in ascending order\n list.sort((a, b) => a - b);\n // Convert the array of IDs to ranges.\n return list.reduce((out, id) => {\n if (out.length == 0) {\n // First element.\n out.push({\n low: id\n });\n } else {\n let prev = out[out.length - 1];\n if ((!prev.hi && (id != prev.low + 1)) || (id > prev.hi)) {\n // New range.\n out.push({\n low: id\n });\n } else {\n // Expand existing range.\n prev.hi = prev.hi ? Math.max(prev.hi, id + 1) : id + 1;\n }\n }\n return out;\n }, []);\n}\n\n// Cuts 'clip' range out of the 'src' range.\n// Returns an array with 0, 1 or 2 elements.\nexport function clipOutRange(src, clip) {\n if (clip.hi <= src.low || clip.low >= src.hi) {\n // Clip is completely outside of src, no intersection.\n return [src];\n }\n\n\n if (clip.low <= src.low) {\n if (clip.hi >= src.hi) {\n // The source range is completely inside the clipping range.\n return [];\n }\n // Partial clipping at the top.\n return [{\n low: clip.hi,\n hi: src.hi\n }];\n }\n\n // Range on the lower end.\n const result = [{\n low: src.low,\n hi: clip.low\n }];\n if (clip.hi < src.hi) {\n // Maybe a range on the higher end, if clip is completely inside the source.\n result.push({\n low: clip.hi,\n hi: src.hi\n });\n }\n\n return result;\n}\n\n// Cuts 'src' range to be completely within 'clip' range.\n// Returns clipped range or null if 'src' is outside of 'clip'.\nexport function clipInRange(src, clip) {\n if (clip.hi <= src.low || clip.low >= src.hi) {\n // The src is completely outside of the clip, no intersection.\n return null;\n }\n\n if (src.low >= clip.low && src.hi <= clip.hi) {\n // Src is completely within the clip, return the entire src.\n return src;\n }\n\n // Partial overlap.\n return {\n low: Math.max(src.low, clip.low),\n hi: Math.min(src.hi, clip.hi)\n };\n\n return result;\n}\n","/**\n * @file Abstraction layer for websocket and long polling connections.\n *\n * @copyright 2015-2022 Tinode LLC.\n */\n'use strict';\n\nimport CommError from './comm-error.js';\nimport {\n jsonParseHelper\n} from './utils.js';\n\nlet WebSocketProvider;\nlet XHRProvider;\n\n// Error code to return in case of a network problem.\nconst NETWORK_ERROR = 503;\nconst NETWORK_ERROR_TEXT = \"Connection failed\";\n\n// Error code to return when user disconnected from server.\nconst NETWORK_USER = 418;\nconst NETWORK_USER_TEXT = \"Disconnected by client\";\n\n// Settings for exponential backoff\nconst _BOFF_BASE = 2000; // 2000 milliseconds, minimum delay between reconnects\nconst _BOFF_MAX_ITER = 10; // Maximum delay between reconnects 2^10 * 2000 ~ 34 minutes\nconst _BOFF_JITTER = 0.3; // Add random delay\n\n// Helper function for creating an endpoint URL.\nfunction makeBaseUrl(host, protocol, version, apiKey) {\n let url = null;\n\n if (['http', 'https', 'ws', 'wss'].includes(protocol)) {\n url = `${protocol}://${host}`;\n if (url.charAt(url.length - 1) !== '/') {\n url += '/';\n }\n url += 'v' + version + '/channels';\n if (['http', 'https'].includes(protocol)) {\n // Long polling endpoint ends with \"lp\", i.e.\n // '/v0/channels/lp' vs just '/v0/channels' for ws\n url += '/lp';\n }\n url += '?apikey=' + apiKey;\n }\n return url;\n}\n\n/**\n * An abstraction for a websocket or a long polling connection.\n *\n * @class Connection\n * @memberof Tinode\n\n * @param {Object} config - configuration parameters.\n * @param {string} config.host - Host name and optional port number to connect to.\n * @param {string} config.apiKey - API key generated by keygen.\n * @param {string} config.transport - Network transport to use, either \"ws\"/\"wss\" for websocket or\n * lp for long polling.\n * @param {boolean} config.secure - Use Secure WebSocket if true.\n * @param {string} version_ - Major value of the protocol version, e.g. '0' in '0.17.1'.\n * @param {boolean} autoreconnect_ - If connection is lost, try to reconnect automatically.\n */\nexport default class Connection {\n // Logger, does nothing by default.\n static #log = _ => {};\n\n #boffTimer = null;\n #boffIteration = 0;\n #boffClosed = false; // Indicator if the socket was manually closed - don't autoreconnect if true.\n\n // Websocket.\n #socket = null;\n\n host;\n secure;\n apiKey;\n\n version;\n autoreconnect;\n\n initialized;\n\n // (config.host, config.apiKey, config.transport, config.secure), PROTOCOL_VERSION, true\n constructor(config, version_, autoreconnect_) {\n this.host = config.host;\n this.secure = config.secure;\n this.apiKey = config.apiKey;\n\n this.version = version_;\n this.autoreconnect = autoreconnect_;\n\n if (config.transport === 'lp') {\n // explicit request to use long polling\n this.#init_lp();\n this.initialized = 'lp';\n } else if (config.transport === 'ws') {\n // explicit request to use web socket\n // if websockets are not available, horrible things will happen\n this.#init_ws();\n this.initialized = 'ws';\n }\n\n if (!this.initialized) {\n // Invalid or undefined network transport.\n Connection.#log(\"Unknown or invalid network transport. Running under Node? Call 'Tinode.setNetworkProviders()'.\");\n throw new Error(\"Unknown or invalid network transport. Running under Node? Call 'Tinode.setNetworkProviders()'.\");\n }\n }\n\n /**\n * To use Connection in a non browser context, supply WebSocket and XMLHttpRequest providers.\n * @static\n * @memberof Connection\n * @param wsProvider WebSocket provider, e.g. for nodeJS , require('ws').\n * @param xhrProvider XMLHttpRequest provider, e.g. for node require('xhr').\n */\n static setNetworkProviders(wsProvider, xhrProvider) {\n WebSocketProvider = wsProvider;\n XHRProvider = xhrProvider;\n }\n\n /**\n * Assign a non-default logger.\n * @static\n * @memberof Connection\n * @param {function} l variadic logging function.\n */\n static set logger(l) {\n Connection.#log = l;\n }\n\n /**\n * Initiate a new connection\n * @memberof Tinode.Connection#\n * @param {string} host_ Host name to connect to; if null the old host name will be used.\n * @param {boolean} force Force new connection even if one already exists.\n * @return {Promise} Promise resolved/rejected when the connection call completes, resolution is called without\n * parameters, rejection passes the {Error} as parameter.\n */\n connect(host_, force) {\n return Promise.reject(null);\n }\n\n /**\n * Try to restore a network connection, also reset backoff.\n * @memberof Tinode.Connection#\n *\n * @param {boolean} force - reconnect even if there is a live connection already.\n */\n reconnect(force) {}\n\n /**\n * Terminate the network connection\n * @memberof Tinode.Connection#\n */\n disconnect() {}\n\n /**\n * Send a string to the server.\n * @memberof Tinode.Connection#\n *\n * @param {string} msg - String to send.\n * @throws Throws an exception if the underlying connection is not live.\n */\n sendText(msg) {}\n\n /**\n * Check if connection is alive.\n * @memberof Tinode.Connection#\n * @returns {boolean} true if connection is live, false otherwise.\n */\n isConnected() {\n return false;\n }\n\n /**\n * Get the name of the current network transport.\n * @memberof Tinode.Connection#\n * @returns {string} name of the transport such as \"ws\" or \"lp\".\n */\n transport() {\n return this.initialized;\n }\n\n /**\n * Send network probe to check if connection is indeed live.\n * @memberof Tinode.Connection#\n */\n probe() {\n this.sendText('1');\n }\n\n /**\n * Reset autoreconnect counter to zero.\n * @memberof Tinode.Connection#\n */\n backoffReset() {\n this.#boffReset();\n }\n\n // Backoff implementation - reconnect after a timeout.\n #boffReconnect() {\n // Clear timer\n clearTimeout(this.#boffTimer);\n // Calculate when to fire the reconnect attempt\n const timeout = _BOFF_BASE * (Math.pow(2, this.#boffIteration) * (1.0 + _BOFF_JITTER * Math.random()));\n // Update iteration counter for future use\n this.#boffIteration = (this.#boffIteration >= _BOFF_MAX_ITER ? this.#boffIteration : this.#boffIteration + 1);\n if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(timeout);\n }\n\n this.#boffTimer = setTimeout(_ => {\n Connection.#log(`Reconnecting, iter=${this.#boffIteration}, timeout=${timeout}`);\n // Maybe the socket was closed while we waited for the timer?\n if (!this.#boffClosed) {\n const prom = this.connect();\n if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(0, prom);\n } else {\n // Suppress error if it's not used.\n prom.catch(_ => {\n /* do nothing */\n });\n }\n } else if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(-1);\n }\n }, timeout);\n }\n\n // Terminate auto-reconnect process.\n #boffStop() {\n clearTimeout(this.#boffTimer);\n this.#boffTimer = null;\n }\n\n // Reset auto-reconnect iteration counter.\n #boffReset() {\n this.#boffIteration = 0;\n }\n\n // Initialization for long polling.\n #init_lp() {\n const XDR_UNSENT = 0; // Client has been created. open() not called yet.\n const XDR_OPENED = 1; // open() has been called.\n const XDR_HEADERS_RECEIVED = 2; // send() has been called, and headers and status are available.\n const XDR_LOADING = 3; // Downloading; responseText holds partial data.\n const XDR_DONE = 4; // The operation is complete.\n\n // Fully composed endpoint URL, with API key & SID\n let _lpURL = null;\n\n let _poller = null;\n let _sender = null;\n\n let lp_sender = (url_) => {\n const sender = new XHRProvider();\n sender.onreadystatechange = (evt) => {\n if (sender.readyState == XDR_DONE && sender.status >= 400) {\n // Some sort of error response\n throw new CommError(\"LP sender failed\", sender.status);\n }\n };\n\n sender.open('POST', url_, true);\n return sender;\n }\n\n let lp_poller = (url_, resolve, reject) => {\n let poller = new XHRProvider();\n let promiseCompleted = false;\n\n poller.onreadystatechange = evt => {\n if (poller.readyState == XDR_DONE) {\n if (poller.status == 201) { // 201 == HTTP.Created, get SID\n let pkt = JSON.parse(poller.responseText, jsonParseHelper);\n _lpURL = url_ + '&sid=' + pkt.ctrl.params.sid;\n poller = lp_poller(_lpURL);\n poller.send(null);\n if (this.onOpen) {\n this.onOpen();\n }\n\n if (resolve) {\n promiseCompleted = true;\n resolve();\n }\n\n if (this.autoreconnect) {\n this.#boffStop();\n }\n } else if (poller.status > 0 && poller.status < 400) { // 0 = network error; 400 = HTTP.BadRequest\n if (this.onMessage) {\n this.onMessage(poller.responseText);\n }\n poller = lp_poller(_lpURL);\n poller.send(null);\n } else {\n // Don't throw an error here, gracefully handle server errors\n if (reject && !promiseCompleted) {\n promiseCompleted = true;\n reject(poller.responseText);\n }\n if (this.onMessage && poller.responseText) {\n this.onMessage(poller.responseText);\n }\n if (this.onDisconnect) {\n const code = poller.status || (this.#boffClosed ? NETWORK_USER : NETWORK_ERROR);\n const text = poller.responseText || (this.#boffClosed ? NETWORK_USER_TEXT : NETWORK_ERROR_TEXT);\n this.onDisconnect(new CommError(text, code), code);\n }\n\n // Polling has stopped. Indicate it by setting poller to null.\n poller = null;\n if (!this.#boffClosed && this.autoreconnect) {\n this.#boffReconnect();\n }\n }\n }\n };\n // Using POST to avoid caching response by service worker.\n poller.open('POST', url_, true);\n return poller;\n }\n\n this.connect = (host_, force) => {\n this.#boffClosed = false;\n\n if (_poller) {\n if (!force) {\n return Promise.resolve();\n }\n _poller.onreadystatechange = undefined;\n _poller.abort();\n _poller = null;\n }\n\n if (host_) {\n this.host = host_;\n }\n\n return new Promise((resolve, reject) => {\n const url = makeBaseUrl(this.host, this.secure ? 'https' : 'http', this.version, this.apiKey);\n Connection.#log(\"LP connecting to:\", url);\n _poller = lp_poller(url, resolve, reject);\n _poller.send(null);\n }).catch(err => {\n Connection.#log(\"LP connection failed:\", err);\n });\n };\n\n this.reconnect = force => {\n this.#boffStop();\n this.connect(null, force);\n };\n\n this.disconnect = _ => {\n this.#boffClosed = true;\n this.#boffStop();\n\n if (_sender) {\n _sender.onreadystatechange = undefined;\n _sender.abort();\n _sender = null;\n }\n if (_poller) {\n _poller.onreadystatechange = undefined;\n _poller.abort();\n _poller = null;\n }\n\n if (this.onDisconnect) {\n this.onDisconnect(new CommError(NETWORK_USER_TEXT, NETWORK_USER), NETWORK_USER);\n }\n // Ensure it's reconstructed\n _lpURL = null;\n };\n\n this.sendText = (msg) => {\n _sender = lp_sender(_lpURL);\n if (_sender && (_sender.readyState == XDR_OPENED)) {\n _sender.send(msg);\n } else {\n throw new Error(\"Long poller failed to connect\");\n }\n };\n\n this.isConnected = _ => {\n return (_poller && true);\n };\n }\n\n // Initialization for Websocket\n #init_ws() {\n this.connect = (host_, force) => {\n this.#boffClosed = false;\n\n if (this.#socket) {\n if (!force && this.#socket.readyState == this.#socket.OPEN) {\n // Issue a probe request to be sure the connection is live.\n // This is a non-blocking call.\n this.probe();\n return Promise.resolve();\n }\n this.#socket.close();\n this.#socket = null;\n }\n\n if (host_) {\n this.host = host_;\n }\n\n return new Promise((resolve, reject) => {\n const url = makeBaseUrl(this.host, this.secure ? 'wss' : 'ws', this.version, this.apiKey);\n\n Connection.#log(\"WS connecting to: \", url);\n\n // It throws when the server is not accessible but the exception cannot be caught:\n // https://stackoverflow.com/questions/31002592/javascript-doesnt-catch-error-in-websocket-instantiation/31003057\n const conn = new WebSocketProvider(url);\n\n conn.onerror = err => {\n reject(err);\n };\n\n conn.onopen = _ => {\n if (this.autoreconnect) {\n this.#boffStop();\n }\n\n if (this.onOpen) {\n this.onOpen();\n }\n\n resolve();\n };\n\n conn.onclose = _ => {\n this.#socket = null;\n\n if (this.onDisconnect) {\n const code = this.#boffClosed ? NETWORK_USER : NETWORK_ERROR;\n this.onDisconnect(new CommError(this.#boffClosed ? NETWORK_USER_TEXT : NETWORK_ERROR_TEXT, code), code);\n }\n\n if (!this.#boffClosed && this.autoreconnect) {\n this.#boffReconnect();\n }\n };\n\n conn.onmessage = evt => {\n if (this.onMessage) {\n this.onMessage(evt.data);\n }\n };\n\n this.#socket = conn;\n });\n }\n\n this.reconnect = force => {\n this.#boffStop();\n this.connect(null, force);\n };\n\n this.disconnect = _ => {\n this.#boffClosed = true;\n this.#boffStop();\n\n if (!this.#socket) {\n return;\n }\n this.#socket.close();\n this.#socket = null;\n };\n\n this.sendText = msg => {\n if (this.#socket && (this.#socket.readyState == this.#socket.OPEN)) {\n this.#socket.send(msg);\n } else {\n throw new Error(\"Websocket is not connected\");\n }\n };\n\n this.isConnected = _ => {\n return (this.#socket && (this.#socket.readyState == this.#socket.OPEN));\n };\n }\n\n // Callbacks:\n\n /**\n * A callback to pass incoming messages to. See {@link Tinode.Connection#onMessage}.\n * @callback Tinode.Connection.OnMessage\n * @memberof Tinode.Connection\n * @param {string} message - Message to process.\n */\n onMessage = undefined;\n\n /**\n * A callback for reporting a dropped connection.\n * @type {function}\n * @memberof Tinode.Connection#\n */\n onDisconnect = undefined;\n\n /**\n * A callback called when the connection is ready to be used for sending. For websockets it's socket open,\n * for long polling it's readyState=1 (OPENED)\n * @type {function}\n * @memberof Tinode.Connection#\n */\n onOpen = undefined;\n\n /**\n * A callback to notify of reconnection attempts. See {@link Tinode.Connection#onAutoreconnectIteration}.\n * @memberof Tinode.Connection\n * @callback AutoreconnectIterationType\n * @param {string} timeout - time till the next reconnect attempt in milliseconds. -1 means reconnect was skipped.\n * @param {Promise} promise resolved or rejected when the reconnect attemp completes.\n *\n */\n /**\n * A callback to inform when the next attampt to reconnect will happen and to receive connection promise.\n * @memberof Tinode.Connection#\n * @type {Tinode.Connection.AutoreconnectIterationType}\n */\n onAutoreconnectIteration = undefined;\n}\n\nConnection.NETWORK_ERROR = NETWORK_ERROR;\nConnection.NETWORK_ERROR_TEXT = NETWORK_ERROR_TEXT;\nConnection.NETWORK_USER = NETWORK_USER;\nConnection.NETWORK_USER_TEXT = NETWORK_USER_TEXT;\n","/**\n * @file Helper methods for dealing with IndexedDB cache of messages, users, and topics.\n *\n * @copyright 2015-2025 Tinode LLC.\n */\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\nconst DB_VERSION = 3;\nconst DB_NAME = 'tinode-web';\n\nlet IDBProvider;\n\nexport default class DB {\n #onError = _ => {};\n #logger = _ => {};\n\n // Instance of IndexDB.\n db = null;\n // Indicator that the cache is disabled.\n disabled = true;\n\n constructor(onError, logger) {\n this.#onError = onError || this.#onError;\n this.#logger = logger || this.#logger;\n }\n\n #mapObjects(source, callback, context) {\n if (!this.db) {\n return disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction([source]);\n trx.onerror = event => {\n this.#logger('PCache', 'mapObjects', source, event.target.error);\n reject(event.target.error);\n };\n trx.objectStore(source).getAll().onsuccess = event => {\n if (callback) {\n event.target.result.forEach(topic => {\n callback.call(context, topic);\n });\n }\n resolve(event.target.result);\n };\n });\n }\n\n /**\n * Initialize persistent cache: open or create/upgrade if needed.\n * @returns {Promise} promise to be resolved/rejected when the DB is initialized.\n */\n initDatabase() {\n return new Promise((resolve, reject) => {\n // Open the database and initialize callbacks.\n const req = IDBProvider.open(DB_NAME, DB_VERSION);\n req.onsuccess = event => {\n this.db = event.target.result;\n this.disabled = false;\n\n // This handler is called when a different tab tries to upgrade the database.\n this.db.onversionchange = _ => {\n this.#logger('PCache', \"another tab tries to upgrade DB, shutting down\");\n this.db.close();\n this.db = null;\n this.disabled = true;\n };\n\n resolve(this.db);\n };\n req.onerror = event => {\n this.#logger('PCache', \"failed to initialize\", event);\n reject(event.target.error);\n this.#onError(event.target.error);\n };\n req.onupgradeneeded = event => {\n this.db = event.target.result;\n\n this.db.onerror = event => {\n this.#logger('PCache', \"failed to create storage\", event);\n this.#onError(event.target.error);\n };\n\n // Individual object stores.\n\n // Alternatively could use event.oldVersion and event.newVersion\n // to determine which object stores to create or upgrade.\n\n if (!this.db.objectStoreNames.contains('topic')) {\n // Object store (table) for topics. The primary key is the topic name.\n this.db.createObjectStore('topic', {\n keyPath: 'name'\n });\n }\n\n if (!this.db.objectStoreNames.contains('user')) {\n // Users object store. UID is the primary key.\n this.db.createObjectStore('user', {\n keyPath: 'uid'\n });\n }\n\n if (!this.db.objectStoreNames.contains('subscription')) {\n // Subscriptions object store topic <-> user. Topic name + UID is the primary key.\n this.db.createObjectStore('subscription', {\n keyPath: ['topic', 'uid']\n });\n }\n\n if (!this.db.objectStoreNames.contains('message')) {\n // Messages object store. The primary key is topic name + seq.\n this.db.createObjectStore('message', {\n keyPath: ['topic', 'seq']\n });\n }\n\n if (!this.db.objectStoreNames.contains('dellog')) {\n // Records of deleted message ranges. The primary key is topic name + low seq.\n const dellog = this.db.createObjectStore('dellog', {\n keyPath: ['topic', 'low', 'hi']\n });\n if (!dellog.indexNames.contains('topic_clear')) {\n dellog.createIndex('topic_clear', ['topic', 'clear'], {\n unique: false\n });\n }\n }\n }\n });\n }\n\n /**\n * Delete persistent cache.\n */\n deleteDatabase() {\n // Close connection, otherwise operations will fail with 'onblocked'.\n if (this.db) {\n this.db.close();\n this.db = null;\n }\n return new Promise((resolve, reject) => {\n const req = IDBProvider.deleteDatabase(DB_NAME);\n req.onblocked = _ => {\n if (this.db) {\n this.db.close();\n }\n const err = new Error(\"blocked\");\n this.#logger('PCache', 'deleteDatabase', err);\n reject(err);\n };\n req.onsuccess = _ => {\n this.db = null;\n this.disabled = true;\n resolve(true);\n };\n req.onerror = event => {\n this.#logger('PCache', 'deleteDatabase', event.target.error);\n reject(event.target.error);\n };\n });\n }\n\n /**\n * Check if persistent cache is ready for use.\n * @memberOf DB\n * @returns {boolean} true if cache is ready, false otherwise.\n */\n isReady() {\n return !!this.db;\n }\n\n // Topics.\n\n /**\n * Save to cache or update topic in persistent cache.\n * @memberOf DB\n * @param {Topic} topic - topic to be added or updated.\n * @returns {Promise} promise resolved/rejected on operation completion.\n */\n updTopic(topic) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['topic'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updTopic', event.target.error);\n reject(event.target.error);\n };\n const req = trx.objectStore('topic').get(topic.name);\n req.onsuccess = _ => {\n trx.objectStore('topic').put(DB.#serializeTopic(req.result, topic));\n trx.commit();\n };\n });\n }\n\n /**\n * Mark or unmark topic as deleted.\n * @memberOf DB\n * @param {string} name - name of the topic to mark or unmark.\n * @param {boolean} deleted - status\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n markTopicAsDeleted(name, deleted) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['topic'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'markTopicAsDeleted', event.target.error);\n reject(event.target.error);\n };\n const req = trx.objectStore('topic').get(name);\n req.onsuccess = event => {\n const topic = event.target.result;\n if (topic && topic._deleted != deleted) {\n topic._deleted = deleted;\n trx.objectStore('topic').put(topic);\n }\n trx.commit();\n };\n });\n }\n\n /**\n * Remove topic from persistent cache.\n * @memberOf DB\n * @param {string} name - name of the topic to remove from database.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n remTopic(name) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['topic', 'subscription', 'message'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'remTopic', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('topic').delete(IDBKeyRange.only(name));\n trx.objectStore('subscription').delete(IDBKeyRange.bound([name, '-'], [name, '~']));\n trx.objectStore('message').delete(IDBKeyRange.bound([name, 0], [name, Number.MAX_SAFE_INTEGER]));\n trx.commit();\n });\n }\n\n /**\n * Execute a callback for each stored topic.\n * @memberOf DB\n * @param {function} callback - function to call for each topic.\n * @param {Object} context - the value or this inside the callback.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n mapTopics(callback, context) {\n return this.#mapObjects('topic', callback, context);\n }\n\n /**\n * Copy data from serialized object to topic.\n * @memberOf DB\n * @param {Topic} topic - target to deserialize to.\n * @param {Object} src - serialized data to copy from.\n */\n deserializeTopic(topic, src) {\n DB.#deserializeTopic(topic, src);\n }\n\n // Users.\n /**\n * Add or update user object in the persistent cache.\n * @memberOf DB\n * @param {string} uid - ID of the user to save or update.\n * @param {Object} pub - user's public information.\n * @returns {Promise} promise resolved/rejected on operation completion.\n */\n updUser(uid, pub) {\n if (arguments.length < 2 || pub === undefined) {\n // No point inupdating user with invalid data.\n return;\n }\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['user'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updUser', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('user').put({\n uid: uid,\n public: pub\n });\n trx.commit();\n });\n }\n\n /**\n * Remove user from persistent cache.\n * @memberOf DB\n * @param {string} uid - ID of the user to remove from the cache.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n remUser(uid) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['user'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'remUser', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('user').delete(IDBKeyRange.only(uid));\n trx.commit();\n });\n }\n\n /**\n * Execute a callback for each stored user.\n * @memberOf DB\n * @param {function} callback - function to call for each topic.\n * @param {Object} context - the value or this inside the callback.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n mapUsers(callback, context) {\n return this.#mapObjects('user', callback, context);\n }\n\n /**\n * Read a single user from persistent cache.\n * @memberOf DB\n * @param {string} uid - ID of the user to fetch from cache.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n getUser(uid) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['user']);\n trx.oncomplete = event => {\n const user = event.target.result;\n resolve({\n user: user.uid,\n public: user.public\n });\n };\n trx.onerror = event => {\n this.#logger('PCache', 'getUser', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('user').get(uid);\n });\n }\n\n // Subscriptions.\n /**\n * Add or update subscription in persistent cache.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {string} uid - ID of the subscribed user.\n * @param {Object} sub - subscription to save.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n updSubscription(topicName, uid, sub) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['subscription'], 'readwrite');\n trx.oncomplete = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updSubscription', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('subscription').get([topicName, uid]).onsuccess = (event) => {\n trx.objectStore('subscription').put(DB.#serializeSubscription(event.target.result, topicName, uid, sub));\n trx.commit();\n };\n });\n }\n\n /**\n * Execute a callback for each cached subscription in a given topic.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the subscriptions.\n * @param {function} callback - function to call for each subscription.\n * @param {Object} context - the value or this inside the callback.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n mapSubscriptions(topicName, callback, context) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['subscription']);\n trx.onerror = (event) => {\n this.#logger('PCache', 'mapSubscriptions', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('subscription').getAll(IDBKeyRange.bound([topicName, '-'], [topicName, '~'])).onsuccess = (event) => {\n if (callback) {\n event.target.result.forEach((topic) => {\n callback.call(context, topic);\n });\n }\n resolve(event.target.result);\n };\n });\n }\n\n // Messages.\n\n /**\n * Save message to persistent cache.\n * @memberOf DB\n * @param {Object} msg - message to save.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n addMessage(msg) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['message'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'addMessage', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('message').add(DB.#serializeMessage(null, msg));\n trx.commit();\n });\n }\n\n /**\n * Update delivery status of a message stored in persistent cache.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {number} seq - ID of the message to update\n * @param {number} status - new delivery status of the message.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n updMessageStatus(topicName, seq, status) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['message'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'updMessageStatus', event.target.error);\n reject(event.target.error);\n };\n const req = trx.objectStore('message').get(IDBKeyRange.only([topicName, seq]));\n req.onsuccess = event => {\n const src = req.result || event.target.result;\n if (!src || src._status == status) {\n trx.commit();\n return;\n }\n trx.objectStore('message').put(DB.#serializeMessage(src, {\n topic: topicName,\n seq: seq,\n _status: status\n }));\n trx.commit();\n };\n });\n }\n\n /**\n * Remove one or more messages from persistent cache.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {number} from - id of the message to remove or lower boundary when removing range (inclusive).\n * @param {number=} to - upper boundary (exclusive) when removing a range of messages.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n remMessages(topicName, from, to) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n if (!from && !to) {\n from = 0;\n to = Number.MAX_SAFE_INTEGER;\n }\n const range = to > 0 ? IDBKeyRange.bound([topicName, from], [topicName, to], false, true) :\n IDBKeyRange.only([topicName, from]);\n const trx = this.db.transaction(['message'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'remMessages', event.target.error);\n reject(event.target.error);\n };\n trx.objectStore('message').delete(range);\n trx.commit();\n });\n }\n\n /**\n * Retrieve messages from persistent store.\n * @memberOf DB\n * @param {string} topicName - name of the topic to retrieve messages from.\n * @param {function} callback to call for each retrieved message.\n * @param {GetDataType} query - parameters of the message range to retrieve.\n *\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n readMessages(topicName, query, callback, context) {\n query = query || {};\n\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n const trx = this.db.transaction(['message']);\n let result = [];\n\n // Handle individual message ranges.\n if (Array.isArray(query.ranges)) {\n return new Promise((resolve, reject) => {\n trx.onerror = event => {\n this.#logger('PCache', 'readMessages', event.target.error);\n reject(event.target.error);\n };\n\n let count = 0;\n query.ranges.forEach(range => {\n const key = range.hi ? IDBKeyRange.bound([topicName, range.low], [topicName, range.hi], false, true) :\n IDBKeyRange.only([topicName, range.low]);\n trx.objectStore('message').getAll(key).onsuccess = event => {\n const msgs = event.target.result;\n if (msgs) {\n if (callback) {\n callback.call(context, msgs);\n }\n if (Array.isArray(msgs)) {\n result = result.concat(msgs);\n } else {\n result.push(msgs);\n }\n }\n count++;\n if (count == query.ranges.length) {\n resolve(result);\n }\n };\n });\n });\n }\n\n // Handle single range.\n return new Promise((resolve, reject) => {\n const since = query.since > 0 ? query.since : 0;\n const before = query.before > 0 ? query.before : Number.MAX_SAFE_INTEGER;\n const limit = query.limit | 0;\n\n trx.onerror = event => {\n this.#logger('PCache', 'readMessages', event.target.error);\n reject(event.target.error);\n };\n\n const range = IDBKeyRange.bound([topicName, since], [topicName, before], false, true);\n // Iterate in descending order.\n trx.objectStore('message').openCursor(range, 'prev')\n .onsuccess = event => {\n const cursor = event.target.result;\n if (cursor) {\n if (callback) {\n callback.call(context, cursor.value);\n }\n result.push(cursor.value);\n if (limit <= 0 || result.length < limit) {\n cursor.continue();\n } else {\n resolve(result);\n }\n } else {\n resolve(result);\n }\n };\n });\n }\n\n // Delete log\n\n /**\n * Add records of deleted messages.\n * @memberOf DB\n * @param {string} topicName - name of the topic which owns the message.\n * @param {number} delId - id of the deletion transaction.\n * @param {Array.} ranges - message to save.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n addDelLog(topicName, delId, ranges) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve() :\n Promise.reject(new Error(\"not initialized\"));\n }\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['dellog'], 'readwrite');\n trx.onsuccess = event => {\n resolve(event.target.result);\n };\n trx.onerror = event => {\n this.#logger('PCache', 'addDelLog', event.target.error);\n reject(event.target.error);\n };\n ranges.forEach(r => trx.objectStore('dellog').add({\n topic: topicName,\n clear: delId,\n low: r.low,\n hi: r.hi || (r.low + 1)\n }));\n trx.commit();\n });\n }\n\n /**\n * Retrieve deleted message records from persistent store.\n * @memberOf DB\n * @param {string} topicName - name of the topic to retrieve records for.\n * @param {GetDataType} query - parameters of the message range to retrieve.\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n readDelLog(topicName, query) {\n query = query || {};\n\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve([]) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n const trx = this.db.transaction(['dellog']);\n let result = [];\n\n // Handle individual message ranges.\n if (Array.isArray(query.ranges)) {\n return new Promise((resolve, reject) => {\n trx.onerror = event => {\n this.#logger('PCache', 'readDelLog', event.target.error);\n reject(event.target.error);\n };\n\n let count = 0;\n query.ranges.forEach(range => {\n const hi = range.hi || (range.low + 1);\n const key = IDBKeyRange.bound([topicName, 0, range.low], [topicName, hi, Number.MAX_SAFE_INTEGER], false, true);\n trx.objectStore('dellog').getAll(key).onsuccess = event => {\n const entries = event.target.result;\n if (entries) {\n if (Array.isArray(entries)) {\n result = result.concat(entries.map(entry => {\n return {\n low: entry.low,\n hi: entry.hi\n };\n }));\n } else {\n result.push({\n low: entries.low,\n hi: entries.hi\n });\n }\n }\n count++;\n if (count == query.ranges.length) {\n resolve(result);\n }\n };\n });\n });\n }\n\n return new Promise((resolve, reject) => {\n const since = query.since > 0 ? query.since : 0;\n const before = query.before > 0 ? query.before : Number.MAX_SAFE_INTEGER;\n const limit = query.limit | 0;\n\n trx.onerror = event => {\n this.#logger('PCache', 'readDelLog', event.target.error);\n reject(event.target.error);\n };\n\n let count = 0;\n const result = [];\n const range = IDBKeyRange.bound([topicName, 0, since], [topicName, before, Number.MAX_SAFE_INTEGER], false, true);\n trx.objectStore('dellog').openCursor(range, 'prev')\n .onsuccess = event => {\n const cursor = event.target.result;\n if (cursor) {\n result.push({\n low: cursor.value.low,\n hi: cursor.value.hi\n });\n count += cursor.value.hi - cursor.value.low;\n if (limit <= 0 || count < limit) {\n cursor.continue();\n } else {\n resolve(result);\n }\n } else {\n resolve(result);\n }\n };\n });\n }\n\n /**\n * Retrieve the latest 'clear' ID for the given topic.\n * @param {string} topicName\n * @return {Promise} promise resolved/rejected on operation completion.\n */\n maxDelId(topicName) {\n if (!this.isReady()) {\n return this.disabled ?\n Promise.resolve(0) :\n Promise.reject(new Error(\"not initialized\"));\n }\n\n return new Promise((resolve, reject) => {\n const trx = this.db.transaction(['dellog']);\n trx.onerror = event => {\n this.#logger('PCache', 'maxDelId', event.target.error);\n reject(event.target.error);\n };\n\n const index = trx.objectStore('dellog').index('topic_clear');\n index.openCursor(IDBKeyRange.bound([topicName, 0], [topicName, Number.MAX_SAFE_INTEGER]), 'prev')\n .onsuccess = event => {\n if (event.target.result) {\n resolve(event.target.result.value);\n }\n };\n });\n }\n\n // Private methods.\n\n // Serializable topic fields.\n static #topic_fields = ['created', 'updated', 'deleted', 'touched', 'read', 'recv', 'seq',\n 'clear', 'defacs', 'creds', 'public', 'trusted', 'private', '_aux', '_deleted'\n ];\n\n // Copy data from src to Topic object.\n static #deserializeTopic(topic, src) {\n DB.#topic_fields.forEach((f) => {\n if (src.hasOwnProperty(f)) {\n topic[f] = src[f];\n }\n });\n if (Array.isArray(src.tags)) {\n topic._tags = src.tags;\n }\n if (src.acs) {\n topic.setAccessMode(src.acs);\n }\n topic.seq |= 0;\n topic.read |= 0;\n topic.unread = Math.max(0, topic.seq - topic.read);\n }\n\n // Copy values from 'src' to 'dst'. Allocate dst if it's null or undefined.\n static #serializeTopic(dst, src) {\n const res = dst || {\n name: src.name\n };\n DB.#topic_fields.forEach(f => {\n if (src.hasOwnProperty(f)) {\n res[f] = src[f];\n }\n });\n if (Array.isArray(src._tags)) {\n res.tags = src._tags;\n }\n if (src.acs) {\n res.acs = src.getAccessMode().jsonHelper();\n }\n return res;\n }\n\n static #serializeSubscription(dst, topicName, uid, sub) {\n const fields = ['updated', 'mode', 'read', 'recv', 'clear', 'lastSeen', 'userAgent'];\n const res = dst || {\n topic: topicName,\n uid: uid\n };\n\n fields.forEach((f) => {\n if (sub.hasOwnProperty(f)) {\n res[f] = sub[f];\n }\n });\n\n return res;\n }\n\n static #serializeMessage(dst, msg) {\n // Serializable fields.\n const fields = ['topic', 'seq', 'ts', '_status', 'from', 'head', 'content'];\n const res = dst || {};\n fields.forEach((f) => {\n if (msg.hasOwnProperty(f)) {\n res[f] = msg[f];\n }\n });\n return res;\n }\n\n /**\n * To use DB in a non browser context, supply indexedDB provider.\n * @static\n * @memberof DB\n * @param idbProvider indexedDB provider, e.g. for node require('fake-indexeddb').\n */\n static setDatabaseProvider(idbProvider) {\n IDBProvider = idbProvider;\n }\n}\n","/**\n * @file Utilities for uploading and downloading files.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport CommError from './comm-error.js';\nimport {\n isUrlRelative,\n jsonParseHelper\n} from './utils.js';\n\nlet XHRProvider;\n\nfunction addURLParam(relUrl, key, value) {\n const url = new URL(relUrl, window.location.origin);\n url.searchParams.append(key, value);\n return url.toString().substring(window.location.origin.length);\n}\n\n/**\n * @class LargeFileHelper - utilities for uploading and downloading files out of band.\n * Don't instantiate this class directly. Use {Tinode.getLargeFileHelper} instead.\n * @memberof Tinode\n *\n * @param {Tinode} tinode - the main Tinode object.\n * @param {string} version - protocol version, i.e. '0'.\n */\nexport default class LargeFileHelper {\n constructor(tinode, version) {\n this._tinode = tinode;\n this._version = version;\n\n this._apiKey = tinode._apiKey;\n this._authToken = tinode.getAuthToken();\n\n // Ongoing requests.\n this.xhr = [];\n }\n\n /**\n * Start uploading the file to an endpoint at baseUrl.\n *\n * @memberof Tinode.LargeFileHelper#\n *\n * @param {string} baseUrl base URL of upload server.\n * @param {File|Blob} data data to upload.\n * @param {string} avatarFor topic name if the upload represents an avatar.\n * @param {Callback} onProgress callback. Takes one {float} parameter 0..1\n * @param {Callback} onSuccess callback. Called when the file is successfully uploaded.\n * @param {Callback} onFailure callback. Called in case of a failure.\n *\n * @returns {Promise} resolved/rejected when the upload is completed/failed.\n */\n uploadWithBaseUrl(baseUrl, data, avatarFor, onProgress, onSuccess, onFailure) {\n let url = `/v${this._version}/file/u/`;\n if (baseUrl) {\n let base = baseUrl;\n if (base.endsWith('/')) {\n // Removing trailing slash.\n base = base.slice(0, -1);\n }\n if (base.startsWith('http://') || base.startsWith('https://')) {\n url = base + url;\n } else {\n throw new Error(`Invalid base URL '${baseUrl}'`);\n }\n }\n\n const instance = this;\n const xhr = new XHRProvider();\n this.xhr.push(xhr);\n\n xhr.open('POST', url, true);\n xhr.setRequestHeader('X-Tinode-APIKey', this._apiKey);\n if (this._authToken) {\n xhr.setRequestHeader('X-Tinode-Auth', `Token ${this._authToken.token}`);\n }\n\n let toResolve = null;\n let toReject = null;\n\n const result = new Promise((resolve, reject) => {\n toResolve = resolve;\n toReject = reject;\n });\n\n xhr.upload.onprogress = e => {\n if (e.lengthComputable) {\n if (onProgress) {\n onProgress(e.loaded / e.total);\n }\n if (this.onProgress) {\n this.onProgress(e.loaded / e.total);\n }\n }\n };\n\n xhr.onload = function() {\n let pkt;\n try {\n pkt = JSON.parse(this.response, jsonParseHelper);\n } catch (err) {\n instance._tinode.logger(\"ERROR: Invalid server response in LargeFileHelper\", this.response);\n pkt = {\n ctrl: {\n code: this.status,\n text: this.statusText\n }\n };\n }\n\n if (this.status >= 200 && this.status < 300) {\n if (toResolve) {\n toResolve(pkt.ctrl.params.url);\n }\n if (onSuccess) {\n onSuccess(pkt.ctrl);\n }\n } else if (this.status >= 400) {\n if (toReject) {\n toReject(new CommError(pkt.ctrl.text, pkt.ctrl.code));\n }\n if (onFailure) {\n onFailure(pkt.ctrl);\n }\n } else {\n instance._tinode.logger(\"ERROR: Unexpected server response status\", this.status, this.response);\n }\n };\n\n xhr.onerror = function(e) {\n if (toReject) {\n toReject(e || new Error(\"failed\"));\n }\n if (onFailure) {\n onFailure(null);\n }\n };\n\n xhr.onabort = function(e) {\n if (toReject) {\n toReject(new Error(\"upload cancelled by user\"));\n }\n if (onFailure) {\n onFailure(null);\n }\n };\n\n try {\n const form = new FormData();\n form.append('file', data);\n form.set('id', this._tinode.getNextUniqueId());\n if (avatarFor) {\n form.set('topic', avatarFor);\n }\n xhr.send(form);\n } catch (err) {\n if (toReject) {\n toReject(err);\n }\n if (onFailure) {\n onFailure(null);\n }\n }\n\n return result;\n }\n /**\n * Start uploading the file to default endpoint.\n *\n * @memberof Tinode.LargeFileHelper#\n *\n * @param {File|Blob} data to upload\n * @param {string} avatarFor topic name if the upload represents an avatar.\n * @param {Callback} onProgress callback. Takes one {float} parameter 0..1\n * @param {Callback} onSuccess callback. Called when the file is successfully uploaded.\n * @param {Callback} onFailure callback. Called in case of a failure.\n *\n * @returns {Promise} resolved/rejected when the upload is completed/failed.\n */\n upload(data, avatarFor, onProgress, onSuccess, onFailure) {\n const baseUrl = (this._tinode._secure ? 'https://' : 'http://') + this._tinode._host;\n return this.uploadWithBaseUrl(baseUrl, data, avatarFor, onProgress, onSuccess, onFailure);\n }\n /**\n * Download the file from a given URL using GET request. This method works with the Tinode server only.\n *\n * @memberof Tinode.LargeFileHelper#\n *\n * @param {string} relativeUrl - URL to download the file from. Must be relative url, i.e. must not contain the host.\n * @param {string=} filename - file name to use for the downloaded file.\n *\n * @returns {Promise} resolved/rejected when the download is completed/failed.\n */\n download(relativeUrl, filename, mimetype, onProgress, onError) {\n if (!isUrlRelative(relativeUrl)) {\n // As a security measure refuse to download from an absolute URL.\n if (onError) {\n onError(`The URL '${relativeUrl}' must be relative, not absolute`);\n }\n return;\n }\n if (!this._authToken) {\n if (onError) {\n onError(\"Must authenticate first\");\n }\n return;\n }\n const instance = this;\n\n const xhr = new XHRProvider();\n this.xhr.push(xhr);\n\n // Add '&asatt=1' to URL to request 'Content-Disposition: attachment' response header.\n relativeUrl = addURLParam(relativeUrl, 'asatt', '1');\n\n // Get data as blob (stored by the browser as a temporary file).\n xhr.open('GET', relativeUrl, true);\n xhr.setRequestHeader('X-Tinode-APIKey', this._apiKey);\n xhr.setRequestHeader('X-Tinode-Auth', 'Token ' + this._authToken.token);\n xhr.responseType = 'blob';\n\n xhr.onprogress = function(e) {\n if (onProgress) {\n // Passing e.loaded instead of e.loaded/e.total because e.total\n // is always 0 with gzip compression enabled by the server.\n onProgress(e.loaded);\n }\n };\n\n let toResolve = null;\n let toReject = null;\n\n const result = new Promise((resolve, reject) => {\n toResolve = resolve;\n toReject = reject;\n });\n\n // The blob needs to be saved as file. There is no known way to\n // save the blob as file other than to fake a click on an .\n xhr.onload = function() {\n if (this.status == 200) {\n const link = document.createElement('a');\n // URL.createObjectURL is not available in non-browser environment. This call will fail.\n link.href = window.URL.createObjectURL(new Blob([this.response], {\n type: mimetype\n }));\n link.style.display = 'none';\n link.setAttribute('download', filename);\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n window.URL.revokeObjectURL(link.href);\n if (toResolve) {\n toResolve();\n }\n } else if (this.status >= 400 && toReject) {\n // The this.responseText is undefined, must use this.response which is a blob.\n // Need to convert this.response to JSON. The blob can only be accessed by the\n // FileReader.\n const reader = new FileReader();\n reader.onload = function() {\n try {\n const pkt = JSON.parse(this.result, jsonParseHelper);\n toReject(new CommError(pkt.ctrl.text, pkt.ctrl.code));\n } catch (err) {\n instance._tinode.logger(\"ERROR: Invalid server response in LargeFileHelper\", this.result);\n toReject(err);\n }\n };\n reader.readAsText(this.response);\n }\n };\n\n xhr.onerror = function(e) {\n if (toReject) {\n toReject(new Error(\"failed\"));\n }\n if (onError) {\n onError(e);\n }\n };\n\n xhr.onabort = function() {\n if (toReject) {\n toReject(null);\n }\n };\n\n try {\n xhr.send();\n } catch (err) {\n if (toReject) {\n toReject(err);\n }\n if (onError) {\n onError(err);\n }\n }\n\n return result;\n }\n /**\n * Try to cancel all ongoing uploads or downloads.\n * @memberof Tinode.LargeFileHelper#\n */\n cancel() {\n this.xhr.forEach(req => {\n if (req.readyState < 4) {\n req.abort();\n }\n });\n }\n /**\n * To use LargeFileHelper in a non browser context, supply XMLHttpRequest provider.\n * @static\n * @memberof LargeFileHelper\n * @param xhrProvider XMLHttpRequest provider, e.g. for node require('xhr').\n */\n static setNetworkProvider(xhrProvider) {\n XHRProvider = xhrProvider;\n }\n}\n","/**\n * @module tinode-sdk\n *\n * @copyright 2015-2025 Tinode LLC.\n * @summary Javascript bindings for Tinode.\n * @license Apache 2.0\n * @version 0.24\n *\n * See https://github.com/tinode/webapp for real-life usage.\n *\n * @example\n * \n * \n * \n *\n * \n * ...\n * \n * \n */\n'use strict';\n\n// NOTE TO DEVELOPERS:\n// Localizable strings should be double quoted \"строка на другом языке\",\n// non-localizable strings should be single quoted 'non-localized'.\n\nimport AccessMode from './access-mode.js';\nimport * as Const from './config.js';\nimport CommError from './comm-error.js';\nimport Connection from './connection.js';\nimport DBCache from './db.js';\nimport Drafty from './drafty.js';\nimport LargeFileHelper from './large-file.js';\nimport MetaGetBuilder from './meta-builder.js';\nimport Topic from './topic.js';\nimport TopicFnd from './fnd-topic.js';\nimport TopicMe from './me-topic.js';\n\nimport {\n isUrlRelative,\n jsonParseHelper,\n mergeObj,\n rfc3339DateString,\n simplify\n} from './utils.js';\n\n// Re-export AccessMode\nexport {\n AccessMode\n};\n\nlet WebSocketProvider;\nif (typeof WebSocket != 'undefined') {\n WebSocketProvider = WebSocket;\n}\n\nlet XHRProvider;\nif (typeof XMLHttpRequest != 'undefined') {\n XHRProvider = XMLHttpRequest;\n}\n\nlet IndexedDBProvider;\nif (typeof indexedDB != 'undefined') {\n IndexedDBProvider = indexedDB;\n}\n\n// Re-export Drafty.\nexport {\n Drafty\n}\n\ninitForNonBrowserApp();\n\n// Utility functions\n\n// Polyfill for non-browser context, e.g. NodeJs.\nfunction initForNonBrowserApp() {\n // Tinode requirement in native mode because react native doesn't provide Base64 method\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n\n if (typeof btoa == 'undefined') {\n global.btoa = function(input = '') {\n let str = input;\n let output = '';\n\n for (let block = 0, charCode, i = 0, map = chars; str.charAt(i | 0) || (map = '=', i % 1); output += map.charAt(63 & block >> 8 - i % 1 * 8)) {\n\n charCode = str.charCodeAt(i += 3 / 4);\n\n if (charCode > 0xFF) {\n throw new Error(\"'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.\");\n }\n block = block << 8 | charCode;\n }\n\n return output;\n };\n }\n\n if (typeof atob == 'undefined') {\n global.atob = function(input = '') {\n let str = input.replace(/=+$/, '');\n let output = '';\n\n if (str.length % 4 == 1) {\n throw new Error(\"'atob' failed: The string to be decoded is not correctly encoded.\");\n }\n for (let bc = 0, bs = 0, buffer, i = 0; buffer = str.charAt(i++);\n\n ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,\n bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0\n ) {\n buffer = chars.indexOf(buffer);\n }\n\n return output;\n };\n }\n\n if (typeof window == 'undefined') {\n global.window = {\n WebSocket: WebSocketProvider,\n XMLHttpRequest: XHRProvider,\n indexedDB: IndexedDBProvider,\n URL: {\n createObjectURL: function() {\n throw new Error(\"Unable to use URL.createObjectURL in a non-browser application\");\n }\n }\n }\n }\n\n Connection.setNetworkProviders(WebSocketProvider, XHRProvider);\n LargeFileHelper.setNetworkProvider(XHRProvider);\n DBCache.setDatabaseProvider(IndexedDBProvider);\n}\n\n// Detect find most useful network transport.\nfunction detectTransport() {\n if (typeof window == 'object') {\n if (window['WebSocket']) {\n return 'ws';\n } else if (window['XMLHttpRequest']) {\n // The browser or node has no websockets, using long polling.\n return 'lp';\n }\n }\n return null;\n}\n\n// btoa replacement. Stock btoa fails on on non-Latin1 strings.\nfunction b64EncodeUnicode(str) {\n // The encodeURIComponent percent-encodes UTF-8 string,\n // then the percent encoding is converted into raw bytes which\n // can be fed into btoa.\n return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,\n function toSolidBytes(match, p1) {\n return String.fromCharCode('0x' + p1);\n }));\n}\n\n// JSON stringify helper - pre-processor for JSON.stringify\nfunction jsonBuildHelper(key, val) {\n if (val instanceof Date) {\n // Convert javascript Date objects to rfc3339 strings\n val = rfc3339DateString(val);\n } else if (val instanceof AccessMode) {\n val = val.jsonHelper();\n } else if (val === undefined || val === null || val === false ||\n (Array.isArray(val) && val.length == 0) ||\n ((typeof val == 'object') && (Object.keys(val).length == 0))) {\n // strip out empty elements while serializing objects to JSON\n return undefined;\n }\n\n return val;\n};\n\n// Trims very long strings (encoded images) to make logged packets more readable.\nfunction jsonLoggerHelper(key, val) {\n if (typeof val == 'string' && val.length > 128) {\n return '<' + val.length + ', bytes: ' + val.substring(0, 12) + '...' + val.substring(val.length - 12) + '>';\n }\n return jsonBuildHelper(key, val);\n};\n\n// Parse browser user agent to extract browser name and version.\nfunction getBrowserInfo(ua, product) {\n ua = ua || '';\n let reactnative = '';\n // Check if this is a ReactNative app.\n if (/reactnative/i.test(product)) {\n reactnative = 'ReactNative; ';\n }\n let result;\n // Remove useless string.\n ua = ua.replace(' (KHTML, like Gecko)', '');\n // Test for WebKit-based browser.\n let m = ua.match(/(AppleWebKit\\/[.\\d]+)/i);\n if (m) {\n // List of common strings, from more useful to less useful.\n // All unknown strings get the highest (-1) priority.\n const priority = ['edg', 'chrome', 'safari', 'mobile', 'version'];\n let tmp = ua.substr(m.index + m[0].length).split(' ');\n let tokens = [];\n let version; // 1.0 in Version/1.0 or undefined;\n // Split string like 'Name/0.0.0' into ['Name', '0.0.0', 3] where the last element is the priority.\n for (let i = 0; i < tmp.length; i++) {\n let m2 = /([\\w.]+)[\\/]([\\.\\d]+)/.exec(tmp[i]);\n if (m2) {\n // Unknown values are highest priority (-1).\n tokens.push([m2[1], m2[2], priority.findIndex((e) => {\n return m2[1].toLowerCase().startsWith(e);\n })]);\n if (m2[1] == 'Version') {\n version = m2[2];\n }\n }\n }\n // Sort by priority: more interesting is earlier than less interesting.\n tokens.sort((a, b) => {\n return a[2] - b[2];\n });\n if (tokens.length > 0) {\n // Return the least common browser string and version.\n if (tokens[0][0].toLowerCase().startsWith('edg')) {\n tokens[0][0] = 'Edge';\n } else if (tokens[0][0] == 'OPR') {\n tokens[0][0] = 'Opera';\n } else if (tokens[0][0] == 'Safari' && version) {\n tokens[0][1] = version;\n }\n result = tokens[0][0] + '/' + tokens[0][1];\n } else {\n // Failed to ID the browser. Return the webkit version.\n result = m[1];\n }\n } else if (/firefox/i.test(ua)) {\n m = /Firefox\\/([.\\d]+)/g.exec(ua);\n if (m) {\n result = 'Firefox/' + m[1];\n } else {\n result = 'Firefox/?';\n }\n } else {\n // Neither AppleWebKit nor Firefox. Try the last resort.\n m = /([\\w.]+)\\/([.\\d]+)/.exec(ua);\n if (m) {\n result = m[1] + '/' + m[2];\n } else {\n m = ua.split(' ');\n result = m[0];\n }\n }\n\n // Shorten the version to one dot 'a.bb.ccc.d -> a.bb' at most.\n m = result.split('/');\n if (m.length > 1) {\n const v = m[1].split('.');\n const minor = v[1] ? '.' + v[1].substr(0, 2) : '';\n result = `${m[0]}/${v[0]}${minor}`;\n }\n return reactnative + result;\n}\n\n/**\n * The main class for interacting with Tinode server.\n */\nexport class Tinode {\n _host;\n _secure;\n\n _appName;\n\n // API Key.\n _apiKey;\n\n // Name and version of the browser.\n _browser = '';\n _platform;\n // Hardware\n _hwos = 'undefined';\n _humanLanguage = 'xx';\n\n // Logging to console enabled\n _loggingEnabled = false;\n // When logging, trip long strings (base64-encoded images) for readability\n _trimLongStrings = false;\n // UID of the currently authenticated user.\n _myUID = null;\n // Status of connection: authenticated or not.\n _authenticated = false;\n // Login used in the last successful basic authentication\n _login = null;\n // Token which can be used for login instead of login/password.\n _authToken = null;\n // Counter of received packets\n _inPacketCount = 0;\n // Counter for generating unique message IDs\n _messageId = Math.floor((Math.random() * 0xFFFF) + 0xFFFF);\n // Information about the server, if connected\n _serverInfo = null;\n // Push notification token. Called deviceToken for consistency with the Android SDK.\n _deviceToken = null;\n\n // Cache of pending promises by message id.\n _pendingPromises = {};\n // The Timeout object returned by the reject expired promises setInterval.\n _expirePromises = null;\n\n // Websocket or long polling connection.\n _connection = null;\n\n // Use indexDB for caching topics and messages.\n _persist = false;\n // IndexedDB wrapper object.\n _db = null;\n\n // Tinode's cache of objects\n _cache = {};\n\n /**\n * Create Tinode object.\n *\n * @param {Object} config - configuration parameters.\n * @param {string} config.appName - Name of the calling application to be reported in the User Agent.\n * @param {string} config.host - Host name and optional port number to connect to.\n * @param {string} config.apiKey - API key generated by keygen.\n * @param {string} config.transport - See {@link Tinode.Connection#transport}.\n * @param {boolean} config.secure - Use Secure WebSocket if true.\n * @param {string} config.platform - Optional platform identifier, one of \"ios\", \"web\", \"android\".\n * @param {boolen} config.persist - Use IndexedDB persistent storage.\n * @param {function} onComplete - callback to call when initialization is completed.\n */\n constructor(config, onComplete) {\n this._host = config.host;\n this._secure = config.secure;\n\n // Client-provided application name, format /\n this._appName = config.appName || \"Undefined\";\n\n // API Key.\n this._apiKey = config.apiKey;\n\n // Name and version of the browser.\n this._platform = config.platform || 'web';\n // Underlying OS.\n if (typeof navigator != 'undefined') {\n this._browser = getBrowserInfo(navigator.userAgent, navigator.product);\n this._hwos = navigator.platform;\n // This is the default language. It could be changed by client.\n this._humanLanguage = navigator.language || 'en-US';\n }\n\n Connection.logger = this.logger;\n Drafty.logger = this.logger;\n\n // WebSocket or long polling network connection.\n if (config.transport != 'lp' && config.transport != 'ws') {\n config.transport = detectTransport();\n }\n this._connection = new Connection(config, Const.PROTOCOL_VERSION, /* autoreconnect */ true);\n this._connection.onMessage = (data) => {\n // Call the main message dispatcher.\n this.#dispatchMessage(data);\n }\n\n // Ready to start sending.\n this._connection.onOpen = _ => this.#connectionOpen();\n this._connection.onDisconnect = (err, code) => this.#disconnected(err, code);\n\n // Wrapper for the reconnect iterator callback.\n this._connection.onAutoreconnectIteration = (timeout, promise) => {\n if (this.onAutoreconnectIteration) {\n this.onAutoreconnectIteration(timeout, promise);\n }\n }\n\n this._persist = config.persist;\n // Initialize object regardless. It simplifies the code.\n this._db = new DBCache(this.logger, this.logger);\n\n if (this._persist) {\n // Create the persistent cache.\n // Store promises to be resolved when messages load into memory.\n const prom = [];\n this._db.initDatabase().then(_ => {\n // First load topics into memory.\n return this._db.mapTopics(data => {\n let topic = this.#cacheGet('topic', data.name);\n if (topic) {\n return;\n }\n if (data.name == Const.TOPIC_ME) {\n topic = new TopicMe();\n } else if (data.name == Const.TOPIC_FND) {\n topic = new TopicFnd();\n } else {\n topic = new Topic(data.name);\n }\n this._db.deserializeTopic(topic, data);\n this.#attachCacheToTopic(topic);\n topic._cachePutSelf();\n this._db.maxDelId(topic.name).then(clear => {\n topic._maxDel = Math.max(topic._maxDel, clear || 0);\n });\n // Topic loaded from DB is not new.\n delete topic._new;\n // Request to load messages and save the promise.\n prom.push(topic._loadMessages(this._db));\n });\n }).then(_ => {\n // Then load users.\n return this._db.mapUsers((data) => {\n this.#cachePut('user', data.uid, mergeObj({}, data.public));\n });\n }).then(_ => {\n // Now wait for all messages to finish loading.\n return Promise.all(prom);\n }).then(_ => {\n if (onComplete) {\n onComplete();\n }\n this.logger(\"Persistent cache initialized.\");\n }).catch(err => {\n if (onComplete) {\n onComplete(err);\n }\n this.logger(\"Failed to initialize persistent cache:\", err);\n });\n } else {\n this._db.deleteDatabase().then(_ => {\n if (onComplete) {\n onComplete();\n }\n });\n }\n }\n\n // Private methods.\n\n // Console logger. Babel somehow fails to parse '...rest' parameter.\n logger(str, ...args) {\n if (this._loggingEnabled) {\n const d = new Date();\n const dateString = ('0' + d.getUTCHours()).slice(-2) + ':' +\n ('0' + d.getUTCMinutes()).slice(-2) + ':' +\n ('0' + d.getUTCSeconds()).slice(-2) + '.' +\n ('00' + d.getUTCMilliseconds()).slice(-3);\n\n console.log('[' + dateString + ']', str, args.join(' '));\n }\n }\n\n // Generator of default promises for sent packets.\n #makePromise(id) {\n let promise = null;\n if (id) {\n promise = new Promise((resolve, reject) => {\n // Stored callbacks will be called when the response packet with this Id arrives\n this._pendingPromises[id] = {\n 'resolve': resolve,\n 'reject': reject,\n 'ts': new Date()\n };\n });\n }\n return promise;\n };\n\n // Resolve or reject a pending promise.\n // Unresolved promises are stored in _pendingPromises.\n #execPromise(id, code, onOK, errorText) {\n const callbacks = this._pendingPromises[id];\n if (callbacks) {\n delete this._pendingPromises[id];\n if (code >= 200 && code < 400) {\n if (callbacks.resolve) {\n callbacks.resolve(onOK);\n }\n } else if (callbacks.reject) {\n callbacks.reject(new CommError(errorText, code));\n }\n }\n }\n\n // Send a packet. If packet id is provided return a promise.\n #send(pkt, id) {\n let promise;\n if (id) {\n promise = this.#makePromise(id);\n }\n pkt = simplify(pkt);\n let msg = JSON.stringify(pkt);\n this.logger(\"out: \" + (this._trimLongStrings ? JSON.stringify(pkt, jsonLoggerHelper) : msg));\n try {\n this._connection.sendText(msg);\n } catch (err) {\n // If sendText throws, wrap the error in a promise or rethrow.\n if (id) {\n this.#execPromise(id, Connection.NETWORK_ERROR, null, err.message);\n } else {\n throw err;\n }\n }\n return promise;\n }\n\n // The main message dispatcher.\n #dispatchMessage(data) {\n // Skip empty response. This happens when LP times out.\n if (!data)\n return;\n\n this._inPacketCount++;\n\n // Send raw message to listener\n if (this.onRawMessage) {\n this.onRawMessage(data);\n }\n\n if (data === '0') {\n // Server response to a network probe.\n if (this.onNetworkProbe) {\n this.onNetworkProbe();\n }\n // No processing is necessary.\n return;\n }\n\n let pkt = JSON.parse(data, jsonParseHelper);\n if (!pkt) {\n this.logger(\"in: \" + data);\n this.logger(\"ERROR: failed to parse data\");\n } else {\n this.logger(\"in: \" + (this._trimLongStrings ? JSON.stringify(pkt, jsonLoggerHelper) : data));\n\n // Send complete packet to listener\n if (this.onMessage) {\n this.onMessage(pkt);\n }\n\n if (pkt.ctrl) {\n // Handling {ctrl} message\n if (this.onCtrlMessage) {\n this.onCtrlMessage(pkt.ctrl);\n }\n\n // Resolve or reject a pending promise, if any\n if (pkt.ctrl.id) {\n this.#execPromise(pkt.ctrl.id, pkt.ctrl.code, pkt.ctrl, pkt.ctrl.text);\n }\n setTimeout(_ => {\n if (pkt.ctrl.code == 205 && pkt.ctrl.text == 'evicted') {\n // User evicted from topic.\n const topic = this.#cacheGet('topic', pkt.ctrl.topic);\n if (topic) {\n topic._resetSub();\n if (pkt.ctrl.params && pkt.ctrl.params.unsub) {\n topic._gone();\n }\n }\n } else if (pkt.ctrl.code < 300 && pkt.ctrl.params) {\n if (pkt.ctrl.params.what == 'data') {\n // code=208, all messages received: \"params\":{\"count\":11,\"what\":\"data\"},\n const topic = this.#cacheGet('topic', pkt.ctrl.topic);\n if (topic) {\n topic._allMessagesReceived(pkt.ctrl.params.count);\n }\n } else if (pkt.ctrl.params.what == 'sub') {\n // code=204, the topic has no (refreshed) subscriptions.\n const topic = this.#cacheGet('topic', pkt.ctrl.topic);\n if (topic) {\n // Trigger topic.onSubsUpdated.\n topic._processMetaSubs([]);\n }\n }\n }\n }, 0);\n } else {\n setTimeout(_ => {\n if (pkt.meta) {\n // Handling a {meta} message.\n // Preferred API: Route meta to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.meta.topic);\n if (topic) {\n topic._routeMeta(pkt.meta);\n }\n\n if (pkt.meta.id) {\n this.#execPromise(pkt.meta.id, 200, pkt.meta, 'META');\n }\n\n // Secondary API: callback\n if (this.onMetaMessage) {\n this.onMetaMessage(pkt.meta);\n }\n } else if (pkt.data) {\n // Handling {data} message\n // Preferred API: Route data to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.data.topic);\n if (topic) {\n topic._routeData(pkt.data);\n }\n\n // Secondary API: Call callback\n if (this.onDataMessage) {\n this.onDataMessage(pkt.data);\n }\n } else if (pkt.pres) {\n // Handling {pres} message\n // Preferred API: Route presence to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.pres.topic);\n if (topic) {\n topic._routePres(pkt.pres);\n }\n\n // Secondary API - callback\n if (this.onPresMessage) {\n this.onPresMessage(pkt.pres);\n }\n } else if (pkt.info) {\n // {info} message - read/received notifications and key presses\n // Preferred API: Route {info}} to topic, if one is registered\n const topic = this.#cacheGet('topic', pkt.info.topic);\n if (topic) {\n topic._routeInfo(pkt.info);\n }\n\n // Secondary API - callback\n if (this.onInfoMessage) {\n this.onInfoMessage(pkt.info);\n }\n } else {\n this.logger(\"ERROR: Unknown packet received.\");\n }\n }, 0);\n }\n }\n }\n\n // Connection open, ready to start sending.\n #connectionOpen() {\n if (!this._expirePromises) {\n // Reject promises which have not been resolved for too long.\n this._expirePromises = setInterval(_ => {\n const err = new CommError(\"timeout\", 504);\n const expires = new Date(new Date().getTime() - Const.EXPIRE_PROMISES_TIMEOUT);\n for (let id in this._pendingPromises) {\n let callbacks = this._pendingPromises[id];\n if (callbacks && callbacks.ts < expires) {\n this.logger(\"Promise expired\", id);\n delete this._pendingPromises[id];\n if (callbacks.reject) {\n callbacks.reject(err);\n }\n }\n }\n }, Const.EXPIRE_PROMISES_PERIOD);\n }\n this.hello();\n }\n\n #disconnected(err, code) {\n this._inPacketCount = 0;\n this._serverInfo = null;\n this._authenticated = false;\n\n if (this._expirePromises) {\n clearInterval(this._expirePromises);\n this._expirePromises = null;\n }\n\n // Mark all topics as unsubscribed\n this.#cacheMap('topic', (topic, key) => {\n topic._resetSub();\n });\n\n // Reject all pending promises\n for (let key in this._pendingPromises) {\n const callbacks = this._pendingPromises[key];\n if (callbacks && callbacks.reject) {\n callbacks.reject(err);\n }\n }\n this._pendingPromises = {};\n\n if (this.onDisconnect) {\n this.onDisconnect(err);\n }\n }\n\n // Get User Agent string\n #getUserAgent() {\n return this._appName + ' (' + (this._browser ? this._browser + '; ' : '') + this._hwos + '); ' + Const.LIBRARY;\n }\n\n // Generator of packets stubs\n #initPacket(type, topic) {\n switch (type) {\n case 'hi':\n return {\n 'hi': {\n 'id': this.getNextUniqueId(),\n 'ver': Const.VERSION,\n 'ua': this.#getUserAgent(),\n 'dev': this._deviceToken,\n 'lang': this._humanLanguage,\n 'platf': this._platform\n }\n };\n\n case 'acc':\n return {\n 'acc': {\n 'id': this.getNextUniqueId(),\n 'user': null,\n 'scheme': null,\n 'secret': null,\n 'tmpscheme': null,\n 'tmpsecret': null,\n 'login': false,\n 'tags': null,\n 'desc': {},\n 'cred': {}\n }\n };\n\n case 'login':\n return {\n 'login': {\n 'id': this.getNextUniqueId(),\n 'scheme': null,\n 'secret': null\n }\n };\n\n case 'sub':\n return {\n 'sub': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'set': {},\n 'get': {}\n }\n };\n\n case 'leave':\n return {\n 'leave': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'unsub': false\n }\n };\n\n case 'pub':\n return {\n 'pub': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'noecho': false,\n 'head': null,\n 'content': {}\n }\n };\n\n case 'get':\n return {\n 'get': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'what': null,\n 'desc': {},\n 'sub': {},\n 'data': {}\n }\n };\n\n case 'set':\n return {\n 'set': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'desc': {},\n 'sub': {},\n 'tags': [],\n 'aux': {}\n }\n };\n\n case 'del':\n return {\n 'del': {\n 'id': this.getNextUniqueId(),\n 'topic': topic,\n 'what': null,\n 'delseq': null,\n 'user': null,\n 'hard': false\n }\n };\n\n case 'note':\n return {\n 'note': {\n // no id by design (except calls).\n 'topic': topic,\n 'what': null, // one of \"recv\", \"read\", \"kp\", \"call\"\n 'seq': undefined // the server-side message id acknowledged as received or read.\n }\n };\n\n default:\n throw new Error(`Unknown packet type requested: ${type}`);\n }\n }\n\n // Cache management\n #cachePut(type, name, obj) {\n this._cache[type + ':' + name] = obj;\n }\n #cacheGet(type, name) {\n return this._cache[type + ':' + name];\n }\n #cacheDel(type, name) {\n delete this._cache[type + ':' + name];\n }\n\n // Enumerate all items in cache, call func for each item.\n // Enumeration stops if func returns true.\n #cacheMap(type, func, context) {\n const key = type ? type + ':' : undefined;\n for (let idx in this._cache) {\n if (!key || idx.indexOf(key) == 0) {\n if (func.call(context, this._cache[idx], idx)) {\n break;\n }\n }\n }\n }\n\n // Make limited cache management available to topic.\n // Caching user.public only. Everything else is per-topic.\n #attachCacheToTopic(topic) {\n topic._tinode = this;\n\n topic._cacheGetUser = (uid) => {\n const pub = this.#cacheGet('user', uid);\n if (pub) {\n return {\n user: uid,\n public: mergeObj({}, pub)\n };\n }\n return undefined;\n };\n topic._cachePutUser = (uid, user) => {\n this.#cachePut('user', uid, mergeObj({}, user.public));\n };\n topic._cacheDelUser = (uid) => {\n this.#cacheDel('user', uid);\n };\n topic._cachePutSelf = _ => {\n this.#cachePut('topic', topic.name, topic);\n };\n topic._cacheDelSelf = _ => {\n this.#cacheDel('topic', topic.name);\n };\n }\n\n // On successful login save server-provided data.\n #loginSuccessful(ctrl) {\n if (!ctrl.params || !ctrl.params.user) {\n return ctrl;\n }\n // This is a response to a successful login,\n // extract UID and security token, save it in Tinode module\n this._myUID = ctrl.params.user;\n this._authenticated = (ctrl && ctrl.code >= 200 && ctrl.code < 300);\n if (ctrl.params && ctrl.params.token && ctrl.params.expires) {\n this._authToken = {\n token: ctrl.params.token,\n expires: ctrl.params.expires\n };\n } else {\n this._authToken = null;\n }\n\n if (this.onLogin) {\n this.onLogin(ctrl.code, ctrl.text);\n }\n\n return ctrl;\n }\n\n // Static methods.\n /**\n * Helper method to package account credential.\n *\n * @param {string | Credential} meth - validation method or object with validation data.\n * @param {string=} val - validation value (e.g. email or phone number).\n * @param {Object=} params - validation parameters.\n * @param {string=} resp - validation response.\n *\n * @returns {Array.} array with a single credential or null if no valid credentials were given.\n */\n static credential(meth, val, params, resp) {\n if (typeof meth == 'object') {\n ({\n val,\n params,\n resp,\n meth\n } = meth);\n }\n if (meth && (val || resp)) {\n return [{\n 'meth': meth,\n 'val': val,\n 'resp': resp,\n 'params': params\n }];\n }\n return null;\n }\n\n /**\n * Determine topic type from topic's name: grp, p2p, me, fnd, sys.\n * @param {string} name - Name of the topic to test.\n * @returns {string} One of \"me\", \"fnd\", \"sys\", \"grp\",\n * \"p2p\" or undefined.\n */\n static topicType(name) {\n return Topic.topicType(name);\n }\n\n /**\n * Check if the given topic name is a name of a 'me' topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'me' topic, false otherwise.\n */\n static isMeTopicName(name) {\n return Topic.isMeTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a 'slf' topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'slf' topic, false otherwise.\n */\n static isSelfTopicName(name) {\n return Topic.isSelfTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a group topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a group topic, false otherwise.\n */\n static isGroupTopicName(name) {\n return Topic.isGroupTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a p2p topic.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p topic, false otherwise.\n */\n static isP2PTopicName(name) {\n return Topic.isP2PTopicName(name);\n }\n /**\n * Check if the given topic name is a name of a communication topic, i.e. P2P or group.\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p or group topic, false otherwise.\n */\n static isCommTopicName(name) {\n return Topic.isCommTopicName(name);\n }\n /**\n * Check if the topic name is a name of a new topic.\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a new topic, false otherwise.\n */\n static isNewGroupTopicName(name) {\n return Topic.isNewGroupTopicName(name);\n }\n /**\n * Check if the topic name is a name of a channel.\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a channel, false otherwise.\n */\n static isChannelTopicName(name) {\n return Topic.isChannelTopicName(name);\n }\n /**\n * Get information about the current version of this Tinode client library.\n * @returns {string} semantic version of the library, e.g. \"0.15.5-rc1\".\n */\n static getVersion() {\n return Const.VERSION;\n }\n /**\n * To use Tinode in a non browser context, supply WebSocket and XMLHttpRequest providers.\n * @static\n *\n * @param wsProvider WebSocket provider, e.g. for nodeJS , require('ws').\n * @param xhrProvider XMLHttpRequest provider, e.g. for node require('xhr').\n */\n static setNetworkProviders(wsProvider, xhrProvider) {\n WebSocketProvider = wsProvider;\n XHRProvider = xhrProvider;\n\n Connection.setNetworkProviders(WebSocketProvider, XHRProvider);\n LargeFileHelper.setNetworkProvider(XHRProvider);\n }\n /**\n * To use Tinode in a non browser context, supply indexedDB provider.\n * @static\n *\n * @param idbProvider indexedDB provider, e.g. for nodeJS , require('fake-indexeddb').\n */\n static setDatabaseProvider(idbProvider) {\n IndexedDBProvider = idbProvider;\n\n DBCache.setDatabaseProvider(IndexedDBProvider);\n }\n /**\n * Return information about the current name and version of this Tinode library.\n * @static\n *\n * @returns {string} the name of the library and it's version.\n */\n static getLibrary() {\n return Const.LIBRARY;\n }\n /**\n * Check if the given string represents NULL value as defined by Tinode ('\\u2421').\n * @param {string} str - string to check for NULL value.\n * @returns {boolean} true if string represents NULL value, false otherwise.\n */\n static isNullValue(str) {\n return str === Const.DEL_CHAR;\n }\n /**\n * Check if the given seq ID is likely to be issued by the server as oppisite to being temporary locally assigned ID.\n * @param {int} seq - seq ID to check.\n * @returns {boolean} true if seq is likely server-issued, false otherwise.\n */\n static isServerAssignedSeq(seq) {\n return seq > 0 && seq < Const.LOCAL_SEQID;\n }\n\n /**\n * Check if the given string is a valid tag value.\n * @param {string} tag - string to check.\n * @returns {boolean} true if the string is a valid tag value, false otherwise.\n */\n static isValidTagValue(tag) {\n // 4-24 characters, starting with letter or digit, then letters, digits, hyphen, underscore.\n const ALIAS_REGEX = /^[a-z0-9][a-z0-9_\\-]{3,23}$/i;\n return tag && typeof tag == 'string' && tag.length > 3 && tag.length < 24 && ALIAS_REGEX.test(tag);\n }\n\n /**\n * Split fully-qualified tag into prefix and value.\n */\n static tagSplit(tag) {\n if (!tag) {\n return null;\n }\n\n tag = tag.trim();\n\n const splitAt = tag.indexOf(':');\n if (splitAt <= 0) {\n // Invalid syntax.\n return null;\n }\n\n const value = tag.substring(splitAt + 1);\n if (!value) {\n return null;\n }\n return {\n prefix: tag.substring(0, splitAt),\n value: value\n };\n }\n\n /**\n * Set a unique namespace tag.\n * If the tag with this namespace is already present then it's replaced with the new tag.\n * @param uniqueTag tag to add, must be fully-qualified; if null or empty, no action is taken.\n */\n static setUniqueTag(tags, uniqueTag) {\n if (!tags || tags.length == 0) {\n // No tags, just add the new one.\n return [uniqueTag];\n }\n\n const parts = Tinode.tagSplit(uniqueTag)\n if (!parts) {\n // Invalid tag.\n return tags;\n }\n\n // Remove the old tag with the same prefix.\n tags = tags.filter(tag => tag && !tag.startsWith(parts.prefix));\n // Add the new tag.\n tags.push(uniqueTag);\n return tags;\n }\n\n /**\n * Remove a unique tag with the given prefix.\n * @param prefix prefix to remove\n */\n static clearTagPrefix(tags, prefix) {\n if (!tags || tags.length == 0) {\n return [];\n }\n return tags.filter(tag => tag && !tag.startsWith(prefix));\n }\n\n /**\n * Find the first tag with the given prefix.\n * @param prefix prefix to search for.\n * @return the first tag with the given prefix if found or undefined.\n */\n static tagByPrefix(tags, prefix) {\n if (!tags) {\n return undefined;\n }\n\n return tags.find(tag => tag && tag.startsWith(prefix));\n }\n\n // Instance methods.\n\n // Generates unique message IDs\n getNextUniqueId() {\n return (this._messageId != 0) ? '' + this._messageId++ : undefined;\n };\n\n /**\n * Connect to the server.\n *\n * @param {string} host_ - name of the host to connect to.\n * @return {Promise} Promise resolved/rejected when the connection call completes:\n * resolve() is called without parameters, reject() receives the\n * Error as a single parameter.\n */\n connect(host_) {\n return this._connection.connect(host_);\n }\n\n /**\n * Attempt to reconnect to the server immediately.\n *\n * @param {string} force - if true, reconnect even if there is a connection already.\n */\n reconnect(force) {\n this._connection.reconnect(force);\n }\n\n /**\n * Disconnect from the server.\n */\n disconnect() {\n this._connection.disconnect();\n }\n\n /**\n * Clear persistent cache: remove IndexedDB.\n *\n * @return {Promise} Promise resolved/rejected when the operation is completed.\n */\n clearStorage() {\n if (this._db.isReady()) {\n return this._db.deleteDatabase();\n }\n return Promise.resolve();\n }\n\n /**\n * Initialize persistent cache: create IndexedDB cache.\n *\n * @return {Promise} Promise resolved/rejected when the operation is completed.\n */\n initStorage() {\n if (!this._db.isReady()) {\n return this._db.initDatabase();\n }\n return Promise.resolve();\n }\n\n /**\n * Send a network probe message to make sure the connection is alive.\n */\n networkProbe() {\n this._connection.probe();\n }\n\n /**\n * Check for live connection to server.\n *\n * @returns {boolean} true if there is a live connection, false otherwise.\n */\n isConnected() {\n return this._connection.isConnected();\n }\n\n /**\n * Check if connection is authenticated (last login was successful).\n *\n * @returns {boolean} true if authenticated, false otherwise.\n */\n isAuthenticated() {\n return this._authenticated;\n }\n\n /**\n * Add API key and auth token to the relative URL making it usable for getting data\n * from the server in a simple HTTP GET request.\n *\n * @param {string} URL - URL to wrap.\n * @returns {string} URL with appended API key and token, if valid token is present.\n */\n authorizeURL(url) {\n if (typeof url != 'string') {\n return url;\n }\n\n if (isUrlRelative(url)) {\n // Fake base to make the relative URL parseable.\n const base = 'scheme://host/';\n const parsed = new URL(url, base);\n if (this._apiKey) {\n parsed.searchParams.append('apikey', this._apiKey);\n }\n if (this._authToken && this._authToken.token) {\n parsed.searchParams.append('auth', 'token');\n parsed.searchParams.append('secret', this._authToken.token);\n }\n // Convert back to string and strip fake base URL except for the root slash.\n url = parsed.toString().substring(base.length - 1);\n }\n return url;\n }\n\n /**\n * @typedef AccountParams\n * @type {Object}\n * @property {DefAcs=} defacs - Default access parameters for user's me topic.\n * @property {Object=} public - Public application-defined data exposed on me topic.\n * @property {Object=} private - Private application-defined data accessible on me topic.\n * @property {Object=} trusted - Trusted user data which can be set by a root user only.\n * @property {Array.} tags - array of string tags for user discovery.\n * @property {string} scheme - Temporary authentication scheme for password reset.\n * @property {string} secret - Temporary authentication secret for password reset.\n * @property {Array.=} attachments - Array of references to out of band attachments used in account description.\n */\n /**\n * @typedef DefAcs\n * @type {Object}\n * @property {string=} auth - Access mode for me for authenticated users.\n * @property {string=} anon - Access mode for me for anonymous users.\n */\n\n /**\n * Create or update an account.\n *\n * @param {string} uid - User id to update\n * @param {string} scheme - Authentication scheme; \"basic\" and \"anonymous\" are the currently supported schemes.\n * @param {string} secret - Authentication secret, assumed to be already base64 encoded.\n * @param {boolean=} login - Use new account to authenticate current session\n * @param {AccountParams=} params - User data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n account(uid, scheme, secret, login, params) {\n const pkt = this.#initPacket('acc');\n pkt.acc.user = uid;\n pkt.acc.scheme = scheme;\n pkt.acc.secret = secret;\n // Log in to the new account using selected scheme\n pkt.acc.login = login;\n\n if (params) {\n pkt.acc.desc.defacs = params.defacs;\n pkt.acc.desc.public = params.public;\n pkt.acc.desc.private = params.private;\n pkt.acc.desc.trusted = params.trusted;\n\n pkt.acc.tags = params.tags;\n pkt.acc.cred = params.cred;\n\n pkt.acc.tmpscheme = params.scheme;\n pkt.acc.tmpsecret = params.secret;\n\n if (Array.isArray(params.attachments) && params.attachments.length > 0) {\n pkt.extra = {\n attachments: params.attachments.filter(ref => isUrlRelative(ref))\n };\n }\n }\n\n return this.#send(pkt, pkt.acc.id);\n }\n\n /**\n * Create a new user. Wrapper for {@link Tinode#account}.\n *\n * @param {string} scheme - Authentication scheme; \"basic\" is the only currently supported scheme.\n * @param {string} secret - Authentication.\n * @param {boolean=} login - Use new account to authenticate current session\n * @param {AccountParams=} params - User data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n createAccount(scheme, secret, login, params) {\n let promise = this.account(Const.USER_NEW, scheme, secret, login, params);\n if (login) {\n promise = promise.then(ctrl => this.#loginSuccessful(ctrl));\n }\n return promise;\n }\n\n /**\n * Create user with 'basic' authentication scheme and immediately\n * use it for authentication. Wrapper for {@link Tinode#account}.\n *\n * @param {string} username - Login to use for the new account.\n * @param {string} password - User's password.\n * @param {AccountParams=} params - User data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n createAccountBasic(username, password, params) {\n // Make sure we are not using 'null' or 'undefined';\n username = username || '';\n password = password || '';\n return this.createAccount('basic',\n b64EncodeUnicode(username + ':' + password), true, params);\n }\n\n /**\n * Update user's credentials for 'basic' authentication scheme. Wrapper for {@link Tinode#account}.\n *\n * @param {string} uid - User ID to update.\n * @param {string} username - Login to use for the new account.\n * @param {string} password - User's password.\n * @param {AccountParams=} params - data to pass to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n updateAccountBasic(uid, username, password, params) {\n // Make sure we are not using 'null' or 'undefined';\n username = username || '';\n password = password || '';\n return this.account(uid, 'basic',\n b64EncodeUnicode(username + ':' + password), false, params);\n }\n\n /**\n * Send handshake to the server.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n hello() {\n const pkt = this.#initPacket('hi');\n\n return this.#send(pkt, pkt.hi.id)\n .then(ctrl => {\n // Reset backoff counter on successful connection.\n this._connection.backoffReset();\n\n // Server response contains server protocol version, build, constraints,\n // session ID for long polling. Save them.\n if (ctrl.params) {\n this._serverInfo = ctrl.params;\n }\n\n if (this.onConnect) {\n this.onConnect();\n }\n\n return ctrl;\n }).catch(err => {\n this._connection.reconnect(true);\n\n if (this.onDisconnect) {\n this.onDisconnect(err);\n }\n });\n }\n\n /**\n * Set or refresh the push notifications/device token. If the client is connected,\n * the deviceToken can be sent to the server.\n *\n * @param {string} dt - token obtained from the provider or false,\n * null or undefined to clear the token.\n *\n * @returns true if attempt was made to send the update to the server.\n */\n setDeviceToken(dt) {\n let sent = false;\n // Convert any falsish value to null.\n dt = dt || null;\n if (dt != this._deviceToken) {\n this._deviceToken = dt;\n if (this.isConnected() && this.isAuthenticated()) {\n this.#send({\n 'hi': {\n 'dev': dt || Tinode.DEL_CHAR\n }\n });\n sent = true;\n }\n }\n return sent;\n }\n\n /**\n * @typedef Credential\n * @type {Object}\n * @property {string} meth - validation method.\n * @property {string} val - value to validate (e.g. email or phone number).\n * @property {string} resp - validation response.\n * @property {Object} params - validation parameters.\n */\n /**\n * Authenticate current session.\n *\n * @param {string} scheme - Authentication scheme; \"basic\" is the only currently supported scheme.\n * @param {string} secret - Authentication secret, assumed to be already base64 encoded.\n * @param {Credential=} cred - credential confirmation, if required.\n *\n * @returns {Promise} Promise which will be resolved/rejected when server reply is received.\n */\n login(scheme, secret, cred) {\n const pkt = this.#initPacket('login');\n pkt.login.scheme = scheme;\n pkt.login.secret = secret;\n pkt.login.cred = cred;\n\n return this.#send(pkt, pkt.login.id)\n .then(ctrl => this.#loginSuccessful(ctrl));\n }\n\n /**\n * Wrapper for {@link Tinode#login} with basic authentication\n *\n * @param {string} uname - User name.\n * @param {string} password - Password.\n * @param {Credential=} cred - credential confirmation, if required.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n loginBasic(uname, password, cred) {\n return this.login('basic', b64EncodeUnicode(uname + ':' + password), cred)\n .then(ctrl => {\n this._login = uname;\n return ctrl;\n });\n }\n\n /**\n * Wrapper for {@link Tinode#login} with token authentication\n *\n * @param {string} token - Token received in response to earlier login.\n * @param {Credential=} cred - credential confirmation, if required.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n loginToken(token, cred) {\n return this.login('token', token, cred);\n }\n\n /**\n * Send a request for resetting an authentication secret.\n *\n * @param {string} scheme - authentication scheme to reset.\n * @param {string} method - method to use for resetting the secret, such as \"email\" or \"tel\".\n * @param {string} value - value of the credential to use, a specific email address or a phone number.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving the server reply.\n */\n requestResetAuthSecret(scheme, method, value) {\n return this.login('reset', b64EncodeUnicode(scheme + ':' + method + ':' + value));\n }\n\n /**\n * @typedef AuthToken\n * @type {Object}\n * @property {string} token - Token value.\n * @property {Date} expires - Token expiration time.\n */\n /**\n * Get stored authentication token.\n *\n * @returns {AuthToken} authentication token.\n */\n getAuthToken() {\n if (this._authToken && (this._authToken.expires.getTime() > Date.now())) {\n return this._authToken;\n } else {\n this._authToken = null;\n }\n return null;\n }\n\n /**\n * Application may provide a saved authentication token.\n *\n * @param {AuthToken} token - authentication token.\n */\n setAuthToken(token) {\n this._authToken = token;\n }\n\n /**\n * @typedef SetParams\n * @type {Object}\n * @property {SetDesc=} desc - Topic initialization parameters when creating a new topic or a new subscription.\n * @property {SetSub=} sub - Subscription initialization parameters.\n * @property {Array.=} tags - Search tags.\n * @property {Object} aux - Auxiliary topic data.\n * @property {Array.=} attachments - URLs of out of band attachments used in parameters.\n */\n /**\n * @typedef SetDesc\n * @type {Object}\n * @property {DefAcs=} defacs - Default access mode.\n * @property {Object=} public - Free-form topic description, publically accessible.\n * @property {Object=} private - Free-form topic description accessible only to the owner.\n * @property {Object=} trusted - Trusted user data which can be set by a root user only.\n */\n /**\n * @typedef SetSub\n * @type {Object}\n * @property {string=} user - UID of the user affected by the request. Default (empty) - current user.\n * @property {string=} mode - User access mode, either requested or assigned dependent on context.\n */\n /**\n * Send a topic subscription request.\n *\n * @param {string} topic - Name of the topic to subscribe to.\n * @param {GetQuery=} getParams - Optional subscription metadata query\n * @param {SetParams=} setParams - Optional initialization parameters\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n subscribe(topicName, getParams, setParams) {\n const pkt = this.#initPacket('sub', topicName)\n if (!topicName) {\n topicName = Const.TOPIC_NEW;\n }\n\n pkt.sub.get = getParams;\n\n if (setParams) {\n if (setParams.sub) {\n pkt.sub.set.sub = setParams.sub;\n }\n\n if (setParams.desc) {\n const desc = setParams.desc;\n if (Tinode.isNewGroupTopicName(topicName)) {\n // Full set.desc params are used for new topics only\n pkt.sub.set.desc = desc;\n } else if (Tinode.isP2PTopicName(topicName) && desc.defacs) {\n // Use optional default permissions only.\n pkt.sub.set.desc = {\n defacs: desc.defacs\n };\n }\n }\n\n // See if external objects were used in topic description.\n if (Array.isArray(setParams.attachments) && setParams.attachments.length > 0) {\n pkt.extra = {\n attachments: setParams.attachments.filter(ref => isUrlRelative(ref))\n };\n }\n\n if (setParams.tags) {\n pkt.sub.set.tags = setParams.tags;\n }\n if (setParams.aux) {\n pkt.sub.set.aux = setParams.aux;\n }\n }\n return this.#send(pkt, pkt.sub.id);\n }\n\n /**\n * Detach and optionally unsubscribe from the topic\n *\n * @param {string} topic - Topic to detach from.\n * @param {boolean} unsub - If true, detach and unsubscribe, otherwise just detach.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n leave(topic, unsub) {\n const pkt = this.#initPacket('leave', topic);\n pkt.leave.unsub = unsub;\n\n return this.#send(pkt, pkt.leave.id);\n }\n\n /**\n * Create message draft without sending it to the server.\n *\n * @param {string} topic - Name of the topic to publish to.\n * @param {Object} content - Payload to publish.\n * @param {boolean=} noEcho - If true, tell the server not to echo the message to the original session.\n *\n * @returns {Object} new message which can be sent to the server or otherwise used.\n */\n createMessage(topic, content, noEcho) {\n const pkt = this.#initPacket('pub', topic);\n\n let dft = typeof content == 'string' ? Drafty.parse(content) : content;\n if (dft && !Drafty.isPlainText(dft)) {\n pkt.pub.head = {\n mime: Drafty.getContentType()\n };\n content = dft;\n }\n pkt.pub.noecho = noEcho;\n pkt.pub.content = content;\n\n return pkt.pub;\n }\n\n /**\n * Publish {data} message to topic.\n *\n * @param {string} topicName - Name of the topic to publish to.\n * @param {Object} content - Payload to publish.\n * @param {boolean=} noEcho - If true, tell the server not to echo the message to the original session.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n publish(topicName, content, noEcho) {\n return this.publishMessage(\n this.createMessage(topicName, content, noEcho)\n );\n }\n\n /**\n * Publish message to topic. The message should be created by {@link Tinode#createMessage}.\n *\n * @param {Object} pub - Message to publish.\n * @param {Array.=} attachments - array of URLs with attachments.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n publishMessage(pub, attachments) {\n // Make a shallow copy. Needed in order to clear locally-assigned temp values;\n pub = Object.assign({}, pub);\n pub.seq = undefined;\n pub.from = undefined;\n pub.ts = undefined;\n const msg = {\n pub: pub,\n };\n if (attachments) {\n msg.extra = {\n attachments: attachments.filter(ref => isUrlRelative(ref))\n };\n }\n return this.#send(msg, pub.id);\n }\n\n /**\n * Out of band notification: notify topic that an external (push) notification was recived by the client.\n *\n * @param {object} data - notification payload.\n * @param {string} data.what - notification type, 'msg', 'read', 'sub'.\n * @param {string} data.topic - name of the updated topic.\n * @param {number=} data.seq - seq ID of the affected message.\n * @param {string=} data.xfrom - UID of the sender.\n * @param {object=} data.given - new subscription 'given', e.g. 'ASWP...'.\n * @param {object=} data.want - new subscription 'want', e.g. 'RWJ...'.\n */\n oobNotification(data) {\n this.logger('oob: ' + (this._trimLongStrings ? JSON.stringify(data, jsonLoggerHelper) : data));\n\n switch (data.what) {\n case 'msg':\n if (!data.seq || data.seq < 1 || !data.topic) {\n // Server sent invalid data.\n break;\n }\n\n if (!this.isConnected()) {\n // Let's ignore the message if there is no connection: no connection means there are no open\n // tabs with Tinode.\n break;\n }\n\n const topic = this.#cacheGet('topic', data.topic);\n if (!topic) {\n // TODO: check if there is a case when a message can arrive from an unknown topic.\n break;\n }\n\n if (topic.isSubscribed()) {\n // No need to fetch: topic is already subscribed and got data through normal channel.\n break;\n }\n\n if (topic.maxMsgSeq() < data.seq) {\n if (topic.isChannelType()) {\n topic._updateReceived(data.seq, 'fake-uid');\n }\n\n // New message.\n if (data.xfrom && !this.#cacheGet('user', data.xfrom)) {\n // Message from unknown sender, fetch description from the server.\n // Sending asynchronously without a subscription.\n this.getMeta(data.xfrom, new MetaGetBuilder().withDesc().build()).catch(err => {\n this.logger(\"Failed to get the name of a new sender\", err);\n });\n }\n\n topic.subscribe(null).then(_ => {\n return topic.getMeta(new MetaGetBuilder(topic).withLaterData(24).withLaterDel(24).build());\n }).then(_ => {\n // Allow data fetch to complete and get processed successfully.\n topic.leaveDelayed(false, 1000);\n }).catch(err => {\n this.logger(\"On push data fetch failed\", err);\n }).finally(_ => {\n this.getMeTopic()._refreshContact('msg', topic);\n });\n }\n break;\n\n case 'read':\n this.getMeTopic()._routePres({\n what: 'read',\n seq: data.seq\n });\n break;\n\n case 'sub':\n if (!this.isMe(data.xfrom)) {\n // TODO: handle updates from other users.\n break;\n }\n\n const mode = {\n given: data.modeGiven,\n want: data.modeWant\n };\n const acs = new AccessMode(mode);\n const pres = (!acs.mode || acs.mode == AccessMode._NONE) ?\n // Subscription deleted.\n {\n what: 'gone',\n src: data.topic\n } :\n // New subscription or subscription updated.\n {\n what: 'acs',\n src: data.topic,\n dacs: mode\n };\n this.getMeTopic()._routePres(pres);\n break;\n\n default:\n this.logger(\"Unknown push type ignored\", data.what);\n }\n }\n\n /**\n * @typedef GetOptsType\n * @type {Object}\n * @property {Date=} ims - \"If modified since\", fetch data only it was was modified since stated date.\n * @property {number=} limit - Maximum number of results to return. Ignored when querying topic description.\n */\n\n /**\n * @typedef GetDataType\n * @type {Object}\n * @property {number=} since - Load messages with seq ID equal or greater than this value.\n * @property {number=} before - Load messages with seq ID lower than this number.\n * @property {number=} limit - Maximum number of results to return.\n * @property {Array.=} range - Ranges of seq IDs to fetch.\n */\n\n /**\n * @typedef GetQuery\n * @type {Object}\n * @property {GetOptsType=} desc - If provided (even if empty), fetch topic description.\n * @property {GetOptsType=} sub - If provided (even if empty), fetch topic subscriptions.\n * @property {GetDataType=} data - If provided (even if empty), get messages.\n */\n\n /**\n * Request topic metadata\n *\n * @param {string} topic - Name of the topic to query.\n * @param {GetQuery} params - Parameters of the query. Use {@link Tinode.MetaGetBuilder} to generate.\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n getMeta(topic, params) {\n const pkt = this.#initPacket('get', topic);\n\n pkt.get = mergeObj(pkt.get, params);\n\n return this.#send(pkt, pkt.get.id);\n }\n\n /**\n * Update topic's metadata: description, subscribtions.\n *\n * @param {string} topic - Topic to update.\n * @param {SetParams} params - topic metadata to update.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n setMeta(topic, params) {\n const pkt = this.#initPacket('set', topic);\n const what = [];\n\n if (params) {\n ['desc', 'sub', 'tags', 'cred', 'aux'].forEach(key => {\n if (params.hasOwnProperty(key)) {\n what.push(key);\n pkt.set[key] = params[key];\n }\n });\n\n if (Array.isArray(params.attachments) && params.attachments.length > 0) {\n pkt.extra = {\n attachments: params.attachments.filter(ref => isUrlRelative(ref))\n };\n }\n }\n\n if (what.length == 0) {\n return Promise.reject(new Error(\"Invalid {set} parameters\"));\n }\n\n return this.#send(pkt, pkt.set.id);\n }\n\n /**\n * Range of message IDs.\n *\n * @typedef SeqRange\n * @type {Object}\n * @property {number} low - low end of the range, inclusive (closed).\n * @property {number=} hi - high end of the range, exclusive (open).\n */\n /**\n * Delete some or all messages in a topic.\n *\n * @param {string} topic - Topic name to delete messages from.\n * @param {Array.} list - Ranges of message IDs to delete.\n * @param {boolean=} hard - Hard or soft delete\n *\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delMessages(topic, ranges, hard) {\n const pkt = this.#initPacket('del', topic);\n\n pkt.del.what = 'msg';\n pkt.del.delseq = ranges;\n pkt.del.hard = hard;\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Delete the topic alltogether. Requires Owner permission.\n *\n * @param {string} topicName - Name of the topic to delete\n * @param {boolean} hard - hard-delete topic.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delTopic(topicName, hard) {\n const pkt = this.#initPacket('del', topicName);\n pkt.del.what = 'topic';\n pkt.del.hard = hard;\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Delete subscription. Requires Share permission.\n *\n * @param {string} topicName - Name of the topic to delete\n * @param {string} user - User ID to remove.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delSubscription(topicName, user) {\n const pkt = this.#initPacket('del', topicName);\n pkt.del.what = 'sub';\n pkt.del.user = user;\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Delete credential. Always sent on 'me' topic.\n *\n * @param {string} method - validation method such as 'email' or 'tel'.\n * @param {string} value - validation value, i.e. 'alice@example.com'.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delCredential(method, value) {\n const pkt = this.#initPacket('del', Const.TOPIC_ME);\n pkt.del.what = 'cred';\n pkt.del.cred = {\n meth: method,\n val: value\n };\n\n return this.#send(pkt, pkt.del.id);\n }\n\n /**\n * Request to delete account of the current user.\n *\n * @param {boolean} hard - hard-delete user.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delCurrentUser(hard) {\n const pkt = this.#initPacket('del', null);\n pkt.del.what = 'user';\n pkt.del.hard = hard;\n\n return this.#send(pkt, pkt.del.id).then(_ => {\n this._myUID = null;\n });\n }\n\n /**\n * Notify server that a message or messages were read or received. Does NOT return promise.\n *\n * @param {string} topicName - Name of the topic where the mesage is being aknowledged.\n * @param {string} what - Action being aknowledged, either \"read\" or \"recv\".\n * @param {number} seq - Maximum id of the message being acknowledged.\n * @throws {Error} if seq is invalid.\n */\n note(topicName, what, seq) {\n if (seq <= 0 || seq >= Const.LOCAL_SEQID) {\n throw new Error(`Invalid message id ${seq}`);\n }\n\n const pkt = this.#initPacket('note', topicName);\n pkt.note.what = what;\n pkt.note.seq = seq;\n this.#send(pkt);\n }\n\n /**\n * Broadcast a key-press notification to topic subscribers. Used to show\n * typing notifications \"user X is typing...\".\n *\n * @param {string} topicName - Name of the topic to broadcast to.\n * @param {string=} type - notification to send, default is 'kp'.\n */\n noteKeyPress(topicName, type) {\n const pkt = this.#initPacket('note', topicName);\n pkt.note.what = type || 'kp';\n this.#send(pkt);\n }\n\n /**\n * Send a video call notification to topic subscribers (including dialing,\n * hangup, etc.).\n *\n * @param {string} topicName - Name of the topic to broadcast to.\n * @param {int} seq - ID of the call message the event pertains to.\n * @param {string} evt - Call event.\n * @param {string} payload - Payload associated with this event (e.g. SDP string).\n *\n * @returns {Promise} Promise (for some call events) which will\n * be resolved/rejected on receiving server reply\n */\n videoCall(topicName, seq, evt, payload) {\n const pkt = this.#initPacket('note', topicName);\n pkt.note.seq = seq;\n pkt.note.what = 'call';\n pkt.note.event = evt;\n pkt.note.payload = payload;\n this.#send(pkt, pkt.note.id);\n }\n\n /**\n * Get a named topic, either pull it from cache or create a new instance.\n * There is a single instance of topic for each name.\n *\n * @param {string} topicName - Name of the topic to get.\n *\n * @returns {Topic} Requested or newly created topic or undefined if topic name is invalid.\n */\n getTopic(topicName) {\n let topic = this.#cacheGet('topic', topicName);\n if (!topic && topicName) {\n if (topicName == Const.TOPIC_ME) {\n topic = new TopicMe();\n } else if (topicName == Const.TOPIC_FND) {\n topic = new TopicFnd();\n } else {\n topic = new Topic(topicName);\n }\n // Cache management.\n this.#attachCacheToTopic(topic);\n topic._cachePutSelf();\n // Don't save to DB here: a record will be added when the topic is subscribed.\n }\n return topic;\n }\n\n /**\n * Get a named topic from cache.\n *\n * @param {string} topicName - Name of the topic to get.\n *\n * @returns {Topic} Requested topic or undefined if topic is not found in cache.\n */\n cacheGetTopic(topicName) {\n return this.#cacheGet('topic', topicName);\n }\n\n /**\n * Remove named topic from cache.\n *\n * @param {string} topicName - Name of the topic to remove from cache.\n */\n cacheRemTopic(topicName) {\n this.#cacheDel('topic', topicName);\n }\n\n /**\n * Iterate over cached topics.\n *\n * @param {Function} func - callback to call for each topic.\n * @param {Object} context - 'this' inside the 'func'.\n */\n mapTopics(func, context) {\n this.#cacheMap('topic', func, context);\n }\n\n /**\n * Check if named topic is already present in cache.\n *\n * @param {string} topicName - Name of the topic to check.\n * @returns {boolean} true if topic is found in cache, false otherwise.\n */\n isTopicCached(topicName) {\n return !!this.#cacheGet('topic', topicName);\n }\n\n /**\n * Generate unique name like 'new123456' suitable for creating a new group topic.\n *\n * @param {boolean} isChan - if the topic is channel-enabled.\n * @returns {string} name which can be used for creating a new group topic.\n */\n newGroupTopicName(isChan) {\n return (isChan ? Const.TOPIC_NEW_CHAN : Const.TOPIC_NEW) + this.getNextUniqueId();\n }\n\n /**\n * Instantiate 'me' topic or get it from cache.\n *\n * @returns {TopicMe} Instance of 'me' topic.\n */\n getMeTopic() {\n return this.getTopic(Const.TOPIC_ME);\n }\n\n /**\n * Instantiate 'fnd' (find) topic or get it from cache.\n *\n * @returns {Topic} Instance of 'fnd' topic.\n */\n getFndTopic() {\n return this.getTopic(Const.TOPIC_FND);\n }\n\n /**\n * Create a new {@link LargeFileHelper} instance\n *\n * @returns {LargeFileHelper} instance of a {@link Tinode.LargeFileHelper}.\n */\n getLargeFileHelper() {\n return new LargeFileHelper(this, Const.PROTOCOL_VERSION);\n }\n\n /**\n * Get the UID of the the current authenticated user.\n *\n * @returns {string} UID of the current user or undefined if the session is not yet\n * authenticated or if there is no session.\n */\n getCurrentUserID() {\n return this._myUID;\n }\n\n /**\n * Check if the given user ID is equal to the current user's UID.\n *\n * @param {string} uid - UID to check.\n *\n * @returns {boolean} true if the given UID belongs to the current logged in user.\n */\n isMe(uid) {\n return this._myUID === uid;\n }\n\n /**\n * Get login used for last successful authentication.\n *\n * @returns {string} login last used successfully or undefined.\n */\n getCurrentLogin() {\n return this._login;\n }\n\n /**\n * Return information about the server: protocol version and build timestamp.\n *\n * @returns {Object} build and version of the server or null if there is no connection or\n * if the first server response has not been received yet.\n */\n getServerInfo() {\n return this._serverInfo;\n }\n\n /**\n * Report a topic for abuse. Wrapper for {@link Tinode#publish}.\n *\n * @param {string} action - the only supported action is 'report'.\n * @param {string} target - name of the topic being reported.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n report(action, target) {\n return this.publish(Const.TOPIC_SYS, Drafty.attachJSON(null, {\n 'action': action,\n 'target': target\n }));\n }\n\n /**\n * Return server-provided configuration value.\n *\n * @param {string} name of the value to return.\n * @param {Object} defaultValue to return in case the parameter is not set or not found.\n *\n * @returns {Object} named value.\n */\n getServerParam(name, defaultValue) {\n return this._serverInfo && this._serverInfo[name] || defaultValue;\n }\n\n /**\n * Toggle console logging. Logging is off by default.\n *\n * @param {boolean} enabled - Set to true to enable logging to console.\n * @param {boolean} trimLongStrings - Set to true to trim long strings.\n */\n enableLogging(enabled, trimLongStrings) {\n this._loggingEnabled = enabled;\n this._trimLongStrings = enabled && trimLongStrings;\n }\n\n /**\n * Set UI language to report to the server. Must be called before 'hi' is sent, otherwise it will not be used.\n *\n * @param {string} hl - human (UI) language, like \"en_US\" or \"zh-Hans\".\n */\n setHumanLanguage(hl) {\n if (hl) {\n this._humanLanguage = hl;\n }\n }\n\n /**\n * Check if given topic is online.\n *\n * @param {string} name of the topic to test.\n * @returns {boolean} true if topic is online, false otherwise.\n */\n isTopicOnline(name) {\n const topic = this.#cacheGet('topic', name);\n return topic && topic.online;\n }\n\n /**\n * Get access mode for the given contact.\n *\n * @param {string} name of the topic to query.\n * @returns {AccessMode} access mode if topic is found, null otherwise.\n */\n getTopicAccessMode(name) {\n const topic = this.#cacheGet('topic', name);\n return topic ? topic.acs : null;\n }\n\n /**\n * Include message ID into all subsequest messages to server instructin it to send aknowledgemens.\n * Required for promises to function. Default is \"on\".\n *\n * @param {boolean} status - Turn aknowledgemens on or off.\n * @deprecated\n */\n wantAkn(status) {\n if (status) {\n this._messageId = Math.floor((Math.random() * 0xFFFFFF) + 0xFFFFFF);\n } else {\n this._messageId = 0;\n }\n }\n\n // Callbacks:\n /**\n * Callback to report when the websocket is opened. The callback has no parameters.\n *\n * @type {onWebsocketOpen}\n */\n onWebsocketOpen = undefined;\n\n /**\n * @typedef ServerParams\n *\n * @type {Object}\n * @property {string} ver - Server version\n * @property {string} build - Server build\n * @property {string=} sid - Session ID, long polling connections only.\n */\n\n /**\n * @callback onConnect\n * @param {number} code - Result code\n * @param {string} text - Text epxplaining the completion, i.e \"OK\" or an error message.\n * @param {ServerParams} params - Parameters returned by the server.\n */\n /**\n * Callback to report when connection with Tinode server is established.\n * @type {onConnect}\n */\n onConnect = undefined;\n\n /**\n * Callback to report when connection is lost. The callback has no parameters.\n * @type {onDisconnect}\n */\n onDisconnect = undefined;\n\n /**\n * @callback onLogin\n * @param {number} code - NUmeric completion code, same as HTTP status codes.\n * @param {string} text - Explanation of the completion code.\n */\n /**\n * Callback to report login completion.\n * @type {onLogin}\n */\n onLogin = undefined;\n\n /**\n * Callback to receive {ctrl} (control) messages.\n * @type {onCtrlMessage}\n */\n onCtrlMessage = undefined;\n\n /**\n * Callback to recieve {data} (content) messages.\n * @type {onDataMessage}\n */\n onDataMessage = undefined;\n\n /**\n * Callback to receive {pres} (presence) messages.\n * @type {onPresMessage}\n */\n onPresMessage = undefined;\n\n /**\n * Callback to receive all messages as objects.\n * @type {onMessage}\n */\n onMessage = undefined;\n\n /**\n * Callback to receive all messages as unparsed text.\n * @type {onRawMessage}\n */\n onRawMessage = undefined;\n\n /**\n * Callback to receive server responses to network probes. See {@link Tinode#networkProbe}\n * @type {onNetworkProbe}\n */\n onNetworkProbe = undefined;\n\n /**\n * Callback to be notified when exponential backoff is iterating.\n * @type {onAutoreconnectIteration}\n */\n onAutoreconnectIteration = undefined;\n};\n\n// Exported constants\nTinode.MESSAGE_STATUS_NONE = Const.MESSAGE_STATUS_NONE;\nTinode.MESSAGE_STATUS_QUEUED = Const.MESSAGE_STATUS_QUEUED;\nTinode.MESSAGE_STATUS_SENDING = Const.MESSAGE_STATUS_SENDING;\nTinode.MESSAGE_STATUS_FAILED = Const.MESSAGE_STATUS_FAILED;\nTinode.MESSAGE_STATUS_FATAL = Const.MESSAGE_STATUS_FATAL;\nTinode.MESSAGE_STATUS_SENT = Const.MESSAGE_STATUS_SENT;\nTinode.MESSAGE_STATUS_RECEIVED = Const.MESSAGE_STATUS_RECEIVED;\nTinode.MESSAGE_STATUS_READ = Const.MESSAGE_STATUS_READ;\nTinode.MESSAGE_STATUS_TO_ME = Const.MESSAGE_STATUS_TO_ME;\n\n// Unicode [del] symbol.\nTinode.DEL_CHAR = Const.DEL_CHAR;\n\n// Names of keys to server-provided configuration limits.\nTinode.MAX_MESSAGE_SIZE = 'maxMessageSize';\nTinode.MAX_SUBSCRIBER_COUNT = 'maxSubscriberCount';\nTinode.MIN_TAG_LENGTH = 'minTagLength';\nTinode.MAX_TAG_LENGTH = 'maxTagLength';\nTinode.MAX_TAG_COUNT = 'maxTagCount';\nTinode.MAX_FILE_UPLOAD_SIZE = 'maxFileUploadSize';\nTinode.REQ_CRED_VALIDATORS = 'reqCred';\nTinode.MSG_DELETE_AGE = 'msgDelAge';\n\n// Tinode URI topic ID prefix, 'scheme:path/'.\nTinode.URI_TOPIC_ID_PREFIX = 'tinode:topic/';\n\n// Tag prefixes for alias, email, phone.\nTinode.TAG_ALIAS = Const.TAG_ALIAS;\nTinode.TAG_EMAIL = Const.TAG_EMAIL;\nTinode.TAG_PHONE = Const.TAG_PHONE;\n","/**\n * @file Helper class for constructing {@link Tinode.GetQuery}.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport {\n listToRanges,\n normalizeRanges\n} from './utils';\n\n/**\n * Helper class for constructing {@link Tinode.GetQuery}.\n *\n * @class MetaGetBuilder\n * @memberof Tinode\n *\n * @param {Tinode.Topic} parent topic which instantiated this builder.\n */\nexport default class MetaGetBuilder {\n constructor(parent) {\n this.topic = parent;\n this.what = {};\n }\n\n // Get timestamp of the most recent desc update.\n #get_desc_ims() {\n return this.topic._deleted ? undefined : this.topic.updated;\n }\n\n // Get timestamp of the most recent subs update.\n #get_subs_ims() {\n if (this.topic.isP2PType()) {\n return this.#get_desc_ims();\n }\n return this.topic._deleted ? undefined : this.topic._lastSubsUpdate;\n }\n /**\n * Add query parameters to fetch messages within explicit limits.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} since - messages newer than this (inclusive);\n * @param {number=} before - older than this (exclusive)\n * @param {number=} limit - number of messages to fetch\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withData(since, before, limit) {\n this.what['data'] = {\n since: since,\n before: before,\n limit: limit\n };\n return this;\n }\n /**\n * Add query parameters to fetch messages newer than the latest saved message.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - number of messages to fetch\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterData(limit) {\n return this.withData(this.topic._maxSeq > 0 ? this.topic._maxSeq + 1 : undefined, undefined, limit);\n }\n /**\n * Add query parameters to fetch messages within ID ranges.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Array.} ranges - ranges of seq IDs to fetch.\n * @param {number=} limit - maximum number of messages to fetch.\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDataRanges(ranges, limit) {\n this.what['data'] = {\n ranges: normalizeRanges(ranges, this.topic._maxSeq),\n limit: limit\n };\n return this;\n }\n /**\n * Add query parameters to fetch messages by an array of IDs.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number[]} list - array of seq IDs to fetch.\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDataList(list) {\n return this.withDataRanges(listToRanges(list));\n }\n /**\n * Add query parameters to fetch messages older than the earliest saved message.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - maximum number of messages to fetch.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withEarlierData(limit) {\n return this.withData(undefined, this.topic._minSeq > 0 ? this.topic._minSeq : undefined, limit);\n }\n /**\n * Add query parameters to fetch topic description if it's newer than the given timestamp.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Date=} ims - fetch messages newer than this timestamp.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDesc(ims) {\n this.what['desc'] = {\n ims: ims\n };\n return this;\n }\n /**\n * Add query parameters to fetch topic description if it's newer than the last update.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterDesc() {\n return this.withDesc(this.#get_desc_ims());\n }\n /**\n * Add query parameters to fetch subscriptions.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Date=} ims - fetch subscriptions modified more recently than this timestamp\n * @param {number=} limit - maximum number of subscriptions to fetch.\n * @param {string=} userOrTopic - user ID or topic name to fetch for fetching one subscription.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withSub(ims, limit, userOrTopic) {\n const opts = {\n ims: ims,\n limit: limit\n };\n if (this.topic.getType() == 'me') {\n opts.topic = userOrTopic;\n } else {\n opts.user = userOrTopic;\n }\n this.what['sub'] = opts;\n return this;\n }\n /**\n * Add query parameters to fetch a single subscription.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {Date=} ims - fetch subscriptions modified more recently than this timestamp\n * @param {string=} userOrTopic - user ID or topic name to fetch for fetching one subscription.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withOneSub(ims, userOrTopic) {\n return this.withSub(ims, undefined, userOrTopic);\n }\n /**\n * Add query parameters to fetch a single subscription if it's been updated since the last update.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {string=} userOrTopic - user ID or topic name to fetch for fetching one subscription.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterOneSub(userOrTopic) {\n return this.withOneSub(this.topic._lastSubsUpdate, userOrTopic);\n }\n /**\n * Add query parameters to fetch subscriptions updated since the last update.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - maximum number of subscriptions to fetch.\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterSub(limit) {\n return this.withSub(this.#get_subs_ims(), limit);\n }\n /**\n * Add query parameters to fetch topic tags.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withTags() {\n this.what['tags'] = true;\n return this;\n }\n /**\n * Add query parameters to fetch user's credentials. 'me' topic only.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withCred() {\n if (this.topic.getType() == 'me') {\n this.what['cred'] = true;\n } else {\n this.topic._tinode.logger(\"ERROR: Invalid topic type for MetaGetBuilder:withCreds\", this.topic.getType());\n }\n return this;\n }\n /**\n * Add query parameters to fetch topic tags.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withAux() {\n this.what['aux'] = true;\n return this;\n }\n /**\n * Add query parameters to fetch deleted messages within explicit limits. Any/all parameters can be null.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} since - ids of messages deleted since this 'del' id (inclusive)\n * @param {number=} limit - number of deleted message ids to fetch\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withDel(since, limit) {\n if (since || limit) {\n this.what['del'] = {\n since: since,\n limit: limit\n };\n }\n return this;\n }\n /**\n * Add query parameters to fetch messages deleted after the saved 'del' id.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @param {number=} limit - number of deleted message ids to fetch\n *\n * @returns {Tinode.MetaGetBuilder} this object.\n */\n withLaterDel(limit) {\n // Specify 'since' only if we have already received some messages. If\n // we have no locally cached messages then we don't care if any messages were deleted.\n return this.withDel(this.topic._maxSeq > 0 ? this.topic._maxDel + 1 : undefined, limit);\n }\n\n /**\n * Extract subquery: get an object that contains specified subquery.\n * @memberof Tinode.MetaGetBuilder#\n * @param {string} what - subquery to return: one of 'data', 'sub', 'desc', 'tags', 'cred', 'del'.\n * @returns {Object} requested subquery or undefined.\n */\n extract(what) {\n return this.what[what];\n }\n\n /**\n * Construct parameters.\n * @memberof Tinode.MetaGetBuilder#\n *\n * @returns {Tinode.GetQuery} Get query\n */\n build() {\n const what = [];\n let params = {};\n ['data', 'sub', 'desc', 'tags', 'cred', 'aux', 'del'].forEach((key) => {\n if (this.what.hasOwnProperty(key)) {\n what.push(key);\n if (Object.getOwnPropertyNames(this.what[key]).length > 0) {\n params[key] = this.what[key];\n }\n }\n });\n if (what.length > 0) {\n params.what = what.join(' ');\n } else {\n params = undefined;\n }\n return params;\n }\n}\n","/**\n * @file In-memory sorted cache of objects.\n *\n * @copyright 2015-2025 Tinode LLC.\n */\n'use strict';\n\n/**\n * In-memory sorted cache of objects.\n *\n * @class CBuffer\n * @memberof Tinode\n * @protected\n *\n * @param {function} compare custom comparator of objects. Takes two parameters a and b;\n * returns -1 if a < b, 0 if a == b, 1 otherwise.\n * @param {boolean} unique enforce element uniqueness: when true replace existing element with a new\n * one on conflict; when false keep both elements.\n */\nexport default class CBuffer {\n #comparator = undefined;\n #unique = false;\n buffer = [];\n\n constructor(compare_, unique_) {\n this.#comparator = compare_ || ((a, b) => {\n return a === b ? 0 : a < b ? -1 : 1;\n });\n this.#unique = unique_;\n }\n\n #findNearest(elem, arr, exact) {\n let start = 0;\n let end = arr.length - 1;\n let pivot = 0;\n let diff = 0;\n let found = false;\n\n while (start <= end) {\n pivot = (start + end) / 2 | 0;\n diff = this.#comparator(arr[pivot], elem);\n if (diff < 0) {\n start = pivot + 1;\n } else if (diff > 0) {\n end = pivot - 1;\n } else {\n found = true;\n break;\n }\n }\n if (found) {\n return {\n idx: pivot,\n exact: true\n };\n }\n if (exact) {\n return {\n idx: -1\n };\n }\n // Not exact - insertion point\n return {\n idx: diff < 0 ? pivot + 1 : pivot\n };\n }\n\n // Insert element into a sorted array.\n #insertSorted(elem, arr) {\n const found = this.#findNearest(elem, arr, false);\n const count = (found.exact && this.#unique) ? 1 : 0;\n arr.splice(found.idx, count, elem);\n return arr;\n }\n\n /**\n * Get an element at the given position.\n * @memberof Tinode.CBuffer#\n * @param {number} at - Position to fetch from.\n * @returns {Object} Element at the given position or undefined.\n */\n getAt(at) {\n return this.buffer[at];\n }\n\n /**\n * Convenience method for getting the last element from the buffer.\n * @memberof Tinode.CBuffer#\n * @param {function} filter - optional filter to apply to elements. If filter is provided, the search\n * for the last element starts from the end of the buffer and goes backwards until the filter returns true.\n * @returns {Object} The last element in the buffer or undefined if buffer is empty.\n */\n getLast(filter) {\n return filter ?\n this.buffer.findLast(filter) :\n this.buffer[this.buffer.length - 1];\n }\n\n /**\n * Insert new element(s) to the buffer at the correct position according to the sort method.\n * Variadic: takes one or more arguments. If an array is passed as a single argument, its\n * elements are inserted individually.\n * @memberof Tinode.CBuffer#\n *\n * @param {...Object|Array} - One or more objects to insert.\n */\n put() {\n let insert;\n // inspect arguments: if array, insert its elements, if one or more non-array arguments, insert them one by one\n if (arguments.length == 1 && Array.isArray(arguments[0])) {\n insert = arguments[0];\n } else {\n insert = arguments;\n }\n for (let idx in insert) {\n this.#insertSorted(insert[idx], this.buffer);\n }\n }\n\n /**\n * Remove element at the given position.\n * @memberof Tinode.CBuffer#\n * @param {number} at - Position to delete at.\n * @returns {Object} Element at the given position or undefined.\n */\n delAt(at) {\n at |= 0;\n let r = this.buffer.splice(at, 1);\n if (r && r.length > 0) {\n return r[0];\n }\n return undefined;\n }\n\n /**\n * Remove elements between two positions.\n * @memberof Tinode.CBuffer#\n * @param {number} since - Position to delete from (inclusive).\n * @param {number} before - Position to delete to (exclusive).\n *\n * @returns {Array} array of removed elements (could be zero length).\n */\n delRange(since, before) {\n return this.buffer.splice(since, before - since);\n }\n\n /**\n * Return the number of elements the buffer holds.\n * @memberof Tinode.CBuffer#\n * @return {number} Number of elements in the buffer.\n */\n length() {\n return this.buffer.length;\n }\n\n /**\n * Reset the buffer discarding all elements\n * @memberof Tinode.CBuffer#\n */\n reset() {\n this.buffer = [];\n }\n\n /**\n * Callback for iterating contents of buffer. See {@link Tinode.CBuffer#forEach}.\n * @callback ForEachCallbackType\n * @memberof Tinode.CBuffer#\n * @param {Object} elem - Current element of the buffer.\n * @param {Object} prev - Previous element of the buffer.\n * @param {Object} next - Next element of the buffer.\n * @param {number} index - Index of the current element.\n */\n\n /**\n * Apply given callback to all elements of the buffer.\n * @memberof Tinode.CBuffer#\n *\n * @param {Tinode.ForEachCallbackType} callback - Function to call for each element.\n * @param {number} startIdx - Optional index to start iterating from (inclusive), default: 0.\n * @param {number} beforeIdx - Optional index to stop iterating before (exclusive), default: length of the buffer.\n * @param {Object} context - calling context (i.e. value of this in callback)\n */\n forEach(callback, startIdx, beforeIdx, context) {\n startIdx = Math.max(0, startIdx | 0);\n beforeIdx = Math.min(beforeIdx || this.buffer.length, this.buffer.length);\n\n for (let i = startIdx; i < beforeIdx; i++) {\n callback.call(context, this.buffer[i],\n (i > startIdx ? this.buffer[i - 1] : undefined),\n (i < beforeIdx - 1 ? this.buffer[i + 1] : undefined), i);\n }\n }\n\n /**\n * Find element in buffer using buffer's comparison function.\n * @memberof Tinode.CBuffer#\n *\n * @param {Object} elem - element to find.\n * @param {boolean=} nearest - when true and exact match is not found, return the nearest element (insertion point).\n * @returns {number} index of the element in the buffer or -1.\n */\n find(elem, nearest) {\n const {\n idx\n } = this.#findNearest(elem, this.buffer, !nearest);\n return idx;\n }\n\n /**\n * Callback for filtering the buffer. See {@link Tinode.CBuffer#filter}.\n * @callback FilterCallbackType\n * @memberof Tinode.CBuffer#\n * @param {Object} elem - Current element of the buffer.\n * @param {number} index - Index of the current element.\n * @returns {boolen} true to keep the element, false to remove.\n */\n\n /**\n * Remove all elements that do not pass the test implemented by the provided callback function.\n * @memberof Tinode.CBuffer#\n *\n * @param {Tinode.FilterCallbackType} callback - Function to call for each element.\n * @param {Object} context - calling context (i.e. value of this in the callback)\n */\n filter(callback, context) {\n let count = 0;\n for (let i = 0; i < this.buffer.length; i++) {\n if (callback.call(context, this.buffer[i], i)) {\n this.buffer[count] = this.buffer[i];\n count++;\n }\n }\n\n this.buffer.splice(count);\n }\n\n /**\n * Check if buffer is empty.\n * @returns {boolean} true if the buffer is empty, false otherwise.\n */\n isEmpty() {\n return this.buffer.length == 0;\n }\n}\n","/**\n * @file Topic management.\n *\n * @copyright 2015-2025 Tinode LLC.\n */\n'use strict';\n\nimport AccessMode from './access-mode.js';\nimport CBuffer from './cbuffer.js';\nimport CommError from './comm-error.js';\nimport * as Const from './config.js';\nimport Drafty from './drafty.js';\nimport MetaGetBuilder from './meta-builder.js';\nimport {\n listToRanges,\n mergeObj,\n mergeToCache,\n normalizeArray,\n normalizeRanges\n} from './utils.js';\n\n/**\n * Topic is a class representing a logical communication channel.\n */\nexport default class Topic {\n /**\n * @callback onData\n * @param {Data} data - Data packet\n */\n\n /**\n * Create topic.\n * @param {string} name - Name of the topic to create.\n * @param {Object=} callbacks - Object with various event callbacks.\n * @param {onData} callbacks.onData - Callback which receives a {data} message.\n * @param {callback} callbacks.onMeta - Callback which receives a {meta} message.\n * @param {callback} callbacks.onPres - Callback which receives a {pres} message.\n * @param {callback} callbacks.onInfo - Callback which receives an {info} message.\n * @param {callback} callbacks.onMetaDesc - Callback which receives changes to topic desctioption {@link desc}.\n * @param {callback} callbacks.onMetaSub - Called for a single subscription record change.\n * @param {callback} callbacks.onSubsUpdated - Called after a batch of subscription changes have been recieved and cached.\n * @param {callback} callbacks.onDeleteTopic - Called after the topic is deleted.\n * @param {callback} callbacls.onAllMessagesReceived - Called when all requested {data} messages have been recived.\n */\n constructor(name, callbacks) {\n // Parent Tinode object.\n this._tinode = null;\n\n // Server-provided data, locally immutable.\n // topic name\n this.name = name;\n // Timestamp when the topic was created.\n this.created = null;\n // Timestamp when the topic was last updated.\n this.updated = null;\n // Timestamp of the last messages\n this.touched = new Date(0);\n // Access mode, see AccessMode\n this.acs = new AccessMode(null);\n // Per-topic private data (accessible by current user only).\n this.private = null;\n // Per-topic public data (accessible by all users).\n this.public = null;\n // Per-topic system-provided data (accessible by all users).\n this.trusted = null;\n\n // Locally cached data\n // Subscribed users, for tracking read/recv/msg notifications.\n this._users = {};\n\n // Current value of locally issued seqId, used for pending messages.\n this._queuedSeqId = Const.LOCAL_SEQID;\n\n // The maximum known {data.seq} value.\n this._maxSeq = 0;\n // The minimum known {data.seq} value.\n this._minSeq = 0;\n // Indicator that the last request for earlier messages returned 0.\n this._noEarlierMsgs = false;\n // The maximum known deletion ID.\n this._maxDel = 0;\n // Timer object used to send 'recv' notifications.\n this._recvNotificationTimer = null;\n\n // User discovery tags\n this._tags = [];\n // Credentials such as email or phone number.\n this._credentials = [];\n // Auxiliary data\n this._aux = {};\n\n // Message versions cache (e.g. for edited messages).\n // Keys: original message seq ID.\n // Values: CBuffers containing newer versions of the original message\n // ordered by seq id.\n this._messageVersions = {};\n // Message cache, sorted by message seq values, from old to new.\n this._messages = new CBuffer((a, b) => {\n return a.seq - b.seq;\n }, true);\n // Boolean, true if the topic is currently live\n this._attached = false;\n // Timestap of the most recently updated subscription.\n this._lastSubsUpdate = new Date(0);\n // Topic created but not yet synced with the server. Used only during initialization.\n this._new = true;\n // The topic is deleted at the server, this is a local copy.\n this._deleted = false;\n\n // Timer used to trgger {leave} request after a delay.\n this._delayedLeaveTimer = null;\n\n // Callbacks\n if (callbacks) {\n this.onData = callbacks.onData;\n this.onMeta = callbacks.onMeta;\n this.onPres = callbacks.onPres;\n this.onInfo = callbacks.onInfo;\n // A single desc update;\n this.onMetaDesc = callbacks.onMetaDesc;\n // A single subscription record;\n this.onMetaSub = callbacks.onMetaSub;\n // All subscription records received;\n this.onSubsUpdated = callbacks.onSubsUpdated;\n this.onTagsUpdated = callbacks.onTagsUpdated;\n this.onCredsUpdated = callbacks.onCredsUpdated;\n this.onAuxUpdated = callbacks.onAuxUpdated;\n this.onDeleteTopic = callbacks.onDeleteTopic;\n this.onAllMessagesReceived = callbacks.onAllMessagesReceived;\n }\n }\n\n // Static methods.\n\n /**\n * Determine topic type from topic's name: grp, p2p, me, fnd, sys.\n *\n * @param {string} name - Name of the topic to test.\n * @returns {string} One of \"me\", \"fnd\", \"sys\", \"grp\",\n * \"p2p\" or undefined.\n */\n static topicType(name) {\n const types = {\n 'me': Const.TOPIC_ME,\n 'fnd': Const.TOPIC_FND,\n 'grp': Const.TOPIC_GRP,\n 'new': Const.TOPIC_GRP,\n 'nch': Const.TOPIC_GRP,\n 'chn': Const.TOPIC_GRP,\n 'usr': Const.TOPIC_P2P,\n 'sys': Const.TOPIC_SYS,\n 'slf': Const.TOPIC_SLF\n };\n return types[(typeof name == 'string') ? name.substring(0, 3) : 'xxx'];\n }\n\n /**\n * Check if the given topic name is a name of a 'me' topic.\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'me' topic, false otherwise.\n */\n static isMeTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_ME;\n }\n\n /**\n * Check if the given topic name is a name of a 'slf' topic.\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a 'slf' topic, false otherwise.\n */\n static isSelfTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_SLF;\n }\n\n /**\n * Check if the given topic name is a name of a group topic.\n * @static\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a group topic, false otherwise.\n */\n static isGroupTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_GRP;\n }\n\n /**\n * Check if the given topic name is a name of a p2p topic.\n * @static\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p topic, false otherwise.\n */\n static isP2PTopicName(name) {\n return Topic.topicType(name) == Const.TOPIC_P2P;\n }\n\n /**\n * Check if the given topic name is a name of a communication topic, i.e. P2P or group.\n * @static\n *\n * @param {string} name - Name of the topic to test.\n * @returns {boolean} true if the name is a name of a p2p or group topic, false otherwise.\n */\n static isCommTopicName(name) {\n return Topic.isP2PTopicName(name) || Topic.isGroupTopicName(name) || Topic.isSelfTopicName(name);\n }\n\n /**\n * Check if the topic name is a name of a new topic.\n * @static\n *\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a new topic, false otherwise.\n */\n static isNewGroupTopicName(name) {\n return (typeof name == 'string') &&\n (name.substring(0, 3) == Const.TOPIC_NEW || name.substring(0, 3) == Const.TOPIC_NEW_CHAN);\n }\n\n /**\n * Check if the topic name is a name of a channel.\n * @static\n *\n * @param {string} name - topic name to check.\n * @returns {boolean} true if the name is a name of a channel, false otherwise.\n */\n static isChannelTopicName(name) {\n return (typeof name == 'string') &&\n (name.substring(0, 3) == Const.TOPIC_CHAN || name.substring(0, 3) == Const.TOPIC_NEW_CHAN);\n }\n\n // Returns true if pub is meant to replace another message (e.g. original message was edited).\n static #isReplacementMsg(pub) {\n return pub.head && pub.head.replace;\n }\n\n /**\n * Check if the topic is subscribed.\n * @returns {boolean} True is topic is attached/subscribed, false otherwise.\n */\n isSubscribed() {\n return this._attached;\n }\n\n /**\n * Request topic to subscribe. Wrapper for {@link Tinode#subscribe}.\n *\n * @param {Tinode.GetQuery=} getParams - get query parameters.\n * @param {Tinode.SetParams=} setParams - set parameters.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n subscribe(getParams, setParams) {\n // Clear request to leave topic.\n clearTimeout(this._delayedLeaveTimer);\n this._delayedLeaveTimer = null;\n\n // If the topic is already subscribed, return resolved promise\n if (this._attached) {\n return Promise.resolve(this);\n }\n\n // Send subscribe message, handle async response.\n // If topic name is explicitly provided, use it. If no name, then it's a new group topic,\n // use \"new\".\n return this._tinode.subscribe(this.name || Const.TOPIC_NEW, getParams, setParams).then(ctrl => {\n if (ctrl.code >= 300) {\n // Do nothing if subscription status has not changed.\n return ctrl;\n }\n\n this._attached = true;\n this._deleted = false;\n this.acs = (ctrl.params && ctrl.params.acs) ? ctrl.params.acs : this.acs;\n\n // Set topic name for new topics and add it to cache.\n if (this._new) {\n delete this._new;\n\n if (this.name != ctrl.topic) {\n // Name may change new123456 -> grpAbCdEf. Remove from cache under the old name.\n this._cacheDelSelf();\n this.name = ctrl.topic;\n }\n this._cachePutSelf();\n\n this.created = ctrl.ts;\n this.updated = ctrl.ts;\n\n if (this.name != Const.TOPIC_ME && this.name != Const.TOPIC_FND) {\n // Add the new topic to the list of contacts maintained by the 'me' topic.\n const me = this._tinode.getMeTopic();\n if (me.onMetaSub) {\n me.onMetaSub(this);\n }\n if (me.onSubsUpdated) {\n me.onSubsUpdated([this.name], 1);\n }\n }\n\n if (setParams && setParams.desc) {\n setParams.desc._noForwarding = true;\n this._processMetaDesc(setParams.desc);\n }\n }\n return ctrl;\n });\n }\n\n /**\n * Create a draft of a message without sending it to the server.\n * @memberof Tinode.Topic#\n *\n * @param {string | Object} data - Content to wrap in a draft.\n * @param {boolean=} noEcho - If true server will not echo message back to originating\n * session. Otherwise the server will send a copy of the message to sender.\n *\n * @returns {Object} message draft.\n */\n createMessage(data, noEcho) {\n return this._tinode.createMessage(this.name, data, noEcho);\n }\n\n /**\n * Immediately publish data to topic. Wrapper for {@link Tinode#publish}.\n * @memberof Tinode.Topic#\n *\n * @param {string | Object} data - Message to publish, either plain string or a Drafty object.\n * @param {boolean=} noEcho - If true server will not echo message back to originating\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n publish(data, noEcho) {\n return this.publishMessage(this.createMessage(data, noEcho));\n }\n\n /**\n * Publish message created by {@link Tinode.Topic#createMessage}.\n * @memberof Tinode.Topic#\n *\n * @param {Object} pub - {data} object to publish. Must be created by {@link Tinode.Topic#createMessage}\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n publishMessage(pub) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot publish on inactive topic\"));\n }\n if (this._sending) {\n return Promise.reject(new Error(\"The message is already being sent\"));\n }\n\n // Send data.\n pub._sending = true;\n pub._failed = false;\n\n // Extract refereces to attachments and out of band image records.\n let attachments = null;\n if (Drafty.hasEntities(pub.content)) {\n attachments = [];\n Drafty.entities(pub.content, data => {\n if (data) {\n if (data.ref) {\n attachments.push(data.ref);\n }\n if (data.preref) {\n attachments.push(data.preref);\n }\n }\n });\n if (attachments.length == 0) {\n attachments = null;\n }\n }\n\n return this._tinode.publishMessage(pub, attachments).then(ctrl => {\n pub._sending = false;\n pub.ts = ctrl.ts;\n this.swapMessageId(pub, ctrl.params.seq);\n this._maybeUpdateMessageVersionsCache(pub);\n this._routeData(pub);\n return ctrl;\n }).catch(err => {\n this._tinode.logger(\"WARNING: Message rejected by the server\", err);\n pub._sending = false;\n pub._failed = true;\n if (this.onData) {\n this.onData();\n }\n });\n }\n\n /**\n * Add message to local message cache, send to the server when the promise is resolved.\n * If promise is null or undefined, the message will be sent immediately.\n * The message is sent when the\n * The message should be created by {@link Tinode.Topic#createMessage}.\n * This is probably not the final API.\n * @memberof Tinode.Topic#\n *\n * @param {Object} pub - Message to use as a draft.\n * @param {Promise} prom - Message will be sent when this promise is resolved, discarded if rejected.\n *\n * @returns {Promise} derived promise.\n */\n publishDraft(pub, prom) {\n const seq = pub.seq || this._getQueuedSeqId();\n if (!pub._noForwarding) {\n // The 'seq', 'ts', and 'from' are added to mimic {data}. They are removed later\n // before the message is sent.\n pub._noForwarding = true;\n pub.seq = seq;\n pub.ts = new Date();\n pub.from = this._tinode.getCurrentUserID();\n\n // Don't need an echo message because the message is added to local cache right away.\n pub.noecho = true;\n // Add to cache.\n this._messages.put(pub);\n this._tinode._db.addMessage(pub);\n\n if (this.onData) {\n this.onData(pub);\n }\n }\n // If promise is provided, send the queued message when it's resolved.\n // If no promise is provided, create a resolved one and send immediately.\n return (prom || Promise.resolve())\n .then(_ => {\n if (pub._cancelled) {\n return {\n code: 300,\n text: \"cancelled\"\n };\n }\n return this.publishMessage(pub);\n }).catch(err => {\n this._tinode.logger(\"WARNING: Message draft rejected\", err);\n pub._sending = false;\n pub._failed = true;\n pub._fatal = err instanceof CommError ? (err.code >= 400 && err.code < 500) : false;\n if (this.onData) {\n this.onData();\n }\n // Rethrow to let caller know that the operation failed.\n throw err;\n });\n }\n\n /**\n * Leave the topic, optionally unsibscribe. Leaving the topic means the topic will stop\n * receiving updates from the server. Unsubscribing will terminate user's relationship with the topic.\n * Wrapper for {@link Tinode#leave}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean=} unsub - If true, unsubscribe, otherwise just leave.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n leave(unsub) {\n // It's possible to unsubscribe (unsub==true) from inactive topic.\n if (!this._attached && !unsub) {\n return Promise.reject(new Error(\"Cannot leave inactive topic\"));\n }\n\n // Send a 'leave' message, handle async response\n return this._tinode.leave(this.name, unsub).then(ctrl => {\n this._resetSub();\n if (unsub) {\n this._gone();\n }\n return ctrl;\n });\n }\n\n /**\n * Leave the topic, optionally unsibscribe after a delay. Leaving the topic means the topic will stop\n * receiving updates from the server. Unsubscribing will terminate user's relationship with the topic.\n * Wrapper for {@link Tinode#leave}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} unsub - If true, unsubscribe, otherwise just leave.\n * @param {number} delay - time in milliseconds to delay leave request.\n */\n leaveDelayed(unsub, delay) {\n clearTimeout(this._delayedLeaveTimer);\n this._delayedLeaveTimer = setTimeout(_ => {\n this._delayedLeaveTimer = null;\n this.leave(unsub)\n }, delay);\n }\n\n /**\n * Request topic metadata from the local cache or from the server.\n * @memberof Tinode.Topic#\n *\n * @param {Tinode.GetQuery} request parameters\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n getMeta(params) {\n // Send {get} message, return promise.\n return this._tinode.getMeta(this.name, params);\n }\n\n /**\n * Request more messages from the server. The goal is to load continous range of messages\n * covering at least between 'min' and 'max' + one full page forward (newer = true) or backwards\n * (newer=false).\n * @memberof Tinode.Topic#\n *\n * @param {number} limit number of messages to get.\n * @param {Array.} gaps - ranges of messages to load.\n * @param {number} min if non-negative, request newer messages with seq >= min.\n * @param {number} max if positive, request older messages with seq < max.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n getMessagesPage(limit, gaps, min, max, newer) {\n let query = gaps ?\n this.startMetaQuery().withDataRanges(gaps, limit) :\n newer ?\n this.startMetaQuery().withData(min, undefined, limit) :\n this.startMetaQuery().withData(undefined, max, limit);\n // First try fetching from DB, then from the server.\n return this._loadMessages(this._tinode._db, query.extract('data'))\n .then(count => {\n // Recalculate missing ranges.\n gaps = this.msgHasMoreMessages(min, max, newer);\n if (gaps.length == 0) {\n // All messages loaded.\n return Promise.resolve({\n topic: this.name,\n code: 200,\n params: {\n count: count\n }\n });\n }\n\n // Reduce the count of requested messages.\n limit -= count;\n // Update query with new values loaded from DB.\n query = this.startMetaQuery().withDataRanges(gaps, limit);\n return this.getMeta(query.build());\n });\n }\n\n /**\n * Request to get pinned messages from the local cache or from the server.\n * @memberof Tinode.Topic#\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n getPinnedMessages() {\n const pins = this.aux('pins');\n if (!Array.isArray(pins)) {\n return Promise.resolve(0);\n }\n\n const loaded = [];\n let remains = pins;\n // First try fetching from DB, then check deleted log, then ask the server.\n return this._tinode._db.readMessages(this.name, {\n ranges: listToRanges(remains)\n })\n .then(msgs => {\n msgs.forEach(data => {\n // The 'data' could be undefined.\n if (data) {\n loaded.push(data.seq);\n this._messages.put(data);\n this._maybeUpdateMessageVersionsCache(data);\n }\n });\n if (loaded.length < pins.length) {\n // Some messages are missing, try dellog.\n remains = pins.filter(seq => !loaded.includes(seq));\n return this._tinode._db.readMessages(this.name, {\n ranges: listToRanges(remains)\n });\n }\n return null;\n })\n .then(ranges => {\n if (ranges) {\n // Found some deleted ranges in dellog.\n remains.forEach(seq => {\n if (ranges.find(r => r.low <= seq && r.hi > seq)) {\n loaded.push(seq);\n }\n });\n }\n if (loaded.length == pins.length) {\n // Got all pinned messages from the local cache.\n return Promise.resolve({\n topic: this.name,\n code: 200,\n params: {\n count: loaded.length\n }\n });\n }\n\n remains = pins.filter(seq => !loaded.includes(seq));\n return this.getMeta(this.startMetaQuery().withDataList(remains).build());\n });\n }\n\n /**\n * Update topic metadata.\n * @memberof Tinode.Topic#\n *\n * @param {Tinode.SetParams} params parameters to update.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n setMeta(params) {\n if (params.tags) {\n params.tags = normalizeArray(params.tags);\n }\n // Send Set message, handle async response.\n return this._tinode.setMeta(this.name, params)\n .then(ctrl => {\n if (ctrl && ctrl.code >= 300) {\n // Not modified\n return ctrl;\n }\n\n if (params.sub) {\n params.sub.topic = this.name;\n if (ctrl.params && ctrl.params.acs) {\n params.sub.acs = ctrl.params.acs;\n params.sub.updated = ctrl.ts;\n }\n if (!params.sub.user) {\n // This is a subscription update of the current user.\n // Assign user ID otherwise the update will be ignored by _processMetaSubs.\n params.sub.user = this._tinode.getCurrentUserID();\n if (!params.desc) {\n // Force update to topic's asc.\n params.desc = {};\n }\n }\n params.sub._noForwarding = true;\n this._processMetaSubs([params.sub]);\n }\n\n if (params.desc) {\n if (ctrl.params && ctrl.params.acs) {\n params.desc.acs = ctrl.params.acs;\n params.desc.updated = ctrl.ts;\n }\n this._processMetaDesc(params.desc);\n }\n\n if (params.tags) {\n this._processMetaTags(params.tags);\n }\n if (params.cred) {\n this._processMetaCreds([params.cred], true);\n }\n if (params.aux) {\n this._processMetaAux(params.aux);\n }\n\n return ctrl;\n });\n }\n /**\n * Update access mode of the current user or of another topic subsriber.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - UID of the user to update or null to update current user.\n * @param {string} update - the update value, full or delta.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n updateMode(uid, update) {\n const user = uid ? this.subscriber(uid) : null;\n const am = user ?\n user.acs.updateGiven(update).getGiven() :\n this.getAccessMode().updateWant(update).getWant();\n\n return this.setMeta({\n sub: {\n user: uid,\n mode: am\n }\n });\n }\n /**\n * Create new topic subscription. Wrapper for {@link Tinode#setMeta}.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - ID of the user to invite\n * @param {string=} mode - Access mode. null means to use default.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n invite(uid, mode) {\n return this.setMeta({\n sub: {\n user: uid,\n mode: mode\n }\n });\n }\n /**\n * Archive or un-archive the topic. Wrapper for {@link Tinode#setMeta}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} arch - true to archive the topic, false otherwise.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n archive(arch) {\n if (this.private && (!this.private.arch == !arch)) {\n return Promise.resolve(arch);\n }\n return this.setMeta({\n desc: {\n private: {\n arch: arch ? true : Const.DEL_CHAR\n }\n }\n });\n }\n /**\n * Set message as pinned or unpinned by adding it to aux.pins array. Wrapper for {@link Tinode#setMeta}.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - seq ID of the message to pin or un-pin.\n * @param {boolean} pin - true to pin the message, false to un-pin.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n pinMessage(seq, pin) {\n let pinned = this.aux('pins');\n if (!Array.isArray(pinned)) {\n pinned = [];\n }\n let changed = false;\n if (pin) {\n if (!pinned.includes(seq)) {\n changed = true;\n if (pinned.length == Const.MAX_PINNED_COUNT) {\n pinned.shift();\n }\n pinned.push(seq);\n }\n } else {\n if (pinned.includes(seq)) {\n changed = true;\n pinned = pinned.filter(id => id != seq);\n if (pinned.length == 0) {\n pinned = Const.DEL_CHAR;\n }\n }\n }\n if (changed) {\n return this.setMeta({\n aux: {\n pins: pinned\n }\n });\n }\n return Promise.resolve();\n }\n /**\n * Delete messages. Hard-deleting messages requires Deleter (D) permission.\n * Wrapper for {@link Tinode#delMessages}.\n * @memberof Tinode.Topic#\n *\n * @param {Array.} ranges - Ranges of message IDs to delete.\n * @param {boolean=} hard - Hard or soft delete\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delMessages(ranges, hard) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot delete messages in inactive topic\"));\n }\n\n const tosend = normalizeRanges(ranges, this._maxSeq)\n\n // Send {del} message, return promise\n let result;\n if (tosend.length > 0) {\n result = this._tinode.delMessages(this.name, tosend, hard);\n } else {\n result = Promise.resolve({\n params: {\n del: 0\n }\n });\n }\n // Update local cache.\n return result.then(ctrl => {\n if (ctrl.params.del > this._maxDel) {\n this._maxDel = Math.max(ctrl.params.del, this._maxDel);\n this.clear = Math.max(ctrl.params.del, this.clear);\n }\n\n ranges.forEach(rec => {\n if (rec.hi) {\n this.flushMessageRange(rec.low, rec.hi);\n } else {\n this.flushMessage(rec.low);\n }\n this._messages.put({\n seq: rec.low,\n low: rec.low,\n hi: rec.hi,\n _deleted: true\n });\n });\n\n // Make a record.\n this._tinode._db.addDelLog(this.name, ctrl.params.del, ranges);\n\n if (this.onData) {\n // Calling with no parameters to indicate the messages were deleted.\n this.onData();\n }\n return ctrl;\n });\n }\n /**\n * Delete all messages. Hard-deleting messages requires Deleter permission.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} hardDel - true if messages should be hard-deleted.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delMessagesAll(hardDel) {\n if (!this._maxSeq || this._maxSeq <= 0) {\n // There are no messages to delete.\n return Promise.resolve();\n }\n return this.delMessages([{\n low: 1,\n hi: this._maxSeq + 1,\n _all: true\n }], hardDel);\n }\n\n /**\n * Delete multiple messages defined by their IDs. Hard-deleting messages requires Deleter permission.\n * @memberof Tinode.Topic#\n *\n * @param {Array.} list - list of seq IDs to delete.\n * @param {boolean=} hardDel - true if messages should be hard-deleted.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delMessagesList(list, hardDel) {\n // Send {del} message, return promise\n return this.delMessages(listToRanges(list), hardDel);\n }\n\n /**\n * Delete original message and edited variants. Hard-deleting messages requires Deleter permission.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - original seq ID of the message to delete.\n * @param {boolean=} hardDel - true if messages should be hard-deleted.\n *\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n delMessagesEdits(seq, hardDel) {\n const list = [seq];\n this.messageVersions(seq, msg => list.push(msg.seq));\n // Send {del} message, return promise\n return this.delMessagesList(list, hardDel);\n }\n\n /**\n * Delete topic. Requires Owner permission. Wrapper for {@link Tinode#delTopic}.\n * @memberof Tinode.Topic#\n *\n * @param {boolean} hard - had-delete topic.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to the request.\n */\n delTopic(hard) {\n if (this._deleted) {\n // The topic is already deleted at the server, just remove from DB.\n this._gone();\n return Promise.resolve(null);\n }\n\n return this._tinode.delTopic(this.name, hard).then(ctrl => {\n this._deleted = true;\n this._resetSub();\n this._gone();\n return ctrl;\n });\n }\n /**\n * Delete subscription. Requires Share permission. Wrapper for {@link Tinode#delSubscription}.\n * @memberof Tinode.Topic#\n *\n * @param {string} user - ID of the user to remove subscription for.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n delSubscription(user) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot delete subscription in inactive topic\"));\n }\n // Send {del} message, return promise\n return this._tinode.delSubscription(this.name, user).then(ctrl => {\n // Remove the object from the subscription cache;\n delete this._users[user];\n // Notify listeners\n if (this.onSubsUpdated) {\n this.onSubsUpdated(Object.keys(this._users));\n }\n return ctrl;\n });\n }\n /**\n * Send a read/recv notification.\n * @memberof Tinode.Topic#\n *\n * @param {string} what - what notification to send: recv, read.\n * @param {number} seq - ID or the message read or received.\n */\n note(what, seq) {\n if (!this._attached) {\n // Cannot sending {note} on an inactive topic\".\n return;\n }\n\n // Update local cache with the new count.\n const user = this._users[this._tinode.getCurrentUserID()];\n let update = false;\n if (user) {\n // Self-subscription is found.\n if (!user[what] || user[what] < seq) {\n user[what] = seq;\n update = true;\n }\n } else {\n // Self-subscription is not found.\n update = (this[what] | 0) < seq;\n }\n\n if (update) {\n // Send notification to the server.\n this._tinode.note(this.name, what, seq);\n // Update locally cached contact with the new count.\n this._updateMyReadRecv(what, seq);\n\n if (this.acs != null && !this.acs.isMuted()) {\n const me = this._tinode.getMeTopic();\n // Sent a notification to 'me' listeners.\n me._refreshContact(what, this);\n }\n }\n }\n\n /**\n * Send a 'recv' receipt. Wrapper for {@link Tinode#noteRecv}.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - ID of the message to aknowledge.\n */\n noteRecv(seq) {\n this.note('recv', seq);\n }\n /**\n * Send a 'read' receipt. Wrapper for {@link Tinode#noteRead}.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - ID of the message to aknowledge or 0/undefined to acknowledge the latest messages.\n */\n noteRead(seq) {\n seq = seq || this._maxSeq;\n if (seq > 0) {\n this.note('read', seq);\n }\n }\n /**\n * Send a key-press notification. Wrapper for {@link Tinode#noteKeyPress}.\n * @memberof Tinode.Topic#\n */\n noteKeyPress() {\n if (this._attached) {\n this._tinode.noteKeyPress(this.name);\n } else {\n this._tinode.logger(\"INFO: Cannot send notification in inactive topic\");\n }\n }\n /**\n * Send a notification than a video or audio message is . Wrapper for {@link Tinode#noteKeyPress}.\n * @memberof Tinode.Topic#\n * @param audioOnly - true if the recording is audio-only, false if it's a video recording.\n */\n noteRecording(audioOnly) {\n if (this._attached) {\n this._tinode.noteKeyPress(this.name, audioOnly ? 'kpa' : 'kpv');\n } else {\n this._tinode.logger(\"INFO: Cannot send notification in inactive topic\");\n }\n }\n\n /**\n * Send a {note what='call'}. Wrapper for {@link Tinode#videoCall}.\n * @memberof Tinode#\n *\n * @param {string} evt - Call event.\n * @param {int} seq - ID of the call message the event pertains to.\n * @param {string} payload - Payload associated with this event (e.g. SDP string).\n *\n * @returns {Promise} Promise (for some call events) which will\n * be resolved/rejected on receiving server reply\n */\n videoCall(evt, seq, payload) {\n if (!this._attached && !['ringing', 'hang-up'].includes(evt)) {\n // Cannot {call} on an inactive topic\".\n return;\n }\n return this._tinode.videoCall(this.name, seq, evt, payload);\n }\n\n // Update cached read/recv/unread counts for the current user.\n _updateMyReadRecv(what, seq, ts) {\n let oldVal, doUpdate = false;\n\n seq = seq | 0;\n this.seq = this.seq | 0;\n this.read = this.read | 0;\n this.recv = this.recv | 0;\n switch (what) {\n case 'recv':\n oldVal = this.recv;\n this.recv = Math.max(this.recv, seq);\n doUpdate = (oldVal != this.recv);\n break;\n case 'read':\n oldVal = this.read;\n this.read = Math.max(this.read, seq);\n doUpdate = (oldVal != this.read);\n break;\n case 'msg':\n oldVal = this.seq;\n this.seq = Math.max(this.seq, seq);\n if (!this.touched || this.touched < ts) {\n this.touched = ts;\n }\n doUpdate = (oldVal != this.seq);\n break;\n }\n\n // Sanity checks.\n if (this.recv < this.read) {\n this.recv = this.read;\n doUpdate = true;\n }\n if (this.seq < this.recv) {\n this.seq = this.recv;\n if (!this.touched || this.touched < ts) {\n this.touched = ts;\n }\n doUpdate = true;\n }\n this.unread = this.seq - this.read;\n return doUpdate;\n }\n /**\n * Get user description from global cache. The user does not need to be a\n * subscriber of this topic.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - ID of the user to fetch.\n * @return {Object} user description or undefined.\n */\n userDesc(uid) {\n // TODO: handle asynchronous requests\n const user = this._cacheGetUser(uid);\n if (user) {\n return user; // Promise.resolve(user)\n }\n }\n /**\n * Get description of the p2p peer from subscription cache.\n * @memberof Tinode.Topic#\n *\n * @return {Object} peer's description or undefined.\n */\n p2pPeerDesc() {\n if (!this.isP2PType()) {\n return undefined;\n }\n return this._users[this.name];\n }\n /**\n * Iterate over cached subscribers. If callback is undefined, use this.onMetaSub.\n * @memberof Tinode.Topic#\n *\n * @param {function} callback - Callback which will receive subscribers one by one.\n * @param {Object=} context - Value of `this` inside the `callback`.\n */\n subscribers(callback, context) {\n const cb = (callback || this.onMetaSub);\n if (cb) {\n for (let idx in this._users) {\n cb.call(context, this._users[idx], idx, this._users);\n }\n }\n }\n /**\n * Get a copy of cached tags.\n * @memberof Tinode.Topic#\n *\n * @return {Array.} a copy of tags\n */\n tags() {\n // Return a copy.\n return this._tags.slice(0);\n }\n /**\n * Get auxiliary entry by key.\n * @memberof Tinode.Topic#\n * @param {string} key - auxiliary data key to retrieve.\n * @return {Object} value for the key or undefined.\n */\n aux(key) {\n return this._aux[key];\n }\n /**\n * Get alias value (unique tag with alias: prefix), if present.\n * The prefix is stripped off.\n * @memberof Tinode.Topic#\n * @return {string} alias or undefined.\n */\n alias() {\n const alias = this._tags && this._tags.find(t => t.startsWith(Const.TAG_ALIAS));\n if (!alias) {\n return undefined;\n }\n // Remove 'alias:' prefix.\n return alias.substring(Const.TAG_ALIAS.length);\n }\n\n /**\n * Get cached subscription for the given user ID.\n * @memberof Tinode.Topic#\n *\n * @param {string} uid - id of the user to query for\n * @return user description or undefined.\n */\n subscriber(uid) {\n return this._users[uid];\n }\n /**\n * Iterate over versions of a message: call callback for each version (excluding original).\n * If callback is undefined, does nothing.\n * @memberof Tinode.Topic#\n *\n * @param {number} origSeq - seq ID of the original message.\n * @param {Tinode.ForEachCallbackType} callback - Callback which will receive messages one by one. See {@link Tinode.CBuffer#forEach}\n * @param {Object} context - Value of `this` inside the `callback`.\n */\n messageVersions(origSeq, callback, context) {\n if (!callback) {\n // No callback? We are done then.\n return;\n }\n const versions = this._messageVersions[origSeq];\n if (!versions) {\n return;\n }\n versions.forEach(callback, undefined, undefined, context);\n }\n /**\n * Iterate over cached messages: call callback for each message in the range [sinceIdx, beforeIdx).\n * If callback is undefined, use this.onData.\n * @memberof Tinode.Topic#\n *\n * @param {Tinode.ForEachCallbackType} callback - Callback which will receive messages one by one. See {@link Tinode.CBuffer#forEach}\n * @param {number} sinceId - Optional seqId to start iterating from (inclusive).\n * @param {number} beforeId - Optional seqId to stop iterating before it is reached (exclusive).\n * @param {Object} context - Value of `this` inside the `callback`.\n */\n messages(callback, sinceId, beforeId, context) {\n const cb = (callback || this.onData);\n if (cb) {\n const startIdx = typeof sinceId == 'number' ? this._messages.find({\n seq: sinceId\n }, true) : undefined;\n const beforeIdx = typeof beforeId == 'number' ? this._messages.find({\n seq: beforeId\n }, true) : undefined;\n if (startIdx != -1 && beforeIdx != -1) {\n // Step 1. Filter out all replacement messages and\n // save displayable messages in a temporary buffer.\n let msgs = [];\n this._messages.forEach((msg, unused1, unused2, i) => {\n if (Topic.#isReplacementMsg(msg)) {\n // Skip replacements.\n return;\n }\n if (msg._deleted) {\n // Skip deleted ranges.\n return;\n }\n // In case the massage was edited, replace timestamp of the version with the original's timestamp.\n const latest = this.latestMsgVersion(msg.seq) || msg;\n if (!latest._origTs) {\n latest._origTs = latest.ts;\n latest._origSeq = latest.seq;\n latest.ts = msg.ts;\n latest.seq = msg.seq;\n }\n msgs.push({\n data: latest,\n idx: i\n });\n }, startIdx, beforeIdx, {});\n // Step 2. Loop over displayble messages invoking cb on each of them.\n msgs.forEach((val, i) => {\n cb.call(context, val.data,\n (i > 0 ? msgs[i - 1].data : undefined),\n (i < msgs.length - 1 ? msgs[i + 1].data : undefined), val.idx);\n });\n }\n }\n }\n /**\n * Get the message from cache by literal seq (does not resolve message edits).\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - message seqId to search for.\n * @returns {Object} the message with the given seq or undefined, if no such message is found.\n */\n findMessage(seq) {\n const idx = this._messages.find({\n seq: seq\n });\n if (idx >= 0) {\n return this._messages.getAt(idx);\n }\n return undefined;\n }\n /**\n * Get the most recent non-deleted message from cache.\n * @memberof Tinode.Topic#\n *\n * @returns {Object} the most recent cached message or undefined, if no messages are cached.\n */\n latestMessage() {\n return this._messages.getLast(msg => !msg._deleted);\n }\n /**\n * Get the latest version for message.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - original seq ID of the message.\n * @returns {Object} the latest version of the message or null if message not found.\n */\n latestMsgVersion(seq) {\n const versions = this._messageVersions[seq];\n return versions ? versions.getLast() : null;\n }\n /**\n * Get the maximum cached seq ID.\n * @memberof Tinode.Topic#\n *\n * @returns {number} the greatest seq ID in cache.\n */\n maxMsgSeq() {\n return this._maxSeq;\n }\n /**\n * Get the minimum cached seq ID.\n * @memberof Tinode.Topic#\n *\n * @returns {number} the smallest seq ID in cache or 0.\n */\n minMsgSeq() {\n return this._minSeq;\n }\n /**\n * Get the maximum deletion ID.\n * @memberof Tinode.Topic#\n *\n * @returns {number} the greatest deletion ID.\n */\n maxClearId() {\n return this._maxDel;\n }\n /**\n * Get the number of messages in the cache.\n * @memberof Tinode.Topic#\n *\n * @returns {number} count of cached messages.\n */\n messageCount() {\n return this._messages.length();\n }\n /**\n * Iterate over cached unsent messages. Wraps {@link Tinode.Topic#messages}.\n * @memberof Tinode.Topic#\n *\n * @param {function} callback - Callback which will receive messages one by one. See {@link Tinode.CBuffer#forEach}\n * @param {Object} context - Value of this inside the callback.\n */\n queuedMessages(callback, context) {\n if (!callback) {\n throw new Error(\"Callback must be provided\");\n }\n this.messages(callback, Const.LOCAL_SEQID, undefined, context);\n }\n /**\n * Get the number of topic subscribers who marked this message as either recv or read\n * Current user is excluded from the count.\n * @memberof Tinode.Topic#\n *\n * @param {string} what - what action to consider: received \"recv\" or read \"read\".\n * @param {number} seq - ID or the message read or received.\n *\n * @returns {number} the number of subscribers who marked the message with the given ID as read or received.\n */\n msgReceiptCount(what, seq) {\n let count = 0;\n if (seq > 0) {\n const me = this._tinode.getCurrentUserID();\n for (let idx in this._users) {\n const user = this._users[idx];\n if (user.user !== me && user[what] >= seq) {\n count++;\n }\n }\n }\n return count;\n }\n /**\n * Get the number of topic subscribers who marked this message (and all older messages) as read.\n * The current user is excluded from the count.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - message id to check.\n * @returns {number} number of subscribers who claim to have received the message.\n */\n msgReadCount(seq) {\n return this.msgReceiptCount('read', seq);\n }\n /**\n * Get the number of topic subscribers who marked this message (and all older messages) as received.\n * The current user is excluded from the count.\n * @memberof Tinode.Topic#\n *\n * @param {number} seq - Message id to check.\n * @returns {number} Number of subscribers who claim to have received the message.\n */\n msgRecvCount(seq) {\n return this.msgReceiptCount('recv', seq);\n }\n /**\n * Check if cached message IDs indicate that the server may have more messages.\n * @memberof Tinode.Topic#\n *\n * @param {number} min - smallest seq ID loaded range.\n * @param {number} max - greatest seq ID in loaded range.\n * @param {boolean} newer - if true, check for newer messages only.\n * @returns {Array.} - missing ranges in the selected direction.\n */\n msgHasMoreMessages(min, max, newer) {\n // Find gaps in cached messages.\n const gaps = [];\n if (min >= max) {\n return gaps;\n }\n let maxSeq = 0;\n let gap;\n this._messages.forEach((msg, prev) => {\n const p = prev || {\n seq: 0\n };\n const expected = p._deleted ? p.hi : p.seq + 1;\n if (msg.seq > expected) {\n gap = {\n low: expected,\n hi: msg.seq\n };\n } else {\n gap = null;\n }\n // If newer: collect all gaps from min to infinity.\n // If older: collect all gaps from max to zero.\n if (gap && (newer ? gap.hi >= min : gap.low < max)) {\n gaps.push(gap);\n }\n maxSeq = expected;\n });\n\n if (maxSeq < this.seq) {\n gap = {\n low: maxSeq + 1,\n hi: this.seq + 1\n };\n if (newer ? gap.hi >= min : gap.low < max) {\n gaps.push(gap);\n }\n }\n return gaps;\n }\n /**\n * Check if the given seq Id is id of the most recent message.\n * @memberof Tinode.Topic#\n *\n * @param {number} seqId id of the message to check\n */\n isNewMessage(seqId) {\n return this._maxSeq <= seqId;\n }\n /**\n * Remove one message from local cache.\n * @memberof Tinode.Topic#\n *\n * @param {number} seqId id of the message to remove from cache.\n * @returns {Message} removed message or undefined if such message was not found.\n */\n flushMessage(seqId) {\n const idx = this._messages.find({\n seq: seqId\n });\n delete this._messageVersions[seqId];\n if (idx >= 0) {\n this._tinode._db.remMessages(this.name, seqId);\n return this._messages.delAt(idx);\n }\n return undefined;\n }\n /**\n * Remove a range of messages from the local cache.\n * @memberof Tinode.Topic#\n *\n * @param {number} fromId seq ID of the first message to remove (inclusive).\n * @param {number} untilId seqID of the last message to remove (exclusive).\n *\n * @returns {Message[]} array of removed messages (could be empty).\n */\n flushMessageRange(fromId, untilId) {\n // Remove range from persistent cache.\n this._tinode._db.remMessages(this.name, fromId, untilId);\n\n // Remove all versions keyed by IDs in the range.\n for (let i = fromId; i < untilId; i++) {\n delete this._messageVersions[i];\n }\n\n // start, end: find insertion points (nearest == true).\n const since = this._messages.find({\n seq: fromId\n }, true);\n return since >= 0 ? this._messages.delRange(since, this._messages.find({\n seq: untilId\n }, true)) : [];\n }\n /**\n * Update message's seqId.\n * @memberof Tinode.Topic#\n *\n * @param {Object} pub message object.\n * @param {number} newSeqId new seq id for pub.\n */\n swapMessageId(pub, newSeqId) {\n const idx = this._messages.find(pub);\n const numMessages = this._messages.length();\n if (0 <= idx && idx < numMessages) {\n // Remove message with the old seq ID.\n this._messages.delAt(idx);\n this._tinode._db.remMessages(this.name, pub.seq);\n // Add message with the new seq ID.\n pub.seq = newSeqId;\n this._messages.put(pub);\n this._tinode._db.addMessage(pub);\n }\n }\n /**\n * Attempt to stop message from being sent.\n * @memberof Tinode.Topic#\n *\n * @param {number} seqId id of the message to stop sending and remove from cache.\n *\n * @returns {boolean} true if message was cancelled, false otherwise.\n */\n cancelSend(seqId) {\n const idx = this._messages.find({\n seq: seqId\n });\n if (idx >= 0) {\n const msg = this._messages.getAt(idx);\n const status = this.msgStatus(msg);\n if (status == Const.MESSAGE_STATUS_QUEUED ||\n status == Const.MESSAGE_STATUS_FAILED ||\n status == Const.MESSAGE_STATUS_FATAL) {\n this._tinode._db.remMessages(this.name, seqId);\n msg._cancelled = true;\n this._messages.delAt(idx);\n if (this.onData) {\n // Calling with no parameters to indicate the message was deleted.\n this.onData();\n }\n return true;\n }\n }\n return false;\n }\n /**\n * Get type of the topic: me, p2p, grp, fnd...\n * @memberof Tinode.Topic#\n *\n * @returns {string} One of 'me', 'p2p', 'grp', 'fnd', 'sys' or undefined.\n */\n getType() {\n return Topic.topicType(this.name);\n }\n /**\n * Get current user's access mode of the topic.\n * @memberof Tinode.Topic#\n *\n * @returns {Tinode.AccessMode} - user's access mode\n */\n getAccessMode() {\n return this.acs;\n }\n /**\n * Set current user's access mode of the topic.\n * @memberof Tinode.Topic#\n *\n * @param {AccessMode | Object} acs - access mode to set.\n */\n setAccessMode(acs) {\n return this.acs = new AccessMode(acs);\n }\n /**\n * Get topic's default access mode.\n * @memberof Tinode.Topic#\n *\n * @returns {Tinode.DefAcs} - access mode, such as {auth: `RWP`, anon: `N`}.\n */\n getDefaultAccess() {\n return this.defacs;\n }\n /**\n * Initialize new meta {@link Tinode.GetQuery} builder. The query is attched to the current topic.\n * It will not work correctly if used with a different topic.\n * @memberof Tinode.Topic#\n *\n * @returns {Tinode.MetaGetBuilder} query attached to the current topic.\n */\n startMetaQuery() {\n return new MetaGetBuilder(this);\n }\n /**\n * Check if topic is archived, i.e. private.arch == true.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is archived, false otherwise.\n */\n isArchived() {\n return this.private && !!this.private.arch;\n }\n /**\n * Check if topic is a 'me' topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a 'me' topic, false otherwise.\n */\n isMeType() {\n return Topic.isMeTopicName(this.name);\n }\n /**\n * Check if topic is a 'slf' topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a 'slf' topic, false otherwise.\n */\n isSelfType() {\n return Topic.isSelfTopicName(this.name);\n }\n /**\n * Check if topic is a channel.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a channel, false otherwise.\n */\n isChannelType() {\n return Topic.isChannelTopicName(this.name);\n }\n /**\n * Check if topic is a group topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a group, false otherwise.\n */\n isGroupType() {\n return Topic.isGroupTopicName(this.name);\n }\n /**\n * Check if topic is a p2p topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a p2p topic, false otherwise.\n */\n isP2PType() {\n return Topic.isP2PTopicName(this.name);\n }\n /**\n * Check if topic is a communication topic, i.e. a group or p2p topic.\n * @memberof Tinode.Topic#\n *\n * @returns {boolean} - true if topic is a p2p or group topic, false otherwise.\n */\n isCommType() {\n return Topic.isCommTopicName(this.name);\n }\n /**\n * Get status (queued, sent, received etc) of a given message in the context\n * of this topic.\n * @memberof Tinode.Topic#\n *\n * @param {Message} msg - message to check for status.\n * @param {boolean} upd - update chached message status.\n *\n * @returns message status constant.\n */\n msgStatus(msg, upd) {\n let status = Const.MESSAGE_STATUS_NONE;\n if (this._tinode.isMe(msg.from)) {\n if (msg._sending) {\n status = Const.MESSAGE_STATUS_SENDING;\n } else if (msg._fatal || msg._cancelled) {\n status = Const.MESSAGE_STATUS_FATAL;\n } else if (msg._failed) {\n status = Const.MESSAGE_STATUS_FAILED;\n } else if (msg.seq >= Const.LOCAL_SEQID) {\n status = Const.MESSAGE_STATUS_QUEUED;\n } else if (this.msgReadCount(msg.seq) > 0) {\n status = Const.MESSAGE_STATUS_READ;\n } else if (this.msgRecvCount(msg.seq) > 0) {\n status = Const.MESSAGE_STATUS_RECEIVED;\n } else if (msg.seq > 0) {\n status = Const.MESSAGE_STATUS_SENT;\n }\n } else {\n status = Const.MESSAGE_STATUS_TO_ME;\n }\n\n if (upd && msg._status != status) {\n msg._status = status;\n this._tinode._db.updMessageStatus(this.name, msg.seq, status);\n }\n\n return status;\n }\n\n // If msg is a replacement for another message, save the msg in the message versions cache\n // as a newer version for the message it's supposed to replace.\n _maybeUpdateMessageVersionsCache(msg) {\n if (!Topic.#isReplacementMsg(msg)) {\n // Check if this message is the original in the chain of edits and if so\n // ensure all version have the same sender.\n if (this._messageVersions[msg.seq]) {\n // Remove versions with different 'from'.\n this._messageVersions[msg.seq].filter(version => version.from == msg.from);\n if (this._messageVersions[msg.seq].isEmpty()) {\n delete this._messageVersions[msg.seq];\n }\n }\n return;\n }\n\n const targetSeq = parseInt(msg.head.replace.split(':')[1]);\n if (targetSeq > msg.seq) {\n // Substitutes are supposed to have higher seq ids.\n return;\n }\n const targetMsg = this.findMessage(targetSeq);\n if (targetMsg && targetMsg.from != msg.from) {\n // Substitute cannot change the sender.\n return;\n }\n const versions = this._messageVersions[targetSeq] || new CBuffer((a, b) => {\n return a.seq - b.seq;\n }, true);\n versions.put(msg);\n this._messageVersions[targetSeq] = versions;\n }\n\n // Process data message\n _routeData(data) {\n if (data.content) {\n if (!this.touched || this.touched < data.ts) {\n this.touched = data.ts;\n this._tinode._db.updTopic(this);\n }\n }\n\n if (data.seq > this._maxSeq) {\n this._maxSeq = data.seq;\n this.msgStatus(data, true);\n // Ackn receiving the message.\n clearTimeout(this._recvNotificationTimer);\n this._recvNotificationTimer = setTimeout(_ => {\n this._recvNotificationTimer = null;\n this.noteRecv(this._maxSeq);\n }, Const.RECV_TIMEOUT);\n }\n\n if (data.seq < this._minSeq || this._minSeq == 0) {\n this._minSeq = data.seq;\n }\n\n const outgoing = ((!this.isChannelType() && !data.from) || this._tinode.isMe(data.from));\n\n if (data.head && data.head.webrtc && data.head.mime == Drafty.getContentType() && data.content) {\n // Rewrite VC body with info from the headers.\n const upd = {\n state: data.head.webrtc,\n duration: data.head['webrtc-duration'],\n incoming: !outgoing,\n };\n if (data.head.vc) {\n upd.vc = true;\n }\n data.content = Drafty.updateVideoCall(data.content, upd);\n }\n\n if (!data._noForwarding) {\n this._messages.put(data);\n this._tinode._db.addMessage(data);\n this._maybeUpdateMessageVersionsCache(data);\n }\n\n if (this.onData) {\n this.onData(data);\n }\n\n // Update locally cached contact with the new message count.\n const what = outgoing ? 'read' : 'msg';\n this._updateMyReadRecv(what, data.seq, data.ts);\n\n if (!outgoing && data.from) {\n // Mark messages as read by the sender.\n this._routeInfo({\n what: 'read',\n from: data.from,\n seq: data.seq,\n _noForwarding: true\n });\n }\n\n // Notify 'me' listeners of the change.\n this._tinode.getMeTopic()._refreshContact(what, this);\n }\n\n // Process metadata message\n _routeMeta(meta) {\n if (meta.desc) {\n this._processMetaDesc(meta.desc);\n }\n if (meta.sub && meta.sub.length > 0) {\n this._processMetaSubs(meta.sub);\n }\n if (meta.del) {\n this._processDelMessages(meta.del.clear, meta.del.delseq);\n }\n if (meta.tags) {\n this._processMetaTags(meta.tags);\n }\n if (meta.cred) {\n this._processMetaCreds(meta.cred);\n }\n if (meta.aux) {\n this._processMetaAux(meta.aux);\n }\n if (this.onMeta) {\n this.onMeta(meta);\n }\n }\n // Process presence change message\n _routePres(pres) {\n let user, uid;\n switch (pres.what) {\n case 'del':\n // Delete cached messages.\n this._processDelMessages(pres.clear, pres.delseq);\n break;\n case 'on':\n case 'off':\n // Update online status of a subscription.\n user = this._users[pres.src];\n if (user) {\n user.online = pres.what == 'on';\n } else {\n this._tinode.logger(\"WARNING: Presence update for an unknown user\", this.name, pres.src);\n }\n break;\n case 'term':\n // Attachment to topic is terminated probably due to cluster rehashing.\n this._resetSub();\n break;\n case 'upd':\n // A topic subscriber has updated his description.\n // Issue {get sub} only if the current user has no p2p topics with the updated user (p2p name is not in cache).\n // Otherwise 'me' will issue a {get desc} request.\n if (pres.src && !this._tinode.isTopicCached(pres.src)) {\n this.getMeta(this.startMetaQuery().withOneSub(undefined, pres.src).build());\n }\n break;\n case 'aux':\n // Auxiliary data updated.\n this.getMeta(this.startMetaQuery().withAux().build());\n break;\n case 'acs':\n uid = pres.src || this._tinode.getCurrentUserID();\n user = this._users[uid];\n if (!user) {\n // Update for an unknown user: notification of a new subscription.\n const acs = new AccessMode().updateAll(pres.dacs);\n if (acs && acs.mode != AccessMode._NONE) {\n user = this._cacheGetUser(uid);\n if (!user) {\n user = {\n user: uid,\n acs: acs\n };\n this.getMeta(this.startMetaQuery().withOneSub(undefined, uid).build());\n } else {\n user.acs = acs;\n }\n user.updated = new Date();\n this._processMetaSubs([user]);\n }\n } else {\n // Known user\n user.acs.updateAll(pres.dacs);\n // Update user's access mode.\n this._processMetaSubs([{\n user: uid,\n updated: new Date(),\n acs: user.acs\n }]);\n }\n break;\n default:\n this._tinode.logger(\"INFO: Ignored presence update\", pres.what);\n }\n\n if (this.onPres) {\n this.onPres(pres);\n }\n }\n // Process {info} message\n _routeInfo(info) {\n switch (info.what) {\n case 'recv':\n case 'read':\n const user = this._users[info.from];\n if (user) {\n user[info.what] = info.seq;\n if (user.recv < user.read) {\n user.recv = user.read;\n }\n }\n const msg = this.latestMessage();\n if (msg) {\n this.msgStatus(msg, true);\n }\n\n // If this is an update from the current user, update the cache with the new count.\n if (this._tinode.isMe(info.from) && !info._noForwarding) {\n this._updateMyReadRecv(info.what, info.seq);\n }\n\n // Notify 'me' listener of the status change.\n this._tinode.getMeTopic()._refreshContact(info.what, this);\n break;\n case 'kp':\n case 'kpa':\n case 'kpv':\n // Typing or audio/video recording notification. Do nothing.\n break;\n case 'call':\n // Do nothing here.\n break;\n default:\n this._tinode.logger(\"INFO: Ignored info update\", info.what);\n }\n\n if (this.onInfo) {\n this.onInfo(info);\n }\n }\n // Called by Tinode when meta.desc packet is received.\n // Called by 'me' topic on contact update (desc._noForwarding is true).\n _processMetaDesc(desc) {\n if (this.isP2PType()) {\n // Synthetic desc may include defacs for p2p topics which is useless.\n // Remove it.\n delete desc.defacs;\n\n // Update to p2p desc is the same as user update. Update cached user.\n this._tinode._db.updUser(this.name, desc.public);\n }\n\n // Copy parameters from desc object to this topic.\n mergeObj(this, desc);\n // Update persistent cache.\n this._tinode._db.updTopic(this);\n\n // Notify 'me' listener, if available:\n if (this.name !== Const.TOPIC_ME && !desc._noForwarding) {\n const me = this._tinode.getMeTopic();\n if (me.onMetaSub) {\n me.onMetaSub(this);\n }\n if (me.onSubsUpdated) {\n me.onSubsUpdated([this.name], 1);\n }\n }\n\n if (this.onMetaDesc) {\n this.onMetaDesc(this);\n }\n }\n // Called by Tinode when meta.sub is recived or in response to received\n // {ctrl} after setMeta-sub.\n _processMetaSubs(subs) {\n for (let idx in subs) {\n const sub = subs[idx];\n\n // Fill defaults.\n sub.online = !!sub.online;\n // Update timestamp of the most recent subscription update.\n this._lastSubsUpdate = new Date(Math.max(this._lastSubsUpdate, sub.updated));\n\n let user = null;\n if (!sub.deleted) {\n // If this is a change to user's own permissions, update them in topic too.\n // Desc will update 'me' topic.\n if (this._tinode.isMe(sub.user) && sub.acs) {\n this._processMetaDesc({\n updated: sub.updated,\n touched: sub.touched,\n acs: sub.acs\n });\n }\n user = this._updateCachedUser(sub.user, sub);\n } else {\n // Subscription is deleted, remove it from topic (but leave in Users cache)\n delete this._users[sub.user];\n user = sub;\n }\n\n if (this.onMetaSub) {\n this.onMetaSub(user);\n }\n }\n\n if (this.onSubsUpdated) {\n this.onSubsUpdated(Object.keys(this._users));\n }\n }\n // Called by Tinode when meta.tags is recived.\n _processMetaTags(tags) {\n if (tags == Const.DEL_CHAR || (tags.length == 1 && tags[0] == Const.DEL_CHAR)) {\n tags = [];\n }\n this._tags = tags;\n this._tinode._db.updTopic(this);\n if (this.onTagsUpdated) {\n this.onTagsUpdated(tags);\n }\n }\n // Do nothing for topics other than 'me'\n _processMetaCreds(creds) {}\n\n // Called by Tinode when meta.aux is recived.\n _processMetaAux(aux) {\n aux = (!aux || aux == Const.DEL_CHAR) ? {} : aux;\n this._aux = mergeObj(this._aux, aux);\n this._tinode._db.updTopic(this);\n if (this.onAuxUpdated) {\n this.onAuxUpdated(this._aux);\n }\n }\n\n // Delete cached messages and update cached transaction IDs\n _processDelMessages(clear, delseq) {\n this._maxDel = Math.max(clear, this._maxDel);\n this.clear = Math.max(clear, this.clear);\n let count = 0;\n if (Array.isArray(delseq)) {\n delseq.forEach(rec => {\n if (!rec.hi) {\n count++;\n this.flushMessage(rec.low);\n } else {\n count += rec.hi - rec.low;\n this.flushMessageRange(rec.low, rec.hi);\n }\n this._messages.put({\n seq: rec.low,\n low: rec.low,\n hi: rec.hi,\n _deleted: true\n });\n });\n\n this._tinode._db.addDelLog(this.name, clear, delseq);\n }\n\n if (count > 0) {\n if (this.onData) {\n this.onData();\n }\n }\n }\n // Topic is informed that the entire response to {get what=data} has been received.\n _allMessagesReceived(count) {\n\n if (this.onAllMessagesReceived) {\n this.onAllMessagesReceived(count);\n }\n }\n // Reset subscribed state\n _resetSub() {\n this._attached = false;\n }\n // This topic is either deleted or unsubscribed from.\n _gone() {\n this._messages.reset();\n this._tinode._db.remMessages(this.name);\n this._users = {};\n this.acs = new AccessMode(null);\n this.private = null;\n this.public = null;\n this.trusted = null;\n this._maxSeq = 0;\n this._minSeq = 0;\n this._attached = false;\n\n const me = this._tinode.getMeTopic();\n if (me) {\n me._routePres({\n _noForwarding: true,\n what: 'gone',\n topic: Const.TOPIC_ME,\n src: this.name\n });\n }\n if (this.onDeleteTopic) {\n this.onDeleteTopic();\n }\n }\n // Update global user cache and local subscribers cache.\n // Don't call this method for non-subscribers.\n _updateCachedUser(uid, obj) {\n // Fetch user object from the global cache.\n // This is a clone of the stored object\n let cached = this._cacheGetUser(uid);\n cached = mergeObj(cached || {}, obj);\n // Save to global cache\n this._cachePutUser(uid, cached);\n // Save to the list of topic subsribers.\n return mergeToCache(this._users, uid, cached);\n }\n // Get local seqId for a queued message.\n _getQueuedSeqId() {\n return this._queuedSeqId++;\n }\n\n // Load most recent messages from persistent cache.\n _loadMessages(db, query) {\n query = query || {};\n query.limit = query.limit || Const.DEFAULT_MESSAGES_PAGE;\n\n // Count of message loaded from DB.\n let count = 0;\n return db.readMessages(this.name, query)\n .then(msgs => {\n msgs.forEach(data => {\n if (data.seq > this._maxSeq) {\n this._maxSeq = data.seq;\n }\n if (data.seq < this._minSeq || this._minSeq == 0) {\n this._minSeq = data.seq;\n }\n this._messages.put(data);\n this._maybeUpdateMessageVersionsCache(data);\n });\n count = msgs.length;\n })\n .then(_ => db.readDelLog(this.name, query))\n .then(dellog => {\n return dellog.forEach(rec => {\n this._messages.put({\n seq: rec.low,\n low: rec.low,\n hi: rec.hi,\n _deleted: true\n });\n });\n })\n .then(_ => {\n // DEBUG\n return count;\n });\n }\n\n // Push or {pres}: message received.\n _updateReceived(seq, act) {\n this.touched = new Date();\n this.seq = seq | 0;\n // Check if message is sent by the current user. If so it's been read already.\n if (!act || this._tinode.isMe(act)) {\n this.read = this.read ? Math.max(this.read, this.seq) : this.seq;\n this.recv = this.recv ? Math.max(this.read, this.recv) : this.read;\n }\n this.unread = this.seq - (this.read | 0);\n this._tinode._db.updTopic(this);\n }\n}\n","/**\n * @file Definition of 'fnd' topic.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport * as Const from './config.js';\nimport Topic from './topic.js';\nimport {\n mergeToCache\n} from './utils.js';\n\n\n/**\n * Special case of {@link Tinode.Topic} for searching for contacts and group topics\n * @extends Tinode.Topic\n *\n */\nexport default class TopicFnd extends Topic {\n // List of users and topics uid or topic_name -> Contact object)\n _contacts = {};\n\n /**\n * Create TopicFnd.\n *\n * @param {TopicFnd.Callbacks} callbacks - Callbacks to receive various events.\n */\n constructor(callbacks) {\n super(Const.TOPIC_FND, callbacks);\n }\n\n // Override the original Topic._processMetaSubs\n _processMetaSubs(subs) {\n let updateCount = Object.getOwnPropertyNames(this._contacts).length;\n // Reset contact list.\n this._contacts = {};\n for (let idx in subs) {\n let sub = subs[idx];\n const indexBy = sub.topic ? sub.topic : sub.user;\n\n sub = mergeToCache(this._contacts, indexBy, sub);\n updateCount++;\n\n if (this.onMetaSub) {\n this.onMetaSub(sub);\n }\n }\n\n if (updateCount > 0 && this.onSubsUpdated) {\n this.onSubsUpdated(Object.keys(this._contacts));\n }\n }\n\n /**\n * Publishing to TopicFnd is not supported. {@link Topic#publish} is overriden and thows an {Error} if called.\n * @memberof Tinode.TopicFnd#\n * @throws {Error} Always throws an error.\n */\n publish() {\n return Promise.reject(new Error(\"Publishing to 'fnd' is not supported\"));\n }\n\n /**\n * setMeta to TopicFnd resets contact list in addition to sending the message.\n * @memberof Tinode.TopicFnd#\n * @param {Tinode.SetParams} params parameters to update.\n * @returns {Promise} Promise to be resolved/rejected when the server responds to request.\n */\n setMeta(params) {\n return Object.getPrototypeOf(TopicFnd.prototype).setMeta.call(this, params).then(_ => {\n if (Object.keys(this._contacts).length > 0) {\n this._contacts = {};\n if (this.onSubsUpdated) {\n this.onSubsUpdated([]);\n }\n }\n });\n }\n\n /**\n * Check if the given tag is unique by asking the server.\n * @param tag tag to check.\n * @return promise to be resolved with true if the tag is unique, false otherwise.\n */\n checkTagUniqueness(tag, caller) {\n return new Promise((resolve, reject) => {\n this.subscribe()\n .then(_ => this.setMeta({\n desc: {\n public: tag\n }\n }))\n .then(_ => this.getMeta(this.startMetaQuery().withTags().build()))\n .then(meta => {\n if (!meta || !Array.isArray(meta.tags) || meta.tags.length == 0) {\n resolve(true);\n }\n const tags = meta.tags.filter(t => t !== caller);\n resolve(tags.length == 0);\n })\n .catch(err => {\n reject(err);\n });\n });\n }\n\n /**\n * Iterate over found contacts. If callback is undefined, use {@link this.onMetaSub}.\n * @function\n * @memberof Tinode.TopicFnd#\n * @param {TopicFnd.ContactCallback} callback - Callback to call for each contact.\n * @param {Object} context - Context to use for calling the `callback`, i.e. the value of `this` inside the callback.\n */\n contacts(callback, context) {\n const cb = (callback || this.onMetaSub);\n if (cb) {\n for (let idx in this._contacts) {\n cb.call(context, this._contacts[idx], idx, this._contacts);\n }\n }\n }\n}\n","/**\n * @file Definition of 'me' topic.\n *\n * @copyright 2015-2023 Tinode LLC.\n */\n'use strict';\n\nimport AccessMode from './access-mode.js';\nimport * as Const from './config.js';\nimport Topic from './topic.js';\nimport {\n mergeObj\n} from './utils.js';\n\n/**\n * @class TopicMe - special case of {@link Tinode.Topic} for\n * managing data of the current user, including contact list.\n * @extends Tinode.Topic\n * @memberof Tinode\n *\n * @param {TopicMe.Callbacks} callbacks - Callbacks to receive various events.\n */\nexport default class TopicMe extends Topic {\n onContactUpdate;\n\n constructor(callbacks) {\n super(Const.TOPIC_ME, callbacks);\n\n // me-specific callbacks\n if (callbacks) {\n this.onContactUpdate = callbacks.onContactUpdate;\n }\n }\n\n // Override the original Topic._processMetaDesc.\n _processMetaDesc(desc) {\n // Check if online contacts need to be turned off because P permission was removed.\n const turnOff = (desc.acs && !desc.acs.isPresencer()) && (this.acs && this.acs.isPresencer());\n\n // Copy parameters from desc object to this topic.\n mergeObj(this, desc);\n this._tinode._db.updTopic(this);\n // Update current user's record in the global cache.\n this._updateCachedUser(this._tinode._myUID, desc);\n\n // 'P' permission was removed. All topics are offline now.\n if (turnOff) {\n this._tinode.mapTopics((cont) => {\n if (cont.online) {\n cont.online = false;\n cont.seen = Object.assign(cont.seen || {}, {\n when: new Date()\n });\n this._refreshContact('off', cont);\n }\n });\n }\n\n if (this.onMetaDesc) {\n this.onMetaDesc(this);\n }\n }\n\n // Override the original Topic._processMetaSubs\n _processMetaSubs(subs) {\n let updateCount = 0;\n subs.forEach((sub) => {\n const topicName = sub.topic;\n // Don't show 'me' and 'fnd' topics in the list of contacts.\n if (topicName == Const.TOPIC_FND || topicName == Const.TOPIC_ME) {\n return;\n }\n sub.online = !!sub.online;\n\n let cont = null;\n if (sub.deleted) {\n cont = sub;\n this._tinode.cacheRemTopic(topicName);\n this._tinode._db.remTopic(topicName);\n } else {\n // Ensure the values are defined and are integers.\n if (typeof sub.seq != 'undefined') {\n sub.seq = sub.seq | 0;\n sub.recv = sub.recv | 0;\n sub.read = sub.read | 0;\n sub.unread = sub.seq - sub.read;\n }\n\n const topic = this._tinode.getTopic(topicName);\n if (topic._new) {\n delete topic._new;\n }\n\n cont = mergeObj(topic, sub);\n this._tinode._db.updTopic(cont);\n\n if (Topic.isP2PTopicName(topicName)) {\n this._cachePutUser(topicName, cont);\n this._tinode._db.updUser(topicName, cont.public);\n }\n // Notify topic of the update if it's an external update.\n if (!sub._noForwarding && topic) {\n sub._noForwarding = true;\n topic._processMetaDesc(sub);\n }\n }\n\n updateCount++;\n\n if (this.onMetaSub) {\n this.onMetaSub(cont);\n }\n });\n\n if (this.onSubsUpdated && updateCount > 0) {\n const keys = [];\n subs.forEach((s) => {\n keys.push(s.topic);\n });\n this.onSubsUpdated(keys, updateCount);\n }\n }\n\n // Called by Tinode when meta.sub is recived.\n _processMetaCreds(creds, upd) {\n if (creds.length == 1 && creds[0] == Const.DEL_CHAR) {\n creds = [];\n }\n if (upd) {\n creds.forEach((cr) => {\n if (cr.val) {\n // Adding a credential.\n let idx = this._credentials.findIndex((el) => {\n return el.meth == cr.meth && el.val == cr.val;\n });\n if (idx < 0) {\n // Not found.\n if (!cr.done) {\n // Unconfirmed credential replaces previous unconfirmed credential of the same method.\n idx = this._credentials.findIndex((el) => {\n return el.meth == cr.meth && !el.done;\n });\n if (idx >= 0) {\n // Remove previous unconfirmed credential.\n this._credentials.splice(idx, 1);\n }\n }\n this._credentials.push(cr);\n } else {\n // Found. Maybe change 'done' status.\n this._credentials[idx].done = cr.done;\n }\n } else if (cr.resp) {\n // Handle credential confirmation.\n const idx = this._credentials.findIndex((el) => {\n return el.meth == cr.meth && !el.done;\n });\n if (idx >= 0) {\n this._credentials[idx].done = true;\n }\n }\n });\n } else {\n this._credentials = creds;\n }\n if (this.onCredsUpdated) {\n this.onCredsUpdated(this._credentials);\n }\n }\n\n // Process presence change message\n _routePres(pres) {\n if (pres.what == 'term') {\n // The 'me' topic itself is detached. Mark as unsubscribed.\n this._resetSub();\n return;\n }\n\n if (pres.what == 'upd' && pres.src == Const.TOPIC_ME) {\n // Update to me's description. Request updated value.\n this.getMeta(this.startMetaQuery().withDesc().build());\n return;\n }\n\n const cont = this._tinode.cacheGetTopic(pres.src);\n if (cont) {\n switch (pres.what) {\n case 'on': // topic came online\n cont.online = true;\n break;\n case 'off': // topic went offline\n if (cont.online) {\n cont.online = false;\n cont.seen = Object.assign(cont.seen || {}, {\n when: new Date()\n });\n }\n break;\n case 'msg': // new message received\n cont._updateReceived(pres.seq, pres.act);\n break;\n case 'upd': // desc updated\n // Request updated subscription.\n this.getMeta(this.startMetaQuery().withLaterOneSub(pres.src).build());\n break;\n case 'acs': // access mode changed\n // If 'tgt' is not set then this is an update to the permissions of the current user.\n // Otherwise it's an update to group topic subscriber permissions while the topic is offline.\n // Just gnore it then.\n if (!pres.tgt) {\n if (cont.acs) {\n cont.acs.updateAll(pres.dacs);\n } else {\n cont.acs = new AccessMode().updateAll(pres.dacs);\n }\n cont.touched = new Date();\n }\n break;\n case 'ua':\n // user agent changed.\n cont.seen = {\n when: new Date(),\n ua: pres.ua\n };\n break;\n case 'recv':\n // user's other session marked some messges as received.\n pres.seq = pres.seq | 0;\n cont.recv = cont.recv ? Math.max(cont.recv, pres.seq) : pres.seq;\n break;\n case 'read':\n // user's other session marked some messages as read.\n pres.seq = pres.seq | 0;\n cont.read = cont.read ? Math.max(cont.read, pres.seq) : pres.seq;\n cont.recv = cont.recv ? Math.max(cont.read, cont.recv) : cont.recv;\n cont.unread = cont.seq - cont.read;\n break;\n case 'gone':\n // topic deleted or unsubscribed from.\n this._tinode.cacheRemTopic(pres.src);\n if (!cont._deleted) {\n cont._deleted = true;\n cont._attached = false;\n this._tinode._db.markTopicAsDeleted(pres.src, true);\n } else {\n this._tinode._db.remTopic(pres.src);\n }\n break;\n case 'del':\n // Update topic.del value.\n break;\n default:\n this._tinode.logger(\"INFO: Unsupported presence update in 'me'\", pres.what);\n }\n\n this._refreshContact(pres.what, cont);\n } else {\n if (pres.what == 'acs') {\n // New subscriptions and deleted/banned subscriptions have full\n // access mode (no + or - in the dacs string). Changes to known subscriptions are sent as\n // deltas, but they should not happen here.\n const acs = new AccessMode(pres.dacs);\n if (!acs || acs.mode == AccessMode._INVALID) {\n this._tinode.logger(\"ERROR: Invalid access mode update\", pres.src, pres.dacs);\n return;\n } else if (acs.mode == AccessMode._NONE) {\n this._tinode.logger(\"WARNING: Removing non-existent subscription\", pres.src, pres.dacs);\n return;\n } else {\n // New subscription. Send request for the full description.\n // Using .withOneSub (not .withLaterOneSub) to make sure IfModifiedSince is not set.\n this.getMeta(this.startMetaQuery().withOneSub(undefined, pres.src).build());\n // Create a dummy entry to catch online status update.\n const dummy = this._tinode.getTopic(pres.src);\n dummy.topic = pres.src;\n dummy.online = false;\n dummy.acs = acs;\n this._tinode._db.updTopic(dummy);\n }\n } else if (pres.what == 'tags') {\n this.getMeta(this.startMetaQuery().withTags().build());\n } else if (pres.what == 'msg') {\n // Message received for un unknown (previously deleted) topic.\n this.getMeta(this.startMetaQuery().withOneSub(undefined, pres.src).build());\n // Create an entry to catch updates and messages.\n const dummy = this._tinode.getTopic(pres.src);\n dummy._deleted = false;\n this._tinode._db.updTopic(dummy);\n }\n\n this._refreshContact(pres.what, cont);\n }\n\n if (this.onPres) {\n this.onPres(pres);\n }\n }\n\n // Contact is updated, execute callbacks.\n _refreshContact(what, cont) {\n if (this.onContactUpdate) {\n this.onContactUpdate(what, cont);\n }\n }\n\n /**\n * Publishing to TopicMe is not supported. {@link Topic#publish} is overriden and thows an {Error} if called.\n * @memberof Tinode.TopicMe#\n * @throws {Error} Always throws an error.\n */\n publish() {\n return Promise.reject(new Error(\"Publishing to 'me' is not supported\"));\n }\n\n /**\n * Delete validation credential.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} topic - Name of the topic to delete\n * @param {string} user - User ID to remove.\n * @returns {Promise} Promise which will be resolved/rejected on receiving server reply.\n */\n delCredential(method, value) {\n if (!this._attached) {\n return Promise.reject(new Error(\"Cannot delete credential in inactive 'me' topic\"));\n }\n // Send {del} message, return promise\n return this._tinode.delCredential(method, value).then(ctrl => {\n // Remove deleted credential from the cache.\n const index = this._credentials.findIndex((el) => {\n return el.meth == method && el.val == value;\n });\n if (index > -1) {\n this._credentials.splice(index, 1);\n }\n // Notify listeners\n if (this.onCredsUpdated) {\n this.onCredsUpdated(this._credentials);\n }\n return ctrl;\n });\n }\n\n /**\n * @callback contactFilter\n * @param {Object} contact to check for inclusion.\n * @returns {boolean} true if contact should be processed, false to exclude it.\n */\n /**\n * Iterate over cached contacts.\n *\n * @function\n * @memberof Tinode.TopicMe#\n * @param {TopicMe.ContactCallback} callback - Callback to call for each contact.\n * @param {contactFilter=} filter - Optionally filter contacts; include all if filter is false-ish, otherwise\n * include those for which filter returns true-ish.\n * @param {Object=} context - Context to use for calling the `callback`, i.e. the value of `this` inside the callback.\n */\n contacts(callback, filter, context) {\n this._tinode.mapTopics((c, idx) => {\n if (c.isCommType() && (!filter || filter(c))) {\n callback.call(context, c, idx);\n }\n });\n }\n\n /**\n * Get a contact from cache.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} name - Name of the contact to get, either a UID (for p2p topics) or a topic name.\n * @returns {Tinode.Contact} - Contact or `undefined`.\n */\n getContact(name) {\n return this._tinode.cacheGetTopic(name);\n }\n\n /**\n * Get access mode of a given contact from cache.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} name - Name of the contact to get access mode for, either a UID (for p2p topics)\n * or a topic name; if missing, access mode for the 'me' topic itself.\n * @returns {string} - access mode, such as `RWP`.\n */\n getAccessMode(name) {\n if (name) {\n const cont = this._tinode.cacheGetTopic(name);\n return cont ? cont.acs : null;\n }\n return this.acs;\n }\n\n /**\n * Check if contact is archived, i.e. contact.private.arch == true.\n * @memberof Tinode.TopicMe#\n *\n * @param {string} name - Name of the contact to check archived status, either a UID (for p2p topics) or a topic name.\n * @returns {boolean} - true if contact is archived, false otherwise.\n */\n isArchived(name) {\n const cont = this._tinode.cacheGetTopic(name);\n return cont && cont.private && !!cont.private.arch;\n }\n\n /**\n * @typedef Tinode.Credential\n * @memberof Tinode\n * @type Object\n * @property {string} meth - validation method such as 'email' or 'tel'.\n * @property {string} val - credential value, i.e. 'jdoe@example.com' or '+17025551234'\n * @property {boolean} done - true if credential is validated.\n */\n /**\n * Get the user's credentials: email, phone, etc.\n * @memberof Tinode.TopicMe#\n *\n * @returns {Tinode.Credential[]} - array of credentials.\n */\n getCredentials() {\n return this._credentials;\n }\n}\n"],"names":["root","factory","exports","module","define","amd","this","JSON_MIME_TYPE","JSON_MIME_TYPE_LEGACY","ALLOWED_ENT_FIELDS","segmenter","Intl","Segmenter","INLINE_STYLES","name","start","end","FMT_WEIGHT","ENTITY_TYPES","dataName","pack","val","test","url","re","slice","FORMAT_TAGS","AU","html_tag","md_tag","undefined","isVoid","BN","BR","CO","DL","EM","EX","FM","HD","HL","HT","IM","LN","MN","RW","QQ","ST","VC","VD","base64toObjectUrl","b64","contentType","logger","bin","atob","length","buf","ArrayBuffer","arr","Uint8Array","i","charCodeAt","URL","createObjectURL","Blob","type","err","message","base64toDataUrl","DECORATORS","open","_","close","data","props","href","target","id","act","ref","mime","Drafty","src","duration","size","tmpPreviewUrl","_tempPreview","previewUrl","downloadUrl","width","height","title","alt","state","preview","premime","poster","preref","txt","fmt","ent","chunkify","line","spans","chunks","span","at","push","chunk","tp","chld","children","toSpanTree","tree","last","draftyToTree","doc","Array","isArray","text","len","key","attachments","forEach","includes","stringToGraphemes","sort","a","b","diff","indexOf","graphemes","spansToTree","treeTopDown","node","child","parent","addNode","n","map","segment","join","att","subspans","inner","tag","treeToDrafty","keymap","c","Object","keys","newKey","transformer","context","dst","call","treeBottomUp","formatter","index","stack","values","pop","shortenTree","limit","tail","lightEntity","allow","copyEntData","lTrim","trimStart","shift","attachmentsToEnd","concat","draftify","startAt","plain","ranges","drafty","light","entries","dc","isEmptyObject","obj","toGraphemeValues","segments","indices","result","graphemeIndex","charIndex","graphemeIndices","correctAt","str","from","init","plainText","parse","content","lines","split","entityMap","entityIndex","blx","entities","block","original","re_start","re_end","exec","start_offset","lastIndexOf","end_offset","spannify","match","extracted","entity","offset","unique","idx","filter","el","extractEntities","ele","s","correctLen","append","first","second","insertImage","imageDesc","ex","refurl","bits","filename","urlPromise","_processing","then","insertVideo","videoDesc","urls","insertAudio","audioDesc","videoCall","audioOnly","aonly","updateVideoCall","params","assign","quote","header","uid","body","appendLineBreak","mention","appendLink","linkData","appendImage","appendAudio","attachFile","attachmentDesc","wrapInto","style","wrapAsForm","insertButton","actionType","actionValue","refUrl","appendButton","attachJSON","UNSAFE_toHTML","format","shorten","forwardedContent","replyContent","startsWith","forwarding","toPlainText","isPlainText","toMarkdown","def","isValid","txt_type","hasAttachments","callback","count","hasEntities","styles","sanitizeEntities","getDownloadUrl","entData","isProcessing","getPreviewUrl","getEntitySize","getEntityMimeType","tagName","attrValue","getContentType","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","getter","__esModule","d","definition","o","defineProperty","enumerable","get","g","globalThis","Function","e","window","prop","prototype","hasOwnProperty","r","Symbol","toStringTag","value","AccessMode","constructor","acs","given","decode","want","mode","side","flag","Error","_BITMASK","_NONE","bitmask","_JOIN","_READ","_WRITE","_PRES","_APPROVE","_SHARE","_DELETE","_OWNER","m0","bit","charAt","toUpperCase","encode","_INVALID","res","update","upd","action","val0","parts","a1","a2","toString","jsonHelper","setMode","m","updateMode","u","getMode","setGiven","updateGiven","getGiven","setWant","w","updateWant","getWant","getMissing","getExcessive","updateAll","isOwner","isPresencer","isMuted","isJoiner","isReader","isWriter","isApprover","isAdmin","isSharer","isDeleter","VERSION","LIBRARY","TOPIC_NEW","TOPIC_NEW_CHAN","TOPIC_ME","TOPIC_FND","TOPIC_GRP","LOCAL_SEQID","DEL_CHAR","TAG_ALIAS","CommError","code","super","jsonParseHelper","date","Date","isNaN","isUrlRelative","isValidDate","getTime","mergeObj","ignore","mergeToCache","cache","newval","simplify","getOwnPropertyNames","normalizeRanges","maxSeq","r1","r2","low","hi","reduce","out","prev","Math","max","listToRanges","list","WebSocketProvider","XHRProvider","NETWORK_ERROR_TEXT","NETWORK_USER","NETWORK_USER_TEXT","makeBaseUrl","host","protocol","version","apiKey","Connection","static","secure","autoreconnect","initialized","config","version_","autoreconnect_","transport","setNetworkProviders","wsProvider","xhrProvider","l","connect","host_","force","Promise","reject","reconnect","disconnect","sendText","msg","isConnected","probe","backoffReset","clearTimeout","timeout","pow","random","onAutoreconnectIteration","setTimeout","prom","catch","_lpURL","_poller","_sender","lp_poller","url_","resolve","poller","promiseCompleted","onreadystatechange","evt","readyState","status","pkt","JSON","responseText","ctrl","sid","send","onOpen","onMessage","onDisconnect","abort","sender","lp_sender","OPEN","conn","onerror","onopen","onclose","onmessage","NETWORK_ERROR","DB_NAME","IDBProvider","DB","db","disabled","onError","source","trx","transaction","event","error","objectStore","getAll","onsuccess","topic","initDatabase","req","onversionchange","onupgradeneeded","objectStoreNames","contains","createObjectStore","keyPath","dellog","indexNames","createIndex","deleteDatabase","onblocked","isReady","updTopic","oncomplete","put","commit","markTopicAsDeleted","deleted","_deleted","remTopic","delete","IDBKeyRange","only","bound","Number","MAX_SAFE_INTEGER","mapTopics","deserializeTopic","updUser","pub","arguments","public","remUser","mapUsers","getUser","user","updSubscription","topicName","sub","mapSubscriptions","addMessage","add","updMessageStatus","seq","_status","remMessages","to","range","readMessages","query","msgs","since","before","openCursor","cursor","continue","addDelLog","delId","clear","readDelLog","entry","maxDelId","f","tags","_tags","setAccessMode","read","unread","getAccessMode","setDatabaseProvider","idbProvider","IndexedDBProvider","LargeFileHelper","tinode","_tinode","_version","_apiKey","_authToken","getAuthToken","xhr","uploadWithBaseUrl","baseUrl","avatarFor","onProgress","onSuccess","onFailure","base","endsWith","instance","setRequestHeader","token","toResolve","toReject","upload","onprogress","lengthComputable","loaded","total","onload","response","statusText","onabort","form","FormData","set","getNextUniqueId","_secure","_host","download","relativeUrl","mimetype","relUrl","location","origin","searchParams","substring","addURLParam","responseType","link","document","createElement","display","setAttribute","appendChild","click","removeChild","revokeObjectURL","reader","FileReader","readAsText","cancel","setNetworkProvider","MetaGetBuilder","what","updated","isP2PType","_lastSubsUpdate","withData","withLaterData","_maxSeq","withDataRanges","withDataList","withEarlierData","_minSeq","withDesc","ims","withLaterDesc","withSub","userOrTopic","opts","getType","withOneSub","withLaterOneSub","withLaterSub","withTags","withCred","withAux","withDel","withLaterDel","_maxDel","extract","build","CBuffer","buffer","compare_","unique_","elem","exact","pivot","found","splice","getAt","getLast","findLast","insert","delAt","delRange","reset","startIdx","beforeIdx","min","find","nearest","isEmpty","Topic","callbacks","created","touched","private","trusted","_users","_queuedSeqId","Const","_noEarlierMsgs","_recvNotificationTimer","_credentials","_aux","_messageVersions","_messages","_attached","_new","_delayedLeaveTimer","onData","onMeta","onPres","onInfo","onMetaDesc","onMetaSub","onSubsUpdated","onTagsUpdated","onCredsUpdated","onAuxUpdated","onDeleteTopic","onAllMessagesReceived","topicType","isMeTopicName","isSelfTopicName","isGroupTopicName","isP2PTopicName","isCommTopicName","isNewGroupTopicName","isChannelTopicName","head","replace","isSubscribed","subscribe","getParams","setParams","_cacheDelSelf","_cachePutSelf","ts","me","getMeTopic","desc","_noForwarding","_processMetaDesc","createMessage","noEcho","publish","publishMessage","_sending","_failed","swapMessageId","_maybeUpdateMessageVersionsCache","_routeData","publishDraft","_getQueuedSeqId","getCurrentUserID","noecho","_db","_cancelled","_fatal","leave","unsub","_resetSub","_gone","leaveDelayed","delay","getMeta","getMessagesPage","gaps","newer","startMetaQuery","_loadMessages","msgHasMoreMessages","getPinnedMessages","pins","aux","remains","setMeta","t","trim","toLowerCase","item","pos","ary","normalizeArray","_processMetaSubs","_processMetaTags","cred","_processMetaCreds","_processMetaAux","subscriber","am","invite","archive","arch","pinMessage","pin","pinned","changed","delMessages","hard","tosend","del","rec","flushMessageRange","flushMessage","delMessagesAll","hardDel","_all","delMessagesList","delMessagesEdits","messageVersions","delTopic","delSubscription","note","_updateMyReadRecv","_refreshContact","noteRecv","noteRead","noteKeyPress","noteRecording","payload","oldVal","doUpdate","recv","userDesc","_cacheGetUser","p2pPeerDesc","subscribers","cb","alias","origSeq","versions","messages","sinceId","beforeId","unused1","unused2","latest","latestMsgVersion","_origTs","_origSeq","findMessage","latestMessage","maxMsgSeq","minMsgSeq","maxClearId","messageCount","queuedMessages","msgReceiptCount","msgReadCount","msgRecvCount","gap","p","expected","isNewMessage","seqId","fromId","untilId","newSeqId","numMessages","cancelSend","msgStatus","getDefaultAccess","defacs","isArchived","isMeType","isSelfType","isChannelType","isGroupType","isCommType","isMe","targetSeq","parseInt","targetMsg","outgoing","webrtc","incoming","vc","_routeInfo","_routeMeta","meta","_processDelMessages","delseq","_routePres","pres","online","isTopicCached","dacs","info","subs","_updateCachedUser","creds","_allMessagesReceived","cached","_cachePutUser","_updateReceived","TopicFnd","_contacts","updateCount","indexBy","getPrototypeOf","checkTagUniqueness","caller","contacts","TopicMe","onContactUpdate","turnOff","_myUID","cont","seen","when","cacheRemTopic","getTopic","cr","findIndex","meth","done","resp","cacheGetTopic","tgt","ua","dummy","delCredential","method","getContact","getCredentials","b64EncodeUnicode","btoa","encodeURIComponent","p1","String","fromCharCode","jsonBuildHelper","pad","sp","repeat","millis","getUTCMilliseconds","getUTCFullYear","getUTCMonth","getUTCDate","getUTCHours","getUTCMinutes","getUTCSeconds","rfc3339DateString","jsonLoggerHelper","WebSocket","XMLHttpRequest","indexedDB","chars","global","input","output","charCode","bc","bs","DBCache","initForNonBrowserApp","Tinode","_appName","_browser","_platform","_hwos","_humanLanguage","_loggingEnabled","_trimLongStrings","_authenticated","_login","_inPacketCount","_messageId","floor","_serverInfo","_deviceToken","_pendingPromises","_expirePromises","_connection","_persist","_cache","onComplete","appName","platform","navigator","product","reactnative","priority","tmp","substr","tokens","m2","v","minor","getBrowserInfo","userAgent","language","detectTransport","promise","persist","all","args","dateString","console","log","onOK","errorText","stringify","onRawMessage","onNetworkProbe","onCtrlMessage","onMetaMessage","onDataMessage","onPresMessage","onInfoMessage","setInterval","expires","hello","clearInterval","func","_cacheDelUser","onLogin","credential","getVersion","getLibrary","isNullValue","isServerAssignedSeq","isValidTagValue","tagSplit","splitAt","prefix","setUniqueTag","uniqueTag","clearTagPrefix","tagByPrefix","clearStorage","initStorage","networkProbe","isAuthenticated","authorizeURL","parsed","account","scheme","secret","login","acc","tmpscheme","tmpsecret","extra","createAccount","createAccountBasic","username","password","updateAccountBasic","onConnect","setDeviceToken","dt","sent","loginBasic","uname","loginToken","requestResetAuthSecret","now","setAuthToken","dft","oobNotification","xfrom","finally","modeGiven","modeWant","delCurrentUser","newGroupTopicName","isChan","getFndTopic","getLargeFileHelper","getCurrentLogin","getServerInfo","report","getServerParam","defaultValue","enableLogging","enabled","trimLongStrings","setHumanLanguage","hl","isTopicOnline","getTopicAccessMode","wantAkn","onWebsocketOpen","MESSAGE_STATUS_NONE","MESSAGE_STATUS_QUEUED","MESSAGE_STATUS_SENDING","MESSAGE_STATUS_FAILED","MESSAGE_STATUS_FATAL","MESSAGE_STATUS_SENT","MESSAGE_STATUS_RECEIVED","MESSAGE_STATUS_READ","MESSAGE_STATUS_TO_ME","MAX_MESSAGE_SIZE","MAX_SUBSCRIBER_COUNT","MIN_TAG_LENGTH","MAX_TAG_LENGTH","MAX_TAG_COUNT","MAX_FILE_UPLOAD_SIZE","REQ_CRED_VALIDATORS","MSG_DELETE_AGE","URI_TOPIC_ID_PREFIX","TAG_EMAIL","TAG_PHONE"],"sourceRoot":""}
\ No newline at end of file